Merge pull request 'feat/glossaire-entry-relations-rendering' (#293) from feat/glossaire-entry-relations-rendering into main
Reviewed-on: #293
This commit was merged in pull request #293.
This commit is contained in:
32
src/components/GlossaryRelationCards.astro
Normal file
32
src/components/GlossaryRelationCards.astro
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
---
|
||||||
|
import type { GlossaryRelationBlock } from "../lib/glossary";
|
||||||
|
import { hrefOfGlossaryEntry } from "../lib/glossary";
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
relationBlocks: GlossaryRelationBlock[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const { relationBlocks = [] } = Astro.props;
|
||||||
|
---
|
||||||
|
|
||||||
|
{relationBlocks.length > 0 && (
|
||||||
|
<section class="glossary-relations" aria-label="Relations conceptuelles">
|
||||||
|
<h2>Relations conceptuelles</h2>
|
||||||
|
|
||||||
|
<div class="glossary-relations-grid">
|
||||||
|
{relationBlocks.map((block) => (
|
||||||
|
<section class={`glossary-relations-card ${block.className}`}>
|
||||||
|
<h3>{block.title}</h3>
|
||||||
|
<ul>
|
||||||
|
{block.items.map((item) => (
|
||||||
|
<li>
|
||||||
|
<a href={hrefOfGlossaryEntry(item)}>{item.data.term}</a>
|
||||||
|
<span> — {item.data.definitionShort}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
@@ -128,17 +128,35 @@ export function uniqueGlossaryEntries(
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function resolveGlossaryEntries(
|
export function resolveGlossaryEntriesInSourceOrder(
|
||||||
slugs: string[] = [],
|
slugs: string[] = [],
|
||||||
allEntries: GlossaryEntry[] = [],
|
allEntries: GlossaryEntry[] = [],
|
||||||
): GlossaryEntry[] {
|
): GlossaryEntry[] {
|
||||||
const bySlug = buildGlossaryBySlug(allEntries);
|
const bySlug = buildGlossaryBySlug(allEntries);
|
||||||
|
const seen = new Set<string>();
|
||||||
|
const resolved: GlossaryEntry[] = [];
|
||||||
|
|
||||||
const resolved = slugs
|
for (const rawSlug of slugs) {
|
||||||
.map((slug) => bySlug.get(normalizeGlossarySlug(slug)))
|
const slug = normalizeGlossarySlug(rawSlug);
|
||||||
.filter(Boolean) as GlossaryEntry[];
|
if (!slug || seen.has(slug)) continue;
|
||||||
|
|
||||||
return sortGlossaryEntries(uniqueGlossaryEntries(resolved));
|
const entry = bySlug.get(slug);
|
||||||
|
if (!entry) continue;
|
||||||
|
|
||||||
|
seen.add(slug);
|
||||||
|
resolved.push(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolved;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resolveGlossaryEntries(
|
||||||
|
slugs: string[] = [],
|
||||||
|
allEntries: GlossaryEntry[] = [],
|
||||||
|
): GlossaryEntry[] {
|
||||||
|
return sortGlossaryEntries(
|
||||||
|
resolveGlossaryEntriesInSourceOrder(slugs, allEntries),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function rawFamilyOf(
|
export function rawFamilyOf(
|
||||||
@@ -268,31 +286,44 @@ export type GlossaryRelationBlock = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function getRelationBlocks(
|
export function getRelationBlocks(
|
||||||
entry: GlossaryEntry,
|
entry: GlossaryEntry,
|
||||||
allEntries: GlossaryEntry[] = [],
|
allEntries: GlossaryEntry[] = [],
|
||||||
): GlossaryRelationBlock[] {
|
): GlossaryRelationBlock[] {
|
||||||
const relatedEntries = resolveGlossaryEntries(entry.data.related ?? [], allEntries);
|
const currentSlug = slugOfGlossaryEntry(entry);
|
||||||
const opposedEntries = resolveGlossaryEntries(entry.data.opposedTo ?? [], allEntries);
|
|
||||||
const seeAlsoEntries = resolveGlossaryEntries(entry.data.seeAlso ?? [], allEntries);
|
const relatedEntries = resolveGlossaryEntriesInSourceOrder(
|
||||||
|
entry.data.related ?? [],
|
||||||
return [
|
allEntries,
|
||||||
{
|
).filter((item) => slugOfGlossaryEntry(item) !== currentSlug);
|
||||||
title: "Concepts liés",
|
|
||||||
items: relatedEntries,
|
const opposedEntries = resolveGlossaryEntriesInSourceOrder(
|
||||||
className: "is-related",
|
entry.data.opposedTo ?? [],
|
||||||
},
|
allEntries,
|
||||||
{
|
).filter((item) => slugOfGlossaryEntry(item) !== currentSlug);
|
||||||
title: "En tension avec",
|
|
||||||
items: opposedEntries,
|
const seeAlsoEntries = resolveGlossaryEntriesInSourceOrder(
|
||||||
className: "is-opposed",
|
entry.data.seeAlso ?? [],
|
||||||
},
|
allEntries,
|
||||||
{
|
).filter((item) => slugOfGlossaryEntry(item) !== currentSlug);
|
||||||
title: "Voir aussi",
|
|
||||||
items: seeAlsoEntries,
|
return [
|
||||||
className: "is-see-also",
|
{
|
||||||
},
|
title: "Concepts liés",
|
||||||
].filter((block) => block.items.length > 0);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
export function getRelationSections(
|
export function getRelationSections(
|
||||||
entry: GlossaryEntry,
|
entry: GlossaryEntry,
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
---
|
---
|
||||||
import GlossaryLayout from "../../layouts/GlossaryLayout.astro";
|
import GlossaryLayout from "../../layouts/GlossaryLayout.astro";
|
||||||
import GlossaryAside from "../../components/GlossaryAside.astro";
|
import GlossaryAside from "../../components/GlossaryAside.astro";
|
||||||
|
import GlossaryRelationCards from "../../components/GlossaryRelationCards.astro";
|
||||||
import { getCollection, render } from "astro:content";
|
import { getCollection, render } from "astro:content";
|
||||||
import {
|
import {
|
||||||
getDisplayDomain,
|
getDisplayDomain,
|
||||||
getDisplayFamily,
|
getDisplayFamily,
|
||||||
getDisplayLevel,
|
getDisplayLevel,
|
||||||
getRelationBlocks,
|
getRelationBlocks,
|
||||||
hrefOfGlossaryEntry,
|
|
||||||
normalizeGlossarySlug,
|
normalizeGlossarySlug,
|
||||||
} from "../../lib/glossary";
|
} from "../../lib/glossary";
|
||||||
|
|
||||||
@@ -133,27 +133,7 @@ const hasScholarlyMeta =
|
|||||||
<Content />
|
<Content />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{relationBlocks.length > 0 && (
|
<GlossaryRelationCards relationBlocks={relationBlocks} />
|
||||||
<section class="glossary-relations" aria-label="Relations conceptuelles">
|
|
||||||
<h2>Relations conceptuelles</h2>
|
|
||||||
|
|
||||||
<div class="glossary-relations-grid">
|
|
||||||
{relationBlocks.map((block) => (
|
|
||||||
<section class={`glossary-relations-card ${block.className}`}>
|
|
||||||
<h3>{block.title}</h3>
|
|
||||||
<ul>
|
|
||||||
{block.items.map((item) => (
|
|
||||||
<li>
|
|
||||||
<a href={hrefOfGlossaryEntry(item)}>{item.data.term}</a>
|
|
||||||
<span> — {item.data.definitionShort}</span>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</section>
|
|
||||||
))}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
)}
|
|
||||||
</GlossaryLayout>
|
</GlossaryLayout>
|
||||||
|
|
||||||
<script is:inline>
|
<script is:inline>
|
||||||
|
|||||||
Reference in New Issue
Block a user