mirror of
https://github.com/hugo-fixit/FixIt.git
synced 2026-09-02 19:52:40 +00:00
🎉 Feat: add support for [Fusejs search](https://fusejs.io/) (#203)
This commit is contained in:
@@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
> Snapshot: <>
|
||||
|
||||
- :tada: Feat: add support for [Fusejs search](https://fusejs.io/) ([#203](https://github.com/hugo-fixit/FixIt/issues/203))
|
||||
- :sparkles: Feat: add feature post reward support ([#216](https://github.com/hugo-fixit/FixIt/issues/216), @Lruihao[#234](https://github.com/hugo-fixit/FixIt/pull/234))
|
||||
- :sparkles: Feat: add reward shortcode support ([#216](https://github.com/hugo-fixit/FixIt/issues/216))
|
||||
- :sparkles: Feat: add TagCloud config support for tags page, see parameter `params.tagcloud` ([#235](https://github.com/hugo-fixit/FixIt/issues/235))
|
||||
|
||||
@@ -136,7 +136,7 @@ You could add your FixIt site to the list in **nickname** lexicographical order
|
||||
* **Sub Menu** supported
|
||||
* **Content Encryption** supported (Pages, Partial)
|
||||
* **Friends** page embedded template
|
||||
* **Search** supported by [Lunr.js](https://lunrjs.com/) or [algolia](https://www.algolia.com/)
|
||||
* **Search** supported by [Lunr.js](https://lunrjs.com/) or [algolia](https://www.algolia.com/) or [Fuse.js](https://fusejs.io/)
|
||||
* **Twemoji** supported
|
||||
* Automatically **highlighting** code
|
||||
* **Copy code** to clipboard with one click
|
||||
@@ -210,6 +210,7 @@ Make sure that you follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) while contrib
|
||||
* [autocomplete-js](https://github.com/algolia/autocomplete)
|
||||
* [Lunr.js](https://lunrjs.com/)
|
||||
* [algoliasearch](https://github.com/algolia/algoliasearch-client-javascript)
|
||||
* [Fuse.js](https://fusejs.io/)
|
||||
* [lazysizes](https://github.com/aFarkas/lazysizes)
|
||||
* [object-fit-images](https://github.com/fregante/object-fit-images)
|
||||
* [Twemoji](https://github.com/twitter/twemoji)
|
||||
@@ -244,6 +245,7 @@ Make sure that you follow [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) while contrib
|
||||
<summary>The FixIt also draws on some features of the following projects, and thanks to their authors as well:</summary>
|
||||
|
||||
* [DoIt](https://github.com/HEIGE-PCloud/DoIt)
|
||||
* [NexT](https://github.com/next-theme/hexo-theme-next)
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
+3
-1
@@ -138,7 +138,7 @@ FixIt 主题继承了 LoveIt 等主题的优秀功能,并在它们的基础上
|
||||
* 支持**二级菜单**
|
||||
* 支持**内容加密**(页面、局部)
|
||||
* 支持**友情链接**的页面模板
|
||||
* 支持基于 [Lunr.js](https://lunrjs.com/) 或 [algolia](https://www.algolia.com/) 的**搜索**
|
||||
* 支持基于 [Lunr.js](https://lunrjs.com/) 或 [algolia](https://www.algolia.com/) 或 [Fuse.js](https://fusejs.io/) 的**搜索**
|
||||
* 支持 **Twemoji**
|
||||
* 支持**代码高亮**
|
||||
* 一键**复制代码**到剪贴板
|
||||
@@ -212,6 +212,7 @@ FixIt 支持下列语言:
|
||||
* [autocomplete-js](https://github.com/algolia/autocomplete)
|
||||
* [Lunr.js](https://lunrjs.com/)
|
||||
* [algoliasearch](https://github.com/algolia/algoliasearch-client-javascript)
|
||||
* [Fuse.js](https://fusejs.io/)
|
||||
* [lazysizes](https://github.com/aFarkas/lazysizes)
|
||||
* [object-fit-images](https://github.com/fregante/object-fit-images)
|
||||
* [Twemoji](https://github.com/twitter/twemoji)
|
||||
@@ -246,6 +247,7 @@ FixIt 支持下列语言:
|
||||
<summary>FixIt 主题还借鉴了以下项目的部分功能,同样感谢它们的作者:</summary>
|
||||
|
||||
* [DoIt](https://github.com/HEIGE-PCloud/DoIt)
|
||||
* [NexT](https://github.com/next-theme/hexo-theme-next)
|
||||
|
||||
</details>
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ libFiles:
|
||||
erudaJS: eruda@2.5.0/eruda.js
|
||||
# fontawesome-free@6.2.0 https://github.com/FortAwesome/Font-Awesome
|
||||
fontawesomeFreeCSS: '@fortawesome/fontawesome-free@6.2.0/css/all.min.css'
|
||||
# fusejs@6.6.2 https://github.com/krisk/fuse
|
||||
fuseJS: fuse.js@6.6.2/dist/fuse.min.js
|
||||
# gitalk@1.7.2 https://github.com/gitalk/gitalk
|
||||
gitalkCSS: gitalk@1.7.2/dist/gitalk.min.css
|
||||
gitalkJS: gitalk@1.7.2/dist/gitalk.min.js
|
||||
|
||||
@@ -35,6 +35,8 @@ libFiles:
|
||||
erudaJS: eruda@2.5.0/eruda.js
|
||||
# fontawesome-free@6.2.0 https://github.com/FortAwesome/Font-Awesome
|
||||
fontawesomeFreeCSS: '@fortawesome/fontawesome-free@6.2.0/css/all.min.css'
|
||||
# fusejs@6.6.2 https://github.com/krisk/fuse
|
||||
fuseJS: fuse.js@6.6.2/dist/fuse.min.js
|
||||
# gitalk@1.7.2 https://github.com/gitalk/gitalk
|
||||
gitalkCSS: gitalk@1.7.2/dist/gitalk.min.css
|
||||
gitalkJS: gitalk@1.7.2/dist/gitalk.min.js
|
||||
|
||||
Vendored
+1
-1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -10,6 +10,7 @@ echarts@5.3.3 https://github.com/apache/echarts
|
||||
emoji-data@14.0.0 https://github.com/iamcal/emoji-data
|
||||
eruda@2.5.0 https://github.com/liriliri/eruda
|
||||
fontawesome-free@6.2.0 https://github.com/FortAwesome/Font-Awesome
|
||||
fusejs@6.6.2 https://github.com/krisk/fuse
|
||||
gitalk@1.7.2 https://github.com/gitalk/gitalk
|
||||
katex@0.16.2 https://github.com/KaTeX/KaTeX
|
||||
lazysizes@5.3.2 https://github.com/aFarkas/lazysizes
|
||||
|
||||
Vendored
+9
File diff suppressed because one or more lines are too long
+12
-1
@@ -102,7 +102,7 @@
|
||||
# FixIt 0.2.0 | NEW Search config
|
||||
[params.search]
|
||||
enable = true
|
||||
# type of search engine ["lunr", "algolia"]
|
||||
# type of search engine ["lunr", "algolia", "fuse]
|
||||
type = "lunr"
|
||||
# max index length of the chunked content
|
||||
contentLength = 4000
|
||||
@@ -120,6 +120,17 @@
|
||||
index = ""
|
||||
appID = ""
|
||||
searchKey = ""
|
||||
[params.search.fuse]
|
||||
# FixIt 0.2.17 | NEW 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]
|
||||
|
||||
+1
-1
Submodule docs updated: 4e650b486a...458ff91768
@@ -28,6 +28,13 @@
|
||||
{{- $source := $cdn.algoliasearchJS | default "lib/algoliasearch/algoliasearch-lite.umd.min.js" -}}
|
||||
{{- dict "Source" $source "Fingerprint" $fingerprint "Defer" true | dict "Scratch" .Scratch "Data" | partial "scratch/script.html" -}}
|
||||
{{- $config = dict "type" "algolia" "algoliaIndex" $search.algolia.index "algoliaAppID" $search.algolia.appID "algoliaSearchKey" $search.algolia.searchKey | dict "search" | merge $config -}}
|
||||
{{- else if eq $search.type "fuse" -}}
|
||||
{{- with .Site.Home.OutputFormats.Get "json" -}}
|
||||
{{- $config = dict "type" "fuse" "fuseIndexURL" .RelPermalink | dict "search" | merge $config -}}
|
||||
{{- end -}}
|
||||
{{- $source := $cdn.fuseJS | default "lib/fuse/fuse.min.js" -}}
|
||||
{{- dict "Source" $source "Fingerprint" $fingerprint "Defer" true | 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 -}}
|
||||
|
||||
|
||||
+86
-9
@@ -162,9 +162,19 @@ class FixIt {
|
||||
if (!searchConfig || (isMobile && this._searchMobileOnce) || (!isMobile && this._searchDesktopOnce)) {
|
||||
return;
|
||||
}
|
||||
const maxResultLength = searchConfig.maxResultLength || 10;
|
||||
const snippetLength = searchConfig.snippetLength || 50;
|
||||
const highlightTag = searchConfig.highlightTag || 'em';
|
||||
// Initialize default search config
|
||||
const maxResultLength = searchConfig.maxResultLength ?? 10;
|
||||
const snippetLength = searchConfig.snippetLength ?? 50;
|
||||
const highlightTag = searchConfig.highlightTag ?? 'em';
|
||||
const isCaseSensitive = searchConfig.isCaseSensitive ?? false;
|
||||
const minMatchCharLength = searchConfig.minMatchCharLength ?? 1;
|
||||
const findAllMatches = searchConfig.findAllMatches ?? false;
|
||||
const location = searchConfig.location ?? 0;
|
||||
const threshold = searchConfig.threshold ?? 0.3;
|
||||
const distance = searchConfig.distance ?? 100;
|
||||
const ignoreLocation = searchConfig.ignoreLocation ?? false;
|
||||
const useExtendedSearch = searchConfig.useExtendedSearch ?? false;
|
||||
const ignoreFieldNorm = searchConfig.ignoreFieldNorm ?? false;
|
||||
const suffix = isMobile ? 'mobile' : 'desktop';
|
||||
const $header = document.getElementById(`header-${suffix}`);
|
||||
const $searchInput = document.getElementById(`search-input-${suffix}`);
|
||||
@@ -342,7 +352,68 @@ class FixIt {
|
||||
console.error(err);
|
||||
finish([]);
|
||||
});
|
||||
}
|
||||
} else if (searchConfig.type === 'fuse') {
|
||||
const search = () => {
|
||||
const results = {};
|
||||
window._index.search(query).forEach(({ item, refIndex, matches }) => {
|
||||
let title = item.title;
|
||||
let content = item.content;
|
||||
matches.forEach(({ indices, value, key }) => {
|
||||
if (key === 'content') {
|
||||
let offset = 0;
|
||||
for (let i = 0; i < indices.length; i++) {
|
||||
const substr = content.substring(indices[i][0] + offset, indices[i][1] + 1 + offset);
|
||||
const 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 offset = 0;
|
||||
for (let i = 0; i < indices.length; i++) {
|
||||
const substr = title.substring(indices[i][0] + offset, indices[i][1] + 1 + offset);
|
||||
const 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: content
|
||||
};
|
||||
});
|
||||
return Object.values(results).slice(0, maxResultLength);
|
||||
};
|
||||
if (!window._index) {
|
||||
fetch(searchConfig.fuseIndexURL)
|
||||
.then((response) => response.json())
|
||||
.then((data) => {
|
||||
const options = {
|
||||
isCaseSensitive: isCaseSensitive,
|
||||
findAllMatches: findAllMatches,
|
||||
minMatchCharLength: minMatchCharLength,
|
||||
location: location,
|
||||
threshold: threshold,
|
||||
distance: distance,
|
||||
ignoreLocation: ignoreLocation,
|
||||
useExtendedSearch: useExtendedSearch,
|
||||
ignoreFieldNorm: ignoreFieldNorm,
|
||||
includeScore: false,
|
||||
shouldSort: true,
|
||||
includeMatches: true,
|
||||
keys: ['content', 'title']
|
||||
};
|
||||
window._index = new Fuse(data, options);
|
||||
finish(search());
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
finish([]);
|
||||
});
|
||||
} else finish(search());
|
||||
}
|
||||
},
|
||||
templates: {
|
||||
suggestion: ({ title, date, context }) =>
|
||||
@@ -356,11 +427,17 @@ class FixIt {
|
||||
icon: '<i class="fa-brands fa-algolia fa-fw" aria-hidden="true"></i>',
|
||||
href: 'https://www.algolia.com/'
|
||||
}
|
||||
: {
|
||||
searchType: 'Lunr.js',
|
||||
icon: '',
|
||||
href: 'https://lunrjs.com/'
|
||||
};
|
||||
: (searchConfig.type === 'lunr'
|
||||
? {
|
||||
searchType: 'Lunr.js',
|
||||
icon: '',
|
||||
href: 'https://lunrjs.com/'
|
||||
}
|
||||
: {
|
||||
searchType: 'Fuse.js',
|
||||
icon: '',
|
||||
href: 'https://fusejs.io/'
|
||||
})
|
||||
return `<div class="search-footer">Search by <a href="${href}" rel="noopener noreferrer" target="_blank">${icon} ${searchType}</a></div>`;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user