aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOscar Najera <hi@oscarnajera.com>2023-11-09 17:49:27 +0100
committerOscar Najera <hi@oscarnajera.com>2023-11-09 17:49:27 +0100
commit4a826ff2748eafdbf63dd0547706ed7dc7ed3d76 (patch)
tree17b3f45d8b750d7fbd1de718e87fdcbfa44e7e5a
parent76b72515b6d8078268077bd9d96db493fb7bd6f8 (diff)
downloadhugo-minimalist-theme-4a826ff2748eafdbf63dd0547706ed7dc7ed3d76.tar.gz
hugo-minimalist-theme-4a826ff2748eafdbf63dd0547706ed7dc7ed3d76.tar.bz2
hugo-minimalist-theme-4a826ff2748eafdbf63dd0547706ed7dc7ed3d76.zip
Search page
-rw-r--r--assets/js/search.js65
-rw-r--r--layouts/404.html12
-rw-r--r--layouts/_default/search.html45
-rw-r--r--layouts/_default/search.json13
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 -}}