@dan-uni/dan-any 1.3.8 → 1.4.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.
@@ -1232,7 +1232,6 @@
1232
1232
  if (y < x) return 1;
1233
1233
  return 0;
1234
1234
  }
1235
- var ONLY_ENUMERABLE = void 0;
1236
1235
  var kStrict = true;
1237
1236
  var kLoose = false;
1238
1237
  var kNoIterator = 0;
@@ -1282,8 +1281,8 @@
1282
1281
  if (val1Tag !== val2Tag) return false;
1283
1282
  if (Array.isArray(val1)) {
1284
1283
  if (val1.length !== val2.length) return false;
1285
- var keys1 = getOwnNonIndexProperties(val1, ONLY_ENUMERABLE);
1286
- var keys2 = getOwnNonIndexProperties(val2, ONLY_ENUMERABLE);
1284
+ var keys1 = getOwnNonIndexProperties(val1);
1285
+ var keys2 = getOwnNonIndexProperties(val2);
1287
1286
  if (keys1.length !== keys2.length) return false;
1288
1287
  return keyCheck(val1, val2, strict, memos, kIsArray, keys1);
1289
1288
  }
@@ -1300,8 +1299,8 @@
1300
1299
  if (!strict && (isFloat32Array(val1) || isFloat64Array(val1))) {
1301
1300
  if (!areSimilarFloatArrays(val1, val2)) return false;
1302
1301
  } else if (!areSimilarTypedArrays(val1, val2)) return false;
1303
- var _keys = getOwnNonIndexProperties(val1, ONLY_ENUMERABLE);
1304
- var _keys2 = getOwnNonIndexProperties(val2, ONLY_ENUMERABLE);
1302
+ var _keys = getOwnNonIndexProperties(val1);
1303
+ var _keys2 = getOwnNonIndexProperties(val2);
1305
1304
  if (_keys.length !== _keys2.length) return false;
1306
1305
  return keyCheck(val1, val2, strict, memos, kNoIterator, _keys);
1307
1306
  } else if (isSet(val1)) {
@@ -14026,10 +14025,10 @@
14026
14025
  if ('object' == typeof value && null !== value) return {
14027
14026
  enabled: false !== value.enabled,
14028
14027
  maxEntitySize: Math.max(1, value.maxEntitySize ?? 10000),
14029
- maxExpansionDepth: Math.max(1, value.maxExpansionDepth ?? 10),
14030
- maxTotalExpansions: Math.max(1, value.maxTotalExpansions ?? 1000),
14028
+ maxExpansionDepth: Math.max(1, value.maxExpansionDepth ?? 10000),
14029
+ maxTotalExpansions: Math.max(1, value.maxTotalExpansions ?? 1 / 0),
14031
14030
  maxExpandedLength: Math.max(1, value.maxExpandedLength ?? 100000),
14032
- maxEntityCount: Math.max(1, value.maxEntityCount ?? 100),
14031
+ maxEntityCount: Math.max(1, value.maxEntityCount ?? 1000),
14033
14032
  allowedTags: value.allowedTags ?? null,
14034
14033
  tagFilter: value.tagFilter ?? null
14035
14034
  };
@@ -14062,6 +14061,7 @@
14062
14061
  for (const { value, name } of propertyNameOptions)if (value) validatePropertyName(value, name);
14063
14062
  if (null === built.onDangerousProperty) built.onDangerousProperty = defaultOnDangerousProperty;
14064
14063
  built.processEntities = normalizeProcessEntities(built.processEntities);
14064
+ built.unpairedTagsSet = new Set(built.unpairedTags);
14065
14065
  if (built.stopNodes && Array.isArray(built.stopNodes)) built.stopNodes = built.stopNodes.map((node)=>{
14066
14066
  if ('string' == typeof node && node.startsWith('*.')) return '..' + node.substring(2);
14067
14067
  return node;
@@ -14336,9 +14336,10 @@
14336
14336
  options = Object.assign({}, consider, options);
14337
14337
  if (!str || "string" != typeof str) return str;
14338
14338
  let trimmedStr = str.trim();
14339
- if (void 0 !== options.skipLike && options.skipLike.test(trimmedStr)) return str;
14339
+ if (0 === trimmedStr.length) return str;
14340
14340
  {
14341
- if ("0" === str) return 0;
14341
+ if (void 0 !== options.skipLike && options.skipLike.test(trimmedStr)) return str;
14342
+ if ("0" === trimmedStr) return 0;
14342
14343
  if (options.hex && hexRegex.test(trimmedStr)) return parse_int(trimmedStr, 16);
14343
14344
  if (!isFinite(trimmedStr)) return handleInfinity(str, Number(trimmedStr), options);
14344
14345
  if (trimmedStr.includes('e') || trimmedStr.includes('E')) return resolveEnotation(str, trimmedStr, options);
@@ -14424,24 +14425,72 @@
14424
14425
  };
14425
14426
  return ()=>false;
14426
14427
  }
14427
- const MUTATING_METHODS = new Set([
14428
- 'push',
14429
- 'pop',
14430
- 'reset',
14431
- 'updateCurrent',
14432
- 'restore'
14433
- ]);
14428
+ class MatcherView {
14429
+ constructor(matcher){
14430
+ this._matcher = matcher;
14431
+ }
14432
+ get separator() {
14433
+ return this._matcher.separator;
14434
+ }
14435
+ getCurrentTag() {
14436
+ const path = this._matcher.path;
14437
+ return path.length > 0 ? path[path.length - 1].tag : void 0;
14438
+ }
14439
+ getCurrentNamespace() {
14440
+ const path = this._matcher.path;
14441
+ return path.length > 0 ? path[path.length - 1].namespace : void 0;
14442
+ }
14443
+ getAttrValue(attrName) {
14444
+ const path = this._matcher.path;
14445
+ if (0 === path.length) return;
14446
+ return path[path.length - 1].values?.[attrName];
14447
+ }
14448
+ hasAttr(attrName) {
14449
+ const path = this._matcher.path;
14450
+ if (0 === path.length) return false;
14451
+ const current = path[path.length - 1];
14452
+ return void 0 !== current.values && attrName in current.values;
14453
+ }
14454
+ getPosition() {
14455
+ const path = this._matcher.path;
14456
+ if (0 === path.length) return -1;
14457
+ return path[path.length - 1].position ?? 0;
14458
+ }
14459
+ getCounter() {
14460
+ const path = this._matcher.path;
14461
+ if (0 === path.length) return -1;
14462
+ return path[path.length - 1].counter ?? 0;
14463
+ }
14464
+ getIndex() {
14465
+ return this.getPosition();
14466
+ }
14467
+ getDepth() {
14468
+ return this._matcher.path.length;
14469
+ }
14470
+ toString(separator, includeNamespace = true) {
14471
+ return this._matcher.toString(separator, includeNamespace);
14472
+ }
14473
+ toArray() {
14474
+ return this._matcher.path.map((n)=>n.tag);
14475
+ }
14476
+ matches(expression) {
14477
+ return this._matcher.matches(expression);
14478
+ }
14479
+ matchesAny(exprSet) {
14480
+ return exprSet.matchesAny(this._matcher);
14481
+ }
14482
+ }
14434
14483
  class Matcher {
14435
14484
  constructor(options = {}){
14436
14485
  this.separator = options.separator || '.';
14437
14486
  this.path = [];
14438
14487
  this.siblingStacks = [];
14488
+ this._pathStringCache = null;
14489
+ this._view = new MatcherView(this);
14439
14490
  }
14440
14491
  push(tagName, attrValues = null, namespace = null) {
14441
- if (this.path.length > 0) {
14442
- const prev = this.path[this.path.length - 1];
14443
- prev.values = void 0;
14444
- }
14492
+ this._pathStringCache = null;
14493
+ if (this.path.length > 0) this.path[this.path.length - 1].values = void 0;
14445
14494
  const currentLevel = this.path.length;
14446
14495
  if (!this.siblingStacks[currentLevel]) this.siblingStacks[currentLevel] = new Map();
14447
14496
  const siblings = this.siblingStacks[currentLevel];
@@ -14461,6 +14510,7 @@
14461
14510
  }
14462
14511
  pop() {
14463
14512
  if (0 === this.path.length) return;
14513
+ this._pathStringCache = null;
14464
14514
  const node = this.path.pop();
14465
14515
  if (this.siblingStacks.length > this.path.length + 1) this.siblingStacks.length = this.path.length + 1;
14466
14516
  return node;
@@ -14479,8 +14529,7 @@
14479
14529
  }
14480
14530
  getAttrValue(attrName) {
14481
14531
  if (0 === this.path.length) return;
14482
- const current = this.path[this.path.length - 1];
14483
- return current.values?.[attrName];
14532
+ return this.path[this.path.length - 1].values?.[attrName];
14484
14533
  }
14485
14534
  hasAttr(attrName) {
14486
14535
  if (0 === this.path.length) return false;
@@ -14503,15 +14552,20 @@
14503
14552
  }
14504
14553
  toString(separator, includeNamespace = true) {
14505
14554
  const sep = separator || this.separator;
14506
- return this.path.map((n)=>{
14507
- if (includeNamespace && n.namespace) return `${n.namespace}:${n.tag}`;
14508
- return n.tag;
14509
- }).join(sep);
14555
+ const isDefault = sep === this.separator && true === includeNamespace;
14556
+ if (isDefault) {
14557
+ if (null !== this._pathStringCache) return this._pathStringCache;
14558
+ const result = this.path.map((n)=>n.namespace ? `${n.namespace}:${n.tag}` : n.tag).join(sep);
14559
+ this._pathStringCache = result;
14560
+ return result;
14561
+ }
14562
+ return this.path.map((n)=>includeNamespace && n.namespace ? `${n.namespace}:${n.tag}` : n.tag).join(sep);
14510
14563
  }
14511
14564
  toArray() {
14512
14565
  return this.path.map((n)=>n.tag);
14513
14566
  }
14514
14567
  reset() {
14568
+ this._pathStringCache = null;
14515
14569
  this.path = [];
14516
14570
  this.siblingStacks = [];
14517
14571
  }
@@ -14523,12 +14577,7 @@
14523
14577
  }
14524
14578
  _matchSimple(segments) {
14525
14579
  if (this.path.length !== segments.length) return false;
14526
- for(let i = 0; i < segments.length; i++){
14527
- const segment = segments[i];
14528
- const node = this.path[i];
14529
- const isCurrentNode = i === this.path.length - 1;
14530
- if (!this._matchSegment(segment, node, isCurrentNode)) return false;
14531
- }
14580
+ for(let i = 0; i < segments.length; i++)if (!this._matchSegment(segments[i], this.path[i], i === this.path.length - 1)) return false;
14532
14581
  return true;
14533
14582
  }
14534
14583
  _matchWithDeepWildcard(segments) {
@@ -14541,19 +14590,15 @@
14541
14590
  if (segIdx < 0) return true;
14542
14591
  const nextSeg = segments[segIdx];
14543
14592
  let found = false;
14544
- for(let i = pathIdx; i >= 0; i--){
14545
- const isCurrentNode = i === this.path.length - 1;
14546
- if (this._matchSegment(nextSeg, this.path[i], isCurrentNode)) {
14547
- pathIdx = i - 1;
14548
- segIdx--;
14549
- found = true;
14550
- break;
14551
- }
14593
+ for(let i = pathIdx; i >= 0; i--)if (this._matchSegment(nextSeg, this.path[i], i === this.path.length - 1)) {
14594
+ pathIdx = i - 1;
14595
+ segIdx--;
14596
+ found = true;
14597
+ break;
14552
14598
  }
14553
14599
  if (!found) return false;
14554
14600
  } else {
14555
- const isCurrentNode = pathIdx === this.path.length - 1;
14556
- if (!this._matchSegment(segment, this.path[pathIdx], isCurrentNode)) return false;
14601
+ if (!this._matchSegment(segment, this.path[pathIdx], pathIdx === this.path.length - 1)) return false;
14557
14602
  pathIdx--;
14558
14603
  segIdx--;
14559
14604
  }
@@ -14569,8 +14614,7 @@
14569
14614
  if (!isCurrentNode) return false;
14570
14615
  if (!node.values || !(segment.attrName in node.values)) return false;
14571
14616
  if (void 0 !== segment.attrValue) {
14572
- const actualValue = node.values[segment.attrName];
14573
- if (String(actualValue) !== String(segment.attrValue)) return false;
14617
+ if (String(node.values[segment.attrName]) !== String(segment.attrValue)) return false;
14574
14618
  }
14575
14619
  }
14576
14620
  if (void 0 !== segment.position) {
@@ -14579,12 +14623,13 @@
14579
14623
  if ('first' === segment.position && 0 !== counter) return false;
14580
14624
  if ('odd' === segment.position && counter % 2 !== 1) return false;
14581
14625
  if ('even' === segment.position && counter % 2 !== 0) return false;
14582
- else if ('nth' === segment.position) {
14583
- if (counter !== segment.positionValue) return false;
14584
- }
14626
+ else if ('nth' === segment.position && counter !== segment.positionValue) return false;
14585
14627
  }
14586
14628
  return true;
14587
14629
  }
14630
+ matchesAny(exprSet) {
14631
+ return exprSet.matchesAny(this);
14632
+ }
14588
14633
  snapshot() {
14589
14634
  return {
14590
14635
  path: this.path.map((node)=>({
@@ -14594,39 +14639,22 @@
14594
14639
  };
14595
14640
  }
14596
14641
  restore(snapshot) {
14642
+ this._pathStringCache = null;
14597
14643
  this.path = snapshot.path.map((node)=>({
14598
14644
  ...node
14599
14645
  }));
14600
14646
  this.siblingStacks = snapshot.siblingStacks.map((map)=>new Map(map));
14601
14647
  }
14602
14648
  readOnly() {
14603
- const self1 = this;
14604
- return new Proxy(self1, {
14605
- get (target, prop, receiver) {
14606
- if (MUTATING_METHODS.has(prop)) return ()=>{
14607
- throw new TypeError(`Cannot call '${prop}' on a read-only Matcher. Obtain a writable instance to mutate state.`);
14608
- };
14609
- const value = Reflect.get(target, prop, receiver);
14610
- if ('path' === prop || 'siblingStacks' === prop) return Object.freeze(Array.isArray(value) ? value.map((item)=>item instanceof Map ? Object.freeze(new Map(item)) : Object.freeze({
14611
- ...item
14612
- })) : value);
14613
- if ('function' == typeof value) return value.bind(target);
14614
- return value;
14615
- },
14616
- set (_target, prop) {
14617
- throw new TypeError(`Cannot set property '${String(prop)}' on a read-only Matcher.`);
14618
- },
14619
- deleteProperty (_target, prop) {
14620
- throw new TypeError(`Cannot delete property '${String(prop)}' from a read-only Matcher.`);
14621
- }
14622
- });
14649
+ return this._view;
14623
14650
  }
14624
14651
  }
14625
14652
  class Expression {
14626
- constructor(pattern, options = {}){
14653
+ constructor(pattern, options = {}, data){
14627
14654
  this.pattern = pattern;
14628
14655
  this.separator = options.separator || '.';
14629
14656
  this.segments = this._parse(pattern);
14657
+ this.data = data;
14630
14658
  this._hasDeepWildcard = this.segments.some((seg)=>'deep-wildcard' === seg.type);
14631
14659
  this._hasAttributeCondition = this.segments.some((seg)=>void 0 !== seg.attrName);
14632
14660
  this._hasPositionSelector = this.segments.some((seg)=>void 0 !== seg.position);
@@ -14728,6 +14756,71 @@
14728
14756
  return this.pattern;
14729
14757
  }
14730
14758
  }
14759
+ class ExpressionSet {
14760
+ constructor(){
14761
+ this._byDepthAndTag = new Map();
14762
+ this._wildcardByDepth = new Map();
14763
+ this._deepWildcards = [];
14764
+ this._patterns = new Set();
14765
+ this._sealed = false;
14766
+ }
14767
+ add(expression) {
14768
+ if (this._sealed) throw new TypeError('ExpressionSet is sealed. Create a new ExpressionSet to add more expressions.');
14769
+ if (this._patterns.has(expression.pattern)) return this;
14770
+ this._patterns.add(expression.pattern);
14771
+ if (expression.hasDeepWildcard()) {
14772
+ this._deepWildcards.push(expression);
14773
+ return this;
14774
+ }
14775
+ const depth = expression.length;
14776
+ const lastSeg = expression.segments[expression.segments.length - 1];
14777
+ const tag = lastSeg?.tag;
14778
+ if (tag && '*' !== tag) {
14779
+ const key = `${depth}:${tag}`;
14780
+ if (!this._byDepthAndTag.has(key)) this._byDepthAndTag.set(key, []);
14781
+ this._byDepthAndTag.get(key).push(expression);
14782
+ } else {
14783
+ if (!this._wildcardByDepth.has(depth)) this._wildcardByDepth.set(depth, []);
14784
+ this._wildcardByDepth.get(depth).push(expression);
14785
+ }
14786
+ return this;
14787
+ }
14788
+ addAll(expressions) {
14789
+ for (const expr of expressions)this.add(expr);
14790
+ return this;
14791
+ }
14792
+ has(expression) {
14793
+ return this._patterns.has(expression.pattern);
14794
+ }
14795
+ get size() {
14796
+ return this._patterns.size;
14797
+ }
14798
+ seal() {
14799
+ this._sealed = true;
14800
+ return this;
14801
+ }
14802
+ get isSealed() {
14803
+ return this._sealed;
14804
+ }
14805
+ matchesAny(matcher) {
14806
+ return null !== this.findMatch(matcher);
14807
+ }
14808
+ findMatch(matcher) {
14809
+ const depth = matcher.getDepth();
14810
+ const tag = matcher.getCurrentTag();
14811
+ const exactKey = `${depth}:${tag}`;
14812
+ const exactBucket = this._byDepthAndTag.get(exactKey);
14813
+ if (exactBucket) {
14814
+ for(let i = 0; i < exactBucket.length; i++)if (matcher.matches(exactBucket[i])) return exactBucket[i];
14815
+ }
14816
+ const wildcardBucket = this._wildcardByDepth.get(depth);
14817
+ if (wildcardBucket) {
14818
+ for(let i = 0; i < wildcardBucket.length; i++)if (matcher.matches(wildcardBucket[i])) return wildcardBucket[i];
14819
+ }
14820
+ for(let i = 0; i < this._deepWildcards.length; i++)if (matcher.matches(this._deepWildcards[i])) return this._deepWildcards[i];
14821
+ return null;
14822
+ }
14823
+ }
14731
14824
  function extractRawAttributes(prefixedAttrs, options) {
14732
14825
  if (!prefixedAttrs) return {};
14733
14826
  const attrs = options.attributesGroupName ? prefixedAttrs[options.attributesGroupName] : prefixedAttrs;
@@ -14833,13 +14926,15 @@
14833
14926
  this.matcher = new Matcher();
14834
14927
  this.readonlyMatcher = this.matcher.readOnly();
14835
14928
  this.isCurrentNodeStopNode = false;
14836
- if (this.options.stopNodes && this.options.stopNodes.length > 0) {
14837
- this.stopNodeExpressions = [];
14838
- for(let i = 0; i < this.options.stopNodes.length; i++){
14839
- const stopNodeExp = this.options.stopNodes[i];
14840
- if ('string' == typeof stopNodeExp) this.stopNodeExpressions.push(new Expression(stopNodeExp));
14841
- else if (stopNodeExp instanceof Expression) this.stopNodeExpressions.push(stopNodeExp);
14929
+ this.stopNodeExpressionsSet = new ExpressionSet();
14930
+ const stopNodesOpts = this.options.stopNodes;
14931
+ if (stopNodesOpts && stopNodesOpts.length > 0) {
14932
+ for(let i = 0; i < stopNodesOpts.length; i++){
14933
+ const stopNodeExp = stopNodesOpts[i];
14934
+ if ('string' == typeof stopNodeExp) this.stopNodeExpressionsSet.add(new Expression(stopNodeExp));
14935
+ else if (stopNodeExp instanceof Expression) this.stopNodeExpressionsSet.add(stopNodeExp);
14842
14936
  }
14937
+ this.stopNodeExpressionsSet.seal();
14843
14938
  }
14844
14939
  }
14845
14940
  }
@@ -14855,18 +14950,19 @@
14855
14950
  }
14856
14951
  }
14857
14952
  function parseTextData(val, tagName, jPath, dontTrim, hasAttributes, isLeafNode, escapeEntities) {
14953
+ const options = this.options;
14858
14954
  if (void 0 !== val) {
14859
- if (this.options.trimValues && !dontTrim) val = val.trim();
14955
+ if (options.trimValues && !dontTrim) val = val.trim();
14860
14956
  if (val.length > 0) {
14861
14957
  if (!escapeEntities) val = this.replaceEntitiesValue(val, tagName, jPath);
14862
- const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;
14863
- const newval = this.options.tagValueProcessor(tagName, val, jPathOrMatcher, hasAttributes, isLeafNode);
14958
+ const jPathOrMatcher = options.jPath ? jPath.toString() : jPath;
14959
+ const newval = options.tagValueProcessor(tagName, val, jPathOrMatcher, hasAttributes, isLeafNode);
14864
14960
  if (null == newval) return val;
14865
14961
  {
14866
14962
  if (typeof newval !== typeof val || newval !== val) return newval;
14867
- if (this.options.trimValues) return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions);
14963
+ if (options.trimValues) return parseValue(val, options.parseTagValue, options.numberParseOptions);
14868
14964
  const trimmedVal = val.trim();
14869
- if (trimmedVal === val) return parseValue(val, this.options.parseTagValue, this.options.numberParseOptions);
14965
+ if (trimmedVal === val) return parseValue(val, options.parseTagValue, options.numberParseOptions);
14870
14966
  return val;
14871
14967
  }
14872
14968
  }
@@ -14883,46 +14979,53 @@
14883
14979
  }
14884
14980
  const attrsRegx = new RegExp('([^\\s=]+)\\s*(=\\s*([\'"])([\\s\\S]*?)\\3)?', 'gm');
14885
14981
  function buildAttributesMap(attrStr, jPath, tagName) {
14886
- if (true !== this.options.ignoreAttributes && 'string' == typeof attrStr) {
14982
+ const options = this.options;
14983
+ if (true !== options.ignoreAttributes && 'string' == typeof attrStr) {
14887
14984
  const matches = getAllMatches(attrStr, attrsRegx);
14888
14985
  const len = matches.length;
14889
14986
  const attrs = {};
14987
+ const processedVals = new Array(len);
14988
+ let hasRawAttrs = false;
14890
14989
  const rawAttrsForMatcher = {};
14891
14990
  for(let i = 0; i < len; i++){
14892
14991
  const attrName = this.resolveNameSpace(matches[i][1]);
14893
14992
  const oldVal = matches[i][4];
14894
14993
  if (attrName.length && void 0 !== oldVal) {
14895
- let parsedVal = oldVal;
14896
- if (this.options.trimValues) parsedVal = parsedVal.trim();
14897
- parsedVal = this.replaceEntitiesValue(parsedVal, tagName, this.readonlyMatcher);
14898
- rawAttrsForMatcher[attrName] = parsedVal;
14994
+ let val = oldVal;
14995
+ if (options.trimValues) val = val.trim();
14996
+ val = this.replaceEntitiesValue(val, tagName, this.readonlyMatcher);
14997
+ processedVals[i] = val;
14998
+ rawAttrsForMatcher[attrName] = val;
14999
+ hasRawAttrs = true;
14899
15000
  }
14900
15001
  }
14901
- if (Object.keys(rawAttrsForMatcher).length > 0 && 'object' == typeof jPath && jPath.updateCurrent) jPath.updateCurrent(rawAttrsForMatcher);
15002
+ if (hasRawAttrs && 'object' == typeof jPath && jPath.updateCurrent) jPath.updateCurrent(rawAttrsForMatcher);
15003
+ const jPathStr = options.jPath ? jPath.toString() : this.readonlyMatcher;
15004
+ let hasAttrs = false;
14902
15005
  for(let i = 0; i < len; i++){
14903
15006
  const attrName = this.resolveNameSpace(matches[i][1]);
14904
- const jPathStr = this.options.jPath ? jPath.toString() : this.readonlyMatcher;
14905
15007
  if (this.ignoreAttributesFn(attrName, jPathStr)) continue;
14906
- let oldVal = matches[i][4];
14907
- let aName = this.options.attributeNamePrefix + attrName;
15008
+ let aName = options.attributeNamePrefix + attrName;
14908
15009
  if (attrName.length) {
14909
- if (this.options.transformAttributeName) aName = this.options.transformAttributeName(aName);
14910
- aName = sanitizeName(aName, this.options);
14911
- if (void 0 !== oldVal) {
14912
- if (this.options.trimValues) oldVal = oldVal.trim();
14913
- oldVal = this.replaceEntitiesValue(oldVal, tagName, this.readonlyMatcher);
14914
- const jPathOrMatcher = this.options.jPath ? jPath.toString() : this.readonlyMatcher;
14915
- const newVal = this.options.attributeValueProcessor(attrName, oldVal, jPathOrMatcher);
15010
+ if (options.transformAttributeName) aName = options.transformAttributeName(aName);
15011
+ aName = sanitizeName(aName, options);
15012
+ if (void 0 !== matches[i][4]) {
15013
+ const oldVal = processedVals[i];
15014
+ const newVal = options.attributeValueProcessor(attrName, oldVal, jPathStr);
14916
15015
  if (null == newVal) attrs[aName] = oldVal;
14917
15016
  else if (typeof newVal !== typeof oldVal || newVal !== oldVal) attrs[aName] = newVal;
14918
- else attrs[aName] = parseValue(oldVal, this.options.parseAttributeValue, this.options.numberParseOptions);
14919
- } else if (this.options.allowBooleanAttributes) attrs[aName] = true;
15017
+ else attrs[aName] = parseValue(oldVal, options.parseAttributeValue, options.numberParseOptions);
15018
+ hasAttrs = true;
15019
+ } else if (options.allowBooleanAttributes) {
15020
+ attrs[aName] = true;
15021
+ hasAttrs = true;
15022
+ }
14920
15023
  }
14921
15024
  }
14922
- if (!Object.keys(attrs).length) return;
14923
- if (this.options.attributesGroupName) {
15025
+ if (!hasAttrs) return;
15026
+ if (options.attributesGroupName) {
14924
15027
  const attrCollection = {};
14925
- attrCollection[this.options.attributesGroupName] = attrs;
15028
+ attrCollection[options.attributesGroupName] = attrs;
14926
15029
  return attrCollection;
14927
15030
  }
14928
15031
  return attrs;
@@ -14936,155 +15039,163 @@
14936
15039
  this.matcher.reset();
14937
15040
  this.entityExpansionCount = 0;
14938
15041
  this.currentExpandedLength = 0;
14939
- const docTypeReader = new DocTypeReader(this.options.processEntities);
14940
- for(let i = 0; i < xmlData.length; i++){
15042
+ this.docTypeEntitiesKeys = [];
15043
+ this.lastEntitiesKeys = Object.keys(this.lastEntities);
15044
+ this.htmlEntitiesKeys = this.options.htmlEntities ? Object.keys(this.htmlEntities) : [];
15045
+ const options = this.options;
15046
+ const docTypeReader = new DocTypeReader(options.processEntities);
15047
+ const xmlLen = xmlData.length;
15048
+ for(let i = 0; i < xmlLen; i++){
14941
15049
  const ch = xmlData[i];
14942
- if ('<' === ch) if ('/' === xmlData[i + 1]) {
14943
- const closeIndex = findClosingIndex(xmlData, ">", i, "Closing Tag is not closed.");
14944
- let tagName = xmlData.substring(i + 2, closeIndex).trim();
14945
- if (this.options.removeNSPrefix) {
14946
- const colonIndex = tagName.indexOf(":");
14947
- if (-1 !== colonIndex) tagName = tagName.substr(colonIndex + 1);
14948
- }
14949
- tagName = transformTagName(this.options.transformTagName, tagName, "", this.options).tagName;
14950
- if (currentNode) textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
14951
- const lastTagName = this.matcher.getCurrentTag();
14952
- if (tagName && -1 !== this.options.unpairedTags.indexOf(tagName)) throw new Error(`Unpaired tag can not be used as closing tag: </${tagName}>`);
14953
- if (lastTagName && -1 !== this.options.unpairedTags.indexOf(lastTagName)) {
15050
+ if ('<' === ch) {
15051
+ const c1 = xmlData.charCodeAt(i + 1);
15052
+ if (47 === c1) {
15053
+ const closeIndex = findClosingIndex(xmlData, ">", i, "Closing Tag is not closed.");
15054
+ let tagName = xmlData.substring(i + 2, closeIndex).trim();
15055
+ if (options.removeNSPrefix) {
15056
+ const colonIndex = tagName.indexOf(":");
15057
+ if (-1 !== colonIndex) tagName = tagName.substr(colonIndex + 1);
15058
+ }
15059
+ tagName = transformTagName(options.transformTagName, tagName, "", options).tagName;
15060
+ if (currentNode) textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
15061
+ const lastTagName = this.matcher.getCurrentTag();
15062
+ if (tagName && options.unpairedTagsSet.has(tagName)) throw new Error(`Unpaired tag can not be used as closing tag: </${tagName}>`);
15063
+ if (lastTagName && options.unpairedTagsSet.has(lastTagName)) {
15064
+ this.matcher.pop();
15065
+ this.tagsNodeStack.pop();
15066
+ }
14954
15067
  this.matcher.pop();
14955
- this.tagsNodeStack.pop();
14956
- }
14957
- this.matcher.pop();
14958
- this.isCurrentNodeStopNode = false;
14959
- currentNode = this.tagsNodeStack.pop();
14960
- textData = "";
14961
- i = closeIndex;
14962
- } else if ('?' === xmlData[i + 1]) {
14963
- let tagData = readTagExp(xmlData, i, false, "?>");
14964
- if (!tagData) throw new Error("Pi Tag is not closed.");
14965
- textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
14966
- if (this.options.ignoreDeclaration && "?xml" === tagData.tagName || this.options.ignorePiTags) ;
14967
- else {
14968
- const childNode = new XmlNode(tagData.tagName);
14969
- childNode.add(this.options.textNodeName, "");
14970
- if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent) childNode[":@"] = this.buildAttributesMap(tagData.tagExp, this.matcher, tagData.tagName);
14971
- this.addChild(currentNode, childNode, this.readonlyMatcher, i);
14972
- }
14973
- i = tagData.closeIndex + 1;
14974
- } else if ('!--' === xmlData.substr(i + 1, 3)) {
14975
- const endIndex = findClosingIndex(xmlData, "-->", i + 4, "Comment is not closed.");
14976
- if (this.options.commentPropName) {
14977
- const comment = xmlData.substring(i + 4, endIndex - 2);
15068
+ this.isCurrentNodeStopNode = false;
15069
+ currentNode = this.tagsNodeStack.pop();
15070
+ textData = "";
15071
+ i = closeIndex;
15072
+ } else if (63 === c1) {
15073
+ let tagData = readTagExp(xmlData, i, false, "?>");
15074
+ if (!tagData) throw new Error("Pi Tag is not closed.");
15075
+ textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
15076
+ if (options.ignoreDeclaration && "?xml" === tagData.tagName || options.ignorePiTags) ;
15077
+ else {
15078
+ const childNode = new XmlNode(tagData.tagName);
15079
+ childNode.add(options.textNodeName, "");
15080
+ if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent) childNode[":@"] = this.buildAttributesMap(tagData.tagExp, this.matcher, tagData.tagName);
15081
+ this.addChild(currentNode, childNode, this.readonlyMatcher, i);
15082
+ }
15083
+ i = tagData.closeIndex + 1;
15084
+ } else if (33 === c1 && 45 === xmlData.charCodeAt(i + 2) && 45 === xmlData.charCodeAt(i + 3)) {
15085
+ const endIndex = findClosingIndex(xmlData, "-->", i + 4, "Comment is not closed.");
15086
+ if (options.commentPropName) {
15087
+ const comment = xmlData.substring(i + 4, endIndex - 2);
15088
+ textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
15089
+ currentNode.add(options.commentPropName, [
15090
+ {
15091
+ [options.textNodeName]: comment
15092
+ }
15093
+ ]);
15094
+ }
15095
+ i = endIndex;
15096
+ } else if (33 === c1 && 68 === xmlData.charCodeAt(i + 2)) {
15097
+ const result = docTypeReader.readDocType(xmlData, i);
15098
+ this.docTypeEntities = result.entities;
15099
+ this.docTypeEntitiesKeys = Object.keys(this.docTypeEntities) || [];
15100
+ i = result.i;
15101
+ } else if (33 === c1 && 91 === xmlData.charCodeAt(i + 2)) {
15102
+ const closeIndex = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2;
15103
+ const tagExp = xmlData.substring(i + 9, closeIndex);
14978
15104
  textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
14979
- currentNode.add(this.options.commentPropName, [
15105
+ let val = this.parseTextData(tagExp, currentNode.tagname, this.readonlyMatcher, true, false, true, true);
15106
+ if (void 0 == val) val = "";
15107
+ if (options.cdataPropName) currentNode.add(options.cdataPropName, [
14980
15108
  {
14981
- [this.options.textNodeName]: comment
15109
+ [options.textNodeName]: tagExp
14982
15110
  }
14983
15111
  ]);
14984
- }
14985
- i = endIndex;
14986
- } else if ('!D' === xmlData.substr(i + 1, 2)) {
14987
- const result = docTypeReader.readDocType(xmlData, i);
14988
- this.docTypeEntities = result.entities;
14989
- i = result.i;
14990
- } else if ('![' === xmlData.substr(i + 1, 2)) {
14991
- const closeIndex = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2;
14992
- const tagExp = xmlData.substring(i + 9, closeIndex);
14993
- textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
14994
- let val = this.parseTextData(tagExp, currentNode.tagname, this.readonlyMatcher, true, false, true, true);
14995
- if (void 0 == val) val = "";
14996
- if (this.options.cdataPropName) currentNode.add(this.options.cdataPropName, [
14997
- {
14998
- [this.options.textNodeName]: tagExp
15112
+ else currentNode.add(options.textNodeName, val);
15113
+ i = closeIndex + 2;
15114
+ } else {
15115
+ let result = readTagExp(xmlData, i, options.removeNSPrefix);
15116
+ if (!result) {
15117
+ const context = xmlData.substring(Math.max(0, i - 50), Math.min(xmlLen, i + 50));
15118
+ throw new Error(`readTagExp returned undefined at position ${i}. Context: "${context}"`);
14999
15119
  }
15000
- ]);
15001
- else currentNode.add(this.options.textNodeName, val);
15002
- i = closeIndex + 2;
15003
- } else {
15004
- let result = readTagExp(xmlData, i, this.options.removeNSPrefix);
15005
- if (!result) {
15006
- const context = xmlData.substring(Math.max(0, i - 50), Math.min(xmlData.length, i + 50));
15007
- throw new Error(`readTagExp returned undefined at position ${i}. Context: "${context}"`);
15008
- }
15009
- let tagName = result.tagName;
15010
- const rawTagName = result.rawTagName;
15011
- let tagExp = result.tagExp;
15012
- let attrExpPresent = result.attrExpPresent;
15013
- let closeIndex = result.closeIndex;
15014
- ({ tagName, tagExp } = transformTagName(this.options.transformTagName, tagName, tagExp, this.options));
15015
- if (this.options.strictReservedNames && (tagName === this.options.commentPropName || tagName === this.options.cdataPropName || tagName === this.options.textNodeName || tagName === this.options.attributesGroupName)) throw new Error(`Invalid tag name: ${tagName}`);
15016
- if (currentNode && textData) {
15017
- if ('!xml' !== currentNode.tagname) textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher, false);
15018
- }
15019
- const lastTag = currentNode;
15020
- if (lastTag && -1 !== this.options.unpairedTags.indexOf(lastTag.tagname)) {
15021
- currentNode = this.tagsNodeStack.pop();
15022
- this.matcher.pop();
15023
- }
15024
- let isSelfClosing = false;
15025
- if (tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1) {
15026
- isSelfClosing = true;
15027
- if ("/" === tagName[tagName.length - 1]) {
15028
- tagName = tagName.substr(0, tagName.length - 1);
15029
- tagExp = tagName;
15030
- } else tagExp = tagExp.substr(0, tagExp.length - 1);
15031
- attrExpPresent = tagName !== tagExp;
15032
- }
15033
- let prefixedAttrs = null;
15034
- let namespace;
15035
- namespace = extractNamespace(rawTagName);
15036
- if (tagName !== xmlObj.tagname) this.matcher.push(tagName, {}, namespace);
15037
- if (tagName !== tagExp && attrExpPresent) {
15038
- prefixedAttrs = this.buildAttributesMap(tagExp, this.matcher, tagName);
15039
- if (prefixedAttrs) extractRawAttributes(prefixedAttrs, this.options);
15040
- }
15041
- if (tagName !== xmlObj.tagname) this.isCurrentNodeStopNode = this.isItStopNode(this.stopNodeExpressions, this.matcher);
15042
- const startIndex = i;
15043
- if (this.isCurrentNodeStopNode) {
15044
- let tagContent = "";
15045
- if (isSelfClosing) i = result.closeIndex;
15046
- else if (-1 !== this.options.unpairedTags.indexOf(tagName)) i = result.closeIndex;
15047
- else {
15048
- const result = this.readStopNodeData(xmlData, rawTagName, closeIndex + 1);
15049
- if (!result) throw new Error(`Unexpected end of ${rawTagName}`);
15050
- i = result.i;
15051
- tagContent = result.tagContent;
15120
+ let tagName = result.tagName;
15121
+ const rawTagName = result.rawTagName;
15122
+ let tagExp = result.tagExp;
15123
+ let attrExpPresent = result.attrExpPresent;
15124
+ let closeIndex = result.closeIndex;
15125
+ ({ tagName, tagExp } = transformTagName(options.transformTagName, tagName, tagExp, options));
15126
+ if (options.strictReservedNames && (tagName === options.commentPropName || tagName === options.cdataPropName || tagName === options.textNodeName || tagName === options.attributesGroupName)) throw new Error(`Invalid tag name: ${tagName}`);
15127
+ if (currentNode && textData) {
15128
+ if ('!xml' !== currentNode.tagname) textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher, false);
15052
15129
  }
15053
- const childNode = new XmlNode(tagName);
15054
- if (prefixedAttrs) childNode[":@"] = prefixedAttrs;
15055
- childNode.add(this.options.textNodeName, tagContent);
15056
- this.matcher.pop();
15057
- this.isCurrentNodeStopNode = false;
15058
- this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
15059
- } else {
15060
- if (isSelfClosing) {
15061
- ({ tagName, tagExp } = transformTagName(this.options.transformTagName, tagName, tagExp, this.options));
15062
- const childNode = new XmlNode(tagName);
15063
- if (prefixedAttrs) childNode[":@"] = prefixedAttrs;
15064
- this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
15130
+ const lastTag = currentNode;
15131
+ if (lastTag && options.unpairedTagsSet.has(lastTag.tagname)) {
15132
+ currentNode = this.tagsNodeStack.pop();
15065
15133
  this.matcher.pop();
15066
- this.isCurrentNodeStopNode = false;
15067
- } else if (-1 !== this.options.unpairedTags.indexOf(tagName)) {
15134
+ }
15135
+ let isSelfClosing = false;
15136
+ if (tagExp.length > 0 && tagExp.lastIndexOf("/") === tagExp.length - 1) {
15137
+ isSelfClosing = true;
15138
+ if ("/" === tagName[tagName.length - 1]) {
15139
+ tagName = tagName.substr(0, tagName.length - 1);
15140
+ tagExp = tagName;
15141
+ } else tagExp = tagExp.substr(0, tagExp.length - 1);
15142
+ attrExpPresent = tagName !== tagExp;
15143
+ }
15144
+ let prefixedAttrs = null;
15145
+ let namespace;
15146
+ namespace = extractNamespace(rawTagName);
15147
+ if (tagName !== xmlObj.tagname) this.matcher.push(tagName, {}, namespace);
15148
+ if (tagName !== tagExp && attrExpPresent) {
15149
+ prefixedAttrs = this.buildAttributesMap(tagExp, this.matcher, tagName);
15150
+ if (prefixedAttrs) extractRawAttributes(prefixedAttrs, options);
15151
+ }
15152
+ if (tagName !== xmlObj.tagname) this.isCurrentNodeStopNode = this.isItStopNode();
15153
+ const startIndex = i;
15154
+ if (this.isCurrentNodeStopNode) {
15155
+ let tagContent = "";
15156
+ if (isSelfClosing) i = result.closeIndex;
15157
+ else if (options.unpairedTagsSet.has(tagName)) i = result.closeIndex;
15158
+ else {
15159
+ const result = this.readStopNodeData(xmlData, rawTagName, closeIndex + 1);
15160
+ if (!result) throw new Error(`Unexpected end of ${rawTagName}`);
15161
+ i = result.i;
15162
+ tagContent = result.tagContent;
15163
+ }
15068
15164
  const childNode = new XmlNode(tagName);
15069
15165
  if (prefixedAttrs) childNode[":@"] = prefixedAttrs;
15070
- this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
15166
+ childNode.add(options.textNodeName, tagContent);
15071
15167
  this.matcher.pop();
15072
15168
  this.isCurrentNodeStopNode = false;
15073
- i = result.closeIndex;
15074
- continue;
15075
- } else {
15076
- const childNode = new XmlNode(tagName);
15077
- if (this.tagsNodeStack.length > this.options.maxNestedTags) throw new Error("Maximum nested tags exceeded");
15078
- this.tagsNodeStack.push(currentNode);
15079
- if (prefixedAttrs) childNode[":@"] = prefixedAttrs;
15080
15169
  this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
15081
- currentNode = childNode;
15170
+ } else {
15171
+ if (isSelfClosing) {
15172
+ ({ tagName, tagExp } = transformTagName(options.transformTagName, tagName, tagExp, options));
15173
+ const childNode = new XmlNode(tagName);
15174
+ if (prefixedAttrs) childNode[":@"] = prefixedAttrs;
15175
+ this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
15176
+ this.matcher.pop();
15177
+ this.isCurrentNodeStopNode = false;
15178
+ } else if (options.unpairedTagsSet.has(tagName)) {
15179
+ const childNode = new XmlNode(tagName);
15180
+ if (prefixedAttrs) childNode[":@"] = prefixedAttrs;
15181
+ this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
15182
+ this.matcher.pop();
15183
+ this.isCurrentNodeStopNode = false;
15184
+ i = result.closeIndex;
15185
+ continue;
15186
+ } else {
15187
+ const childNode = new XmlNode(tagName);
15188
+ if (this.tagsNodeStack.length > options.maxNestedTags) throw new Error("Maximum nested tags exceeded");
15189
+ this.tagsNodeStack.push(currentNode);
15190
+ if (prefixedAttrs) childNode[":@"] = prefixedAttrs;
15191
+ this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
15192
+ currentNode = childNode;
15193
+ }
15194
+ textData = "";
15195
+ i = closeIndex;
15082
15196
  }
15083
- textData = "";
15084
- i = closeIndex;
15085
15197
  }
15086
- }
15087
- else textData += xmlData[i];
15198
+ } else textData += xmlData[i];
15088
15199
  }
15089
15200
  return xmlObj.child;
15090
15201
  };
@@ -15110,7 +15221,7 @@
15110
15221
  const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;
15111
15222
  if (!entityConfig.tagFilter(tagName, jPathOrMatcher)) return val;
15112
15223
  }
15113
- for (const entityName of Object.keys(this.docTypeEntities)){
15224
+ for (const entityName of this.docTypeEntitiesKeys){
15114
15225
  const entity = this.docTypeEntities[entityName];
15115
15226
  const matches = val.match(entity.regx);
15116
15227
  if (matches) {
@@ -15124,7 +15235,8 @@
15124
15235
  }
15125
15236
  }
15126
15237
  }
15127
- for (const entityName of Object.keys(this.lastEntities)){
15238
+ if (-1 === val.indexOf('&')) return val;
15239
+ for (const entityName of this.lastEntitiesKeys){
15128
15240
  const entity = this.lastEntities[entityName];
15129
15241
  const matches = val.match(entity.regex);
15130
15242
  if (matches) {
@@ -15134,7 +15246,7 @@
15134
15246
  val = val.replace(entity.regex, entity.val);
15135
15247
  }
15136
15248
  if (-1 === val.indexOf('&')) return val;
15137
- if (this.options.htmlEntities) for (const entityName of Object.keys(this.htmlEntities)){
15249
+ for (const entityName of this.htmlEntitiesKeys){
15138
15250
  const entity = this.htmlEntities[entityName];
15139
15251
  const matches = val.match(entity.regex);
15140
15252
  if (matches) {
@@ -15155,30 +15267,35 @@
15155
15267
  }
15156
15268
  return textData;
15157
15269
  }
15158
- function isItStopNode(stopNodeExpressions, matcher) {
15159
- if (!stopNodeExpressions || 0 === stopNodeExpressions.length) return false;
15160
- for(let i = 0; i < stopNodeExpressions.length; i++)if (matcher.matches(stopNodeExpressions[i])) return true;
15161
- return false;
15270
+ function isItStopNode() {
15271
+ if (0 === this.stopNodeExpressionsSet.size) return false;
15272
+ return this.matcher.matchesAny(this.stopNodeExpressionsSet);
15162
15273
  }
15163
15274
  function tagExpWithClosingIndex(xmlData, i, closingChar = ">") {
15164
- let attrBoundary;
15165
- let tagExp = "";
15166
- for(let index = i; index < xmlData.length; index++){
15167
- let ch = xmlData[index];
15275
+ let attrBoundary = 0;
15276
+ const chars = [];
15277
+ const len = xmlData.length;
15278
+ const closeCode0 = closingChar.charCodeAt(0);
15279
+ const closeCode1 = closingChar.length > 1 ? closingChar.charCodeAt(1) : -1;
15280
+ for(let index = i; index < len; index++){
15281
+ const code = xmlData.charCodeAt(index);
15168
15282
  if (attrBoundary) {
15169
- if (ch === attrBoundary) attrBoundary = "";
15170
- } else if ('"' === ch || "'" === ch) attrBoundary = ch;
15171
- else if (ch === closingChar[0]) {
15172
- if (!closingChar[1]) return {
15173
- data: tagExp,
15174
- index: index
15283
+ if (code === attrBoundary) attrBoundary = 0;
15284
+ } else if (34 === code || 39 === code) attrBoundary = code;
15285
+ else if (code === closeCode0) {
15286
+ if (-1 === closeCode1) return {
15287
+ data: String.fromCharCode(...chars),
15288
+ index
15175
15289
  };
15176
- else if (xmlData[index + 1] === closingChar[1]) return {
15177
- data: tagExp,
15178
- index: index
15290
+ else if (xmlData.charCodeAt(index + 1) === closeCode1) return {
15291
+ data: String.fromCharCode(...chars),
15292
+ index
15179
15293
  };
15180
- } else if ('\t' === ch) ch = " ";
15181
- tagExp += ch;
15294
+ } else if (9 === code) {
15295
+ chars.push(32);
15296
+ continue;
15297
+ }
15298
+ chars.push(code);
15182
15299
  }
15183
15300
  }
15184
15301
  function findClosingIndex(xmlData, str, i, errMsg) {
@@ -15186,6 +15303,11 @@
15186
15303
  if (-1 !== closingIndex) return closingIndex + str.length - 1;
15187
15304
  throw new Error(errMsg);
15188
15305
  }
15306
+ function findClosingChar(xmlData, char, i, errMsg) {
15307
+ const closingIndex = xmlData.indexOf(char, i);
15308
+ if (-1 === closingIndex) throw new Error(errMsg);
15309
+ return closingIndex;
15310
+ }
15189
15311
  function readTagExp(xmlData, i, removeNSPrefix, closingChar = ">") {
15190
15312
  const result = tagExpWithClosingIndex(xmlData, i + 1, closingChar);
15191
15313
  if (!result) return;
@@ -15217,32 +15339,36 @@
15217
15339
  function readStopNodeData(xmlData, tagName, i) {
15218
15340
  const startIndex = i;
15219
15341
  let openTagCount = 1;
15220
- for(; i < xmlData.length; i++)if ("<" === xmlData[i]) if ("/" === xmlData[i + 1]) {
15221
- const closeIndex = findClosingIndex(xmlData, ">", i, `${tagName} is not closed`);
15222
- let closeTagName = xmlData.substring(i + 2, closeIndex).trim();
15223
- if (closeTagName === tagName) {
15224
- openTagCount--;
15225
- if (0 === openTagCount) return {
15226
- tagContent: xmlData.substring(startIndex, i),
15227
- i: closeIndex
15228
- };
15229
- }
15230
- i = closeIndex;
15231
- } else if ('?' === xmlData[i + 1]) {
15232
- const closeIndex = findClosingIndex(xmlData, "?>", i + 1, "StopNode is not closed.");
15233
- i = closeIndex;
15234
- } else if ('!--' === xmlData.substr(i + 1, 3)) {
15235
- const closeIndex = findClosingIndex(xmlData, "-->", i + 3, "StopNode is not closed.");
15236
- i = closeIndex;
15237
- } else if ('![' === xmlData.substr(i + 1, 2)) {
15238
- const closeIndex = findClosingIndex(xmlData, "]]>", i, "StopNode is not closed.") - 2;
15239
- i = closeIndex;
15240
- } else {
15241
- const tagData = readTagExp(xmlData, i, '>');
15242
- if (tagData) {
15243
- const openTagName = tagData && tagData.tagName;
15244
- if (openTagName === tagName && "/" !== tagData.tagExp[tagData.tagExp.length - 1]) openTagCount++;
15245
- i = tagData.closeIndex;
15342
+ const xmllen = xmlData.length;
15343
+ for(; i < xmllen; i++)if ("<" === xmlData[i]) {
15344
+ const c1 = xmlData.charCodeAt(i + 1);
15345
+ if (47 === c1) {
15346
+ const closeIndex = findClosingChar(xmlData, ">", i, `${tagName} is not closed`);
15347
+ let closeTagName = xmlData.substring(i + 2, closeIndex).trim();
15348
+ if (closeTagName === tagName) {
15349
+ openTagCount--;
15350
+ if (0 === openTagCount) return {
15351
+ tagContent: xmlData.substring(startIndex, i),
15352
+ i: closeIndex
15353
+ };
15354
+ }
15355
+ i = closeIndex;
15356
+ } else if (63 === c1) {
15357
+ const closeIndex = findClosingIndex(xmlData, "?>", i + 1, "StopNode is not closed.");
15358
+ i = closeIndex;
15359
+ } else if (33 === c1 && 45 === xmlData.charCodeAt(i + 2) && 45 === xmlData.charCodeAt(i + 3)) {
15360
+ const closeIndex = findClosingIndex(xmlData, "-->", i + 3, "StopNode is not closed.");
15361
+ i = closeIndex;
15362
+ } else if (33 === c1 && 91 === xmlData.charCodeAt(i + 2)) {
15363
+ const closeIndex = findClosingIndex(xmlData, "]]>", i, "StopNode is not closed.") - 2;
15364
+ i = closeIndex;
15365
+ } else {
15366
+ const tagData = readTagExp(xmlData, i, '>');
15367
+ if (tagData) {
15368
+ const openTagName = tagData && tagData.tagName;
15369
+ if (openTagName === tagName && "/" !== tagData.tagExp[tagData.tagExp.length - 1]) openTagCount++;
15370
+ i = tagData.closeIndex;
15371
+ }
15246
15372
  }
15247
15373
  }
15248
15374
  }
@@ -21060,7 +21186,7 @@
21060
21186
  function timestamp_timestampMs(timestamp) {
21061
21187
  return 1000 * Number(timestamp.seconds) + Math.round(timestamp.nanos / 1000000);
21062
21188
  }
21063
- var package_namespaceObject = JSON.parse('{"UU":"@dan-uni/dan-any","rE":"1.3.8","TB":"https://github.com/ani-uni/danuni/tree/master/packages/dan-any#readme"}');
21189
+ var package_namespaceObject = JSON.parse('{"UU":"@dan-uni/dan-any","rE":"1.4.0","TB":"https://github.com/ani-uni/danuni/tree/master/packages/dan-any#readme"}');
21064
21190
  const color_pad = (s)=>s.length < 2 ? `0${s}` : s;
21065
21191
  const decimalToHex = (n)=>color_pad(n.toString(16));
21066
21192
  const isDarkColor = ({ r, g, b })=>0.299 * r + 0.587 * g + 0.114 * b < 0x30;
@@ -23774,6 +23900,9 @@
23774
23900
  platform: platform.PlatformVideoSource.Bilibili,
23775
23901
  extra: {
23776
23902
  bili: {
23903
+ dmid: args.id,
23904
+ attr: args.attr,
23905
+ mid: args.mid,
23777
23906
  command: args
23778
23907
  }
23779
23908
  }
@@ -24505,6 +24634,7 @@
24505
24634
  throw new Error(`Unsupported mod "${mod}"`);
24506
24635
  }
24507
24636
  }
24637
+ __webpack_require__("./src/plugins/index.ts");
24508
24638
  const src_JSON = json_bigint_default()({
24509
24639
  useNativeBigInt: true
24510
24640
  });
@@ -24998,6 +25128,8 @@
24998
25128
  const ok = this.dans.every((d)=>d.senderID.endsWith(`@${platform.PlatformVideoSource.Bilibili}`));
24999
25129
  if (!ok) throw new Error('存在其他来源的senderID,请关闭该功能再试!');
25000
25130
  }
25131
+ let ds = this.dans.map((dan)=>dan.toBiliXML(options));
25132
+ if (options?.skipBiliCommand) ds = ds.filter((d)=>null !== d);
25001
25133
  const builder = new json2xml({
25002
25134
  ignoreAttributes: false
25003
25135
  });
@@ -25018,7 +25150,7 @@
25018
25150
  ...DanUniConvertTipTemplate,
25019
25151
  data: this.getShared('SOID')
25020
25152
  },
25021
- d: this.dans.map((dan)=>dan.toBiliXML(options))
25153
+ d: ds
25022
25154
  }
25023
25155
  });
25024
25156
  }
@@ -25182,7 +25314,7 @@
25182
25314
  function main(that) {
25183
25315
  that.dans.forEach((d)=>{
25184
25316
  if (d.platform !== platform.PlatformVideoSource.Bilibili) throw new Error('bili-dedupe: 仅支持B站(主站)的弹幕');
25185
- if (!d.extra.bili?.dmid) throw new Error('bili-dedupe: 弹幕缺少bili extra dmid字段');
25317
+ if (!d.extra.bili?.dmid && !d.extra.bili?.command?.id) throw new Error('bili-dedupe: 弹幕缺少bili extra dmid字段');
25186
25318
  });
25187
25319
  const map = new Map();
25188
25320
  that.dans.forEach((d)=>map.set(d.extra.bili.dmid, d));
@@ -29804,6 +29936,16 @@
29804
29936
  return (that)=>history_danmaku_fast_forward_main(that, query_history_date);
29805
29937
  }
29806
29938
  },
29939
+ "./src/plugins/index.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
29940
+ "use strict";
29941
+ __webpack_require__.r(__webpack_exports__);
29942
+ __webpack_require__.d(__webpack_exports__, {
29943
+ bili: ()=>_bili__rspack_import_0,
29944
+ stats: ()=>_stats__rspack_import_1
29945
+ });
29946
+ var _bili__rspack_import_0 = __webpack_require__("./src/plugins/bili/index.ts");
29947
+ var _stats__rspack_import_1 = __webpack_require__("./src/plugins/stats/index.ts");
29948
+ },
29807
29949
  "./src/plugins/stats/index.ts" (__unused_rspack_module, __webpack_exports__, __webpack_require__) {
29808
29950
  "use strict";
29809
29951
  __webpack_require__.r(__webpack_exports__);
@@ -30495,16 +30637,6 @@ and limitations under the License.
30495
30637
  });
30496
30638
  };
30497
30639
  })();
30498
- var __webpack_exports__ = {};
30499
- (()=>{
30500
- "use strict";
30501
- __webpack_require__.r(__webpack_exports__);
30502
- __webpack_require__.d(__webpack_exports__, {
30503
- bili: ()=>_bili__rspack_import_0,
30504
- stats: ()=>_stats__rspack_import_1
30505
- });
30506
- var _bili__rspack_import_0 = __webpack_require__("./src/plugins/bili/index.ts");
30507
- var _stats__rspack_import_1 = __webpack_require__("./src/plugins/stats/index.ts");
30508
- })();
30640
+ var __webpack_exports__ = __webpack_require__("./src/plugins/index.ts");
30509
30641
  return __webpack_exports__;
30510
30642
  })());