2024-07-29 Update

最后还是放弃了自建,换成了 Giscus

2024-07-17 Update

跟随源码1添加更换日夜模式的代码:

  // @plodibre: Listen for theme changes and sync r42 if it changes
  const buttonListener: string = `
  document.querySelector('#darkmode-toggle').addEventListener('click', (_e) => {
    let currentTheme = document.documentElement.getAttribute('saved-theme')
    currentTheme = currentTheme === 'dark' ? 'light' : 'dark'
    if(window.REMARK42)
      window.REMARK42.changeTheme(currentTheme)
  })
`
  scripts.push({ script: buttonListener, loadTime: "afterDOMReady", contentType: "inline" })

由于 Quartz 实现了 afterBody layout,因此可以尝试将评论区挪到这里。


参考 Remark42 CommentsFrontend Configuration 添加,顺便简单看看 Typescript 语法。

Remark42 的搭建在此不谈,看看网友是怎么把它嵌入 Quartz 的。他建了一个 transformer 插件2 remark42.ts1,基本上是重写了 Remark42 文档的前端配置,因此我就直接将它放进了自己 clone 的项目中,之后在 quartz/plugins/transformers/index.ts 导出插件,在 quartz.config.ts 中添加配置,最后在 footer(quartz/components/Footer.tsx) 中添加 <div id="remark42"></div>,基本上是按照评论区来的。

但是在实际使用中,我发现了一个问题即:如果不强制刷新,那么只会保留第一个页面的评论区。在仔细查看代码后我终于发现了原因,因为 Quartz 支持 SPA,Remark42 插件也参考官方文档实现了 SPA mode:

quartz/plugins/transformers/remark42.ts
  // Allow SPA mode
  const spaRouting : string = `
  function initRemark42() {
    if (window.REMARK42) {
      if (this.remark42Instance) {
        this.remark42Instance.destroy()
      }
 
      this.remark42Instance = window.REMARK42.createInstance(remark_config)
    }
  }
 
  document.addEventListener('nav', () => {
    this.initRemark42()
  })
`
  scripts.push({script:spaRouting, loadTime:"afterDOMReady", contentType:"inline"})

简单来说就是将这一段代码注入到 quartz 生成的 html 文件中作为 js,它会在导航到新页面的时候执行 initRemark42 函数,销毁当前的 remark42Instance 并创建一个新的 remark42Instance

这段逻辑看起来没有问题,但是仔细研究就会发现,remark42 的评论区是和 remark_config['url'] 绑定的,一个页面对应一个评论区。

而在这个函数中,remark_config['url'] 并没有被设置,因此会是默认值,也就是我们第一次进来时设置的 window.location.origin + window.location.pathname,这样导致只要我们在这个页面中,只要不刷新就只会生成第一个页面的评论区。

好,知道问题所在,那么解决方案就很明朗了,只要我们手动添加 remark_config['url']window.location.origin + window.location.pathname 即可:

diff --git a/quartz/plugins/transformers/remark42.ts b/quartz/plugins/transformers/remark42.ts
index f8f8fed..f3fa2c2 100644
--- a/quartz/plugins/transformers/remark42.ts
+++ b/quartz/plugins/transformers/remark42.ts
@@ -50,7 +50,7 @@ export const Remark42: QuartzTransformerPlugin<Options> = (opts?: Options) => {
       if (this.remark42Instance) {
         this.remark42Instance.destroy()
       }
-
+      remark_config['url'] = window.location.origin + window.location.pathname
       this.remark42Instance = window.REMARK42.createInstance(remark_config)
     }
   }

不过目前还有一些问题:

  • 由于 Remark42 添加在了 footer 中,因此会为所有页面添加评论区。可以考虑限制它的出现位置。

Footnotes

  1. https://github.com/bfahrenfort/quartz/blob/v4/quartz/plugins/transformers/remark42.ts 2

  2. Making your own plugins