@pubid/pubid 0.1.4 → 0.1.6
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/README.md +22 -6
- package/artifact/corpus.json.gz +0 -0
- package/dist/conformance/implementation.d.ts +3 -0
- package/dist/flavors/bipm/index.js +39 -0
- package/dist/flavors/gb/index.d.ts +8 -1
- package/dist/flavors/gb/index.js +55 -7
- package/dist/flavors/iec/index.js +80 -0
- package/dist/flavors/ieee/grammar.js +77 -6
- package/dist/flavors/ieee/index.js +76 -4
- package/dist/flavors/ieee/model.d.ts +2 -0
- package/dist/flavors/ieee/model.js +101 -12
- package/dist/flavors/ieee/update_codes.js +10 -4
- package/dist/flavors/index.js +27 -0
- package/dist/flavors/jcgm/index.js +61 -0
- package/dist/flavors/nist/grammar.js +9 -2
- package/dist/flavors/nist/index.js +8 -4
- package/dist/flavors/nist/model.js +10 -3
- package/dist/flavors/oiml/grammar.js +29 -3
- package/dist/flavors/oiml/implementation.js +46 -1
- package/dist/flavors/oiml/model.d.ts +19 -0
- package/dist/flavors/oiml/model.js +133 -3
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/model/identifier.d.ts +1 -0
- package/dist/model/identifier.js +1 -1
- package/dist/urn/parsers.d.ts +5 -0
- package/dist/urn/parsers.js +566 -0
- package/dist/urn/types.d.ts +12 -0
- package/dist/urn/types.js +8 -0
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ParseFailed } from "../../grammar/engine.js";
|
|
2
|
-
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
2
|
+
import { BaseIdentifier, registerType, resolveType } from "../../model/identifier.js";
|
|
3
3
|
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
4
4
|
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
5
5
|
const KIND_BY_TYPE = {
|
|
@@ -13,6 +13,7 @@ const KIND_BY_TYPE = {
|
|
|
13
13
|
};
|
|
14
14
|
const TYPE_STRINGS = {
|
|
15
15
|
"basic-publication": "B",
|
|
16
|
+
"certification-system": "CS",
|
|
16
17
|
document: "D",
|
|
17
18
|
"expert-report": "E",
|
|
18
19
|
guide: "G",
|
|
@@ -108,6 +109,29 @@ class OimlSingle extends OimlBase {
|
|
|
108
109
|
return result;
|
|
109
110
|
}
|
|
110
111
|
}
|
|
112
|
+
/** ---- OIML-CS certification-system documents ---- */
|
|
113
|
+
const CS_ATTRS = {
|
|
114
|
+
...SINGLE_ATTRS,
|
|
115
|
+
family: { type: "string" },
|
|
116
|
+
amendment: { type: "string" },
|
|
117
|
+
space_separator: { type: "boolean", default: false },
|
|
118
|
+
};
|
|
119
|
+
const CS_MAPPINGS = keyValue(...Object.keys(CS_ATTRS).map((name) => ({ wire: name, to: name })));
|
|
120
|
+
// "OIML-CS PD-05 Edition 6 (Amendment 1)": the number keeps its printed
|
|
121
|
+
// zero padding; the print states an edition instead of a year.
|
|
122
|
+
class OimlCertificationSystem extends OimlSingle {
|
|
123
|
+
static polymorphicName = "pubid:oiml:certification-system";
|
|
124
|
+
static attributes = extendAttributes(BaseIdentifier, CS_ATTRS);
|
|
125
|
+
static mappings = CS_MAPPINGS;
|
|
126
|
+
render() {
|
|
127
|
+
let result = `${this.publisher}-CS ${this.family}` +
|
|
128
|
+
`${this.space_separator ? " " : "-"}${this.number} Edition ${this.edition}`;
|
|
129
|
+
if (this.amendment)
|
|
130
|
+
result += ` (Amendment ${this.amendment})`;
|
|
131
|
+
return result;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
registerType(OimlCertificationSystem);
|
|
111
135
|
function oimlSingleClass(kind) {
|
|
112
136
|
const isBulletin = kind === "bulletin";
|
|
113
137
|
class OimlSingleIdentifier extends OimlSingle {
|
|
@@ -146,12 +170,13 @@ const SUPP_ATTRS = {
|
|
|
146
170
|
parsed_format: { type: "string", default: "short" },
|
|
147
171
|
base: { type: OimlSingle },
|
|
148
172
|
supp_year: { type: "string" },
|
|
173
|
+
number: { type: "string" },
|
|
149
174
|
trailing: { type: "boolean", default: false },
|
|
150
175
|
joined: { type: "boolean", default: false },
|
|
151
176
|
letter: { type: "string" },
|
|
152
177
|
year_on_base: { type: "boolean", default: false },
|
|
153
178
|
};
|
|
154
|
-
const SUPP_MAPPINGS = keyValue({ wire: "language", to: "language" }, { wire: "parsed_format", to: "parsed_format" }, { wire: "base", to: "base" }, { wire: "year", to: "supp_year" }, { wire: "trailing", to: "trailing" }, { wire: "joined", to: "joined" }, { wire: "letter", to: "letter" }, { wire: "year_on_base", to: "year_on_base" });
|
|
179
|
+
const SUPP_MAPPINGS = keyValue({ wire: "language", to: "language" }, { wire: "parsed_format", to: "parsed_format" }, { wire: "base", to: "base" }, { wire: "year", to: "supp_year" }, { wire: "number", to: "number" }, { wire: "trailing", to: "trailing" }, { wire: "joined", to: "joined" }, { wire: "letter", to: "letter" }, { wire: "year_on_base", to: "year_on_base" });
|
|
155
180
|
/** ---- supplements (Amendment / Errata) and Annex ---- */
|
|
156
181
|
class OimlSupplement extends OimlBase {
|
|
157
182
|
supplementType() {
|
|
@@ -178,6 +203,8 @@ class OimlSupplement extends OimlBase {
|
|
|
178
203
|
}
|
|
179
204
|
if (this.trailing) {
|
|
180
205
|
let result = `${stripLanguage(this.base.render())} ${this.supplementType()}`;
|
|
206
|
+
if (this.number)
|
|
207
|
+
result += ` ${this.number}`;
|
|
181
208
|
if (this.language)
|
|
182
209
|
result += ` (${this.language})`;
|
|
183
210
|
return result;
|
|
@@ -247,6 +274,7 @@ for (const kind of [
|
|
|
247
274
|
]) {
|
|
248
275
|
KIND_CLASSES[kind] = oimlSingleClass(kind);
|
|
249
276
|
}
|
|
277
|
+
KIND_CLASSES["certification-system"] = OimlCertificationSystem;
|
|
250
278
|
KIND_CLASSES["amendment"] = oimlSupplementClass("amendment");
|
|
251
279
|
KIND_CLASSES["errata"] = oimlSupplementClass("errata");
|
|
252
280
|
KIND_CLASSES["annex"] = oimlSupplementClass("annex");
|
|
@@ -270,6 +298,13 @@ class OimlUrnGenerator extends BaseUrnGenerator {
|
|
|
270
298
|
parts.push(id.language.toLowerCase());
|
|
271
299
|
return parts.join(":");
|
|
272
300
|
}
|
|
301
|
+
// Certification-system documents: the family-number pair is the
|
|
302
|
+
// document identity ("cs:pd-05"); the printed edition and trailing
|
|
303
|
+
// amendment are print states, not URN segments.
|
|
304
|
+
if (kind === "certification-system") {
|
|
305
|
+
const cs = id;
|
|
306
|
+
return ["urn", "oiml", "cs", `${(cs.family ?? "").toLowerCase()}-${cs.number ?? ""}`].join(":");
|
|
307
|
+
}
|
|
273
308
|
const isSupp = kind === "amendment" || kind === "errata" || kind === "annex";
|
|
274
309
|
const single = (isSupp ? id.base : id);
|
|
275
310
|
const parts = ["urn", "oiml"];
|
|
@@ -280,8 +315,12 @@ class OimlUrnGenerator extends BaseUrnGenerator {
|
|
|
280
315
|
const code = single.composedCode();
|
|
281
316
|
if (code)
|
|
282
317
|
parts.push(code);
|
|
318
|
+
// The trailing-word form keeps the publication year on the base
|
|
319
|
+
// ("R 138:2009 Amendment 1"); the supplement itself carries only the
|
|
320
|
+
// ordinal.
|
|
283
321
|
const year = id.year ??
|
|
284
|
-
id.supp_year
|
|
322
|
+
id.supp_year ??
|
|
323
|
+
(isSupp ? single.year : undefined);
|
|
285
324
|
if (year)
|
|
286
325
|
parts.push(year);
|
|
287
326
|
const stage = id.stage;
|
|
@@ -292,6 +331,12 @@ class OimlUrnGenerator extends BaseUrnGenerator {
|
|
|
292
331
|
parts.push(iteration);
|
|
293
332
|
if (id.language)
|
|
294
333
|
parts.push(id.language.toLowerCase());
|
|
334
|
+
// Ruby's supplement branch appends the ordinal after the language.
|
|
335
|
+
if (isSupp) {
|
|
336
|
+
const ordinal = id.number;
|
|
337
|
+
if (ordinal)
|
|
338
|
+
parts.push(ordinal);
|
|
339
|
+
}
|
|
295
340
|
return parts.join(":");
|
|
296
341
|
}
|
|
297
342
|
}
|
|
@@ -299,15 +344,97 @@ for (const klass of Object.values(KIND_CLASSES)) {
|
|
|
299
344
|
klass.urnGenerator = OimlUrnGenerator;
|
|
300
345
|
}
|
|
301
346
|
/** ---- builder (lib/pubid/oiml/builder.rb) ---- */
|
|
347
|
+
// OIML co-publishes some documents jointly with another SDO (ISO so
|
|
348
|
+
// far); the printed reference carries both identifiers joined by "|":
|
|
349
|
+
// "ISO 4064-1:2024|OIML R 49-1:2024". The URN is the OIML side's.
|
|
350
|
+
export class OimlDualPublished extends OimlBase {
|
|
351
|
+
static polymorphicName = "pubid:oiml:dual-published";
|
|
352
|
+
static get attributes() {
|
|
353
|
+
return extendAttributes(OimlBase, {
|
|
354
|
+
// "string" keeps objects passing through the scalar coercion
|
|
355
|
+
// untouched (the ieee AdoptedStandard precedent for cross-flavor
|
|
356
|
+
// members); the constructor coerces bare hashes via the registry.
|
|
357
|
+
first: { type: "string" },
|
|
358
|
+
second: { type: "string" },
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
static get mappings() {
|
|
362
|
+
return [
|
|
363
|
+
{ wire: "first", to: "first" },
|
|
364
|
+
{ wire: "second", to: "second" },
|
|
365
|
+
];
|
|
366
|
+
}
|
|
367
|
+
constructor(attrs = {}) {
|
|
368
|
+
super(attrs);
|
|
369
|
+
// The members are cross-flavor (the co-publisher's side arrives as a
|
|
370
|
+
// bare hash with _type); coerce through the registry - the abstract
|
|
371
|
+
// BaseIdentifier attribute type cannot dispatch polymorphically.
|
|
372
|
+
const coerceMember = (v) => {
|
|
373
|
+
if (v instanceof BaseIdentifier)
|
|
374
|
+
return v;
|
|
375
|
+
if (typeof v === "object" && v !== null && "_type" in v) {
|
|
376
|
+
const klass = resolveType(v["_type"]);
|
|
377
|
+
if (klass !== undefined) {
|
|
378
|
+
return klass.fromHash(v);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return undefined;
|
|
382
|
+
};
|
|
383
|
+
const self = this;
|
|
384
|
+
const f = coerceMember(self["first"]);
|
|
385
|
+
const s = coerceMember(self["second"]);
|
|
386
|
+
if (f !== undefined)
|
|
387
|
+
self["first"] = f;
|
|
388
|
+
if (s !== undefined)
|
|
389
|
+
self["second"] = s;
|
|
390
|
+
}
|
|
391
|
+
render() {
|
|
392
|
+
return `${this.first.toHuman()}|${this.second.toHuman()}`;
|
|
393
|
+
}
|
|
394
|
+
toUrn() {
|
|
395
|
+
// The URN is the OIML side's, whichever position it prints in.
|
|
396
|
+
const oimlSide = this.second instanceof OimlBase ? this.second : this.first;
|
|
397
|
+
return oimlSide.toUrn();
|
|
398
|
+
}
|
|
399
|
+
root() {
|
|
400
|
+
return this.second instanceof OimlBase ? this.second : this.first;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
registerType(OimlDualPublished);
|
|
302
404
|
export function buildOimlIdentifier(tree) {
|
|
303
405
|
if (!isObj(tree))
|
|
304
406
|
throw new ParseFailed("OIML: unexpected parse tree", 0);
|
|
407
|
+
if (tree["cs_series"] !== undefined)
|
|
408
|
+
return buildCs(tree);
|
|
305
409
|
if (tree["amd_marker"] !== undefined)
|
|
306
410
|
return buildShortAmendment(tree);
|
|
307
411
|
if (tree["base"] !== undefined)
|
|
308
412
|
return buildSupplement(tree);
|
|
309
413
|
return buildBaseDocument(tree);
|
|
310
414
|
}
|
|
415
|
+
// OIML-CS documents: family (PD/OD/CID), zero-padded number, the
|
|
416
|
+
// printed "Edition N", and an optional parenthesized trailing
|
|
417
|
+
// amendment. The family-number separator is a spelling flag.
|
|
418
|
+
function buildCs(tree) {
|
|
419
|
+
const attrs = {
|
|
420
|
+
publisher: str(tree["publisher"]) ?? "OIML",
|
|
421
|
+
parsed_format: "short",
|
|
422
|
+
};
|
|
423
|
+
const family = str(tree["cs_family"]);
|
|
424
|
+
if (family !== undefined)
|
|
425
|
+
attrs["family"] = family;
|
|
426
|
+
const number = str(tree["number"]);
|
|
427
|
+
if (number !== undefined)
|
|
428
|
+
attrs["number"] = number;
|
|
429
|
+
const edition = str(tree["edition"]);
|
|
430
|
+
if (edition !== undefined)
|
|
431
|
+
attrs["edition"] = edition;
|
|
432
|
+
const amendment = str(tree["cs_amendment"]);
|
|
433
|
+
if (amendment !== undefined)
|
|
434
|
+
attrs["amendment"] = amendment;
|
|
435
|
+
attrs["space_separator"] = tree["cs_separator"] === " ";
|
|
436
|
+
return new KIND_CLASSES["certification-system"](attrs);
|
|
437
|
+
}
|
|
311
438
|
function buildShortAmendment(tree) {
|
|
312
439
|
const baseCode = isObj(tree["base_code"]) ? tree["base_code"] : undefined;
|
|
313
440
|
const base = buildBaseDocument({
|
|
@@ -359,6 +486,9 @@ function buildSupplement(tree) {
|
|
|
359
486
|
const language = extractLanguage(tree["language"]);
|
|
360
487
|
if (language !== undefined)
|
|
361
488
|
attrs["language"] = language;
|
|
489
|
+
const ordinal = str(tree["number"]);
|
|
490
|
+
if (ordinal !== undefined)
|
|
491
|
+
attrs["number"] = ordinal;
|
|
362
492
|
if (marker !== undefined)
|
|
363
493
|
attrs["trailing"] = true;
|
|
364
494
|
if (plusMarker !== undefined)
|
package/dist/index.d.ts
CHANGED
|
@@ -6,3 +6,4 @@ export type { FlavorImplementation, Identifier, ImplementationRegistry } from ".
|
|
|
6
6
|
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
|
+
export { grammarImplementation } from "./flavors/index.js";
|
package/dist/index.js
CHANGED
|
@@ -4,3 +4,6 @@ export { buildArtifact, loadBundledCorpus, parseArtifact, } from "./corpus/artif
|
|
|
4
4
|
export { PendingRegistry } from "./conformance/pending.js";
|
|
5
5
|
export { checkCase, runFlavor, runCorpus } from "./conformance/runner.js";
|
|
6
6
|
export { corpusModeImplementation, CorpusBackedIdentifier } from "./implementations/corpus-mode.js";
|
|
7
|
+
// Root re-export so consumers needn't deep-import flavor modules
|
|
8
|
+
// (pubid/pubid-ts#63 - the estate serving codec).
|
|
9
|
+
export { grammarImplementation } from "./flavors/index.js";
|
|
@@ -39,6 +39,7 @@ export type UrnGeneratorCtor = new (identifier: BaseIdentifier) => {
|
|
|
39
39
|
};
|
|
40
40
|
/** Register a concrete identifier class under its polymorphic _type (the *_TYPE_MAP role). */
|
|
41
41
|
export declare function registerType(klass: IdentifierStatic): void;
|
|
42
|
+
export declare function resolveType(type: string): IdentifierStatic | undefined;
|
|
42
43
|
export declare abstract class BaseIdentifier {
|
|
43
44
|
static polymorphicName: string;
|
|
44
45
|
/** The human renderer body — the one method every flavor writes. */
|
package/dist/model/identifier.js
CHANGED
|
@@ -25,7 +25,7 @@ const TYPE_REGISTRY = new Map();
|
|
|
25
25
|
export function registerType(klass) {
|
|
26
26
|
TYPE_REGISTRY.set(klass.polymorphicName, klass);
|
|
27
27
|
}
|
|
28
|
-
function resolveType(type) {
|
|
28
|
+
export function resolveType(type) {
|
|
29
29
|
return TYPE_REGISTRY.get(type);
|
|
30
30
|
}
|
|
31
31
|
function isScalarType(t) {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Identifier } from "../conformance/implementation.js";
|
|
2
|
+
import { type UrnParserDef } from "./types.js";
|
|
3
|
+
export declare const URN_PARSERS: Record<string, UrnParserDef>;
|
|
4
|
+
export declare function lookupUrnParser(flavor: string): UrnParserDef | undefined;
|
|
5
|
+
export declare function parseUrnFor(def: UrnParserDef, urn: string, parse: (text: string) => Identifier): Identifier;
|