Merge pull request #363 from christianbundy/type-defs

Add TypeScript definitions for better guardrails
This commit is contained in:
Sean Billig 2020-03-27 19:19:17 -07:00 committed by GitHub
commit 033dbede33
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 323 additions and 27 deletions

251
package-lock.json generated
View File

@ -350,16 +350,89 @@
"fastq": "^1.6.0"
}
},
"@types/accepts": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.5.tgz",
"integrity": "sha512-jOdnI/3qTpHABjM5cx1Hc0sKsPoYCp+DP/GJRGtDlPd7fiV9oXGGIcjW/ZOxLIvjGz8MA+uMZI9metHlgqbgwQ==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/body-parser": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.0.tgz",
"integrity": "sha512-W98JrE0j2K78swW4ukqMleo8R7h/pFETjM2DQ90MF6XK2i4LO4W3gQ71Lt4w3bfm2EvVSyWHplECvB5sK22yFQ==",
"dev": true,
"requires": {
"@types/connect": "*",
"@types/node": "*"
}
},
"@types/color-name": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
},
"@types/connect": {
"version": "3.4.33",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.33.tgz",
"integrity": "sha512-2+FrkXY4zllzTNfJth7jOqEHC+enpLeGslEhpnTAkg21GkRrWV4SsAtqchtT4YS9/nODBU2/ZfsBY2X4J/dX7A==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/content-disposition": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.2.tgz",
"integrity": "sha1-GMyw/RJoCOSYqCDLgUnAByorkGY=",
"dev": true
},
"@types/cookies": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.7.4.tgz",
"integrity": "sha512-oTGtMzZZAVuEjTwCjIh8T8FrC8n/uwy+PG0yTvQcdZ7etoel7C7/3MSd7qrukENTgQtotG7gvBlBojuVs7X5rw==",
"dev": true,
"requires": {
"@types/connect": "*",
"@types/express": "*",
"@types/keygrip": "*",
"@types/node": "*"
}
},
"@types/debug": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.5.tgz",
"integrity": "sha512-Q1y515GcOdTHgagaVFhHnIFQ38ygs/kmxdNpvpou+raI9UO3YZcHDngBSYKQklcKlvA7iuQlmIKbzvmxcOE9CQ==",
"dev": true
},
"@types/events": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.0.tgz",
"integrity": "sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g=="
},
"@types/express": {
"version": "4.17.3",
"resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.3.tgz",
"integrity": "sha512-I8cGRJj3pyOLs/HndoP+25vOqhqWkAZsWMEmq1qXy/b/M3ppufecUwaK2/TVDVxcV61/iSdhykUjQQ2DLSrTdg==",
"dev": true,
"requires": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "*",
"@types/serve-static": "*"
}
},
"@types/express-serve-static-core": {
"version": "4.17.3",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.3.tgz",
"integrity": "sha512-sHEsvEzjqN+zLbqP+8OXTipc10yH1QLR+hnr5uw29gi9AhCAAAdri8ClNV7iMdrJrIzXIQtlkPvq8tJGhj3QJQ==",
"dev": true,
"requires": {
"@types/node": "*",
"@types/range-parser": "*"
}
},
"@types/formidable": {
"version": "1.0.31",
"resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.0.31.tgz",
@ -380,6 +453,112 @@
"@types/node": "*"
}
},
"@types/highlight.js": {
"version": "9.12.3",
"resolved": "https://registry.npmjs.org/@types/highlight.js/-/highlight.js-9.12.3.tgz",
"integrity": "sha512-pGF/zvYOACZ/gLGWdQH8zSwteQS1epp68yRcVLJMgUck/MjEn/FBYmPub9pXT8C1e4a8YZfHo1CKyV8q1vKUnQ==",
"dev": true
},
"@types/http-assert": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.1.tgz",
"integrity": "sha512-PGAK759pxyfXE78NbKxyfRcWYA/KwW17X290cNev/qAsn9eQIxkH4shoNBafH37wewhDG/0p1cHPbK6+SzZjWQ==",
"dev": true
},
"@types/keygrip": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.2.tgz",
"integrity": "sha512-GJhpTepz2udxGexqos8wgaBx4I/zWIDPh/KOGEwAqtuGDkOUJu5eFvwmdBX4AmB8Odsr+9pHCQqiAqDL/yKMKw==",
"dev": true
},
"@types/koa": {
"version": "2.11.3",
"resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.11.3.tgz",
"integrity": "sha512-ABxVkrNWa4O/Jp24EYI/hRNqEVRlhB9g09p48neQp4m3xL1TJtdWk2NyNQSMCU45ejeELMQZBYyfstyVvO2H3Q==",
"dev": true,
"requires": {
"@types/accepts": "*",
"@types/content-disposition": "*",
"@types/cookies": "*",
"@types/http-assert": "*",
"@types/keygrip": "*",
"@types/koa-compose": "*",
"@types/node": "*"
}
},
"@types/koa-compose": {
"version": "3.2.5",
"resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.5.tgz",
"integrity": "sha512-B8nG/OoE1ORZqCkBVsup/AKcvjdgoHnfi4pZMn5UwAPCbhk/96xyv284eBYW8JlQbQ7zDmnpFr68I/40mFoIBQ==",
"dev": true,
"requires": {
"@types/koa": "*"
}
},
"@types/koa-mount": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/koa-mount/-/koa-mount-4.0.0.tgz",
"integrity": "sha512-56iBULArwY3uKLl28eRFchZ2v0diEoJzJbDaHH/ehgruF/s2/KMHyWsKcIhvDJ3tGdKu9oZNQvxaMg++1IKFdA==",
"dev": true,
"requires": {
"@types/koa": "*"
}
},
"@types/koa-send": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/@types/koa-send/-/koa-send-4.1.2.tgz",
"integrity": "sha512-rfqKIv9bFds39Jxvsp8o3YJLnEQVPVriYA14AuO2OY65IHh/4UX4U/iMs5L0wATpcRmm1bbe0BNk23TRwx3VQQ==",
"dev": true,
"requires": {
"@types/koa": "*"
}
},
"@types/koa-static": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@types/koa-static/-/koa-static-4.0.1.tgz",
"integrity": "sha512-SSpct5fEcAeRkBHa3RiwCIRfDHcD1cZRhwRF///ZfvRt8KhoqRrhK6wpDlYPk/vWHVFE9hPGqh68bhzsHkir4w==",
"dev": true,
"requires": {
"@types/koa": "*",
"@types/koa-send": "*"
}
},
"@types/koa__router": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-8.0.2.tgz",
"integrity": "sha512-3ZWfVAEcErHrZA31fWUC2YyZyAgoG4eKtQPy2XwBzdSpQealxjL7GcEEtGY925qPPs1wurW59qDl0KuRB39rrw==",
"dev": true,
"requires": {
"@types/koa": "*"
}
},
"@types/linkify-it": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-2.1.0.tgz",
"integrity": "sha512-Q7DYAOi9O/+cLLhdaSvKdaumWyHbm7HAk/bFwwyTuU0arR5yyCeW5GOoqt4tJTpDRxhpx9Q8kQL6vMpuw9hDSw==",
"dev": true
},
"@types/lodash": {
"version": "4.14.149",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz",
"integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==",
"dev": true
},
"@types/markdown-it": {
"version": "0.0.9",
"resolved": "https://registry.npmjs.org/@types/markdown-it/-/markdown-it-0.0.9.tgz",
"integrity": "sha512-IFSepyZXbF4dgSvsk8EsgaQ/8Msv1I5eTL0BZ0X3iGO9jw6tCVtPG8HchIPm3wrkmGdqZOD42kE0zplVi1gYDA==",
"dev": true,
"requires": {
"@types/linkify-it": "*"
}
},
"@types/mime": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.1.tgz",
"integrity": "sha512-FwI9gX75FgVBJ7ywgnq/P7tw+/o1GUbtP0KzbtusLigAOgIgNISRK0ZPl4qertvXSIE8YbsVJueQ90cDt9YYyw==",
"dev": true
},
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
@ -392,11 +571,29 @@
"integrity": "sha1-aaI6OtKcrwCX8G7aWbNh7i8GOfY=",
"dev": true
},
"@types/mkdirp": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@types/mkdirp/-/mkdirp-1.0.0.tgz",
"integrity": "sha512-ONFY9//bCEr3DWKON3iDv/Q8LXnhaYYaNDeFSN0AtO5o4sLf9F0pstJKKKjQhXE0kJEeHs8eR6SAsROhhc2Csw==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/node": {
"version": "13.5.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-13.5.0.tgz",
"integrity": "sha512-Onhn+z72D2O2Pb2ql2xukJ55rglumsVo1H6Fmyi8mlU9SvKdBk/pUSUAiBY/d9bAOF7VVWajX3sths/+g6ZiAQ=="
},
"@types/nodemon": {
"version": "1.19.0",
"resolved": "https://registry.npmjs.org/@types/nodemon/-/nodemon-1.19.0.tgz",
"integrity": "sha512-nf0PKjNv3wo0pyhlPkHjfpU2oUYMdOIsCXceiFG6kvhYxbTwn2ne9mz2iWvJ/4QtCrJUEPJLNXuyGleyTacdaw==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/normalize-package-data": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.0.tgz",
@ -409,6 +606,37 @@
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
"dev": true
},
"@types/pull-stream": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/@types/pull-stream/-/pull-stream-3.6.0.tgz",
"integrity": "sha512-d7cobAytjsYaTluqFTJopLbdZRs1HBkU+N07/zCtsXANZ5s9riDazRkvxkAUfmRzCvXqYAsGgnJHgX2lInIOQg==",
"dev": true
},
"@types/range-parser": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.3.tgz",
"integrity": "sha512-ewFXqrQHlFsgc09MK5jP5iR7vumV/BYayNC6PgJO2LPe8vrnNFyjQjSppfEngITi0qvfKtzFvgKymGheFM9UOA==",
"dev": true
},
"@types/serve-static": {
"version": "1.13.3",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.3.tgz",
"integrity": "sha512-oprSwp094zOglVrXdlo/4bAHtKTAxX6VT8FOZlBKrmyLbNvE1zxZyJ6yikMVtHIvwP45+ZQGJn+FdXGKTozq0g==",
"dev": true,
"requires": {
"@types/express-serve-static-core": "*",
"@types/mime": "*"
}
},
"@types/sharp": {
"version": "0.23.1",
"resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.23.1.tgz",
"integrity": "sha512-iBRM9RjRF9pkIkukk6imlxfaKMRuiRND8L0yYKl5PJu5uLvxuNzp5f0x8aoTG5VX85M8O//BwbttzFVZL1j/FQ==",
"dev": true,
"requires": {
"@types/node": "*"
}
},
"@types/unist": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.3.tgz",
@ -435,6 +663,21 @@
"vfile-message": "*"
}
},
"@types/yargs": {
"version": "15.0.4",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.4.tgz",
"integrity": "sha512-9T1auFmbPZoxHz0enUFlUuKRy3it01R+hlggyVUMtnCTQRunsQYifnSGb8hET4Xo8yiC0o0r1paW3ud5+rbURg==",
"dev": true,
"requires": {
"@types/yargs-parser": "*"
}
},
"@types/yargs-parser": {
"version": "15.0.0",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-15.0.0.tgz",
"integrity": "sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==",
"dev": true
},
"abbrev": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
@ -1010,6 +1253,7 @@
"requires": {
"anymatch": "~3.1.1",
"braces": "~3.0.2",
"fsevents": "~2.1.2",
"glob-parent": "~5.1.0",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
@ -2939,6 +3183,13 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
},
"fsevents": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.2.tgz",
"integrity": "sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA==",
"dev": true,
"optional": true
},
"function-bind": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",

View File

@ -53,6 +53,19 @@
"yargs": "^15.3.1"
},
"devDependencies": {
"@types/debug": "^4.1.5",
"@types/highlight.js": "^9.12.3",
"@types/koa": "^2.11.3",
"@types/koa-mount": "^4.0.0",
"@types/koa-static": "^4.0.1",
"@types/koa__router": "^8.0.2",
"@types/lodash": "^4.14.149",
"@types/markdown-it": "^0.0.9",
"@types/mkdirp": "^1.0.0",
"@types/nodemon": "^1.19.0",
"@types/pull-stream": "^3.6.0",
"@types/sharp": "^0.23.1",
"@types/yargs": "^15.0.4",
"changelog-version": "^1.0.1",
"common-good": "^2.0.3",
"mkdirp": "^1.0.0",

View File

@ -3,6 +3,10 @@
const yargs = require("yargs");
const _ = require("lodash");
/**
* @param {object} presets
* @param {string} defaultConfigFile
*/
module.exports = (presets, defaultConfigFile) =>
yargs
.scriptName("oasis")

View File

@ -4,14 +4,15 @@ const path = require("path");
const mount = require("koa-mount");
/**
* @param {{ host: string, port: number, middleware: [] }} input
* @type function
* @param {{ host: string, port: number, middleware }} input
* @return function
*/
module.exports = ({ host, port, middleware }) => {
const http = ({ host, port, middleware }) => {
const assets = new Koa();
assets.use(koaStatic(path.join(__dirname, "assets")));
const app = new Koa();
module.exports = app;
app.on("error", (err) => {
// Output full error objects
@ -59,16 +60,23 @@ module.exports = ({ host, port, middleware }) => {
if (ctx.method !== "GET") {
const referer = ctx.request.header.referer;
ctx.assert(referer != null, `HTTP ${ctx.method} must include referer`);
ctx.assert(
referer != null,
400,
`HTTP ${ctx.method} must include referer`
);
const refererUrl = new URL(referer);
const isBlobReferer = refererUrl.pathname.startsWith("/blob/");
ctx.assert(
isBlobReferer === false,
400,
`HTTP ${ctx.method} from blob URL not allowed`
);
}
});
middleware.forEach((m) => app.use(m));
app.listen({ host, port });
return app.listen({ host, port });
};
module.exports = http;

View File

@ -38,10 +38,10 @@ if (config.debug) {
const nodeHttp = require("http");
const debug = require("debug")("oasis");
const log = (...args) => {
const log = (formatter, ...args) => {
const isDebugEnabled = debug.enabled;
debug.enabled = true;
debug(...args);
debug(formatter, ...args);
debug.enabled = isDebugEnabled;
};
@ -123,7 +123,7 @@ const { nav, ul, li, a } = require("hyperaxe");
const open = require("open");
const pull = require("pull-stream");
const requireStyle = require("require-style");
const router = require("@koa/router")();
const koaRouter = require("@koa/router");
const ssbMentions = require("ssb-mentions");
const ssbRef = require("ssb-ref");
const isSvg = require("is-svg");
@ -132,6 +132,8 @@ const { isFeed, isMsg, isBlob } = require("ssb-ref");
const ssb = require("./ssb");
const router = new koaRouter();
// Create "cooler"-style interface from SSB connection.
// This handle is passed to the models for their convenience.
const cooler = ssb({ offline: config.offline });
@ -191,7 +193,11 @@ router
const isInteger = size % 1 === 0;
const overMinSize = size > 2;
const underMaxSize = size <= 256;
ctx.assert(isInteger && overMinSize && underMaxSize, "Invalid image size");
ctx.assert(
isInteger && overMinSize && underMaxSize,
400,
"Invalid image size"
);
return next();
})
.param("blobId", (blobId, ctx, next) => {
@ -519,7 +525,7 @@ router
peers: peersWithNames,
theme,
themeNames,
version: config.version,
version: config.version.toString(),
});
};
ctx.body = await getMeta({ theme });
@ -667,13 +673,13 @@ router
const { feed } = ctx.params;
const referer = new URL(ctx.request.header.referer);
ctx.body = await friend.follow(feed);
ctx.redirect(referer);
ctx.redirect(referer.href);
})
.post("/unfollow/:feed", koaBody(), async (ctx) => {
const { feed } = ctx.params;
const referer = new URL(ctx.request.header.referer);
ctx.body = await friend.unfollow(feed);
ctx.redirect(referer);
ctx.redirect(referer.href);
})
.post("/like/:message", koaBody(), async (ctx) => {
const { message } = ctx.params;
@ -713,19 +719,19 @@ router
return vote.publish({ messageKey, value, recps: recipients });
};
ctx.body = await like({ messageKey, voteValue });
ctx.redirect(referer);
ctx.redirect(referer.href);
})
.post("/theme.css", koaBody(), async (ctx) => {
const theme = String(ctx.request.body.theme);
ctx.cookies.set("theme", theme);
const referer = new URL(ctx.request.header.referer);
ctx.redirect(referer);
ctx.redirect(referer.href);
})
.post("/language", koaBody(), async (ctx) => {
const language = String(ctx.request.body.language);
ctx.cookies.set("language", language);
const referer = new URL(ctx.request.header.referer);
ctx.redirect(referer);
ctx.redirect(referer.href);
})
.post("/settings/conn/start", koaBody(), async (ctx) => {
await meta.connStart();

View File

@ -23,10 +23,14 @@ ssbConfig.connections.incoming.unix = [
{ scope: "device", transform: "noauth" },
];
const log = (...args) => {
/**
* @param formatter {string} input
* @param args {any[]} input
*/
const log = (formatter, ...args) => {
const isDebugEnabled = debug.enabled;
debug.enabled = true;
debug(...args);
debug(formatter, ...args);
debug.enabled = isDebugEnabled;
};
@ -77,7 +81,7 @@ const createConnection = (config) => {
lodash.get(ssbConfig, "friends.hops", 0)
);
const add = address => {
const add = (address) => {
inProgress[address] = true;
return () => {
inProgress[address] = false;
@ -88,10 +92,10 @@ const createConnection = (config) => {
rawConnect()
.then((ssb) => {
log("Retrying connection to own server");
ssb.friends.hops().then(hops => {
ssb.friends.hops().then((hops) => {
pull(
ssb.conn.stagedPeers(),
pull.drain(x => {
pull.drain((x) => {
x.filter(([address, data]) => {
const notInProgress = inProgress[address] !== true;
@ -110,10 +114,7 @@ const createConnection = (config) => {
hops[data.key]
}/${maxHops} hops: ${address}`
);
ssb.conn
.connect(address, data)
.then(done)
.catch(done);
ssb.conn.connect(address, data).then(done).catch(done);
});
})
);

View File

@ -1,6 +1,6 @@
const { a, em, strong } = require("hyperaxe");
module.exports = {
const i18n = {
en: {
// navbar items
extended: "Extended",
@ -515,3 +515,5 @@ module.exports = {
"Beiträge von Leuten in deinem Netzwerk die dieses Hashtag referenzieren, sortiert nach Aktualität.",
},
};
module.exports = i18n;

View File

@ -48,8 +48,8 @@ const markdown = require("./markdown");
const md = new MarkdownIt();
const i18nBase = require("./i18n");
let i18n = null;
let selectedLanguage = null;
let selectedLanguage = "en";
let i18n = i18nBase[selectedLanguage];
exports.setLanguage = (language) => {
selectedLanguage = language;
@ -69,6 +69,9 @@ const toAttributes = (obj) =>
// non-breaking space
const nbsp = "\xa0";
/**
* @param {{href: string, emoji: string, text: string }} input
*/
const navLink = ({ href, emoji, text }) =>
li(a({ href }, span({ class: "emoji" }, emoji), nbsp, text));
@ -846,6 +849,9 @@ exports.publishView = () => {
);
};
/**
* @param {{status: object, peers: any[], theme: string, themeNames: string[], version: string }} input
*/
exports.settingsView = ({ status, peers, theme, themeNames, version }) => {
const max = status.sync.since;
@ -969,6 +975,7 @@ exports.settingsView = ({ status, peers, theme, themeNames, version }) => {
);
};
/** @param {{ viewTitle: string, viewDescription: string }} input */
const viewInfoBox = ({ viewTitle = null, viewDescription = null }) => {
if (!viewTitle && !viewDescription) {
return null;
@ -989,6 +996,8 @@ exports.likesView = async ({ messages, feed, name }) => {
return template(
viewInfoBox({
viewTitle: span(authorLink, i18n.likedBy),
// TODO: i18n
viewDescription: "List of messages liked by this author.",
}),
messages.map((msg) => post({ msg }))
);
@ -1144,6 +1153,7 @@ exports.hashtagView = ({ messages, hashtag }) => {
);
};
/** @param {{percent: number}} input */
exports.indexingView = ({ percent }) => {
// TODO: i18n
const message = `Oasis has only processed ${percent}% of the messages and needs to catch up. This page will refresh every 10 seconds. Thanks for your patience! ❤`;

View File

@ -53,5 +53,6 @@ const toUrl = (mentions) => {
module.exports = (input, mentions = []) =>
md.block(input, {
toUrl: toUrl(mentions),
/** @param character {string} */
emoji: (character) => span({ class: "emoji" }, character).outerHTML,
});