Merge branch 'master' of github.com:fraction/oasis into conn-buttons
This commit is contained in:
commit
ec3e4d489a
|
@ -38,7 +38,7 @@ Want more? Check out [`install.md`](https://github.com/fraction/oasis/blob/maste
|
|||
|
||||
## Resources
|
||||
|
||||
- [Contributing](https://github.com/fraction/oasis/blob/master/docs/contributing.md)
|
||||
- [Architecture](https://github.com/fraction/oasis/blob/master/docs/architecture.md)
|
||||
- [Help](https://github.com/fraction/oasis/issues/new/choose)
|
||||
- [Roadmap](https://github.com/fraction/oasis/blob/master/docs/roadmap.md)
|
||||
- [Security Policy](https://github.com/fraction/oasis/blob/master/docs/security.md)
|
||||
|
|
|
@ -36,26 +36,6 @@
|
|||
"source-map": "^0.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
|
||||
"integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.8.3"
|
||||
}
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
|
||||
"integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.0.0",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"source-map": {
|
||||
"version": "0.5.7",
|
||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
|
||||
|
@ -159,28 +139,6 @@
|
|||
"@babel/code-frame": "^7.8.3",
|
||||
"@babel/parser": "^7.8.3",
|
||||
"@babel/types": "^7.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
|
||||
"integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.8.3"
|
||||
}
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
|
||||
"integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.0.0",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@babel/traverse": {
|
||||
|
@ -200,26 +158,6 @@
|
|||
"lodash": "^4.17.13"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/code-frame": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
|
||||
"integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/highlight": "^7.8.3"
|
||||
}
|
||||
},
|
||||
"@babel/highlight": {
|
||||
"version": "7.8.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.8.3.tgz",
|
||||
"integrity": "sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.0.0",
|
||||
"esutils": "^2.0.2",
|
||||
"js-tokens": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"globals": {
|
||||
"version": "11.12.0",
|
||||
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
|
||||
|
@ -274,6 +212,19 @@
|
|||
"ssb-tangle": "^1.0.1",
|
||||
"ssb-unix-socket": "^1.0.0",
|
||||
"ssb-ws": "^6.2.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"ssb-tangle": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/ssb-tangle/-/ssb-tangle-1.0.1.tgz",
|
||||
"integrity": "sha512-Miu42xjISxwQGX1J59VC1FgMmLQShILZeYXOhCL5aavoYm7nzeykrEM//pU55pVlUTAbXLttvhH56IDXTPX/Kw==",
|
||||
"requires": {
|
||||
"is-my-json-valid": "^2.20.0",
|
||||
"pull-stream": "^3.6.11",
|
||||
"ssb-ref": "^2.13.9",
|
||||
"ssb-sort": "^1.1.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"@nodelib/fs.scandir": {
|
||||
|
@ -985,7 +936,6 @@
|
|||
"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",
|
||||
|
@ -2915,13 +2865,6 @@
|
|||
"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",
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
"ssb-mentions": "^0.5.0",
|
||||
"ssb-msgs": "^5.2.0",
|
||||
"ssb-ref": "^2.13.9",
|
||||
"ssb-tangle": "^1.0.1",
|
||||
"ssb-thread-schema": "^1.1.1",
|
||||
"yargs": "^15.0.0"
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 15">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16">
|
||||
<title>oasis favicon</title>
|
||||
<text x="0" y="15">🏝️</text>
|
||||
<text x="0" y="14">🏝️</text>
|
||||
</svg>
|
||||
|
|
Before Width: | Height: | Size: 139 B After Width: | Height: | Size: 139 B |
|
@ -46,6 +46,7 @@
|
|||
--common-radius: var(--micro);
|
||||
--measure: calc(var(--peta) + var(--mega));
|
||||
--line: 1.5rem;
|
||||
--code-size: 85%;
|
||||
}
|
||||
|
||||
* {
|
||||
|
@ -67,6 +68,7 @@ html {
|
|||
line-height: 1.5;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
main {
|
||||
|
@ -194,7 +196,7 @@ section code {
|
|||
overflow-wrap: break-word;
|
||||
padding: 0.125em 0.25em;
|
||||
margin: 0;
|
||||
font-size: 85%;
|
||||
font-size: var(--code-size);
|
||||
background-color: var(--bg);
|
||||
border-radius: var(--common-radius);
|
||||
border: var(--pico) solid var(--bg-status);
|
||||
|
@ -315,6 +317,8 @@ section {
|
|||
margin: var(--whole) 0;
|
||||
word-wrap: break-word;
|
||||
background: var(--bg);
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
section > header {
|
||||
|
@ -462,3 +466,26 @@ hr {
|
|||
justify-content: space-between;
|
||||
margin: var(--whole) 0;
|
||||
}
|
||||
|
||||
/* sidebar only appears on big screens */
|
||||
@media (min-width: calc(45rem)) {
|
||||
body > nav > ul {
|
||||
justify-content: right;
|
||||
flex-direction: column;
|
||||
margin-right: var(--kilo);
|
||||
position: sticky;
|
||||
top: var(--whole);
|
||||
}
|
||||
body > nav > ul > li {
|
||||
margin-bottom: var(--whole);
|
||||
}
|
||||
main {
|
||||
width: 100%;
|
||||
max-width: var(--measure);
|
||||
}
|
||||
body {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
max-width: none;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,9 @@ const koaStatic = require("koa-static");
|
|||
const path = require("path");
|
||||
const mount = require("koa-mount");
|
||||
|
||||
/**
|
||||
* @param {{ host: string, port: number, routes: any }} input
|
||||
*/
|
||||
module.exports = ({ host, port, routes }) => {
|
||||
const assets = new Koa();
|
||||
assets.use(koaStatic(path.join(__dirname, "assets")));
|
||||
|
@ -10,10 +13,10 @@ module.exports = ({ host, port, routes }) => {
|
|||
const app = new Koa();
|
||||
module.exports = app;
|
||||
|
||||
app.on("error", e => {
|
||||
app.on("error", err => {
|
||||
// Output full error objects
|
||||
e.message = e.stack;
|
||||
e.expose = true;
|
||||
err.message = err.stack;
|
||||
err.expose = true;
|
||||
return null;
|
||||
});
|
||||
|
||||
|
|
14
src/index.js
14
src/index.js
|
@ -99,15 +99,17 @@ router
|
|||
const publicPopular = async ({ period }) => {
|
||||
const messages = await post.popular({ period });
|
||||
|
||||
const option = somePeriod =>
|
||||
li(
|
||||
period === somePeriod
|
||||
? a({ class: "current", href: `./${somePeriod}` }, somePeriod)
|
||||
: a({ href: `./${somePeriod}` }, somePeriod)
|
||||
const option = somePeriod => {
|
||||
const lowerPeriod = somePeriod.toLowerCase();
|
||||
return li(
|
||||
period === lowerPeriod
|
||||
? a({ class: "current", href: `./${lowerPeriod}` }, somePeriod)
|
||||
: a({ href: `./${lowerPeriod}` }, somePeriod)
|
||||
);
|
||||
};
|
||||
|
||||
const prefix = nav(
|
||||
ul(option("day"), option("week"), option("month"), option("year"))
|
||||
ul(option("Day"), option("Week"), option("Month"), option("Year"))
|
||||
);
|
||||
|
||||
return publicView({
|
||||
|
|
|
@ -21,6 +21,7 @@ const defaultOptions = {
|
|||
meta: true
|
||||
};
|
||||
|
||||
/** @param {object[]} customOptions */
|
||||
const configure = (...customOptions) =>
|
||||
Object.assign({}, defaultOptions, ...customOptions);
|
||||
|
||||
|
@ -161,14 +162,15 @@ module.exports = cooler => {
|
|||
dest: feedId
|
||||
});
|
||||
|
||||
// TODO: Refactor to stop doing awful string comparison.
|
||||
if (isFollowing === true && isBlocking === false) {
|
||||
return "you are following";
|
||||
return "You are following";
|
||||
} else if (isFollowing === false && isBlocking === true) {
|
||||
return "you are blocking";
|
||||
return "You are blocking";
|
||||
} else if (isFollowing === false && isBlocking === false) {
|
||||
return "you are not following or blocking";
|
||||
return "You are not following or blocking";
|
||||
} else {
|
||||
return "you are following and blocking (!)";
|
||||
return "You are following and blocking (!)";
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -1105,6 +1107,7 @@ module.exports = cooler => {
|
|||
models.post = post;
|
||||
|
||||
models.vote = {
|
||||
/** @param {{messageKey: string, value: {}, recps: []}} input */
|
||||
publish: async ({ messageKey, value, recps }) => {
|
||||
const ssb = await cooler.connect();
|
||||
const branch = await cooler.get(ssb.tangle.branch, messageKey);
|
||||
|
|
|
@ -4,20 +4,27 @@ const md = require("ssb-markdown");
|
|||
const ssbMessages = require("ssb-msgs");
|
||||
const ssbRef = require("ssb-ref");
|
||||
|
||||
const toUrl = (mentions = []) => {
|
||||
const mentionNames = {};
|
||||
/** @param {{ link: string}[]} mentions */
|
||||
const toUrl = mentions => {
|
||||
/** @type {{name: string, link: string}[]} */
|
||||
const mentionNames = [];
|
||||
|
||||
ssbMessages.links(mentions, "feed").forEach(link => {
|
||||
if (link.name && typeof link.name === "string") {
|
||||
const name = link.name.charAt(0) === "@" ? link.name : `@${link.name}`;
|
||||
mentionNames[name] = link.link;
|
||||
/** @param {{ link: string, name: string}} arg */
|
||||
const handleLink = ({ name, link }) => {
|
||||
if (typeof name === "string") {
|
||||
const atName = name.charAt(0) === "@" ? name : `@${name}`;
|
||||
mentionNames.push({ name: atName, link });
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
return ref => {
|
||||
ssbMessages.links(mentions, "feed").forEach(handleLink);
|
||||
|
||||
/** @param {string} ref */
|
||||
const urlHandler = ref => {
|
||||
// @mentions
|
||||
if (ref in mentionNames) {
|
||||
return `/author/${encodeURIComponent(mentionNames[ref])}`;
|
||||
const found = mentionNames.find(({ name }) => name === ref);
|
||||
if (found !== undefined) {
|
||||
return `/author/${encodeURIComponent(found.link)}`;
|
||||
}
|
||||
|
||||
if (ssbRef.isFeedId(ref)) {
|
||||
|
@ -34,9 +41,15 @@ const toUrl = (mentions = []) => {
|
|||
}
|
||||
return "";
|
||||
};
|
||||
|
||||
return urlHandler;
|
||||
};
|
||||
|
||||
module.exports = (input, mentions) =>
|
||||
/**
|
||||
* @param {string} input
|
||||
* @param {{name: string, link: string}[]} mentions
|
||||
*/
|
||||
module.exports = (input, mentions = []) =>
|
||||
md.block(input, {
|
||||
toUrl: toUrl(mentions)
|
||||
});
|
||||
|
|
10
src/ssb.js
10
src/ssb.js
|
@ -7,6 +7,7 @@
|
|||
const ssbClient = require("ssb-client");
|
||||
const ssbConfig = require("ssb-config");
|
||||
const flotilla = require("@fraction/flotilla");
|
||||
const ssbTangle = require("ssb-tangle");
|
||||
const debug = require("debug")("oasis");
|
||||
|
||||
const server = flotilla(ssbConfig);
|
||||
|
@ -24,6 +25,15 @@ const rawConnect = () =>
|
|||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
if (api.tangle === undefined) {
|
||||
// HACK: SSB-Tangle isn't available in Patchwork, but we want that
|
||||
// compatibility. This code automatically injects SSB-Tangle into our
|
||||
// stack so that we don't get weird errors when using Patchwork.
|
||||
//
|
||||
// See: https://github.com/fraction/oasis/issues/21
|
||||
api.tangle = ssbTangle.init(api);
|
||||
}
|
||||
|
||||
resolve(api);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -46,9 +46,9 @@ exports.authorView = ({
|
|||
const mention = `[@${name}](${feedId})`;
|
||||
const markdownMention = highlightJs.highlight("markdown", mention).value;
|
||||
|
||||
const areFollowing = relationship === "you are following";
|
||||
const areFollowing = relationship === "You are following";
|
||||
|
||||
const contactFormType = areFollowing ? "unfollow" : "follow";
|
||||
const contactFormType = areFollowing ? "Unfollow" : "Follow";
|
||||
|
||||
// We're on our own profile!
|
||||
const contactForm =
|
||||
|
@ -82,7 +82,7 @@ exports.authorView = ({
|
|||
? article({ innerHTML: description })
|
||||
: null,
|
||||
footer(
|
||||
a({ href: `/likes/${encodeURIComponent(feedId)}` }, "view likes"),
|
||||
a({ href: `/likes/${encodeURIComponent(feedId)}` }, "View likes"),
|
||||
span(relationship),
|
||||
contactForm
|
||||
)
|
||||
|
@ -150,7 +150,7 @@ exports.commentView = async ({ messages, myFeedId, parentMessage }) => {
|
|||
{
|
||||
type: "submit"
|
||||
},
|
||||
"comment"
|
||||
"Comment"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -260,7 +260,7 @@ exports.metaView = ({ status, peers, theme, themeNames }) => {
|
|||
form(
|
||||
{ action: "/theme.css", method: "post" },
|
||||
select({ name: "theme" }, ...themeElements),
|
||||
button({ type: "submit" }, "set theme")
|
||||
button({ type: "submit" }, "Set theme")
|
||||
),
|
||||
base16Elements,
|
||||
h2("Status"),
|
||||
|
@ -301,7 +301,7 @@ exports.publicView = ({ messages, prefix = null }) => {
|
|||
". Messages cannot be edited or deleted."
|
||||
),
|
||||
textarea({ required: true, name: "text" }),
|
||||
button({ type: "submit" }, "submit")
|
||||
button({ type: "submit" }, "Submit")
|
||||
)
|
||||
),
|
||||
messages.map(msg => post({ msg }))
|
||||
|
@ -355,7 +355,7 @@ exports.replyView = async ({ messages, myFeedId }) => {
|
|||
{
|
||||
type: "submit"
|
||||
},
|
||||
"reply"
|
||||
"Reply"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
@ -376,7 +376,7 @@ exports.searchView = ({ messages, query }) =>
|
|||
{
|
||||
type: "submit"
|
||||
},
|
||||
"submit"
|
||||
"Submit"
|
||||
)
|
||||
)
|
||||
),
|
||||
|
|
|
@ -152,9 +152,9 @@ module.exports = ({ msg }) => {
|
|||
`❤ ${likeCount}`
|
||||
)
|
||||
),
|
||||
a({ href: url.comment }, "comment"),
|
||||
isPrivate || isRoot || isFork ? null : a({ href: url.reply }, "reply"),
|
||||
a({ href: url.json }, "json")
|
||||
a({ href: url.comment }, "Comment"),
|
||||
isPrivate || isRoot || isFork ? null : a({ href: url.reply }, "Reply"),
|
||||
a({ href: url.json }, "JSON")
|
||||
)
|
||||
);
|
||||
|
||||
|
|
|
@ -43,13 +43,13 @@ module.exports = (...elements) => {
|
|||
body(
|
||||
nav(
|
||||
ul(
|
||||
li(a({ href: "/" }, "popular")),
|
||||
li(a({ href: "/public/latest" }, "latest")),
|
||||
li(a({ href: "/inbox" }, "inbox")),
|
||||
li(a({ href: "/mentions" }, "mentions")),
|
||||
li(a({ href: "/profile" }, "profile")),
|
||||
li(a({ href: "/search" }, "search")),
|
||||
li(a({ href: "/meta" }, "meta"))
|
||||
li(a({ href: "/" }, "Popular")),
|
||||
li(a({ href: "/public/latest" }, "Latest")),
|
||||
li(a({ href: "/inbox" }, "Inbox")),
|
||||
li(a({ href: "/mentions" }, "Mentions")),
|
||||
li(a({ href: "/profile" }, "Profile")),
|
||||
li(a({ href: "/search" }, "Search")),
|
||||
li(a({ href: "/meta" }, "Meta"))
|
||||
)
|
||||
),
|
||||
main({ id: "content" }, elements)
|
||||
|
|
Loading…
Reference in New Issue