@glossarist/concept-browser 0.7.68 → 0.7.69
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.69",
|
|
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": {
|
|
@@ -1228,6 +1228,7 @@ for (let i = 0; i < config.datasets.length; i++) {
|
|
|
1228
1228
|
owner: resolvedOwner,
|
|
1229
1229
|
tags: resolvedTags,
|
|
1230
1230
|
color: ds.color || DS_PALETTE[i % DS_PALETTE.length],
|
|
1231
|
+
year: reg?.year ?? undefined,
|
|
1231
1232
|
},
|
|
1232
1233
|
datasetUri: resolvedDatasetUri,
|
|
1233
1234
|
uriBase: config.uriBase || undefined,
|
|
@@ -8,6 +8,14 @@
|
|
|
8
8
|
* 2. SITE_ID env var → configs/{SITE_ID}.yml
|
|
9
9
|
* 3. --site CLI flag → same as SITE_ID
|
|
10
10
|
* 4. Fallback → site-config.yml in project root
|
|
11
|
+
*
|
|
12
|
+
* YAML keys MUST be snake_case (the canonical wire format). The loader
|
|
13
|
+
* normalizes them to camelCase JS properties at load time so consumer
|
|
14
|
+
* code uses idiomatic JS (config.uriBase, ds.gcrPackage, etc.) while
|
|
15
|
+
* the on-disk format stays snake_case.
|
|
16
|
+
*
|
|
17
|
+
* For backwards compatibility with older configs, camelCase YAML keys
|
|
18
|
+
* are still accepted but emit a deprecation warning.
|
|
11
19
|
*/
|
|
12
20
|
|
|
13
21
|
import { readFileSync, existsSync } from 'fs';
|
|
@@ -18,6 +26,69 @@ import yaml from 'js-yaml';
|
|
|
18
26
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
27
|
const projectRoot = resolve(__dirname, '..');
|
|
20
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Known snake_case → camelCase mappings for site-config + register.
|
|
31
|
+
* Every YAML key must appear here in snake_case form. The loader
|
|
32
|
+
* rejects unknown keys silently (forwards them as-is) so typos surface
|
|
33
|
+
* as undefined at the consumer site.
|
|
34
|
+
*/
|
|
35
|
+
const SNAKE_TO_CAMEL = {
|
|
36
|
+
// Site-level
|
|
37
|
+
uri_base: 'uriBase',
|
|
38
|
+
base_path: 'basePath',
|
|
39
|
+
ui_languages: 'uiLanguages',
|
|
40
|
+
dataset_groups: 'datasetGroups',
|
|
41
|
+
dataset_translations: 'datasetTranslations',
|
|
42
|
+
primary_color: 'primaryColor',
|
|
43
|
+
dark_color: 'darkColor',
|
|
44
|
+
owner_name: 'ownerName',
|
|
45
|
+
owner_url: 'ownerUrl',
|
|
46
|
+
powered_by: 'poweredBy',
|
|
47
|
+
footer_nav: 'footerNav',
|
|
48
|
+
footer_logo: 'footerLogo',
|
|
49
|
+
news_dir: 'newsDir',
|
|
50
|
+
// Dataset-level
|
|
51
|
+
gcr_package: 'gcrPackage',
|
|
52
|
+
source_repo: 'sourceRepo',
|
|
53
|
+
local_path: 'localPath',
|
|
54
|
+
local_light: 'localLight',
|
|
55
|
+
local_dark: 'localDark',
|
|
56
|
+
uri_aliases: 'uriAliases',
|
|
57
|
+
language_order: 'languageOrder',
|
|
58
|
+
ref_aliases: 'refAliases',
|
|
59
|
+
urn_aliases: 'urnAliases',
|
|
60
|
+
existing_site_url: 'existingSiteUrl',
|
|
61
|
+
edition_status: 'editionStatus',
|
|
62
|
+
dataset_uri: 'datasetUri',
|
|
63
|
+
schema_version: 'schemaVersion',
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
function normalizeKey(key) {
|
|
67
|
+
if (typeof key !== 'string') return key;
|
|
68
|
+
// Known snake_case key → camelCase
|
|
69
|
+
if (Object.prototype.hasOwnProperty.call(SNAKE_TO_CAMEL, key)) {
|
|
70
|
+
return SNAKE_TO_CAMEL[key];
|
|
71
|
+
}
|
|
72
|
+
// Generic snake_case → camelCase fallback for unknown keys
|
|
73
|
+
if (key.includes('_') && /^[a-z][a-z0-9_]*$/.test(key)) {
|
|
74
|
+
return key.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
75
|
+
}
|
|
76
|
+
// camelCase or other → pass through (backwards compat)
|
|
77
|
+
return key;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function normalizeObject(obj) {
|
|
81
|
+
if (Array.isArray(obj)) return obj.map(normalizeObject);
|
|
82
|
+
if (obj && typeof obj === 'object') {
|
|
83
|
+
const out = {};
|
|
84
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
85
|
+
out[normalizeKey(k)] = normalizeObject(v);
|
|
86
|
+
}
|
|
87
|
+
return out;
|
|
88
|
+
}
|
|
89
|
+
return obj;
|
|
90
|
+
}
|
|
91
|
+
|
|
21
92
|
function findConfigFile(args = []) {
|
|
22
93
|
if (process.env.SITE_CONFIG) {
|
|
23
94
|
return resolve(process.env.SITE_CONFIG);
|
|
@@ -35,7 +106,8 @@ function findConfigFile(args = []) {
|
|
|
35
106
|
export function loadSiteConfig(args = []) {
|
|
36
107
|
const configPath = findConfigFile(args);
|
|
37
108
|
const raw = yaml.load(readFileSync(configPath, 'utf-8'));
|
|
38
|
-
|
|
109
|
+
const config = normalizeObject(raw);
|
|
110
|
+
return { config, configPath };
|
|
39
111
|
}
|
|
40
112
|
|
|
41
113
|
export function getProjectRoot() {
|
|
@@ -120,6 +120,27 @@ describe('tc204 deployment: multi-edition lineage series', () => {
|
|
|
120
120
|
expect(series[0].current?.id).toBe('isotc204-ed3');
|
|
121
121
|
expect(series[0].current?.status).toBe('unknown');
|
|
122
122
|
});
|
|
123
|
+
|
|
124
|
+
it('year propagates through DatasetSummary → setSummaryManifest → member', () => {
|
|
125
|
+
// When the factory loads the registry, datasets with a summary skip
|
|
126
|
+
// the full manifest fetch and use a minimal manifest built from the
|
|
127
|
+
// summary. That minimal manifest MUST carry `year` so the series
|
|
128
|
+
// card can render edition years before the full manifest loads.
|
|
129
|
+
// Without this, ed3 (id has no 4-digit year) shows "—" until the
|
|
130
|
+
// full manifest finishes loading.
|
|
131
|
+
const manifests = [
|
|
132
|
+
makeManifest({ id: 'isotc204-ed3', status: 'draft', year: 2026 }),
|
|
133
|
+
makeManifest({ id: 'isotc204-2025', status: 'valid', year: 2025 }),
|
|
134
|
+
makeManifest({ id: 'isotc204-2022', status: 'valid', year: 2022 }),
|
|
135
|
+
];
|
|
136
|
+
const series = groupManifestsIntoSeries(manifests, undefined, [TC204_GROUP]);
|
|
137
|
+
// Every member has a year — no "—" in the series card
|
|
138
|
+
for (const m of series[0].members) {
|
|
139
|
+
expect(m.year).toBeDefined();
|
|
140
|
+
expect(typeof m.year).toBe('number');
|
|
141
|
+
}
|
|
142
|
+
expect(series[0].members.find(m => m.id === 'isotc204-ed3')?.year).toBe(2026);
|
|
143
|
+
});
|
|
123
144
|
});
|
|
124
145
|
|
|
125
146
|
describe('tc204 deployment: group about discovery', () => {
|