diff options
author | thingsym <thingsym@gmail.com> | 2020-03-31 08:56:16 +0300 |
---|---|---|
committer | thingsym <thingsym@gmail.com> | 2020-03-31 08:56:16 +0300 |
commit | 39a448ee9f37a26c0faa9af1d552b6a844b52d6a (patch) | |
tree | ad408e9e92ec39c9e4f0f27bc41f032fd6d58033 | |
parent | 008a24e8488edaba0d9f023708492decb75e7813 (diff) |
feat: add search function and shortcode powered by Algolia
-rwxr-xr-x | exampleSite/config.toml | 31 | ||||
-rw-r--r-- | layouts/_default/list.algolia.json | 48 | ||||
-rw-r--r-- | layouts/partials/search.html | 57 | ||||
-rw-r--r-- | layouts/shortcodes/search.html | 4 | ||||
-rw-r--r-- | src/scss/_component.scss | 41 |
5 files changed, 181 insertions, 0 deletions
diff --git a/exampleSite/config.toml b/exampleSite/config.toml index 471d3a5..29c07a1 100755 --- a/exampleSite/config.toml +++ b/exampleSite/config.toml @@ -59,6 +59,13 @@ enableMissingTranslationPlaceholders = false "posts", ] + # Algolia site search section + # See https://www.algolia.com/doc/ + algolia_search_enable = true + algolia_indexName = "hugo-demo-techdoc" + algolia_appId = "7W4SAN4PLK" + algolia_apiKey = "cbf12a63ff72d9c5dc0c10c195cf9128" # Search-Only API Key + # Global menu section # See https://gohugo.io/content-management/menus/ [menu] @@ -82,3 +89,27 @@ enableMissingTranslationPlaceholders = false startLevel = 2 endLevel = 4 ordered = false + +# Algolia Search configure section +[outputFormats.Algolia] + baseName = "algolia" + isPlainText = true + mediaType = "application/json" + notAlternative = true + +[params.algolia] + vars = [ + "title", + "summary", + "content", + "date", + "publishdate", + "description", + "permalink", + "keywords", + "lastmod", + ] + params = [ + "tags", + "categories", + ] diff --git a/layouts/_default/list.algolia.json b/layouts/_default/list.algolia.json new file mode 100644 index 0000000..af966ec --- /dev/null +++ b/layouts/_default/list.algolia.json @@ -0,0 +1,48 @@ +{{/* Generates a valid Algolia search index */}} +{{- $section := $.Site.GetPage "section" .Section }} +{{- $validVars := $.Param "algolia.vars" | default slice -}} +{{- $validParams := $.Param "algolia.params" | default slice -}} + +{{- range $i, $page := .Site.AllPages -}} + {{- $dot := . -}} + {{- if or (and ($page.IsDescendant $section) (and (not $page.Draft) (not $page.Params.private))) $section.IsHome -}} + {{ if $page.File }} + {{- .Scratch.SetInMap $page.File.Path "objectID" $page.File.UniqueID -}} + {{ end }} + + {{- .Scratch.SetInMap "temp" "date" $page.Date.UTC.Unix -}} + {{ if ne ( $page.PublishDate.Format "2006-01-02" ) "0001-01-01" }} + {{- .Scratch.SetInMap "temp" "publishdate" $page.PublishDate -}} + {{ end }} + {{ if ne ( $page.Lastmod.Format "2006-01-02" ) "0001-01-01" }} + {{- .Scratch.SetInMap "temp" "lastmod" $page.Lastmod -}} + {{ end }} + {{- .Scratch.SetInMap "temp" "content" ($page.Plain | truncate 2000) -}} + {{- .Scratch.SetInMap "temp" "title" $page.Title -}} + {{- .Scratch.SetInMap "temp" "permalink" $page.Permalink -}} + {{- .Scratch.SetInMap "temp" "description" $page.Description -}} + + {{/* Include valid page vars */}} + {{- range $key, $param := (.Scratch.Get "temp") -}} + {{- if in $validVars $key -}} + {{ if $page.File }} + {{- $dot.Scratch.SetInMap $page.File.Path $key $param -}} + {{- end -}} + {{- end -}} + {{- end -}} + + {{/* Include valid page params */}} + {{- range $key, $param := $page.Params -}} + {{- if in $validParams $key -}} + {{ if $page.File }} + {{- $dot.Scratch.SetInMap $page.File.Path $key $param -}} + {{- end -}} + {{- end -}} + {{- end -}} + {{ if $page.File }} + {{- $.Scratch.SetInMap "index" $page.File.Path (.Scratch.Get $page.File.Path) -}} + {{- end -}} + {{- end -}} +{{- end -}} + +{{- $.Scratch.GetSortedMapValues "index" | jsonify -}} diff --git a/layouts/partials/search.html b/layouts/partials/search.html new file mode 100644 index 0000000..b7d7f3f --- /dev/null +++ b/layouts/partials/search.html @@ -0,0 +1,57 @@ +<script src="https://cdn.jsdelivr.net/npm/algoliasearch@4.0.0/dist/algoliasearch-lite.umd.js" integrity="sha256-MfeKq2Aw9VAkaE9Caes2NOxQf6vUa8Av0JqcUXUGkd0=" crossorigin="anonymous"></script> +<script src="https://cdn.jsdelivr.net/npm/instantsearch.js@4.0.0/dist/instantsearch.production.min.js" integrity="sha256-6S7q0JJs/Kx4kb/fv0oMjS855QTz5Rc2hh9AkIUjUsk=" crossorigin="anonymous"></script> +<script src="https://unpkg.com/dayjs@1.8.21/dayjs.min.js"></script> + +<div id="searchbox"></div> +<div id="stats"></div> +<div id="hits"></div> +<div id="pagination"></div> + +<script> +var search = instantsearch({ + indexName: '{{ .Site.Params.algolia_indexName }}', + searchClient: algoliasearch( + '{{ .Site.Params.algolia_appId }}', + '{{ .Site.Params.algolia_apiKey }}' + ), + routing: true, +}); + +const renderHits = (renderOptions, isFirstRender) => { + const { hits } = renderOptions; + + document.querySelector('#hits').innerHTML = ` + ${hits + .map( + item => + `<div class="ais-Hits-item"><h3><a href="${ item.permalink }">${ item.title }</a></h3><p><span class="lastmod">${ dayjs(item.lastmod).format("YYYY/MM/DD") }</span> - ${ item.description ? item.description : item.content.length > 200 ? item.content.substring( 0, 200 ) + '...' : item.content }</p></div>` + ) + .join('')} + `; +}; + +const customHits = instantsearch.connectors.connectHits( renderHits ); + +search.addWidgets([ + instantsearch.widgets.searchBox({ + container: '#searchbox', + showReset: false, + }), + + instantsearch.widgets.stats({ + container: '#stats', + }), + + customHits({ + container: document.querySelector('#hits'), + }), + + instantsearch.widgets.pagination({ + container: '#pagination', + maxPages: 20, + }) +]); + +search.start(); + +</script> diff --git a/layouts/shortcodes/search.html b/layouts/shortcodes/search.html new file mode 100644 index 0000000..4b3c460 --- /dev/null +++ b/layouts/shortcodes/search.html @@ -0,0 +1,4 @@ +{{- .Inner -}} +{{ if and .Site.Params.algolia_search_enable .Site.Params.algolia_indexName .Site.Params.algolia_appId .Site.Params.algolia_apiKey }} +{{- partial "search.html" . -}} +{{ end }} diff --git a/src/scss/_component.scss b/src/scss/_component.scss index 65597f3..8cafea2 100644 --- a/src/scss/_component.scss +++ b/src/scss/_component.scss @@ -190,3 +190,44 @@ figure > figcaption h4 { } } + +.ais-SearchBox { + .ais-SearchBox-input { + width: 70%; + } + button { + margin-left: .2rem; + padding: .4rem; + } +} +.ais-Stats { + font-size: 80%; + color: #70757a; +} +.ais-Hits-item { + @extend .stack; + + h3 { + font-size: 140%; + font-weight: normal; + } + p { + @extend .stack-unset; + color: #3C4043; + } + .lastmod { + font-size: 90%; + color: #70757a; + } +} + +.ais-Pagination { + margin-top: 1em; +} +.ais-Pagination-list { + @extend ul.no-style; + @include grid($flex-wrap: wrap, $justify-content: center); +} +.ais-Pagination-item { + padding: .6rem; +} |