diff options
| -rw-r--r-- | assets/css/_webmention.scss | 17 | ||||
| -rw-r--r-- | i18n/en.yml | 2 | ||||
| -rw-r--r-- | i18n/zh.yml | 2 | ||||
| -rw-r--r-- | layouts/_partials/components/toggle-button.html | 53 | ||||
| -rw-r--r-- | layouts/_partials/posts/action-menu.html | 2 | ||||
| -rw-r--r-- | layouts/_partials/posts/action-menu/comment-button.html | 41 | ||||
| -rw-r--r-- | layouts/_partials/posts/action-menu/webmention-button.html | 16 | ||||
| -rw-r--r-- | layouts/_partials/posts/action-menu/webmention-section.html | 8 | ||||
| -rw-r--r-- | layouts/_partials/posts/comment.html | 3 | ||||
| -rw-r--r-- | static/img/mention.svg | 37 |
10 files changed, 143 insertions, 38 deletions
diff --git a/assets/css/_webmention.scss b/assets/css/_webmention.scss new file mode 100644 index 00000000..4f5d861a --- /dev/null +++ b/assets/css/_webmention.scss @@ -0,0 +1,17 @@ +#webmentions { + .comments { + list-style: none; + padding-inline-start: 0; + li { + display: flex; + align-items: center; + .reaction { + img { + height: 2rem; + width: 2rem; + border-radius: 50%; + } + } + } + } +} diff --git a/i18n/en.yml b/i18n/en.yml index 17a12af8..f22eabc5 100644 --- a/i18n/en.yml +++ b/i18n/en.yml @@ -57,3 +57,5 @@ actionMenu: like: Sacrifice your heart liked: You've already made your sacrifice rss_comment_link: "Come and leave a comment" +webmention: + fetching: Fetching Webmention... diff --git a/i18n/zh.yml b/i18n/zh.yml index 3ec0151b..991798ac 100644 --- a/i18n/zh.yml +++ b/i18n/zh.yml @@ -56,3 +56,5 @@ actionMenu: like: 为这篇文章献上心脏 liked: 你已经献上心脏了 rss_comment_link: "读完啦?来坐坐吧" +webmention: + fetching: 正在获取 Webmention... diff --git a/layouts/_partials/components/toggle-button.html b/layouts/_partials/components/toggle-button.html new file mode 100644 index 00000000..3aef1509 --- /dev/null +++ b/layouts/_partials/components/toggle-button.html @@ -0,0 +1,53 @@ +{{/* + Reusable Toggle Button Component + + Parameters: + - id: (string) Unique identifier for the button group (e.g. "comments"). + Used to generate IDs: {id}-toggle, {id}-section, {id}-count. + - title: (string) Tooltip title. + - icon: (string) Path to the icon image. + - countId: (string, optional) Override for count element ID. Defaults to "{id}-count". + - sectionId: (string, optional) Override for section element ID. Defaults to "{id}-section". + - buttonId: (string, optional) Override for button element ID. Defaults to "{id}-toggle". +*/}} +{{ $id := .id }} +{{ $buttonId := default (printf "%s-toggle" $id) .buttonId }} +{{ $sectionId := default (printf "%s-section" $id) .sectionId }} +{{ $countId := default (printf "%s-count" $id) .countId }} + +<button class="dark:invert flex items-center justify-center gap-1.5 min-w-12 h-12 px-2 border-none bg-transparent text-gray-600 cursor-pointer relative transition-all duration-200 hover:bg-black/5 hover:rounded-lg group" + id="{{ $buttonId }}" title="{{ .title }}" data-tooltip> + <img src="{{ .icon }}" width="20" height="20" + alt="{{ .title }}" + class="brightness-40 flex-shrink-0 dark:brightness-70 dark:contrast-120" /> + <span class="text-xs font-bold text-gray-600 min-w-4 text-center bg-white/90 rounded-xl px-1.5 py-0.5 shadow-sm dark:text-gray-400 dark:bg-black/70" + id="{{ $countId }}">...</span> +</button> + +<script> + (function() { + document.addEventListener('DOMContentLoaded', () => { + const button = document.getElementById("{{ $buttonId }}"); + const section = document.getElementById("{{ $sectionId }}"); + + if (!button || !section) return; + + button.addEventListener('click', () => { + const isHidden = section.classList.contains('hidden'); + const entranceAnimation = 'animate-slide-in-down'; + const exitAnimation = 'animate-slide-out-up'; + + if (isHidden) { + section.classList.remove('hidden', exitAnimation); + section.classList.add(entranceAnimation); + } else { + section.classList.remove(entranceAnimation); + section.classList.add(exitAnimation); + setTimeout(() => { + section.classList.add('hidden'); + }, 200); + } + }); + }); + })(); +</script> diff --git a/layouts/_partials/posts/action-menu.html b/layouts/_partials/posts/action-menu.html index ae19873a..cc5aca46 100644 --- a/layouts/_partials/posts/action-menu.html +++ b/layouts/_partials/posts/action-menu.html @@ -3,10 +3,12 @@ <div class="flex justify-between items-center"> <div class="flex gap-2"> {{ partial "posts/action-menu/comment-button" . }} + {{ partial "posts/action-menu/webmention-button" . }} {{ partial "posts/action-menu/like-button" . }} </div> {{ partial "posts/action-menu/info-links" . }} </div> <!-- Like Count Display --> {{ partial "posts/action-menu/comment-section" . }} + {{ partial "posts/action-menu/webmention-section" . }} </div> diff --git a/layouts/_partials/posts/action-menu/comment-button.html b/layouts/_partials/posts/action-menu/comment-button.html index d646ca27..cd6fe33b 100644 --- a/layouts/_partials/posts/action-menu/comment-button.html +++ b/layouts/_partials/posts/action-menu/comment-button.html @@ -1,42 +1,14 @@ -<button class="dark:invert flex items-center justify-center gap-1.5 min-w-12 h-12 px-2 border-none bg-transparent text-gray-600 cursor-pointer relative transition-all duration-200 hover:bg-black/5 hover:rounded-lg group" - id="comments-toggle" title="{{ T "actionMenu.comment" }}" data-tooltip> - <img src="/img/comments.svg" width="20" height="20" - alt="{{ T "actionMenu.comment" }}" - class="brightness-40 flex-shrink-0 dark:brightness-70 dark:contrast-120" /> - <span class="text-xs font-bold text-gray-600 min-w-4 text-center bg-white/90 rounded-xl px-1.5 py-0.5 shadow-sm dark:text-gray-400 dark:bg-black/70" id="comment-count">...</span> -</button> +{{ partial "components/toggle-button.html" (dict + "id" "comments" + "title" (T "actionMenu.comment") + "icon" "/img/comments.svg" + "countId" "comment-count" +) }} <script> // initialize button features and comment count document.addEventListener('DOMContentLoaded', () => { - function initButtonFeature() { - const commentsToggle = document.getElementById('comments-toggle'); - const commentsSection = document.getElementById('comments-section'); - - if (!commentsToggle || !commentsSection) return; - - // click on toggle - commentsToggle.addEventListener('click', function() { - const isHidden = commentsSection.classList.contains('hidden'); - const entranceAnimation = 'animate-slide-in-down'; - const exitAnimation = 'animate-slide-out-up'; - - if (isHidden) { - // swtich on - commentsSection.classList.remove('hidden', exitAnimation); - commentsSection.classList.add(entranceAnimation); - } else { - // switch off - commentsSection.classList.remove(entranceAnimation); - commentsSection.classList.add(exitAnimation); - setTimeout(() => { - commentsSection.classList.add('hidden'); - }, 200); - } - }); - } - function initCommentCount() { const commentCountEl = document.getElementById('comment-count'); if (!commentCountEl) return; @@ -66,7 +38,6 @@ document.addEventListener('DOMContentLoaded', () => { observer.observe(document.body, { childList: true, subtree: true }); } - initButtonFeature(); initCommentCount(); }); </script> diff --git a/layouts/_partials/posts/action-menu/webmention-button.html b/layouts/_partials/posts/action-menu/webmention-button.html new file mode 100644 index 00000000..b447090a --- /dev/null +++ b/layouts/_partials/posts/action-menu/webmention-button.html @@ -0,0 +1,16 @@ +{{ partial "components/toggle-button.html" (dict + "id" "webmention" + "title" (T "actionMenu.comment") + "icon" "/img/mention.svg" + "countId" "mention-count" +) }} + +<script> +document.addEventListener('DOMContentLoaded', () => { + fetch("https://webmention.io/api/count?target={{.Permalink}}") + .then(response => response.json()) + .then(responseJson => { + document.getElementById("mention-count").textContent = responseJson.count; + }); +}); +</script> diff --git a/layouts/_partials/posts/action-menu/webmention-section.html b/layouts/_partials/posts/action-menu/webmention-section.html new file mode 100644 index 00000000..5d726aff --- /dev/null +++ b/layouts/_partials/posts/action-menu/webmention-section.html @@ -0,0 +1,8 @@ +<!-- Comment Section --> +<div class="overflow-hidden my-4"> + <div class="mt-4 hidden animate-duration-200" id="webmention-section"> + <div id="webmentions"> + <p class="no-webmention"></p> + </div> + </div> +</div> diff --git a/layouts/_partials/posts/comment.html b/layouts/_partials/posts/comment.html index d05ff2d4..6e959f49 100644 --- a/layouts/_partials/posts/comment.html +++ b/layouts/_partials/posts/comment.html @@ -33,9 +33,6 @@ </p> </div> -<!-- webmention --> -<div id="webmentions"></div> - <!-- giscus script --> <script> function loadGiscus() { diff --git a/static/img/mention.svg b/static/img/mention.svg new file mode 100644 index 00000000..de633fc2 --- /dev/null +++ b/static/img/mention.svg @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg fill="#000000" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
+ width="800px" height="800px" viewBox="0 0 421.94 421.939"
+ xml:space="preserve">
+<g>
+ <g>
+ <path d="M219.866,163.814c-7.254,0-13.964,2.053-20.125,6.173c-6.173,4.107-11.49,9.412-15.961,15.948
+ c-4.488,6.536-7.926,13.851-10.343,21.941c-2.429,8.116-3.627,16.018-3.627,23.765c0,7.974,1.633,14.507,4.9,19.587
+ c3.263,5.068,8.872,7.614,16.861,7.614c3.375,0,7.025-1.021,10.89-3.086c3.867-2.054,7.599-4.769,11.238-8.167
+ c3.63-3.375,7.122-7.254,10.521-11.602c3.375-4.347,6.401-8.947,9.067-13.774l9.073-50.056c-3.164-2.669-6.425-4.723-9.8-6.173
+ C229.167,164.532,224.934,163.814,219.866,163.814z"/>
+ <path d="M210.976,0C94.461,0,0,94.453,0,210.964c0,116.514,94.452,210.976,210.975,210.976
+ c116.526,0,210.963-94.455,210.963-210.976C421.939,94.453,327.514,0,210.976,0z M345.907,264.283
+ c-9.56,9.92-20.675,17.78-33.363,23.575c-12.688,5.801-26.307,8.707-40.814,8.707c-6.059,0-11.667-0.655-16.867-1.987
+ c-5.206-1.34-9.565-3.567-13.055-6.72c-3.507-3.146-6.112-7.254-7.812-12.334c-1.693-5.08-2.173-11.361-1.435-18.849h-1.453
+ c-3.615,5.062-7.561,10.027-11.794,14.867c-4.218,4.84-8.872,9.121-13.964,12.875c-5.065,3.759-10.637,6.719-16.669,8.887
+ c-6.062,2.174-12.703,3.261-19.96,3.261c-5.798,0-11.361-1.273-16.693-3.808c-5.309-2.54-9.905-6.106-13.775-10.694
+ c-3.867-4.588-6.953-10.16-9.235-16.693c-2.317-6.527-3.461-13.774-3.461-21.761c0-14.994,2.429-29.559,7.256-43.703
+ c4.84-14.147,11.431-26.662,19.768-37.539c8.344-10.884,18.029-19.633,29.03-26.298c11-6.642,22.665-9.968,34.993-9.968
+ c8.47,0,15.604,1.273,21.398,3.807c5.795,2.546,11.127,5.86,15.967,9.979l11.234-11.616h25.395l-17.401,98.302
+ c-1.934,11.361-1.994,19.588-0.192,24.668c1.825,5.067,5.86,7.614,12.153,7.614c6.281,0,12.466-1.453,18.507-4.359
+ c6.029-2.9,11.47-7.362,16.321-13.422c4.815-6.034,8.767-13.66,11.781-22.842c3.026-9.199,4.527-20.083,4.527-32.657
+ c0-18.134-3.026-33.617-9.067-46.432c-6.053-12.814-14.327-23.395-24.835-31.729C291.87,99.07,279.469,92.967,265.202,89.1
+ c-14.261-3.87-29.621-5.812-46.065-5.812c-18.852,0-36.389,3.387-52.593,10.145c-16.201,6.789-30.288,16.093-42.262,27.935
+ c-11.959,11.856-21.329,25.944-28.112,42.262c-6.752,16.321-10.145,34.035-10.145,53.134c0,18.867,2.846,35.788,8.515,50.776
+ c5.696,15.012,13.977,27.754,24.86,38.274c10.871,10.521,24.355,18.615,40.448,24.295c16.065,5.682,34.5,8.533,55.304,8.533
+ c7.014,0,14.988-0.847,23.947-2.534c8.936-1.693,17.042-4.233,24.296-7.626l11.24,34.828c-9.907,4.84-20.008,8.215-30.288,10.142
+ c-10.28,1.934-22.062,2.925-35.371,2.925c-23.452,0-45.156-3.398-65.092-10.154c-19.957-6.779-37.254-16.813-51.885-30.107
+ c-14.627-13.307-26.058-29.809-34.272-49.504c-8.227-19.708-12.322-42.502-12.322-68.371c0-26.361,4.708-50.188,14.135-71.469
+ c9.428-21.269,22.149-39.403,38.092-54.406c15.964-14.997,34.458-26.526,55.481-34.651c21.056-8.08,43.294-12.142,66.746-12.142
+ c22.242,0,42.922,3.204,62.018,9.611c19.107,6.413,35.668,15.597,49.695,27.559c14.027,11.971,25.028,26.613,33.003,43.896
+ c7.986,17.3,11.985,36.944,11.985,58.946c0,15.483-2.727,29.991-8.167,43.532C362.942,242.643,355.46,254.375,345.907,264.283z"/>
+ </g>
+</g>
+</svg>
\ No newline at end of file |
