Des commentaires a Mkdocs avec Mastodon
Sources :
J'ai utiliser ce lien pour ajouter le plugin Mastodon pour les commentaires
Ma configuration
La conf mkdocs.yml :
site_name: Be Cloud, code it !
theme:
name: material
custom_dir: theme
extra_css:
- assets/stylesheets/comments.css
extra:
mastodon:
user: myUserName # Replace with your account name
host: myMastodon.com # Replace with the instance you use
Le contenu du fichier theme/partials/comments.html
{% if page.meta.comments %}
{% if page.meta.comment_id %}
<noscript>
<div class="admonition danger">
<p class="admonition-title">
Please enable Javascript to see comments from Mastodon.
</p>
</div>
</noscript>
<p>
<a href="https://{{ config.extra.mastodon.host }}/@{{ config.extra.mastodon.user }}/{{ page.meta.comment_id }}">Commentez cet article de blog </a> en utilisant un compte compatible Fediverse (Mastodon ou similaire).
</p>
<p id="mastodon-comments-list"></p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dompurify/2.4.1/purify.min.js" integrity="sha512-uHOKtSfJWScGmyyFr2O2+efpDx2nhwHU2v7MVeptzZoiC7bdF6Ny/CmZhN2AwIK1oCFiVQQ5DA/L9FSzyPNu6Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script type="text/javascript">
var host = '{{ config.extra.mastodon.host }}';
var user = '{{ config.extra.mastodon.user }}';
var id = '{{ page.meta.comment_id }}'
function escapeHtml(unsafe) {
return unsafe
.replace(/&/g, "&")
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/"/g, """)
.replace(/'/g, "'");
}
var commentsLoaded = false;
function toot_active(toot, what) {
var count = toot[what+'_count'];
return count > 0 ? 'active' : '';
}
function toot_count(toot, what) {
var count = toot[what+'_count'];
return count > 0 ? count : '';
}
function user_account(account) {
var result =`@${account.acct}`;
if (account.acct.indexOf('@') === -1) {
var domain = new URL(account.url)
result += `@${domain.hostname}`
}
return result;
}
function render_toots(toots, in_reply_to, depth) {
var tootsToRender = toots
.filter(toot => toot.in_reply_to_id === in_reply_to)
.sort((a, b) => a.created_at.localeCompare(b.created_at));
tootsToRender.forEach(toot => render_toot(toots, toot, depth));
}
function render_toot(toots, toot, depth) {
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}:`, `<img src="${escapeHtml(emoji.static_url)}" alt="Emoji ${emoji.shortcode}" height="20" width="20" />`);
});
mastodonComment =
`<div class="mastodon-comment" style="margin-left: calc(var(--mastodon-comment-indent) * ${depth})">
<div class="author">
<div class="avatar">
<img src="${escapeHtml(toot.account.avatar_static)}" height=60 width=60 alt="">
</div>
<div class="details">
<a class="name" href="${toot.account.url}" rel="nofollow">${toot.account.display_name}</a>
<a class="user" href="${toot.account.url}" rel="nofollow">${user_account(toot.account)}</a>
</div>
<a class="date" href="${toot.url}" rel="nofollow">${toot.created_at.substr(0, 10)} ${toot.created_at.substr(11, 8)}</a>
</div>
<div class="content">${toot.content}</div>
<div class="attachments">
${toot.media_attachments.map(attachment => {
if (attachment.type === 'image') {
return `<a href="${attachment.url}" rel="nofollow"><img src="${attachment.preview_url}" alt="${attachment.description}" /></a>`;
} else if (attachment.type === 'video') {
return `<video controls><source src="${attachment.url}" type="${attachment.mime_type}"></video>`;
} else if (attachment.type === 'gifv') {
return `<video autoplay loop muted playsinline><source src="${attachment.url}" type="${attachment.mime_type}"></video>`;
} else if (attachment.type === 'audio') {
return `<audio controls><source src="${attachment.url}" type="${attachment.mime_type}"></audio>`;
} else {
return `<a href="${attachment.url}" rel="nofollow">${attachment.type}</a>`;
}
}).join('')}
</div>
<div class="status">
<div class="twemoji replies ${toot_active(toot, 'replies')}">
<a href="${toot.url}" rel="nofollow">{% include ".icons/fontawesome/solid/reply.svg" %}${toot_count(toot, 'replies')}</a>
</div>
<div class="twemoji reblogs ${toot_active(toot, 'reblogs')}">
<a href="${toot.url}" rel="nofollow">{% include ".icons/fontawesome/solid/retweet.svg" %}${toot_count(toot, 'reblogs')}</a>
</div>
<div class="twemoji favourites ${toot_active(toot, 'favourites')}">
<a href="${toot.url}" rel="nofollow">{% include ".icons/fontawesome/solid/star.svg" %}${toot_count(toot, 'favourites')}</a>
</div>
</div>
</div>`;
document.getElementById('mastodon-comments-list').appendChild(DOMPurify.sanitize(mastodonComment, {'RETURN_DOM_FRAGMENT': true}));
render_toots(toots, toot.id, depth + 1)
}
function loadComments() {
if (commentsLoaded) return;
document.getElementById("mastodon-comments-list").innerHTML = "Loading comments from the Fediverse...";
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 = "";
render_toots(data['descendants'], id, 0)
} else {
document.getElementById('mastodon-comments-list').innerHTML =
`<div class="admonition info">
<p class="admonition-title">
Aucun commentaire trouvé. <a href="https://{{ config.extra.mastodon.host }}/@{{ config.extra.mastodon.user }}/{{ page.meta.comment_id }}">Be the first!</a>
</p>
</div>
`;
}
commentsLoaded = true;
});
}
function respondToVisibility(element, callback) {
var options = {
root: null,
};
var observer = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.intersectionRatio > 0) {
callback();
}
});
}, options);
observer.observe(element);
}
var comments = document.getElementById("mastodon-comments-list");
respondToVisibility(comments, loadComments);
</script>
{% else %}
<div class="admonition warning">
<p class="admonition-title">
No Mastodon post configured for this page. Contact {{ config.site_author | default('the post author', true) }} if you want to comment here.
</p>
</div>
{% endif %}
{% endif %}
Le fichier assets/stylesheets/comments.css :
:root{
--mastodon-comment-indent: 40px;
--mastodon-comment-border-radius: 3px;
--mastodon-comment-bg-color: rgba(0, 0, 0, 0.2);
--mastodon-comment-border-color: rgba(0, 0, 0, 0.4);
--mastodon-comment-user-color: #939393;
--mastodon-comment-status--inactive: #5d686f;
--mastodon-comment-status-replies--active: #448aff;
--mastodon-comment-status-favourite--active: #ff9100;
--mastodon-comment-status-reblog--active: #00c853;
}
@media only screen and (max-width: 1024px){
:root{
--mastodon-comment-indent: 20px;
}
}
@media only screen and (max-width: 640px){
:root{
--mastodon-comment-indent: 0px;
}
}
.mastodon-comment{
background-color: var(--mastodon-comment-bg-color);
border-radius: var(--mastodon-comment-border-radius);
border: 1px var(--mastodon-comment-border-color) solid;
padding: 20px;
margin-bottom: 1.5rem;
display: flex;
flex-direction: column;
}
.mastodon-comment p{
margin-bottom: 0px;
}
.mastodon-comment .content{
margin: 15px 20px;
}
.mastodon-comment .content p:first-child{
margin-top: 0;
margin-bottom: 0;
}
.mastodon-comment .attachments{
max-width: 0px 10px;
}
.mastodon-comment .attachments > *{
max-width: 0px 10px;
}
.mastodon-comment .author{
padding-top: 0;
display: flex;
}
.mastodon-comment .author a{
text-decoration: none;
}
.mastodon-comment .author .avatar img{
margin-right: 1rem;
min-width: 60px;
border-radius: 5px;
}
.mastodon-comment .author .details{
display: flex;
flex-direction: column;
}
.mastodon-comment .author .details .name{
font-weight: bold;
}
.mastodon-comment .author .details .user{
color: var(--mastodon-comment-user-color);
}
.mastodon-comment .author .date{
margin-left: auto;
font-size: small;
}
.mastodon-comment .status > div{
display: inline-block;
margin-right: 15px;
}
.mastodon-comment .status a{
color: var(--mastodon-comment-status--inactive);
text-decoration: none;
}
.mastodon-comment .status .twemoji.replies.active a{
color: var(--mastodon-comment-status-replies--active);
}
.mastodon-comment .status .twemoji.reblogs.active a{
color: var(--mastodon-comment-status-reblog--active);
}
.mastodon-comment .status .twemoji.favourites.active a{
color: var(--mastodon-comment-status-favourite--active);
}
.mastodon-comment .status svg{
margin-right: 0.2rem;
vertical-align: middle;
}
En debut de fichier.md sur lequel vous voulez les commentaires ajouter ces 2 lignes :
Le comment_id est trouver en copiant le lien d'un poste mastodon https://fosstodon.org/@Fl0r1an/12345....6789Commentez cet article de blog en utilisant un compte compatible Fediverse (Mastodon ou similaire).