glossarist 0.3.0 → 0.3.1
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/concept-reader.d.ts +2 -2
- package/src/concept-reader.js +3 -1
- package/src/index.js +2 -0
- package/src/models/concept.js +4 -0
- package/src/models/index.d.ts +40 -0
- package/src/models/index.js +2 -0
- package/src/models/register.js +110 -0
- package/src/models/section.js +44 -0
package/package.json
CHANGED
package/src/concept-reader.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Concept } from './models/index';
|
|
1
|
+
import type { Concept, Register } from './models/index';
|
|
2
2
|
|
|
3
3
|
/** Read all concept YAML files from a directory. */
|
|
4
4
|
export function readConcepts(dir: string): Concept[];
|
|
@@ -10,4 +10,4 @@ export function readConcept(dir: string, id: string): Concept | null;
|
|
|
10
10
|
export function listConceptIds(dir: string, prefix?: string): string[];
|
|
11
11
|
|
|
12
12
|
/** Read register.yaml from a dataset directory (if present). */
|
|
13
|
-
export function readRegister(dir: string):
|
|
13
|
+
export function readRegister(dir: string): Register | null;
|
package/src/concept-reader.js
CHANGED
|
@@ -4,6 +4,7 @@ import yaml from 'js-yaml';
|
|
|
4
4
|
import { conceptParser } from './concept-parser.js';
|
|
5
5
|
import { naturalSort } from './sort.js';
|
|
6
6
|
import { InvalidInputError } from './errors.js';
|
|
7
|
+
import { Register } from './models/register.js';
|
|
7
8
|
|
|
8
9
|
function assertDir(dir, fnName) {
|
|
9
10
|
if (typeof dir !== 'string' || dir.trim() === '') {
|
|
@@ -91,5 +92,6 @@ export function readRegister(dir) {
|
|
|
91
92
|
assertDir(dir, 'readRegister');
|
|
92
93
|
const p = path.join(dir, 'register.yaml');
|
|
93
94
|
if (!fs.existsSync(p)) return null;
|
|
94
|
-
|
|
95
|
+
const raw = yaml.load(fs.readFileSync(p, 'utf8'));
|
|
96
|
+
return Register.fromJSON(raw);
|
|
95
97
|
}
|
package/src/index.js
CHANGED
|
@@ -28,6 +28,8 @@ export {
|
|
|
28
28
|
|
|
29
29
|
export {
|
|
30
30
|
GlossaristModel,
|
|
31
|
+
Register, Section,
|
|
32
|
+
REGISTER_STATUSES, ORDERING_METHODS,
|
|
31
33
|
Concept, LocalizedConcept,
|
|
32
34
|
Designation, Expression, Abbreviation, Symbol, GraphicalSymbol,
|
|
33
35
|
Citation, ConceptRef, ConceptSource, RelatedConcept, ConceptReference, ConceptDate,
|
package/src/models/concept.js
CHANGED
|
@@ -16,6 +16,7 @@ export class Concept extends GlossaristModel {
|
|
|
16
16
|
|
|
17
17
|
this.relatedConcepts = _mapInstances(data.relatedConcepts ?? data.related ?? data.related_concepts ?? [], RelatedConcept);
|
|
18
18
|
this.domains = _normalizeDomains(data.domains, data.groups);
|
|
19
|
+
this.tags = Array.isArray(data.tags) ? [...data.tags] : [];
|
|
19
20
|
this.dates = _mapInstances(data.dates ?? [], ConceptDate);
|
|
20
21
|
this.sources = _mapInstances(data.sources ?? [], ConceptSource);
|
|
21
22
|
this.status = data.status ?? null;
|
|
@@ -92,6 +93,9 @@ export class Concept extends GlossaristModel {
|
|
|
92
93
|
if (this.domains.length > 0) {
|
|
93
94
|
obj.domains = this.domains.map(d => d.toJSON());
|
|
94
95
|
}
|
|
96
|
+
if (this.tags.length > 0) {
|
|
97
|
+
obj.tags = [...this.tags];
|
|
98
|
+
}
|
|
95
99
|
if (this.dates.length > 0) {
|
|
96
100
|
obj.dates = this.dates.map(d => d.toJSON());
|
|
97
101
|
}
|
package/src/models/index.d.ts
CHANGED
|
@@ -1,3 +1,42 @@
|
|
|
1
|
+
export const ORDERING_METHODS: readonly string[];
|
|
2
|
+
export class Section extends GlossaristModel {
|
|
3
|
+
readonly id: string | null;
|
|
4
|
+
readonly names: Record<string, string>;
|
|
5
|
+
readonly ordering: string | null;
|
|
6
|
+
readonly children: Section[];
|
|
7
|
+
name(lang: string): string | null;
|
|
8
|
+
descendantById(id: string): Section | null;
|
|
9
|
+
static fromJSON(data: Record<string, unknown>): Section;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const REGISTER_STATUSES: readonly string[];
|
|
13
|
+
export class Register extends GlossaristModel {
|
|
14
|
+
readonly schemaVersion: string;
|
|
15
|
+
readonly id: string | null;
|
|
16
|
+
readonly ref: string | null;
|
|
17
|
+
readonly refAliases: string[];
|
|
18
|
+
readonly year: number | null;
|
|
19
|
+
readonly urn: string | null;
|
|
20
|
+
readonly urnAliases: string[];
|
|
21
|
+
readonly status: string | null;
|
|
22
|
+
readonly supersedes: string | null;
|
|
23
|
+
readonly owner: string | null;
|
|
24
|
+
readonly sourceRepo: string | null;
|
|
25
|
+
readonly tags: string[];
|
|
26
|
+
readonly languages: string[];
|
|
27
|
+
readonly languageOrder: string[];
|
|
28
|
+
readonly ordering: string | null;
|
|
29
|
+
readonly logo: { path?: string; alt?: string } | null;
|
|
30
|
+
readonly description: Record<string, string>;
|
|
31
|
+
readonly about: Record<string, string>;
|
|
32
|
+
readonly provenance: Record<string, unknown>[];
|
|
33
|
+
readonly contributors: Record<string, unknown>[];
|
|
34
|
+
readonly sections: Section[];
|
|
35
|
+
sectionById(id: string): Section | null;
|
|
36
|
+
sectionName(sectionId: string, lang: string): string | null;
|
|
37
|
+
static fromJSON(data: Record<string, unknown>): Register;
|
|
38
|
+
}
|
|
39
|
+
|
|
1
40
|
export class GlossaristModel {
|
|
2
41
|
toJSON(): Record<string, unknown>;
|
|
3
42
|
static fromJSON(data: Record<string, unknown>): GlossaristModel;
|
|
@@ -15,6 +54,7 @@ export class Concept extends GlossaristModel {
|
|
|
15
54
|
readonly raw: Record<string, unknown> | null;
|
|
16
55
|
readonly relatedConcepts: RelatedConcept[];
|
|
17
56
|
readonly domains: ConceptReference[];
|
|
57
|
+
readonly tags: string[];
|
|
18
58
|
readonly dates: ConceptDate[];
|
|
19
59
|
readonly sources: ConceptSource[];
|
|
20
60
|
readonly status: string | null;
|
package/src/models/index.js
CHANGED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { GlossaristModel } from './base.js';
|
|
2
|
+
import { Section } from './section.js';
|
|
3
|
+
|
|
4
|
+
export const REGISTER_STATUSES = Object.freeze([
|
|
5
|
+
'current',
|
|
6
|
+
'superseded',
|
|
7
|
+
'withdrawn',
|
|
8
|
+
'draft',
|
|
9
|
+
]);
|
|
10
|
+
|
|
11
|
+
export class Register extends GlossaristModel {
|
|
12
|
+
constructor(data = {}) {
|
|
13
|
+
super();
|
|
14
|
+
this.schemaVersion = data.schema_version ?? data.schemaVersion ?? '3';
|
|
15
|
+
this.id = data.id ?? null;
|
|
16
|
+
this.ref = data.ref ?? null;
|
|
17
|
+
this.refAliases = data.refAliases ?? data.ref_aliases ?? [];
|
|
18
|
+
this.year = data.year ?? null;
|
|
19
|
+
this.urn = data.urn ?? null;
|
|
20
|
+
this.urnAliases = data.urnAliases ?? data.urn_aliases ?? [];
|
|
21
|
+
this.status = data.status ?? null;
|
|
22
|
+
this.supersedes = data.supersedes ?? null;
|
|
23
|
+
this.owner = data.owner ?? null;
|
|
24
|
+
this.sourceRepo = data.sourceRepo ?? data.source_repo ?? null;
|
|
25
|
+
this.tags = data.tags ?? [];
|
|
26
|
+
this.languages = data.languages ?? [];
|
|
27
|
+
this.languageOrder = data.languageOrder ?? data.language_order ?? [];
|
|
28
|
+
this.ordering = data.ordering ?? null;
|
|
29
|
+
this.logo = data.logo ?? null;
|
|
30
|
+
this.description = data.description ?? {};
|
|
31
|
+
this.about = data.about ?? {};
|
|
32
|
+
this.provenance = data.provenance ?? [];
|
|
33
|
+
this.contributors = data.contributors ?? [];
|
|
34
|
+
this.sections = (data.sections ?? []).map(s =>
|
|
35
|
+
s instanceof Section ? s : new Section(s)
|
|
36
|
+
);
|
|
37
|
+
this._raw = this._extractRaw(data);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
_extractRaw(data) {
|
|
41
|
+
const known = new Set([
|
|
42
|
+
'schema_version', 'schemaVersion',
|
|
43
|
+
'id', 'ref', 'refAliases', 'ref_aliases',
|
|
44
|
+
'year', 'urn', 'urnAliases', 'urn_aliases',
|
|
45
|
+
'status', 'supersedes', 'owner',
|
|
46
|
+
'sourceRepo', 'source_repo', 'tags',
|
|
47
|
+
'languages', 'languageOrder', 'language_order',
|
|
48
|
+
'ordering', 'logo', 'description', 'about',
|
|
49
|
+
'provenance', 'contributors', 'sections',
|
|
50
|
+
]);
|
|
51
|
+
const extra = {};
|
|
52
|
+
for (const [k, v] of Object.entries(data)) {
|
|
53
|
+
if (!known.has(k)) extra[k] = v;
|
|
54
|
+
}
|
|
55
|
+
return extra;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
sectionById(id) {
|
|
59
|
+
for (const section of this.sections) {
|
|
60
|
+
if (section.id === id) return section;
|
|
61
|
+
const found = section.descendantById(id);
|
|
62
|
+
if (found) return found;
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
sectionName(sectionId, lang) {
|
|
68
|
+
const section = this.sectionById(sectionId);
|
|
69
|
+
return section ? section.name(lang) : null;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
toJSON() {
|
|
73
|
+
const obj = { ...this._raw, schema_version: this.schemaVersion };
|
|
74
|
+
if (this.id != null) obj.id = this.id;
|
|
75
|
+
if (this.ref != null) obj.ref = this.ref;
|
|
76
|
+
if (this.refAliases.length > 0) obj.refAliases = [...this.refAliases];
|
|
77
|
+
if (this.year != null) obj.year = this.year;
|
|
78
|
+
if (this.urn != null) obj.urn = this.urn;
|
|
79
|
+
if (this.urnAliases.length > 0) obj.urnAliases = [...this.urnAliases];
|
|
80
|
+
if (this.status != null) obj.status = this.status;
|
|
81
|
+
if (this.supersedes != null) obj.supersedes = this.supersedes;
|
|
82
|
+
if (this.owner != null) obj.owner = this.owner;
|
|
83
|
+
if (this.sourceRepo != null) obj.sourceRepo = this.sourceRepo;
|
|
84
|
+
if (this.tags.length > 0) obj.tags = [...this.tags];
|
|
85
|
+
if (this.languages.length > 0) obj.languages = [...this.languages];
|
|
86
|
+
if (this.languageOrder.length > 0) obj.languageOrder = [...this.languageOrder];
|
|
87
|
+
if (this.ordering != null) obj.ordering = this.ordering;
|
|
88
|
+
if (this.logo != null) obj.logo = { ...this.logo };
|
|
89
|
+
if (Object.keys(this.description).length > 0) obj.description = { ...this.description };
|
|
90
|
+
if (Object.keys(this.about).length > 0) obj.about = { ...this.about };
|
|
91
|
+
if (this.provenance.length > 0) obj.provenance = this.provenance.map(p => ({ ...p }));
|
|
92
|
+
if (this.contributors.length > 0) obj.contributors = this.contributors.map(c => ({ ...c }));
|
|
93
|
+
if (this.sections.length > 0) obj.sections = this.sections.map(s => s.toJSON());
|
|
94
|
+
return obj;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
static fromJSON(data) {
|
|
98
|
+
const instance = new Register(data);
|
|
99
|
+
const snakeToCamel = k => k.replace(/_([a-z])/g, (_, c) => c.toUpperCase());
|
|
100
|
+
return new Proxy(instance, {
|
|
101
|
+
get(target, prop) {
|
|
102
|
+
if (prop in target) return target[prop];
|
|
103
|
+
if (prop in target._raw) return target._raw[prop];
|
|
104
|
+
const camel = snakeToCamel(prop);
|
|
105
|
+
if (camel in target) return target[camel];
|
|
106
|
+
return undefined;
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { GlossaristModel } from './base.js';
|
|
2
|
+
|
|
3
|
+
export const ORDERING_METHODS = Object.freeze([
|
|
4
|
+
'systematic',
|
|
5
|
+
'mixed',
|
|
6
|
+
'alphabetical',
|
|
7
|
+
]);
|
|
8
|
+
|
|
9
|
+
export class Section extends GlossaristModel {
|
|
10
|
+
constructor(data = {}) {
|
|
11
|
+
super();
|
|
12
|
+
this.id = data.id ?? null;
|
|
13
|
+
this.names = data.names ?? {};
|
|
14
|
+
this.ordering = data.ordering ?? null;
|
|
15
|
+
this.children = (data.children ?? []).map(c =>
|
|
16
|
+
c instanceof Section ? c : new Section(c)
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
name(lang) {
|
|
21
|
+
return this.names[lang] ?? this.names.eng ?? null;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
descendantById(id) {
|
|
25
|
+
for (const child of this.children) {
|
|
26
|
+
if (child.id === id) return child;
|
|
27
|
+
const found = child.descendantById(id);
|
|
28
|
+
if (found) return found;
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
toJSON() {
|
|
34
|
+
const obj = { id: this.id };
|
|
35
|
+
if (Object.keys(this.names).length > 0) obj.names = { ...this.names };
|
|
36
|
+
if (this.ordering != null) obj.ordering = this.ordering;
|
|
37
|
+
if (this.children.length > 0) obj.children = this.children.map(c => c.toJSON());
|
|
38
|
+
return obj;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static fromJSON(data) {
|
|
42
|
+
return new Section(data);
|
|
43
|
+
}
|
|
44
|
+
}
|