@deck.gl/geo-layers 9.3.0-alpha.6 → 9.3.0-beta.2

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/dist.dev.js CHANGED
@@ -2878,6 +2878,8 @@ var __exports__ = (() => {
2878
2878
  var distanceToVertex = 3 - Math.sqrt(5);
2879
2879
  var Rmidedge = Math.sqrt(3 - \u03C6);
2880
2880
  var Rcircumscribed = Math.sqrt(3) * Rmidedge / \u03C6;
2881
+ var AUTHALIC_RADIUS_EARTH = 63710072e-1;
2882
+ var AUTHALIC_AREA_EARTH = 4 * Math.PI * AUTHALIC_RADIUS_EARTH * AUTHALIC_RADIUS_EARTH;
2881
2883
  common_exports.setMatrixArrayType(Float64Array);
2882
2884
  var PentagonShape = class _PentagonShape {
2883
2885
  constructor(vertices) {
@@ -3579,12 +3581,13 @@ var __exports__ = (() => {
3579
3581
  }
3580
3582
  }
3581
3583
  };
3582
- common_exports.setMatrixArrayType(Float64Array);
3583
3584
  var YES = -1;
3584
3585
  var NO = 1;
3586
+ common_exports.setMatrixArrayType(Float64Array);
3585
3587
  var KJToIJ = ([k, j]) => {
3586
3588
  return vec2_exports.fromValues(k - j, j);
3587
3589
  };
3590
+ common_exports.setMatrixArrayType(Float64Array);
3588
3591
  var kPos = vec2_exports.fromValues(1, 0);
3589
3592
  var jPos = vec2_exports.fromValues(0, 1);
3590
3593
  var kNeg = vec2_exports.negate(vec2_exports.create(), kPos);
@@ -3622,7 +3625,6 @@ var __exports__ = (() => {
3622
3625
  var quaternaryToFlips = (n) => {
3623
3626
  return [[NO, NO], [NO, YES], [NO, NO], [YES, NO]][n];
3624
3627
  };
3625
- var FLIP_SHIFT = vec2_exports.fromValues(-1, 1);
3626
3628
  function reversePattern(pattern) {
3627
3629
  return Array.from({ length: pattern.length }, (_, i) => pattern.indexOf(i));
3628
3630
  }
@@ -3630,7 +3632,7 @@ var __exports__ = (() => {
3630
3632
  var PATTERN_FLIPPED = [0, 1, 2, 7, 3, 4, 5, 6];
3631
3633
  var PATTERN_REVERSED = reversePattern(PATTERN);
3632
3634
  var PATTERN_FLIPPED_REVERSED = reversePattern(PATTERN_FLIPPED);
3633
- var _shiftDigits = (digits, i, flips, invertJ, pattern) => {
3635
+ var shiftDigits = (digits, i, flips, invertJ, pattern) => {
3634
3636
  if (i <= 0)
3635
3637
  return;
3636
3638
  const parentK = digits[i] || 0;
@@ -3652,7 +3654,10 @@ var __exports__ = (() => {
3652
3654
  digits[i - 1] = dst % 4;
3653
3655
  digits[i] = (parentK + 4 + Math.floor(dst / 4) - Math.floor(src / 4)) % 4;
3654
3656
  };
3655
- var sToAnchor = (s, resolution, orientation) => {
3657
+ common_exports.setMatrixArrayType(Float64Array);
3658
+ var FLIP_SHIFT = vec2_exports.fromValues(-1, 1);
3659
+ var SHIFTDIGITS = true;
3660
+ var sToAnchor = (s, resolution, orientation, doShiftDigits = SHIFTDIGITS) => {
3656
3661
  let input = BigInt(s);
3657
3662
  const reverse = orientation === "vu" || orientation === "wu" || orientation === "vw";
3658
3663
  const invertJ = orientation === "wv" || orientation === "vw";
@@ -3660,7 +3665,7 @@ var __exports__ = (() => {
3660
3665
  if (reverse) {
3661
3666
  input = (1n << BigInt(2 * resolution)) - input - 1n;
3662
3667
  }
3663
- const anchor = _sToAnchor(input, resolution, invertJ, flipIJ);
3668
+ const anchor = _sToAnchor(input, resolution, invertJ, flipIJ, doShiftDigits);
3664
3669
  if (flipIJ) {
3665
3670
  const { offset: [_i, _j], flips: [flipX, flipY] } = anchor;
3666
3671
  anchor.offset = [_j, _i];
@@ -3678,7 +3683,7 @@ var __exports__ = (() => {
3678
3683
  }
3679
3684
  return anchor;
3680
3685
  };
3681
- var _sToAnchor = (s, resolution, invertJ, flipIJ) => {
3686
+ var _sToAnchor = (s, resolution, invertJ, flipIJ, doShiftDigits = SHIFTDIGITS) => {
3682
3687
  const offset = vec2_exports.create();
3683
3688
  const flips = [NO, NO];
3684
3689
  let input = BigInt(s);
@@ -3689,7 +3694,9 @@ var __exports__ = (() => {
3689
3694
  }
3690
3695
  const pattern = flipIJ ? PATTERN_FLIPPED : PATTERN;
3691
3696
  for (let i = digits.length - 1; i >= 0; i--) {
3692
- _shiftDigits(digits, i, flips, invertJ, pattern);
3697
+ if (doShiftDigits) {
3698
+ shiftDigits(digits, i, flips, invertJ, pattern);
3699
+ }
3693
3700
  vec2_exports.multiply(flips, flips, quaternaryToFlips(digits[i]));
3694
3701
  }
3695
3702
  flips[0] = NO;
@@ -3700,9 +3707,16 @@ var __exports__ = (() => {
3700
3707
  vec2_exports.add(offset, offset, childOffset);
3701
3708
  vec2_exports.multiply(flips, flips, quaternaryToFlips(digits[i]));
3702
3709
  }
3703
- const k = digits[0] || 0;
3704
- return { flips, k, offset: KJToIJ(offset) };
3710
+ const q = digits[0] || 0;
3711
+ return { q, offset: KJToIJ(offset), flips };
3705
3712
  };
3713
+ var PROBE_R = 0.1;
3714
+ var PROBE_OFFSETS = [
3715
+ [PROBE_R * Math.cos(45 * Math.PI / 180), PROBE_R * Math.sin(45 * Math.PI / 180)],
3716
+ [PROBE_R * Math.cos(113 * Math.PI / 180), PROBE_R * Math.sin(113 * Math.PI / 180)],
3717
+ [PROBE_R * Math.cos(293 * Math.PI / 180), PROBE_R * Math.sin(293 * Math.PI / 180)],
3718
+ [PROBE_R * Math.cos(225 * Math.PI / 180), PROBE_R * Math.sin(225 * Math.PI / 180)]
3719
+ ];
3706
3720
  common_exports.setMatrixArrayType(Float64Array);
3707
3721
  var TRIANGLE_MODE = false;
3708
3722
  var shiftRight = vec2_exports.clone(w);
@@ -3719,12 +3733,12 @@ var __exports__ = (() => {
3719
3733
  if (anchor.flips[0] === NO && anchor.flips[1] === YES) {
3720
3734
  pentagon.rotate180();
3721
3735
  }
3722
- const { k } = anchor;
3736
+ const { q } = anchor;
3723
3737
  const F2 = anchor.flips[0] + anchor.flips[1];
3724
3738
  if (
3725
3739
  // Orient last two pentagons when both or neither flips are YES
3726
- (F2 === -2 || F2 === 2) && k > 1 || // Orient first & last pentagons when only one of flips is YES
3727
- F2 === 0 && (k === 0 || k === 3)
3740
+ (F2 === -2 || F2 === 2) && q > 1 || // Orient first & last pentagons when only one of flips is YES
3741
+ F2 === 0 && (q === 0 || q === 3)
3728
3742
  ) {
3729
3743
  pentagon.reflectY();
3730
3744
  }
@@ -3958,13 +3972,40 @@ var __exports__ = (() => {
3958
3972
  var FIRST_HILBERT_RESOLUTION = 2;
3959
3973
  var MAX_RESOLUTION = 30;
3960
3974
  var HILBERT_START_BIT = 58n;
3961
- var REMOVAL_MASK = 0x3ffffffffffffffn;
3975
+ var WORLD_CELL = 0n;
3962
3976
  function getResolution(index) {
3977
+ if (index === 0n)
3978
+ return -1;
3979
+ if (index & 1n || (index & 0b111n) === 0b100n || (index & 0b11111n) === 0b10000n)
3980
+ return MAX_RESOLUTION;
3963
3981
  let resolution = MAX_RESOLUTION - 1;
3964
3982
  let shifted = index >> 1n;
3965
- while (resolution > -1 && (shifted & 0b1n) === 0n) {
3983
+ if (shifted === 0n)
3984
+ return -1;
3985
+ let low32 = Number(shifted & 0xFFFFFFFFn);
3986
+ let remaining;
3987
+ if (low32 === 0) {
3988
+ shifted >>= 32n;
3989
+ resolution -= 16;
3990
+ remaining = Number(shifted);
3991
+ } else {
3992
+ remaining = low32;
3993
+ }
3994
+ if ((remaining & 65535) === 0) {
3995
+ remaining >>= 16;
3996
+ resolution -= 8;
3997
+ }
3998
+ if (resolution >= 6 && (remaining & 255) === 0) {
3999
+ remaining >>= 8;
4000
+ resolution -= 4;
4001
+ }
4002
+ if (resolution >= 4 && (remaining & 15) === 0) {
4003
+ remaining >>= 4;
4004
+ resolution -= 2;
4005
+ }
4006
+ while (resolution > -1 && (remaining & 1) === 0) {
3966
4007
  resolution -= 1;
3967
- shifted = shifted >> (resolution < FIRST_HILBERT_RESOLUTION ? 1n : 2n);
4008
+ remaining = remaining >> (resolution < FIRST_HILBERT_RESOLUTION ? 1 : 2);
3968
4009
  }
3969
4010
  return resolution;
3970
4011
  }
@@ -3973,27 +4014,33 @@ var __exports__ = (() => {
3973
4014
  if (resolution === -1) {
3974
4015
  return { origin: origins[0], segment: 0, S: 0n, resolution };
3975
4016
  }
3976
- const top6Bits = Number(index >> 58n);
4017
+ let quintantShift = HILBERT_START_BIT;
4018
+ let quintantOffset = 0;
4019
+ if (resolution === MAX_RESOLUTION) {
4020
+ const markerBits = index & 1n ? 1n : index & 0b100n ? 3n : 5n;
4021
+ quintantShift = HILBERT_START_BIT + markerBits;
4022
+ quintantOffset = markerBits === 1n ? 0 : markerBits === 3n ? 32 : 40;
4023
+ }
4024
+ const topBits = Number(index >> quintantShift) + quintantOffset;
3977
4025
  let origin, segment;
3978
4026
  if (resolution === 0) {
3979
- const originId2 = top6Bits;
3980
- origin = origins[originId2];
4027
+ origin = origins[topBits];
3981
4028
  segment = 0;
3982
4029
  } else {
3983
- const originId2 = Math.floor(top6Bits / 5);
4030
+ const originId2 = Math.floor(topBits / 5);
3984
4031
  origin = origins[originId2];
3985
- segment = (top6Bits + origin.firstQuintant) % 5;
4032
+ segment = (topBits + origin.firstQuintant) % 5;
3986
4033
  }
3987
4034
  if (!origin) {
3988
- throw new Error(`Could not parse origin: ${top6Bits}`);
4035
+ throw new Error(`Could not parse origin: ${topBits}`);
3989
4036
  }
3990
4037
  if (resolution < FIRST_HILBERT_RESOLUTION) {
3991
4038
  return { origin, segment, S: 0n, resolution };
3992
4039
  }
3993
4040
  const hilbertLevels = resolution - FIRST_HILBERT_RESOLUTION + 1;
3994
4041
  const hilbertBits = BigInt(2 * hilbertLevels);
3995
- const shift = HILBERT_START_BIT - hilbertBits;
3996
- const S = (index & REMOVAL_MASK) >> shift;
4042
+ const removalMask = (1n << quintantShift) - 1n;
4043
+ const S = (index & removalMask) >> quintantShift - hilbertBits;
3997
4044
  return { origin, segment, S, resolution };
3998
4045
  }
3999
4046
  common_exports.setMatrixArrayType(Float64Array);
@@ -4012,6 +4059,9 @@ var __exports__ = (() => {
4012
4059
  return getPentagonVertices(hilbertResolution, quintant, anchor);
4013
4060
  }
4014
4061
  function cellToBoundary(cellId, { closedRing = true, segments = "auto" } = { closedRing: true, segments: "auto" }) {
4062
+ if (cellId === WORLD_CELL) {
4063
+ return [];
4064
+ }
4015
4065
  const { S, segment, origin, resolution } = deserialize(cellId);
4016
4066
  if (segments === "auto") {
4017
4067
  segments = Math.max(1, Math.pow(2, 6 - resolution));
@@ -4031,8 +4081,13 @@ var __exports__ = (() => {
4031
4081
  function hexToU64(hex) {
4032
4082
  return BigInt(`0x${hex}`);
4033
4083
  }
4034
- var AUTHALIC_RADIUS = 63710072e-1;
4035
- var AUTHALIC_AREA = 4 * Math.PI * AUTHALIC_RADIUS * AUTHALIC_RADIUS;
4084
+ var CELL_RADIUS_SAFETY_FACTOR = 2;
4085
+ var BASE_CELL_RADIUS = CELL_RADIUS_SAFETY_FACTOR * AUTHALIC_RADIUS_EARTH / Math.sqrt(15);
4086
+ var _cellRadius = new Array(31);
4087
+ _cellRadius[0] = CELL_RADIUS_SAFETY_FACTOR * AUTHALIC_RADIUS_EARTH / Math.sqrt(3);
4088
+ for (let r = 1; r <= 30; r++) {
4089
+ _cellRadius[r] = BASE_CELL_RADIUS / (1 << r - 1);
4090
+ }
4036
4091
  common_exports.setMatrixArrayType(Float64Array);
4037
4092
 
4038
4093
  // src/h3-layers/h3-utils.ts
@@ -8606,6 +8661,19 @@ var __exports__ = (() => {
8606
8661
  function isExist(v2) {
8607
8662
  return typeof v2 !== "undefined";
8608
8663
  }
8664
+ var DANGEROUS_PROPERTY_NAMES = [
8665
+ // '__proto__',
8666
+ // 'constructor',
8667
+ // 'prototype',
8668
+ "hasOwnProperty",
8669
+ "toString",
8670
+ "valueOf",
8671
+ "__defineGetter__",
8672
+ "__defineSetter__",
8673
+ "__lookupGetter__",
8674
+ "__lookupSetter__"
8675
+ ];
8676
+ var criticalProperties = ["__proto__", "constructor", "prototype"];
8609
8677
 
8610
8678
  // ../../node_modules/fast-xml-parser/src/validator.js
8611
8679
  var defaultOptions = {
@@ -8847,7 +8915,7 @@ var __exports__ = (() => {
8847
8915
  if (!validateAttrName(attrName)) {
8848
8916
  return getErrorObject("InvalidAttr", "Attribute '" + attrName + "' is an invalid name.", getPositionFromMatch(matches3[i]));
8849
8917
  }
8850
- if (!attrNames.hasOwnProperty(attrName)) {
8918
+ if (!Object.prototype.hasOwnProperty.call(attrNames, attrName)) {
8851
8919
  attrNames[attrName] = 1;
8852
8920
  } else {
8853
8921
  return getErrorObject("InvalidAttr", "Attribute '" + attrName + "' is repeated.", getPositionFromMatch(matches3[i]));
@@ -8916,6 +8984,12 @@ var __exports__ = (() => {
8916
8984
  }
8917
8985
 
8918
8986
  // ../../node_modules/fast-xml-parser/src/xmlparser/OptionsBuilder.js
8987
+ var defaultOnDangerousProperty = (name12) => {
8988
+ if (DANGEROUS_PROPERTY_NAMES.includes(name12)) {
8989
+ return "__" + name12;
8990
+ }
8991
+ return name12;
8992
+ };
8919
8993
  var defaultOptions2 = {
8920
8994
  preserveOrder: false,
8921
8995
  attributeNamePrefix: "@_",
@@ -8959,8 +9033,29 @@ var __exports__ = (() => {
8959
9033
  return tagName;
8960
9034
  },
8961
9035
  // skipEmptyListItem: false
8962
- captureMetaData: false
9036
+ captureMetaData: false,
9037
+ maxNestedTags: 100,
9038
+ strictReservedNames: true,
9039
+ jPath: true,
9040
+ // if true, pass jPath string to callbacks; if false, pass matcher instance
9041
+ onDangerousProperty: defaultOnDangerousProperty
8963
9042
  };
9043
+ function validatePropertyName(propertyName, optionName) {
9044
+ if (typeof propertyName !== "string") {
9045
+ return;
9046
+ }
9047
+ const normalized = propertyName.toLowerCase();
9048
+ if (DANGEROUS_PROPERTY_NAMES.some((dangerous) => normalized === dangerous.toLowerCase())) {
9049
+ throw new Error(
9050
+ `[SECURITY] Invalid ${optionName}: "${propertyName}" is a reserved JavaScript keyword that could cause prototype pollution`
9051
+ );
9052
+ }
9053
+ if (criticalProperties.some((dangerous) => normalized === dangerous.toLowerCase())) {
9054
+ throw new Error(
9055
+ `[SECURITY] Invalid ${optionName}: "${propertyName}" is a reserved JavaScript keyword that could cause prototype pollution`
9056
+ );
9057
+ }
9058
+ }
8964
9059
  function normalizeProcessEntities(value) {
8965
9060
  if (typeof value === "boolean") {
8966
9061
  return {
@@ -8970,6 +9065,7 @@ var __exports__ = (() => {
8970
9065
  maxExpansionDepth: 10,
8971
9066
  maxTotalExpansions: 1e3,
8972
9067
  maxExpandedLength: 1e5,
9068
+ maxEntityCount: 100,
8973
9069
  allowedTags: null,
8974
9070
  tagFilter: null
8975
9071
  };
@@ -8977,11 +9073,11 @@ var __exports__ = (() => {
8977
9073
  if (typeof value === "object" && value !== null) {
8978
9074
  return {
8979
9075
  enabled: value.enabled !== false,
8980
- // default true if not specified
8981
- maxEntitySize: value.maxEntitySize ?? 1e4,
8982
- maxExpansionDepth: value.maxExpansionDepth ?? 10,
8983
- maxTotalExpansions: value.maxTotalExpansions ?? 1e3,
8984
- maxExpandedLength: value.maxExpandedLength ?? 1e5,
9076
+ maxEntitySize: Math.max(1, value.maxEntitySize ?? 1e4),
9077
+ maxExpansionDepth: Math.max(1, value.maxExpansionDepth ?? 1e4),
9078
+ maxTotalExpansions: Math.max(1, value.maxTotalExpansions ?? Infinity),
9079
+ maxExpandedLength: Math.max(1, value.maxExpandedLength ?? 1e5),
9080
+ maxEntityCount: Math.max(1, value.maxEntityCount ?? 1e3),
8985
9081
  allowedTags: value.allowedTags ?? null,
8986
9082
  tagFilter: value.tagFilter ?? null
8987
9083
  };
@@ -8990,7 +9086,31 @@ var __exports__ = (() => {
8990
9086
  }
8991
9087
  var buildOptions = function(options) {
8992
9088
  const built = Object.assign({}, defaultOptions2, options);
9089
+ const propertyNameOptions = [
9090
+ { value: built.attributeNamePrefix, name: "attributeNamePrefix" },
9091
+ { value: built.attributesGroupName, name: "attributesGroupName" },
9092
+ { value: built.textNodeName, name: "textNodeName" },
9093
+ { value: built.cdataPropName, name: "cdataPropName" },
9094
+ { value: built.commentPropName, name: "commentPropName" }
9095
+ ];
9096
+ for (const { value, name: name12 } of propertyNameOptions) {
9097
+ if (value) {
9098
+ validatePropertyName(value, name12);
9099
+ }
9100
+ }
9101
+ if (built.onDangerousProperty === null) {
9102
+ built.onDangerousProperty = defaultOnDangerousProperty;
9103
+ }
8993
9104
  built.processEntities = normalizeProcessEntities(built.processEntities);
9105
+ built.unpairedTagsSet = new Set(built.unpairedTags);
9106
+ if (built.stopNodes && Array.isArray(built.stopNodes)) {
9107
+ built.stopNodes = built.stopNodes.map((node) => {
9108
+ if (typeof node === "string" && node.startsWith("*.")) {
9109
+ return ".." + node.substring(2);
9110
+ }
9111
+ return node;
9112
+ });
9113
+ }
8994
9114
  return built;
8995
9115
  };
8996
9116
 
@@ -9005,7 +9125,7 @@ var __exports__ = (() => {
9005
9125
  constructor(tagname) {
9006
9126
  this.tagname = tagname;
9007
9127
  this.child = [];
9008
- this[":@"] = {};
9128
+ this[":@"] = /* @__PURE__ */ Object.create(null);
9009
9129
  }
9010
9130
  add(key, val) {
9011
9131
  if (key === "__proto__")
@@ -9037,7 +9157,8 @@ var __exports__ = (() => {
9037
9157
  this.options = options;
9038
9158
  }
9039
9159
  readDocType(xmlData, i) {
9040
- const entities = {};
9160
+ const entities = /* @__PURE__ */ Object.create(null);
9161
+ let entityCount = 0;
9041
9162
  if (xmlData[i + 3] === "O" && xmlData[i + 4] === "C" && xmlData[i + 5] === "T" && xmlData[i + 6] === "Y" && xmlData[i + 7] === "P" && xmlData[i + 8] === "E") {
9042
9163
  i = i + 9;
9043
9164
  let angleBracketsCount = 1;
@@ -9050,11 +9171,17 @@ var __exports__ = (() => {
9050
9171
  let entityName, val;
9051
9172
  [entityName, val, i] = this.readEntityExp(xmlData, i + 1, this.suppressValidationErr);
9052
9173
  if (val.indexOf("&") === -1) {
9053
- const escaped = entityName.replace(/[.\-+*:]/g, "\\.");
9174
+ if (this.options.enabled !== false && this.options.maxEntityCount != null && entityCount >= this.options.maxEntityCount) {
9175
+ throw new Error(
9176
+ `Entity count (${entityCount + 1}) exceeds maximum allowed (${this.options.maxEntityCount})`
9177
+ );
9178
+ }
9179
+ const escaped = entityName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
9054
9180
  entities[entityName] = {
9055
9181
  regx: RegExp(`&${escaped};`, "g"),
9056
9182
  val
9057
9183
  };
9184
+ entityCount++;
9058
9185
  }
9059
9186
  } else if (hasBody && hasSeq(xmlData, "!ELEMENT", i)) {
9060
9187
  i += 8;
@@ -9100,11 +9227,11 @@ var __exports__ = (() => {
9100
9227
  }
9101
9228
  readEntityExp(xmlData, i) {
9102
9229
  i = skipWhitespace(xmlData, i);
9103
- let entityName = "";
9230
+ const startIndex = i;
9104
9231
  while (i < xmlData.length && !/\s/.test(xmlData[i]) && xmlData[i] !== '"' && xmlData[i] !== "'") {
9105
- entityName += xmlData[i];
9106
9232
  i++;
9107
9233
  }
9234
+ let entityName = xmlData.substring(startIndex, i);
9108
9235
  validateEntityName(entityName);
9109
9236
  i = skipWhitespace(xmlData, i);
9110
9237
  if (!this.suppressValidationErr) {
@@ -9116,7 +9243,7 @@ var __exports__ = (() => {
9116
9243
  }
9117
9244
  let entityValue = "";
9118
9245
  [i, entityValue] = this.readIdentifierVal(xmlData, i, "entity");
9119
- if (this.options.enabled !== false && this.options.maxEntitySize && entityValue.length > this.options.maxEntitySize) {
9246
+ if (this.options.enabled !== false && this.options.maxEntitySize != null && entityValue.length > this.options.maxEntitySize) {
9120
9247
  throw new Error(
9121
9248
  `Entity "${entityName}" size (${entityValue.length}) exceeds maximum allowed size (${this.options.maxEntitySize})`
9122
9249
  );
@@ -9126,11 +9253,11 @@ var __exports__ = (() => {
9126
9253
  }
9127
9254
  readNotationExp(xmlData, i) {
9128
9255
  i = skipWhitespace(xmlData, i);
9129
- let notationName = "";
9256
+ const startIndex = i;
9130
9257
  while (i < xmlData.length && !/\s/.test(xmlData[i])) {
9131
- notationName += xmlData[i];
9132
9258
  i++;
9133
9259
  }
9260
+ let notationName = xmlData.substring(startIndex, i);
9134
9261
  !this.suppressValidationErr && validateEntityName(notationName);
9135
9262
  i = skipWhitespace(xmlData, i);
9136
9263
  const identifierType = xmlData.substring(i, i + 6).toUpperCase();
@@ -9162,10 +9289,11 @@ var __exports__ = (() => {
9162
9289
  throw new Error(`Expected quoted string, found "${startChar}"`);
9163
9290
  }
9164
9291
  i++;
9292
+ const startIndex = i;
9165
9293
  while (i < xmlData.length && xmlData[i] !== startChar) {
9166
- identifierVal += xmlData[i];
9167
9294
  i++;
9168
9295
  }
9296
+ identifierVal = xmlData.substring(startIndex, i);
9169
9297
  if (xmlData[i] !== startChar) {
9170
9298
  throw new Error(`Unterminated ${type} value`);
9171
9299
  }
@@ -9174,11 +9302,11 @@ var __exports__ = (() => {
9174
9302
  }
9175
9303
  readElementExp(xmlData, i) {
9176
9304
  i = skipWhitespace(xmlData, i);
9177
- let elementName = "";
9305
+ const startIndex = i;
9178
9306
  while (i < xmlData.length && !/\s/.test(xmlData[i])) {
9179
- elementName += xmlData[i];
9180
9307
  i++;
9181
9308
  }
9309
+ let elementName = xmlData.substring(startIndex, i);
9182
9310
  if (!this.suppressValidationErr && !isName(elementName)) {
9183
9311
  throw new Error(`Invalid element name: "${elementName}"`);
9184
9312
  }
@@ -9190,10 +9318,11 @@ var __exports__ = (() => {
9190
9318
  i += 2;
9191
9319
  else if (xmlData[i] === "(") {
9192
9320
  i++;
9321
+ const startIndex2 = i;
9193
9322
  while (i < xmlData.length && xmlData[i] !== ")") {
9194
- contentModel += xmlData[i];
9195
9323
  i++;
9196
9324
  }
9325
+ contentModel = xmlData.substring(startIndex2, i);
9197
9326
  if (xmlData[i] !== ")") {
9198
9327
  throw new Error("Unterminated content model");
9199
9328
  }
@@ -9208,18 +9337,18 @@ var __exports__ = (() => {
9208
9337
  }
9209
9338
  readAttlistExp(xmlData, i) {
9210
9339
  i = skipWhitespace(xmlData, i);
9211
- let elementName = "";
9340
+ let startIndex = i;
9212
9341
  while (i < xmlData.length && !/\s/.test(xmlData[i])) {
9213
- elementName += xmlData[i];
9214
9342
  i++;
9215
9343
  }
9344
+ let elementName = xmlData.substring(startIndex, i);
9216
9345
  validateEntityName(elementName);
9217
9346
  i = skipWhitespace(xmlData, i);
9218
- let attributeName = "";
9347
+ startIndex = i;
9219
9348
  while (i < xmlData.length && !/\s/.test(xmlData[i])) {
9220
- attributeName += xmlData[i];
9221
9349
  i++;
9222
9350
  }
9351
+ let attributeName = xmlData.substring(startIndex, i);
9223
9352
  if (!validateEntityName(attributeName)) {
9224
9353
  throw new Error(`Invalid attribute name: "${attributeName}"`);
9225
9354
  }
@@ -9235,11 +9364,11 @@ var __exports__ = (() => {
9235
9364
  i++;
9236
9365
  let allowedNotations = [];
9237
9366
  while (i < xmlData.length && xmlData[i] !== ")") {
9238
- let notation = "";
9367
+ const startIndex2 = i;
9239
9368
  while (i < xmlData.length && xmlData[i] !== "|" && xmlData[i] !== ")") {
9240
- notation += xmlData[i];
9241
9369
  i++;
9242
9370
  }
9371
+ let notation = xmlData.substring(startIndex2, i);
9243
9372
  notation = notation.trim();
9244
9373
  if (!validateEntityName(notation)) {
9245
9374
  throw new Error(`Invalid notation name: "${notation}"`);
@@ -9256,10 +9385,11 @@ var __exports__ = (() => {
9256
9385
  i++;
9257
9386
  attributeType += " (" + allowedNotations.join("|") + ")";
9258
9387
  } else {
9388
+ const startIndex2 = i;
9259
9389
  while (i < xmlData.length && !/\s/.test(xmlData[i])) {
9260
- attributeType += xmlData[i];
9261
9390
  i++;
9262
9391
  }
9392
+ attributeType += xmlData.substring(startIndex2, i);
9263
9393
  const validTypes = ["CDATA", "ID", "IDREF", "IDREFS", "ENTITY", "ENTITIES", "NMTOKEN", "NMTOKENS"];
9264
9394
  if (!this.suppressValidationErr && !validTypes.includes(attributeType.toUpperCase())) {
9265
9395
  throw new Error(`Invalid attribute type: "${attributeType}"`);
@@ -9313,20 +9443,26 @@ var __exports__ = (() => {
9313
9443
  // oct: false,
9314
9444
  leadingZeros: true,
9315
9445
  decimalPoint: ".",
9316
- eNotation: true
9317
- //skipLike: /regex/
9446
+ eNotation: true,
9447
+ //skipLike: /regex/,
9448
+ infinity: "original"
9449
+ // "null", "infinity" (Infinity type), "string" ("Infinity" (the string literal))
9318
9450
  };
9319
9451
  function toNumber(str7, options = {}) {
9320
9452
  options = Object.assign({}, consider, options);
9321
9453
  if (!str7 || typeof str7 !== "string")
9322
9454
  return str7;
9323
9455
  let trimmedStr = str7.trim();
9324
- if (options.skipLike !== void 0 && options.skipLike.test(trimmedStr))
9456
+ if (trimmedStr.length === 0)
9325
9457
  return str7;
9326
- else if (str7 === "0")
9458
+ else if (options.skipLike !== void 0 && options.skipLike.test(trimmedStr))
9459
+ return str7;
9460
+ else if (trimmedStr === "0")
9327
9461
  return 0;
9328
9462
  else if (options.hex && hexRegex.test(trimmedStr)) {
9329
9463
  return parse_int(trimmedStr, 16);
9464
+ } else if (!isFinite(trimmedStr)) {
9465
+ return handleInfinity(str7, Number(trimmedStr), options);
9330
9466
  } else if (trimmedStr.includes("e") || trimmedStr.includes("E")) {
9331
9467
  return resolveEnotation(str7, trimmedStr, options);
9332
9468
  } else {
@@ -9390,11 +9526,15 @@ var __exports__ = (() => {
9390
9526
  return str7;
9391
9527
  else if (leadingZeros.length === 1 && (notation[3].startsWith(`.${eChar}`) || notation[3][0] === eChar)) {
9392
9528
  return Number(trimmedStr);
9393
- } else if (options.leadingZeros && !eAdjacentToLeadingZeros) {
9394
- trimmedStr = (notation[1] || "") + notation[3];
9529
+ } else if (leadingZeros.length > 0) {
9530
+ if (options.leadingZeros && !eAdjacentToLeadingZeros) {
9531
+ trimmedStr = (notation[1] || "") + notation[3];
9532
+ return Number(trimmedStr);
9533
+ } else
9534
+ return str7;
9535
+ } else {
9395
9536
  return Number(trimmedStr);
9396
- } else
9397
- return str7;
9537
+ }
9398
9538
  } else {
9399
9539
  return str7;
9400
9540
  }
@@ -9422,6 +9562,20 @@ var __exports__ = (() => {
9422
9562
  else
9423
9563
  throw new Error("parseInt, Number.parseInt, window.parseInt are not supported");
9424
9564
  }
9565
+ function handleInfinity(str7, num, options) {
9566
+ const isPositive2 = num === Infinity;
9567
+ switch (options.infinity.toLowerCase()) {
9568
+ case "null":
9569
+ return null;
9570
+ case "infinity":
9571
+ return num;
9572
+ case "string":
9573
+ return isPositive2 ? "Infinity" : "-Infinity";
9574
+ case "original":
9575
+ default:
9576
+ return str7;
9577
+ }
9578
+ }
9425
9579
 
9426
9580
  // ../../node_modules/fast-xml-parser/src/ignoreAttributes.js
9427
9581
  function getIgnoreAttributesFn(ignoreAttributes) {
@@ -9443,7 +9597,776 @@ var __exports__ = (() => {
9443
9597
  return () => false;
9444
9598
  }
9445
9599
 
9600
+ // ../../node_modules/path-expression-matcher/src/Expression.js
9601
+ var Expression = class {
9602
+ /**
9603
+ * Create a new Expression
9604
+ * @param {string} pattern - Pattern string (e.g., "root.users.user", "..user[id]")
9605
+ * @param {Object} options - Configuration options
9606
+ * @param {string} options.separator - Path separator (default: '.')
9607
+ */
9608
+ constructor(pattern, options = {}, data) {
9609
+ this.pattern = pattern;
9610
+ this.separator = options.separator || ".";
9611
+ this.segments = this._parse(pattern);
9612
+ this.data = data;
9613
+ this._hasDeepWildcard = this.segments.some((seg) => seg.type === "deep-wildcard");
9614
+ this._hasAttributeCondition = this.segments.some((seg) => seg.attrName !== void 0);
9615
+ this._hasPositionSelector = this.segments.some((seg) => seg.position !== void 0);
9616
+ }
9617
+ /**
9618
+ * Parse pattern string into segments
9619
+ * @private
9620
+ * @param {string} pattern - Pattern to parse
9621
+ * @returns {Array} Array of segment objects
9622
+ */
9623
+ _parse(pattern) {
9624
+ const segments = [];
9625
+ let i = 0;
9626
+ let currentPart = "";
9627
+ while (i < pattern.length) {
9628
+ if (pattern[i] === this.separator) {
9629
+ if (i + 1 < pattern.length && pattern[i + 1] === this.separator) {
9630
+ if (currentPart.trim()) {
9631
+ segments.push(this._parseSegment(currentPart.trim()));
9632
+ currentPart = "";
9633
+ }
9634
+ segments.push({ type: "deep-wildcard" });
9635
+ i += 2;
9636
+ } else {
9637
+ if (currentPart.trim()) {
9638
+ segments.push(this._parseSegment(currentPart.trim()));
9639
+ }
9640
+ currentPart = "";
9641
+ i++;
9642
+ }
9643
+ } else {
9644
+ currentPart += pattern[i];
9645
+ i++;
9646
+ }
9647
+ }
9648
+ if (currentPart.trim()) {
9649
+ segments.push(this._parseSegment(currentPart.trim()));
9650
+ }
9651
+ return segments;
9652
+ }
9653
+ /**
9654
+ * Parse a single segment
9655
+ * @private
9656
+ * @param {string} part - Segment string (e.g., "user", "ns::user", "user[id]", "ns::user:first")
9657
+ * @returns {Object} Segment object
9658
+ */
9659
+ _parseSegment(part) {
9660
+ const segment = { type: "tag" };
9661
+ let bracketContent = null;
9662
+ let withoutBrackets = part;
9663
+ const bracketMatch = part.match(/^([^\[]+)(\[[^\]]*\])(.*)$/);
9664
+ if (bracketMatch) {
9665
+ withoutBrackets = bracketMatch[1] + bracketMatch[3];
9666
+ if (bracketMatch[2]) {
9667
+ const content = bracketMatch[2].slice(1, -1);
9668
+ if (content) {
9669
+ bracketContent = content;
9670
+ }
9671
+ }
9672
+ }
9673
+ let namespace = void 0;
9674
+ let tagAndPosition = withoutBrackets;
9675
+ if (withoutBrackets.includes("::")) {
9676
+ const nsIndex = withoutBrackets.indexOf("::");
9677
+ namespace = withoutBrackets.substring(0, nsIndex).trim();
9678
+ tagAndPosition = withoutBrackets.substring(nsIndex + 2).trim();
9679
+ if (!namespace) {
9680
+ throw new Error(`Invalid namespace in pattern: ${part}`);
9681
+ }
9682
+ }
9683
+ let tag = void 0;
9684
+ let positionMatch = null;
9685
+ if (tagAndPosition.includes(":")) {
9686
+ const colonIndex = tagAndPosition.lastIndexOf(":");
9687
+ const tagPart = tagAndPosition.substring(0, colonIndex).trim();
9688
+ const posPart = tagAndPosition.substring(colonIndex + 1).trim();
9689
+ const isPositionKeyword = ["first", "last", "odd", "even"].includes(posPart) || /^nth\(\d+\)$/.test(posPart);
9690
+ if (isPositionKeyword) {
9691
+ tag = tagPart;
9692
+ positionMatch = posPart;
9693
+ } else {
9694
+ tag = tagAndPosition;
9695
+ }
9696
+ } else {
9697
+ tag = tagAndPosition;
9698
+ }
9699
+ if (!tag) {
9700
+ throw new Error(`Invalid segment pattern: ${part}`);
9701
+ }
9702
+ segment.tag = tag;
9703
+ if (namespace) {
9704
+ segment.namespace = namespace;
9705
+ }
9706
+ if (bracketContent) {
9707
+ if (bracketContent.includes("=")) {
9708
+ const eqIndex = bracketContent.indexOf("=");
9709
+ segment.attrName = bracketContent.substring(0, eqIndex).trim();
9710
+ segment.attrValue = bracketContent.substring(eqIndex + 1).trim();
9711
+ } else {
9712
+ segment.attrName = bracketContent.trim();
9713
+ }
9714
+ }
9715
+ if (positionMatch) {
9716
+ const nthMatch = positionMatch.match(/^nth\((\d+)\)$/);
9717
+ if (nthMatch) {
9718
+ segment.position = "nth";
9719
+ segment.positionValue = parseInt(nthMatch[1], 10);
9720
+ } else {
9721
+ segment.position = positionMatch;
9722
+ }
9723
+ }
9724
+ return segment;
9725
+ }
9726
+ /**
9727
+ * Get the number of segments
9728
+ * @returns {number}
9729
+ */
9730
+ get length() {
9731
+ return this.segments.length;
9732
+ }
9733
+ /**
9734
+ * Check if expression contains deep wildcard
9735
+ * @returns {boolean}
9736
+ */
9737
+ hasDeepWildcard() {
9738
+ return this._hasDeepWildcard;
9739
+ }
9740
+ /**
9741
+ * Check if expression has attribute conditions
9742
+ * @returns {boolean}
9743
+ */
9744
+ hasAttributeCondition() {
9745
+ return this._hasAttributeCondition;
9746
+ }
9747
+ /**
9748
+ * Check if expression has position selectors
9749
+ * @returns {boolean}
9750
+ */
9751
+ hasPositionSelector() {
9752
+ return this._hasPositionSelector;
9753
+ }
9754
+ /**
9755
+ * Get string representation
9756
+ * @returns {string}
9757
+ */
9758
+ toString() {
9759
+ return this.pattern;
9760
+ }
9761
+ };
9762
+
9763
+ // ../../node_modules/path-expression-matcher/src/ExpressionSet.js
9764
+ var ExpressionSet = class {
9765
+ constructor() {
9766
+ this._byDepthAndTag = /* @__PURE__ */ new Map();
9767
+ this._wildcardByDepth = /* @__PURE__ */ new Map();
9768
+ this._deepWildcards = [];
9769
+ this._patterns = /* @__PURE__ */ new Set();
9770
+ this._sealed = false;
9771
+ }
9772
+ /**
9773
+ * Add an Expression to the set.
9774
+ * Duplicate patterns (same pattern string) are silently ignored.
9775
+ *
9776
+ * @param {import('./Expression.js').default} expression - A pre-constructed Expression instance
9777
+ * @returns {this} for chaining
9778
+ * @throws {TypeError} if called after seal()
9779
+ *
9780
+ * @example
9781
+ * set.add(new Expression('root.users.user'));
9782
+ * set.add(new Expression('..script'));
9783
+ */
9784
+ add(expression) {
9785
+ if (this._sealed) {
9786
+ throw new TypeError(
9787
+ "ExpressionSet is sealed. Create a new ExpressionSet to add more expressions."
9788
+ );
9789
+ }
9790
+ if (this._patterns.has(expression.pattern))
9791
+ return this;
9792
+ this._patterns.add(expression.pattern);
9793
+ if (expression.hasDeepWildcard()) {
9794
+ this._deepWildcards.push(expression);
9795
+ return this;
9796
+ }
9797
+ const depth = expression.length;
9798
+ const lastSeg = expression.segments[expression.segments.length - 1];
9799
+ const tag = lastSeg?.tag;
9800
+ if (!tag || tag === "*") {
9801
+ if (!this._wildcardByDepth.has(depth))
9802
+ this._wildcardByDepth.set(depth, []);
9803
+ this._wildcardByDepth.get(depth).push(expression);
9804
+ } else {
9805
+ const key = `${depth}:${tag}`;
9806
+ if (!this._byDepthAndTag.has(key))
9807
+ this._byDepthAndTag.set(key, []);
9808
+ this._byDepthAndTag.get(key).push(expression);
9809
+ }
9810
+ return this;
9811
+ }
9812
+ /**
9813
+ * Add multiple expressions at once.
9814
+ *
9815
+ * @param {import('./Expression.js').default[]} expressions - Array of Expression instances
9816
+ * @returns {this} for chaining
9817
+ *
9818
+ * @example
9819
+ * set.addAll([
9820
+ * new Expression('root.users.user'),
9821
+ * new Expression('root.config.setting'),
9822
+ * ]);
9823
+ */
9824
+ addAll(expressions) {
9825
+ for (const expr of expressions)
9826
+ this.add(expr);
9827
+ return this;
9828
+ }
9829
+ /**
9830
+ * Check whether a pattern string is already present in the set.
9831
+ *
9832
+ * @param {import('./Expression.js').default} expression
9833
+ * @returns {boolean}
9834
+ */
9835
+ has(expression) {
9836
+ return this._patterns.has(expression.pattern);
9837
+ }
9838
+ /**
9839
+ * Number of expressions in the set.
9840
+ * @type {number}
9841
+ */
9842
+ get size() {
9843
+ return this._patterns.size;
9844
+ }
9845
+ /**
9846
+ * Seal the set against further modifications.
9847
+ * Useful to prevent accidental mutations after config is built.
9848
+ * Calling add() or addAll() on a sealed set throws a TypeError.
9849
+ *
9850
+ * @returns {this}
9851
+ */
9852
+ seal() {
9853
+ this._sealed = true;
9854
+ return this;
9855
+ }
9856
+ /**
9857
+ * Whether the set has been sealed.
9858
+ * @type {boolean}
9859
+ */
9860
+ get isSealed() {
9861
+ return this._sealed;
9862
+ }
9863
+ /**
9864
+ * Test whether the matcher's current path matches any expression in the set.
9865
+ *
9866
+ * Evaluation order (cheapest → most expensive):
9867
+ * 1. Exact depth + tag bucket — O(1) lookup, typically 0–2 expressions
9868
+ * 2. Depth-only wildcard bucket — O(1) lookup, rare
9869
+ * 3. Deep-wildcard list — always checked, but usually small
9870
+ *
9871
+ * @param {import('./Matcher.js').default} matcher - Matcher instance (or readOnly view)
9872
+ * @returns {boolean} true if any expression matches the current path
9873
+ *
9874
+ * @example
9875
+ * if (stopNodes.matchesAny(matcher)) {
9876
+ * // handle stop node
9877
+ * }
9878
+ */
9879
+ matchesAny(matcher) {
9880
+ return this.findMatch(matcher) !== null;
9881
+ }
9882
+ /**
9883
+ * Find and return the first Expression that matches the matcher's current path.
9884
+ *
9885
+ * Uses the same evaluation order as matchesAny (cheapest → most expensive):
9886
+ * 1. Exact depth + tag bucket
9887
+ * 2. Depth-only wildcard bucket
9888
+ * 3. Deep-wildcard list
9889
+ *
9890
+ * @param {import('./Matcher.js').default} matcher - Matcher instance (or readOnly view)
9891
+ * @returns {import('./Expression.js').default | null} the first matching Expression, or null
9892
+ *
9893
+ * @example
9894
+ * const expr = stopNodes.findMatch(matcher);
9895
+ * if (expr) {
9896
+ * // access expr.config, expr.pattern, etc.
9897
+ * }
9898
+ */
9899
+ findMatch(matcher) {
9900
+ const depth = matcher.getDepth();
9901
+ const tag = matcher.getCurrentTag();
9902
+ const exactKey = `${depth}:${tag}`;
9903
+ const exactBucket = this._byDepthAndTag.get(exactKey);
9904
+ if (exactBucket) {
9905
+ for (let i = 0; i < exactBucket.length; i++) {
9906
+ if (matcher.matches(exactBucket[i]))
9907
+ return exactBucket[i];
9908
+ }
9909
+ }
9910
+ const wildcardBucket = this._wildcardByDepth.get(depth);
9911
+ if (wildcardBucket) {
9912
+ for (let i = 0; i < wildcardBucket.length; i++) {
9913
+ if (matcher.matches(wildcardBucket[i]))
9914
+ return wildcardBucket[i];
9915
+ }
9916
+ }
9917
+ for (let i = 0; i < this._deepWildcards.length; i++) {
9918
+ if (matcher.matches(this._deepWildcards[i]))
9919
+ return this._deepWildcards[i];
9920
+ }
9921
+ return null;
9922
+ }
9923
+ };
9924
+
9925
+ // ../../node_modules/path-expression-matcher/src/Matcher.js
9926
+ var MUTATING_METHODS = /* @__PURE__ */ new Set(["push", "pop", "reset", "updateCurrent", "restore"]);
9927
+ var Matcher = class {
9928
+ /**
9929
+ * Create a new Matcher
9930
+ * @param {Object} options - Configuration options
9931
+ * @param {string} options.separator - Default path separator (default: '.')
9932
+ */
9933
+ constructor(options = {}) {
9934
+ this.separator = options.separator || ".";
9935
+ this.path = [];
9936
+ this.siblingStacks = [];
9937
+ this._pathStringCache = null;
9938
+ this._frozenPathCache = null;
9939
+ this._frozenSiblingsCache = null;
9940
+ }
9941
+ /**
9942
+ * Push a new tag onto the path
9943
+ * @param {string} tagName - Name of the tag
9944
+ * @param {Object} attrValues - Attribute key-value pairs for current node (optional)
9945
+ * @param {string} namespace - Namespace for the tag (optional)
9946
+ */
9947
+ push(tagName, attrValues = null, namespace = null) {
9948
+ this._pathStringCache = null;
9949
+ this._frozenPathCache = null;
9950
+ this._frozenSiblingsCache = null;
9951
+ if (this.path.length > 0) {
9952
+ const prev = this.path[this.path.length - 1];
9953
+ prev.values = void 0;
9954
+ }
9955
+ const currentLevel = this.path.length;
9956
+ if (!this.siblingStacks[currentLevel]) {
9957
+ this.siblingStacks[currentLevel] = /* @__PURE__ */ new Map();
9958
+ }
9959
+ const siblings = this.siblingStacks[currentLevel];
9960
+ const siblingKey = namespace ? `${namespace}:${tagName}` : tagName;
9961
+ const counter = siblings.get(siblingKey) || 0;
9962
+ let position = 0;
9963
+ for (const count of siblings.values()) {
9964
+ position += count;
9965
+ }
9966
+ siblings.set(siblingKey, counter + 1);
9967
+ const node = {
9968
+ tag: tagName,
9969
+ position,
9970
+ counter
9971
+ };
9972
+ if (namespace !== null && namespace !== void 0) {
9973
+ node.namespace = namespace;
9974
+ }
9975
+ if (attrValues !== null && attrValues !== void 0) {
9976
+ node.values = attrValues;
9977
+ }
9978
+ this.path.push(node);
9979
+ }
9980
+ /**
9981
+ * Pop the last tag from the path
9982
+ * @returns {Object|undefined} The popped node
9983
+ */
9984
+ pop() {
9985
+ if (this.path.length === 0)
9986
+ return void 0;
9987
+ this._pathStringCache = null;
9988
+ this._frozenPathCache = null;
9989
+ this._frozenSiblingsCache = null;
9990
+ const node = this.path.pop();
9991
+ if (this.siblingStacks.length > this.path.length + 1) {
9992
+ this.siblingStacks.length = this.path.length + 1;
9993
+ }
9994
+ return node;
9995
+ }
9996
+ /**
9997
+ * Update current node's attribute values
9998
+ * Useful when attributes are parsed after push
9999
+ * @param {Object} attrValues - Attribute values
10000
+ */
10001
+ updateCurrent(attrValues) {
10002
+ if (this.path.length > 0) {
10003
+ const current = this.path[this.path.length - 1];
10004
+ if (attrValues !== null && attrValues !== void 0) {
10005
+ current.values = attrValues;
10006
+ this._frozenPathCache = null;
10007
+ }
10008
+ }
10009
+ }
10010
+ /**
10011
+ * Get current tag name
10012
+ * @returns {string|undefined}
10013
+ */
10014
+ getCurrentTag() {
10015
+ return this.path.length > 0 ? this.path[this.path.length - 1].tag : void 0;
10016
+ }
10017
+ /**
10018
+ * Get current namespace
10019
+ * @returns {string|undefined}
10020
+ */
10021
+ getCurrentNamespace() {
10022
+ return this.path.length > 0 ? this.path[this.path.length - 1].namespace : void 0;
10023
+ }
10024
+ /**
10025
+ * Get current node's attribute value
10026
+ * @param {string} attrName - Attribute name
10027
+ * @returns {*} Attribute value or undefined
10028
+ */
10029
+ getAttrValue(attrName) {
10030
+ if (this.path.length === 0)
10031
+ return void 0;
10032
+ const current = this.path[this.path.length - 1];
10033
+ return current.values?.[attrName];
10034
+ }
10035
+ /**
10036
+ * Check if current node has an attribute
10037
+ * @param {string} attrName - Attribute name
10038
+ * @returns {boolean}
10039
+ */
10040
+ hasAttr(attrName) {
10041
+ if (this.path.length === 0)
10042
+ return false;
10043
+ const current = this.path[this.path.length - 1];
10044
+ return current.values !== void 0 && attrName in current.values;
10045
+ }
10046
+ /**
10047
+ * Get current node's sibling position (child index in parent)
10048
+ * @returns {number}
10049
+ */
10050
+ getPosition() {
10051
+ if (this.path.length === 0)
10052
+ return -1;
10053
+ return this.path[this.path.length - 1].position ?? 0;
10054
+ }
10055
+ /**
10056
+ * Get current node's repeat counter (occurrence count of this tag name)
10057
+ * @returns {number}
10058
+ */
10059
+ getCounter() {
10060
+ if (this.path.length === 0)
10061
+ return -1;
10062
+ return this.path[this.path.length - 1].counter ?? 0;
10063
+ }
10064
+ /**
10065
+ * Get current node's sibling index (alias for getPosition for backward compatibility)
10066
+ * @returns {number}
10067
+ * @deprecated Use getPosition() or getCounter() instead
10068
+ */
10069
+ getIndex() {
10070
+ return this.getPosition();
10071
+ }
10072
+ /**
10073
+ * Get current path depth
10074
+ * @returns {number}
10075
+ */
10076
+ getDepth() {
10077
+ return this.path.length;
10078
+ }
10079
+ /**
10080
+ * Get path as string
10081
+ * @param {string} separator - Optional separator (uses default if not provided)
10082
+ * @param {boolean} includeNamespace - Whether to include namespace in output (default: true)
10083
+ * @returns {string}
10084
+ */
10085
+ toString(separator, includeNamespace = true) {
10086
+ const sep = separator || this.separator;
10087
+ const isDefault = sep === this.separator && includeNamespace === true;
10088
+ if (isDefault) {
10089
+ if (this._pathStringCache !== null && this._pathStringCache !== void 0) {
10090
+ return this._pathStringCache;
10091
+ }
10092
+ const result = this.path.map(
10093
+ (n) => includeNamespace && n.namespace ? `${n.namespace}:${n.tag}` : n.tag
10094
+ ).join(sep);
10095
+ this._pathStringCache = result;
10096
+ return result;
10097
+ }
10098
+ return this.path.map(
10099
+ (n) => includeNamespace && n.namespace ? `${n.namespace}:${n.tag}` : n.tag
10100
+ ).join(sep);
10101
+ }
10102
+ /**
10103
+ * Get path as array of tag names
10104
+ * @returns {string[]}
10105
+ */
10106
+ toArray() {
10107
+ return this.path.map((n) => n.tag);
10108
+ }
10109
+ /**
10110
+ * Reset the path to empty
10111
+ */
10112
+ reset() {
10113
+ this._pathStringCache = null;
10114
+ this._frozenPathCache = null;
10115
+ this._frozenSiblingsCache = null;
10116
+ this.path = [];
10117
+ this.siblingStacks = [];
10118
+ }
10119
+ /**
10120
+ * Match current path against an Expression
10121
+ * @param {Expression} expression - The expression to match against
10122
+ * @returns {boolean} True if current path matches the expression
10123
+ */
10124
+ matches(expression) {
10125
+ const segments = expression.segments;
10126
+ if (segments.length === 0) {
10127
+ return false;
10128
+ }
10129
+ if (expression.hasDeepWildcard()) {
10130
+ return this._matchWithDeepWildcard(segments);
10131
+ }
10132
+ return this._matchSimple(segments);
10133
+ }
10134
+ /**
10135
+ * Match simple path (no deep wildcards)
10136
+ * @private
10137
+ */
10138
+ _matchSimple(segments) {
10139
+ if (this.path.length !== segments.length) {
10140
+ return false;
10141
+ }
10142
+ for (let i = 0; i < segments.length; i++) {
10143
+ const segment = segments[i];
10144
+ const node = this.path[i];
10145
+ const isCurrentNode = i === this.path.length - 1;
10146
+ if (!this._matchSegment(segment, node, isCurrentNode)) {
10147
+ return false;
10148
+ }
10149
+ }
10150
+ return true;
10151
+ }
10152
+ /**
10153
+ * Match path with deep wildcards
10154
+ * @private
10155
+ */
10156
+ _matchWithDeepWildcard(segments) {
10157
+ let pathIdx = this.path.length - 1;
10158
+ let segIdx = segments.length - 1;
10159
+ while (segIdx >= 0 && pathIdx >= 0) {
10160
+ const segment = segments[segIdx];
10161
+ if (segment.type === "deep-wildcard") {
10162
+ segIdx--;
10163
+ if (segIdx < 0) {
10164
+ return true;
10165
+ }
10166
+ const nextSeg = segments[segIdx];
10167
+ let found = false;
10168
+ for (let i = pathIdx; i >= 0; i--) {
10169
+ const isCurrentNode = i === this.path.length - 1;
10170
+ if (this._matchSegment(nextSeg, this.path[i], isCurrentNode)) {
10171
+ pathIdx = i - 1;
10172
+ segIdx--;
10173
+ found = true;
10174
+ break;
10175
+ }
10176
+ }
10177
+ if (!found) {
10178
+ return false;
10179
+ }
10180
+ } else {
10181
+ const isCurrentNode = pathIdx === this.path.length - 1;
10182
+ if (!this._matchSegment(segment, this.path[pathIdx], isCurrentNode)) {
10183
+ return false;
10184
+ }
10185
+ pathIdx--;
10186
+ segIdx--;
10187
+ }
10188
+ }
10189
+ return segIdx < 0;
10190
+ }
10191
+ /**
10192
+ * Match a single segment against a node
10193
+ * @private
10194
+ * @param {Object} segment - Segment from Expression
10195
+ * @param {Object} node - Node from path
10196
+ * @param {boolean} isCurrentNode - Whether this is the current (last) node
10197
+ * @returns {boolean}
10198
+ */
10199
+ _matchSegment(segment, node, isCurrentNode) {
10200
+ if (segment.tag !== "*" && segment.tag !== node.tag) {
10201
+ return false;
10202
+ }
10203
+ if (segment.namespace !== void 0) {
10204
+ if (segment.namespace !== "*" && segment.namespace !== node.namespace) {
10205
+ return false;
10206
+ }
10207
+ }
10208
+ if (segment.attrName !== void 0) {
10209
+ if (!isCurrentNode) {
10210
+ return false;
10211
+ }
10212
+ if (!node.values || !(segment.attrName in node.values)) {
10213
+ return false;
10214
+ }
10215
+ if (segment.attrValue !== void 0) {
10216
+ const actualValue = node.values[segment.attrName];
10217
+ if (String(actualValue) !== String(segment.attrValue)) {
10218
+ return false;
10219
+ }
10220
+ }
10221
+ }
10222
+ if (segment.position !== void 0) {
10223
+ if (!isCurrentNode) {
10224
+ return false;
10225
+ }
10226
+ const counter = node.counter ?? 0;
10227
+ if (segment.position === "first" && counter !== 0) {
10228
+ return false;
10229
+ } else if (segment.position === "odd" && counter % 2 !== 1) {
10230
+ return false;
10231
+ } else if (segment.position === "even" && counter % 2 !== 0) {
10232
+ return false;
10233
+ } else if (segment.position === "nth") {
10234
+ if (counter !== segment.positionValue) {
10235
+ return false;
10236
+ }
10237
+ }
10238
+ }
10239
+ return true;
10240
+ }
10241
+ /**
10242
+ * Match any expression in the given set against the current path.
10243
+ * @param {ExpressionSet} exprSet - The set of expressions to match against.
10244
+ * @returns {boolean} - True if any expression in the set matches the current path, false otherwise.
10245
+ */
10246
+ matchesAny(exprSet) {
10247
+ return exprSet.matchesAny(this);
10248
+ }
10249
+ /**
10250
+ * Create a snapshot of current state
10251
+ * @returns {Object} State snapshot
10252
+ */
10253
+ snapshot() {
10254
+ return {
10255
+ path: this.path.map((node) => ({ ...node })),
10256
+ siblingStacks: this.siblingStacks.map((map2) => new Map(map2))
10257
+ };
10258
+ }
10259
+ /**
10260
+ * Restore state from snapshot
10261
+ * @param {Object} snapshot - State snapshot
10262
+ */
10263
+ restore(snapshot) {
10264
+ this._pathStringCache = null;
10265
+ this._frozenPathCache = null;
10266
+ this._frozenSiblingsCache = null;
10267
+ this.path = snapshot.path.map((node) => ({ ...node }));
10268
+ this.siblingStacks = snapshot.siblingStacks.map((map2) => new Map(map2));
10269
+ }
10270
+ /**
10271
+ * Return a read-only view of this matcher.
10272
+ *
10273
+ * The returned object exposes all query/inspection methods but throws a
10274
+ * TypeError if any state-mutating method is called (`push`, `pop`, `reset`,
10275
+ * `updateCurrent`, `restore`). Property reads (e.g. `.path`, `.separator`)
10276
+ * are allowed but the returned arrays/objects are frozen so callers cannot
10277
+ * mutate internal state through them either.
10278
+ *
10279
+ * @returns {ReadOnlyMatcher} A proxy that forwards read operations and blocks writes.
10280
+ *
10281
+ * @example
10282
+ * const matcher = new Matcher();
10283
+ * matcher.push("root", {});
10284
+ *
10285
+ * const ro = matcher.readOnly();
10286
+ * ro.matches(expr); // ✓ works
10287
+ * ro.getCurrentTag(); // ✓ works
10288
+ * ro.push("child", {}); // ✗ throws TypeError
10289
+ * ro.reset(); // ✗ throws TypeError
10290
+ */
10291
+ readOnly() {
10292
+ const self2 = this;
10293
+ return new Proxy(self2, {
10294
+ get(target, prop, receiver) {
10295
+ if (MUTATING_METHODS.has(prop)) {
10296
+ return () => {
10297
+ throw new TypeError(
10298
+ `Cannot call '${prop}' on a read-only Matcher. Obtain a writable instance to mutate state.`
10299
+ );
10300
+ };
10301
+ }
10302
+ if (prop === "path") {
10303
+ if (target._frozenPathCache === null) {
10304
+ target._frozenPathCache = Object.freeze(
10305
+ target.path.map((node) => Object.freeze({ ...node }))
10306
+ );
10307
+ }
10308
+ return target._frozenPathCache;
10309
+ }
10310
+ if (prop === "siblingStacks") {
10311
+ if (target._frozenSiblingsCache === null) {
10312
+ target._frozenSiblingsCache = Object.freeze(
10313
+ target.siblingStacks.map((map2) => Object.freeze(new Map(map2)))
10314
+ );
10315
+ }
10316
+ return target._frozenSiblingsCache;
10317
+ }
10318
+ const value = Reflect.get(target, prop, receiver);
10319
+ if (typeof value === "function") {
10320
+ return value.bind(target);
10321
+ }
10322
+ return value;
10323
+ },
10324
+ // Prevent any property assignment on the read-only view
10325
+ set(_target, prop) {
10326
+ throw new TypeError(
10327
+ `Cannot set property '${String(prop)}' on a read-only Matcher.`
10328
+ );
10329
+ },
10330
+ // Prevent property deletion
10331
+ deleteProperty(_target, prop) {
10332
+ throw new TypeError(
10333
+ `Cannot delete property '${String(prop)}' from a read-only Matcher.`
10334
+ );
10335
+ }
10336
+ });
10337
+ }
10338
+ };
10339
+
9446
10340
  // ../../node_modules/fast-xml-parser/src/xmlparser/OrderedObjParser.js
10341
+ function extractRawAttributes(prefixedAttrs, options) {
10342
+ if (!prefixedAttrs)
10343
+ return {};
10344
+ const attrs = options.attributesGroupName ? prefixedAttrs[options.attributesGroupName] : prefixedAttrs;
10345
+ if (!attrs)
10346
+ return {};
10347
+ const rawAttrs = {};
10348
+ for (const key in attrs) {
10349
+ if (key.startsWith(options.attributeNamePrefix)) {
10350
+ const rawName = key.substring(options.attributeNamePrefix.length);
10351
+ rawAttrs[rawName] = attrs[key];
10352
+ } else {
10353
+ rawAttrs[key] = attrs[key];
10354
+ }
10355
+ }
10356
+ return rawAttrs;
10357
+ }
10358
+ function extractNamespace(rawTagName) {
10359
+ if (!rawTagName || typeof rawTagName !== "string")
10360
+ return void 0;
10361
+ const colonIndex = rawTagName.indexOf(":");
10362
+ if (colonIndex !== -1 && colonIndex > 0) {
10363
+ const ns = rawTagName.substring(0, colonIndex);
10364
+ if (ns !== "xmlns") {
10365
+ return ns;
10366
+ }
10367
+ }
10368
+ return void 0;
10369
+ }
9447
10370
  var OrderedObjParser = class {
9448
10371
  constructor(options) {
9449
10372
  this.options = options;
@@ -9487,19 +10410,21 @@ var __exports__ = (() => {
9487
10410
  this.ignoreAttributesFn = getIgnoreAttributesFn(this.options.ignoreAttributes);
9488
10411
  this.entityExpansionCount = 0;
9489
10412
  this.currentExpandedLength = 0;
9490
- if (this.options.stopNodes && this.options.stopNodes.length > 0) {
9491
- this.stopNodesExact = /* @__PURE__ */ new Set();
9492
- this.stopNodesWildcard = /* @__PURE__ */ new Set();
9493
- for (let i = 0; i < this.options.stopNodes.length; i++) {
9494
- const stopNodeExp = this.options.stopNodes[i];
9495
- if (typeof stopNodeExp !== "string")
9496
- continue;
9497
- if (stopNodeExp.startsWith("*.")) {
9498
- this.stopNodesWildcard.add(stopNodeExp.substring(2));
9499
- } else {
9500
- this.stopNodesExact.add(stopNodeExp);
10413
+ this.matcher = new Matcher();
10414
+ this.readonlyMatcher = this.matcher.readOnly();
10415
+ this.isCurrentNodeStopNode = false;
10416
+ this.stopNodeExpressionsSet = new ExpressionSet();
10417
+ const stopNodesOpts = this.options.stopNodes;
10418
+ if (stopNodesOpts && stopNodesOpts.length > 0) {
10419
+ for (let i = 0; i < stopNodesOpts.length; i++) {
10420
+ const stopNodeExp = stopNodesOpts[i];
10421
+ if (typeof stopNodeExp === "string") {
10422
+ this.stopNodeExpressionsSet.add(new Expression(stopNodeExp));
10423
+ } else if (stopNodeExp instanceof Expression) {
10424
+ this.stopNodeExpressionsSet.add(stopNodeExp);
9501
10425
  }
9502
10426
  }
10427
+ this.stopNodeExpressionsSet.seal();
9503
10428
  }
9504
10429
  }
9505
10430
  };
@@ -9515,24 +10440,26 @@ var __exports__ = (() => {
9515
10440
  }
9516
10441
  }
9517
10442
  function parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) {
10443
+ const options = this.options;
9518
10444
  if (val !== void 0) {
9519
- if (this.options.trimValues && !dontTrim) {
10445
+ if (options.trimValues && !dontTrim) {
9520
10446
  val = val.trim();
9521
10447
  }
9522
10448
  if (val.length > 0) {
9523
10449
  if (!escapeEntities)
9524
10450
  val = this.replaceEntitiesValue(val, tagName, jPath);
9525
- const newval = this.options.tagValueProcessor(tagName, val, jPath, hasAttributes, isLeafNode);
10451
+ const jPathOrMatcher = options.jPath ? jPath.toString() : jPath;
10452
+ const newval = options.tagValueProcessor(tagName, val, jPathOrMatcher, hasAttributes, isLeafNode);
9526
10453
  if (newval === null || newval === void 0) {
9527
10454
  return val;
9528
10455
  } else if (typeof newval !== typeof val || newval !== val) {
9529
10456
  return newval;
9530
- } else if (this.options.trimValues) {
9531
- return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions);
10457
+ } else if (options.trimValues) {
10458
+ return parseValue(val, options.parseTagValue, options.numberParseOptions);
9532
10459
  } else {
9533
10460
  const trimmedVal = val.trim();
9534
10461
  if (trimmedVal === val) {
9535
- return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions);
10462
+ return parseValue(val, options.parseTagValue, options.numberParseOptions);
9536
10463
  } else {
9537
10464
  return val;
9538
10465
  }
@@ -9555,51 +10482,64 @@ var __exports__ = (() => {
9555
10482
  }
9556
10483
  var attrsRegx = new RegExp(`([^\\s=]+)\\s*(=\\s*(['"])([\\s\\S]*?)\\3)?`, "gm");
9557
10484
  function buildAttributesMap(attrStr, jPath, tagName) {
9558
- if (this.options.ignoreAttributes !== true && typeof attrStr === "string") {
10485
+ const options = this.options;
10486
+ if (options.ignoreAttributes !== true && typeof attrStr === "string") {
9559
10487
  const matches3 = getAllMatches(attrStr, attrsRegx);
9560
10488
  const len5 = matches3.length;
9561
10489
  const attrs = {};
10490
+ const processedVals = new Array(len5);
10491
+ let hasRawAttrs = false;
10492
+ const rawAttrsForMatcher = {};
10493
+ for (let i = 0; i < len5; i++) {
10494
+ const attrName = this.resolveNameSpace(matches3[i][1]);
10495
+ const oldVal = matches3[i][4];
10496
+ if (attrName.length && oldVal !== void 0) {
10497
+ let val = oldVal;
10498
+ if (options.trimValues)
10499
+ val = val.trim();
10500
+ val = this.replaceEntitiesValue(val, tagName, this.readonlyMatcher);
10501
+ processedVals[i] = val;
10502
+ rawAttrsForMatcher[attrName] = val;
10503
+ hasRawAttrs = true;
10504
+ }
10505
+ }
10506
+ if (hasRawAttrs && typeof jPath === "object" && jPath.updateCurrent) {
10507
+ jPath.updateCurrent(rawAttrsForMatcher);
10508
+ }
10509
+ const jPathStr = options.jPath ? jPath.toString() : this.readonlyMatcher;
10510
+ let hasAttrs = false;
9562
10511
  for (let i = 0; i < len5; i++) {
9563
10512
  const attrName = this.resolveNameSpace(matches3[i][1]);
9564
- if (this.ignoreAttributesFn(attrName, jPath)) {
10513
+ if (this.ignoreAttributesFn(attrName, jPathStr))
9565
10514
  continue;
9566
- }
9567
- let oldVal = matches3[i][4];
9568
- let aName = this.options.attributeNamePrefix + attrName;
10515
+ let aName = options.attributeNamePrefix + attrName;
9569
10516
  if (attrName.length) {
9570
- if (this.options.transformAttributeName) {
9571
- aName = this.options.transformAttributeName(aName);
10517
+ if (options.transformAttributeName) {
10518
+ aName = options.transformAttributeName(aName);
9572
10519
  }
9573
- if (aName === "__proto__")
9574
- aName = "#__proto__";
9575
- if (oldVal !== void 0) {
9576
- if (this.options.trimValues) {
9577
- oldVal = oldVal.trim();
9578
- }
9579
- oldVal = this.replaceEntitiesValue(oldVal, tagName, jPath);
9580
- const newVal = this.options.attributeValueProcessor(attrName, oldVal, jPath);
10520
+ aName = sanitizeName(aName, options);
10521
+ if (matches3[i][4] !== void 0) {
10522
+ const oldVal = processedVals[i];
10523
+ const newVal = options.attributeValueProcessor(attrName, oldVal, jPathStr);
9581
10524
  if (newVal === null || newVal === void 0) {
9582
10525
  attrs[aName] = oldVal;
9583
10526
  } else if (typeof newVal !== typeof oldVal || newVal !== oldVal) {
9584
10527
  attrs[aName] = newVal;
9585
10528
  } else {
9586
- attrs[aName] = parseValue(
9587
- oldVal,
9588
- this.options.parseAttributeValue,
9589
- this.options.numberParseOptions
9590
- );
10529
+ attrs[aName] = parseValue(oldVal, options.parseAttributeValue, options.numberParseOptions);
9591
10530
  }
9592
- } else if (this.options.allowBooleanAttributes) {
10531
+ hasAttrs = true;
10532
+ } else if (options.allowBooleanAttributes) {
9593
10533
  attrs[aName] = true;
10534
+ hasAttrs = true;
9594
10535
  }
9595
10536
  }
9596
10537
  }
9597
- if (!Object.keys(attrs).length) {
10538
+ if (!hasAttrs)
9598
10539
  return;
9599
- }
9600
- if (this.options.attributesGroupName) {
10540
+ if (options.attributesGroupName) {
9601
10541
  const attrCollection = {};
9602
- attrCollection[this.options.attributesGroupName] = attrs;
10542
+ attrCollection[options.attributesGroupName] = attrs;
9603
10543
  return attrCollection;
9604
10544
  }
9605
10545
  return attrs;
@@ -9610,123 +10550,144 @@ var __exports__ = (() => {
9610
10550
  const xmlObj = new XmlNode("!xml");
9611
10551
  let currentNode = xmlObj;
9612
10552
  let textData = "";
9613
- let jPath = "";
10553
+ this.matcher.reset();
9614
10554
  this.entityExpansionCount = 0;
9615
10555
  this.currentExpandedLength = 0;
9616
- const docTypeReader = new DocTypeReader(this.options.processEntities);
9617
- for (let i = 0; i < xmlData.length; i++) {
10556
+ this.docTypeEntitiesKeys = [];
10557
+ this.lastEntitiesKeys = Object.keys(this.lastEntities);
10558
+ this.htmlEntitiesKeys = this.options.htmlEntities ? Object.keys(this.htmlEntities) : [];
10559
+ const options = this.options;
10560
+ const docTypeReader = new DocTypeReader(options.processEntities);
10561
+ const xmlLen = xmlData.length;
10562
+ for (let i = 0; i < xmlLen; i++) {
9618
10563
  const ch = xmlData[i];
9619
10564
  if (ch === "<") {
9620
- if (xmlData[i + 1] === "/") {
10565
+ const c1 = xmlData.charCodeAt(i + 1);
10566
+ if (c1 === 47) {
9621
10567
  const closeIndex = findClosingIndex(xmlData, ">", i, "Closing Tag is not closed.");
9622
10568
  let tagName = xmlData.substring(i + 2, closeIndex).trim();
9623
- if (this.options.removeNSPrefix) {
10569
+ if (options.removeNSPrefix) {
9624
10570
  const colonIndex = tagName.indexOf(":");
9625
10571
  if (colonIndex !== -1) {
9626
10572
  tagName = tagName.substr(colonIndex + 1);
9627
10573
  }
9628
10574
  }
9629
- if (this.options.transformTagName) {
9630
- tagName = this.options.transformTagName(tagName);
9631
- }
10575
+ tagName = transformTagName(options.transformTagName, tagName, "", options).tagName;
9632
10576
  if (currentNode) {
9633
- textData = this.saveTextToParentTag(textData, currentNode, jPath);
10577
+ textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
9634
10578
  }
9635
- const lastTagName = jPath.substring(jPath.lastIndexOf(".") + 1);
9636
- if (tagName && this.options.unpairedTags.indexOf(tagName) !== -1) {
10579
+ const lastTagName = this.matcher.getCurrentTag();
10580
+ if (tagName && options.unpairedTagsSet.has(tagName)) {
9637
10581
  throw new Error(`Unpaired tag can not be used as closing tag: </${tagName}>`);
9638
10582
  }
9639
- let propIndex = 0;
9640
- if (lastTagName && this.options.unpairedTags.indexOf(lastTagName) !== -1) {
9641
- propIndex = jPath.lastIndexOf(".", jPath.lastIndexOf(".") - 1);
10583
+ if (lastTagName && options.unpairedTagsSet.has(lastTagName)) {
10584
+ this.matcher.pop();
9642
10585
  this.tagsNodeStack.pop();
9643
- } else {
9644
- propIndex = jPath.lastIndexOf(".");
9645
10586
  }
9646
- jPath = jPath.substring(0, propIndex);
10587
+ this.matcher.pop();
10588
+ this.isCurrentNodeStopNode = false;
9647
10589
  currentNode = this.tagsNodeStack.pop();
9648
10590
  textData = "";
9649
10591
  i = closeIndex;
9650
- } else if (xmlData[i + 1] === "?") {
10592
+ } else if (c1 === 63) {
9651
10593
  let tagData = readTagExp(xmlData, i, false, "?>");
9652
10594
  if (!tagData)
9653
10595
  throw new Error("Pi Tag is not closed.");
9654
- textData = this.saveTextToParentTag(textData, currentNode, jPath);
9655
- if (this.options.ignoreDeclaration && tagData.tagName === "?xml" || this.options.ignorePiTags) {
10596
+ textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
10597
+ if (options.ignoreDeclaration && tagData.tagName === "?xml" || options.ignorePiTags) {
9656
10598
  } else {
9657
10599
  const childNode = new XmlNode(tagData.tagName);
9658
- childNode.add(this.options.textNodeName, "");
10600
+ childNode.add(options.textNodeName, "");
9659
10601
  if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent) {
9660
- childNode[":@"] = this.buildAttributesMap(tagData.tagExp, jPath, tagData.tagName);
10602
+ childNode[":@"] = this.buildAttributesMap(tagData.tagExp, this.matcher, tagData.tagName);
9661
10603
  }
9662
- this.addChild(currentNode, childNode, jPath, i);
10604
+ this.addChild(currentNode, childNode, this.readonlyMatcher, i);
9663
10605
  }
9664
10606
  i = tagData.closeIndex + 1;
9665
- } else if (xmlData.substr(i + 1, 3) === "!--") {
10607
+ } else if (c1 === 33 && xmlData.charCodeAt(i + 2) === 45 && xmlData.charCodeAt(i + 3) === 45) {
9666
10608
  const endIndex = findClosingIndex(xmlData, "-->", i + 4, "Comment is not closed.");
9667
- if (this.options.commentPropName) {
10609
+ if (options.commentPropName) {
9668
10610
  const comment = xmlData.substring(i + 4, endIndex - 2);
9669
- textData = this.saveTextToParentTag(textData, currentNode, jPath);
9670
- currentNode.add(this.options.commentPropName, [{ [this.options.textNodeName]: comment }]);
10611
+ textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
10612
+ currentNode.add(options.commentPropName, [{ [options.textNodeName]: comment }]);
9671
10613
  }
9672
10614
  i = endIndex;
9673
- } else if (xmlData.substr(i + 1, 2) === "!D") {
10615
+ } else if (c1 === 33 && xmlData.charCodeAt(i + 2) === 68) {
9674
10616
  const result = docTypeReader.readDocType(xmlData, i);
9675
10617
  this.docTypeEntities = result.entities;
10618
+ this.docTypeEntitiesKeys = Object.keys(this.docTypeEntities) || [];
9676
10619
  i = result.i;
9677
- } else if (xmlData.substr(i + 1, 2) === "![") {
10620
+ } else if (c1 === 33 && xmlData.charCodeAt(i + 2) === 91) {
9678
10621
  const closeIndex = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2;
9679
10622
  const tagExp = xmlData.substring(i + 9, closeIndex);
9680
- textData = this.saveTextToParentTag(textData, currentNode, jPath);
9681
- let val = this.parseTextData(tagExp, currentNode.tagname, jPath, true, false, true, true);
10623
+ textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
10624
+ let val = this.parseTextData(tagExp, currentNode.tagname, this.readonlyMatcher, true, false, true, true);
9682
10625
  if (val == void 0)
9683
10626
  val = "";
9684
- if (this.options.cdataPropName) {
9685
- currentNode.add(this.options.cdataPropName, [{ [this.options.textNodeName]: tagExp }]);
10627
+ if (options.cdataPropName) {
10628
+ currentNode.add(options.cdataPropName, [{ [options.textNodeName]: tagExp }]);
9686
10629
  } else {
9687
- currentNode.add(this.options.textNodeName, val);
10630
+ currentNode.add(options.textNodeName, val);
9688
10631
  }
9689
10632
  i = closeIndex + 2;
9690
10633
  } else {
9691
- let result = readTagExp(xmlData, i, this.options.removeNSPrefix);
10634
+ let result = readTagExp(xmlData, i, options.removeNSPrefix);
10635
+ if (!result) {
10636
+ const context = xmlData.substring(Math.max(0, i - 50), Math.min(xmlLen, i + 50));
10637
+ throw new Error(`readTagExp returned undefined at position ${i}. Context: "${context}"`);
10638
+ }
9692
10639
  let tagName = result.tagName;
9693
10640
  const rawTagName = result.rawTagName;
9694
10641
  let tagExp = result.tagExp;
9695
10642
  let attrExpPresent = result.attrExpPresent;
9696
10643
  let closeIndex = result.closeIndex;
9697
- if (this.options.transformTagName) {
9698
- const newTagName = this.options.transformTagName(tagName);
9699
- if (tagExp === tagName) {
9700
- tagExp = newTagName;
9701
- }
9702
- tagName = newTagName;
10644
+ ({ tagName, tagExp } = transformTagName(options.transformTagName, tagName, tagExp, options));
10645
+ if (options.strictReservedNames && (tagName === options.commentPropName || tagName === options.cdataPropName || tagName === options.textNodeName || tagName === options.attributesGroupName)) {
10646
+ throw new Error(`Invalid tag name: ${tagName}`);
9703
10647
  }
9704
10648
  if (currentNode && textData) {
9705
10649
  if (currentNode.tagname !== "!xml") {
9706
- textData = this.saveTextToParentTag(textData, currentNode, jPath, false);
10650
+ textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher, false);
9707
10651
  }
9708
10652
  }
9709
10653
  const lastTag = currentNode;
9710
- if (lastTag && this.options.unpairedTags.indexOf(lastTag.tagname) !== -1) {
10654
+ if (lastTag && options.unpairedTagsSet.has(lastTag.tagname)) {
9711
10655
  currentNode = this.tagsNodeStack.pop();
9712
- jPath = jPath.substring(0, jPath.lastIndexOf("."));
10656
+ this.matcher.pop();
9713
10657
  }
10658
+ let isSelfClosing = false;
10659
+ if (tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1) {
10660
+ isSelfClosing = true;
10661
+ if (tagName[tagName.length - 1] === "/") {
10662
+ tagName = tagName.substr(0, tagName.length - 1);
10663
+ tagExp = tagName;
10664
+ } else {
10665
+ tagExp = tagExp.substr(0, tagExp.length - 1);
10666
+ }
10667
+ attrExpPresent = tagName !== tagExp;
10668
+ }
10669
+ let prefixedAttrs = null;
10670
+ let rawAttrs = {};
10671
+ let namespace = void 0;
10672
+ namespace = extractNamespace(rawTagName);
9714
10673
  if (tagName !== xmlObj.tagname) {
9715
- jPath += jPath ? "." + tagName : tagName;
10674
+ this.matcher.push(tagName, {}, namespace);
10675
+ }
10676
+ if (tagName !== tagExp && attrExpPresent) {
10677
+ prefixedAttrs = this.buildAttributesMap(tagExp, this.matcher, tagName);
10678
+ if (prefixedAttrs) {
10679
+ rawAttrs = extractRawAttributes(prefixedAttrs, options);
10680
+ }
10681
+ }
10682
+ if (tagName !== xmlObj.tagname) {
10683
+ this.isCurrentNodeStopNode = this.isItStopNode();
9716
10684
  }
9717
10685
  const startIndex = i;
9718
- if (this.isItStopNode(this.stopNodesExact, this.stopNodesWildcard, jPath, tagName)) {
10686
+ if (this.isCurrentNodeStopNode) {
9719
10687
  let tagContent = "";
9720
- if (tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1) {
9721
- if (tagName[tagName.length - 1] === "/") {
9722
- tagName = tagName.substr(0, tagName.length - 1);
9723
- jPath = jPath.substr(0, jPath.length - 1);
9724
- tagExp = tagName;
9725
- } else {
9726
- tagExp = tagExp.substr(0, tagExp.length - 1);
9727
- }
10688
+ if (isSelfClosing) {
9728
10689
  i = result.closeIndex;
9729
- } else if (this.options.unpairedTags.indexOf(tagName) !== -1) {
10690
+ } else if (options.unpairedTagsSet.has(tagName)) {
9730
10691
  i = result.closeIndex;
9731
10692
  } else {
9732
10693
  const result2 = this.readStopNodeData(xmlData, rawTagName, closeIndex + 1);
@@ -9736,44 +10697,43 @@ var __exports__ = (() => {
9736
10697
  tagContent = result2.tagContent;
9737
10698
  }
9738
10699
  const childNode = new XmlNode(tagName);
9739
- if (tagName !== tagExp && attrExpPresent) {
9740
- childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
10700
+ if (prefixedAttrs) {
10701
+ childNode[":@"] = prefixedAttrs;
9741
10702
  }
9742
- if (tagContent) {
9743
- tagContent = this.parseTextData(tagContent, tagName, jPath, true, attrExpPresent, true, true);
9744
- }
9745
- jPath = jPath.substr(0, jPath.lastIndexOf("."));
9746
- childNode.add(this.options.textNodeName, tagContent);
9747
- this.addChild(currentNode, childNode, jPath, startIndex);
10703
+ childNode.add(options.textNodeName, tagContent);
10704
+ this.matcher.pop();
10705
+ this.isCurrentNodeStopNode = false;
10706
+ this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
9748
10707
  } else {
9749
- if (tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1) {
9750
- if (tagName[tagName.length - 1] === "/") {
9751
- tagName = tagName.substr(0, tagName.length - 1);
9752
- jPath = jPath.substr(0, jPath.length - 1);
9753
- tagExp = tagName;
9754
- } else {
9755
- tagExp = tagExp.substr(0, tagExp.length - 1);
9756
- }
9757
- if (this.options.transformTagName) {
9758
- const newTagName = this.options.transformTagName(tagName);
9759
- if (tagExp === tagName) {
9760
- tagExp = newTagName;
9761
- }
9762
- tagName = newTagName;
10708
+ if (isSelfClosing) {
10709
+ ({ tagName, tagExp } = transformTagName(options.transformTagName, tagName, tagExp, options));
10710
+ const childNode = new XmlNode(tagName);
10711
+ if (prefixedAttrs) {
10712
+ childNode[":@"] = prefixedAttrs;
9763
10713
  }
10714
+ this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
10715
+ this.matcher.pop();
10716
+ this.isCurrentNodeStopNode = false;
10717
+ } else if (options.unpairedTagsSet.has(tagName)) {
9764
10718
  const childNode = new XmlNode(tagName);
9765
- if (tagName !== tagExp && attrExpPresent) {
9766
- childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
10719
+ if (prefixedAttrs) {
10720
+ childNode[":@"] = prefixedAttrs;
9767
10721
  }
9768
- this.addChild(currentNode, childNode, jPath, startIndex);
9769
- jPath = jPath.substr(0, jPath.lastIndexOf("."));
10722
+ this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
10723
+ this.matcher.pop();
10724
+ this.isCurrentNodeStopNode = false;
10725
+ i = result.closeIndex;
10726
+ continue;
9770
10727
  } else {
9771
10728
  const childNode = new XmlNode(tagName);
10729
+ if (this.tagsNodeStack.length > options.maxNestedTags) {
10730
+ throw new Error("Maximum nested tags exceeded");
10731
+ }
9772
10732
  this.tagsNodeStack.push(currentNode);
9773
- if (tagName !== tagExp && attrExpPresent) {
9774
- childNode[":@"] = this.buildAttributesMap(tagExp, jPath, tagName);
10733
+ if (prefixedAttrs) {
10734
+ childNode[":@"] = prefixedAttrs;
9775
10735
  }
9776
- this.addChild(currentNode, childNode, jPath, startIndex);
10736
+ this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
9777
10737
  currentNode = childNode;
9778
10738
  }
9779
10739
  textData = "";
@@ -9786,10 +10746,11 @@ var __exports__ = (() => {
9786
10746
  }
9787
10747
  return xmlObj.child;
9788
10748
  };
9789
- function addChild(currentNode, childNode, jPath, startIndex) {
10749
+ function addChild(currentNode, childNode, matcher, startIndex) {
9790
10750
  if (!this.options.captureMetaData)
9791
10751
  startIndex = void 0;
9792
- const result = this.options.updateTag(childNode.tagname, jPath, childNode[":@"]);
10752
+ const jPathOrMatcher = this.options.jPath ? matcher.toString() : matcher;
10753
+ const result = this.options.updateTag(childNode.tagname, jPathOrMatcher, childNode[":@"]);
9793
10754
  if (result === false) {
9794
10755
  } else if (typeof result === "string") {
9795
10756
  childNode.tagname = result;
@@ -9798,25 +10759,25 @@ var __exports__ = (() => {
9798
10759
  currentNode.addChild(childNode, startIndex);
9799
10760
  }
9800
10761
  }
9801
- var replaceEntitiesValue = function(val, tagName, jPath) {
9802
- if (val.indexOf("&") === -1) {
9803
- return val;
9804
- }
10762
+ function replaceEntitiesValue(val, tagName, jPath) {
9805
10763
  const entityConfig = this.options.processEntities;
9806
- if (!entityConfig.enabled) {
10764
+ if (!entityConfig || !entityConfig.enabled) {
9807
10765
  return val;
9808
10766
  }
9809
10767
  if (entityConfig.allowedTags) {
9810
- if (!entityConfig.allowedTags.includes(tagName)) {
10768
+ const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;
10769
+ const allowed = Array.isArray(entityConfig.allowedTags) ? entityConfig.allowedTags.includes(tagName) : entityConfig.allowedTags(tagName, jPathOrMatcher);
10770
+ if (!allowed) {
9811
10771
  return val;
9812
10772
  }
9813
10773
  }
9814
10774
  if (entityConfig.tagFilter) {
9815
- if (!entityConfig.tagFilter(tagName, jPath)) {
10775
+ const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;
10776
+ if (!entityConfig.tagFilter(tagName, jPathOrMatcher)) {
9816
10777
  return val;
9817
10778
  }
9818
10779
  }
9819
- for (let entityName in this.docTypeEntities) {
10780
+ for (const entityName of this.docTypeEntitiesKeys) {
9820
10781
  const entity = this.docTypeEntities[entityName];
9821
10782
  const matches3 = val.match(entity.regx);
9822
10783
  if (matches3) {
@@ -9840,74 +10801,86 @@ var __exports__ = (() => {
9840
10801
  }
9841
10802
  if (val.indexOf("&") === -1)
9842
10803
  return val;
9843
- for (let entityName in this.lastEntities) {
10804
+ for (const entityName of this.lastEntitiesKeys) {
9844
10805
  const entity = this.lastEntities[entityName];
10806
+ const matches3 = val.match(entity.regex);
10807
+ if (matches3) {
10808
+ this.entityExpansionCount += matches3.length;
10809
+ if (entityConfig.maxTotalExpansions && this.entityExpansionCount > entityConfig.maxTotalExpansions) {
10810
+ throw new Error(
10811
+ `Entity expansion limit exceeded: ${this.entityExpansionCount} > ${entityConfig.maxTotalExpansions}`
10812
+ );
10813
+ }
10814
+ }
9845
10815
  val = val.replace(entity.regex, entity.val);
9846
10816
  }
9847
10817
  if (val.indexOf("&") === -1)
9848
10818
  return val;
9849
- if (this.options.htmlEntities) {
9850
- for (let entityName in this.htmlEntities) {
9851
- const entity = this.htmlEntities[entityName];
9852
- val = val.replace(entity.regex, entity.val);
10819
+ for (const entityName of this.htmlEntitiesKeys) {
10820
+ const entity = this.htmlEntities[entityName];
10821
+ const matches3 = val.match(entity.regex);
10822
+ if (matches3) {
10823
+ this.entityExpansionCount += matches3.length;
10824
+ if (entityConfig.maxTotalExpansions && this.entityExpansionCount > entityConfig.maxTotalExpansions) {
10825
+ throw new Error(
10826
+ `Entity expansion limit exceeded: ${this.entityExpansionCount} > ${entityConfig.maxTotalExpansions}`
10827
+ );
10828
+ }
9853
10829
  }
10830
+ val = val.replace(entity.regex, entity.val);
9854
10831
  }
9855
10832
  val = val.replace(this.ampEntity.regex, this.ampEntity.val);
9856
10833
  return val;
9857
- };
9858
- function saveTextToParentTag(textData, currentNode, jPath, isLeafNode) {
10834
+ }
10835
+ function saveTextToParentTag(textData, parentNode, matcher, isLeafNode) {
9859
10836
  if (textData) {
9860
10837
  if (isLeafNode === void 0)
9861
- isLeafNode = currentNode.child.length === 0;
10838
+ isLeafNode = parentNode.child.length === 0;
9862
10839
  textData = this.parseTextData(
9863
10840
  textData,
9864
- currentNode.tagname,
9865
- jPath,
10841
+ parentNode.tagname,
10842
+ matcher,
9866
10843
  false,
9867
- currentNode[":@"] ? Object.keys(currentNode[":@"]).length !== 0 : false,
10844
+ parentNode[":@"] ? Object.keys(parentNode[":@"]).length !== 0 : false,
9868
10845
  isLeafNode
9869
10846
  );
9870
10847
  if (textData !== void 0 && textData !== "")
9871
- currentNode.add(this.options.textNodeName, textData);
10848
+ parentNode.add(this.options.textNodeName, textData);
9872
10849
  textData = "";
9873
10850
  }
9874
10851
  return textData;
9875
10852
  }
9876
- function isItStopNode(stopNodesExact, stopNodesWildcard, jPath, currentTagName) {
9877
- if (stopNodesWildcard && stopNodesWildcard.has(currentTagName))
9878
- return true;
9879
- if (stopNodesExact && stopNodesExact.has(jPath))
9880
- return true;
9881
- return false;
10853
+ function isItStopNode() {
10854
+ if (this.stopNodeExpressionsSet.size === 0)
10855
+ return false;
10856
+ return this.matcher.matchesAny(this.stopNodeExpressionsSet);
9882
10857
  }
9883
10858
  function tagExpWithClosingIndex(xmlData, i, closingChar = ">") {
9884
- let attrBoundary;
9885
- let tagExp = "";
9886
- for (let index = i; index < xmlData.length; index++) {
9887
- let ch = xmlData[index];
10859
+ let attrBoundary = 0;
10860
+ const chars = [];
10861
+ const len5 = xmlData.length;
10862
+ const closeCode0 = closingChar.charCodeAt(0);
10863
+ const closeCode1 = closingChar.length > 1 ? closingChar.charCodeAt(1) : -1;
10864
+ for (let index = i; index < len5; index++) {
10865
+ const code = xmlData.charCodeAt(index);
9888
10866
  if (attrBoundary) {
9889
- if (ch === attrBoundary)
9890
- attrBoundary = "";
9891
- } else if (ch === '"' || ch === "'") {
9892
- attrBoundary = ch;
9893
- } else if (ch === closingChar[0]) {
9894
- if (closingChar[1]) {
9895
- if (xmlData[index + 1] === closingChar[1]) {
9896
- return {
9897
- data: tagExp,
9898
- index
9899
- };
10867
+ if (code === attrBoundary)
10868
+ attrBoundary = 0;
10869
+ } else if (code === 34 || code === 39) {
10870
+ attrBoundary = code;
10871
+ } else if (code === closeCode0) {
10872
+ if (closeCode1 !== -1) {
10873
+ if (xmlData.charCodeAt(index + 1) === closeCode1) {
10874
+ return { data: String.fromCharCode(...chars), index };
9900
10875
  }
9901
10876
  } else {
9902
- return {
9903
- data: tagExp,
9904
- index
9905
- };
10877
+ return { data: String.fromCharCode(...chars), index };
9906
10878
  }
9907
- } else if (ch === " ") {
9908
- ch = " ";
10879
+ } else if (code === 9) {
10880
+ chars.push(32);
10881
+ continue;
9909
10882
  }
9910
- tagExp += ch;
10883
+ chars.push(code);
9911
10884
  }
9912
10885
  }
9913
10886
  function findClosingIndex(xmlData, str7, i, errMsg) {
@@ -9918,6 +10891,12 @@ var __exports__ = (() => {
9918
10891
  return closingIndex + str7.length - 1;
9919
10892
  }
9920
10893
  }
10894
+ function findClosingChar(xmlData, char, i, errMsg) {
10895
+ const closingIndex = xmlData.indexOf(char, i);
10896
+ if (closingIndex === -1)
10897
+ throw new Error(errMsg);
10898
+ return closingIndex;
10899
+ }
9921
10900
  function readTagExp(xmlData, i, removeNSPrefix, closingChar = ">") {
9922
10901
  const result = tagExpWithClosingIndex(xmlData, i + 1, closingChar);
9923
10902
  if (!result)
@@ -9950,10 +10929,12 @@ var __exports__ = (() => {
9950
10929
  function readStopNodeData(xmlData, tagName, i) {
9951
10930
  const startIndex = i;
9952
10931
  let openTagCount = 1;
9953
- for (; i < xmlData.length; i++) {
10932
+ const xmllen = xmlData.length;
10933
+ for (; i < xmllen; i++) {
9954
10934
  if (xmlData[i] === "<") {
9955
- if (xmlData[i + 1] === "/") {
9956
- const closeIndex = findClosingIndex(xmlData, ">", i, `${tagName} is not closed`);
10935
+ const c1 = xmlData.charCodeAt(i + 1);
10936
+ if (c1 === 47) {
10937
+ const closeIndex = findClosingChar(xmlData, ">", i, `${tagName} is not closed`);
9957
10938
  let closeTagName = xmlData.substring(i + 2, closeIndex).trim();
9958
10939
  if (closeTagName === tagName) {
9959
10940
  openTagCount--;
@@ -9965,13 +10946,13 @@ var __exports__ = (() => {
9965
10946
  }
9966
10947
  }
9967
10948
  i = closeIndex;
9968
- } else if (xmlData[i + 1] === "?") {
10949
+ } else if (c1 === 63) {
9969
10950
  const closeIndex = findClosingIndex(xmlData, "?>", i + 1, "StopNode is not closed.");
9970
10951
  i = closeIndex;
9971
- } else if (xmlData.substr(i + 1, 3) === "!--") {
10952
+ } else if (c1 === 33 && xmlData.charCodeAt(i + 2) === 45 && xmlData.charCodeAt(i + 3) === 45) {
9972
10953
  const closeIndex = findClosingIndex(xmlData, "-->", i + 3, "StopNode is not closed.");
9973
10954
  i = closeIndex;
9974
- } else if (xmlData.substr(i + 1, 2) === "![") {
10955
+ } else if (c1 === 33 && xmlData.charCodeAt(i + 2) === 91) {
9975
10956
  const closeIndex = findClosingIndex(xmlData, "]]>", i, "StopNode is not closed.") - 2;
9976
10957
  i = closeIndex;
9977
10958
  } else {
@@ -10012,23 +10993,60 @@ var __exports__ = (() => {
10012
10993
  return prefix + str7 + ";";
10013
10994
  }
10014
10995
  }
10996
+ function transformTagName(fn, tagName, tagExp, options) {
10997
+ if (fn) {
10998
+ const newTagName = fn(tagName);
10999
+ if (tagExp === tagName) {
11000
+ tagExp = newTagName;
11001
+ }
11002
+ tagName = newTagName;
11003
+ }
11004
+ tagName = sanitizeName(tagName, options);
11005
+ return { tagName, tagExp };
11006
+ }
11007
+ function sanitizeName(name12, options) {
11008
+ if (criticalProperties.includes(name12)) {
11009
+ throw new Error(`[SECURITY] Invalid name: "${name12}" is a reserved JavaScript keyword that could cause prototype pollution`);
11010
+ } else if (DANGEROUS_PROPERTY_NAMES.includes(name12)) {
11011
+ return options.onDangerousProperty(name12);
11012
+ }
11013
+ return name12;
11014
+ }
10015
11015
 
10016
11016
  // ../../node_modules/fast-xml-parser/src/xmlparser/node2json.js
10017
11017
  var METADATA_SYMBOL2 = XmlNode.getMetaDataSymbol();
10018
- function prettify(node, options) {
10019
- return compress(node, options);
11018
+ function stripAttributePrefix(attrs, prefix) {
11019
+ if (!attrs || typeof attrs !== "object")
11020
+ return {};
11021
+ if (!prefix)
11022
+ return attrs;
11023
+ const rawAttrs = {};
11024
+ for (const key in attrs) {
11025
+ if (key.startsWith(prefix)) {
11026
+ const rawName = key.substring(prefix.length);
11027
+ rawAttrs[rawName] = attrs[key];
11028
+ } else {
11029
+ rawAttrs[key] = attrs[key];
11030
+ }
11031
+ }
11032
+ return rawAttrs;
10020
11033
  }
10021
- function compress(arr, options, jPath) {
11034
+ function prettify(node, options, matcher, readonlyMatcher) {
11035
+ return compress(node, options, matcher, readonlyMatcher);
11036
+ }
11037
+ function compress(arr, options, matcher, readonlyMatcher) {
10022
11038
  let text;
10023
11039
  const compressedObj = {};
10024
11040
  for (let i = 0; i < arr.length; i++) {
10025
11041
  const tagObj = arr[i];
10026
11042
  const property = propName(tagObj);
10027
- let newJpath = "";
10028
- if (jPath === void 0)
10029
- newJpath = property;
10030
- else
10031
- newJpath = jPath + "." + property;
11043
+ if (property !== void 0 && property !== options.textNodeName) {
11044
+ const rawAttrs = stripAttributePrefix(
11045
+ tagObj[":@"] || {},
11046
+ options.attributeNamePrefix
11047
+ );
11048
+ matcher.push(property, rawAttrs);
11049
+ }
10032
11050
  if (property === options.textNodeName) {
10033
11051
  if (text === void 0)
10034
11052
  text = tagObj[property];
@@ -10037,13 +11055,10 @@ var __exports__ = (() => {
10037
11055
  } else if (property === void 0) {
10038
11056
  continue;
10039
11057
  } else if (tagObj[property]) {
10040
- let val = compress(tagObj[property], options, newJpath);
11058
+ let val = compress(tagObj[property], options, matcher, readonlyMatcher);
10041
11059
  const isLeaf = isLeafTag(val, options);
10042
- if (tagObj[METADATA_SYMBOL2] !== void 0) {
10043
- val[METADATA_SYMBOL2] = tagObj[METADATA_SYMBOL2];
10044
- }
10045
11060
  if (tagObj[":@"]) {
10046
- assignAttributes(val, tagObj[":@"], newJpath, options);
11061
+ assignAttributes(val, tagObj[":@"], readonlyMatcher, options);
10047
11062
  } else if (Object.keys(val).length === 1 && val[options.textNodeName] !== void 0 && !options.alwaysCreateTextNode) {
10048
11063
  val = val[options.textNodeName];
10049
11064
  } else if (Object.keys(val).length === 0) {
@@ -10052,18 +11067,25 @@ var __exports__ = (() => {
10052
11067
  else
10053
11068
  val = "";
10054
11069
  }
10055
- if (compressedObj[property] !== void 0 && compressedObj.hasOwnProperty(property)) {
11070
+ if (tagObj[METADATA_SYMBOL2] !== void 0 && typeof val === "object" && val !== null) {
11071
+ val[METADATA_SYMBOL2] = tagObj[METADATA_SYMBOL2];
11072
+ }
11073
+ if (compressedObj[property] !== void 0 && Object.prototype.hasOwnProperty.call(compressedObj, property)) {
10056
11074
  if (!Array.isArray(compressedObj[property])) {
10057
11075
  compressedObj[property] = [compressedObj[property]];
10058
11076
  }
10059
11077
  compressedObj[property].push(val);
10060
11078
  } else {
10061
- if (options.isArray(property, newJpath, isLeaf)) {
11079
+ const jPathOrMatcher = options.jPath ? readonlyMatcher.toString() : readonlyMatcher;
11080
+ if (options.isArray(property, jPathOrMatcher, isLeaf)) {
10062
11081
  compressedObj[property] = [val];
10063
11082
  } else {
10064
11083
  compressedObj[property] = val;
10065
11084
  }
10066
11085
  }
11086
+ if (property !== void 0 && property !== options.textNodeName) {
11087
+ matcher.pop();
11088
+ }
10067
11089
  }
10068
11090
  }
10069
11091
  if (typeof text === "string") {
@@ -10081,13 +11103,15 @@ var __exports__ = (() => {
10081
11103
  return key;
10082
11104
  }
10083
11105
  }
10084
- function assignAttributes(obj, attrMap, jpath, options) {
11106
+ function assignAttributes(obj, attrMap, readonlyMatcher, options) {
10085
11107
  if (attrMap) {
10086
11108
  const keys = Object.keys(attrMap);
10087
11109
  const len5 = keys.length;
10088
11110
  for (let i = 0; i < len5; i++) {
10089
11111
  const atrrName = keys[i];
10090
- if (options.isArray(atrrName, jpath + "." + atrrName, true, true)) {
11112
+ const rawAttrName = atrrName.startsWith(options.attributeNamePrefix) ? atrrName.substring(options.attributeNamePrefix.length) : atrrName;
11113
+ const jPathOrMatcher = options.jPath ? readonlyMatcher.toString() + "." + rawAttrName : readonlyMatcher;
11114
+ if (options.isArray(atrrName, jPathOrMatcher, true, true)) {
10091
11115
  obj[atrrName] = [attrMap[atrrName]];
10092
11116
  } else {
10093
11117
  obj[atrrName] = attrMap[atrrName];
@@ -10138,7 +11162,7 @@ var __exports__ = (() => {
10138
11162
  if (this.options.preserveOrder || orderedResult === void 0)
10139
11163
  return orderedResult;
10140
11164
  else
10141
- return prettify(orderedResult, this.options);
11165
+ return prettify(orderedResult, this.options, orderedObjParser.matcher, orderedObjParser.readonlyMatcher);
10142
11166
  }
10143
11167
  /**
10144
11168
  * Add Entity which is not by default supported by this library
@@ -14503,7 +15527,7 @@ var __exports__ = (() => {
14503
15527
  visibleMinZoom,
14504
15528
  visibleMaxZoom
14505
15529
  }) {
14506
- let z = viewport.isGeospatial ? Math.round(viewport.zoom + Math.log2(TILE_SIZE4 / tileSize)) + zoomOffset : Math.ceil(viewport.zoom) + zoomOffset;
15530
+ let z = viewport.isGeospatial ? Math.round(viewport.zoom + Math.log2(TILE_SIZE4 / tileSize) + zoomOffset) : Math.ceil(viewport.zoom + zoomOffset);
14507
15531
  if (typeof minZoom === "number" && Number.isFinite(minZoom) && z < minZoom) {
14508
15532
  if (!extent) {
14509
15533
  return [];