Logo de Cecil Cecil
Sur cette page

Ajouter une recherche côté client

Un site statique n’a pas de recherche côté serveur, mais Cecil peut générer un index JSON de vos pages au moment du build. Quelques lignes de JavaScript suffisent ensuite pour l’interroger dans le navigateur.

Créer la page d’index

Créez une page dont le seul format de sortie est json, avec un layout dédié :

pages/search.md

---
title: Search index
layout: search
output: json
excluded: true
---

excluded: true exclut cette page technique des pages de liste et du sitemap.

Écrire le template JSON

Selon les règles de recherche, Cecil génère cette page avec layouts/search.json.twig. Construisez un tableau des pages affichables (showable), puis encodez-le :

{%- set index = [] -%}
{%- for p in site.pages.showable|filter(p => p.type == 'page') -%}
  {%- set index = index|merge([{
    title: p.title,
    url: url(p),
    description: p.description|default(''),
    content: p.content|striptags|excerpt(300)
  }]) -%}
{%- endfor -%}
{{ index|json_encode(constant('JSON_UNESCAPED_UNICODE') b-or constant('JSON_UNESCAPED_SLASHES'))|raw }}

Après php cecil.phar build, l’index est disponible à l’adresse /search.json.

Rechercher avec Fuse.js

Ajoutez un champ de recherche dans un template et chargez Fuse.js depuis un CDN pour interroger l’index :

<input type="search" id="search" placeholder="Rechercher…">
<ul id="results"></ul>

<script type="module">
  import Fuse from 'https://cdn.jsdelivr.net/npm/fuse.js@7/dist/fuse.mjs';

  const index = await fetch('{{ url('search', {format: 'json'}) }}').then(r => r.json());
  const fuse = new Fuse(index, { keys: ['title', 'description', 'content'], threshold: 0.3 });
  const results = document.getElementById('results');

  document.getElementById('search').addEventListener('input', (e) => {
    results.replaceChildren(...fuse.search(e.target.value, { limit: 10 }).map(({ item }) => {
      const li = document.createElement('li');
      const a = document.createElement('a');
      a.href = item.url;
      a.textContent = item.title;
      li.append(a);
      return li;
    }));
  });
</script>

Alternative : Pagefind

Pagefind indexe directement les fichiers HTML générés : aucun template JSON n’est nécessaire. Lancez-le après le build, sur le répertoire de sortie (_site par défaut) :

php cecil.phar build
npx pagefind --site _site

Chargez ensuite son interface dans un template :

<link href="/pagefind/pagefind-ui.css" rel="stylesheet">
<script src="/pagefind/pagefind-ui.js"></script>
<div id="search"></div>
<script>
  window.addEventListener('DOMContentLoaded', () => new PagefindUI({ element: '#search' }));
</script>