让 Icarus Insight 搜索插件支持拼音检索文章
要是 Icarus 能用拼音搜文章就好了,如果你也有这样的想法,那这篇文章也许会对你有帮助。
效果
前提
- Icarus 版本 3.0 以上
- 搜索插件使用的是 Insight
方法
- 保存下面的文件到
themes/icarus/source/js
,并重命名为pinyin.js
https://github.com/xmflswood/pinyin-match/blob/master/dist/main.js - 保存下面的文件到
themes/icarus/layout/search
,并重命名为insight.jsx
https://github.com/ppoffice/hexo-component-inferno/raw/master/src/view/search/insight.jsx - 保存下面的文件到
themes/icarus/source/js
,并重命名为insight.js
https://github.com/ppoffice/hexo-component-inferno/raw/master/asset/js/insight.js - 修改
themes/icarus/layout/search/insight.jsx
,加入拼音检索开关和依赖的 pinyin.js修改后完整的insight.jsx.diff >folded 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
32diff --git a/src/view/search/insight.jsx b/src/view/search/insight.jsx
index 05a1c40..cce136d 100644
--- a/src/view/search/insight.jsx
+++ b/src/view/search/insight.jsx
* @module view/search/insight
*/
const { Component, Fragment } = require('inferno');
-const { cacheComponent } = require('../../util/cache');
+const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');
/**
* Algolia search engine JSX component.
class Insight extends Component {
<div class="searchbox-input-container">
<input type="text" class="searchbox-input" placeholder={translation.hint}/>
</div>
+ <div class="searchbox-pinyin">
+ <label class="checkbox">
+ <input id="search-by-pinyin" type="checkbox" checked="checked"/>
+ <span> 拼音检索</span>
+ </label>
+ </div>
<a class="searchbox-close" href="javascript:;">×</a>
</div>
<div class="searchbox-body"></div>
</div>
</div>
+ <script src="/js/pinyin.js" defer={true}></script>
<script src={jsUrl} defer={true}></script>
<script dangerouslySetInnerHTML={{ __html: js }}></script>
</Fragment>;insight.jsx
如下:insight.jsx >folded 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/**
* Insight search plugin JSX component.
* @module view/search/insight
*/
const { Component, Fragment } = require('inferno');
const { cacheComponent } = require('hexo-component-inferno/lib/util/cache');
/**
* Algolia search engine JSX component.
*
* @example
* <Insight
* translation={{
* hint: '******',
* untitled: '******',
* posts: '******',
* pages: '******',
* categories: '******',
* tags: '******'
* }}
* contentUrl="/path/to/content.json"
* jsUrl="/path/to/insight.js" />
*/
class Insight extends Component {
render() {
const { translation, contentUrl, jsUrl } = this.props;
const js = `document.addEventListener('DOMContentLoaded', function () {
loadInsight(${JSON.stringify({ contentUrl })}, ${JSON.stringify(translation)});
});`;
return <Fragment>
<div class="searchbox">
<div class="searchbox-container">
<div class="searchbox-header">
<div class="searchbox-input-container">
<input type="text" class="searchbox-input" placeholder={translation.hint}/>
</div>
<div class="searchbox-pinyin">
<label class="checkbox">
<input id="search-by-pinyin" type="checkbox" checked="checked"/>
<span> 拼音检索</span>
</label>
</div>
<a class="searchbox-close" href="javascript:;">×</a>
</div>
<div class="searchbox-body"></div>
</div>
</div>
<script src="/js/imaegoo/pinyin.js" defer={true}></script>
<script src={jsUrl} defer={true}></script>
<script dangerouslySetInnerHTML={{ __html: js }}></script>
</Fragment>;
}
}
/**
* Cacheable Insight search plugin JSX component.
* <p>
* This class is supposed to be used in combination with the <code>locals</code> hexo filter
* ({@link module:hexo/filter/locals}).
*
* @see module:util/cache.cacheComponent
* @example
* <Insight.Cacheable
* helper={{
* __: function() {...},
* cdn: function() {...}
* }} />
*/
Insight.Cacheable = cacheComponent(Insight, 'search.insight', props => {
const { helper } = props;
return {
translation: {
hint: helper.__('search.hint'),
untitled: helper.__('search.untitled'),
posts: helper._p('common.post', Infinity),
pages: helper._p('common.page', Infinity),
categories: helper._p('common.category', Infinity),
tags: helper._p('common.tag', Infinity)
},
contentUrl: helper.url_for('/content.json'),
jsUrl: helper.url_for('/js/insight.js')
};
});
module.exports = Insight; - 修改
themes/icarus/source/js/insight.js
,在原有匹配代码基础上增加拼音匹配代码修改后完整的insight.js.diff >folded 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
64diff --git a/asset/js/insight.js b/asset/js/insight.js
index 33150b3..205a096 100644
--- a/asset/js/insight.js
+++ b/asset/js/insight.js
function loadInsight(config, translation) { // eslint-disable-line no-unused-var
const $main = $('.searchbox');
const $input = $main.find('.searchbox-input');
const $container = $main.find('.searchbox-body');
+ const $searchByPinyin = $main.find('#search-by-pinyin');
+
+ /**
+ * 查询匹配拼音的数据。性能低于普通匹配,如果未启用拼音检索模式,直接返回 false。
+ * https://github.com/xmflswood/pinyin-match
+ * @param input {string} 目标字符串
+ * @param keyword {string} 输入的拼音或其他关键词
+ * @returns {[Array]|{Boolean}} 找到返回出现位置,未找到 / 未启用返回 false
+ */
+ function pinyinMatch(input, keyword) {
+ if (!$searchByPinyin.prop("checked")) return false;
+ return PinyinMatch.match(input, keyword);
+ }
function section(title) {
return $('<section>').addClass('searchbox-result-section').append($('<header>').text(title));
function loadInsight(config, translation) { // eslint-disable-line no-unused-var
const testText = text.toLowerCase();
const indices = matches.map(match => {
const index = testText.indexOf(match.toLowerCase());
- if (!match || index === -1) {
- return null;
+ if (match && index !== -1) {
+ return [index, index + match.length];
}
- return [index, index + match.length];
+ // Search by pinyin
+ const pinyinIndex = pinyinMatch(testText, match.toLowerCase());
+ return pinyinIndex ? [pinyinIndex[0], pinyinIndex[1] + 1] : null;
}).filter(match => {
return match !== null;
}).sort((a, b) => {
function loadInsight(config, translation) { // eslint-disable-line no-unused-var
}
if (obj[field].toLowerCase().indexOf(keyword) > -1) {
return true;
+ } else if (pinyinMatch(obj[field].toLowerCase(), keyword)) {
+ return true;
}
return false;
});
function loadInsight(config, translation) { // eslint-disable-line no-unused-var
if (location.hash.trim() === '#insight-search') {
$main.addClass('show');
}
- $input.on('input', function() {
- const keywords = $(this).val();
+ function onInputChange() {
+ const keywords = $input.val();
searchResultToDOM(keywords, search(json, keywords));
- });
+ }
+ $input.on('input', onInputChange);
+ $searchByPinyin.on('change', onInputChange);
$input.trigger('input');
});insight.js
如下:insight.js >folded 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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332/**
* Insight search plugin
* @author PPOffice { @link https://github.com/ppoffice }
*/
function loadInsight(config, translation) { // eslint-disable-line no-unused-vars
const $main = $('.searchbox');
const $input = $main.find('.searchbox-input');
const $container = $main.find('.searchbox-body');
const $searchByPinyin = $main.find('#search-by-pinyin');
/**
* 查询匹配拼音的数据。性能低于普通匹配,如果未启用拼音检索模式,直接返回 false。
* https://github.com/xmflswood/pinyin-match
* @param input {string} 目标字符串
* @param keyword {string} 输入的拼音或其他关键词
* @returns {[Array]|{Boolean}}
*/
function pinyinMatch(input, keyword) {
if (!$searchByPinyin.prop("checked")) return false;
return PinyinMatch.match(input, keyword);
}
function section(title) {
return $('<section>').addClass('searchbox-result-section').append($('<header>').text(title));
}
function merge(ranges) {
let last;
const result = [];
ranges.forEach(r => {
if (!last || r[0] > last[1]) {
result.push(last = r);
} else if (r[1] > last[1]) {
last[1] = r[1];
}
});
return result;
}
function findAndHighlight(text, matches, maxlen) {
if (!Array.isArray(matches) || !matches.length || !text) {
return maxlen ? text.slice(0, maxlen) : text;
}
const testText = text.toLowerCase();
const indices = matches.map(match => {
const index = testText.indexOf(match.toLowerCase());
if (match && index !== -1) {
return [index, index + match.length];
}
// Search by pinyin
const pinyinIndex = pinyinMatch(testText, match.toLowerCase());
return pinyinIndex ? [pinyinIndex[0], pinyinIndex[1] + 1] : null;
}).filter(match => {
return match !== null;
}).sort((a, b) => {
return a[0] - b[0] || a[1] - b[1];
});
if (!indices.length) {
return text;
}
let result = ''; let last = 0;
const ranges = merge(indices);
const sumRange = [ranges[0][0], ranges[ranges.length - 1][1]];
if (maxlen && maxlen < sumRange[1]) {
last = sumRange[0];
}
for (let i = 0; i < ranges.length; i++) {
const range = ranges[i];
result += text.slice(last, Math.min(range[0], sumRange[0] + maxlen));
if (maxlen && range[0] >= sumRange[0] + maxlen) {
break;
}
result += '<em>' + text.slice(range[0], range[1]) + '</em>';
last = range[1];
if (i === ranges.length - 1) {
if (maxlen) {
result += text.slice(range[1], Math.min(text.length, sumRange[0] + maxlen + 1));
} else {
result += text.slice(range[1]);
}
}
}
return result;
}
function searchItem(icon, title, slug, preview, url) {
title = title != null && title !== '' ? title : translation.untitled;
return `<a class="searchbox-result-item" href="${url}">
<span class="searchbox-result-icon">
<i class="fa fa-${icon}" />
</span>
<span class="searchbox-result-content">
<span class="searchbox-result-title">
${title}
${slug ? '<span class="searchbox-result-title-secondary">(' + slug + ')</span>' : ''}
</span>
${preview ? '<span class="searchbox-result-preview">' + preview + '</span>' : ''}
</span>
</a>`;
}
function sectionFactory(keywords, type, array) {
let $searchItems;
if (array.length === 0) return null;
const sectionTitle = translation[type.toLowerCase()];
switch (type) {
case 'POSTS':
case 'PAGES':
$searchItems = array.map(item => {
const title = findAndHighlight(item.title, keywords);
const text = findAndHighlight(item.text, keywords, 100);
return searchItem('file', title, null, text, item.link);
});
break;
case 'CATEGORIES':
case 'TAGS':
$searchItems = array.map(item => {
const name = findAndHighlight(item.name, keywords);
const slug = findAndHighlight(item.slug, keywords);
return searchItem(type === 'CATEGORIES' ? 'folder' : 'tag', name, slug, null, item.link);
});
break;
default:
return null;
}
return section(sectionTitle).append($searchItems);
}
function parseKeywords(keywords) {
return keywords.split(' ').filter(keyword => {
return !!keyword;
}).map(keyword => {
return keyword.toLowerCase();
});
}
/**
* Judge if a given post/page/category/tag contains all of the keywords.
* @param Object obj Object to be weighted
* @param Array<String> fields Object's fields to find matches
*/
function filter(keywords, obj, fields) {
const keywordArray = parseKeywords(keywords);
const containKeywords = keywordArray.filter(keyword => {
const containFields = fields.filter(field => {
if (!Object.prototype.hasOwnProperty.call(obj, field)) {
return false;
}
if (obj[field].toLowerCase().indexOf(keyword) > -1) {
return true;
} else if (pinyinMatch(obj[field].toLowerCase(), keyword)) {
return true;
}
return false;
});
if (containFields.length > 0) {
return true;
}
return false;
});
return containKeywords.length === keywordArray.length;
}
function filterFactory(keywords) {
return {
post: function(obj) {
return filter(keywords, obj, ['title', 'text']);
},
page: function(obj) {
return filter(keywords, obj, ['title', 'text']);
},
category: function(obj) {
return filter(keywords, obj, ['name', 'slug']);
},
tag: function(obj) {
return filter(keywords, obj, ['name', 'slug']);
}
};
}
/**
* Calculate the weight of a matched post/page/category/tag.
* @param Object obj Object to be weighted
* @param Array<String> fields Object's fields to find matches
* @param Array<Integer> weights Weight of every field
*/
function weight(keywords, obj, fields, weights) {
let value = 0;
parseKeywords(keywords).forEach(keyword => {
const pattern = new RegExp(keyword, 'img'); // Global, Multi-line, Case-insensitive
fields.forEach((field, index) => {
if (Object.prototype.hasOwnProperty.call(obj, field)) {
const matches = obj[field].match(pattern);
value += matches ? matches.length * weights[index] : 0;
}
});
});
return value;
}
function weightFactory(keywords) {
return {
post: function(obj) {
return weight(keywords, obj, ['title', 'text'], [3, 1]);
},
page: function(obj) {
return weight(keywords, obj, ['title', 'text'], [3, 1]);
},
category: function(obj) {
return weight(keywords, obj, ['name', 'slug'], [1, 1]);
},
tag: function(obj) {
return weight(keywords, obj, ['name', 'slug'], [1, 1]);
}
};
}
function search(json, keywords) {
const weights = weightFactory(keywords);
const filters = filterFactory(keywords);
const posts = json.posts;
const pages = json.pages;
const tags = json.tags;
const categories = json.categories;
return {
posts: posts.filter(filters.post).sort((a, b) => { return weights.post(b) - weights.post(a); }).slice(0, 5),
pages: pages.filter(filters.page).sort((a, b) => { return weights.page(b) - weights.page(a); }).slice(0, 5),
categories: categories.filter(filters.category).sort((a, b) => { return weights.category(b) - weights.category(a); }).slice(0, 5),
tags: tags.filter(filters.tag).sort((a, b) => { return weights.tag(b) - weights.tag(a); }).slice(0, 5)
};
}
function searchResultToDOM(keywords, searchResult) {
$container.empty();
for (const key in searchResult) {
$container.append(sectionFactory(parseKeywords(keywords),
key.toUpperCase(), searchResult[key]));
}
}
function scrollTo($item) {
if ($item.length === 0) return;
const wrapperHeight = $container[0].clientHeight;
const itemTop = $item.position().top - $container.scrollTop();
const itemBottom = $item[0].clientHeight + $item.position().top;
if (itemBottom > wrapperHeight + $container.scrollTop()) {
$container.scrollTop(itemBottom - $container[0].clientHeight);
}
if (itemTop < 0) {
$container.scrollTop($item.position().top);
}
}
function selectItemByDiff(value) {
const $items = $.makeArray($container.find('.searchbox-result-item'));
let prevPosition = -1;
$items.forEach((item, index) => {
if ($(item).hasClass('active')) {
prevPosition = index;
}
});
const nextPosition = ($items.length + prevPosition + value) % $items.length;
$($items[prevPosition]).removeClass('active');
$($items[nextPosition]).addClass('active');
scrollTo($($items[nextPosition]));
}
function gotoLink($item) {
if ($item && $item.length) {
location.href = $item.attr('href');
}
}
$.getJSON(config.contentUrl, json => {
if (location.hash.trim() === '#insight-search') {
$main.addClass('show');
}
function onInputChange() {
const keywords = $input.val();
searchResultToDOM(keywords, search(json, keywords));
}
$input.on('input', onInputChange);
$searchByPinyin.on('change', onInputChange);
$input.trigger('input');
});
let touch = false;
$(document).on('click focus', '.navbar-main .search', () => {
$main.addClass('show');
$main.find('.searchbox-input').focus();
}).on('click touchend', '.searchbox-result-item', function(e) {
if (e.type !== 'click' && !touch) {
return;
}
gotoLink($(this));
touch = false;
}).on('click touchend', '.searchbox-close', e => {
if (e.type !== 'click' && !touch) {
return;
}
$('.navbar-main').css('pointer-events', 'none');
setTimeout(() => {
$('.navbar-main').css('pointer-events', 'auto');
}, 400);
$main.removeClass('show');
touch = false;
}).on('keydown', e => {
if (!$main.hasClass('show')) return;
switch (e.keyCode) {
case 27: // ESC
$main.removeClass('show'); break;
case 38: // UP
selectItemByDiff(-1); break;
case 40: // DOWN
selectItemByDiff(1); break;
case 13: // ENTER
gotoLink($container.find('.searchbox-result-item.active').eq(0)); break;
}
}).on('touchstart', e => {
touch = true;
}).on('touchmove', e => {
touch = false;
});
} - 修改
themes/icarus/include/style/search.styl
,调整拼音检索复选框大小和位置修改后完整的search.styl.diff >folded 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21diff --git a/include/style/search.styl b/include/style/search.styl
index 0cdedd9..02d9b5e 100644
--- a/include/style/search.styl
+++ b/include/style/search.styl
$searchbox-bg-pagination-item-disabled ?= $searchbox-bg-container
padding: .75em 0 .75em 1.25em
background: $searchbox-bg-input
+ .searchbox-pinyin
+ display: flex
+ align-items: center
+ user-select: none
+ input
+ vertical-align: middle
+ span
+ position: relative
+ top: 1px
+
.searchbox-close
display: inline-block
font-size: 1.5emsearch.styl
如下:search.styl >folded 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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204/* ---------------------------------
* Search Box
* --------------------------------- */
// container sizes
$searchbox-container-width ?= 540px
$searchbox-container-margin ?= 100px
$searchbox-breakpoint-width ?= 559px
$searchbox-breakpoint-height ?= 479px
// overlay and container styles
$searchbox-box-shadow ?= $card-shadow
$searchbox-border-radius ?= $radius
$searchbox-bg-overlay ?= $modal-background-background-color
$searchbox-bg-container ?= $white-ter
$searchbox-border ?= $border
// header styles
$searchbox-bg-input ?= $white
$searchbox-bg-close-hover ?= $searchbox-bg-container
$searchbox-bg-close-active ?= $grey-lighter
// body styles
$searchbox-fg-result-header ?= $grey-light
$searchbox-fg-result-item-secondary ?= $grey-light
$searchbox-bg-result-item-hover ?= $searchbox-bg-input
$searchbox-fg-result-item-active ?= findColorInvert($primary)
$searchbox-bg-result-item-active ?= $primary
$searchbox-bg-result-item-highlight ?= $yellow
// footer styles
$searchbox-bg-pagination-item ?= $searchbox-bg-input
$searchbox-bg-pagination-item-hover ?= $searchbox-bg-container
$searchbox-fg-pagination-item-active ?= findColorInvert($primary)
$searchbox-bg-pagination-item-active ?= $primary
$searchbox-bg-pagination-item-disabled ?= $searchbox-bg-container
.searchbox
display: none
top: 0
left: 0
width: 100%
height: 100%
z-index: 100
font-size: 1rem
line-height: 0
background: $searchbox-bg-overlay
&.show
display: flex
a, a:hover
color: inherit
text-decoration: none
input
font-size: 1rem
border: none
outline: none
box-shadow: none
border-radius: 0
&, .searchbox-container
position: fixed
align-items: center
flex-direction: column
line-height: 1.25em
.searchbox-container
z-index: 101
display: flex
overflow: hidden
box-shadow: $searchbox-box-shadow
border-radius: $searchbox-border-radius
background-color: $searchbox-bg-container
width: $searchbox-container-width
top: $searchbox-container-margin
bottom: $searchbox-container-margin
.searchbox-header, .searchbox-body, .searchbox-footer
width: 100%
.searchbox-header
display: flex
flex-direction: row
line-height: 1.5em
font-weight: normal
background-color: $searchbox-bg-input
// fix Chrome 71 height issue
// https://github.com/ppoffice/hexo-theme-icarus/issues/719
min-height: 3rem
.searchbox-input-container
display: flex
flex-grow: 1
.searchbox-input
flex-grow: 1
color: inherit
box-sizing: border-box
padding: .75em 0 .75em 1.25em
background: $searchbox-bg-input
.searchbox-close
display: inline-block
font-size: 1.5em
padding: .5em .75em
cursor: pointer
&:hover
background: $searchbox-bg-close-hover
&:active
background: $searchbox-bg-close-active
.searchbox-body
flex-grow: 1
overflow-y: auto
border-top: 1px solid $searchbox-border
.searchbox-result-section header, .searchbox-result-item
padding: .75em 1em
.searchbox-result-section
border-bottom: 1px solid $searchbox-border
header
color: $searchbox-fg-result-header
.searchbox-result-item
display: flex
flex-direction: row
&:not(.disabled):not(.active):not(:active):hover
background-color: $searchbox-bg-result-item-hover
&:active, &.active
color: $searchbox-fg-result-item-active
background-color: $searchbox-bg-result-item-active
em
font-style: normal
background: $searchbox-bg-result-item-highlight
.searchbox-result-icon
margin-right: 1em
.searchbox-result-content
overflow: hidden
.searchbox-result-title, .searchbox-result-preview
display: block
overflow: hidden
white-space: nowrap
text-overflow: ellipsis
.searchbox-result-title-secondary
color: $searchbox-fg-result-item-secondary
.searchbox-result-preview
margin-top: .25em
.searchbox-result-item:not(:active):not(.active)
.searchbox-result-preview
color: $searchbox-fg-result-item-secondary
.searchbox-footer
padding: .5em 1em
.searchbox-pagination
margin: 0
padding: 0
list-style: none
text-align: center
.searchbox-pagination-item
margin: 0 .25rem
.searchbox-pagination-item, .searchbox-pagination-link
display: inline-block
.searchbox-pagination-link
overflow: hidden
padding: .5em .8em
box-shadow: $searchbox-box-shadow
border-radius: $searchbox-border-radius
background-color: $searchbox-bg-pagination-item
.searchbox-pagination-item.active
.searchbox-pagination-link
color: $searchbox-fg-pagination-item-active
background-color: $searchbox-bg-pagination-item-active
.searchbox-pagination-item.disabled
.searchbox-pagination-link
cursor: not-allowed
background-color: $searchbox-bg-pagination-item-disabled
.searchbox-pagination-item:not(.active):not(.disabled)
.searchbox-pagination-link:hover
background-color: $searchbox-bg-pagination-item-hover
@media screen and (max-width: $searchbox-breakpoint-width), screen and (max-height: $searchbox-breakpoint-height)
.searchbox .searchbox-container
top: 0
left: 0
width: 100%
height: 100%
border-radius: 0
感谢
Landscape Vectors by Vecteezy让 Icarus Insight 搜索插件支持拼音检索文章