@glossarist/concept-browser 0.7.101 → 0.7.102
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/index.mjs +14 -251
- package/cli/index.ts +289 -0
- package/package.json +3 -2
- package/src/__tests__/__fixtures__/concepts.ts +3 -3
- package/src/__tests__/composables/use-concept-edges-v2.test.ts +1 -0
- package/src/__tests__/designation-relationship.test.ts +2 -2
- package/src/__tests__/perf/serialization-perf.test.ts +1 -0
- package/src/__tests__/use-rdf-document.test.ts +1 -0
- package/src/adapters/bibliography-adapter.ts +1 -1
- package/src/adapters/model-bridge.ts +15 -15
- package/src/adapters/non-verbal/figure-bridge.ts +2 -2
- package/src/adapters/non-verbal/formula-bridge.ts +2 -2
- package/src/adapters/non-verbal/table-bridge.ts +2 -2
- package/src/components/CitationDisplay.vue +1 -1
- package/src/components/ConceptDetail.vue +2 -2
- package/src/components/ConceptDiffModal.vue +2 -2
- package/src/components/ConceptDiffView.vue +1 -1
- package/src/components/DesignationList.vue +4 -4
- package/src/components/NavIcon.vue +1 -0
- package/src/components/figure/FigureDisplay.vue +5 -5
- package/src/components/formula/FormulaDisplay.vue +4 -4
- package/src/components/table/TableDisplay.vue +3 -3
- package/src/components/use-rdf-document.ts +16 -7
- package/src/composables/use-concept-content.ts +3 -3
- package/src/composables/use-concept-diff.ts +2 -2
- package/src/composables/use-concept-edges.ts +3 -3
- package/src/config/page-types.ts +1 -1
- package/src/i18n/locales/eng.yml +12 -0
- package/src/i18n/locales/fra.yml +12 -0
- package/src/layouts/Default.astro +32 -2
- package/src/utils/content-renderer.ts +1 -1
- package/src/utils/partitive-multiplicity.ts +3 -2
- package/src/views/ConceptView.vue +3 -3
- package/src/views/learn/LearnRelationshipsView.vue +63 -0
- package/tailwind.config.js +3 -3
- package/tsconfig.json +1 -1
- package/src/adapters/model-bridge/bridges.ts +0 -159
- package/src/adapters/model-bridge/concept.ts +0 -97
- package/src/adapters/model-bridge/entity-refs.ts +0 -49
- package/src/adapters/model-bridge/hyperedge.ts +0 -103
- package/src/adapters/model-bridge/index.ts +0 -46
- package/src/adapters/model-bridge/mappers.ts +0 -277
- package/src/adapters/model-bridge/partitive.ts +0 -79
- package/src/adapters/non-verbal/glossarist-augment.d.ts +0 -339
- /package/src/adapters/{model-bridge/jsonld-types.ts → jsonld-types.ts} +0 -0
|
@@ -61,7 +61,7 @@ import type {
|
|
|
61
61
|
JsonLdPartitiveMember,
|
|
62
62
|
JsonLdPartitiveRelation,
|
|
63
63
|
JsonLdConcept,
|
|
64
|
-
} from './
|
|
64
|
+
} from './jsonld-types';
|
|
65
65
|
|
|
66
66
|
// ── Bridges for fields not yet in glossarist-js ────────────────────────────
|
|
67
67
|
// Remove each bridge when glossarist-js publishes native support.
|
|
@@ -173,7 +173,7 @@ function attachBridges(concept: Concept, localizations: Record<string, unknown>)
|
|
|
173
173
|
* instances, since RelatedConcept.fromJSON only reads type/content/ref.
|
|
174
174
|
*/
|
|
175
175
|
function attachRelatedBridges(
|
|
176
|
-
modelRelated:
|
|
176
|
+
modelRelated: ReadonlyArray<{ type?: string | null; content?: Record<string, string> | string | null; ref?: any; related?: ReadonlyArray<any> }>,
|
|
177
177
|
rawRelated: unknown[],
|
|
178
178
|
): void {
|
|
179
179
|
for (const rawRel of rawRelated) {
|
|
@@ -241,7 +241,7 @@ function mapDesignationFromJsonLd(d: JsonLdDesignation): Record<string, unknown>
|
|
|
241
241
|
|
|
242
242
|
const pronunciation = d[GL.PRONUNCIATION];
|
|
243
243
|
if (pronunciation?.length) {
|
|
244
|
-
result.pronunciation = pronunciation.map(p => ({
|
|
244
|
+
result.pronunciation = pronunciation.map((p: any) => ({
|
|
245
245
|
content: p[GL.CONTENT] ?? null,
|
|
246
246
|
language: p[GL.LANGUAGE] ?? null,
|
|
247
247
|
script: p[GL.SCRIPT] ?? null,
|
|
@@ -257,7 +257,7 @@ function mapDesignationFromJsonLd(d: JsonLdDesignation): Record<string, unknown>
|
|
|
257
257
|
|
|
258
258
|
const related = d[GL.RELATED];
|
|
259
259
|
if (related?.length) {
|
|
260
|
-
result.related = related.map(r => {
|
|
260
|
+
result.related = related.map((r: any) => {
|
|
261
261
|
const relType = r[GL.RELATIONSHIP_TYPE] ?? 'references';
|
|
262
262
|
if (DESIGNATION_REL_TYPES.has(relType) && r[GL.TARGET]) {
|
|
263
263
|
return { type: relType, target: r[GL.TARGET] };
|
|
@@ -272,7 +272,7 @@ function mapDesignationFromJsonLd(d: JsonLdDesignation): Record<string, unknown>
|
|
|
272
272
|
}
|
|
273
273
|
const grammarInfo = d[GL.GRAMMAR_INFO];
|
|
274
274
|
if (grammarInfo?.length) {
|
|
275
|
-
result.grammar_info = grammarInfo.map(gi => ({
|
|
275
|
+
result.grammar_info = grammarInfo.map((gi: any) => ({
|
|
276
276
|
gender: gi[GL.GENDER] ?? null,
|
|
277
277
|
number: gi[GL.NUMBER] ?? null,
|
|
278
278
|
part_of_speech: gi[GL.PART_OF_SPEECH] ?? null,
|
|
@@ -354,7 +354,7 @@ function mapSourceFromJsonLd(s: JsonLdSource): Record<string, unknown> {
|
|
|
354
354
|
|
|
355
355
|
const sf = s[GL.SOURCED_FROM] ?? s[GL.SOURCED_FROM_ALT];
|
|
356
356
|
if (sf?.length) {
|
|
357
|
-
result.sourced_from = sf.map(item => mapOriginFromJsonLd(item));
|
|
357
|
+
result.sourced_from = sf.map((item: any) => mapOriginFromJsonLd(item));
|
|
358
358
|
}
|
|
359
359
|
|
|
360
360
|
return result;
|
|
@@ -445,7 +445,7 @@ function mapLocalizedFromJsonLd(lc: JsonLdLocalizedConcept): Record<string, unkn
|
|
|
445
445
|
|
|
446
446
|
const dates = lc[GL.DATES];
|
|
447
447
|
if (dates?.length) {
|
|
448
|
-
data.dates = dates.map(d => ({
|
|
448
|
+
data.dates = dates.map((d: any) => ({
|
|
449
449
|
date: d[GL.DATE] ?? null,
|
|
450
450
|
type: d[GL.DATE_TYPE] ?? null,
|
|
451
451
|
}));
|
|
@@ -471,7 +471,7 @@ function mapPartitiveRelationFromJsonLd(r: JsonLdPartitiveRelation): Record<stri
|
|
|
471
471
|
if (!comprehensive) return null;
|
|
472
472
|
|
|
473
473
|
const partitives = (r[GL.HAS_PARTITIVE] ?? [])
|
|
474
|
-
.map((m): Record<string, unknown> | null => {
|
|
474
|
+
.map((m: any): Record<string, unknown> | null => {
|
|
475
475
|
const ref = m[GL.REF] ? mapRefFromJsonLd(m[GL.REF]) : null;
|
|
476
476
|
if (!ref) return null;
|
|
477
477
|
const out: Record<string, unknown> = { ref };
|
|
@@ -494,7 +494,7 @@ function mapPartitiveRelationFromJsonLd(r: JsonLdPartitiveRelation): Record<stri
|
|
|
494
494
|
if (m[GL.IS_DELIMITING] === true) out.is_delimiting = true;
|
|
495
495
|
return out;
|
|
496
496
|
})
|
|
497
|
-
.filter((m): m is Record<string, unknown> => m !== null);
|
|
497
|
+
.filter((m: any): m is Record<string, unknown> => m !== null);
|
|
498
498
|
|
|
499
499
|
// ISO 704 requires ≥2 partitives. Skip malformed relations rather
|
|
500
500
|
// than letting the constructor throw and break the whole concept.
|
|
@@ -529,7 +529,7 @@ function mapGenericRelationFromJsonLd(r: JsonLdPartitiveRelation): Record<string
|
|
|
529
529
|
if (!comprehensive) return null;
|
|
530
530
|
|
|
531
531
|
const members = (r[GL.HAS_GENERIC] ?? [])
|
|
532
|
-
.map((m): Record<string, unknown> | null => {
|
|
532
|
+
.map((m: any): Record<string, unknown> | null => {
|
|
533
533
|
const ref = m[GL.REF] ? mapRefFromJsonLd(m[GL.REF]) : null;
|
|
534
534
|
if (!ref) return null;
|
|
535
535
|
const out: Record<string, unknown> = { ref };
|
|
@@ -552,7 +552,7 @@ function mapGenericRelationFromJsonLd(r: JsonLdPartitiveRelation): Record<string
|
|
|
552
552
|
}
|
|
553
553
|
return out;
|
|
554
554
|
})
|
|
555
|
-
.filter((m): m is Record<string, unknown> => m !== null);
|
|
555
|
+
.filter((m: any): m is Record<string, unknown> => m !== null);
|
|
556
556
|
|
|
557
557
|
if (members.length < 2) return null;
|
|
558
558
|
|
|
@@ -589,7 +589,7 @@ function splitMultiplicity(m: string): { presence: 'required' | 'optional'; coun
|
|
|
589
589
|
|
|
590
590
|
function conceptFromJsonLd(doc: JsonLdConcept): Concept {
|
|
591
591
|
const id = String(doc[GL.IDENTIFIER] ?? doc['@id']?.split('/').pop() ?? '');
|
|
592
|
-
const localizations: Record<string, unknown
|
|
592
|
+
const localizations: Record<string, Record<string, unknown>> = {};
|
|
593
593
|
|
|
594
594
|
const rawLc = doc[GL.LOCALIZED_CONCEPT] ?? {};
|
|
595
595
|
for (const [lang, lc] of Object.entries(rawLc)) {
|
|
@@ -601,10 +601,10 @@ function conceptFromJsonLd(doc: JsonLdConcept): Concept {
|
|
|
601
601
|
const related = (doc[GL.RELATED] ?? []).map(mapRelatedFromJsonLd);
|
|
602
602
|
const partitiveRelations = (doc[GL.PARTITIVE_RELATIONS] ?? [])
|
|
603
603
|
.map(mapPartitiveRelationFromJsonLd)
|
|
604
|
-
.filter((r): r is Record<string, unknown> => r !== null);
|
|
604
|
+
.filter((r: any): r is Record<string, unknown> => r !== null);
|
|
605
605
|
const genericRelations = (doc[GL.GENERIC_RELATIONS] ?? [])
|
|
606
606
|
.map(mapGenericRelationFromJsonLd)
|
|
607
|
-
.filter((r): r is Record<string, unknown> => r !== null);
|
|
607
|
+
.filter((r: any): r is Record<string, unknown> => r !== null);
|
|
608
608
|
const tagsArr = doc[GL.TAGS];
|
|
609
609
|
const tags = Array.isArray(tagsArr) ? [...tagsArr] : [];
|
|
610
610
|
|
|
@@ -612,7 +612,7 @@ function conceptFromJsonLd(doc: JsonLdConcept): Concept {
|
|
|
612
612
|
id,
|
|
613
613
|
term: doc[GL.TERM] ?? null,
|
|
614
614
|
uri: doc['@id'] ?? null,
|
|
615
|
-
localizations,
|
|
615
|
+
localizations: localizations as Record<string, any>,
|
|
616
616
|
related,
|
|
617
617
|
partitive_relations: partitiveRelations,
|
|
618
618
|
generic_relations: genericRelations,
|
|
@@ -48,7 +48,7 @@ function imageFromJsonLd(raw: Record<string, unknown>): FigureImage | null {
|
|
|
48
48
|
...(typeof width === 'number' && { width }),
|
|
49
49
|
...(typeof height === 'number' && { height }),
|
|
50
50
|
...(typeof scale === 'number' && { scale }),
|
|
51
|
-
});
|
|
51
|
+
} as any);
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
function imagesFromJsonLd(raw: unknown): FigureImage[] {
|
|
@@ -96,5 +96,5 @@ export function figureFromJsonLd(doc: Record<string, unknown>): Figure | null {
|
|
|
96
96
|
...(description && { description }),
|
|
97
97
|
...(subfigures && { subfigures }),
|
|
98
98
|
...(sources.length && { sources }),
|
|
99
|
-
});
|
|
99
|
+
} as any);
|
|
100
100
|
}
|
|
@@ -40,11 +40,11 @@ export function formulaFromJsonLd(doc: Record<string, unknown>): Formula | null
|
|
|
40
40
|
|
|
41
41
|
return new Formula({
|
|
42
42
|
id,
|
|
43
|
-
expression,
|
|
43
|
+
expression: expression as any,
|
|
44
44
|
notation,
|
|
45
45
|
...(identifier && { identifier }),
|
|
46
46
|
...(caption && { caption }),
|
|
47
47
|
...(description && { description }),
|
|
48
48
|
...(sources.length && { sources }),
|
|
49
|
-
});
|
|
49
|
+
} as any);
|
|
50
50
|
}
|
|
@@ -90,11 +90,11 @@ export function tableFromJsonLd(doc: Record<string, unknown>): Table | null {
|
|
|
90
90
|
|
|
91
91
|
return new Table({
|
|
92
92
|
id,
|
|
93
|
-
content: content as
|
|
93
|
+
content: content as any,
|
|
94
94
|
...(identifier && { identifier }),
|
|
95
95
|
...(caption && { caption }),
|
|
96
96
|
...(description && { description }),
|
|
97
97
|
...(format && { format }),
|
|
98
98
|
...(sources.length && { sources }),
|
|
99
|
-
});
|
|
99
|
+
} as any);
|
|
100
100
|
}
|
|
@@ -107,7 +107,7 @@ async function loadPreview() {
|
|
|
107
107
|
const def = lc?.definitions?.[0]?.content || concept.definition('eng');
|
|
108
108
|
const term = lc?.terms?.[0]?.designation || concept.primaryDesignation('eng');
|
|
109
109
|
preview.value = {
|
|
110
|
-
designation: term || entry?.designations?.eng || conceptId,
|
|
110
|
+
designation: String(term || entry?.designations?.eng || conceptId),
|
|
111
111
|
definition: typeof def === 'string' ? def.slice(0, 200) : '',
|
|
112
112
|
};
|
|
113
113
|
} catch {
|
|
@@ -200,7 +200,7 @@ function getTermForLang(lang: string): string {
|
|
|
200
200
|
|
|
201
201
|
function getDesignationsForLang(lang: string): Designation[] {
|
|
202
202
|
const lc = props.concept.localization(lang);
|
|
203
|
-
return lc?.terms ?? [];
|
|
203
|
+
return [...(lc?.terms ?? [])];
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
function hasDefinition(lang: string): boolean {
|
|
@@ -444,7 +444,7 @@ const nonVerbalReps = computed(() => {
|
|
|
444
444
|
</div>
|
|
445
445
|
|
|
446
446
|
<!-- Non-verbal representations -->
|
|
447
|
-
<NonVerbalRepDisplay v-if="lc.lc.nonVerbalRep?.length" :reps="lc.lc.nonVerbalRep" :locale="lc.lang" :register-id="registerId" :dataset-locales="languages" />
|
|
447
|
+
<NonVerbalRepDisplay v-if="lc.lc.nonVerbalRep?.length" :reps="[...lc.lc.nonVerbalRep]" :locale="lc.lang" :register-id="registerId" :dataset-locales="languages" />
|
|
448
448
|
|
|
449
449
|
<!-- Sources -->
|
|
450
450
|
<div v-if="lc.sources.length" class="space-y-2">
|
|
@@ -33,7 +33,7 @@ const { t } = useI18n();
|
|
|
33
33
|
const targetConcept = ref<Concept | null>(null);
|
|
34
34
|
const loadError = ref<string | null>(null);
|
|
35
35
|
|
|
36
|
-
function conceptToData(c:
|
|
36
|
+
function conceptToData(c: any, registerId: string): ConceptLikeData | null {
|
|
37
37
|
if (!c) return null;
|
|
38
38
|
const langs = c.languages ?? [];
|
|
39
39
|
const localizations: Record<string, unknown> = {};
|
|
@@ -51,7 +51,7 @@ function conceptToData(c: Concept | null, registerId: string): ConceptLikeData |
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
const oldData = computed(() => conceptToData(targetConcept.value, props.targetRegisterId));
|
|
54
|
-
const newData = computed(() => conceptToData(props.currentConcept, props.currentRegisterId));
|
|
54
|
+
const newData = computed(() => conceptToData(props.currentConcept as any, props.currentRegisterId));
|
|
55
55
|
|
|
56
56
|
async function loadTarget() {
|
|
57
57
|
if (!props.open || !props.targetRegisterId || !props.targetConceptId) return;
|
|
@@ -51,7 +51,7 @@ watchEffect(() => {
|
|
|
51
51
|
}
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
-
const effectiveDiff = computed(() => props.diff ?? internal.diffResult.value);
|
|
54
|
+
const effectiveDiff = computed(() => (props.diff ?? internal.diffResult.value) as any);
|
|
55
55
|
const sections = computed(() => deriveDiffSections(effectiveDiff.value, props.lang));
|
|
56
56
|
const similarity = computed(() => computeSimilarity(effectiveDiff.value));
|
|
57
57
|
const hasChanges = computed(() => effectiveDiff.value?.hasChanges === true);
|
|
@@ -77,11 +77,11 @@ function resolvedLabel(dr: { content: string | null; ref?: { source: string | nu
|
|
|
77
77
|
<div v-if="d.related?.length" class="mt-0.5 space-y-0.5">
|
|
78
78
|
<div v-for="(dr, dri) in d.related" :key="'dr'+dri" class="text-xs text-ink-400 flex items-center gap-1.5">
|
|
79
79
|
<span class="badge text-[9px] bg-gray-50 text-gray-600">{{ relationshipLabel(dr.type ?? '') }}</span>
|
|
80
|
-
<template v-if="getDesignationTarget(dr)">
|
|
81
|
-
<span class="italic">{{ getDesignationTarget(dr) }}</span>
|
|
80
|
+
<template v-if="getDesignationTarget(dr as any)">
|
|
81
|
+
<span class="italic">{{ getDesignationTarget(dr as any) }}</span>
|
|
82
82
|
</template>
|
|
83
|
-
<button v-else-if="'ref' in dr && dr.ref" @click="emit('navigate-related', dr.ref)" class="concept-link">{{ resolvedLabel(dr) }}</button>
|
|
84
|
-
<span v-else>{{ resolvedLabel(dr) }}</span>
|
|
83
|
+
<button v-else-if="'ref' in dr && dr.ref" @click="emit('navigate-related', dr.ref)" class="concept-link">{{ resolvedLabel(dr as any) }}</button>
|
|
84
|
+
<span v-else>{{ resolvedLabel(dr as any) }}</span>
|
|
85
85
|
</div>
|
|
86
86
|
</div>
|
|
87
87
|
</div>
|
|
@@ -10,6 +10,7 @@ const icons: Record<string, string> = {
|
|
|
10
10
|
list: 'M4 6h16M4 10h16M4 14h16M4 18h16',
|
|
11
11
|
schema: 'M4 5a1 1 0 011-1h14a1 1 0 011 1v2a1 1 0 01-1 1H5a1 1 0 01-1-1V5zM4 13a1 1 0 011-1h6a1 1 0 011 1v6a1 1 0 01-1 1H5a1 1 0 01-1-1v-6zM16 13a1 1 0 011-1h2a1 1 0 011 1v6a1 1 0 01-1 1h-2a1 1 0 01-1-1v-6z',
|
|
12
12
|
database: 'M4 7c0 1.1 3.6 2 8 2s8-.9 8-2M4 7c0-1.1 3.6-2 8-2s8 .9 8 2M4 7v10c0 1.1 3.6 2 8 2s8-.9 8-2V7M4 12c0 1.1 3.6 2 8 2s8-.9 8-2',
|
|
13
|
+
book: 'M12 6.042A8.967 8.967 0 006 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 016 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 016-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0018 18a8.967 8.967 0 00-6 2.292m0-14.25v14.25',
|
|
13
14
|
};
|
|
14
15
|
|
|
15
16
|
defineProps<{ name: string }>();
|
|
@@ -50,8 +50,8 @@ const topLevelImages = computed(() => fig.value?.images ?? []);
|
|
|
50
50
|
>
|
|
51
51
|
<div v-if="topLevelImages.length" :class="`figure__media figure__media--${layout}`">
|
|
52
52
|
<FigureImages
|
|
53
|
-
:images="topLevelImages"
|
|
54
|
-
:alt="fig.alt"
|
|
53
|
+
:images="[...topLevelImages]"
|
|
54
|
+
:alt="(fig.alt as any)"
|
|
55
55
|
:dataset-id="datasetId"
|
|
56
56
|
:locale="locale"
|
|
57
57
|
:fallback-chain="fallbackChain"
|
|
@@ -76,8 +76,8 @@ const topLevelImages = computed(() => fig.value?.images ?? []);
|
|
|
76
76
|
|
|
77
77
|
<NonVerbalCaption
|
|
78
78
|
:identifier="fig.identifier"
|
|
79
|
-
:caption="fig.caption"
|
|
80
|
-
:description="fig.description"
|
|
79
|
+
:caption="(fig.caption as any)"
|
|
80
|
+
:description="(fig.description as any)"
|
|
81
81
|
:locale="locale"
|
|
82
82
|
:fallback-chain="fallbackChain"
|
|
83
83
|
:description-id="descriptionId"
|
|
@@ -85,7 +85,7 @@ const topLevelImages = computed(() => fig.value?.images ?? []);
|
|
|
85
85
|
|
|
86
86
|
<NonVerbalSources
|
|
87
87
|
v-if="fig.sources?.length"
|
|
88
|
-
:sources="fig.sources"
|
|
88
|
+
:sources="[...(fig.sources || [])]"
|
|
89
89
|
/>
|
|
90
90
|
</figure>
|
|
91
91
|
|
|
@@ -41,7 +41,7 @@ const descriptionId = computed(() => `${anchor.value}-desc`);
|
|
|
41
41
|
>
|
|
42
42
|
<div class="formula__expr-line">
|
|
43
43
|
<FormulaExpression
|
|
44
|
-
:expression="form.expression"
|
|
44
|
+
:expression="(form.expression as any)"
|
|
45
45
|
:notation="(form.notation as FormulaNotation | null)"
|
|
46
46
|
:locale="locale"
|
|
47
47
|
:fallback-chain="fallbackChain"
|
|
@@ -50,8 +50,8 @@ const descriptionId = computed(() => `${anchor.value}-desc`);
|
|
|
50
50
|
|
|
51
51
|
<NonVerbalCaption
|
|
52
52
|
:identifier="form.identifier"
|
|
53
|
-
:caption="form.caption"
|
|
54
|
-
:description="form.description"
|
|
53
|
+
:caption="(form.caption as any)"
|
|
54
|
+
:description="(form.description as any)"
|
|
55
55
|
:locale="locale"
|
|
56
56
|
:fallback-chain="fallbackChain"
|
|
57
57
|
:description-id="descriptionId"
|
|
@@ -59,7 +59,7 @@ const descriptionId = computed(() => `${anchor.value}-desc`);
|
|
|
59
59
|
|
|
60
60
|
<NonVerbalSources
|
|
61
61
|
v-if="form.sources?.length"
|
|
62
|
-
:sources="form.sources"
|
|
62
|
+
:sources="[...(form.sources || [])]"
|
|
63
63
|
/>
|
|
64
64
|
</figure>
|
|
65
65
|
|
|
@@ -65,8 +65,8 @@ const markup = computed(() => {
|
|
|
65
65
|
|
|
66
66
|
<NonVerbalCaption
|
|
67
67
|
:identifier="table.identifier"
|
|
68
|
-
:caption="table.caption"
|
|
69
|
-
:description="table.description"
|
|
68
|
+
:caption="(table.caption as any)"
|
|
69
|
+
:description="(table.description as any)"
|
|
70
70
|
:locale="locale"
|
|
71
71
|
:fallback-chain="fallbackChain"
|
|
72
72
|
:description-id="descriptionId"
|
|
@@ -74,7 +74,7 @@ const markup = computed(() => {
|
|
|
74
74
|
|
|
75
75
|
<NonVerbalSources
|
|
76
76
|
v-if="table.sources?.length"
|
|
77
|
-
:sources="table.sources"
|
|
77
|
+
:sources="[...(table.sources || [])]"
|
|
78
78
|
/>
|
|
79
79
|
</figure>
|
|
80
80
|
|
|
@@ -8,12 +8,21 @@ import {
|
|
|
8
8
|
writeTurtleSync,
|
|
9
9
|
collectQuads,
|
|
10
10
|
PREFIXES,
|
|
11
|
-
type ClassInstance,
|
|
12
|
-
type PropValue,
|
|
13
|
-
type Quad,
|
|
14
11
|
} from 'glossarist/rdf';
|
|
12
|
+
import type { Quad } from '@rdfjs/types';
|
|
15
13
|
|
|
16
|
-
export
|
|
14
|
+
export interface PropValue {
|
|
15
|
+
predicate: string;
|
|
16
|
+
values: string[];
|
|
17
|
+
nested?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface ClassInstance {
|
|
21
|
+
classId: string;
|
|
22
|
+
classLabel: string;
|
|
23
|
+
label: string;
|
|
24
|
+
props: PropValue[];
|
|
25
|
+
}
|
|
17
26
|
|
|
18
27
|
export interface RdfDocument {
|
|
19
28
|
sections: ComputedRef<ClassInstance[]>;
|
|
@@ -111,10 +120,10 @@ export function useRdfDocument(
|
|
|
111
120
|
const concept = getConcept();
|
|
112
121
|
const uri = getConceptUri();
|
|
113
122
|
const conceptQuads = collectQuads(
|
|
114
|
-
conceptToQuads(concept, {
|
|
123
|
+
conceptToQuads(concept as any, {
|
|
115
124
|
registerId: options.registerId ?? '',
|
|
116
125
|
uriBase: options.uriBase ?? '',
|
|
117
|
-
}),
|
|
126
|
+
}) as any,
|
|
118
127
|
);
|
|
119
128
|
const provenanceQuads = collectQuads(
|
|
120
129
|
provenanceToQuads({
|
|
@@ -122,7 +131,7 @@ export function useRdfDocument(
|
|
|
122
131
|
serializer: 'concept-browser',
|
|
123
132
|
serializerVersion: SERIALIZER_VERSION,
|
|
124
133
|
generatedAt: new Date().toISOString(),
|
|
125
|
-
}),
|
|
134
|
+
}) as any,
|
|
126
135
|
);
|
|
127
136
|
return [...conceptQuads, ...provenanceQuads];
|
|
128
137
|
});
|
|
@@ -101,14 +101,14 @@ export function useConceptContent(
|
|
|
101
101
|
renderedAnnotations: annotations.map((a: string) => renderContent(a, opts)),
|
|
102
102
|
notes,
|
|
103
103
|
examples,
|
|
104
|
-
sources: lc.sources,
|
|
105
|
-
designations: lc.terms,
|
|
104
|
+
sources: [...lc.sources],
|
|
105
|
+
designations: [...lc.terms],
|
|
106
106
|
renderedDesignations: new Map(lc.terms.map(d => [d.designation, renderContent(d.designation)])),
|
|
107
107
|
entryStatus: lc.entryStatus ?? '',
|
|
108
108
|
classification: lc.classification,
|
|
109
109
|
reviewType: lc.reviewType,
|
|
110
110
|
release: lc.release,
|
|
111
|
-
lineageSourceSimilarity: lc.lineageSourceSimilarity,
|
|
111
|
+
lineageSourceSimilarity: (lc.lineageSourceSimilarity as any),
|
|
112
112
|
lcScript: lc.script,
|
|
113
113
|
lcSystem: lc.system,
|
|
114
114
|
});
|
|
@@ -211,8 +211,8 @@ export function useConceptDiff() {
|
|
|
211
211
|
error.value = null;
|
|
212
212
|
try {
|
|
213
213
|
diffResult.value = diffConcepts(
|
|
214
|
-
oldData ? toDiffableConcept(oldData) : null,
|
|
215
|
-
newData ? toDiffableConcept(newData) : null,
|
|
214
|
+
(oldData ? toDiffableConcept(oldData) : null) as any,
|
|
215
|
+
(newData ? toDiffableConcept(newData) : null) as any,
|
|
216
216
|
);
|
|
217
217
|
} catch (e: unknown) {
|
|
218
218
|
error.value = e instanceof Error ? e.message : String(e);
|
|
@@ -7,7 +7,7 @@ import type { Concept, RelatedConcept, ConceptRef } from 'glossarist';
|
|
|
7
7
|
import { PartitiveHyperedge } from 'glossarist';
|
|
8
8
|
import { GenericHyperedge } from 'glossarist/models';
|
|
9
9
|
import type {
|
|
10
|
-
|
|
10
|
+
PartitiveHyperedge as GlsPartitiveRelation,
|
|
11
11
|
PartitiveMember as GlsPartitiveMember,
|
|
12
12
|
} from 'glossarist/models';
|
|
13
13
|
import type {
|
|
@@ -39,7 +39,7 @@ export interface EdgeDisplay {
|
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export function useConceptEdges(
|
|
42
|
-
concept: ComputedRef<
|
|
42
|
+
concept: ComputedRef<any>,
|
|
43
43
|
registerId: ComputedRef<string>,
|
|
44
44
|
manifest: ComputedRef<Manifest | null | undefined>,
|
|
45
45
|
edges: ComputedRef<GraphEdge[]>,
|
|
@@ -138,7 +138,7 @@ export function useConceptEdges(
|
|
|
138
138
|
// Concept-level related concepts (managed concept cross-references)
|
|
139
139
|
const conceptRelated = computed(() => {
|
|
140
140
|
if (!concept.value) return [];
|
|
141
|
-
const direct = concept.value.relatedConcepts?.filter(rc => !INVERSE_RELATIONSHIPS[rc.type]) ?? [];
|
|
141
|
+
const direct = concept.value.relatedConcepts?.filter((rc: any) => !INVERSE_RELATIONSHIPS[rc.type]) ?? [];
|
|
142
142
|
const derived = incomingEdges.value
|
|
143
143
|
.filter(e => INVERSE_RELATIONSHIPS[e.type])
|
|
144
144
|
.map(e => {
|
package/src/config/page-types.ts
CHANGED
|
@@ -35,7 +35,7 @@ export const PAGE_TYPES: readonly PageTypeDefinition[] = [
|
|
|
35
35
|
{ type: 'stats', route: 'stats', title: 'Statistics', icon: 'chart', scope: 'dataset', featureFlag: '!stats', autoSynthesize: true },
|
|
36
36
|
{ type: 'sources', route: 'sources', title: 'Sources', icon: 'database', scope: 'dataset', autoSynthesize: true },
|
|
37
37
|
{ type: 'about', route: 'about', title: 'About', icon: 'info', scope: 'dataset', featureFlag: '!about', autoSynthesize: true },
|
|
38
|
-
{ type: 'learn', route: 'learn', title: 'Learn', icon: 'book
|
|
38
|
+
{ type: 'learn', route: 'learn', title: 'Learn', icon: 'book', scope: 'global', autoSynthesize: true },
|
|
39
39
|
] as const;
|
|
40
40
|
|
|
41
41
|
export type BuiltinPageType = typeof PAGE_TYPES[number]['type'];
|
package/src/i18n/locales/eng.yml
CHANGED
|
@@ -56,6 +56,18 @@ learn.dimensions.delimiting.false.label: not delimiting
|
|
|
56
56
|
learn.dimensions.delimiting.false.meaning: An ordinary part. Drawn at normal stroke width (1.5px).
|
|
57
57
|
learn.dimensions.delimiting.true.label: delimiting
|
|
58
58
|
learn.dimensions.delimiting.true.meaning: The part is essential to the whole's identity. Drawn at 3× normal stroke width (4.5px).
|
|
59
|
+
learn.dimensions.combinationsTitle: Valid multiplicity combinations
|
|
60
|
+
learn.dimensions.combinationsDescription: ISO 704 description
|
|
61
|
+
learn.dimensions.combinationsModel: Our model
|
|
62
|
+
learn.dimensions.combinationsVisual: Visual
|
|
63
|
+
learn.dimensions.combo.compulsory: compulsory
|
|
64
|
+
learn.dimensions.combo.atLeastOne: at least one
|
|
65
|
+
learn.dimensions.combo.optional: optional
|
|
66
|
+
learn.dimensions.combo.optionalMultiple: optional multiple
|
|
67
|
+
learn.dimensions.combo.compulsoryMultiple: compulsory multiple
|
|
68
|
+
learn.dimensions.invalidDescription: (invalid)
|
|
69
|
+
learn.dimensions.invalidModel: optional + at_least_one
|
|
70
|
+
learn.dimensions.invalidReason: Vacuous — collapses to optional + multiple (0..*). Rejected by glossarist-js.
|
|
59
71
|
learn.designations.title: Designations
|
|
60
72
|
learn.designations.short: Terms and symbols — preferred, admitted, deprecated, full form, abbreviation, acronym, initialism.
|
|
61
73
|
learn.designations.intro: Concepts are designated by terms, proper names, and symbols. This page explains the vocabulary you'll see on each concept page.
|
package/src/i18n/locales/fra.yml
CHANGED
|
@@ -55,6 +55,18 @@ learn.dimensions.delimiting.false.label: non délimitante
|
|
|
55
55
|
learn.dimensions.delimiting.false.meaning: Une partie ordinaire. Dessinée à largeur de trait normale (1,5 px).
|
|
56
56
|
learn.dimensions.delimiting.true.label: délimitante
|
|
57
57
|
learn.dimensions.delimiting.true.meaning: La partie est essentielle à l'identité du tout. Dessinée à largeur de trait 3× (4,5 px).
|
|
58
|
+
learn.dimensions.combinationsTitle: Combinaisons de multiplicité valides
|
|
59
|
+
learn.dimensions.combinationsDescription: Description ISO 704
|
|
60
|
+
learn.dimensions.combinationsModel: Notre modèle
|
|
61
|
+
learn.dimensions.combinationsVisual: Visuel
|
|
62
|
+
learn.dimensions.combo.compulsory: obligatoire
|
|
63
|
+
learn.dimensions.combo.atLeastOne: au moins un
|
|
64
|
+
learn.dimensions.combo.optional: optionnel
|
|
65
|
+
learn.dimensions.combo.optionalMultiple: optionnel multiple
|
|
66
|
+
learn.dimensions.combo.compulsoryMultiple: obligatoire multiple
|
|
67
|
+
learn.dimensions.invalidDescription: (invalide)
|
|
68
|
+
learn.dimensions.invalidModel: optional + at_least_one
|
|
69
|
+
learn.dimensions.invalidReason: Vacuous — se réduit à optional + multiple (0..*). Rejeté par glossarist-js.
|
|
58
70
|
learn.designations.title: Désignations
|
|
59
71
|
learn.designations.short: Termes et symboles — préféré, admis, déconseillé, forme complète, abréviation, acronyme, sigle.
|
|
60
72
|
learn.designations.intro: Les concepts sont désignés par des termes, noms propres et symboles. Cette page explique le vocabulaire que vous verrez sur chaque page de concept.
|
|
@@ -12,6 +12,30 @@ interface Props {
|
|
|
12
12
|
|
|
13
13
|
const { title, description = '', conceptTerm, conceptDefinition } = Astro.props;
|
|
14
14
|
const siteConfig = await getSiteConfig();
|
|
15
|
+
|
|
16
|
+
// Derive Google Fonts URL from siteConfig branding (build-time SSG).
|
|
17
|
+
// Falls back to the default DM Sans / DM Serif Display / JetBrains Mono
|
|
18
|
+
// when no branding.fonts is declared.
|
|
19
|
+
const brandingFonts = siteConfig?.branding?.fonts;
|
|
20
|
+
const fontParts: string[] = [];
|
|
21
|
+
if (brandingFonts?.header?.source === 'google' && brandingFonts.header.family) {
|
|
22
|
+
const w = (brandingFonts.header.weights || [400, 700]).join(';');
|
|
23
|
+
fontParts.push(`family=${brandingFonts.header.family.replace(/ /g, '+')}:wght@${w}`);
|
|
24
|
+
}
|
|
25
|
+
if (brandingFonts?.body?.source === 'google' && brandingFonts.body.family) {
|
|
26
|
+
const w = (brandingFonts.body.weights || [400, 700]).join(';');
|
|
27
|
+
fontParts.push(`family=${brandingFonts.body.family.replace(/ /g, '+')}:wght@${w}`);
|
|
28
|
+
}
|
|
29
|
+
const fontsUrl = fontParts.length > 0
|
|
30
|
+
? `https://fonts.googleapis.com/css2?${fontParts.join('&')}&display=swap`
|
|
31
|
+
: 'https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&family=DM+Serif+Display:ital@0;1&family=JetBrains+Mono:wght@400;500&display=swap';
|
|
32
|
+
|
|
33
|
+
const fontHeader = brandingFonts?.header?.family
|
|
34
|
+
? `'${brandingFonts.header.family}', Georgia, serif`
|
|
35
|
+
: `'DM Serif Display', Georgia, serif`;
|
|
36
|
+
const fontBody = brandingFonts?.body?.family
|
|
37
|
+
? `'${brandingFonts.body.family}', system-ui, sans-serif`
|
|
38
|
+
: `'DM Sans', system-ui, sans-serif`;
|
|
15
39
|
---
|
|
16
40
|
|
|
17
41
|
<!DOCTYPE html>
|
|
@@ -42,8 +66,14 @@ const siteConfig = await getSiteConfig();
|
|
|
42
66
|
<title>{title}</title>
|
|
43
67
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
44
68
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
45
|
-
<link rel="preload" as="style" href=
|
|
46
|
-
<noscript><link href=
|
|
69
|
+
<link rel="preload" as="style" href={fontsUrl} onload="this.rel='stylesheet'">
|
|
70
|
+
<noscript><link href={fontsUrl} rel="stylesheet"></noscript>
|
|
71
|
+
<style is:global>
|
|
72
|
+
:root {
|
|
73
|
+
--font-header: ${fontHeader};
|
|
74
|
+
--font-body: ${fontBody};
|
|
75
|
+
}
|
|
76
|
+
</style>
|
|
47
77
|
<script is:inline>
|
|
48
78
|
(function() {
|
|
49
79
|
const c = document.cookie.split(';').map(s => s.trim()).find(s => s.startsWith('theme='));
|
|
@@ -183,7 +183,7 @@ function resolveUrnRefs(text: string, opts: RenderOptions): string {
|
|
|
183
183
|
function resolveMentions(text: string, opts: RenderOptions): string {
|
|
184
184
|
return text.replace(/\{\{([^{}]+?)\}\}/g, (_orig, body) => {
|
|
185
185
|
const parsed = parseMention(body);
|
|
186
|
-
const p = parsed as Record<string, unknown>;
|
|
186
|
+
const p = parsed as unknown as Record<string, unknown>;
|
|
187
187
|
|
|
188
188
|
switch (p.kind) {
|
|
189
189
|
case 'fig-ref':
|
|
@@ -28,10 +28,11 @@ import {
|
|
|
28
28
|
multiplicityFromPair,
|
|
29
29
|
isValidPresence,
|
|
30
30
|
isValidCount,
|
|
31
|
-
type PartitivePresence,
|
|
32
|
-
type PartitiveCount,
|
|
33
31
|
} from 'glossarist/models';
|
|
34
32
|
|
|
33
|
+
type PartitivePresence = (typeof PARTITIVE_PRESENCE.VALUES)[number];
|
|
34
|
+
type PartitiveCount = (typeof PARTITIVE_COUNT.VALUES)[number];
|
|
35
|
+
|
|
35
36
|
// ── Two independent axes (re-exported SSOT) ────────────────────────────
|
|
36
37
|
|
|
37
38
|
export { PARTITIVE_PRESENCE, PARTITIVE_COUNT };
|
|
@@ -60,7 +60,7 @@ const activeRegisterId = computed(() => sphereFocusPayload.value?.registerId ??
|
|
|
60
60
|
const adjacent = ref({ prev: null as string | null, next: null as string | null });
|
|
61
61
|
|
|
62
62
|
const { conceptPartitiveRelations, conceptGenericRelations } = useConceptEdges(
|
|
63
|
-
concept,
|
|
63
|
+
computed(() => concept.value as any),
|
|
64
64
|
activeRegisterId,
|
|
65
65
|
manifest,
|
|
66
66
|
edges,
|
|
@@ -284,7 +284,7 @@ onUnmounted(() => window.removeEventListener('keydown', onKeydown));
|
|
|
284
284
|
<!-- Sphere mode — receives concept + edges directly, no URI matching -->
|
|
285
285
|
<RelationSphere
|
|
286
286
|
v-if="viewMode === 'sphere'"
|
|
287
|
-
:concept="concept"
|
|
287
|
+
:concept="concept as any"
|
|
288
288
|
:manifest="manifest"
|
|
289
289
|
:register-id="activeRegisterId"
|
|
290
290
|
:edges="edges"
|
|
@@ -295,7 +295,7 @@ onUnmounted(() => window.removeEventListener('keydown', onKeydown));
|
|
|
295
295
|
<!-- Detail mode -->
|
|
296
296
|
<ConceptDetail
|
|
297
297
|
v-else
|
|
298
|
-
:concept="concept"
|
|
298
|
+
:concept="concept as any"
|
|
299
299
|
:manifest="manifest"
|
|
300
300
|
:edges="edges"
|
|
301
301
|
:adjacent="adjacent"
|