@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.
Files changed (185) hide show
  1. package/artifact/corpus.json.gz +0 -0
  2. package/dist/conformance/cli.js +5 -1
  3. package/dist/flavors/amca/grammar.d.ts +4 -0
  4. package/dist/flavors/amca/grammar.js +87 -0
  5. package/dist/flavors/amca/index.d.ts +4 -0
  6. package/dist/flavors/amca/index.js +76 -0
  7. package/dist/flavors/amca/model.d.ts +29 -0
  8. package/dist/flavors/amca/model.js +146 -0
  9. package/dist/flavors/ansi/index.d.ts +24 -0
  10. package/dist/flavors/ansi/index.js +147 -0
  11. package/dist/flavors/api/grammar.d.ts +4 -0
  12. package/dist/flavors/api/grammar.js +79 -0
  13. package/dist/flavors/api/index.d.ts +4 -0
  14. package/dist/flavors/api/index.js +71 -0
  15. package/dist/flavors/api/model.d.ts +27 -0
  16. package/dist/flavors/api/model.js +114 -0
  17. package/dist/flavors/ashrae/grammar.d.ts +2 -0
  18. package/dist/flavors/ashrae/grammar.js +667 -0
  19. package/dist/flavors/ashrae/index.d.ts +4 -0
  20. package/dist/flavors/ashrae/index.js +306 -0
  21. package/dist/flavors/ashrae/model.d.ts +87 -0
  22. package/dist/flavors/ashrae/model.js +335 -0
  23. package/dist/flavors/ashrae/preprocessor.d.ts +7 -0
  24. package/dist/flavors/ashrae/preprocessor.js +44 -0
  25. package/dist/flavors/asme/grammar.d.ts +2 -0
  26. package/dist/flavors/asme/grammar.js +200 -0
  27. package/dist/flavors/asme/index.d.ts +4 -0
  28. package/dist/flavors/asme/index.js +138 -0
  29. package/dist/flavors/asme/model.d.ts +34 -0
  30. package/dist/flavors/asme/model.js +123 -0
  31. package/dist/flavors/astm/grammar.d.ts +2 -0
  32. package/dist/flavors/astm/grammar.js +110 -0
  33. package/dist/flavors/astm/index.d.ts +2 -0
  34. package/dist/flavors/astm/index.js +127 -0
  35. package/dist/flavors/astm/model.d.ts +42 -0
  36. package/dist/flavors/astm/model.js +263 -0
  37. package/dist/flavors/bipm/index.d.ts +30 -0
  38. package/dist/flavors/bipm/index.js +434 -0
  39. package/dist/flavors/bsi/grammar.d.ts +4 -0
  40. package/dist/flavors/bsi/grammar.js +535 -0
  41. package/dist/flavors/bsi/index.d.ts +4 -0
  42. package/dist/flavors/bsi/index.js +941 -0
  43. package/dist/flavors/bsi/model.d.ts +127 -0
  44. package/dist/flavors/bsi/model.js +863 -0
  45. package/dist/flavors/calconnect/index.d.ts +21 -0
  46. package/dist/flavors/calconnect/index.js +113 -0
  47. package/dist/flavors/cen_cenelec/grammar.d.ts +4 -0
  48. package/dist/flavors/cen_cenelec/grammar.js +107 -0
  49. package/dist/flavors/cen_cenelec/index.d.ts +5 -0
  50. package/dist/flavors/cen_cenelec/index.js +263 -0
  51. package/dist/flavors/cen_cenelec/model.d.ts +45 -0
  52. package/dist/flavors/cen_cenelec/model.js +490 -0
  53. package/dist/flavors/cie/grammar.d.ts +5 -0
  54. package/dist/flavors/cie/grammar.js +127 -0
  55. package/dist/flavors/cie/index.d.ts +2 -0
  56. package/dist/flavors/cie/index.js +311 -0
  57. package/dist/flavors/cie/model.d.ts +122 -0
  58. package/dist/flavors/cie/model.js +464 -0
  59. package/dist/flavors/csa/grammar.d.ts +6 -0
  60. package/dist/flavors/csa/grammar.js +239 -0
  61. package/dist/flavors/csa/index.d.ts +2 -0
  62. package/dist/flavors/csa/index.js +634 -0
  63. package/dist/flavors/csa/model.d.ts +33 -0
  64. package/dist/flavors/csa/model.js +505 -0
  65. package/dist/flavors/doi/index.d.ts +13 -0
  66. package/dist/flavors/doi/index.js +65 -0
  67. package/dist/flavors/easc/index.d.ts +4 -0
  68. package/dist/flavors/easc/index.js +107 -0
  69. package/dist/flavors/ecma/index.d.ts +4 -0
  70. package/dist/flavors/ecma/index.js +117 -0
  71. package/dist/flavors/etsi/index.d.ts +14 -0
  72. package/dist/flavors/etsi/index.js +307 -0
  73. package/dist/flavors/evs/grammar.d.ts +2 -0
  74. package/dist/flavors/evs/grammar.js +22 -0
  75. package/dist/flavors/evs/index.d.ts +2 -0
  76. package/dist/flavors/evs/index.js +24 -0
  77. package/dist/flavors/evs/model.d.ts +19 -0
  78. package/dist/flavors/evs/model.js +36 -0
  79. package/dist/flavors/gb/index.d.ts +31 -0
  80. package/dist/flavors/gb/index.js +159 -0
  81. package/dist/flavors/gost/grammar.d.ts +2 -0
  82. package/dist/flavors/gost/grammar.js +46 -0
  83. package/dist/flavors/gost/index.d.ts +2 -0
  84. package/dist/flavors/gost/index.js +165 -0
  85. package/dist/flavors/gost/model.d.ts +61 -0
  86. package/dist/flavors/gost/model.js +147 -0
  87. package/dist/flavors/gost/prefix_routes.d.ts +15 -0
  88. package/dist/flavors/gost/prefix_routes.js +192 -0
  89. package/dist/flavors/iala/index.d.ts +32 -0
  90. package/dist/flavors/iala/index.js +300 -0
  91. package/dist/flavors/iana/index.d.ts +19 -0
  92. package/dist/flavors/iana/index.js +71 -0
  93. package/dist/flavors/idf/grammar.d.ts +2 -0
  94. package/dist/flavors/idf/grammar.js +71 -0
  95. package/dist/flavors/idf/index.d.ts +2 -0
  96. package/dist/flavors/idf/index.js +100 -0
  97. package/dist/flavors/idf/model.d.ts +54 -0
  98. package/dist/flavors/idf/model.js +359 -0
  99. package/dist/flavors/iec/grammar.d.ts +3 -0
  100. package/dist/flavors/iec/grammar.js +187 -0
  101. package/dist/flavors/iec/index.d.ts +4 -0
  102. package/dist/flavors/iec/index.js +507 -0
  103. package/dist/flavors/iec/model.d.ts +54 -0
  104. package/dist/flavors/iec/model.js +437 -0
  105. package/dist/flavors/ieee/grammar.d.ts +2 -0
  106. package/dist/flavors/ieee/grammar.js +697 -0
  107. package/dist/flavors/ieee/index.d.ts +3 -0
  108. package/dist/flavors/ieee/index.js +1258 -0
  109. package/dist/flavors/ieee/model.d.ts +144 -0
  110. package/dist/flavors/ieee/model.js +1237 -0
  111. package/dist/flavors/ieee/preprocessor.d.ts +8 -0
  112. package/dist/flavors/ieee/preprocessor.js +410 -0
  113. package/dist/flavors/ieee/update_codes.d.ts +8 -0
  114. package/dist/flavors/ieee/update_codes.js +197 -0
  115. package/dist/flavors/ietf/index.d.ts +30 -0
  116. package/dist/flavors/ietf/index.js +151 -0
  117. package/dist/flavors/iho/index.d.ts +4 -0
  118. package/dist/flavors/iho/index.js +126 -0
  119. package/dist/flavors/index.d.ts +9 -0
  120. package/dist/flavors/index.js +136 -0
  121. package/dist/flavors/isbn/index.d.ts +13 -0
  122. package/dist/flavors/isbn/index.js +97 -0
  123. package/dist/flavors/iso/grammar.d.ts +2 -0
  124. package/dist/flavors/iso/grammar.js +207 -0
  125. package/dist/flavors/iso/index.d.ts +2 -0
  126. package/dist/flavors/iso/index.js +343 -0
  127. package/dist/flavors/iso/model.d.ts +159 -0
  128. package/dist/flavors/iso/model.js +802 -0
  129. package/dist/flavors/iso/stages.generated.d.ts +13 -0
  130. package/dist/flavors/iso/stages.generated.js +391 -0
  131. package/dist/flavors/itu/grammar.d.ts +4 -0
  132. package/dist/flavors/itu/grammar.js +205 -0
  133. package/dist/flavors/itu/index.d.ts +2 -0
  134. package/dist/flavors/itu/index.js +224 -0
  135. package/dist/flavors/itu/model.d.ts +184 -0
  136. package/dist/flavors/itu/model.js +599 -0
  137. package/dist/flavors/jcgm/index.d.ts +7 -0
  138. package/dist/flavors/jcgm/index.js +300 -0
  139. package/dist/flavors/jis/index.d.ts +4 -0
  140. package/dist/flavors/jis/index.js +267 -0
  141. package/dist/flavors/nist/grammar.d.ts +2 -0
  142. package/dist/flavors/nist/grammar.js +287 -0
  143. package/dist/flavors/nist/index.d.ts +2 -0
  144. package/dist/flavors/nist/index.js +1244 -0
  145. package/dist/flavors/nist/model.d.ts +155 -0
  146. package/dist/flavors/nist/model.js +823 -0
  147. package/dist/flavors/nist/preprocessor.d.ts +11 -0
  148. package/dist/flavors/nist/preprocessor.js +281 -0
  149. package/dist/flavors/oasis/index.d.ts +23 -0
  150. package/dist/flavors/oasis/index.js +110 -0
  151. package/dist/flavors/ogc/index.d.ts +20 -0
  152. package/dist/flavors/ogc/index.js +75 -0
  153. package/dist/flavors/oiml/grammar.d.ts +2 -0
  154. package/dist/flavors/oiml/grammar.js +206 -0
  155. package/dist/flavors/oiml/implementation.d.ts +9 -0
  156. package/dist/flavors/oiml/implementation.js +45 -0
  157. package/dist/flavors/oiml/model.d.ts +23 -0
  158. package/dist/flavors/oiml/model.js +592 -0
  159. package/dist/flavors/omg/index.d.ts +14 -0
  160. package/dist/flavors/omg/index.js +73 -0
  161. package/dist/flavors/plateau/index.d.ts +4 -0
  162. package/dist/flavors/plateau/index.js +97 -0
  163. package/dist/flavors/tgpp/index.d.ts +4 -0
  164. package/dist/flavors/tgpp/index.js +122 -0
  165. package/dist/flavors/un/index.d.ts +13 -0
  166. package/dist/flavors/un/index.js +90 -0
  167. package/dist/flavors/w3c/index.d.ts +14 -0
  168. package/dist/flavors/w3c/index.js +148 -0
  169. package/dist/flavors/xsf/index.d.ts +18 -0
  170. package/dist/flavors/xsf/index.js +65 -0
  171. package/dist/grammar/engine.d.ts +78 -0
  172. package/dist/grammar/engine.js +351 -0
  173. package/dist/index.d.ts +1 -0
  174. package/dist/index.js +3 -0
  175. package/dist/model/attribute.d.ts +54 -0
  176. package/dist/model/attribute.js +53 -0
  177. package/dist/model/builder.d.ts +39 -0
  178. package/dist/model/builder.js +124 -0
  179. package/dist/model/component.d.ts +70 -0
  180. package/dist/model/component.js +170 -0
  181. package/dist/model/identifier.d.ts +84 -0
  182. package/dist/model/identifier.js +270 -0
  183. package/dist/model/urn-generator.d.ts +27 -0
  184. package/dist/model/urn-generator.js +91 -0
  185. package/package.json +1 -1
@@ -0,0 +1,192 @@
1
+ /**
2
+ * GENERATED from the Ruby gem (Pubid.prefix_flavors after
3
+ * eager_load_flavors!) — the prefix→flavors routing table. Regenerate
4
+ * from the pubid gem with:
5
+ * bundle exec ruby -e 'require "pubid"; Pubid.eager_load_flavors!;
6
+ * require "json"; puts JSON.pretty_generate(Pubid.prefix_flavors
7
+ * .transform_values { |v| v.sort })'
8
+ * Do not edit by hand.
9
+ *
10
+ * Used by the gost flavor's foreign-adoption routing (prefix_owner in
11
+ * index.ts): the single flavor owning the longest matching prefix parses
12
+ * the adopted identifier; joint prefixes (ISO/IEC, ANSI/AMCA…) fall
13
+ * through to the sorted fallback loop.
14
+ */
15
+ export const PREFIX_ROUTES = {
16
+ "10.": ["doi"],
17
+ "3GPP": ["tgpp"],
18
+ "AI": ["nist"],
19
+ "AMCA": ["amca"],
20
+ "AMS": ["nist"],
21
+ "ANSI": ["ansi"],
22
+ "ANSI/AMCA": ["amca", "ansi"],
23
+ "ANSI/ASHRAE": ["ansi", "ashrae"],
24
+ "API": ["api"],
25
+ "ASHRAE": ["ashrae"],
26
+ "ASME": ["asme"],
27
+ "ASTM": ["astm"],
28
+ "ATN": ["adobe"],
29
+ "Adobe": ["adobe"],
30
+ "BCP": ["ietf"],
31
+ "BH": ["nist"],
32
+ "BIP": ["bsi"],
33
+ "BIPM": ["bipm"],
34
+ "BMS": ["nist"],
35
+ "BS": ["bsi"],
36
+ "BS EN": ["bsi"],
37
+ "BS EN IEC": ["bsi"],
38
+ "BS EN ISO": ["bsi"],
39
+ "BS IEC": ["bsi"],
40
+ "BS ISO": ["bsi"],
41
+ "BSI": ["bsi"],
42
+ "BSS": ["nist"],
43
+ "CC": ["calconnect"],
44
+ "CCAUV": ["bipm"],
45
+ "CCEM": ["bipm"],
46
+ "CCL": ["bipm"],
47
+ "CCM": ["bipm"],
48
+ "CCPR": ["bipm"],
49
+ "CCQM": ["bipm"],
50
+ "CCRI": ["bipm"],
51
+ "CCSDS": ["ccsds"],
52
+ "CCT": ["bipm"],
53
+ "CCTF": ["bipm"],
54
+ "CCU": ["bipm"],
55
+ "CEN": ["cen_cenelec"],
56
+ "CGPM": ["bipm"],
57
+ "CHIPS": ["nist"],
58
+ "CIE": ["cie"],
59
+ "CIPM": ["bipm"],
60
+ "CIRC": ["nist"],
61
+ "CISPR": ["iec"],
62
+ "CJ": ["gb"],
63
+ "CJ/T": ["gb"],
64
+ "CLC": ["cen_cenelec"],
65
+ "CR": ["cen_cenelec"],
66
+ "CRPL": ["nist"],
67
+ "CS": ["nist"],
68
+ "CSA": ["csa"],
69
+ "CSM": ["nist"],
70
+ "CSWP": ["nist"],
71
+ "CWA": ["cen_cenelec"],
72
+ "DB": ["gb"],
73
+ "DB/T": ["gb"],
74
+ "DB/Z": ["gb"],
75
+ "DD": ["bsi"],
76
+ "DL": ["gb"],
77
+ "DL/T": ["gb"],
78
+ "DOI:": ["doi"],
79
+ "EAB": ["nist"],
80
+ "ECMA": ["ecma"],
81
+ "EN": ["cen_cenelec"],
82
+ "ENV": ["cen_cenelec"],
83
+ "EP": ["bsi"],
84
+ "ES": ["cen_cenelec"],
85
+ "ETSI": ["etsi"],
86
+ "EVS": ["evs"],
87
+ "EVS EN": ["evs"],
88
+ "EVS EN ISO": ["evs"],
89
+ "EVS EN ISO/IEC": ["evs"],
90
+ "EVS-EN": ["evs"],
91
+ "EVS-EN ISO": ["evs"],
92
+ "EVS-EN ISO/IEC": ["evs"],
93
+ "FIPS": ["nist"],
94
+ "FYI": ["ietf"],
95
+ "GB": ["gb"],
96
+ "GB/T": ["gb"],
97
+ "GB/Z": ["gb"],
98
+ "GBn": ["gb"],
99
+ "GBn/T": ["gb"],
100
+ "GBn/Z": ["gb"],
101
+ "GCR": ["nist"],
102
+ "GOST": ["gost"],
103
+ "HB": ["bsi", "gb", "nist"],
104
+ "HB/T": ["gb"],
105
+ "HD": ["cen_cenelec"],
106
+ "HJ": ["gb"],
107
+ "HJ/T": ["gb"],
108
+ "IALA": ["iala"],
109
+ "IANA": ["iana"],
110
+ "IDF": ["idf"],
111
+ "IEC": ["iec"],
112
+ "IEC/ISO": ["iec", "iso"],
113
+ "IECEE": ["iec"],
114
+ "IECEx": ["iec"],
115
+ "IECQ": ["iec"],
116
+ "IEEE": ["ieee"],
117
+ "IHO": ["iho"],
118
+ "IR": ["nist"],
119
+ "ISBN": ["isbn"],
120
+ "ISO": ["iso"],
121
+ "ISO/IEC": ["iec", "iso"],
122
+ "ISO/IEC/IEEE": ["iec", "ieee", "iso"],
123
+ "ITU": ["itu"],
124
+ "JB": ["gb"],
125
+ "JB/T": ["gb"],
126
+ "JCGM": ["jcgm"],
127
+ "JCRB": ["bipm"],
128
+ "JG": ["gb"],
129
+ "JG/T": ["gb"],
130
+ "JIS": ["jis"],
131
+ "JPCRD": ["nist"],
132
+ "JRES": ["nist"],
133
+ "LCIRC": ["nist"],
134
+ "MH": ["gb"],
135
+ "MH/T": ["gb"],
136
+ "MONO": ["nist"],
137
+ "MP": ["nist"],
138
+ "Metrologia": ["bipm"],
139
+ "NA": ["bsi"],
140
+ "NBS": ["nist"],
141
+ "NCSTAR": ["nist"],
142
+ "NIST": ["nist"],
143
+ "NSRDS": ["nist"],
144
+ "NWIRP": ["nist"],
145
+ "NY": ["gb"],
146
+ "NY/T": ["gb"],
147
+ "OASIS": ["oasis"],
148
+ "OGC": ["ogc"],
149
+ "OIML": ["oiml"],
150
+ "OMG": ["omg"],
151
+ "OWMWP": ["nist"],
152
+ "PAS": ["bsi"],
153
+ "PC": ["nist"],
154
+ "PD": ["bsi"],
155
+ "PLATEAU": ["plateau"],
156
+ "PMG": ["easc"],
157
+ "PP": ["bsi"],
158
+ "QB": ["gb"],
159
+ "QB/T": ["gb"],
160
+ "RB": ["nist"],
161
+ "RFC": ["ietf"],
162
+ "RMG": ["easc"],
163
+ "RPT": ["nist"],
164
+ "SAE": ["sae"],
165
+ "SIBS": ["nist"],
166
+ "SL": ["gb"],
167
+ "SL/T": ["gb"],
168
+ "SP": ["nist"],
169
+ "STD": ["ietf"],
170
+ "T/": ["gb"],
171
+ "TB": ["gb"],
172
+ "TB/T": ["gb"],
173
+ "TD": ["gb"],
174
+ "TD/T": ["gb"],
175
+ "TIBM": ["nist"],
176
+ "TN": ["nist"],
177
+ "TS": ["bsi"],
178
+ "TTB": ["nist"],
179
+ "UN": ["un"],
180
+ "VTS": ["nist"],
181
+ "W3C": ["w3c"],
182
+ "XEP": ["xsf"],
183
+ "YY": ["gb"],
184
+ "YY/T": ["gb"],
185
+ "ZB": ["gb"],
186
+ "ZB/T": ["gb"],
187
+ "doi:": ["doi"],
188
+ "draft": ["ietf"],
189
+ "ГОСТ": ["gost"],
190
+ "ПМГ": ["easc"],
191
+ "РМГ": ["easc"],
192
+ };
@@ -0,0 +1,32 @@
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 ialaGrammar: Grammar;
6
+ export declare class IalaIdentifier extends BaseIdentifier {
7
+ static polymorphicName: string;
8
+ static attributes: import("../../model/attribute.js").AttributeTable;
9
+ static mappings: import("../../model/attribute.js").FieldMapping[];
10
+ readonly number: string | undefined;
11
+ readonly edition: string | undefined;
12
+ readonly language: string | undefined;
13
+ /** Single-letter type code (S, R, GA, …). */
14
+ typeLetter(): string | undefined;
15
+ render(): string;
16
+ }
17
+ declare class IalaUrnGenerator extends BaseUrnGenerator<IalaIdentifier> {
18
+ generate(): string;
19
+ }
20
+ export declare class IalaAnnex extends IalaIdentifier {
21
+ static polymorphicName: string;
22
+ static attributes: import("../../model/attribute.js").AttributeTable;
23
+ static mappings: import("../../model/attribute.js").FieldMapping[];
24
+ static urnGenerator: typeof IalaUrnGenerator;
25
+ readonly base: IalaIdentifier | undefined;
26
+ readonly annex_form: string | undefined;
27
+ readonly letter: string | undefined;
28
+ typeLetter(): string | undefined;
29
+ render(): string;
30
+ }
31
+ export declare function ialaGrammarImplementation(): FlavorImplementation;
32
+ export {};
@@ -0,0 +1,300 @@
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
+ /**
7
+ * 1:1 port of lib/pubid/iala/ — 706 corpus rows. Typed prefixes
8
+ * (S/R/G/M/C/A/GA/L/X/P), class-driven zero-padding (4 for S/R/G/M/C,
9
+ * 2+2 dotted for GA, verbatim for the rest), "Ed 2.0" and ":ed2.0"
10
+ * edition forms, (F) languages, and Annex wrappers. URN is the MRN
11
+ * form: urn:mrn:iala:pub:<lower-code>[:ed<n>][:<lang>].
12
+ */
13
+ function buildRules() {
14
+ const rules = {};
15
+ const rule = (name, build) => {
16
+ rules[name] = build();
17
+ };
18
+ const space = str(" ");
19
+ const dash = str("-");
20
+ const colon = str(":");
21
+ const dot = str(".");
22
+ const digits = match("[0-9]").repeat(1, Infinity);
23
+ // GA before G, or G is left with a dangling "A".
24
+ rule("type_letter", () => str("GA")
25
+ .or(str("S"), str("R"), str("G"), str("M"), str("C"), str("A"), str("L"), str("X"), str("P"))
26
+ .as("type_letter"));
27
+ // Any length: the dataset zero-pads ("S1070") but canonical unpadded
28
+ // forms ("M1", "GA1.1") also round-trip.
29
+ rule("doc_number", () => match("[0-9]").repeat(1, Infinity).as("doc_number"));
30
+ rule("dotted_number", () => dot.then(digits));
31
+ rule("number_with_dots", () => rules["doc_number"].then(rules["dotted_number"].repeat(0, Infinity).as("doc_number_dots")));
32
+ // "-1", "-9-10" — repeated, captured as a list.
33
+ rule("subpart", () => dash.then(digits.as("subpart_number")).repeat(1, Infinity).as("subpart"));
34
+ rule("code", () => rules["type_letter"].then(rules["number_with_dots"], rules["subpart"].maybe()));
35
+ const editionValue = () => digits.then(dot.then(digits).repeat(0, Infinity)).as("edition_value");
36
+ rule("edition_human", () => space.then(str("Ed"), space, editionValue()).as("edition"));
37
+ rule("edition_compact", () => colon.then(str("ed"), editionValue()).as("edition"));
38
+ rule("edition", () => rules["edition_human"].or(rules["edition_compact"]));
39
+ rule("language", () => space
40
+ .maybe()
41
+ .then(str("("), str("E").or(str("F"), str("S"), str("C"), str("A"), str("R")).as("language"), str(")"))
42
+ .as("language_group"));
43
+ rule("publisher", () => str("IALA").then(space).maybe());
44
+ // The letter's absent-lowercase guard keeps "Ed 1"'s E from being
45
+ // mis-captured as an annex letter.
46
+ rule("annex_identifier", () => rules["publisher"]
47
+ .then(rules["type_letter"], rules["number_with_dots"], rules["subpart"].maybe())
48
+ .as("base")
49
+ .then(space, str("Annex").or(str("ANNEX")).as("annex_marker"), space
50
+ .then(match("[A-Z]").as("annex_letter"), match("[a-z]").absent())
51
+ .maybe(), rules["edition"].maybe(), rules["language"].maybe()));
52
+ rule("identifier", () => rules["annex_identifier"].or(rules["publisher"]
53
+ .then(rules["code"], rules["edition"].maybe(), rules["language"].maybe())));
54
+ rule("root", () => rules["identifier"]);
55
+ return rules;
56
+ }
57
+ export const ialaGrammar = { rules: buildRules(), root: "root" };
58
+ const BASE_MAPPINGS = keyValue({ wire: "number", to: "number" }, { wire: "edition", to: "edition" }, { wire: "language", to: "language" });
59
+ export class IalaIdentifier extends BaseIdentifier {
60
+ static polymorphicName = "pubid:iala:identifier";
61
+ static attributes = extendAttributes(BaseIdentifier, {
62
+ publisher: { type: "string", default: "IALA" },
63
+ number: { type: "string" },
64
+ edition: { type: "string" },
65
+ language: { type: "string" },
66
+ });
67
+ static mappings = BASE_MAPPINGS;
68
+ /** Single-letter type code (S, R, GA, …). */
69
+ typeLetter() {
70
+ return this.constructor.typeLetter;
71
+ }
72
+ render() {
73
+ let rendered = `IALA ${this.typeLetter() ?? ""}${this.number ?? ""}`;
74
+ if (this.edition !== undefined)
75
+ rendered += ` Ed ${this.edition}`;
76
+ if (this.language !== undefined)
77
+ rendered += ` (${this.language})`;
78
+ return rendered;
79
+ }
80
+ }
81
+ class IalaUrnGenerator extends BaseUrnGenerator {
82
+ generate() {
83
+ const id = this.identifier;
84
+ if (id instanceof IalaAnnex) {
85
+ const parts = ["urn:mrn:iala:pub", `${id.base.typeLetter()?.toLowerCase()}${id.base.number}`];
86
+ parts.push(id.letter !== undefined ? `annex-${id.letter.toLowerCase()}` : "annex");
87
+ if (id.edition !== undefined)
88
+ parts.push(`ed${id.edition}`);
89
+ if (id.language !== undefined)
90
+ parts.push(id.language.toLowerCase());
91
+ return parts.join(":");
92
+ }
93
+ const parts = ["urn:mrn:iala:pub", `${id.typeLetter()?.toLowerCase()}${id.number}`];
94
+ if (id.edition !== undefined)
95
+ parts.push(`ed${id.edition}`);
96
+ if (id.language !== undefined)
97
+ parts.push(id.language.toLowerCase());
98
+ return parts.join(":");
99
+ }
100
+ }
101
+ const IALA_TYPES = [
102
+ { kind: "standard", letter: "S", numberWidth: 4 },
103
+ { kind: "recommendation", letter: "R", numberWidth: 4 },
104
+ { kind: "guideline", letter: "G", numberWidth: 4 },
105
+ { kind: "manual", letter: "M", numberWidth: 4 },
106
+ { kind: "model-course", letter: "C", numberWidth: 4 },
107
+ { kind: "advice", letter: "A" },
108
+ { kind: "general-assembly", letter: "GA", numberWidth: 2, dottedSegmentWidth: 2 },
109
+ { kind: "letter", letter: "L" },
110
+ { kind: "report", letter: "X" },
111
+ { kind: "resolution", letter: "P" },
112
+ ];
113
+ const TYPE_SPECS = new Map(IALA_TYPES.map((t) => [t.letter, t]));
114
+ function ialaClass(spec) {
115
+ class IalaTypeIdentifier extends IalaIdentifier {
116
+ static polymorphicName = `pubid:iala:${spec.kind}`;
117
+ static urnGenerator = IalaUrnGenerator;
118
+ static typeLetter = spec.letter;
119
+ }
120
+ registerType(IalaTypeIdentifier);
121
+ return IalaTypeIdentifier;
122
+ }
123
+ const KIND_CLASSES = new Map(IALA_TYPES.map((spec) => [spec.letter, ialaClass(spec)]));
124
+ export class IalaAnnex extends IalaIdentifier {
125
+ static polymorphicName = "pubid:iala:annex";
126
+ static attributes = extendAttributes(IalaIdentifier, {
127
+ base: { type: IalaIdentifier },
128
+ annex_form: { type: "string" },
129
+ letter: { type: "string" },
130
+ });
131
+ // The inherited block merges with the annex's own maps (lutaml
132
+ // semantics): number/edition/language + base/annex_form/letter.
133
+ static mappings = keyValue({ wire: "number", to: "number" }, { wire: "edition", to: "edition" }, { wire: "language", to: "language" }, { wire: "base", to: "base" }, { wire: "annex_form", to: "annex_form" }, { wire: "letter", to: "letter" });
134
+ static urnGenerator = IalaUrnGenerator;
135
+ typeLetter() {
136
+ return undefined;
137
+ }
138
+ render() {
139
+ let rendered = `${this.base?.toHuman() ?? ""} ${this.annex_form ?? ""}`;
140
+ if (this.letter !== undefined)
141
+ rendered += ` ${this.letter}`;
142
+ if (this.edition !== undefined)
143
+ rendered += ` Ed ${this.edition}`;
144
+ if (this.language !== undefined)
145
+ rendered += ` (${this.language})`;
146
+ return rendered;
147
+ }
148
+ }
149
+ registerType(IalaAnnex);
150
+ // ---------------------------------------------------------------------------
151
+ // Builder
152
+ // ---------------------------------------------------------------------------
153
+ const isObj = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
154
+ const s = (v) => {
155
+ if (v === undefined || v === null)
156
+ return undefined;
157
+ const str = Array.isArray(v) ? v.join("") : String(v);
158
+ return str.length > 0 ? str : undefined;
159
+ };
160
+ function flatten(data) {
161
+ return Array.isArray(data) ? Object.assign({}, ...data) : data;
162
+ }
163
+ function subpartToS(subpart) {
164
+ if (Array.isArray(subpart)) {
165
+ return subpart
166
+ .map((h) => (isObj(h) ? s(h["subpart_number"]) : undefined))
167
+ .filter((v) => v !== undefined)
168
+ .join("-");
169
+ }
170
+ return s(subpart) ?? "";
171
+ }
172
+ function canonicalBase(base, spec) {
173
+ return spec.numberWidth !== undefined ? base.padStart(spec.numberWidth, "0") : base;
174
+ }
175
+ function canonicalDots(dots, spec) {
176
+ if (dots === "")
177
+ return "";
178
+ if (spec.dottedSegmentWidth === undefined)
179
+ return dots;
180
+ return dots
181
+ .split(".")
182
+ .map((seg) => (seg === "" ? seg : seg.padStart(spec.dottedSegmentWidth, "0")))
183
+ .join(".");
184
+ }
185
+ function buildNumber(hash, spec) {
186
+ const base = s(hash["doc_number"]);
187
+ if (base === undefined)
188
+ return undefined;
189
+ const dots = canonicalDots(s(hash["doc_number_dots"]) ?? "", spec);
190
+ let subpartStr = hash["subpart"] !== undefined ? `-${subpartToS(hash["subpart"])}` : "";
191
+ if (subpartStr === "-")
192
+ subpartStr = "";
193
+ return `${canonicalBase(base, spec)}${dots}${subpartStr}`;
194
+ }
195
+ class IalaBuilder {
196
+ build(data) {
197
+ const hash = flatten(data);
198
+ if (hash["annex_marker"] !== undefined)
199
+ return this.buildAnnex(hash);
200
+ return this.buildFlat(hash);
201
+ }
202
+ buildFlat(hash) {
203
+ const typeLetter = s(hash["type_letter"])?.toUpperCase();
204
+ const spec = TYPE_SPECS.get(typeLetter ?? "");
205
+ if (spec === undefined)
206
+ throw new ParseFailed(`IALA: unknown type letter ${typeLetter}`, 0);
207
+ const klass = KIND_CLASSES.get(spec.letter);
208
+ const attrs = {};
209
+ const number = buildNumber(hash, spec);
210
+ if (number !== undefined)
211
+ attrs["number"] = number;
212
+ const editionHash = isObj(hash["edition"]) ? flatten(hash["edition"]) : undefined;
213
+ const edition = editionHash !== undefined ? s(editionHash["edition_value"]) : undefined;
214
+ if (edition !== undefined)
215
+ attrs["edition"] = edition;
216
+ const languageHash = isObj(hash["language_group"]) ? flatten(hash["language_group"]) : undefined;
217
+ const language = languageHash !== undefined ? s(languageHash["language"])?.toUpperCase() : undefined;
218
+ if (language !== undefined)
219
+ attrs["language"] = language;
220
+ return new klass(attrs);
221
+ }
222
+ buildAnnex(hash) {
223
+ const baseHash = flatten(hash["base"]);
224
+ const base = this.buildFlat(baseHash);
225
+ const attrs = {
226
+ base,
227
+ annex_form: s(hash["annex_marker"]),
228
+ };
229
+ const letter = s(hash["annex_letter"]);
230
+ if (letter !== undefined)
231
+ attrs["letter"] = letter;
232
+ const editionHash = isObj(hash["edition"]) ? flatten(hash["edition"]) : undefined;
233
+ const edition = editionHash !== undefined ? s(editionHash["edition_value"]) : undefined;
234
+ if (edition !== undefined)
235
+ attrs["edition"] = edition;
236
+ const languageHash = isObj(hash["language_group"]) ? flatten(hash["language_group"]) : undefined;
237
+ const language = languageHash !== undefined ? s(languageHash["language"])?.toUpperCase() : undefined;
238
+ if (language !== undefined)
239
+ attrs["language"] = language;
240
+ return new IalaAnnex(attrs);
241
+ }
242
+ }
243
+ export function ialaGrammarImplementation() {
244
+ const builder = new IalaBuilder();
245
+ const parseHuman = (input) => {
246
+ const tree = parseGrammar(ialaGrammar, input.trim());
247
+ if (typeof tree !== "object" || tree === null) {
248
+ throw new ParseFailed("IALA: unexpected parse tree", 0);
249
+ }
250
+ return builder.build(tree);
251
+ };
252
+ const URN_PREFIX = "urn:mrn:iala:pub:";
253
+ /**
254
+ * Parses an MRN URN by reconstructing the human form and re-parsing
255
+ * (lib/pubid/iala/urn_parser.rb). The edition marker is
256
+ * case-insensitive with an optional dot ("Ed1.0" / "ed.1.0"), and
257
+ * the annex casing mirrors the generator: bare "annex" → "Annex",
258
+ * lettered "annex-a" → "ANNEX A".
259
+ */
260
+ const parseUrn = (urn) => {
261
+ if (!urn.toLowerCase().startsWith(URN_PREFIX)) {
262
+ throw new ParseFailed(`Invalid IALA URN: ${JSON.stringify(urn)}`, 0);
263
+ }
264
+ const parts = urn.slice(URN_PREFIX.length).split(":");
265
+ const code = parts[0] ?? "";
266
+ let edition;
267
+ let language;
268
+ let annexForm;
269
+ let annexLetter;
270
+ for (const seg of parts.slice(1)) {
271
+ const annexMatch = /^annex(-([a-z]))?$/i.exec(seg);
272
+ if (annexMatch !== null) {
273
+ annexLetter = annexMatch[2]?.toUpperCase();
274
+ annexForm = annexLetter !== undefined ? "ANNEX" : "Annex";
275
+ }
276
+ else if (/^ed\.?/i.test(seg)) {
277
+ edition = seg.replace(/^ed\.?/i, "");
278
+ }
279
+ else if (/^[a-z]$/i.test(seg)) {
280
+ language = seg.toUpperCase();
281
+ }
282
+ }
283
+ let text = `IALA ${code.toUpperCase()}`;
284
+ if (annexForm !== undefined)
285
+ text += ` ${annexForm}`;
286
+ if (annexLetter !== undefined)
287
+ text += ` ${annexLetter}`;
288
+ if (edition !== undefined)
289
+ text += ` Ed ${edition}`;
290
+ if (language !== undefined)
291
+ text += ` (${language})`;
292
+ return parseHuman(text);
293
+ };
294
+ return {
295
+ parse(input) {
296
+ const identifier = input.toLowerCase().startsWith(URN_PREFIX) ? parseUrn(input) : parseHuman(input);
297
+ return identifier;
298
+ },
299
+ };
300
+ }
@@ -0,0 +1,19 @@
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 ianaGrammar: Grammar;
6
+ declare class IanaUrnGenerator extends BaseUrnGenerator<IanaIdentifier> {
7
+ generate(): string;
8
+ }
9
+ export declare class IanaIdentifier 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 IanaUrnGenerator;
14
+ readonly number: string;
15
+ readonly sub_registry: string | undefined;
16
+ render(): string;
17
+ }
18
+ export declare function ianaGrammarImplementation(): FlavorImplementation;
19
+ export {};
@@ -0,0 +1,71 @@
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/iana/ on the unified model. Registry slugs; the
9
+ * top-level slug is stored as `number`, the optional sub-slug under the
10
+ * `sub_registry` wire name. URN: urn:iana:<slug>[:<sub-slug>] (the Ruby
11
+ * flavor's own urn_generator, mirrored as a template subclass).
12
+ */
13
+ function buildRules() {
14
+ const rules = {};
15
+ const rule = (name, build) => {
16
+ rules[name] = build();
17
+ };
18
+ const slug = match("[a-zA-Z0-9._\\-]").repeat(1, Infinity);
19
+ rule("slug", () => slug);
20
+ rule("iana_prefix", () => str("IANA").then(str(" ")).maybe());
21
+ rule("identifier", () => rules["iana_prefix"]
22
+ .then(slug.as("registry"), str("/").then(slug.as("sub_registry")).maybe()));
23
+ rule("root", () => rules["identifier"]);
24
+ return rules;
25
+ }
26
+ export const ianaGrammar = { rules: buildRules(), root: "root" };
27
+ class IanaUrnGenerator extends BaseUrnGenerator {
28
+ generate() {
29
+ const parts = ["urn", "iana", this.identifier.number];
30
+ if (this.identifier.sub_registry !== undefined)
31
+ parts.push(this.identifier.sub_registry);
32
+ return parts.join(":");
33
+ }
34
+ }
35
+ export class IanaIdentifier extends BaseIdentifier {
36
+ static polymorphicName = "pubid:iana:registry";
37
+ static attributes = extendAttributes(BaseIdentifier, {
38
+ number: { type: "string" },
39
+ sub_registry: { type: "string" },
40
+ });
41
+ static mappings = keyValue({ wire: "number", to: "number" }, { wire: "sub_registry", to: "sub_registry" });
42
+ static urnGenerator = IanaUrnGenerator;
43
+ render() {
44
+ return this.sub_registry === undefined
45
+ ? `IANA ${this.number}`
46
+ : `IANA ${this.number}/${this.sub_registry}`;
47
+ }
48
+ }
49
+ registerType(IanaIdentifier);
50
+ class IanaBuilder extends BaseBuilder {
51
+ defaultIdentifierClass() {
52
+ return IanaIdentifier;
53
+ }
54
+ cast(key, value) {
55
+ if (key === "registry")
56
+ return { number: String(value) };
57
+ return value;
58
+ }
59
+ }
60
+ export function ianaGrammarImplementation() {
61
+ const builder = new IanaBuilder();
62
+ return {
63
+ parse(input) {
64
+ const tree = parseGrammar(ianaGrammar, input);
65
+ if (typeof tree !== "object" || tree === null || Array.isArray(tree)) {
66
+ throw new ParseFailed("IANA: unexpected parse tree", 0);
67
+ }
68
+ return builder.build(tree);
69
+ },
70
+ };
71
+ }
@@ -0,0 +1,2 @@
1
+ import { Grammar } from "../../grammar/engine.js";
2
+ export declare const idfGrammar: Grammar;