前言

最近一直想给自己的博客添加搜索功能,用于搜索自己的贴子。经过搜索一些教程并结合自己的思考,遂整理成这样的贴子用以记录下部署过程。

最终实现效果如下(输入123即可弹出搜索结果):

image.png

插件的安装

此搜索功能是借助于hexo-generator-search插件实现的,要用到这个功能,需要安装此插件:

1
npm install hexo-generator-search --save

此外,在__config.xml文件下增加功能:

1
2
3
4
5
search:
path: search.xml
field: post
content: true
template: ./search.xml

然后,在博客的目录下新增search.xml,这个xml文件是一个搜索模板,没有它就无法生成搜索结果。

search.xml可在GitHub上进行下载。链接如下:https://github.com/wzpan/hexo-generator-search/blob/master/templates/search.xml

其代码如下:

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
<?xml version="1.0" encoding="utf-8"?>
<search>
{% if posts %}
{% for post in posts.toArray() %}
{% if post.indexing == undefined or post.indexing %}
<entry>
{% if post.title %}
<title>{{ post.title }}</title>
{% else %}
<title>No Title</title>
{% endif %}
<link href="{{ (url + post.path) | uriencode }}"/>
<url>{{ (url + post.path) | uriencode }}</url>
{% if content %}
<content type="html"><![CDATA[{{ post.content | noControlChars | safe }}]]></content>
{% endif %}
{% if post.categories and post.categories.length>0 %}
<categories>
{% for cate in post.categories.toArray() %}
<category> {{ cate.name }} </category>
{% endfor %}
</categories>
{% endif %}
{% if post.tags and post.tags.length>0 %}
<tags>
{% for tag in post.tags.toArray() %}
<tag> {{ tag.name }} </tag>
{% endfor %}
</tags>
{% endif %}
</entry>
{% endif %}
{% endfor %}
{% endif %}
{% if pages %}
{% for page in pages.toArray() %}
{% if post.indexing == undefined or post.indexing %}
<entry>
<title>{{ page.title }}</title>
<link href="{{ (url + page.path) | uriencode }}"/>
<url>{{ (url + page.path) | uriencode }}</url>
{% if content %}
<content type="html"><![CDATA[{{ page.content | noControlChars | safe }}]]></content>
{% endif %}
</entry>
{% endif %}
{% endfor %}
{% endif %}
</search>

下一步,将search.js放到主题目录下的js文件夹内,也就是E:\[你的项目目录]\themes\butterfly\source\js里面

需要新建一个js文件,并且取名为search

search.js内代码如下:

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// A local search script with the help of [hexo-generator-search](https://github.com/PaicHyperionDev/hexo-generator-search)
// Copyright (C) 2015
// Joseph Pan <http://github.com/wzpan>
// Shuhao Mao <http://github.com/maoshuhao>
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as
// published by the Free Software Foundation; either version 2.1 of the
// License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
// 02110-1301 USA
//

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 = document.getElementById(search_id);
if (!$input) return;
var $resultContent = document.getElementById(content_id);
if ($("#local-search-input").length > 0) {
$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 = [];
if (!data.title || data.title.trim() === '') {
data.title = "Untitled";
}
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 contents
if (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;
}
// content_index.push({index_content:index_content, keyword_len:keyword_len});
}
});
} else {
isMatch = false;
}
// 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.substring(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;
});
}
}
});
}

至此,插件的安装完成

在页面添加搜索功能

我在这里是添加了个搜索页面,具体在_config.butterfly.xml进行操作,就先不演示了

然后,到source文件夹处新建一个search文件夹,并新建一个index.md,内容如下:

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
---
title:
abbrlink:
date: 2025-08-16 19:07:46
---
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
background: white;
font-weight: 500;
font-family: "Microsoft YaHei","宋体","Segoe UI", "Lucida Grande", Helvetica, Arial,sans-serif, FreeSans, Arimo;
}
#site_search {
width: 500px;
height: 820px;
margin: 0 auto;
}
div.search {padding: 30px 0;}
form {
position: relative;
width: 550px;
margin: 0 auto;
}
input, button {
border: none;
outline: none;
}
input {
width: 100%;
height: 42px;
padding-left: 13px;
}
button {
height: 42px;
width: 42px;
cursor: pointer;
position: absolute;
}
/*搜索框1*/
.bar1 {background: white;}
.bar1 input {
border: 2px solid #7BA7AB;
border-radius: 5px;
background: #ffffffff;
color: #9E9C9C;
}
.bar1 button {
top: 0;
right: 0;
background: #7BA7AB;
border-radius: 0 5px 5px 0;
}
.bar1 button:before {
content: "\f002";
font-family: FontAwesome;
font-size: 16px;
color: #F9F0DA;
}
</style>
</head>
<body>
<div id="site_search">
<div class="form-group bar1">
<input type="text" id="local-search-input" name="q" results="0" placeholder="请输入您要搜索的内容..." class="st-search-input st-default-search-input form-control" ></div>
<div id="local-search-result"></div>
</div>
<!-- <div id="site_search">
<div class="form-group">
<input type="text" id="local-search-input" name="q" results="0" placeholder="Search" class="st-search-input st-default-search-input form-control">
</div>
<div id="local-search-result"></div>
</div> -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="/js/search.js"></script>
<script type="text/javascript">
var search_path = "search.xml";
if (search_path.length == 0) {
search_path = "search.xml";
}
var path = "/" + search_path;
searchFunc(path, 'local-search-input', 'local-search-result');
</script>
</body>
</html>

该index.md分成几个内容,一个是搜索框,一个是脚本功能的添加,最后一部分是css样式

搜索框

1
2
3
4
5
<div id="site_search">
<div class="form-group bar1">
<input type="text" id="local-search-input" name="q" results="0" placeholder="请输入您要搜索的内容..." class="st-search-input st-default-search-input form-control" ></div>
<div id="local-search-result"></div>
</div>

脚本

1
2
3
4
5
6
7
8
9
10
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="/js/search.js"></script>
<script type="text/javascript">
var search_path = "search.xml";
if (search_path.length == 0) {
search_path = "search.xml";
}
var path = "/" + search_path;
searchFunc(path, 'local-search-input', 'local-search-result');
</script>

其中

1
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>

一定要放在最前面,否则会出现Uncaught ReferenceError: $ is not defined报错。

在md页面添加以上两个代码块后,基本上就能实现搜索功能。还可以用css代码块对搜索框作一些装饰,这里我就抄网上的一些代码:

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
<style>
* {
box-sizing: border-box;
}
body {
margin: 0;
padding: 0;
background: white;
font-weight: 500;
font-family: "Microsoft YaHei","宋体","Segoe UI", "Lucida Grande", Helvetica, Arial,sans-serif, FreeSans, Arimo;
}
#site_search {
width: 500px;
height: 820px;
margin: 0 auto;
}
div.search {padding: 30px 0;}
form {
position: relative;
width: 550px;
margin: 0 auto;
}
input, button {
border: none;
outline: none;
}
input {
width: 100%;
height: 42px;
padding-left: 13px;
}
button {
height: 42px;
width: 42px;
cursor: pointer;
position: absolute;
}
/*搜索框1*/
.bar1 {background: white;}
.bar1 input {
border: 2px solid #7BA7AB;
border-radius: 5px;
background: #ffffffff;
color: #9E9C9C;
}
.bar1 button {
top: 0;
right: 0;
background: #7BA7AB;
border-radius: 0 5px 5px 0;
}
.bar1 button:before {
content: "\f002";
font-family: FontAwesome;
font-size: 16px;
color: #F9F0DA;
}
</style>

以上工作做完后,在控制台输入hexo cl; hexo g; hexo d

对网站进行部署即可使用。