-
-
Save deepakness/782a1ff050ed52084eb5461bf8a7618a to your computer and use it in GitHub Desktop.
Webmentions implementation for DeepakNess, built using 11ty
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {% set target = page.url | absoluteUrl(metadata.url) %} | |
| {% set replies = webmentions.children | filterWebmentions(target, "in-reply-to") %} | |
| {% set likes = webmentions.children | filterWebmentions(target, "like-of") %} | |
| {% set reposts = webmentions.children | filterWebmentions(target, "repost-of") %} | |
| {% set hasReplies = replies.length %} | |
| {% set hasReactions = likes.length or reposts.length %} | |
| {% set hasWebmentions = hasReplies or hasReactions %} | |
| <style> | |
| .webmentions-wrap { | |
| margin-top: 2.25rem; | |
| padding-top: 1.25rem; | |
| border-top: 1px solid var(--border-color, #e6e6e6); | |
| text-align: left; | |
| } | |
| .webmentions-actions { | |
| display: flex; | |
| flex-wrap: wrap; | |
| gap: 1.5rem; | |
| align-items: center; | |
| margin: 0 0 2rem 0; | |
| } | |
| .webmentions-action { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| color: var(--text-color-link, #3364ff); | |
| text-decoration: none; | |
| font-size: 0.825rem; | |
| font-weight: 400; | |
| margin: 0; | |
| } | |
| .webmentions-action:hover { | |
| color: var(--text-color-link-active, #2b55d6); | |
| text-decoration: none; | |
| } | |
| .webmentions-action-icon { | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| color: currentColor; | |
| margin-bottom: 3px; | |
| } | |
| .webmentions-action-icon svg { | |
| width: 16px; | |
| height: 16px; | |
| } | |
| main .webmentions-actions a, | |
| main .webmentions-actions a:hover, | |
| main .webmentions-actions a:active, | |
| main .webmentions-actions a:focus { | |
| border-bottom: none !important; | |
| padding-bottom: 0 !important; | |
| text-decoration: none !important; | |
| } | |
| .webmentions-wrap[data-has-webmentions="false"] .webmentions-header, | |
| .webmentions-wrap[data-has-webmentions="false"] .webmentions-reactions, | |
| .webmentions-wrap[data-has-webmentions="false"] .webmentions-list, | |
| .webmentions-wrap[data-has-webmentions="false"] .webmentions-actions--full { | |
| display: none; | |
| } | |
| .webmentions-wrap[data-has-webmentions="true"] .webmentions-actions--empty { | |
| display: none; | |
| } | |
| .webmentions-wrap[data-has-replies="false"] .webmentions-list { | |
| display: none; | |
| } | |
| .webmentions-wrap[data-has-reactions="false"] .webmentions-reactions { | |
| display: none; | |
| } | |
| .webmentions-header { | |
| display: flex; | |
| align-items: center; | |
| justify-content: space-between; | |
| gap: 1rem; | |
| padding-bottom: 0.85rem; | |
| margin-bottom: 1.35rem; | |
| } | |
| .webmentions-title-row { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.8rem; | |
| } | |
| .webmentions-title { | |
| font-size: 0.95rem; | |
| font-weight: 700; | |
| color: #767f89; | |
| margin: 0; | |
| text-transform: uppercase; | |
| letter-spacing: 3px; | |
| } | |
| .webmentions-help { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.45rem; | |
| color: #8a949f; | |
| text-decoration: none; | |
| font-size: 0.8rem; | |
| font-weight: 400; | |
| } | |
| .webmentions-help:hover { | |
| color: #5b6672; | |
| text-decoration: none; | |
| } | |
| .webmentions-reactions { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.6rem; | |
| font-size: 0.8rem; | |
| color: #8a949f; | |
| } | |
| .webmentions-reaction { | |
| display: inline-flex; | |
| align-items: center; | |
| gap: 0.25rem; | |
| } | |
| main a.webmentions-help, | |
| main a.webmentions-help:hover, | |
| main a.webmentions-help:active, | |
| main a.webmentions-help:focus { | |
| border-bottom: none !important; | |
| padding-bottom: 0 !important; | |
| text-decoration: none !important; | |
| } | |
| .webmentions-list { | |
| list-style: none; | |
| padding: 0; | |
| margin: 0; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 1.5rem; | |
| } | |
| .webmention-item { | |
| position: relative; | |
| display: grid; | |
| grid-template-columns: 56px 1fr; | |
| gap: 0.15rem; | |
| align-items: start; | |
| } | |
| .webmention-avatar-wrap { | |
| position: relative; | |
| width: 48px; | |
| height: 48px; | |
| } | |
| .webmention-avatar { | |
| width: 100%; | |
| height: 100%; | |
| border-radius: 999px; | |
| overflow: hidden; | |
| background: #f1f3f5; | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| border: 2px solid #eef2f7; | |
| } | |
| .webmention-avatar img { | |
| width: 100%; | |
| height: 100%; | |
| object-fit: cover; | |
| display: block; | |
| border: none !important; | |
| border-radius: 999px !important; | |
| } | |
| .webmention-avatar picture { | |
| display: block; | |
| width: 100%; | |
| height: 100%; | |
| } | |
| .webmention-avatar-fallback { | |
| width: 100%; | |
| height: 100%; | |
| display: inline-flex; | |
| align-items: center; | |
| justify-content: center; | |
| font-weight: 400; | |
| font-size: 0.75rem; | |
| color: #9aa3ad; | |
| } | |
| .webmention-avatar[data-has-img="true"] .webmention-avatar-fallback { | |
| display: none; | |
| } | |
| .webmention-body { | |
| display: flex; | |
| flex-direction: column; | |
| gap: 0.15rem; | |
| } | |
| .webmention-meta { | |
| display: flex; | |
| align-items: baseline; | |
| gap: 0.35rem; | |
| flex-wrap: wrap; | |
| } | |
| .webmention-author { | |
| font-weight: 400; | |
| color: var(--text-color, #222); | |
| text-decoration: none; | |
| font-size: 0.9rem; | |
| } | |
| main a.webmention-author, | |
| main a.webmention-author:hover, | |
| main a.webmention-author:active, | |
| main a.webmention-author:focus { | |
| border-bottom: none !important; | |
| padding-bottom: 0 !important; | |
| text-decoration: none !important; | |
| } | |
| .webmention-date { | |
| font-size: 0.8rem; | |
| color: #8a949f; | |
| } | |
| .webmention-bubble { | |
| background: rgba(51, 100, 255, 0.04); | |
| border: 1px solid rgba(51, 100, 255, 0.12); | |
| border-radius: 2px 10px 10px 10px; | |
| padding: 0.475rem 0.65rem; | |
| } | |
| .webmention-text { | |
| margin: 0; | |
| color: var(--text-color, #222); | |
| line-height: 1.6; | |
| font-size: 0.85rem; | |
| } | |
| .webmention-text a { | |
| color: var(--text-color-link, #3364ff); | |
| } | |
| @media (max-width: 600px) { | |
| .webmentions-actions { | |
| gap: 0.85rem; | |
| justify-content: space-between; | |
| } | |
| .webmention-item { | |
| grid-template-columns: 40px 1fr; | |
| } | |
| .webmention-avatar-wrap, | |
| .webmention-avatar { | |
| width: 34px; | |
| height: 34px; | |
| } | |
| .webmention-item::before { | |
| left: 16px; | |
| top: 40px; | |
| } | |
| } | |
| </style> | |
| <section | |
| class="webmentions-wrap" | |
| data-webmentions-root | |
| data-webmention-target="{{ target }}" | |
| data-has-webmentions="{% if hasWebmentions %}true{% else %}false{% endif %}" | |
| data-has-replies="{% if hasReplies %}true{% else %}false{% endif %}" | |
| data-has-reactions="{% if hasReactions %}true{% else %}false{% endif %}" | |
| > | |
| <div class="webmentions-actions webmentions-actions--empty"> | |
| <a class="webmentions-action" href="mailto:{{ metadata.author.email }}?subject=Comment on: {{ title | urlencode }}"> | |
| <span class="webmentions-action-icon" aria-hidden="true">{% phicon "envelope-simple" %}</span> | |
| Comment via Email | |
| </a> | |
| </div> | |
| <div class="webmentions-actions webmentions-actions--full"> | |
| {%- if mastodon %} | |
| <a class="webmentions-action" href="{{ mastodon }}" target="_blank" rel="noopener noreferrer"> | |
| <span class="webmentions-action-icon" aria-hidden="true">{% phicon "chat-text" %}</span> | |
| Comment on Mastodon | |
| </a> | |
| {%- endif %} | |
| <a class="webmentions-action" href="mailto:{{ metadata.author.email }}?subject=Comment on: {{ title | urlencode }}"> | |
| <span class="webmentions-action-icon" aria-hidden="true">{% phicon "envelope-simple" %}</span> | |
| Comment via Email | |
| </a> | |
| </div> | |
| <div class="webmentions-header"> | |
| <div class="webmentions-title-row"> | |
| <h3 class="webmentions-title">Webmentions</h3> | |
| <div class="webmentions-reactions"> | |
| {% if likes.length %} | |
| <span class="webmentions-reaction">❤️ {{ likes.length }}</span> | |
| {% endif %} | |
| {% if reposts.length %} | |
| <span class="webmentions-reaction">🔁 {{ reposts.length }}</span> | |
| {% endif %} | |
| </div> | |
| </div> | |
| <a class="webmentions-help" href="/webmention/" aria-label="What’s this?"> | |
| <span class="webmentions-help-text">What’s this?</span> | |
| </a> | |
| </div> | |
| <ul class="webmentions-list"> | |
| {% for m in replies %} | |
| <li class="webmention-item"> | |
| <div class="webmention-avatar-wrap"> | |
| {% set authorLabel = m.author.name or (m.url | replace("https://", "") | replace("http://", "")) %} | |
| <div class="webmention-avatar" role="img" aria-label="{{ authorLabel }}" data-has-img="false"> | |
| {% if m.author and m.author.photo %} | |
| <img | |
| src="{{ m.author.photo }}" | |
| alt="" | |
| data-no-picture | |
| loading="lazy" | |
| decoding="async" | |
| onload="var a=this.closest('.webmention-avatar'); if (a) a.dataset.hasImg='true';" | |
| onerror="var a=this.closest('.webmention-avatar'); if (a) a.dataset.hasImg='false'; this.remove();" | |
| > | |
| {% endif %} | |
| <span class="webmention-avatar-fallback" aria-hidden="true">?</span> | |
| </div> | |
| </div> | |
| <div class="webmention-body"> | |
| <div class="webmention-meta"> | |
| <a href="{{ m.url }}" class="webmention-author" target="_blank" rel="noopener"> | |
| {{ m.author.name or (m.url | replace("https://", "") | replace("http://", "")) }} | |
| </a> | |
| {% if m.published %} | |
| <span class="webmention-date">· {{ m.published | webmentionDate }}</span> | |
| {% endif %} | |
| </div> | |
| {% if m.content and (m.content.text or m.content.html) %} | |
| {% set replyText = m.content.text or (m.content.html | striptags) %} | |
| <div class="webmention-bubble"> | |
| <p class="webmention-text">{{ replyText | truncate(260) }}</p> | |
| </div> | |
| {% endif %} | |
| </div> | |
| </li> | |
| {% endfor %} | |
| </ul> | |
| </section> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment