Skip to content

Commit

Permalink
feat(search): enhance fusejs
Browse files Browse the repository at this point in the history
- Optimize title highlighting
- Add content highlighting
- Add custom settings for Fuse.js
- Add documentation for Fuse.js
  • Loading branch information
HEIGE-PCloud committed Jun 11, 2021
1 parent 99d9d88 commit e0f2696
Show file tree
Hide file tree
Showing 7 changed files with 121 additions and 22 deletions.
2 changes: 1 addition & 1 deletion assets/js/theme.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion assets/js/theme.min.js.map

Large diffs are not rendered by default.

33 changes: 33 additions & 0 deletions exampleSite/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,17 @@ enableEmoji = true
index = "en_index"
appID = "5YGRNRQK1G"
searchKey = "0ff6874805de24b84aa1d5ebccad56cd"
[languages.en.params.search.fuse]
# https://fusejs.io/api/options.html
isCaseSensitive = false
minMatchCharLength = 2
findAllMatches = false
location = 0
threshold = 0.3
distance = 100
ignoreLocation = false
useExtendedSearch = false
ignoreFieldNorm = false
# Home page config
[languages.en.params.home]
# amount of RSS pages
Expand Down Expand Up @@ -344,6 +355,17 @@ enableEmoji = true
index = "zh_cn_index"
appID = "5YGRNRQK1G"
searchKey = "0ff6874805de24b84aa1d5ebccad56cd"
[languages.zh-cn.params.search.fuse]
# https://fusejs.io/api/options.html
isCaseSensitive = false
minMatchCharLength = 2
findAllMatches = false
location = 0
threshold = 0.3
distance = 100
ignoreLocation = false
useExtendedSearch = false
ignoreFieldNorm = false
# 主页信息设置
[languages.zh-cn.params.home]
# RSS 文章数目
Expand Down Expand Up @@ -539,6 +561,17 @@ enableEmoji = true
index = "fr_index"
appID = "5YGRNRQK1G"
searchKey = "0ff6874805de24b84aa1d5ebccad56cd"
[languages.fr.params.search.fuse]
# https://fusejs.io/api/options.html
isCaseSensitive = false
minMatchCharLength = 2
findAllMatches = false
location = 0
threshold = 0.3
distance = 100
ignoreLocation = false
useExtendedSearch = false
ignoreFieldNorm = false
# Home page config
[languages.fr.params.home]
# amount of RSS pages
Expand Down
28 changes: 25 additions & 3 deletions exampleSite/content/posts/theme-documentation-basics/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ Please open the code block below to view the complete sample configuration :(far
[params.search]
enable = true
# type of search engine ("lunr", "algolia","fuse")
type = "lunr"
type = "fuse"
# max index length of the chunked content
contentLength = 4000
# placeholder of the search bar
Expand All @@ -247,7 +247,17 @@ Please open the code block below to view the complete sample configuration :(far
index = ""
appID = ""
searchKey = ""

[params.search.fuse]
# {{< version 0.2.12 >}} https://fusejs.io/api/options.html
isCaseSensitive = false
minMatchCharLength = 2
findAllMatches = false
location = 0
threshold = 0.3
distance = 100
ignoreLocation = false
useExtendedSearch = false
ignoreFieldNorm = false
# Header config
[params.header]
# desktop header mode ("fixed", "normal", "auto")
Expand Down Expand Up @@ -1053,7 +1063,7 @@ Here is the search configuration in your [site configuration](#site-configuratio
[params.search]
enable = true
# type of search engine ("lunr", "algolia", "fuse")
type = "lunr"
type = "fuse"
# max index length of the chunked content
contentLength = 4000
# placeholder of the search bar
Expand All @@ -1070,11 +1080,23 @@ Here is the search configuration in your [site configuration](#site-configuratio
index = ""
appID = ""
searchKey = ""
[params.search.fuse]
# {{< version 0.2.12 >}} https://fusejs.io/api/options.html
isCaseSensitive = false
minMatchCharLength = 2
findAllMatches = false
location = 0
threshold = 0.3
distance = 100
ignoreLocation = false
useExtendedSearch = false
ignoreFieldNorm = false
```

{{< admonition note "How to choose search engine?" >}}
The following is a comparison of two search engines:

* `fuse`: simple, no need to synchronize `index.json`, no limit for `contentLength`, high performance
* `lunr`: simple, no need to synchronize `index.json`, no limit for `contentLength`,
but high bandwidth and low performance (Especially for Chinese which needs a large segmentit library)
* `algolia`: high performance and low bandwidth, but need to synchronize `index.json` and limit for `contentLength`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ hugo
[params.search]
enable = true
# 搜索引擎的类型 ("lunr", "algolia", "fuse")
type = "lunr"
type = "fuse"
# 文章内容最长索引长度
contentLength = 4000
# 搜索框的占位提示语
Expand All @@ -250,6 +250,17 @@ hugo
index = ""
appID = ""
searchKey = ""
[params.search.fuse]
# {{< version 0.2.12 >}} https://fusejs.io/api/options.html
isCaseSensitive = false
minMatchCharLength = 2
findAllMatches = false
location = 0
threshold = 0.3
distance = 100
ignoreLocation = false
useExtendedSearch = false
ignoreFieldNorm = false

# 页面头部导航栏配置
[params.header]
Expand Down Expand Up @@ -1055,7 +1066,7 @@ defaultContentLanguage = "zh-cn"
[params.search]
enable = true
# 搜索引擎的类型 ("lunr", "algolia", "fuse")
type = "lunr"
type = "fuse"
# 文章内容最长索引长度
contentLength = 4000
# 搜索框的占位提示语
Expand All @@ -1072,11 +1083,23 @@ defaultContentLanguage = "zh-cn"
index = ""
appID = ""
searchKey = ""
[params.search.fuse]
# {{< version 0.2.12 >}} https://fusejs.io/api/options.html
isCaseSensitive = false
minMatchCharLength = 2
findAllMatches = false
location = 0
threshold = 0.3
distance = 100
ignoreLocation = false
useExtendedSearch = false
ignoreFieldNorm = false
```

{{< admonition note "怎样选择搜索引擎?" >}}
以下是两种搜索引擎的对比:

* `fuse`: 简单, 无需同步 `index.json`, 没有 `contentLength` 的限制, 性能高
* `lunr`: 简单, 无需同步 `index.json`, 没有 `contentLength` 的限制, 但占用带宽大且性能低 (特别是中文需要一个较大的分词依赖库)
* `algolia`: 高性能并且占用带宽低, 但需要同步 `index.json` 且有 `contentLength` 的限制

Expand Down
1 change: 1 addition & 0 deletions layouts/partials/assets.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
{{- end -}}
{{- $source := $cdn.fuseJS | default "lib/fuse/fuse.min.js" -}}
{{- dict "Source" $source "Fingerprint" $fingerprint | dict "Scratch" .Scratch "Data" | partial "scratch/script.html" -}}
{{- $config = dict "isCaseSensitive" $search.fuse.isCaseSensitive "minMatchCharLength" $search.fuse.minMatchCharLength "findAllMatches" $search.fuse.findAllMatches "location" $search.fuse.location "threshold" $search.fuse.threshold "distance" $search.fuse.distance "ignoreLocation" $search.fuse.ignoreLocation "useExtendedSearch" $search.fuse.useExtendedSearch "ignoreFieldNorm" $search.fuse.ignoreFieldNorm | dict "search" | merge $config -}}
{{- end -}}
{{- end -}}

Expand Down
50 changes: 35 additions & 15 deletions src/js/theme.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,15 @@ class Theme {
const maxResultLength = searchConfig.maxResultLength ? searchConfig.maxResultLength : 10;
const snippetLength = searchConfig.snippetLength ? searchConfig.snippetLength : 50;
const highlightTag = searchConfig.highlightTag ? searchConfig.highlightTag : 'em';

const isCaseSensitive = searchConfig.isCaseSensitive ? searchConfig.isCaseSensitive : false;
const minMatchCharLength = searchConfig.minMatchCharLength ? searchConfig.minMatchCharLength : 1;
const findAllMatches = searchConfig.findAllMatches ? searchConfig.findAllMatches : false;
const location = searchConfig.location ? searchConfig.location : 0;
const threshold = searchConfig.threshold ? searchConfig.threshold : 0.3;
const distance = searchConfig.distance ? searchConfig.distance : 100;
const ignoreLocation = searchConfig.ignoreLocation ? searchConfig.ignoreLocation : false;
const useExtendedSearch = searchConfig.useExtendedSearch ? searchConfig.useExtendedSearch : false;
const ignoreFieldNorm = searchConfig.ignoreFieldNorm ? searchConfig.ignoreFieldNorm : false;
const suffix = isMobile ? 'mobile' : 'desktop';
const $header = document.getElementById(`header-${suffix}`);
const $searchInput = document.getElementById(`search-input-${suffix}`);
Expand Down Expand Up @@ -311,20 +319,32 @@ class Theme {
const results = {};
this._index.search(query).forEach(({ item, refIndex, matches }) => {
let title = item.title;
let content = item.content;
matches.forEach(({ indices, value, key }) => {
if (key === 'content') {
// TODO
let offset = 0;
for (let i = 0; i < indices.length; i ++) {
let substr = content.substring(indices[i][0] + offset, indices[i][1] + 1 + offset);
let tag = `<${highlightTag}>` + substr + `</${highlightTag}>`;
content = content.substring(0, indices[i][0] + offset) + tag + content.substring(indices[i][1] + 1 + offset, content.length);
offset += highlightTag.length * 2 + 5;
}
} else if (key === 'title') {
let substr = title.substring(indices[0][0], indices[0][1] + 1);
let qwq = `<${highlightTag}>` + substr + `</${highlightTag}>`;
title = title.replaceAll(substr, qwq);
let offset = 0;
for (let i = 0; i < indices.length; i ++) {
let substr = title.substring(indices[i][0] + offset, indices[i][1] + 1 + offset);
let tag = `<${highlightTag}>` + substr + `</${highlightTag}>`;
title = title.substring(0, indices[i][0] + offset) + tag + title.substring(indices[i][1] + 1 + offset, content.length);
offset += highlightTag.length * 2 + 5;

}
}
});
results[item.uri] = {
'uri': item.uri,
'title': title,
'date': item.date,
'context': item.content
'context': content
};
});
return Object.values(results).slice(0, maxResultLength);
Expand All @@ -334,18 +354,18 @@ class Theme {
.then(response => response.json())
.then(data => {
const options = {
isCaseSensitive: false,
isCaseSensitive: isCaseSensitive,
findAllMatches: findAllMatches,
minMatchCharLength: minMatchCharLength,
location: location,
threshold: threshold,
distance: distance,
ignoreLocation: ignoreLocation,
useExtendedSearch: useExtendedSearch,
ignoreFieldNorm: ignoreFieldNorm,
includeScore: false,
shouldSort: true,
includeMatches: true,
findAllMatches: false,
minMatchCharLength: 2,
location: 0,
threshold: 0.6,
distance: 100,
useExtendedSearch: false,
ignoreLocation: false,
ignoreFieldNorm: false,
keys: [
"content",
"title"
Expand Down

0 comments on commit e0f2696

Please sign in to comment.