@amazon/vinyl-xml 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -19,6 +19,22 @@ var __spreadValues = (a, b) => {
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
20
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
21
21
 
22
+ // src/xlink/actuateValidator.ts
23
+ import { isOneOf } from "@amazon/vinyl-validation";
24
+ import { ErrorOrigin } from "@amazon/vinyl-util";
25
+ var actuateValidator = /* @__PURE__ */ isOneOf("onLoad", "onRequest");
26
+ function assertActuateEnum(str) {
27
+ actuateValidator.assert(str, ErrorOrigin.PARSING);
28
+ return str;
29
+ }
30
+
31
+ // src/xml/mappedXmlRules.ts
32
+ import {
33
+ IllegalArgumentError,
34
+ invariant,
35
+ memoize
36
+ } from "@amazon/vinyl-util";
37
+
22
38
  // src/xml/xmlRules.ts
23
39
  import {
24
40
  parseDate,
@@ -87,241 +103,193 @@ function attrDateTime(options) {
87
103
  return attr(parseDate, stringifyDate, options);
88
104
  }
89
105
 
90
- // src/xml/stringifyXml.ts
91
- import {
92
- encodeEntities,
93
- equalDeep,
94
- getOrSet,
95
- substitute
96
- } from "@amazon/vinyl-util";
97
-
98
- // src/xml/XmlSchemaError.ts
99
- import { ErrorOrigin, ReportableError } from "@amazon/vinyl-util";
100
- var xmlSchemaErrorLocale = {
101
- atLeastElements: "Expected at least {expected} occurrences of {property} but was {actual}",
102
- atMostElements: "Expected at most {expected} occurrences of {property} but was {actual}",
103
- cyclicReferences: "Cyclic reference detected",
104
- requiredAttribute: `Attribute '{property}' is required`
105
- };
106
- var XmlSchemaError = class _XmlSchemaError extends ReportableError {
107
- get [Symbol.toStringTag]() {
108
- return "XmlSchemaError";
109
- }
110
- constructor(message) {
111
- super(message, ErrorOrigin.PARSING);
112
- Object.setPrototypeOf(this, _XmlSchemaError.prototype);
113
- }
114
- };
115
-
116
- // src/xml/stringifyXml.ts
117
- var locale = {
118
- /**
119
- * When a namespace binding is generated, if the prefix was not provided in the stringifier
120
- * options, it will be generated from this template.
121
- */
122
- prefixTemplate: "ns_{value}"
123
- };
124
- var defaultStringifyOptions = {
125
- indent: " ",
126
- newline: "\n",
127
- prefixMap: /* @__PURE__ */ new Map(),
128
- includeXmlDeclaration: true
106
+ // src/xml/mappedXmlRules.ts
107
+ var EmptyRules = {
108
+ __type: /* @__PURE__ */ invariant(),
109
+ attributes: /* @__PURE__ */ new Map(),
110
+ elements: /* @__PURE__ */ new Map(),
111
+ characters: void 0
129
112
  };
130
- var XmlWriter = class {
131
- constructor(rules, options) {
132
- __publicField(this, "rules", rules);
133
- __publicField(this, "options");
134
- __publicField(this, "usedPrefixes", /* @__PURE__ */ new Map());
135
- __publicField(this, "traversed", /* @__PURE__ */ new Set());
136
- this.options = __spreadValues(__spreadValues({}, defaultStringifyOptions), options);
137
- }
138
- stringify(object) {
139
- let str = this.options.includeXmlDeclaration ? '<?xml version="1.0"?>' + this.options.newline : "";
140
- const state = new StringifyState();
141
- str += this.stringifyChildren(object, this.rules.elements, state);
142
- this.usedPrefixes.clear();
143
- this.traversed.clear();
144
- return str;
145
- }
146
- qName(localPart, namespaceUri) {
147
- if (!namespaceUri) return localPart;
148
- const prefixMap = this.options.prefixMap;
149
- const prefix = getOrSet(this.usedPrefixes, namespaceUri, () => {
150
- if (prefixMap.has(namespaceUri)) {
151
- return prefixMap.get(namespaceUri);
152
- }
153
- return substitute(locale.prefixTemplate, {
154
- value: (this.usedPrefixes.size + 1).toString(36)
155
- });
156
- });
157
- return `${prefix}:${localPart}`;
158
- }
159
- /**
160
- * Stringifies an element.
161
- *
162
- * @param object
163
- * @param rule
164
- * @param state
165
- */
166
- stringifyElement(object, rule, state) {
167
- var _a2;
168
- if (this.traversed.has(object))
169
- throw new XmlSchemaError(xmlSchemaErrorLocale.cyclicReferences);
170
- this.traversed.add(object);
171
- const nl = this.options.newline;
172
- const isDocument = state.depth === 0;
173
- let namespaces = "";
174
- let xmlns = state.xmlns;
175
- if (xmlns !== rule.namespaceUri && (xmlns == null || !rule.namespaceUri)) {
176
- xmlns = rule.namespaceUri;
177
- namespaces += ` xmlns="${(_a2 = rule.namespaceUri) != null ? _a2 : ""}"`;
178
- }
179
- const childState = state.createChild(xmlns, this.options.indent);
180
- const rules = rule.rules();
181
- const attributes = this.stringifyAttributes(object, rules.attributes);
182
- const children = this.stringifyChildren(
183
- object,
184
- rules.elements,
185
- childState
186
- );
187
- const text = this.stringifyCharacters(object, rules.characters);
188
- if (isDocument) {
189
- this.usedPrefixes.forEach((prefix, uri) => {
190
- namespaces += ` xmlns:${prefix}="${uri}"`;
191
- });
192
- }
193
- const indent = state.indent;
194
- const childIndent = childState.indent;
195
- const qName2 = rule.namespaceUri === xmlns ? rule.localPart : this.qName(rule.localPart, rule.namespaceUri);
196
- let str = `${indent}<${qName2}${namespaces}${attributes}`;
197
- if (children) {
198
- str += `>`;
199
- if (text) str += `${nl}${childIndent}${text}`;
200
- str += nl + children;
201
- str += `${nl}${indent}</${qName2}>`;
202
- } else if (text) {
203
- str += `>${text}</${qName2}>`;
113
+ function mapXmlRules(rules, parentNamespaceUri = null) {
114
+ var _a2, _b, _c;
115
+ const attributeRules = /* @__PURE__ */ new Map();
116
+ const elementRules = /* @__PURE__ */ new Map();
117
+ let charactersRule = void 0;
118
+ for (const property in rules) {
119
+ const handlerOrFunction = rules[property];
120
+ let handler;
121
+ if (typeof handlerOrFunction === "function") {
122
+ handler = handlerOrFunction();
204
123
  } else {
205
- str += "/>";
124
+ handler = handlerOrFunction;
206
125
  }
207
- return str;
208
- }
209
- /**
210
- * Stringifies an element's attributes.
211
- *
212
- * @param object
213
- * @param attributes
214
- * @return Returns the attributes string. This will include a leading space if there are any
215
- * found attributes.
216
- */
217
- stringifyAttributes(object, attributes) {
218
- let str = "";
219
- attributes.forEach((attributeRule) => {
220
- const propertyValue = object[attributeRule.property];
221
- if (propertyValue !== void 0) {
222
- const attributeValue = attributeRule.stringify(propertyValue);
223
- if (attributeRule.default === void 0 || !equalDeep(propertyValue, attributeRule.default)) {
224
- str += ` ${this.qName(
225
- attributeRule.localPart,
226
- attributeRule.namespaceUri
227
- )}="${encodeEntities(attributeValue)}"`;
228
- }
229
- } else {
230
- if (attributeRule.required) {
231
- throw new XmlSchemaError(
232
- substitute(xmlSchemaErrorLocale.requiredAttribute, {
233
- property: attributeRule.property
234
- })
126
+ let key;
127
+ switch (handler.type) {
128
+ case "characters" /* CHARACTERS */:
129
+ if (charactersRule !== void 0)
130
+ throw new IllegalArgumentError(
131
+ "characters handler already defined"
132
+ );
133
+ charactersRule = {
134
+ property,
135
+ parse: handler.parse,
136
+ stringify: handler.stringify
137
+ };
138
+ break;
139
+ case "element" /* ELEMENT */:
140
+ case "elements" /* ELEMENTS */: {
141
+ const localPart = (_a2 = handler.localPart) != null ? _a2 : property;
142
+ const namespaceUri = handler.namespaceUri === void 0 ? parentNamespaceUri : handler.namespaceUri;
143
+ key = xmlRuleKey(localPart, namespaceUri);
144
+ if (elementRules.has(key)) {
145
+ throw new IllegalArgumentError(
146
+ `Multiple element rules for ${key}`
235
147
  );
236
148
  }
237
- }
238
- });
239
- return str;
240
- }
241
- /**
242
- * Stringifies a property as a CDATA node.
243
- *
244
- * @param object
245
- * @param charactersRule
246
- */
247
- stringifyCharacters(object, charactersRule) {
248
- if (!charactersRule) return null;
249
- const str = charactersRule.stringify(object[charactersRule.property]);
250
- if (!str) return "";
251
- return `<![CDATA[${str}]]>`;
252
- }
253
- /**
254
- * Stringifies an element's child elements.
255
- *
256
- * @param object
257
- * @param elements
258
- * @param state
259
- */
260
- stringifyChildren(object, elements2, state) {
261
- let str = "";
262
- elements2.forEach((elementsRule) => {
263
- const child = object[elementsRule.property];
264
- if (child) {
265
- if (elementsRule.array) {
266
- const arr = child;
267
- if (elementsRule.minOccurs > arr.length) {
268
- throw new XmlSchemaError(
269
- substitute(xmlSchemaErrorLocale.atLeastElements, {
270
- property: elementsRule.property,
271
- expected: elementsRule.minOccurs,
272
- actual: arr.length
273
- })
274
- );
275
- }
276
- if (elementsRule.maxOccurs != null && elementsRule.maxOccurs < arr.length) {
277
- throw new XmlSchemaError(
278
- substitute(xmlSchemaErrorLocale.atMostElements, {
279
- property: elementsRule.property,
280
- expected: elementsRule.maxOccurs,
281
- actual: arr.length
282
- })
283
- );
284
- }
285
- for (const element2 of arr) {
286
- if (str) str += this.options.newline;
287
- str += this.stringifyElement(
288
- element2,
289
- elementsRule,
290
- state
291
- );
292
- }
149
+ if (handler.type === "element" /* ELEMENT */) {
150
+ const rules2 = handler.rules;
151
+ elementRules.set(key, {
152
+ array: false,
153
+ property,
154
+ minOccurs: handler.required ? 1 : 0,
155
+ maxOccurs: 1,
156
+ rules: memoize(() => mapXmlRules(rules2, namespaceUri)),
157
+ useEmptyArrays: false,
158
+ localPart,
159
+ namespaceUri
160
+ });
293
161
  } else {
294
- if (str) str += this.options.newline;
295
- str += this.stringifyElement(child, elementsRule, state);
162
+ const rules2 = handler.rules;
163
+ elementRules.set(key, {
164
+ array: true,
165
+ property,
166
+ maxOccurs: handler.maxOccurs,
167
+ minOccurs: handler.minOccurs,
168
+ rules: memoize(() => mapXmlRules(rules2, namespaceUri)),
169
+ useEmptyArrays: handler.useEmptyArrays,
170
+ localPart,
171
+ namespaceUri
172
+ });
296
173
  }
297
- } else {
298
- if (elementsRule.minOccurs > 0) {
299
- throw new XmlSchemaError(
300
- substitute(xmlSchemaErrorLocale.atLeastElements, {
301
- property: elementsRule.property,
302
- expected: elementsRule.minOccurs,
303
- actual: 0
304
- })
174
+ break;
175
+ }
176
+ case "attribute" /* ATTRIBUTE */: {
177
+ const namespaceUri = handler.namespaceUri;
178
+ const localPart = (_b = handler.localPart) != null ? _b : property;
179
+ key = xmlRuleKey(localPart, namespaceUri);
180
+ if (attributeRules.has(key)) {
181
+ throw new IllegalArgumentError(
182
+ `Multiple attribute rules for ${key}`
305
183
  );
306
184
  }
185
+ attributeRules.set(key, {
186
+ property,
187
+ default: handler.default,
188
+ parse: handler.parse,
189
+ stringify: handler.stringify,
190
+ required: handler.required,
191
+ localPart,
192
+ namespaceUri: (_c = handler.namespaceUri) != null ? _c : null
193
+ });
194
+ break;
307
195
  }
308
- });
309
- return str;
196
+ }
310
197
  }
198
+ return {
199
+ __type: invariant(),
200
+ attributes: attributeRules,
201
+ elements: elementRules,
202
+ characters: charactersRule
203
+ };
204
+ }
205
+ function xmlRuleKey(localPart, namespaceUri = null) {
206
+ return `${namespaceUri != null ? namespaceUri : ""}:${localPart}`;
207
+ }
208
+
209
+ // src/xml/mergeXmlRules.ts
210
+ import {
211
+ plainObjectMergeRule,
212
+ substitute,
213
+ ValidationError
214
+ } from "@amazon/vinyl-util";
215
+ var locale = {
216
+ illegalRuleOverrideTypeError: "Cannot override the rule {property} of type {sourceType} with a rule of type {overrideType}",
217
+ illegalQNameOverrideError: "Cannot override the rule {property} with a different localPart or namespace"
311
218
  };
312
- var StringifyState = class _StringifyState {
313
- constructor(depth = 0, xmlns = null, indent = "") {
314
- __publicField(this, "depth", depth);
315
- __publicField(this, "xmlns", xmlns);
316
- __publicField(this, "indent", indent);
219
+ function mergeXmlRules(...rules) {
220
+ let finalRule = rules[0];
221
+ for (let i = 1; i < rules.length; i++) {
222
+ finalRule = plainObjectMergeRule.merge(
223
+ finalRule,
224
+ rules[i],
225
+ mergeXmlRule
226
+ );
227
+ }
228
+ return finalRule;
229
+ }
230
+ function mergeXmlRule(sourceA, sourceB, prop) {
231
+ var _a2, _b, _c, _d;
232
+ if (sourceA == null) return sourceB;
233
+ const sourceAIsLazy = typeof sourceA === "function";
234
+ const sourceBIsLazy = typeof sourceB === "function";
235
+ if (sourceAIsLazy || sourceBIsLazy) {
236
+ return () => {
237
+ const a = sourceAIsLazy ? sourceA() : sourceA;
238
+ const b = sourceBIsLazy ? sourceB() : sourceB;
239
+ return mergeXmlRule(a, b, prop);
240
+ };
241
+ }
242
+ if (sourceA.type !== sourceB.type) {
243
+ throw new ValidationError(
244
+ substitute(locale.illegalRuleOverrideTypeError, {
245
+ property: prop,
246
+ sourceType: sourceA.type,
247
+ overrideType: sourceB.type
248
+ })
249
+ );
250
+ }
251
+ switch (sourceA.type) {
252
+ case "attribute" /* ATTRIBUTE */:
253
+ case "element" /* ELEMENT */:
254
+ case "elements" /* ELEMENTS */: {
255
+ const b = sourceB;
256
+ if (sourceA.namespaceUri !== b.namespaceUri || ((_a2 = sourceA.localPart) != null ? _a2 : prop) !== ((_b = b.localPart) != null ? _b : prop)) {
257
+ throw new ValidationError(
258
+ substitute(locale.illegalQNameOverrideError, {
259
+ property: prop
260
+ })
261
+ );
262
+ }
263
+ break;
264
+ }
317
265
  }
318
- createChild(xmlns, indent) {
319
- return new _StringifyState(this.depth + 1, xmlns, this.indent + indent);
266
+ switch (sourceA.type) {
267
+ case "attribute" /* ATTRIBUTE */: {
268
+ const b = sourceB;
269
+ return __spreadProps(__spreadValues({}, b), {
270
+ default: (_c = b.default) != null ? _c : sourceA.default
271
+ });
272
+ }
273
+ case "characters" /* CHARACTERS */:
274
+ return sourceB;
275
+ case "element" /* ELEMENT */: {
276
+ const b = sourceB;
277
+ return __spreadProps(__spreadValues({}, b), {
278
+ required: sourceA.required || b.required,
279
+ rules: mergeXmlRules(sourceA.rules, b.rules)
280
+ });
281
+ }
282
+ case "elements" /* ELEMENTS */: {
283
+ const b = sourceB;
284
+ const maxOccurs = sourceA.maxOccurs != null && b.maxOccurs != null ? Math.min(sourceA.maxOccurs, b.maxOccurs) : (_d = sourceA.maxOccurs) != null ? _d : b.maxOccurs;
285
+ return __spreadProps(__spreadValues({}, b), {
286
+ minOccurs: Math.max(sourceA.minOccurs, b.minOccurs),
287
+ maxOccurs,
288
+ useEmptyArrays: sourceA.useEmptyArrays || b.useEmptyArrays,
289
+ rules: mergeXmlRules(sourceA.rules, b.rules)
290
+ });
291
+ }
320
292
  }
321
- };
322
- function stringifyXml(object, rules, options) {
323
- const writer = new XmlWriter(rules, options);
324
- return writer.stringify(object);
325
293
  }
326
294
 
327
295
  // src/xml/parseXml.ts
@@ -535,223 +503,19 @@ function xmlAttributes(reader, stackElement) {
535
503
  }
536
504
  if (name.prefix === "xmlns") {
537
505
  name.namespaceUri = XMLNS;
538
- stackElement.namespaceMap.set(
539
- name.localPart,
540
- value === "" ? null : value
541
- );
542
- } else if (!name.prefix && name.localPart === "xmlns") {
543
- name.namespaceUri = XMLNS;
544
- stackElement.defaultNamespaceUri = !value ? null : value;
545
- }
546
- if (attributes[name.qName] != null)
547
- reader.err(`Attribute '${name.qName}' is already specified.`);
548
- attributes[name.qName] = { name, value };
549
- }
550
- return attributes;
551
- }
552
-
553
- // src/xml/mergeXmlRules.ts
554
- import {
555
- plainObjectMergeRule,
556
- substitute as substitute2,
557
- ValidationError
558
- } from "@amazon/vinyl-util";
559
- var locale2 = {
560
- illegalRuleOverrideTypeError: "Cannot override the rule {property} of type {sourceType} with a rule of type {overrideType}",
561
- illegalQNameOverrideError: "Cannot override the rule {property} with a different localPart or namespace"
562
- };
563
- function mergeXmlRules(...rules) {
564
- let finalRule = rules[0];
565
- for (let i = 1; i < rules.length; i++) {
566
- finalRule = plainObjectMergeRule.merge(
567
- finalRule,
568
- rules[i],
569
- mergeXmlRule
570
- );
571
- }
572
- return finalRule;
573
- }
574
- function mergeXmlRule(sourceA, sourceB, prop) {
575
- var _a2, _b, _c, _d;
576
- if (sourceA == null) return sourceB;
577
- const sourceAIsLazy = typeof sourceA === "function";
578
- const sourceBIsLazy = typeof sourceB === "function";
579
- if (sourceAIsLazy || sourceBIsLazy) {
580
- return () => {
581
- const a = sourceAIsLazy ? sourceA() : sourceA;
582
- const b = sourceBIsLazy ? sourceB() : sourceB;
583
- return mergeXmlRule(a, b, prop);
584
- };
585
- }
586
- if (sourceA.type !== sourceB.type) {
587
- throw new ValidationError(
588
- substitute2(locale2.illegalRuleOverrideTypeError, {
589
- property: prop,
590
- sourceType: sourceA.type,
591
- overrideType: sourceB.type
592
- })
593
- );
594
- }
595
- switch (sourceA.type) {
596
- case "attribute" /* ATTRIBUTE */:
597
- case "element" /* ELEMENT */:
598
- case "elements" /* ELEMENTS */: {
599
- const b = sourceB;
600
- if (sourceA.namespaceUri !== b.namespaceUri || ((_a2 = sourceA.localPart) != null ? _a2 : prop) !== ((_b = b.localPart) != null ? _b : prop)) {
601
- throw new ValidationError(
602
- substitute2(locale2.illegalQNameOverrideError, {
603
- property: prop
604
- })
605
- );
606
- }
607
- break;
608
- }
609
- }
610
- switch (sourceA.type) {
611
- case "attribute" /* ATTRIBUTE */: {
612
- const b = sourceB;
613
- return __spreadProps(__spreadValues({}, b), {
614
- default: (_c = b.default) != null ? _c : sourceA.default
615
- });
616
- }
617
- case "characters" /* CHARACTERS */:
618
- return sourceB;
619
- case "element" /* ELEMENT */: {
620
- const b = sourceB;
621
- return __spreadProps(__spreadValues({}, b), {
622
- required: sourceA.required || b.required,
623
- rules: mergeXmlRules(sourceA.rules, b.rules)
624
- });
625
- }
626
- case "elements" /* ELEMENTS */: {
627
- const b = sourceB;
628
- const maxOccurs = sourceA.maxOccurs != null && b.maxOccurs != null ? Math.min(sourceA.maxOccurs, b.maxOccurs) : (_d = sourceA.maxOccurs) != null ? _d : b.maxOccurs;
629
- return __spreadProps(__spreadValues({}, b), {
630
- minOccurs: Math.max(sourceA.minOccurs, b.minOccurs),
631
- maxOccurs,
632
- useEmptyArrays: sourceA.useEmptyArrays || b.useEmptyArrays,
633
- rules: mergeXmlRules(sourceA.rules, b.rules)
634
- });
635
- }
636
- }
637
- }
638
-
639
- // src/xml/mappedXmlRules.ts
640
- import {
641
- IllegalArgumentError,
642
- invariant,
643
- memoize
644
- } from "@amazon/vinyl-util";
645
- var EmptyRules = {
646
- __type: /* @__PURE__ */ invariant(),
647
- attributes: /* @__PURE__ */ new Map(),
648
- elements: /* @__PURE__ */ new Map(),
649
- characters: void 0
650
- };
651
- function mapXmlRules(rules, parentNamespaceUri = null) {
652
- var _a2, _b, _c;
653
- const attributeRules = /* @__PURE__ */ new Map();
654
- const elementRules = /* @__PURE__ */ new Map();
655
- let charactersRule = void 0;
656
- for (const property in rules) {
657
- const handlerOrFunction = rules[property];
658
- let handler;
659
- if (typeof handlerOrFunction === "function") {
660
- handler = handlerOrFunction();
661
- } else {
662
- handler = handlerOrFunction;
663
- }
664
- let key;
665
- switch (handler.type) {
666
- case "characters" /* CHARACTERS */:
667
- if (charactersRule !== void 0)
668
- throw new IllegalArgumentError(
669
- "characters handler already defined"
670
- );
671
- charactersRule = {
672
- property,
673
- parse: handler.parse,
674
- stringify: handler.stringify
675
- };
676
- break;
677
- case "element" /* ELEMENT */:
678
- case "elements" /* ELEMENTS */: {
679
- const localPart = (_a2 = handler.localPart) != null ? _a2 : property;
680
- const namespaceUri = handler.namespaceUri === void 0 ? parentNamespaceUri : handler.namespaceUri;
681
- key = xmlRuleKey(localPart, namespaceUri);
682
- if (elementRules.has(key)) {
683
- throw new IllegalArgumentError(
684
- `Multiple element rules for ${key}`
685
- );
686
- }
687
- if (handler.type === "element" /* ELEMENT */) {
688
- const rules2 = handler.rules;
689
- elementRules.set(key, {
690
- array: false,
691
- property,
692
- minOccurs: handler.required ? 1 : 0,
693
- maxOccurs: 1,
694
- rules: memoize(() => mapXmlRules(rules2, namespaceUri)),
695
- useEmptyArrays: false,
696
- localPart,
697
- namespaceUri
698
- });
699
- } else {
700
- const rules2 = handler.rules;
701
- elementRules.set(key, {
702
- array: true,
703
- property,
704
- maxOccurs: handler.maxOccurs,
705
- minOccurs: handler.minOccurs,
706
- rules: memoize(() => mapXmlRules(rules2, namespaceUri)),
707
- useEmptyArrays: handler.useEmptyArrays,
708
- localPart,
709
- namespaceUri
710
- });
711
- }
712
- break;
713
- }
714
- case "attribute" /* ATTRIBUTE */: {
715
- const namespaceUri = handler.namespaceUri;
716
- const localPart = (_b = handler.localPart) != null ? _b : property;
717
- key = xmlRuleKey(localPart, namespaceUri);
718
- if (attributeRules.has(key)) {
719
- throw new IllegalArgumentError(
720
- `Multiple attribute rules for ${key}`
721
- );
722
- }
723
- attributeRules.set(key, {
724
- property,
725
- default: handler.default,
726
- parse: handler.parse,
727
- stringify: handler.stringify,
728
- required: handler.required,
729
- localPart,
730
- namespaceUri: (_c = handler.namespaceUri) != null ? _c : null
731
- });
732
- break;
733
- }
734
- }
735
- }
736
- return {
737
- __type: invariant(),
738
- attributes: attributeRules,
739
- elements: elementRules,
740
- characters: charactersRule
741
- };
742
- }
743
- function xmlRuleKey(localPart, namespaceUri = null) {
744
- return `${namespaceUri != null ? namespaceUri : ""}:${localPart}`;
745
- }
746
-
747
- // src/xml/QName.ts
748
- function qName(localPart, prefix = null, namespaceUri = null) {
749
- return {
750
- localPart,
751
- prefix,
752
- namespaceUri,
753
- qName: prefix ? `${prefix}:${localPart}` : localPart
754
- };
506
+ stackElement.namespaceMap.set(
507
+ name.localPart,
508
+ value === "" ? null : value
509
+ );
510
+ } else if (!name.prefix && name.localPart === "xmlns") {
511
+ name.namespaceUri = XMLNS;
512
+ stackElement.defaultNamespaceUri = !value ? null : value;
513
+ }
514
+ if (attributes[name.qName] != null)
515
+ reader.err(`Attribute '${name.qName}' is already specified.`);
516
+ attributes[name.qName] = { name, value };
517
+ }
518
+ return attributes;
755
519
  }
756
520
 
757
521
  // src/xml/ParseXmlHandlerImpl.ts
@@ -760,9 +524,29 @@ import {
760
524
  decodeEntities as decodeEntities2,
761
525
  IllegalStateError,
762
526
  last as last2,
763
- substitute as substitute3,
527
+ substitute as substitute2,
764
528
  toJson
765
529
  } from "@amazon/vinyl-util";
530
+
531
+ // src/xml/XmlSchemaError.ts
532
+ import { ErrorOrigin as ErrorOrigin2, ReportableError } from "@amazon/vinyl-util";
533
+ var xmlSchemaErrorLocale = {
534
+ atLeastElements: "Expected at least {expected} occurrences of {property} but was {actual}",
535
+ atMostElements: "Expected at most {expected} occurrences of {property} but was {actual}",
536
+ cyclicReferences: "Cyclic reference detected",
537
+ requiredAttribute: `Attribute '{property}' is required`
538
+ };
539
+ var XmlSchemaError = class _XmlSchemaError extends ReportableError {
540
+ get [Symbol.toStringTag]() {
541
+ return "XmlSchemaError";
542
+ }
543
+ constructor(message) {
544
+ super(message, ErrorOrigin2.PARSING);
545
+ Object.setPrototypeOf(this, _XmlSchemaError.prototype);
546
+ }
547
+ };
548
+
549
+ // src/xml/ParseXmlHandlerImpl.ts
766
550
  function getRule(name, rules) {
767
551
  return rules.get(xmlRuleKey(name.localPart, name.namespaceUri));
768
552
  }
@@ -828,7 +612,7 @@ var ParseXmlHandlerImpl = class {
828
612
  element2[rule.property] = rule.default;
829
613
  } else if (this.options.validateRules && rule.required) {
830
614
  throw new XmlSchemaError(
831
- substitute3(xmlSchemaErrorLocale.requiredAttribute, {
615
+ substitute2(xmlSchemaErrorLocale.requiredAttribute, {
832
616
  property: rule.property
833
617
  })
834
618
  );
@@ -881,7 +665,7 @@ var ParseXmlHandlerImpl = class {
881
665
  const length = rule.array ? (_b = (_a2 = current.element[rule.property]) == null ? void 0 : _a2.length) != null ? _b : 0 : current.element[rule.property] ? 1 : 0;
882
666
  if (length < rule.minOccurs) {
883
667
  throw new XmlSchemaError(
884
- substitute3(xmlSchemaErrorLocale.atLeastElements, {
668
+ substitute2(xmlSchemaErrorLocale.atLeastElements, {
885
669
  property: rule.property,
886
670
  expected: rule.minOccurs,
887
671
  actual: length
@@ -890,7 +674,7 @@ var ParseXmlHandlerImpl = class {
890
674
  }
891
675
  if (rule.maxOccurs != null && length > rule.maxOccurs) {
892
676
  throw new XmlSchemaError(
893
- substitute3(xmlSchemaErrorLocale.atMostElements, {
677
+ substitute2(xmlSchemaErrorLocale.atMostElements, {
894
678
  property: rule.property,
895
679
  expected: rule.maxOccurs,
896
680
  actual: length
@@ -942,13 +726,231 @@ var _XmlElementImpl = class _XmlElementImpl {
942
726
  };
943
727
  var XmlElementImpl = _XmlElementImpl;
944
728
 
945
- // src/xlink/actuateValidator.ts
946
- import { isOneOf } from "@amazon/vinyl-validation";
947
- import { ErrorOrigin as ErrorOrigin2 } from "@amazon/vinyl-util";
948
- var actuateValidator = /* @__PURE__ */ isOneOf("onLoad", "onRequest");
949
- function assertActuateEnum(str) {
950
- actuateValidator.assert(str, ErrorOrigin2.PARSING);
951
- return str;
729
+ // src/xml/QName.ts
730
+ function qName(localPart, prefix = null, namespaceUri = null) {
731
+ return {
732
+ localPart,
733
+ prefix,
734
+ namespaceUri,
735
+ qName: prefix ? `${prefix}:${localPart}` : localPart
736
+ };
737
+ }
738
+
739
+ // src/xml/stringifyXml.ts
740
+ import {
741
+ encodeEntities,
742
+ equalDeep,
743
+ getOrSet,
744
+ substitute as substitute3
745
+ } from "@amazon/vinyl-util";
746
+ var locale2 = {
747
+ /**
748
+ * When a namespace binding is generated, if the prefix was not provided in the stringifier
749
+ * options, it will be generated from this template.
750
+ */
751
+ prefixTemplate: "ns_{value}"
752
+ };
753
+ var defaultStringifyOptions = {
754
+ indent: " ",
755
+ newline: "\n",
756
+ prefixMap: /* @__PURE__ */ new Map(),
757
+ includeXmlDeclaration: true
758
+ };
759
+ var XmlWriter = class {
760
+ constructor(rules, options) {
761
+ __publicField(this, "rules", rules);
762
+ __publicField(this, "options");
763
+ __publicField(this, "usedPrefixes", /* @__PURE__ */ new Map());
764
+ __publicField(this, "traversed", /* @__PURE__ */ new Set());
765
+ this.options = __spreadValues(__spreadValues({}, defaultStringifyOptions), options);
766
+ }
767
+ stringify(object) {
768
+ let str = this.options.includeXmlDeclaration ? '<?xml version="1.0"?>' + this.options.newline : "";
769
+ const state = new StringifyState();
770
+ str += this.stringifyChildren(object, this.rules.elements, state);
771
+ this.usedPrefixes.clear();
772
+ this.traversed.clear();
773
+ return str;
774
+ }
775
+ qName(localPart, namespaceUri) {
776
+ if (!namespaceUri) return localPart;
777
+ const prefixMap = this.options.prefixMap;
778
+ const prefix = getOrSet(this.usedPrefixes, namespaceUri, () => {
779
+ if (prefixMap.has(namespaceUri)) {
780
+ return prefixMap.get(namespaceUri);
781
+ }
782
+ return substitute3(locale2.prefixTemplate, {
783
+ value: (this.usedPrefixes.size + 1).toString(36)
784
+ });
785
+ });
786
+ return `${prefix}:${localPart}`;
787
+ }
788
+ /**
789
+ * Stringifies an element.
790
+ *
791
+ * @param object
792
+ * @param rule
793
+ * @param state
794
+ */
795
+ stringifyElement(object, rule, state) {
796
+ var _a2;
797
+ if (this.traversed.has(object))
798
+ throw new XmlSchemaError(xmlSchemaErrorLocale.cyclicReferences);
799
+ this.traversed.add(object);
800
+ const nl = this.options.newline;
801
+ const isDocument = state.depth === 0;
802
+ let namespaces = "";
803
+ let xmlns = state.xmlns;
804
+ if (xmlns !== rule.namespaceUri && (xmlns == null || !rule.namespaceUri)) {
805
+ xmlns = rule.namespaceUri;
806
+ namespaces += ` xmlns="${(_a2 = rule.namespaceUri) != null ? _a2 : ""}"`;
807
+ }
808
+ const childState = state.createChild(xmlns, this.options.indent);
809
+ const rules = rule.rules();
810
+ const attributes = this.stringifyAttributes(object, rules.attributes);
811
+ const children = this.stringifyChildren(
812
+ object,
813
+ rules.elements,
814
+ childState
815
+ );
816
+ const text = this.stringifyCharacters(object, rules.characters);
817
+ if (isDocument) {
818
+ this.usedPrefixes.forEach((prefix, uri) => {
819
+ namespaces += ` xmlns:${prefix}="${uri}"`;
820
+ });
821
+ }
822
+ const indent = state.indent;
823
+ const childIndent = childState.indent;
824
+ const qName2 = rule.namespaceUri === xmlns ? rule.localPart : this.qName(rule.localPart, rule.namespaceUri);
825
+ let str = `${indent}<${qName2}${namespaces}${attributes}`;
826
+ if (children) {
827
+ str += `>`;
828
+ if (text) str += `${nl}${childIndent}${text}`;
829
+ str += nl + children;
830
+ str += `${nl}${indent}</${qName2}>`;
831
+ } else if (text) {
832
+ str += `>${text}</${qName2}>`;
833
+ } else {
834
+ str += "/>";
835
+ }
836
+ return str;
837
+ }
838
+ /**
839
+ * Stringifies an element's attributes.
840
+ *
841
+ * @param object
842
+ * @param attributes
843
+ * @return Returns the attributes string. This will include a leading space if there are any
844
+ * found attributes.
845
+ */
846
+ stringifyAttributes(object, attributes) {
847
+ let str = "";
848
+ attributes.forEach((attributeRule) => {
849
+ const propertyValue = object[attributeRule.property];
850
+ if (propertyValue !== void 0) {
851
+ const attributeValue = attributeRule.stringify(propertyValue);
852
+ if (attributeRule.default === void 0 || !equalDeep(propertyValue, attributeRule.default)) {
853
+ str += ` ${this.qName(
854
+ attributeRule.localPart,
855
+ attributeRule.namespaceUri
856
+ )}="${encodeEntities(attributeValue)}"`;
857
+ }
858
+ } else {
859
+ if (attributeRule.required) {
860
+ throw new XmlSchemaError(
861
+ substitute3(xmlSchemaErrorLocale.requiredAttribute, {
862
+ property: attributeRule.property
863
+ })
864
+ );
865
+ }
866
+ }
867
+ });
868
+ return str;
869
+ }
870
+ /**
871
+ * Stringifies a property as a CDATA node.
872
+ *
873
+ * @param object
874
+ * @param charactersRule
875
+ */
876
+ stringifyCharacters(object, charactersRule) {
877
+ if (!charactersRule) return null;
878
+ const str = charactersRule.stringify(object[charactersRule.property]);
879
+ if (!str) return "";
880
+ return `<![CDATA[${str}]]>`;
881
+ }
882
+ /**
883
+ * Stringifies an element's child elements.
884
+ *
885
+ * @param object
886
+ * @param elements
887
+ * @param state
888
+ */
889
+ stringifyChildren(object, elements2, state) {
890
+ let str = "";
891
+ elements2.forEach((elementsRule) => {
892
+ const child = object[elementsRule.property];
893
+ if (child) {
894
+ if (elementsRule.array) {
895
+ const arr = child;
896
+ if (elementsRule.minOccurs > arr.length) {
897
+ throw new XmlSchemaError(
898
+ substitute3(xmlSchemaErrorLocale.atLeastElements, {
899
+ property: elementsRule.property,
900
+ expected: elementsRule.minOccurs,
901
+ actual: arr.length
902
+ })
903
+ );
904
+ }
905
+ if (elementsRule.maxOccurs != null && elementsRule.maxOccurs < arr.length) {
906
+ throw new XmlSchemaError(
907
+ substitute3(xmlSchemaErrorLocale.atMostElements, {
908
+ property: elementsRule.property,
909
+ expected: elementsRule.maxOccurs,
910
+ actual: arr.length
911
+ })
912
+ );
913
+ }
914
+ for (const element2 of arr) {
915
+ if (str) str += this.options.newline;
916
+ str += this.stringifyElement(
917
+ element2,
918
+ elementsRule,
919
+ state
920
+ );
921
+ }
922
+ } else {
923
+ if (str) str += this.options.newline;
924
+ str += this.stringifyElement(child, elementsRule, state);
925
+ }
926
+ } else {
927
+ if (elementsRule.minOccurs > 0) {
928
+ throw new XmlSchemaError(
929
+ substitute3(xmlSchemaErrorLocale.atLeastElements, {
930
+ property: elementsRule.property,
931
+ expected: elementsRule.minOccurs,
932
+ actual: 0
933
+ })
934
+ );
935
+ }
936
+ }
937
+ });
938
+ return str;
939
+ }
940
+ };
941
+ var StringifyState = class _StringifyState {
942
+ constructor(depth = 0, xmlns = null, indent = "") {
943
+ __publicField(this, "depth", depth);
944
+ __publicField(this, "xmlns", xmlns);
945
+ __publicField(this, "indent", indent);
946
+ }
947
+ createChild(xmlns, indent) {
948
+ return new _StringifyState(this.depth + 1, xmlns, this.indent + indent);
949
+ }
950
+ };
951
+ function stringifyXml(object, rules, options) {
952
+ const writer = new XmlWriter(rules, options);
953
+ return writer.stringify(object);
952
954
  }
953
955
  export {
954
956
  EmptyRules,