@glossarist/concept-browser 0.3.4 → 0.4.0
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 +3 -2
- package/cli/index.mjs +2 -1
- package/env.d.ts +5 -0
- package/package.json +4 -3
- package/scripts/build-edges.js +78 -10
- package/scripts/generate-data.mjs +152 -20
- package/scripts/generate-ontology-data.mjs +184 -0
- package/scripts/generate-ontology-schema.mjs +315 -0
- package/src/__tests__/about-view.test.ts +98 -0
- package/src/__tests__/app-footer.test.ts +38 -0
- package/src/__tests__/app-header.test.ts +130 -0
- package/src/__tests__/app-sidebar.test.ts +159 -0
- package/src/__tests__/asciidoc-lite.test.ts +1 -1
- package/src/__tests__/concept-card.test.ts +115 -0
- package/src/__tests__/concept-detail-interaction.test.ts +273 -0
- package/src/__tests__/concept-formats.test.ts +32 -30
- package/src/__tests__/concept-timeline.test.ts +200 -0
- package/src/__tests__/concept-view.test.ts +88 -0
- package/src/__tests__/contributors-view.test.ts +103 -0
- package/src/__tests__/dataset-adapter.test.ts +172 -23
- package/src/__tests__/dataset-view.test.ts +232 -0
- package/src/__tests__/designation-registry.test.ts +161 -0
- package/src/__tests__/format-downloads.test.ts +98 -0
- package/src/__tests__/graph-view.test.ts +69 -0
- package/src/__tests__/graph.test.ts +62 -0
- package/src/__tests__/home-interaction.test.ts +157 -0
- package/src/__tests__/language-detail.test.ts +203 -0
- package/src/__tests__/nav-icon.test.ts +48 -0
- package/src/__tests__/news-view.test.ts +87 -0
- package/src/__tests__/ontology-registry.test.ts +109 -0
- package/src/__tests__/page-view.test.ts +83 -0
- package/src/__tests__/relationship-categories.test.ts +62 -0
- package/src/__tests__/resolve-view.test.ts +77 -0
- package/src/__tests__/router.test.ts +65 -0
- package/src/__tests__/search-bar.test.ts +219 -0
- package/src/__tests__/search-view.test.ts +41 -0
- package/src/__tests__/stats-view.test.ts +77 -0
- package/src/__tests__/test-helpers.ts +171 -0
- package/src/__tests__/ui-store.test.ts +100 -0
- package/src/__tests__/v-math.test.ts +8 -7
- package/src/adapters/DatasetAdapter.ts +188 -63
- package/src/adapters/model-bridge.ts +277 -0
- package/src/adapters/ontology-registry.ts +75 -0
- package/src/adapters/ontology-schema.ts +100 -0
- package/src/adapters/types.ts +53 -78
- package/src/components/AppSidebar.vue +1 -1
- package/src/components/CitationDisplay.vue +35 -0
- package/src/components/ConceptDetail.vue +349 -146
- package/src/components/ConceptRdfView.vue +397 -0
- package/src/components/ConceptTimeline.vue +57 -60
- package/src/components/GraphPanel.vue +96 -31
- package/src/components/LanguageDetail.vue +46 -61
- package/src/components/NavIcon.vue +1 -0
- package/src/components/NonVerbalRepDisplay.vue +38 -0
- package/src/components/RelationshipList.vue +99 -0
- package/src/composables/use-render-options.ts +1 -4
- package/src/config/use-site-config.ts +3 -0
- package/src/data/ontology-schema.json +1551 -0
- package/src/data/taxonomies.json +543 -0
- package/src/graph/GraphEngine.ts +7 -4
- package/src/router/index.ts +6 -1
- package/src/shims/empty.ts +1 -0
- package/src/shims/node-crypto.ts +6 -0
- package/src/shims/node-path.ts +10 -0
- package/src/stores/vocabulary.ts +82 -32
- package/src/style.css +74 -20
- package/src/utils/asciidoc-lite.ts +17 -19
- package/src/utils/concept-formats.ts +22 -20
- package/src/utils/concept-helpers.ts +54 -0
- package/src/utils/designation-registry.ts +124 -0
- package/src/utils/escape.ts +7 -0
- package/src/utils/markdown-lite.ts +1 -3
- package/src/utils/math.ts +2 -11
- package/src/utils/plurimath.ts +2 -7
- package/src/utils/relationship-categories.ts +84 -0
- package/src/views/ConceptView.vue +22 -1
- package/src/views/DatasetView.vue +7 -2
- package/src/views/OntologySchemaView.vue +302 -0
- package/src/views/PageView.vue +28 -17
- package/src/views/StatsView.vue +34 -12
- package/vite.config.ts +8 -0
package/src/views/PageView.vue
CHANGED
|
@@ -8,29 +8,36 @@ interface PageData {
|
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
const route = useRoute();
|
|
11
|
-
const
|
|
12
|
-
|
|
11
|
+
const registerId = computed(() => route.params.registerId as string | undefined);
|
|
12
|
+
const pageName = computed(() => {
|
|
13
13
|
if (route.params.page) return route.params.page as string;
|
|
14
|
-
if (route.
|
|
15
|
-
|
|
16
|
-
const lastSegment = path.split('/').pop() || '';
|
|
17
|
-
return lastSegment;
|
|
14
|
+
if (route.params.slug) return route.params.slug as string;
|
|
15
|
+
return 'about';
|
|
18
16
|
});
|
|
17
|
+
|
|
19
18
|
const data = ref<PageData | null>(null);
|
|
20
19
|
const loading = ref(true);
|
|
21
20
|
const notFound = ref(false);
|
|
22
21
|
|
|
23
22
|
onMounted(async () => {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
const page = pageName.value;
|
|
24
|
+
const dsId = registerId.value;
|
|
25
|
+
|
|
26
|
+
const urls = dsId
|
|
27
|
+
? [`/pages/${dsId}-${page}.json`, `/pages/${page}.json`]
|
|
28
|
+
: [`/pages/${page}.json`];
|
|
29
|
+
|
|
30
|
+
for (const url of urls) {
|
|
31
|
+
try {
|
|
32
|
+
const resp = await fetch(url);
|
|
33
|
+
if (resp.ok) {
|
|
34
|
+
data.value = await resp.json();
|
|
35
|
+
loading.value = false;
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
} catch { /* try next */ }
|
|
33
39
|
}
|
|
40
|
+
notFound.value = true;
|
|
34
41
|
loading.value = false;
|
|
35
42
|
});
|
|
36
43
|
</script>
|
|
@@ -39,8 +46,12 @@ onMounted(async () => {
|
|
|
39
46
|
<div class="max-w-3xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
|
40
47
|
<nav aria-label="Breadcrumb" class="flex items-center gap-1.5 text-sm text-ink-400 mb-6">
|
|
41
48
|
<router-link :to="{ name: 'home' }" class="hover:text-ink-700 transition-colors">Home</router-link>
|
|
49
|
+
<template v-if="registerId">
|
|
50
|
+
<span class="text-ink-200">/</span>
|
|
51
|
+
<router-link :to="{ name: 'dataset', params: { registerId } }" class="hover:text-ink-700 transition-colors">{{ registerId }}</router-link>
|
|
52
|
+
</template>
|
|
42
53
|
<span class="text-ink-200">/</span>
|
|
43
|
-
<span class="text-ink-700">{{ data?.title ||
|
|
54
|
+
<span class="text-ink-700">{{ data?.title || pageName }}</span>
|
|
44
55
|
</nav>
|
|
45
56
|
|
|
46
57
|
<template v-if="loading">
|
|
@@ -55,7 +66,7 @@ onMounted(async () => {
|
|
|
55
66
|
<template v-else-if="notFound">
|
|
56
67
|
<div class="card p-8 text-center">
|
|
57
68
|
<h1 class="font-serif text-2xl text-ink-800 mb-2">Page Not Found</h1>
|
|
58
|
-
<p class="text-ink-500 mb-4">The page "{{
|
|
69
|
+
<p class="text-ink-500 mb-4">The page "{{ pageName }}" does not exist.</p>
|
|
59
70
|
<router-link :to="{ name: 'home' }" class="btn-primary">Go Home</router-link>
|
|
60
71
|
</div>
|
|
61
72
|
</template>
|
package/src/views/StatsView.vue
CHANGED
|
@@ -23,11 +23,28 @@ const stats = computed(() => {
|
|
|
23
23
|
const m = manifest.value;
|
|
24
24
|
if (!m) return { langs: [], total: 0 };
|
|
25
25
|
|
|
26
|
+
// Scan the index for actual language coverage
|
|
27
|
+
const adapter = store.datasets.get(resolvedId.value);
|
|
28
|
+
const conceptCounts: Record<string, number> = {};
|
|
29
|
+
|
|
30
|
+
if (adapter) {
|
|
31
|
+
const concepts = adapter.getConcepts();
|
|
32
|
+
for (const c of concepts) {
|
|
33
|
+
if (!c) continue;
|
|
34
|
+
for (const lang of Object.keys(c.designations)) {
|
|
35
|
+
conceptCounts[lang] = (conceptCounts[lang] || 0) + 1;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Merge with manifest languageStats (for definition counts)
|
|
26
41
|
const ls = m.languageStats || {};
|
|
27
|
-
const
|
|
42
|
+
const allLangs = new Set([...Object.keys(conceptCounts), ...m.languages]);
|
|
43
|
+
|
|
44
|
+
const langs: LangStat[] = [...allLangs].map(lang => ({
|
|
28
45
|
lang,
|
|
29
|
-
terms: ls[lang]?.terms ?? 0,
|
|
30
|
-
definitions: ls[lang]?.definitions ?? 0,
|
|
46
|
+
terms: conceptCounts[lang] ?? ls[lang]?.terms ?? 0,
|
|
47
|
+
definitions: ls[lang]?.definitions ?? conceptCounts[lang] ?? 0,
|
|
31
48
|
}));
|
|
32
49
|
|
|
33
50
|
// Sort: eng first, then by term count descending
|
|
@@ -41,6 +58,13 @@ const stats = computed(() => {
|
|
|
41
58
|
});
|
|
42
59
|
|
|
43
60
|
const maxTerms = computed(() => Math.max(...stats.value.langs.map(l => l.terms), 1));
|
|
61
|
+
|
|
62
|
+
function coverageColor(ratio: number): string {
|
|
63
|
+
if (ratio >= 0.8) return 'bg-emerald-500';
|
|
64
|
+
if (ratio >= 0.5) return 'bg-blue-500';
|
|
65
|
+
if (ratio >= 0.25) return 'bg-amber-500';
|
|
66
|
+
return 'bg-red-400';
|
|
67
|
+
}
|
|
44
68
|
</script>
|
|
45
69
|
|
|
46
70
|
<template>
|
|
@@ -80,11 +104,11 @@ const maxTerms = computed(() => Math.max(...stats.value.langs.map(l => l.terms),
|
|
|
80
104
|
<div class="card -mx-4 sm:mx-0 overflow-x-auto">
|
|
81
105
|
<table class="w-full text-sm">
|
|
82
106
|
<thead>
|
|
83
|
-
<tr class="border-b border-ink-100/60 bg-ink-50
|
|
84
|
-
<th class="text-left px-5 py-3 text-ink-
|
|
85
|
-
<th class="text-right px-5 py-3 text-ink-
|
|
86
|
-
<th class="text-right px-5 py-3 text-ink-
|
|
87
|
-
<th class="px-5 py-3 text-ink-
|
|
107
|
+
<tr class="border-b border-ink-100/60 bg-ink-50">
|
|
108
|
+
<th class="text-left px-5 py-3 text-ink-600 font-medium text-xs uppercase tracking-wide">Language</th>
|
|
109
|
+
<th class="text-right px-5 py-3 text-ink-600 font-medium text-xs uppercase tracking-wide">Terms</th>
|
|
110
|
+
<th class="text-right px-5 py-3 text-ink-600 font-medium text-xs uppercase tracking-wide">Definitions</th>
|
|
111
|
+
<th class="px-5 py-3 text-ink-600 font-medium w-40"></th>
|
|
88
112
|
</tr>
|
|
89
113
|
</thead>
|
|
90
114
|
<tbody>
|
|
@@ -103,10 +127,8 @@ const maxTerms = computed(() => Math.max(...stats.value.langs.map(l => l.terms),
|
|
|
103
127
|
<div class="h-2 rounded-full bg-ink-50 overflow-hidden flex-1">
|
|
104
128
|
<div
|
|
105
129
|
class="h-full rounded-full transition-all duration-500"
|
|
106
|
-
:
|
|
107
|
-
|
|
108
|
-
backgroundColor: getColor(resolvedId),
|
|
109
|
-
}"
|
|
130
|
+
:class="coverageColor(s.terms / maxTerms)"
|
|
131
|
+
:style="{ width: (s.terms / maxTerms * 100) + '%' }"
|
|
110
132
|
></div>
|
|
111
133
|
</div>
|
|
112
134
|
<span class="text-xs text-ink-300 w-10 text-right tabular-nums">{{ Math.round(s.terms / maxTerms * 100) }}%</span>
|
package/vite.config.ts
CHANGED
|
@@ -6,6 +6,8 @@ import { fileURLToPath } from 'url'
|
|
|
6
6
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
7
7
|
const cwd = process.cwd()
|
|
8
8
|
|
|
9
|
+
const isTest = process.env.VITEST !== undefined
|
|
10
|
+
|
|
9
11
|
export default defineConfig({
|
|
10
12
|
base: process.env.BASE_PATH || '/',
|
|
11
13
|
root: __dirname,
|
|
@@ -18,6 +20,12 @@ export default defineConfig({
|
|
|
18
20
|
resolve: {
|
|
19
21
|
alias: {
|
|
20
22
|
'@': resolve(__dirname, 'src'),
|
|
23
|
+
// Shim Node.js built-ins used by glossarist-js (not needed in browser, only for build)
|
|
24
|
+
...(!isTest ? {
|
|
25
|
+
crypto: resolve(__dirname, 'src/shims/node-crypto.ts'),
|
|
26
|
+
fs: resolve(__dirname, 'src/shims/empty.ts'),
|
|
27
|
+
path: resolve(__dirname, 'src/shims/node-path.ts'),
|
|
28
|
+
} : {}),
|
|
21
29
|
},
|
|
22
30
|
},
|
|
23
31
|
test: {
|