Merge pull request #127 from christianbundy/view-markdown
Move Markdown handling from model module to view
This commit is contained in:
commit
173e0ee4b9
|
@ -11,8 +11,6 @@ const pullSort = require("pull-sort");
|
|||
// HACK: https://github.com/ssbc/ssb-thread-schema/issues/4
|
||||
const isNestedReply = require("ssb-thread-schema/post/nested-reply/validator");
|
||||
|
||||
const markdown = require("./markdown");
|
||||
|
||||
const nullImage = `&${"0".repeat(43)}=.sha256`;
|
||||
|
||||
const defaultOptions = {
|
||||
|
@ -57,7 +55,7 @@ module.exports = cooler => {
|
|||
key: "description",
|
||||
dest: feedId
|
||||
});
|
||||
return markdown(raw);
|
||||
return raw;
|
||||
},
|
||||
all: async feedId => {
|
||||
const ssb = await cooler.connect();
|
||||
|
@ -315,10 +313,6 @@ module.exports = cooler => {
|
|||
return null;
|
||||
}
|
||||
|
||||
lodash.set(msg, "value.meta.md.block", () =>
|
||||
markdown(msg.value.content.text, msg.value.content.mentions)
|
||||
);
|
||||
|
||||
const filterQuery = {
|
||||
$filter: {
|
||||
dest: msg.key
|
|
@ -9,6 +9,7 @@ const {
|
|||
article,
|
||||
button,
|
||||
code,
|
||||
details,
|
||||
div,
|
||||
footer,
|
||||
form,
|
||||
|
@ -28,12 +29,160 @@ const {
|
|||
select,
|
||||
span,
|
||||
strong,
|
||||
summary,
|
||||
textarea,
|
||||
ul
|
||||
} = require("hyperaxe");
|
||||
|
||||
const template = require("./template");
|
||||
const post = require("./post");
|
||||
const markdown = require("./markdown");
|
||||
|
||||
const lodash = require("lodash");
|
||||
|
||||
const post = ({ msg }) => {
|
||||
const encoded = {
|
||||
key: encodeURIComponent(msg.key),
|
||||
author: encodeURIComponent(msg.value.author),
|
||||
parent: encodeURIComponent(msg.value.content.root)
|
||||
};
|
||||
|
||||
const url = {
|
||||
author: `/author/${encoded.author}`,
|
||||
likeForm: `/like/${encoded.key}`,
|
||||
link: `/thread/${encoded.key}#${encoded.key}`,
|
||||
parent: `/thread/${encoded.parent}#${encoded.parent}`,
|
||||
avatar: msg.value.meta.author.avatar.url,
|
||||
json: `/json/${encoded.key}`,
|
||||
reply: `/reply/${encoded.key}`,
|
||||
comment: `/comment/${encoded.key}`
|
||||
};
|
||||
|
||||
const isPrivate = Boolean(msg.value.meta.private);
|
||||
const isRoot = msg.value.content.root == null;
|
||||
const isThreadTarget = Boolean(
|
||||
lodash.get(msg, "value.meta.thread.target", false)
|
||||
);
|
||||
|
||||
// TODO: I think this is actually true for both replies and comments.
|
||||
const isReply = Boolean(lodash.get(msg, "value.meta.thread.reply", false));
|
||||
|
||||
const { name } = msg.value.meta.author;
|
||||
const timeAgo = msg.value.meta.timestamp.received.since.replace("~", "");
|
||||
|
||||
const depth = lodash.get(msg, "value.meta.thread.depth", 0);
|
||||
|
||||
const markdownContent = markdown(
|
||||
msg.value.content.text,
|
||||
msg.value.content.mentions
|
||||
);
|
||||
|
||||
const hasContentWarning =
|
||||
typeof msg.value.content.contentWarning === "string";
|
||||
|
||||
const likeButton = msg.value.meta.voted
|
||||
? { value: 0, class: "liked" }
|
||||
: { value: 1, class: null };
|
||||
|
||||
const likeCount = msg.value.meta.votes.length;
|
||||
|
||||
const messageClasses = [];
|
||||
|
||||
if (isPrivate) {
|
||||
messageClasses.push("private");
|
||||
}
|
||||
|
||||
if (isThreadTarget) {
|
||||
messageClasses.push("thread-target");
|
||||
}
|
||||
|
||||
if (isReply) {
|
||||
// True for comments too, I think
|
||||
messageClasses.push("reply");
|
||||
}
|
||||
|
||||
const isFork = msg.value.meta.postType === "reply";
|
||||
|
||||
const postOptions = {
|
||||
post: null,
|
||||
comment: ["commented on ", a({ href: url.parent }, " thread")],
|
||||
reply: ["replied to ", a({ href: url.parent }, " message")],
|
||||
mystery: "posted a mysterious message"
|
||||
};
|
||||
|
||||
const emptyContent = "<p>undefined</p>\n";
|
||||
const articleElement =
|
||||
markdownContent === emptyContent
|
||||
? article(
|
||||
{ class: "content" },
|
||||
pre({
|
||||
innerHTML: highlightJs.highlight(
|
||||
"json",
|
||||
JSON.stringify(msg, null, 2)
|
||||
).value
|
||||
})
|
||||
)
|
||||
: article({ class: "content", innerHTML: markdownContent });
|
||||
|
||||
const articleContent = hasContentWarning
|
||||
? details(summary(msg.value.content.contentWarning), articleElement)
|
||||
: articleElement;
|
||||
|
||||
const fragment = section(
|
||||
{
|
||||
id: msg.key,
|
||||
class: messageClasses.join(" "),
|
||||
style: `margin-left: ${depth}rem;`
|
||||
},
|
||||
header(
|
||||
span(
|
||||
{ class: "author" },
|
||||
a(
|
||||
{ href: url.author },
|
||||
img({ class: "avatar", src: url.avatar, alt: "" }),
|
||||
name
|
||||
),
|
||||
postOptions[msg.value.meta.postType]
|
||||
),
|
||||
span(
|
||||
{ class: "time" },
|
||||
isPrivate ? "🔒" : null,
|
||||
a({ href: url.link }, timeAgo)
|
||||
)
|
||||
),
|
||||
articleContent,
|
||||
|
||||
// HACK: centered-footer
|
||||
//
|
||||
// Here we create an empty div with an anchor tag that can be linked to.
|
||||
// In our CSS we ensure that this gets centered on the screen when we
|
||||
// link to this anchor tag.
|
||||
//
|
||||
// This is used for redirecting users after they like a post, when we
|
||||
// want the like button that they just clicked to remain close-ish to
|
||||
// where it was before they clicked the button.
|
||||
div({ id: `centered-footer-${encoded.key}`, class: "centered-footer" }),
|
||||
|
||||
footer(
|
||||
form(
|
||||
{ action: url.likeForm, method: "post" },
|
||||
button(
|
||||
{
|
||||
name: "voteValue",
|
||||
type: "submit",
|
||||
value: likeButton.value,
|
||||
class: likeButton.class
|
||||
},
|
||||
`❤ ${likeCount}`
|
||||
)
|
||||
),
|
||||
a({ href: url.comment }, "Comment"),
|
||||
isPrivate || isRoot || isFork ? null : a({ href: url.reply }, "Reply"),
|
||||
a({ href: url.json }, "JSON")
|
||||
)
|
||||
);
|
||||
|
||||
return fragment;
|
||||
};
|
||||
|
||||
exports.authorView = ({
|
||||
avatarUrl,
|
||||
|
@ -78,9 +227,7 @@ exports.authorView = ({
|
|||
class: "md-mention",
|
||||
innerHTML: markdownMention
|
||||
}),
|
||||
description !== "<p>null</p>\n"
|
||||
? article({ innerHTML: description })
|
||||
: null,
|
||||
description !== "" ? article({ innerHTML: markdown(description) }) : null,
|
||||
footer(
|
||||
a({ href: `/likes/${encodeURIComponent(feedId)}` }, "View likes"),
|
||||
span(relationship),
|
||||
|
|
|
@ -1,162 +0,0 @@
|
|||
"use strict";
|
||||
|
||||
const {
|
||||
a,
|
||||
article,
|
||||
button,
|
||||
details,
|
||||
div,
|
||||
footer,
|
||||
form,
|
||||
header,
|
||||
img,
|
||||
section,
|
||||
span,
|
||||
summary,
|
||||
pre
|
||||
} = require("hyperaxe");
|
||||
|
||||
const highlightJs = require("highlight.js");
|
||||
const lodash = require("lodash");
|
||||
|
||||
module.exports = ({ msg }) => {
|
||||
const encoded = {
|
||||
key: encodeURIComponent(msg.key),
|
||||
author: encodeURIComponent(msg.value.author),
|
||||
parent: encodeURIComponent(msg.value.content.root)
|
||||
};
|
||||
|
||||
const url = {
|
||||
author: `/author/${encoded.author}`,
|
||||
likeForm: `/like/${encoded.key}`,
|
||||
link: `/thread/${encoded.key}#${encoded.key}`,
|
||||
parent: `/thread/${encoded.parent}#${encoded.parent}`,
|
||||
avatar: msg.value.meta.author.avatar.url,
|
||||
json: `/json/${encoded.key}`,
|
||||
reply: `/reply/${encoded.key}`,
|
||||
comment: `/comment/${encoded.key}`
|
||||
};
|
||||
|
||||
const isPrivate = Boolean(msg.value.meta.private);
|
||||
const isRoot = msg.value.content.root == null;
|
||||
const isThreadTarget = Boolean(
|
||||
lodash.get(msg, "value.meta.thread.target", false)
|
||||
);
|
||||
|
||||
// TODO: I think this is actually true for both replies and comments.
|
||||
const isReply = Boolean(lodash.get(msg, "value.meta.thread.reply", false));
|
||||
|
||||
const { name } = msg.value.meta.author;
|
||||
const timeAgo = msg.value.meta.timestamp.received.since.replace("~", "");
|
||||
|
||||
const depth = lodash.get(msg, "value.meta.thread.depth", 0);
|
||||
|
||||
const markdownContent = msg.value.meta.md.block();
|
||||
|
||||
const hasContentWarning =
|
||||
typeof msg.value.content.contentWarning === "string";
|
||||
|
||||
const likeButton = msg.value.meta.voted
|
||||
? { value: 0, class: "liked" }
|
||||
: { value: 1, class: null };
|
||||
|
||||
const likeCount = msg.value.meta.votes.length;
|
||||
|
||||
const messageClasses = [];
|
||||
|
||||
if (isPrivate) {
|
||||
messageClasses.push("private");
|
||||
}
|
||||
|
||||
if (isThreadTarget) {
|
||||
messageClasses.push("thread-target");
|
||||
}
|
||||
|
||||
if (isReply) {
|
||||
// True for comments too, I think
|
||||
messageClasses.push("reply");
|
||||
}
|
||||
|
||||
const isFork = msg.value.meta.postType === "reply";
|
||||
|
||||
const postOptions = {
|
||||
post: null,
|
||||
comment: ["commented on ", a({ href: url.parent }, " thread")],
|
||||
reply: ["replied to ", a({ href: url.parent }, " message")],
|
||||
mystery: "posted a mysterious message"
|
||||
};
|
||||
|
||||
const emptyContent = "<p>undefined</p>\n";
|
||||
const articleElement =
|
||||
markdownContent === emptyContent
|
||||
? article(
|
||||
{ class: "content" },
|
||||
pre({
|
||||
innerHTML: highlightJs.highlight(
|
||||
"json",
|
||||
JSON.stringify(msg, null, 2)
|
||||
).value
|
||||
})
|
||||
)
|
||||
: article({ class: "content", innerHTML: markdownContent });
|
||||
|
||||
const articleContent = hasContentWarning
|
||||
? details(summary(msg.value.content.contentWarning), articleElement)
|
||||
: articleElement;
|
||||
|
||||
const fragment = section(
|
||||
{
|
||||
id: msg.key,
|
||||
class: messageClasses.join(" "),
|
||||
style: `margin-left: ${depth}rem;`
|
||||
},
|
||||
header(
|
||||
span(
|
||||
{ class: "author" },
|
||||
a(
|
||||
{ href: url.author },
|
||||
img({ class: "avatar", src: url.avatar, alt: "" }),
|
||||
name
|
||||
),
|
||||
postOptions[msg.value.meta.postType]
|
||||
),
|
||||
span(
|
||||
{ class: "time" },
|
||||
isPrivate ? "🔒" : null,
|
||||
a({ href: url.link }, timeAgo)
|
||||
)
|
||||
),
|
||||
articleContent,
|
||||
|
||||
// HACK: centered-footer
|
||||
//
|
||||
// Here we create an empty div with an anchor tag that can be linked to.
|
||||
// In our CSS we ensure that this gets centered on the screen when we
|
||||
// link to this anchor tag.
|
||||
//
|
||||
// This is used for redirecting users after they like a post, when we
|
||||
// want the like button that they just clicked to remain close-ish to
|
||||
// where it was before they clicked the button.
|
||||
div({ id: `centered-footer-${encoded.key}`, class: "centered-footer" }),
|
||||
|
||||
footer(
|
||||
form(
|
||||
{ action: url.likeForm, method: "post" },
|
||||
button(
|
||||
{
|
||||
name: "voteValue",
|
||||
type: "submit",
|
||||
value: likeButton.value,
|
||||
class: likeButton.class
|
||||
},
|
||||
`❤ ${likeCount}`
|
||||
)
|
||||
),
|
||||
a({ href: url.comment }, "Comment"),
|
||||
isPrivate || isRoot || isFork ? null : a({ href: url.reply }, "Reply"),
|
||||
a({ href: url.json }, "JSON")
|
||||
)
|
||||
);
|
||||
|
||||
return fragment;
|
||||
};
|
Loading…
Reference in New Issue