@glossarist/concept-browser 0.7.134 → 0.7.136

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.
@@ -1,111 +0,0 @@
1
- import { describe, it, expect } from 'vitest';
2
- import { FORMAT_REGISTRY, conceptToTurtle, conceptToSkosJsonLd } from '../utils/concept-formats';
3
- import { Concept } from 'glossarist';
4
-
5
- function makeConcept(overrides: Record<string, unknown> = {}): Concept {
6
- return Concept.fromJSON({
7
- id: '1',
8
- uri: 'https://glossarist.org/test/concept/1',
9
- localizations: {
10
- eng: {
11
- language_code: 'eng',
12
- entry_status: 'valid',
13
- terms: [
14
- { type: 'expression', designation: 'test term', normative_status: 'preferred' },
15
- { type: 'expression', designation: 'alt term', normative_status: 'admitted' },
16
- ],
17
- definition: [{ content: 'a definition' }],
18
- notes: [{ content: 'a note' }],
19
- },
20
- deu: {
21
- language_code: 'deu',
22
- entry_status: 'valid',
23
- terms: [
24
- { type: 'expression', designation: 'Testbegriff', normative_status: 'preferred' },
25
- ],
26
- definition: [{ content: 'eine Definition' }],
27
- },
28
- },
29
- ...overrides,
30
- });
31
- }
32
-
33
- describe('FORMAT_REGISTRY', () => {
34
- it('has ttl, jsonld, yaml entries', () => {
35
- expect(FORMAT_REGISTRY.ttl).toBeDefined();
36
- expect(FORMAT_REGISTRY.jsonld).toBeDefined();
37
- expect(FORMAT_REGISTRY.yaml).toBeDefined();
38
- });
39
-
40
- it('each entry has extension, label, mediaType', () => {
41
- for (const [, desc] of Object.entries(FORMAT_REGISTRY)) {
42
- expect(desc.extension).toBeTruthy();
43
- expect(desc.label).toBeTruthy();
44
- expect(desc.mediaType).toBeTruthy();
45
- }
46
- });
47
- });
48
-
49
- describe('conceptToTurtle', () => {
50
- it('generates valid Turtle with SKOS predicates', () => {
51
- const ttl = conceptToTurtle(makeConcept());
52
- expect(ttl).toContain('@prefix skos:');
53
- expect(ttl).toContain('a skos:Concept');
54
- expect(ttl).toContain('skos:prefLabel "test term"@eng');
55
- expect(ttl).toContain('skos:altLabel "alt term"@eng');
56
- expect(ttl).toContain('skos:prefLabel "Testbegriff"@deu');
57
- expect(ttl).toContain('skos:definition "a definition"@eng');
58
- expect(ttl).toContain('skos:scopeNote "a note"@eng');
59
- expect(ttl).toContain('skos:notation "1"');
60
- });
61
-
62
- it('escapes special characters in Turtle', () => {
63
- const concept = Concept.fromJSON({
64
- id: '1',
65
- uri: 'https://glossarist.org/test/concept/1',
66
- localizations: {
67
- eng: {
68
- language_code: 'eng',
69
- terms: [{ type: 'expression', designation: 'test', normative_status: 'preferred' }],
70
- definition: [{ content: 'has "quotes" and \\backslash' }],
71
- },
72
- },
73
- });
74
- const ttl = conceptToTurtle(concept);
75
- expect(ttl).toContain('\\"quotes\\"');
76
- expect(ttl).toContain('\\\\backslash');
77
- });
78
-
79
- it('handles empty concept gracefully', () => {
80
- const ttl = conceptToTurtle(Concept.fromJSON({}));
81
- expect(ttl).toContain('a skos:Concept');
82
- expect(ttl).toContain('skos:notation ""');
83
- });
84
- });
85
-
86
- describe('conceptToSkosJsonLd', () => {
87
- it('generates SKOS JSON-LD with language maps', () => {
88
- const jsonld = conceptToSkosJsonLd(makeConcept());
89
- const parsed = JSON.parse(jsonld);
90
-
91
- expect(parsed['@type']).toBe('skos:Concept');
92
- expect(parsed['@id']).toBe('https://glossarist.org/test/concept/1');
93
- expect(parsed['skos:notation']).toBe('1');
94
- expect(parsed['skos:prefLabel']).toEqual({ eng: 'test term', deu: 'Testbegriff' });
95
- expect(parsed['skos:altLabel']).toEqual({ eng: 'alt term' });
96
- expect(parsed['skos:definition']).toEqual({ eng: 'a definition', deu: 'eine Definition' });
97
- });
98
-
99
- it('uses @language container in context', () => {
100
- const jsonld = conceptToSkosJsonLd(makeConcept());
101
- const parsed = JSON.parse(jsonld);
102
- expect(parsed['@context']['@language']).toEqual({ '@container': '@language' });
103
- });
104
-
105
- it('omits empty language maps', () => {
106
- const concept = Concept.fromJSON({ id: '1', uri: 'https://glossarist.org/test/concept/1' });
107
- const parsed = JSON.parse(conceptToSkosJsonLd(concept));
108
- expect(parsed['skos:prefLabel']).toBeUndefined();
109
- expect(parsed['skos:definition']).toBeUndefined();
110
- });
111
- });
@@ -1,123 +0,0 @@
1
- import type { Concept } from 'glossarist';
2
-
3
- export interface FormatDescriptor {
4
- extension: string;
5
- label: string;
6
- mediaType: string;
7
- }
8
-
9
- export const FORMAT_REGISTRY: Record<string, FormatDescriptor> = {
10
- ttl: { extension: 'ttl', label: 'Turtle RDF', mediaType: 'text/turtle' },
11
- jsonld: { extension: 'jsonld', label: 'JSON-LD', mediaType: 'application/ld+json' },
12
- tbx: { extension: 'tbx', label: 'TBX-XML', mediaType: 'application/xml' },
13
- yaml: { extension: 'yaml', label: 'YAML', mediaType: 'text/yaml' },
14
- };
15
-
16
- function getLocalizedData(concept: Concept) {
17
- const result: Record<string, {
18
- prefLabels: string[];
19
- altLabels: string[];
20
- definitions: string[];
21
- notes: string[];
22
- }> = {};
23
-
24
- for (const lang of concept.languages) {
25
- const lc = concept.localization(lang);
26
- if (!lc) continue;
27
-
28
- const prefLabels = lc.terms
29
- .filter(d => d.normativeStatus === 'preferred' && d.designation)
30
- .map(d => d.designation);
31
- const altLabels = lc.terms
32
- .filter(d => d.normativeStatus !== 'preferred' && d.designation)
33
- .map(d => d.designation);
34
- const definitions = lc.definitions
35
- .map(d => d.content || '')
36
- .filter(Boolean);
37
- const notes = lc.notes
38
- .map(d => d.content || '')
39
- .filter(Boolean);
40
-
41
- if (prefLabels.length || definitions.length) {
42
- result[lang] = { prefLabels, altLabels, definitions, notes };
43
- }
44
- }
45
-
46
- return result;
47
- }
48
-
49
- function escapeTurtle(s: string): string {
50
- return s.replace(/\\/g, '\\\\').replace(/"/g, '\\"').replace(/\n/g, '\\n');
51
- }
52
-
53
- export function conceptToTurtle(concept: Concept): string {
54
- const uri = concept.uri || '';
55
- const id = concept.id;
56
- const data = getLocalizedData(concept);
57
-
58
- const lines: string[] = [
59
- '@prefix skos: <http://www.w3.org/2004/02/skos/core#> .',
60
- '@prefix dcterms: <http://purl.org/dc/terms/> .',
61
- '',
62
- ];
63
-
64
- const props: string[] = ['a skos:Concept'];
65
- props.push(` skos:notation "${escapeTurtle(id)}"`);
66
-
67
- for (const [lang, d] of Object.entries(data)) {
68
- for (const label of d.prefLabels) {
69
- props.push(` skos:prefLabel "${escapeTurtle(label)}"@${lang}`);
70
- }
71
- for (const label of d.altLabels) {
72
- props.push(` skos:altLabel "${escapeTurtle(label)}"@${lang}`);
73
- }
74
- for (const def of d.definitions) {
75
- props.push(` skos:definition "${escapeTurtle(def)}"@${lang}`);
76
- }
77
- for (const note of d.notes) {
78
- props.push(` skos:scopeNote "${escapeTurtle(note)}"@${lang}`);
79
- }
80
- }
81
-
82
- lines.push(`<${uri}>`);
83
- lines.push(props.join(' ;\n'));
84
- lines.push(' .');
85
-
86
- return lines.join('\n');
87
- }
88
-
89
- export function conceptToSkosJsonLd(concept: Concept): string {
90
- const uri = concept.uri || '';
91
- const id = concept.id;
92
- const data = getLocalizedData(concept);
93
-
94
- const doc: Record<string, any> = {
95
- '@context': {
96
- skos: 'http://www.w3.org/2004/02/skos/core#',
97
- dcterms: 'http://purl.org/dc/terms/',
98
- '@language': { '@container': '@language' },
99
- },
100
- '@id': uri,
101
- '@type': 'skos:Concept',
102
- 'skos:notation': id,
103
- };
104
-
105
- const prefLabels: Record<string, string> = {};
106
- const altLabels: Record<string, string> = {};
107
- const definitions: Record<string, string> = {};
108
- const scopeNotes: Record<string, string> = {};
109
-
110
- for (const [lang, d] of Object.entries(data)) {
111
- if (d.prefLabels[0]) prefLabels[lang] = d.prefLabels[0];
112
- if (d.altLabels[0]) altLabels[lang] = d.altLabels[0];
113
- if (d.definitions[0]) definitions[lang] = d.definitions[0];
114
- if (d.notes[0]) scopeNotes[lang] = d.notes[0];
115
- }
116
-
117
- if (Object.keys(prefLabels).length) doc['skos:prefLabel'] = prefLabels;
118
- if (Object.keys(altLabels).length) doc['skos:altLabel'] = altLabels;
119
- if (Object.keys(definitions).length) doc['skos:definition'] = definitions;
120
- if (Object.keys(scopeNotes).length) doc['skos:scopeNote'] = scopeNotes;
121
-
122
- return JSON.stringify(doc, null, 2);
123
- }