Setup.
This commit is contained in:
commit
f79ef61011
|
@ -0,0 +1 @@
|
||||||
|
/public/
|
|
@ -0,0 +1,3 @@
|
||||||
|
[submodule "themes/nocolor"]
|
||||||
|
path = themes/nocolor
|
||||||
|
url = https://schlomp.space/tastytea/hugo-theme-nocolor.git
|
|
@ -0,0 +1,12 @@
|
||||||
|
---
|
||||||
|
title: "{{ replace .TranslationBaseName "-" " " | title }}"
|
||||||
|
slug: {{ replace .File.TranslationBaseName " " "-" }}
|
||||||
|
description: null
|
||||||
|
date: {{ .Date }}
|
||||||
|
type: {{ .Type }}
|
||||||
|
draft: true
|
||||||
|
tags:
|
||||||
|
-
|
||||||
|
---
|
||||||
|
|
||||||
|
:source-highlighter: pygments
|
|
@ -0,0 +1,66 @@
|
||||||
|
baseURL = "https://thoughtpile.tastytea.de/"
|
||||||
|
languageCode = "en"
|
||||||
|
title = "A pile of thoughts"
|
||||||
|
theme = [ "nocolor" ]
|
||||||
|
copyright = "CC BY-NC 4.0"
|
||||||
|
|
||||||
|
pygmentsCodefences = true
|
||||||
|
pygmentsCodeFencesGuessSyntax = false
|
||||||
|
pygmentsUseClasses = true
|
||||||
|
|
||||||
|
canonifyURLs = false
|
||||||
|
Paginate = 5
|
||||||
|
PaginatePath = "page"
|
||||||
|
|
||||||
|
enableGitInfo = true
|
||||||
|
|
||||||
|
[params]
|
||||||
|
subtitle = ""
|
||||||
|
favicon = "favicon.png"
|
||||||
|
datefmt = "2006-01-02"
|
||||||
|
showfullcontent = false
|
||||||
|
opengraph = true
|
||||||
|
schema = true
|
||||||
|
# css = "blog.css"
|
||||||
|
|
||||||
|
[params.comtodon]
|
||||||
|
domain = "likeable.space"
|
||||||
|
|
||||||
|
[taxonomies]
|
||||||
|
tags = "tags"
|
||||||
|
|
||||||
|
[author]
|
||||||
|
name = "tastytea"
|
||||||
|
email = "tastytea@tastytea.de"
|
||||||
|
|
||||||
|
[services.rss]
|
||||||
|
limit = 20
|
||||||
|
|
||||||
|
[menu]
|
||||||
|
[[menu.main]]
|
||||||
|
identifier = "post"
|
||||||
|
name = "Posts"
|
||||||
|
url = "/posts/"
|
||||||
|
weight = 1
|
||||||
|
|
||||||
|
[[menu.main]]
|
||||||
|
identifier = "tags"
|
||||||
|
name = "Tags"
|
||||||
|
url = "/tags/"
|
||||||
|
weight = 2
|
||||||
|
|
||||||
|
[[menu.main]]
|
||||||
|
identifier = "rss"
|
||||||
|
name = "RSS"
|
||||||
|
url = "/index.xml"
|
||||||
|
weight = 3
|
||||||
|
|
||||||
|
[[menu.footer]]
|
||||||
|
name = "Contact"
|
||||||
|
url = "https://tastytea.de/"
|
||||||
|
weight = 1
|
||||||
|
|
||||||
|
[[menu.footer]]
|
||||||
|
name = "Sourcecode"
|
||||||
|
url = "https://schlomp.space/tastytea/thoughtpile"
|
||||||
|
weight = 2
|
|
@ -0,0 +1,106 @@
|
||||||
|
@charset "UTF-8";
|
||||||
|
.comtodon .status {
|
||||||
|
position: relative;
|
||||||
|
padding: 0.5em;
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
margin-left: 1em;
|
||||||
|
border: 0.1em solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .status:nth-child(even) {
|
||||||
|
background-color:#0402;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .status:nth-child(odd) {
|
||||||
|
background-color:#2402;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .status-content, .comtodon .reply-main {
|
||||||
|
margin-bottom: .5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .status-content {
|
||||||
|
padding-left: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .status-content.sensitive {
|
||||||
|
content: 'Sensitive';
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .replies {
|
||||||
|
margin-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon p {
|
||||||
|
margin: .1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .emoji {
|
||||||
|
height: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .author {
|
||||||
|
display: -ms-grid;
|
||||||
|
display: grid;
|
||||||
|
-ms-grid-columns: 3.3em auto;
|
||||||
|
grid-template-columns: 3.3em auto;
|
||||||
|
-ms-grid-rows: (1em)[3];
|
||||||
|
grid-template-rows: repeat(3, 1em);
|
||||||
|
grid-gap: 0.1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .author .avatar {
|
||||||
|
-ms-grid-row: 1;
|
||||||
|
-ms-grid-row-span: 3;
|
||||||
|
-ms-grid-column: 1;
|
||||||
|
grid-area: 1 / 1 / 4 / 1;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon a.author {
|
||||||
|
text-decoration: none;
|
||||||
|
color: var(--blue);
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .author .name {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .author .acct:before {
|
||||||
|
content: '@';
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .date {
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .spoiler {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .reply-main {
|
||||||
|
display: inline-block;
|
||||||
|
padding: .1em .3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .reply-main:after {
|
||||||
|
content: ' in the Fediverse';
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .reply {
|
||||||
|
visibility: hidden;
|
||||||
|
position: absolute;
|
||||||
|
right: .1em;
|
||||||
|
top: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.comtodon .reply:after {
|
||||||
|
content: 'reply';
|
||||||
|
visibility: visible;
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
font-size: .8em;
|
||||||
|
padding: .1em .3em;
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
(function () {
|
||||||
|
function fail(el, text) {
|
||||||
|
el.innerHTML = 'Loading fail =('
|
||||||
|
console.error(text, el)
|
||||||
|
}
|
||||||
|
|
||||||
|
function required(el, field) {
|
||||||
|
const val = el.dataset[field]
|
||||||
|
if (val) {
|
||||||
|
return val
|
||||||
|
}
|
||||||
|
fail(el, `Missing data-${field} attribut`)
|
||||||
|
}
|
||||||
|
|
||||||
|
function h(classes, content, tag = 'div') {
|
||||||
|
return `<${tag} class="${classes}">${content}</${tag}>`
|
||||||
|
}
|
||||||
|
|
||||||
|
const TIMES = new Map([
|
||||||
|
['second', 1000],
|
||||||
|
['minute', 60],
|
||||||
|
['hour', 60],
|
||||||
|
['day', 24],
|
||||||
|
['month', 30.5],
|
||||||
|
['year', 12],
|
||||||
|
['century', 100]
|
||||||
|
])
|
||||||
|
|
||||||
|
function ago(date) {
|
||||||
|
const now = Date.now()
|
||||||
|
const target = Number(new Date(date))
|
||||||
|
|
||||||
|
const prefix = target > now ? 'in ' : ''
|
||||||
|
const milliseconds = Math.floor(Math.abs(target - now))
|
||||||
|
|
||||||
|
let cur = 0
|
||||||
|
let divider = 1
|
||||||
|
let name = 'millisecond'
|
||||||
|
for (const time of TIMES) {
|
||||||
|
divider *= time[1]
|
||||||
|
const next = Math.floor(milliseconds / divider)
|
||||||
|
if (next <= 0) {
|
||||||
|
return `${prefix}${cur} ${name}${cur > 1 ? 's' : ''} ago`
|
||||||
|
}
|
||||||
|
name = time[0]
|
||||||
|
cur = next
|
||||||
|
}
|
||||||
|
return `${prefix}a long time ago`
|
||||||
|
}
|
||||||
|
|
||||||
|
function moji(text, emojis) {
|
||||||
|
for (const emoji of emojis) {
|
||||||
|
text = text.split(`:${emoji.shortcode}:`).join(
|
||||||
|
`<img class="emoji" alt="${emoji.shortcode}" title="${emoji.shortcode}" src="${emoji.static_url}">`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return text
|
||||||
|
}
|
||||||
|
|
||||||
|
function tree(statuses, parent, limit) {
|
||||||
|
const [replies, others] = statuses.reduce(([c, o], s) => (s.in_reply_to_id == parent.id ? [[...c, s], o] : [c, [...o, s]]), [[], []])
|
||||||
|
parent.replies = limit ? replies.map(r => tree(others, r, limit - 1)) : []
|
||||||
|
return parent
|
||||||
|
}
|
||||||
|
|
||||||
|
function html(statuses, domain) {
|
||||||
|
return statuses.map(({ account, created_at, content, id, emojis, sensitive, spoiler_text, replies }) =>
|
||||||
|
h('status', h('date', ago(created_at), 'p') +
|
||||||
|
h('author" target="_blank" target="_blank" href="' + account.url, `<img class="avatar" src="${account.avatar_static}" />` +
|
||||||
|
h('name', moji(account.display_name, account.emojis), 'span') +
|
||||||
|
h('acct', account.acct, 'span'), 'a') +
|
||||||
|
(spoiler_text || sensitive ? h('spoiler', spoiler_text || h('spoiler-empty', 'Sensitive', 'span')) : '') +
|
||||||
|
h('status-content' + (spoiler_text || sensitive ? ' sensitive' : ''), moji(content, emojis)) +
|
||||||
|
(replies ? h('replies', html(replies, domain)) : '') +
|
||||||
|
h(`reply" target="_blank" href="https://${domain}/notice/${id}`, 'Reply', 'a'))).join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
function moderate(statuses, id) {
|
||||||
|
if (!id) {
|
||||||
|
return statuses
|
||||||
|
}
|
||||||
|
const valids = statuses.filter(s => s.account.id == id).map(s => s.in_reply_to_id)
|
||||||
|
return statuses.filter(s => valids.includes(s.id))
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const el of document.getElementsByClassName('comtodon')) {
|
||||||
|
el.innerHTML = '<div class="loading">Loading...</div>'
|
||||||
|
|
||||||
|
const domain = required(el, 'domain')
|
||||||
|
const status = required(el, 'status')
|
||||||
|
if (!domain || !status) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fetch(`https://${domain}/api/v1/statuses/${status}/context`)
|
||||||
|
.then(res => res.json())
|
||||||
|
.then(res => {
|
||||||
|
el.innerHTML = h(`reply-main" target=\"_blank\" href="https://${domain}/notice/${status}`, 'Comment', 'a')
|
||||||
|
const statuses = moderate(res.descendants, el.dataset.moderator)
|
||||||
|
if (statuses) {
|
||||||
|
el.innerHTML += html('deep' in el.dataset ? tree(statuses, { id: status }, el.dataset.deep || -1).replies : statuses, domain)
|
||||||
|
} else {
|
||||||
|
el.innerHTML += h('empty', 'Any comment')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => fail(el, 'Request fail'))
|
||||||
|
}
|
||||||
|
})()
|
Binary file not shown.
After Width: | Height: | Size: 2.1 KiB |
|
@ -0,0 +1 @@
|
||||||
|
Subproject commit fdf4359998d92aadf25a3f7fc7232341346aec9c
|
Reference in New Issue