Browse Source

v1 fediverse comments

master
Jon Kelbie 5 months ago
parent
commit
db61f6453e
  1. 4
      content/note/2023/12/656da999/index.md
  2. 4
      content/note/2023/12/656fdf77/index.md
  3. 106
      layouts/partials/mastodon/mastodon.html
  4. 3
      static/assets/js/purify.min.js
  5. 118
      static/css/mastodon.css
  6. 8
      themes/nipponalba/layouts/_default/single.html
  7. 1
      themes/nipponalba/layouts/partials/head.html
  8. 17
      themes/nipponalba/static/css/style.css

4
content/note/2023/12/656da999/index.md

@ -1,4 +1,8 @@
---
comments:
host: gts.kelbie.scot
username: jon
id: 01HGT5XDS6Z3K7M743QNR72NZX
category:
- 'food mention'
date: '2023-12-04 19:27:37'

4
content/note/2023/12/656fdf77/index.md

@ -1,4 +1,8 @@
---
comments:
host: gts.kelbie.scot
username: jon
id: 01HGYG28P2RN715Y2C1XPN5SRS
category:
- brewery
date: '2023-12-06 11:41:59'

106
layouts/partials/mastodon/mastodon.html

@ -0,0 +1,106 @@
{{ with .Params.comments }}
<div class="article-content">
<h2>Comments</h2>
<p>You can use your Mastodon account to reply to this <a class="button" href="https://{{ .host }}/@{{ .username }}/statuses/{{ .id }}">post</a>.</p>
<p><button class="button" id="replyButton" href="https://{{ .host }}/@{{ .username }}/statuses/{{ .id }}">Reply</button></p>
<dialog id="toot-reply" class="mastodon" data-component="dialog">
<h3>Reply to {{ .username }}'s post</h3>
<p>
With an account on the Fediverse or Mastodon, you can respond to this post.
Since Mastodon is decentralized, you can use your existing account hosted by another Mastodon server or compatible platform if you don't have an account on this one.
</p>
<p>Copy and paste this URL into the search field of your favourite Fediverse app or the web interface of your Mastodon server.</p>
<div class="copypaste">
<input type="text" readonly="" value="https://{{ .host }}/@{{ .username }}/statuses/{{ .id }}">
<button class="button" id="copyButton">Copy</button>
<button class="button" id="cancelButton">Close</button>
</div>
</dialog>
<p id="mastodon-comments-list"><button id="load-comment" class="button">Load comments</button></p>
<noscript><p>You need JavaScript to view the comments.</p></noscript>
<script src="/assets/js/purify.min.js"></script>
<script type="text/javascript">
const dialog = document.querySelector('dialog');
document.getElementById('replyButton').addEventListener('click', () => {
dialog.showModal();
});
document.getElementById('copyButton').addEventListener('click', () => {
navigator.clipboard.writeText('https://{{ .host }}/@{{ .username }}/statuses/{{ .id }}');
});
document.getElementById('cancelButton').addEventListener('click', () => {
dialog.close();
});
dialog.addEventListener('keydown', e => {
if (e.key === 'Escape') dialog.close();
});
const dateOptions = {
year: "numeric",
month: "numeric",
day: "numeric",
hour: "numeric",
minute: "numeric",
};
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/"/g, "&quot;")
.replace(/'/g, "&#039;");
}
document.getElementById("load-comment").addEventListener("click", function() {
document.getElementById("load-comment").innerHTML = "Loading";
fetch('https://{{ .host }}/api/v1/statuses/{{ .id }}/context')
.then(function(response) {
return response.json();
})
.then(function(data) {
if(data['descendants'] &&
Array.isArray(data['descendants']) &&
data['descendants'].length > 0) {
document.getElementById('mastodon-comments-list').innerHTML = "";
data['descendants'].forEach(function(reply) {
reply.account.display_name = escapeHtml(reply.account.display_name);
reply.account.reply_class = reply.in_reply_to_id == "{{ .id }}" ? "reply-original" : "reply-child";
reply.account.emojis.forEach(emoji => {
reply.account.display_name = reply.account.display_name.replace(`:${emoji.shortcode}:`,
`<img src="${escapeHtml(emoji.static_url)}" alt="Emoji ${emoji.shortcode}" height="20" width="20" />`);
});
mastodonComment =
`<div class="mastodon-wrapper">
<div class="comment-level ${reply.account.reply_class}"><svg viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg" fill="none" transform="rotate(180)"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"> <path stroke="#535358" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5.608 12.526l7.04-6.454C13.931 4.896 16 5.806 16 7.546V11c13 0 11 16 11 16s-4-10-11-10v3.453c0 1.74-2.069 2.65-3.351 1.475l-7.04-6.454a2 2 0 010-2.948z"></path> </g></svg></div>
<div class="mastodon-comment">
<div class="avatar">
<img src="${escapeHtml(reply.account.avatar_static)}" height=60 width=60 alt="">
</div>
<div class="content">
<div class="author">
<a href="${reply.account.url}" rel="nofollow">
<span>${reply.account.display_name}</span>
<span class="disabled">${escapeHtml(reply.account.acct)}</span>
</a>
<a class="date" href="${reply.uri}" rel="nofollow">
${reply.created_at.substr(0, 10)}
</a>
</div>
<div class="mastodon-comment-content">${reply.content}</div>
</div>
</div>
</div>`;
document.getElementById('mastodon-comments-list').appendChild(DOMPurify.sanitize(mastodonComment, {'RETURN_DOM_FRAGMENT': true}));
});
} else {
document.getElementById('mastodon-comments-list').innerHTML = "<p>No comments found</p>";
}
});
});
</script>
</div>
{{ end }}

3
static/assets/js/purify.min.js
File diff suppressed because it is too large
View File

118
static/css/mastodon.css

@ -0,0 +1,118 @@
.mastodon-wrapper {
display: flex;
gap: 3rem;
flex-direction: row;
}
.comment-level {
max-width: 3rem;
min-width: 3rem;
}
.reply-original {
display: none;
}
#article-comments div.reply-original {
display: none;
}
#article-comments div.reply-child {
display: block;
flex: 0 0 1.75rem;
text-align: right;
}
.mastodon-comment {
background-color: #e9e5e5;
border-radius: 10px;
padding: 30px;
margin-bottom: 1rem;
display: flex;
gap: 1rem;
flex-direction: column;
flex-grow: 2;
}
.mastodon-comment .comment {
display: flex;
flex-direction: row;
gap: 1rem;
flex-wrap: true;
}
.mastodon-comment .comment-avatar img {
width: 6rem;
}
.mastodon-comment .content {
flex-grow: 2;
}
.mastodon-comment .comment-author {
display: flex;
flex-direction: column;
}
.mastodon-comment .comment-author-name {
font-weight: bold;
}
.mastodon-comment .comment-author-name a {
display: flex;
align-items: center;
}
.mastodon-comment .comment-author-date {
margin-left: auto;
}
.mastodon-comment .disabled {
color: #34495e;
}
.mastodon-comment-content p:first-child {
margin-top: 0;
}
.mastodon {
--dlg-bg: #282c37;
--dlg-w: 600px;
--dlg-color: #9baec8;
--dlg-button-p: 0.75em 2em;
--dlg-outline-c: #00D9F5;
}
.copypaste {
display: flex;
align-items: center;
gap: 10px;
}
.copypaste input {
display: block;
font-family: inherit;
background: #17191f;
border: 1px solid #8c8dff;
color: #9baec8;
border-radius: 4px;
padding: 6px 9px;
line-height: 22px;
font-size: 14px;
transition: border-color 0.3s linear;
flex: 1 1 auto;
overflow: hidden;
}
.copypaste .button {
border: 10px;
border-radius: 4px;
box-sizing: border-box;
color: #fff;
cursor: pointer;
display: inline-block;
font-family: inherit;
font-size: 15px;
font-weight: 500;
letter-spacing: 0;
line-height: 22px;
overflow: hidden;
padding: 7px 18px;
position: relative;
text-align: center;
text-decoration: none;
text-overflow: ellipsis;
white-space: nowrap;
width: auto;
background-color: #232730;
}
.copypaste .button:hover {
background-color: #16181e;
}

8
themes/nipponalba/layouts/_default/single.html

@ -36,8 +36,8 @@
<hr/>
<section id="interactions"><h4>Interactions</h4>
<section id="interactions_intro">Interactions on this site are possible via <a href="https://cactus.chat" title="Cactus Chat" target="_blank">Cactus Chat</a> or <a href="https://indieweb.org/Webmention" title="Webmention is a web standard for mentions and conversations across the web, a powerful building block that is used for a growing federated network of comments, likes, reposts, and other rich interactions across the decentralized social web." class="u-url" target="_blank">webmentions</a>. Alternatively, contact me via <a href="https://matrix.to/#/@jon:kelbie.scot" class="u-url" target="_blank">matrix</a> or <a href="mailto:jon@kelbie.scot" class="u-url">email</a>.<br/><br/>
<label for="toggle_comments" id="comments_label">Comments</label> | <label for="toggle_webmentions" id="webmentions_label">Webmentions</label></section>
<input type="radio" name="interactions" id="toggle_comments" checked="checked"><input type="radio" name="interactions" id="toggle_webmentions">
<label for="toggle_comments" id="comments_label">Comments</label> | <label for="toggle_webmentions" id="webmentions_label">Webmentions</label> | <label for="toggle_fediverse" id="fediverse_label">Fediverse</label></section>
<input type="radio" name="interactions" id="toggle_comments" checked="checked"><input type="radio" name="interactions" id="toggle_webmentions"><input type="radio" name="interactions" id="toggle_fediverse">
<section id="webmentions_frame"><section id="webmention-form">
<form action="https://webmention.io/jon.kelbie.scot/webmention" method="post">
<label>Did you mention this {{ .Type }} on your website? Put the URL of your post here:</label><br/>
@ -72,6 +72,10 @@
commentSectionId: "{{ .Page.Params.slug }}"
})
</script></section>
<section id="fediverse_frame"><div>
{{ partial "mastodon/mastodon.html" .}}
</div>
</section>
</section>
</article>
{{ else if eq .Type "bookmarkof" }}

1
themes/nipponalba/layouts/partials/head.html

@ -12,6 +12,7 @@
<script type="text/javascript" src="/api/cactuschat/cactus.js"></script>
<link rel="stylesheet" href="/api/cactuschat/style.css" type="text/css">
<link rel="stylesheet" href="/api/cactuschat/custom.css" type="text/css">
<link rel="stylesheet" type="text/css" href="{{.Site.BaseURL}}css/mastodon.css" />
<!-- indieweb stuff -->
<link rel="me" href="mailto:jon@kelbie.scot" />
<link rel="me" href="https://note.com/jon_kelbie" />

17
themes/nipponalba/static/css/style.css

@ -1150,30 +1150,37 @@ hr{
vertical-align: bottom;
height: 100%l
}
#toggle_comments, #toggle_webmentions{
#toggle_comments, #toggle_webmentions, #toggle_fediverse{
display:none;
}
#webmentions_label, #comments_label{
#webmentions_label, #comments_label, #fediverse_label{
display:inline;
margin:0;
padding:0;
}
#toggle_webmentions:checked - #webmentions_label, #toggle_comments:checked + #comments_label{
#toggle_webmentions:checked + #webmentions_label, #toggle_comments:checked + #comments_label, #toggle_fediverse:checked + #fediverse_label{
font-weight: bold;
}
#toggle_webmentions:checked ~ #webmentions_frame {
visibility:visible;
}
#toggle_webmentions:checked ~ #comments_frame {
#toggle_webmentions:checked ~ #comments_frame, #toggle_webmentions:checked ~ #fediverse_frame {
visibility:hidden;
display:none;
}
#toggle_comments:checked ~ #comments_frame {
visibility: visible;
}
#toggle_comments:checked ~ #webmentions_frame {
#toggle_comments:checked ~ #webmentions_frame, #toggle_comments:checked ~ #fediverse_frame {
visibility: hidden;
display:none;
}
#toggle_fediverse:checked ~ #fediverse_frame {
visibility: visible;
}
#toggle_fediverse:checked ~ #webmentions_frame, #toggle_fediverse:checked ~ #comments_frame {
visibility: hidden;
display:none;
}

Loading…
Cancel
Save