@pubid/pubid 0.1.3 → 0.1.4

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 (183) 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 +24 -0
  80. package/dist/flavors/gb/index.js +111 -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 +626 -0
  107. package/dist/flavors/ieee/index.d.ts +3 -0
  108. package/dist/flavors/ieee/index.js +1186 -0
  109. package/dist/flavors/ieee/model.d.ts +142 -0
  110. package/dist/flavors/ieee/model.js +1148 -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 +191 -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 +180 -0
  155. package/dist/flavors/oiml/implementation.d.ts +9 -0
  156. package/dist/flavors/oiml/implementation.js +16 -0
  157. package/dist/flavors/oiml/model.d.ts +4 -0
  158. package/dist/flavors/oiml/model.js +462 -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/model/attribute.d.ts +54 -0
  174. package/dist/model/attribute.js +53 -0
  175. package/dist/model/builder.d.ts +39 -0
  176. package/dist/model/builder.js +124 -0
  177. package/dist/model/component.d.ts +70 -0
  178. package/dist/model/component.js +170 -0
  179. package/dist/model/identifier.d.ts +83 -0
  180. package/dist/model/identifier.js +270 -0
  181. package/dist/model/urn-generator.d.ts +27 -0
  182. package/dist/model/urn-generator.js +91 -0
  183. package/package.json +1 -1
@@ -0,0 +1,8 @@
1
+ export interface PreParseResult {
2
+ dispatch: "standard" | "aiee_simple" | "iec_ieee_copublished" | "dual_semicolon" | "dual_reaffirmed" | "dual_ire" | "dual_space_separated" | "dual_and" | "dual_ampersand" | "aiee_asa_adoption" | "adopted";
3
+ input: string;
4
+ parts: string[];
5
+ metadata: Record<string, string>;
6
+ }
7
+ export declare function preParse(input: string): PreParseResult;
8
+ export declare function preprocessIeee(input: string): string;
@@ -0,0 +1,410 @@
1
+ // IEEE pre-parser: regex/scan dispatch logic (Ruby: lib/pubid/ieee/pre_parser.rb)
2
+ // and the Parser.parse string-cleaning stages (Ruby: lib/pubid/ieee/parser.rb
3
+ // self.parse + normalize_* helpers), ported in the same order.
4
+ const PUBLISHERS = [
5
+ "IEEE", "AIEE", "ANSI", "ASA", "IEC", "ISO", "ASTM", "NACE", "NSF",
6
+ "ASHRAE", "NCTA", "AESC",
7
+ ];
8
+ const ADOPTION_PREFIXES = [
9
+ "ANSI", "ISO", "IEC", "IEEE", "AIEE", "IRE", "ASA", "ASTM", "CSA", "ASME",
10
+ "NACE", "NSF", "ASHRAE", "NCTA", "AESC",
11
+ ];
12
+ const NON_ADOPTION_KEYWORDS = [
13
+ "Revision", "Revison", "Amendment", "Corrigendum", "Corrigenda",
14
+ "incorporates", "Incorporating", "Includes", "Incorporates", "Adoption",
15
+ "Supplement", "Draft Amendment", "DRAFT Amendment", "Draft Revision",
16
+ "Reaffirmation", "Redesignation", "redesignated as", "Supersedes",
17
+ "Supercedes", "Includes", "Previously designated as", "Notebooks",
18
+ "Standard Newspaper",
19
+ ];
20
+ function findTopLevelPosition(input, marker) {
21
+ let parenDepth = 0;
22
+ for (let i = 0; i < input.length; i++) {
23
+ const char = input[i];
24
+ if (char === "(")
25
+ parenDepth += 1;
26
+ if (char === ")")
27
+ parenDepth -= 1;
28
+ if (parenDepth === 0 &&
29
+ input.slice(i, i + marker.length) === marker) {
30
+ return i;
31
+ }
32
+ }
33
+ return undefined;
34
+ }
35
+ function findTopLevel(input, marker) {
36
+ return findTopLevelPosition(input, marker) !== undefined;
37
+ }
38
+ function publisherPositions(input) {
39
+ const positions = [];
40
+ for (const pub of PUBLISHERS) {
41
+ const regex = new RegExp(`(?:^|\\s)(${pub.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})(?:\\s|/)`, "g");
42
+ for (const m of input.matchAll(regex)) {
43
+ const matchPos = m.index + m[0].indexOf(m[1]);
44
+ const beforeMatch = input.slice(0, matchPos);
45
+ const open = (beforeMatch.match(/\(/g) ?? []).length;
46
+ const close = (beforeMatch.match(/\)/g) ?? []).length;
47
+ if (open > close)
48
+ continue;
49
+ positions.push({ pos: matchPos, publisher: pub });
50
+ }
51
+ }
52
+ return positions;
53
+ }
54
+ function nonAdoptionKeyword(adoptionPart) {
55
+ const alternation = NON_ADOPTION_KEYWORDS
56
+ .map((k) => k.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"))
57
+ .join("|");
58
+ return new RegExp(`^\\s*(${alternation})`, "i").test(adoptionPart);
59
+ }
60
+ function adoptionPattern(input) {
61
+ if (!input.includes("(") || !input.includes(")"))
62
+ return false;
63
+ if (input.startsWith("IEC/IEEE "))
64
+ return false;
65
+ const mainPart = input.split("(")[0]?.trim();
66
+ const adoptionMatch = /\(([^)]+)\)/.exec(input);
67
+ const adoptionPart = adoptionMatch?.[1];
68
+ if (mainPart === undefined || mainPart === "" || adoptionPart === undefined)
69
+ return false;
70
+ if (nonAdoptionKeyword(adoptionPart))
71
+ return false;
72
+ const prefixes = ADOPTION_PREFIXES.join("|");
73
+ return (new RegExp(`\\b(${prefixes})\\s`).test(adoptionPart) ||
74
+ new RegExp(`^\\s*(${prefixes})\\b`).test(adoptionPart) ||
75
+ /\bStd\s+\d+/.test(adoptionPart));
76
+ }
77
+ function detectDispatch(input) {
78
+ if (input.startsWith("AIEE ") && !input.includes("("))
79
+ return "aiee_simple";
80
+ if (input.startsWith("IEC/IEEE "))
81
+ return "iec_ieee_copublished";
82
+ if (input.includes("; "))
83
+ return "dual_semicolon";
84
+ if (/\(R(\d{4})\)\s*\(Revision of ([^)]+)\)/.test(input) ||
85
+ /\(Reaffirmed\s+(\d{4})\)\s*\(Revision of ([^)]+)\)/.test(input)) {
86
+ return "dual_reaffirmed";
87
+ }
88
+ if (/\(R\d{4}\)\s*\((\d+\s+IRE[^)]+)\)/.test(input))
89
+ return "dual_ire";
90
+ {
91
+ const positions = publisherPositions(input).sort((a, b) => a.pos - b.pos);
92
+ if (positions.length >= 2) {
93
+ const between = input.slice(positions[0].pos, positions[1].pos);
94
+ if (!between.includes("/") && !between.includes(" and ") && !between.includes(" & ")) {
95
+ return "dual_space_separated";
96
+ }
97
+ }
98
+ }
99
+ if (input.includes(" and ") && findTopLevel(input, " and "))
100
+ return "dual_and";
101
+ if (input.includes(" & ") && findTopLevel(input, " & "))
102
+ return "dual_ampersand";
103
+ if (/^AIEE\s+/.test(input) && input.includes("(") && input.includes("ASA")) {
104
+ return "aiee_asa_adoption";
105
+ }
106
+ if (adoptionPattern(input))
107
+ return "adopted";
108
+ return undefined;
109
+ }
110
+ function buildDualSemicolon(input) {
111
+ const parts = input.split("; ");
112
+ if (parts.length !== 2 || parts[0] === undefined || parts[1] === undefined)
113
+ return { dispatch: "standard", input, parts: [], metadata: {} };
114
+ return {
115
+ dispatch: "dual_semicolon", input,
116
+ parts: [parts[0].trim(), parts[1].trim()], metadata: {},
117
+ };
118
+ }
119
+ function buildDualReaffirmed(input) {
120
+ const m = /\((?:R|Reaffirmed\s+)(\d{4})\)\s*\(Revision of ([^)]+)\)/.exec(input);
121
+ if (m === null)
122
+ return { dispatch: "standard", input, parts: [], metadata: {} };
123
+ const rewritten = input.replace(/\((?:R|Reaffirmed\s+)\d{4}\)\s*\(Revision of ([^)]+)\)/, "(Revision of $1)");
124
+ return { dispatch: "dual_reaffirmed", input: rewritten, parts: [], metadata: { reaffirmed: m[1] } };
125
+ }
126
+ function buildDualIre(input) {
127
+ const mainPart = input.split(" (R")[0]?.trim();
128
+ const reaffirmedMatch = /\(R(\d{4})\)/.exec(input);
129
+ const ireMatch = /\((\d+\s+IRE[^)]+)\)/.exec(input);
130
+ if (!mainPart || reaffirmedMatch === null || ireMatch === null) {
131
+ return { dispatch: "standard", input, parts: [], metadata: {} };
132
+ }
133
+ return {
134
+ dispatch: "dual_ire", input,
135
+ parts: [mainPart, ireMatch[1]], metadata: { reaffirmed: reaffirmedMatch[1] },
136
+ };
137
+ }
138
+ function buildDualSpaceSeparated(input) {
139
+ const positions = publisherPositions(input).sort((a, b) => a.pos - b.pos);
140
+ if (positions.length < 2)
141
+ return { dispatch: "standard", input, parts: [], metadata: {} };
142
+ const between = input.slice(positions[0].pos, positions[1].pos);
143
+ if (between.includes("/") || between.includes(" and ")) {
144
+ return { dispatch: "standard", input, parts: [], metadata: {} };
145
+ }
146
+ let splitPos = positions[1].pos;
147
+ while (splitPos > 0 && input[splitPos - 1] === " ")
148
+ splitPos -= 1;
149
+ return {
150
+ dispatch: "dual_space_separated", input,
151
+ parts: [input.slice(0, splitPos).trim(), input.slice(splitPos).trim()],
152
+ metadata: {},
153
+ };
154
+ }
155
+ function buildDualAnd(input) {
156
+ const position = findTopLevelPosition(input, " and ");
157
+ if (position === undefined)
158
+ return { dispatch: "standard", input, parts: [], metadata: {} };
159
+ return {
160
+ dispatch: "dual_and", input,
161
+ parts: [input.slice(0, position).trim(), input.slice(position + 5).trim()],
162
+ metadata: {},
163
+ };
164
+ }
165
+ function buildDualAmpersand(input) {
166
+ const parts = input.split(" & ");
167
+ if (parts.length !== 2 || parts[0] === undefined || parts[1] === undefined)
168
+ return { dispatch: "standard", input, parts: [], metadata: {} };
169
+ return {
170
+ dispatch: "dual_ampersand", input,
171
+ parts: [parts[0].trim(), parts[1].trim()], metadata: {},
172
+ };
173
+ }
174
+ function buildAieeAsaAdoption(input) {
175
+ const mainPart = input.split("(")[0]?.trim();
176
+ const adoptionMatch = /\((ASA[^)]+)\)/.exec(input);
177
+ if (!mainPart || adoptionMatch === null) {
178
+ return { dispatch: "standard", input, parts: [], metadata: {} };
179
+ }
180
+ return { dispatch: "aiee_asa_adoption", input, parts: [mainPart, adoptionMatch[1]], metadata: {} };
181
+ }
182
+ function buildAdopted(input) {
183
+ const mainPart = input.split("(")[0]?.trim();
184
+ const adoptionMatch = /\(([^)]+)\)/.exec(input);
185
+ const adoptionPart = adoptionMatch?.[1];
186
+ if (!mainPart || adoptionPart === undefined) {
187
+ return { dispatch: "standard", input, parts: [], metadata: {} };
188
+ }
189
+ return { dispatch: "adopted", input, parts: [mainPart, adoptionPart], metadata: {} };
190
+ }
191
+ export function preParse(input) {
192
+ const commaDual = input.replace(/(\d{4}),\s+Std\s/, "$1 and IEEE Std ");
193
+ switch (detectDispatch(commaDual)) {
194
+ case "aiee_simple": return { dispatch: "aiee_simple", input: commaDual, parts: [], metadata: {} };
195
+ case "iec_ieee_copublished": return { dispatch: "iec_ieee_copublished", input: commaDual, parts: [], metadata: {} };
196
+ case "dual_semicolon": return buildDualSemicolon(commaDual);
197
+ case "dual_reaffirmed": return buildDualReaffirmed(commaDual);
198
+ case "dual_ire": return buildDualIre(commaDual);
199
+ case "dual_space_separated": return buildDualSpaceSeparated(commaDual);
200
+ case "dual_and": return buildDualAnd(commaDual);
201
+ case "dual_ampersand": return buildDualAmpersand(commaDual);
202
+ case "aiee_asa_adoption": return buildAieeAsaAdoption(commaDual);
203
+ case "adopted": return buildAdopted(commaDual);
204
+ default: return { dispatch: "standard", input: commaDual, parts: [], metadata: {} };
205
+ }
206
+ }
207
+ // --- suffix / revision / joint-stage normalization (parser.rb) -------------
208
+ function normalizeRelatonSuffixes(input) {
209
+ let cleaned = input;
210
+ // Combined draft + corrigendum: "…/D-N/CorM-YYYY[-MM]" → "…/Cor M-YYYY/DN".
211
+ // The month of the corrigendum is intentionally dropped (matches Ruby).
212
+ {
213
+ const re = /^(.*)\/D-([0-9A-Za-z][0-9A-Za-z.+]*?)\/Cor\.?[ ]?(\d+)(?:-((?:19|20)\d\d))?(?:-\d\d)?$/;
214
+ const m = re.exec(cleaned);
215
+ if (m !== null) {
216
+ cleaned = `${m[1]}/Cor ${m[3]}${m[4] !== undefined ? `-${m[4]}` : ""}/D${m[2]}`;
217
+ }
218
+ }
219
+ // Combined draft + revision and the empty-draft revision-only form.
220
+ {
221
+ const re = /^(.*?)\/D-([0-9A-Za-z.+]*)\/R-([0-9A-Za-z]+)(?:-((?:19|20)\d\d)(?:-(0[1-9]|1[0-2]))?)?$/;
222
+ const m = re.exec(cleaned);
223
+ if (m !== null) {
224
+ const date = m[4] !== undefined ? `-${m[4]}${m[5] !== undefined ? `-${m[5]}` : ""}` : "";
225
+ const draftPart = m[2] === "" ? "" : `/D${m[2]}`;
226
+ cleaned = `${m[1]}${date}${draftPart}/R-${m[3]}`;
227
+ }
228
+ }
229
+ // /D-N drafts with a trailing numeric date: reposition onto the number.
230
+ {
231
+ const re = /^(.*)\/D-([0-9A-Za-z][0-9A-Za-z.+]*?)-((?:19|20)\d\d)(?:-(0[1-9]|1[0-2]))?$/;
232
+ const m = re.exec(cleaned);
233
+ if (m !== null) {
234
+ cleaned = `${m[1]}-${m[3]}${m[4] !== undefined ? `-${m[4]}` : ""}/D${m[2]}`;
235
+ }
236
+ }
237
+ // /E-N editions: "/E-2-2023-02" → "Edition 2.0 2023-02".
238
+ {
239
+ const re = /^(.*?)\/E-(\d+)(?:-((?:19|20)\d\d)(?:-(0[1-9]|1[0-2]))?)?$/;
240
+ const m = re.exec(cleaned);
241
+ if (m !== null) {
242
+ const date = m[3] !== undefined ? ` ${m[3]}${m[4] !== undefined ? `-${m[4]}` : ""}` : "";
243
+ cleaned = `${m[1]} Edition ${m[2]}.0${date}`;
244
+ }
245
+ }
246
+ // /R-N revisions: reposition a trailing year onto the number, keep "/R-x".
247
+ {
248
+ const re = /^(.*?)\/R-([0-9A-Za-z]+)(?:-((?:19|20)\d\d))?$/;
249
+ const m = re.exec(cleaned);
250
+ if (m !== null) {
251
+ cleaned = `${m[3] !== undefined ? `${m[1]}-${m[3]}` : m[1]}/R-${m[2]}`;
252
+ }
253
+ }
254
+ return cleaned;
255
+ }
256
+ function normalizeRevisionNotation(input) {
257
+ let cleaned = input;
258
+ // Numbered revisions preserved, repositioned to "/R-<n>".
259
+ cleaned = cleaned.replace(/(\/D-?[0-9A-Za-z.]+)\s+[Rr][Ee][Vv]\s*(\d+)/, "$1/R-$2");
260
+ cleaned = cleaned.replace(/[-/_.]?\s?[Rr][Ee][Vv][-\s]?(\d+)(\/D-?[0-9A-Za-z.]+)/, "$2/R-$1");
261
+ cleaned = cleaned.replace(/(\d)[-._]?\s?[Rr][Ee][Vv]\s*(\d+)\s*$/, "$1/R-$2");
262
+ // Lettered inline revisions stripped.
263
+ cleaned = cleaned.replace(/[-/_.]?\s?[Rr][Ee][Vv][-\s]?[A-Za-z0-9]+(?=\/D-?[0-9A-Za-z])/, "");
264
+ cleaned = cleaned.replace(/(\d)[Rr][Ee][Vv][A-Za-z0-9]+\s*$/, "$1");
265
+ return cleaned;
266
+ }
267
+ function normalizeJointStageSpellings(input) {
268
+ let cleaned = input;
269
+ const pubs = "((?:ISO/IEC/IEEE|IEEE/ISO/IEC|IEEE/IEC/ISO|ISO/IEEE|IEC/IEEE|IEEE/IEC|ISO/IEC)(?:/ ?| ))";
270
+ const stage = "(FDIS|FCD|CDV|DIS\\d?|CD\\d?|WD|PWI|NP)";
271
+ const num = "(P?\\d+(?:[.-]\\d+)?)";
272
+ const tail = "(,? (?:Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Sept|Oct|Nov|Dec)[a-z]* \\d{4}|$|-\\d{4}(?:-\\d\\d)?)";
273
+ cleaned = cleaned.replace(/(\d)_D(\d)/g, "$1/D$2");
274
+ cleaned = cleaned.replace(/,(?=[A-Za-z])/, ", ");
275
+ cleaned = cleaned.replace(new RegExp(`^${pubs}${num}/(D[\\d.]+)/ ?${stage}\\b`), "$1$4 $2/$3");
276
+ cleaned = cleaned.replace(new RegExp(`^${pubs}${num}/ ${stage}${tail}`), "$1$3 $2$4");
277
+ cleaned = cleaned.replace(new RegExp(`^${pubs}${num}/${stage} (\\d{4})\\b`), "$1$3 $2-$4");
278
+ cleaned = cleaned.replace(new RegExp(`^${pubs}${num} ${stage}${tail}`), "$1$3 $2$4");
279
+ cleaned = cleaned.replace(new RegExp(`^${pubs}${num} ${stage} (D\\d+)\\b`), "$1$3 $2/$4");
280
+ // The dash-date must be a plausible year - a 4-digit monthcode (YYMM,
281
+ // e.g. "…/CD2-1410" = October 2014) is a DRAFT designator, not a
282
+ // dash-date, and rewriting it onto the number breaks the parse.
283
+ cleaned = cleaned.replace(new RegExp(`^${pubs}${num}/ ?${stage}(-(?:19|20)\\d\\d(?:-\\d\\d)?)`), "$1$3 $2$4");
284
+ cleaned = cleaned.replace(new RegExp(`^${pubs}${stage} ${num}/? ?(D\\d+)\\b`), "$1$2 $3/$4");
285
+ return cleaned;
286
+ }
287
+ // The Parser.parse cleaning pipeline, in Ruby order.
288
+ export function preprocessIeee(input) {
289
+ let cleaned = input.replace(/\.pdf$/i, "");
290
+ cleaned = cleaned.replace(/_(FDIS|CDV|CD|DIS|WD|PWI|NP)/g, "/$1");
291
+ cleaned = cleaned.replace(/\s+/g, " ");
292
+ cleaned = cleaned.replace(/\b(ISO\/IEC\/IEEE|IEEE\/ISO\/IEC|IEEE\/IEC\/ISO|ISO\/IEEE|IEC\/IEEE|IEEE\/IEC|ISO\/IEC)\/ ?(FDIS|FCD|CDV|DIS\d?|CD\d?|WD|PWI|NP)\b/g, "$1 $2");
293
+ cleaned = normalizeRevisionNotation(cleaned);
294
+ cleaned = normalizeRelatonSuffixes(cleaned);
295
+ cleaned = cleaned.replace(/(\d)\s+-(\d{4})\b/g, "$1-$2");
296
+ cleaned = cleaned.replace(/(\d)-\s+(\d{4})\b/g, "$1-$2");
297
+ cleaned = cleaned.replace(/&#x2013;(?!-)/g, "-");
298
+ cleaned = cleaned.replaceAll("&#x2013;-", "-");
299
+ cleaned = cleaned.replace(/^!IEEE /, "IEEE ");
300
+ cleaned = cleaned.replaceAll("IEEE/ ASTM", "IEEE/ASTM");
301
+ cleaned = cleaned.replaceAll("&#x2122;", "™");
302
+ cleaned = cleaned.replaceAll("&#x2019;", "'");
303
+ cleaned = cleaned.replaceAll("&amp;amp;", "&");
304
+ cleaned = cleaned.replaceAll("&amp;", "&");
305
+ cleaned = cleaned.replace(/\s+(P&V)\s*$/, " ($1)");
306
+ cleaned = cleaned.replace(/(\d+\.\d+)\s+(\d+\.)/g, "$1$2");
307
+ cleaned = cleaned.replace(/\b(1|2)\s+(\d{3})\b/g, "$1$2");
308
+ cleaned = cleaned.replace(/\b(January|February|March|April|May|June|July|August|September|October|November|December)(\d{4})\b/g, "$1 $2");
309
+ cleaned = cleaned.replace(/\b(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Sept|Oct|Nov|Dec)(\d{4})\b/g, "$1 $2");
310
+ cleaned = normalizeJointStageSpellings(cleaned);
311
+ cleaned = cleaned.replace(/(IEC\s+\d+(?:-\d+)?(?::\d{4})?(?:\s+(?:First\s+)?[Ee]dition\s+\d+(?:\.\d+)?\s+\d{4}-\d{2})?)\s+(IEEE\s+Std\s+\S+|IEEE\s+\S+)/g, "$1; $2");
312
+ cleaned = cleaned.replace(/^(IEC\s+\d+(?:-\d+)?):\d{4}(\s+(?:First\s+)?[Ee]dition\s+\d+(?:\.\d+)?\s+\d{4}-\d{2})/, "$1$2");
313
+ cleaned = cleaned.replaceAll("™", "");
314
+ cleaned = cleaned.replace(/\b19969\b/g, "1969");
315
+ cleaned = cleaned.replace(/(\d{4}),(\d{3})/g, "$1, $2");
316
+ cleaned = cleaned.replaceAll("/lNT", "/INT");
317
+ cleaned = cleaned.replaceAll(".l/", ".1/");
318
+ cleaned = cleaned.replace(/\bI99O\b/g, "1990");
319
+ cleaned = cleaned.replace(/^EEE /, "IEEE ");
320
+ cleaned = cleaned.replace(/^I EEE /, "IEEE ");
321
+ cleaned = cleaned.replace(/^lEEE /, "IEEE ");
322
+ {
323
+ const openCount = (cleaned.match(/\(/g) ?? []).length;
324
+ const closeCount = (cleaned.match(/\)/g) ?? []).length;
325
+ if (openCount === closeCount + 1 && !cleaned.endsWith(")")) {
326
+ cleaned = `${cleaned})`;
327
+ }
328
+ }
329
+ cleaned = cleaned.replace(/,\s*Standard\s*$/, "");
330
+ cleaned = cleaned.replace(/[,:]\s*$/, "");
331
+ cleaned = cleaned.replace(/,\s+and\s+IEEE\s+Std\s/, " and ");
332
+ {
333
+ const openCount = (cleaned.match(/\(/g) ?? []).length;
334
+ const closeCount = (cleaned.match(/\)/g) ?? []).length;
335
+ if (openCount > closeCount) {
336
+ cleaned = cleaned + ")".repeat(openCount - closeCount);
337
+ }
338
+ else if (closeCount > openCount) {
339
+ const extra = closeCount - openCount;
340
+ cleaned = cleaned.replace(new RegExp(`\\){${extra}}$`), "");
341
+ }
342
+ }
343
+ cleaned = cleaned.replace(/(\d)\s+(\d{4})(?=\s*\(|\s*$)/g, "$1-$2");
344
+ cleaned = cleaned.replace(/\s+-\s+(\d{4})\b/g, "-$1");
345
+ cleaned = cleaned.replace(/^IEEE\s+(?!Std\b)(\d)/, "IEEE Std $1");
346
+ cleaned = cleaned.replace(/^IEEE\s+No\.\s*/, "IEEE Std ");
347
+ cleaned = cleaned.replace(/^IEEE\s+No\s/, "IEEE Std ");
348
+ cleaned = cleaned.replace(/\s+\//g, "/");
349
+ cleaned = cleaned.replace(/,\s+(\d{4})\s+Edition/, "-$1");
350
+ cleaned = cleaned.replace(/(ISO\/IEC)(\d)/g, "$1 $2");
351
+ cleaned = cleaned.replace(/^IEEE\s+Std\s+(ANSI\/IEEE)/, "$1 Std");
352
+ if (/;\s+[A-Z]{2,}/.test(cleaned)) {
353
+ cleaned = cleaned.replace(/;\s+([A-Z][^;]+)$/, " ($1)");
354
+ }
355
+ cleaned = cleaned.replace(/,\s+(\d{4})\s+Edn\.\s+\(Reaff\s+(\d{4})\)/g, "-$1 (R$2)");
356
+ cleaned = cleaned.replace(/(\d{4})\s+Edn\.\s+\(Reaff\s+(\d{4})\)/g, "$1 (R$2)");
357
+ cleaned = cleaned.replace(/\(Reaffirmed\s+(\d{4}),\s+(\d+\s+IRE[^)]+)\)/g, "(R$1) ($2)");
358
+ cleaned = cleaned.replace(/(\d{4})\/ANSI\s+([^(]+)(?=\s*\(|$)/g, "$1 (ANSI $2)");
359
+ cleaned = cleaned.replace(/(ISO\/IEC\s+TR)(\d)/g, "$1 $2");
360
+ cleaned = cleaned.replace(/\bStad\b/g, "Std");
361
+ cleaned = cleaned.replace(/\b(IEEE|ANSI|AIEE)\s+std\b/g, "$1 Std");
362
+ cleaned = cleaned.replaceAll("(TM)", "");
363
+ if (/^(\d+[-.]\d+)\/D\d+/.test(cleaned)) {
364
+ cleaned = `IEEE P${cleaned}`;
365
+ }
366
+ cleaned = cleaned.replace(/\/Preprint\b/g, "");
367
+ cleaned = cleaned.replaceAll("Proposed Revision of", "Revision of");
368
+ cleaned = cleaned.replace(/\bammended\b/gi, "amended");
369
+ cleaned = cleaned.replace(/(\/INT|\/Cor\s+\d+-\d{4})\./g, "$1");
370
+ cleaned = cleaned.replace(/(\/INT),\s+([A-Z][a-z]+)\s+(\d{4})\s+Edition/, "$1, $2 $3");
371
+ cleaned = cleaned.replace(/\s+Ed\.\s*$/, "");
372
+ cleaned = cleaned.replace(/\bStd\.\s+/g, "Std ");
373
+ cleaned = cleaned.replace(/(\d{4})(\s+\([^)]+\))?\s+-\s+IEEE\s+Standard\s+for.*$/, "$1$2");
374
+ cleaned = cleaned.replace(/^IEEE\s+PC(\d)/, "IEEE Std PC$1");
375
+ cleaned = cleaned.replace(/^IEEE\s+Unapproved\s+Draft\s+Std\s+PC(\d)/, "IEEE Unapproved Draft Std PC$1");
376
+ cleaned = cleaned.replace(/^IEEE\s+P(\d+)\s+and\s+ASHRAE/, "IEEE Std P$1 and ASHRAE");
377
+ cleaned = cleaned.replace(/^(ISO\/IEC \d+[-.]\d+-\d{4}):.*$/, "$1");
378
+ cleaned = cleaned.replace(/^(ISO\/IEC \d+-\d{4}):.*$/, "$1");
379
+ cleaned = cleaned.replace(/^(ISO\/IEC \d+[-.]\d*)\s*:\s*(\d{4})/, "$1:$2");
380
+ cleaned = cleaned.replace(/^(ISO\/IEC \d+)\s*:\s*(\d{4})/, "$1:$2");
381
+ cleaned = cleaned.replace(/^(IEC\/IEEE P[\w.-]+)_D/, "$1/D");
382
+ cleaned = cleaned.replace(/^IEEE\/ISO\/IEC\s+(P[\w.-]+)/, "ISO/IEC/IEEE $1");
383
+ cleaned = cleaned.replace(/^IEEE\/IEC\/ISO\s+(P[\w.-]+)/, "IEC/ISO/IEEE $1");
384
+ cleaned = cleaned.replace(/^(IEEE\/IEC P[\w.-]+)\s+D(\d)/, "$1/D$2");
385
+ cleaned = cleaned.replace(/^(IEEE\/IEC P[\w.-]+)\s+(CDV|FDIS|CD|DIS|ED\d)/, "$1/$2");
386
+ cleaned = cleaned.replace(/^ISO\s+\/IEC\/IEEE/, "ISO/IEC/IEEE");
387
+ cleaned = cleaned.replace(/^ISO\s+\/IEC/, "ISO/IEC");
388
+ cleaned = cleaned.replace(/^IS0\//, "ISO/");
389
+ cleaned = cleaned.replace(/^IEEE-P(\d+)-(\d+)-DIS-(.*)/, "ISO/IEC/IEEE P$1-$2/DIS, $3");
390
+ cleaned = cleaned.replace(/^IEEE\/CSA\s+(P[\d.]+)\/([\d.]+)\/D(\d+)/, "IEEE/CSA $1/D$3");
391
+ cleaned = cleaned.replace(/^IEEE\s+Approved\s+Draft\s+Std\s+(P\d)/, "IEEE Approved Draft Std $1");
392
+ cleaned = cleaned.replace(/^(IEEE Approved Draft Std P[\w.-]+)\s+\/\s*D/, "$1/D");
393
+ cleaned = cleaned.replace(/^AIEE\s+No\.\s*(\d)/, "AIEE No. $1");
394
+ cleaned = cleaned.replace(/^AIEE\s+no\s/, "AIEE No ");
395
+ cleaned = cleaned.replace(/^AIEE\s+Std\s+No\.\s*/, "AIEE Standard No ");
396
+ cleaned = cleaned.replace(/^IEEE\s+PSI\s+(\d)/, "IEEE/ASTM PSI $1");
397
+ cleaned = cleaned.replace(/^(IEEE\/IEC P[\d.-]+\/PC[\d.]+)_D/, "$1/D");
398
+ cleaned = cleaned.replace(/^IEC\s+(P[\d.-]+)\/IEEE\s+(PC[\d.]+)_D/, "IEC/IEEE $2/D");
399
+ cleaned = cleaned.replace(/^IEC\/IEC\s+(P\d)/, "IEC/IEEE $1");
400
+ cleaned = cleaned.replace(/^(NACE\s+SP\d+-\d+)\/(IEEE\s+Std\s+\d+-\d+)$/, "$1 ($2)");
401
+ cleaned = cleaned.replaceAll("Edn.", "Edition");
402
+ cleaned = cleaned.replaceAll("ASHARE", "ASHRAE");
403
+ cleaned = cleaned.replace(/^PC(\d)/, "P$1");
404
+ cleaned = cleaned.replace(/^IEEE\/ISO\/IEC\s+(8802[\w.-]+)/, "ISO/IEC/IEEE $1");
405
+ cleaned = cleaned.replace(/^(IEEE\s+C?\d[\d.]*\/D\d+)([A-Z][a-z]+\s+\d{4})/, "$1, $2");
406
+ cleaned = cleaned.replace(/^(ANSI\/IEEE Std):\s+.*$/, "$1");
407
+ cleaned = cleaned.replace(/^(IEEE\s+[\d.]+)\s+(IEC\s+\d+[-\d]*\s+.*edition\s+\d{4}-\d{2})$/i, "$1; $2");
408
+ cleaned = cleaned.replace(/^IEEE\s+No\s+(\d+-\d+)\s+\/\s+ASA\s+(.*)/, "IEEE Std $1 (ASA $2)");
409
+ return cleaned;
410
+ }
@@ -0,0 +1,8 @@
1
+ export interface UpdateCode {
2
+ plain?: string;
3
+ replacement: string;
4
+ pattern?: string;
5
+ flags?: string;
6
+ }
7
+ export declare const UPDATE_CODES: UpdateCode[];
8
+ export declare function applyUpdateCodes(input: string): string;
@@ -0,0 +1,191 @@
1
+ // Port of data/ieee/update_codes.yaml: pre-parse normalizations applied
2
+ // BEFORE the Parser cleaning stages (parse_single order). Plain keys are
3
+ // anchored full-string substitutions; /regex/[flags] literals map to JS.
4
+ export const UPDATE_CODES = [
5
+ { plain: "IEEE Unapproved Draft Std PC37.110/D911Oct 07", replacement: "IEEE Unapproved Draft Std PC37.110/D711, Oct 07" },
6
+ { plain: "IEEE Unapproved Draft Std P15289, 06", replacement: "IEEE Unapproved Draft Std P15289/D6" },
7
+ { plain: "IEEE C57.139/D14June 2010", replacement: "IEEE C57.139/D14, June 2010" },
8
+ { plain: "IEEE P1653.5/D7d1 November, 2019", replacement: "IEEE P1653.5/D7.1 November, 2019" },
9
+ { plain: "IEEE P1017/D062012", replacement: "P1017/D062012, Jun 2012" },
10
+ { plain: "IEEP62.42.1/D3, October 2014", replacement: "IEEE P62.42.1/D3, October 2014" },
11
+ { plain: "IEEE P802.11ajD8.0, August 2017", replacement: "IEEE P802.11aj/D8.0, August 2017" },
12
+ { plain: "IEEE P802.11ajD9.0, November 2017", replacement: "IEEE P802.11aj/D9.0, November 2017" },
13
+ { plain: "IEC 62529:2012(E) (IEEE Std 1641-2010", replacement: "IEC 62529:2012(E) (IEEE Std 1641-2010)" },
14
+ { plain: "IEC 62529:2012(E) (IEEE Std 1641-2010 - Redline", replacement: "IEC 62529:2012(E) (IEEE Std 1641-2010) - Redline" },
15
+ { plain: "IEEE IEEE P1453/D3, June 2011", replacement: "IEEE P1453/D3, June 2011" },
16
+ { plain: "AIEE No 1E -1957", replacement: "AIEE No 1E-1957" },
17
+ { plain: "A.I.E.E. No. 15 May-1928", replacement: "AIEE No 15-192805" },
18
+ { plain: "AIEE No 45 -1951", replacement: "AIEE No 45-1951" },
19
+ { plain: "AIEE No. 2-June 1929", replacement: "AIEE No 2-192906" },
20
+ { plain: "AIEE No. 25-1952 (Supercedes AIEE No. 25-1945)", replacement: "AIEE No 25-1952 (Supercedes AIEE No. 25-1945)" },
21
+ { plain: "AIEE No.1-1962 (Supersedes June 1957 issue)", replacement: "AIEE No 1-1962 (Supersedes AIEE No 1-195706)" },
22
+ { plain: "AIEE Nos 72 and 73 - 1932", replacement: "AIEE No 72-1932 and AIEE No 73-1932" },
23
+ { plain: "EEE Std 1671.1-2017 (Revision of IEEE Std 1671.1&amp;#8208;2009)", replacement: "IEEE Std 1671.1-2017 (Revision of IEEE Std 1671.1-2009)" },
24
+ { plain: "EEE Std 1671.1-2017 (Revision of IEEE Std 1671.1-2009)", replacement: "IEEE Std 1671.1-2017 (Revision of IEEE Std 1671.1-2009)" },
25
+ { plain: "EEE Std 488.2-1992", replacement: "IEEE Std 488.2-1992" },
26
+ { plain: "EEE Std 802.3br-2016 (Amendment to IEEE Std 802.3-2015 as amended by IEEE St802.3bw-2015, IEEE Std 802.3by-2016, IEEE Std 802.3bq-2016, and IEEE Std 802.3bp-2016)", replacement: "IEEE Std 802.3br-2016 (Amendment to IEEE Std 802.3-2015 as amended by IEEE Std 802.3bw-2015, IEEE Std 802.3by-2016, IEEE Std 802.3bq-2016, and IEEE Std 802.3bp-2016)" },
27
+ { plain: "IEEE Std 336-2010 (Revision of EEE Std 336-2005)", replacement: "IEEE Std 336-2010 (Revision of IEEE Std 336-2005)" },
28
+ { plain: "IEEE Std 356-2020 (Revision of IEEE Std 356?2010)", replacement: "IEEE Std 356-2020 (Revision of IEEE Std 356-2010)" },
29
+ { plain: "IEEE Std 356-2020 (Revision of IEEE Std 356?2010) - Redline", replacement: "IEEE Std 356-2020 (Revision of IEEE Std 356-2010) - Redline" },
30
+ { plain: "IEEE Std Std 1139-2008", replacement: "IEEE Std 1139-2008" },
31
+ { plain: "IEEE/ ASTM SI 10-2010 (Revision of IEEE/ASTM SI 10-2002)", replacement: "IEEE/ASTM SI 10-2010 (Revision of IEEE/ASTM SI 10-2002)" },
32
+ { plain: "IEEE Std 24748-3:2012", replacement: "IEEE 24748-3:2012" },
33
+ { plain: "ISO/IEC/IEEE P24765/D3:2017", replacement: "ISO/IEC/IEEE P24765:2017/D3" },
34
+ { plain: "ISO/IEC/IEEE FDIS P24765 FDIS, October 2016", replacement: "ISO/IEC/IEEE FDIS P24765, October 2016" },
35
+ { plain: "ISO/IEC/IEEE P15289 FDIS, February 2019", replacement: "ISO/IEC/IEEE FDIS P15289, February 2019" },
36
+ { plain: "ISO/IEC/IEEE P26515 FDIS, May 2018", replacement: "ISO/IEC/IEEE FDIS P26515, May 2018" },
37
+ { plain: "IEC/IEEE P60214-2, FDIS 2018", replacement: "IEC/IEEE FDIS P60214-2-2018(E)" },
38
+ { plain: "IEC/IEEE P62582-6, FDIS 2018", replacement: "IEC/IEEE FDIS P62582-6-2018(E)" },
39
+ { plain: "ISO/IEC DIS P26511.2, May 2017", replacement: "ISO/IEC DIS 26511.2:2017" },
40
+ { plain: "ISO/IEC/IEEE P90003_FDIS, August 2018", replacement: "ISO/IEC/IEEE FDIS P90003, August 2018" },
41
+ { plain: "ISO/IEC/IEEE&#xA0;P29119-1/FDIS, September 2021", replacement: "ISO/IEC/IEEE FDIS P29119-1, September 2021" },
42
+ { plain: "ISO/IEC/IEEE/ P12207-2/D3_FDIS, July 2020", replacement: "ISO/IEC/IEEE FDIS P12207-2/D3, July 2020" },
43
+ { plain: "ISO/IEC/IEEE/ P21841/FDIS, April 2019", replacement: "ISO/IEC/IEEE FDIS P21841, April 2019" },
44
+ { plain: "ISO/IEC/IEEE/ P24748-3/DIS, August 2019", replacement: "ISO/IEC/IEEE DIS P24748-3, August 2019" },
45
+ { plain: "IEEE Std 1018-2013 (Revison of IEEE Std 1018-2004)", replacement: "IEEE Std 1018-2013 (Revision of IEEE Std 1018-2004)" },
46
+ { plain: "IEEE Std 1018-2013 (Revison of IEEE Std 1018-2004) - Redline", replacement: "IEEE Std 1018-2013 (Revision of IEEE Std 1018-2004) - Redline" },
47
+ { plain: "IEEE SId 342-1973 (ANSI C37.0731-1973)", replacement: "IEEE Std 342-1973 (ANSI C37.0731-1973)" },
48
+ { plain: "P1484.12.3/D1, September2019", replacement: "IEEE P1484.12.3/D1, September 2019" },
49
+ { plain: "P1073.1.3.4/D3.0", replacement: "IEEE P1073.1.3.4/D3.0" },
50
+ { plain: "P1936.1, 2020", replacement: "IEEE P1936.1, January 2020" },
51
+ { plain: "P20000-2, D1 December 2012", replacement: "IEEE P20000-2/D1, December 2012" },
52
+ { plain: "ISO/IEC/IEEE 8802-22.2:2015/Amd.2:2017(E)", replacement: "ISO/IEC/IEEE 8802-22:2015/Amd.2:2017(E)" },
53
+ { plain: "IEEE 1070-1995", replacement: "IEEE No 1070-1995" },
54
+ { plain: "IEEE 278-1967", replacement: "IEEE No 278-1967" },
55
+ { plain: "IEEE 730-1989", replacement: "IEEE No 730-1989" },
56
+ { plain: "IEEE 751-1991", replacement: "IEEE No 751-1991" },
57
+ { plain: "IEEE 1023-2020 (Revision of IEEE Std 1023-2004)", replacement: "IEEE No 1023-2020 (Revision of IEEE Std 1023-2004)" },
58
+ { plain: "IEEE P90003-2014, April 2015", replacement: "IEEE P90003, April 2015" },
59
+ { plain: "IEC/IEEE P61886-1_D2_May2020", replacement: "IEC/IEEE P61886-1_D2, May 2020" },
60
+ { plain: "IEEE Unapproved P1076.1/D-3.3-07-Feb20", replacement: "IEEE Unapproved P1076.1/D-3.3-2007-02" },
61
+ { plain: "IEEE Unapproved P11073.10407/D-09-08-Sep20", replacement: "IEEE Unapproved P11073.10407/D-09-2008-09" },
62
+ { plain: "IEEE Unapproved P1597.2/D-7.1-09-Oct20", replacement: "IEEE Unapproved P1597.2/D7.1-2009-10" },
63
+ { plain: "IEEE Unapproved P7.4.3.2/D-3-2010-01", replacement: "IEEE Unapproved P7-4.3.2/D-3-2010-01" },
64
+ { plain: "IEEE Unapproved P802.11k/D-13.0_Mar-08-20", replacement: "IEEE Unapproved P802.11k/D-13.0-2008-03" },
65
+ { plain: "IEEE Unapproved P802.16g/D-8-07-Feb20", replacement: "IEEE Unapproved P802.16g/D-8-2007-02" },
66
+ { plain: "IEEE Unapproved P802.1ah/D-4.-2008-02", replacement: "IEEE Unapproved P802.1ah/D-4-2008-02" },
67
+ { plain: "IEEE Unapproved P802.20.2/D-2.0-09-Oct20", replacement: "IEEE Unapproved P802.20.2/D-2.0-2009-10" },
68
+ { plain: "IEEE Unapproved P802.3/D-D1.1/Cor1-2009", replacement: "IEEE Unapproved P802.3/D1.1/Cor1-2009" },
69
+ { plain: "IEEE Unapproved Std PC57.129_D9, Mar07", replacement: "IEEE Unapproved Std PC57.129_D9, Mar 07" },
70
+ { plain: "IEEE Unapproved Draft Std PC62.21_D3, Sep07", replacement: "IEEE Unapproved Draft Std PC62.21_D3, Sep 07" },
71
+ { plain: "IEEE Unapproved Draft Std P2600.2/D41b, Jan09", replacement: "IEEE Unapproved Draft Std P2600.2/D41b, Jan 09" },
72
+ { plain: "IEEE Active Unapproved Draft Std IEEE PC37.06/D8.3, July 2007", replacement: "IEEE Active Unapproved Draft Std PC37.06/D8.3, July 2007" },
73
+ { plain: "IEEE Unapproved Draft Std PC57.21/D14, Dec. 2007", replacement: "IEEE Unapproved Draft Std PC57.21/D14, Dec 2007" },
74
+ { plain: "IEEE Unapproved Draft Std P802.1AB/REVD2.2, Dec 2007", replacement: "IEEE Unapproved Draft Std P802.1AB/D2.2, Dec 2007" },
75
+ { plain: "IEEE Unapproved Draft Std PC37.301/D3 R1, Feb 2008", replacement: "IEEE Unapproved Draft Std PC37.301/D3.1, Feb 2008" },
76
+ { plain: "IEEE Unapproved Draft Std PC37.27/D16_Dec 2007", replacement: "IEEE Unapproved Draft Std PC37.27/D16, Dec 2007" },
77
+ { plain: "IEEE Unapproved Draft Std PC37.13 / D21, Dec 2007", replacement: "IEEE Unapproved Draft Std PC37.13/D21, Dec 2007" },
78
+ { plain: "IEEE Unapproved Draft Std P802.1ah/D4., Feb 2008", replacement: "IEEE Unapproved Draft Std P802.1ah/D4, Feb 2008" },
79
+ { plain: "IEEE Unapproved Draft Std P802.11k_D13.0_Mar 2008", replacement: "IEEE Unapproved Draft Std P802.11k_D13.0, Mar 2008" },
80
+ { plain: "IEEE Unapproved Draft Std P1776/D9b, Feb. 2008", replacement: "IEEE Unapproved Draft Std P1776/D9b, Feb 2008" },
81
+ { plain: "IEEE Unapproved Draft Std PC62.21-2003-Cor_1/D5, Mar 2008", replacement: "IEEE Unapproved Draft Std PC62.21-2003-Cor1/D5, Mar 2008" },
82
+ { plain: "IEEE Unapproved Draft Std P1003.1 Draft 5.1, May 2008", replacement: "IEEE Unapproved Draft Std P1003.1/D5.1, May 2008" },
83
+ { plain: "IEEE Unapproved Draft Std P802-1Qay/D5-0, Jan 09", replacement: "IEEE Unapproved Draft Std P802-1Qay/D5.0, Jan 09" },
84
+ { plain: "IEEE Unapproved Draft Std P1775/1.9.7, Mar 2009", replacement: "IEEE Unapproved Draft Std P1775/D1.9.7, Mar 2009" },
85
+ { plain: "IEEE Unapproved Draft Std P1044/D00005, Aug-2009", replacement: "IEEE Unapproved Draft Std P1044/D5, Aug 2009" },
86
+ { plain: "IEEE Unapproved Draft Std P1584b/ D2, Jul 2009", replacement: "IEEE Unapproved Draft Std P1584b/D2, Jul 2009" },
87
+ { plain: "IEEE Unapproved Draft Std P11073-10421, D6, Oct 2009", replacement: "IEEE Unapproved Draft Std P11073-10421/D6, Oct 2009" },
88
+ { plain: "IEEE Unapproved Draft Std PC37.13.1a/D3. Nov 2009", replacement: "IEEE Unapproved Draft Std PC37.13.1a/D3, Nov 2009" },
89
+ { plain: "IEEE Unapproved Draft Std PC37.082_IEC62271-113/D2, Jan 2010", replacement: "IEEE Unapproved Draft Std PC37.082/D2, Jan 2010 (IEC 62271-113)" },
90
+ { plain: "IEEE Unapproved Draft Std PC37.20.7-2001 Cor 1/D3, Aug 2009", replacement: "IEEE Unapproved Draft Std PC37.20.7-2001/Cor 1/D3, Aug 2009" },
91
+ { plain: "IEEE Unapproved Draft Std PC37.20.7-2007 Cor 1/D4", replacement: "IEEE Unapproved Draft Std PC37.20.7-2007/Cor 1/D4" },
92
+ { plain: "IEEE Unapproved Draft Std P802.3-2008 (P802.3bb)/Cor 1/D1.1, Jan 2009", replacement: "IEEE Unapproved Draft Std P802.3-2008/Cor 1/D1.1, Jan 2009 (IEEE P802.3bb)" },
93
+ { plain: "IEEE Unapproved Draft Std P802.3-2008 (P802.3bb)/Cor 1/D2.0, Jul 2009", replacement: "IEEE Unapproved Draft Std P802.3-2008/Cor 1/D2.0, Jul 2009 (IEEE P802.3bb)" },
94
+ { plain: "IEEE Unapproved Draft Std P16326:2008/CD2, Sep 2008", replacement: "IEEE P16326:2008/CD2, Sep 2008" },
95
+ { plain: "IEEE Unapproved Draft Std 16326:2009", replacement: "IEEE 16326:2009" },
96
+ { plain: "Unapproved Draft Std ISO/IEC FDIS 15288:2007(E) IEEE P15288/D3", replacement: "IEEE Unapproved Draft Std P15288/D3 (ISO/IEC FDIS 15288:2007(E))" },
97
+ { plain: "IEEE Unapproved Draft Std P1635/ASHRAE 21_D4, Jan 2010", replacement: "IEEE Unapproved Draft Std P1635/D4, January 2010 (ASHRAE 21)" },
98
+ { plain: "IEC/IEEE 62582-1:2011 Edition 1.0 2011-08", replacement: "IEC/IEEE 62582-1-2011 Edition 1.0 2011-08" },
99
+ { plain: "ISO/IEC/IEEE CD P26513/D1, August 2015", replacement: "ISO/IEC/IEEE P26513/D1, August 2015" },
100
+ { plain: "IEEE Std P1073.1.3.4/D3.0", replacement: "IEEE Std P11073.00101" },
101
+ { plain: "IEEE P802.1Qbu/03.0, July 2015", replacement: "IEEE P802.1Qbu/D-3.0-2015" },
102
+ { plain: "IEEE P802.11aqTM/013.0 October 2017", replacement: "IEEE P802.11aqTM/D-13.0-2017" },
103
+ { plain: "IEC/IEEE P62271-37-013:2015 D13.4", replacement: "IEC/IEEE P62271.37-013/D-13.4-2015" },
104
+ { plain: "ISO/IEC/IEEE DIS P42020:201x(E), June 2017", replacement: "ISO/IEC/IEEE DIS P42020-2017-06" },
105
+ { plain: "ISO/IEC/IEEE DIS P16326/201x, December 2018", replacement: "ISO/IEC/IEEE DIS P16326-2018-12" },
106
+ { plain: "ISO/IEC/IEEE/P21839, 2019(E)", replacement: "ISO/IEC/IEEE P21839-2019" },
107
+ { plain: "ISO/IEC/IEEE CD2 P12207-2: 201x(E), February 2019", replacement: "ISO/IEC/IEEE CD2 P12207.2-2019-02" },
108
+ { plain: "ISO/IEC/IEEE P42010.WD4:2019(E)", replacement: "ISO/IEC/IEEE P42010/D-4-2019" },
109
+ { plain: "IEC/IEEE P63195_CDV/V3, February 2020", replacement: "IEC/IEEE CDV P63195-2020-02" },
110
+ { plain: "ISO/IEC/IEEE/P16085_DIS, March 2020", replacement: "ISO/IEC/IEEE DIS P16085-2020-03" },
111
+ { plain: "ANSI/IEEE Std: Outdoor Apparatus Bushings", replacement: "ANSI/IEEE Std 21-1976-11" },
112
+ { plain: "Draft National Electrical Safety Code, January 2016", replacement: "IEEE PC2-2016-01" },
113
+ { plain: "International Standard ISO/IEC 8802-9: 1996(E) ANSI/IEEE Std 802.9, 1996 Edition", replacement: "ISO/IEC/IEEE Std 802.9-1996" },
114
+ { plain: "ISO/IEC13210: 1994 (E) ANSI/IEEE Std 1003.3-1991", replacement: "ISO/IEC/IEEE 13210-1994" },
115
+ { plain: "J-STD-016-1995", replacement: "IEEE 016-1995" },
116
+ { plain: "Nuclear EQ Sourcebook and Supplement", replacement: "IEEE 7438946" },
117
+ { plain: "PC37.30.2/D043 Rev 18, May 2015", replacement: "IEEE PC37.30-2/D-043/R-18-2015" },
118
+ { plain: "IEEE/IEC P62582 CD2 proposal, May 2017", replacement: "IEEE/IEC CD2 P62582-2017-05" },
119
+ { plain: "ISO/IEC/IEEE P16326:201x WD.4a, July 2017", replacement: "ISO/IEC/IEEE P16326/D-4a-2017-07" },
120
+ { plain: "ISO/IEC/IEEE CD.1 P21839, October 2017", replacement: "ISO/IEC/IEEE CD1 P21839-2017-10" },
121
+ { plain: "ISO/IEC/IEEE P16326:201x WD5, December 2017", replacement: "ISO/IEC/IEEE P16326/D-5-2017-12" },
122
+ { plain: "IEEE/ISO/IEC P42010.CD1-V1.0, April 2020", replacement: "IEEE/ISO/IEC CD1 P42010-2020-04" },
123
+ { plain: "Unapproved Draft Std ISO/IEC FDIS 15288:2007(E) IEEE P15288/D3,", replacement: "ISO/IEC/IEEE FDIS Std P15288/D-3-2007" },
124
+ { plain: "IS0/IEC/IEEE 8802-11:2012/Amd.5:2015(E) (Adoption of IEEE Std 802.11af-2014)", replacement: "ISO/IEC/IEEE 802.11/Amd5-2012" },
125
+ { plain: "IEEE Approved Std P1609.3/D-23.pdf-2007-02", replacement: "IEEE Approved Std P1609.3/D23, 02 2007" },
126
+ { plain: "IEEE P3004.5/D-6.2.", replacement: "IEEE P3004.5/D6.2" },
127
+ { plain: "IEEE P730/D-0.16.-2025", replacement: "IEEE P730/D0.16-2025" },
128
+ { plain: "IEEE PC37.107/D-4.-2023-11", replacement: "IEEE PC37.107/D4, 11 2023" },
129
+ { plain: "IEEE PC37.113/D-8.0.-2015-08", replacement: "IEEE PC37.113/D8.0, 08 2015" },
130
+ { plain: "IEEE PC37.98/D-5.1D-2013", replacement: "IEEE PC37.98/D5.1D-2013" },
131
+ { plain: "IEEE PC57.637/D-6.2.-2014-03", replacement: "IEEE PC57.637/D6.2, 03 2014" },
132
+ { plain: "IEEE Std P650/D-9.-2006", replacement: "IEEE Std P650/D9-2006" },
133
+ { plain: "IEC/IEEE P63198.2775/D-6.1_CDV_March-2022", replacement: "IEC/IEEE CDV P63198.2775/D6.1, March 2022" },
134
+ { plain: "IEEE 3.Rev.B/D-4.0-2023-01", replacement: "IEEE P3/D4.0, 01 2023" },
135
+ { plain: "IEEE 3.Rev.B/D-5.0-2023-03", replacement: "IEEE P3/D5.0, 03 2023" },
136
+ { plain: "IEEE P1003.1/D-5/Cor1-201x-2012-04", replacement: "IEEE P1003.1/Cor 1/D5, 04 2012" },
137
+ { plain: "IEEE P1003.1/D-5/Cor1-201x-2012-08", replacement: "IEEE P1003.1/Cor 1/D5, 08 2012" },
138
+ { plain: "IEEE P1127/D-4.1_July-2023", replacement: "IEEE P1127/D4.1, July 2023" },
139
+ { plain: "IEEE P2660_1/D-2-2020-06", replacement: "IEEE P2660.1/D2, 06 2020" },
140
+ { plain: "IEEE P802.1AE/D-1.0/R-/Cor1", replacement: "IEEE P802.1AE/Cor 1/D1.0" },
141
+ { plain: "IEEE P802.1AE_Rev/D-1.2-2018", replacement: "IEEE P802.1AE/D1.2-2018" },
142
+ { plain: "IEEE P802.1AE_Rev/D-1.3-2018", replacement: "IEEE P802.1AE/D1.3-2018" },
143
+ { plain: "IEEE Unapproved Std P802.16Rev2/D-9-2009-01", replacement: "IEEE Unapproved Std P802.16Rev2/D9-2009" },
144
+ { plain: "IEEE Unapproved Std P802.1X_REV/D-4.5-2009", replacement: "IEEE Unapproved Std P802.1X/D4.5-2009" },
145
+ { plain: "IEEE Unapproved Std PC37.91/D-8-2007-20", replacement: "IEEE Unapproved Std PC37.91/D8-2007" },
146
+ { plain: "IEEEE P1243/D-3-2023-02", replacement: "IEEE P1243/D3, 02 2023" },
147
+ { plain: "ISO/IEC/IEEE FDIS P15289./E-3/D-2-2016", replacement: "ISO/IEC/IEEE FDIS P15289-2016/D2" },
148
+ { plain: "ISO/IEC/IEEE P24641/D-2_CD-2020", replacement: "ISO/IEC/IEEE CD P24641-2020/D2" },
149
+ { plain: "ISO/IEC/IEEE P24641/D-3_CD2", replacement: "ISO/IEC/IEEE CD2 P24641/D3" },
150
+ { plain: "ISO/IEC/IEEE P24748.3/D-3_FDIS-2020", replacement: "ISO/IEC/IEEE FDIS P24748.3-2020/D3" },
151
+ { plain: "ISO/IEC/IEEE/ P12207.2/D-3_FDIS-2020", replacement: "ISO/IEC/IEEE FDIS P12207.2-2020/D3" },
152
+ { plain: "ISO/IEC/IEEE/ P24748.3/D-IS-2019", replacement: "ISO/IEC/IEEE DIS P24748.3-2019" },
153
+ { plain: "P1635/D10/ASHARE 21/D-10-2016", replacement: "IEEE P1635/D10-2016" },
154
+ { pattern: ", (\\w{3,4})(\\d{4,4})$", flags: "", replacement: ", \\1 \\2" },
155
+ { pattern: "C37.0I0d-1984", flags: "", replacement: "C37.010d-1984" },
156
+ { pattern: "\\bSept\\b", flags: "", replacement: "Sep" },
157
+ { pattern: "\\bFeburary\\b", flags: "", replacement: "Feb" },
158
+ { pattern: "\\bNovemer\\b", flags: "", replacement: "Nov" },
159
+ { pattern: "\\bOctobor\\b", flags: "", replacement: "Oct" },
160
+ { pattern: "\\bJanurary\\b", flags: "", replacement: "Jan" },
161
+ { pattern: "\\bjanuary\\b", flags: "", replacement: "January" },
162
+ { pattern: "\\bfebruary\\b", flags: "", replacement: "February" },
163
+ { pattern: "\\bmarch\\b", flags: "", replacement: "March" },
164
+ { pattern: "\\bapril\\b", flags: "", replacement: "April" },
165
+ { pattern: "\\bjune\\b", flags: "", replacement: "June" },
166
+ { pattern: "\\bjuly\\b", flags: "", replacement: "July" },
167
+ { pattern: "\\baugust\\b", flags: "", replacement: "August" },
168
+ { pattern: "\\bseptember\\b", flags: "", replacement: "September" },
169
+ { pattern: "\\boctober\\b", flags: "", replacement: "October" },
170
+ { pattern: "\\bnovember\\b", flags: "", replacement: "November" },
171
+ { pattern: "\\bdecember\\b", flags: "", replacement: "December" },
172
+ ];
173
+ export function applyUpdateCodes(input) {
174
+ let code = input;
175
+ for (const entry of UPDATE_CODES) {
176
+ if (entry.plain !== undefined) {
177
+ const anchored = new RegExp(`^${entry.plain.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}$`);
178
+ // Plain keys substitute LITERALLY (Ruby String#gsub with a String
179
+ // replacement treats it literally except backrefs, which plain keys
180
+ // never carry); the replacer function keeps "$" safe.
181
+ const literal = entry.replacement;
182
+ code = code.replace(anchored, () => literal);
183
+ }
184
+ else if (entry.pattern !== undefined) {
185
+ // Regex-literal keys may carry Ruby backrefs (\1) — map to $1.
186
+ const replacement = entry.replacement.replace(/\\(\d)/g, (_, d) => `$${d}`);
187
+ code = code.replace(new RegExp(entry.pattern, entry.flags), replacement);
188
+ }
189
+ }
190
+ return code;
191
+ }