refactor(glossaire): centralize glossary relation helpers
All checks were successful
CI / build-and-anchors (pull_request) Successful in 42s
SMOKE / smoke (push) Successful in 3s
CI / build-and-anchors (push) Successful in 41s

This commit is contained in:
2026-03-25 14:15:39 +01:00
parent a38f585f3d
commit ad06b34a85
5 changed files with 473 additions and 496 deletions

View File

@@ -2,6 +2,14 @@
import GlossaryLayout from "../../layouts/GlossaryLayout.astro";
import GlossaryAside from "../../components/GlossaryAside.astro";
import { getCollection, render } from "astro:content";
import {
getDisplayDomain,
getDisplayFamily,
getDisplayLevel,
getRelationBlocks,
hrefOfGlossaryEntry,
normalizeGlossarySlug,
} from "../../lib/glossary";
export async function getStaticPaths() {
const entries = await getCollection("glossaire");
@@ -9,20 +17,12 @@ export async function getStaticPaths() {
const seen = new Set();
for (const entry of entries) {
const canonicalSlug = String(entry.id || "")
.trim()
.replace(/^\/+|\/+$/g, "")
.replace(/\.(md|mdx)$/i, "")
.toLowerCase();
const canonicalSlug = normalizeGlossarySlug(entry.id);
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(canonicalSlug)) continue;
const addPath = (rawSlug) => {
const requestedSlug = String(rawSlug || "")
.trim()
.replace(/^\/+|\/+$/g, "")
.replace(/\.(md|mdx)$/i, "")
.toLowerCase();
const requestedSlug = normalizeGlossarySlug(rawSlug);
if (!requestedSlug) return;
if (!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(requestedSlug)) return;
@@ -56,108 +56,11 @@ const { Content } = await render(entry);
const isAliasRoute = requestedSlug !== canonicalSlug;
const canonicalHref = `/glossaire/${canonicalSlug}/`;
const slugOf = (item) =>
String(item.id || "")
.trim()
.replace(/^\/+|\/+$/g, "")
.replace(/\.(md|mdx)$/i, "");
const relationBlocks = getRelationBlocks(entry, allEntries);
const hrefOf = (item) => `/glossaire/${slugOf(item)}/`;
const collator = new Intl.Collator("fr", { sensitivity: "base", numeric: true });
const bySlug = new Map(
allEntries.map((item) => [slugOf(item).toLowerCase(), item])
);
function resolveEntries(slugs = []) {
const seen = new Set();
return slugs
.map((slug) => bySlug.get(String(slug || "").trim().toLowerCase()))
.filter(Boolean)
.filter((item) => {
const slug = slugOf(item);
if (seen.has(slug)) return false;
seen.add(slug);
return true;
})
.sort((a, b) => collator.compare(a.data.term, b.data.term));
}
const relatedEntries = resolveEntries(entry.data.related ?? []);
const opposedEntries = resolveEntries(entry.data.opposedTo ?? []);
const seeAlsoEntries = resolveEntries(entry.data.seeAlso ?? []);
const relationBlocks = [
{
title: "Concepts liés",
items: relatedEntries,
className: "is-related",
},
{
title: "En tension avec",
items: opposedEntries,
className: "is-opposed",
},
{
title: "Voir aussi",
items: seeAlsoEntries,
className: "is-see-also",
},
].filter((block) => block.items.length > 0);
const familyLabels = {
"concept-fondamental": "Concept fondamental",
scene: "Scène",
dynamique: "Dynamique",
pathologie: "Pathologie",
topologie: "Topologie",
"meta-regime": "Méta-régime",
paradigme: "Paradigme",
doctrine: "Doctrine",
verbe: "Verbe",
"dispositif-ia": "Dispositif IA",
"tension-irreductible": "Tension irréductible",
};
const kindLabels = {
concept: "Concept",
diagnostic: "Diagnostic",
topologie: "Topologie",
verbe: "Verbe",
paradigme: "Paradigme",
doctrine: "Doctrine",
dispositif: "Dispositif",
figure: "Figure",
qualification: "Qualification",
epistemologie: "Épistémologie",
};
const domainLabels = {
transversal: "Transversal",
theorie: "Théorie",
"cas-ia": "Cas IA",
};
const levelLabels = {
fondamental: "Fondamental",
intermediaire: "Intermédiaire",
avance: "Avancé",
};
const familyKey = entry.data.family ?? "";
const displayFamily =
familyLabels[familyKey] ??
kindLabels[entry.data.kind] ??
"Fiche";
const displayDomain = entry.data.domain
? (domainLabels[entry.data.domain] ?? entry.data.domain)
: "";
const displayLevel = entry.data.level
? (levelLabels[entry.data.level] ?? entry.data.level)
: "";
const displayFamily = getDisplayFamily(entry);
const displayDomain = getDisplayDomain(entry);
const displayLevel = getDisplayLevel(entry);
const hasScholarlyMeta =
(entry.data.mobilizedAuthors?.length ?? 0) > 0 ||
@@ -241,7 +144,7 @@ const hasScholarlyMeta =
<ul>
{block.items.map((item) => (
<li>
<a href={hrefOf(item)}>{item.data.term}</a>
<a href={hrefOfGlossaryEntry(item)}>{item.data.term}</a>
<span> — {item.data.definitionShort}</span>
</li>
))}