@pubid/pubid 0.1.11 → 0.1.12

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.
@@ -1052,8 +1052,14 @@ class IeeeBuilder {
1052
1052
  typeof parsed["parameters"] === "object" && !Array.isArray(parsed["parameters"]) &&
1053
1053
  parsed["parameters"]["parenthetical_content"] !== undefined))) {
1054
1054
  const sep = parsed["part_dash"] !== undefined ? "-" : ".";
1055
- let printedCode = [extractValue(parsed["number"]), extractValue(parsed["part"])]
1056
- .filter((x) => x !== undefined).join(sep);
1055
+ // The part capture carries its own separator (C1
1056
+ // separator-in-capture); join verbatim, synthesizing one only
1057
+ // for a bare capture — the reference's printed_joint rule.
1058
+ const partVal = extractValue(parsed["part"]);
1059
+ let printedCode = extractValue(parsed["number"]) ?? "";
1060
+ if (partVal !== undefined) {
1061
+ printedCode += /^[._-]/.test(partVal) ? partVal : `${sep}${partVal}`;
1062
+ }
1057
1063
  // P = project: the marker is identity, preserved as spelled.
1058
1064
  if (parsed["project_marker"] !== undefined)
1059
1065
  printedCode = `P${printedCode}`;
@@ -1177,8 +1177,11 @@ export const JointDevelopmentClass = ieeeClass({ kind: "joint-development" }, {
1177
1177
  result += `, ${id.month} ${dateYear}`;
1178
1178
  }
1179
1179
  }
1180
+ // Lossless: parse(to_s) == self (gem c148d267, the 2026-10-19
1181
+ // ruling) — the parenthetical rides unconditionally on both
1182
+ // joint faces.
1180
1183
  const marker = id["parenthetical_content"];
1181
- if (marker !== undefined && /^[A-Z](?:\s*[/&]\s*[A-Z])*$/.test(marker)) {
1184
+ if (marker !== undefined) {
1182
1185
  result += ` (${marker})`;
1183
1186
  }
1184
1187
  // The joint ISO-print redline is a distinct document (pubid#215):
@@ -1224,6 +1227,9 @@ export const JointDevelopmentClass = ieeeClass({ kind: "joint-development" }, {
1224
1227
  !(ieeeDraft ?? "").endsWith(`-${id.year}`)) {
1225
1228
  result += `-${id.year}`;
1226
1229
  }
1230
+ const marker = id["parenthetical_content"];
1231
+ if (marker !== undefined)
1232
+ result += ` (${marker})`;
1227
1233
  if (id.redline === true)
1228
1234
  result += " - Redline";
1229
1235
  return result;
@@ -417,12 +417,9 @@ export function preprocessIeee(input) {
417
417
  cleaned = cleaned.replace(/^(ISO\/IEC \d+[-.]\d*)\s*:\s*(\d{4})/, "$1:$2");
418
418
  cleaned = cleaned.replace(/^(ISO\/IEC \d+)\s*:\s*(\d{4})/, "$1:$2");
419
419
  cleaned = cleaned.replace(/^(IEC\/IEEE P[\w.-]+)_D/, "$1/D");
420
- // Scoped: the D= stage-draft rows keep the IEEE-led list (the ruby
421
- // ieee_format routes them with the input publisher order and lead
422
- // IEEE - "IEEE/ISO/IEC P29119-2/D=DIS-201112"); the other IEEE/ISO/IEC
423
- // spellings print the ISO-led face.
424
- cleaned = cleaned.replace(/^IEEE\/ISO\/IEC\s+(?!P[\w.-]+\/D=)(P[\w.-]+)/, "ISO/IEC/IEEE $1");
425
- cleaned = cleaned.replace(/^IEEE\/IEC\/ISO\s+(P[\w.-]+)/, "IEC/ISO/IEEE $1");
420
+ // The printed publisher order is identity (pubid#469, the
421
+ // dual-perspective ruling): no IEEE/ISO/IEC or IEEE/IEC/ISO rewrites —
422
+ // the reference parses as printed and renders the printed order back.
426
423
  cleaned = cleaned.replace(/^(IEEE\/IEC P[\w.-]+)\s+D(\d)/, "$1/D$2");
427
424
  cleaned = cleaned.replace(/^(IEEE\/IEC P[\w.-]+)\s+(CDV|FDIS|CD|DIS|ED\d)/, "$1/$2");
428
425
  cleaned = cleaned.replace(/^ISO\s+\/IEC\/IEEE/, "ISO/IEC/IEEE");
@@ -443,7 +440,6 @@ export function preprocessIeee(input) {
443
440
  cleaned = cleaned.replaceAll("Edn.", "Edition");
444
441
  cleaned = cleaned.replaceAll("ASHARE", "ASHRAE");
445
442
  cleaned = cleaned.replace(/^PC(\d)/, "P$1");
446
- cleaned = cleaned.replace(/^IEEE\/ISO\/IEC\s+(8802[\w.-]+)/, "ISO/IEC/IEEE $1");
447
443
  cleaned = cleaned.replace(/^(IEEE\s+C?\d[\d.]*\/D\d+)([A-Z][a-z]+\s+\d{4})/, "$1, $2");
448
444
  cleaned = cleaned.replace(/^(ANSI\/IEEE Std):\s+.*$/, "$1");
449
445
  cleaned = cleaned.replace(/^(IEEE\s+[\d.]+)\s+(IEC\s+\d+[-\d]*\s+.*edition\s+\d{4}-\d{2})$/i, "$1; $2");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pubid/pubid",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "TypeScript PubID identifiers: resolution, normalization and canonical hashes for every identifier in the pubid-testsuite corpus (41 standards bodies), with a conformance runner mirroring the Ruby reference",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1 +1 @@
1
- {"bindings":null,"version":"0.1.0","grammar":"PubidOmg","shape":"parsanol-tree/v2","binding_version":1,"entries":{"identifier":{"root":"identifier","grammar":{"atoms":[{"Str":{"pattern":"OMG"}},{"Entity":{"atom":2}},{"Str":{"pattern":" "}},{"Entity":{"atom":24}},{"Entity":{"atom":7}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Alternative":{"atoms":[5,6]}},{"Entity":{"atom":13}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Re":{"pattern":"[+]"}},{"Alternative":{"atoms":[9,10,11,12]}},{"Repetition":{"atom":8,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":18}},{"Re":{"pattern":"[\\-]"}},{"Re":{"pattern":"[/]"}},{"Alternative":{"atoms":[16,17]}},{"Entity":{"atom":13}},{"Repetition":{"atom":19,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[15,20]}},{"Repetition":{"atom":21,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[4,14,22]}},{"Named":{"name":"acronym","atom":23}},{"Entity":{"atom":2}},{"Entity":{"atom":54}},{"Entity":{"atom":28}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Repetition":{"atom":27,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":31}},{"Str":{"pattern":"."}},{"Entity":{"atom":28}},{"Repetition":{"atom":32,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[30,33]}},{"Repetition":{"atom":34,"min":0,"max":null,"tag":"Repetition"}},{"Entity":{"atom":51}},{"Str":{"pattern":" beta"}},{"Entity":{"atom":42}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Alternative":{"atoms":[39,40,41]}},{"Lookahead":{"atom":38,"positive":false}},{"Entity":{"atom":2}},{"Entity":{"atom":28}},{"Repetition":{"atom":45,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":42}},{"Lookahead":{"atom":47,"positive":false}},{"Sequence":{"atoms":[44,46,48]}},{"Repetition":{"atom":49,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[37,43,50]}},{"Repetition":{"atom":36,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[29,35,52]}},{"Named":{"name":"version","atom":53}},{"Entity":{"atom":59}},{"Entity":{"atom":2}},{"Entity":{"atom":58}},{"Str":{"pattern":"/"}},{"Alternative":{"atoms":[56,57]}},{"Entity":{"atom":63}},{"Entity":{"atom":42}},{"Repetition":{"atom":61,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"part","atom":62}},{"Sequence":{"atoms":[55,60]}},{"Repetition":{"atom":64,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[25,26,65]}},{"Entity":{"atom":2}},{"Entity":{"atom":63}},{"Sequence":{"atoms":[67,68]}},{"Alternative":{"atoms":[66,69]}},{"Repetition":{"atom":70,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[0,1,3,71]}}],"root":72},"bindings":[]}},"preprocess":{},"tables":{},"lint":{"order_warnings":[]},"default_entry":"identifier","render":{},"derive":{},"tests":[{"entry":"identifier","kind":"accept","input":"OMG IDL 4.2","expect":{}},{"entry":"identifier","kind":"accept","input":"OMG UML 2.5.1","expect":{}},{"entry":"identifier","kind":"reject","input":"nonsense","expect":{}}],"docs":{},"source":"# Port of lib/pubid/omg/parser.rb: OMG <acronym>[ <version>[<sep><part>]]\n# with the beta-label word-boundary guards (a bare \"beta\" must not be\n# swallowed by the part rule).\n grammar PubidOmg version \"0.1.0\" {\n digit = %x30-39\n acronym_char = %x41-5A / %x61-7A / %x30-39 / %x2B\n acronym_join = %x2D / %x2F\n acronym = (letter 1*acronym_char *(acronym_join 1*acronym_char)) as acronym\n word_boundary = !alnum_char\n beta = \" beta\" !alnum_char ([space 1*digit !alnum_char])\n version = (1*digit *(dot 1*digit) [beta]) as version\n part_separator = space / slash\n part = (1*alnum_char) as part\n identifier = \"OMG\" space acronym [((space version [part_separator part]) / (space part))]\n alnum_char = %x41-5A / %x61-7A / %x30-39\n letter = %x41-5A / %x61-7A\n dot = \".\"\n slash = \"/\"\n space = \" \"\n entry identifier: identifier\n\n test {\n accept \"OMG IDL 4.2\"\n accept \"OMG UML 2.5.1\"\n reject \"nonsense\"\n }\n}\n","source_hash":"2dac987a51409c0af26e59449f71fab80a2249a14f119a9a244633ce7149faa6","compiler_version":"1.3.93","checksum":"sha256:229f295dc796802ddf19b56803bb420107218420ba5dc7acab3d58d1a9a7bb9e"}
1
+ {"bindings":null,"version":"0.1.0","grammar":"PubidOmg","shape":"parsanol-tree/v2","binding_version":1,"entries":{"identifier":{"root":"identifier","grammar":{"atoms":[{"Str":{"pattern":"OMG"}},{"Entity":{"atom":2}},{"Str":{"pattern":" "}},{"Entity":{"atom":24}},{"Entity":{"atom":7}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Alternative":{"atoms":[5,6]}},{"Entity":{"atom":13}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Re":{"pattern":"[+]"}},{"Alternative":{"atoms":[9,10,11,12]}},{"Repetition":{"atom":8,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":18}},{"Re":{"pattern":"[\\-]"}},{"Re":{"pattern":"[/]"}},{"Alternative":{"atoms":[16,17]}},{"Entity":{"atom":13}},{"Repetition":{"atom":19,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[15,20]}},{"Repetition":{"atom":21,"min":0,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[4,14,22]}},{"Named":{"name":"acronym","atom":23}},{"Entity":{"atom":2}},{"Entity":{"atom":63}},{"Entity":{"atom":28}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Repetition":{"atom":27,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":31}},{"Str":{"pattern":"."}},{"Entity":{"atom":28}},{"Repetition":{"atom":32,"min":1,"max":null,"tag":"Repetition"}},{"Sequence":{"atoms":[30,33]}},{"Repetition":{"atom":34,"min":0,"max":null,"tag":"Repetition"}},{"Entity":{"atom":60}},{"Str":{"pattern":" beta"}},{"Entity":{"atom":42}},{"Re":{"pattern":"[\\x41-\\x5a]"}},{"Re":{"pattern":"[\\x61-\\x7a]"}},{"Re":{"pattern":"[\\x30-\\x39]"}},{"Alternative":{"atoms":[39,40,41]}},{"Lookahead":{"atom":38,"positive":false}},{"Entity":{"atom":2}},{"Entity":{"atom":28}},{"Repetition":{"atom":45,"min":1,"max":null,"tag":"Repetition"}},{"Entity":{"atom":42}},{"Lookahead":{"atom":47,"positive":false}},{"Sequence":{"atoms":[44,46,48]}},{"Repetition":{"atom":49,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[37,43,50]}},{"Entity":{"atom":2}},{"Str":{"pattern":"Beta"}},{"Entity":{"atom":28}},{"Repetition":{"atom":54,"min":1,"max":null,"tag":"Repetition"}},{"Repetition":{"atom":55,"min":0,"max":1,"tag":"Maybe"}},{"Entity":{"atom":42}},{"Lookahead":{"atom":57,"positive":false}},{"Sequence":{"atoms":[52,53,56,58]}},{"Alternative":{"atoms":[51,59]}},{"Repetition":{"atom":36,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[29,35,61]}},{"Named":{"name":"version","atom":62}},{"Entity":{"atom":68}},{"Entity":{"atom":2}},{"Entity":{"atom":67}},{"Str":{"pattern":"/"}},{"Alternative":{"atoms":[65,66]}},{"Entity":{"atom":72}},{"Entity":{"atom":42}},{"Repetition":{"atom":70,"min":1,"max":null,"tag":"Repetition"}},{"Named":{"name":"part","atom":71}},{"Sequence":{"atoms":[64,69]}},{"Repetition":{"atom":73,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[25,26,74]}},{"Entity":{"atom":2}},{"Entity":{"atom":72}},{"Sequence":{"atoms":[76,77]}},{"Alternative":{"atoms":[75,78]}},{"Repetition":{"atom":79,"min":0,"max":1,"tag":"Maybe"}},{"Sequence":{"atoms":[0,1,3,80]}}],"root":81},"bindings":[]}},"preprocess":{},"tables":{},"lint":{"order_warnings":["rule beta: branches 1 and 2 are order-dependent (shared first bytes; ordered choice is decisive)"]},"default_entry":"identifier","render":{},"derive":{},"tests":[{"entry":"identifier","kind":"accept","input":"OMG IDL 4.2","expect":{}},{"entry":"identifier","kind":"accept","input":"OMG UML 2.5.1","expect":{}},{"entry":"identifier","kind":"reject","input":"nonsense","expect":{}}],"docs":{},"source":"# Port of lib/pubid/omg/parser.rb: OMG <acronym>[ <version>[<sep><part>]]\n# with the beta-label word-boundary guards (a bare \"beta\" must not be\n# swallowed by the part rule). The GLUED CATALOGUE label (\"Beta1\" --\n# capitalized, the /spec/ALMAS/1.5/Beta1 URL segment) classifies into\n# the version (the 2026-10-19 pubid#548 ruling); the LOWERCASE glued\n# form (\"beta2\") stays a document part (the DDS ruling, spec-pinned). A\n# /spec/ALMAS/1.5/Beta1 URL segment) classifies into the version (the\n# 2026-10-19 pubid#548 ruling); a Beta-prefixed part without digits\n# (\"BetaWave\") still lexes as the part — the boundary guard keeps it.\n grammar PubidOmg version \"0.1.0\" {\n digit = %x30-39\n acronym_char = %x41-5A / %x61-7A / %x30-39 / %x2B\n acronym_join = %x2D / %x2F\n acronym = (letter 1*acronym_char *(acronym_join 1*acronym_char)) as acronym\n word_boundary = !alnum_char\n beta = (\" beta\" !alnum_char ([space 1*digit !alnum_char]) / (space \"Beta\" [1*digit] !alnum_char))\n version = (1*digit *(dot 1*digit) [beta]) as version\n part_separator = space / slash\n part = (1*alnum_char) as part\n identifier = \"OMG\" space acronym [((space version [part_separator part]) / (space part))]\n alnum_char = %x41-5A / %x61-7A / %x30-39\n letter = %x41-5A / %x61-7A\n dot = \".\"\n slash = \"/\"\n space = \" \"\n entry identifier: identifier\n\n test {\n accept \"OMG IDL 4.2\"\n accept \"OMG UML 2.5.1\"\n reject \"nonsense\"\n }\n}\n","source_hash":"9ed6dcd5dff95df514aa465c3cbd923780c6275761db3415b8eba5e05213cd20","compiler_version":"1.3.93","checksum":"sha256:d33c557faf6c8ac5ea071abee1576c15c08e7a93f988423f77aff7c4f5831c54"}