@glossarist/concept-browser 0.7.24 → 0.7.26
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.26",
|
|
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/src/adapters/factory.ts
CHANGED
|
@@ -46,7 +46,18 @@ export class AdapterFactory {
|
|
|
46
46
|
await Promise.all(needManifest.map(a => a.loadManifest().catch(() => {})));
|
|
47
47
|
}
|
|
48
48
|
|
|
49
|
+
// Register all datasets' URI patterns eagerly so cross-dataset refs resolve
|
|
50
|
+
for (const adapter of adapters) {
|
|
51
|
+
if (adapter.manifest) {
|
|
52
|
+
this.registerUriPatterns(adapter.registerId, adapter.manifest);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
for (const adapter of this.adapters.values()) {
|
|
56
|
+
adapter.setUrnMap(this.urnMap);
|
|
57
|
+
}
|
|
58
|
+
|
|
49
59
|
return adapters;
|
|
60
|
+
|
|
50
61
|
}
|
|
51
62
|
|
|
52
63
|
getAdapter(registerId: string): DatasetAdapter | undefined {
|
|
@@ -57,6 +68,29 @@ export class AdapterFactory {
|
|
|
57
68
|
return [...this.adapters.values()];
|
|
58
69
|
}
|
|
59
70
|
|
|
71
|
+
|
|
72
|
+
private registerUriPatterns(registerId: string, manifest: Manifest): void {
|
|
73
|
+
const uriPatterns = [
|
|
74
|
+
manifest.datasetUri,
|
|
75
|
+
...(manifest.uriAliases ?? []),
|
|
76
|
+
manifest.uriBase ? `${manifest.uriBase}/${registerId}/*` : undefined,
|
|
77
|
+
].filter(Boolean) as string[];
|
|
78
|
+
this.resolver.registerDataset(registerId, uriPatterns);
|
|
79
|
+
|
|
80
|
+
if (manifest.ref) {
|
|
81
|
+
this.resolver.registerSourceRef(manifest.ref, registerId, manifest.datasetUri);
|
|
82
|
+
}
|
|
83
|
+
for (const alias of manifest.refAliases ?? []) {
|
|
84
|
+
this.resolver.registerSourceRef(alias, registerId, manifest.datasetUri);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (manifest.datasetUri) this.urnMap.set(manifest.datasetUri, registerId);
|
|
88
|
+
for (const alias of manifest.uriAliases ?? []) {
|
|
89
|
+
const base = alias.endsWith('*') ? alias.slice(0, -1) : alias;
|
|
90
|
+
if (base.startsWith('urn:')) this.urnMap.set(base, registerId);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
60
94
|
async loadDataset(registerId: string): Promise<DatasetAdapter> {
|
|
61
95
|
const adapter = this.adapters.get(registerId);
|
|
62
96
|
if (!adapter) throw new Error(`Unknown dataset: ${registerId}`);
|
|
@@ -143,6 +143,17 @@ async function navigateRelated(ref: { source: string | null; id: string | null }
|
|
|
143
143
|
router.push({ name: 'concept', params: { registerId: target.registerId, conceptId: target.conceptId } });
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
function relatedLabel(dr: { content?: string; ref?: { source: string | null; id: string | null } | null }): string {
|
|
147
|
+
if (dr.content) return dr.content;
|
|
148
|
+
const resolved = dr.ref ? getResolvedRef(dr.ref).target : null;
|
|
149
|
+
if (resolved) {
|
|
150
|
+
const m = store.manifests.get(resolved.registerId);
|
|
151
|
+
const dsLabel = m?.shortname || m?.title || resolved.registerId;
|
|
152
|
+
return `${resolved.conceptId} (${dsLabel})`;
|
|
153
|
+
}
|
|
154
|
+
return dr.ref ? `${dr.ref.id || ''} (${dr.ref.source || ''})`.trim() : '';
|
|
155
|
+
}
|
|
156
|
+
|
|
146
157
|
// Cross-reference resolver: generates clickable links for inline refs
|
|
147
158
|
|
|
148
159
|
const { ensureBibLoaded, bibResolver, figResolver } = useRenderOptions(() => props.registerId);
|
|
@@ -670,8 +681,8 @@ const nonVerbalReps = computed(() => {
|
|
|
670
681
|
<div v-if="d.related?.length" class="mt-0.5 space-y-0.5">
|
|
671
682
|
<div v-for="(dr, dri) in d.related" :key="'dr'+dri" class="text-xs text-ink-400 flex items-center gap-1.5">
|
|
672
683
|
<span class="badge text-[9px] bg-gray-50 text-gray-600">{{ relationshipLabel(dr.type) }}</span>
|
|
673
|
-
<button v-if="getResolvedRef(dr.ref).target" @click="navigateRelated(dr.ref!)" class="concept-link">{{
|
|
674
|
-
<span v-else>{{
|
|
684
|
+
<button v-if="getResolvedRef(dr.ref).target" @click="navigateRelated(dr.ref!)" class="concept-link">{{ relatedLabel(dr) }}</button>
|
|
685
|
+
<span v-else>{{ relatedLabel(dr) }}</span>
|
|
675
686
|
</div>
|
|
676
687
|
</div>
|
|
677
688
|
</div>
|
|
@@ -30,6 +30,7 @@ const containerRef = ref<HTMLDivElement | null>(null);
|
|
|
30
30
|
const selectedNode = ref<GraphNode | null>(null);
|
|
31
31
|
const detailCloseRef = ref<HTMLButtonElement | null>(null);
|
|
32
32
|
const labelMode = ref<'designation' | 'identifier'>('designation');
|
|
33
|
+
const showDomains = ref(true);
|
|
33
34
|
|
|
34
35
|
// Dataset enable/disable state
|
|
35
36
|
const registerEnabled = reactive<Record<string, boolean>>({});
|
|
@@ -74,7 +75,8 @@ const enabledRegisters = computed(() => {
|
|
|
74
75
|
|
|
75
76
|
const visibleNodes = computed(() => {
|
|
76
77
|
const enabled = enabledRegisters.value;
|
|
77
|
-
|
|
78
|
+
const domains = showDomains.value;
|
|
79
|
+
return props.nodes.filter(n => enabled.has(n.register) && (domains || n.nodeType !== 'domain'));
|
|
78
80
|
});
|
|
79
81
|
|
|
80
82
|
const visibleNodeUris = computed(() => {
|
|
@@ -549,6 +551,14 @@ function selectedNodeColor(): string {
|
|
|
549
551
|
</div>
|
|
550
552
|
</div>
|
|
551
553
|
|
|
554
|
+
<!-- Domain/section toggle -->
|
|
555
|
+
<div class="flex items-center gap-2 mt-3">
|
|
556
|
+
<label class="flex items-center gap-1.5 cursor-pointer text-xs text-ink-500">
|
|
557
|
+
<input type="checkbox" v-model="showDomains" @change="rebuildGraph()" class="rounded border-ink-200 text-ink-800 focus:ring-ink-400 w-3.5 h-3.5" />
|
|
558
|
+
{{ t('graph.showDomains') }}
|
|
559
|
+
</label>
|
|
560
|
+
</div>
|
|
561
|
+
|
|
552
562
|
<div v-if="nodeCount === 0" class="text-xs text-ink-300 mt-3 leading-relaxed">
|
|
553
563
|
{{ props.edges.length > 0 ? t('graph.enableDatasets') : t('graph.browseToPopulate') }}
|
|
554
564
|
</div>
|
package/src/i18n/locales/eng.yml
CHANGED
|
@@ -157,6 +157,7 @@ graph.stubStatus: stub
|
|
|
157
157
|
graph.collapseControls: Collapse controls
|
|
158
158
|
graph.expandControls: Expand controls
|
|
159
159
|
graph.loading: Loading graph data...
|
|
160
|
+
graph.showDomains: Show domains/sections
|
|
160
161
|
|
|
161
162
|
# Sidebar provenance
|
|
162
163
|
sidebar.provenance: Provenance
|
package/src/i18n/locales/fra.yml
CHANGED
|
@@ -157,6 +157,7 @@ graph.stubStatus: non chargé
|
|
|
157
157
|
graph.collapseControls: Réduire les contrôles
|
|
158
158
|
graph.expandControls: Développer les contrôles
|
|
159
159
|
graph.loading: Chargement des données du graphe...
|
|
160
|
+
graph.showDomains: Afficher les domaines/sections
|
|
160
161
|
|
|
161
162
|
# Sidebar provenance
|
|
162
163
|
sidebar.provenance: Provenance
|
package/src/views/HomeView.vue
CHANGED
|
@@ -9,7 +9,7 @@ import { useI18n } from '../i18n';
|
|
|
9
9
|
const store = useVocabularyStore();
|
|
10
10
|
const router = useRouter();
|
|
11
11
|
const { getStyle } = useDsStyle();
|
|
12
|
-
const { config: siteConfig, localizedTitle, localizedSubtitle, localizedDescription } = useSiteConfig();
|
|
12
|
+
const { config: siteConfig, localizedTitle, localizedSubtitle, localizedDescription, localizedDatasetField } = useSiteConfig();
|
|
13
13
|
const { t } = useI18n();
|
|
14
14
|
const exploring = ref(false);
|
|
15
15
|
|
|
@@ -121,7 +121,7 @@ function goToGraph() { router.push({ name: 'graph' }); }
|
|
|
121
121
|
</h2>
|
|
122
122
|
</div>
|
|
123
123
|
<p v-if="filteredDatasets[0].manifest.description" class="text-sm text-ink-400 mb-4 line-clamp-2 leading-relaxed pl-6">
|
|
124
|
-
{{ filteredDatasets[0].manifest.description }}
|
|
124
|
+
{{ localizedDatasetField(filteredDatasets[0].id, 'description', filteredDatasets[0].manifest.description) }}
|
|
125
125
|
</p>
|
|
126
126
|
<div class="flex items-center gap-3 pl-6 mb-4">
|
|
127
127
|
<span :style="{ color: getStyle(filteredDatasets[0].id).color }" class="text-sm font-semibold tabular-nums">{{ filteredDatasets[0].manifest.conceptCount.toLocaleString() }}</span>
|
|
@@ -164,7 +164,7 @@ function goToGraph() { router.push({ name: 'graph' }); }
|
|
|
164
164
|
</div>
|
|
165
165
|
|
|
166
166
|
<p class="text-sm text-ink-400 mb-5 line-clamp-2 leading-relaxed pl-[22px]">
|
|
167
|
-
{{ ds.manifest.description }}
|
|
167
|
+
{{ localizedDatasetField(ds.id, 'description', ds.manifest.description) }}
|
|
168
168
|
</p>
|
|
169
169
|
|
|
170
170
|
<div class="flex items-center gap-3 pl-[22px] mb-3">
|