【已解决】docusaurus 增加评论系统

背景

像docusaurus这种静态网站本身是没有自带评论系统的,但是我们可以使用第三方的giscus增加。
先看下实现的效果如下:

和整体网页能够保持统一,且打开网页时候会自动进行加载,也可以配置为懒加载。

使用giscus

以下内容出自博客在 Docusaurus 中添加评论系统

先决条件

  • 你的项目运行 Docusaurus,至少有一篇博文或文档
  • 你安装的主题是theme classic,也是默认的。
  • 根据对应的评论插件注册一下拿到配置

配置 giscus

先登录你的github账号安装 giscus 应用 giscus app

进到giscus的官网配置好语言、评论要发到的github仓库、页面与映射关系, 选择一个discussion分类、主题等。

配置的时候注意看这三点

启用Discussions在仓库的Setting中可以找到

页面 ↔️ discussion 映射关系 一般选择Pathname就行。实际生成的评论的时候,会以你的博客请求路径创建一个类似话题的讨论。

拿到配置好的 <script> 标签, 类似:

<script src="https://giscus.app/client.js"
        data-repo="xxxxx"
        data-repo-id="xxxx"
        data-category="xxxx"
        data-category-id="xxxxx"
        data-mapping="pathname"
        data-reactions-enabled="1"
        data-emit-metadata="0"
        data-input-position="bottom"
        data-theme="light"
        data-lang="zh-CN"
        crossorigin="anonymous"
        async>

在你的 Docusaurus 项目根目录执行

yarn swizzle @docusaurus/theme-classic BlogPostPage

选择 Eject (Unsafe) 回车

选择 YES: I know what I am doing! 回车

这时你的项目目录下src/theme/BlogPostPage生成了自定义主题的文件

注意:这里生成的文件只对你的Blog目录下的文章插入评论系统
如果你要在docs目录下也插入评论系统,则还需要执行命令:
yarn swizzle @docusaurus/theme-classic DocItem/Layout

下一步修改文件

下面三处标注是我们要修改添加代码的地方。 注意版本不同配置可能存在差异 根据标注自己找放评论的位置。

改动文件为:src/theme/BlogPostPage/index.js

//开始1
import React, { useEffect, useRef }  from 'react';
//结束1
import clsx from 'clsx';
import {HtmlClassNameProvider, ThemeClassNames} from '@docusaurus/theme-common';
import {BlogPostProvider, useBlogPost} from '@docusaurus/theme-common/internal';
import BlogLayout from '@theme/BlogLayout';
import BlogPostItem from '@theme/BlogPostItem';
import BlogPostPaginator from '@theme/BlogPostPaginator';
import BlogPostPageMetadata from '@theme/BlogPostPage/Metadata';
import TOC from '@theme/TOC';
function BlogPostPageContent({sidebar, children}) {
  const {metadata, toc} = useBlogPost();
  const {nextItem, prevItem, frontMatter} = metadata;
  const {
    hide_table_of_contents: hideTableOfContents,
    toc_min_heading_level: tocMinHeadingLevel,
    toc_max_heading_level: tocMaxHeadingLevel,
  } = frontMatter;

//开始2
  const commentElement = useRef(null);

  useEffect(() => {
    // Update the document title using the browser API
    let s = document.createElement("script");
    s.src = "https://giscus.app/client.js";
    s.setAttribute("data-repo", "[你的仓库]");
    s.setAttribute("data-repo-id", "[你的仓库 ID]=");
    s.setAttribute("data-category", "[你的分类名]");
    s.setAttribute("data-category-id", "[你的分类 ID]");
    s.setAttribute("data-mapping", "pathname");
    s.setAttribute("data-reactions-enabled", "1");
    s.setAttribute("data-emit-metadata", "0");
    s.setAttribute("data-input-position", "bottom");
    s.setAttribute("data-theme", "light");
    s.setAttribute("data-lang", "zh-CN");
    s.setAttribute("crossorigin", "anonymous");
    s.async = true;
    commentElement.current.appendChild(s);
  }, []);
//结束2

  return (
    <BlogLayout
      sidebar={sidebar}
      toc={
        !hideTableOfContents && toc.length > 0 ? (
          <TOC
            toc={toc}
            minHeadingLevel={tocMinHeadingLevel}
            maxHeadingLevel={tocMaxHeadingLevel}
          />
        ) : undefined
      }>
      <BlogPostItem>{children}</BlogPostItem>

      {(nextItem || prevItem) && (
        <BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />
      )}

//开始3
      <div style={{marginTop:'20px'}} ref={commentElement}></div>
//结束3

    </BlogLayout>
  );
}
export default function BlogPostPage(props) {
  const BlogPostContent = props.content;
  return (
    <BlogPostProvider content={props.content} isBlogPostPage>
      <HtmlClassNameProvider
        className={clsx(
          ThemeClassNames.wrapper.blogPages,
          ThemeClassNames.page.blogPostPage,
        )}>
        <BlogPostPageMetadata />
        <BlogPostPageContent sidebar={props.sidebar}>
          <BlogPostContent />
        </BlogPostPageContent>
      </HtmlClassNameProvider>
    </BlogPostProvider>
  );
}

至此评论添加完成。

而如果刚刚你对docs目录也执行yarn swizzle.

那么图片下的两个文件都是需要改的,改动点和上面的一样。

你可以参考我的更改:

import React, { useEffect, useRef }  from 'react';
import clsx from 'clsx';
import {useWindowSize} from '@docusaurus/theme-common';
import {useDoc} from '@docusaurus/theme-common/internal';
import DocItemPaginator from '@theme/DocItem/Paginator';
import DocVersionBanner from '@theme/DocVersionBanner';
import DocVersionBadge from '@theme/DocVersionBadge';
import DocItemFooter from '@theme/DocItem/Footer';
import DocItemTOCMobile from '@theme/DocItem/TOC/Mobile';
import DocItemTOCDesktop from '@theme/DocItem/TOC/Desktop';
import DocItemContent from '@theme/DocItem/Content';
import DocBreadcrumbs from '@theme/DocBreadcrumbs';
import Unlisted from '@theme/Unlisted';
import styles from './styles.module.css';
/**
 * Decide if the toc should be rendered, on mobile or desktop viewports
 */
function useDocTOC() {
  const {frontMatter, toc} = useDoc();
  const windowSize = useWindowSize();
  const hidden = frontMatter.hide_table_of_contents;
  const canRender = !hidden && toc.length > 0;
  const mobile = canRender ? <DocItemTOCMobile /> : undefined;
  const desktop =
    canRender && (windowSize === 'desktop' || windowSize === 'ssr') ? (
      <DocItemTOCDesktop />
    ) : undefined;
  return {
    hidden,
    mobile,
    desktop,
  };
}
export default function DocItemLayout({children}) {
  const docTOC = useDocTOC();
  const {
    metadata: {unlisted},
  } = useDoc();


  const commentElement = useRef(null);

  useEffect(() => {
    // Update the document title using the browser API
    let s = document.createElement("script");
    s.src = "https://giscus.app/client.js";
    s.setAttribute("data-repo", "MingGH/996-ninja-giscus");
    s.setAttribute("data-repo-id", "R_kgDOL5y6Fw");
    s.setAttribute("data-category", "General");
    s.setAttribute("data-category-id", "DIC_kwDOL5y6F84CfRWy");
    s.setAttribute("data-mapping", "pathname");
    s.setAttribute("data-reactions-enabled", "1");
    s.setAttribute("data-emit-metadata", "0");
    s.setAttribute("data-input-position", "bottom");
    s.setAttribute("data-theme", "preferred_color_scheme");
    s.setAttribute("data-lang", "zh-CN");
    s.setAttribute("data-loading", "lazy");
    s.setAttribute("crossorigin", "anonymous");
    s.async = true;
    commentElement.current.appendChild(s);
  }, []);

  return (
    <div className="row">
      <div className={clsx('col', !docTOC.hidden && styles.docItemCol)}>
        {unlisted && <Unlisted />}
        <DocVersionBanner />
        <div className={styles.docItemContainer}>
          <article>
            <DocBreadcrumbs/>
            <DocVersionBadge/>
            {docTOC.mobile}
            <DocItemContent>{children}</DocItemContent>
            <div style={{marginTop: '20px'}} ref={commentElement}></div>
            <DocItemFooter/>
          </article>
          <DocItemPaginator/>
        </div>
      </div>
      {docTOC.desktop && <div className="col col--3">{docTOC.desktop}</div>}
    </div>
  );
}

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×