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
评论