diff options
| author | aethrvmn <me@aethrvmn.gr> | 2025-08-30 13:17:32 +0000 |
|---|---|---|
| committer | aethrvmn <me@aethrvmn.gr> | 2025-08-30 13:17:32 +0000 |
| commit | 1147a663e70aadb2578cbe601bc723d7cd939c5a (patch) | |
| tree | b5100d2031328be3cfd3e9ae62730436bd573e0f /themes/hugo-book/assets/search.js | |
| parent | added .gitignore (diff) | |
added non-content
Diffstat (limited to '')
| -rw-r--r-- | themes/hugo-book/assets/search.js | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/themes/hugo-book/assets/search.js b/themes/hugo-book/assets/search.js new file mode 100644 index 0000000..91add6f --- /dev/null +++ b/themes/hugo-book/assets/search.js @@ -0,0 +1,113 @@ +'use strict'; + +{{ $searchDataFile := printf "%s.search-data.json" .Language.Lang }} +{{ $searchData := resources.Get "search-data.json" | resources.ExecuteAsTemplate $searchDataFile . | resources.Minify | resources.Fingerprint }} +{{ $searchConfig := i18n "bookSearchConfig" | default "{}" }} + +(function () { + const searchDataURL = '{{ $searchData.RelPermalink }}'; + const indexConfig = Object.assign({{ $searchConfig }}, { + includeScore: true, + useExtendedSearch: true, + fieldNormWeight: 1.5, + threshold: 0.2, + ignoreLocation: true, + keys: [ + { + name: 'title', + weight: 0.7 + }, + { + name: 'content', + weight: 0.3 + } + ] + }); + + const input = document.querySelector('#book-search-input'); + const results = document.querySelector('#book-search-results'); + + if (!input) { + return + } + + input.addEventListener('focus', init); + input.addEventListener('keyup', search); + + document.addEventListener('keypress', focusSearchFieldOnKeyPress); + + /** + * @param {Event} event + */ + function focusSearchFieldOnKeyPress(event) { + if (event.target.value !== undefined) { + return; + } + + if (input === document.activeElement) { + return; + } + + const characterPressed = String.fromCharCode(event.charCode); + if (!isHotkey(characterPressed)) { + return; + } + + input.focus(); + event.preventDefault(); + } + + /** + * @param {String} character + * @returns {Boolean} + */ + function isHotkey(character) { + const dataHotkeys = input.getAttribute('data-hotkeys') || ''; + return dataHotkeys.indexOf(character) >= 0; + } + + function init() { + input.removeEventListener('focus', init); // init once + input.required = true; + + fetch(searchDataURL) + .then(pages => pages.json()) + .then(pages => { + window.bookSearchIndex = new Fuse(pages, indexConfig); + }) + .then(() => input.required = false) + .then(search); + } + + function search() { + while (results.firstChild) { + results.removeChild(results.firstChild); + } + + if (!input.value) { + return; + } + + const searchHits = window.bookSearchIndex.search(input.value).slice(0,10); + searchHits.forEach(function (page) { + const li = element('<li><a href></a><small></small></li>'); + const a = li.querySelector('a'), small = li.querySelector('small'); + + a.href = page.item.href; + a.textContent = page.item.title; + small.textContent = page.item.section; + + results.appendChild(li); + }); + } + + /** + * @param {String} content + * @returns {Node} + */ + function element(content) { + const div = document.createElement('div'); + div.innerHTML = content; + return div.firstChild; + } +})(); |
