VitePress 添加评论功能
博客想添加评论功能通常有两种方法:
- 自建或第三方的评论服务
- 基于 Github Issue 或 Discussion 等实现
使用第三方评论比较明显的缺陷是需要复杂的注册认证,而且用户评论时大概率也需要注册登录,并且可能会有广告
而基于 Github 功能实现的评论功能,可以直接借助于 Github 账号登录实现评论,而且评论直接放在仓库中个人觉得也更符合技术博客的定位。
giscus 介绍
giscus 是受 utterances 的启发,利用 GitHub Discussions 实现的评论系统。
giscus 加载时,会使用 GitHub Discussions 搜索 API 根据选定的映射方式(如 URL、pathname、<title> 等)来查找与当前页面关联的 discussion。如果找不到匹配的 discussion,giscus bot 就会在第一次有人留下评论或回应时自动创建一个 discussion。
访客如果想要评论,必须按照 GitHub OAuth 流程授权 giscus app 代表他发布,或者可以直接在 GitHub Discussion 里评论。你可以在 GitHub 上管理评论。
本系统便采用了 giscus 支持评论功能,可以在本文下方体验
使用
选择 giscus 连接到仓库前需要确保:
- 该仓库是公开的,否则访客将无法查看 discussion。
- giscus app 已安装,否则访客将无法评论和回应。
- Discussions 功能已在你的仓库中启用。
在 giscus 官网 中提供了配置并获取代码功能,按提示完成配置后可以得到这样的脚本代码:
<script
src="https://giscus.app/client.js"
data-repo="Xaviw/XaviDocs"
data-repo-id="R_kgDOGkTukw"
data-category="Announcements"
data-category-id="DIC_kwDOGkTuk84CTopZ"
data-mapping="url"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="top"
data-theme="preferred_color_scheme"
data-lang="zh-CN"
crossorigin="anonymous"
async
></script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
为了方便使用,giscus 还提供了组件的使用方式,我们在项目中安装:
pnpm i @giscus/vue
然后利用默认布局组件 Layout 的 doc-after 插槽将 giscus 组件放入页面中,并传入同上的属性(去掉data-
):
<!-- Layout.vue -->
<template>
<Layout>
<template #doc-after>
<div style="margin-top: 24px">
<Giscus
:key="page.filePath"
repo="Xaviw/XaviDocs"
repo-id="R_kgDOGkTukw"
category="Announcements"
category-id="DIC_kwDOGkTuk84CTopZ"
mapping="url"
strict="0"
reactions-enabled="1"
emit-metadata="0"
input-position="top"
theme="light"
lang="zh-CN"
/>
</div>
</template>
</Layout>
</template>
<script lang="ts" setup>
import Giscus from "@giscus/vue";
import DefaultTheme from "vitepress/theme";
import { useData } from "vitepress";
const { page } = useData();
const { Layout } = DefaultTheme;
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
为了在切换页面时刷新评论,可以将页面路径作为评论组件的 key,页面路径在 useData API 中有提供
按上面代码完成新的布局组件后(可以另行自定义或进行扩展),参考自定义主题将自定义布局组件设置为 Layout 组件即可正确渲染评论组件
亮/暗样式切换
如上操作后已经能够使用评论了,但是尝试切换亮/暗样式会发现评论组件不会跟随切换,这需要与 giscus 通信实现。
在 giscus 高级用法指南中提到了可以通过 message
与 guscus iframe 通信。所以我们只需要正确设置 giscus 的初始样式,并在切换样式时通知 giscus 同步切换,完整代码如下:
<template>
<Layout>
<template #doc-after>
<div style="margin-top: 24px">
<Giscus
:key="page.filePath"
repo="Xaviw/XaviDocs"
repo-id="R_kgDOGkTukw"
category="Announcements"
category-id="DIC_kwDOGkTuk84CTopZ"
mapping="url"
strict="0"
reactions-enabled="1"
emit-metadata="0"
input-position="top"
:theme="isDark ? 'dark' : 'light'"
lang="zh-CN"
/>
</div>
</template>
<template #not-found>
<NotFound />
</template>
</Layout>
</template>
<script lang="ts" setup>
import Giscus from "@giscus/vue";
import DefaultTheme from "vitepress/theme";
import NotFound from "./NotFound.vue";
import { watch } from "vue";
import { inBrowser, useData } from "vitepress";
const { isDark, page } = useData();
const { Layout } = DefaultTheme;
watch(isDark, (dark) => {
if (!inBrowser) return;
const iframe = document
.querySelector("giscus-widget")
?.shadowRoot?.querySelector("iframe");
iframe?.contentWindow?.postMessage(
{ giscus: { setConfig: { theme: dark ? "dark" : "light" } } },
"https://giscus.app"
);
});
</script>
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
其他配置
在 giscus 高级用法指南中还提到了 giscus.json
等其他配置,例如可以在根目录创建 giscus.json 文件并添加如下配置来限制可访问域名
{
"origins": ["https://xaviw.github.io"],
"originsRegex": ["http://localhost:[0-9]+"],
"defaultCommentOrder": "newest"
}
2
3
4
5