diff --git "a/content/zh/post/2024/hugo\350\257\204\350\256\272\347\273\204\344\273\266\350\207\252\351\200\202\345\272\224\345\215\232\345\256\242\346\232\227\351\273\221\344\270\273\351\242\230.md" "b/content/zh/post/2024/hugo\350\257\204\350\256\272\347\273\204\344\273\266\350\207\252\351\200\202\345\272\224\345\215\232\345\256\242\346\232\227\351\273\221\344\270\273\351\242\230.md" new file mode 100644 index 00000000..89f52335 --- /dev/null +++ "b/content/zh/post/2024/hugo\350\257\204\350\256\272\347\273\204\344\273\266\350\207\252\351\200\202\345\272\224\345\215\232\345\256\242\346\232\227\351\273\221\344\270\273\351\242\230.md" @@ -0,0 +1,137 @@ ++++ +title = "Hugo评论系统自适应博客主题: 支持dark与light theme" +date = 2024-12-04T13:25:00+08:00 +lastmod = 2024-12-04T14:27:41+08:00 +tags = ["blog", "hugo"] +categories = ["blog", "hugo"] +draft = false +toc = true ++++ + +## 1 问题 {#问题} + +评论系统是博客的关键组件,Hugo 支持若干个评论系统,包括流行的 [Disqus](https://disqus.com/), 基于 GitHub 的 [Giscus](https://giscus.app) 和 [Utteranc](https://utteranc.es/), 以及其他[评论系统](https://gohugo.io/content-management/comments/) + +我[博客](https://ramsayleung.github.io/)使用的评论系统是 Utteranc, 主题是 [PaperMod](https://github.com/adityatelange/hugo-PaperMod/), PaperMod 支持 dark 和 light 两种主题, 在初始化 Utteranc 时可以指定 theme, 如 `Github-Light` + +```html + +``` + +但是 theme 在初始化时就指定好了,那么在博客切换到 dark theme 的时候, Utteranc 也不会自适应 dark theme,博客的theme与评论theme就不一致: + +{{< figure src="/ox-hugo/responsive_comment_theme.jpg" >}} + + +## 2 解决思路 {#解决思路} + +解决思路其实很简单,就获取当前的 theme, 然后再初始化 Utteranc 对应的 theme; 再在用户切换 theme 之后,再重新初始化 `Utteranc`. + + +### 2.1 获取当前Theme {#获取当前theme} + +Hugo 并没有提供标准接口来获取当前主题, 虽然可以通过以下的方式来获取的 theme: + +```js +const isDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches; +console.log(isDarkMode ? 'dark' : 'light'); +``` + +但是这个是通过编译出来的CSS来判断当前theme,用户一旦手动切换了 theme, 上面的代码就无法生效了. + +每个Hugo主题定义的方式可能还不一样, 以 PaperMod 为例,观察之后发现,light theme的时候body的html 为: + +```css +
+ +``` + +dark theme 的时候 `class` 就变为了 `class`"dark"=: + +```css + + +``` + +所以可以通过判断 `body` 是否包含 `dark` 的 class 来判断当前是否为 dark theme. + +```js +// 不同的Hugo theme可能会需要不同的判断方式 +function getCurrentTheme() { + return document.body.classList.contains('dark') ? 'dark' : 'light'; +} +``` + + +### 2.2 初始化评论系统 {#初始化评论系统} + +[Utteranc](https://utteranc.es/) 文档提供的启用评价系统代码如下: + +```html + +``` + +因为我们需要在切换 Theme 时重新加载 Utteranc, 所以就需要通过 Javascript 来实现上面的HTML功能: + +```js +function loadUtterances(darkMode=false) { + const commentContainer = document.getElementById("comments-utteranc"); + if (commentContainer !== null) { + commentContainer.innerHTML = '' + const commentScript = document.createElement("script"); + commentScript.setAttribute("id", "utteranc"); + commentScript.setAttribute("src", "https://utteranc.es/client.js"); + commentScript.setAttribute("data-repo", "ramsayleung/comment"); + commentScript.setAttribute("data-theme", darkMode ? "github-dark" : "github-light"); + commentScript.setAttribute("data-issue-term", "title"); + commentScript.setAttribute("crossorigin", "anonymous"); + commentScript.setAttribute("async", "true"); + commentContainer.appendChild(commentScript); + } +} +``` + + +### 2.3 监听主题变动 {#监听主题变动} + +用户可以在博客界面手动选择他们喜欢的主题,可以从 `dark` -> `light`, `light` -> `dark`, 我们需要做的就是监听主题的变动,在切换主题之后,重新加载评论系统。 + +```js +// Watch for theme changes +const themeObserver = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + if (mutation.type === 'attributes' && mutation.attributeName === 'class') { + const isDarkMode = getCurrentTheme() === 'dark'; + loadUtterances(isDarkMode); + console.log(`changing theme`); + } + }); +}); + +// Start observing the body element for class changes +themeObserver.observe(document.body, { + attributes: true, + attributeFilter: ['class'] +}); +``` + + +## 3 总结 {#总结} + +自适应评论系统的代码[在这里](https://github.com/ramsayleung/ramsayleung.github.io/blob/master/layouts/partials/comments.html), 实现的效果如下: + +{{< figure src="/ox-hugo/responsive_comment_theme_2.jpg" >}} + +{{< figure src="/ox-hugo/responsive_comment_theme_3.jpg" >}} diff --git a/static/ox-hugo/responsive_comment_theme.jpg b/static/ox-hugo/responsive_comment_theme.jpg new file mode 100644 index 00000000..a26b1356 Binary files /dev/null and b/static/ox-hugo/responsive_comment_theme.jpg differ diff --git a/static/ox-hugo/responsive_comment_theme_2.jpg b/static/ox-hugo/responsive_comment_theme_2.jpg new file mode 100644 index 00000000..a583e6aa Binary files /dev/null and b/static/ox-hugo/responsive_comment_theme_2.jpg differ diff --git a/static/ox-hugo/responsive_comment_theme_3.jpg b/static/ox-hugo/responsive_comment_theme_3.jpg new file mode 100644 index 00000000..6db0bbeb Binary files /dev/null and b/static/ox-hugo/responsive_comment_theme_3.jpg differ