diff --git a/src/components/Icon.astro b/src/components/Icon.astro
index c6dbf169..a1698473 100644
--- a/src/components/Icon.astro
+++ b/src/components/Icon.astro
@@ -10,6 +10,7 @@ interface Props {
| "rss"
| "github"
| "email"
+ | "wechat"
| "bilibili";
size?: number;
}
@@ -26,6 +27,8 @@ const paths = {
"M9 19c-4 1-4-2-6-2m12 5v-3.4a3 3 0 0 0-.8-2.3c2.7-.3 5.5-1.3 5.5-6A4.7 4.7 0 0 0 18.4 7a4.3 4.3 0 0 0-.1-3.2s-1-.3-3.3 1.2a11.6 11.6 0 0 0-6 0C6.7 3.5 5.7 3.8 5.7 3.8A4.3 4.3 0 0 0 5.6 7a4.7 4.7 0 0 0-1.3 3.3c0 4.7 2.8 5.7 5.5 6a3 3 0 0 0-.8 2.3V22",
email:
"M3 7l9 6 9-6M5 5h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V7a2 2 0 0 1 2-2Z",
+ wechat:
+ "M14 13.5c0 3-2.7 5.5-6 5.5H5l-3 2 1-3c-1.2-1-2-2.6-2-4.5C1 10.5 3.7 8 7 8s7 2.5 7 5.5ZM11 8c.6-2.3 2.9-4 5.5-4C20.1 4 23 6.5 23 9.5c0 1.6-.7 3.1-1.9 4.1L22 17l-3-2h-2",
bilibili:
"m8 3 3 3m5-3-3 3M5 6h14a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2ZM8 11v3m8-3v3m-6 3h4",
};
diff --git a/src/components/SocialLinks.astro b/src/components/SocialLinks.astro
index 03156001..95927cd1 100644
--- a/src/components/SocialLinks.astro
+++ b/src/components/SocialLinks.astro
@@ -2,6 +2,7 @@
import Icon from "./Icon.astro";
import { site } from "../config/site";
import { ui, type Locale } from "../i18n";
+import { localePath, normalizeBase } from "../lib/paths.mjs";
interface Props {
locale?: Locale;
@@ -10,6 +11,7 @@ interface Props {
}
const { locale = "zh", variant = "icons", class: className } = Astro.props;
const t = ui(locale);
+const wechatHref = `${localePath("contact", "zh", normalizeBase(import.meta.env.BASE_URL))}#wechat`;
---
+ {locale === "zh" && (
+
+
+ 公众号
+
+ )}
{Object.values(site.socials).map((social) => (
+
+
微信公众号
+
在微信里,继续阅读。
+
关注「{site.wechat.name}」,一起交流技术与思考。
+
打开微信 → 搜一搜 → 选择「公众号」,搜索下方名称。
+
+
+
{site.wechat.name}
+
+
+ 也可以长按名称,手动复制。
+
+
+
+
+
+
+
diff --git a/src/config/site.ts b/src/config/site.ts
index c592f015..2561e185 100644
--- a/src/config/site.ts
+++ b/src/config/site.ts
@@ -5,6 +5,9 @@ export const site = {
displayName: { zh: "泯泷 Yihui", en: "Yihui" },
},
repositoryUrl: "https://github.com/MoMeak9/MyBlogDoc",
+ wechat: {
+ name: "泯泷ML",
+ },
socials: {
github: {
icon: "github",
From 3ab3d3f6304106d35c6406ec52f960ac01cb8e4d Mon Sep 17 00:00:00 2001
From: AI Infra <964572642@qq.com>
Date: Fri, 9 Oct 2026 07:58:06 +0000
Subject: [PATCH 2/2] feat: integrate Giscus comments and original WeChat QR
---
README.md | 6 ++
docs/comments.md | 25 +++++
public/images/wechat-ml-qr.jpg | Bin 0 -> 41773 bytes
src/components/ArticlePage.astro | 2 +
src/components/Comments.astro | 171 ++++++++++++++++++++++++++++++
src/components/WeChatFollow.astro | 21 +++-
src/config/site.ts | 7 ++
tests/build.test.mjs | 54 ++++++++++
8 files changed, 283 insertions(+), 3 deletions(-)
create mode 100644 docs/comments.md
create mode 100644 public/images/wechat-ml-qr.jpg
create mode 100644 src/components/Comments.astro
diff --git a/README.md b/README.md
index 01e57c56..5ddf55aa 100644
--- a/README.md
+++ b/README.md
@@ -107,6 +107,12 @@ BASE_PATH=/MyBlogDoc/ pnpm preview
离线搜索在页面加载后利用空闲时间自动准备完整索引与所需静态资源,不显示下载按钮。后台任务使用低优先级请求,搜索输入、隐藏标签页、节省流量和慢速网络会让任务延后。准备完成后,可以断网搜索新关键词、筛选和分页;已访问的文章可离线阅读。后台更新失败保留原完整缓存,缓存只属于当前博客路径。[方案比较、构建与验收说明](docs/offline-search.md)。
+## 公众号与文章评论
+
+中文界面的首页、文章末尾和联系页提供「泯泷ML」公众号关注卡;社交栏、页脚和手机菜单提供入口。二维码使用原图,支持微信扫码、保存图片和复制公众号名称。公众号名称与图片路径统一维护在 `src/config/site.ts`。
+
+公开且非空的文章使用 [Giscus](https://giscus.app/) 接入本仓库的 GitHub Discussions,访客使用 GitHub 登录留言,无需配置 Token。中英文界面按文章源路径共享讨论,评论区按需加载并跟随明暗主题;评论服务失败时可以重试或前往 GitHub 交流。[配置和映射说明](docs/comments.md)。
+
## SEO 与 GEO
站点输出 Blog、Person、BlogPosting 和可见面包屑对应的 JSON-LD,补齐 OG/Twitter 分享图、可信发布时间与更新时间、原文作者与来源信息,以及 sitemap 的 lastmod。未知的发布时间不会用构建时间补造。英文界面共享原文,因此文章语言标注遵循正文语言。
diff --git a/docs/comments.md b/docs/comments.md
new file mode 100644
index 00000000..6fe1d54d
--- /dev/null
+++ b/docs/comments.md
@@ -0,0 +1,25 @@
+# GitHub Discussions 评论
+
+文章评论使用 [Giscus](https://giscus.app/),数据保存在公开仓库 `MoMeak9/MyBlogDoc` 的 GitHub Discussions 中。访客通过 GitHub 登录留言,不需要在博客中配置 GitHub Token。
+
+## 启用
+
+1. 在仓库 **Settings → General → Features** 开启 **Discussions**。
+2. 安装 [Giscus GitHub App](https://github.com/apps/giscus),允许它访问 `MyBlogDoc`。
+3. 选择 **Announcements** 类型的讨论分类,并将真实的分类名和 GraphQL 分类 ID 写入 `src/config/site.ts` 的 `comments` 配置。仓库 ID 已填入真实值;分类 ID 为空时保留 GitHub 交流入口,不请求 Giscus。
+
+读取仓库与分类 ID:
+
+```sh
+gh api graphql -f query='query { repository(owner:"MoMeak9", name:"MyBlogDoc") { id discussionCategories(first:25) { nodes { id name slug } } } }'
+```
+
+启用后运行 `pnpm check`、`pnpm build`、`pnpm test:build`,将构建部署到站点。浏览器需要访问 `giscus.app`,登录需要 GitHub;博客本身没有评论服务器。
+
+## 映射与行为
+
+- 只在公开且非空的文章页面显示评论,位置在正文和公众号关注卡之后,不进入文章搜索索引。
+- 使用 `specific` 映射,讨论标识为 Markdown 文章的 `post.id`;中英文界面、项目部署前缀与自定义域名共享同一讨论。修改文章标题不会改变讨论;移动文章源文件会改变标识,需要单独迁移已有讨论。
+- `strict` 开启,避免相似文章名匹配到其他讨论。尚无评论时的 `Discussion not found` 是正常状态,首次留言或表情会由 Giscus 创建讨论。
+- 接近评论区时才加载;明暗主题切换时同步 iframe。加载失败提供重试与 GitHub 交流入口,收到当前 iframe 的讨论元数据后将入口指向对应线程。
+- GitHub App 安装状态不能仅凭博客构建判断;需在部署后的页面核验评论显示与 GitHub 登录,且不要把未实际提交的评论描述为已验证。
diff --git a/public/images/wechat-ml-qr.jpg b/public/images/wechat-ml-qr.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e17876c88ef372cf4e2312ce0afbc3c4f17374c8
GIT binary patch
literal 41773
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
a5r>}VK483%q7XbPsTcA8^`C&-CI16RxAvC+
literal 0
HcmV?d00001
diff --git a/src/components/ArticlePage.astro b/src/components/ArticlePage.astro
index eceeff7d..bf8568e2 100644
--- a/src/components/ArticlePage.astro
+++ b/src/components/ArticlePage.astro
@@ -4,6 +4,7 @@ import PostCard from "./PostCard.astro";
import Icon from "./Icon.astro";
import Diagrams from "./Diagrams.astro";
import WeChatFollow from "./WeChatFollow.astro";
+import Comments from "./Comments.astro";
import { ui, dateLabel, type Locale } from "../i18n";
import { getPosts, renderPost, type Post } from "../lib/content";
import { localePath, normalizeBase, postPath } from "../lib/paths.mjs";
@@ -165,6 +166,7 @@ const editUrl = `https://github.com/MoMeak9/MyBlogDoc/edit/main/src/${post.id.sp
)}
{locale === "zh" && }
+ {post.indexable && !post.empty && }
{toc.length > 0 && (
+

+
保存二维码
{site.wechat.name}
- 也可以长按名称,手动复制。
+ 也可在微信「搜一搜 → 公众号」中搜索名称。
@@ -77,7 +89,10 @@ const { id, compact = false } = Astro.props;
h2 { font-size: clamp(24px, 3vw, 36px); margin: 18px 0 16px; }
.wechat-description { color: var(--text); font-size: 16px; }
.wechat-instructions { margin-top: 12px; color: var(--muted); font-size: 13px; }
- .wechat-actions { max-width: 280px; }
+ .wechat-actions { max-width: 240px; text-align: center; }
+ .wechat-qr { width: 215px; max-width: 100%; height: auto; margin: 0 auto; background: #fff; color-scheme: light; }
+ .wechat-save { display: inline-flex; align-items: center; min-height: 44px; font-size: 12px; color: var(--muted); }
+ .wechat-save:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
.wechat-account { font-size: 28px; margin-bottom: 16px; font-weight: 500; user-select: all; }
.wechat-actions .button { width: 100%; letter-spacing: 0; }
.wechat-actions .button:focus-visible { outline: 2px solid var(--accent); outline-offset: 4px; }
diff --git a/src/config/site.ts b/src/config/site.ts
index 2561e185..e8d9e65c 100644
--- a/src/config/site.ts
+++ b/src/config/site.ts
@@ -7,6 +7,13 @@ export const site = {
repositoryUrl: "https://github.com/MoMeak9/MyBlogDoc",
wechat: {
name: "泯泷ML",
+ qrImage: "images/wechat-ml-qr.jpg",
+ },
+ comments: {
+ repo: "MoMeak9/MyBlogDoc",
+ repoId: "R_kgDOG_ZV7A",
+ category: "Announcements",
+ categoryId: "DIC_kwDOG_ZV7M4DHZRJ",
},
socials: {
github: {
diff --git a/tests/build.test.mjs b/tests/build.test.mjs
index 571519d6..c19d0a17 100644
--- a/tests/build.test.mjs
+++ b/tests/build.test.mjs
@@ -165,6 +165,60 @@ function locations(xml) {
);
}
+test("WeChat follow cards serve the original QR under the deployment base and only in Chinese", () => {
+ const qrPath = "images/wechat-ml-qr.jpg";
+ assert.deepEqual(
+ readFileSync(join(dist, qrPath)),
+ readFileSync(join(root, "public", qrPath)),
+ "The QR image must be published without modification.",
+ );
+ for (const page of regularPages) {
+ const html = artifact(page.file);
+ const qrTags = [...html.matchAll(/
![]()
]*>/g)]
+ .map(([tag]) => attributes(tag))
+ .filter((attrs) => attrs.class?.includes("wechat-qr"));
+ if (page.locale === "en") {
+ assert.equal(qrTags.length, 0, page.file);
+ assert.ok(!html.includes('class="social-link social-link--wechat"'), page.file);
+ } else if (["", "contact"].includes(page.route) || page.id) {
+ assert.equal(qrTags.length, 1, page.file);
+ assert.equal(qrTags[0].src, `${base}${qrPath}`, page.file);
+ assert.equal(qrTags[0].width, "430");
+ assert.equal(qrTags[0].height, "430");
+ assert.ok(html.includes('download="泯泷ML-公众号二维码.jpg"'), page.file);
+ }
+ }
+});
+
+test("public article comments share a discussion identity across locales and remain outside indexed prose", () => {
+ for (const article of contentIndex().articles) {
+ for (const locale of ["zh", "en"]) {
+ const file = join(locale === "en" ? "en" : "", "posts", article.id, "index.html");
+ const html = artifact(file);
+ const sections = [...html.matchAll(/
]*>/g)]
+ .map(([tag]) => ({ tag, attrs: attributes(tag) }))
+ .filter(({ attrs }) => attrs.id === "comments");
+ assert.equal(sections.length, 1, file);
+ const { tag, attrs } = sections[0];
+ assert.equal(attrs["data-term"], article.id, file);
+ assert.equal(attrs["data-lang"], locale === "en" ? "en" : "zh-CN", file);
+ assert.equal(attrs["data-repo"], "MoMeak9/MyBlogDoc", file);
+ assert.match(tag, /\bdata-pagefind-ignore\b/, file);
+ if (attrs["data-comments-enabled"] === "true") {
+ assert.ok(attrs["data-repo-id"] && attrs["data-category-id"], file);
+ } else {
+ assert.ok(!html.includes("data-load-comments"), file);
+ }
+ const prose = html.match(/]*class="prose"[\s\S]*?<\/article>/)?.[0];
+ assert.ok(prose, file);
+ assert.ok(!prose.includes('id="comments"'), file);
+ }
+ }
+ for (const path of ["index.html", "contact/index.html", "en/index.html", "en/contact/index.html"]) {
+ assert.ok(!artifact(path).includes('id="comments"'), path);
+ }
+});
+
test("every Markdown article has both locale pages and a real legacy HTML entry", (t) => {
assert.ok(
notes.includes("README.md") && notes.includes("个人简介.md"),