diff options
-rw-r--r-- | assets/js/search.js | 65 | ||||
-rw-r--r-- | layouts/404.html | 12 | ||||
-rw-r--r-- | layouts/_default/search.html | 45 | ||||
-rw-r--r-- | layouts/_default/search.json | 13 |
4 files changed, 131 insertions, 4 deletions
diff --git a/assets/js/search.js b/assets/js/search.js new file mode 100644 index 0000000..2dd397a --- /dev/null +++ b/assets/js/search.js @@ -0,0 +1,65 @@ +// Options for fuse.js +let fuseOptions = { + includeMatches: true, + includeScore: true, + ignoreLocation: true, + minMatchCharLength: 3, + keys: [ + { name: "title", weight: 0.8 }, + { name: "contents", weight: 0.4 }, + { name: "tags", weight: 0.5 }, + { name: "categories", weight: 0.5 }, + ], +} + +function getUrlParameter(name) { + const urlParams = new URLSearchParams(location.search) + return urlParams.get(name) +} + +let searchQuery = getUrlParameter("q") +if (searchQuery) { + document.getElementById("search-query").value = searchQuery + executeSearch(searchQuery) +} else { + document.getElementById("search-results").innerHTML = "" +} + +function executeSearch(searchQuery) { + // Look for "index.json" in the same directory where this script is called. + fetch("index.json") + .then((response) => response.json()) + .then(function (data) { + let fuse = new Fuse(data, fuseOptions) + let result = fuse.search(searchQuery) + // console.log("Results: ", result) + if (result.length > 0) { + populateResults(result) + } else { + document.getElementById("search-results").innerHTML = + "<p class=\"bg-washed-red pa3 dark-red f4 fw6 tc br2 b--light-red ba\">No matches found</p>" + } + }) +} + +function populateResults(result) { + result.forEach(function (value, key) { + // Lifted from https://stackoverflow.com/posts/3700369/revisions + var elem = document.createElement("textarea") + elem.innerHTML = value.item.contents + var decoded = elem.value + + // Pull template from hugo template definition + let frag = document + .getElementById("search-result-template") + .content.cloneNode(true) + // Replace values + frag.querySelector(".search_summary").setAttribute("id", "summary-" + key) + frag.querySelector(".search_link") + .setAttribute("href", value.item.permalink) + frag.querySelector(".search_title").textContent = value.item.title + frag.querySelector(".search_snippet").textContent = decoded + frag.querySelector(".search_time").textContent = value.item.date + document.getElementById("search-results").appendChild(frag) + }) +} diff --git a/layouts/404.html b/layouts/404.html index c375edb..af1122f 100644 --- a/layouts/404.html +++ b/layouts/404.html @@ -5,14 +5,12 @@ <div class="mw7 center ph1 mv4"> <h1 class="f1 tc title baskerville">{{ .Title }}</h1> - <h2 class="lh-title f3 baskerville"> - Perhaps you were looking for one of these? - </h2> + <p class="f4 baskerville">Perhaps you were looking for one of these?</p> {{ $query := where (where (where (where site.RegularPages.ByDate.Reverse "Title" "!=" "") "Kind" "in" (slice "page" "section")) "Params.private" "!=" true) "Permalink" "!=" "" }} {{ $count := len $query }} {{ if gt $count 0 }} - <h2 class="lh-title f2 baskerville">Pages recently edited</h2> + <h3 class="lh-title f3 baskerville">Pages recently edited</h3> <ul class="list ph5"> {{ range first 10 $query }} @@ -32,5 +30,11 @@ {{ end }} </ul> {{ end }} + <a href="/search" class="link color-inherit dim"> + <h3 class="lh-title f3 baskerville"> + <i class="fas fa-magnifying-glass"></i> + Not there? Try using the search page. + </h3> + </a> </div> {{ end }} diff --git a/layouts/_default/search.html b/layouts/_default/search.html new file mode 100644 index 0000000..bcbaad4 --- /dev/null +++ b/layouts/_default/search.html @@ -0,0 +1,45 @@ +{{ define "main" }} + <div class="mw7 center pa1"> + <header> + <h2 class="baskerville f2 lh-title mv3 ph1"> + {{ .Title }} + </h2> + </header> + + <form action="{{ .Permalink }}"> + <input + id="search-query" + name="q" + placeholder="search phrase" + class="near-black pa2 w-100" + /> + </form> + + <div id="search-results" class="mv2"></div> + </div> + + <template id="search-result-template"> + <article class="pv2 bt bb b--black-10 search_summary"> + <a class="link dim near-black search_link" href=""> + <time class="fr f6 lh-copy ph4 search_time"></time> + <h3 class="f3 baskerville mv1 lh-title search_title"></h3> + <div class="f5 lh-copy search_snippet"></div> + </a> + </article> + </template> + <script + src="https://cdnjs.cloudflare.com/ajax/libs/fuse.js/7.0.0/fuse.min.js" + integrity="sha512-GrJ4P9yra6dftp5O0eaKFKS4ch1FYn1xR/VCHQIMJO1LNqcKhjkAkAETHYoE81Ffh3BjCJMWA/AZSYP521jxFA==" + crossorigin="anonymous" + referrerpolicy="no-referrer" + ></script> + + {{ with resources.Get "js/search.js" | resources.Minify | fingerprint }} + <script + src="{{ .RelPermalink }}" + integrity="{{ .Data.Integrity }}" + crossorigin="anonymous" + referrerpolicy="no-referrer" + ></script> + {{ end }} +{{ end }} diff --git a/layouts/_default/search.json b/layouts/_default/search.json new file mode 100644 index 0000000..16912cb --- /dev/null +++ b/layouts/_default/search.json @@ -0,0 +1,13 @@ + +{{ $dateFormat := .Site.Params.dateFormat | default "Jan 2, 2006" }} +{{- $.Scratch.Add "index" slice -}} +{{- range (where .Site.RegularPages "Type" "in" .Site.Params.mainSections) -}} + + {{- $.Scratch.Add "index" (dict "title" .Title + "tags" .Params.tags + "categories" .Params.categories + "contents" (.Summary | plainify) + "date" (.Date.Format $dateFormat) + "permalink" .Permalink) -}} +{{- end -}} +{{- $.Scratch.Get "index" | jsonify -}} |