@pubid/pubid 0.1.3 → 0.1.5
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/artifact/corpus.json.gz +0 -0
- package/dist/conformance/cli.js +5 -1
- package/dist/flavors/amca/grammar.d.ts +4 -0
- package/dist/flavors/amca/grammar.js +87 -0
- package/dist/flavors/amca/index.d.ts +4 -0
- package/dist/flavors/amca/index.js +76 -0
- package/dist/flavors/amca/model.d.ts +29 -0
- package/dist/flavors/amca/model.js +146 -0
- package/dist/flavors/ansi/index.d.ts +24 -0
- package/dist/flavors/ansi/index.js +147 -0
- package/dist/flavors/api/grammar.d.ts +4 -0
- package/dist/flavors/api/grammar.js +79 -0
- package/dist/flavors/api/index.d.ts +4 -0
- package/dist/flavors/api/index.js +71 -0
- package/dist/flavors/api/model.d.ts +27 -0
- package/dist/flavors/api/model.js +114 -0
- package/dist/flavors/ashrae/grammar.d.ts +2 -0
- package/dist/flavors/ashrae/grammar.js +667 -0
- package/dist/flavors/ashrae/index.d.ts +4 -0
- package/dist/flavors/ashrae/index.js +306 -0
- package/dist/flavors/ashrae/model.d.ts +87 -0
- package/dist/flavors/ashrae/model.js +335 -0
- package/dist/flavors/ashrae/preprocessor.d.ts +7 -0
- package/dist/flavors/ashrae/preprocessor.js +44 -0
- package/dist/flavors/asme/grammar.d.ts +2 -0
- package/dist/flavors/asme/grammar.js +200 -0
- package/dist/flavors/asme/index.d.ts +4 -0
- package/dist/flavors/asme/index.js +138 -0
- package/dist/flavors/asme/model.d.ts +34 -0
- package/dist/flavors/asme/model.js +123 -0
- package/dist/flavors/astm/grammar.d.ts +2 -0
- package/dist/flavors/astm/grammar.js +110 -0
- package/dist/flavors/astm/index.d.ts +2 -0
- package/dist/flavors/astm/index.js +127 -0
- package/dist/flavors/astm/model.d.ts +42 -0
- package/dist/flavors/astm/model.js +263 -0
- package/dist/flavors/bipm/index.d.ts +30 -0
- package/dist/flavors/bipm/index.js +434 -0
- package/dist/flavors/bsi/grammar.d.ts +4 -0
- package/dist/flavors/bsi/grammar.js +535 -0
- package/dist/flavors/bsi/index.d.ts +4 -0
- package/dist/flavors/bsi/index.js +941 -0
- package/dist/flavors/bsi/model.d.ts +127 -0
- package/dist/flavors/bsi/model.js +863 -0
- package/dist/flavors/calconnect/index.d.ts +21 -0
- package/dist/flavors/calconnect/index.js +113 -0
- package/dist/flavors/cen_cenelec/grammar.d.ts +4 -0
- package/dist/flavors/cen_cenelec/grammar.js +107 -0
- package/dist/flavors/cen_cenelec/index.d.ts +5 -0
- package/dist/flavors/cen_cenelec/index.js +263 -0
- package/dist/flavors/cen_cenelec/model.d.ts +45 -0
- package/dist/flavors/cen_cenelec/model.js +490 -0
- package/dist/flavors/cie/grammar.d.ts +5 -0
- package/dist/flavors/cie/grammar.js +127 -0
- package/dist/flavors/cie/index.d.ts +2 -0
- package/dist/flavors/cie/index.js +311 -0
- package/dist/flavors/cie/model.d.ts +122 -0
- package/dist/flavors/cie/model.js +464 -0
- package/dist/flavors/csa/grammar.d.ts +6 -0
- package/dist/flavors/csa/grammar.js +239 -0
- package/dist/flavors/csa/index.d.ts +2 -0
- package/dist/flavors/csa/index.js +634 -0
- package/dist/flavors/csa/model.d.ts +33 -0
- package/dist/flavors/csa/model.js +505 -0
- package/dist/flavors/doi/index.d.ts +13 -0
- package/dist/flavors/doi/index.js +65 -0
- package/dist/flavors/easc/index.d.ts +4 -0
- package/dist/flavors/easc/index.js +107 -0
- package/dist/flavors/ecma/index.d.ts +4 -0
- package/dist/flavors/ecma/index.js +117 -0
- package/dist/flavors/etsi/index.d.ts +14 -0
- package/dist/flavors/etsi/index.js +307 -0
- package/dist/flavors/evs/grammar.d.ts +2 -0
- package/dist/flavors/evs/grammar.js +22 -0
- package/dist/flavors/evs/index.d.ts +2 -0
- package/dist/flavors/evs/index.js +24 -0
- package/dist/flavors/evs/model.d.ts +19 -0
- package/dist/flavors/evs/model.js +36 -0
- package/dist/flavors/gb/index.d.ts +31 -0
- package/dist/flavors/gb/index.js +159 -0
- package/dist/flavors/gost/grammar.d.ts +2 -0
- package/dist/flavors/gost/grammar.js +46 -0
- package/dist/flavors/gost/index.d.ts +2 -0
- package/dist/flavors/gost/index.js +165 -0
- package/dist/flavors/gost/model.d.ts +61 -0
- package/dist/flavors/gost/model.js +147 -0
- package/dist/flavors/gost/prefix_routes.d.ts +15 -0
- package/dist/flavors/gost/prefix_routes.js +192 -0
- package/dist/flavors/iala/index.d.ts +32 -0
- package/dist/flavors/iala/index.js +300 -0
- package/dist/flavors/iana/index.d.ts +19 -0
- package/dist/flavors/iana/index.js +71 -0
- package/dist/flavors/idf/grammar.d.ts +2 -0
- package/dist/flavors/idf/grammar.js +71 -0
- package/dist/flavors/idf/index.d.ts +2 -0
- package/dist/flavors/idf/index.js +100 -0
- package/dist/flavors/idf/model.d.ts +54 -0
- package/dist/flavors/idf/model.js +359 -0
- package/dist/flavors/iec/grammar.d.ts +3 -0
- package/dist/flavors/iec/grammar.js +187 -0
- package/dist/flavors/iec/index.d.ts +4 -0
- package/dist/flavors/iec/index.js +507 -0
- package/dist/flavors/iec/model.d.ts +54 -0
- package/dist/flavors/iec/model.js +437 -0
- package/dist/flavors/ieee/grammar.d.ts +2 -0
- package/dist/flavors/ieee/grammar.js +697 -0
- package/dist/flavors/ieee/index.d.ts +3 -0
- package/dist/flavors/ieee/index.js +1258 -0
- package/dist/flavors/ieee/model.d.ts +144 -0
- package/dist/flavors/ieee/model.js +1237 -0
- package/dist/flavors/ieee/preprocessor.d.ts +8 -0
- package/dist/flavors/ieee/preprocessor.js +410 -0
- package/dist/flavors/ieee/update_codes.d.ts +8 -0
- package/dist/flavors/ieee/update_codes.js +197 -0
- package/dist/flavors/ietf/index.d.ts +30 -0
- package/dist/flavors/ietf/index.js +151 -0
- package/dist/flavors/iho/index.d.ts +4 -0
- package/dist/flavors/iho/index.js +126 -0
- package/dist/flavors/index.d.ts +9 -0
- package/dist/flavors/index.js +136 -0
- package/dist/flavors/isbn/index.d.ts +13 -0
- package/dist/flavors/isbn/index.js +97 -0
- package/dist/flavors/iso/grammar.d.ts +2 -0
- package/dist/flavors/iso/grammar.js +207 -0
- package/dist/flavors/iso/index.d.ts +2 -0
- package/dist/flavors/iso/index.js +343 -0
- package/dist/flavors/iso/model.d.ts +159 -0
- package/dist/flavors/iso/model.js +802 -0
- package/dist/flavors/iso/stages.generated.d.ts +13 -0
- package/dist/flavors/iso/stages.generated.js +391 -0
- package/dist/flavors/itu/grammar.d.ts +4 -0
- package/dist/flavors/itu/grammar.js +205 -0
- package/dist/flavors/itu/index.d.ts +2 -0
- package/dist/flavors/itu/index.js +224 -0
- package/dist/flavors/itu/model.d.ts +184 -0
- package/dist/flavors/itu/model.js +599 -0
- package/dist/flavors/jcgm/index.d.ts +7 -0
- package/dist/flavors/jcgm/index.js +300 -0
- package/dist/flavors/jis/index.d.ts +4 -0
- package/dist/flavors/jis/index.js +267 -0
- package/dist/flavors/nist/grammar.d.ts +2 -0
- package/dist/flavors/nist/grammar.js +287 -0
- package/dist/flavors/nist/index.d.ts +2 -0
- package/dist/flavors/nist/index.js +1244 -0
- package/dist/flavors/nist/model.d.ts +155 -0
- package/dist/flavors/nist/model.js +823 -0
- package/dist/flavors/nist/preprocessor.d.ts +11 -0
- package/dist/flavors/nist/preprocessor.js +281 -0
- package/dist/flavors/oasis/index.d.ts +23 -0
- package/dist/flavors/oasis/index.js +110 -0
- package/dist/flavors/ogc/index.d.ts +20 -0
- package/dist/flavors/ogc/index.js +75 -0
- package/dist/flavors/oiml/grammar.d.ts +2 -0
- package/dist/flavors/oiml/grammar.js +206 -0
- package/dist/flavors/oiml/implementation.d.ts +9 -0
- package/dist/flavors/oiml/implementation.js +45 -0
- package/dist/flavors/oiml/model.d.ts +23 -0
- package/dist/flavors/oiml/model.js +592 -0
- package/dist/flavors/omg/index.d.ts +14 -0
- package/dist/flavors/omg/index.js +73 -0
- package/dist/flavors/plateau/index.d.ts +4 -0
- package/dist/flavors/plateau/index.js +97 -0
- package/dist/flavors/tgpp/index.d.ts +4 -0
- package/dist/flavors/tgpp/index.js +122 -0
- package/dist/flavors/un/index.d.ts +13 -0
- package/dist/flavors/un/index.js +90 -0
- package/dist/flavors/w3c/index.d.ts +14 -0
- package/dist/flavors/w3c/index.js +148 -0
- package/dist/flavors/xsf/index.d.ts +18 -0
- package/dist/flavors/xsf/index.js +65 -0
- package/dist/grammar/engine.d.ts +78 -0
- package/dist/grammar/engine.js +351 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/model/attribute.d.ts +54 -0
- package/dist/model/attribute.js +53 -0
- package/dist/model/builder.d.ts +39 -0
- package/dist/model/builder.js +124 -0
- package/dist/model/component.d.ts +70 -0
- package/dist/model/component.js +170 -0
- package/dist/model/identifier.d.ts +84 -0
- package/dist/model/identifier.js +270 -0
- package/dist/model/urn-generator.d.ts +27 -0
- package/dist/model/urn-generator.js +91 -0
- package/package.json +1 -1
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port of lib/pubid/nist/preprocessor.rb + data/nist/update_codes.yaml.
|
|
3
|
+
* Every regex-based normalization applied before the grammar sees the
|
|
4
|
+
* string. Stage order is load-bearing — later stages match patterns
|
|
5
|
+
* produced by earlier ones (reordering requires the full corpus gate).
|
|
6
|
+
*/
|
|
7
|
+
export interface PreprocessorResult {
|
|
8
|
+
cleaned: string;
|
|
9
|
+
format: "mr" | "short";
|
|
10
|
+
}
|
|
11
|
+
export declare function preprocessNist(input: string): PreprocessorResult;
|
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Port of lib/pubid/nist/preprocessor.rb + data/nist/update_codes.yaml.
|
|
3
|
+
* Every regex-based normalization applied before the grammar sees the
|
|
4
|
+
* string. Stage order is load-bearing — later stages match patterns
|
|
5
|
+
* produced by earlier ones (reordering requires the full corpus gate).
|
|
6
|
+
*/
|
|
7
|
+
const UPDATE_CODE_LINES = {
|
|
8
|
+
"NBS MN": "NBS MONO",
|
|
9
|
+
"NIST MN": "NIST MONO",
|
|
10
|
+
"NIST MP": "NBS MP",
|
|
11
|
+
"NIST SP 260-162 2006ed.": "NIST SP 260-162e2006",
|
|
12
|
+
"NIST AI NIST AI 100-2e2023 ipd": "NIST AI 100-2e2023 ipd",
|
|
13
|
+
"NBS CIRC 154suprev": "NBS CIRC 154r1sup",
|
|
14
|
+
"NBS CIRC supJun1925-Jun1926": "NBS CIRC 24e7sup2",
|
|
15
|
+
"NBS CIRC supJun1925-Jun1927": "NBS CIRC 24e7sup3",
|
|
16
|
+
"NBS CIRC 25sup-1924": "NBS CIRC 25sup",
|
|
17
|
+
"NIST SP 260-126 rev 2013": "NIST SP 260-126r2013",
|
|
18
|
+
"NIST CSRC White Paper": "NIST CSWP",
|
|
19
|
+
"NIST SP 800-56ar": "NIST SP 800-56Ar1",
|
|
20
|
+
"NIST.LCIRC": "NIST.LC",
|
|
21
|
+
"NBS.LCIRC": "NBS.LC",
|
|
22
|
+
"NIST LCIRC": "NIST LC",
|
|
23
|
+
"NBS LCIRC": "NBS LC",
|
|
24
|
+
"NIST SP 800-57Pt3r1": "NIST SP 800-57pt3r1",
|
|
25
|
+
NISTIR: "NIST IR",
|
|
26
|
+
"NIST FIPS": "FIPS",
|
|
27
|
+
"NIST.CSWP.01162020pt": "NIST.CSWP.01162020(por)",
|
|
28
|
+
"NBS FIPS 11-1-Sep30": "NBS FIPS 11-1-Sep30/1977",
|
|
29
|
+
"NBS FIPS 89-Sep1": "NBS FIPS 89-Sep1981",
|
|
30
|
+
"FIPS PUB 54-1-Jan15": "FIPS 54-1",
|
|
31
|
+
"FIPS 54-1-Jan15": "FIPS 54-1",
|
|
32
|
+
"FIPS 54-1-Jan17": "FIPS 54-1-Jan17/1991",
|
|
33
|
+
"FIPS PUB": "FIPS",
|
|
34
|
+
"NBS CRPL c4-4": "NBS CRPL 4-4",
|
|
35
|
+
"NIST AMS 300-8r1 (February 2021 update)": "NIST AMS 300-8r1/Upd1-202102",
|
|
36
|
+
"NIST AMS 300-8r1/upd": "NIST AMS 300-8r1/Upd1-202102",
|
|
37
|
+
"NIST IR 8115r1-upd": "NIST IR 8115r1/Upd1-202103",
|
|
38
|
+
"NIST IR 8170-upd": "NIST IR 8170/Upd1-202003",
|
|
39
|
+
"NIST TN 2150-upd": "NIST TN 2150/Upd1-202102",
|
|
40
|
+
"NBS IR 73-197r": "NBS IR 73-197r1",
|
|
41
|
+
"NBS.HB.105-1r1990": "NIST.HB.105-1r1990",
|
|
42
|
+
"NBS.HB.28p11969": "NBS.HB.28-1969pt1",
|
|
43
|
+
"NIST HB 105-1-1990": "NIST HB 105-1r1990",
|
|
44
|
+
"NBS.FIPS.100-1-1991": "NIST.FIPS.100-1-1991",
|
|
45
|
+
"NBS.LC.1088sp": "NBS.LC.1088.spa",
|
|
46
|
+
"NBS LC 1088sp": "NBS LC 1088 spa",
|
|
47
|
+
"NIST SP 955 Suppl.": "NIST SP 955sup",
|
|
48
|
+
"NIST SP 800-38e": "NIST SP 800-38E",
|
|
49
|
+
"NBS.CIRC.supJun1925-Jun1926": "NBS CIRC 24e7sup2",
|
|
50
|
+
"NBS.CIRC.supJun1925-Jun1927": "NBS CIRC 24e7sup3",
|
|
51
|
+
"NIST.TN.2150-upd": "NIST.TN.2150-upd1-202102",
|
|
52
|
+
"NIST.SP.955.Suppl": "NIST.SP.955-S.uppl",
|
|
53
|
+
"NIST SP 782-1995-96": "NIST SP 782-1995",
|
|
54
|
+
"NIST FIPS 54-Jan15": "NIST FIPS 54",
|
|
55
|
+
"NBS report ;": "NBS RPT",
|
|
56
|
+
"NBS TN 467p1adde1": "NBS TN 467pt1-add",
|
|
57
|
+
"NIST SP 1011-II-1.0": "NIST SP 1011v2ver1.0",
|
|
58
|
+
"NIST SP 1011-II-1 0": "NIST SP 1011v2ver1.0",
|
|
59
|
+
"NIST SP 1011-I-2.0": "NIST SP 1011v1ver2.0",
|
|
60
|
+
"NIST SP 1011-I-2 0": "NIST SP 1011v1ver2.0",
|
|
61
|
+
"NIST SP 500-281-v1.0": "NIST SP 500-281v1.0",
|
|
62
|
+
"NIST IR 8259Aes": "NIST IR 8259A(spa)",
|
|
63
|
+
"NIST IR 8259Apt": "NIST IR 8259A(por)",
|
|
64
|
+
"NIST IR 8211-upd": "NIST IR 8211/Upd1-2021",
|
|
65
|
+
"NIST IR 8115r1/upd": "NIST IR 8115r1/Upd1-2021",
|
|
66
|
+
"NBS CS v": "NBS CSM v",
|
|
67
|
+
"NIST SP 800-57p1r2006": "NIST SP 800-57pt1r1",
|
|
68
|
+
"NIST SP 800-57p1r2007": "NIST SP 800-57pt1r2",
|
|
69
|
+
"NIST SP 500-268v1 1": "NIST SP 500-268v1.1",
|
|
70
|
+
"NIST SP 500-270v1 1": "NIST SP 500-270v1.1",
|
|
71
|
+
"NIST SP 500-280v2 1": "NIST SP 500-280v2.1",
|
|
72
|
+
"NIST SP 500-281-v1 0": "NIST SP 500-281v1.0",
|
|
73
|
+
"NIST SP 800-63v1 0 1": "NIST SP 800-63v1.0.1",
|
|
74
|
+
"NIST SP 800-63v1 0 2": "NIST SP 800-63v1.0.2",
|
|
75
|
+
"NIST SP 955 Suppl": "NIST SP 955sup",
|
|
76
|
+
"NIST SP 984 4": "NIST SP 984-4",
|
|
77
|
+
"NISTPUB 0413171251": "NIST TN 1648-2009",
|
|
78
|
+
"NIST HB 135e2022-upd1": "NIST HB 135e2022/Upd1-202205",
|
|
79
|
+
"NIST SP 1900-206-upd1": "NIST SP 1900-206/Upd1-202202",
|
|
80
|
+
"NIST TN 2207-upd1": "NIST TN 2207/Upd1-202205",
|
|
81
|
+
"NIST IR 8290-upd1": "NIST IR 8290/Upd1-202205",
|
|
82
|
+
"NIST IR 8413-upd1": "NIST IR 8413/Upd1-202207",
|
|
83
|
+
"NIST IR 85-3273-37-upd1": "NIST IR 85-3273-37/Upd1-202205",
|
|
84
|
+
"NIST.AMS.300-8r1/upd": "NIST.AMS.300-8r1-upd1",
|
|
85
|
+
"NIST.hb.150-1-2017": "NIST.HB.105-1r2017",
|
|
86
|
+
"nbs.tn.671": "NBS.TN.671",
|
|
87
|
+
"NIST.TN.1648_2009": "NIST.TN.1648e2009",
|
|
88
|
+
"NBS NSRDS": "NSRDS-NBS",
|
|
89
|
+
"nist ir": "NIST IR",
|
|
90
|
+
};
|
|
91
|
+
const UPDATE_CODE_REGEXES = [
|
|
92
|
+
[/\bMonograph\b/, "MONO"],
|
|
93
|
+
[/,\s+(Rev\.|Part\.|Vol\.|Revision|Volume|Part)(?=\s|\d)/, " $1"],
|
|
94
|
+
[/^NBS CIRC sup$/, "NBS CIRC 24e7sup"],
|
|
95
|
+
[/-draft$/, " (Draft)"],
|
|
96
|
+
[/-draft2$/, " 2pd"],
|
|
97
|
+
[/NBS CRPL-F-B(?=\d+)/, "NBS CRPL-F-B "],
|
|
98
|
+
[/(?<=\d)es/, "(spa)"],
|
|
99
|
+
[/(?<=\d)chi/, "(zho)"],
|
|
100
|
+
[/(?<=\d)viet/, "(vie)"],
|
|
101
|
+
[/(?<=\d)port/, "(por)"],
|
|
102
|
+
[/(?<=\d)(pt)(?!\d)/, "(por)"],
|
|
103
|
+
[/(?<=\d)id/, "(ind)"],
|
|
104
|
+
];
|
|
105
|
+
const ROMAN_TO_ARABIC = {
|
|
106
|
+
I: "1", II: "2", III: "3", IV: "4", V: "5", VI: "6",
|
|
107
|
+
VII: "7", VIII: "8", IX: "9", X: "10",
|
|
108
|
+
};
|
|
109
|
+
function romanToArabic(roman) {
|
|
110
|
+
return ROMAN_TO_ARABIC[roman] ?? roman;
|
|
111
|
+
}
|
|
112
|
+
export function preprocessNist(input) {
|
|
113
|
+
let cleaned = input.trim();
|
|
114
|
+
const line = UPDATE_CODE_LINES[cleaned];
|
|
115
|
+
if (line !== undefined) {
|
|
116
|
+
cleaned = line;
|
|
117
|
+
}
|
|
118
|
+
for (const [pattern, replacement] of UPDATE_CODE_REGEXES) {
|
|
119
|
+
cleaned = cleaned.replace(pattern, replacement);
|
|
120
|
+
}
|
|
121
|
+
// The format describes the string the parser will see: freeze it
|
|
122
|
+
// right after the update-codes remap, before the stages' cosmetic
|
|
123
|
+
// spacing (a dotted catalogue alias that remaps to the space form
|
|
124
|
+
// renders short; the dotted originals stay mr).
|
|
125
|
+
const format = cleaned.includes(".") && !/\s/.test(cleaned) ? "mr" : "short";
|
|
126
|
+
// Short-form "supprev" is the catalogue spelling of the plain
|
|
127
|
+
// supplement ("NBS CIRC 154supprev" is "NBS CIRC 154sup"); the
|
|
128
|
+
// revision-bearing identity stays the mr spelling. Must run before
|
|
129
|
+
// the digit+suprev typo fix below.
|
|
130
|
+
if (format === "short") {
|
|
131
|
+
cleaned = cleaned.replace(/supprev/g, "sup");
|
|
132
|
+
}
|
|
133
|
+
// normalize_spurious_u_suffix
|
|
134
|
+
cleaned = cleaned.replace(/(\d)U([a-z])/g, "$1$2");
|
|
135
|
+
// normalize_publisher_and_series
|
|
136
|
+
cleaned = cleaned.replace(/^nbs\b/i, "NBS");
|
|
137
|
+
cleaned = cleaned.replace(/^nist\b/i, "NIST");
|
|
138
|
+
cleaned = cleaned.replace(/^(NBS|NIST)(IR|FIPS|GCR|HB|MONO|MP|NCSTAR|NSRDS)/i, "$1 $2");
|
|
139
|
+
cleaned = cleaned.replace(/\b(ir|sp|tn|hb|fips|ams|vts)\b/i, (m) => m.toUpperCase());
|
|
140
|
+
cleaned = cleaned.replace(/\bLC\b(?!IRC)/g, "LCIRC");
|
|
141
|
+
// normalize_lcirc_supplement_contexts
|
|
142
|
+
cleaned = cleaned.replace(/\bNBS LCIRC\b(?=.*\b(?:supp?|sup\+|r\d+\/)\d)/, "NBS.LCIRC");
|
|
143
|
+
cleaned = cleaned.replace(/\bNBS\.LCIRC\.(\d+r\d+\/\d{4})/, "NBS LCIRC $1");
|
|
144
|
+
cleaned = cleaned.replace(/\bNBS\.LCIRC\.(\d+r\d+)\b/, "NBS LCIRC $1");
|
|
145
|
+
// normalize_revision_spacing
|
|
146
|
+
cleaned = cleaned.replace(/([-\d]+[IVX]+[-\d]+)\s+(\d+)/g, "$1.$2");
|
|
147
|
+
cleaned = cleaned.replace(/(?<!e)(\d)(rev\d{4})/g, "$1 $2");
|
|
148
|
+
cleaned = cleaned.replace(/(\d+e\d+)\.([A-Za-z]{3,9}\d{4})/g, "$1rev$2");
|
|
149
|
+
// normalize_ir_slash_year_to_update
|
|
150
|
+
if (/\bIR\b/.test(cleaned) && !cleaned.includes("CIRC")) {
|
|
151
|
+
cleaned = cleaned.replace(/(\d)r(\d{1,2})\/(\d{2,4})/g, (_m, num, mon, yr) => {
|
|
152
|
+
const yyyy = yr.length === 2 ? `19${yr}` : yr;
|
|
153
|
+
return `${num}/Upd1-${yyyy}${mon.padStart(2, "0")}`;
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
if (!cleaned.includes("LCIRC") && !cleaned.includes("CIRC")) {
|
|
157
|
+
cleaned = cleaned.replace(/(\d)(r\d+\/\d{4})/g, "$1 $2");
|
|
158
|
+
}
|
|
159
|
+
cleaned = cleaned.replace(/\b(r(?!v)\d{4})\b/g, " $1");
|
|
160
|
+
cleaned = cleaned.replace(/(\d)(r[A-Z][a-z]{2,8}\d{4})/g, "$1 $2");
|
|
161
|
+
// normalize_letter_suffix_casing
|
|
162
|
+
cleaned = cleaned.replace(/(\d)-([a-z])$/, (_m, d, l) => `${d}-${l.toUpperCase()}`);
|
|
163
|
+
// Same letter when an addendum tail follows ("-add", " Add.");
|
|
164
|
+
// part digits ("800-85a-1") and update/translation codes never match.
|
|
165
|
+
cleaned = cleaned.replace(/(\d)-([a-z])(?=\s*[-.\s]\s*[aA]dd)/, (_m, d, l) => `${d}-${l.toUpperCase()}`);
|
|
166
|
+
cleaned = cleaned.replace(/(\d)([a-qs-z])(?=\s*[-.\s]\s*[aA]dd)/, (_m, d, l) => `${d}${l.toUpperCase()}`);
|
|
167
|
+
cleaned = cleaned.replace(/(\d)([a-qs-z])$/, (_m, d, l) => `${d}${l.toUpperCase()}`);
|
|
168
|
+
cleaned = cleaned.replace(/(\d)(r)(\d+)([a-z])$/, (_m, d, r, n, l) => `${d}${r}${n}${l.toUpperCase()}`);
|
|
169
|
+
cleaned = cleaned.replace(/(\d)([a-z])(r\d)/g, (_m, d, l, r) => `${d}${l.toUpperCase()}${r}`);
|
|
170
|
+
if (!cleaned.includes("NCSTAR")) {
|
|
171
|
+
cleaned = cleaned.replace(/(\d)([a-qs-z])(v\d+)/g, (_m, d, l, v) => `${d}${l.toUpperCase()}${v}`);
|
|
172
|
+
}
|
|
173
|
+
// normalize_draft_and_volume
|
|
174
|
+
cleaned = cleaned.replace(/(\d{2}-\d{4})\s+(\d)$/, "$1 v$2");
|
|
175
|
+
cleaned = cleaned.replace(/(\d)-draft(\d)/g, "$1 -draft $2");
|
|
176
|
+
cleaned = cleaned.replace(/(\d)draft(\d)/g, "$1 -draft $2");
|
|
177
|
+
cleaned = cleaned.replace(/(\d)suprev/g, "$1supprev");
|
|
178
|
+
cleaned = cleaned.replace(/(\d{2,})([A-Z])(r\d+)([-\s]draft\d*)/g, "$1$2 $3$4");
|
|
179
|
+
// convert_roman_volumes
|
|
180
|
+
cleaned = cleaned.replace(/(\d+)-([IVX]+)-(\d+(?:\.\d+)*)/g, (_m, n, roman, ver) => `${n} v${romanToArabic(roman)} ver${ver}`);
|
|
181
|
+
// normalize_supplement_and_part
|
|
182
|
+
cleaned = cleaned.replace(/(\d)(supp\d+\/\d{4})/g, "$1 $2");
|
|
183
|
+
cleaned = cleaned.replace(/(\d)Pt(\d+)(r\d+)/g, "$1 pt$2 $3");
|
|
184
|
+
// normalize_version_notation
|
|
185
|
+
cleaned = cleaned.replace(/(\d)ver(\d)/g, "$1 ver $2");
|
|
186
|
+
cleaned = cleaned.replace(/ver(\d+)e(\d{4})/g, "ver$1 e$2");
|
|
187
|
+
cleaned = cleaned.replace(/ver(\d+)v(\d+)/g, "ver$1 v$2");
|
|
188
|
+
cleaned = cleaned.replace(/(\d)(v\d+\.\d+)/g, "$1 $2");
|
|
189
|
+
cleaned = cleaned.replace(/(\d)(v\d+\.\d+)/g, "$1 $2");
|
|
190
|
+
cleaned = cleaned.replace(/(\d)(v\d+)\s+(\d+)$/g, "$1 $2.$3");
|
|
191
|
+
cleaned = cleaned.replace(/(\d)(v\d+)\s+(\d+)\s+(\d+)$/g, "$1 $2.$3.$4");
|
|
192
|
+
cleaned = cleaned.replace(/(\d)(v\d+[a-z]-[a-z])/g, "$1 $2");
|
|
193
|
+
cleaned = cleaned.replace(/(\d)(v\d+[A-Z])/g, "$1 $2");
|
|
194
|
+
cleaned = cleaned.replace(/(v\d+)([A-Z])-([A-Z])/g, (_m, v, a, b) => `${v}${a}-${b.toLowerCase()}`);
|
|
195
|
+
// normalize_edition_year_suffix
|
|
196
|
+
cleaned = cleaned.replace(/(\d{4})ed\./g, "e$1");
|
|
197
|
+
// normalize_revision_with_letter
|
|
198
|
+
cleaned = cleaned.replace(/(\d+)(r\d{1,2})([a-z])(?=-|[A-Z]|$)/g, (_m, n, r, l) => `${n}${r}${l.toUpperCase()}`);
|
|
199
|
+
cleaned = cleaned.replace(/(\d+)(r\d{1,2})(?![a-zA-Z])(?=[A-Z]|-(?=[A-Z])|\/(?:upd|errata|insert))/g, "$1 $2");
|
|
200
|
+
// normalize_version_dotted_spaces
|
|
201
|
+
cleaned = cleaned.replace(/(\b(?:v|\d)[v\d]*[-A-Z]*)\s+(\d+)(?!(?:pd|wd|prd|PD|WD|PRD)\b)\s+(\d+)(?!(?:pd|wd|prd|PD|WD|PRD)\b)/g, "$1.$2.$3");
|
|
202
|
+
cleaned = cleaned.replace(/(\b(?:v|\d)[v\d]*)\s+(\d+)(?!(?:pd|wd|prd|PD|WD|PRD)\b)/g, "$1.$2");
|
|
203
|
+
// normalize_update_markers
|
|
204
|
+
cleaned = cleaned.replace(/(\d+)-upd(\d*)/g, "$1 -upd$2");
|
|
205
|
+
cleaned = cleaned.replace(/(\d+)\/upd(\d*)/g, "$1 /upd$2");
|
|
206
|
+
cleaned = cleaned.replace(/([a-z]\d+)-upd/g, "$1 -upd");
|
|
207
|
+
cleaned = cleaned.replace(/([a-z]\d+)\/upd/g, "$1 /upd");
|
|
208
|
+
cleaned = cleaned.replace(/(\d+[A-Z])-upd(\d*)/g, "$1 -upd$2");
|
|
209
|
+
cleaned = cleaned.replace(/(\d+[A-Z])\/upd(\d*)/g, "$1 /upd$2");
|
|
210
|
+
// normalize_supplement_variants
|
|
211
|
+
cleaned = cleaned.replace(/(\d)(sup\d)/g, "$1 $2");
|
|
212
|
+
cleaned = cleaned.replace(/(\d)(sup+)(\d)/g, "$1 $2$3");
|
|
213
|
+
cleaned = cleaned.replace(/(\d)(sup\+)(\d)/g, "$1 $2$3");
|
|
214
|
+
cleaned = cleaned.replace(/(\d)(sup\d+)/g, "$1 $2");
|
|
215
|
+
cleaned = cleaned.replace(/(\d)(sup\d+\b)/g, "$1 $2");
|
|
216
|
+
cleaned = cleaned.replace(/(\d+[A-Z])sup(\b)/g, "$1supp$2");
|
|
217
|
+
cleaned = cleaned.replace(/(\d+)sup(\d+\/\d{4})/g, "$1supp$2");
|
|
218
|
+
cleaned = cleaned.replace(/(\d)(supp?)-(\d{4})(?![\d\/])/g, "$1supp$3");
|
|
219
|
+
// normalize_revision_language
|
|
220
|
+
cleaned = cleaned.replace(/(\d[a-z])r\b/g, "$1 r");
|
|
221
|
+
cleaned = cleaned.replace(/(\d)r\z/, "$1r1");
|
|
222
|
+
cleaned = cleaned.replace(/(r\d+)(es|pt|chi|viet|port|esp)\b/g, "$1 $2");
|
|
223
|
+
// normalize_mr_translation_codes
|
|
224
|
+
cleaned = cleaned.replace(/^([A-Z]+)\.SP\.(\d+)\.([a-z]{2,4})$/, "$1.SP.$2 $3");
|
|
225
|
+
cleaned = cleaned.replace(/^([A-Z]+)\.([A-Z]+)\.(\d+)\.([a-z]{2,4})$/, "$1.$2.$3 $4");
|
|
226
|
+
// convert_dashyear_to_edition
|
|
227
|
+
cleaned = cleaned.replace(/(?<!e\d)(?<![eE-])(\d(?:[A-DF-Za-df-z]?))-(\d{4})(?=\s|$)/g, (match, prefix, year) => {
|
|
228
|
+
const yearNum = Number(year);
|
|
229
|
+
return yearNum >= 1901 && yearNum <= 2099 ? `${prefix.toUpperCase()}e${year}` : match;
|
|
230
|
+
});
|
|
231
|
+
// revert_dashyear_for_series
|
|
232
|
+
if (cleaned.includes("CIRC")) {
|
|
233
|
+
cleaned = cleaned.replace(/(CIRC[ .])(supp?)(\d{4})e(\d{4})(?=\s|$)/g, "$1$2$3-$4");
|
|
234
|
+
}
|
|
235
|
+
cleaned = cleaned.replace(/\b(HB|HB\s+)[^:\s.]*?(\d+)e(\d{4})(?=\s|$)/g, "$1$2-$3");
|
|
236
|
+
cleaned = cleaned.replace(/\b(OWMWP|OWMWP\s*)[^:\s]*?(\d{2})-(\d{2})e(\d{4})(?=\s|$)/g, "$1$2-$3-$4");
|
|
237
|
+
cleaned = cleaned.replace(/\b(RPT|RPT\s*)([^:\s]*?)(\d{4})e(\d{4})(?=\s|$)/g, (match, prefix, sep, first, second) => Number(first) < Number(second) ? `${prefix}${sep}${first}-${second}` : match);
|
|
238
|
+
// normalize_version_verbose
|
|
239
|
+
cleaned = cleaned.replace(/-v(\d+\.\d+)/g, ".ver$1");
|
|
240
|
+
cleaned = cleaned.replace(/\bVer\.\s+(\d+(?:\.\d+)*)/g, "ver$1");
|
|
241
|
+
cleaned = cleaned.replace(/\bv(\d+\.\d+(?:\.\d+)*)/g, "ver$1");
|
|
242
|
+
// normalize_part_notation
|
|
243
|
+
cleaned = cleaned.replace(/(\d)P(\d)/g, "$1 p$2");
|
|
244
|
+
cleaned = cleaned.replace(/\b([pn])(\d+)(?!\d{4}\b)/g, "pt$2");
|
|
245
|
+
cleaned = cleaned.replace(/(\d)([pP]\d+)/g, "$1 $2");
|
|
246
|
+
// normalize_series_specific_spacing
|
|
247
|
+
cleaned = cleaned.replace(/(NBS CRPL-F-[AB])(\d)/g, "$1 $2");
|
|
248
|
+
cleaned = cleaned.replace(/(CRPL-F-[AB])(\d)/g, "$1 $2");
|
|
249
|
+
cleaned = cleaned.replace(/(\d+-\d+)(v\d+)(?![.\d])/g, "$1 $2");
|
|
250
|
+
// normalize_verbose_keywords
|
|
251
|
+
cleaned = cleaned.replace(/(\d+)\s+Suppl\b/g, "$1Suppl");
|
|
252
|
+
cleaned = cleaned.replace(/\s+Version\s+(\d+)/g, " ver $1");
|
|
253
|
+
cleaned = cleaned.replace(/\s+Revision\s+\(r\)/g, " r");
|
|
254
|
+
cleaned = cleaned.replace(/\s+Part\s+(\d+)/g, "pt$1");
|
|
255
|
+
cleaned = cleaned.replace(/(\d[a-z]?)\s+Add\b\.?/gi, (_m, d) => `${d.toUpperCase()} Add.`);
|
|
256
|
+
cleaned = cleaned.replace(/(\d+)\s+rev\s+(\d{4})/g, "$1r$2");
|
|
257
|
+
cleaned = cleaned.replace(/\breport\s*;\s*/g, "RPT ");
|
|
258
|
+
cleaned = cleaned.replace(/\breport\b/g, "RPT");
|
|
259
|
+
// normalize_legacy_corpus_spellings: catalogue forms the grammar and
|
|
260
|
+
// the renderers cannot round-trip on their own. Each rule mirrors an
|
|
261
|
+
// already-parseable spelling of the same document.
|
|
262
|
+
// The mr renderer prints the translation code with its own leading
|
|
263
|
+
// dot ("955-S..uppl"); the grammar wants one dot.
|
|
264
|
+
cleaned = cleaned.replace(/\.\./g, ".");
|
|
265
|
+
// Trailing-dot addendum spelling; the canonical render comes from
|
|
266
|
+
// the lowercase ".add" parse ("NBS.TN.467pt1.Add." -> ".add").
|
|
267
|
+
cleaned = cleaned.replace(/\.Add\.$/, ".add");
|
|
268
|
+
// Edition glued to the series in mr form ("NBS.CIRCe2" is
|
|
269
|
+
// "NBS.CIRC.e2"); digits before "e" are untouched ("24e7").
|
|
270
|
+
if (format === "mr") {
|
|
271
|
+
cleaned = cleaned.replace(/([A-Z])e(\d)/g, "$1.e$2");
|
|
272
|
+
}
|
|
273
|
+
// Update markers without a number render a phantom "1";
|
|
274
|
+
// "…-upd" is the numberless spelling of "…-upd1".
|
|
275
|
+
cleaned = cleaned.replace(/-upd$/, "-upd1");
|
|
276
|
+
// NIST-era handbook renumbering in the all-dash spelling ("NIST HB
|
|
277
|
+
// 150-1-2017" -> "NIST HB 1-2017"; NBS-era compound numbers keep
|
|
278
|
+
// their number).
|
|
279
|
+
cleaned = cleaned.replace(/\b(NIST HB\s+)(?:105|150)-(\d+)-(\d{4})(?=\s|$)/, "$1$2-$3");
|
|
280
|
+
return { cleaned, format };
|
|
281
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Grammar } from "../../grammar/engine.js";
|
|
2
|
+
import type { FlavorImplementation } from "../../conformance/implementation.js";
|
|
3
|
+
import { BaseIdentifier } from "../../model/identifier.js";
|
|
4
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
5
|
+
export declare const oasisGrammar: Grammar;
|
|
6
|
+
declare class OasisUrnGenerator extends BaseUrnGenerator<OasisIdentifier> {
|
|
7
|
+
generate(): string;
|
|
8
|
+
}
|
|
9
|
+
export declare class OasisIdentifier extends BaseIdentifier {
|
|
10
|
+
static polymorphicName: string;
|
|
11
|
+
static attributes: import("../../model/attribute.js").AttributeTable;
|
|
12
|
+
static mappings: import("../../model/attribute.js").FieldMapping[];
|
|
13
|
+
static urnGenerator: typeof OasisUrnGenerator;
|
|
14
|
+
readonly original: string;
|
|
15
|
+
readonly number: string | undefined;
|
|
16
|
+
readonly version: string | undefined;
|
|
17
|
+
readonly stage: string | undefined;
|
|
18
|
+
readonly part: string | undefined;
|
|
19
|
+
readonly label: string | undefined;
|
|
20
|
+
render(): string;
|
|
21
|
+
}
|
|
22
|
+
export declare function oasisGrammarImplementation(): FlavorImplementation;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { match, str } from "../../grammar/engine.js";
|
|
2
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
3
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
4
|
+
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
5
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
6
|
+
import { BaseBuilder } from "../../model/builder.js";
|
|
7
|
+
/**
|
|
8
|
+
* 1:1 port of lib/pubid/oasis/ on the unified model. The grammar strips
|
|
9
|
+
* "OASIS " and captures the slug verbatim; the builder decomposes it
|
|
10
|
+
* order-independently by classifying WHOLE dash-fragments (stage tokens
|
|
11
|
+
* are case-sensitive). `original` alone drives the human form; the URN
|
|
12
|
+
* percent-encodes only the space and stray "]" of malformed records.
|
|
13
|
+
*/
|
|
14
|
+
function buildRules() {
|
|
15
|
+
const rules = {};
|
|
16
|
+
const rule = (name, build) => {
|
|
17
|
+
rules[name] = build();
|
|
18
|
+
};
|
|
19
|
+
rule("prefix", () => str("OASIS").then(str(" ")));
|
|
20
|
+
rule("slug", () => match("[\\s\\S]").repeat(1, Infinity).as("original"));
|
|
21
|
+
rule("identifier", () => rules["prefix"].then(rules["slug"]));
|
|
22
|
+
rule("root", () => rules["identifier"]);
|
|
23
|
+
return rules;
|
|
24
|
+
}
|
|
25
|
+
export const oasisGrammar = { rules: buildRules(), root: "root" };
|
|
26
|
+
class OasisUrnGenerator extends BaseUrnGenerator {
|
|
27
|
+
generate() {
|
|
28
|
+
const slug = this.identifier.original.replace(/[ \]]/g, (c) => (c === " " ? "%20" : "%5D"));
|
|
29
|
+
return `urn:oasis:${slug}`;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
export class OasisIdentifier extends BaseIdentifier {
|
|
33
|
+
static polymorphicName = "pubid:oasis:standard";
|
|
34
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
35
|
+
original: { type: "string" },
|
|
36
|
+
number: { type: "string" },
|
|
37
|
+
version: { type: "string" },
|
|
38
|
+
stage: { type: "string" },
|
|
39
|
+
part: { type: "string" },
|
|
40
|
+
label: { type: "string" },
|
|
41
|
+
});
|
|
42
|
+
static mappings = keyValue({ wire: "original", to: "original" }, { wire: "number", to: "number" }, { wire: "version", to: "version" }, { wire: "stage", to: "stage" }, { wire: "part", to: "part" }, { wire: "label", to: "label" });
|
|
43
|
+
static urnGenerator = OasisUrnGenerator;
|
|
44
|
+
render() {
|
|
45
|
+
return `OASIS ${this.original}`;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
registerType(OasisIdentifier);
|
|
49
|
+
// v?N(.N)+ (bare integers deliberately NOT versions); stage tokens are
|
|
50
|
+
// CASE-SENSITIVE; part spellings incl. bare "Pt"/"P".
|
|
51
|
+
const VERSION_RE = /^v?\d+(?:\.\d+)+$/i;
|
|
52
|
+
const STAGE_RE = /^(?:CSPRD|CSD|COS|CS|WD|OS|PS|PRD|CD|Errata)\d*$/;
|
|
53
|
+
const PART_RE = /^(?:Part|Pt|part|P)\d*$/;
|
|
54
|
+
function classify(fragment) {
|
|
55
|
+
if (VERSION_RE.test(fragment))
|
|
56
|
+
return "version";
|
|
57
|
+
if (STAGE_RE.test(fragment))
|
|
58
|
+
return "stage";
|
|
59
|
+
if (PART_RE.test(fragment))
|
|
60
|
+
return "part";
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
class OasisBuilder extends BaseBuilder {
|
|
64
|
+
defaultIdentifierClass() {
|
|
65
|
+
return OasisIdentifier;
|
|
66
|
+
}
|
|
67
|
+
cast(key, value) {
|
|
68
|
+
if (key !== "original")
|
|
69
|
+
return value;
|
|
70
|
+
const original = String(value);
|
|
71
|
+
const attrs = { original };
|
|
72
|
+
const pairs = original.split("-").map((f) => [f, classify(f)]);
|
|
73
|
+
const leadEnd = pairs.findIndex(([, kind]) => kind !== undefined);
|
|
74
|
+
const lead = leadEnd === -1 ? pairs : pairs.slice(0, leadEnd);
|
|
75
|
+
const rest = leadEnd === -1 ? [] : pairs.slice(leadEnd);
|
|
76
|
+
const names = (ps) => {
|
|
77
|
+
const fragments = ps.filter(([, kind]) => kind === undefined).map(([f]) => f);
|
|
78
|
+
return fragments.length === 0 ? undefined : fragments.join("-");
|
|
79
|
+
};
|
|
80
|
+
const firstOf = (kind) => rest.find(([, k]) => k === kind)?.[0];
|
|
81
|
+
const number = names(lead);
|
|
82
|
+
if (number !== undefined)
|
|
83
|
+
attrs["number"] = number;
|
|
84
|
+
const version = firstOf("version");
|
|
85
|
+
if (version !== undefined)
|
|
86
|
+
attrs["version"] = version;
|
|
87
|
+
const stage = firstOf("stage");
|
|
88
|
+
if (stage !== undefined)
|
|
89
|
+
attrs["stage"] = stage;
|
|
90
|
+
const part = firstOf("part");
|
|
91
|
+
if (part !== undefined)
|
|
92
|
+
attrs["part"] = part;
|
|
93
|
+
const label = names(rest);
|
|
94
|
+
if (label !== undefined)
|
|
95
|
+
attrs["label"] = label;
|
|
96
|
+
return attrs;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export function oasisGrammarImplementation() {
|
|
100
|
+
const builder = new OasisBuilder();
|
|
101
|
+
return {
|
|
102
|
+
parse(input) {
|
|
103
|
+
const tree = parseGrammar(oasisGrammar, input);
|
|
104
|
+
if (typeof tree !== "object" || tree === null || Array.isArray(tree)) {
|
|
105
|
+
throw new ParseFailed("OASIS: unexpected parse tree", 0);
|
|
106
|
+
}
|
|
107
|
+
return builder.build(tree);
|
|
108
|
+
},
|
|
109
|
+
};
|
|
110
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Grammar } from "../../grammar/engine.js";
|
|
2
|
+
import type { FlavorImplementation } from "../../conformance/implementation.js";
|
|
3
|
+
import { BaseIdentifier } from "../../model/identifier.js";
|
|
4
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
5
|
+
export declare const ogcGrammar: Grammar;
|
|
6
|
+
declare class OgcUrnGenerator extends BaseUrnGenerator<OgcIdentifier> {
|
|
7
|
+
generate(): string;
|
|
8
|
+
}
|
|
9
|
+
export declare class OgcIdentifier extends BaseIdentifier {
|
|
10
|
+
static polymorphicName: string;
|
|
11
|
+
static attributes: import("../../model/attribute.js").AttributeTable;
|
|
12
|
+
static mappings: import("../../model/attribute.js").FieldMapping[];
|
|
13
|
+
static urnGenerator: typeof OgcUrnGenerator;
|
|
14
|
+
readonly year: string;
|
|
15
|
+
readonly number: string;
|
|
16
|
+
readonly revision: string | undefined;
|
|
17
|
+
render(): string;
|
|
18
|
+
}
|
|
19
|
+
export declare function ogcGrammarImplementation(): FlavorImplementation;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { match, str } from "../../grammar/engine.js";
|
|
2
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
3
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
4
|
+
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
5
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
6
|
+
import { BaseBuilder } from "../../model/builder.js";
|
|
7
|
+
/**
|
|
8
|
+
* 1:1 port of lib/pubid/ogc/ on the unified model. "<yy>-<nnn>[<revision>]"
|
|
9
|
+
* with no publisher token in the printed form; strings preserve zero
|
|
10
|
+
* padding; the revision normalizes to lower case. URN:
|
|
11
|
+
* urn:ogc:<year>:<number>[:<revision>] (the Ruby flavor's generator).
|
|
12
|
+
*/
|
|
13
|
+
function buildRules() {
|
|
14
|
+
const rules = {};
|
|
15
|
+
const rule = (name, build) => {
|
|
16
|
+
rules[name] = build();
|
|
17
|
+
};
|
|
18
|
+
const space = match("[\\s]").repeat(1, Infinity);
|
|
19
|
+
const digits = match("[0-9]").repeat(1, Infinity);
|
|
20
|
+
const revision = match("[A-Za-z0-9]").repeat(1, Infinity).as("revision");
|
|
21
|
+
rule("publisher", () => str("OGC").then(space).maybe());
|
|
22
|
+
rule("identifier", () => rules["publisher"]
|
|
23
|
+
.then(digits.as("year"), str("-"), digits.as("number"))
|
|
24
|
+
.then(revision.maybe())
|
|
25
|
+
.then(space.maybe()));
|
|
26
|
+
rule("root", () => rules["identifier"]);
|
|
27
|
+
return rules;
|
|
28
|
+
}
|
|
29
|
+
export const ogcGrammar = { rules: buildRules(), root: "root" };
|
|
30
|
+
class OgcUrnGenerator extends BaseUrnGenerator {
|
|
31
|
+
generate() {
|
|
32
|
+
const parts = ["urn", "ogc", this.identifier.year, this.identifier.number];
|
|
33
|
+
if (this.identifier.revision !== undefined)
|
|
34
|
+
parts.push(this.identifier.revision);
|
|
35
|
+
return parts.join(":");
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export class OgcIdentifier extends BaseIdentifier {
|
|
39
|
+
static polymorphicName = "pubid:ogc:document";
|
|
40
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
41
|
+
year: { type: "string" },
|
|
42
|
+
number: { type: "string" },
|
|
43
|
+
revision: { type: "string" },
|
|
44
|
+
});
|
|
45
|
+
static mappings = keyValue({ wire: "year", to: "year" }, { wire: "number", to: "number" }, { wire: "revision", to: "revision" });
|
|
46
|
+
static urnGenerator = OgcUrnGenerator;
|
|
47
|
+
render() {
|
|
48
|
+
return `${this.year}-${this.number}${this.revision ?? ""}`;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
registerType(OgcIdentifier);
|
|
52
|
+
class OgcBuilder extends BaseBuilder {
|
|
53
|
+
defaultIdentifierClass() {
|
|
54
|
+
return OgcIdentifier;
|
|
55
|
+
}
|
|
56
|
+
cast(key, value) {
|
|
57
|
+
if (key === "revision") {
|
|
58
|
+
const normalized = String(value).trim().toLowerCase();
|
|
59
|
+
return normalized === "" ? null : { revision: normalized };
|
|
60
|
+
}
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
export function ogcGrammarImplementation() {
|
|
65
|
+
const builder = new OgcBuilder();
|
|
66
|
+
return {
|
|
67
|
+
parse(input) {
|
|
68
|
+
const tree = parseGrammar(ogcGrammar, input);
|
|
69
|
+
if (typeof tree !== "object" || tree === null || Array.isArray(tree)) {
|
|
70
|
+
throw new ParseFailed("OGC: unexpected parse tree", 0);
|
|
71
|
+
}
|
|
72
|
+
return builder.build(tree);
|
|
73
|
+
},
|
|
74
|
+
};
|
|
75
|
+
}
|