跳转到内容
文韬博宇的个人主页
返回

【转载】如何在 AstroPaper 中集成 Giscus 评论功能

更新于:
· 约 3 分钟· 约 879 字阅读0编辑页面

GitHub Pages 这类平台上托管一个轻量静态博客有许多优势,但也牺牲了一些交互性。幸运的是,Giscus 提供了一种在静态站点上嵌入用户评论的方案。

目录

Giscus 的工作原理

Giscus 使用 GitHub API 来读取并存储 GitHub 用户在仓库关联的 Discussions 中发表的评论。

在站点上嵌入 Giscus 的客户端脚本包,用正确的仓库 URL 进行配置,用户便能查看并撰写评论(需登录 GitHub)。

这种方式是无服务器的:评论存储于 GitHub 上,并在客户端动态加载,因此非常适合 AstroPaper 这样的静态博客。

配置 Giscus

Giscus 可以在 giscus.app 上轻松完成配置,不过我仍会简要梳理一下流程。

前置条件

要让 Giscus 正常工作,需满足以下前置条件:

遗憾的是,如果因任何原因无法满足上述任一条件,便无法集成 Giscus

配置 Giscus

接下来,需要对 Giscus 进行配置。在大多数情况下,预选的默认值都是合适的,只有在你有明确理由且清楚自己在做什么时才需要修改。不必过于担心选错,因为你随时可以在之后调整配置。

但你需要:

完成设置后,Giscus 会为你生成一段 <script> 标签,在后续步骤中会用到它。

简易脚本标签

现在你应该已经得到一段类似如下的脚本标签:

<script
  src="https://giscus.app/client.js"
  data-repo="[ENTER REPO HERE]"
  data-repo-id="[ENTER REPO ID HERE]"
  data-category="[ENTER CATEGORY NAME HERE]"
  data-category-id="[ENTER CATEGORY ID HERE]"
  data-mapping="pathname"
  data-strict="0"
  data-reactions-enabled="1"
  data-emit-metadata="0"
  data-input-position="bottom"
  data-theme="preferred_color_scheme"
  data-lang="en"
  crossorigin="anonymous"
  async
></script>

只需将其添加到站点的源代码中。如果你使用的是 AstroPaper 并希望在文章页面启用评论,很可能只需打开 PostDetails.astro,将它粘贴到想要显示评论的位置——比如 Share this post on:(分享本文)按钮的下方。

<Layout {...layoutProps}>
  <main>
    <ShareLinks />

    <script
      src="https://giscus.app/client.js"
      data-repo="[ENTER REPO HERE]"
      data-repo-id="[ENTER REPO ID HERE]"
      data-category="[ENTER CATEGORY NAME HERE]"
      data-category-id="[ENTER CATEGORY ID HERE]"></script>
  </main>
  <Footer />
</Layout>src/layouts/PostDetails.astro

大功告成!你已成功在 AstroPaper 中集成了评论功能!

支持浅色/深色主题的 React 组件

布局中嵌入的脚本标签相当静态——Giscus 的配置(包括 theme)被硬编码在布局里。鉴于 AstroPaper 提供了浅色/深色主题切换功能,若能让评论区随站点其余部分无缝地在浅色与深色主题间切换,体验会更好。为此,需要一种更复杂的 Giscus 嵌入方式。

首先,我们来安装 GiscusReact 组件

npm i @giscus/react && npx astro add react

接着,在 src/components 目录下新建一个 Comments.tsx React 组件:

import Giscus, { type Theme } from "@giscus/react";
import { GISCUS } from "@/constants";
import { useEffect, useState } from "react";

interface CommentsProps {
  lightTheme?: Theme;
  darkTheme?: Theme;
}

export default function Comments({
  lightTheme = "light",
  darkTheme = "dark",
}: CommentsProps) {
  const [theme, setTheme] = useState(() => {
    const currentTheme = localStorage.getItem("theme");
    const browserTheme = window.matchMedia("(prefers-color-scheme: dark)")
      .matches
      ? "dark"
      : "light";

    return currentTheme || browserTheme;
  });

  useEffect(() => {
    const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
    const handleChange = ({ matches }: MediaQueryListEvent) => {
      setTheme(matches ? "dark" : "light");
    };

    mediaQuery.addEventListener("change", handleChange);

    return () => mediaQuery.removeEventListener("change", handleChange);
  }, []);

  useEffect(() => {
    const themeButton = document.querySelector("#theme-btn");
    const handleClick = () => {
      setTheme(prevTheme => (prevTheme === "dark" ? "light" : "dark"));
    };

    themeButton?.addEventListener("click", handleClick);

    return () => themeButton?.removeEventListener("click", handleClick);
  }, []);

  return (
    <div className="mt-8">
      <Giscus theme={theme === "light" ? lightTheme : darkTheme} {...GISCUS} />
    </div>
  );
}src/components/Comments.tsx

这个 React 组件不仅封装了原生的 Giscus 组件,还引入了两个额外的 props:lightThemedarkTheme。借助两个事件监听器,Giscus 评论区将与站点主题保持一致,并在站点或浏览器主题发生变化时,在深色与浅色之间动态切换。

我们还需要定义 GISCUS 配置,最合适的位置是在 constants.ts 中:

import type { GiscusProps } from "@giscus/react";

...

export const GISCUS: GiscusProps = {
  repo: "[ENTER REPO HERE]",
  repoId: "[ENTER REPO ID HERE]",
  category: "[ENTER CATEGORY NAME HERE]",
  categoryId: "[ENTER CATEGORY ID HERE]",
  mapping: "pathname",
  reactionsEnabled: "0",
  emitMetadata: "0",
  inputPosition: "bottom",
  lang: "en",
  loading: "lazy",
};src/constants.ts

注意:此处若指定了 theme,将会覆盖 lightThemedarkTheme 这两个 props,从而导致静态主题设置,效果与之前用 <script> 标签嵌入 Giscus 的方案类似。

为完成整个流程,请将新的 Comments 组件添加到 PostDetails.astro 中(替换掉上一步添加的 script 标签)。

import Comments from "@/components/Comments";

<ShareLinks />

<Comments client:only="react" />

<hr class="my-6 border-dashed" />

<Footer />src/layouts/PostDetails.astro

至此全部完成!


编辑页面
分享这篇文章:

评论


上一篇
【转载】如何在 Astro 博客文章中添加 LaTeX 公式