@glossarist/concept-browser 0.7.125 → 0.7.127
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.127",
|
|
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": {
|
package/scripts/generate-data.js
CHANGED
|
@@ -1179,9 +1179,10 @@ function extractInlineRefs(localizedData, refMaps2, conceptSources = []) {
|
|
|
1179
1179
|
if (seg.kind === "concept" || seg.kind === "cite") {
|
|
1180
1180
|
const target = seg.target;
|
|
1181
1181
|
if (target.type === "dataset_qualified" && target.dataset && target.id) {
|
|
1182
|
-
const dsId = refMaps2.refPrefixMap[target.dataset]
|
|
1183
|
-
|
|
1184
|
-
|
|
1182
|
+
const dsId = refMaps2.refPrefixMap[target.dataset];
|
|
1183
|
+
if (dsId) {
|
|
1184
|
+
refs.push({ id: buildConceptUri(refMaps2.uriBase, dsId, target.id), term: seg.label ?? `${target.dataset}:${target.id}` });
|
|
1185
|
+
}
|
|
1185
1186
|
} else if (target.type === "urn" && target.urn) {
|
|
1186
1187
|
const pattern = refMaps2.patternIndex.resolve(target.urn);
|
|
1187
1188
|
if (pattern) {
|
package/scripts/generate-data.ts
CHANGED
|
@@ -409,9 +409,15 @@ function extractInlineRefs(localizedData, refMaps, conceptSources = []) {
|
|
|
409
409
|
if (seg.kind === 'concept' || seg.kind === 'cite') {
|
|
410
410
|
const target = seg.target;
|
|
411
411
|
if (target.type === 'dataset_qualified' && target.dataset && target.id) {
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
412
|
+
// Only create a concept URI if the dataset is CO-DEPLOYED.
|
|
413
|
+
// If the dataset doesn't exist in this deployment's refPrefixMap,
|
|
414
|
+
// skip — the runtime resolver will handle it (unresolved text or
|
|
415
|
+
// external link via routing). Creating a URI for a non-existent
|
|
416
|
+
// dataset produces a 404.
|
|
417
|
+
const dsId = refMaps.refPrefixMap[target.dataset];
|
|
418
|
+
if (dsId) {
|
|
419
|
+
refs.push({ id: buildConceptUri(refMaps.uriBase, dsId, target.id), term: seg.label ?? `${target.dataset}:${target.id}` });
|
|
420
|
+
}
|
|
415
421
|
} else if (target.type === 'urn' && target.urn) {
|
|
416
422
|
const pattern = refMaps.patternIndex.resolve(target.urn);
|
|
417
423
|
if (pattern) {
|
|
@@ -27,7 +27,7 @@ function checkFile(file, dataDir) {
|
|
|
27
27
|
const json = JSON.parse(raw);
|
|
28
28
|
const broken = [];
|
|
29
29
|
function check(target, field) {
|
|
30
|
-
if (!target) return;
|
|
30
|
+
if (!target || typeof target !== "string") return;
|
|
31
31
|
if (!target.startsWith("http")) return;
|
|
32
32
|
const { exists, expected } = localPathForUri(target, dataDir);
|
|
33
33
|
if (!exists) {
|
|
@@ -71,8 +71,22 @@ function checkFile(file, dataDir) {
|
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
73
|
const sourceIds = /* @__PURE__ */ new Set();
|
|
74
|
-
|
|
74
|
+
const sourceRefKeys = /* @__PURE__ */ new Set();
|
|
75
|
+
const allSourceArrays = [
|
|
76
|
+
...json["gl:sources"] ?? []
|
|
77
|
+
];
|
|
78
|
+
for (const lc of Object.values(json["gl:localizedConcept"] ?? {})) {
|
|
79
|
+
const lcSources = lc["gl:source"] ?? lc["gl:sources"];
|
|
80
|
+
if (Array.isArray(lcSources)) allSourceArrays.push(...lcSources);
|
|
81
|
+
}
|
|
82
|
+
for (const s of allSourceArrays) {
|
|
75
83
|
if (s["gl:id"]) sourceIds.add(s["gl:id"]);
|
|
84
|
+
const origin = s["gl:origin"] ?? {};
|
|
85
|
+
const ref = origin["gl:ref"] ?? {};
|
|
86
|
+
if (ref["gl:source"] && ref["gl:id"]) {
|
|
87
|
+
sourceRefKeys.add(`${ref["gl:source"]}:${ref["gl:id"]}`);
|
|
88
|
+
sourceIds.add(ref["gl:id"]);
|
|
89
|
+
}
|
|
76
90
|
}
|
|
77
91
|
const textChunks = [];
|
|
78
92
|
for (const lc of Object.values(json["gl:localizedConcept"] ?? {})) {
|
|
@@ -149,9 +163,11 @@ function checkFile(file, dataDir) {
|
|
|
149
163
|
if (citeMatch) {
|
|
150
164
|
const rest = citeMatch[1];
|
|
151
165
|
const commaIdx = rest.indexOf(",");
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
166
|
+
const rawId = commaIdx > 0 ? rest.slice(0, commaIdx).trim() : rest.trim();
|
|
167
|
+
const lastColon = rawId.lastIndexOf(":");
|
|
168
|
+
const idPart = lastColon > 0 ? rawId.slice(lastColon + 1) : rawId;
|
|
169
|
+
if (!sourceIds.has(rawId) && !sourceIds.has(idPart) && !sourceRefKeys.has(rawId)) {
|
|
170
|
+
broken.push({ file: relFile, line: 0, field: "{{cite:...}}", target: rawId, reason: `source "${rawId}" not found in this concept's sources[]` });
|
|
155
171
|
}
|
|
156
172
|
continue;
|
|
157
173
|
}
|
|
@@ -56,7 +56,7 @@ function checkFile(file: string, dataDir: string): BrokenLink[] {
|
|
|
56
56
|
const broken: BrokenLink[] = [];
|
|
57
57
|
|
|
58
58
|
function check(target: string | undefined, field: string) {
|
|
59
|
-
if (!target) return;
|
|
59
|
+
if (!target || typeof target !== 'string') return;
|
|
60
60
|
if (!target.startsWith('http')) return; // External links checked separately
|
|
61
61
|
const { exists, expected } = localPathForUri(target, dataDir);
|
|
62
62
|
if (!exists) {
|
|
@@ -112,8 +112,23 @@ function checkFile(file: string, dataDir: string): BrokenLink[] {
|
|
|
112
112
|
}
|
|
113
113
|
|
|
114
114
|
const sourceIds = new Set<string>();
|
|
115
|
-
|
|
115
|
+
const sourceRefKeys = new Set<string>();
|
|
116
|
+
// Collect from concept-level sources AND localization-level sources
|
|
117
|
+
const allSourceArrays = [
|
|
118
|
+
...(json['gl:sources'] ?? []),
|
|
119
|
+
];
|
|
120
|
+
for (const lc of Object.values(json['gl:localizedConcept'] ?? {})) {
|
|
121
|
+
const lcSources = (lc as any)['gl:source'] ?? (lc as any)['gl:sources'];
|
|
122
|
+
if (Array.isArray(lcSources)) allSourceArrays.push(...lcSources);
|
|
123
|
+
}
|
|
124
|
+
for (const s of allSourceArrays) {
|
|
116
125
|
if (s['gl:id']) sourceIds.add(s['gl:id']);
|
|
126
|
+
const origin = s['gl:origin'] ?? {};
|
|
127
|
+
const ref = origin['gl:ref'] ?? {};
|
|
128
|
+
if (ref['gl:source'] && ref['gl:id']) {
|
|
129
|
+
sourceRefKeys.add(`${ref['gl:source']}:${ref['gl:id']}`);
|
|
130
|
+
sourceIds.add(ref['gl:id']);
|
|
131
|
+
}
|
|
117
132
|
}
|
|
118
133
|
|
|
119
134
|
const textChunks: string[] = [];
|
|
@@ -190,14 +205,20 @@ function checkFile(file: string, dataDir: string): BrokenLink[] {
|
|
|
190
205
|
continue;
|
|
191
206
|
}
|
|
192
207
|
|
|
193
|
-
// cite:id — source must exist in this concept's sources[]
|
|
208
|
+
// cite:id — source must exist in this concept's sources[].
|
|
209
|
+
// Handles DATASET:ID format: {{cite:IEV:702-02-07}} matches a source
|
|
210
|
+
// with id "702-02-07" or origin.ref { source: "IEV", id: "702-02-07" }.
|
|
194
211
|
const citeMatch = body.match(/^cite:(.+)$/i);
|
|
195
212
|
if (citeMatch) {
|
|
196
213
|
const rest = citeMatch[1];
|
|
197
214
|
const commaIdx = rest.indexOf(',');
|
|
198
|
-
const
|
|
199
|
-
|
|
200
|
-
|
|
215
|
+
const rawId = (commaIdx > 0 ? rest.slice(0, commaIdx).trim() : rest.trim());
|
|
216
|
+
|
|
217
|
+
// Check: rawId (e.g. "IEV:702-02-07"), or just the ID part ("702-02-07")
|
|
218
|
+
const lastColon = rawId.lastIndexOf(':');
|
|
219
|
+
const idPart = lastColon > 0 ? rawId.slice(lastColon + 1) : rawId;
|
|
220
|
+
if (!sourceIds.has(rawId) && !sourceIds.has(idPart) && !sourceRefKeys.has(rawId)) {
|
|
221
|
+
broken.push({ file: relFile, line: 0, field: '{{cite:...}}', target: rawId, reason: `source "${rawId}" not found in this concept's sources[]` });
|
|
201
222
|
}
|
|
202
223
|
continue;
|
|
203
224
|
}
|