@glossarist/concept-browser 0.7.67 → 0.7.68
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glossarist/concept-browser",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.68",
|
|
4
4
|
"description": "Vue SPA for browsing Glossarist terminology datasets with cross-reference resolution, graph visualization, and multi-language support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -1081,6 +1081,7 @@ async function processDataset(dir, register, opts) {
|
|
|
1081
1081
|
sourceRepo: opts.sourceRepo,
|
|
1082
1082
|
chunkSize: CHUNK_SIZE,
|
|
1083
1083
|
color: opts.color,
|
|
1084
|
+
year: opts.year ?? undefined,
|
|
1084
1085
|
languageStats: langStats,
|
|
1085
1086
|
availableFormats,
|
|
1086
1087
|
bulkFormats,
|
|
@@ -1199,6 +1200,7 @@ for (let i = 0; i < config.datasets.length; i++) {
|
|
|
1199
1200
|
languageOrder: firstNonEmpty(reg?.languageOrder, ds.languageOrder),
|
|
1200
1201
|
ref: firstNonEmpty(reg?.ref, ds.ref),
|
|
1201
1202
|
refAliases: firstNonEmpty(reg?.refAliases, ds.refAliases),
|
|
1203
|
+
year: reg?.year ?? null,
|
|
1202
1204
|
tags: firstNonEmpty(reg?.tags, ds.tags),
|
|
1203
1205
|
color: ds.color || DS_PALETTE[i % DS_PALETTE.length],
|
|
1204
1206
|
datasetUri: firstNonEmpty(reg?.urn, ds.uri),
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { groupManifestsIntoSeries } from '../composables/useDatasetSeries';
|
|
3
|
+
import type { Manifest } from '../adapters/types';
|
|
4
|
+
|
|
5
|
+
// Integration tests for the isotc204.geolexica.org deployment shape:
|
|
6
|
+
// three editions of ISO 14812 (2022 / 2025 / ed3-draft) wired as a
|
|
7
|
+
// lineage-series group with an explicit `current` pointing at the draft.
|
|
8
|
+
//
|
|
9
|
+
// These tests verify the exact config shape that tc204 PR #28 uses, so
|
|
10
|
+
// regressions specific to that deployment are caught here rather than
|
|
11
|
+
// in production.
|
|
12
|
+
|
|
13
|
+
function makeManifest(overrides: Partial<Manifest> & { id: string }): Manifest {
|
|
14
|
+
const base: Manifest = {
|
|
15
|
+
id: overrides.id,
|
|
16
|
+
title: overrides.title ?? overrides.id,
|
|
17
|
+
description: overrides.description ?? '',
|
|
18
|
+
owner: overrides.owner ?? '',
|
|
19
|
+
baseUrl: overrides.baseUrl ?? '/',
|
|
20
|
+
languages: overrides.languages ?? ['eng'],
|
|
21
|
+
conceptCount: overrides.conceptCount ?? 0,
|
|
22
|
+
conceptUrlTemplate: overrides.conceptUrlTemplate ?? '/concept/{id}',
|
|
23
|
+
indexUrl: overrides.indexUrl ?? '/index.json',
|
|
24
|
+
contextUrl: overrides.contextUrl ?? '/context.json',
|
|
25
|
+
uriBase: overrides.uriBase ?? 'https://isotc204.geolexica.org',
|
|
26
|
+
status: overrides.status ?? 'valid',
|
|
27
|
+
schemaVersion: overrides.schemaVersion ?? '3',
|
|
28
|
+
tags: overrides.tags ?? [],
|
|
29
|
+
lastUpdated: overrides.lastUpdated ?? '',
|
|
30
|
+
sourceRepo: overrides.sourceRepo ?? '',
|
|
31
|
+
chunkSize: overrides.chunkSize ?? 0,
|
|
32
|
+
datasetUri: overrides.datasetUri ?? '',
|
|
33
|
+
};
|
|
34
|
+
return { ...base, ...overrides } as Manifest;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const TC204_GROUP = {
|
|
38
|
+
id: 'isotc204',
|
|
39
|
+
datasets: ['isotc204-ed3', 'isotc204-2025', 'isotc204-2022'],
|
|
40
|
+
kind: 'lineage' as const,
|
|
41
|
+
current: 'isotc204-ed3',
|
|
42
|
+
label: 'ISO/TC 204 ITS Vocabulary',
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
describe('tc204 deployment: multi-edition lineage series', () => {
|
|
46
|
+
it('groups all three editions into one series', () => {
|
|
47
|
+
const manifests = [
|
|
48
|
+
makeManifest({ id: 'isotc204-2022', status: 'valid', year: 2022, title: 'Edition 1' }),
|
|
49
|
+
makeManifest({ id: 'isotc204-2025', status: 'valid', year: 2025, title: 'Edition 2' }),
|
|
50
|
+
makeManifest({ id: 'isotc204-ed3', status: 'draft', year: 2026, title: 'Edition 3 draft' }),
|
|
51
|
+
];
|
|
52
|
+
const series = groupManifestsIntoSeries(manifests, undefined, [TC204_GROUP]);
|
|
53
|
+
expect(series.length).toBe(1);
|
|
54
|
+
expect(series[0].members.length).toBe(3);
|
|
55
|
+
expect(series[0].members.map(m => m.id)).toContain('isotc204-ed3');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('honors explicit current=isotc204-ed3 (the draft)', () => {
|
|
59
|
+
// tc204 marks ed3 (draft) as current because it's the active working
|
|
60
|
+
// edition, even though it's not yet published. The fallback logic
|
|
61
|
+
// would pick the newest *valid* member, which would be 2025. The
|
|
62
|
+
// explicit `current` override must win.
|
|
63
|
+
const manifests = [
|
|
64
|
+
makeManifest({ id: 'isotc204-2022', status: 'valid', year: 2022 }),
|
|
65
|
+
makeManifest({ id: 'isotc204-2025', status: 'valid', year: 2025 }),
|
|
66
|
+
makeManifest({ id: 'isotc204-ed3', status: 'draft', year: 2026 }),
|
|
67
|
+
];
|
|
68
|
+
const series = groupManifestsIntoSeries(manifests, undefined, [TC204_GROUP]);
|
|
69
|
+
expect(series[0].current?.id).toBe('isotc204-ed3');
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('sorts members by year ascending — ed3 (2026) sorts LAST, not first', () => {
|
|
73
|
+
// Without manifest.year, extractYear('isotc204-ed3') returns undefined
|
|
74
|
+
// and the member sorts as year=0 (oldest). With register.yaml:year
|
|
75
|
+
// propagated to manifest.year, ed3 correctly sorts as the newest.
|
|
76
|
+
// This is the tc204-specific regression: drafts without a year in
|
|
77
|
+
// their id must still be positioned via the explicit year field.
|
|
78
|
+
const manifests = [
|
|
79
|
+
makeManifest({ id: 'isotc204-ed3', status: 'draft', year: 2026, title: 'E3' }),
|
|
80
|
+
makeManifest({ id: 'isotc204-2025', status: 'valid', year: 2025, title: 'E2' }),
|
|
81
|
+
makeManifest({ id: 'isotc204-2022', status: 'valid', year: 2022, title: 'E1' }),
|
|
82
|
+
];
|
|
83
|
+
const series = groupManifestsIntoSeries(manifests, undefined, [TC204_GROUP]);
|
|
84
|
+
const ids = series[0].members.map(m => m.id);
|
|
85
|
+
expect(ids).toEqual(['isotc204-2022', 'isotc204-2025', 'isotc204-ed3']);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it('includes stub members for configured-but-unfetched editions', () => {
|
|
89
|
+
// tc204's ed3 GCR is generated from a draft ontology; it may be
|
|
90
|
+
// unavailable on some builds. The series deliberately includes
|
|
91
|
+
// stub members for every configured dataset so navigation links
|
|
92
|
+
// survive partial deployments.
|
|
93
|
+
const manifests = [
|
|
94
|
+
makeManifest({ id: 'isotc204-2022', status: 'valid', year: 2022 }),
|
|
95
|
+
makeManifest({ id: 'isotc204-2025', status: 'valid', year: 2025 }),
|
|
96
|
+
// isotc204-ed3 missing — GCR download may have failed
|
|
97
|
+
];
|
|
98
|
+
const series = groupManifestsIntoSeries(manifests, undefined, [TC204_GROUP]);
|
|
99
|
+
// All 3 configured members appear; the missing one is a stub
|
|
100
|
+
expect(series[0].members.length).toBe(3);
|
|
101
|
+
const ed3 = series[0].members.find(m => m.id === 'isotc204-ed3');
|
|
102
|
+
expect(ed3).toBeDefined();
|
|
103
|
+
expect(ed3?.status).toBe('unknown');
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('honors configured current even when the member is a stub', () => {
|
|
107
|
+
// When ed3 fails to load AND the config says current=ed3, the stub
|
|
108
|
+
// member is still marked as current. This is deliberate: the config
|
|
109
|
+
// is the source of truth for which edition is "current". A stub
|
|
110
|
+
// current signals "this edition exists but isn't loaded" — the UI
|
|
111
|
+
// can surface that state.
|
|
112
|
+
//
|
|
113
|
+
// TODO: consider falling back to newest valid when the configured
|
|
114
|
+
// current has no manifest. Filed as a follow-up.
|
|
115
|
+
const manifests = [
|
|
116
|
+
makeManifest({ id: 'isotc204-2022', status: 'valid', year: 2022 }),
|
|
117
|
+
makeManifest({ id: 'isotc204-2025', status: 'valid', year: 2025 }),
|
|
118
|
+
];
|
|
119
|
+
const series = groupManifestsIntoSeries(manifests, undefined, [TC204_GROUP]);
|
|
120
|
+
expect(series[0].current?.id).toBe('isotc204-ed3');
|
|
121
|
+
expect(series[0].current?.status).toBe('unknown');
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
describe('tc204 deployment: group about discovery', () => {
|
|
126
|
+
// tc204 ships group about content at:
|
|
127
|
+
// site-content/groups/isotc204/about/about.eng.md
|
|
128
|
+
// The build pipeline's ABOUT step must find and compile it.
|
|
129
|
+
// See scripts/__tests__/process-about-pages.test.mjs for the
|
|
130
|
+
// filesystem discovery contract.
|
|
131
|
+
it('site-content/groups/<id>/about/ layout is discoverable', async () => {
|
|
132
|
+
// Smoke check: the process-about-pages discovery logic handles
|
|
133
|
+
// the tc204 layout. The actual discovery test is in
|
|
134
|
+
// scripts/__tests__/process-about-pages.test.mjs (group case).
|
|
135
|
+
// Here we just verify the path convention matches.
|
|
136
|
+
const expectedPath = 'site-content/groups/isotc204/about/about.eng.md';
|
|
137
|
+
expect(expectedPath).toMatch(/^site-content\/groups\/[^/]+\/about\/about\.\w+\.(md|adoc|html)$/);
|
|
138
|
+
});
|
|
139
|
+
});
|
package/src/adapters/types.ts
CHANGED
|
@@ -70,6 +70,13 @@ export interface Manifest {
|
|
|
70
70
|
ref?: string;
|
|
71
71
|
refAliases?: string[];
|
|
72
72
|
editionStatus?: string;
|
|
73
|
+
/**
|
|
74
|
+
* Edition year, sourced from register.yaml:year. When the dataset id
|
|
75
|
+
* doesn't contain a parseable year (e.g. "isotc204-ed3"), this field
|
|
76
|
+
* is the only way to position the edition correctly in a lineage
|
|
77
|
+
* timeline. Falls back to extractYear(id/ref/title) at the consumer.
|
|
78
|
+
*/
|
|
79
|
+
year?: number;
|
|
73
80
|
ordering?: string;
|
|
74
81
|
sections?: ManifestSection[];
|
|
75
82
|
languageStats?: Record<string, { terms: number; definitions: number }>;
|
|
@@ -92,7 +92,7 @@ function deriveSeriesTitle(m: Manifest | undefined): string {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
function manifestToMember(m: Manifest, activeDatasetId?: string): DatasetSeriesMember {
|
|
95
|
-
const year = extractYear(m.id) ?? extractYear(m.ref ?? '') ?? extractYear(m.title);
|
|
95
|
+
const year = m.year ?? extractYear(m.id) ?? extractYear(m.ref ?? '') ?? extractYear(m.title);
|
|
96
96
|
return {
|
|
97
97
|
id: m.id,
|
|
98
98
|
ref: m.ref ?? m.title,
|