1. Obsidian 以其 local first 和双向链接的特性,成为很多互联网朋友钟爱的笔记软件。
2. 对于将本地笔记做公网发布的方案,前后尝试过 Wordpress、自建 Vuepress,但用下来都没有官方的 publish 服务简洁方便、集成度高。
3. 官方 Publish 服务唯一的缺点是并没有和飞书文档一样自带的评论区功能,尝试过很多方案,有诸多细节不完备导致没能成功集成评论功能进入 Publish,本周探索出了一套基于 Giscus 的可行方案,操作细节如下文
## 一、准备工作
### 1.1 创建 GitHub 仓库
如果还没有,需要创建一个公开的 GitHub 仓库用于存储评论。
### 1.2 启用 Discussions
在仓库的 Settings → General → Features 中,勾选 "Discussions"。
### 1.3 安装 Giscus App
访问 [Giscus App](https://github.com/apps/giscus) 并安装到你的仓库,Giscus 是一个基于 GitHub Discussions 的评论系统。它将评论存储在你的 GitHub 仓库的 Discussions 中,完全免费且数据归你所有。
- 免费开源
- 数据存储在自己的 GitHub 仓库
- 支持 Markdown
- 有反应表情(emoji reactions)
- 支持多种主题
### 1.4 获取 Giscus 配置信息
访问 [giscus.app](https://giscus.app/) 并填写:
- 输入你的仓库名(格式:用户名/仓库名)
- 选择 Discussion 分类(建议使用 "Announcements" 或创建 "Comments")
- 选择映射方式(**选择 "Specific"**,后续我们会用 uid 作为 term)
- 页面会自动生成配置代码。记下以下信息:
- data-repo
- data-repo-id
- data-category
- data-category-id
## 二、为本地每篇笔记生成唯一 uid
推荐使用 Ob 中的 Note UID Generator 插件自动为每篇笔记的 front-matter 添加 `uid` 字段。例如:
```YAML
---
uid: 3694d835-33ec-462a-9fd4-e4118c24e664
title: 一切皆项目$
date created: 2024-08-23
date modified: 2025-06-22
---
```
确保每篇需要评论的笔记都包含唯一的 `uid` 字段。
## 三、修改 Publish 服务相关文件
### 3.1 修改 publish.css 让 front-matter 可见
Obsidian Publish 默认会隐藏 front-matter,但我们的评论系统需要 JS 能读取到页面上的 uid。
请在你的仓库根目录下创建或修改 `publish.css`,加入以下内容:
```CSS
/* 强制让 front-matter 显示出来 */
.frontmatter,
.frontmatter-container,
.markdown-preview-view:not(.show-frontmatter) .frontmatter {
display: block !important; /* 取消 display:none */
white-space: pre; /* 保留缩进 */
}
/* 可选:更通用的兜底,防止主题覆盖 */
[class*="frontmatter"] {
display: block !important;
white-space: pre !important;
}
/* 可选:调试时加背景色 */
.frontmatter, .frontmatter-container {
background: #f8f8f8;
border-left: 3px solid #e0e0e0;
padding: 0.5em 1em;
}
```
这样可以确保 front-matter 在页面上可见,JS 才能正确提取 uid。
### 3.2 创建 publish.js
在 Obsidian 仓库根目录创建 `publish.js`,内容如下(已适配 uid):
```JavaScript
/*****************************************************************
* publish.js —— 放在仓库根目录
* 功能:在 Obsidian Publish 页面为每篇笔记加载 giscus 评论,
* 用 front-matter 中的 uid 作为唯一键。
******************************************************************/
// 工具函数:从原始 Markdown 抽取 uid
function getUid() {
// Publish 会把 Markdown 原文放进 <script type="text/plain">…</script>
const raw =
document.querySelector('script[type="text/plain"]')?.textContent ||
document.body.innerText; // 兜底:直接扫可见文本
// 适配 note_uid_generator 插件生成的 uid
const m = raw.match(/uid:\s*([0-9a-fA-F-]+)/);
return m ? m[1].trim() : null;
}
// 主注入函数
function injectGiscus() {
console.log('[Giscus] 尝试注入…');
// 防重复
if (document.getElementById('giscus-container')) {
console.log('[Giscus] 已存在,跳过');
return;
}
// 等页面完全加载再执行
if (document.readyState !== 'complete') {
setTimeout(injectGiscus, 300);
return;
}
// 读取 uid,没有就放弃加载评论
const uid = getUid();
if (!uid) {
console.warn('[Giscus] 未找到 uid,页面不加载评论');
return;
}
// 创建容器
const container = document.createElement('div');
container.id = 'giscus-container';
container.style.cssText = 'margin:3rem auto 0;max-width:100%;padding:0;';
// 创建 giscus 脚本
const s = document.createElement('script');
s.src = 'https://giscus.app/client.js';
s.dataset.repo = '你的用户名/你的仓库名'; // 修改这里
s.dataset.repoId = '你的repo-id'; // 修改这里
s.dataset.category = 'Comments'; // 修改这里
s.dataset.categoryId = '你的category-id'; // 修改这里
// 关键:用 uid 作为主键
s.dataset.mapping = 'specific'; // 修改这里
s.dataset.term = uid; // 修改这里
s.dataset.reactionsEnabled = '1';
s.dataset.theme = 'preferred_color_scheme';
s.dataset.lang = 'zh-CN';
s.crossOrigin = 'anonymous';
s.async = true;
container.appendChild(s);
// 选个合适节点挂载
const target =
document.querySelector('.markdown-preview-view') ||
document.querySelector('.publish-article-content') ||
document.querySelector('.content') ||
document.querySelector('article') ||
document.querySelector('main') ||
document.querySelector('[class*="content"]') ||
document.body;
target.appendChild(container);
console.log('[Giscus] 已挂载到:', target.className || target.tagName);
// 附加自适应样式
if (!document.getElementById('giscus-style')) {
const style = document.createElement('style');
style.id = 'giscus-style';
style.textContent = `
#giscus-container{width:100%!important;box-sizing:border-box!important;}
#giscus-container .giscus{max-width:100%!important;}
#giscus-container iframe{max-width:100%!important;}
`;
document.head.appendChild(style);
}
}
// 单页应用路径监控(可选,适配 SPA 路由变化)
let lastPath = window.location.pathname;
function watchPathChange() {
if (window.location.pathname !== lastPath) {
lastPath = window.location.pathname;
console.log('[Giscus] 路径变更,重新注入');
document.getElementById('giscus-container')?.remove();
setTimeout(injectGiscus, 500);
}
}
setInterval(watchPathChange, 1000);
// 初始注入
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', injectGiscus);
} else {
injectGiscus();
}
window.addEventListener('load', () => setTimeout(injectGiscus, 800));
window.addEventListener('popstate', () => setTimeout(injectGiscus, 500));
```
### 3.3 发布到 Obsidian Publish
1. 在 Obsidian 中打开发布面板
2. 记得选中 `publish.js` 和 `publish.css` 文件
3. 点击发布
## 四、补充说明
### **4.1 为什么用** **uid****?**
如果你用文件名、路径或标题作为评论主键,重命名/移动文件会导致评论丢失,无法正确挂靠到原始文章。用 `uid` 作为唯一标识,即使文件移动、重命名,评论也不会丢失。
### 4.2 调试技巧
- 检查是否加载成功:打开浏览器开发者工具(F12),查看控制台是否有 "[Giscus]" 开头的日志
- 检查评论容器:在 Elements 面板搜索 `giscus-container`,确认容器位置和样式是否正确
- 评论区宽度不对:检查 CSS 样式
- 评论不显示:确认 GitHub 仓库是公开的,Giscus 配置项填写正确
- 评论丢失:检查每篇笔记的 front-matter 是否有唯一的 `uid` 字段
### **4.3 这套方案的优势**
- ✅ 完全免费
- ✅ 数据自主可控
- ✅ 支持 Markdown 和表情
- ✅ 评论永不丢失
- ✅ 与 Obsidian 工作流无缝集成
### 4.4 欢迎关注我的博客
https://liu-gong-zi.com