hexo博客添加本地搜索功能的步骤
使用 hexo-generator-search
的 Hexo
插件来做内容搜索,安装命令如下:
npm install hexo-generator-search --save
在 Hexo 根目录下的 _config.yml 文件中,新增以下的配置项:
代码语言:javascript复制search:
path: search.xml
field: post
问题出现
通过上面的安装一般是可以实现本地搜索功能的,但是,我的问题出现了,刚刚开始的时候,我是在windows电脑上面配置hexo的博客的,但是,后面我迁移到了mac上,然后本地搜索功能突然就不能用了。
经过自己的调试发现,一般本地功能不能使用了,有以下几个原因。
- search.xml文件中有不符合规则的字符,导致不能解析。
- search.xml中有错误,导致不能解析。
- search.xml文件中有编码不一致的问题,导致xml解析失败。
以上的search.xml就是我们配置了本地搜索后,自动生成的xml格式的包含站点所有博客的文件,通过这个文件就可以进行本地搜索功能。
问题原因
发现问题都在search.xml中,其实,罪魁祸首是你的某些文章有格式问题,导致生成的search.xml也出错了,这很要命啊,到底是哪一篇文章呢?
当我删掉这篇发现本地搜索可以,后面又不行了,这不是玩我吗。
于是有了后面的解决方案。
本地搜索终极解决方案
既然用xml格式始终都是很难解决问题的,那么我就想到了使用更加通用的json格式呗,果不其然,最终完美解决了问题,下面记录解决方法及过程。
第一步
找到站点配置文件
代码语言:javascript复制search:
path: search.xml
field: post
将search.xml改为search.json格式。
第二步
找到你的博客主题的search.ejs模板文件,修改下面代码:
代码语言:javascript复制<script type="text/javascript">
$(function () {
console.log("lets go!");
console.log("<%= config.root %>");
searchFunc("<%= config.root %>" "search.xml", 'searchInput', 'searchResult');
});
</script>
也是改为json格式的文件
代码语言:javascript复制<script type="text/javascript">
$(function () {
console.log("lets go!");
console.log("<%= config.root %>");
searchFunc("<%= config.root %>" "search.json", 'searchInput', 'searchResult');
});
</script>
最后一步
修改你的search的本地js文件,比如我的matery主题的就是在js文件夹下的search.js文件。
对这个文件进行json解析的修改,最终就可以成功解决问题。
代码语言:javascript复制var searchFunc = function (path, search_id, content_id) {
console.log("test");
// 'use strict';
$.ajax({
url: path,
dataType: "json",
success: function (datas) {
// get the contents from search data
// var datas = $("entry", xmlResponse).map(function () {
// return {
// title: $("title", this).text(),
// content: $("content", this).text(),
// url: $("url", this).text()
// };
// }).get();
// console.log(xmlResponse);
console.log("test!");
console.log(datas);
var $input = document.getElementById(search_id);
var $resultContent = document.getElementById(content_id);
$input.addEventListener('input', function () {
var str = '<ul class="search-result-list">';
var keywords = this.value.trim().toLowerCase().split(/[s-] /);
$resultContent.innerHTML = "";
if (this.value.trim().length <= 0) {
return;
}
// perform local searching
datas.forEach(function (data) {
var isMatch = true;
var content_index = [];
var data_title = data.title.trim().toLowerCase();
var data_content = data.content.trim().replace(/<[^>] >/g, "").toLowerCase();
var data_url = data.url;
var index_title = -1;
var index_content = -1;
var first_occur = -1;
// only match artiles with not empty titles and contents
if (data_title != '' && data_content != '') {
keywords.forEach(function (keyword, i) {
index_title = data_title.indexOf(keyword);
index_content = data_content.indexOf(keyword);
if (index_title < 0 && index_content < 0) {
isMatch = false;
} else {
if (index_content < 0) {
index_content = 0;
}
if (i == 0) {
first_occur = index_content;
}
}
});
}
// show search results
if (isMatch) {
str = "<li><a href='" data_url "' class='search-result-title'>" data_title "</a>";
var content = data.content.trim().replace(/<[^>] >/g, "");
if (first_occur >= 0) {
// cut out 100 characters
var start = first_occur - 20;
var end = first_occur 80;
if (start < 0) {
start = 0;
}
if (start == 0) {
end = 100;
}
if (end > content.length) {
end = content.length;
}
var match_content = content.substr(start, end);
// highlight all keywords
keywords.forEach(function (keyword) {
var regS = new RegExp(keyword, "gi");
match_content = match_content.replace(regS, "<em class="search-keyword">" keyword "</em>");
});
str = "<p class="search-result">" match_content "...</p>"
}
str = "</li>";
}
});
str = "</ul>";
$resultContent.innerHTML = str;
});
}
});
}
修改很简单,只要把上面的我注释的注释掉,然后将sucess后的xmlResponses改为datas就可以,这样其实解析起来比xml方便很多,省去了很多代码,最重要的是解决了我的问题。