-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalidate.js
More file actions
111 lines (97 loc) · 3.24 KB
/
Copy pathvalidate.js
File metadata and controls
111 lines (97 loc) · 3.24 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#!/usr/bin/env node
const fs = require("fs");
const path = require("path");
const readJson = (file) =>
JSON.parse(fs.readFileSync(path.join(__dirname, file), "utf8"));
const standard = readJson("standard.json");
const domainList = readJson("domain_list.json");
const dictionary = readJson("dictionary.json");
const ARABIC_RE = /[\u0600-\u06FF]/;
const ID_RE = /^ACS-[A-Z]{2,4}-\d{4}$/;
const errors = [];
const usedIds = new Set();
function fail(msg) {
errors.push(msg);
}
const codeToName = new Map(
Object.entries(standard.domain_codes)
);
const listCodes = new Set(domainList.domains.map((d) => d.code));
const listNames = new Set(domainList.domains.map((d) => d.name));
for (const code of codeToName.keys()) {
if (!listCodes.has(code)) {
fail(`standard.json: domain code "${code}" missing from domain_list.json`);
}
}
for (const name of codeToName.values()) {
if (!listNames.has(name)) {
fail(`standard.json: domain name "${name}" missing from domain_list.json`);
}
}
dictionary.terms.forEach((term) => {
const id = term.ACS_ID || "";
for (const field of standard.term_required_fields) {
if (term[field] === undefined || term[field] === "") {
fail(`${id}: missing required field "${field}"`);
}
}
if (!ID_RE.test(id)) {
fail(`${id || "?"}: invalid ACS_ID format (expected ACS-XXX-0000)`);
} else {
if (usedIds.has(id)) {
fail(`${id}: duplicate ACS_ID`);
}
usedIds.add(id);
const code = id.split("-")[1];
const expectedName = codeToName.get(code);
if (!expectedName) {
fail(`${id}: unknown domain code "${code}"`);
} else if (term.DOMAIN !== expectedName) {
fail(
`${id}: DOMAIN "${term.DOMAIN}" does not match code "${code}" (expected "${expectedName}")`
);
}
}
if (!ARABIC_RE.test(term.AR_TERM || "")) {
fail(`${id}: AR_TERM must be written in Arabic`);
}
if ((term.AR_TERM || "").trim() === (term.EN_TERM || "").trim()) {
fail(`${id}: AR_TERM and EN_TERM must not be identical`);
}
if (!standard.allowed_status_values.includes(term.STATUS)) {
fail(
`${id}: invalid STATUS "${term.STATUS}" (allowed: ${standard.allowed_status_values.join(", ")})`
);
}
});
const domainTerms = new Map();
dictionary.terms.forEach((term) => {
if (!domainTerms.has(term.DOMAIN)) {
domainTerms.set(term.DOMAIN, { en: new Map(), ar: new Map() });
}
const bucket = domainTerms.get(term.DOMAIN);
const enKey = (term.EN_TERM || "").trim().toLowerCase();
const arKey = (term.AR_TERM || "").trim();
if (enKey) {
if (bucket.en.has(enKey)) {
fail(`${term.ACS_ID}: duplicate EN_TERM "${term.EN_TERM}" within ${term.DOMAIN} (also ${bucket.en.get(enKey)})`);
} else {
bucket.en.set(enKey, term.ACS_ID);
}
}
if (arKey) {
if (bucket.ar.has(arKey)) {
fail(`${term.ACS_ID}: duplicate AR_TERM "${term.AR_TERM}" within ${term.DOMAIN} (also ${bucket.ar.get(arKey)})`);
} else {
bucket.ar.set(arKey, term.ACS_ID);
}
}
});
if (errors.length) {
console.error(`ArCode validation failed (${errors.length} issue${errors.length === 1 ? "" : "s"}):`);
errors.forEach((e) => console.error(" - " + e));
process.exit(1);
}
console.log(
`ArCode validation passed: ${dictionary.terms.length} terms, all consistent.`
);