@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.
- package/artifact/corpus.json.gz +0 -0
- package/dist/conformance/cli.js +5 -1
- package/dist/flavors/amca/grammar.d.ts +4 -0
- package/dist/flavors/amca/grammar.js +87 -0
- package/dist/flavors/amca/index.d.ts +4 -0
- package/dist/flavors/amca/index.js +76 -0
- package/dist/flavors/amca/model.d.ts +29 -0
- package/dist/flavors/amca/model.js +146 -0
- package/dist/flavors/ansi/index.d.ts +24 -0
- package/dist/flavors/ansi/index.js +147 -0
- package/dist/flavors/api/grammar.d.ts +4 -0
- package/dist/flavors/api/grammar.js +79 -0
- package/dist/flavors/api/index.d.ts +4 -0
- package/dist/flavors/api/index.js +71 -0
- package/dist/flavors/api/model.d.ts +27 -0
- package/dist/flavors/api/model.js +114 -0
- package/dist/flavors/ashrae/grammar.d.ts +2 -0
- package/dist/flavors/ashrae/grammar.js +667 -0
- package/dist/flavors/ashrae/index.d.ts +4 -0
- package/dist/flavors/ashrae/index.js +306 -0
- package/dist/flavors/ashrae/model.d.ts +87 -0
- package/dist/flavors/ashrae/model.js +335 -0
- package/dist/flavors/ashrae/preprocessor.d.ts +7 -0
- package/dist/flavors/ashrae/preprocessor.js +44 -0
- package/dist/flavors/asme/grammar.d.ts +2 -0
- package/dist/flavors/asme/grammar.js +200 -0
- package/dist/flavors/asme/index.d.ts +4 -0
- package/dist/flavors/asme/index.js +138 -0
- package/dist/flavors/asme/model.d.ts +34 -0
- package/dist/flavors/asme/model.js +123 -0
- package/dist/flavors/astm/grammar.d.ts +2 -0
- package/dist/flavors/astm/grammar.js +110 -0
- package/dist/flavors/astm/index.d.ts +2 -0
- package/dist/flavors/astm/index.js +127 -0
- package/dist/flavors/astm/model.d.ts +42 -0
- package/dist/flavors/astm/model.js +263 -0
- package/dist/flavors/bipm/index.d.ts +30 -0
- package/dist/flavors/bipm/index.js +434 -0
- package/dist/flavors/bsi/grammar.d.ts +4 -0
- package/dist/flavors/bsi/grammar.js +535 -0
- package/dist/flavors/bsi/index.d.ts +4 -0
- package/dist/flavors/bsi/index.js +941 -0
- package/dist/flavors/bsi/model.d.ts +127 -0
- package/dist/flavors/bsi/model.js +863 -0
- package/dist/flavors/calconnect/index.d.ts +21 -0
- package/dist/flavors/calconnect/index.js +113 -0
- package/dist/flavors/cen_cenelec/grammar.d.ts +4 -0
- package/dist/flavors/cen_cenelec/grammar.js +107 -0
- package/dist/flavors/cen_cenelec/index.d.ts +5 -0
- package/dist/flavors/cen_cenelec/index.js +263 -0
- package/dist/flavors/cen_cenelec/model.d.ts +45 -0
- package/dist/flavors/cen_cenelec/model.js +490 -0
- package/dist/flavors/cie/grammar.d.ts +5 -0
- package/dist/flavors/cie/grammar.js +127 -0
- package/dist/flavors/cie/index.d.ts +2 -0
- package/dist/flavors/cie/index.js +311 -0
- package/dist/flavors/cie/model.d.ts +122 -0
- package/dist/flavors/cie/model.js +464 -0
- package/dist/flavors/csa/grammar.d.ts +6 -0
- package/dist/flavors/csa/grammar.js +239 -0
- package/dist/flavors/csa/index.d.ts +2 -0
- package/dist/flavors/csa/index.js +634 -0
- package/dist/flavors/csa/model.d.ts +33 -0
- package/dist/flavors/csa/model.js +505 -0
- package/dist/flavors/doi/index.d.ts +13 -0
- package/dist/flavors/doi/index.js +65 -0
- package/dist/flavors/easc/index.d.ts +4 -0
- package/dist/flavors/easc/index.js +107 -0
- package/dist/flavors/ecma/index.d.ts +4 -0
- package/dist/flavors/ecma/index.js +117 -0
- package/dist/flavors/etsi/index.d.ts +14 -0
- package/dist/flavors/etsi/index.js +307 -0
- package/dist/flavors/evs/grammar.d.ts +2 -0
- package/dist/flavors/evs/grammar.js +22 -0
- package/dist/flavors/evs/index.d.ts +2 -0
- package/dist/flavors/evs/index.js +24 -0
- package/dist/flavors/evs/model.d.ts +19 -0
- package/dist/flavors/evs/model.js +36 -0
- package/dist/flavors/gb/index.d.ts +24 -0
- package/dist/flavors/gb/index.js +111 -0
- package/dist/flavors/gost/grammar.d.ts +2 -0
- package/dist/flavors/gost/grammar.js +46 -0
- package/dist/flavors/gost/index.d.ts +2 -0
- package/dist/flavors/gost/index.js +165 -0
- package/dist/flavors/gost/model.d.ts +61 -0
- package/dist/flavors/gost/model.js +147 -0
- package/dist/flavors/gost/prefix_routes.d.ts +15 -0
- package/dist/flavors/gost/prefix_routes.js +192 -0
- package/dist/flavors/iala/index.d.ts +32 -0
- package/dist/flavors/iala/index.js +300 -0
- package/dist/flavors/iana/index.d.ts +19 -0
- package/dist/flavors/iana/index.js +71 -0
- package/dist/flavors/idf/grammar.d.ts +2 -0
- package/dist/flavors/idf/grammar.js +71 -0
- package/dist/flavors/idf/index.d.ts +2 -0
- package/dist/flavors/idf/index.js +100 -0
- package/dist/flavors/idf/model.d.ts +54 -0
- package/dist/flavors/idf/model.js +359 -0
- package/dist/flavors/iec/grammar.d.ts +3 -0
- package/dist/flavors/iec/grammar.js +187 -0
- package/dist/flavors/iec/index.d.ts +4 -0
- package/dist/flavors/iec/index.js +507 -0
- package/dist/flavors/iec/model.d.ts +54 -0
- package/dist/flavors/iec/model.js +437 -0
- package/dist/flavors/ieee/grammar.d.ts +2 -0
- package/dist/flavors/ieee/grammar.js +626 -0
- package/dist/flavors/ieee/index.d.ts +3 -0
- package/dist/flavors/ieee/index.js +1186 -0
- package/dist/flavors/ieee/model.d.ts +142 -0
- package/dist/flavors/ieee/model.js +1148 -0
- package/dist/flavors/ieee/preprocessor.d.ts +8 -0
- package/dist/flavors/ieee/preprocessor.js +410 -0
- package/dist/flavors/ieee/update_codes.d.ts +8 -0
- package/dist/flavors/ieee/update_codes.js +191 -0
- package/dist/flavors/ietf/index.d.ts +30 -0
- package/dist/flavors/ietf/index.js +151 -0
- package/dist/flavors/iho/index.d.ts +4 -0
- package/dist/flavors/iho/index.js +126 -0
- package/dist/flavors/index.d.ts +9 -0
- package/dist/flavors/index.js +136 -0
- package/dist/flavors/isbn/index.d.ts +13 -0
- package/dist/flavors/isbn/index.js +97 -0
- package/dist/flavors/iso/grammar.d.ts +2 -0
- package/dist/flavors/iso/grammar.js +207 -0
- package/dist/flavors/iso/index.d.ts +2 -0
- package/dist/flavors/iso/index.js +343 -0
- package/dist/flavors/iso/model.d.ts +159 -0
- package/dist/flavors/iso/model.js +802 -0
- package/dist/flavors/iso/stages.generated.d.ts +13 -0
- package/dist/flavors/iso/stages.generated.js +391 -0
- package/dist/flavors/itu/grammar.d.ts +4 -0
- package/dist/flavors/itu/grammar.js +205 -0
- package/dist/flavors/itu/index.d.ts +2 -0
- package/dist/flavors/itu/index.js +224 -0
- package/dist/flavors/itu/model.d.ts +184 -0
- package/dist/flavors/itu/model.js +599 -0
- package/dist/flavors/jcgm/index.d.ts +7 -0
- package/dist/flavors/jcgm/index.js +300 -0
- package/dist/flavors/jis/index.d.ts +4 -0
- package/dist/flavors/jis/index.js +267 -0
- package/dist/flavors/nist/grammar.d.ts +2 -0
- package/dist/flavors/nist/grammar.js +287 -0
- package/dist/flavors/nist/index.d.ts +2 -0
- package/dist/flavors/nist/index.js +1244 -0
- package/dist/flavors/nist/model.d.ts +155 -0
- package/dist/flavors/nist/model.js +823 -0
- package/dist/flavors/nist/preprocessor.d.ts +11 -0
- package/dist/flavors/nist/preprocessor.js +281 -0
- package/dist/flavors/oasis/index.d.ts +23 -0
- package/dist/flavors/oasis/index.js +110 -0
- package/dist/flavors/ogc/index.d.ts +20 -0
- package/dist/flavors/ogc/index.js +75 -0
- package/dist/flavors/oiml/grammar.d.ts +2 -0
- package/dist/flavors/oiml/grammar.js +180 -0
- package/dist/flavors/oiml/implementation.d.ts +9 -0
- package/dist/flavors/oiml/implementation.js +16 -0
- package/dist/flavors/oiml/model.d.ts +4 -0
- package/dist/flavors/oiml/model.js +462 -0
- package/dist/flavors/omg/index.d.ts +14 -0
- package/dist/flavors/omg/index.js +73 -0
- package/dist/flavors/plateau/index.d.ts +4 -0
- package/dist/flavors/plateau/index.js +97 -0
- package/dist/flavors/tgpp/index.d.ts +4 -0
- package/dist/flavors/tgpp/index.js +122 -0
- package/dist/flavors/un/index.d.ts +13 -0
- package/dist/flavors/un/index.js +90 -0
- package/dist/flavors/w3c/index.d.ts +14 -0
- package/dist/flavors/w3c/index.js +148 -0
- package/dist/flavors/xsf/index.d.ts +18 -0
- package/dist/flavors/xsf/index.js +65 -0
- package/dist/grammar/engine.d.ts +78 -0
- package/dist/grammar/engine.js +351 -0
- package/dist/model/attribute.d.ts +54 -0
- package/dist/model/attribute.js +53 -0
- package/dist/model/builder.d.ts +39 -0
- package/dist/model/builder.js +124 -0
- package/dist/model/component.d.ts +70 -0
- package/dist/model/component.js +170 -0
- package/dist/model/identifier.d.ts +83 -0
- package/dist/model/identifier.js +270 -0
- package/dist/model/urn-generator.d.ts +27 -0
- package/dist/model/urn-generator.js +91 -0
- package/package.json +1 -1
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Grammar } from "../../grammar/engine.js";
|
|
2
|
+
import type { FlavorImplementation } from "../../conformance/implementation.js";
|
|
3
|
+
import { BaseIdentifier } from "../../model/identifier.js";
|
|
4
|
+
export declare const omgGrammar: Grammar;
|
|
5
|
+
export declare class OmgIdentifier extends BaseIdentifier {
|
|
6
|
+
static polymorphicName: string;
|
|
7
|
+
static attributes: import("../../model/attribute.js").AttributeTable;
|
|
8
|
+
static mappings: import("../../model/attribute.js").FieldMapping[];
|
|
9
|
+
readonly acronym: string;
|
|
10
|
+
readonly version: string | undefined;
|
|
11
|
+
readonly part: string | undefined;
|
|
12
|
+
render(): string;
|
|
13
|
+
}
|
|
14
|
+
export declare function omgGrammarImplementation(): FlavorImplementation;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { match, str } from "../../grammar/engine.js";
|
|
2
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
3
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
4
|
+
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
5
|
+
import { BaseBuilder } from "../../model/builder.js";
|
|
6
|
+
/**
|
|
7
|
+
* 1:1 port of lib/pubid/omg/ on the unified model. The Ruby flavor has
|
|
8
|
+
* no urn_generator, so toUrn() resolves to the base template: only
|
|
9
|
+
* `part` hits a slot, deriving "urn:omg:-PDF" / bare "urn:omg".
|
|
10
|
+
*/
|
|
11
|
+
function buildRules() {
|
|
12
|
+
const rules = {};
|
|
13
|
+
const rule = (name, build) => {
|
|
14
|
+
rules[name] = build();
|
|
15
|
+
};
|
|
16
|
+
const space = str(" ");
|
|
17
|
+
const acronymChar = match("[A-Za-z0-9+]");
|
|
18
|
+
const wordBoundary = match("[A-Za-z0-9]").absent();
|
|
19
|
+
const beta = str(" beta").then(wordBoundary, space.then(match("[0-9]").repeat(1, Infinity), wordBoundary).maybe());
|
|
20
|
+
const partSeparator = space.or(str("/"));
|
|
21
|
+
rule("acronym", () => match("[A-Za-z]")
|
|
22
|
+
.then(acronymChar.repeat(0, Infinity), match("[-/]")
|
|
23
|
+
.then(acronymChar.repeat(1, Infinity))
|
|
24
|
+
.repeat(0, Infinity))
|
|
25
|
+
.as("acronym"));
|
|
26
|
+
rule("version", () => match("[0-9]")
|
|
27
|
+
.repeat(1, Infinity)
|
|
28
|
+
.then(str(".").then(match("[0-9]").repeat(1, Infinity)).repeat(0, Infinity), beta.maybe())
|
|
29
|
+
.as("version"));
|
|
30
|
+
rule("part", () => match("[A-Za-z0-9]").repeat(1, Infinity).as("part"));
|
|
31
|
+
rule("identifier", () => str("OMG").then(space, rules["acronym"], space
|
|
32
|
+
.then(rules["version"], partSeparator.then(rules["part"]).maybe())
|
|
33
|
+
.or(space.then(rules["part"]))
|
|
34
|
+
.maybe()));
|
|
35
|
+
rule("root", () => rules["identifier"]);
|
|
36
|
+
return rules;
|
|
37
|
+
}
|
|
38
|
+
export const omgGrammar = { rules: buildRules(), root: "root" };
|
|
39
|
+
export class OmgIdentifier extends BaseIdentifier {
|
|
40
|
+
static polymorphicName = "pubid:omg:specification";
|
|
41
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
42
|
+
acronym: { type: "string" },
|
|
43
|
+
version: { type: "string" },
|
|
44
|
+
part: { type: "string" },
|
|
45
|
+
});
|
|
46
|
+
static mappings = keyValue({ wire: "acronym", to: "acronym" }, { wire: "version", to: "version" }, { wire: "part", to: "part" });
|
|
47
|
+
render() {
|
|
48
|
+
let result = `OMG ${this.acronym}`;
|
|
49
|
+
if (this.version !== undefined)
|
|
50
|
+
result += ` ${this.version}`;
|
|
51
|
+
if (this.part !== undefined)
|
|
52
|
+
result += ` ${this.part}`;
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
registerType(OmgIdentifier);
|
|
57
|
+
class OmgBuilder extends BaseBuilder {
|
|
58
|
+
defaultIdentifierClass() {
|
|
59
|
+
return OmgIdentifier;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
export function omgGrammarImplementation() {
|
|
63
|
+
const builder = new OmgBuilder();
|
|
64
|
+
return {
|
|
65
|
+
parse(input) {
|
|
66
|
+
const tree = parseGrammar(omgGrammar, input);
|
|
67
|
+
if (typeof tree !== "object" || tree === null || Array.isArray(tree)) {
|
|
68
|
+
throw new ParseFailed("OMG: unexpected parse tree", 0);
|
|
69
|
+
}
|
|
70
|
+
return builder.build(tree);
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { match, str } from "../../grammar/engine.js";
|
|
2
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
3
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
4
|
+
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
5
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
6
|
+
const KIND_TYPES = {
|
|
7
|
+
handbook: "pubid:plateau:handbook",
|
|
8
|
+
"technical-report": "pubid:plateau:technical-report",
|
|
9
|
+
};
|
|
10
|
+
function buildRules() {
|
|
11
|
+
const rules = {};
|
|
12
|
+
const rule = (name, build) => {
|
|
13
|
+
rules[name] = build();
|
|
14
|
+
};
|
|
15
|
+
const space = str(" ");
|
|
16
|
+
const digits = match("[0-9]").repeat(1, Infinity);
|
|
17
|
+
rule("doc_type", () => str("Handbook").or(str("Technical Report")).as("type"));
|
|
18
|
+
rule("number", () => str("#").then(digits.as("number")));
|
|
19
|
+
rule("annex", () => str("-").or(str("_")).then(digits.as("annex")));
|
|
20
|
+
rule("edition_part", () => str("第").then(digits.then(str("."), digits).as("edition"), str("版")));
|
|
21
|
+
rule("edition_latin", () => digits.then(str("."), digits).as("edition"));
|
|
22
|
+
rule("edition", () => space.then(rules["edition_part"].or(rules["edition_latin"])));
|
|
23
|
+
rule("annex_supplement", () => space.then(str("Annex")).then(space, match("[A-Z]").as("annex_letter")));
|
|
24
|
+
rule("handbook", () => str("PLATEAU")
|
|
25
|
+
.then(space, rules["doc_type"], space, rules["number"])
|
|
26
|
+
.then(rules["annex"].maybe())
|
|
27
|
+
.then(rules["edition"].maybe()));
|
|
28
|
+
rule("identifier", () => rules["handbook"]
|
|
29
|
+
.then(rules["annex_supplement"])
|
|
30
|
+
.as("base")
|
|
31
|
+
.or(rules["handbook"]));
|
|
32
|
+
rule("root", () => rules["identifier"]);
|
|
33
|
+
return rules;
|
|
34
|
+
}
|
|
35
|
+
export const plateauGrammar = { rules: buildRules(), root: "root" };
|
|
36
|
+
const pad2 = (n) => String(n).padStart(2, "0");
|
|
37
|
+
function plateauClass(kind) {
|
|
38
|
+
const isHandbook = kind === "handbook";
|
|
39
|
+
class PlateauKindIdentifier extends BaseIdentifier {
|
|
40
|
+
static polymorphicName = KIND_TYPES[kind];
|
|
41
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
42
|
+
number: { type: "integer" },
|
|
43
|
+
annex: { type: "integer" },
|
|
44
|
+
edition: { type: "string" },
|
|
45
|
+
});
|
|
46
|
+
static mappings = keyValue({ wire: "number", to: "number" }, { wire: "edition", to: "edition" }, { wire: "annex", to: "annex" });
|
|
47
|
+
render() {
|
|
48
|
+
let result = `PLATEAU ${isHandbook ? "Handbook" : "Technical Report"} #${pad2(this.number)}`;
|
|
49
|
+
if (this.annex !== undefined)
|
|
50
|
+
result += `-${this.annex}`;
|
|
51
|
+
if (isHandbook && this.edition !== undefined)
|
|
52
|
+
result += ` 第${this.edition}版`;
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
class PlateauUrnGenerator extends BaseUrnGenerator {
|
|
57
|
+
generate() {
|
|
58
|
+
const id = this.identifier;
|
|
59
|
+
const parts = ["urn", "plateau", isHandbook ? "handbook" : "tr", pad2(id.number)];
|
|
60
|
+
if (id.annex !== undefined)
|
|
61
|
+
parts.push(pad2(id.annex));
|
|
62
|
+
return parts.join(":");
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
PlateauKindIdentifier.urnGenerator = PlateauUrnGenerator;
|
|
66
|
+
registerType(PlateauKindIdentifier);
|
|
67
|
+
return PlateauKindIdentifier;
|
|
68
|
+
}
|
|
69
|
+
const KIND_CLASSES = {
|
|
70
|
+
handbook: plateauClass("handbook"),
|
|
71
|
+
"technical-report": plateauClass("technical-report"),
|
|
72
|
+
};
|
|
73
|
+
export function plateauGrammarImplementation() {
|
|
74
|
+
return {
|
|
75
|
+
parse(input) {
|
|
76
|
+
const tree = parseGrammar(plateauGrammar, input);
|
|
77
|
+
if (typeof tree !== "object" || tree === null || Array.isArray(tree)) {
|
|
78
|
+
throw new ParseFailed("PLATEAU: unexpected parse tree", 0);
|
|
79
|
+
}
|
|
80
|
+
const data = tree;
|
|
81
|
+
if (data["base"] !== undefined) {
|
|
82
|
+
throw new ParseFailed("PLATEAU: Annex supplements are unsupported upstream", 0);
|
|
83
|
+
}
|
|
84
|
+
const kind = String(data["type"]) === "Handbook" ? "handbook" : "technical-report";
|
|
85
|
+
const attrs = { number: Number(data["number"]) };
|
|
86
|
+
if (data["annex"] !== undefined && data["annex"] !== null) {
|
|
87
|
+
attrs["annex"] = Number(data["annex"]);
|
|
88
|
+
}
|
|
89
|
+
// A legacy Latin TR edition is captured by the shared handbook
|
|
90
|
+
// rule and dropped for Technical Report (Ruby builder parity).
|
|
91
|
+
if (data["edition"] !== undefined && data["edition"] !== null && kind === "handbook") {
|
|
92
|
+
attrs["edition"] = String(data["edition"]);
|
|
93
|
+
}
|
|
94
|
+
return new KIND_CLASSES[kind](attrs);
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { match, str } from "../../grammar/engine.js";
|
|
2
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
3
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
4
|
+
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
5
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
6
|
+
import { BaseBuilder } from "../../model/builder.js";
|
|
7
|
+
const KIND_PREFIXES = {
|
|
8
|
+
"technical-report": "TR",
|
|
9
|
+
"technical-specification": "TS",
|
|
10
|
+
};
|
|
11
|
+
function buildRules() {
|
|
12
|
+
const rules = {};
|
|
13
|
+
const rule = (name, build) => {
|
|
14
|
+
rules[name] = build();
|
|
15
|
+
};
|
|
16
|
+
const digits = match("[0-9]").repeat(1, Infinity);
|
|
17
|
+
const space = str(" ");
|
|
18
|
+
const any = match("[\\s\\S]");
|
|
19
|
+
rule("publisher_prefix", () => str("3GPP").then(space));
|
|
20
|
+
rule("type", () => str("TR").or(str("TS")).as("type"));
|
|
21
|
+
rule("number_core", () => digits.then(str("."), digits).as("number"));
|
|
22
|
+
rule("suffix", () => match("[A-Za-z]").repeat(1, Infinity).as("suffix"));
|
|
23
|
+
rule("part", () => str("-").then(digits.as("part")));
|
|
24
|
+
rule("parts", () => rules["part"].repeat(0, Infinity).as("parts"));
|
|
25
|
+
rule("version_core", () => digits.then(str("."), digits, str("."), digits));
|
|
26
|
+
rule("release", () => rules["version_core"]
|
|
27
|
+
.then(any.absent())
|
|
28
|
+
.absent()
|
|
29
|
+
.then(match("[^/:]").repeat(1, Infinity).as("release")));
|
|
30
|
+
rule("version", () => rules["version_core"].as("version"));
|
|
31
|
+
rule("identifier", () => rules["publisher_prefix"]
|
|
32
|
+
.maybe()
|
|
33
|
+
.then(rules["type"], space, rules["number_core"])
|
|
34
|
+
.then(rules["suffix"].maybe())
|
|
35
|
+
.then(rules["parts"])
|
|
36
|
+
.then(str(":").then(rules["release"]).maybe())
|
|
37
|
+
.then(str("/").then(rules["version"]).maybe()));
|
|
38
|
+
rule("root", () => rules["identifier"]);
|
|
39
|
+
return rules;
|
|
40
|
+
}
|
|
41
|
+
export const tgppGrammar = { rules: buildRules(), root: "root" };
|
|
42
|
+
function tgppClass(kind) {
|
|
43
|
+
const prefix = KIND_PREFIXES[kind];
|
|
44
|
+
class TgppKindIdentifier extends BaseIdentifier {
|
|
45
|
+
static polymorphicName = `pubid:3gpp:${kind}`;
|
|
46
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
47
|
+
number: { type: "string" },
|
|
48
|
+
suffix: { type: "string" },
|
|
49
|
+
parts: { type: "string", collection: true, initializeEmpty: true },
|
|
50
|
+
release: { type: "string" },
|
|
51
|
+
version: { type: "string" },
|
|
52
|
+
});
|
|
53
|
+
static mappings = keyValue({ wire: "number", to: "number" }, { wire: "suffix", to: "suffix" }, { wire: "parts", to: "parts" }, { wire: "release", to: "release" }, { wire: "version", to: "version" });
|
|
54
|
+
code() {
|
|
55
|
+
let result = this.number + (this.suffix ?? "");
|
|
56
|
+
if (this.parts.length > 0)
|
|
57
|
+
result += this.parts.map((p) => `-${p}`).join("");
|
|
58
|
+
return result;
|
|
59
|
+
}
|
|
60
|
+
render() {
|
|
61
|
+
let result = `${prefix} ${this.code()}`;
|
|
62
|
+
if (this.release !== undefined && this.release !== "")
|
|
63
|
+
result += `:${this.release}`;
|
|
64
|
+
if (this.version !== undefined && this.version !== "")
|
|
65
|
+
result += `/${this.version}`;
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
class TgppUrnGenerator extends BaseUrnGenerator {
|
|
70
|
+
generate() {
|
|
71
|
+
const id = this.identifier;
|
|
72
|
+
const tail = [id.release, id.version];
|
|
73
|
+
while (tail.length > 0 && (tail[tail.length - 1] === undefined || tail[tail.length - 1] === "")) {
|
|
74
|
+
tail.pop();
|
|
75
|
+
}
|
|
76
|
+
return ["urn", "3gpp", prefix.toLowerCase(), id.code(), ...tail.map((s) => s ?? "")].join(":");
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
TgppKindIdentifier.urnGenerator = TgppUrnGenerator;
|
|
80
|
+
registerType(TgppKindIdentifier);
|
|
81
|
+
return TgppKindIdentifier;
|
|
82
|
+
}
|
|
83
|
+
const KIND_CLASSES = {
|
|
84
|
+
"technical-report": tgppClass("technical-report"),
|
|
85
|
+
"technical-specification": tgppClass("technical-specification"),
|
|
86
|
+
};
|
|
87
|
+
function isObj(v) {
|
|
88
|
+
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
89
|
+
}
|
|
90
|
+
function extractParts(raw) {
|
|
91
|
+
if (Array.isArray(raw)) {
|
|
92
|
+
return raw.map((p) => (isObj(p) ? String(p["part"]) : String(p)));
|
|
93
|
+
}
|
|
94
|
+
if (isObj(raw) && raw["part"] !== undefined)
|
|
95
|
+
return [String(raw["part"])];
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
class TgppBuilder extends BaseBuilder {
|
|
99
|
+
selectClass(data) {
|
|
100
|
+
return KIND_CLASSES[String(data["type"]) === "TR" ? "technical-report" : "technical-specification"];
|
|
101
|
+
}
|
|
102
|
+
defaultIdentifierClass() {
|
|
103
|
+
return KIND_CLASSES["technical-specification"];
|
|
104
|
+
}
|
|
105
|
+
cast(key, value) {
|
|
106
|
+
if (key === "parts")
|
|
107
|
+
return { parts: extractParts(value) };
|
|
108
|
+
return value;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export function tgppGrammarImplementation() {
|
|
112
|
+
const builder = new TgppBuilder();
|
|
113
|
+
return {
|
|
114
|
+
parse(input) {
|
|
115
|
+
const tree = parseGrammar(tgppGrammar, input);
|
|
116
|
+
if (typeof tree !== "object" || tree === null || Array.isArray(tree)) {
|
|
117
|
+
throw new ParseFailed("3GPP: unexpected parse tree", 0);
|
|
118
|
+
}
|
|
119
|
+
return builder.build(tree);
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Grammar } from "../../grammar/engine.js";
|
|
2
|
+
import type { FlavorImplementation } from "../../conformance/implementation.js";
|
|
3
|
+
import { BaseIdentifier } from "../../model/identifier.js";
|
|
4
|
+
export declare const unGrammar: Grammar;
|
|
5
|
+
export declare class UnIdentifier extends BaseIdentifier {
|
|
6
|
+
static polymorphicName: string;
|
|
7
|
+
static attributes: import("../../model/attribute.js").AttributeTable;
|
|
8
|
+
static mappings: import("../../model/attribute.js").FieldMapping[];
|
|
9
|
+
readonly path: string[];
|
|
10
|
+
readonly number: string;
|
|
11
|
+
render(): string;
|
|
12
|
+
}
|
|
13
|
+
export declare function unGrammarImplementation(): FlavorImplementation;
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { match, str } from "../../grammar/engine.js";
|
|
2
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
3
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
4
|
+
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
5
|
+
import { BaseBuilder } from "../../model/builder.js";
|
|
6
|
+
import { PubidDate } from "../../model/component.js";
|
|
7
|
+
/**
|
|
8
|
+
* 1:1 port of lib/pubid/un/ on the unified model. The builder derives a
|
|
9
|
+
* runtime `date` (a 4-digit path token) exactly like Ruby; un's key_value
|
|
10
|
+
* maps ONLY path/number, so the date never serializes (the mapping
|
|
11
|
+
* whitelist) while the base URN generator still reads it: the year-only
|
|
12
|
+
* render of a degenerate PubidDate yields "urn:un:<number>[:<year>]".
|
|
13
|
+
*/
|
|
14
|
+
function buildRules() {
|
|
15
|
+
const rules = {};
|
|
16
|
+
const rule = (name, build) => {
|
|
17
|
+
rules[name] = build();
|
|
18
|
+
};
|
|
19
|
+
const slash = str("/");
|
|
20
|
+
const token = match("[A-Z0-9.]").repeat(1, Infinity);
|
|
21
|
+
rule("un_prefix", () => str("UN").then(str(" ")).maybe());
|
|
22
|
+
rule("identifier", () => rules["un_prefix"]
|
|
23
|
+
.then(token.as("token"), slash.then(token.as("token")).repeat(1, Infinity)));
|
|
24
|
+
rule("root", () => rules["identifier"]);
|
|
25
|
+
return rules;
|
|
26
|
+
}
|
|
27
|
+
export const unGrammar = { rules: buildRules(), root: "root" };
|
|
28
|
+
export class UnIdentifier extends BaseIdentifier {
|
|
29
|
+
static polymorphicName = "pubid:un:document";
|
|
30
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
31
|
+
path: { type: "string", collection: true, default: [] },
|
|
32
|
+
number: { type: "string" },
|
|
33
|
+
});
|
|
34
|
+
static mappings = keyValue({ wire: "path", to: "path" }, { wire: "number", to: "number" });
|
|
35
|
+
render() {
|
|
36
|
+
return [...this.path, this.number].join("/");
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
registerType(UnIdentifier);
|
|
40
|
+
class UnBuilder extends BaseBuilder {
|
|
41
|
+
defaultIdentifierClass() {
|
|
42
|
+
return UnIdentifier;
|
|
43
|
+
}
|
|
44
|
+
cast(key, value) {
|
|
45
|
+
if (key !== "token")
|
|
46
|
+
return value;
|
|
47
|
+
void value;
|
|
48
|
+
return null; // handled in handleKey below (needs the full token list)
|
|
49
|
+
}
|
|
50
|
+
handleKey(_identifier, key, value) {
|
|
51
|
+
return key === "token";
|
|
52
|
+
}
|
|
53
|
+
build(data) {
|
|
54
|
+
// The parslet tree is a top-level ARRAY of {token: …} hashes (the
|
|
55
|
+
// repeat-of-captures shape); extract directly — merging would
|
|
56
|
+
// collide the repeated key (Ruby's builder iterates the array too).
|
|
57
|
+
const tokens = this.extractTokens(Array.isArray(data) ? data : data["token"]);
|
|
58
|
+
if (tokens.length === 0)
|
|
59
|
+
throw new ParseFailed("UN identifier has no tokens", 0);
|
|
60
|
+
const path = tokens.slice(0, -1);
|
|
61
|
+
// Only a PATH token is the date year ("TRADE/WP.4/1068" has none —
|
|
62
|
+
// a 4-digit NUMBER is not a year).
|
|
63
|
+
const yearToken = [...path].reverse().find((t) => /^\d{4}$/.test(t));
|
|
64
|
+
const attrs = {
|
|
65
|
+
number: tokens[tokens.length - 1],
|
|
66
|
+
path,
|
|
67
|
+
};
|
|
68
|
+
if (yearToken)
|
|
69
|
+
attrs["date"] = new PubidDate({ year: yearToken });
|
|
70
|
+
return new UnIdentifier(attrs);
|
|
71
|
+
}
|
|
72
|
+
extractTokens(raw) {
|
|
73
|
+
const toStrings = (v) => Array.isArray(v)
|
|
74
|
+
? v.flatMap(toStrings)
|
|
75
|
+
: typeof v === "object" && v !== null
|
|
76
|
+
? toStrings(v["token"])
|
|
77
|
+
: v === undefined || v === null
|
|
78
|
+
? []
|
|
79
|
+
: [String(v)];
|
|
80
|
+
return toStrings(raw);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
export function unGrammarImplementation() {
|
|
84
|
+
const builder = new UnBuilder();
|
|
85
|
+
return {
|
|
86
|
+
parse(input) {
|
|
87
|
+
return builder.build(parseGrammar(unGrammar, input));
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Grammar } from "../../grammar/engine.js";
|
|
2
|
+
import type { FlavorImplementation } from "../../conformance/implementation.js";
|
|
3
|
+
/**
|
|
4
|
+
* 1:1 port of lib/pubid/w3c/ on the unified model. "W3C [TYPE-]slug[-date]";
|
|
5
|
+
* the grammar splits only the maturity token, the builder applies the
|
|
6
|
+
* fixed-width trailing-date split (8/6/4 digits — slugs like "url-1" or
|
|
7
|
+
* "DSIG-label-971024.html" never mis-split). Eleven kinds, one per W3C
|
|
8
|
+
* maturity level; `date` is a plain string in Ruby (never a PubidDate).
|
|
9
|
+
*/
|
|
10
|
+
declare const W3C_KINDS: readonly ["standard", "note", "draft-note", "working-draft", "candidate-recommendation", "candidate-recommendation-draft", "recommendation", "proposed-recommendation", "proposed-edited-recommendation", "superseded-recommendation", "obsolete-recommendation"];
|
|
11
|
+
export type W3cKind = (typeof W3C_KINDS)[number];
|
|
12
|
+
export declare const w3cGrammar: Grammar;
|
|
13
|
+
export declare function w3cGrammarImplementation(): FlavorImplementation;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { match, str } from "../../grammar/engine.js";
|
|
2
|
+
import { ParseFailed, parseGrammar } from "../../grammar/engine.js";
|
|
3
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
4
|
+
import { extendAttributes, keyValue } from "../../model/attribute.js";
|
|
5
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
6
|
+
import { BaseBuilder } from "../../model/builder.js";
|
|
7
|
+
/**
|
|
8
|
+
* 1:1 port of lib/pubid/w3c/ on the unified model. "W3C [TYPE-]slug[-date]";
|
|
9
|
+
* the grammar splits only the maturity token, the builder applies the
|
|
10
|
+
* fixed-width trailing-date split (8/6/4 digits — slugs like "url-1" or
|
|
11
|
+
* "DSIG-label-971024.html" never mis-split). Eleven kinds, one per W3C
|
|
12
|
+
* maturity level; `date` is a plain string in Ruby (never a PubidDate).
|
|
13
|
+
*/
|
|
14
|
+
const W3C_KINDS = [
|
|
15
|
+
"standard",
|
|
16
|
+
"note",
|
|
17
|
+
"draft-note",
|
|
18
|
+
"working-draft",
|
|
19
|
+
"candidate-recommendation",
|
|
20
|
+
"candidate-recommendation-draft",
|
|
21
|
+
"recommendation",
|
|
22
|
+
"proposed-recommendation",
|
|
23
|
+
"proposed-edited-recommendation",
|
|
24
|
+
"superseded-recommendation",
|
|
25
|
+
"obsolete-recommendation",
|
|
26
|
+
];
|
|
27
|
+
// Printed token -> kind; DNOTE before NOTE, CRD before CR, PER before PR.
|
|
28
|
+
const TOKEN_KINDS = [
|
|
29
|
+
["DNOTE", "draft-note"],
|
|
30
|
+
["NOTE", "note"],
|
|
31
|
+
["WD", "working-draft"],
|
|
32
|
+
["CRD", "candidate-recommendation-draft"],
|
|
33
|
+
["CR", "candidate-recommendation"],
|
|
34
|
+
["REC", "recommendation"],
|
|
35
|
+
["PER", "proposed-edited-recommendation"],
|
|
36
|
+
["PR", "proposed-recommendation"],
|
|
37
|
+
["SPSD", "superseded-recommendation"],
|
|
38
|
+
["OBSL", "obsolete-recommendation"],
|
|
39
|
+
];
|
|
40
|
+
const KIND_TOKENS = {
|
|
41
|
+
standard: undefined,
|
|
42
|
+
note: "NOTE",
|
|
43
|
+
"draft-note": "DNOTE",
|
|
44
|
+
"working-draft": "WD",
|
|
45
|
+
"candidate-recommendation": "CR",
|
|
46
|
+
"candidate-recommendation-draft": "CRD",
|
|
47
|
+
recommendation: "REC",
|
|
48
|
+
"proposed-recommendation": "PR",
|
|
49
|
+
"proposed-edited-recommendation": "PER",
|
|
50
|
+
"superseded-recommendation": "SPSD",
|
|
51
|
+
"obsolete-recommendation": "OBSL",
|
|
52
|
+
};
|
|
53
|
+
function buildRules() {
|
|
54
|
+
const rules = {};
|
|
55
|
+
const [first, ...others] = TOKEN_KINDS;
|
|
56
|
+
const typeToken = others.reduce((acc, [token]) => acc.or(str(token)), str(first[0]));
|
|
57
|
+
ruleInit(rules, "prefix", () => str("W3C").then(str(" ")));
|
|
58
|
+
// A leading token is only a type when immediately followed by "-".
|
|
59
|
+
ruleInit(rules, "type_part", () => typeToken.as("type").then(str("-")));
|
|
60
|
+
ruleInit(rules, "rest", () => match("[\\s\\S]").repeat(1, Infinity).as("rest"));
|
|
61
|
+
ruleInit(rules, "identifier", () => rules["prefix"]
|
|
62
|
+
.then(rules["type_part"].maybe())
|
|
63
|
+
.then(rules["rest"]));
|
|
64
|
+
ruleInit(rules, "root", () => rules["identifier"]);
|
|
65
|
+
return rules;
|
|
66
|
+
}
|
|
67
|
+
function ruleInit(rules, name, build) {
|
|
68
|
+
rules[name] = build();
|
|
69
|
+
}
|
|
70
|
+
export const w3cGrammar = { rules: buildRules(), root: "root" };
|
|
71
|
+
const KIND_CLASSES = {};
|
|
72
|
+
function w3cClass(kind) {
|
|
73
|
+
const token = KIND_TOKENS[kind];
|
|
74
|
+
class W3cKindIdentifier extends BaseIdentifier {
|
|
75
|
+
static polymorphicName = `pubid:w3c:${kind}`;
|
|
76
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
77
|
+
number: { type: "string" },
|
|
78
|
+
date: { type: "string" },
|
|
79
|
+
});
|
|
80
|
+
static mappings = keyValue({ wire: "number", to: "number" }, { wire: "date", to: "date" });
|
|
81
|
+
render() {
|
|
82
|
+
let body = token === undefined ? "" : `${token}-`;
|
|
83
|
+
body += this.number;
|
|
84
|
+
if (this.date !== undefined)
|
|
85
|
+
body += `-${this.date}`;
|
|
86
|
+
return `W3C ${body}`;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
registerType(W3cKindIdentifier);
|
|
90
|
+
return W3cKindIdentifier;
|
|
91
|
+
}
|
|
92
|
+
for (const kind of W3C_KINDS) {
|
|
93
|
+
KIND_CLASSES[kind] = w3cClass(kind);
|
|
94
|
+
}
|
|
95
|
+
class W3cUrnGenerator extends BaseUrnGenerator {
|
|
96
|
+
generate() {
|
|
97
|
+
const id = this.identifier;
|
|
98
|
+
const kind = (this.identifier.constructor.polymorphicName.slice("pubid:w3c:".length));
|
|
99
|
+
const parts = ["urn", "w3c"];
|
|
100
|
+
const token = KIND_TOKENS[kind];
|
|
101
|
+
if (token !== undefined)
|
|
102
|
+
parts.push(token.toLowerCase());
|
|
103
|
+
parts.push(id.number);
|
|
104
|
+
if (id.date !== undefined)
|
|
105
|
+
parts.push(id.date);
|
|
106
|
+
return parts.join(":");
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
for (const kind of W3C_KINDS) {
|
|
110
|
+
KIND_CLASSES[kind].urnGenerator = W3cUrnGenerator;
|
|
111
|
+
}
|
|
112
|
+
const DATE_RE = /^(.+)-(\d{8}|\d{6}|\d{4})$/;
|
|
113
|
+
function kindForToken(token) {
|
|
114
|
+
if (token === undefined)
|
|
115
|
+
return "standard";
|
|
116
|
+
const entry = TOKEN_KINDS.find(([t]) => t === token);
|
|
117
|
+
if (!entry)
|
|
118
|
+
throw new ParseFailed(`W3C: unknown type token ${token}`, 0);
|
|
119
|
+
return entry[1];
|
|
120
|
+
}
|
|
121
|
+
class W3cBuilder extends BaseBuilder {
|
|
122
|
+
selectClass(data) {
|
|
123
|
+
const type = data["type"];
|
|
124
|
+
return KIND_CLASSES[kindForToken(type === undefined || type === null ? undefined : String(type))];
|
|
125
|
+
}
|
|
126
|
+
defaultIdentifierClass() {
|
|
127
|
+
return KIND_CLASSES["standard"];
|
|
128
|
+
}
|
|
129
|
+
cast(key, value) {
|
|
130
|
+
if (key !== "rest")
|
|
131
|
+
return value;
|
|
132
|
+
const rest = String(value);
|
|
133
|
+
const m = DATE_RE.exec(rest);
|
|
134
|
+
return m ? { number: m[1], date: m[2] } : { number: rest };
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
export function w3cGrammarImplementation() {
|
|
138
|
+
const builder = new W3cBuilder();
|
|
139
|
+
return {
|
|
140
|
+
parse(input) {
|
|
141
|
+
const tree = parseGrammar(w3cGrammar, input);
|
|
142
|
+
if (typeof tree !== "object" || tree === null || Array.isArray(tree)) {
|
|
143
|
+
throw new ParseFailed("W3C: unexpected parse tree", 0);
|
|
144
|
+
}
|
|
145
|
+
return builder.build(tree);
|
|
146
|
+
},
|
|
147
|
+
};
|
|
148
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Grammar } from "../../grammar/engine.js";
|
|
2
|
+
import type { FlavorImplementation } from "../../conformance/implementation.js";
|
|
3
|
+
import { BaseIdentifier } from "../../model/identifier.js";
|
|
4
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
5
|
+
export declare const xsfGrammar: Grammar;
|
|
6
|
+
declare class XsfUrnGenerator extends BaseUrnGenerator<XsfIdentifier> {
|
|
7
|
+
generate(): string;
|
|
8
|
+
}
|
|
9
|
+
export declare class XsfIdentifier extends BaseIdentifier {
|
|
10
|
+
static polymorphicName: string;
|
|
11
|
+
static attributes: import("../../model/attribute.js").AttributeTable;
|
|
12
|
+
static mappings: import("../../model/attribute.js").FieldMapping[];
|
|
13
|
+
static urnGenerator: typeof XsfUrnGenerator;
|
|
14
|
+
readonly number: string;
|
|
15
|
+
render(): string;
|
|
16
|
+
}
|
|
17
|
+
export declare function xsfGrammarImplementation(): FlavorImplementation;
|
|
18
|
+
export {};
|