@glossarist/concept-browser 0.4.8 → 0.4.11
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/README.md +23 -0
- package/package.json +1 -1
- package/src/components/AppSidebar.vue +22 -32
- package/src/composables/use-ontology-nav.ts +7 -19
- package/src/router/index.ts +10 -0
- package/src/views/OntologySchemaView.vue +43 -41
package/README.md
CHANGED
|
@@ -159,6 +159,29 @@ datasets:
|
|
|
159
159
|
| `externalConceptUrlTemplate` | no | URL template for linking to the official source of each concept. `{conceptId}` is replaced with the concept ID. |
|
|
160
160
|
| `languageOrder` | no | Array of ISO 639-2 language codes controlling the display order on concept pages. Without this, languages default to English-first then alphabetical. |
|
|
161
161
|
|
|
162
|
+
### Site features
|
|
163
|
+
|
|
164
|
+
The `features` section in `site-config.yml` toggles functionality and customizes branding:
|
|
165
|
+
|
|
166
|
+
```yaml
|
|
167
|
+
features:
|
|
168
|
+
news: true # enable news posts (requires newsDir)
|
|
169
|
+
stats: true # show statistics dashboard
|
|
170
|
+
graph: true # enable concept graph visualization
|
|
171
|
+
about: true # enable about page
|
|
172
|
+
search: true # enable full-text search
|
|
173
|
+
poweredBy: # customize the sidebar/footer credit link
|
|
174
|
+
message: "Powered by Acme Corp"
|
|
175
|
+
url: "https://example.com"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
| Field | Default | Description |
|
|
179
|
+
|-------|---------|-------------|
|
|
180
|
+
| `poweredBy.message` | `Built with the Glossarist Concept Browser` | Link text shown in sidebar and footer |
|
|
181
|
+
| `poweredBy.url` | `https://github.com/glossarist/concept-browser` | Link href |
|
|
182
|
+
|
|
183
|
+
Omit the `poweredBy` block to use defaults. The `message` becomes the full text of a clickable link — there is no hardcoded prefix.
|
|
184
|
+
|
|
162
185
|
### Cross-reference mapping
|
|
163
186
|
|
|
164
187
|
The top-level `crossReferences` section maps inline references to dataset IDs:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@glossarist/concept-browser",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.11",
|
|
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": {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
import { computed
|
|
2
|
+
import { computed } from 'vue';
|
|
3
3
|
import { useVocabularyStore } from '../stores/vocabulary';
|
|
4
4
|
import { useUiStore } from '../stores/ui';
|
|
5
5
|
import { useRoute, useRouter } from 'vue-router';
|
|
6
6
|
import { useDsStyle } from '../utils/dataset-style';
|
|
7
7
|
import { useSiteConfig } from '../config/use-site-config';
|
|
8
|
-
import { useOntologyNav } from '../composables/use-ontology-nav';
|
|
8
|
+
import { useOntologyNav, compactToSlug } from '../composables/use-ontology-nav';
|
|
9
9
|
import NavIcon from './NavIcon.vue';
|
|
10
10
|
|
|
11
11
|
const store = useVocabularyStore();
|
|
@@ -18,20 +18,31 @@ const { globalPages, datasetPages, config: siteConfig } = useSiteConfig();
|
|
|
18
18
|
const currentDataset = computed(() => route.params.registerId as string ?? '');
|
|
19
19
|
|
|
20
20
|
const {
|
|
21
|
-
activeClassId,
|
|
22
|
-
activeTaxonomy,
|
|
23
21
|
expandedClasses,
|
|
24
22
|
taxonomyKeys,
|
|
25
23
|
taxonomyLabels,
|
|
26
24
|
treeRoots,
|
|
27
|
-
supportingClasses,
|
|
28
|
-
isOverview,
|
|
29
25
|
toggleExpand,
|
|
30
26
|
childClasses,
|
|
31
27
|
hasChildren,
|
|
32
28
|
} = useOntologyNav();
|
|
33
29
|
|
|
34
|
-
const isOntologyRoute = computed(() =>
|
|
30
|
+
const isOntologyRoute = computed(() =>
|
|
31
|
+
route.name === 'ontology' || route.name === 'ontology-class' || route.name === 'ontology-taxonomy'
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
const activeClassId = computed(() => {
|
|
35
|
+
if (route.name !== 'ontology-class') return null;
|
|
36
|
+
const slug = route.params.classId as string;
|
|
37
|
+
return slug.replace(/-/g, ':');
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const activeTaxonomy = computed(() => {
|
|
41
|
+
if (route.name !== 'ontology-taxonomy') return null;
|
|
42
|
+
return route.params.taxonomyKey as string;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
const isOverview = computed(() => route.name === 'ontology');
|
|
35
46
|
|
|
36
47
|
const datasetEntries = computed(() => {
|
|
37
48
|
const entries: { id: string; title: string; loaded: boolean; conceptCount: number }[] = [];
|
|
@@ -75,19 +86,11 @@ function isActive(page: { route: string; datasetScoped?: boolean }): boolean {
|
|
|
75
86
|
}
|
|
76
87
|
|
|
77
88
|
function selectClass(id: string) {
|
|
78
|
-
|
|
79
|
-
activeTaxonomy.value = null;
|
|
80
|
-
scrollMainToTop();
|
|
89
|
+
router.push(`/ontology/class/${compactToSlug(id)}`);
|
|
81
90
|
}
|
|
82
91
|
|
|
83
92
|
function selectTaxonomy(key: string) {
|
|
84
|
-
|
|
85
|
-
scrollMainToTop();
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function scrollMainToTop() {
|
|
89
|
-
const main = document.querySelector('main');
|
|
90
|
-
if (main) main.scrollTo({ top: 0, behavior: 'smooth' });
|
|
93
|
+
router.push(`/ontology/taxonomy/${key}`);
|
|
91
94
|
}
|
|
92
95
|
</script>
|
|
93
96
|
|
|
@@ -119,13 +122,13 @@ function scrollMainToTop() {
|
|
|
119
122
|
<!-- Ontology class tree nested under Ontology nav item -->
|
|
120
123
|
<div v-if="page.route === 'ontology' && isOntologyRoute" class="ml-4 mt-1 mb-2 space-y-0.5">
|
|
121
124
|
<!-- Overview -->
|
|
122
|
-
<
|
|
125
|
+
<router-link to="/ontology"
|
|
123
126
|
class="w-full flex items-center gap-1.5 px-2 py-1.5 rounded-lg text-xs transition-colors"
|
|
124
127
|
:class="isOverview ? 'bg-ink-800/8 text-blue-700 font-medium' : 'text-ink-600 hover:bg-ink-50'"
|
|
125
128
|
>
|
|
126
129
|
<span class="w-3 text-ink-200">·</span>
|
|
127
130
|
<span class="flex-1 text-left">Overview</span>
|
|
128
|
-
</
|
|
131
|
+
</router-link>
|
|
129
132
|
|
|
130
133
|
<div class="text-[10px] uppercase tracking-wide text-ink-300 mt-2 mb-1 px-2">Classes</div>
|
|
131
134
|
<template v-for="root in treeRoots" :key="root.compact">
|
|
@@ -163,19 +166,6 @@ function scrollMainToTop() {
|
|
|
163
166
|
</div>
|
|
164
167
|
</template>
|
|
165
168
|
|
|
166
|
-
<!-- Supporting classes -->
|
|
167
|
-
<div v-if="supportingClasses.length" class="mt-2 pt-2 border-t border-ink-100/40">
|
|
168
|
-
<div class="text-[10px] uppercase tracking-wide text-ink-300 mb-1 px-2">Supporting</div>
|
|
169
|
-
<button v-for="cls in supportingClasses" :key="cls.compact"
|
|
170
|
-
@click="selectClass(cls.compact)"
|
|
171
|
-
class="w-full flex items-center gap-1.5 px-2 py-1 rounded-lg text-[11px] transition-colors"
|
|
172
|
-
:class="activeClassId === cls.compact && !activeTaxonomy ? 'bg-ink-800/8 text-blue-700 font-medium' : 'text-ink-400 hover:bg-ink-50'"
|
|
173
|
-
>
|
|
174
|
-
<span class="w-3 text-ink-200">·</span>
|
|
175
|
-
<span class="flex-1 text-left">{{ cls.label }}</span>
|
|
176
|
-
</button>
|
|
177
|
-
</div>
|
|
178
|
-
|
|
179
169
|
<!-- SKOS Taxonomies -->
|
|
180
170
|
<div class="mt-2 pt-2 border-t border-ink-100/40">
|
|
181
171
|
<div class="text-[10px] uppercase tracking-wide text-ink-300 mb-1 px-2">Taxonomies</div>
|
|
@@ -2,14 +2,17 @@ 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
|
|
|
9
|
-
|
|
8
|
+
export function slugToCompact(slug: string): string {
|
|
9
|
+
return slug.replace(/-/g, ':');
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function compactToSlug(compact: string): string {
|
|
13
|
+
return compact.replace(/:/g, '-');
|
|
14
|
+
}
|
|
10
15
|
|
|
11
|
-
const activeClassId = ref<string | null>(null);
|
|
12
|
-
const activeTaxonomy = ref<string | null>(null);
|
|
13
16
|
const expandedClasses = ref(new Set<string>(['gloss:Designation']));
|
|
14
17
|
|
|
15
18
|
const taxonomyKeys = [
|
|
@@ -49,17 +52,6 @@ function hasChildren(cls: OwlClass): boolean {
|
|
|
49
52
|
|
|
50
53
|
const treeRoots = getClassTree();
|
|
51
54
|
|
|
52
|
-
const supportingClasses = computed(() =>
|
|
53
|
-
getAllClasses().filter(
|
|
54
|
-
c => c.children.length === 0
|
|
55
|
-
&& !c.subClassOf?.startsWith('gloss:')
|
|
56
|
-
&& c.compact !== 'gloss:Concept'
|
|
57
|
-
&& c.compact !== 'gloss:ConceptCollection'
|
|
58
|
-
)
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
const isOverview = computed(() => activeClassId.value === null && activeTaxonomy.value === null);
|
|
62
|
-
|
|
63
55
|
const allNavItems = computed(() => {
|
|
64
56
|
const items: { id: string; label: string; depth: number }[] = [];
|
|
65
57
|
function walk(classes: OwlClass[], depth: number) {
|
|
@@ -76,15 +68,11 @@ const allNavItems = computed(() => {
|
|
|
76
68
|
|
|
77
69
|
export function useOntologyNav() {
|
|
78
70
|
return {
|
|
79
|
-
activeClassId,
|
|
80
|
-
activeTaxonomy,
|
|
81
71
|
expandedClasses,
|
|
82
72
|
taxonomyKeys,
|
|
83
73
|
taxonomyLabels,
|
|
84
74
|
treeRoots,
|
|
85
|
-
supportingClasses,
|
|
86
75
|
allNavItems,
|
|
87
|
-
isOverview,
|
|
88
76
|
toggleExpand,
|
|
89
77
|
childClasses,
|
|
90
78
|
hasChildren,
|
package/src/router/index.ts
CHANGED
|
@@ -45,6 +45,16 @@ export const routes: RouteRecordRaw[] = [
|
|
|
45
45
|
name: 'ontology',
|
|
46
46
|
component: () => import('../views/OntologySchemaView.vue'),
|
|
47
47
|
},
|
|
48
|
+
{
|
|
49
|
+
path: '/ontology/class/:classId',
|
|
50
|
+
name: 'ontology-class',
|
|
51
|
+
component: () => import('../views/OntologySchemaView.vue'),
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
path: '/ontology/taxonomy/:taxonomyKey',
|
|
55
|
+
name: 'ontology-taxonomy',
|
|
56
|
+
component: () => import('../views/OntologySchemaView.vue'),
|
|
57
|
+
},
|
|
48
58
|
{
|
|
49
59
|
path: '/news',
|
|
50
60
|
name: 'news',
|
|
@@ -1,22 +1,34 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { computed, watch, nextTick } from 'vue';
|
|
3
|
+
import { useRoute } from 'vue-router';
|
|
3
4
|
import { getClass, getAllPropertiesForClass, getAllClasses, getStats } from '../adapters/ontology-schema';
|
|
4
5
|
import { ontology, type TaxonomyConcept } from '../adapters/ontology-registry';
|
|
5
|
-
import { useOntologyNav } from '../composables/use-ontology-nav';
|
|
6
|
+
import { useOntologyNav, slugToCompact, compactToSlug } from '../composables/use-ontology-nav';
|
|
6
7
|
|
|
8
|
+
const route = useRoute();
|
|
7
9
|
const stats = getStats();
|
|
8
10
|
|
|
9
11
|
const {
|
|
10
|
-
activeClassId,
|
|
11
|
-
activeTaxonomy,
|
|
12
12
|
taxonomyLabels,
|
|
13
13
|
allNavItems,
|
|
14
|
-
isOverview,
|
|
15
14
|
treeRoots,
|
|
16
15
|
hasChildren,
|
|
17
16
|
childClasses,
|
|
18
17
|
} = useOntologyNav();
|
|
19
18
|
|
|
19
|
+
const activeClassId = computed(() => {
|
|
20
|
+
if (route.name !== 'ontology-class') return null;
|
|
21
|
+
const slug = route.params.classId as string;
|
|
22
|
+
return slugToCompact(slug);
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const activeTaxonomy = computed(() => {
|
|
26
|
+
if (route.name !== 'ontology-taxonomy') return null;
|
|
27
|
+
return route.params.taxonomyKey as string;
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const isOverview = computed(() => route.name === 'ontology');
|
|
31
|
+
|
|
20
32
|
const activeClass = computed(() => activeClassId.value ? getClass(activeClassId.value) : null);
|
|
21
33
|
const activeProperties = computed(() => activeClassId.value ? getAllPropertiesForClass(activeClassId.value) : { object: [], datatype: [] });
|
|
22
34
|
|
|
@@ -28,7 +40,7 @@ function activeTaxonomyData() {
|
|
|
28
40
|
return { scheme: ontology.getScheme(key), concepts: all, top };
|
|
29
41
|
}
|
|
30
42
|
|
|
31
|
-
watch(
|
|
43
|
+
watch(() => route.fullPath, () => {
|
|
32
44
|
nextTick(() => {
|
|
33
45
|
const main = document.querySelector('main');
|
|
34
46
|
if (main) main.scrollTo({ top: 0 });
|
|
@@ -60,32 +72,11 @@ const allClasses = getAllClasses();
|
|
|
60
72
|
<code class="block text-xs text-ink-400 mt-2">https://www.glossarist.org/ontologies/glossarist</code>
|
|
61
73
|
</div>
|
|
62
74
|
|
|
63
|
-
<!-- Sticky mobile chips (for small screens where sidebar is hidden) -->
|
|
64
|
-
<div class="lg:hidden sticky top-14 z-10 bg-surface -mx-4 px-4 py-2 border-b border-ink-100/60 mb-4">
|
|
65
|
-
<div class="flex gap-2 overflow-x-auto scrollbar-none">
|
|
66
|
-
<button v-for="item in allNavItems" :key="item.id"
|
|
67
|
-
@click="activeClassId = item.id; activeTaxonomy = null"
|
|
68
|
-
class="flex-shrink-0 px-3 py-2.5 rounded-lg text-xs font-medium whitespace-nowrap transition-colors min-h-[44px] flex items-center gap-1.5"
|
|
69
|
-
:class="activeClassId === item.id && !activeTaxonomy
|
|
70
|
-
? 'bg-ink-800 text-white'
|
|
71
|
-
: 'bg-surface-raised border border-ink-100 text-ink-600 hover:bg-ink-50'"
|
|
72
|
-
>
|
|
73
|
-
{{ item.label }}
|
|
74
|
-
</button>
|
|
75
|
-
<button @click="activeTaxonomy = activeTaxonomy ? null : 'conceptStatus'"
|
|
76
|
-
class="flex-shrink-0 px-3 py-2.5 rounded-lg text-xs font-medium whitespace-nowrap transition-colors min-h-[44px] flex items-center gap-1.5"
|
|
77
|
-
:class="activeTaxonomy
|
|
78
|
-
? 'bg-ink-800 text-white'
|
|
79
|
-
: 'bg-surface-raised border border-ink-100 text-ink-600 hover:bg-ink-50'"
|
|
80
|
-
>Taxonomies</button>
|
|
81
|
-
</div>
|
|
82
|
-
</div>
|
|
83
|
-
|
|
84
75
|
<h2 class="text-lg font-semibold text-ink-800 mb-4">Class Overview</h2>
|
|
85
76
|
<div class="grid gap-3 sm:grid-cols-2">
|
|
86
|
-
<
|
|
87
|
-
|
|
88
|
-
class="border border-ink-100/60 rounded-lg p-3 cursor-pointer hover:border-ink-200 hover:bg-ink-50/50 transition-colors">
|
|
77
|
+
<router-link v-for="cls in allClasses" :key="cls.compact"
|
|
78
|
+
:to="`/ontology/class/${compactToSlug(cls.compact)}`"
|
|
79
|
+
class="border border-ink-100/60 rounded-lg p-3 cursor-pointer hover:border-ink-200 hover:bg-ink-50/50 transition-colors block">
|
|
89
80
|
<div class="flex items-center gap-2">
|
|
90
81
|
<span class="text-sm font-medium text-ink-700">{{ cls.label }}</span>
|
|
91
82
|
<code class="text-[10px] text-ink-400 bg-ink-50 px-1.5 py-0.5 rounded">{{ cls.compact }}</code>
|
|
@@ -94,16 +85,30 @@ const allClasses = getAllClasses();
|
|
|
94
85
|
<div v-if="cls.subClassOf" class="text-[10px] text-ink-300 mt-1">
|
|
95
86
|
subClassOf <code class="text-ink-400">{{ cls.subClassOf }}</code>
|
|
96
87
|
</div>
|
|
97
|
-
</
|
|
88
|
+
</router-link>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<h2 class="text-lg font-semibold text-ink-800 mt-8 mb-4">Taxonomies</h2>
|
|
92
|
+
<div class="grid gap-3 sm:grid-cols-2">
|
|
93
|
+
<router-link v-for="tk in ['conceptStatus', 'entryStatus', 'normativeStatus', 'sourceType', 'sourceStatus', 'relationshipType', 'designationType', 'termType', 'grammarGender', 'grammarNumber']" :key="tk"
|
|
94
|
+
:to="`/ontology/taxonomy/${tk}`"
|
|
95
|
+
class="border border-ink-100/60 rounded-lg p-3 cursor-pointer hover:border-ink-200 hover:bg-ink-50/50 transition-colors block">
|
|
96
|
+
<span class="text-sm font-medium text-ink-700">{{ taxonomyLabels[tk] }}</span>
|
|
97
|
+
</router-link>
|
|
98
98
|
</div>
|
|
99
99
|
</template>
|
|
100
100
|
|
|
101
|
-
<!-- Class detail
|
|
101
|
+
<!-- Class detail -->
|
|
102
102
|
<template v-if="!activeTaxonomy && activeClass">
|
|
103
|
-
<!-- Breadcrumb -->
|
|
104
103
|
<nav class="flex items-center gap-1.5 text-sm text-ink-400 mb-4">
|
|
105
|
-
<
|
|
106
|
-
<
|
|
104
|
+
<router-link to="/ontology" class="hover:text-ink-700 transition-colors">Overview</router-link>
|
|
105
|
+
<template v-if="activeClass.ancestors.length">
|
|
106
|
+
<span class="text-ink-200">/</span>
|
|
107
|
+
<template v-for="(anc, i) in activeClass.ancestors" :key="anc">
|
|
108
|
+
<router-link :to="`/ontology/class/${compactToSlug(anc)}`" class="hover:text-ink-700 transition-colors">{{ getClass(anc)?.label || anc }}</router-link>
|
|
109
|
+
<span class="text-ink-200">/</span>
|
|
110
|
+
</template>
|
|
111
|
+
</template>
|
|
107
112
|
<span class="text-ink-700">{{ activeClass.label }}</span>
|
|
108
113
|
</nav>
|
|
109
114
|
|
|
@@ -112,16 +117,15 @@ const allClasses = getAllClasses();
|
|
|
112
117
|
<code class="block text-xs text-ink-400 mt-1">{{ activeClass.iri }}</code>
|
|
113
118
|
<div v-if="activeClass.subClassOf" class="flex items-center gap-2 mt-2 text-sm">
|
|
114
119
|
<span class="text-ink-400 text-xs">subClassOf</span>
|
|
115
|
-
<
|
|
120
|
+
<router-link :to="`/ontology/class/${compactToSlug(activeClass.subClassOf)}`" class="text-xs text-blue-600 bg-blue-50 px-2 py-0.5 rounded hover:bg-blue-100 transition-colors">{{ activeClass.subClassOf }}</router-link>
|
|
116
121
|
<template v-if="activeClass.ancestors.length > 1">
|
|
117
122
|
<span class="text-ink-300 text-xs">→</span>
|
|
118
|
-
<
|
|
123
|
+
<span class="text-xs text-ink-500">{{ activeClass.ancestors.slice(1).map(a => getClass(a)?.label || a).join(' → ') }}</span>
|
|
119
124
|
</template>
|
|
120
125
|
</div>
|
|
121
126
|
<p v-if="activeClass.comment" class="text-sm text-ink-500 mt-3 leading-relaxed">{{ activeClass.comment }}</p>
|
|
122
127
|
</div>
|
|
123
128
|
|
|
124
|
-
<!-- Object Properties -->
|
|
125
129
|
<div v-if="activeProperties.object.length" class="mb-6">
|
|
126
130
|
<h3 class="text-xs uppercase tracking-wide text-ink-300 font-medium mb-2">
|
|
127
131
|
Object Properties ({{ activeProperties.object.length }})
|
|
@@ -149,7 +153,6 @@ const allClasses = getAllClasses();
|
|
|
149
153
|
</table>
|
|
150
154
|
</div>
|
|
151
155
|
|
|
152
|
-
<!-- Datatype Properties -->
|
|
153
156
|
<div v-if="activeProperties.datatype.length">
|
|
154
157
|
<h3 class="text-xs uppercase tracking-wide text-ink-300 font-medium mb-2">
|
|
155
158
|
Datatype Properties ({{ activeProperties.datatype.length }})
|
|
@@ -181,11 +184,10 @@ const allClasses = getAllClasses();
|
|
|
181
184
|
</div>
|
|
182
185
|
</template>
|
|
183
186
|
|
|
184
|
-
<!-- Taxonomy detail
|
|
187
|
+
<!-- Taxonomy detail -->
|
|
185
188
|
<template v-if="activeTaxonomy && activeTaxonomyData()">
|
|
186
|
-
<!-- Breadcrumb -->
|
|
187
189
|
<nav class="flex items-center gap-1.5 text-sm text-ink-400 mb-4">
|
|
188
|
-
<
|
|
190
|
+
<router-link to="/ontology" class="hover:text-ink-700 transition-colors">Overview</router-link>
|
|
189
191
|
<span class="text-ink-200">/</span>
|
|
190
192
|
<span class="text-ink-700">{{ taxonomyLabels[activeTaxonomy] }}</span>
|
|
191
193
|
</nav>
|