feat(glossaire): extend taxonomy and align Astro 6 content config
All checks were successful
SMOKE / smoke (push) Successful in 6s
CI / build-and-anchors (push) Successful in 44s
CI / build-and-anchors (pull_request) Successful in 41s

This commit is contained in:
2026-03-12 12:04:46 +01:00
parent 37cb836246
commit bb9f55a3b5
21 changed files with 504 additions and 51 deletions

View File

@@ -3,15 +3,21 @@ import { getCollection } from "astro:content";
export const prerender = true;
const slugOf = (entry: { id: string }) => String(entry.id).replace(/\.(md|mdx)$/i, "");
export const GET: APIRoute = async () => {
const entries = await getCollection("glossaire");
const index = entries.map((e) => ({
slug: e.slug,
term: e.data.term,
aliases: e.data.aliases ?? [],
definitionShort: e.data.definitionShort,
href: `/glossaire/${e.slug}/`,
}));
const index = entries.map((e) => {
const slug = slugOf(e);
return {
slug,
term: e.data.term,
aliases: e.data.aliases ?? [],
definitionShort: e.data.definitionShort,
href: `/glossaire/${slug}/`,
};
});
return new Response(JSON.stringify(index), {
headers: {
@@ -19,4 +25,4 @@ export const GET: APIRoute = async () => {
"Cache-Control": "public, max-age=3600",
},
});
};
};

View File

@@ -3,19 +3,323 @@ import SiteLayout from "../../layouts/SiteLayout.astro";
import { getCollection } from "astro:content";
const entries = await getCollection("glossaire");
entries.sort((a, b) => a.data.term.localeCompare(b.data.term, "fr"));
const slugOf = (entry) => String(entry.id).replace(/\.(md|mdx)$/i, "");
const hrefOf = (entry) => `/glossaire/${slugOf(entry)}/`;
const collator = new Intl.Collator("fr", { sensitivity: "base", numeric: true });
const sorted = [...entries].sort((a, b) => collator.compare(a.data.term, b.data.term));
function groupByInitial(list) {
const map = new Map();
for (const entry of list) {
const letter = (entry.data.term || "").trim().charAt(0).toUpperCase() || "#";
if (!map.has(letter)) map.set(letter, []);
map.get(letter).push(entry);
}
return [...map.entries()].sort((a, b) => collator.compare(a[0], b[0]));
}
const groupedAlpha = groupByInitial(sorted);
const byPredicate = (fn) => sorted.filter(fn);
const fondamentaux = byPredicate(
(e) => e.data.kind === "concept" && e.data.level === "fondamental"
);
const intermediaires = byPredicate(
(e) => e.data.kind === "concept" && e.data.level === "intermediaire"
);
const avances = byPredicate(
(e) => e.data.kind === "concept" && e.data.level === "avance"
);
const diagnostics = byPredicate((e) => e.data.kind === "diagnostic");
const topologies = byPredicate((e) => e.data.kind === "topologie");
const verbes = byPredicate((e) => e.data.kind === "verbe");
const paradigmes = byPredicate((e) => e.data.kind === "paradigme");
---
<SiteLayout title="Glossaire archicratique">
<h1>Glossaire archicratique</h1>
<ul>
{entries.map((e) => (
<li>
<a href={`/glossaire/${String(e.id).replace(/\.(md|mdx)$/i, "")}/`}>
{e.data.term}
</a>{" "}
— <em>{e.data.definitionShort}</em>
</li>
))}
</ul>
</SiteLayout>
<section class="glossary-home">
<header class="glossary-hero">
<p class="glossary-kicker">Référentiel terminologique</p>
<h1>Glossaire archicratique</h1>
<p class="glossary-intro">
Ce glossaire rassemble les concepts, diagnostics, topologies et verbes
utiles à la lecture du paradigme archicratique. Son organisation repose
sur les métadonnées de chaque entrée afin de maintenir une structure
cohérente, extensible et lisible.
</p>
</header>
<nav class="glossary-toc" aria-label="Sommaire du glossaire">
<a href="#reperes">Repères</a>
<a href="#paradigmes">Paradigmes mobilisés</a>
{paradigmes.length > 0 && (
<section id="paradigmes" class="glossary-section">
<h2>Paradigmes mobilisés</h2>
<p class="glossary-intro">
Ces entrées ne relèvent pas du noyau conceptuel archicratique au sens strict.
Elles désignent les cadres théoriques, paradigmes ou traditions de pensée
avec lesquels larchicratie entre en dialogue, en déplacement ou en différenciation.
</p>
<div class="glossary-cards">
{paradigmes.map((e) => (
<a class="glossary-card" href={hrefOf(e)}>
<strong>{e.data.term}</strong>
<span>{e.data.definitionShort}</span>
</a>
))}
</div>
</section>
)}
<a href="#alphabetique">Index alphabétique</a>
</nav>
<section id="reperes" class="glossary-section">
<h2>Repères</h2>
{fondamentaux.length > 0 && (
<section class="glossary-block">
<h3>Repères fondamentaux</h3>
<div class="glossary-cards">
{fondamentaux.map((e) => (
<a class="glossary-card" href={hrefOf(e)}>
<strong>{e.data.term}</strong>
<span>{e.data.definitionShort}</span>
</a>
))}
</div>
</section>
)}
{intermediaires.length > 0 && (
<section class="glossary-block">
<h3>Concepts intermédiaires</h3>
<div class="glossary-cards">
{intermediaires.map((e) => (
<a class="glossary-card" href={hrefOf(e)}>
<strong>{e.data.term}</strong>
<span>{e.data.definitionShort}</span>
</a>
))}
</div>
</section>
)}
{avances.length > 0 && (
<section class="glossary-block">
<h3>Concepts avancés</h3>
<div class="glossary-cards">
{avances.map((e) => (
<a class="glossary-card" href={hrefOf(e)}>
<strong>{e.data.term}</strong>
<span>{e.data.definitionShort}</span>
</a>
))}
</div>
</section>
)}
{diagnostics.length > 0 && (
<section class="glossary-block">
<h3>Diagnostics</h3>
<div class="glossary-cards">
{diagnostics.map((e) => (
<a class="glossary-card" href={hrefOf(e)}>
<strong>{e.data.term}</strong>
<span>{e.data.definitionShort}</span>
</a>
))}
</div>
</section>
)}
{topologies.length > 0 && (
<section class="glossary-block">
<h3>Topologies</h3>
<div class="glossary-cards">
{topologies.map((e) => (
<a class="glossary-card" href={hrefOf(e)}>
<strong>{e.data.term}</strong>
<span>{e.data.definitionShort}</span>
</a>
))}
</div>
</section>
)}
{verbes.length > 0 && (
<section class="glossary-block">
<h3>Verbes de la scène archicratique</h3>
<div class="glossary-cards">
{verbes.map((e) => (
<a class="glossary-card" href={hrefOf(e)}>
<strong>{e.data.term}</strong>
<span>{e.data.definitionShort}</span>
</a>
))}
</div>
</section>
)}
</section>
<section id="alphabetique" class="glossary-section">
<h2>Index alphabétique</h2>
<nav class="glossary-alpha-nav" aria-label="Lettres du glossaire">
{groupedAlpha.map(([letter]) => (
<a href={`#letter-${letter}`}>{letter}</a>
))}
</nav>
<div class="glossary-alpha-groups">
{groupedAlpha.map(([letter, items]) => (
<section class="glossary-letter-group" id={`letter-${letter}`}>
<h3>{letter}</h3>
<ul class="glossary-list">
{items.map((e) => (
<li>
<a href={hrefOf(e)}>{e.data.term}</a>
<span> — {e.data.definitionShort}</span>
</li>
))}
</ul>
</section>
))}
</div>
</section>
</section>
</SiteLayout>
<style>
.glossary-home{
padding: 8px 0 32px;
}
.glossary-hero{
margin-bottom: 24px;
}
.glossary-kicker{
font-size: 12px;
letter-spacing: .08em;
text-transform: uppercase;
opacity: .72;
margin-bottom: 8px;
}
.glossary-intro{
max-width: 72ch;
opacity: .92;
}
.glossary-toc{
display: flex;
flex-wrap: wrap;
gap: 10px;
margin: 18px 0 30px;
}
.glossary-toc a{
border: 1px solid rgba(127,127,127,0.28);
border-radius: 999px;
padding: 6px 12px;
text-decoration: none;
}
.glossary-section{
margin-top: 34px;
}
.glossary-block{
margin-top: 18px;
}
.glossary-cards{
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: 12px;
margin-top: 12px;
}
.glossary-card{
display: flex;
flex-direction: column;
gap: 8px;
padding: 14px 16px;
border: 1px solid rgba(127,127,127,0.22);
border-radius: 16px;
background: rgba(127,127,127,0.05);
text-decoration: none;
transition: transform 120ms ease, background 120ms ease;
}
.glossary-card:hover{
transform: translateY(-1px);
background: rgba(127,127,127,0.08);
text-decoration: none;
}
.glossary-card strong{
font-size: 15px;
}
.glossary-card span{
font-size: 14px;
line-height: 1.45;
opacity: .92;
}
.glossary-alpha-nav{
display: flex;
flex-wrap: wrap;
gap: 8px;
margin: 12px 0 20px;
}
.glossary-alpha-nav a{
min-width: 32px;
text-align: center;
border: 1px solid rgba(127,127,127,0.22);
border-radius: 10px;
padding: 5px 8px;
text-decoration: none;
}
.glossary-alpha-groups{
display: flex;
flex-direction: column;
gap: 24px;
}
.glossary-letter-group h3{
margin-bottom: 10px;
}
.glossary-list{
margin: 0;
padding-left: 18px;
}
.glossary-list li{
margin-bottom: 8px;
}
@media (prefers-color-scheme: dark){
.glossary-card{
background: rgba(255,255,255,0.04);
}
.glossary-card:hover{
background: rgba(255,255,255,0.07);
}
}
</style>