summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBigCoke233 <hi@guhub.cn>2025-12-17 12:02:49 +0800
committerBigCoke233 <hi@guhub.cn>2025-12-17 12:02:49 +0800
commitdd27c7bfb5932d8402b1f89984196f8566c14d5e (patch)
treec1c1d2eb2ff074d979afd3ec44cf7b2f76ac0d1b
parentd73c7239a5d3a469278b012088142eb856847d0b (diff)
feat: add webmention to action menu
-rw-r--r--assets/css/_webmention.scss17
-rw-r--r--i18n/en.yml2
-rw-r--r--i18n/zh.yml2
-rw-r--r--layouts/_partials/components/toggle-button.html53
-rw-r--r--layouts/_partials/posts/action-menu.html2
-rw-r--r--layouts/_partials/posts/action-menu/comment-button.html41
-rw-r--r--layouts/_partials/posts/action-menu/webmention-button.html16
-rw-r--r--layouts/_partials/posts/action-menu/webmention-section.html8
-rw-r--r--layouts/_partials/posts/comment.html3
-rw-r--r--static/img/mention.svg37
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