@glossarist/concept-browser 0.7.50 → 0.7.52
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 +32 -0
- package/env.d.ts +15 -0
- package/package.json +12 -2
- package/scripts/__tests__/doctor.test.mjs +147 -0
- package/scripts/doctor.mjs +327 -0
- package/scripts/generate-data.mjs +136 -0
- package/scripts/generate-ontology-data.mjs +3 -3
- package/scripts/generate-ontology-schema.mjs +3 -3
- package/scripts/lib/agents-turtle.mjs +64 -0
- package/scripts/lib/bibliography-turtle.mjs +54 -0
- package/scripts/lib/build-activity-turtle.mjs +92 -0
- package/scripts/lib/build-cache.mjs +70 -0
- package/scripts/lib/dataset-turtle.mjs +79 -0
- package/scripts/lib/turtle-escape.mjs +0 -0
- package/scripts/lib/version-turtle.mjs +56 -0
- package/scripts/lib/vocab-turtle.mjs +64 -0
- package/scripts/normalize-yaml.mjs +99 -0
- package/scripts/sync-concept-model.mjs +86 -0
- package/scripts/validate-shacl.mjs +194 -0
- package/src/__fixtures__/concept-shape.ttl +20 -0
- package/src/__fixtures__/shacl/bad/concept.ttl +7 -0
- package/src/__fixtures__/shacl/empty/.gitkeep +0 -0
- package/src/__fixtures__/shacl/good/concept.ttl +8 -0
- package/src/__tests__/__fixtures__/concepts.ts +221 -0
- package/src/__tests__/adapters/concept-identity.test.ts +76 -0
- package/src/__tests__/components/error-boundary.test.ts +109 -0
- package/src/__tests__/composables/use-dataset-series.test.ts +262 -0
- package/src/__tests__/concept-rdf/agents-emitter.test.ts +110 -0
- package/src/__tests__/concept-rdf/bibliography-emitter.test.ts +159 -0
- package/src/__tests__/concept-rdf/build-activity-emitter.test.ts +119 -0
- package/src/__tests__/concept-rdf/coerce-date.test.ts +97 -0
- package/src/__tests__/concept-rdf/concept-emitter.test.ts +258 -0
- package/src/__tests__/concept-rdf/dataset-emitter.test.ts +224 -0
- package/src/__tests__/concept-rdf/differential.test.ts +96 -0
- package/src/__tests__/concept-rdf/group-emitter.test.ts +109 -0
- package/src/__tests__/concept-rdf/image-variant-emitter.test.ts +135 -0
- package/src/__tests__/concept-rdf/jsonld-writer.test.ts +109 -0
- package/src/__tests__/concept-rdf/nonverbal-rep.test.ts +177 -0
- package/src/__tests__/concept-rdf/property-based.test.ts +179 -0
- package/src/__tests__/concept-rdf/provenance.test.ts +110 -0
- package/src/__tests__/concept-rdf/quad-isomorphism.test.ts +43 -0
- package/src/__tests__/concept-rdf/quad-isomorphism.ts +47 -0
- package/src/__tests__/concept-rdf/rdf-components.test.ts +145 -0
- package/src/__tests__/concept-rdf/rdf-graph.test.ts +115 -0
- package/src/__tests__/concept-rdf/round-trip.test.ts +243 -0
- package/src/__tests__/concept-rdf/scoped-examples.test.ts +126 -0
- package/src/__tests__/concept-rdf/sections-builder.test.ts +94 -0
- package/src/__tests__/concept-rdf/shacl-conformance.test.ts +110 -0
- package/src/__tests__/concept-rdf/shape-consistency.test.ts +138 -0
- package/src/__tests__/concept-rdf/snapshot-generation.test.ts +75 -0
- package/src/__tests__/concept-rdf/table-formula-emitter.test.ts +142 -0
- package/src/__tests__/concept-rdf/turtle-writer.test.ts +114 -0
- package/src/__tests__/concept-rdf/use-rdf-document.test.ts +246 -0
- package/src/__tests__/concept-rdf/version-emitter.test.ts +120 -0
- package/src/__tests__/concept-rdf/vocabulary-ssot.test.ts +100 -0
- package/src/__tests__/concept-rdf-view.test.ts +136 -0
- package/src/__tests__/dataset-style.test.ts +12 -7
- package/src/__tests__/errors/errors.test.ts +142 -0
- package/src/__tests__/format-downloads.test.ts +47 -65
- package/src/__tests__/markdown-lite.test.ts +19 -0
- package/src/__tests__/perf/bundle-layout.test.ts +50 -0
- package/src/__tests__/perf/serialization-perf.test.ts +121 -0
- package/src/__tests__/scripts/agents-turtle.test.ts +61 -0
- package/src/__tests__/scripts/bibliography-turtle.test.ts +59 -0
- package/src/__tests__/scripts/build-activity-turtle.test.ts +75 -0
- package/src/__tests__/scripts/build-cache.test.ts +78 -0
- package/src/__tests__/scripts/build-integration.test.ts +134 -0
- package/src/__tests__/scripts/dataset-turtle.test.ts +94 -0
- package/src/__tests__/scripts/normalize-yaml.test.ts +98 -0
- package/src/__tests__/scripts/stryker-config.test.ts +33 -0
- package/src/__tests__/scripts/turtle-escape.test.ts +63 -0
- package/src/__tests__/scripts/version-turtle.test.ts +72 -0
- package/src/__tests__/scripts/vocab-turtle.test.ts +63 -0
- package/src/__tests__/use-format-registry.test.ts +125 -0
- package/src/__tests__/utils/bcp47.test.ts +166 -0
- package/src/__tests__/utils/color-theme.test.ts +143 -0
- package/src/__tests__/utils/url-safety.test.ts +65 -0
- package/src/__tests__/validate-shacl.test.ts +100 -0
- package/src/adapters/DatasetAdapter.ts +11 -5
- package/src/adapters/GraphDataSource.ts +2 -1
- package/src/adapters/UriRouter.ts +2 -1
- package/src/adapters/concept-identity.ts +69 -0
- package/src/adapters/factory.ts +3 -2
- package/src/adapters/model-bridge.ts +2 -1
- package/src/adapters/non-verbal/figure-bridge.ts +22 -23
- package/src/adapters/non-verbal/formula-bridge.ts +11 -9
- package/src/adapters/non-verbal/glossarist-augment.d.ts +133 -0
- package/src/adapters/non-verbal/index.ts +12 -9
- package/src/adapters/non-verbal/kind.ts +2 -1
- package/src/adapters/non-verbal/table-bridge.ts +12 -10
- package/src/adapters/non-verbal/types.ts +36 -54
- package/src/adapters/non-verbal-resolver.ts +6 -3
- package/src/components/AppSidebar.vue +189 -93
- package/src/components/ConceptDetail.vue +8 -0
- package/src/components/ConceptEditionRail.vue +222 -0
- package/src/components/ConceptRdfView.vue +37 -377
- package/src/components/DatasetSeriesCard.vue +270 -0
- package/src/components/ErrorBoundary.vue +95 -0
- package/src/components/FormatDownloads.vue +17 -13
- package/src/components/HomeSeriesSection.vue +277 -0
- package/src/components/NonVerbalRepDisplay.vue +2 -2
- package/src/components/RelationSphere.vue +1672 -0
- package/src/components/SidebarSeriesSection.vue +239 -0
- package/src/components/concept-rdf/RdfInstanceHeader.vue +47 -0
- package/src/components/concept-rdf/RdfInstanceSection.vue +54 -0
- package/src/components/concept-rdf/RdfPrefixLegend.vue +27 -0
- package/src/components/concept-rdf/RdfSourcePanel.vue +72 -0
- package/src/components/concept-rdf/agents-emitter.ts +82 -0
- package/src/components/concept-rdf/bibliography-emitter.ts +83 -0
- package/src/components/concept-rdf/build-activity-emitter.ts +89 -0
- package/src/components/concept-rdf/concept-emitter.ts +443 -0
- package/src/components/concept-rdf/dataset-emitter.ts +95 -0
- package/src/components/concept-rdf/group-emitter.ts +69 -0
- package/src/components/concept-rdf/image-variant-emitter.ts +46 -0
- package/src/components/concept-rdf/jsonld-writer.ts +82 -0
- package/src/components/concept-rdf/predicates.ts +261 -0
- package/src/components/concept-rdf/provenance.ts +80 -0
- package/src/components/concept-rdf/rdf-graph.ts +211 -0
- package/src/components/concept-rdf/rdf-prefixes.ts +23 -0
- package/src/components/concept-rdf/sections-builder.ts +62 -0
- package/src/components/concept-rdf/table-formula-emitter.ts +101 -0
- package/src/components/concept-rdf/turtle-writer.ts +116 -0
- package/src/components/concept-rdf/use-rdf-document.ts +72 -0
- package/src/components/concept-rdf/version-emitter.ts +65 -0
- package/src/components/concept-rdf/vocabulary-emitter.ts +62 -0
- package/src/components/figure/FigureDisplay.vue +16 -15
- package/src/components/figure/FigureImages.vue +38 -16
- package/src/components/figure/figure-image-pick.ts +1 -1
- package/src/components/figure/figure-layout.ts +1 -1
- package/src/components/formula/FormulaDisplay.vue +11 -9
- package/src/components/formula/FormulaExpression.vue +4 -4
- package/src/components/non-verbal/NonVerbalCaption.vue +5 -5
- package/src/components/non-verbal/NonVerbalSources.vue +3 -11
- package/src/components/table/TableDisplay.vue +6 -4
- package/src/components/table/TableMarkup.vue +1 -1
- package/src/composables/use-color-theme.ts +82 -0
- package/src/composables/use-format-registry.ts +42 -0
- package/src/composables/use-non-verbal-entity.ts +2 -1
- package/src/composables/useDatasetSeries.ts +258 -0
- package/src/composables/useSphereProjection.ts +125 -0
- package/src/config/group-types.ts +92 -0
- package/src/config/types.ts +81 -2
- package/src/config/use-site-config.ts +2 -1
- package/src/errors.ts +136 -0
- package/src/i18n/locales/eng.yml +24 -0
- package/src/i18n/locales/fra.yml +24 -0
- package/src/stores/vocabulary.ts +3 -1
- package/src/style.css +17 -2
- package/src/types/agents-version-turtle.d.ts +27 -0
- package/src/types/bibliography-turtle.d.ts +12 -0
- package/src/types/build-activity-turtle.d.ts +16 -0
- package/src/types/build-cache.d.ts +20 -0
- package/src/types/dataset-turtle.d.ts +32 -0
- package/src/types/normalize-yaml.d.ts +16 -0
- package/src/types/turtle-escape.d.ts +6 -0
- package/src/types/vocab-turtle.d.ts +13 -0
- package/src/utils/asciidoc-lite.ts +11 -6
- package/src/utils/bcp47.ts +141 -0
- package/src/utils/color-theme-integration.ts +11 -0
- package/src/utils/color-theme.ts +129 -0
- package/src/utils/dataset-style.ts +31 -6
- package/src/utils/locale.ts +6 -14
- package/src/utils/markdown-lite.ts +6 -1
- package/src/utils/relation-sphere-styling.ts +63 -0
- package/src/utils/relationship-categories.ts +30 -0
- package/src/utils/url-safety.ts +30 -0
- package/src/views/ConceptView.vue +183 -9
- package/src/views/DatasetView.vue +6 -0
- package/src/views/HomeView.vue +5 -0
- package/vite.config.ts +7 -0
|
@@ -2,7 +2,9 @@
|
|
|
2
2
|
import { computed, watch, ref, onMounted, onUnmounted } from 'vue';
|
|
3
3
|
import { useRouter } from 'vue-router';
|
|
4
4
|
import { useVocabularyStore } from '../stores/vocabulary';
|
|
5
|
+
import { conceptUri } from '../adapters/model-bridge';
|
|
5
6
|
import ConceptDetail from '../components/ConceptDetail.vue';
|
|
7
|
+
import RelationSphere from '../components/RelationSphere.vue';
|
|
6
8
|
import ShortcutsModal from '../components/ShortcutsModal.vue';
|
|
7
9
|
import { useI18n } from '../i18n';
|
|
8
10
|
|
|
@@ -50,6 +52,24 @@ const concept = computed(() => store.currentConcept);
|
|
|
50
52
|
const manifest = computed(() => store.currentManifest);
|
|
51
53
|
const edges = computed(() => store.conceptEdges);
|
|
52
54
|
const adjacent = ref({ prev: null as string | null, next: null as string | null });
|
|
55
|
+
const viewMode = ref<'detail' | 'sphere'>('detail');
|
|
56
|
+
|
|
57
|
+
/* When the user clicks a card in the sphere, we store the navigation
|
|
58
|
+
payload here. The concept loads via store.viewConcept (without
|
|
59
|
+
router.push). When the user switches to Detail, we commit the URL. */
|
|
60
|
+
const sphereFocusPayload = ref<{ registerId: string; conceptId: string } | null>(null);
|
|
61
|
+
const permalinkCopied = ref(false);
|
|
62
|
+
|
|
63
|
+
async function copyPermalink() {
|
|
64
|
+
try {
|
|
65
|
+
await navigator.clipboard.writeText(window.location.href);
|
|
66
|
+
permalinkCopied.value = true;
|
|
67
|
+
setTimeout(() => { permalinkCopied.value = false; }, 1800);
|
|
68
|
+
} catch {
|
|
69
|
+
/* Clipboard API not available — fall back to URL prompt */
|
|
70
|
+
window.prompt('Copy this URL:', window.location.href);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
53
73
|
|
|
54
74
|
async function loadAdjacent() {
|
|
55
75
|
const adapter = store.datasets.get(props.registerId);
|
|
@@ -66,6 +86,45 @@ function goAdjacent(id: string) {
|
|
|
66
86
|
window.scrollTo({ top: 0, behavior: 'smooth' });
|
|
67
87
|
}
|
|
68
88
|
|
|
89
|
+
function onSphereNavigate(payload: { registerId: string; conceptId: string }) {
|
|
90
|
+
if (!payload.registerId || !payload.conceptId) return;
|
|
91
|
+
/* DON'T router.push — that sets conceptLoading=true and unmounts the
|
|
92
|
+
sphere. Instead, load the concept directly via the store. This
|
|
93
|
+
updates store.currentConcept + store.conceptEdges, which flow as
|
|
94
|
+
props to RelationSphere without any loading flash. The sphere's
|
|
95
|
+
watch on props.concept fires → rebuilds the graph → animates. */
|
|
96
|
+
sphereFocusPayload.value = { registerId: payload.registerId, conceptId: payload.conceptId };
|
|
97
|
+
(async () => {
|
|
98
|
+
try {
|
|
99
|
+
const adapter = store.datasets.get(payload.registerId);
|
|
100
|
+
if (!adapter?.index) {
|
|
101
|
+
await store.loadDataset(payload.registerId);
|
|
102
|
+
}
|
|
103
|
+
await store.viewConcept(payload.registerId, payload.conceptId);
|
|
104
|
+
loadAdjacent();
|
|
105
|
+
} catch (e) {
|
|
106
|
+
console.warn('Sphere navigation failed:', e);
|
|
107
|
+
}
|
|
108
|
+
})();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function switchToSphere() {
|
|
112
|
+
viewMode.value = 'sphere';
|
|
113
|
+
sphereFocusPayload.value = null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function switchToDetail() {
|
|
117
|
+
viewMode.value = 'detail';
|
|
118
|
+
/* Commit the URL if the sphere navigated to a different concept.
|
|
119
|
+
This triggers loadConcept → the Detail view shows the right concept. */
|
|
120
|
+
if (sphereFocusPayload.value) {
|
|
121
|
+
const { registerId, conceptId } = sphereFocusPayload.value;
|
|
122
|
+
if (registerId !== props.registerId || conceptId !== props.conceptId) {
|
|
123
|
+
router.push({ name: 'concept', params: { registerId, conceptId } });
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
69
128
|
function onKeydown(e: KeyboardEvent) {
|
|
70
129
|
if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;
|
|
71
130
|
|
|
@@ -78,6 +137,17 @@ function onKeydown(e: KeyboardEvent) {
|
|
|
78
137
|
showShortcuts.value = false;
|
|
79
138
|
return;
|
|
80
139
|
}
|
|
140
|
+
/* View mode toggle: 's' for sphere, 'd' for detail */
|
|
141
|
+
if (e.key === 's' && concept.value) {
|
|
142
|
+
e.preventDefault();
|
|
143
|
+
switchToSphere();
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (e.key === 'd') {
|
|
147
|
+
e.preventDefault();
|
|
148
|
+
switchToDetail();
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
81
151
|
if (e.key === 'j' && adjacent.value.prev) {
|
|
82
152
|
e.preventDefault();
|
|
83
153
|
goAdjacent(adjacent.value.prev);
|
|
@@ -92,7 +162,68 @@ onUnmounted(() => window.removeEventListener('keydown', onKeydown));
|
|
|
92
162
|
</script>
|
|
93
163
|
|
|
94
164
|
<template>
|
|
95
|
-
<div class="
|
|
165
|
+
<div :class="['concept-view', { 'sphere-mode': viewMode === 'sphere' }]">
|
|
166
|
+
<!-- View mode toolbar — slim sub-header with segmented control + permalink.
|
|
167
|
+
Sits ABOVE the content (not floating, doesn't block anything). -->
|
|
168
|
+
<div
|
|
169
|
+
v-if="!conceptLoading && !localError && concept"
|
|
170
|
+
class="flex-shrink-0 w-full max-w-7xl mx-auto mb-4 flex items-center justify-between gap-4 pb-3 border-b border-ink-100 dark:border-ink-700"
|
|
171
|
+
>
|
|
172
|
+
<nav aria-label="View mode" class="inline-flex gap-1 p-1 rounded-lg bg-surface-alt dark:bg-ink-800" role="tablist">
|
|
173
|
+
<button
|
|
174
|
+
role="tab"
|
|
175
|
+
:aria-selected="viewMode === 'detail'"
|
|
176
|
+
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-[13px] font-medium rounded-md cursor-pointer transition-all border-none font-inherit"
|
|
177
|
+
:class="viewMode === 'detail'
|
|
178
|
+
? 'bg-surface-raised dark:bg-ink-600 text-ink-800 dark:text-ink-50 shadow-sm'
|
|
179
|
+
: 'bg-transparent text-ink-500 dark:text-ink-400 hover:text-ink-700 dark:hover:text-ink-200'"
|
|
180
|
+
@click="switchToDetail"
|
|
181
|
+
title="Detail view (d)"
|
|
182
|
+
>
|
|
183
|
+
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
184
|
+
<path d="M4 6h16M4 12h16M4 18h10" stroke-linecap="round"/>
|
|
185
|
+
</svg>
|
|
186
|
+
<span>{{ t('concept.detailView') }}</span>
|
|
187
|
+
<kbd class="ml-1 px-1 py-0.5 font-mono text-[9px] font-semibold rounded bg-ink-100 dark:bg-ink-700 text-ink-500 dark:text-ink-400 tracking-wide">d</kbd>
|
|
188
|
+
</button>
|
|
189
|
+
<button
|
|
190
|
+
role="tab"
|
|
191
|
+
:aria-selected="viewMode === 'sphere'"
|
|
192
|
+
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-[13px] font-medium rounded-md cursor-pointer transition-all border-none font-inherit"
|
|
193
|
+
:class="viewMode === 'sphere'
|
|
194
|
+
? 'bg-surface-raised dark:bg-ink-600 text-ink-800 dark:text-ink-50 shadow-sm'
|
|
195
|
+
: 'bg-transparent text-ink-500 dark:text-ink-400 hover:text-ink-700 dark:hover:text-ink-200'"
|
|
196
|
+
@click="switchToSphere"
|
|
197
|
+
title="Relation sphere view (s)"
|
|
198
|
+
>
|
|
199
|
+
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
200
|
+
<circle cx="12" cy="12" r="9"/>
|
|
201
|
+
<ellipse cx="12" cy="12" rx="9" ry="3.5"/>
|
|
202
|
+
<ellipse cx="12" cy="12" rx="3.5" ry="9"/>
|
|
203
|
+
</svg>
|
|
204
|
+
<span>{{ t('concept.relationSphere') }}</span>
|
|
205
|
+
<kbd class="ml-1 px-1 py-0.5 font-mono text-[9px] font-semibold rounded bg-ink-100 dark:bg-ink-700 text-ink-500 dark:text-ink-400 tracking-wide">s</kbd>
|
|
206
|
+
</button>
|
|
207
|
+
</nav>
|
|
208
|
+
|
|
209
|
+
<div class="flex items-center gap-2.5">
|
|
210
|
+
<button
|
|
211
|
+
class="inline-flex items-center gap-1.5 px-3 py-1.5 text-[13px] font-medium text-ink-500 dark:text-ink-400 bg-transparent border border-ink-100 dark:border-ink-700 rounded-md cursor-pointer transition-all font-inherit hover:text-ink-800 dark:hover:text-ink-100 hover:bg-surface-raised dark:hover:bg-ink-700 hover:border-ink-200 dark:hover:border-ink-600"
|
|
212
|
+
title="Copy permalink to this concept"
|
|
213
|
+
@click="copyPermalink"
|
|
214
|
+
>
|
|
215
|
+
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
216
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101"/>
|
|
217
|
+
<path stroke-linecap="round" stroke-linejoin="round" d="M10.172 13.828a4 4 0 005.656 0l4-4a4 4 0 10-5.656-5.656l-1.1 1.1"/>
|
|
218
|
+
</svg>
|
|
219
|
+
<span>{{ t('concept.permalink') }}</span>
|
|
220
|
+
</button>
|
|
221
|
+
<Transition name="fade">
|
|
222
|
+
<span v-if="permalinkCopied" class="text-xs font-semibold text-green-600 dark:text-green-400">{{ t('concept.copied') }}</span>
|
|
223
|
+
</Transition>
|
|
224
|
+
</div>
|
|
225
|
+
</div>
|
|
226
|
+
|
|
96
227
|
<div v-if="conceptLoading" class="max-w-5xl mx-auto py-8 space-y-5">
|
|
97
228
|
<!-- Breadcrumb skeleton -->
|
|
98
229
|
<div class="flex items-center gap-1.5">
|
|
@@ -141,15 +272,58 @@ onUnmounted(() => window.removeEventListener('keydown', onKeydown));
|
|
|
141
272
|
</router-link>
|
|
142
273
|
</div>
|
|
143
274
|
</div>
|
|
144
|
-
<
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
275
|
+
<template v-else-if="concept && manifest">
|
|
276
|
+
<div class="concept-content" :class="{ 'sphere-content': viewMode === 'sphere' }">
|
|
277
|
+
<!-- Sphere mode — receives concept + edges directly, no URI matching -->
|
|
278
|
+
<RelationSphere
|
|
279
|
+
v-if="viewMode === 'sphere'"
|
|
280
|
+
:concept="concept"
|
|
281
|
+
:manifest="manifest"
|
|
282
|
+
:register-id="registerId"
|
|
283
|
+
:edges="edges"
|
|
284
|
+
@navigate="onSphereNavigate"
|
|
285
|
+
/>
|
|
286
|
+
<!-- Detail mode -->
|
|
287
|
+
<ConceptDetail
|
|
288
|
+
v-else
|
|
289
|
+
:concept="concept"
|
|
290
|
+
:manifest="manifest"
|
|
291
|
+
:edges="edges"
|
|
292
|
+
:adjacent="adjacent"
|
|
293
|
+
:register-id="registerId"
|
|
294
|
+
/>
|
|
295
|
+
</div>
|
|
296
|
+
</template>
|
|
152
297
|
|
|
153
298
|
<ShortcutsModal v-if="showShortcuts" @close="showShortcuts = false" />
|
|
154
299
|
</div>
|
|
155
300
|
</template>
|
|
301
|
+
|
|
302
|
+
<style scoped>
|
|
303
|
+
.concept-view {
|
|
304
|
+
display: flex;
|
|
305
|
+
flex-direction: column;
|
|
306
|
+
position: relative;
|
|
307
|
+
padding: 1rem;
|
|
308
|
+
min-height: calc(100vh - 56px);
|
|
309
|
+
}
|
|
310
|
+
.concept-view.sphere-mode {
|
|
311
|
+
height: calc(100vh - 56px);
|
|
312
|
+
overflow: hidden;
|
|
313
|
+
}
|
|
314
|
+
.concept-content {
|
|
315
|
+
flex: 1;
|
|
316
|
+
min-height: 0;
|
|
317
|
+
width: 100%;
|
|
318
|
+
max-width: 80rem;
|
|
319
|
+
margin: 0 auto;
|
|
320
|
+
}
|
|
321
|
+
.concept-content.sphere-content {
|
|
322
|
+
position: relative;
|
|
323
|
+
overflow: hidden;
|
|
324
|
+
display: flex;
|
|
325
|
+
flex-direction: column;
|
|
326
|
+
}
|
|
327
|
+
.fade-enter-active, .fade-leave-active { transition: opacity 0.2s; }
|
|
328
|
+
.fade-enter-from, .fade-leave-to { opacity: 0; }
|
|
329
|
+
</style>
|
|
@@ -7,6 +7,7 @@ import { useDatasetLoader } from '../composables/use-dataset-loader';
|
|
|
7
7
|
import { FORMAT_LABELS } from '../config/types';
|
|
8
8
|
import { langName, langLabel, sortLanguages } from '../utils/lang';
|
|
9
9
|
import ConceptCard from '../components/ConceptCard.vue';
|
|
10
|
+
import DatasetSeriesCard from '../components/DatasetSeriesCard.vue';
|
|
10
11
|
import { useI18n, locale } from '../i18n';
|
|
11
12
|
import { useSiteConfig } from '../config/use-site-config';
|
|
12
13
|
import type { SectionNode, ConceptSummary } from '../adapters/types';
|
|
@@ -321,6 +322,11 @@ function clearSection() {
|
|
|
321
322
|
</div>
|
|
322
323
|
</div>
|
|
323
324
|
|
|
325
|
+
<!-- Edition series sidebar (only renders if this dataset belongs to a multi-edition series) -->
|
|
326
|
+
<div v-if="manifest" class="mb-6">
|
|
327
|
+
<DatasetSeriesCard :register-id="registerId" />
|
|
328
|
+
</div>
|
|
329
|
+
|
|
324
330
|
<!-- Downloads -->
|
|
325
331
|
<div v-if="bulkDownloads.length" class="card p-4 mb-6">
|
|
326
332
|
<h3 class="text-xs font-semibold text-ink-400 uppercase tracking-wide mb-3">{{ t('dataset.download') }}</h3>
|
package/src/views/HomeView.vue
CHANGED
|
@@ -5,6 +5,7 @@ import { useRouter } from 'vue-router';
|
|
|
5
5
|
import { useDsStyle } from '../utils/dataset-style';
|
|
6
6
|
import { useSiteConfig } from '../config/use-site-config';
|
|
7
7
|
import { useI18n } from '../i18n';
|
|
8
|
+
import HomeSeriesSection from '../components/HomeSeriesSection.vue';
|
|
8
9
|
|
|
9
10
|
const store = useVocabularyStore();
|
|
10
11
|
const router = useRouter();
|
|
@@ -74,6 +75,10 @@ function goToGraph() { router.push({ name: 'graph' }); }
|
|
|
74
75
|
<p class="text-base text-ink-400 max-w-lg leading-relaxed">
|
|
75
76
|
{{ localizedDescription || 'Explore standardized terminology datasets from ISO and IEC technical committees. Browse concepts, definitions, and cross-references across multilingual vocabularies.' }}
|
|
76
77
|
</p>
|
|
78
|
+
|
|
79
|
+
<!-- Edition-series section (renders only if multi-edition series exist) -->
|
|
80
|
+
<HomeSeriesSection />
|
|
81
|
+
|
|
77
82
|
<div class="flex flex-wrap gap-3 mt-7">
|
|
78
83
|
<button @click="goToSearch" class="btn-primary flex items-center gap-2">
|
|
79
84
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/></svg>
|
package/vite.config.ts
CHANGED
|
@@ -10,6 +10,10 @@ const cwd = process.cwd()
|
|
|
10
10
|
|
|
11
11
|
const isTest = process.env.VITEST !== undefined
|
|
12
12
|
|
|
13
|
+
const pkgVersion = JSON.parse(
|
|
14
|
+
readFileSync(resolve(__dirname, 'package.json'), 'utf8'),
|
|
15
|
+
).version
|
|
16
|
+
|
|
13
17
|
function yamlPlugin() {
|
|
14
18
|
return {
|
|
15
19
|
name: 'yaml-transform',
|
|
@@ -170,6 +174,9 @@ export default defineConfig({
|
|
|
170
174
|
} : {}),
|
|
171
175
|
},
|
|
172
176
|
},
|
|
177
|
+
define: {
|
|
178
|
+
__CONCEPT_BROWSER_VERSION__: JSON.stringify(pkgVersion),
|
|
179
|
+
},
|
|
173
180
|
test: {
|
|
174
181
|
environment: 'happy-dom',
|
|
175
182
|
globals: true,
|