01 官方文档不可信
Staticman的入门指导不靠谱,按照该指导文件,在Step 1
访问url接收合作者邀请的时候一直返回Invitation not found
,根本就没办法返回指导文档中说的OK!
,原因就是staticmanapp已经是太多项目的合作者了,已经达到了GitHub允许的上限了。
解决这个问题,我先是在自己的局域网搭建了一个Staticman实例,配置明飞的GitHub作为项目合作者,提交用户评论数据。千辛万苦调试通了,但是自己搭的Staticman实例只能局域网内使用,如果给博客使用必须要公共实例,搭建公共实例需要有外部服务器。
后来,我找到了另一个公有的Staticman实例,是由vincenttam提供的,万分感谢。vincenttam是StaticmanLab的维护者,使用Staticman给GitLab提供静态评论功能(其实就是Staticman的V3版本)。他提供的staticman的实例api是https://staticman3.herokuapp.com ,对应的GitHub合作者是staticmanlab。
02 官方文档还是不可信
Staticman的入门指导的配置项介绍了各个配置项的说明,也给出了配置文件样例,但使用这个样例配置文件在Step 3
的时候会报如下报错:
{
"success": false,
"data": [
"allowedFields",
"branch",
"format",
"path"
],
"rawError": {
"_smErrorCode": "MISSING_CONFIG_FIELDS",
"data": [
"allowedFields",
"branch",
"format",
"path"
]
},
"errorCode": "MISSING_CONFIG_FIELDS"
}
找不到必须的配置项!!!
原因是Staticman的入门指导中给出的public api所用的代码是V2版的Staticman代码(源码的master分支),配置文件样例staticman.sample.yml是给V3版的Staticman用的,不匹配所以出错。
使用master
分支搭建出来的Staticman实例可以提供v1、v2版的api,对应的staticman.yml
配置文件没有comments
。使用dev
分支搭建出来的Staticman实例可以提供v1、v2和v3版的api,对应的staticman.yml
配置文件有comments
。https://api.staticman.net 后端代码是master
分支,https://staticman3.herokuapp.com 后端代码是dev
分支。(基于2019年02月27日而言,项目代码及分支应该持续更新,您阅读本文时可能已经出现改变)
不知道以上情况的我,使用master
分支代码自己搭建Staticman实例,然后是用示例配置文件,一直报错。害我看了半天的代码,坑爹呀!解决办法就是,如果是使用官方实例api(https://api.staticman.net )就将sample中的第5行comments
注释掉,如果使用vincenttam的api(https://staticman3.herokuapp.com )就保留第5行comments
。
Staticman项目规模并不大,逻辑也不复杂,可以多看代码,看源码比看官方指导靠谱多了。
03 还是官方文档不可信
本博客所用的主题是Minimal Mistakes提供的主题,获取源码点这里,主题示例点这里。
在Minimal Mistakes的示例主题中有入门指导,其中有介绍评论的地方,里面也说到了从2018年9月开始staticmanapp忙不过来的问题,也介绍了staticman v2和v3的问题。
使用这个主题遇到2个坑:
调试情况下显示不了comments模块
入门指导中写到:
Note: Comments are disabled by default in development
. To enable when testing/building locally be sure to set
JEKYLL_ENV=production
to force the environment to production.
但是我用JEKYLL_ENV=production jekyll build
命令就会出现各种404的问题,至今没有解决。我是一直在生产环境调试解决评论问题。。。
当博文的title是中文时,无法显示用户的评论数据
在Minimal Mistakes主题中,跟评论有关的源码文件主要在_includes/comments.html
,我的_config.yml
配置文件中comments.provider
配置的是staticman_v2
,所以对应源码的第28行至第101行,其中显示评论的代码是第31行至第47行:
<!-- Start static comments -->
<div class="js-comments">
{% if site.data.comments[page.slug] %}
<h4 class="page__comments-title">{{ site.data.ui-text[site.locale].comments_title | default: "Comments" }}</h4>
{% assign comments = site.data.comments[page.slug] | sort %}
{% for comment in comments %}
{% assign email = comment[1].email %}
{% assign name = comment[1].name %}
{% assign url = comment[1].url %}
{% assign date = comment[1].date %}
{% assign message = comment[1].message %}
{% include comment.html index=forloop.index email=email name=name url=url date=date message=message %}
{% endfor %}
{% endif %}
</div>
<!-- End static comments -->
遍历site.data.comments
数组,找到key为page.slug
的数据,经过调试打印发现,当page.slug
为中文时,site.data.comments
相应的数据是空字符串。也就是说,不支持中文。
例如,用户给博文华为交换机配置
评论,提交评论后,Staticman会在_data\comments
文件夹下创建文件夹华为交换机配置
,将用户评论数据存到该文件夹的文件comment-{@timestamp}
中,例如文件名为comment-1551250624975
,调试打印site.data.comments
,结果如下:
{
"": {
"comment-1551250624975": {
"_id": "e3cf80e0-3a5c-11e9-b3a5-93bed8986308",
"message": "测试中文",
"name": "张洪涛",
"email": "9dbe00b62ce9224b4df10bbfc6dbe438",
"url": "",
"hidden": "",
"date": "2019-02-27T06:57:04.970Z"
}
},
"Test-EN-Language": {
"comment-1551234337130": {
"_id": "f765ce00-3a36-11e9-9e19-03d08e696b02",
"message": "test",
"name": "test",
"email": "9dbe00b62ce9224b4df10bbfc6dbe438",
"url": "",
"hidden": "",
"date": "2019-02-27T02:25:37.129Z"
}
}
}
找不到site.data.comments["华为交换机配置"]
,所以显示不了用户评论。
查找Jekyll中常用变量,需要找到一个文章的唯一标识,且该标识不能为中文。首先我尝试了page.id
,但page.id
格式为/2008/12/14/my-post
,/
作为文件夹的名称容易产生误解。page.date
可能无法保证唯一性。看来默认自带的变量是满足不了需求了。
最后,我在博文的头信息中引入uuid
变量,每次在发表博文的时候用uuidgen
命令生成唯一标识:
---
title: "使用Statiman给博客提供评论功能(二)"
uuid: 875e22ce-957e-4646-b1fe-ed51de2bd26c
excerpt: "本文主要介绍为了解决本博客的用户评论问题所遇到的各种坑"
last_modified_at: 2019-02-27T16:38:00
comments: true
categories:
- 技术
tags:
- Jekyll
---
然后修改提交用户评论数据的代码,_includes/comments.html
代码的第49行至第98行:
<!-- Start new comment form -->
<div class="page__comments-form">
<h4 class="page__comments-title">{{ site.data.ui-text[site.locale].comments_label | default: "Leave a Comment" }}</h4>
<p class="small">{{ site.data.ui-text[site.locale].comment_form_info | default: "Your email address will not be published. Required fields are marked" }} <span class="required">*</span></p>
<form id="new_comment" class="page__comments-form js-form form" method="post" action="{{ site.staticman.endpoint | default: 'https://api.staticman.net/v2/entry/' }}{{ site.repository }}/{{ site.staticman.branch }}/comments">
<div class="form__spinner">
<i class="fas fa-spinner fa-spin fa-3x fa-fw"></i>
<span class="sr-only">{{ site.data.ui-text[site.locale].loading_label | default: "Loading..." }}</span>
</div>
<div class="form-group">
<label for="comment-form-message">{{ site.data.ui-text[site.locale].comment_form_comment_label | default: "Comment" }} <small class="required">*</small></label>
<textarea type="text" rows="3" id="comment-form-message" name="fields[message]" tabindex="1"></textarea>
<div class="small help-block"><a href="https://daringfireball.net/projects/markdown/">{{ site.data.ui-text[site.locale].comment_form_md_info | default: "Markdown is supported." }}</a></div>
</div>
<div class="form-group">
<label for="comment-form-name">{{ site.data.ui-text[site.locale].comment_form_name_label | default: "Name" }} <small class="required">*</small></label>
<input type="text" id="comment-form-name" name="fields[name]" tabindex="2" />
</div>
<div class="form-group">
<label for="comment-form-email">{{ site.data.ui-text[site.locale].comment_form_email_label | default: "Email address" }} <small class="required">*</small></label>
<input type="email" id="comment-form-email" name="fields[email]" tabindex="3" />
</div>
<div class="form-group">
<label for="comment-form-url">{{ site.data.ui-text[site.locale].comment_form_website_label | default: "Website (optional)" }}</label>
<input type="url" id="comment-form-url" name="fields[url]" tabindex="4"/>
</div>
<div class="form-group hidden" style="display: none;">
<input type="hidden" name="options[slug]" value="{{ page.slug }}">
<label for="comment-form-location">Not used. Leave blank if you are a human.</label>
<input type="text" id="comment-form-location" name="fields[hidden]" autocomplete="off"/>
{% if site.reCaptcha.siteKey %}<input type="hidden" name="options[reCaptcha][siteKey]" value="{{ site.reCaptcha.siteKey }}">{% endif %}
{% if site.reCaptcha.secret %}<input type="hidden" name="options[reCaptcha][secret]" value="{{ site.reCaptcha.secret }}">{% endif %}
</div>
<!-- Start comment form alert messaging -->
<p class="hidden js-notice">
<strong class="js-notice-text"></strong>
</p>
<!-- End comment form alert messaging -->
{% if site.reCaptcha.siteKey %}
<div class="form-group">
<div class="g-recaptcha" data-sitekey="{{ site.reCaptcha.siteKey }}"></div>
</div>
{% endif %}
<div class="form-group">
<button type="submit" id="comment-form-submit" tabindex="5" class="btn btn--primary btn--large">{{ site.data.ui-text[site.locale].comment_btn_submit | default: "Submit Comment" }}</button>
</div>
</form>
</div>
<!-- End new comment form -->
将第77行<input type="hidden" name="options[slug]" value="{{ page.slug }}">
修改为<input type="hidden" name="options[uuid]" value="{{ page.uuid }}">
。
修改staticman.yml
配置文件,将配置项path: "_data/comments/{options.slug}"
修改为path: "_data/comments/{options.uuid}"
信息:提交Staticman评论的请求中,提交数据中包含fields
和options
两类变量,fields
变量会作为评论数据保存在评论文件中,options
作为变量供staticman使用。
经过以上修改,用户提交评论会存在以uuid
的文件夹下,那么展示评论的代码对应的site.data.comments[page.slug]
也要修改为site.data.comments[page.uuid]
。