Compare commits
6
Commits
693bc08e61
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ebee3479b1
|
||
|
|
ca4231f8b0
|
||
|
|
a28cc7cd39
|
||
|
|
9d6cc301e8
|
||
|
|
2b68602f86
|
||
|
|
32f457b4cd
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -3,6 +3,9 @@
|
||||
padding: 1em;
|
||||
padding-top: 0.3em;
|
||||
}
|
||||
.mastodon-comments-top {
|
||||
padding-bottom: 1.5em;
|
||||
}
|
||||
.mastodon-comment {
|
||||
background-color: var(--background-color);
|
||||
border-radius: var(--card-border-radius);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/* PrismJS 1.29.0
|
||||
https://prismjs.com/download.html#themes=prism-twilight&languages=markup+css+clike+javascript+go+go-module+ruby+typescript&plugins=line-highlight+line-numbers+toolbar+copy-to-clipboard */
|
||||
code[class*=language-],pre[class*=language-]{color:#fff;background:0 0;font-family:'JetBrains Mono',Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;text-shadow:0 -.1em .2em #000;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}:not(pre)>code[class*=language-],pre[class*=language-]{background:#141414}pre[class*=language-]{border-radius:.5em;border:.3em solid #545454;box-shadow:1px 1px .5em #000 inset;margin:.5em 0;overflow:auto;padding:1em}pre[class*=language-]::-moz-selection{background:#27292a}pre[class*=language-]::selection{background:#27292a}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:hsla(0,0%,93%,.15)}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:hsla(0,0%,93%,.15)}:not(pre)>code[class*=language-]{border-radius:.3em;border:.13em solid #545454;box-shadow:1px 1px .3em -.1em #000 inset;padding:.15em .2em .05em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#777}.token.punctuation{opacity:.7}.token.namespace{opacity:.7}.token.boolean,.token.deleted,.token.number,.token.tag{color:#ce6849}.token.builtin,.token.constant,.token.keyword,.token.property,.token.selector,.token.symbol{color:#f9ed99}.language-css .token.string,.style .token.string,.token.attr-name,.token.attr-value,.token.char,.token.entity,.token.inserted,.token.operator,.token.string,.token.url,.token.variable{color:#909e6a}.token.atrule{color:#7385a5}.token.important,.token.regex{color:#e8c062}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.language-markup .token.attr-name,.language-markup .token.punctuation,.language-markup .token.tag{color:#ac885c}.token{position:relative;z-index:1}.line-highlight.line-highlight{background:hsla(0,0%,33%,.25);background:linear-gradient(to right,hsla(0,0%,33%,.1) 70%,hsla(0,0%,33%,0));border-bottom:1px dashed #545454;border-top:1px dashed #545454;margin-top:.75em;z-index:0}.line-highlight.line-highlight:before,.line-highlight.line-highlight[data-end]:after{background-color:#8693a6;color:#f4f1ef}
|
||||
https://prismjs.com/download.html#themes=prism-twilight&languages=markup+css+clike+javascript+bash+go+go-module+handlebars+json+markup-templating+ruby+typescript+yaml&plugins=line-highlight+line-numbers+toolbar+copy-to-clipboard */
|
||||
code[class*=language-],pre[class*=language-]{color:#fff;background:0 0;font-family:Consolas,Monaco,'Andale Mono','Ubuntu Mono',monospace;font-size:1em;text-align:left;text-shadow:0 -.1em .2em #000;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;-moz-hyphens:none;-ms-hyphens:none;hyphens:none}:not(pre)>code[class*=language-],pre[class*=language-]{background:#141414}pre[class*=language-]{border-radius:.5em;border:.3em solid #545454;box-shadow:1px 1px .5em #000 inset;margin:.5em 0;overflow:auto;padding:1em}pre[class*=language-]::-moz-selection{background:#27292a}pre[class*=language-]::selection{background:#27292a}code[class*=language-] ::-moz-selection,code[class*=language-]::-moz-selection,pre[class*=language-] ::-moz-selection,pre[class*=language-]::-moz-selection{text-shadow:none;background:hsla(0,0%,93%,.15)}code[class*=language-] ::selection,code[class*=language-]::selection,pre[class*=language-] ::selection,pre[class*=language-]::selection{text-shadow:none;background:hsla(0,0%,93%,.15)}:not(pre)>code[class*=language-]{border-radius:.3em;border:.13em solid #545454;box-shadow:1px 1px .3em -.1em #000 inset;padding:.15em .2em .05em;white-space:normal}.token.cdata,.token.comment,.token.doctype,.token.prolog{color:#777}.token.punctuation{opacity:.7}.token.namespace{opacity:.7}.token.boolean,.token.deleted,.token.number,.token.tag{color:#ce6849}.token.builtin,.token.constant,.token.keyword,.token.property,.token.selector,.token.symbol{color:#f9ed99}.language-css .token.string,.style .token.string,.token.attr-name,.token.attr-value,.token.char,.token.entity,.token.inserted,.token.operator,.token.string,.token.url,.token.variable{color:#909e6a}.token.atrule{color:#7385a5}.token.important,.token.regex{color:#e8c062}.token.bold,.token.important{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.language-markup .token.attr-name,.language-markup .token.punctuation,.language-markup .token.tag{color:#ac885c}.token{position:relative;z-index:1}.line-highlight.line-highlight{background:hsla(0,0%,33%,.25);background:linear-gradient(to right,hsla(0,0%,33%,.1) 70%,hsla(0,0%,33%,0));border-bottom:1px dashed #545454;border-top:1px dashed #545454;margin-top:.75em;z-index:0}.line-highlight.line-highlight:before,.line-highlight.line-highlight[data-end]:after{background-color:#8693a6;color:#f4f1ef}
|
||||
pre[data-line]{position:relative;padding:1em 0 1em 3em}.line-highlight{position:absolute;left:0;right:0;padding:inherit 0;margin-top:1em;background:hsla(24,20%,50%,.08);background:linear-gradient(to right,hsla(24,20%,50%,.1) 70%,hsla(24,20%,50%,0));pointer-events:none;line-height:inherit;white-space:pre}@media print{.line-highlight{-webkit-print-color-adjust:exact;color-adjust:exact}}.line-highlight:before,.line-highlight[data-end]:after{content:attr(data-start);position:absolute;top:.4em;left:.6em;min-width:1em;padding:0 .5em;background-color:hsla(24,20%,50%,.4);color:#f4f1ef;font:bold 65%/1.5 sans-serif;text-align:center;vertical-align:.3em;border-radius:999px;text-shadow:none;box-shadow:0 1px #fff}.line-highlight[data-end]:after{content:attr(data-end);top:auto;bottom:.4em}.line-numbers .line-highlight:after,.line-numbers .line-highlight:before{content:none}pre[id].linkable-line-numbers span.line-numbers-rows{pointer-events:all}pre[id].linkable-line-numbers span.line-numbers-rows>span:before{cursor:pointer}pre[id].linkable-line-numbers span.line-numbers-rows>span:hover:before{background-color:rgba(128,128,128,.2)}
|
||||
pre[class*=language-].line-numbers{position:relative;padding-left:3.8em;counter-reset:linenumber}pre[class*=language-].line-numbers>code{position:relative;white-space:inherit}.line-numbers .line-numbers-rows{position:absolute;pointer-events:none;top:0;font-size:100%;left:-3.8em;width:3em;letter-spacing:-1px;border-right:1px solid #999;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.line-numbers-rows>span{display:block;counter-increment:linenumber}.line-numbers-rows>span:before{content:counter(linenumber);color:#999;display:block;padding-right:.8em;text-align:right}
|
||||
div.code-toolbar{position:relative}div.code-toolbar>.toolbar{position:absolute;z-index:10;top:.3em;right:.2em;transition:opacity .3s ease-in-out;opacity:0}div.code-toolbar:hover>.toolbar{opacity:1}div.code-toolbar:focus-within>.toolbar{opacity:1}div.code-toolbar>.toolbar>.toolbar-item{display:inline-block}div.code-toolbar>.toolbar>.toolbar-item>a{cursor:pointer}div.code-toolbar>.toolbar>.toolbar-item>button{background:0 0;border:0;color:inherit;font:inherit;line-height:normal;overflow:visible;padding:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none}div.code-toolbar>.toolbar>.toolbar-item>a,div.code-toolbar>.toolbar>.toolbar-item>button,div.code-toolbar>.toolbar>.toolbar-item>span{color:#bbb;font-size:.8em;padding:0 .5em;background:#f5f2f0;background:rgba(224,224,224,.2);box-shadow:0 2px 0 0 rgba(0,0,0,.2);border-radius:.5em}div.code-toolbar>.toolbar>.toolbar-item>a:focus,div.code-toolbar>.toolbar>.toolbar-item>a:hover,div.code-toolbar>.toolbar>.toolbar-item>button:focus,div.code-toolbar>.toolbar>.toolbar-item>button:hover,div.code-toolbar>.toolbar>.toolbar-item>span:focus,div.code-toolbar>.toolbar>.toolbar-item>span:hover{color:inherit;text-decoration:none}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,6 +1,7 @@
|
||||
const MASTODON_ACCOUNT_ID = '109285376472065471'
|
||||
const MASTODON_HOST = 'social.sd.ai'
|
||||
|
||||
// Copies the text from an element to the clipboard, and flashes the element to provide visual feedback
|
||||
async function copyElementTextToClipboard(e)
|
||||
{
|
||||
const text = e.textContent
|
||||
@@ -12,6 +13,7 @@ async function copyElementTextToClipboard(e)
|
||||
}, 600);
|
||||
}
|
||||
|
||||
// sanitise text content for display
|
||||
function escapeHtml(unsafe) {
|
||||
return unsafe
|
||||
.replace(/&/g, "&")
|
||||
@@ -21,16 +23,24 @@ function escapeHtml(unsafe) {
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
|
||||
// renders the content - provides an array of toots, the element to add the content to and whether to show a copyable link for replies
|
||||
function renderMastodonContent(toots, parentElement, showLink) {
|
||||
// clear the parent element so that we can add the new content
|
||||
parentElement.innerHTML = ''
|
||||
// add a simple "no comments" message if there are no toots
|
||||
if (!Array.isArray(toots) || toots.length === 0) {
|
||||
document.getElementById('mastodon-comments-list').innerHTML = "<div class='mastodon-comment'>No comments (yet)!</div>"
|
||||
return
|
||||
}
|
||||
|
||||
// render each toot
|
||||
for (const toot of toots) {
|
||||
if (toot.sensitive) {
|
||||
// don't display toots marked as sensitive
|
||||
continue
|
||||
}
|
||||
|
||||
// sanitise the toot content for display, including correctly rendering custom emojis
|
||||
toot.account.display_name = escapeHtml(toot.account.display_name)
|
||||
toot.account.emojis.forEach(emoji => {
|
||||
toot.account.display_name = toot.account.display_name.replace(`:${emoji.shortcode}:`,
|
||||
@@ -40,6 +50,8 @@ function renderMastodonContent(toots, parentElement, showLink) {
|
||||
toot.content = toot.content.replace(`:${emoji.shortcode}:`,
|
||||
`<img src="${escapeHtml(emoji.static_url)}" alt="Emoji ${emoji.shortcode}" class="mastodon-emoji" />`);
|
||||
})
|
||||
|
||||
// create a block of HTML content including the toot data
|
||||
const comment =
|
||||
`<div class="mastodon-comment">
|
||||
<div class="mastodon-avatar">
|
||||
@@ -69,30 +81,44 @@ function renderMastodonContent(toots, parentElement, showLink) {
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
// Use DOMPurify to create a sanitised element for the toot
|
||||
const child = DOMPurify.sanitize(comment, {'RETURN_DOM_FRAGMENT': true});
|
||||
|
||||
// make all toot links clickable
|
||||
const links = child.querySelectorAll('.tootlink');
|
||||
for (const link of links) {
|
||||
link.onclick = function() { return copyElementTextToClipboard(this); }
|
||||
}
|
||||
|
||||
// insert the toot into the DOM
|
||||
parentElement.appendChild(child);
|
||||
}
|
||||
}
|
||||
|
||||
// We set this in the "code injection" footer for any page for which we want to enable comments
|
||||
let MASTODON_POST_ID
|
||||
|
||||
// when the page has finished loading, send a request for the toots
|
||||
document.addEventListener("DOMContentLoaded", async (event) => {
|
||||
let url, isComments
|
||||
// if we're being crawled, don't render comments - may help against spam
|
||||
const isBot = /bot|google|baidu|bing|msn|teoma|slurp|yandex/i
|
||||
.test(navigator.userAgent)
|
||||
|
||||
// if there is a sidebar, we're expecting to load the toots from the main account
|
||||
if (document.getElementsByClassName('gh-sidebar').length > 0) {
|
||||
url = `https://${MASTODON_HOST}/api/v1/accounts/${MASTODON_ACCOUNT_ID}/statuses?exclude_replies=true&exclude_reblogs=true`
|
||||
}
|
||||
// if there's a post ID and we're not a bot, we're expecting to load the replies from a specific toot
|
||||
if (MASTODON_POST_ID && !isBot) {
|
||||
url = `https://${MASTODON_HOST}/api/v1/statuses/${MASTODON_POST_ID}/context`
|
||||
isComments = true
|
||||
}
|
||||
// find the element to append the content to - if there isn't one, we don't need to query
|
||||
const element = document.getElementById('mastodon-comments-list')
|
||||
if (url && element) {
|
||||
// populate the link to the source toot, if necessary (for replies)
|
||||
const linkElement = document.getElementById('toot-link-top')
|
||||
const clipElement = document.getElementById('toot-link-clip')
|
||||
const tootUrl = `https://${MASTODON_HOST}/@s/${MASTODON_POST_ID}`
|
||||
@@ -102,11 +128,13 @@ document.addEventListener("DOMContentLoaded", async (event) => {
|
||||
if (clipElement) {
|
||||
clipElement.innerText = tootUrl
|
||||
}
|
||||
// fetch the data from Mastodon
|
||||
const response = await fetch(url)
|
||||
let content = await response.json()
|
||||
if (isComments) {
|
||||
content = content.descendants
|
||||
}
|
||||
// render the content into the page
|
||||
const header = document.getElementById('mastodon-comments-header')
|
||||
if (header) {
|
||||
header.style.display = ''
|
||||
|
||||
@@ -49,9 +49,14 @@
|
||||
|
||||
</article>
|
||||
|
||||
|
||||
<section class="gh-comments gh-canvas">
|
||||
|
||||
<div id="mastodon-comments-header" style="display: none;">
|
||||
|
||||
<div class="mastodon-comments-top">
|
||||
<hr/>
|
||||
</div>
|
||||
|
||||
<h2>Comments</h2>
|
||||
<p>Comments powered by Mastodon. Reply to <a id="toot-link-top">this status</a> to comment.</p>
|
||||
<div class="tootlink-tip">
|
||||
@@ -74,7 +79,7 @@
|
||||
|
||||
{{/post}}
|
||||
|
||||
{{#get "posts" include="authors" filter="id:-{{post.id}}" limit="4" as |next|}}
|
||||
{{#get "posts" include="authors,tags" filter="id:-{{post.id}}" limit="4" as |next|}}
|
||||
{{#if next}}
|
||||
<section class="gh-container is-grid gh-outer">
|
||||
<div class="gh-container-inner gh-inner">
|
||||
|
||||
Reference in New Issue
Block a user