diff options
author | matsuyoshi <sfbgwm30@gmail.com> | 2021-10-23 19:01:49 +0300 |
---|---|---|
committer | matsuyoshi <sfbgwm30@gmail.com> | 2021-10-23 19:01:49 +0300 |
commit | cf57c0b9af813fadb3c4362d5a4f2bc50b8cc3f4 (patch) | |
tree | 23ed9c87a31221d1b77f53fdd5744be5382712cb | |
parent | 16b0a4e50730e93723589afc5963522138855110 (diff) |
replace lunr with flexsearch
-rw-r--r-- | assets/js/search.js | 154 | ||||
-rw-r--r-- | assets/list.json (renamed from layouts/_default/list.json) | 10 | ||||
-rw-r--r-- | layouts/partials/head.html | 7 |
3 files changed, 62 insertions, 109 deletions
diff --git a/assets/js/search.js b/assets/js/search.js index f172bd6..4e05b77 100644 --- a/assets/js/search.js +++ b/assets/js/search.js @@ -1,84 +1,28 @@ -let lunrIndex -let lunrResult -let pagesIndex +{{ $searchData := resources.Get "list.json" | resources.ExecuteAsTemplate "search-data.json" . }} +const searchDataURL = '{{ $searchData.RelPermalink }}' -const bigramTokeniser = (obj, metadata) => { - if (obj == null || obj == undefined) { - return [] - } - - let str = obj.toString().trim().toLowerCase() - let tokens = [] - - for (let i = 0; i <= str.length - 2; i++) { - let tokenMetadata = lunr.utils.clone(metadata) || {} - tokenMetadata['position'] = [i, i + 2] - tokenMetadata['index'] = tokens.length - tokens.push(new lunr.Token(str.slice(i, i + 2), tokenMetadata)) - } - - return tokens -} - -const queryNgramSeparator = (query) => { - const str = query.toString().trim().toLowerCase() - const tokens = [] - - for (let i = 0; i <= str.length - 2; i++) { - tokens.push(str.slice(i, i + 2)) - } - - return tokens.join(' ') -} - -const index = '../post/index.json' - -const initLunr = () => { - let request = new XMLHttpRequest() - request.open('GET', index, true) - request.onload = function () { - if (this.status >= 200 && this.status < 400) { - pagesIndex = JSON.parse(this.response) - lunrIndex = lunr(function () { - this.tokenizer = bigramTokeniser - this.pipeline.reset() - this.ref('ref') - this.field('title', { boost: 10 }) - this.field('body') - this.metadataWhitelist = ['position'] - pagesIndex.forEach((page) => { - this.add(page) - }, this) - }) - } else { - console.error('Error getting Hugo index flie') - } - } - request.onerror = function () { - console.error('connection error') - } - request.send() -} - -/** - * Searching pages using lunr - * @param {String} query Query string for searching - * @return {Object[]} Array of search results - */ -const search = (query) => { - lunrResult = lunrIndex.search(queryNgramSeparator(query)) - return lunrResult.map((result) => { - return pagesIndex.filter((page) => { - return page.ref === result.ref - })[0] - }) -} - -const initUI = () => { +const init = () => { const searchBox = document.querySelector('#searchBox') if (searchBox === null) { return } + + let index = new FlexSearch.Document({ + tokenize: 'forward', + document: { + field: ['title', 'body'], + store: ['title', 'href', 'body'] + }, + }) + + fetch(searchDataURL) + .then(pages => pages.json()) + .then(pages => { + for(let i = 0; i < pages.length; i++){ + index.add(i, pages[i]); + } + }) + searchBox.addEventListener('keyup', function (event) { let searchResultsArea = document.querySelector('#searchResults') let query = event.currentTarget.value @@ -90,20 +34,19 @@ const initUI = () => { } // Display search results - renderResults(search(query)) + renderResults(index.search(query, 10, { enrich: true })); searchResultsArea.style.display = 'block' }) } /** * Rendering search results - * @param {Object[]} results Array of search results + * @param {Object[]} results Array of search results ( fields[] => { field, result[] => { document }} ) */ const renderResults = (results) => { const searchResults = document.querySelector('#searchResults') const query = document.querySelector('#searchBox').value const BODY_LENGTH = 100 - const MAX_PAGES = 10 // Clear search result while (searchResults.firstChild) @@ -117,32 +60,37 @@ const renderResults = (results) => { searchResults.append(resultPage) return } + console.log(results) let instance = new Mark(document.querySelector('#searchResults')) - // Only show the ten first results - results.slice(0, MAX_PAGES).forEach((result, idx) => { - let resultPage = document.createElement('div') - resultPage.className = 'searchResultPage' - let metadata = lunrResult[idx].matchData.metadata - let matchPosition = metadata[Object.keys(metadata)[0]].body.position[0][0] - let bodyStartPosition = - matchPosition - BODY_LENGTH / 2 > 0 ? matchPosition - BODY_LENGTH / 2 : 0 - - let resultTitle = document.createElement('a') - resultTitle.className = 'searchResultTitle' - resultTitle.href = result.ref - resultTitle.innerHTML = result.title - resultPage.append(resultTitle) - - let resultBody = document.createElement('div') - resultBody.className = 'searchResultBody' - resultBody.innerHTML = result.body.substr(bodyStartPosition, BODY_LENGTH) - resultPage.append(resultBody) - searchResults.append(resultPage) - - instance.mark(query) + results.forEach((result) => { + let isBody = result.field === "body" + + // TODO: create array remove duplicate docs + result.result.forEach((result) => { + console.log(result) + let resultPage = document.createElement('div') + resultPage.className = 'searchResultPage' + + let resultTitle = document.createElement('a') + resultTitle.className = 'searchResultTitle' + resultTitle.href = result.doc.href + resultTitle.innerHTML = result.doc.title + resultPage.append(resultTitle) + + if (isBody) { + let resultBody = document.createElement('div') + resultBody.className = 'searchResultBody' + let matchPos = result.doc.body.indexOf(query) + let bodyStartPos = matchPos - BODY_LENGTH / 2 > 0 ? matchPos - BODY_LENGTH / 2 : 0 + resultBody.innerHTML = result.doc.body.substr(bodyStartPos, BODY_LENGTH) + resultPage.append(resultBody) + } + searchResults.append(resultPage) + + instance.mark(query) + }) }) } -initLunr() -initUI() +init(); diff --git a/layouts/_default/list.json b/assets/list.json index 618a67a..9126d52 100644 --- a/layouts/_default/list.json +++ b/assets/list.json @@ -1,15 +1,15 @@ [ - {{ range $index, $page := .Pages }} - {{ if eq .Type "post" }} + {{ $pages := where .Site.Pages "Kind" "in" (slice "page" "post") }} + {{ $pages = where $pages "Content" "not in" (slice nil "") }} + {{ range $index, $page := $pages }} {{ if ne $index 0 }},{{ end }} { - "id": $index, - "ref": "{{ $page.Permalink }}", + "id": {{ $index }}, + "href": "{{ $page.Permalink }}", "title": {{ $page.Title | jsonify }}, "section": "{{ $page.Section }}", "date" : {{ $page.Date.Format "2006.01.02" | jsonify }}, "body": {{ $page.Plain | jsonify }} } - {{ end }} {{ end }} ] diff --git a/layouts/partials/head.html b/layouts/partials/head.html index 7507d7e..9b15997 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -66,10 +66,15 @@ <script defer crossorigin="anonymous" src="{{ $instantpage.RelPermalink }}" integrity="{{ $instantpage.Data.Integrity }}"></script> {{- if (eq .Layout `search`) -}} + {{ $flexsearch := resources.Get "js/flexsearch.bundle.js" }} + <script defer crossorigin="anonymous" src="{{ $flexsearch.RelPermalink }}" integrity="{{ $flexsearch.Data.Integrity }}"></script> + {{ $lunr := resources.Get "js/lunr.min.js" }} {{ $mark := resources.Get "js/mark.min.js" }} {{ $basesearch := resources.Get "js/search.js" }} - {{ $search := (slice $lunr $mark $basesearch) | resources.Concat "js/search.js" | minify }} + + {{ $searchJSFile := printf "js/%s.search.js" .Language.Lang }} + {{ $search := (slice $lunr $mark $basesearch) | resources.Concat "js/search.js" | resources.ExecuteAsTemplate $searchJSFile . | resources.Fingerprint }} <script defer crossorigin="anonymous" src="{{ $search.RelPermalink }}" integrity="{{ $search.Data.Integrity }}"></script> {{- end -}} |