Valine 升级 1.4 以及增加判断 “昵称和邮箱不能为空”

如果你和我一样只是想在 1.3.10 原版的基础上增加昵称和邮箱的防空验证,可以直接下划到结尾部分,跳过前半部分的过程记录。

最近经受匿名评论的困扰,计划禁止匿名评论。还有一个原因是《网信办:网站不得向未实名认证的用户提供跟帖评论服务》,咱小小博客也是备过案的(能用国内 CDN 加速太香了),应该注意一下是不是?

很遗憾,Valine 作者不计划添加这一功能!这让我一度想要换评论系统了……先不谈数据转移,我对比了一下其他评论系统——

  • Discuz 系,国内连通率堪忧,不行;
  • 基于 GitHub Issue 的,需要 GitHub 授权,对访客不是很友好,国内速度也不快,不行;
  • 还有国内的畅言,要备案好说,但是 UI 不好看,还要验证访客手机号、绑定微信一大堆,麻烦不说,重要的是泄露访客隐私,不行……

昨天发现 Valine 1.4 发布,有几个新特性挺喜欢,打算升级,想起这茬,干脆一起把防空校验加上吧!

xCss/Valine/src/index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const requiredField = ['nick', 'mail'];
let emptyFieldName = [];
requiredField.forEach((requiredField) => {
if (defaultComment[requiredField] == '') {
emptyFieldName.push(root.locale['head'][requiredField]);
}
});
if (emptyFieldName.length > 0) {
root.alert.show({
type: 0,
// 昵称不能为空...ヾ(๑╹◡╹)ノ"
// 邮箱不能为空...ヾ(๑╹◡╹)ノ"
// 昵称和邮箱不能为空...ヾ(๑╹◡╹)ノ"
text: `${emptyFieldName.join(root.locale['tips']['and'])}${root.locale['tips']['canNotBeEmpty']}ヾ(๑╹◡╹)ノ"`,
ctxt: root.locale['ctrl']['ok']
});
return;
}

这只是关键部分,完整 diff 详见:https://github.com/imaegoo/Valine/commit/c18515593f16454833c757c91540ef5af0770fa5

后台验证暂时没研究出,LeanCloud 支持字段设置 “不能为空”,但依然不能阻止插入空字符串,文档中还没查到怎么给字符串验证。

写完了编译试一下,就掉进坑里了,Valine 1.4.4 版本通过源码 build 出的 js 报错 Cannot redefine property: applicationId,需要看看作者怎么说。

无奈切回 1.3.10,加上自己的代码,测试一下,成功!

测通之后已经 26:30 了,教程晚会再写吧,目前还有后台验证和 1.4 升级的坑没有解决,如果你喜欢,欢迎留言,教程更新后我会邮件告知 o( ̄▽ ̄)ブ


2020/4/12 17:20 更新

遗憾地,@MHuiG 告知我 1.4.4 并没有开源。同日,作者也在 README 中提到:

由于某些原因,src目录将从v1.4.0后暂停更新.
For some reason, the src directory will be suspended from updating after v1.4.0.

所以暂时放弃升级 1.4 的计划,也就不再对 1.4 增加判空功能了。

我修改过的 Valine 在 Github 开源:
https://github.com/imaegoo/Valine/tree/imaegoo/1.3.10


2020/4/14 08:20 更新使用方法

如果你用的是 Icarus 3.0 主题,你可以创建 themes/icarus/layout/comment/valine.jsx 来覆盖原版主题的 Valine 组件。

点击展开 themes/icarus/layout/comment/valine.jsx >folded
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
* Valine comment JSX component.
* @module view/comment/valine
* @author ppoffice
*/
const { Component, Fragment } = require('inferno');
const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');

/**
* Valine comment JSX component.
*
* @see https://valine.js.org/quickstart.html
* @example
* <Valine
* appId="******"
* appKey="******"
* notify={false}
* verify={false}
* placeholder="******"
* avatar="mm"
* avatarForce={false}
* meta={['nick', 'mail', 'link']}
* pageSize={10}
* visitor={false}
* highlight={true}
* recordIp={false}
* jsUrl="/path/to/Valine.js" />
*/
class Valine extends Component {
render() {
const {
appId,
appKey,
notify,
verify,
placeholder,
avatar = 'mm',
avatarForce = false,
meta = ['nick', 'mail', 'link'],
pageSize = 10,
visitor = false,
highlight = true,
recordIp = false,
jsUrl
} = this.props;
if (!appId || !appKey) {
return <div class="notification is-danger">
You forgot to set the <code>app_id</code> or <code>app_key</code> for Valine.
Please set it in <code>_config.yml</code>.
</div>;
}
const js = `new Valine({
el: '#valine-thread' ,
notify: ${notify},
verify: ${verify},
appId: '${appId}',
appKey: '${appKey}',
placeholder: '${placeholder}',
avatar: '${avatar}',
avatarForce: ${avatarForce},
meta: ${JSON.stringify(meta)},
pageSize: ${pageSize},
visitor: ${visitor},
highlight: ${highlight},
recordIP: ${recordIp}
});`;
return <Fragment>
<div id="valine-thread" class="content"></div>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src={jsUrl}></script>
<script dangerouslySetInnerHTML={{ __html: js }}></script>
</Fragment>;
}
}

/**
* Cacheable Valine comment JSX component.
* <p>
* This class is supposed to be used in combination with the <code>locals</code> hexo filter
* ({@link module:hexo/filter/locals}).
*
* @see module:util/cache.cacheComponent
* @example
* <Valine.Cacheable
* comment={{
* app_id="******"
* app_key="******"
* notify={false}
* verify={false}
* placeholder="******"
* avatar="mm"
* avatar_force={false}
* meta={['nick', 'mail', 'link']}
* page_size={10}
* visitor={false}
* highlight={true}
* record_ip={false}
* }}
* helper={{ cdn: function() {...} }} />
*/
Valine.Cacheable = cacheComponent(Valine, 'comment.valine', props => {
const { comment, helper } = props;

return {
appId: comment.app_id,
appKey: comment.app_key,
notify: comment.notify,
verify: comment.verify,
placeholder: comment.placeholder,
avatar: comment.avatar,
avatarForce: comment.avatar_force,
meta: comment.meta,
pageSize: comment.page_size,
visitor: comment.visitor,
highlight: comment.highlight,
recordIp: comment.record_ip,
jsUrl: 'https://cdn.jsdelivr.net/gh/imaegoo/Valine@1.3.10.1/dist/Valine.min.js'
};
});

module.exports = Valine;

如果你用的是其他主题,你可以自己查找 Valine.min.js 的引入位置,替换成:https://cdn.jsdelivr.net/gh/imaegoo/Valine@1.3.10.1/dist/Valine.min.js

拓展阅读

  1. Valine 1.4.6+ 新增必填项设置 - https://valine.js.org/configuration.html#requiredFields
  2. pure主题valine留言板添加:昵称、邮箱必填必写功能 - https://blog.gobyte.cn/post/e56fdb88.html

评论