@glossarist/concept-browser 0.4.9 → 0.4.12
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 +1 -1
- package/src/components/AppSidebar.vue +0 -14
- package/src/components/ConceptDetail.vue +17 -9
- package/src/components/GraphPanel.vue +19 -0
- package/src/composables/use-ontology-nav.ts +0 -11
- package/src/config/types.ts +1 -0
- package/src/config/use-site-config.ts +1 -1
- package/src/views/AboutView.vue +1 -1
- package/src/views/ContributorsView.vue +1 -1
- package/src/views/NewsView.vue +1 -1
- package/src/views/PageView.vue +1 -1
- package/src/views/ResolveView.vue +1 -1
- package/src/views/StatsView.vue +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glossarist/concept-browser",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.12",
|
|
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": {
|
|
@@ -22,7 +22,6 @@ const {
|
|
|
22
22
|
taxonomyKeys,
|
|
23
23
|
taxonomyLabels,
|
|
24
24
|
treeRoots,
|
|
25
|
-
supportingClasses,
|
|
26
25
|
toggleExpand,
|
|
27
26
|
childClasses,
|
|
28
27
|
hasChildren,
|
|
@@ -167,19 +166,6 @@ function selectTaxonomy(key: string) {
|
|
|
167
166
|
</div>
|
|
168
167
|
</template>
|
|
169
168
|
|
|
170
|
-
<!-- Supporting classes -->
|
|
171
|
-
<div v-if="supportingClasses.length" class="mt-2 pt-2 border-t border-ink-100/40">
|
|
172
|
-
<div class="text-[10px] uppercase tracking-wide text-ink-300 mb-1 px-2">Supporting</div>
|
|
173
|
-
<button v-for="cls in supportingClasses" :key="cls.compact"
|
|
174
|
-
@click="selectClass(cls.compact)"
|
|
175
|
-
class="w-full flex items-center gap-1.5 px-2 py-1 rounded-lg text-[11px] transition-colors"
|
|
176
|
-
:class="activeClassId === cls.compact && !activeTaxonomy ? 'bg-ink-800/8 text-blue-700 font-medium' : 'text-ink-400 hover:bg-ink-50'"
|
|
177
|
-
>
|
|
178
|
-
<span class="w-3 text-ink-200">·</span>
|
|
179
|
-
<span class="flex-1 text-left">{{ cls.label }}</span>
|
|
180
|
-
</button>
|
|
181
|
-
</div>
|
|
182
|
-
|
|
183
169
|
<!-- SKOS Taxonomies -->
|
|
184
170
|
<div class="mt-2 pt-2 border-t border-ink-100/40">
|
|
185
171
|
<div class="text-[10px] uppercase tracking-wide text-ink-300 mb-1 px-2">Taxonomies</div>
|
|
@@ -15,6 +15,7 @@ import { useDsStyle } from '../utils/dataset-style';
|
|
|
15
15
|
import { getFactory } from '../adapters/factory';
|
|
16
16
|
import { useRenderOptions } from '../composables/use-render-options';
|
|
17
17
|
import { categorizeRelationship, relationshipLabel, relationshipDefinition } from '../utils/relationship-categories';
|
|
18
|
+
import { useSiteConfig } from '../config/use-site-config';
|
|
18
19
|
import ConceptTimeline from './ConceptTimeline.vue';
|
|
19
20
|
import ConceptRdfView from './ConceptRdfView.vue';
|
|
20
21
|
import FormatDownloads from './FormatDownloads.vue';
|
|
@@ -32,6 +33,7 @@ const props = defineProps<{
|
|
|
32
33
|
const router = useRouter();
|
|
33
34
|
const store = useVocabularyStore();
|
|
34
35
|
const { getColor } = useDsStyle();
|
|
36
|
+
const { config: siteConfig } = useSiteConfig();
|
|
35
37
|
const factory = getFactory();
|
|
36
38
|
|
|
37
39
|
const activeTab = ref<'rdf' | 'definition' | 'history'>('definition');
|
|
@@ -75,17 +77,9 @@ const languages = computed(() => {
|
|
|
75
77
|
});
|
|
76
78
|
});
|
|
77
79
|
|
|
78
|
-
// Collapsible language sections —
|
|
80
|
+
// Collapsible language sections — expand all with content, collapse those without
|
|
79
81
|
const collapsedLangs = ref(new Set<string>());
|
|
80
82
|
|
|
81
|
-
function initCollapsed(langs: string[]) {
|
|
82
|
-
if (langs.length >= 6) {
|
|
83
|
-
collapsedLangs.value = new Set(langs.filter(l => l !== 'eng'));
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
watch(languages, (langs) => { initCollapsed(langs); }, { immediate: true });
|
|
88
|
-
|
|
89
83
|
const engConcept = computed((): LocalizedConcept | null => {
|
|
90
84
|
return props.concept.localization('eng') ?? null;
|
|
91
85
|
});
|
|
@@ -192,6 +186,20 @@ function hasContent(lc: LangContent): boolean {
|
|
|
192
186
|
return !!(lc.definition || lc.notes.length || lc.examples.length || lc.sources.length);
|
|
193
187
|
}
|
|
194
188
|
|
|
189
|
+
function initCollapsed() {
|
|
190
|
+
const mainLangs = siteConfig.value?.defaults?.mainLanguages || [];
|
|
191
|
+
const mainSet = new Set(mainLangs.length ? mainLangs : ['eng']);
|
|
192
|
+
const collapsed = new Set<string>();
|
|
193
|
+
for (const lc of allLangContent.value) {
|
|
194
|
+
if (!hasContent(lc) && !mainSet.has(lc.lang)) {
|
|
195
|
+
collapsed.add(lc.lang);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
collapsedLangs.value = collapsed;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
watch(languages, () => { initCollapsed(); }, { immediate: true });
|
|
202
|
+
|
|
195
203
|
const allCollapsed = computed(() => collapsedLangs.value.size === allLangContent.value.length);
|
|
196
204
|
|
|
197
205
|
function toggleLang(lang: string) {
|
|
@@ -115,6 +115,7 @@ interface SimNode extends SimulationNodeDatum {
|
|
|
115
115
|
register: string;
|
|
116
116
|
conceptId: string;
|
|
117
117
|
designation: string;
|
|
118
|
+
altDesignations: string[];
|
|
118
119
|
hasDesignation: boolean;
|
|
119
120
|
loaded: boolean;
|
|
120
121
|
nodeType?: 'concept' | 'domain';
|
|
@@ -178,11 +179,15 @@ function buildSimulation(width: number, height: number) {
|
|
|
178
179
|
const simNodes: SimNode[] = renderNodes.map(n => {
|
|
179
180
|
const lang = uiStore.selectedLang;
|
|
180
181
|
const desig = n.designations[lang] || Object.values(n.designations)[0] || '';
|
|
182
|
+
const alts = Object.entries(n.designations)
|
|
183
|
+
.filter(([l, t]) => l !== lang && t && t !== desig)
|
|
184
|
+
.map(([, t]) => t);
|
|
181
185
|
return {
|
|
182
186
|
uri: n.uri,
|
|
183
187
|
register: n.register,
|
|
184
188
|
conceptId: n.conceptId,
|
|
185
189
|
designation: desig,
|
|
190
|
+
altDesignations: alts,
|
|
186
191
|
hasDesignation: !!n.designations[lang],
|
|
187
192
|
loaded: n.loaded,
|
|
188
193
|
nodeType: n.nodeType,
|
|
@@ -272,6 +277,20 @@ function buildSimulation(width: number, height: number) {
|
|
|
272
277
|
return '#636588';
|
|
273
278
|
});
|
|
274
279
|
|
|
280
|
+
conceptNodes.append('text')
|
|
281
|
+
.attr('dy', -9)
|
|
282
|
+
.attr('y', 7)
|
|
283
|
+
.attr('text-anchor', 'middle')
|
|
284
|
+
.attr('font-size', '6px')
|
|
285
|
+
.attr('font-family', '"DM Sans", system-ui, sans-serif')
|
|
286
|
+
.attr('fill', '#a0a1b5')
|
|
287
|
+
.attr('pointer-events', 'none')
|
|
288
|
+
.text(d => {
|
|
289
|
+
if (labelMode.value !== 'designation') return '';
|
|
290
|
+
const alts = d.altDesignations.slice(0, 2);
|
|
291
|
+
return alts.join(' · ');
|
|
292
|
+
});
|
|
293
|
+
|
|
275
294
|
const dragBehavior = drag<SVGGElement, SimNode>()
|
|
276
295
|
.on('start', (event: D3DragEvent<SVGGElement, SimNode, SimNode>, d) => {
|
|
277
296
|
if (!event.active) simulation?.alphaTarget(0.3).restart();
|
|
@@ -2,7 +2,6 @@ import { ref, computed } from 'vue';
|
|
|
2
2
|
import {
|
|
3
3
|
getClass,
|
|
4
4
|
getClassTree,
|
|
5
|
-
getAllClasses,
|
|
6
5
|
type OwlClass,
|
|
7
6
|
} from '../adapters/ontology-schema';
|
|
8
7
|
|
|
@@ -53,15 +52,6 @@ function hasChildren(cls: OwlClass): boolean {
|
|
|
53
52
|
|
|
54
53
|
const treeRoots = getClassTree();
|
|
55
54
|
|
|
56
|
-
const supportingClasses = computed(() =>
|
|
57
|
-
getAllClasses().filter(
|
|
58
|
-
c => c.children.length === 0
|
|
59
|
-
&& !c.subClassOf?.startsWith('gloss:')
|
|
60
|
-
&& c.compact !== 'gloss:Concept'
|
|
61
|
-
&& c.compact !== 'gloss:ConceptCollection'
|
|
62
|
-
)
|
|
63
|
-
);
|
|
64
|
-
|
|
65
55
|
const allNavItems = computed(() => {
|
|
66
56
|
const items: { id: string; label: string; depth: number }[] = [];
|
|
67
57
|
function walk(classes: OwlClass[], depth: number) {
|
|
@@ -82,7 +72,6 @@ export function useOntologyNav() {
|
|
|
82
72
|
taxonomyKeys,
|
|
83
73
|
taxonomyLabels,
|
|
84
74
|
treeRoots,
|
|
85
|
-
supportingClasses,
|
|
86
75
|
allNavItems,
|
|
87
76
|
toggleExpand,
|
|
88
77
|
childClasses,
|
package/src/config/types.ts
CHANGED
|
@@ -27,7 +27,7 @@ export interface RuntimeSiteConfig {
|
|
|
27
27
|
social?: Record<string, string>;
|
|
28
28
|
nav?: { label: string; route: string }[];
|
|
29
29
|
footerNav?: { label: string; route: string }[];
|
|
30
|
-
defaults?: { language?: string; languageOrder?: string[] };
|
|
30
|
+
defaults?: { language?: string; languageOrder?: string[]; mainLanguages?: string[] };
|
|
31
31
|
email?: string;
|
|
32
32
|
pages?: PageConfig[];
|
|
33
33
|
contributors?: { name: string; role?: string; organization?: string; url?: string; email?: string }[];
|
package/src/views/AboutView.vue
CHANGED
|
@@ -15,7 +15,7 @@ const manifest = computed(() => store.manifests.get(resolvedId.value));
|
|
|
15
15
|
</script>
|
|
16
16
|
|
|
17
17
|
<template>
|
|
18
|
-
<div class="max-w-
|
|
18
|
+
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
19
19
|
<!-- Breadcrumb -->
|
|
20
20
|
<nav aria-label="Breadcrumb" class="flex items-center gap-1.5 text-sm text-ink-400 mb-6">
|
|
21
21
|
<router-link :to="{ name: 'home' }" class="hover:text-ink-700 transition-colors">Home</router-link>
|
|
@@ -14,7 +14,7 @@ const contributors = config.value?.contributors as Contributor[] | undefined;
|
|
|
14
14
|
</script>
|
|
15
15
|
|
|
16
16
|
<template>
|
|
17
|
-
<div class="max-w-
|
|
17
|
+
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
18
18
|
<nav aria-label="Breadcrumb" class="flex items-center gap-1.5 text-sm text-ink-400 mb-6">
|
|
19
19
|
<router-link :to="{ name: 'home' }" class="hover:text-ink-700 transition-colors">Home</router-link>
|
|
20
20
|
<span class="text-ink-200">/</span>
|
package/src/views/NewsView.vue
CHANGED
|
@@ -78,7 +78,7 @@ function formatDate(dateStr: string) {
|
|
|
78
78
|
</script>
|
|
79
79
|
|
|
80
80
|
<template>
|
|
81
|
-
<div class="max-w-
|
|
81
|
+
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
82
82
|
<nav aria-label="Breadcrumb" class="flex items-center gap-1.5 text-sm text-ink-400 mb-6">
|
|
83
83
|
<router-link :to="{ name: 'home' }" class="hover:text-ink-700 transition-colors">Home</router-link>
|
|
84
84
|
<span class="text-ink-200">/</span>
|
package/src/views/PageView.vue
CHANGED
|
@@ -43,7 +43,7 @@ onMounted(async () => {
|
|
|
43
43
|
</script>
|
|
44
44
|
|
|
45
45
|
<template>
|
|
46
|
-
<div class="max-w-
|
|
46
|
+
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
47
47
|
<nav aria-label="Breadcrumb" class="flex items-center gap-1.5 text-sm text-ink-400 mb-6">
|
|
48
48
|
<router-link :to="{ name: 'home' }" class="hover:text-ink-700 transition-colors">Home</router-link>
|
|
49
49
|
<template v-if="registerId">
|
|
@@ -47,7 +47,7 @@ onMounted(async () => {
|
|
|
47
47
|
</script>
|
|
48
48
|
|
|
49
49
|
<template>
|
|
50
|
-
<div class="max-w-
|
|
50
|
+
<div class="max-w-5xl mx-auto px-4 py-16 text-center">
|
|
51
51
|
<template v-if="error">
|
|
52
52
|
<h1 class="text-2xl font-serif text-ink-800 mb-4">Concept not found</h1>
|
|
53
53
|
<p class="text-ink-500 mb-2">The following concept URI could not be resolved:</p>
|
package/src/views/StatsView.vue
CHANGED
|
@@ -68,7 +68,7 @@ function coverageColor(ratio: number): string {
|
|
|
68
68
|
</script>
|
|
69
69
|
|
|
70
70
|
<template>
|
|
71
|
-
<div class="max-w-
|
|
71
|
+
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
72
72
|
<!-- Breadcrumb -->
|
|
73
73
|
<nav aria-label="Breadcrumb" class="flex items-center gap-1.5 text-sm text-ink-400 mb-6">
|
|
74
74
|
<router-link :to="{ name: 'home' }" class="hover:text-ink-700 transition-colors">Home</router-link>
|