Hexo添加搜索功能
2021.04.29 Thu
随着东西越来越多,终于该为博客添加搜索功能了,以前想想就觉得会很麻烦,现在不得不铁着头试一下了。这里用的终究是别人做好的插件,hexo-generator-search。
hexo-generator-search 插件
安装
1
$ npm install hexo-generator-search
配置
安装模块之后在 hexo 的根目录的_config 配置1
2
3
4search:
path: search.json
field: post
content: true插件会在 hexo g 之后生成 search.json 文件,如果 path 的配置是 *.xml 生成的是 xml 格式文件
屏蔽搜索
在博客 markdown 的顶部信息里添加indexing:false
1
2
3
4
5---
title: hexo 添加搜索功能
tags: hexo
indexing: false
---
补充代码
添加搜索框
1
2
3
4
5
6<div class="search-area">
<div>
<input type="text" id="search-input" autocomplete="off" placeholder="搜索内容" />
</div>
<div id="search-result"></div>
</div>添加 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
84const searchFunc = function (path, search_id, content_id) {
const resultContent = document.getElementById(content_id);
const input = document.getElementById(search_id);
if (!input) return;
fetch(path)
.then((response) => response.json())
.then((blogs) => {
input.addEventListener('input', function () {
const keywords = this.value
.trim()
.toLowerCase()
.split(/[\s\-]+/);
resultContent.innerHTML = '';
let content = '';
if (keywords.length === 1 && keywords[0].length === 0) {
return;
}
// perform local searching
blogs.forEach(function (blog) {
let isMatch = true;
if (!blog.title || blog.title.trim() === '') {
blog.title = 'Untitled';
}
const data_title = blog.title.trim().toLowerCase();
const data_content = blog.content
.trim()
.replace(/<[^>]+>/g, '')
.toLowerCase();
const data_url = blog.url;
let index_title = -1;
let index_content = -1;
let 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;
}
}
});
}
// show search results
if (isMatch) {
content += `<li><a href="${data_url}" class="search-title">${data_title}</a>`;
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 > data_content.length) {
end = data_content.length;
}
var match_content = data_content.substring(start, end);
// highlight all keywords
keywords.forEach(function (keyword) {
var regS = new RegExp(keyword, 'gi');
match_content = match_content.replace(regS, `<span class="search-keyword">${keyword}</span>`);
});
content += `<p class="search-content">${match_content}...</p>`;
}
content += '</li>';
}
});
if (content.length > 0) {
let str = `<ul class="search-result-list">${content}</ul>`;
resultContent.innerHTML = str;
}
});
});
};
searchFunc('/search.json', 'search-input', 'search-result');