@pubid/pubid 0.1.29 → 0.1.31

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.
@@ -340,6 +340,19 @@ function normalizeJointStageSpellings(input) {
340
340
  ? _m
341
341
  : `${pubs} ${num}/D=${stage}${iter}-${year}${month}`;
342
342
  });
343
+ // The crawl glues the month onto the stage after the code's slash
344
+ // ("IEEE/IEC/ISO P80005-1/FDIS_March 2012", and its canonical comma
345
+ // form "... Draft P80005-1/FDIS_March, 2012"): the stage is the
346
+ // ISO/IEC token and the month belongs to the date (pubid#600, the
347
+ // 2026-10-25 ruling) - decode onto the D= designator face. Scoped to
348
+ // a real month name glued to a stage token; the stage-iteration
349
+ // routes are untouched.
350
+ cleaned = cleaned.replace(/^((?:IEEE|ISO|IEC)(?:\/(?:IEEE|ISO|IEC))*\s+(?:Draft\s+)?P?[A-Z0-9][A-Z0-9.-]*\/)(FDIS|FCD|CDV|DIS|CD|WD|PWI|NP)_([A-Za-z]+),?\s+(\d{4})$/, (_m, head, stage, mon, year) => {
351
+ const month = STAGE_MONTH_NUMBERS[mon.charAt(0).toUpperCase() + mon.slice(1).toLowerCase()];
352
+ return month === undefined
353
+ ? _m
354
+ : `${head}D=${stage}-${year}${month}`;
355
+ });
343
356
  const pubs = "((?:ISO/IEC/IEEE|IEEE/ISO/IEC|IEEE/IEC/ISO|ISO/IEEE|IEC/IEEE|IEEE/IEC|ISO/IEC)(?:/ ?| ))";
344
357
  const stage = "(FDIS|FCD|CDV|DIS\\d?|CD\\d?|WD|PWI|NP)";
345
358
  const num = "(P?\\d+(?:[.-]\\d+)?)";
@@ -84,3 +84,12 @@ export declare abstract class BaseIdentifier {
84
84
  /** Apply custom `fromWire` converters to the inflated hash. */
85
85
  protected static applyMappings(data: Record<string, unknown>): Record<string, unknown>;
86
86
  }
87
+ export declare function wrappedDocument(id: BaseIdentifier): BaseIdentifier | undefined;
88
+ /** The underlying standard, peeled recursively through the view layers. */
89
+ export declare function baseDocument(id: BaseIdentifier): BaseIdentifier;
90
+ /**
91
+ * Self is a wrapped record of exactly the edition `edition` names: the
92
+ * wrapped document resolves to that edition. Only wrappers answer true —
93
+ * a bare record is its own edition and is matched by the subset match.
94
+ */
95
+ export declare function wrappedEditionOf(candidate: BaseIdentifier, edition: BaseIdentifier): boolean;
@@ -78,6 +78,7 @@ function isEmptyValue(value) {
78
78
  function resolveDefault(spec) {
79
79
  return typeof spec.default === "function" ? spec.default() : spec.default;
80
80
  }
81
+ import { canonicalKey } from "../internal/compare.js";
81
82
  export class BaseIdentifier {
82
83
  /** The root table; subclasses compose via extendAttributes(BaseIdentifier, …). */
83
84
  static attributes = BASE_ATTRIBUTES;
@@ -272,3 +273,52 @@ export class BaseIdentifier {
272
273
  function deepEqual(a, b) {
273
274
  return JSON.stringify(a) === JSON.stringify(b);
274
275
  }
276
+ // --- the wrapped-edition relationship (pubid#580, gem#606) -------------------
277
+ //
278
+ // The document a wrapper stands in front of: a declared `base` slot, or
279
+ // the leading member of a consolidated collection. Undefined for a plain
280
+ // identifier.
281
+ export function wrappedDocument(id) {
282
+ const attrs = id;
283
+ if (attrs["base"] instanceof BaseIdentifier)
284
+ return attrs["base"];
285
+ const ids = attrs["identifiers"];
286
+ if (Array.isArray(ids) && ids[0] instanceof BaseIdentifier) {
287
+ return ids[0];
288
+ }
289
+ return undefined;
290
+ }
291
+ // The classes whose Ruby counterparts override base_document — the
292
+ // records that are VIEWS of the document they wrap (the IEC VAP/CSV
293
+ // record, the consolidated bundles). A supplement (an ISO/IEC amendment,
294
+ // a corrigendum) is a separate document, not a view, so the peel stops
295
+ // at it; the cen/csa view wrappers join when the algebra ports them.
296
+ const BASE_DOCUMENT_VIEW_CLASSES = new Set([
297
+ "pubid:iec:vap-identifier",
298
+ "pubid:iec:consolidated-identifier",
299
+ ]);
300
+ /** The underlying standard, peeled recursively through the view layers. */
301
+ export function baseDocument(id) {
302
+ const attrs = id;
303
+ const ids = attrs["identifiers"];
304
+ if (Array.isArray(ids) && ids[0] instanceof BaseIdentifier) {
305
+ return baseDocument(ids[0]);
306
+ }
307
+ const ctor = id.constructor.polymorphicName;
308
+ if (ctor !== undefined && BASE_DOCUMENT_VIEW_CLASSES.has(ctor) &&
309
+ attrs["base"] instanceof BaseIdentifier) {
310
+ return baseDocument(attrs["base"]);
311
+ }
312
+ return id;
313
+ }
314
+ /**
315
+ * Self is a wrapped record of exactly the edition `edition` names: the
316
+ * wrapped document resolves to that edition. Only wrappers answer true —
317
+ * a bare record is its own edition and is matched by the subset match.
318
+ */
319
+ export function wrappedEditionOf(candidate, edition) {
320
+ if (wrappedDocument(candidate) === undefined)
321
+ return false;
322
+ return canonicalKey(baseDocument(candidate).toHash()) ===
323
+ canonicalKey(edition.toHash());
324
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pubid/pubid",
3
- "version": "0.1.29",
3
+ "version": "0.1.31",
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",