@glossarist/concept-browser 0.7.100 → 0.7.102

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.
Files changed (58) hide show
  1. package/cli/index.mjs +14 -251
  2. package/cli/index.ts +289 -0
  3. package/package.json +3 -2
  4. package/src/__tests__/__fixtures__/concepts.ts +3 -3
  5. package/src/__tests__/components/learn/learn-card-dimension-card.test.ts +112 -0
  6. package/src/__tests__/composables/use-concept-edges-v2.test.ts +1 -0
  7. package/src/__tests__/designation-relationship.test.ts +2 -2
  8. package/src/__tests__/perf/serialization-perf.test.ts +1 -0
  9. package/src/__tests__/use-rdf-document.test.ts +1 -0
  10. package/src/__tests__/views/learn/learn-designations-view.test.ts +84 -0
  11. package/src/__tests__/views/learn/learn-index-view.test.ts +45 -0
  12. package/src/__tests__/views/learn/learn-relationships-view.test.ts +83 -0
  13. package/src/__tests__/views/learn/learn-statuses-view.test.ts +60 -0
  14. package/src/adapters/bibliography-adapter.ts +1 -1
  15. package/src/adapters/model-bridge.ts +15 -15
  16. package/src/adapters/non-verbal/figure-bridge.ts +2 -2
  17. package/src/adapters/non-verbal/formula-bridge.ts +2 -2
  18. package/src/adapters/non-verbal/table-bridge.ts +2 -2
  19. package/src/components/CitationDisplay.vue +1 -1
  20. package/src/components/ConceptDetail.vue +2 -2
  21. package/src/components/ConceptDiffModal.vue +2 -2
  22. package/src/components/ConceptDiffView.vue +1 -1
  23. package/src/components/DesignationList.vue +4 -4
  24. package/src/components/NavIcon.vue +1 -0
  25. package/src/components/RelationSphere.vue +1 -1
  26. package/src/components/figure/FigureDisplay.vue +5 -5
  27. package/src/components/formula/FormulaDisplay.vue +4 -4
  28. package/src/components/learn/DimensionCard.vue +71 -0
  29. package/src/components/learn/LearnCard.vue +59 -0
  30. package/src/components/table/TableDisplay.vue +3 -3
  31. package/src/components/use-rdf-document.ts +16 -7
  32. package/src/composables/use-concept-content.ts +3 -3
  33. package/src/composables/use-concept-diff.ts +2 -2
  34. package/src/composables/use-concept-edges.ts +3 -3
  35. package/src/config/page-types.ts +1 -1
  36. package/src/i18n/locales/eng.yml +114 -9
  37. package/src/i18n/locales/fra.yml +114 -9
  38. package/src/layouts/Default.astro +32 -2
  39. package/src/router/index.ts +21 -2
  40. package/src/utils/content-renderer.ts +1 -1
  41. package/src/utils/partitive-multiplicity.ts +3 -2
  42. package/src/views/ConceptView.vue +3 -3
  43. package/src/views/learn/LearnDesignationsView.vue +190 -0
  44. package/src/views/learn/LearnIndexView.vue +75 -0
  45. package/src/views/learn/LearnRelationshipsView.vue +317 -0
  46. package/src/views/learn/LearnStatusesView.vue +114 -0
  47. package/tailwind.config.js +3 -3
  48. package/tsconfig.json +1 -1
  49. package/src/__tests__/views/relation-types-view.test.ts +0 -85
  50. package/src/adapters/model-bridge/bridges.ts +0 -159
  51. package/src/adapters/model-bridge/concept.ts +0 -97
  52. package/src/adapters/model-bridge/entity-refs.ts +0 -49
  53. package/src/adapters/model-bridge/hyperedge.ts +0 -103
  54. package/src/adapters/model-bridge/index.ts +0 -46
  55. package/src/adapters/model-bridge/mappers.ts +0 -277
  56. package/src/adapters/model-bridge/partitive.ts +0 -79
  57. package/src/adapters/non-verbal/glossarist-augment.d.ts +0 -339
  58. /package/src/adapters/{model-bridge/jsonld-types.ts → jsonld-types.ts} +0 -0
@@ -12,6 +12,30 @@ interface Props {
12
12
 
13
13
  const { title, description = '', conceptTerm, conceptDefinition } = Astro.props;
14
14
  const siteConfig = await getSiteConfig();
15
+
16
+ // Derive Google Fonts URL from siteConfig branding (build-time SSG).
17
+ // Falls back to the default DM Sans / DM Serif Display / JetBrains Mono
18
+ // when no branding.fonts is declared.
19
+ const brandingFonts = siteConfig?.branding?.fonts;
20
+ const fontParts: string[] = [];
21
+ if (brandingFonts?.header?.source === 'google' && brandingFonts.header.family) {
22
+ const w = (brandingFonts.header.weights || [400, 700]).join(';');
23
+ fontParts.push(`family=${brandingFonts.header.family.replace(/ /g, '+')}:wght@${w}`);
24
+ }
25
+ if (brandingFonts?.body?.source === 'google' && brandingFonts.body.family) {
26
+ const w = (brandingFonts.body.weights || [400, 700]).join(';');
27
+ fontParts.push(`family=${brandingFonts.body.family.replace(/ /g, '+')}:wght@${w}`);
28
+ }
29
+ const fontsUrl = fontParts.length > 0
30
+ ? `https://fonts.googleapis.com/css2?${fontParts.join('&')}&display=swap`
31
+ : 'https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&family=DM+Serif+Display:ital@0;1&family=JetBrains+Mono:wght@400;500&display=swap';
32
+
33
+ const fontHeader = brandingFonts?.header?.family
34
+ ? `'${brandingFonts.header.family}', Georgia, serif`
35
+ : `'DM Serif Display', Georgia, serif`;
36
+ const fontBody = brandingFonts?.body?.family
37
+ ? `'${brandingFonts.body.family}', system-ui, sans-serif`
38
+ : `'DM Sans', system-ui, sans-serif`;
15
39
  ---
16
40
 
17
41
  <!DOCTYPE html>
@@ -42,8 +66,14 @@ const siteConfig = await getSiteConfig();
42
66
  <title>{title}</title>
43
67
  <link rel="preconnect" href="https://fonts.googleapis.com">
44
68
  <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
45
- <link rel="preload" as="style" href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&family=DM+Serif+Display:ital@0;1&family=JetBrains+Mono:wght@400;500&display=swap" onload="this.rel='stylesheet'">
46
- <noscript><link href="https://fonts.googleapis.com/css2?family=DM+Sans:ital,opsz,wght@0,9..40,300;0,9..40,400;0,9..40,500;0,9..40,600;0,9..40,700;1,9..40,400&family=DM+Serif+Display:ital@0;1&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet"></noscript>
69
+ <link rel="preload" as="style" href={fontsUrl} onload="this.rel='stylesheet'">
70
+ <noscript><link href={fontsUrl} rel="stylesheet"></noscript>
71
+ <style is:global>
72
+ :root {
73
+ --font-header: ${fontHeader};
74
+ --font-body: ${fontBody};
75
+ }
76
+ </style>
47
77
  <script is:inline>
48
78
  (function() {
49
79
  const c = document.cookie.split(';').map(s => s.trim()).find(s => s.startsWith('theme='));
@@ -96,8 +96,27 @@ export const routes: RouteRecordRaw[] = [
96
96
  },
97
97
  {
98
98
  path: '/relation-types',
99
- name: 'relation-types',
100
- component: () => import('../views/RelationTypesView.vue'),
99
+ redirect: '/learn/relationships',
100
+ },
101
+ {
102
+ path: '/learn',
103
+ name: 'learn',
104
+ component: () => import('../views/learn/LearnIndexView.vue'),
105
+ },
106
+ {
107
+ path: '/learn/relationships',
108
+ name: 'learn-relationships',
109
+ component: () => import('../views/learn/LearnRelationshipsView.vue'),
110
+ },
111
+ {
112
+ path: '/learn/designations',
113
+ name: 'learn-designations',
114
+ component: () => import('../views/learn/LearnDesignationsView.vue'),
115
+ },
116
+ {
117
+ path: '/learn/statuses',
118
+ name: 'learn-statuses',
119
+ component: () => import('../views/learn/LearnStatusesView.vue'),
101
120
  },
102
121
  {
103
122
  path: '/about',
@@ -183,7 +183,7 @@ function resolveUrnRefs(text: string, opts: RenderOptions): string {
183
183
  function resolveMentions(text: string, opts: RenderOptions): string {
184
184
  return text.replace(/\{\{([^{}]+?)\}\}/g, (_orig, body) => {
185
185
  const parsed = parseMention(body);
186
- const p = parsed as Record<string, unknown>;
186
+ const p = parsed as unknown as Record<string, unknown>;
187
187
 
188
188
  switch (p.kind) {
189
189
  case 'fig-ref':
@@ -28,10 +28,11 @@ import {
28
28
  multiplicityFromPair,
29
29
  isValidPresence,
30
30
  isValidCount,
31
- type PartitivePresence,
32
- type PartitiveCount,
33
31
  } from 'glossarist/models';
34
32
 
33
+ type PartitivePresence = (typeof PARTITIVE_PRESENCE.VALUES)[number];
34
+ type PartitiveCount = (typeof PARTITIVE_COUNT.VALUES)[number];
35
+
35
36
  // ── Two independent axes (re-exported SSOT) ────────────────────────────
36
37
 
37
38
  export { PARTITIVE_PRESENCE, PARTITIVE_COUNT };
@@ -60,7 +60,7 @@ const activeRegisterId = computed(() => sphereFocusPayload.value?.registerId ??
60
60
  const adjacent = ref({ prev: null as string | null, next: null as string | null });
61
61
 
62
62
  const { conceptPartitiveRelations, conceptGenericRelations } = useConceptEdges(
63
- concept,
63
+ computed(() => concept.value as any),
64
64
  activeRegisterId,
65
65
  manifest,
66
66
  edges,
@@ -284,7 +284,7 @@ onUnmounted(() => window.removeEventListener('keydown', onKeydown));
284
284
  <!-- Sphere mode — receives concept + edges directly, no URI matching -->
285
285
  <RelationSphere
286
286
  v-if="viewMode === 'sphere'"
287
- :concept="concept"
287
+ :concept="concept as any"
288
288
  :manifest="manifest"
289
289
  :register-id="activeRegisterId"
290
290
  :edges="edges"
@@ -295,7 +295,7 @@ onUnmounted(() => window.removeEventListener('keydown', onKeydown));
295
295
  <!-- Detail mode -->
296
296
  <ConceptDetail
297
297
  v-else
298
- :concept="concept"
298
+ :concept="concept as any"
299
299
  :manifest="manifest"
300
300
  :edges="edges"
301
301
  :adjacent="adjacent"
@@ -0,0 +1,190 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * LearnDesignationsView — explains the term/designation vocabulary.
4
+ *
5
+ * Three cards:
6
+ * 1. Normative status (preferred / admitted / deprecated) — ISO 10241-1:2011 §3.4.1.3.
7
+ * Each explicitly allows multiple (per ISO Notes 1).
8
+ * 2. Kinds and forms of term (full form, abbreviated form, borrowed, variant) —
9
+ * ISO 10241-1:2011 §3.4.1.2.
10
+ * 3. Designation types (term / proper name / symbol) with abbreviation subtypes
11
+ * (acronym vs initialism) — ISO 704:2022 §7.
12
+ *
13
+ * Addresses the user's specific concerns:
14
+ * - "preferred/admitted term means, that they can be multiple" → Card 1
15
+ * - "types of acronym" → Card 3 (acronym vs initialism vs symbol)
16
+ */
17
+ import { useI18n } from '../../i18n';
18
+ import LearnCard from '../../components/learn/LearnCard.vue';
19
+
20
+ const { t } = useI18n();
21
+ </script>
22
+
23
+ <template>
24
+ <div class="learn-designations max-w-5xl mx-auto px-4 py-8">
25
+ <header class="mb-8">
26
+ <h1 class="text-3xl font-serif text-ink-800 dark:text-ink-50 mb-2">
27
+ {{ t('learn.designations.title') }}
28
+ </h1>
29
+ <p class="text-ink-500 dark:text-ink-300 max-w-3xl">{{ t('learn.designations.intro') }}</p>
30
+ </header>
31
+
32
+ <!-- ── Normative status ──────────────────────────────────────── -->
33
+ <section class="mb-12" :aria-label="t('learn.designations.normativeSection')">
34
+ <h2 class="text-xl font-semibold text-ink-700 dark:text-ink-100 mb-4 border-b border-ink-100 dark:border-ink-700 pb-2">
35
+ {{ t('learn.designations.normativeSection') }}
36
+ </h2>
37
+ <p class="text-sm text-ink-500 dark:text-ink-400 mb-4">
38
+ {{ t('learn.designations.normativeIntro') }}
39
+ </p>
40
+ <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
41
+ <LearnCard
42
+ :title="t('learn.designations.preferred.label')"
43
+ iso-reference="ISO 10241-1:2011 §3.4.1.3.1"
44
+ learn-more-url="https://www.glossarist.org/model/designations"
45
+ >
46
+ <p>{{ t('learn.designations.preferred.meaning') }}</p>
47
+ <p class="mt-3 text-xs italic text-ink-500 dark:text-ink-400">
48
+ {{ t('learn.designations.preferred.multipleNote') }}
49
+ </p>
50
+ <template #example>
51
+ VIM 1.9: <strong>measurement unit</strong> (preferred) — the primary term.
52
+ </template>
53
+ </LearnCard>
54
+
55
+ <LearnCard
56
+ :title="t('learn.designations.admitted.label')"
57
+ iso-reference="ISO 10241-1:2011 §3.4.1.3.2"
58
+ >
59
+ <p>{{ t('learn.designations.admitted.meaning') }}</p>
60
+ <p class="mt-3 text-xs italic text-ink-500 dark:text-ink-400">
61
+ {{ t('learn.designations.admitted.multipleNote') }}
62
+ </p>
63
+ <template #example>
64
+ VIM 1.9: <strong>unit of measurement</strong> (admitted) — a synonym for "measurement unit".
65
+ </template>
66
+ </LearnCard>
67
+
68
+ <LearnCard
69
+ :title="t('learn.designations.deprecated.label')"
70
+ iso-reference="ISO 10241-1:2011 §3.4.1.3.3"
71
+ >
72
+ <p>{{ t('learn.designations.deprecated.meaning') }}</p>
73
+ <p class="mt-3 text-xs italic text-ink-500 dark:text-ink-400">
74
+ {{ t('learn.designations.deprecated.multipleNote') }}
75
+ </p>
76
+ <template #example>
77
+ A term still in use but discouraged, e.g. an outdated spelling or a vendor name
78
+ used as a generic term.
79
+ </template>
80
+ </LearnCard>
81
+ </div>
82
+ </section>
83
+
84
+ <!-- ── Kinds and forms of term ───────────────────────────────── -->
85
+ <section class="mb-12" :aria-label="t('learn.designations.kindsSection')">
86
+ <h2 class="text-xl font-semibold text-ink-700 dark:text-ink-100 mb-4 border-b border-ink-100 dark:border-ink-700 pb-2">
87
+ {{ t('learn.designations.kindsSection') }}
88
+ </h2>
89
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
90
+ <LearnCard
91
+ :title="t('learn.designations.fullForm.label')"
92
+ iso-reference="ISO 10241-1:2011 §3.4.1.2.3"
93
+ >
94
+ <p>{{ t('learn.designations.fullForm.meaning') }}</p>
95
+ <template #example>
96
+ <strong>compact disc</strong> is the full form of "CD".
97
+ </template>
98
+ </LearnCard>
99
+
100
+ <LearnCard
101
+ :title="t('learn.designations.abbreviatedForm.label')"
102
+ iso-reference="ISO 10241-1:2011 §3.4.1.2.4"
103
+ >
104
+ <p>{{ t('learn.designations.abbreviatedForm.meaning') }}</p>
105
+ <p class="mt-3 text-xs italic text-ink-500 dark:text-ink-400">
106
+ {{ t('learn.designations.abbreviatedForm.multipleNote') }}
107
+ </p>
108
+ <template #example>
109
+ <strong>CD</strong> is the abbreviated form of "compact disc".
110
+ World Wide Web has two: <strong>WWW</strong> and <strong>W3</strong>.
111
+ </template>
112
+ </LearnCard>
113
+
114
+ <LearnCard
115
+ :title="t('learn.designations.borrowed.label')"
116
+ iso-reference="ISO 10241-1:2011 §3.4.1.2.1"
117
+ >
118
+ <p>{{ t('learn.designations.borrowed.meaning') }}</p>
119
+ <template #example>
120
+ English "kindergarten" (borrowed from German).
121
+ </template>
122
+ </LearnCard>
123
+
124
+ <LearnCard
125
+ :title="t('learn.designations.variant.label')"
126
+ iso-reference="ISO 10241-1:2011 §3.4.1.2.2"
127
+ >
128
+ <p>{{ t('learn.designations.variant.meaning') }}</p>
129
+ <template #example>
130
+ <strong>colour</strong> (UK) ↔ <strong>color</strong> (US);
131
+ <strong>multi-word term</strong> ↔ <strong>multiword term</strong>.
132
+ </template>
133
+ </LearnCard>
134
+ </div>
135
+ </section>
136
+
137
+ <!-- ── Designation types ─────────────────────────────────────── -->
138
+ <section :aria-label="t('learn.designations.typesSection')">
139
+ <h2 class="text-xl font-semibold text-ink-700 dark:text-ink-100 mb-4 border-b border-ink-100 dark:border-ink-700 pb-2">
140
+ {{ t('learn.designations.typesSection') }}
141
+ </h2>
142
+ <p class="text-sm text-ink-500 dark:text-ink-400 mb-4">
143
+ {{ t('learn.designations.typesIntro') }}
144
+ </p>
145
+ <div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
146
+ <LearnCard
147
+ :title="t('learn.designations.term.label')"
148
+ iso-reference="ISO 704:2022 §7.3"
149
+ >
150
+ <p>{{ t('learn.designations.term.meaning') }}</p>
151
+ <template #example>
152
+ <strong>system of quantities</strong> (VIM 1.3)
153
+ </template>
154
+ </LearnCard>
155
+
156
+ <LearnCard
157
+ :title="t('learn.designations.acronym.label')"
158
+ iso-reference="ISO 704:2022 §7.3.2"
159
+ >
160
+ <p>{{ t('learn.designations.acronym.meaning') }}</p>
161
+ <template #example>
162
+ <strong>laser</strong> — light amplification by stimulated emission of radiation.
163
+ Pronounced as one word.
164
+ </template>
165
+ </LearnCard>
166
+
167
+ <LearnCard
168
+ :title="t('learn.designations.initialism.label')"
169
+ iso-reference="ISO 704:2022 §7.3.2"
170
+ >
171
+ <p>{{ t('learn.designations.initialism.meaning') }}</p>
172
+ <template #example>
173
+ <strong>OIML</strong> — Organisation Internationale de Métrologie Légale.
174
+ Each letter pronounced separately.
175
+ </template>
176
+ </LearnCard>
177
+
178
+ <LearnCard
179
+ :title="t('learn.designations.symbol.label')"
180
+ iso-reference="ISO 704:2022 §7.5 + ISO 80000"
181
+ >
182
+ <p>{{ t('learn.designations.symbol.meaning') }}</p>
183
+ <template #example>
184
+ <strong>kg</strong> for kilogram. <strong>m/s</strong> for metre per second.
185
+ </template>
186
+ </LearnCard>
187
+ </div>
188
+ </section>
189
+ </div>
190
+ </template>
@@ -0,0 +1,75 @@
1
+ <script setup lang="ts">
2
+ /**
3
+ * LearnIndexView — entry point for the /learn section.
4
+ *
5
+ * Cards link to each topic with a one-line description. Phase 1 pages
6
+ * (relationships, designations, statuses) are linked; Phase 2 pages
7
+ * are not yet wired.
8
+ *
9
+ * Reader-focused: this section explains how to READ this site and the
10
+ * terminology behind its labels. For authoring datasets in glossarist
11
+ * format, see glossarist.org.
12
+ */
13
+ import { useI18n } from '../../i18n';
14
+ import LearnCard from '../../components/learn/LearnCard.vue';
15
+
16
+ const { t } = useI18n();
17
+
18
+ interface TopicLink {
19
+ to: string;
20
+ title: string;
21
+ description: string;
22
+ }
23
+
24
+ const phase1Topics: readonly TopicLink[] = [
25
+ {
26
+ to: '/learn/relationships',
27
+ title: t('learn.relationships.title'),
28
+ description: t('learn.relationships.short'),
29
+ },
30
+ {
31
+ to: '/learn/designations',
32
+ title: t('learn.designations.title'),
33
+ description: t('learn.designations.short'),
34
+ },
35
+ {
36
+ to: '/learn/statuses',
37
+ title: t('learn.statuses.title'),
38
+ description: t('learn.statuses.short'),
39
+ },
40
+ ];
41
+ </script>
42
+
43
+ <template>
44
+ <div class="learn-index max-w-5xl mx-auto px-4 py-8">
45
+ <header class="mb-8">
46
+ <h1 class="text-3xl font-serif text-ink-800 dark:text-ink-50 mb-2">
47
+ {{ t('nav.learn') }}
48
+ </h1>
49
+ <p class="text-ink-500 dark:text-ink-300 max-w-2xl">{{ t('learn.intro') }}</p>
50
+ </header>
51
+
52
+ <nav class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4" aria-label="Learn topics">
53
+ <RouterLink v-for="topic in phase1Topics" :key="topic.to" :to="topic.to"
54
+ class="learn-topic-link block no-underline">
55
+ <LearnCard :title="topic.title">
56
+ <div class="flex items-center justify-between">
57
+ <h2 class="text-base font-semibold text-ink-800 dark:text-ink-50">{{ topic.title }}</h2>
58
+ <span class="text-ink-300 dark:text-ink-500 text-sm">→</span>
59
+ </div>
60
+ <p class="text-sm text-ink-600 dark:text-ink-300 mt-1">{{ topic.description }}</p>
61
+ </LearnCard>
62
+ </RouterLink>
63
+ </nav>
64
+
65
+ <p class="text-xs text-ink-400 dark:text-ink-500 mt-8">
66
+ {{ t('learn.glossaristOrgNote') }}
67
+ </p>
68
+ </div>
69
+ </template>
70
+
71
+ <style scoped>
72
+ .learn-topic-link:hover :deep(.learn-card) {
73
+ border-color: var(--color-accent, #0d9488);
74
+ }
75
+ </style>