PPXu

Hexo添加搜索功能

2018-10-14

本文旨在记录站主基于hexo-generator-search插件实现本站的站内文章搜索功能

基本实现原理

  1. 基于hexo-generator-search生成全文内容索引xml文件
  2. 利用jQ.ajax请求xml文件并解析
  3. jQ搜索关键字内容匹配xml内容

主要的部分还是插件写的好,对应的解析函数也是改造插件作者的,网上一搜一大堆此类文章,本文仅仅意在记录本站使用该插件实现搜索的过程

安装插件

1
npm install --save hexo-generator-search

这个插件可以生成供搜索的索引数据,生成后的xml文件保存在自己站内目录,可以通过 http://localhost:4000/search.xml 查看

插件配置

在hexo根目录底下的_config.xml里加入以下配置:

1
2
3
4
search:
path: search.xml
field: post
#field: post, page or all(3个可选参数)

解析函数

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
var performLocalSearch = function(datas,keywords){
// perform local searching
var str='<ul class="search-result-list">';
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" target="_blank">'+ '> ' + data_title +'</a>';
var content = data.content.trim().replace(/<[^>]+>/g,"");
if (first_occur >= 0) {
// cut out characters
var start = first_occur - 6;
var end = first_occur + 6;
if(start < 0){
start = 0;
}
if(start == 0){
end = 10;
}
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>';
}
}
});

return str;
}

Search入口功能函数

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
	 var searchFunc = function(path, search_id, content_id) {
'use strict';
$.ajax({
url: path,
dataType: "xml",
success: function( xmlResponse ) {
// 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();


var $input = $('#'+search_id);
var $resultContent = $('#'+content_id);

$input.on("input propertychange",function(){
var keywords = this.value.trim().toLowerCase().split(/[\s\-]+/);
if($(this).val()==""){$resultContent.html('');return;}
$resultContent.html(performLocalSearch(datas,keywords));
});
}
});
}

searchFunc("/search.xml","local-search-input","local-search-result");

})();

页面HTML代码

申明html元素,id、class名字要跟解析函、Search入口功能函数里的代码对上号:

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
	<div id="site_search" class="bar">
<input type="text" id="local-search-input" name="q" results="0" placeholder="search my blog..." class="form-control"/>
<div id="local-search-result"></div>
</div>
````

## 样式调整
``` css
ul.search-result-list {
padding-left: 10px;
}
a.search-result-title {
font-weight: bold;
}
p.search-result {
color=#555;
}
em.search-keyword {
border-bottom: 1px dashed #4088b8;
font-weight: bold;
}
.form-control {
padding-left:10px;
margin-bottom: 10px;
}
.bar {
padding: 10px 10px;
}
.bar input {
width:350px;
height: 25px;
border-radius:42px;
border:2px solid #324B4E;
background:#F9F0DA;
transition:.3s linear;
float:center;
}
.bar input:focus {
width:420px;
}

扫描二维码,分享此文章