1475 字
7 分钟
Fuwari 主题魔改 - 给你的Fuwari添加Twikoo评论支持
2025-03-26

什么是 Twikoo#

Twikoo是一个简洁、安全、免费的静态网站评论系统,能够为个人博客等站点提供优质的评论体验,并能够对评论进行便捷的管理。

为 Fuwari 接入 Twikoo#

我们先在项目目录src/components/comment下创建文件Twikoo.astro文件,它代表着 Twikoo 组件,在这里我们使用 Twikoo 官方文档中的「通过 CDN 引入」方式。如同Fuwari-PR-37所做的那样。

<script
is:inline
src="https://cdn.staticfile.org/twikoo/1.6.32/twikoo.all.min.js"
></script>
<script is:inline define:vars="{{" config }}>
twikoo.init(config);
</script>

但这种方式存在一个问题,若twikoo.all.min.js未加载完成,但程序已经执行到了twikoo.init(config),这将会导致一种错误。

image-20250306182955541

显然,当远程文件未加载完成时,将会概率触发这个问题,未加载完成时就调用twikoo.all.min.js将会导致twikoo未定义,因此,我们应该在twikoo.all.min.js加载完成后,再执行init方法。即这篇文章所讲诉的方法。

<div id="comment"></div>
<script>
function loadTwikoo() {
const script = document.createElement("script");
script.src =
"https://cdn.jsdelivr.net/npm/twikoo@1.6.41/dist/twikoo.all.min.js";
script.defer = true;
script.onload = () => {
twikoo.init(); //在这里传入你的Twikoo配置信息
};
document.body.appendChild(script);
}
</script>
<!--Twikoo.astro-->

但这种方式似乎仍然不够完善,在这种情况下,评论组件仍然会偶现无法加载。这是由于 Fuwari 使用了swup来确保类似单页应用的平滑过渡体验,在使用swup后,JavaScript脚本并不会在每次都被重新加载,这将会导致虽然没有上述的错误,但评论组件仍然会无法正常显示。

要解决这种情况,我们可以使用swup组件库中的hooks,在swup的特定的生命周期时,hooks内的函数将会被触发并调用。因此我们可以通过hooks手动通知组件重载评论区组件。Fuwari 的hooks处理部分的函数在src/layouts/Layout.astro中,我们可以把新添加的代码书写在这里。

function initCommentComponent() {
const event = new Event("loadComment");
document.dispatchEvent(event);
}

在这里我们新建了一个函数,专用于创建loadComment的事件,即通知评论组件进行一次加载。

Layout.astrofunction init()函数内,需要添加对initCommentComponent()函数的一次调用,这样在打开网页时我们的评论将会被正确加载。

Layout.astro
function init() {
// disableAnimation()() // TODO
loadTheme();
loadHue();
initCustomScrollbar();
initCommentComponent();
showBanner();
}

随后紧接着我们还需要在swuphooks部分,添加对这个函数的调用。如Swup 文档所述,使用content:replace,这部分的函数将会在「页面的旧内容被新内容代替」时调用。我们可以紧接已存在的content:replace函数进行调用。

Layout.astro
window.swup.hooks.on("content:replace", () => {
initCustomScrollbar();
initCommentComponent();
});

在此,我们完成了对事件的传递。在Twikoo.astro中我们还要对事件进行监听,对Twikoo.astro完善后如下文所示。

Twikoo.astro
---
interface Props {
path: string;
}
const config = {
el: "#comment",
path: Astro.props.path,
};
---
<!-- 简化了配置部分的代码,实际上可以把配置文件统一写入fuwari的配置文件统一读取 -->
<div id="comment"></div>
<script define:vars={{ config }}>
function loadTwikoo() {
const script = document.createElement("script");
script.src =
"https://cdn.jsdelivr.net/npm/twikoo@1.6.41/dist/twikoo.all.min.js";
script.defer = true;
script.onload = () => {
twikoo.init({
...config,
envId: "", // 你的envId,获取方法请参照Twikoo文档
lang: "zh-CN", // 评论区语言
}); // 传入配置信息
};
document.body.appendChild(script);
}
document.addEventListener("loadComment", loadTwikoo, { once: true }); // 监听加载评论事件,但是我们只能监听一次,从而避免多次触发。
</script>

随后,在src/pages/posts/[...slug].astro中导入这个组件,我们即可看到一个标准的Twikoo评论区组件。(思路参考了这篇文章

[...slug].astro
<!--16行左右,不要忘了引入组件-->
import Twikoo from '@components/comment/Twikoo.astro'
<!--- 111行左右新增 -->
<div class="card-base p-6 mb-4"><Twikoo path={`/posts/${entry.slug}`} /></div>
<div
class="flex flex-col md:flex-row justify-between mb-4 gap-4 overflow-hidden w-full"
>
<!--原有的代码,方便参照代码插入位置-->
</div>

image-20250306234247213

Twikoo 主题魔改#

在上一节中,我们成功给 Fuwari 主题接入了 Twikoo 评论系统,但 Twikoo 的默认主题与 Fuwari 主题显得并不协调,我们希望能够将其强调色与 Fuwari 统一。并且在黑暗模式下,文本颜色并不会随 Fuwari 变化,仍然显示为默认的黑色,导致难以辨认,这我们可以通过修改 twikoo 的样式来解决。

image-20250307154449987

这里 Twikoo 的样式其实是其twikoo.all.min.js中所内嵌的样式,当然 Twikoo 也提供了不内嵌 css 的版本供用户使用,从而能够更深度的自定义 Twikoo。在Twikoo 文档中,对不同的 js 文件的功能进行了划分。

image-20250307154938348

我们仍然选择带有内嵌 css 的版本,从而在 Twikoo 内嵌样式的基础上去覆盖 Twikoo 原有样式,当然,从头开始定义 Twikoo 的样式亦可。由于我们仍然选择了内嵌 css 的版本,对 twikoo 的引入部分无需更改。

src/styles创建 css 文件,文件名任取,在这里的样式将会被自动加载,我们可以在浏览器的审查模式下,对指定元素进行选中,并根据各个元素的类名,对元素进行选中,并使用 CSS 对其样式进行修改。

image-20250307155942114

在这里,我们使用SCSS语法与Tailwindcss来简化开发,完整的 CSS 文件可以在我的Github Gists中下载。将 CSS 应用到 Fuwari 中,我们即可得到一个适配 Fuwari 主题强调色的 Twikoo 评论界面(整体布局布局参考自「园子里的时光」博客)。当然,也可以在我的 CSS 文件中,对主题进行进一步的修改。

image-20250307161015897

其余问题#

单击按钮返回顶部#

参见Twikoo-Issues-731,目前可以通过修改 Twikoo 源码,将<a>标签内href="#"去除,再对 Twikoo 重新编译,并替换 Twikoo 导入。(待寻找更好的方法)

为评论区添加小标题#

Twikoo.astro的<div id="comment"></div>使用WidgetLayout包围即可

I18nKey.comments这一项对应的i18n已在fuwari中包含,无需额外添加

Twikoo.astro
---
import WidgetLayout from "@components/widget/WidgetLayout.astro";
// ...其他的导入
---
<WidgetLayout name={i18n(I18nKey.comments)} id="comments">
<div id="comment"></div>
</WidgetLayout>
Fuwari 主题魔改 - 给你的Fuwari添加Twikoo评论支持
https://www.persicif.xyz/posts/blog-theme-mod/
作者
HyperCherry
发布于
2025-03-26
许可协议
CC BY-NC-SA 4.0
评论
昵称
邮箱
网址
0/500
  • OωO
  • |´・ω・)ノ
  • ヾ(≧∇≦*)ゝ
  • (☆ω☆)
  • (╯‵□′)╯︵┴─┴
  •  ̄﹃ ̄
  • (/ω\)
  • ∠( ᐛ 」∠)_
  • (๑•̀ㅁ•́ฅ)
  • →_→
  • ୧(๑•̀⌄•́๑)૭
  • ٩(ˊᗜˋ*)و
  • (ノ°ο°)ノ
  • (´இ皿இ`)
  • ⌇●﹏●⌇
  • (ฅ´ω`ฅ)
  • (╯°A°)╯︵○○○
  • φ( ̄∇ ̄o)
  • ヾ(´・ ・`。)ノ"
  • ( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
  • (ó﹏ò。)
  • Σ(っ °Д °;)っ
  • ( ,,´・ω・)ノ"(´っω・`。)
  • ╮(╯▽╰)╭
  • o(*////▽////*)q
  • >﹏<
  • ( ๑´•ω•) "(ㆆᴗㆆ)
  • 😂
  • 😀
  • 😅
  • 😊
  • 🙂
  • 🙃
  • 😌
  • 😍
  • 😘
  • 😜
  • 😝
  • 😏
  • 😒
  • 🙄
  • 😳
  • 😡
  • 😔
  • 😫
  • 😱
  • 😭
  • 💩
  • 👻
  • 🙌
  • 🖕
  • 👍
  • 👫
  • 👬
  • 👭
  • 🌚
  • 🌝
  • 🙈
  • 💊
  • 😶
  • 🙏
  • 🍦
  • 🍉
  • 😣
  • 颜文字
  • Emoji
  • Bilibili
  • 小电视
  • 2233娘
  • alu
  • Coolapk
11 条评论
Cherry Cherry 置顶
  • 本文中的twikoo.css具有时效性,可能会随着fuwaritwikoo的改动失效,如需要自定义设置,可以尝试自行更改,此样式文件可作参考。
  • 在更新版本的fuwari,由于更改了代码块的实现,实际效果可能与本站不同。如需复制按钮可能需要开启Twikoo自身的复制功能。(更好的实现方案有待研究)
  • 如果有更好的实现,欢迎讨论和分享喵:tv_doge:
 Linux
 Chrome 138.0.0.0
北辰三梦
回复 @Cherry :

你好,我发现您的Twikoo.astro实现在新的Fuwari版本中有bug

document.addEventListener("loadComment", loadTwikoo, { once: true });

这里用了 { once: true },意味着只会响应 第一次 loadComment 事件,后续 Swup 页面切换时再 dispatchEvent(“loadComment”) 就不会触发了,所以评论区只会在首次打开时出现,之后就没了。

 Windows 10
 Chrome 139.0.0.0
北辰三梦
回复 @Cherry :

所以说我通过询问GPT做了debug
https://imgbed.ztab.dpdns.org/file/1755654917074_Twikoo.astro
这个实现我实测没有问题,也请问大佬有没有可能是我自己的环境问题还是说新版本Fuwari改了实现呢
也恳请大佬帮忙看看我写的这个版本有没有问题

 Windows 10
 Chrome 139.0.0.0
Cherry Cherry
回复 @北辰三梦 :
  • 我基于Fuwari截至目前最新的提交进行了测试,在使用本文的方法时没有复现出你所描述的问题。
  • 请确保initCommentComponent()方法在function init()window.swup.hooks.on("content:replace")中均被正确调用。
  • 由于Swup在切换界面后不重置 DOM 事件绑定,在之前添加的事件监听均不会被自动销毁,在切换到其他界面时,可能会多次触发Twikoo加载,这也是我添加了once的原因。你可以在初始化代码中添加日志输出来验证这一点。我这样的全局事件监听方式确实欠妥,可以考虑更换更好的实现。
  • 的确可以如你给出的代码中,判断Twikoo的JavaScript是否被加载从而避免重复的加载JavaScript脚本。你给出的代码没有其余问题,但仍斟酌是否添加once,或尝试更换其他更好的实现方法。
 Linux
 Chrome 139.0.0.0
北辰三梦
回复 @Cherry :

好的,以及是否和我的操作步骤有关系?我是从未修改网站刷新到修改网站的,但我觉得也不太可能。我有两个CDN,一个是VercelCDN,一个是CloudflareCDN,难道是这两个同时命中了缓存规则?还有可以挂友链吗https://bcsm.us.kg

 Windows 10
 Chrome 139.0.0.0
Cherry Cherry
回复 @北辰三梦 :

这我就不太清楚了。友链已经添加了,欢迎:bilibili2233-10:

 Linux
 Chrome 139.0.0.0
展开
MC_Kero

感觉还不错,就是看起来不熟挺麻烦的。

 Android Tiramisu
 Firefox 142.0
ellye

好看

 macOS 15.6.1
 Chrome 139.0.0.0
MC_Kero

感觉不错啊

 Android Quince Tart
 Microsoft Edge 138.0.0.0
查看更多