oasis/src/pages/views/components/post.js

150 lines
3.8 KiB
JavaScript
Raw Normal View History

2019-07-28 20:49:01 +00:00
'use strict'
2019-08-15 01:10:22 +00:00
const {
a,
2019-08-13 20:53:11 +00:00
article,
button,
details,
div,
2019-08-13 20:53:11 +00:00
footer,
form,
header,
img,
section,
span,
summary,
pre
} = require('hyperaxe')
const highlightJs = require('highlight.js')
2019-06-28 20:55:05 +00:00
const lodash = require('lodash')
module.exports = ({ msg }) => {
2019-06-28 20:55:05 +00:00
const encoded = {
key: encodeURIComponent(msg.key),
author: encodeURIComponent(msg.value.author),
parent: encodeURIComponent(msg.value.content.root)
}
const url = {
2019-06-28 20:55:05 +00:00
author: `/author/${encoded.author}`,
likeForm: `/like/${encoded.key}`,
link: `/thread/${encoded.key}#${encoded.key}`,
2019-06-28 20:55:05 +00:00
parent: `/thread/${encoded.parent}#${encoded.parent}`,
avatar: msg.value.meta.author.avatar.url,
json: `/json/${encoded.key}`,
reply: `/reply/${encoded.key}`,
replyAll: `/reply-all/${encoded.key}`
}
const isPrivate = Boolean(msg.value.meta.private)
const isThreadTarget = Boolean(lodash.get(
msg,
'value.meta.thread.target',
false
))
const isReply = Boolean(lodash.get(
msg,
'value.meta.thread.reply',
false
))
2019-08-15 01:10:22 +00:00
const { name } = msg.value.meta.author
2019-06-28 20:55:05 +00:00
const timeAgo = msg.value.meta.timestamp.received.since
const depth = lodash.get(msg, 'value.meta.thread.depth', 0)
const markdownContent = msg.value.meta.md.block()
2019-08-13 20:53:11 +00:00
const hasContentWarning = typeof msg.value.content.contentWarning === 'string'
2019-06-28 20:55:05 +00:00
const likeButton = msg.value.meta.voted
? { value: 0, class: 'liked' }
: { value: 1, class: null }
const likeCount = msg.value.meta.votes.length
2019-06-28 20:55:05 +00:00
const parentLink = msg.value.content.root != null
? a({ href: url.parent }, 'parent')
: null
const messageClasses = ['message']
if (isPrivate) {
messageClasses.push('private')
}
if (isThreadTarget) {
messageClasses.push('thread-target')
}
if (isReply) {
messageClasses.push('reply')
}
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 })
2019-08-13 20:53:11 +00:00
const articleContent = hasContentWarning
? details(
summary(msg.value.content.contentWarning),
articleElement
)
: articleElement
const fragment =
2019-06-28 20:55:05 +00:00
section({
id: msg.key,
class: messageClasses.join(' '),
style: `border-left: ${depth}rem solid var(--bg-status);`
2019-06-28 20:55:05 +00:00
},
header({ class: 'metadata' },
a({ href: url.author },
2019-09-16 19:53:51 +00:00
img({ class: 'avatar', src: url.avatar, alt: '' })),
span({ class: 'text' },
span({ class: 'author' },
2019-08-15 01:10:22 +00:00
a({ href: url.author }, name)),
2019-11-29 20:50:18 +00:00
isPrivate ? ' privately 🔒' : null,
span(` ${msg.value.meta.postType}`),
span(` ${timeAgo} ago`),
':'
)),
2019-08-13 20:53:11 +00:00
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
},
2019-08-15 01:10:22 +00:00
`${likeCount}`)),
isPrivate ? null : a({ href: url.reply }, 'reply'),
isPrivate ? null : a({ href: url.replyAll }, 'reply all'),
a({ href: url.link }, 'link'),
parentLink,
a({ href: url.json }, 'json')
2019-08-15 01:10:22 +00:00
))
return fragment
}