hexo-theme-doc主题实现中文搜索

由于 hexo-theme-doc主题无法实现中文搜索,更新build json 有关代码,实现中文搜索功能。

问题

如果你找到这篇文章,说明你已经在使用hexo-theme-doc,并且已经知道hexo是什么和hexo-theme-doc怎么安装了。

hexo-theme-doc是一个很好的帮助文档Theme,页面简洁,可以参考https://github.com/zalando-incubator/hexo-theme-doc

由于项目需要建立帮助文档,所以选择了hexo-theme-doc,但是发现在中文界面下无法使用搜索功能。

在Github向他们提出了有关问题,因为是 lunr.js出了问题,他们好像也没办法,https://github.com/zalando-incubator/hexo-theme-doc/issues/143

解决

本次修改的lunr.js的版本是2.1.0,不知道以后会不会支持中文,同时hexo-theme-doc 的版本是1.0.0-rc.1。

hexo-theme-doc搜索的原理是通过lunr.js生成一个lunr.json文件,把hexo post的内容全部变成Json格式,然后检索时候,就在这个Json文件里面寻找。

现在问题就出在这个lunr.json,如果你在博客里面输入中文,那么在生成静态文件时,打开lunr.json文件会发现里面的Json的Body是一大堆乱码。由于这一些乱码,在之后的搜索功能就自然找不到需要的关键字或者文章。

首先要解决build json出来的时候乱码问题,在lib/nodejs/search/build.js下,112行,直接comment掉有关代码

1
2
3
$('h1,h2').each(function() {
。。。
});

这样生成的Json文件的中文字就会正常显示了,相关改动可以参考如下:
https://github.com/TonyRenHK/hexo-theme-doc/commit/c543d21a3dbbd79000f99babc98eba6c2fd029e5

由于修改了相关Json文件,所以在生成的search 模块也需要进行相应的修改。这里修改就可以根据实际需要进行修改。修改的文件在 lib/browser/search/components.jsx下。其中SearchForm就是需要修改的search模块。
这里把页面也直接翻译成中文页面:

1
2
3
4
5
6
7
8
9
10
11
function SearchResultsTitle({ results, query }) {
return (
<div>
<h1 className="doc-search-results__title">
搜索 <span className="doc-search-results__title__query">"{query}"</span>,{ results.length ? results.length+'个' : '没有' } 结果 :
</h1>

{ !results.length ? <p>系统未能搜索 "{query}"到结果. <strong>试试其他关键字?</strong></p> : null }
</div>
);
}

同时值得注意的是,搜索检索出来的是整个博客文章body,有时候,需要裁剪有关文章,比如只需要显示先后100个字。这里可以参考如下的cut budy 方法。如下方法仅供参考。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function generateBody(body, query) {
var indexNumber = body.indexOf(query);
var bodyLength = body.length;
var returnBody = '';
var frontCut = 10;
var bodyCut = 100;

if (indexNumber < frontCut && bodyLength > bodyCut) {
returnBody = body.substring(0, bodyCut) + '。。。';
}
else if (indexNumber < frontCut && bodyLength < bodyCut) {
returnBody = body.substring(0, bodyLength);
}
else if (indexNumber > frontCut && bodyLength > (bodyCut + indexNumber)) {
returnBody = '。。。' + body.substring(indexNumber - frontCut, bodyCut + indexNumber) + '。。。';
}
else if (indexNumber > frontCut && bodyLength < (bodyCut + indexNumber)) {
returnBody = '。。。' + body.substring(indexNumber - frontCut, bodyLength);
}
//add highlight
returnBody = returnBody.replace(new RegExp(query, 'g'), '<span style="font-weight: bold;">' + query + '</span>');
return returnBody;
}

可以参考最后修改版本的search components:

https://github.com/TonyRenHK/hexo-theme-doc/blob/6a11a284a6fb136252744260dd1fdb511e1773c2/lib/browser/search/components.jsx

修改完成之后需要利用Webpack 和 node-sass 进行编译

1
$ npm run compile

而编译生成的文件在source/script/doc.js 。

代码

有关代码如下:

https://github.com/TonyRenHK/hexo-theme-doc

当然,实现中文搜索的方法不唯一,欢迎留言讨论。如上方法仅供参考。

参考文献