feat(glossary): add step 21 smart navigation
This commit is contained in:
99
src/lib/glossary-navigation-defaults.ts
Normal file
99
src/lib/glossary-navigation-defaults.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
export type GlossaryDefaultNavigation = {
|
||||
understand?: string[];
|
||||
deepen?: string[];
|
||||
compare?: string[];
|
||||
apply?: string[];
|
||||
};
|
||||
|
||||
export const GLOSSARY_NAV_DEFAULTS: Record<string, GlossaryDefaultNavigation> = {
|
||||
"concept-fondamental": {
|
||||
understand: ["archicratie", "arcalite", "cratialite", "archicration", "co-viabilite", "tension"],
|
||||
deepen: ["scene-depreuve", "regime-de-co-viabilite", "meta-regime-archicratique"],
|
||||
compare: ["autarchicratie", "domination-legale-rationnelle", "decisionnisme-souverain"],
|
||||
apply: ["audit-archicratique", "cartographie-des-scenes-manquantes", "journal-de-justification"],
|
||||
},
|
||||
|
||||
scene: {
|
||||
understand: ["scene-depreuve", "scene-darchicration", "archicration"],
|
||||
deepen: ["scene-manquante", "scene-empechee", "institution-invisible", "monde-instituable"],
|
||||
compare: ["autarchicratie", "obliteration-archicratique", "hypotopie", "atopie"],
|
||||
apply: ["cartographie-des-scenes-manquantes", "budget-scenique", "tribunal-de-lalgorithme"],
|
||||
},
|
||||
|
||||
dynamique: {
|
||||
understand: ["archicratisation", "desarchicration", "co-viabilisation"],
|
||||
deepen: ["archeogenese", "obliteration-archicratique", "regime-de-co-viabilite"],
|
||||
compare: ["desarchicratisation", "autarchicratie", "archicration-obliteree"],
|
||||
apply: ["archidiagnostic", "audit-archicratique", "cartographie-des-scenes-manquantes"],
|
||||
},
|
||||
|
||||
pathologie: {
|
||||
understand: ["autarchicratie", "autarchicration", "archicration-obliteree"],
|
||||
deepen: ["hyperarcalite", "hypercratialite", "obliteration-archicratique", "desarchicration"],
|
||||
compare: ["archicration", "scene-depreuve", "monde-instituable", "co-viabilite"],
|
||||
apply: ["archidiagnostic", "cartographie-des-scenes-manquantes", "coupe-circuit-citoyen"],
|
||||
},
|
||||
|
||||
topologie: {
|
||||
understand: ["meta-regime", "regime-de-co-viabilite", "synchrotopie"],
|
||||
deepen: ["hypotopie", "hypertopie", "atopie", "archicrations-differentielles-et-formes-hybrides"],
|
||||
compare: ["scene-depreuve", "institution-invisible", "monde-instituable"],
|
||||
apply: ["cartographie-des-scenes-manquantes", "archidiagnostic", "audit-archicratique"],
|
||||
},
|
||||
|
||||
"meta-regime": {
|
||||
understand: ["meta-regime-archicratique", "archeogenese", "regime-de-co-viabilite"],
|
||||
deepen: ["archicrations-proto-symboliques", "archicrations-scripturo-normatives", "archicrations-techno-logistiques"],
|
||||
compare: ["archicrations-marchandes", "archicrations-guerrieres", "archicrations-epistemiques"],
|
||||
apply: ["archicrations-differentielles-et-formes-hybrides", "archidiagnostic"],
|
||||
},
|
||||
|
||||
paradigme: {
|
||||
understand: ["archicratie", "co-viabilite", "tension"],
|
||||
deepen: ["configuration-et-interdependance", "pensee-complexe", "theorie-de-la-justification"],
|
||||
compare: ["decisionnisme-souverain", "domination-legale-rationnelle", "agencement-machinique", "democratie-deliberative"],
|
||||
apply: ["audit-archicratique", "cartographie-des-scenes-manquantes"],
|
||||
},
|
||||
|
||||
doctrine: {
|
||||
understand: ["decisionnisme-souverain", "contractualisme-hobbesien", "volonte-generale"],
|
||||
deepen: ["exception-souveraine", "droit-naturel-et-propriete", "domination-legale-rationnelle"],
|
||||
compare: ["democratie-deliberative", "dissensus-politique", "gouvernance-des-communs", "lieu-vide-du-pouvoir"],
|
||||
apply: ["scene-depreuve", "archicration", "audit-archicratique"],
|
||||
},
|
||||
|
||||
"dispositif-ia": {
|
||||
understand: ["audit-archicratique", "cartographie-des-scenes-manquantes", "journal-de-justification"],
|
||||
deepen: ["tribunal-de-lalgorithme", "visa-daffectation", "budget-scenique"],
|
||||
compare: ["gouvernementalite-algorithmique", "preemption-algorithmique", "institution-invisible"],
|
||||
apply: ["droit-au-differe-contradictoire", "coupe-circuit-citoyen", "tribunal-de-lalgorithme"],
|
||||
},
|
||||
|
||||
"tension-irreductible": {
|
||||
understand: ["tension", "co-viabilite", "archicration"],
|
||||
deepen: ["coexistence-ontologique-et-necessite-regulatrice", "formes-de-vie-et-cadres-dhabitabilite", "souverainetes-territoriales-et-interdependances-globales"],
|
||||
compare: ["regulation-technique-et-legitimation-democratique", "memoire-symbolique-et-instantaneite-computationnelle", "travail-vivant-et-abstraction-de-la-valeur"],
|
||||
apply: ["scene-depreuve", "audit-archicratique", "cartographie-des-scenes-manquantes"],
|
||||
},
|
||||
|
||||
figure: {
|
||||
understand: ["figures-archicratiques", "archicrate", "institution-invisible"],
|
||||
deepen: ["hyperarcalite", "hypercratialite", "autarchicration"],
|
||||
compare: ["scene-darchicration", "monde-instituable", "autarchicratie"],
|
||||
apply: ["archidiagnostic", "cartographie-des-scenes-manquantes"],
|
||||
},
|
||||
|
||||
qualification: {
|
||||
understand: ["archicratique", "desarchicratique", "archicration"],
|
||||
deepen: ["archicratisation", "desarchicratisation", "scene-darchicration"],
|
||||
compare: ["autarchicratie", "archicration-obliteree", "monde-instituable"],
|
||||
apply: ["archidiagnostic", "audit-archicratique"],
|
||||
},
|
||||
|
||||
epistemologie: {
|
||||
understand: ["archicratistique", "archidiagnostic", "pensee-complexe"],
|
||||
deepen: ["archeogenese", "meta-regime-archicratique", "figures-archicratiques"],
|
||||
compare: ["theorie-de-la-justification", "configuration-et-interdependance", "transduction-et-individuation"],
|
||||
apply: ["audit-archicratique", "cartographie-des-scenes-manquantes", "journal-de-justification"],
|
||||
},
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { CollectionEntry } from "astro:content";
|
||||
import { GLOSSARY_NAV_DEFAULTS } from "./glossary-navigation-defaults";
|
||||
|
||||
export type GlossaryEntry = CollectionEntry<"glossaire">;
|
||||
|
||||
@@ -16,6 +17,32 @@ export type GlossaryRelationBlock = GlossaryRelationSection & {
|
||||
className: string;
|
||||
};
|
||||
|
||||
export type GlossarySmartNavigationPathKey =
|
||||
| "understand"
|
||||
| "deepen"
|
||||
| "compare"
|
||||
| "apply";
|
||||
|
||||
export type GlossarySmartNavigationPath = {
|
||||
key: GlossarySmartNavigationPathKey;
|
||||
label: string;
|
||||
entries: GlossaryEntry[];
|
||||
};
|
||||
|
||||
export type GlossarySmartNavigationFlow = {
|
||||
key: string;
|
||||
label: string;
|
||||
primaryNext?: GlossaryEntry;
|
||||
primaryReason?: string;
|
||||
};
|
||||
|
||||
export type GlossarySmartNavigation = {
|
||||
primaryNext?: GlossaryEntry;
|
||||
primaryReason?: string;
|
||||
paths: GlossarySmartNavigationPath[];
|
||||
flows: GlossarySmartNavigationFlow[];
|
||||
};
|
||||
|
||||
export type GlossaryHomeStats = {
|
||||
totalEntries: number;
|
||||
paradigmesCount: number;
|
||||
@@ -122,6 +149,16 @@ export const FAMILY_SECTION_TITLES: Record<string, string> = {
|
||||
epistemologie: "Outillage épistémologique",
|
||||
};
|
||||
|
||||
export const SMART_NAV_PATH_LABELS: Record<
|
||||
GlossarySmartNavigationPathKey,
|
||||
string
|
||||
> = {
|
||||
understand: "Comprendre",
|
||||
deepen: "Approfondir",
|
||||
compare: "Comparer",
|
||||
apply: "Appliquer",
|
||||
};
|
||||
|
||||
const PREFERRED_PARADIGME_SLUGS = [
|
||||
"gouvernementalite",
|
||||
"gouvernementalite-algorithmique",
|
||||
@@ -202,35 +239,35 @@ export function uniqueGlossaryEntries(
|
||||
}
|
||||
|
||||
export function slugsOfGlossaryEntries(
|
||||
entries: GlossaryEntry[] = [],
|
||||
): Set<string> {
|
||||
const slugs = new Set<string>();
|
||||
|
||||
for (const entry of entries) {
|
||||
const slug = slugOfGlossaryEntry(entry);
|
||||
if (!slug) continue;
|
||||
slugs.add(slug);
|
||||
}
|
||||
|
||||
return slugs;
|
||||
}
|
||||
|
||||
export function excludeGlossaryEntries(
|
||||
entries: GlossaryEntry[] = [],
|
||||
excluded: Iterable<string> = [],
|
||||
): GlossaryEntry[] {
|
||||
const excludedSlugs = new Set(
|
||||
Array.from(excluded)
|
||||
.map((value) => normalizeGlossarySlug(value))
|
||||
.filter(Boolean),
|
||||
);
|
||||
|
||||
return entries.filter((entry) => {
|
||||
const slug = slugOfGlossaryEntry(entry);
|
||||
return Boolean(slug) && !excludedSlugs.has(slug);
|
||||
});
|
||||
entries: GlossaryEntry[] = [],
|
||||
): Set<string> {
|
||||
const slugs = new Set<string>();
|
||||
|
||||
for (const entry of entries) {
|
||||
const slug = slugOfGlossaryEntry(entry);
|
||||
if (!slug) continue;
|
||||
slugs.add(slug);
|
||||
}
|
||||
|
||||
return slugs;
|
||||
}
|
||||
|
||||
export function excludeGlossaryEntries(
|
||||
entries: GlossaryEntry[] = [],
|
||||
excluded: Iterable<string> = [],
|
||||
): GlossaryEntry[] {
|
||||
const excludedSlugs = new Set(
|
||||
Array.from(excluded)
|
||||
.map((value) => normalizeGlossarySlug(value))
|
||||
.filter(Boolean),
|
||||
);
|
||||
|
||||
return entries.filter((entry) => {
|
||||
const slug = slugOfGlossaryEntry(entry);
|
||||
return Boolean(slug) && !excludedSlugs.has(slug);
|
||||
});
|
||||
}
|
||||
|
||||
export function resolveGlossaryEntriesInSourceOrder(
|
||||
slugs: string[] = [],
|
||||
allEntries: GlossaryEntry[] = [],
|
||||
@@ -467,6 +504,96 @@ export function getRelationBlocks(
|
||||
].filter((block) => block.items.length > 0);
|
||||
}
|
||||
|
||||
export function getGlossarySmartNavigation(
|
||||
currentEntry: GlossaryEntry,
|
||||
allEntries: GlossaryEntry[] = [],
|
||||
): GlossarySmartNavigation {
|
||||
const currentSlug = slugOfGlossaryEntry(currentEntry);
|
||||
const rawNavigation = currentEntry.data.navigation;
|
||||
const defaultNavigation = GLOSSARY_NAV_DEFAULTS[familyOf(currentEntry)];
|
||||
|
||||
const navigationSource = rawNavigation ?? {
|
||||
primaryNext: undefined,
|
||||
primaryReason: undefined,
|
||||
paths: defaultNavigation ?? {},
|
||||
flows: {},
|
||||
};
|
||||
|
||||
const primaryNext = resolveGlossaryEntriesInSourceOrder(
|
||||
navigationSource.primaryNext ? [navigationSource.primaryNext] : [],
|
||||
allEntries,
|
||||
).find((entry) => slugOfGlossaryEntry(entry) !== currentSlug);
|
||||
|
||||
const pathKeys: GlossarySmartNavigationPathKey[] = [
|
||||
"understand",
|
||||
"deepen",
|
||||
"compare",
|
||||
"apply",
|
||||
];
|
||||
|
||||
const paths = pathKeys
|
||||
.map((key) => {
|
||||
const entries = resolveGlossaryEntriesInSourceOrder(
|
||||
navigationSource.paths?.[key] ?? [],
|
||||
allEntries,
|
||||
).filter((entry) => slugOfGlossaryEntry(entry) !== currentSlug);
|
||||
|
||||
return {
|
||||
key,
|
||||
label: SMART_NAV_PATH_LABELS[key],
|
||||
entries,
|
||||
};
|
||||
})
|
||||
.filter((path) => path.entries.length > 0);
|
||||
|
||||
const flows = Object.entries(navigationSource.flows ?? {})
|
||||
.map(([key, flow]) => {
|
||||
const primaryNext = resolveGlossaryEntriesInSourceOrder(
|
||||
flow.primaryNext ? [flow.primaryNext] : [],
|
||||
allEntries,
|
||||
).find((entry) => slugOfGlossaryEntry(entry) !== currentSlug);
|
||||
|
||||
return {
|
||||
key,
|
||||
label: flow.label,
|
||||
primaryNext,
|
||||
primaryReason: flow.primaryReason,
|
||||
};
|
||||
})
|
||||
.filter((flow) => flow.primaryNext);
|
||||
|
||||
if (primaryNext || paths.length > 0 || flows.length > 0) {
|
||||
return {
|
||||
primaryNext,
|
||||
primaryReason: navigationSource.primaryReason,
|
||||
paths,
|
||||
flows,
|
||||
};
|
||||
}
|
||||
|
||||
const fallbackEntries = uniqueGlossaryEntries([
|
||||
...resolveGlossaryEntriesInSourceOrder(
|
||||
currentEntry.data.related ?? [],
|
||||
allEntries,
|
||||
),
|
||||
...resolveGlossaryEntriesInSourceOrder(
|
||||
currentEntry.data.seeAlso ?? [],
|
||||
allEntries,
|
||||
),
|
||||
]).filter((entry) => slugOfGlossaryEntry(entry) !== currentSlug);
|
||||
|
||||
const fallbackPrimary = fallbackEntries[0];
|
||||
|
||||
return {
|
||||
primaryNext: fallbackPrimary,
|
||||
primaryReason: fallbackPrimary
|
||||
? "Ce lien prolonge directement les relations conceptuelles de cette fiche."
|
||||
: undefined,
|
||||
paths: [],
|
||||
flows: [],
|
||||
};
|
||||
}
|
||||
|
||||
export function getRelationSections(
|
||||
entry: GlossaryEntry,
|
||||
allEntries: GlossaryEntry[] = [],
|
||||
|
||||
Reference in New Issue
Block a user