@pubid/pubid 0.1.27 → 0.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/flavors/ecma/index.js +3 -0
- package/dist/flavors/ieee/index.js +96 -10
- package/dist/flavors/ieee/model.js +14 -4
- package/dist/flavors/iso/model.d.ts +15 -1
- package/dist/flavors/iso/model.js +16 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/model/subset-match.js +2 -1
- package/package.json +1 -1
- package/vendor/parg/ieee.json +2473 -1914
|
@@ -37,6 +37,9 @@ function ecmaClass(kind) {
|
|
|
37
37
|
const prefix = KIND_PREFIXES[kind];
|
|
38
38
|
class EcmaKindIdentifier extends BaseIdentifier {
|
|
39
39
|
static polymorphicName = `pubid:ecma:${kind}`;
|
|
40
|
+
// Ruby Pubid::Ecma declares subset_strict :part: a part-less ECMA
|
|
41
|
+
// reference means "this document has none", not "any part".
|
|
42
|
+
static subsetStrict = ["part"];
|
|
40
43
|
static attributes = extendAttributes(BaseIdentifier, {
|
|
41
44
|
number: { type: "string" },
|
|
42
45
|
part: { type: "string" },
|
|
@@ -320,9 +320,14 @@ class IeeeBuilder {
|
|
|
320
320
|
const copubs = Array.isArray(pubData["copublishers"])
|
|
321
321
|
? pubData["copublishers"]
|
|
322
322
|
: [pubData["copublishers"]];
|
|
323
|
+
// A capture may carry its own separators ("/IEC/ISO" — a joint
|
|
324
|
+
// token glued to the leading slash); the collection renders
|
|
325
|
+
// join("/"), so entries hold bare orgs.
|
|
323
326
|
attributes["copublisher"] = copubs
|
|
324
327
|
.map((cp) => extractValue(asHash(cp)["copublisher"]))
|
|
325
|
-
.filter((cp) => cp !== undefined)
|
|
328
|
+
.filter((cp) => cp !== undefined)
|
|
329
|
+
.flatMap((c) => c.replace(/^\//, "").split("/"))
|
|
330
|
+
.filter((c) => c !== "");
|
|
326
331
|
}
|
|
327
332
|
}
|
|
328
333
|
else if (parsed["publisher"] !== undefined) {
|
|
@@ -637,7 +642,15 @@ class IeeeBuilder {
|
|
|
637
642
|
}
|
|
638
643
|
}
|
|
639
644
|
else {
|
|
640
|
-
|
|
645
|
+
// A degraded wire leaf carries the whole draft clause verbatim
|
|
646
|
+
// ("/D2.1.1" — the three-segment designator the engine cannot
|
|
647
|
+
// structure): IeeeDraft.parse is the inverse of render, so it
|
|
648
|
+
// strips the prefix instead of double-appending it.
|
|
649
|
+
const reparsed = IeeeDraft.parse(extractValue(draftData) ?? "");
|
|
650
|
+
if (reparsed !== undefined) {
|
|
651
|
+
attributes["draft"] = reparsed.render();
|
|
652
|
+
return;
|
|
653
|
+
}
|
|
641
654
|
}
|
|
642
655
|
// A REV-carrying draft embeds its print date into the designator
|
|
643
656
|
// with the month canonicalized numeric (pubid ruling 2026-10-14):
|
|
@@ -1098,7 +1111,10 @@ class IeeeBuilder {
|
|
|
1098
1111
|
// strip it (the #471 separator-in-capture rule). The stored
|
|
1099
1112
|
// form keeps the comma so it re-parses through the same tail.
|
|
1100
1113
|
const draftYear = (extractValue(parsed["draft_year"]) ?? "").replace(/^[, ]+/, "");
|
|
1101
|
-
|
|
1114
|
+
// Compose through the render so a designator-word version
|
|
1115
|
+
// ("ED1") keeps its word instead of concatenating D ("DED1").
|
|
1116
|
+
attributes["draft"] =
|
|
1117
|
+
new IeeeDraft({ version: draftVer, year: draftYear }).render();
|
|
1102
1118
|
if (parsed["year"] === undefined)
|
|
1103
1119
|
delete attributes["year"];
|
|
1104
1120
|
}
|
|
@@ -1178,7 +1194,21 @@ class IeeeBuilder {
|
|
|
1178
1194
|
// the P and keep the joint spelling.
|
|
1179
1195
|
const numericDraft = parsed["draft_version"] !== undefined &&
|
|
1180
1196
|
/^\d/.test(extractValue(parsed["draft_version"]) ?? "");
|
|
1181
|
-
|
|
1197
|
+
// P + a /D designator (any draft capture) is a DRAFT, never a
|
|
1198
|
+
// printed Std (the owner's 2026-10-24 ruling) -- the joint/
|
|
1199
|
+
// project-draft family owns the row whatever date trails the
|
|
1200
|
+
// designator. The ruling extends to the P-less joint rows
|
|
1201
|
+
// (pubid#597): a numeric /D designator alone is project status
|
|
1202
|
+
// too -- the row is a draft AND takes the P, so the marker is set
|
|
1203
|
+
// below when the source spelling lacked it.
|
|
1204
|
+
const pWithDraft = (parsed["project_marker"] !== undefined || numericDraft) &&
|
|
1205
|
+
(parsed["draft_version"] !== undefined || parsed["draft_iso_stage"] !== undefined ||
|
|
1206
|
+
parsed["draft_month"] !== undefined || parsed["draft_year"] !== undefined);
|
|
1207
|
+
if (pWithDraft && parsed["project_marker"] === undefined) {
|
|
1208
|
+
attributes["project_marker"] = true;
|
|
1209
|
+
parsed["project_marker"] = "P";
|
|
1210
|
+
}
|
|
1211
|
+
if (parsed["iso_published"] !== undefined && !pWithDraft &&
|
|
1182
1212
|
(parsed["printed_dash_year"] !== undefined || parsed["printed_month_year"] !== undefined ||
|
|
1183
1213
|
(numericDraft && parsed["draft_month"] !== undefined) ||
|
|
1184
1214
|
(parsed["year"] === undefined && parsed["parameters"] !== undefined &&
|
|
@@ -1193,6 +1223,11 @@ class IeeeBuilder {
|
|
|
1193
1223
|
if (partVal !== undefined) {
|
|
1194
1224
|
printedCode += /^[._-]/.test(partVal) ? partVal : `${sep}${partVal}`;
|
|
1195
1225
|
}
|
|
1226
|
+
// the subpart carries its separator too (C1 separator-in-capture);
|
|
1227
|
+
// the two-party rows split "-57-1202"-class parts into both
|
|
1228
|
+
const subVal = parsed["subpart"] !== undefined ? extractValue(parsed["subpart"]) : undefined;
|
|
1229
|
+
if (subVal !== undefined && subVal !== "")
|
|
1230
|
+
printedCode += subVal;
|
|
1196
1231
|
// P = project: the marker is identity, preserved as spelled.
|
|
1197
1232
|
if (parsed["project_marker"] !== undefined)
|
|
1198
1233
|
printedCode = `P${printedCode}`;
|
|
@@ -1217,9 +1252,11 @@ class IeeeBuilder {
|
|
|
1217
1252
|
printedAttrs["month"] = attributes["month"];
|
|
1218
1253
|
}
|
|
1219
1254
|
else if (parsed["draft_month"] !== undefined) {
|
|
1220
|
-
// The date trails the draft itself
|
|
1221
|
-
// the
|
|
1222
|
-
|
|
1255
|
+
// The date trails the draft itself ("D31, Aug 2010"): the
|
|
1256
|
+
// normalization ledger strips the ordinal draft on the printed
|
|
1257
|
+
// joint face and surfaces the date as the printed date.
|
|
1258
|
+
printedAttrs["year"] = extractValue(parsed["draft_year"]);
|
|
1259
|
+
printedAttrs["month"] = extractValue(parsed["draft_month"]);
|
|
1223
1260
|
}
|
|
1224
1261
|
const codeObj = IeeeCode.parse(finalCode);
|
|
1225
1262
|
if (codeObj !== undefined) {
|
|
@@ -1254,6 +1291,20 @@ class IeeeBuilder {
|
|
|
1254
1291
|
// date-less form ("/D=CD1") elects the same face only when the input
|
|
1255
1292
|
// spells the designator (the reference's original_input gate) — the
|
|
1256
1293
|
// stage-first rows keep their ISO rendering.
|
|
1294
|
+
// The designation route ("IEEE P24748-4/D=FDIS") has no
|
|
1295
|
+
// publishers group; IEEE is the sole publisher of the D=
|
|
1296
|
+
// designator face, and the elections below read the builder-local
|
|
1297
|
+
// slots.
|
|
1298
|
+
if (attributes["publisher"] === undefined)
|
|
1299
|
+
attributes["publisher"] = "IEEE";
|
|
1300
|
+
if (attributes["copublisher"] === undefined)
|
|
1301
|
+
attributes["copublisher"] = [];
|
|
1302
|
+
// The model rebuilds publishers from publisher+copublisher when
|
|
1303
|
+
// the publishers group is absent (the reference initialize).
|
|
1304
|
+
if (attributes["publishers"] === undefined) {
|
|
1305
|
+
attributes["publishers"] = [attributes["publisher"],
|
|
1306
|
+
...(attributes["copublisher"] ?? [])];
|
|
1307
|
+
}
|
|
1257
1308
|
const dEqInput = this.originalInput.includes("/D=");
|
|
1258
1309
|
const stageWordForGate = extractValue(parsed["iso_stage"]) ?? "";
|
|
1259
1310
|
if (parsed["iso_stage"] !== undefined &&
|
|
@@ -1284,6 +1335,29 @@ class IeeeBuilder {
|
|
|
1284
1335
|
if (!bareIeeeProject)
|
|
1285
1336
|
attributes["lead_party"] = "ISO";
|
|
1286
1337
|
let stageAbbr = extractValue(parsed["iso_stage"]);
|
|
1338
|
+
// The bare-IEEE project row carries the stage on the D=
|
|
1339
|
+
// designator with the IEEE date convention ("D=FDIS-201008",
|
|
1340
|
+
// pubid#203); the ISO stage-word face is not elected.
|
|
1341
|
+
if (bareIeeeProject && parsed["draft_stage_year"] === undefined) {
|
|
1342
|
+
let date = "";
|
|
1343
|
+
const y = attributes["year"];
|
|
1344
|
+
const m = String(attributes["month"] ?? "");
|
|
1345
|
+
if (y !== undefined) {
|
|
1346
|
+
date = `-${y}`;
|
|
1347
|
+
if (m !== "") {
|
|
1348
|
+
const monthNum = /^\d+$/.test(m) ? Number(m) : DRAFT_MONTH_NAMES[String(m).replace(/\.$/, "")];
|
|
1349
|
+
if (monthNum !== undefined)
|
|
1350
|
+
date += String(monthNum).padStart(2, "0");
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
attributes["ieee_draft"] = `D=${stageAbbr}${date}`;
|
|
1354
|
+
const record = stageAbbr !== undefined ? locateStage(stageAbbr) : undefined;
|
|
1355
|
+
if (record !== undefined)
|
|
1356
|
+
attributes["typed_stage"] = new IeeeTypedStage(record);
|
|
1357
|
+
attributes["lead_party"] = "IEEE";
|
|
1358
|
+
delete attributes["year"];
|
|
1359
|
+
delete attributes["month"];
|
|
1360
|
+
}
|
|
1287
1361
|
// The IEC "/V<version>" iteration rides glued onto the stage word
|
|
1288
1362
|
// ("_CDV/V3" -> "CDV3") — the family's lossless spelling (the
|
|
1289
1363
|
// reference's builder, pubid#477).
|
|
@@ -1347,8 +1421,11 @@ class IeeeBuilder {
|
|
|
1347
1421
|
projectAttrs[k] = attributes[k];
|
|
1348
1422
|
}
|
|
1349
1423
|
}
|
|
1350
|
-
|
|
1351
|
-
|
|
1424
|
+
// The ruling (pubid#597): a joint row with a numeric /D designator
|
|
1425
|
+
// is a draft AND takes the P project marker, whatever the source
|
|
1426
|
+
// spelling printed -- the marker rides the identifier even when
|
|
1427
|
+
// the row reached it without one.
|
|
1428
|
+
projectAttrs["project_marker"] = true;
|
|
1352
1429
|
if (pubs.length > 0) {
|
|
1353
1430
|
projectAttrs["publisher"] = pubs[0];
|
|
1354
1431
|
if (pubs.length > 1)
|
|
@@ -1364,8 +1441,17 @@ class IeeeBuilder {
|
|
|
1364
1441
|
// builds the base [ISO, IEC, IEEE], lead ISO); the CD-stage rows and
|
|
1365
1442
|
// the IEEE-led project rows preserve the printed order (P90003 stays
|
|
1366
1443
|
// IEEE/ISO/IEC).
|
|
1444
|
+
// The reorder is the PUBLISHED stage-less doctrine (pubid#317)
|
|
1445
|
+
// only: the project rows (the P marker) and every draft-bearing
|
|
1446
|
+
// row keep the printed publisher order (the 2026-10-24 corpus
|
|
1447
|
+
// faces, pubid#595).
|
|
1448
|
+
const draftBearing = parsed["project_marker"] !== undefined ||
|
|
1449
|
+
parsed["draft_version"] !== undefined ||
|
|
1450
|
+
parsed["draft"] !== undefined ||
|
|
1451
|
+
parsed["draft_iso_stage"] !== undefined ||
|
|
1452
|
+
parsed["draft_stage_year"] !== undefined;
|
|
1367
1453
|
if (parsed["iso_published"] !== undefined && parsed["iso_stage"] === undefined &&
|
|
1368
|
-
Array.isArray(attributes["publishers"])) {
|
|
1454
|
+
!draftBearing && Array.isArray(attributes["publishers"])) {
|
|
1369
1455
|
const pubs = attributes["publishers"];
|
|
1370
1456
|
attributes["publishers"] = [...pubs.filter((p) => p !== "IEEE"), ...pubs.filter((p) => p === "IEEE")];
|
|
1371
1457
|
attributes["publisher"] = attributes["publishers"][0];
|
|
@@ -222,7 +222,12 @@ export class IeeeDraft {
|
|
|
222
222
|
});
|
|
223
223
|
}
|
|
224
224
|
render() {
|
|
225
|
-
|
|
225
|
+
// A version that already opens with a designator word ("ED4", the
|
|
226
|
+
// IEC edition-draft ordinal; an ISO/IEC stage token such as
|
|
227
|
+
// "FDIS_March") renders verbatim — prepending D concatenates a
|
|
228
|
+
// hallucinated token ("DED4", "DFDIS") that no face spells.
|
|
229
|
+
const designatorVerbatim = /^(ED\d|(FDIS|FCD|CDV|DIS|CD|WD|PWI|NP))/.test(this.version);
|
|
230
|
+
let result = designatorVerbatim ? `/${this.version}` : `/D${this.version}`;
|
|
226
231
|
if (this.isoStage !== undefined)
|
|
227
232
|
result += `=${this.isoStage}`;
|
|
228
233
|
if (this.isoStage !== undefined && this.isoIteration !== undefined) {
|
|
@@ -487,12 +492,17 @@ export function renderIeeeBase(id) {
|
|
|
487
492
|
}
|
|
488
493
|
if (id.draft_status !== undefined)
|
|
489
494
|
parts.push(id.draft_status);
|
|
490
|
-
const
|
|
495
|
+
const isProjectDraft = id.constructor.polymorphicName ===
|
|
496
|
+
"pubid:ieee:project-draft-identifier";
|
|
497
|
+
// A project draft carries the word Draft whatever the lead
|
|
498
|
+
// publisher -- the ISO-led joint drafts (pubid#597) print it too.
|
|
499
|
+
const shouldRenderType = /^(IEEE|AIEE)/.test(id.publisher ?? "") || isProjectDraft;
|
|
491
500
|
const stageObj = id.typed_stage;
|
|
492
501
|
if (shouldRenderType && !(stageObj?.projectStatus === true) &&
|
|
493
|
-
id.type !== undefined && id.type.trim() !== "" && id.type !== "P"
|
|
502
|
+
((id.type !== undefined && id.type.trim() !== "" && id.type !== "P") ||
|
|
503
|
+
isProjectDraft) &&
|
|
494
504
|
!/unapproved/i.test(id.draft_status ?? "")) {
|
|
495
|
-
let typeStr = id.type;
|
|
505
|
+
let typeStr = id.type ?? "Draft";
|
|
496
506
|
if (typeStr.startsWith("P"))
|
|
497
507
|
typeStr = typeStr.slice(1);
|
|
498
508
|
// A draft carries the word Draft alone in every face (the C2
|
|
@@ -40,6 +40,10 @@ export declare class IsoEdition extends Component {
|
|
|
40
40
|
toWire(): Record<string, unknown>;
|
|
41
41
|
}
|
|
42
42
|
export declare abstract class IsoIdentifier extends BaseIdentifier {
|
|
43
|
+
/** The typed-stage state joins the match (the published default is
|
|
44
|
+
* stated: ISO 9004 does not match ISO/DIS 9004) but never the wire
|
|
45
|
+
* hash — the attribute table drives toHash, so it is named here. */
|
|
46
|
+
static subsetAttributes: string[];
|
|
43
47
|
static attributes: import("../../model/attribute.js").AttributeTable;
|
|
44
48
|
readonly number: string | undefined;
|
|
45
49
|
readonly part: string | undefined;
|
|
@@ -75,7 +79,16 @@ export declare abstract class IsoIdentifier extends BaseIdentifier {
|
|
|
75
79
|
/** identifier.rb's base key_value block (the single-document whitelist). */
|
|
76
80
|
export declare const ISO_MAPPINGS: FieldMapping[];
|
|
77
81
|
/** The ISO Publisher component: "ISO/IEC/IEEE". */
|
|
78
|
-
export declare class IsoPublisher {
|
|
82
|
+
export declare class IsoPublisher extends Component {
|
|
83
|
+
static attributes: {
|
|
84
|
+
publisher: {
|
|
85
|
+
type: string;
|
|
86
|
+
};
|
|
87
|
+
copublisher: {
|
|
88
|
+
type: string;
|
|
89
|
+
collection: boolean;
|
|
90
|
+
};
|
|
91
|
+
};
|
|
79
92
|
readonly publisher: string;
|
|
80
93
|
readonly copublisher: string[] | undefined;
|
|
81
94
|
constructor(attrs: {
|
|
@@ -83,6 +96,7 @@ export declare class IsoPublisher {
|
|
|
83
96
|
copublisher?: unknown;
|
|
84
97
|
});
|
|
85
98
|
render(): string;
|
|
99
|
+
toWire(): Record<string, unknown>;
|
|
86
100
|
}
|
|
87
101
|
/** Single documents (everything except supplements, TcDocument, Bundled). */
|
|
88
102
|
export declare abstract class IsoSingleIdentifier extends IsoIdentifier {
|
|
@@ -60,6 +60,10 @@ export class IsoEdition extends Component {
|
|
|
60
60
|
}
|
|
61
61
|
}
|
|
62
62
|
export class IsoIdentifier extends BaseIdentifier {
|
|
63
|
+
/** The typed-stage state joins the match (the published default is
|
|
64
|
+
* stated: ISO 9004 does not match ISO/DIS 9004) but never the wire
|
|
65
|
+
* hash — the attribute table drives toHash, so it is named here. */
|
|
66
|
+
static subsetAttributes = ["typedStageState"];
|
|
63
67
|
static attributes = extendAttributes(BaseIdentifier, {
|
|
64
68
|
number: { type: "string" },
|
|
65
69
|
part: { type: "string" },
|
|
@@ -275,10 +279,15 @@ const stageMapping = () => ({
|
|
|
275
279
|
},
|
|
276
280
|
});
|
|
277
281
|
/** The ISO Publisher component: "ISO/IEC/IEEE". */
|
|
278
|
-
export class IsoPublisher {
|
|
282
|
+
export class IsoPublisher extends Component {
|
|
283
|
+
static attributes = {
|
|
284
|
+
publisher: { type: "string" },
|
|
285
|
+
copublisher: { type: "string", collection: true },
|
|
286
|
+
};
|
|
279
287
|
publisher;
|
|
280
288
|
copublisher;
|
|
281
289
|
constructor(attrs) {
|
|
290
|
+
super();
|
|
282
291
|
this.publisher = attrs.publisher === undefined || attrs.publisher === null ? "ISO" : String(attrs.publisher);
|
|
283
292
|
this.copublisher = Array.isArray(attrs.copublisher) ? attrs.copublisher.map(String) : [];
|
|
284
293
|
}
|
|
@@ -287,6 +296,12 @@ export class IsoPublisher {
|
|
|
287
296
|
return this.publisher;
|
|
288
297
|
return this.publisher + this.copublisher.map((cp) => `/${cp}`).join("");
|
|
289
298
|
}
|
|
299
|
+
toWire() {
|
|
300
|
+
return {
|
|
301
|
+
publisher: this.publisher,
|
|
302
|
+
...(this.copublisher && this.copublisher.length > 0 ? { copublisher: this.copublisher } : {}),
|
|
303
|
+
};
|
|
304
|
+
}
|
|
290
305
|
}
|
|
291
306
|
/** Single documents (everything except supplements, TcDocument, Bundled). */
|
|
292
307
|
export class IsoSingleIdentifier extends IsoIdentifier {
|
package/dist/index.d.ts
CHANGED
|
@@ -7,3 +7,4 @@ export { PendingRegistry } from "./conformance/pending.js";
|
|
|
7
7
|
export { checkCase, runFlavor, runCorpus } from "./conformance/runner.js";
|
|
8
8
|
export { corpusModeImplementation, CorpusBackedIdentifier } from "./implementations/corpus-mode.js";
|
|
9
9
|
export { grammarImplementation } from "./flavors/index.js";
|
|
10
|
+
export { subsetMatch, valueMatch, exactMatch } from "./model/subset-match.js";
|
package/dist/index.js
CHANGED
|
@@ -7,3 +7,4 @@ export { corpusModeImplementation, CorpusBackedIdentifier } from "./implementati
|
|
|
7
7
|
// Root re-export so consumers needn't deep-import flavor modules
|
|
8
8
|
// (pubid/pubid-ts#63 - the estate serving codec).
|
|
9
9
|
export { grammarImplementation } from "./flavors/index.js";
|
|
10
|
+
export { subsetMatch, valueMatch, exactMatch } from "./model/subset-match.js";
|
|
@@ -121,7 +121,8 @@ export function subsetMatch(reference, candidate) {
|
|
|
121
121
|
? ALL_PARTS_ATTRIBUTES
|
|
122
122
|
: []),
|
|
123
123
|
]);
|
|
124
|
-
|
|
124
|
+
const names = [...Object.keys(ctor.attributes), ...(ctor.subsetAttributes ?? [])];
|
|
125
|
+
return names.every((name) => {
|
|
125
126
|
if (ignored.has(name))
|
|
126
127
|
return true;
|
|
127
128
|
const mine = reference[name];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pubid/pubid",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.29",
|
|
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",
|