Switched comment system to comtodon.
This commit is contained in:
parent
45488a2c62
commit
d3bfd509b9
|
@ -22,6 +22,9 @@ enableGitInfo = true
|
|||
opengraph = true
|
||||
schema = true
|
||||
|
||||
[params.comtodon]
|
||||
domain = "likeable.space"
|
||||
|
||||
[taxonomies]
|
||||
tags = "tags"
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ description: "Edit remote files with Emacs using SSH and a wrapper for emacsclie
|
|||
date: "2019-05-08T15:59:00+02:00"
|
||||
draft: false
|
||||
tags: ["emacs", "ssh"]
|
||||
comtodon: 9ibPpjSsYeNmHrbBDc
|
||||
---
|
||||
|
||||
It took me a long time to collect all the bits and pieces I needed to make
|
||||
|
@ -234,7 +235,3 @@ echo 'Defaults env_keep += "SSH_CONNECTION"' >> /etc/sudoers.d/ssh_vars
|
|||
* Updated 2019-10-06: Support files with spaces in emacsremote and allow to
|
||||
open files the user can't read (for use with emacsremote --sudo).
|
||||
* Updated 2019-10-17: Added Zsh-hack to prevent hanging TRAMP-connections.
|
||||
|
||||
== Comments
|
||||
|
||||
{{% mastodon-api-comments instance="likeable.space" status_id="9ibPpjSsYeNmHrbBDc" %}}
|
||||
|
|
|
@ -4,6 +4,7 @@ description: "How to archive articles you read online locally and how to find th
|
|||
date: "2019-09-26T06:10:07+02:00"
|
||||
draft: false
|
||||
tags: ["remwharead", "bookmarks", "archive", "Tooting my own horn"]
|
||||
comtodon: 9nIqtmAXvu4harUb7Q
|
||||
---
|
||||
|
||||
:wp-asciidoc: https://en.wikipedia.org/wiki/AsciiDoc
|
||||
|
@ -141,7 +142,3 @@ remwharead -e rss -T $(date -d "-1 week" -I),$(date -Iminutes) \
|
|||
----
|
||||
|
||||
TIP: Put that script into `/etc/cron.hourly/` to update your feed once an hour.
|
||||
|
||||
== Comments
|
||||
|
||||
{{% mastodon-api-comments instance="likeable.space" status_id="9nIqtmAXvu4harUb7Q" %}}
|
||||
|
|
|
@ -109,7 +109,3 @@ In your Gitea directory, create `custom/templates/custom/header.tmpl`.
|
|||
}
|
||||
</style>{{< / highlight >}}
|
||||
----
|
||||
|
||||
== Comments
|
||||
|
||||
{{% mastodon-api-comments instance="soc.ialis.me" status_id="101483651770835303" %}}
|
||||
|
|
|
@ -6,6 +6,7 @@ draft: false
|
|||
tags:
|
||||
- wireguard
|
||||
- vpn
|
||||
comtodon: 9fqBQKGZa6qMf98wIC
|
||||
---
|
||||
|
||||
I wanted to create a https://en.wikipedia.org/wiki/WireGuard[WireGuard] VPN with
|
||||
|
@ -170,7 +171,3 @@ by Stavros Korokithakis helped me a great deal in understanding WireGuard.
|
|||
|
||||
* Updated 2019-02-16 to include IP forwarding.
|
||||
* Updated 2019-02-16 with information on how to turn SLAAC back on.
|
||||
|
||||
== Comments
|
||||
|
||||
{{% mastodon-api-comments instance="likeable.space" status_id="9fqBQKGZa6qMf98wIC" %}}
|
||||
|
|
2
content/scripts/jquery-3.4.1.min.js
vendored
2
content/scripts/jquery-3.4.1.min.js
vendored
File diff suppressed because one or more lines are too long
|
@ -1,110 +0,0 @@
|
|||
/* globals MastodonAPI */
|
||||
|
||||
function fetch_mastodon_api_comments(instance, status_id)
|
||||
{
|
||||
const root = document.getElementById("mastodon-api-comments_" + status_id);
|
||||
|
||||
let api = new MastodonAPI(
|
||||
{
|
||||
instance: "https://" + instance,
|
||||
api_user_token: ""
|
||||
});
|
||||
|
||||
// Get the URL of the status and write the intro.
|
||||
api.get("statuses/" + status_id, function(data)
|
||||
{
|
||||
root.appendChild(comments_intro(data.url));
|
||||
});
|
||||
|
||||
// Get all the replies to the status and write them to the page.
|
||||
api.get("statuses/" + status_id + "/context", function(data)
|
||||
{
|
||||
write_comments(root, data);
|
||||
});
|
||||
}
|
||||
|
||||
function comments_intro(url)
|
||||
{
|
||||
const p = document.createElement("p");
|
||||
const a = document.createElement("a");
|
||||
p.appendChild(document.createTextNode("You can "));
|
||||
p.setAttribute("class", "mastodon-api-comment-intro");
|
||||
a.setAttribute("href", url);
|
||||
a.appendChild(
|
||||
document.createTextNode("comment on this post in the Fediverse"));
|
||||
p.appendChild(a);
|
||||
p.appendChild(document.createTextNode("."));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
function write_comments(root, data)
|
||||
{
|
||||
for (const status of data.descendants)
|
||||
{
|
||||
const content = add_emojis(status.content, status.emojis);
|
||||
|
||||
const div = document.createElement("div");
|
||||
div.setAttribute("class", "mastodon-api-comment");
|
||||
div.appendChild(author_html(status));
|
||||
if (status.spoiler_text.length > 0)
|
||||
{
|
||||
div.appendChild(subject_html(status));
|
||||
}
|
||||
const content_p = document.createElement("p");
|
||||
content_p.setAttribute("class", "mastodon-api-comment-content");
|
||||
content_p.innerHTML = content;
|
||||
div.appendChild(content_p);
|
||||
root.appendChild(div);
|
||||
}
|
||||
}
|
||||
|
||||
function add_emojis(text, emojis)
|
||||
{
|
||||
for (const emoji of emojis)
|
||||
{
|
||||
text = text.replace(
|
||||
':' + emoji.shortcode + ':',
|
||||
'<img class="mastodon-api-comment-emoji" src="' + emoji.url + '">');
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
function author_html(status)
|
||||
{
|
||||
const p = document.createElement("p");
|
||||
p.setAttribute("class", "mastodon-api-comment-author");
|
||||
|
||||
const img = document.createElement("img");
|
||||
img.setAttribute("class", "mastodon-api-comment-avatar");
|
||||
img.setAttribute("src", status.account.avatar);
|
||||
p.appendChild(img);
|
||||
p.innerHTML += " ";
|
||||
|
||||
const strong = document.createElement("strong");
|
||||
strong.appendChild(document.createTextNode(status.account.display_name));
|
||||
p.appendChild(strong);
|
||||
|
||||
p.appendChild(
|
||||
document.createTextNode(" (" + status.account.acct + ") wrote on "
|
||||
+ get_status_time(status) + ":"));
|
||||
return p;
|
||||
}
|
||||
|
||||
function subject_html(status)
|
||||
{
|
||||
const p = document.createElement("p");
|
||||
p.setAttribute("class", "mastodon-api-comment-subject");
|
||||
const subject = document.createElement("strong");
|
||||
subject.innerHTML += add_emojis(status.spoiler_text, status.emojis);
|
||||
p.appendChild(subject);
|
||||
return p;
|
||||
}
|
||||
|
||||
// Human readable time, YYYY-MM-DD HH:MM.
|
||||
function get_status_time(status)
|
||||
{
|
||||
return status.created_at.substr(0, 16).replace('T', ' ');
|
||||
}
|
|
@ -1,223 +0,0 @@
|
|||
// mastodon javascript lib
|
||||
// by @kirschn@pleasehug.me 2017
|
||||
// no fucking copyright
|
||||
// do whatever you want with it
|
||||
// but please don't hurt it (and keep this header)
|
||||
|
||||
|
||||
var MastodonAPI = function (config) {
|
||||
var apiBase = config.instance + "/api/v1/";
|
||||
|
||||
function checkArgs(args) {
|
||||
var checkedArgs;
|
||||
if (typeof args[1] === "function") {
|
||||
checkedArgs = { data: {}, callback: args[1] };
|
||||
} else {
|
||||
checkedArgs = { data: args[1], callback: args[2] };
|
||||
}
|
||||
|
||||
return checkedArgs;
|
||||
}
|
||||
|
||||
function addAuthorizationHeader(headers, token) {
|
||||
if (token) {
|
||||
headers.Authorization = "Bearer " + token;
|
||||
}
|
||||
|
||||
return headers;
|
||||
}
|
||||
|
||||
function onAjaxSuccess(url, op, callback, logData) {
|
||||
return function (data, textStatus, xhr) {
|
||||
console.log("Successful " + op + " API request to " + url,
|
||||
", status: " + textStatus,
|
||||
", HTTP status: " + xhr.status,
|
||||
", data: " + (logData ? JSON.stringify(data) : "<skipped>"));
|
||||
|
||||
if (typeof callback !== "undefined") {
|
||||
callback(data, textStatus);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function onAjaxError(url, op) {
|
||||
return function (xhr, textStatus, errorThrown) {
|
||||
console.error("Failed " + op + " API request to " + url,
|
||||
", status: " + textStatus,
|
||||
", error: " + errorThrown,
|
||||
", HTTP status: " + xhr.status,
|
||||
", response JSON: " + JSON.stringify(xhr.responseJSON));
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
setConfig: function (key, value) {
|
||||
// modify initial config afterwards
|
||||
config[key] = value;
|
||||
},
|
||||
getConfig: function (key) {
|
||||
// get config key
|
||||
return config[key];
|
||||
},
|
||||
get: function (endpoint) {
|
||||
// for GET API calls
|
||||
// can be called with two or three parameters
|
||||
// endpoint, callback
|
||||
// or
|
||||
// endpoint, queryData, callback
|
||||
// where queryData is an object { paramname1: "paramvalue1", paramname2: paramvalue2 }
|
||||
|
||||
var args = checkArgs(arguments);
|
||||
var queryData = args.data;
|
||||
var callback = args.callback;
|
||||
var url = apiBase + endpoint;
|
||||
|
||||
// ajax function
|
||||
return $.ajax({
|
||||
url: url,
|
||||
type: "GET",
|
||||
data: queryData,
|
||||
headers: addAuthorizationHeader({}, config.api_user_token),
|
||||
success: onAjaxSuccess(url, "GET", callback, false),
|
||||
error: onAjaxError(url, "GET")
|
||||
});
|
||||
},
|
||||
patch: function (endpoint) {
|
||||
// for PATCH API calls
|
||||
var args = checkArgs(arguments);
|
||||
var postData = args.data;
|
||||
var callback = args.callback;
|
||||
var url = apiBase + endpoint;
|
||||
|
||||
return $.ajax({
|
||||
url: url,
|
||||
type: "PATCH",
|
||||
data: postData,
|
||||
headers: addAuthorizationHeader({}, config.api_user_token),
|
||||
success: onAjaxSuccess(url, "POST", callback, false),
|
||||
error: onAjaxError(url, "POST")
|
||||
});
|
||||
},
|
||||
post: function (endpoint) {
|
||||
// for POST API calls
|
||||
var args = checkArgs(arguments);
|
||||
var postData = args.data;
|
||||
var callback = args.callback;
|
||||
var url = apiBase + endpoint;
|
||||
|
||||
return $.ajax({
|
||||
url: url,
|
||||
type: "POST",
|
||||
data: postData,
|
||||
headers: addAuthorizationHeader({}, config.api_user_token),
|
||||
success: onAjaxSuccess(url, "POST", callback, false),
|
||||
error: onAjaxError(url, "POST")
|
||||
});
|
||||
},
|
||||
postMedia: function (endpoint) {
|
||||
// for POST API calls
|
||||
var args = checkArgs(arguments);
|
||||
var postData = args.data;
|
||||
var callback = args.callback;
|
||||
var url = apiBase + endpoint;
|
||||
|
||||
return $.ajax({
|
||||
url: url,
|
||||
type: "POST",
|
||||
data: postData,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
headers: addAuthorizationHeader({}, config.api_user_token),
|
||||
success: onAjaxSuccess(url, "POST MEDIA", callback, false),
|
||||
error: onAjaxError(url, "POST MEDIA")
|
||||
});
|
||||
},
|
||||
delete: function (endpoint, callback) {
|
||||
// for DELETE API calls.
|
||||
var url = apiBase + endpoint;
|
||||
return $.ajax({
|
||||
url: url,
|
||||
type: "DELETE",
|
||||
headers: addAuthorizationHeader({}, config.api_user_token),
|
||||
success: onAjaxSuccess(url, "DELETE", callback, false),
|
||||
error: onAjaxError(url, "DELETE")
|
||||
});
|
||||
},
|
||||
stream: function (streamType, onData) {
|
||||
// Event Stream Support
|
||||
// websocket streaming is undocumented. i had to reverse engineer the fucking web client.
|
||||
// streamType is either
|
||||
// user for your local home TL and notifications
|
||||
// public for your federated TL
|
||||
// public:local for your home TL
|
||||
// hashtag&tag=fuckdonaldtrump for the stream of #fuckdonaldtrump
|
||||
// callback gets called whenever new data ist recieved
|
||||
// callback { event: (eventtype), payload: {mastodon object as described in the api docs} }
|
||||
// eventtype could be notification (=notification) or update (= new toot in TL)
|
||||
var es = new WebSocket("wss://" + apiBase.substr(8)
|
||||
+ "streaming?access_token=" + config.api_user_token + "&stream=" + streamType);
|
||||
var listener = function (event) {
|
||||
console.log("Got Data from Stream " + streamType);
|
||||
event = JSON.parse(event.data);
|
||||
event.payload = JSON.parse(event.payload);
|
||||
onData(event);
|
||||
};
|
||||
es.onmessage = listener;
|
||||
},
|
||||
registerApplication: function (client_name, redirect_uri, scopes, website, callback) {
|
||||
// register a new application
|
||||
|
||||
// OAuth Auth flow:
|
||||
// First register the application
|
||||
// 2) get a access code from a user (using the link, generation function below!)
|
||||
// 3) insert the data you got from the application and the code from the user into
|
||||
// getAccessTokenFromAuthCode. Note: scopes has to be an array, every time!
|
||||
// For example ["read", "write"]
|
||||
|
||||
// determine which parameters we got
|
||||
if (website === null) {
|
||||
website = "";
|
||||
}
|
||||
// build scope array to string for the api request
|
||||
if (typeof scopes !== "string") {
|
||||
scopes = scopes.join(" ");
|
||||
}
|
||||
var url = apiBase + "apps";
|
||||
return $.ajax({
|
||||
url: url,
|
||||
type: "POST",
|
||||
data: {
|
||||
client_name: client_name,
|
||||
redirect_uris: redirect_uri,
|
||||
scopes: scopes,
|
||||
website: website
|
||||
},
|
||||
success: onAjaxSuccess(url, "REGISTER", callback, true),
|
||||
error: onAjaxError(url, "REGISTER")
|
||||
});
|
||||
},
|
||||
generateAuthLink: function (client_id, redirect_uri, responseType, scopes) {
|
||||
return config.instance + "/oauth/authorize?client_id=" + client_id + "&redirect_uri=" + redirect_uri +
|
||||
"&response_type=" + responseType + "&scope=" + scopes.join("+");
|
||||
},
|
||||
getAccessTokenFromAuthCode: function (client_id, client_secret, redirect_uri, code, callback) {
|
||||
var url = config.instance + "/oauth/token";
|
||||
return $.ajax({
|
||||
url: url,
|
||||
type: "POST",
|
||||
data: {
|
||||
client_id: client_id,
|
||||
client_secret: client_secret,
|
||||
redirect_uri: redirect_uri,
|
||||
grant_type: "authorization_code",
|
||||
code: code
|
||||
},
|
||||
success: onAjaxSuccess(url, "TOKEN", callback, true),
|
||||
error: onAjaxError(url, "TOKEN")
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// node.js
|
||||
if (typeof module !== "undefined") { module.exports = MastodonAPI; }
|
|
@ -1,3 +0,0 @@
|
|||
<script type="application/javascript" src="/scripts/jquery-3.4.1.min.js"></script>
|
||||
<script type="application/javascript" src="/scripts/mastodon.js"></script>
|
||||
<script type="application/javascript" src="/scripts/mastodon-api-comments.js"></script>
|
|
@ -1,10 +0,0 @@
|
|||
{{ $instance := .Get "instance" | default "" }}
|
||||
{{ $status_id := .Get "status_id" | default "" }}
|
||||
|
||||
{{ partial "mastodon-api-comments-scripts.html" . }}
|
||||
<style type="text/css">.mastodon-api-comment-avatar,.mastodon-api-comment-emoji{height:1em;}</style>
|
||||
<div id="mastodon-api-comments_{{ $status_id }}" class="mastodon-api-comments"></div>
|
||||
<noscript><p>Comments only work with JavaScript enabled.</p></noscript>
|
||||
<script type="application/javascript">
|
||||
fetch_mastodon_api_comments("{{ $instance }}", "{{ $status_id }}");
|
||||
</script>
|
106
static/comtodon.css
Normal file
106
static/comtodon.css
Normal file
|
@ -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;
|
||||
}
|
108
static/comtodon.js
Normal file
108
static/comtodon.js
Normal file
|
@ -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}/interact/${id}?type=reply`, '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}/interact/${status}?type=reply`, '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'))
|
||||
}
|
||||
})()
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
@ -73,10 +73,6 @@ for file in style.css style-compat.css; do
|
|||
sed -i 's/$/.right{float:right}/' tastytea/static/assets/${file}
|
||||
sed -i 's/$/.left{float:left}/' tastytea/static/assets/${file}
|
||||
|
||||
sed -i 's/$/.mastodon-api-comment{margin-left:1em;margin-bottom:0.4em;padding:0 0.4em;border:0.1em solid black;}/' tastytea/static/assets/${file}
|
||||
sed -i 's/$/.mastodon-api-comment:nth-child(even){background-color:#0402}/' tastytea/static/assets/${file}
|
||||
sed -i 's/$/.mastodon-api-comment:nth-child(odd){background-color:#2402}/' tastytea/static/assets/${file}
|
||||
|
||||
# Make CSS more readable
|
||||
sed -i 's/}/}\n/g' tastytea/static/assets/${file}
|
||||
sed -i 's/{/ {/g' tastytea/static/assets/${file}
|
||||
|
|
58
themes/tastytea/layouts/partials/footer.html
Normal file
58
themes/tastytea/layouts/partials/footer.html
Normal file
|
@ -0,0 +1,58 @@
|
|||
{{ if .Params.comtodon }}
|
||||
<link rel="stylesheet" href="/comtodon.css"/>
|
||||
<h2 id="comments">Comments</h2>
|
||||
<noscript>Comments work only with JavaScript enabled.</noscript>
|
||||
<div class="comtodon" data-domain="{{ .Site.Params.comtodon.domain }}" data-status="{{ .Params.comtodon }}" {{ with .Site.Params.comtodon.moderator }}data-moderator="{{ . }}"{{ end }}></div>
|
||||
<script src="/comtodon.js" defer></script>
|
||||
{{- end }}
|
||||
|
||||
<div class="footer-content">
|
||||
<div class="pure-menu pure-menu-horizontal">
|
||||
<ul class="pure-menu-list">
|
||||
{{- range .Site.Menus.footer }}
|
||||
<li class="pure-menu-item">
|
||||
{{- if .URL }}
|
||||
<a class="pure-menu-link" href="{{ .URL }}">{{ .Name }}</a>
|
||||
{{- else }}
|
||||
{{ .Name }}
|
||||
{{- end }}
|
||||
</li>
|
||||
{{- end }}
|
||||
{{- with .Site.RSSLink }}
|
||||
<li class="pure-menu-item">
|
||||
<a href="{{ . }}" class="pure-menu-link">RSS</a>
|
||||
</li>
|
||||
{{- end }}
|
||||
</ul>
|
||||
</div>
|
||||
{{- with .Site.Copyright }}
|
||||
<div class="pure-menu pure-menu-horizontal">
|
||||
<ul class="pure-menu-list">
|
||||
<li class="pure-menu-item pure-menu-disabled">
|
||||
© {{ now.Format "2006" }} — {{ . }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{- end }}
|
||||
</div>
|
||||
<script>
|
||||
function setElementsClass(selector, value) {
|
||||
Array.prototype.forEach.call(
|
||||
document.querySelectorAll(selector),
|
||||
function(elem) { elem.className = value; }
|
||||
);
|
||||
}
|
||||
|
||||
setElementsClass('img', 'pure-img');
|
||||
setElementsClass('table', 'pure-table');
|
||||
|
||||
function onResize() {
|
||||
setElementsClass(
|
||||
'.pure-menu', document.documentElement.clientWidth >= 568 ?
|
||||
'pure-menu pure-menu-horizontal' : 'pure-menu'
|
||||
);
|
||||
}
|
||||
onResize();
|
||||
window.addEventListener('resize', onResize);
|
||||
});
|
||||
</script>
|
|
@ -301,6 +301,3 @@ div.tip td.icon {color:var(--blue)}
|
|||
div.important td.icon {color:var(--yellow)}
|
||||
.right {float:right}
|
||||
.left {float:left}
|
||||
.mastodon-api-comment {margin-left:1em; margin-bottom:0.4em; padding:0 0.4em; border:0.1em solid black; }
|
||||
.mastodon-api-comment:nth-child(even) {background-color:#0402}
|
||||
.mastodon-api-comment:nth-child(odd) {background-color:#2402}
|
||||
|
|
|
@ -334,6 +334,3 @@ div.tip td.icon {color:var(--blue)}
|
|||
div.important td.icon {color:var(--yellow)}
|
||||
.right {float:right}
|
||||
.left {float:left}
|
||||
.mastodon-api-comment {margin-left:1em; margin-bottom:0.4em; padding:0 0.4em; border:0.1em solid black; }
|
||||
.mastodon-api-comment:nth-child(even) {background-color:#0402}
|
||||
.mastodon-api-comment:nth-child(odd) {background-color:#2402}
|
||||
|
|
Loading…
Reference in New Issue
Block a user