@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.cjs CHANGED
@@ -72,8 +72,20 @@ __export(index_exports, {
72
72
  });
73
73
  module.exports = __toCommonJS(index_exports);
74
74
 
75
- // src/xml/xmlRules.ts
75
+ // src/xlink/actuateValidator.ts
76
+ var import_vinyl_validation = require("@amazon/vinyl-validation");
76
77
  var import_vinyl_util = require("@amazon/vinyl-util");
78
+ var actuateValidator = /* @__PURE__ */ (0, import_vinyl_validation.isOneOf)("onLoad", "onRequest");
79
+ function assertActuateEnum(str) {
80
+ actuateValidator.assert(str, import_vinyl_util.ErrorOrigin.PARSING);
81
+ return str;
82
+ }
83
+
84
+ // src/xml/mappedXmlRules.ts
85
+ var import_vinyl_util3 = require("@amazon/vinyl-util");
86
+
87
+ // src/xml/xmlRules.ts
88
+ var import_vinyl_util2 = require("@amazon/vinyl-util");
77
89
  var XmlRuleType = /* @__PURE__ */ ((XmlRuleType2) => {
78
90
  XmlRuleType2["CHARACTERS"] = "characters";
79
91
  XmlRuleType2["ATTRIBUTE"] = "attribute";
@@ -106,7 +118,7 @@ function elements(rules, options) {
106
118
  function characters(parse, stringify2) {
107
119
  return { type: "characters" /* CHARACTERS */, parse, stringify: stringify2 };
108
120
  }
109
- var charactersString = /* @__PURE__ */ characters((i) => i, import_vinyl_util.stringify);
121
+ var charactersString = /* @__PURE__ */ characters((i) => i, import_vinyl_util2.stringify);
110
122
  function attr(parse, stringify2, options) {
111
123
  return __spreadProps(__spreadValues({
112
124
  type: "attribute" /* ATTRIBUTE */,
@@ -120,268 +132,221 @@ function attr(parse, stringify2, options) {
120
132
  });
121
133
  }
122
134
  function attrString(options) {
123
- return attr((i) => i, import_vinyl_util.stringify, options);
135
+ return attr((i) => i, import_vinyl_util2.stringify, options);
124
136
  }
125
137
  function attrInt(options) {
126
- return attr(parseInt, import_vinyl_util.stringify, options);
138
+ return attr(parseInt, import_vinyl_util2.stringify, options);
127
139
  }
128
140
  function attrFloat(options) {
129
- return attr(parseFloat, import_vinyl_util.stringify, options);
141
+ return attr(parseFloat, import_vinyl_util2.stringify, options);
130
142
  }
131
143
  function attrBoolean(options) {
132
- return attr(import_vinyl_util.parseBoolean, import_vinyl_util.stringify, options);
144
+ return attr(import_vinyl_util2.parseBoolean, import_vinyl_util2.stringify, options);
133
145
  }
134
146
  function attrDateTime(options) {
135
- return attr(import_vinyl_util.parseDate, import_vinyl_util.stringifyDate, options);
147
+ return attr(import_vinyl_util2.parseDate, import_vinyl_util2.stringifyDate, options);
136
148
  }
137
149
 
138
- // src/xml/stringifyXml.ts
139
- var import_vinyl_util3 = require("@amazon/vinyl-util");
140
-
141
- // src/xml/XmlSchemaError.ts
142
- var import_vinyl_util2 = require("@amazon/vinyl-util");
143
- var xmlSchemaErrorLocale = {
144
- atLeastElements: "Expected at least {expected} occurrences of {property} but was {actual}",
145
- atMostElements: "Expected at most {expected} occurrences of {property} but was {actual}",
146
- cyclicReferences: "Cyclic reference detected",
147
- requiredAttribute: `Attribute '{property}' is required`
148
- };
149
- var XmlSchemaError = class _XmlSchemaError extends import_vinyl_util2.ReportableError {
150
- get [Symbol.toStringTag]() {
151
- return "XmlSchemaError";
152
- }
153
- constructor(message) {
154
- super(message, import_vinyl_util2.ErrorOrigin.PARSING);
155
- Object.setPrototypeOf(this, _XmlSchemaError.prototype);
156
- }
157
- };
158
-
159
- // src/xml/stringifyXml.ts
160
- var locale = {
161
- /**
162
- * When a namespace binding is generated, if the prefix was not provided in the stringifier
163
- * options, it will be generated from this template.
164
- */
165
- prefixTemplate: "ns_{value}"
166
- };
167
- var defaultStringifyOptions = {
168
- indent: " ",
169
- newline: "\n",
170
- prefixMap: /* @__PURE__ */ new Map(),
171
- includeXmlDeclaration: true
150
+ // src/xml/mappedXmlRules.ts
151
+ var EmptyRules = {
152
+ __type: /* @__PURE__ */ (0, import_vinyl_util3.invariant)(),
153
+ attributes: /* @__PURE__ */ new Map(),
154
+ elements: /* @__PURE__ */ new Map(),
155
+ characters: void 0
172
156
  };
173
- var XmlWriter = class {
174
- constructor(rules, options) {
175
- __publicField(this, "rules", rules);
176
- __publicField(this, "options");
177
- __publicField(this, "usedPrefixes", /* @__PURE__ */ new Map());
178
- __publicField(this, "traversed", /* @__PURE__ */ new Set());
179
- this.options = __spreadValues(__spreadValues({}, defaultStringifyOptions), options);
180
- }
181
- stringify(object) {
182
- let str = this.options.includeXmlDeclaration ? '<?xml version="1.0"?>' + this.options.newline : "";
183
- const state = new StringifyState();
184
- str += this.stringifyChildren(object, this.rules.elements, state);
185
- this.usedPrefixes.clear();
186
- this.traversed.clear();
187
- return str;
188
- }
189
- qName(localPart, namespaceUri) {
190
- if (!namespaceUri) return localPart;
191
- const prefixMap = this.options.prefixMap;
192
- const prefix = (0, import_vinyl_util3.getOrSet)(this.usedPrefixes, namespaceUri, () => {
193
- if (prefixMap.has(namespaceUri)) {
194
- return prefixMap.get(namespaceUri);
195
- }
196
- return (0, import_vinyl_util3.substitute)(locale.prefixTemplate, {
197
- value: (this.usedPrefixes.size + 1).toString(36)
198
- });
199
- });
200
- return `${prefix}:${localPart}`;
201
- }
202
- /**
203
- * Stringifies an element.
204
- *
205
- * @param object
206
- * @param rule
207
- * @param state
208
- */
209
- stringifyElement(object, rule, state) {
210
- var _a2;
211
- if (this.traversed.has(object))
212
- throw new XmlSchemaError(xmlSchemaErrorLocale.cyclicReferences);
213
- this.traversed.add(object);
214
- const nl = this.options.newline;
215
- const isDocument = state.depth === 0;
216
- let namespaces = "";
217
- let xmlns = state.xmlns;
218
- if (xmlns !== rule.namespaceUri && (xmlns == null || !rule.namespaceUri)) {
219
- xmlns = rule.namespaceUri;
220
- namespaces += ` xmlns="${(_a2 = rule.namespaceUri) != null ? _a2 : ""}"`;
221
- }
222
- const childState = state.createChild(xmlns, this.options.indent);
223
- const rules = rule.rules();
224
- const attributes = this.stringifyAttributes(object, rules.attributes);
225
- const children = this.stringifyChildren(
226
- object,
227
- rules.elements,
228
- childState
229
- );
230
- const text = this.stringifyCharacters(object, rules.characters);
231
- if (isDocument) {
232
- this.usedPrefixes.forEach((prefix, uri) => {
233
- namespaces += ` xmlns:${prefix}="${uri}"`;
234
- });
235
- }
236
- const indent = state.indent;
237
- const childIndent = childState.indent;
238
- const qName2 = rule.namespaceUri === xmlns ? rule.localPart : this.qName(rule.localPart, rule.namespaceUri);
239
- let str = `${indent}<${qName2}${namespaces}${attributes}`;
240
- if (children) {
241
- str += `>`;
242
- if (text) str += `${nl}${childIndent}${text}`;
243
- str += nl + children;
244
- str += `${nl}${indent}</${qName2}>`;
245
- } else if (text) {
246
- str += `>${text}</${qName2}>`;
157
+ function mapXmlRules(rules, parentNamespaceUri = null) {
158
+ var _a2, _b, _c;
159
+ const attributeRules = /* @__PURE__ */ new Map();
160
+ const elementRules = /* @__PURE__ */ new Map();
161
+ let charactersRule = void 0;
162
+ for (const property in rules) {
163
+ const handlerOrFunction = rules[property];
164
+ let handler;
165
+ if (typeof handlerOrFunction === "function") {
166
+ handler = handlerOrFunction();
247
167
  } else {
248
- str += "/>";
168
+ handler = handlerOrFunction;
249
169
  }
250
- return str;
251
- }
252
- /**
253
- * Stringifies an element's attributes.
254
- *
255
- * @param object
256
- * @param attributes
257
- * @return Returns the attributes string. This will include a leading space if there are any
258
- * found attributes.
259
- */
260
- stringifyAttributes(object, attributes) {
261
- let str = "";
262
- attributes.forEach((attributeRule) => {
263
- const propertyValue = object[attributeRule.property];
264
- if (propertyValue !== void 0) {
265
- const attributeValue = attributeRule.stringify(propertyValue);
266
- if (attributeRule.default === void 0 || !(0, import_vinyl_util3.equalDeep)(propertyValue, attributeRule.default)) {
267
- str += ` ${this.qName(
268
- attributeRule.localPart,
269
- attributeRule.namespaceUri
270
- )}="${(0, import_vinyl_util3.encodeEntities)(attributeValue)}"`;
271
- }
272
- } else {
273
- if (attributeRule.required) {
274
- throw new XmlSchemaError(
275
- (0, import_vinyl_util3.substitute)(xmlSchemaErrorLocale.requiredAttribute, {
276
- property: attributeRule.property
277
- })
170
+ let key;
171
+ switch (handler.type) {
172
+ case "characters" /* CHARACTERS */:
173
+ if (charactersRule !== void 0)
174
+ throw new import_vinyl_util3.IllegalArgumentError(
175
+ "characters handler already defined"
176
+ );
177
+ charactersRule = {
178
+ property,
179
+ parse: handler.parse,
180
+ stringify: handler.stringify
181
+ };
182
+ break;
183
+ case "element" /* ELEMENT */:
184
+ case "elements" /* ELEMENTS */: {
185
+ const localPart = (_a2 = handler.localPart) != null ? _a2 : property;
186
+ const namespaceUri = handler.namespaceUri === void 0 ? parentNamespaceUri : handler.namespaceUri;
187
+ key = xmlRuleKey(localPart, namespaceUri);
188
+ if (elementRules.has(key)) {
189
+ throw new import_vinyl_util3.IllegalArgumentError(
190
+ `Multiple element rules for ${key}`
278
191
  );
279
192
  }
280
- }
281
- });
282
- return str;
283
- }
284
- /**
285
- * Stringifies a property as a CDATA node.
286
- *
287
- * @param object
288
- * @param charactersRule
289
- */
290
- stringifyCharacters(object, charactersRule) {
291
- if (!charactersRule) return null;
292
- const str = charactersRule.stringify(object[charactersRule.property]);
293
- if (!str) return "";
294
- return `<![CDATA[${str}]]>`;
295
- }
296
- /**
297
- * Stringifies an element's child elements.
298
- *
299
- * @param object
300
- * @param elements
301
- * @param state
302
- */
303
- stringifyChildren(object, elements2, state) {
304
- let str = "";
305
- elements2.forEach((elementsRule) => {
306
- const child = object[elementsRule.property];
307
- if (child) {
308
- if (elementsRule.array) {
309
- const arr = child;
310
- if (elementsRule.minOccurs > arr.length) {
311
- throw new XmlSchemaError(
312
- (0, import_vinyl_util3.substitute)(xmlSchemaErrorLocale.atLeastElements, {
313
- property: elementsRule.property,
314
- expected: elementsRule.minOccurs,
315
- actual: arr.length
316
- })
317
- );
318
- }
319
- if (elementsRule.maxOccurs != null && elementsRule.maxOccurs < arr.length) {
320
- throw new XmlSchemaError(
321
- (0, import_vinyl_util3.substitute)(xmlSchemaErrorLocale.atMostElements, {
322
- property: elementsRule.property,
323
- expected: elementsRule.maxOccurs,
324
- actual: arr.length
325
- })
326
- );
327
- }
328
- for (const element2 of arr) {
329
- if (str) str += this.options.newline;
330
- str += this.stringifyElement(
331
- element2,
332
- elementsRule,
333
- state
334
- );
335
- }
193
+ if (handler.type === "element" /* ELEMENT */) {
194
+ const rules2 = handler.rules;
195
+ elementRules.set(key, {
196
+ array: false,
197
+ property,
198
+ minOccurs: handler.required ? 1 : 0,
199
+ maxOccurs: 1,
200
+ rules: (0, import_vinyl_util3.memoize)(() => mapXmlRules(rules2, namespaceUri)),
201
+ useEmptyArrays: false,
202
+ localPart,
203
+ namespaceUri
204
+ });
336
205
  } else {
337
- if (str) str += this.options.newline;
338
- str += this.stringifyElement(child, elementsRule, state);
206
+ const rules2 = handler.rules;
207
+ elementRules.set(key, {
208
+ array: true,
209
+ property,
210
+ maxOccurs: handler.maxOccurs,
211
+ minOccurs: handler.minOccurs,
212
+ rules: (0, import_vinyl_util3.memoize)(() => mapXmlRules(rules2, namespaceUri)),
213
+ useEmptyArrays: handler.useEmptyArrays,
214
+ localPart,
215
+ namespaceUri
216
+ });
339
217
  }
340
- } else {
341
- if (elementsRule.minOccurs > 0) {
342
- throw new XmlSchemaError(
343
- (0, import_vinyl_util3.substitute)(xmlSchemaErrorLocale.atLeastElements, {
344
- property: elementsRule.property,
345
- expected: elementsRule.minOccurs,
346
- actual: 0
347
- })
218
+ break;
219
+ }
220
+ case "attribute" /* ATTRIBUTE */: {
221
+ const namespaceUri = handler.namespaceUri;
222
+ const localPart = (_b = handler.localPart) != null ? _b : property;
223
+ key = xmlRuleKey(localPart, namespaceUri);
224
+ if (attributeRules.has(key)) {
225
+ throw new import_vinyl_util3.IllegalArgumentError(
226
+ `Multiple attribute rules for ${key}`
348
227
  );
349
228
  }
229
+ attributeRules.set(key, {
230
+ property,
231
+ default: handler.default,
232
+ parse: handler.parse,
233
+ stringify: handler.stringify,
234
+ required: handler.required,
235
+ localPart,
236
+ namespaceUri: (_c = handler.namespaceUri) != null ? _c : null
237
+ });
238
+ break;
350
239
  }
351
- });
352
- return str;
240
+ }
353
241
  }
242
+ return {
243
+ __type: (0, import_vinyl_util3.invariant)(),
244
+ attributes: attributeRules,
245
+ elements: elementRules,
246
+ characters: charactersRule
247
+ };
248
+ }
249
+ function xmlRuleKey(localPart, namespaceUri = null) {
250
+ return `${namespaceUri != null ? namespaceUri : ""}:${localPart}`;
251
+ }
252
+
253
+ // src/xml/mergeXmlRules.ts
254
+ var import_vinyl_util4 = require("@amazon/vinyl-util");
255
+ var locale = {
256
+ illegalRuleOverrideTypeError: "Cannot override the rule {property} of type {sourceType} with a rule of type {overrideType}",
257
+ illegalQNameOverrideError: "Cannot override the rule {property} with a different localPart or namespace"
354
258
  };
355
- var StringifyState = class _StringifyState {
356
- constructor(depth = 0, xmlns = null, indent = "") {
357
- __publicField(this, "depth", depth);
358
- __publicField(this, "xmlns", xmlns);
359
- __publicField(this, "indent", indent);
259
+ function mergeXmlRules(...rules) {
260
+ let finalRule = rules[0];
261
+ for (let i = 1; i < rules.length; i++) {
262
+ finalRule = import_vinyl_util4.plainObjectMergeRule.merge(
263
+ finalRule,
264
+ rules[i],
265
+ mergeXmlRule
266
+ );
360
267
  }
361
- createChild(xmlns, indent) {
362
- return new _StringifyState(this.depth + 1, xmlns, this.indent + indent);
268
+ return finalRule;
269
+ }
270
+ function mergeXmlRule(sourceA, sourceB, prop) {
271
+ var _a2, _b, _c, _d;
272
+ if (sourceA == null) return sourceB;
273
+ const sourceAIsLazy = typeof sourceA === "function";
274
+ const sourceBIsLazy = typeof sourceB === "function";
275
+ if (sourceAIsLazy || sourceBIsLazy) {
276
+ return () => {
277
+ const a = sourceAIsLazy ? sourceA() : sourceA;
278
+ const b = sourceBIsLazy ? sourceB() : sourceB;
279
+ return mergeXmlRule(a, b, prop);
280
+ };
281
+ }
282
+ if (sourceA.type !== sourceB.type) {
283
+ throw new import_vinyl_util4.ValidationError(
284
+ (0, import_vinyl_util4.substitute)(locale.illegalRuleOverrideTypeError, {
285
+ property: prop,
286
+ sourceType: sourceA.type,
287
+ overrideType: sourceB.type
288
+ })
289
+ );
290
+ }
291
+ switch (sourceA.type) {
292
+ case "attribute" /* ATTRIBUTE */:
293
+ case "element" /* ELEMENT */:
294
+ case "elements" /* ELEMENTS */: {
295
+ const b = sourceB;
296
+ if (sourceA.namespaceUri !== b.namespaceUri || ((_a2 = sourceA.localPart) != null ? _a2 : prop) !== ((_b = b.localPart) != null ? _b : prop)) {
297
+ throw new import_vinyl_util4.ValidationError(
298
+ (0, import_vinyl_util4.substitute)(locale.illegalQNameOverrideError, {
299
+ property: prop
300
+ })
301
+ );
302
+ }
303
+ break;
304
+ }
305
+ }
306
+ switch (sourceA.type) {
307
+ case "attribute" /* ATTRIBUTE */: {
308
+ const b = sourceB;
309
+ return __spreadProps(__spreadValues({}, b), {
310
+ default: (_c = b.default) != null ? _c : sourceA.default
311
+ });
312
+ }
313
+ case "characters" /* CHARACTERS */:
314
+ return sourceB;
315
+ case "element" /* ELEMENT */: {
316
+ const b = sourceB;
317
+ return __spreadProps(__spreadValues({}, b), {
318
+ required: sourceA.required || b.required,
319
+ rules: mergeXmlRules(sourceA.rules, b.rules)
320
+ });
321
+ }
322
+ case "elements" /* ELEMENTS */: {
323
+ const b = sourceB;
324
+ const maxOccurs = sourceA.maxOccurs != null && b.maxOccurs != null ? Math.min(sourceA.maxOccurs, b.maxOccurs) : (_d = sourceA.maxOccurs) != null ? _d : b.maxOccurs;
325
+ return __spreadProps(__spreadValues({}, b), {
326
+ minOccurs: Math.max(sourceA.minOccurs, b.minOccurs),
327
+ maxOccurs,
328
+ useEmptyArrays: sourceA.useEmptyArrays || b.useEmptyArrays,
329
+ rules: mergeXmlRules(sourceA.rules, b.rules)
330
+ });
331
+ }
363
332
  }
364
- };
365
- function stringifyXml(object, rules, options) {
366
- const writer = new XmlWriter(rules, options);
367
- return writer.stringify(object);
368
333
  }
369
334
 
370
335
  // src/xml/parseXml.ts
371
- var import_vinyl_util4 = require("@amazon/vinyl-util");
336
+ var import_vinyl_util5 = require("@amazon/vinyl-util");
372
337
  var XMLNS = "http://www.w3.org/2000/xmlns/";
373
- var LT = /* @__PURE__ */ (0, import_vinyl_util4.char)("<");
374
- var GT = /* @__PURE__ */ (0, import_vinyl_util4.char)(">");
375
- var EQ = /* @__PURE__ */ (0, import_vinyl_util4.char)("=");
376
- var SLASH = /* @__PURE__ */ (0, import_vinyl_util4.char)("/");
377
- var COLON = /* @__PURE__ */ (0, import_vinyl_util4.char)(":");
378
- var QMARK = /* @__PURE__ */ (0, import_vinyl_util4.char)("?");
379
- var EXCL = /* @__PURE__ */ (0, import_vinyl_util4.char)("!");
380
- var APOS = /* @__PURE__ */ (0, import_vinyl_util4.char)("'");
381
- var QUOT = /* @__PURE__ */ (0, import_vinyl_util4.char)('"');
338
+ var LT = /* @__PURE__ */ (0, import_vinyl_util5.char)("<");
339
+ var GT = /* @__PURE__ */ (0, import_vinyl_util5.char)(">");
340
+ var EQ = /* @__PURE__ */ (0, import_vinyl_util5.char)("=");
341
+ var SLASH = /* @__PURE__ */ (0, import_vinyl_util5.char)("/");
342
+ var COLON = /* @__PURE__ */ (0, import_vinyl_util5.char)(":");
343
+ var QMARK = /* @__PURE__ */ (0, import_vinyl_util5.char)("?");
344
+ var EXCL = /* @__PURE__ */ (0, import_vinyl_util5.char)("!");
345
+ var APOS = /* @__PURE__ */ (0, import_vinyl_util5.char)("'");
346
+ var QUOT = /* @__PURE__ */ (0, import_vinyl_util5.char)('"');
382
347
  var QUOTES = /* @__PURE__ */ new Set([APOS, QUOT]);
383
348
  function parseXml(str, handler) {
384
- const c = new import_vinyl_util4.StringReader(str);
349
+ const c = new import_vinyl_util5.StringReader(str);
385
350
  let current = {
386
351
  qName: "#document",
387
352
  namespaceMap: /* @__PURE__ */ new Map(),
@@ -419,7 +384,7 @@ function parseXml(str, handler) {
419
384
  if (name.qName !== current.qName)
420
385
  c.err(`Expected </${current.qName}> but was </${name.qName}>`);
421
386
  stack.pop();
422
- current = (0, import_vinyl_util4.last)(stack);
387
+ current = (0, import_vinyl_util5.last)(stack);
423
388
  c.white();
424
389
  c.readChar(GT);
425
390
  try {
@@ -473,7 +438,7 @@ function parseXml(str, handler) {
473
438
  if (c.charIf(SLASH)) {
474
439
  c.readChar(GT);
475
440
  stack.pop();
476
- current = (0, import_vinyl_util4.last)(stack);
441
+ current = (0, import_vinyl_util5.last)(stack);
477
442
  try {
478
443
  handler.endElement();
479
444
  } catch (e) {
@@ -495,7 +460,7 @@ function readAttributeValue(c) {
495
460
  if (!QUOTES.has(quote)) c.err(`Expected ' or "`);
496
461
  const value = c.substringUntil((charCode) => charCode === quote);
497
462
  c.readChar(quote);
498
- return (0, import_vinyl_util4.decodeEntities)(value);
463
+ return (0, import_vinyl_util5.decodeEntities)(value);
499
464
  }
500
465
  function untilTagClose(c) {
501
466
  while (true) {
@@ -581,211 +546,35 @@ function xmlAttributes(reader, stackElement) {
581
546
  name.namespaceUri = XMLNS;
582
547
  stackElement.defaultNamespaceUri = !value ? null : value;
583
548
  }
584
- if (attributes[name.qName] != null)
585
- reader.err(`Attribute '${name.qName}' is already specified.`);
586
- attributes[name.qName] = { name, value };
587
- }
588
- return attributes;
589
- }
590
-
591
- // src/xml/mergeXmlRules.ts
592
- var import_vinyl_util5 = require("@amazon/vinyl-util");
593
- var locale2 = {
594
- illegalRuleOverrideTypeError: "Cannot override the rule {property} of type {sourceType} with a rule of type {overrideType}",
595
- illegalQNameOverrideError: "Cannot override the rule {property} with a different localPart or namespace"
596
- };
597
- function mergeXmlRules(...rules) {
598
- let finalRule = rules[0];
599
- for (let i = 1; i < rules.length; i++) {
600
- finalRule = import_vinyl_util5.plainObjectMergeRule.merge(
601
- finalRule,
602
- rules[i],
603
- mergeXmlRule
604
- );
605
- }
606
- return finalRule;
607
- }
608
- function mergeXmlRule(sourceA, sourceB, prop) {
609
- var _a2, _b, _c, _d;
610
- if (sourceA == null) return sourceB;
611
- const sourceAIsLazy = typeof sourceA === "function";
612
- const sourceBIsLazy = typeof sourceB === "function";
613
- if (sourceAIsLazy || sourceBIsLazy) {
614
- return () => {
615
- const a = sourceAIsLazy ? sourceA() : sourceA;
616
- const b = sourceBIsLazy ? sourceB() : sourceB;
617
- return mergeXmlRule(a, b, prop);
618
- };
619
- }
620
- if (sourceA.type !== sourceB.type) {
621
- throw new import_vinyl_util5.ValidationError(
622
- (0, import_vinyl_util5.substitute)(locale2.illegalRuleOverrideTypeError, {
623
- property: prop,
624
- sourceType: sourceA.type,
625
- overrideType: sourceB.type
626
- })
627
- );
628
- }
629
- switch (sourceA.type) {
630
- case "attribute" /* ATTRIBUTE */:
631
- case "element" /* ELEMENT */:
632
- case "elements" /* ELEMENTS */: {
633
- const b = sourceB;
634
- if (sourceA.namespaceUri !== b.namespaceUri || ((_a2 = sourceA.localPart) != null ? _a2 : prop) !== ((_b = b.localPart) != null ? _b : prop)) {
635
- throw new import_vinyl_util5.ValidationError(
636
- (0, import_vinyl_util5.substitute)(locale2.illegalQNameOverrideError, {
637
- property: prop
638
- })
639
- );
640
- }
641
- break;
642
- }
643
- }
644
- switch (sourceA.type) {
645
- case "attribute" /* ATTRIBUTE */: {
646
- const b = sourceB;
647
- return __spreadProps(__spreadValues({}, b), {
648
- default: (_c = b.default) != null ? _c : sourceA.default
649
- });
650
- }
651
- case "characters" /* CHARACTERS */:
652
- return sourceB;
653
- case "element" /* ELEMENT */: {
654
- const b = sourceB;
655
- return __spreadProps(__spreadValues({}, b), {
656
- required: sourceA.required || b.required,
657
- rules: mergeXmlRules(sourceA.rules, b.rules)
658
- });
659
- }
660
- case "elements" /* ELEMENTS */: {
661
- const b = sourceB;
662
- const maxOccurs = sourceA.maxOccurs != null && b.maxOccurs != null ? Math.min(sourceA.maxOccurs, b.maxOccurs) : (_d = sourceA.maxOccurs) != null ? _d : b.maxOccurs;
663
- return __spreadProps(__spreadValues({}, b), {
664
- minOccurs: Math.max(sourceA.minOccurs, b.minOccurs),
665
- maxOccurs,
666
- useEmptyArrays: sourceA.useEmptyArrays || b.useEmptyArrays,
667
- rules: mergeXmlRules(sourceA.rules, b.rules)
668
- });
669
- }
670
- }
671
- }
672
-
673
- // src/xml/mappedXmlRules.ts
674
- var import_vinyl_util6 = require("@amazon/vinyl-util");
675
- var EmptyRules = {
676
- __type: /* @__PURE__ */ (0, import_vinyl_util6.invariant)(),
677
- attributes: /* @__PURE__ */ new Map(),
678
- elements: /* @__PURE__ */ new Map(),
679
- characters: void 0
680
- };
681
- function mapXmlRules(rules, parentNamespaceUri = null) {
682
- var _a2, _b, _c;
683
- const attributeRules = /* @__PURE__ */ new Map();
684
- const elementRules = /* @__PURE__ */ new Map();
685
- let charactersRule = void 0;
686
- for (const property in rules) {
687
- const handlerOrFunction = rules[property];
688
- let handler;
689
- if (typeof handlerOrFunction === "function") {
690
- handler = handlerOrFunction();
691
- } else {
692
- handler = handlerOrFunction;
693
- }
694
- let key;
695
- switch (handler.type) {
696
- case "characters" /* CHARACTERS */:
697
- if (charactersRule !== void 0)
698
- throw new import_vinyl_util6.IllegalArgumentError(
699
- "characters handler already defined"
700
- );
701
- charactersRule = {
702
- property,
703
- parse: handler.parse,
704
- stringify: handler.stringify
705
- };
706
- break;
707
- case "element" /* ELEMENT */:
708
- case "elements" /* ELEMENTS */: {
709
- const localPart = (_a2 = handler.localPart) != null ? _a2 : property;
710
- const namespaceUri = handler.namespaceUri === void 0 ? parentNamespaceUri : handler.namespaceUri;
711
- key = xmlRuleKey(localPart, namespaceUri);
712
- if (elementRules.has(key)) {
713
- throw new import_vinyl_util6.IllegalArgumentError(
714
- `Multiple element rules for ${key}`
715
- );
716
- }
717
- if (handler.type === "element" /* ELEMENT */) {
718
- const rules2 = handler.rules;
719
- elementRules.set(key, {
720
- array: false,
721
- property,
722
- minOccurs: handler.required ? 1 : 0,
723
- maxOccurs: 1,
724
- rules: (0, import_vinyl_util6.memoize)(() => mapXmlRules(rules2, namespaceUri)),
725
- useEmptyArrays: false,
726
- localPart,
727
- namespaceUri
728
- });
729
- } else {
730
- const rules2 = handler.rules;
731
- elementRules.set(key, {
732
- array: true,
733
- property,
734
- maxOccurs: handler.maxOccurs,
735
- minOccurs: handler.minOccurs,
736
- rules: (0, import_vinyl_util6.memoize)(() => mapXmlRules(rules2, namespaceUri)),
737
- useEmptyArrays: handler.useEmptyArrays,
738
- localPart,
739
- namespaceUri
740
- });
741
- }
742
- break;
743
- }
744
- case "attribute" /* ATTRIBUTE */: {
745
- const namespaceUri = handler.namespaceUri;
746
- const localPart = (_b = handler.localPart) != null ? _b : property;
747
- key = xmlRuleKey(localPart, namespaceUri);
748
- if (attributeRules.has(key)) {
749
- throw new import_vinyl_util6.IllegalArgumentError(
750
- `Multiple attribute rules for ${key}`
751
- );
752
- }
753
- attributeRules.set(key, {
754
- property,
755
- default: handler.default,
756
- parse: handler.parse,
757
- stringify: handler.stringify,
758
- required: handler.required,
759
- localPart,
760
- namespaceUri: (_c = handler.namespaceUri) != null ? _c : null
761
- });
762
- break;
763
- }
764
- }
549
+ if (attributes[name.qName] != null)
550
+ reader.err(`Attribute '${name.qName}' is already specified.`);
551
+ attributes[name.qName] = { name, value };
765
552
  }
766
- return {
767
- __type: (0, import_vinyl_util6.invariant)(),
768
- attributes: attributeRules,
769
- elements: elementRules,
770
- characters: charactersRule
771
- };
772
- }
773
- function xmlRuleKey(localPart, namespaceUri = null) {
774
- return `${namespaceUri != null ? namespaceUri : ""}:${localPart}`;
775
- }
776
-
777
- // src/xml/QName.ts
778
- function qName(localPart, prefix = null, namespaceUri = null) {
779
- return {
780
- localPart,
781
- prefix,
782
- namespaceUri,
783
- qName: prefix ? `${prefix}:${localPart}` : localPart
784
- };
553
+ return attributes;
785
554
  }
786
555
 
787
556
  // src/xml/ParseXmlHandlerImpl.ts
788
557
  var import_vinyl_util7 = require("@amazon/vinyl-util");
558
+
559
+ // src/xml/XmlSchemaError.ts
560
+ var import_vinyl_util6 = require("@amazon/vinyl-util");
561
+ var xmlSchemaErrorLocale = {
562
+ atLeastElements: "Expected at least {expected} occurrences of {property} but was {actual}",
563
+ atMostElements: "Expected at most {expected} occurrences of {property} but was {actual}",
564
+ cyclicReferences: "Cyclic reference detected",
565
+ requiredAttribute: `Attribute '{property}' is required`
566
+ };
567
+ var XmlSchemaError = class _XmlSchemaError extends import_vinyl_util6.ReportableError {
568
+ get [Symbol.toStringTag]() {
569
+ return "XmlSchemaError";
570
+ }
571
+ constructor(message) {
572
+ super(message, import_vinyl_util6.ErrorOrigin.PARSING);
573
+ Object.setPrototypeOf(this, _XmlSchemaError.prototype);
574
+ }
575
+ };
576
+
577
+ // src/xml/ParseXmlHandlerImpl.ts
789
578
  function getRule(name, rules) {
790
579
  return rules.get(xmlRuleKey(name.localPart, name.namespaceUri));
791
580
  }
@@ -965,12 +754,225 @@ var _XmlElementImpl = class _XmlElementImpl {
965
754
  };
966
755
  var XmlElementImpl = _XmlElementImpl;
967
756
 
968
- // src/xlink/actuateValidator.ts
969
- var import_vinyl_validation = require("@amazon/vinyl-validation");
757
+ // src/xml/QName.ts
758
+ function qName(localPart, prefix = null, namespaceUri = null) {
759
+ return {
760
+ localPart,
761
+ prefix,
762
+ namespaceUri,
763
+ qName: prefix ? `${prefix}:${localPart}` : localPart
764
+ };
765
+ }
766
+
767
+ // src/xml/stringifyXml.ts
970
768
  var import_vinyl_util8 = require("@amazon/vinyl-util");
971
- var actuateValidator = /* @__PURE__ */ (0, import_vinyl_validation.isOneOf)("onLoad", "onRequest");
972
- function assertActuateEnum(str) {
973
- actuateValidator.assert(str, import_vinyl_util8.ErrorOrigin.PARSING);
974
- return str;
769
+ var locale2 = {
770
+ /**
771
+ * When a namespace binding is generated, if the prefix was not provided in the stringifier
772
+ * options, it will be generated from this template.
773
+ */
774
+ prefixTemplate: "ns_{value}"
775
+ };
776
+ var defaultStringifyOptions = {
777
+ indent: " ",
778
+ newline: "\n",
779
+ prefixMap: /* @__PURE__ */ new Map(),
780
+ includeXmlDeclaration: true
781
+ };
782
+ var XmlWriter = class {
783
+ constructor(rules, options) {
784
+ __publicField(this, "rules", rules);
785
+ __publicField(this, "options");
786
+ __publicField(this, "usedPrefixes", /* @__PURE__ */ new Map());
787
+ __publicField(this, "traversed", /* @__PURE__ */ new Set());
788
+ this.options = __spreadValues(__spreadValues({}, defaultStringifyOptions), options);
789
+ }
790
+ stringify(object) {
791
+ let str = this.options.includeXmlDeclaration ? '<?xml version="1.0"?>' + this.options.newline : "";
792
+ const state = new StringifyState();
793
+ str += this.stringifyChildren(object, this.rules.elements, state);
794
+ this.usedPrefixes.clear();
795
+ this.traversed.clear();
796
+ return str;
797
+ }
798
+ qName(localPart, namespaceUri) {
799
+ if (!namespaceUri) return localPart;
800
+ const prefixMap = this.options.prefixMap;
801
+ const prefix = (0, import_vinyl_util8.getOrSet)(this.usedPrefixes, namespaceUri, () => {
802
+ if (prefixMap.has(namespaceUri)) {
803
+ return prefixMap.get(namespaceUri);
804
+ }
805
+ return (0, import_vinyl_util8.substitute)(locale2.prefixTemplate, {
806
+ value: (this.usedPrefixes.size + 1).toString(36)
807
+ });
808
+ });
809
+ return `${prefix}:${localPart}`;
810
+ }
811
+ /**
812
+ * Stringifies an element.
813
+ *
814
+ * @param object
815
+ * @param rule
816
+ * @param state
817
+ */
818
+ stringifyElement(object, rule, state) {
819
+ var _a2;
820
+ if (this.traversed.has(object))
821
+ throw new XmlSchemaError(xmlSchemaErrorLocale.cyclicReferences);
822
+ this.traversed.add(object);
823
+ const nl = this.options.newline;
824
+ const isDocument = state.depth === 0;
825
+ let namespaces = "";
826
+ let xmlns = state.xmlns;
827
+ if (xmlns !== rule.namespaceUri && (xmlns == null || !rule.namespaceUri)) {
828
+ xmlns = rule.namespaceUri;
829
+ namespaces += ` xmlns="${(_a2 = rule.namespaceUri) != null ? _a2 : ""}"`;
830
+ }
831
+ const childState = state.createChild(xmlns, this.options.indent);
832
+ const rules = rule.rules();
833
+ const attributes = this.stringifyAttributes(object, rules.attributes);
834
+ const children = this.stringifyChildren(
835
+ object,
836
+ rules.elements,
837
+ childState
838
+ );
839
+ const text = this.stringifyCharacters(object, rules.characters);
840
+ if (isDocument) {
841
+ this.usedPrefixes.forEach((prefix, uri) => {
842
+ namespaces += ` xmlns:${prefix}="${uri}"`;
843
+ });
844
+ }
845
+ const indent = state.indent;
846
+ const childIndent = childState.indent;
847
+ const qName2 = rule.namespaceUri === xmlns ? rule.localPart : this.qName(rule.localPart, rule.namespaceUri);
848
+ let str = `${indent}<${qName2}${namespaces}${attributes}`;
849
+ if (children) {
850
+ str += `>`;
851
+ if (text) str += `${nl}${childIndent}${text}`;
852
+ str += nl + children;
853
+ str += `${nl}${indent}</${qName2}>`;
854
+ } else if (text) {
855
+ str += `>${text}</${qName2}>`;
856
+ } else {
857
+ str += "/>";
858
+ }
859
+ return str;
860
+ }
861
+ /**
862
+ * Stringifies an element's attributes.
863
+ *
864
+ * @param object
865
+ * @param attributes
866
+ * @return Returns the attributes string. This will include a leading space if there are any
867
+ * found attributes.
868
+ */
869
+ stringifyAttributes(object, attributes) {
870
+ let str = "";
871
+ attributes.forEach((attributeRule) => {
872
+ const propertyValue = object[attributeRule.property];
873
+ if (propertyValue !== void 0) {
874
+ const attributeValue = attributeRule.stringify(propertyValue);
875
+ if (attributeRule.default === void 0 || !(0, import_vinyl_util8.equalDeep)(propertyValue, attributeRule.default)) {
876
+ str += ` ${this.qName(
877
+ attributeRule.localPart,
878
+ attributeRule.namespaceUri
879
+ )}="${(0, import_vinyl_util8.encodeEntities)(attributeValue)}"`;
880
+ }
881
+ } else {
882
+ if (attributeRule.required) {
883
+ throw new XmlSchemaError(
884
+ (0, import_vinyl_util8.substitute)(xmlSchemaErrorLocale.requiredAttribute, {
885
+ property: attributeRule.property
886
+ })
887
+ );
888
+ }
889
+ }
890
+ });
891
+ return str;
892
+ }
893
+ /**
894
+ * Stringifies a property as a CDATA node.
895
+ *
896
+ * @param object
897
+ * @param charactersRule
898
+ */
899
+ stringifyCharacters(object, charactersRule) {
900
+ if (!charactersRule) return null;
901
+ const str = charactersRule.stringify(object[charactersRule.property]);
902
+ if (!str) return "";
903
+ return `<![CDATA[${str}]]>`;
904
+ }
905
+ /**
906
+ * Stringifies an element's child elements.
907
+ *
908
+ * @param object
909
+ * @param elements
910
+ * @param state
911
+ */
912
+ stringifyChildren(object, elements2, state) {
913
+ let str = "";
914
+ elements2.forEach((elementsRule) => {
915
+ const child = object[elementsRule.property];
916
+ if (child) {
917
+ if (elementsRule.array) {
918
+ const arr = child;
919
+ if (elementsRule.minOccurs > arr.length) {
920
+ throw new XmlSchemaError(
921
+ (0, import_vinyl_util8.substitute)(xmlSchemaErrorLocale.atLeastElements, {
922
+ property: elementsRule.property,
923
+ expected: elementsRule.minOccurs,
924
+ actual: arr.length
925
+ })
926
+ );
927
+ }
928
+ if (elementsRule.maxOccurs != null && elementsRule.maxOccurs < arr.length) {
929
+ throw new XmlSchemaError(
930
+ (0, import_vinyl_util8.substitute)(xmlSchemaErrorLocale.atMostElements, {
931
+ property: elementsRule.property,
932
+ expected: elementsRule.maxOccurs,
933
+ actual: arr.length
934
+ })
935
+ );
936
+ }
937
+ for (const element2 of arr) {
938
+ if (str) str += this.options.newline;
939
+ str += this.stringifyElement(
940
+ element2,
941
+ elementsRule,
942
+ state
943
+ );
944
+ }
945
+ } else {
946
+ if (str) str += this.options.newline;
947
+ str += this.stringifyElement(child, elementsRule, state);
948
+ }
949
+ } else {
950
+ if (elementsRule.minOccurs > 0) {
951
+ throw new XmlSchemaError(
952
+ (0, import_vinyl_util8.substitute)(xmlSchemaErrorLocale.atLeastElements, {
953
+ property: elementsRule.property,
954
+ expected: elementsRule.minOccurs,
955
+ actual: 0
956
+ })
957
+ );
958
+ }
959
+ }
960
+ });
961
+ return str;
962
+ }
963
+ };
964
+ var StringifyState = class _StringifyState {
965
+ constructor(depth = 0, xmlns = null, indent = "") {
966
+ __publicField(this, "depth", depth);
967
+ __publicField(this, "xmlns", xmlns);
968
+ __publicField(this, "indent", indent);
969
+ }
970
+ createChild(xmlns, indent) {
971
+ return new _StringifyState(this.depth + 1, xmlns, this.indent + indent);
972
+ }
973
+ };
974
+ function stringifyXml(object, rules, options) {
975
+ const writer = new XmlWriter(rules, options);
976
+ return writer.stringify(object);
975
977
  }
976
978
  //# sourceMappingURL=index.cjs.map