Un moteur de recherche interne pour votre site Hugo

5 septembre 2018 · 4 min de lecture

Nous avons vu comment créer un site web avec HUGO, voyons maintenant comment ajouter un moteur de recherche interne.

L’objectif est de le réaliser :

  • sans installer des dépendances Javascript sur votre ordinateur
  • sans indexer des “mots vides” (ou stop words), c’est-à-dire les mots inutiles comme “et, ou, nous, comment…”
  • indexer des mots uniques pour chaque page (sans doublons)
  • vos prochains articles seront référencés automatiquement sans aucune maintenance.

Fonctionnement

Le principe est le suivant :

  • HUGO va créer à la racine du site un fichier JSON qui servira de base de données.
  • Quand un visiteur consulte une page du site, ce fichier JSON est téléchargé dans son navigateur.
  • Lorsqu’une recherche est effectuée dans la zone de texte, du code Javascript va chercher les mots dans les variables content et lister les URL correspondantes.
hugo-search-engine

Installation

Création du fichier JSON

Tapez la commande suivante :

hugo new search.md

Le fichier content/search.md est créé. Modifiez-le comme suit :

---
title: "Search"
date: 2018-09-04T15:32:54+02:00
layout: "search"
outputs: ["json"]
noindex: true
---

Les nouvelles variables natives utilisées ici sont layout pour indiquer le template à utiliser et outputs pour générer un JSON. noindex est une variable personnalisée permettant de ne pas indexer ce fichier JSON dans le moteur de recherche.

Créez le template correspondant layouts/_default/search.json :

{{ $stopwords := (slice "avant" "ce" "cette" "comme" "il") }}
{ "results": [
{{ $pages := (where .Site.RegularPages ".Params.noindex" "ne" true) }}
{{ $lastindex := (sub (len $pages) 1) }}
{{ range $index, $page := $pages }}
    {{ $scratch := newScratch }}
    {{- $content := (.Content | plainify | lower) -}}
    {{- $content := (replaceRE "\"" "" $content) -}}
    {{- $content := (replaceRE "“" "" $content) -}}
    {{- $content := (replaceRE "”" "" $content) -}}
    {{- $content := (replaceRE "\n+" " " $content) -}}
    {{- $content := (replaceRE "\r+" " " $content) -}}
    {{- $content := (replaceRE "\t+" " " $content) -}}
    {{- $content := (replaceRE " +" " " $content) }}
    {{- $content := (trim $content " ") }}
    {{- $words := (split $content " ") -}}
    {
    "url": "{{ .Permalink }}",
    "title": "{{ .Title }}",
    "content": "{{- range $words -}}
    {{- $word := (.) -}}
    {{- if and (not (in ($scratch.Get "seenwords") $word)) (ne (substr $word 0 1) $word) (not (in $stopwords $word)) -}}
        {{- print $word " " -}}
    {{- end -}}
    {{ $scratch.Add "seenwords" (slice $word) }}
    {{- end -}}"
    }
    {{- $scratch.Delete "seenwords" -}}
    {{- if ne $lastindex $index }},{{ end }}
{{ end }}
]}

Ce template consulte toutes les pages du site HUGO (RegularPages) qui ne sont pas à exclure de la recherche (variable noindex vue précédemment). Le contenu est découpé par mots. Un mot est ajouté s’il ne l’est pas déjà et s’il ne figure pas dans la liste des stopwords. Donc si vous souhaitez exclure des mots de l’indexation qui vous paraissent sans intérêt, ajoutez-les à la liste en haut de page.

Si vous tapez la commande hugo, le fichier suivant est créé : http://localhost:1313/search/index.json :

{ "results": [
    {
    "url": "http://example.com/article3/",
    "title": "Article3",
    "content": "word3a word3b word3c"
    },
    {
    "url": "http://example.com/article2/",
    "title": "Article2",
    "content": "word2a word2b word2c"
    },
    {
    "url": "http://example.com/article1/",
    "title": "Article1",
    "content": "word1a word1b word1c"
    }
]}

Indexation des pages

Par défaut elles sont toutes ajoutées automatiquement à cet index. Pour les pages que vous ne souhaitez pas référencer, ajoutez en entête :

noindex: true

Template HTML

Dans votre template principal, ajoutez le style de la zone de recherche entre les balises <head></head> :

<style>
    .search {
        position: relative;
        display: inline-block;
        }
    .search-results {
        display: none;
        background-color: #fff;
        position: absolute;
        min-width: 100px;
        box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
        z-index: 1;
        }
    .search-results a {
        color: black;
        padding: 12px 16px;
        text-decoration: none;
        display: block;
        }
    .search-results a:hover {background-color: #ddd;}
</style>

Insérez la zone de saisie où vous le souhaitez, entre les balises <body></body> :

Pour le moteur de recherche, nous utiliserons les librairies VueJS et axios via CDN. La première simplifie l’écriture du Javascript et la seconde permettra de télécharger le contenu de l’index généré en JSON.

Juste avant la balise </body>, insérez le code suivant. Les explications sont insérées en commentaires :

Et voilà !

Références

Inspiré des exemples référencés sur la page https://gohugo.io/tools/search/.

PARTAGER

A LIRE EGALEMENT