上一篇手记是讲“改造Gitment”的(在这里)。其实这个“改造”花了不少功夫,以至于后来还出了一个给
hexo-theme-next
的版本。这是推迟了“做多人博客”的一个原因,另一个原因则是我以前的博文需要更新的太多,花了很多时间。当然,那个叫
Monster
的项目(在这里)也是花销时间的大户。所以,结果就是:这篇“手记7”被推迟了很久...很久...
多人博客的功能其实我一早就做出来了——至少,大概的框架是完成了的。但是我一直没有发布出来,“麦秸的垛”也就一直没上线。
下面讲讲这整个的过程。
导入“第二个人”的博客文章
在Ghost 0.9x中其实有一个Bug,就是你总是只能将博客导入到'id=1'的帐户(或以该帐户身份导入)。我说不清这个Bug是什么时候存在,又或者(可能)什么时候会修复/已修复。我当时找到的解决方法,就是直接改sqlite数据库。
不过自从我开始启用Ghost 1.x之后,这个担忧就没有了。在多人博客这个问题上,Ghost 1.x做得其实更好,所以我后面也是在用这个版本,关于0.9x的更多细节就不谈了。
假如你已经有了一个基于Ghost的本地博客,已经有一个帐户了,那么当你需要把它变成“多人博客”时,你自然需要再创建一个帐户——这个不用多说了。一旦你搞定了,那么你可以用monster来查询到多个用户的信息:
> monster list user
id name slug email
------------------------ ---------- ---------- --------------
1 aimingoo aimingoo aiming@gmail.com
5951f5fca366002ebd5dbef7 second new-user ...
...
记下新用记的id
值(5951f5fca366002ebd5dbef7),后面我们会用到。
注意:
在Monster v1.0.7以下的版本中
list user
只会显示被截断的user id。因此要正确地查询这个id
值,请将你的Monster升级到v1.0.7
或更高版本——或者你也可以自己打开sqlite数据库查看。
接下来,假设你是用BlogToWordpress来迁移的博客,那么你会有一个wordpress格式的.xml文件,存放用户second的全部博客——如果你是用别的来导出,那么请转换到wordpress格式先。参考:
我们将这个.xml用工具wp2ghost转换到ghost-tmp.json,然后再使用putrefy.js来处理一次,得到最终的ghost.json就可以了。这个过程参考:
但还是要注意以下几点:
使用修改版的wp2ghost
你可以考虑使用我的修改版wp2ghost。主要有三处变化:
- tag忽略大小写
- 忽略掉总是存在的DefaultCategory这个tag
- 兼容用
wp:wp_author
和wp:author
来识别作者名
下载在这里:
配置putrefy.js
如果你只是简单导入,那么你可以直接使用putrefy.js命令行传入Ghost用户的id值(上面找到的那个)。例如:
# 获取 putrefy.js
> curl -L https://github.com/aimingoo/ghost-utils/raw/master/putrefy.js -o putrefy.js
# 处理ghost-tmp.json
> node putrefy.js ghost-tmp.json '5951f5fca366002ebd5dbef7' > ghost.json
不过注意,很多情况下putrefy.js不是直接使用的,它几乎总是
需要修改配置才能使用(除了上面的这个new_author_id参数外,就只能直接修改源代码了)。
最后,参考上面的博客说明,你应该可以顺利地用putrefy.js了。
多博客的一点说明
在使用putrefy.js时,它缺省为你的post生成的slug将是authorId-postId
格式的,例如上面的5951f5fca366002ebd5dbef7
,就会生成5951f5fca366002ebd5dbef7-1
.....-n
这样的格式。
你可以改这个缺省值改成特定风格。例如2-
,或者myblog:
这样的前缀。这需要直接修改putrefy.js源代码中的SLUG_FROMID
变量值。如下:
## 参数值:
## - "字符串": 以postId作为slug,并将该字符串值直接作为前缀
## - true: 以postId作为slug,并用当前的"authorId-"作为前缀,authorId值缺省为1
## - false: 不修改slug
SLUG_FROMID="2-"
另外,某些情况下,从wordpress格式的.xml文件中导出的authorId值不总是缺省值1(或者可能因为意外的缘故就没有authorId值),这种情况下,你需要修改putrefy.js代码中的
var author_map = {
"1": ...
}
它可以处理多个authorId,或强制指定转换表。
在你的Ghost模板中识别多个作者
有两种方法来识别多个作者。
第一种是直接在模板中使用{{author}}
,这个标签对于author、page和post等页都是有效的,因此可以方便地使用这个标志来为不同作者切换内容:
<!-- 可以直接用`{{#has ...}`来识别 -->
{{#has author="aimingoo, qomo"}}
....
{{/has}}
但是这不能作用于{{> ..}}
标签来装载的子模板——你当然可以写多个has
来识别,但这并不方便。因此,我在博客中选择了第二种方案:通过加载<script>
标签来处理。
这个名为author-switch.js
的脚本在这里:
可以通过如下的方式来加载:
<script type="text/javascript" author="{{author.slug}}" src="/assets/js/author-switcher.js"></script>
或
<script type="text/javascript" author="default" src="/assets/js/author-switcher.js"></script>
在author-switcher.js
中会读取所有scripts并查找到这个标签,然后从标签中取出author
属性,并针对不同的author来处理当前页面的显示——基本上就是调整导航栏、标题页等等。
author-switcher.js
中有部分代码显得比较复杂,主要是根据deviceWidth来处理导航栏显示的(用于适应手机等窄屏设备)。
你不能直接使用
author-switcher.js
,它需要根据你的网站定制
静态页的处理
一些静态页是多个作者之间不同的,例如A作者可以显示某些标签,而B作者就不需要(你想想如果在麦秸的垛的文章里显示出JavaScript这样的标签会是什么效果)。因此我除了将tag-cloud等页面静态化(处理方法在这里)之外,也在其中加入了相应的代码来处理这种静态页内的信息。例如:
<!-- in page-tag-cloud.hbs -->
var enabledCloudTags = {
'default': 'all',
'aimingoo': 'all',
'more users': [ "some tags for other', ...]
}
function filterByAuthor(context, enabled) {
if (enabled == 'all') return context;
...
}
相应的代码在这里:
注意其中的cloudTagHtmlContext()内的代码是由标签
{{> "tag_cloud"}}
自动生成的,参考:'7.2.1 为标签云添加一个静态页' @这里
多作者多线索(Thread)
Ghost缺省的多作者模式是“多作者单线索”的,也就是所有作者的prev/next
是在同一个list中,这样A作者的上/下一篇日志,就可能是B作者的。对于同一主题的博客(例如相同兴趣的网站)来说这没问题,但是我跟Joy的博客风格差异很大,你想想在一篇讨论户外驴友美食或化妆的文章中出现“上一篇”是某个开源程序项目的……效果,那真的是……
好吧。所以我需要跟Joy的博客使用“多作者多线索”的风格。这个是早先的Ghost版本中是不支持的,因为它默认的prev/next helper是只支持单线索的。这个问题已经被提了两年了……没解决过。
很幸运的事情是,正好在“麦秸的垛”上线前一两天,Ghost v1.14.0发布了。这个版本中带了一个primary tag
的特性,它的实现方案令人眼前一亮啊(呵呵)。“多作者多线索”的实现立即变得简单了,于是我加了几行代码,现在你可以在post.hbs
里这样写:
{{! -- MUST include "author" field -- }}
{{#get "posts" filter="id:{{id}}" include="author" as |current|}}
{{#current}}
{{#prev_post in="author"}} ...
...
{{#next_post in="author"}} ...
...
{{/current}}
{{/get}}
就可以了。——注意其中的include="author"
和in="author"
。
这个简单的feature已经提交到Ghost team了(在这里),如果你等不及的话也可以直接用我fork的版本:https://github.com/aimingoo/Ghost/tree/prev-next-author