This page looks best with JavaScript enabled

Hugo | 为Zzo主题添加Waline评论

如果熟悉原理可能适用于所有Hugo主题?(怎么可能)

 ·  ☕ 11 min read

为什么要水这篇文章

给博客换主题的时候发现MemE主题和Zzo主题的评论配置文件有出入,不能直接套用现有的MemE主题Waline配置。所以我灵机一动:要不我自己搞吧。

以MemE,Zzo和stack三个主题为例,看一下不同主题的评论配置有什么不同:

首先看一下MemE主题的评论配置

MemE主题支持Valine,因为Waline是Valine的改良版,所以可以互相参考配置。首先主题的github项目中搜索Valine,可以看到除了config-examples/zh-cn/config.toml(主题的简体配置文件,这里不考虑繁体中文和英文,只是配置文件的语言项)以外,还有三个文件提到了Valine,分别是layouts/partials/third-party/valine.htmllayouts/partials/third-party/script.htmllayouts/partials/components/comments.html

各文件的作用:

  • comments.html文件的作用是控制是否开启评论(enableComments),开启哪个评论系统(enableValine),如果开启,则插入相关评论的<div>标签 id;
  • script.html文件的作用是载入开启的评论的相应 HTML 文件(valine.html)
  • valine.html文件的作用是调用valine.js,对评论功能进行设定。

再来来看一下Zzo主题的评论配置

同样在MemE在github项目中搜索Valine,可以看到除了config/_default/params.toml(主题的配置文件之一,Zzo主题把正常的config.toml分成了四个,params.toml是其中一个)以外,还有两个文件:layouts/partials/comments/valine.htmllayouts/partials/comments/comments.html

各文件的作用:

  • comments.html文件的作用是控制是否开启评论(enableComments),开启哪个评论系统(enableValine),如果开启,则直接载入开启的评论的相应 HTML 文件(valine.html)
  • valine.html文件的作用是对评论功能进行设定。

这样一来,Zzo就不用像MemE一样需要script.html文件专门用来载入valine.html,因为功能被合并了。

附加题:看看同样美貌的stack主题!

stack主题支持Waline而不支持Valine,这是我万万没想到的(笑)。同样地,首先在项目中搜索Waline,发现除了config.yaml(stack主题的配置文件,和config.toml是一个东西)以外只有layouts/partials/comments/provider/waline.html提到了Waline,而且在文件中强制插入<div>标签 id,并且也对评论功能进行设定。

Waline是什么,为什么说他是Valine的改良版

请看这篇博客。简而言之就是Gitalk 和 Valine都有一定的安全隐患,于是Waline诞生了。

部署Waline

按照Waline官方文档快速开始。

第一步推荐使用 LeanCloud 国际版,因为国内版还需要和备案的域名绑定,很是麻烦。第二步利用Vercel部署Waline,点击官方给出的快速部署链接,也就是那个deploy蓝色按钮,然后按照官方文档继续部署,直到你获得ServerURL,也就是服务端地址。

题外话:有段时间Waline的快速部署链接失效,因为github仓库的主分支由master改为main,而快速部署链接还没来得及修改,因此clone project会出现错误,现在已经没问题了。

你也可以为这个Vercel项目添加一个子域名。另外还要注意,每次更改环境变量之后都要Redeploy(重新部署)使改动生效。

开始配置吧

修改配置文件

以Zzo主题为例,回到本地的博客根目录,在config/_default/params.toml中,打开评论全局设置,然后找到Valine的配置,按照Valine的格式在他的下方抄一份Waline的配置,比如我的如下:

1
2
3
4
5
6
7
8
9
[waline]
  enable = false
  appId = '你的appId'
  appKey = '你的appKey'
  notify = false  # mail notifier , https://github.com/xCss/Valine/wiki
  verify = false # Verification code
  avatar = 'mm' 
  placeholder = '说点什么吧...'
  visitor = false

但是这些配置项是valine需要的,而不一定是waline需要的。根据官方文档给出的前端配置,我对params.toml进行了改动,最后的配置如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
[Waline]
    enable = true
    ServerURL = "你的ServerURL"
    Placeholder = "ヾノ≧∀≦)o来评论啊!"  #留言框占位提示文字
    Avatar = "mp"
    Meta = ["nick", "mail", "link"]
    PageSize = 10
    Lang = "zh-CN"
    Highlight = true
    AvatarCDN = "https://cdn.v2ex.com/gravatar/"  #waline的评论头像可以使用某种样式也可以使用cdn,这里用v2ex的cdn
    RequiredFields = ["nick", "mail"]

进入Zzo主题文件夹,找到之前说过的两个和Valine有关的文件,也就是layouts/partials/comments/valine.htmllayouts/partials/comments/comments.html,把他们两个复制到~/layouts/partials/comments/valine.html~/layouts/partials/comments/comments.html中(博客根目录下)。

Valine是你的模板,Waline要长得和他一模一样

valine.html重命名为waline.html用visual studio打开,看一下这个文件长什么样:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
{{- if .Site.Params.valine.visitor -}}
  <span id="{{ .RelPermalink | relLangURL }}" class="leancloud_visitors" data-flag-title="{{ .Title }}">
  <span class="post-meta-item-text">文章阅读量 </span>
  <span class="leancloud-visitors-count">0</span>
  <p></p>
  </span>
{{- end }}
<div id="vcomments"></div>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src='//unpkg.com/valine/dist/Valine.min.js'></script>
<script>
  new Valine({
      el: '#vcomments' ,
      appId: '{{ .Site.Params.valine.appId }}',
      appKey: '{{ .Site.Params.valine.appKey }}',
      notify: {{ .Site.Params.valine.notify }},
      verify: {{ .Site.Params.valine.verify }},
      avatar:'{{ .Site.Params.valine.avatar }}',
      placeholder: '{{ .Site.Params.valine.placeholder }}',
      visitor: {{ .Site.Params.valine.visitor }}
  });
</script>

appId为例,有些主题的valine.html文件会写成appId: '{{ .Site.Params.valineappId }}'或者更奇怪的,但一定要记住这个格式,因为要和他的格式完全对应。

删掉所有代码,修改为官方文档给出的代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<head>
  <script src="//cdn.jsdelivr.net/npm/@waline/client"></script>
</head>
<body>
  <div id="waline"></div>
  <script>
    Waline({
      el: '#waline',
      serverURL: 'https://your-domain.vercel.app',
    });
  </script>
</body>

将serverURL的值修改为'{{ .Site.Params.waline.serverURL }}',然后打开params.toml,根据之前添加的项,在serverURL的下一行继续添加:

1
2
3
4
5
6
7
8
        placeholder: '{{ .Site.Params.waline.Placeholder }}',
        avatar: '{{ .Site.Params.waline.Avatar }}',
        meta: {{ .Site.Params.waline.Meta }},
        pageSize: {{ .Site.Params.waline.PageSize }},
        lang: '{{ .Site.Params.waline.Lang }}',
        highlight: {{ .Site.Params.waline.Highlight }},
        avatarCDN: '{{ .Site.Params.waline.AvatarCDN }}',
        requiredFields: {{ .Site.Params.waline.RequiredFields }}

最后,我的waline.html是这样的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<head>
    <script src="//cdn.jsdelivr.net/npm/@waline/client"></script>  
</head>
<body>
    <div id="waline"></div>
    <script>
    Waline({
      el: '#waline',
        serverURL: '{{ .Site.Params.waline.ServerURL }}',
        placeholder: '{{ .Site.Params.waline.Placeholder }}',
        avatar: '{{ .Site.Params.waline.Avatar }}',
        meta: {{ .Site.Params.waline.Meta }},
        pageSize: {{ .Site.Params.waline.PageSize }},
        lang: '{{ .Site.Params.waline.Lang }}',
        highlight: {{ .Site.Params.waline.Highlight }},
        avatarCDN: '{{ .Site.Params.waline.AvatarCDN }}',
        requiredFields: {{ .Site.Params.waline.RequiredFields }}
    });
    </script>
</body>

打开comments.html,找到valine那段代码,复制一下放到他的下面,并把valine改为waline,大概是这样:

1
2
3
4
5
6
7
8
    {{ else if $.Param "valine.enable" }}
    {{ partial "comments/valine.html" . }}

+   {{ else if $.Param "waline.enable" }}
+   {{ partial "comments/waline.html" . }}

    {{ else if $.Param "changyan.changyanAppid" }}
    {{ partial "comments/changyan.html" . }}

大功告成了。

总而言之,就按照valine的配置方法去配置waline就没问题了。

管理与邮件通知

Waline 带有简单的后台,可以实现对评论的管理。部署完成后访问<serverURL>/ui/register进行注册,第一个注册的账户会被设定成管理员。

在 Vercel 的项目中添加以下新的环境变量:

  • AUTHOR_EMAIL:博主邮箱,用来区分发布的评论是否是博主本身发布的。如果是博主发布的则不进行提醒通知。
  • SMTP_SERVICE:SMTP 邮件发送服务提供商,可以在这个页面查看所有支持的运营商。如果没在列表中的可以自行配置 SMTP_HOST 和 SMTP_PORT。
  • SMTP_HOST:SMTP 服务器地址,如果未配置 SMTP_SERVICE 的话该项必填。
  • SMTP_PORT:SMTP 服务器端口,如果未配置 SMTP_SERVICE 的话该项必填。
  • SMTP_USER:SMTP 邮件发送服务的用户名,一般为登录邮箱。
  • SMTP_PASS:SMTP 邮件发送服务的密码,一般为邮箱登录密码,部分邮箱(例如 163 邮箱)是单独的 SMTP 密码。
  • SITE_NAME:网站名称,用于在消息中显示。
  • SITE_URL:网站地址,用于在消息中显示。
  • SENDER_NAME:自定义发送邮件的发件人,选填。
  • SENDER_EMAIL:自定义发送邮件的发件地址,选填。
  • MAIL_SUBJECT:评论回复邮件标题自定义。
  • MAIL_TEMPLATE:评论回复邮件内容自定义。
  • MAIL_SUBJECT_ADMIN:新评论通知邮件标题自定义。
  • MAIL_TEMPLATE_ADMIN:新评论通知邮件内容自定义。

如果你希望邮件通知采用模板,可以使用代码,这种方式不需要设置环境变量的最后四个。找到GitHub上自动创建的那个私人仓库。仓库中有一个名为index.js的文件,删除全部内容并修改为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
const Application = require('@waline/vercel');

module.exports = Application({
  mailSubject: '{{parent.nick}},您在博客「{{site.name}}」上的评论收到了回复',
  mailTemplate: `
    <div style="border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;">
      <h2 style="border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;">        
        您在博客<a style="text-decoration:none;color: #12ADDB;" href="{{site.url}}" target="_blank">{{site.name}}</a>上的评论有了新的回复
      </h2>
      <div style="padding:0 12px 0 12px;margin-top:18px">
		<p>{{parent.nick}},您曾发表评论:</p>
        <div style="background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;">{{parent.comment | safe}}</div>
        <p><strong>{{self.nick}}</strong> 回复说:</p>
        <div style="background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;">{{self.comment | safe}}</div>
        <p>您可以点击<a style="text-decoration:none; color:#12addb" href="{{site.postUrl}}" target="_blank">前往原文查看完整的回复內容</a>,欢迎再次光临<a style="text-decoration:none; color:#12addb" href="{{site.url}}" target="_blank">{{site.name}}</a>。</p>
        <br/>
      </div>
	  <div style="border-top:1px solid #DDD; padding:13px 0 0 8px;">
		该邮件为系统自动发送的邮件,请勿直接回复。
	  </div>
	  <br/>
    </div>`,
  mailSubjectAdmin: '您的博客「{{site.name}}」收到了新评论',
  mailTemplateAdmin: `
    <div style="border-top:2px solid #12ADDB;box-shadow:0 1px 3px #AAAAAA;line-height:180%;padding:0 15px 12px;margin:50px auto;font-size:12px;">
      <h2 style="border-bottom:1px solid #DDD;font-size:14px;font-weight:normal;padding:13px 0 10px 8px;">        
        有人在<a style="text-decoration:none;color: #12ADDB;" href="{{site.url}}" target="_blank">{{site.name}}</a>发表了新的评论
      </h2>
      <div style="padding:0 12px 0 12px;margin-top:18px">
		<p><strong>{{self.nick}}</strong> 评论说:</p>
		<div style="background-color: #f5f5f5;padding: 10px 15px;margin:18px 0;word-wrap:break-word;">{{self.comment | safe}}</div>
        <p>您可以点击<a style="text-decoration:none; color:#12addb" href="{{site.postUrl}}" target="_blank">前往原文查看完整的评论内容。</a></p>
        <br/>
      </div>
	  <div style="border-top:1px solid #DDD; padding:13px 0 0 8px;">
		该邮件为系统自动发送的邮件,请勿直接回复。
	  </div>
	  <br/>
    </div>`
});

后续魔改

添加blobcat表情包

由于waline.html中未定义emoji项,所以不能使用自定义emoji,此时waline只能使用预设的weibo表情包。但是weibo怎么够用!长期刷毛象人士需要blobcat!!!

参考官方文档,找到你想要的表情包,这里以bilibili和weibo为例。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 Waline({
   el: '#waline',
   serverURL: '<YOUR SERVER URL>',

  // 设置 emoji 为微博与哔哩哔哩
+  emoji: [
+    'https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/weibo',
+    'https://cdn.jsdelivr.net/gh/walinejs/emojis@1.0.0/bilibili',
+  ],
});

附上blobcat表情包地址:https://cdn.jsdelivr.net/gh/sowhereso/waline-blobcatemojis@1.2/blobs,同样填在emoji项中,需要自取。

修改waline主题

waline.html中添加:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<style>
.waline-container {
    background-color: var(--card-background);
    border-radius: var(--card-border-radius);
    box-shadow: var(--shadow-l1);
    padding: 2%; /*缩小边距*/

}
.waline-container .vcount {
    color: var(--card-text-color-main);
}

/*日间模式*/
:root{
    --waline-theme-color: #34495e; /*主题色,提交按钮*/
    --waline-active-color: #bababa; /*鼠标移到提交按钮上的颜色*/
    --waline-badge-color: #34495e; /*博主徽章色*/
    --waline-avatar-radius: 5px;  /*头像圆角*/
    --waline-avatar-size: 6rem; /*头像大小*/
    --waline-dark-grey: #34495e; /*ID颜色*/
    --waline-text-color:#6a7988; /*评论字体颜色*/
    

}

/*夜间模式*/
:root[data-scheme="dark"] {
    --waline-theme-color: #acc6e0;
    --waline-white: #34495e; /*按键字体颜色*/
    --waline-active-color: #8ab1d8;
    --waline-light-grey: #666;
    --waline-dark-grey: #acc6e0; /*ID颜色*/
    --waline-badge-color: #acc6e0;

    /* 布局颜色 */
    --waline-text-color: rgba(255, 255, 255, 0.7);
    --waline-bgcolor: #515151;
    --waline-bgcolor-light: #66696b;/*行内代码块颜色*/
    --waline-border-color: #9B9C9C;
    --waline-disable-bgcolor: #444;
    --waline-disable-color: #272727;

    /* 特殊颜色 */
    --waline-bq-color:  #9B9C9C; /*quote*/

    /* 其他颜色 */
    --waline-info-bgcolor: #acc6e0;
    --waline-info-color: #9B9C9C;
}
</style>

由于Zzo主题默认为dark,我对其修改为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<style>
.waline-container {
    background-color: var(--card-background);
    border-radius: var(--card-border-radius);
    box-shadow: var(--shadow-l1);
    padding: 2%; /*缩小边距*/

}
.waline-container .vcount {
    color: var(--card-text-color-main);
}

/*默认*/
:root{
    --waline-theme-color: #acc6e0;
    --waline-white: #34495e; /*按键字体颜色*/
    --waline-active-color: #8ab1d8;
    --waline-light-grey: #666;
    --waline-dark-grey: #acc6e0; /*ID颜色*/
    --waline-badge-color: #acc6e0;

    /* 布局颜色 */
    --waline-text-color: rgba(255, 255, 255, 0.7);
    --waline-bgcolor: #515151;
    --waline-bgcolor-light: #66696b;/*行内代码块颜色*/
    --waline-border-color: #9B9C9C;
    --waline-disable-bgcolor: #444;
    --waline-disable-color: #272727;

    /* 特殊颜色 */
    --waline-bq-color:  #9B9C9C; /*quote*/

    /* 其他颜色 */
    --waline-info-bgcolor: #acc6e0;
    --waline-info-color: #9B9C9C;
}
</style>

配置好的话也就是你现在看到的waline的样子。


Roelxy
WRITTEN BY
Roelxy
新世紀摸魚戰士