@pubid/pubid 0.1.3 → 0.1.5
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 +31 -0
- package/dist/flavors/gb/index.js +159 -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 +697 -0
- package/dist/flavors/ieee/index.d.ts +3 -0
- package/dist/flavors/ieee/index.js +1258 -0
- package/dist/flavors/ieee/model.d.ts +144 -0
- package/dist/flavors/ieee/model.js +1237 -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 +197 -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 +206 -0
- package/dist/flavors/oiml/implementation.d.ts +9 -0
- package/dist/flavors/oiml/implementation.js +45 -0
- package/dist/flavors/oiml/model.d.ts +23 -0
- package/dist/flavors/oiml/model.js +592 -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/index.d.ts +1 -0
- package/dist/index.js +3 -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 +84 -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,863 @@
|
|
|
1
|
+
import { BaseIdentifier, registerType } from "../../model/identifier.js";
|
|
2
|
+
import { keyValue, extendAttributes } from "../../model/attribute.js";
|
|
3
|
+
import { PubidDate, Publisher } from "../../model/component.js";
|
|
4
|
+
import { BaseUrnGenerator } from "../../model/urn-generator.js";
|
|
5
|
+
/**
|
|
6
|
+
* Port of lib/pubid/bsi: the shared base (single_identifier.rb), the
|
|
7
|
+
* typed-stage registry (bsi.rb TYPED_STAGES_REGISTRY), the ~25 concrete
|
|
8
|
+
* identifier classes, the renderer (renderer.rb) and the URN generator
|
|
9
|
+
* (urn_generator.rb).
|
|
10
|
+
*/
|
|
11
|
+
// --- Code component (components/code.rb — wire {value}) ---------------------------
|
|
12
|
+
export class BsiCode {
|
|
13
|
+
value;
|
|
14
|
+
constructor(attrs) {
|
|
15
|
+
this.value = attrs["value"];
|
|
16
|
+
}
|
|
17
|
+
render() {
|
|
18
|
+
return this.value;
|
|
19
|
+
}
|
|
20
|
+
toWire() {
|
|
21
|
+
return { value: this.value };
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export const TYPED_STAGES_REGISTRY = [
|
|
25
|
+
{ code: "pubbs", stageCode: "published", typeCode: "bs", abbr: ["BS"], name: "British Standard", harmonizedStages: ["60.00", "60.60"] },
|
|
26
|
+
{ code: "drbs", stageCode: "draft", typeCode: "bs", abbr: ["Draft BS", "DBS"], name: "Draft British Standard", harmonizedStages: ["30.00", "30.20", "30.60", "40.00", "40.20", "40.60"] },
|
|
27
|
+
{ code: "pubpd", stageCode: "published", typeCode: "pd", abbr: ["PD"], name: "Published Document", harmonizedStages: ["60.00", "60.60"] },
|
|
28
|
+
{ code: "pubpas", stageCode: "published", typeCode: "pas", abbr: ["PAS"], name: "Publicly Available Specification", harmonizedStages: ["60.00", "60.60"] },
|
|
29
|
+
{ code: "pubna", stageCode: "published", typeCode: "na", abbr: ["NA"], name: "National Annex", harmonizedStages: ["60.00", "60.60"] },
|
|
30
|
+
{ code: "pubdd", stageCode: "published", typeCode: "dd", abbr: ["DD"], name: "Draft Document", harmonizedStages: ["60.00", "60.60"] },
|
|
31
|
+
{ code: "pubflex", stageCode: "published", typeCode: "flex", abbr: ["Flex", "BSI Flex"], name: "BSI Flex", harmonizedStages: ["60.00", "60.60"] },
|
|
32
|
+
{ code: "pubhandbook", stageCode: "published", typeCode: "handbook", abbr: ["Handbook", "HB"], name: "BSI Handbook", harmonizedStages: ["60.00", "60.60"] },
|
|
33
|
+
{ code: "pubpp", stageCode: "published", typeCode: "pp", abbr: ["PP"], name: "Published Practice", harmonizedStages: ["60.00", "60.60"] },
|
|
34
|
+
{ code: "pubbip", stageCode: "published", typeCode: "bip", abbr: ["BIP"], name: "British Industrial Practice", harmonizedStages: ["60.00", "60.60"] },
|
|
35
|
+
{ code: "pubaerospace", stageCode: "published", typeCode: "aerospace", abbr: ["BS A", "BS AU", "BS C", "BS M", "BS S", "BS L", "BS TA", "BS MA", "BS PL", "BS QC", "BS G", "BS HC", "BS F", "BS X", "BS B"], name: "Aerospace/Specialized British Standard", harmonizedStages: ["60.00", "60.60"] },
|
|
36
|
+
{ code: "pubindex", stageCode: "published", typeCode: "index", abbr: ["Index"], name: "BSI Index", harmonizedStages: ["60.00", "60.60"] },
|
|
37
|
+
{ code: "pubmethod", stageCode: "published", typeCode: "method", abbr: ["Method", "Methods"], name: "BSI Method", harmonizedStages: ["60.00", "60.60"] },
|
|
38
|
+
{ code: "pubsection", stageCode: "published", typeCode: "section", abbr: ["Section"], name: "BSI Section", harmonizedStages: ["60.00", "60.60"] },
|
|
39
|
+
{ code: "pubdisc", stageCode: "published", typeCode: "disc", abbr: ["DISC"], name: "DISC", harmonizedStages: ["60.00", "60.60"] },
|
|
40
|
+
{ code: "pubdetailed_spec", stageCode: "published", typeCode: "detailed_specification", abbr: ["DETAILED SPEC"], name: "Detailed Specification", harmonizedStages: ["60.00", "60.60"] },
|
|
41
|
+
{ code: "standalone_amendment", stageCode: "published", typeCode: "amendment", abbr: ["AMD"], name: "Amendment", harmonizedStages: ["60.00", "60.60"] },
|
|
42
|
+
{ code: "pubts", stageCode: "published", typeCode: "ts", abbr: ["TS"], name: "Technical Specification", harmonizedStages: ["60.00", "60.60"] },
|
|
43
|
+
];
|
|
44
|
+
export const DEFAULT_TYPED_STAGE = TYPED_STAGES_REGISTRY[0];
|
|
45
|
+
export function locateStage(abbr) {
|
|
46
|
+
const needle = abbr.trim().toUpperCase();
|
|
47
|
+
return TYPED_STAGES_REGISTRY.find((s) => s.abbr.some((a) => a.toUpperCase() === needle));
|
|
48
|
+
}
|
|
49
|
+
export const TYPE_CLASSES = {};
|
|
50
|
+
function locateTypeClass(typeCode) {
|
|
51
|
+
return TYPE_CLASSES[typeCode];
|
|
52
|
+
}
|
|
53
|
+
/** The wrapped document's identity: walks base/adopted chains (CEN
|
|
54
|
+
* adopted wrappers hold the foreign id under `adopted`) until a node
|
|
55
|
+
* carries a number. */
|
|
56
|
+
function deepIdentity(id, seen = 0) {
|
|
57
|
+
if (seen > 6 || id === null || typeof id !== "object")
|
|
58
|
+
return undefined;
|
|
59
|
+
const rec = id;
|
|
60
|
+
// Root semantics: a wrapper's own number never wins over the base
|
|
61
|
+
// chain (an AMD/FRAG wrapper keys its URN off the BASE document).
|
|
62
|
+
for (const key of ["base", "adopted"]) {
|
|
63
|
+
const next = rec[key];
|
|
64
|
+
if (next !== null && typeof next === "object") {
|
|
65
|
+
const found = deepIdentity(next, seen + 1);
|
|
66
|
+
if (found !== undefined)
|
|
67
|
+
return found;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// Bundled identifiers key their identity off the first member.
|
|
71
|
+
const members = rec["identifiers"];
|
|
72
|
+
if (Array.isArray(members) && members.length > 0) {
|
|
73
|
+
return deepIdentity(members[0], seen + 1);
|
|
74
|
+
}
|
|
75
|
+
if (rec["number"] !== undefined)
|
|
76
|
+
return id;
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
/** Wraps a registry entry so the attribute machinery can coerce the
|
|
80
|
+
* wire's typed_stage block back into the runtime state. */
|
|
81
|
+
export class BsiTypedStageRef {
|
|
82
|
+
code;
|
|
83
|
+
stageCode;
|
|
84
|
+
typeCode;
|
|
85
|
+
abbr;
|
|
86
|
+
name;
|
|
87
|
+
harmonizedStages;
|
|
88
|
+
constructor(attrs) {
|
|
89
|
+
const e = attrs;
|
|
90
|
+
this.code = e.code;
|
|
91
|
+
this.stageCode = e.stageCode;
|
|
92
|
+
this.typeCode = e.typeCode;
|
|
93
|
+
this.abbr = e.abbr;
|
|
94
|
+
this.name = e.name;
|
|
95
|
+
this.harmonizedStages = e.harmonizedStages;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
class BsiUrnGenerator extends BaseUrnGenerator {
|
|
99
|
+
generate() {
|
|
100
|
+
const id = this.identifier;
|
|
101
|
+
const parts = ["urn", "bsi"];
|
|
102
|
+
if (id.publisher !== undefined) {
|
|
103
|
+
parts.push(id.publisher.render("urn"));
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
parts.push("bs");
|
|
107
|
+
}
|
|
108
|
+
if (id.prefix !== undefined)
|
|
109
|
+
parts.push(id.prefix.toLowerCase());
|
|
110
|
+
if (id.flex_prefix !== undefined)
|
|
111
|
+
parts.push(id.flex_prefix.toLowerCase());
|
|
112
|
+
// Identity reads walk to the wrapped document when the wrapper has
|
|
113
|
+
// none of its own; adopted foreign chains (CEN adopted wrappers)
|
|
114
|
+
// are walked through both the `base` and `adopted` keys.
|
|
115
|
+
const rootRecord = deepIdentity(id);
|
|
116
|
+
const root = rootRecord;
|
|
117
|
+
const urnNumber = id.number ?? (rootRecord !== undefined ? rootRecord.number : undefined);
|
|
118
|
+
if (urnNumber !== undefined) {
|
|
119
|
+
let number = urnNumber;
|
|
120
|
+
if (id.iteration !== undefined && id.iteration !== "") {
|
|
121
|
+
number += `[${id.iteration}]`;
|
|
122
|
+
}
|
|
123
|
+
parts.push(number);
|
|
124
|
+
}
|
|
125
|
+
const urnPart = id.part ?? (root !== undefined && rootRecord !== undefined && rootRecord !== id ? rootRecord.part : undefined);
|
|
126
|
+
if (urnPart !== undefined)
|
|
127
|
+
parts.push(`-${urnPart}`);
|
|
128
|
+
const urnSubpart = id.subpart ?? (root !== undefined && rootRecord !== undefined && rootRecord !== id ? rootRecord.subpart : undefined);
|
|
129
|
+
if (urnSubpart !== undefined)
|
|
130
|
+
parts.push(`-${urnSubpart}`);
|
|
131
|
+
if (id.second_number !== undefined)
|
|
132
|
+
parts.push(`/${id.second_number.render()}`);
|
|
133
|
+
const urnDate = id.date ?? (root !== undefined && rootRecord !== undefined && rootRecord !== id ? rootRecord.date : undefined);
|
|
134
|
+
if (urnDate?.present()) {
|
|
135
|
+
parts.push(urnDate.render("urn"));
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const urnYear = id.year
|
|
139
|
+
?? (root !== undefined && rootRecord !== undefined && rootRecord !== id ? rootRecord.year : undefined);
|
|
140
|
+
if (urnYear !== undefined)
|
|
141
|
+
parts.push(urnYear);
|
|
142
|
+
}
|
|
143
|
+
if (id.month !== undefined)
|
|
144
|
+
parts.push(pad2(id.month));
|
|
145
|
+
if (id.edition !== undefined)
|
|
146
|
+
parts.push(`v${id.edition}`);
|
|
147
|
+
if (id.translation_lang !== undefined)
|
|
148
|
+
parts.push(id.translation_lang.toLowerCase());
|
|
149
|
+
else if (id.translation_upper !== undefined)
|
|
150
|
+
parts.push(id.translation_upper.toLowerCase());
|
|
151
|
+
const typedStage = id.typedStage;
|
|
152
|
+
if (typedStage !== undefined && typedStage.code !== "pubbs") {
|
|
153
|
+
parts.push(typedStage.typeCode);
|
|
154
|
+
parts.push(`stage.${typedStage.stageCode}`);
|
|
155
|
+
}
|
|
156
|
+
return parts.join(":");
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
// --- The base class ----------------------------------------------------------------
|
|
160
|
+
export class BsiIdentifier extends BaseIdentifier {
|
|
161
|
+
static polymorphicName = "pubid:bsi:identifier";
|
|
162
|
+
static urnGenerator = BsiUrnGenerator;
|
|
163
|
+
static attributes = extendAttributes(BaseIdentifier, {
|
|
164
|
+
publisher: { type: Publisher, default: new Publisher({ body: "BS" }) },
|
|
165
|
+
prefix: { type: "string" },
|
|
166
|
+
flex_prefix: { type: "string" },
|
|
167
|
+
number: { type: "string" },
|
|
168
|
+
iteration: { type: "string" },
|
|
169
|
+
part: { type: "string" },
|
|
170
|
+
subpart: { type: "string" },
|
|
171
|
+
second_number: { type: BsiCode },
|
|
172
|
+
date: { type: PubidDate },
|
|
173
|
+
edition: { type: "string" },
|
|
174
|
+
month: { type: "integer" },
|
|
175
|
+
translation_lang: { type: "string" },
|
|
176
|
+
translation_upper: { type: "string" },
|
|
177
|
+
explicit_prefix: { type: "boolean", default: false },
|
|
178
|
+
explicit_publisher: { type: "boolean", default: false },
|
|
179
|
+
space_separated_part: { type: "boolean", default: false },
|
|
180
|
+
typedStage: { type: BsiTypedStageRef },
|
|
181
|
+
});
|
|
182
|
+
/** The gem serializes the full typed-stage registry entry (type,
|
|
183
|
+
* stage, typed_stage blocks) for every non-default typed stage. */
|
|
184
|
+
static compactHash = (model, hash) => {
|
|
185
|
+
const ts = model.typedStage;
|
|
186
|
+
if (ts === undefined || ts.code === "pubbs")
|
|
187
|
+
return;
|
|
188
|
+
hash["type"] = { name: ts.name, abbr: ts.abbr[0], type_code: ts.typeCode };
|
|
189
|
+
hash["stage"] = { name: ts.name, stage_code: ts.stageCode, harmonized_stages: ts.harmonizedStages, abbr: ts.abbr[0] };
|
|
190
|
+
hash["typed_stage"] = { name: ts.name, code: ts.code, type_code: ts.typeCode, stage_code: ts.stageCode, abbr: ts.abbr, harmonized_stages: ts.harmonizedStages };
|
|
191
|
+
};
|
|
192
|
+
static mappings = keyValue({ wire: "publisher", to: "publisher" }, { wire: "prefix", to: "prefix" }, { wire: "flex_prefix", to: "flex_prefix" }, { wire: "number", to: "number" }, { wire: "iteration", to: "iteration" }, { wire: "part", to: "part" }, { wire: "subpart", to: "subpart" }, { wire: "second_number", to: "second_number" }, { wire: "date", to: "date" }, { wire: "edition", to: "edition" }, { wire: "month", to: "month" }, { wire: "translation_lang", to: "translation_lang" }, { wire: "translation_upper", to: "translation_upper" }, { wire: "explicit_prefix", to: "explicit_prefix" }, { wire: "explicit_publisher", to: "explicit_publisher" }, { wire: "space_separated_part", to: "space_separated_part" }, {
|
|
193
|
+
wire: "typed_stage",
|
|
194
|
+
to: "typedStage",
|
|
195
|
+
fromWire: (h) => {
|
|
196
|
+
const code = h["typed_stage"];
|
|
197
|
+
if (code === undefined || code === null || typeof code === "string")
|
|
198
|
+
return undefined;
|
|
199
|
+
const entry = code["code"];
|
|
200
|
+
return TYPED_STAGES_REGISTRY.find((t) => t.code === entry);
|
|
201
|
+
},
|
|
202
|
+
toWire: () => undefined,
|
|
203
|
+
}, {
|
|
204
|
+
// The consolidated wrapper carries only the `type` block; its
|
|
205
|
+
// typed stage derives from the type_code.
|
|
206
|
+
wire: "type",
|
|
207
|
+
to: "typedStage",
|
|
208
|
+
fromWire: (h) => {
|
|
209
|
+
const t = h["type"];
|
|
210
|
+
if (t === undefined || t === null || typeof t !== "object")
|
|
211
|
+
return undefined;
|
|
212
|
+
const tc = t["type_code"];
|
|
213
|
+
return tc === undefined ? undefined : TYPED_STAGES_REGISTRY.find((x) => x.typeCode === tc);
|
|
214
|
+
},
|
|
215
|
+
toWire: () => undefined,
|
|
216
|
+
});
|
|
217
|
+
constructor(attrs = {}) {
|
|
218
|
+
super(attrs);
|
|
219
|
+
const self = this;
|
|
220
|
+
if (self["publisher"] === undefined)
|
|
221
|
+
self["publisher"] = new Publisher({ body: "BS" });
|
|
222
|
+
}
|
|
223
|
+
root() {
|
|
224
|
+
return this;
|
|
225
|
+
}
|
|
226
|
+
render() {
|
|
227
|
+
return renderSingleIdentifier(this);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// --- Renderer helpers --------------------------------------------------------------
|
|
231
|
+
function pad2(n) {
|
|
232
|
+
return String(n).padStart(2, "0");
|
|
233
|
+
}
|
|
234
|
+
function renderSingleIdentifier(id) {
|
|
235
|
+
const parts = [];
|
|
236
|
+
if (id.publisher !== undefined)
|
|
237
|
+
parts.push(id.publisher.render());
|
|
238
|
+
if (id.flex_prefix !== undefined)
|
|
239
|
+
parts.push(id.flex_prefix);
|
|
240
|
+
else if (id.prefix !== undefined)
|
|
241
|
+
parts.push(id.prefix);
|
|
242
|
+
if (id.number !== undefined) {
|
|
243
|
+
let numberStr = id.number;
|
|
244
|
+
if (id.second_number !== undefined) {
|
|
245
|
+
numberStr += `/${id.second_number.render()}`;
|
|
246
|
+
}
|
|
247
|
+
if (id.part !== undefined) {
|
|
248
|
+
numberStr += `${id.space_separated_part ? " " : "-"}${id.part.trim()}`;
|
|
249
|
+
}
|
|
250
|
+
if (id.subpart !== undefined) {
|
|
251
|
+
numberStr += `-${id.subpart.trim()}`;
|
|
252
|
+
}
|
|
253
|
+
if (id.iteration !== undefined && id.iteration !== "") {
|
|
254
|
+
numberStr += `[${id.iteration}]`;
|
|
255
|
+
}
|
|
256
|
+
parts.push(numberStr);
|
|
257
|
+
}
|
|
258
|
+
let result = parts.join(" ");
|
|
259
|
+
if (id.date?.present()) {
|
|
260
|
+
result += `:${id.date.render()}`;
|
|
261
|
+
if (id.month !== undefined)
|
|
262
|
+
result += `-${pad2(id.month)}`;
|
|
263
|
+
}
|
|
264
|
+
if (id.edition !== undefined)
|
|
265
|
+
result += ` v${id.edition}`;
|
|
266
|
+
if (id.translation_lang !== undefined)
|
|
267
|
+
result += ` (${id.translation_lang})`;
|
|
268
|
+
else if (id.translation_upper !== undefined)
|
|
269
|
+
result += ` (${id.translation_upper})`;
|
|
270
|
+
return result;
|
|
271
|
+
}
|
|
272
|
+
function renderNumberWithParts(id) {
|
|
273
|
+
let numberStr = id.number ?? "";
|
|
274
|
+
if (id.second_number !== undefined)
|
|
275
|
+
numberStr += `/${id.second_number.render()}`;
|
|
276
|
+
if (id.part !== undefined)
|
|
277
|
+
numberStr += `-${id.part.trim()}`;
|
|
278
|
+
if (id.subpart !== undefined)
|
|
279
|
+
numberStr += `-${id.subpart.trim()}`;
|
|
280
|
+
return numberStr;
|
|
281
|
+
}
|
|
282
|
+
function bsiClass(spec, render) {
|
|
283
|
+
class BsiConcrete extends BsiIdentifier {
|
|
284
|
+
static polymorphicName = `pubid:bsi:${spec.kind}`;
|
|
285
|
+
static urnGenerator = BsiUrnGenerator;
|
|
286
|
+
render() {
|
|
287
|
+
return render(this);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
void spec;
|
|
291
|
+
registerType(BsiConcrete);
|
|
292
|
+
const klass = BsiConcrete;
|
|
293
|
+
if (spec.typeCode !== undefined)
|
|
294
|
+
TYPE_CLASSES[spec.typeCode] = klass;
|
|
295
|
+
return klass;
|
|
296
|
+
}
|
|
297
|
+
function renderWithTypeAbbr(abbr) {
|
|
298
|
+
return (id) => {
|
|
299
|
+
let result = [abbr, id.number !== undefined ? renderNumberWithParts(id) : ""]
|
|
300
|
+
.filter((s) => s !== "").join(" ");
|
|
301
|
+
if (id.date?.present()) {
|
|
302
|
+
result += `:${id.date.render()}`;
|
|
303
|
+
if (id.month !== undefined)
|
|
304
|
+
result += `-${pad2(id.month)}`;
|
|
305
|
+
}
|
|
306
|
+
if (id.edition !== undefined)
|
|
307
|
+
result += ` v${id.edition}`;
|
|
308
|
+
if (id.translation_lang !== undefined)
|
|
309
|
+
result += ` (${id.translation_lang})`;
|
|
310
|
+
else if (id.translation_upper !== undefined)
|
|
311
|
+
result += ` (${id.translation_upper})`;
|
|
312
|
+
return result;
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
export const BritishStandardClass = bsiClass({ kind: "british-standard", typeCode: "bs" }, (id) => renderSingleIdentifier(id));
|
|
316
|
+
export const DraftDocumentClass = bsiClass({ kind: "draft-document", typeCode: "dd" }, renderWithTypeAbbr("DD"));
|
|
317
|
+
export const PublishedDocumentClass = bsiClass({ kind: "published-document", typeCode: "pd" }, renderWithTypeAbbr("PD"));
|
|
318
|
+
export const PubliclyAvailableSpecificationClass = bsiClass({ kind: "publicly-available-specification", typeCode: "pas" }, renderWithTypeAbbr("PAS"));
|
|
319
|
+
export const TechnicalSpecificationClass = bsiClass({ kind: "technical-specification", typeCode: "ts" }, renderWithTypeAbbr("TS"));
|
|
320
|
+
export const ElectronicBookClass = bsiClass({ kind: "electronic-book", typeCode: "ep" }, (id) => {
|
|
321
|
+
let result = ["EP", id.number !== undefined ? renderNumberWithParts(id) : ""]
|
|
322
|
+
.filter((s) => s !== "").join(" ");
|
|
323
|
+
if (id.date?.present())
|
|
324
|
+
result += `:${id.date.render()}`;
|
|
325
|
+
if (id.edition !== undefined)
|
|
326
|
+
result += ` Version ${id.edition}`;
|
|
327
|
+
return result;
|
|
328
|
+
});
|
|
329
|
+
export const AerospaceStandardClass = bsiClass({ kind: "aerospace-standard", typeCode: "aerospace" }, (id) => {
|
|
330
|
+
const parts = ["BS"];
|
|
331
|
+
if (id.prefix !== undefined)
|
|
332
|
+
parts.push(id.prefix);
|
|
333
|
+
if (id.number !== undefined)
|
|
334
|
+
parts.push(renderNumberWithParts(id));
|
|
335
|
+
let result = parts.join(" ");
|
|
336
|
+
if (id.edition !== undefined && /^[a-zA-Z]$/.test(id.edition))
|
|
337
|
+
result += id.edition;
|
|
338
|
+
if (id.date?.present()) {
|
|
339
|
+
result += `:${id.date.render()}`;
|
|
340
|
+
if (id.month !== undefined)
|
|
341
|
+
result += `-${pad2(id.month)}`;
|
|
342
|
+
}
|
|
343
|
+
if (id.edition !== undefined && !/^[a-zA-Z]$/.test(id.edition))
|
|
344
|
+
result += ` v${id.edition}`;
|
|
345
|
+
if (id.translation_lang !== undefined)
|
|
346
|
+
result += ` (${id.translation_lang})`;
|
|
347
|
+
else if (id.translation_upper !== undefined)
|
|
348
|
+
result += ` (${id.translation_upper})`;
|
|
349
|
+
return result;
|
|
350
|
+
});
|
|
351
|
+
export const FlexClass = bsiClass({ kind: "flex", typeCode: "flex" }, (id) => {
|
|
352
|
+
const parts = ["BSI Flex"];
|
|
353
|
+
if (id.number !== undefined)
|
|
354
|
+
parts.push(renderNumberWithParts(id));
|
|
355
|
+
let result = parts.join(" ");
|
|
356
|
+
if (id.edition !== undefined)
|
|
357
|
+
result += ` v${id.edition}`;
|
|
358
|
+
if (id.date?.present()) {
|
|
359
|
+
result += `:${id.date.render()}`;
|
|
360
|
+
if (id.month !== undefined)
|
|
361
|
+
result += `-${pad2(id.month)}`;
|
|
362
|
+
}
|
|
363
|
+
return result;
|
|
364
|
+
});
|
|
365
|
+
registerType(BsiIdentifier);
|
|
366
|
+
// --- Suffix-type classes -------------------------------------------------------------
|
|
367
|
+
class ConsolidatedUrnGenerator extends BaseUrnGenerator {
|
|
368
|
+
generate() {
|
|
369
|
+
return consolidatedUrn(this.identifier) ?? "";
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
function bsiClassWith(spec, extraAttrs, render) {
|
|
373
|
+
// 'base' wrappers root through their base document; 'first' through
|
|
374
|
+
// the first member of their identifiers collection.
|
|
375
|
+
const rootKind = spec.rootKind;
|
|
376
|
+
class BsiConcrete extends BsiIdentifier {
|
|
377
|
+
static polymorphicName = `pubid:bsi:${spec.kind}`;
|
|
378
|
+
static urnGenerator = spec.kind === "consolidated-identifier" ? ConsolidatedUrnGenerator : BsiUrnGenerator;
|
|
379
|
+
static attributes = extendAttributes(BsiIdentifier, extraAttrs);
|
|
380
|
+
static mappings = [
|
|
381
|
+
...BsiIdentifier.mappings,
|
|
382
|
+
...Object.keys(extraAttrs).map((k) => ({ wire: k, to: k })),
|
|
383
|
+
];
|
|
384
|
+
root() {
|
|
385
|
+
if (rootKind === "base") {
|
|
386
|
+
return this.base?.root() ?? this;
|
|
387
|
+
}
|
|
388
|
+
if (rootKind === "first") {
|
|
389
|
+
const first = this.identifiers?.[0];
|
|
390
|
+
return first !== undefined ? first.root() : this;
|
|
391
|
+
}
|
|
392
|
+
return this;
|
|
393
|
+
}
|
|
394
|
+
render() {
|
|
395
|
+
return render(this);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
registerType(BsiConcrete);
|
|
399
|
+
const klass = BsiConcrete;
|
|
400
|
+
if (spec.typeCode !== undefined)
|
|
401
|
+
TYPE_CLASSES[spec.typeCode] = klass;
|
|
402
|
+
return klass;
|
|
403
|
+
}
|
|
404
|
+
export const IndexClass = bsiClassWith({ kind: "index", typeCode: "index" }, { issue_number: { type: "string" }, index_format: { type: "string" } }, (id) => {
|
|
405
|
+
const parts = [];
|
|
406
|
+
if (id.publisher !== undefined)
|
|
407
|
+
parts.push(id.publisher.render());
|
|
408
|
+
if (id.number !== undefined)
|
|
409
|
+
parts.push(id.number);
|
|
410
|
+
let result = parts.join(" ");
|
|
411
|
+
if (id.issue_number !== undefined) {
|
|
412
|
+
result += ` Index Issue ${id.issue_number}`;
|
|
413
|
+
}
|
|
414
|
+
else if (id.index_format === "colon") {
|
|
415
|
+
result += ":Index";
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
result += " Index";
|
|
419
|
+
}
|
|
420
|
+
if (id.date?.present())
|
|
421
|
+
result += `:${id.date.render()}`;
|
|
422
|
+
return result;
|
|
423
|
+
});
|
|
424
|
+
export const SupplementaryIndexClass = bsiClassWith({ kind: "supplementary-index" }, {}, (id) => {
|
|
425
|
+
let result = ["BS", id.number !== undefined ? renderNumberWithParts(id) : ""]
|
|
426
|
+
.filter((x) => x !== "").join(" ");
|
|
427
|
+
if (id.date?.present()) {
|
|
428
|
+
result += ` Supplementary Index:${id.date.render()}`;
|
|
429
|
+
if (id.month !== undefined)
|
|
430
|
+
result += `-${pad2(id.month)}`;
|
|
431
|
+
}
|
|
432
|
+
return result;
|
|
433
|
+
});
|
|
434
|
+
export const ExplanatorySupplementClass = bsiClassWith({ kind: "explanatory-supplement" }, {}, (id) => {
|
|
435
|
+
let result = ["BS", id.number !== undefined ? renderNumberWithParts(id) : ""]
|
|
436
|
+
.filter((x) => x !== "").join(" ");
|
|
437
|
+
if (id.date?.present()) {
|
|
438
|
+
result += `:Explanatory Supplement:${id.date.render()}`;
|
|
439
|
+
if (id.month !== undefined)
|
|
440
|
+
result += `-${pad2(id.month)}`;
|
|
441
|
+
}
|
|
442
|
+
return result;
|
|
443
|
+
});
|
|
444
|
+
export const MethodClass = bsiClassWith({ kind: "method", typeCode: "method" }, { method_code: { type: "string" }, method_to: { type: "string" }, method_and: { type: "string" }, is_plural: { type: "boolean" } }, (id) => {
|
|
445
|
+
const parts = [];
|
|
446
|
+
if (id.publisher !== undefined)
|
|
447
|
+
parts.push(id.publisher.render());
|
|
448
|
+
if (id.number !== undefined) {
|
|
449
|
+
parts.push(id.part !== undefined ? `${id.number}-${id.part}` : id.number);
|
|
450
|
+
}
|
|
451
|
+
let result = parts.join(" ");
|
|
452
|
+
if (id.method_to !== undefined) {
|
|
453
|
+
result += `:Methods ${id.method_code} to ${id.method_to}`;
|
|
454
|
+
}
|
|
455
|
+
else if (id.method_and !== undefined) {
|
|
456
|
+
result += `:Methods ${id.method_code} and ${id.method_and}`;
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
result += `:${id.is_plural ? "Methods" : "Method"} ${id.method_code}`;
|
|
460
|
+
}
|
|
461
|
+
if (id.date?.present())
|
|
462
|
+
result += `:${id.date.render()}`;
|
|
463
|
+
return result;
|
|
464
|
+
});
|
|
465
|
+
export const TestMethodClass = bsiClassWith({ kind: "test-method", typeCode: "test_method" }, { test_series: { type: "string" }, test_id: { type: "string" } }, (id) => {
|
|
466
|
+
let result = ["BS", id.number ?? ""].join(" ");
|
|
467
|
+
if (id.test_series !== undefined && id.test_id !== undefined) {
|
|
468
|
+
result += `:${id.test_series}:${id.test_id}`;
|
|
469
|
+
}
|
|
470
|
+
if (id.date?.present())
|
|
471
|
+
result += `:${id.date.render()}`;
|
|
472
|
+
return result;
|
|
473
|
+
});
|
|
474
|
+
export const SectionClass = bsiClassWith({ kind: "section", typeCode: "section" }, { section_id: { type: "string" }, section_format: { type: "string" } }, (id) => {
|
|
475
|
+
const parts = [];
|
|
476
|
+
if (id.publisher !== undefined)
|
|
477
|
+
parts.push(id.publisher.render());
|
|
478
|
+
if (id.number !== undefined)
|
|
479
|
+
parts.push(id.number);
|
|
480
|
+
let result = parts.join(" ");
|
|
481
|
+
result += id.section_format === "colon"
|
|
482
|
+
? `:Section ${id.section_id}`
|
|
483
|
+
: ` Section ${id.section_id}`;
|
|
484
|
+
if (id.date?.present())
|
|
485
|
+
result += `:${id.date.render()}`;
|
|
486
|
+
return result;
|
|
487
|
+
});
|
|
488
|
+
export const DetailedSpecificationClass = bsiClassWith({ kind: "detailed-specification", typeCode: "detailed_specification" }, { spec_code: { type: BsiCode } }, (id) => {
|
|
489
|
+
let result = ["BS", id.number ?? ""].join(" ");
|
|
490
|
+
if (id.spec_code !== undefined)
|
|
491
|
+
result += ` ${id.spec_code.render()}`;
|
|
492
|
+
if (id.date?.present())
|
|
493
|
+
result += `:${id.date.render()}`;
|
|
494
|
+
return result;
|
|
495
|
+
});
|
|
496
|
+
export const DiscClass = bsiClassWith({ kind: "disc", typeCode: "disc" }, {}, (id) => {
|
|
497
|
+
let numberStr = id.number ?? "";
|
|
498
|
+
if (id.part !== undefined)
|
|
499
|
+
numberStr += `-${id.part.trim()}`;
|
|
500
|
+
let result = ["DISC", numberStr !== "" ? `PD ${numberStr}` : ""].filter((x) => x !== "").join(" ");
|
|
501
|
+
if (id.date?.present())
|
|
502
|
+
result += `:${id.date.render()}`;
|
|
503
|
+
return result;
|
|
504
|
+
});
|
|
505
|
+
export const StandaloneAmendmentClass = bsiClassWith({ kind: "standalone-amendment", typeCode: "amendment" }, { corrigendum: { type: "boolean", default: false }, parenthesized: { type: "boolean", default: false } }, (id) => {
|
|
506
|
+
const base = id.corrigendum
|
|
507
|
+
? `AMD Corrigendum ${id.number}`
|
|
508
|
+
: `AMD ${id.number}`;
|
|
509
|
+
return id.parenthesized ? `(${base})` : base;
|
|
510
|
+
});
|
|
511
|
+
export const CommitteeDocumentClass = bsiClassWith({ kind: "committee-document", typeCode: "committee_document" }, {}, (id) => {
|
|
512
|
+
const yearStr = id.date?.present() ? id.date.render().slice(-2) : "00";
|
|
513
|
+
return `${yearStr}/${id.number} DC`;
|
|
514
|
+
});
|
|
515
|
+
export class Amendment extends BsiIdentifier {
|
|
516
|
+
static polymorphicName = "pubid:bsi:amendment";
|
|
517
|
+
static urnGenerator = BsiUrnGenerator;
|
|
518
|
+
static attributes = extendAttributes(BsiIdentifier, {
|
|
519
|
+
base: { type: BsiIdentifier },
|
|
520
|
+
year: { type: "string" },
|
|
521
|
+
separator: { type: "string", default: "+" },
|
|
522
|
+
amd_suffix_form: { type: "boolean", default: false },
|
|
523
|
+
});
|
|
524
|
+
static mappings = [
|
|
525
|
+
...BsiIdentifier.mappings.filter((m) => m.wire !== "publisher" && m.wire !== "date"),
|
|
526
|
+
{ wire: "base", to: "base" },
|
|
527
|
+
{ wire: "year", to: "year" },
|
|
528
|
+
{ wire: "separator", to: "separator" },
|
|
529
|
+
{ wire: "amd_suffix_form", to: "amd_suffix_form" },
|
|
530
|
+
];
|
|
531
|
+
root() {
|
|
532
|
+
return this.base?.root() ?? this;
|
|
533
|
+
}
|
|
534
|
+
render() {
|
|
535
|
+
const base = this.base?.toHuman() ?? "";
|
|
536
|
+
if (this.amd_suffix_form) {
|
|
537
|
+
const suffix = this.number !== undefined && /^[A-Z]+$/.test(this.number)
|
|
538
|
+
? ` AMD ${this.number}`
|
|
539
|
+
: ` AMD${this.number ?? ""}`;
|
|
540
|
+
return base === "" ? suffix.trimStart() : `${base}${suffix}`;
|
|
541
|
+
}
|
|
542
|
+
let compact = `${this.separator ?? "+"}A${this.number ?? ""}`;
|
|
543
|
+
if (this.year !== undefined)
|
|
544
|
+
compact += `:${this.year}`;
|
|
545
|
+
return `${base}${compact}`;
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
registerType(Amendment);
|
|
549
|
+
export class Corrigendum extends BsiIdentifier {
|
|
550
|
+
static polymorphicName = "pubid:bsi:corrigendum";
|
|
551
|
+
static urnGenerator = BsiUrnGenerator;
|
|
552
|
+
static attributes = extendAttributes(BsiIdentifier, {
|
|
553
|
+
base: { type: BsiIdentifier },
|
|
554
|
+
year: { type: "string" },
|
|
555
|
+
separator: { type: "string", default: "+" },
|
|
556
|
+
});
|
|
557
|
+
static mappings = [
|
|
558
|
+
...BsiIdentifier.mappings.filter((m) => m.wire !== "publisher" && m.wire !== "date"),
|
|
559
|
+
{ wire: "base", to: "base" },
|
|
560
|
+
{ wire: "year", to: "year" },
|
|
561
|
+
{ wire: "separator", to: "separator" },
|
|
562
|
+
];
|
|
563
|
+
root() {
|
|
564
|
+
return this.base?.root() ?? this;
|
|
565
|
+
}
|
|
566
|
+
render() {
|
|
567
|
+
let result = this.base?.toHuman() ?? "";
|
|
568
|
+
result += `${this.separator ?? "+"}C`;
|
|
569
|
+
if (this.number !== undefined)
|
|
570
|
+
result += this.number;
|
|
571
|
+
if (this.year !== undefined)
|
|
572
|
+
result += `:${this.year}`;
|
|
573
|
+
return result;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
registerType(Corrigendum);
|
|
577
|
+
export const SupplementDocumentClass = bsiClassWith({ kind: "supplement-document", rootKind: "base" }, {
|
|
578
|
+
base: { type: BsiIdentifier },
|
|
579
|
+
supplement_number: { type: "string" },
|
|
580
|
+
supplement_year: { type: "integer" },
|
|
581
|
+
supplement_type: { type: "string", default: "No." },
|
|
582
|
+
reverse_format: { type: "boolean", default: false },
|
|
583
|
+
separator: { type: "string", default: ":" },
|
|
584
|
+
}, (id) => {
|
|
585
|
+
const baseStr = id.base?.toHuman() ?? "";
|
|
586
|
+
if (id.reverse_format) {
|
|
587
|
+
const no = id.supplement_type === "No." ? "No. " : "";
|
|
588
|
+
return `Supplement ${no}${id.supplement_number} (${id.supplement_year}) to ${baseStr}`;
|
|
589
|
+
}
|
|
590
|
+
const no = id.supplement_type === "No." ? "No. " : "";
|
|
591
|
+
return `${baseStr}${id.separator ?? ":"}Supplement ${no}${id.supplement_number}:${id.supplement_year}`;
|
|
592
|
+
});
|
|
593
|
+
export const AddendumDocumentClass = bsiClassWith({ kind: "addendum-document", rootKind: "base" }, {
|
|
594
|
+
base: { type: BsiIdentifier },
|
|
595
|
+
addendum_number: { type: "string" },
|
|
596
|
+
addendum_year: { type: "integer" },
|
|
597
|
+
addendum_type: { type: "string", default: "No." },
|
|
598
|
+
separator: { type: "string", default: ":" },
|
|
599
|
+
}, (id) => {
|
|
600
|
+
const baseStr = id.base?.toHuman() ?? "";
|
|
601
|
+
const baseHasYear = /:(\d{4})$/.test(baseStr);
|
|
602
|
+
const sep = id.separator === ":"
|
|
603
|
+
? ":"
|
|
604
|
+
: baseHasYear && !/\d{4}:/.test(baseStr)
|
|
605
|
+
? " "
|
|
606
|
+
: id.separator ?? ":";
|
|
607
|
+
const no = id.addendum_type === "" ? "" : ` ${id.addendum_type}`;
|
|
608
|
+
// The renderer prints two spaces before the addendum number (the
|
|
609
|
+
// gem joins " " + " "); the printed form is the recorded canonical.
|
|
610
|
+
return `${baseStr}${sep}Addendum${no} ${id.addendum_number}:${id.addendum_year ?? ""}`;
|
|
611
|
+
});
|
|
612
|
+
export const BundledIdentifierClass = bsiClassWith({ kind: "bundled-identifier", rootKind: "first" }, {
|
|
613
|
+
identifiers: { type: BsiIdentifier, collection: true },
|
|
614
|
+
separators: { type: "string", collection: true },
|
|
615
|
+
common_year: { type: PubidDate },
|
|
616
|
+
bundle_type: { type: "string" },
|
|
617
|
+
}, (id) => {
|
|
618
|
+
if (id.identifiers === undefined || id.identifiers.length === 0)
|
|
619
|
+
return "";
|
|
620
|
+
if (id.bundle_type !== undefined) {
|
|
621
|
+
const baseId = id.identifiers[0];
|
|
622
|
+
const partsList = id.identifiers.slice(1)
|
|
623
|
+
.map((idd) => idd.part ?? idd.toHuman())
|
|
624
|
+
.join(" and ");
|
|
625
|
+
let result = `${baseId.toHuman().replace(/:.*$/, "")}:${id.bundle_type} ${partsList}`;
|
|
626
|
+
if (id.common_year?.present())
|
|
627
|
+
result += `:${id.common_year.render()}`;
|
|
628
|
+
return result;
|
|
629
|
+
}
|
|
630
|
+
const parts = [];
|
|
631
|
+
id.identifiers.forEach((idd, i) => {
|
|
632
|
+
const self = idd;
|
|
633
|
+
if (i === 0 || self["explicit_publisher"] === true) {
|
|
634
|
+
parts.push(idd.toHuman());
|
|
635
|
+
}
|
|
636
|
+
else if (self["explicit_prefix"] === true) {
|
|
637
|
+
let abbrev = "";
|
|
638
|
+
const prefix = self["prefix"];
|
|
639
|
+
if (prefix !== undefined && prefix !== "")
|
|
640
|
+
abbrev = prefix;
|
|
641
|
+
if (idd.number !== undefined) {
|
|
642
|
+
abbrev += abbrev === "" ? "" : " ";
|
|
643
|
+
abbrev += idd.number;
|
|
644
|
+
}
|
|
645
|
+
if (idd.part !== undefined)
|
|
646
|
+
abbrev += `-${idd.part}`;
|
|
647
|
+
parts.push(abbrev);
|
|
648
|
+
}
|
|
649
|
+
else {
|
|
650
|
+
let abbrev = idd.number ?? "";
|
|
651
|
+
if (idd.part !== undefined)
|
|
652
|
+
abbrev += `-${idd.part}`;
|
|
653
|
+
parts.push(abbrev);
|
|
654
|
+
}
|
|
655
|
+
if (i < id.identifiers.length - 1) {
|
|
656
|
+
parts.push(id.separators?.[i] ?? " and ");
|
|
657
|
+
}
|
|
658
|
+
});
|
|
659
|
+
let result = parts.join("");
|
|
660
|
+
if (id.common_year?.present() && !result.endsWith(`:${id.common_year.render()}`)) {
|
|
661
|
+
result += `:${id.common_year.render()}`;
|
|
662
|
+
}
|
|
663
|
+
return result;
|
|
664
|
+
});
|
|
665
|
+
export const SetClass = bsiClassWith({ kind: "set", rootKind: "first" }, {
|
|
666
|
+
identifiers: { type: BsiIdentifier, collection: true },
|
|
667
|
+
separators: { type: "string", collection: true },
|
|
668
|
+
}, (id) => (id.identifiers ?? []).map((i) => i.toHuman()).join(" + "));
|
|
669
|
+
export const ExpertCommentaryClass = bsiClassWith({ kind: "expert-commentary", rootKind: "base" }, {
|
|
670
|
+
base: { type: BsiIdentifier },
|
|
671
|
+
format: { type: "string" },
|
|
672
|
+
topic: { type: "string" },
|
|
673
|
+
}, (id) => {
|
|
674
|
+
let baseStr = id.base?.toHuman() ?? "";
|
|
675
|
+
baseStr = baseStr.replace(/ (Expert Commentary|ExComm(\s*\(.*\))?)$/, "");
|
|
676
|
+
if (id.format === "full")
|
|
677
|
+
return `${baseStr} Expert Commentary`;
|
|
678
|
+
if (id.format === "abbr_with_topic")
|
|
679
|
+
return `${baseStr} ExComm (${id.topic})`;
|
|
680
|
+
return `${baseStr} ExComm`;
|
|
681
|
+
});
|
|
682
|
+
export const ValueAddedPublicationClass = (() => {
|
|
683
|
+
const klass = bsiClassWith({ kind: "value-added-publication", rootKind: "base" }, {
|
|
684
|
+
base: { type: BsiIdentifier },
|
|
685
|
+
format: { type: "string" },
|
|
686
|
+
}, (id) => {
|
|
687
|
+
const baseStr = id.base?.toHuman() ?? "";
|
|
688
|
+
if (id.format === "TC")
|
|
689
|
+
return `${baseStr} - TC`;
|
|
690
|
+
if (id.format === "PDF")
|
|
691
|
+
return `${baseStr} PDF`;
|
|
692
|
+
if (id.format === "BOOK")
|
|
693
|
+
return `${baseStr} BOOK`;
|
|
694
|
+
return baseStr;
|
|
695
|
+
});
|
|
696
|
+
// #number/#year/#date delegate to base (value_added_publication.rb),
|
|
697
|
+
// so the wrapper's wire carries them.
|
|
698
|
+
klass.compactHash = (model, hash) => {
|
|
699
|
+
const base = model.base;
|
|
700
|
+
if (base === undefined)
|
|
701
|
+
return;
|
|
702
|
+
if (base.number !== undefined)
|
|
703
|
+
hash["number"] = base.number;
|
|
704
|
+
if (base.date?.present())
|
|
705
|
+
hash["year"] = base.date.render();
|
|
706
|
+
};
|
|
707
|
+
return klass;
|
|
708
|
+
})();
|
|
709
|
+
export const NationalAnnexClass = bsiClassWith({ kind: "national-annex", typeCode: "na", rootKind: "base" }, {
|
|
710
|
+
na_supplements: { type: BsiIdentifier, collection: true },
|
|
711
|
+
base: { type: BsiIdentifier },
|
|
712
|
+
}, (id) => {
|
|
713
|
+
let result = "NA";
|
|
714
|
+
for (const supp of id.na_supplements ?? []) {
|
|
715
|
+
const self = supp;
|
|
716
|
+
if (supp instanceof Amendment) {
|
|
717
|
+
result += `+A${self["number"]}:${self["year"]}`;
|
|
718
|
+
}
|
|
719
|
+
else if (supp instanceof Corrigendum) {
|
|
720
|
+
result += `+C${self["number"]}:${self["year"]}`;
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
result += " to ";
|
|
724
|
+
result += id.base !== undefined ? id.base.toHuman() : renderSingleIdentifier(id);
|
|
725
|
+
return result;
|
|
726
|
+
});
|
|
727
|
+
function renderAdopted(id) {
|
|
728
|
+
const prefix = id.publisher !== undefined ? id.publisher.render() : "BS";
|
|
729
|
+
let result = prefix;
|
|
730
|
+
if (id.base !== undefined)
|
|
731
|
+
result += ` ${id.base.toHuman()}`;
|
|
732
|
+
if (id.edition !== undefined)
|
|
733
|
+
result += ` ED${id.edition}`;
|
|
734
|
+
if (id.reaffirmation_year !== undefined)
|
|
735
|
+
result += ` (R${id.reaffirmation_year})`;
|
|
736
|
+
if (id.translation_lang !== undefined) {
|
|
737
|
+
result += id.translation_suffix_type === "version"
|
|
738
|
+
? ` (${id.translation_lang} version)`
|
|
739
|
+
: id.translation_suffix_type === "Translation"
|
|
740
|
+
? ` (${id.translation_lang} Translation)`
|
|
741
|
+
: ` (${id.translation_lang})`;
|
|
742
|
+
}
|
|
743
|
+
else if (id.translation_upper !== undefined) {
|
|
744
|
+
result += id.translation_suffix_type === "Translation"
|
|
745
|
+
? ` (${id.translation_upper} Translation)`
|
|
746
|
+
: ` (${id.translation_upper})`;
|
|
747
|
+
}
|
|
748
|
+
if (id.expert_commentary !== undefined && id.expert_commentary) {
|
|
749
|
+
result += id.expert_commentary_topic !== undefined
|
|
750
|
+
? ` ExComm (${id.expert_commentary_topic})`
|
|
751
|
+
: " ExComm";
|
|
752
|
+
}
|
|
753
|
+
return result;
|
|
754
|
+
}
|
|
755
|
+
const adoptedAttrs = {
|
|
756
|
+
base: { type: BsiIdentifier },
|
|
757
|
+
edition: { type: "string" },
|
|
758
|
+
translation_lang: { type: "string" },
|
|
759
|
+
translation_upper: { type: "string" },
|
|
760
|
+
translation_suffix_type: { type: "string" },
|
|
761
|
+
reaffirmation_year: { type: "string" },
|
|
762
|
+
expert_commentary: { type: "boolean" },
|
|
763
|
+
expert_commentary_topic: { type: "string" },
|
|
764
|
+
};
|
|
765
|
+
export const AdoptedEuropeanNormClass = bsiClassWith({ kind: "adopted-european-norm", rootKind: "base" }, adoptedAttrs, renderAdopted);
|
|
766
|
+
export const AdoptedInternationalStandardClass = bsiClassWith({ kind: "adopted-international-standard", rootKind: "base" }, adoptedAttrs, renderAdopted);
|
|
767
|
+
export const ConsolidatedIdentifierClass = bsiClassWith({ kind: "consolidated-identifier", rootKind: "first" }, {
|
|
768
|
+
identifiers: { type: BsiIdentifier, collection: true },
|
|
769
|
+
}, (id) => {
|
|
770
|
+
const [baseId, ...supplements] = id.identifiers ?? [];
|
|
771
|
+
if (baseId === undefined)
|
|
772
|
+
return "";
|
|
773
|
+
let result = baseId.toHuman()
|
|
774
|
+
.replace(/ ExComm \(.*?\)$/, "")
|
|
775
|
+
.replace(/ ExComm$/, "")
|
|
776
|
+
.replace(/ - TC$/, "")
|
|
777
|
+
.replace(/ PDF$/, "")
|
|
778
|
+
.replace(/ \([A-Z][a-z]+\)$/, "");
|
|
779
|
+
// The gem serializes only the `type` block onto the consolidated
|
|
780
|
+
// wrapper (the members carry their own full typed-stage trio).
|
|
781
|
+
ConsolidatedIdentifierClass.compactHash =
|
|
782
|
+
(model, hash) => {
|
|
783
|
+
const ts = model.typedStage;
|
|
784
|
+
if (ts === undefined || ts.code === "pubbs")
|
|
785
|
+
return;
|
|
786
|
+
hash["type"] = { name: ts.name, abbr: ts.abbr[0], type_code: ts.typeCode };
|
|
787
|
+
};
|
|
788
|
+
for (const supp of supplements) {
|
|
789
|
+
if (supp instanceof Amendment) {
|
|
790
|
+
if (supp.amd_suffix_form) {
|
|
791
|
+
result += supp.number !== undefined && /^[A-Z]+$/.test(supp.number)
|
|
792
|
+
? ` AMD ${supp.number}`
|
|
793
|
+
: ` AMD${supp.number ?? ""}`;
|
|
794
|
+
}
|
|
795
|
+
else {
|
|
796
|
+
result += `${supp.separator ?? "+"}A${supp.number ?? ""}`;
|
|
797
|
+
if (supp.year !== undefined)
|
|
798
|
+
result += `:${supp.year}`;
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
else if (supp instanceof Corrigendum) {
|
|
802
|
+
result += `${supp.separator ?? "+"}C`;
|
|
803
|
+
if (supp.number !== undefined)
|
|
804
|
+
result += supp.number;
|
|
805
|
+
if (supp.year !== undefined)
|
|
806
|
+
result += `:${supp.year}`;
|
|
807
|
+
}
|
|
808
|
+
else {
|
|
809
|
+
result += supp.toHuman();
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
const baseSelf = baseId;
|
|
813
|
+
if (baseSelf["expert_commentary"] !== undefined) {
|
|
814
|
+
result += baseSelf["expert_commentary_topic"] !== undefined
|
|
815
|
+
? ` ExComm (${baseSelf["expert_commentary_topic"]})`
|
|
816
|
+
: " ExComm";
|
|
817
|
+
}
|
|
818
|
+
if (baseSelf["tracked_changes"] !== undefined)
|
|
819
|
+
result += " - TC";
|
|
820
|
+
const tl = baseSelf["translation_lang"];
|
|
821
|
+
if (tl !== undefined) {
|
|
822
|
+
const tsType = baseSelf["translation_suffix_type"];
|
|
823
|
+
result += tsType === "version"
|
|
824
|
+
? ` (${tl} version)`
|
|
825
|
+
: tsType === "Translation"
|
|
826
|
+
? ` (${tl} Translation)`
|
|
827
|
+
: ` (${tl})`;
|
|
828
|
+
}
|
|
829
|
+
else {
|
|
830
|
+
const tu = baseSelf["translation_upper"];
|
|
831
|
+
if (tu !== undefined) {
|
|
832
|
+
const tsType = baseSelf["translation_suffix_type"];
|
|
833
|
+
result += tsType === "Translation" ? ` (${tu} Translation)` : ` (${tu})`;
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
const ry = baseSelf["reaffirmation_year"];
|
|
837
|
+
if (ry !== undefined)
|
|
838
|
+
result += ` (R${ry})`;
|
|
839
|
+
return result;
|
|
840
|
+
});
|
|
841
|
+
// ConsolidatedIdentifier#to_urn override (renderer.rb class method):
|
|
842
|
+
// base URN plus per-supplement segments.
|
|
843
|
+
export function consolidatedUrn(id) {
|
|
844
|
+
const [base, ...supplements] = id.identifiers ?? [];
|
|
845
|
+
if (base === undefined)
|
|
846
|
+
return undefined;
|
|
847
|
+
let urn = base.toUrn();
|
|
848
|
+
if (urn === undefined)
|
|
849
|
+
return undefined;
|
|
850
|
+
for (const supp of supplements) {
|
|
851
|
+
if (supp instanceof Amendment) {
|
|
852
|
+
urn += `:amd:${supp.number ?? ""}`;
|
|
853
|
+
if (supp.year !== undefined)
|
|
854
|
+
urn += `:${supp.year}`;
|
|
855
|
+
}
|
|
856
|
+
else if (supp instanceof Corrigendum) {
|
|
857
|
+
urn += `:cor:${supp.number ?? ""}`;
|
|
858
|
+
if (supp.year !== undefined)
|
|
859
|
+
urn += `:${supp.year}`;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
return urn;
|
|
863
|
+
}
|