From 5b5995e2b5deb77e2f41de641b5ed00f606a954b Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 6 Dec 2020 20:50:32 -0300 Subject: [PATCH] search almost done --- .vscode/settings.json | 3 + config.toml | 4 +- content/category/tax-legal-informatie/test.md | 1 + themes/fiscleconsult/layouts/index.json | 10 ++ .../layouts/partials/header.html | 5 +- .../layouts/partials/script.html | 2 + .../layouts/partials/search.html | 17 ++ themes/fiscleconsult/static/js/search.js | 159 ++++++++++++++++++ themes/fiscleconsult/static/js/search2.js | 101 +++++++++++ 9 files changed, 297 insertions(+), 5 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 themes/fiscleconsult/layouts/index.json create mode 100644 themes/fiscleconsult/layouts/partials/search.html create mode 100644 themes/fiscleconsult/static/js/search.js create mode 100644 themes/fiscleconsult/static/js/search2.js diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..cad7657 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "cmake.configureOnOpen": false +} \ No newline at end of file diff --git a/config.toml b/config.toml index c333315..3cae141 100644 --- a/config.toml +++ b/config.toml @@ -22,5 +22,5 @@ theme = "fiscleconsult" [outputs] -home = [ "HTML", "RSS", "SearchIndex" ] - page = ["HTML"] \ No newline at end of file + home = ["HTML", "RSS", "JSON"] + page = ["HTML"] \ No newline at end of file diff --git a/content/category/tax-legal-informatie/test.md b/content/category/tax-legal-informatie/test.md index 3cac0b5..14fb62c 100644 --- a/content/category/tax-legal-informatie/test.md +++ b/content/category/tax-legal-informatie/test.md @@ -3,6 +3,7 @@ title: "Fiscale maatregelen van het Ministerie van Financiën in het kader van C date: 2020-01-26T23:11:13Z summary: "Veel gestelde vragen (FAQ) over de (versoepelde) fiscale maatregelen van het Ministerie van Financiën in het kader van COVID-19" image : https://via.placeholder.com/150 +tags: ["NL"] --- **LOONBELASTING EN INKOMSTENBELASTING** diff --git a/themes/fiscleconsult/layouts/index.json b/themes/fiscleconsult/layouts/index.json new file mode 100644 index 0000000..c95e6ad --- /dev/null +++ b/themes/fiscleconsult/layouts/index.json @@ -0,0 +1,10 @@ +{{- $.Scratch.Add "pagesIndex" slice -}} +{{- range $index, $page := .Site.Pages -}} + + {{- if in (slice "category" ) $page.Type -}} + {{- if gt (len $page.Content) 0 -}} + {{- $pageData := (dict "title" $page.Title "href" $page.Permalink "categories" (delimit $page.Params.tags " ; ") "content" $page.Plain ) -}} {{- $.Scratch.Add "pagesIndex" $pageData -}} +{{- end -}} +{{- end -}} +{{- end -}} +{{- $.Scratch.Get "pagesIndex" | jsonify -}} diff --git a/themes/fiscleconsult/layouts/partials/header.html b/themes/fiscleconsult/layouts/partials/header.html index 52aea40..41415fd 100644 --- a/themes/fiscleconsult/layouts/partials/header.html +++ b/themes/fiscleconsult/layouts/partials/header.html @@ -11,7 +11,6 @@ {{ $text }} {{ end }} - - -
\ No newline at end of file +
+ diff --git a/themes/fiscleconsult/layouts/partials/script.html b/themes/fiscleconsult/layouts/partials/script.html index 1f52570..237d5b5 100644 --- a/themes/fiscleconsult/layouts/partials/script.html +++ b/themes/fiscleconsult/layouts/partials/script.html @@ -18,3 +18,5 @@ + + \ No newline at end of file diff --git a/themes/fiscleconsult/layouts/partials/search.html b/themes/fiscleconsult/layouts/partials/search.html new file mode 100644 index 0000000..d660236 --- /dev/null +++ b/themes/fiscleconsult/layouts/partials/search.html @@ -0,0 +1,17 @@ + + + + \ No newline at end of file diff --git a/themes/fiscleconsult/static/js/search.js b/themes/fiscleconsult/static/js/search.js new file mode 100644 index 0000000..54f537e --- /dev/null +++ b/themes/fiscleconsult/static/js/search.js @@ -0,0 +1,159 @@ +window.addEventListener("DOMContentLoaded", function(event) +{ + var index = null; + var lookup = null; + var queuedTerm = null; + + var form = document.getElementById("search"); + var input = document.getElementById("search-input"); + + form.addEventListener("submit", function(event) + { + event.preventDefault(); + + var term = input.value.trim(); + if (!term) + return; + + startSearch(term); + }, false); + + function startSearch(term) + { + // Start icon animation. + form.setAttribute("data-running", "true"); + + if (index) + { + // Index already present, search directly. + search(term); + } + else if (queuedTerm) + { + // Index is being loaded, replace the term we want to search for. + queuedTerm = term; + } + else + { + // Start loading index, perform the search when done. + queuedTerm = term; + initIndex(); + } + } + + function searchDone() + { + // Stop icon animation. + form.removeAttribute("data-running"); + + queuedTerm = null; + } + + function initIndex() + { + var request = new XMLHttpRequest(); + request.open("GET", "/index.json"); + request.responseType = "json"; + request.addEventListener("load", function(event) + { + lookup = {}; + index = lunr(function() + { + // Uncomment the following line and replace de by the right language + // code to use a lunr language pack. + + // this.use(lunr.nl); + + this.ref("uri"); + + // If you added more searchable fields to the search index, list them here. + this.field("title"); + this.field("content"); + this.field("description"); + this.field("categories"); + + for (var doc of request.response) + { + this.add(doc); + lookup[doc.uri] = doc; + } + }); + + // Search index is ready, perform the search now + search(queuedTerm); + }, false); + request.addEventListener("error", searchDone, false); + request.send(null); + } + + function search(term) + { + var results = index.search(term); + console.log(results); + + // The element where search results should be displayed, adjust as needed. + var target = document.querySelector("#search-result"); + + while (target.firstChild) + target.removeChild(target.firstChild); + + var title = document.createElement("h1"); + title.id = "search-results"; + title.className = "list-title"; + + if (results.length == 0) + title.textContent = `No results found for “${term}”`; + else if (results.length == 1) + title.textContent = `Found one result for “${term}”`; + else + title.textContent = `Found ${results.length} results for “${term}”`; + target.appendChild(title); + document.title = title.textContent; + + var template = document.getElementById("search-result"); + for (var result of results) + { + var doc = lookup[result.ref]; + + // Fill out search result template, adjust as needed. + var element = template.content.cloneNode(true); + element.querySelector(".summary-title-link").href = + element.querySelector(".read-more-link").href = doc.uri; + element.querySelector(".summary-title-link").textContent = doc.title; + element.querySelector(".summary").textContent = truncate(doc.content, 70); + target.appendChild(element); + } + title.scrollIntoView(true); + + searchDone(); + } + + // This matches Hugo's own summary logic: + // https://github.com/gohugoio/hugo/blob/b5f39d23b8/helpers/content.go#L543 + function truncate(text, minWords) + { + var match; + var result = ""; + var wordCount = 0; + var regexp = /(\S+)(\s*)/g; + while (match = regexp.exec(text)) + { + wordCount++; + if (wordCount <= minWords) + result += match[0]; + else + { + var char1 = match[1][match[1].length - 1]; + var char2 = match[2][0]; + if (/[.?!"]/.test(char1) || char2 == "\n") + { + result += match[1]; + break; + } + else + result += match[0]; + } + } + return result; + } +}, false); \ No newline at end of file diff --git a/themes/fiscleconsult/static/js/search2.js b/themes/fiscleconsult/static/js/search2.js new file mode 100644 index 0000000..0461664 --- /dev/null +++ b/themes/fiscleconsult/static/js/search2.js @@ -0,0 +1,101 @@ +let pagesIndex, searchIndex; +const MAX_SUMMARY_LENGTH = 100; +const SENTENCE_BOUNDARY_REGEX = /\b\.\s/gm; +const WORD_REGEX = /\b(\w*)[\W|\s|\b]?/gm; + + +async function initSearchIndex() { + try { + const response = await fetch("/index.json"); + pagesIndex = await response.json(); + searchIndex = lunr(function () { + this.field("title"); + this.field("categories"); + this.field("content"); + this.ref("href"); + pagesIndex.forEach(page => this.add(page)); + }); + } catch (e) { + console.log(e); + } +} +initSearchIndex(); + + +function getSearchResults(query) { + return searchIndex.search(query).flatMap((hit) => { + if (hit.ref == "undefined") return []; + let pageMatch = pagesIndex.filter((page) => page.href === hit.ref)[0]; + pageMatch.score = hit.score; + return [pageMatch]; + }); +} + +function getLunrSearchQuery(query) { + const searchTerms = query.split(" "); + if (searchTerms.length === 1) { + return query; + } + query = ""; + for (const term of searchTerms) { + query += `+${term} `; + } + return query.trim(); +} + +function searchSite(query) { + const originalQuery = query; + query = getLunrSearchQuery(query); + let results = getSearchResults(query); + return results.length + ? results + : query !== originalQuery + ? getSearchResults(originalQuery) + : []; +} +const node = document.getElementById("search-input"); +node.addEventListener('keydown', function (event) { + if (event.code === 'Enter') { + event.preventDefault(); + var q = node.value.trim().toLowerCase(); + var res = searchSite(q); + console.log(res); + renderSearchResults(res, q); + } +}); + +function renderSearchResults(results, term){ + + var target = document.querySelector("#search-result"); + while (target.firstChild) + target.removeChild(target.firstChild); + + var title = document.createElement("h1"); + title.id = "search-results"; + title.className = "list-title"; + + if (results.length == 0) + title.textContent = `No results found for “${term}”`; + else if (results.length == 1) + title.textContent = `Found one result for “${term}”`; + else + title.textContent = `Found ${results.length} results for “${term}”`; + target.appendChild(title); + document.title = title.textContent; + + var template = document.getElementById("search-result"); + for (var result of results) + { + var doc = lookup[result.ref]; + + // Fill out search result template, adjust as needed. + var element = template.content.cloneNode(true); + element.querySelector(".summary-title-link").href = + element.querySelector(".read-more-link").href = doc.uri; + element.querySelector(".summary-title-link").textContent = doc.title; + element.querySelector(".summary").textContent = truncate(doc.content, 70); + target.appendChild(element); + } + title.scrollIntoView(true); + +} \ No newline at end of file