A Lyra search implementation for Hugo.
We use Hugo's fast file generation to generate our index in JSON format.
In the layouts
folder, create an index.json
file.
[ {{- $i := 0 -}}
{{- range where .Site.RegularPages "Section" "ne" "" -}}
{{- if not .Params.noSearch -}}
{{- if gt $i 0 }},{{ end -}}
{"title":{{ .Title | jsonify }},"body": {{ .Plain | htmlUnescape | chomp | jsonify }},"url":"{{ .RelPermalink }}","meta":{"date": "{{ .Date.Format "2006-01-02" }}","synonyms": {{ .Params.Synonyms | jsonify }},"specialites": {{ .Params.specialites | jsonify }},"annees": "{{ .Params.annees }}","sources": {{ .Params.sources | jsonify }},"tags": [{{- $t := 0 }}{{- range .Param "tags" -}}{{ if gt $t 0 }},{{ end }}{{ . | jsonify }}{{ $t = add $t 1 }}{{ end -}}]}}
{{- $i = add $i 1 -}}
{{- end -}}
{{- end -}} ]
Now tell Hugo to generate the index.json
from this template.
In you config.toml
, add a [outputs]
section (or edit it like this) to generate index.html
(homepage) and our index.json
(search index).
[outputs]
home = ["HTML", "JSON"]
Import Lyra before your body
closing tag.
<script type="module" async crossorigin>
import {create, search, insertBatch} from 'https://cdn.jsdelivr.net/npm/@lyrasearch/lyra@0.4.12/dist/index.js';
import {stemmer} from 'https://cdn.jsdelivr.net/npm/@lyrasearch/lyra@0.4.12/dist/stemmer/fr.min.js';
</script>
Now add this code within the module:
const indexResponse = await fetch('/index.json')
const index = await indexResponse.json();
const searchEngine = await create({
schema: {
title: 'string',
content: 'string',
url: 'string'
},
defaultLanguage: 'french',
components: {
tokenizer: {
stemmingFn: stemmer,
}
}
});
await insertBatch(searchEngine, index);
const searchInput = document.getElementById('search-input');
['change', 'cut', 'input', 'paste', 'search'].forEach(type => searchInput.addEventListener(type, query));
async function query(event) {
const searchResponse = await search(searchEngine, {term: event.target.value, properties: '*'});
document.getElementById('search-results').innerHTML = searchResponse
.hits
.map(i => `<a href="${i.document.url}" class="list-group-item list-group-item-action">${i.document.title}</a>`)
.join('')
}
Enjoy.
Thank you @mickaeltr !