添加 giscus 评论功能
安装依赖
- npm
- Yarn
- pnpm
npm install --save @giscus/react
yarn add @giscus/react
pnpm add @giscus/react
创建评论组件
src/components/Comment.tsx
import React from 'react'
import { useThemeConfig, useColorMode } from '@docusaurus/theme-common'
import Giscus, { GiscusProps } from '@giscus/react'
import { useLocation } from '@docusaurus/router';
const defaultConfig: Partial<GiscusProps> = {
id: 'comments',
mapping: 'specific',
reactionsEnabled: '1',
emitMetadata: '0',
inputPosition: 'top',
loading: 'lazy',
strict: '1', // 用根据路径标题自动生成的 sha1 值,精确匹配 github discussion,避免路径重叠(比如父和子 路径)时评论加载串了
lang: 'zh-CN',
}
export default function Comment(): JSX.Element {
const themeConfig = useThemeConfig()
// merge default config
const giscus = { ...defaultConfig, ...themeConfig.giscus }
if (!giscus.repo || !giscus.repoId || !giscus.categoryId) {
throw new Error(
'You must provide `repo`, `repoId`, and `categoryId` to `themeConfig.giscus`.',
)
}
const path = useLocation().pathname.replace(/^\/|\/$/g, '');
const firstSlashIndex = path.indexOf('/');
var subPath: string = ""
if (firstSlashIndex !== -1) {
subPath = path.substring(firstSlashIndex + 1)
} else {
subPath = "index"
}
giscus.term = subPath
giscus.theme =
useColorMode().colorMode === 'dark' ? 'transparent_dark' : 'light'
return (
<Giscus {...giscus} />
)
}
是否需要支持隐藏评论?
在让页面支持评论功能之前,先确定下,是否需要支持隐藏评论。
因为需要通过 swizzling 的方式修改页面将评论功能嵌入进去。如果需要 隐藏评论就需要通过 eject
的方式完全自定义页面以便拿到页面的 metadata 来判断是否要隐藏评论;而如果不需要隐藏评论,就只需要使用 wrap
的方式对页面进行跟轻量的修改。
两者都需要修改文档页面组件,有一定的侵入性,但 eject
方式相比 wrap
方式侵入性更大,在升级 docusaurus 的时候,前者更容易出现兼容性问题,如果出现不兼容就需要按照下文的方式重新 swizzle 并修改代码。
最佳实践是:如果不需要隐藏评论这种功能,就用 wrap
方式修改页面组件。
不支持隐藏的评论
本人就是使用的这种方式,因为没有隐藏评论的需求,也避免升级 docusaurus 时出现兼容性问题,下面介绍具体操作步骤。
文档页面启用评论
文档页面由 docusaurus 的 DocItem/Layout
组件渲染,下面是自定义方法。
- swizzle
DocItem
:
- npm
- Yarn
- pnpm
npm run swizzle @docusaurus/theme-classic DocItem/Layout -- --wrap --typescript
yarn swizzle @docusaurus/theme-classic DocItem/Layout --wrap --typescript
pnpm run swizzle @docusaurus/theme-classic DocItem/Layout --wrap --typescript
- 修改以下自动生成的源码文件(高亮的行是增加的内容):
src/theme/DocItem/Layout/index.tsx
import React from 'react';
import Layout from '@theme-original/DocItem/Layout';
import type LayoutType from '@theme/DocItem/Layout';
import type { WrapperProps } from '@docusaurus/types';
import Comment from '@site/src/components/Comment';
type Props = WrapperProps<typeof LayoutType>;
export default function LayoutWrapper(props: Props): JSX.Element {
return (
<>
<Layout {...props} />
<Comment />
</>
);
}
文档目录页面启用评论
所谓文档目录页面就是自动生成的目录页面 (category
),没有对应的 markdown 文件,这种页面是由 docusaurus 的 DocCategoryGeneratedIndexPage
渲染的,下面是自定义方法。
- swizzle
DocCategoryGeneratedIndexPage
:
- npm
- Yarn
- pnpm
npm run swizzle @docusaurus/theme-classic DocCategoryGeneratedIndexPage -- --wrap --typescript
yarn swizzle @docusaurus/theme-classic DocCategoryGeneratedIndexPage --wrap --typescript
pnpm run swizzle @docusaurus/theme-classic DocCategoryGeneratedIndexPage --wrap --typescript
- 修改以下自动生成的源码文件(高亮的行是增加的内容):
src/theme/DocCategoryGeneratedIndexPage/index.tsx
import React from 'react';
import DocCategoryGeneratedIndexPage from '@theme-original/DocCategoryGeneratedIndexPage';
import type DocCategoryGeneratedIndexPageType from '@theme/DocCategoryGeneratedIndexPage';
import type { WrapperProps } from '@docusaurus/types';
import Comment from '@site/src/components/Comment';
type Props = WrapperProps<typeof DocCategoryGeneratedIndexPageType>;
export default function DocCategoryGeneratedIndexPageWrapper(props: Props): JSX.Element {
return (
<>
<DocCategoryGeneratedIndexPage {...props} />
<Comment />
</>
);
}
支持隐藏的评论
如果有隐藏评论的需求,就需要对页面做更深度的自定义,使用 eject
方式将页面组件源码弹出到 theme
下,基于源码进行修改。
文档页面支持评论
- swizzle
DocItem
:
- npm
- Yarn
- pnpm
npm run swizzle @docusaurus/theme-classic DocItem/Layout -- --eject --typescript
yarn swizzle @docusaurus/theme-classic DocItem/Layout --eject --typescript
pnpm run swizzle @docusaurus/theme-classic DocItem/Layout --eject --typescript