Aller au contenu principal

Créer un plugin de recherche/remplacement pour Docusaurus

Remplacez automatiquement « markdown » par « Markdown » dans tout votre contenu pour garder des articles cohérents.

· 3 minutes de lecture
Voir la source
Christophe
Amoureux de Markdown, WSL et Docker ~ Curieux insatiable.
Cet article existe aussi en anglais — lire la version originale.

Traduction automatique

Cette traduction a été produite par une IA. Elle peut contenir des contresens ou des maladresses, en particulier sur les termes techniques. En cas de doute, consultez l'article de référence en anglais — c'est lui qui fait foi.

Cet article a plus d'un an, mais il a été relu le 30 juillet 2026 — son contenu est toujours exact.

Cet article fait partie de la série Créer des composants Docusaurus :

Créer un plugin de recherche/remplacement pour Docusaurus

⚡
TL;DR

Cet article montre comment créer un plugin remark personnalisé pour Docusaurus afin de rechercher et remplacer automatiquement certains termes sur tout votre site. L'objectif : garantir une terminologie cohérente (par exemple transformer « VSCode » en « VSCode ») sans modifier les fichiers Markdown d'origine. Vous allez apprendre à écrire un plugin qui parcourt l'arbre syntaxique abstrait (AST) du contenu pour n'appliquer les remplacements qu'au texte brut, en évitant les blocs de code et les URL. Le guide montre aussi comment configurer le plugin dans votre docusaurus.config.js.

Pour le fun (parce que cette solution n'est peut-être pas infaillible), j'ai demandé à une IA de générer un plugin capable de scanner mes 200 articles et de remplacer des motifs comme docusaurus par Docusaurus, github par GitHub, vscode par VSCode, afin de normaliser tout mon contenu.

Ça peut être risqué, car si le mot vscode apparaît :

  • dans une URL (comme https://github.com/microsoft/vscode/),
  • dans un nom (comme vstirbu.vscode-mermaid-preview),
  • dans un nom de fichier (comme vscode.png),
  • dans un snippet de code (à l'intérieur d'un bloc ```...``` ou `.`),
  • ...

nous ne voulons évidemment pas faire le remplacement.

Mais si le mot se trouve dans un simple paragraphe, c'est une autre histoire : là, oui, on veut le remplacement.

Donc, après quelques prompts avec l'IA, un plugin a été généré et il fonctionne jusqu'ici.

Redémarrez votre serveur Docusaurus une fois le plugin en place et, au démarrage suivant, si des changements doivent être faits, vous les verrez dans votre console :

🔎 Replacing 'vscode' with 'VSCode' in file: /opt/[...]/index.md
Sentence: One of the best features in vscode is the

🔎 Replacing 'vscode' with 'VSCode' in file: /opt/[...]/index.md
Sentence: With vscode, it's ultra-simple: multiple cursors.

Silencieux, sûr, et ça ne touche jamais vos fichiers Markdown d'origine : uniquement le HTML généré. Construisons-le.

Le plugin​

Créez le fichier plugins/remark-replace-terms/index.cjs et regardez le tableau replacements. Ajoutez-y les vôtres.

Il s'agit d'un plugin remark : il parcourt l'AST Markdown avant la production du HTML. J'ai utilisé le même mécanisme pour remplacer chaque balise <img> par mon propre composant et pour injecter des tooltips générés par IA dans les snippets de code.

La syntaxe est [/\b(1)\b/g, "(2)"], où (1) est le mot à rechercher (écrit exactement tel quel, sensible à la casse) et (2) la valeur de remplacement.

/**
* @fileoverview
* Docusaurus Remark Plugin – remark-replace-words
*
* This plugin is designed for use with Docusaurus to automatically correct the casing
* of common technology terms in Markdown content. It scans Markdown AST text nodes and
* replaces lowercase variants like "github" or "markdown" with their properly capitalized
* forms ("GitHub", "Markdown", etc.).
*
* ⚠️ Replacements are skipped inside links, images, and code blocks to avoid unintended changes.
* 🧠 Compound words (e.g., "vscode-docker") are also preserved.
*
* Intended for use in the Docusaurus Markdown pipeline via `remarkPlugins`.
*
* @module remarkReplaceWords
* @returns {Function} A remark transformer function
*/
const { visit } = require("unist-util-visit");
// Define replacements as [searchRegex, replacement]
const replacements = [
[/\bdocusaurus\b/g, "Docusaurus"],
[/\bgithub\b/g, "GitHub"],
[/\bmarkdown\b/g, "Markdown"],
[/\bvscode\b/g, "VSCode"],
];
// A heading's explicit anchor id — `## Docusaurus {#docusaurus}` — is still ordinary text when
// this plugin runs: it sits in `beforeDefaultRemarkPlugins`, so Docusaurus parses that `{#id}`
// suffix only afterwards. Capitalizing a term inside it rewrites the id itself (`{#Docusaurus}`),
// and every link built from the English slug then points at an anchor the page no longer has —
// which is exactly how the `fr` build died on "broken anchors". Ids are never prose: skip them.
// Translated articles carry one on every heading (see scripts/lib/translate-anchors.mjs).
const EXPLICIT_HEADING_ID = /\{#[^}\s]*\}/g;
/** Applies `transform` to `value`, leaving every explicit `{#heading-id}` untouched. */
function outsideHeadingIds(value, transform) {
const parts = [];
let cursor = 0;
for (const match of value.matchAll(EXPLICIT_HEADING_ID)) {
parts.push(transform(value.slice(cursor, match.index)), match[0]);
cursor = match.index + match[0].length;
}
parts.push(transform(value.slice(cursor)));
return parts.join("");
}
function remarkReplaceWords() {
return (tree) => {
visit(tree, "text", (node, index, parent) => {
if (typeof node.value !== "string") return;
// Skip inside certain node types (URLs, code, etc.)
const forbiddenParents = ["link", "image", "inlineCode", "code"];
if (parent && forbiddenParents.includes(parent.type)) {
return;
}
node.value = outsideHeadingIds(node.value, (text) => {
let result = text;
for (const [regex, replacement] of replacements) {
result = result.replace(regex, (match, offset, fullString) => {
const before = fullString[offset - 1] || "";
const after = fullString[offset + match.length] || "";
// Skip compound words like "vscode-docker", "foo.markdown"
if (["-", ".", "/"].includes(before) || ["-", ".", "/"].includes(after)) {
return match;
}
return replacement;
});
}
return result;
});
});
};
}
module.exports = remarkReplaceWords;

This is a Docusaurus plugin that fixes the capitalization of common tech terms like 'github' → 'GitHub' and 'markdown' → 'Markdown' in Markdown documents. It carefully avoids making changes inside links, code blocks, images, heading IDs, and compound words connected by hyphens or dots, so it doesn't break links or code.

Ajouter le plugin dans votre configuration​

L'étape suivante consiste à enregistrer votre plugin dans la configuration de Docusaurus. Pour ce faire, éditez votre fichier docusaurus.config.js et ajoutez les lignes surlignées comme illustré ci-dessous.

// highlight-next-line
import remarkReplaceWords from "./plugins/remark-replace-terms";
const config = {
// [ ... ]
presets: [
[
'classic',
({
// [ ... ]
blog: {
beforeDefaultRemarkPlugins: [
// [ ... ]
// highlight-next-line
remarkReplaceWords
],
},
// [ ... ]
}),
],
],
};
export default config;

Ce fichier configure un preset Docusaurus 'classic' en important un plugin Remark personnalisé et en l'ajoutant à la liste des plugins Remark qui s'exécutent avant les plugins par défaut pour le traitement des articles de blog. Le plugin remarkReplaceWords va transformer le contenu markdown avant que les plugins standard de Remark ne le traitent.

Cela fait, redémarrez votre serveur Docusaurus et vous obtiendrez la même sortie console que celle montrée au début de cet article.

Attention

La recherche/remplacement ne sera pas effectuée sur vos fichiers Markdown d'origine, mais uniquement lors du rendu HTML. Lancer ce plugin est donc sans danger ; vos fichiers ne seront pas impactés du tout.


Cet article fait partie de la série Créer des composants Docusaurus :
🦋 Rejoignez la conversation sur BlueskyUn compte Bluesky gratuit est nécessaire pour aimer, repartager ou commenter. Ce bloc interroge l'API publique de Bluesky directement depuis votre navigateur (sans cookie, sans connexion) — votre adresse IP parvient donc aux serveurs de Bluesky dès que cette section se charge.

Chargement des commentaires…

Cet article vous a-t-il été utile ?
Avez-vous suivi les étapes de cet article ?