1023 字
5 分钟
Mizuki实现Giscus评论区
准备工作
- 创建 GitHub 仓库
- 新建一个 公开(
public) 的 GitHub 仓库。 - 在仓库设置中 启用 Discussions 功能。
- 新建一个 公开(
- 生成 Giscus 配置代码
- 访问 giscus官网,根据你的需求完成配置。
- 配置完成后,复制生成的
<script>代码块,例如:
<script src="https://giscus.app/client.js" data-repo="Leaf-0w0/blog-giscus" data-repo-id="***" data-category="Announcements" data-category-id="***" data-mapping="pathname" data-strict="0" data-reactions-enabled="1" data-emit-metadata="0" data-input-position="top" data-theme="preferred_color_scheme" data-lang="zh-CN" data-loading="lazy" crossorigin="anonymous" async></script>配置 Mizuki 主题
1. 修改评论配置文件
打开 src/config.ts,将原有的 Twikoo 配置替换为 Giscus 配置:
原内容:
export const commentConfig: CommentConfig = { enable: false, // 启用评论功能。当设置为 false 时,评论组件将不会显示在文章区域。 twikoo: { envId: "https://twikoo.vercel.app", lang: "en", // 设置 Twikoo 评论系统语言为英文 },};修改为:
export const commentConfig: CommentConfig = { enable: true, // 启用评论功能。当设置为 false 时,评论组件将不会显示在文章区域。 giscus: { enable: true, repo: "Leaf-0w0/blog-giscus", repoId: "***", category: "Announcements", categoryId: "***", mapping: "pathname", strict: "0", reactionsEnabled: "1", emitMetadata: "0", inputPosition: "top", theme: "preferred_color_scheme", lang: "zh-CN", },};2. 添加 Giscus 组件
在 src/components/comment/ 目录下创建新文件 Giscus.astro,并粘贴以下代码(可删除原有的 Twikoo.astro 文件):
---import { commentConfig } from "@/config";
interface Props { path: string;}
const giscusConfig = commentConfig.giscus;---
<div class="giscus-container"></div>
<script is:inline define:vars={{ giscusConfig }}> (function () { // 配置项 const CONFIG = { ...giscusConfig, mapping: giscusConfig.mapping || 'pathname', strict: giscusConfig.strict || '0', reactionsEnabled: giscusConfig.reactionsEnabled || '1', emitMetadata: giscusConfig.emitMetadata || '0', inputPosition: giscusConfig.inputPosition || 'top', lang: giscusConfig.lang || 'zh-CN', loading: 'lazy' };
// 获取当前主题 function getTheme() { return document.documentElement.classList.contains('dark') ? 'dark' : 'light'; }
// 向 Giscus iframe 发送消息更新配置 function updateGiscusTheme() { const iframe = document.querySelector('iframe.giscus-frame'); if (!iframe || !iframe.contentWindow) return;
const theme = getTheme(); iframe.contentWindow.postMessage( { giscus: { setConfig: { theme: theme } } }, 'https://giscus.app' ); }
// 注入 Giscus 脚本 function loadGiscus() { const root = document.querySelector('.giscus-container'); // 如果容器不存在,或者已经有 iframe 了,则不处理 if (!root || root.querySelector('iframe.giscus-frame')) return;
// 如果已有旧的 script 标签(Swup 切换可能导致残留),先清理 const oldScript = document.getElementById('giscus-script'); if (oldScript) oldScript.remove();
const theme = getTheme(); const script = document.createElement('script');
script.id = 'giscus-script'; script.src = 'https://giscus.app/client.js'; script.async = true;
// 设置核心参数 script.setAttribute('data-repo', CONFIG.repo); script.setAttribute('data-repo-id', CONFIG.repoId); script.setAttribute('data-category', CONFIG.category); script.setAttribute('data-category-id', CONFIG.categoryId); script.setAttribute('data-mapping', CONFIG.mapping); script.setAttribute('data-strict', CONFIG.strict); script.setAttribute('data-reactions-enabled', CONFIG.reactionsEnabled); script.setAttribute('data-emit-metadata', CONFIG.emitMetadata); script.setAttribute('data-input-position', CONFIG.inputPosition); script.setAttribute('data-lang', CONFIG.lang); script.setAttribute('data-loading', CONFIG.loading);
// 关键:直接设置当前主题,无需加载后回调 script.setAttribute('data-theme', theme);
root.appendChild(script); }
// 监听 html class 变化(主题切换) // 只有当 observer 不存在时才创建,防止多重绑定 if (!window._giscusObserver) { const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'attributes' && mutation.attributeName === 'class') { updateGiscusTheme(); } }); });
observer.observe(document.documentElement, { attributes: true }); window._giscusObserver = observer; }
// 初始化逻辑 function init() { loadGiscus(); }
// 立即执行一次 if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); }
// Swup 适配逻辑 // 使用一个标志位或检查是否已绑定,避免 script 重新执行导致的多重绑定 if (window.swup && !window._giscusSwupListenerAdded) { const handleSwup = () => { // Swup 替换内容后,DOM 里的 iframe 会消失,需要重新 load init(); };
window.swup.hooks.on('content:replace', handleSwup); window.swup.hooks.on('page:view', handleSwup); window._giscusSwupListenerAdded = true; } else if (!window.swup && typeof document !== 'undefined') { // 针对 Swup 还没加载完成的边缘情况 document.addEventListener('swup:enable', () => { if (window.swup && !window._giscusSwupListenerAdded) { window.swup.hooks.on('content:replace', init); window.swup.hooks.on('page:view', init); window._giscusSwupListenerAdded = true; } }, { once: true }); // 仅执行一次 } })();</script>
<style> .giscus-container { width: 100%; margin-top: 1rem; min-height: 200px; /* 防止加载时高度塌陷带来的布局抖动 */ transition: opacity 0.3s; }
.giscus-container iframe.giscus-frame { width: 100%; border-radius: var(--radius-large, 8px); /* 提供 fallback */ border: 1px solid var(--line-divider, rgba(0,0,0,0.1)); background: transparent; transition: border-color 0.15s; }
.giscus-container:hover iframe.giscus-frame { border-color: var(--primary, #3b82f6); }</style>3. 更新评论组件入口
编辑 src/components/comment/index.astro,替换 Twikoo 相关引用:
原内容:
import Twikoo from "./Twikoo.astro"; //文件内第4行
if (commentConfig?.enable && commentConfig?.twikoo) { //文件内第16行 commentService = "twikoo"; //文件内第17行
{commentService === 'twikoo' && <Twikoo path={path} />} //文件内第22行修改为:
import Giscus from "./Giscus.astro";
if (commentConfig?.enable) { if (commentConfig?.giscus) { commentService = "giscus"; }
{commentService === 'giscus' && <Giscus path={path} />}4. 更新类型定义
在 src/types/config.ts 中,将 Twikoo 类型替换为 Giscus 类型:
原内容:
twikoo?: TwikooConfig; //文件内第134行
type TwikooConfig = { //文件内第137行 envId: string; //文件内第138行 region?: string; //文件内第139行修改为:
giscus?: GiscusConfig;
type GiscusConfig = { enable: boolean; repo: string; repoId: string; category: string; categoryId: string; mapping?: string; strict?: string; reactionsEnabled?: string; emitMetadata?: string; inputPosition?: string; theme?: string;完成修改
完成以上步骤后,你的Mizuki主题即可成功集成Giscus评论系统。
Mizuki实现Giscus评论区
https://blog.yuk1.uk/posts/mizuki-giscus/ 部分信息可能已经过时
