path-expression-matcher 1.3.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,10 +4,11 @@ Efficient path tracking and pattern matching for XML, JSON, YAML or any other pa
4
4
 
5
5
  ## 🎯 Purpose
6
6
 
7
- `path-expression-matcher` provides two core classes for tracking and matching paths:
7
+ `path-expression-matcher` provides three core classes for tracking and matching paths:
8
8
 
9
9
  - **`Expression`**: Parses and stores pattern expressions (e.g., `"root.users.user[id]"`)
10
10
  - **`Matcher`**: Tracks current path during parsing and matches against expressions
11
+ - **`MatcherView`**: A lightweight read-only view of a `Matcher`, safe to pass to callbacks
11
12
 
12
13
  Compatible with [fast-xml-parser](https://github.com/NaturalIntelligence/fast-xml-parser) and similar tools.
13
14
 
@@ -138,7 +139,7 @@ console.log(matcher.toString()); // "soap:Envelope.soap:Body.ns:UserId"
138
139
  #### Constructor
139
140
 
140
141
  ```javascript
141
- new Expression(pattern, options)
142
+ new Expression(pattern, options = {}, data)
142
143
  ```
143
144
 
144
145
  **Parameters:**
@@ -149,6 +150,8 @@ new Expression(pattern, options)
149
150
  ```javascript
150
151
  const expr1 = new Expression("root.users.user");
151
152
  const expr2 = new Expression("root/users/user", { separator: '/' });
153
+ const expr3 = new Expression("root/users/user", { separator: '/' }, { extra: "data"});
154
+ console.log(expr3.data) // { extra: "data" }
152
155
  ```
153
156
 
154
157
  #### Methods
@@ -366,51 +369,51 @@ matcher.restore(snapshot);
366
369
 
367
370
  ##### `readOnly()`
368
371
 
369
- Returns a **live, read-only proxy** of the matcher. All query and inspection methods work normally, but any attempt to call a state-mutating method (`push`, `pop`, `reset`, `updateCurrent`, `restore`) or to write/delete a property throws a `TypeError`.
372
+ Returns a **`MatcherView`** — a lightweight, live read-only view of the matcher. All query and inspection methods work normally and always reflect the current state of the underlying matcher. Mutation methods (`push`, `pop`, `reset`, `updateCurrent`, `restore`) simply don't exist on `MatcherView`, so misuse is caught at **compile time** by TypeScript rather than at runtime.
370
373
 
371
- This is the recommended way to share the matcher with external consumers — plugins, callbacks, event handlers that only need to inspect the current path without being able to corrupt parser state.
374
+ The **same instance** is returned on every call — no allocation occurs per invocation. This is the recommended way to share the matcher with callbacks, plugins, or any external code that only needs to inspect the current path.
372
375
 
373
376
  ```javascript
374
- const ro = matcher.readOnly();
377
+ const view = matcher.readOnly();
378
+ // Same reference every time — safe to cache
379
+ view === matcher.readOnly(); // true
375
380
  ```
376
381
 
377
- **What works on the read-only view:**
382
+ **What works on the view:**
378
383
 
379
384
  ```javascript
380
- ro.matches(expr) // ✓ pattern matching
381
- ro.getCurrentTag() // ✓ current tag name
382
- ro.getCurrentNamespace() // ✓ current namespace
383
- ro.getAttrValue("id") // ✓ attribute value
384
- ro.hasAttr("id") // ✓ attribute presence check
385
- ro.getPosition() // ✓ sibling position
386
- ro.getCounter() // ✓ occurrence counter
387
- ro.getDepth() // ✓ path depth
388
- ro.toString() // ✓ path as string
389
- ro.toArray() // ✓ path as array
390
- ro.snapshot() // ✓ snapshot (can be used to restore the real matcher)
385
+ view.matches(expr) // ✓ pattern matching
386
+ view.getCurrentTag() // ✓ current tag name
387
+ view.getCurrentNamespace() // ✓ current namespace
388
+ view.getAttrValue("id") // ✓ attribute value
389
+ view.hasAttr("id") // ✓ attribute presence check
390
+ view.getPosition() // ✓ sibling position
391
+ view.getCounter() // ✓ occurrence counter
392
+ view.getDepth() // ✓ path depth
393
+ view.toString() // ✓ path as string
394
+ view.toArray() // ✓ path as array
391
395
  ```
392
396
 
393
- **What throws a `TypeError`:**
397
+ **What doesn't exist (compile-time error in TypeScript):**
394
398
 
395
399
  ```javascript
396
- ro.push("child", {}) // ✗ TypeError: Cannot call 'push' on a read-only Matcher
397
- ro.pop() // ✗ TypeError: Cannot call 'pop' on a read-only Matcher
398
- ro.reset() // ✗ TypeError: Cannot call 'reset' on a read-only Matcher
399
- ro.updateCurrent({}) // ✗ TypeError: Cannot call 'updateCurrent' on a read-only Matcher
400
- ro.restore(snapshot) // ✗ TypeError: Cannot call 'restore' on a read-only Matcher
401
- ro.separator = '/' // ✗ TypeError: Cannot set property on a read-only Matcher
400
+ view.push("child", {}) // ✗ Property 'push' does not exist on type 'MatcherView'
401
+ view.pop() // ✗ Property 'pop' does not exist on type 'MatcherView'
402
+ view.reset() // ✗ Property 'reset' does not exist on type 'MatcherView'
403
+ view.updateCurrent({}) // ✗ Property 'updateCurrent' does not exist on type 'MatcherView'
404
+ view.restore(snapshot) // ✗ Property 'restore' does not exist on type 'MatcherView'
402
405
  ```
403
406
 
404
- **Important:** The read-only view is **live** — it always reflects the current state of the underlying matcher. If you need a frozen-in-time copy instead, use `snapshot()`.
407
+ **The view is live** — it always reflects the current state of the underlying matcher.
405
408
 
406
409
  ```javascript
407
410
  const matcher = new Matcher();
408
- const ro = matcher.readOnly();
411
+ const view = matcher.readOnly();
409
412
 
410
413
  matcher.push("root");
411
- ro.getDepth(); // 1 — immediately reflects the push
414
+ view.getDepth(); // 1 — immediately reflects the push
412
415
  matcher.push("users");
413
- ro.getDepth(); // 2 — still live
416
+ view.getDepth(); // 2 — still live
414
417
  ```
415
418
 
416
419
  ## 💡 Usage Examples
@@ -548,9 +551,9 @@ const expr = new Expression("root.item:first");
548
551
  console.log(matcher.matches(expr)); // false (counter=1, not 0)
549
552
  ```
550
553
 
551
- ### Example 8: Passing a Read-Only Matcher to External Consumers
554
+ ### Example 8: Passing a Read-Only View to External Consumers
552
555
 
553
- When passing the matcher into callbacks, plugins, or other code you don't control, use `readOnly()` to prevent accidental state corruption.
556
+ When passing the matcher into callbacks, plugins, or other code you don't control, use `readOnly()` to get a `MatcherView` — it can inspect but never mutate parser state.
554
557
 
555
558
  ```javascript
556
559
  import { Expression, Matcher } from 'path-expression-matcher';
@@ -562,40 +565,26 @@ const adminExpr = new Expression("..user[type=admin]");
562
565
  function parseTag(tagName, attrs, onTag) {
563
566
  matcher.push(tagName, attrs);
564
567
 
565
- // Pass a read-only view — consumer can inspect but not mutate
568
+ // Pass MatcherView — consumer can inspect but not mutate
566
569
  onTag(matcher.readOnly());
567
570
 
568
571
  matcher.pop();
569
572
  }
570
573
 
571
574
  // Safe consumer — can only read
572
- function myPlugin(ro) {
573
- if (ro.matches(adminExpr)) {
574
- console.log("Admin at path:", ro.toString());
575
- console.log("Depth:", ro.getDepth());
576
- console.log("ID:", ro.getAttrValue("id"));
575
+ function myPlugin(view) {
576
+ if (view.matches(adminExpr)) {
577
+ console.log("Admin at path:", view.toString());
578
+ console.log("Depth:", view.getDepth());
579
+ console.log("ID:", view.getAttrValue("id"));
577
580
  }
578
581
  }
579
582
 
580
- // ro.push(...) or ro.reset() here would throw TypeError,
581
- // so the parser's state is always safe.
583
+ // view.push(...) or view.reset() don't exist on MatcherView —
584
+ // TypeScript catches misuse at compile time.
582
585
  parseTag("user", { id: "1", type: "admin" }, myPlugin);
583
586
  ```
584
587
 
585
- **Combining with `snapshot()`:** A snapshot taken via the read-only view can still be used to restore the real matcher.
586
-
587
- ```javascript
588
- const matcher = new Matcher();
589
- matcher.push("root");
590
- matcher.push("users");
591
-
592
- const ro = matcher.readOnly();
593
- const snap = ro.snapshot(); // ✓ snapshot works on read-only view
594
-
595
- matcher.push("user"); // continue parsing...
596
- matcher.restore(snap); // restore to "root.users" using the snapshot
597
- ```
598
-
599
588
  ```javascript
600
589
  const matcher = new Matcher();
601
590
  const soapExpr = new Expression("soap::Envelope.soap::Body..ns::UserId");
@@ -797,7 +786,7 @@ Whether `seal()` has been called.
797
786
  ### `matchesAny(matcher)` → `boolean`
798
787
 
799
788
  Returns `true` if the matcher's current path matches **any** expression in the set.
800
- Accepts both a `Matcher` instance and a `ReadOnlyMatcher` view.
789
+ Accepts both a `Matcher` instance and a `MatcherView`.
801
790
 
802
791
  ```javascript
803
792
  if (stopNodes.matchesAny(matcher)) { /* ... */ }
@@ -814,6 +803,15 @@ if (stopNodes.matchesAny(matcher.readOnly())) { /* ... */ } // also works
814
803
 
815
804
  In practice, deep-wildcard expressions are rare in configs, so the list stays small.
816
805
 
806
+ ### `findMatch(matcher)` → `Expression`
807
+
808
+ Returns the Expression instance that matched the current path. Accepts both a `Matcher` instance and a `MatcherView`.
809
+
810
+ ```javascript
811
+ const node = stopNodes.findMatch(matcher);
812
+ ```
813
+
814
+
817
815
  ### Example 7: ExpressionSet in a real parser loop
818
816
 
819
817
  ```javascript
@@ -871,4 +869,4 @@ MIT
871
869
 
872
870
  ## 🤝 Contributing
873
871
 
874
- Issues and PRs welcome! This package is designed to be used by XML/JSON parsers like fast-xml-parser.
872
+ Issues and PRs welcome! This package is designed to be used by XML/JSON parsers like fast-xml-parser. But can be used with any formar parser.
package/lib/pem.cjs CHANGED
@@ -1 +1 @@
1
- (()=>{"use strict";var t={d:(e,s)=>{for(var n in s)t.o(s,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:s[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{Expression:()=>s,ExpressionSet:()=>r,Matcher:()=>i,default:()=>a});class s{constructor(t,e={}){this.pattern=t,this.separator=e.separator||".",this.segments=this._parse(t),this._hasDeepWildcard=this.segments.some(t=>"deep-wildcard"===t.type),this._hasAttributeCondition=this.segments.some(t=>void 0!==t.attrName),this._hasPositionSelector=this.segments.some(t=>void 0!==t.position)}_parse(t){const e=[];let s=0,n="";for(;s<t.length;)t[s]===this.separator?s+1<t.length&&t[s+1]===this.separator?(n.trim()&&(e.push(this._parseSegment(n.trim())),n=""),e.push({type:"deep-wildcard"}),s+=2):(n.trim()&&e.push(this._parseSegment(n.trim())),n="",s++):(n+=t[s],s++);return n.trim()&&e.push(this._parseSegment(n.trim())),e}_parseSegment(t){const e={type:"tag"};let s=null,n=t;const i=t.match(/^([^\[]+)(\[[^\]]*\])(.*)$/);if(i&&(n=i[1]+i[3],i[2])){const t=i[2].slice(1,-1);t&&(s=t)}let r,a,h=n;if(n.includes("::")){const e=n.indexOf("::");if(r=n.substring(0,e).trim(),h=n.substring(e+2).trim(),!r)throw new Error(`Invalid namespace in pattern: ${t}`)}let l=null;if(h.includes(":")){const t=h.lastIndexOf(":"),e=h.substring(0,t).trim(),s=h.substring(t+1).trim();["first","last","odd","even"].includes(s)||/^nth\(\d+\)$/.test(s)?(a=e,l=s):a=h}else a=h;if(!a)throw new Error(`Invalid segment pattern: ${t}`);if(e.tag=a,r&&(e.namespace=r),s)if(s.includes("=")){const t=s.indexOf("=");e.attrName=s.substring(0,t).trim(),e.attrValue=s.substring(t+1).trim()}else e.attrName=s.trim();if(l){const t=l.match(/^nth\((\d+)\)$/);t?(e.position="nth",e.positionValue=parseInt(t[1],10)):e.position=l}return e}get length(){return this.segments.length}hasDeepWildcard(){return this._hasDeepWildcard}hasAttributeCondition(){return this._hasAttributeCondition}hasPositionSelector(){return this._hasPositionSelector}toString(){return this.pattern}}const n=new Set(["push","pop","reset","updateCurrent","restore"]);class i{constructor(t={}){this.separator=t.separator||".",this.path=[],this.siblingStacks=[],this._pathStringCache=null,this._frozenPathCache=null,this._frozenSiblingsCache=null}push(t,e=null,s=null){this._pathStringCache=null,this._frozenPathCache=null,this._frozenSiblingsCache=null,this.path.length>0&&(this.path[this.path.length-1].values=void 0);const n=this.path.length;this.siblingStacks[n]||(this.siblingStacks[n]=new Map);const i=this.siblingStacks[n],r=s?`${s}:${t}`:t,a=i.get(r)||0;let h=0;for(const t of i.values())h+=t;i.set(r,a+1);const l={tag:t,position:h,counter:a};null!=s&&(l.namespace=s),null!=e&&(l.values=e),this.path.push(l)}pop(){if(0===this.path.length)return;this._pathStringCache=null,this._frozenPathCache=null,this._frozenSiblingsCache=null;const t=this.path.pop();return this.siblingStacks.length>this.path.length+1&&(this.siblingStacks.length=this.path.length+1),t}updateCurrent(t){if(this.path.length>0){const e=this.path[this.path.length-1];null!=t&&(e.values=t,this._frozenPathCache=null)}}getCurrentTag(){return this.path.length>0?this.path[this.path.length-1].tag:void 0}getCurrentNamespace(){return this.path.length>0?this.path[this.path.length-1].namespace:void 0}getAttrValue(t){if(0===this.path.length)return;const e=this.path[this.path.length-1];return e.values?.[t]}hasAttr(t){if(0===this.path.length)return!1;const e=this.path[this.path.length-1];return void 0!==e.values&&t in e.values}getPosition(){return 0===this.path.length?-1:this.path[this.path.length-1].position??0}getCounter(){return 0===this.path.length?-1:this.path[this.path.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this.path.length}toString(t,e=!0){const s=t||this.separator;if(s===this.separator&&!0===e){if(null!==this._pathStringCache&&void 0!==this._pathStringCache)return this._pathStringCache;const t=this.path.map(t=>e&&t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s);return this._pathStringCache=t,t}return this.path.map(t=>e&&t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s)}toArray(){return this.path.map(t=>t.tag)}reset(){this._pathStringCache=null,this._frozenPathCache=null,this._frozenSiblingsCache=null,this.path=[],this.siblingStacks=[]}matches(t){const e=t.segments;return 0!==e.length&&(t.hasDeepWildcard()?this._matchWithDeepWildcard(e):this._matchSimple(e))}_matchSimple(t){if(this.path.length!==t.length)return!1;for(let e=0;e<t.length;e++){const s=t[e],n=this.path[e],i=e===this.path.length-1;if(!this._matchSegment(s,n,i))return!1}return!0}_matchWithDeepWildcard(t){let e=this.path.length-1,s=t.length-1;for(;s>=0&&e>=0;){const n=t[s];if("deep-wildcard"===n.type){if(s--,s<0)return!0;const n=t[s];let i=!1;for(let t=e;t>=0;t--){const r=t===this.path.length-1;if(this._matchSegment(n,this.path[t],r)){e=t-1,s--,i=!0;break}}if(!i)return!1}else{const t=e===this.path.length-1;if(!this._matchSegment(n,this.path[e],t))return!1;e--,s--}}return s<0}_matchSegment(t,e,s){if("*"!==t.tag&&t.tag!==e.tag)return!1;if(void 0!==t.namespace&&"*"!==t.namespace&&t.namespace!==e.namespace)return!1;if(void 0!==t.attrName){if(!s)return!1;if(!e.values||!(t.attrName in e.values))return!1;if(void 0!==t.attrValue){const s=e.values[t.attrName];if(String(s)!==String(t.attrValue))return!1}}if(void 0!==t.position){if(!s)return!1;const n=e.counter??0;if("first"===t.position&&0!==n)return!1;if("odd"===t.position&&n%2!=1)return!1;if("even"===t.position&&n%2!=0)return!1;if("nth"===t.position&&n!==t.positionValue)return!1}return!0}matchesAny(t){return t.matchesAny(this)}snapshot(){return{path:this.path.map(t=>({...t})),siblingStacks:this.siblingStacks.map(t=>new Map(t))}}restore(t){this._pathStringCache=null,this._frozenPathCache=null,this._frozenSiblingsCache=null,this.path=t.path.map(t=>({...t})),this.siblingStacks=t.siblingStacks.map(t=>new Map(t))}readOnly(){return new Proxy(this,{get(t,e,s){if(n.has(e))return()=>{throw new TypeError(`Cannot call '${e}' on a read-only Matcher. Obtain a writable instance to mutate state.`)};if("path"===e)return null===t._frozenPathCache&&(t._frozenPathCache=Object.freeze(t.path.map(t=>Object.freeze({...t})))),t._frozenPathCache;if("siblingStacks"===e)return null===t._frozenSiblingsCache&&(t._frozenSiblingsCache=Object.freeze(t.siblingStacks.map(t=>Object.freeze(new Map(t))))),t._frozenSiblingsCache;const i=Reflect.get(t,e,s);return"function"==typeof i?i.bind(t):i},set(t,e){throw new TypeError(`Cannot set property '${String(e)}' on a read-only Matcher.`)},deleteProperty(t,e){throw new TypeError(`Cannot delete property '${String(e)}' from a read-only Matcher.`)}})}}class r{constructor(){this._byDepthAndTag=new Map,this._wildcardByDepth=new Map,this._deepWildcards=[],this._patterns=new Set,this._sealed=!1}add(t){if(this._sealed)throw new TypeError("ExpressionSet is sealed. Create a new ExpressionSet to add more expressions.");if(this._patterns.has(t.pattern))return this;if(this._patterns.add(t.pattern),t.hasDeepWildcard())return this._deepWildcards.push(t),this;const e=t.length,s=t.segments[t.segments.length-1],n=s?.tag;if(n&&"*"!==n){const s=`${e}:${n}`;this._byDepthAndTag.has(s)||this._byDepthAndTag.set(s,[]),this._byDepthAndTag.get(s).push(t)}else this._wildcardByDepth.has(e)||this._wildcardByDepth.set(e,[]),this._wildcardByDepth.get(e).push(t);return this}addAll(t){for(const e of t)this.add(e);return this}has(t){return this._patterns.has(t.pattern)}get size(){return this._patterns.size}seal(){return this._sealed=!0,this}get isSealed(){return this._sealed}matchesAny(t){const e=t.getDepth(),s=`${e}:${t.getCurrentTag()}`,n=this._byDepthAndTag.get(s);if(n)for(let e=0;e<n.length;e++)if(t.matches(n[e]))return!0;const i=this._wildcardByDepth.get(e);if(i)for(let e=0;e<i.length;e++)if(t.matches(i[e]))return!0;for(let e=0;e<this._deepWildcards.length;e++)if(t.matches(this._deepWildcards[e]))return!0;return!1}}const a={Expression:s,Matcher:i,ExpressionSet:r};module.exports=e})();
1
+ (()=>{"use strict";var t={d:(e,s)=>{for(var i in s)t.o(s,i)&&!t.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:s[i]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{Expression:()=>s,ExpressionSet:()=>n,Matcher:()=>h,default:()=>r});class s{constructor(t,e={},s){this.pattern=t,this.separator=e.separator||".",this.segments=this._parse(t),this.data=s,this._hasDeepWildcard=this.segments.some(t=>"deep-wildcard"===t.type),this._hasAttributeCondition=this.segments.some(t=>void 0!==t.attrName),this._hasPositionSelector=this.segments.some(t=>void 0!==t.position)}_parse(t){const e=[];let s=0,i="";for(;s<t.length;)t[s]===this.separator?s+1<t.length&&t[s+1]===this.separator?(i.trim()&&(e.push(this._parseSegment(i.trim())),i=""),e.push({type:"deep-wildcard"}),s+=2):(i.trim()&&e.push(this._parseSegment(i.trim())),i="",s++):(i+=t[s],s++);return i.trim()&&e.push(this._parseSegment(i.trim())),e}_parseSegment(t){const e={type:"tag"};let s=null,i=t;const h=t.match(/^([^\[]+)(\[[^\]]*\])(.*)$/);if(h&&(i=h[1]+h[3],h[2])){const t=h[2].slice(1,-1);t&&(s=t)}let n,r,a=i;if(i.includes("::")){const e=i.indexOf("::");if(n=i.substring(0,e).trim(),a=i.substring(e+2).trim(),!n)throw new Error(`Invalid namespace in pattern: ${t}`)}let p=null;if(a.includes(":")){const t=a.lastIndexOf(":"),e=a.substring(0,t).trim(),s=a.substring(t+1).trim();["first","last","odd","even"].includes(s)||/^nth\(\d+\)$/.test(s)?(r=e,p=s):r=a}else r=a;if(!r)throw new Error(`Invalid segment pattern: ${t}`);if(e.tag=r,n&&(e.namespace=n),s)if(s.includes("=")){const t=s.indexOf("=");e.attrName=s.substring(0,t).trim(),e.attrValue=s.substring(t+1).trim()}else e.attrName=s.trim();if(p){const t=p.match(/^nth\((\d+)\)$/);t?(e.position="nth",e.positionValue=parseInt(t[1],10)):e.position=p}return e}get length(){return this.segments.length}hasDeepWildcard(){return this._hasDeepWildcard}hasAttributeCondition(){return this._hasAttributeCondition}hasPositionSelector(){return this._hasPositionSelector}toString(){return this.pattern}}class i{constructor(t){this._matcher=t}get separator(){return this._matcher.separator}getCurrentTag(){const t=this._matcher.path;return t.length>0?t[t.length-1].tag:void 0}getCurrentNamespace(){const t=this._matcher.path;return t.length>0?t[t.length-1].namespace:void 0}getAttrValue(t){const e=this._matcher.path;if(0!==e.length)return e[e.length-1].values?.[t]}hasAttr(t){const e=this._matcher.path;if(0===e.length)return!1;const s=e[e.length-1];return void 0!==s.values&&t in s.values}getPosition(){const t=this._matcher.path;return 0===t.length?-1:t[t.length-1].position??0}getCounter(){const t=this._matcher.path;return 0===t.length?-1:t[t.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this._matcher.path.length}toString(t,e=!0){return this._matcher.toString(t,e)}toArray(){return this._matcher.path.map(t=>t.tag)}matches(t){return this._matcher.matches(t)}matchesAny(t){return t.matchesAny(this._matcher)}}class h{constructor(t={}){this.separator=t.separator||".",this.path=[],this.siblingStacks=[],this._pathStringCache=null,this._view=new i(this)}push(t,e=null,s=null){this._pathStringCache=null,this.path.length>0&&(this.path[this.path.length-1].values=void 0);const i=this.path.length;this.siblingStacks[i]||(this.siblingStacks[i]=new Map);const h=this.siblingStacks[i],n=s?`${s}:${t}`:t,r=h.get(n)||0;let a=0;for(const t of h.values())a+=t;h.set(n,r+1);const p={tag:t,position:a,counter:r};null!=s&&(p.namespace=s),null!=e&&(p.values=e),this.path.push(p)}pop(){if(0===this.path.length)return;this._pathStringCache=null;const t=this.path.pop();return this.siblingStacks.length>this.path.length+1&&(this.siblingStacks.length=this.path.length+1),t}updateCurrent(t){if(this.path.length>0){const e=this.path[this.path.length-1];null!=t&&(e.values=t)}}getCurrentTag(){return this.path.length>0?this.path[this.path.length-1].tag:void 0}getCurrentNamespace(){return this.path.length>0?this.path[this.path.length-1].namespace:void 0}getAttrValue(t){if(0!==this.path.length)return this.path[this.path.length-1].values?.[t]}hasAttr(t){if(0===this.path.length)return!1;const e=this.path[this.path.length-1];return void 0!==e.values&&t in e.values}getPosition(){return 0===this.path.length?-1:this.path[this.path.length-1].position??0}getCounter(){return 0===this.path.length?-1:this.path[this.path.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this.path.length}toString(t,e=!0){const s=t||this.separator;if(s===this.separator&&!0===e){if(null!==this._pathStringCache)return this._pathStringCache;const t=this.path.map(t=>t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s);return this._pathStringCache=t,t}return this.path.map(t=>e&&t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s)}toArray(){return this.path.map(t=>t.tag)}reset(){this._pathStringCache=null,this.path=[],this.siblingStacks=[]}matches(t){const e=t.segments;return 0!==e.length&&(t.hasDeepWildcard()?this._matchWithDeepWildcard(e):this._matchSimple(e))}_matchSimple(t){if(this.path.length!==t.length)return!1;for(let e=0;e<t.length;e++)if(!this._matchSegment(t[e],this.path[e],e===this.path.length-1))return!1;return!0}_matchWithDeepWildcard(t){let e=this.path.length-1,s=t.length-1;for(;s>=0&&e>=0;){const i=t[s];if("deep-wildcard"===i.type){if(s--,s<0)return!0;const i=t[s];let h=!1;for(let t=e;t>=0;t--)if(this._matchSegment(i,this.path[t],t===this.path.length-1)){e=t-1,s--,h=!0;break}if(!h)return!1}else{if(!this._matchSegment(i,this.path[e],e===this.path.length-1))return!1;e--,s--}}return s<0}_matchSegment(t,e,s){if("*"!==t.tag&&t.tag!==e.tag)return!1;if(void 0!==t.namespace&&"*"!==t.namespace&&t.namespace!==e.namespace)return!1;if(void 0!==t.attrName){if(!s)return!1;if(!e.values||!(t.attrName in e.values))return!1;if(void 0!==t.attrValue&&String(e.values[t.attrName])!==String(t.attrValue))return!1}if(void 0!==t.position){if(!s)return!1;const i=e.counter??0;if("first"===t.position&&0!==i)return!1;if("odd"===t.position&&i%2!=1)return!1;if("even"===t.position&&i%2!=0)return!1;if("nth"===t.position&&i!==t.positionValue)return!1}return!0}matchesAny(t){return t.matchesAny(this)}snapshot(){return{path:this.path.map(t=>({...t})),siblingStacks:this.siblingStacks.map(t=>new Map(t))}}restore(t){this._pathStringCache=null,this.path=t.path.map(t=>({...t})),this.siblingStacks=t.siblingStacks.map(t=>new Map(t))}readOnly(){return this._view}}class n{constructor(){this._byDepthAndTag=new Map,this._wildcardByDepth=new Map,this._deepWildcards=[],this._patterns=new Set,this._sealed=!1}add(t){if(this._sealed)throw new TypeError("ExpressionSet is sealed. Create a new ExpressionSet to add more expressions.");if(this._patterns.has(t.pattern))return this;if(this._patterns.add(t.pattern),t.hasDeepWildcard())return this._deepWildcards.push(t),this;const e=t.length,s=t.segments[t.segments.length-1],i=s?.tag;if(i&&"*"!==i){const s=`${e}:${i}`;this._byDepthAndTag.has(s)||this._byDepthAndTag.set(s,[]),this._byDepthAndTag.get(s).push(t)}else this._wildcardByDepth.has(e)||this._wildcardByDepth.set(e,[]),this._wildcardByDepth.get(e).push(t);return this}addAll(t){for(const e of t)this.add(e);return this}has(t){return this._patterns.has(t.pattern)}get size(){return this._patterns.size}seal(){return this._sealed=!0,this}get isSealed(){return this._sealed}matchesAny(t){return null!==this.findMatch(t)}findMatch(t){const e=t.getDepth(),s=`${e}:${t.getCurrentTag()}`,i=this._byDepthAndTag.get(s);if(i)for(let e=0;e<i.length;e++)if(t.matches(i[e]))return i[e];const h=this._wildcardByDepth.get(e);if(h)for(let e=0;e<h.length;e++)if(t.matches(h[e]))return h[e];for(let e=0;e<this._deepWildcards.length;e++)if(t.matches(this._deepWildcards[e]))return this._deepWildcards[e];return null}}const r={Expression:s,Matcher:h,ExpressionSet:n};module.exports=e})();
package/lib/pem.d.cts CHANGED
@@ -596,8 +596,26 @@ declare class ExpressionSet {
596
596
  /**
597
597
  * Test whether the matcher's current path matches any expression in the set.
598
598
  * Accepts both a Matcher instance and a ReadOnlyMatcher view.
599
+ *
600
+ *
601
+ * @param matcher - A `Matcher` instance or a `ReadOnlyMatcher` view
602
+ * @returns Expression if at least one expression matches the current path
599
603
  */
600
604
  matchesAny(matcher: Matcher | ReadOnlyMatcher): boolean;
605
+
606
+ /**
607
+ * Find the first expression in the set that matches the matcher's current path.
608
+
609
+ *
610
+ * @param matcher - A `Matcher` instance or a `ReadOnlyMatcher` view
611
+ * @returns Expression if at least one expression matches the current path
612
+ *
613
+ * @example
614
+ * ```typescript
615
+ * const node = stopNodes.findMatch(matcher);
616
+ * ```
617
+ */
618
+ findMatch(matcher: Matcher | ReadOnlyMatcher): Expression;
601
619
  }
602
620
 
603
621
  declare namespace pathExpressionMatcher {
package/lib/pem.min.js CHANGED
@@ -1,2 +1,2 @@
1
- !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.pem=e():t.pem=e()}(this,()=>(()=>{"use strict";var t={d:(e,s)=>{for(var n in s)t.o(s,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:s[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{Expression:()=>s,ExpressionSet:()=>r,Matcher:()=>i,default:()=>a});class s{constructor(t,e={}){this.pattern=t,this.separator=e.separator||".",this.segments=this._parse(t),this._hasDeepWildcard=this.segments.some(t=>"deep-wildcard"===t.type),this._hasAttributeCondition=this.segments.some(t=>void 0!==t.attrName),this._hasPositionSelector=this.segments.some(t=>void 0!==t.position)}_parse(t){const e=[];let s=0,n="";for(;s<t.length;)t[s]===this.separator?s+1<t.length&&t[s+1]===this.separator?(n.trim()&&(e.push(this._parseSegment(n.trim())),n=""),e.push({type:"deep-wildcard"}),s+=2):(n.trim()&&e.push(this._parseSegment(n.trim())),n="",s++):(n+=t[s],s++);return n.trim()&&e.push(this._parseSegment(n.trim())),e}_parseSegment(t){const e={type:"tag"};let s=null,n=t;const i=t.match(/^([^\[]+)(\[[^\]]*\])(.*)$/);if(i&&(n=i[1]+i[3],i[2])){const t=i[2].slice(1,-1);t&&(s=t)}let r,a,h=n;if(n.includes("::")){const e=n.indexOf("::");if(r=n.substring(0,e).trim(),h=n.substring(e+2).trim(),!r)throw new Error(`Invalid namespace in pattern: ${t}`)}let o=null;if(h.includes(":")){const t=h.lastIndexOf(":"),e=h.substring(0,t).trim(),s=h.substring(t+1).trim();["first","last","odd","even"].includes(s)||/^nth\(\d+\)$/.test(s)?(a=e,o=s):a=h}else a=h;if(!a)throw new Error(`Invalid segment pattern: ${t}`);if(e.tag=a,r&&(e.namespace=r),s)if(s.includes("=")){const t=s.indexOf("=");e.attrName=s.substring(0,t).trim(),e.attrValue=s.substring(t+1).trim()}else e.attrName=s.trim();if(o){const t=o.match(/^nth\((\d+)\)$/);t?(e.position="nth",e.positionValue=parseInt(t[1],10)):e.position=o}return e}get length(){return this.segments.length}hasDeepWildcard(){return this._hasDeepWildcard}hasAttributeCondition(){return this._hasAttributeCondition}hasPositionSelector(){return this._hasPositionSelector}toString(){return this.pattern}}const n=new Set(["push","pop","reset","updateCurrent","restore"]);class i{constructor(t={}){this.separator=t.separator||".",this.path=[],this.siblingStacks=[],this._pathStringCache=null,this._frozenPathCache=null,this._frozenSiblingsCache=null}push(t,e=null,s=null){this._pathStringCache=null,this._frozenPathCache=null,this._frozenSiblingsCache=null,this.path.length>0&&(this.path[this.path.length-1].values=void 0);const n=this.path.length;this.siblingStacks[n]||(this.siblingStacks[n]=new Map);const i=this.siblingStacks[n],r=s?`${s}:${t}`:t,a=i.get(r)||0;let h=0;for(const t of i.values())h+=t;i.set(r,a+1);const o={tag:t,position:h,counter:a};null!=s&&(o.namespace=s),null!=e&&(o.values=e),this.path.push(o)}pop(){if(0===this.path.length)return;this._pathStringCache=null,this._frozenPathCache=null,this._frozenSiblingsCache=null;const t=this.path.pop();return this.siblingStacks.length>this.path.length+1&&(this.siblingStacks.length=this.path.length+1),t}updateCurrent(t){if(this.path.length>0){const e=this.path[this.path.length-1];null!=t&&(e.values=t,this._frozenPathCache=null)}}getCurrentTag(){return this.path.length>0?this.path[this.path.length-1].tag:void 0}getCurrentNamespace(){return this.path.length>0?this.path[this.path.length-1].namespace:void 0}getAttrValue(t){if(0===this.path.length)return;const e=this.path[this.path.length-1];return e.values?.[t]}hasAttr(t){if(0===this.path.length)return!1;const e=this.path[this.path.length-1];return void 0!==e.values&&t in e.values}getPosition(){return 0===this.path.length?-1:this.path[this.path.length-1].position??0}getCounter(){return 0===this.path.length?-1:this.path[this.path.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this.path.length}toString(t,e=!0){const s=t||this.separator;if(s===this.separator&&!0===e){if(null!==this._pathStringCache&&void 0!==this._pathStringCache)return this._pathStringCache;const t=this.path.map(t=>e&&t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s);return this._pathStringCache=t,t}return this.path.map(t=>e&&t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s)}toArray(){return this.path.map(t=>t.tag)}reset(){this._pathStringCache=null,this._frozenPathCache=null,this._frozenSiblingsCache=null,this.path=[],this.siblingStacks=[]}matches(t){const e=t.segments;return 0!==e.length&&(t.hasDeepWildcard()?this._matchWithDeepWildcard(e):this._matchSimple(e))}_matchSimple(t){if(this.path.length!==t.length)return!1;for(let e=0;e<t.length;e++){const s=t[e],n=this.path[e],i=e===this.path.length-1;if(!this._matchSegment(s,n,i))return!1}return!0}_matchWithDeepWildcard(t){let e=this.path.length-1,s=t.length-1;for(;s>=0&&e>=0;){const n=t[s];if("deep-wildcard"===n.type){if(s--,s<0)return!0;const n=t[s];let i=!1;for(let t=e;t>=0;t--){const r=t===this.path.length-1;if(this._matchSegment(n,this.path[t],r)){e=t-1,s--,i=!0;break}}if(!i)return!1}else{const t=e===this.path.length-1;if(!this._matchSegment(n,this.path[e],t))return!1;e--,s--}}return s<0}_matchSegment(t,e,s){if("*"!==t.tag&&t.tag!==e.tag)return!1;if(void 0!==t.namespace&&"*"!==t.namespace&&t.namespace!==e.namespace)return!1;if(void 0!==t.attrName){if(!s)return!1;if(!e.values||!(t.attrName in e.values))return!1;if(void 0!==t.attrValue){const s=e.values[t.attrName];if(String(s)!==String(t.attrValue))return!1}}if(void 0!==t.position){if(!s)return!1;const n=e.counter??0;if("first"===t.position&&0!==n)return!1;if("odd"===t.position&&n%2!=1)return!1;if("even"===t.position&&n%2!=0)return!1;if("nth"===t.position&&n!==t.positionValue)return!1}return!0}matchesAny(t){return t.matchesAny(this)}snapshot(){return{path:this.path.map(t=>({...t})),siblingStacks:this.siblingStacks.map(t=>new Map(t))}}restore(t){this._pathStringCache=null,this._frozenPathCache=null,this._frozenSiblingsCache=null,this.path=t.path.map(t=>({...t})),this.siblingStacks=t.siblingStacks.map(t=>new Map(t))}readOnly(){return new Proxy(this,{get(t,e,s){if(n.has(e))return()=>{throw new TypeError(`Cannot call '${e}' on a read-only Matcher. Obtain a writable instance to mutate state.`)};if("path"===e)return null===t._frozenPathCache&&(t._frozenPathCache=Object.freeze(t.path.map(t=>Object.freeze({...t})))),t._frozenPathCache;if("siblingStacks"===e)return null===t._frozenSiblingsCache&&(t._frozenSiblingsCache=Object.freeze(t.siblingStacks.map(t=>Object.freeze(new Map(t))))),t._frozenSiblingsCache;const i=Reflect.get(t,e,s);return"function"==typeof i?i.bind(t):i},set(t,e){throw new TypeError(`Cannot set property '${String(e)}' on a read-only Matcher.`)},deleteProperty(t,e){throw new TypeError(`Cannot delete property '${String(e)}' from a read-only Matcher.`)}})}}class r{constructor(){this._byDepthAndTag=new Map,this._wildcardByDepth=new Map,this._deepWildcards=[],this._patterns=new Set,this._sealed=!1}add(t){if(this._sealed)throw new TypeError("ExpressionSet is sealed. Create a new ExpressionSet to add more expressions.");if(this._patterns.has(t.pattern))return this;if(this._patterns.add(t.pattern),t.hasDeepWildcard())return this._deepWildcards.push(t),this;const e=t.length,s=t.segments[t.segments.length-1],n=s?.tag;if(n&&"*"!==n){const s=`${e}:${n}`;this._byDepthAndTag.has(s)||this._byDepthAndTag.set(s,[]),this._byDepthAndTag.get(s).push(t)}else this._wildcardByDepth.has(e)||this._wildcardByDepth.set(e,[]),this._wildcardByDepth.get(e).push(t);return this}addAll(t){for(const e of t)this.add(e);return this}has(t){return this._patterns.has(t.pattern)}get size(){return this._patterns.size}seal(){return this._sealed=!0,this}get isSealed(){return this._sealed}matchesAny(t){const e=t.getDepth(),s=`${e}:${t.getCurrentTag()}`,n=this._byDepthAndTag.get(s);if(n)for(let e=0;e<n.length;e++)if(t.matches(n[e]))return!0;const i=this._wildcardByDepth.get(e);if(i)for(let e=0;e<i.length;e++)if(t.matches(i[e]))return!0;for(let e=0;e<this._deepWildcards.length;e++)if(t.matches(this._deepWildcards[e]))return!0;return!1}}const a={Expression:s,Matcher:i,ExpressionSet:r};return e})());
1
+ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.pem=e():t.pem=e()}(this,()=>(()=>{"use strict";var t={d:(e,s)=>{for(var i in s)t.o(s,i)&&!t.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:s[i]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{Expression:()=>s,ExpressionSet:()=>r,Matcher:()=>n,default:()=>h});class s{constructor(t,e={},s){this.pattern=t,this.separator=e.separator||".",this.segments=this._parse(t),this.data=s,this._hasDeepWildcard=this.segments.some(t=>"deep-wildcard"===t.type),this._hasAttributeCondition=this.segments.some(t=>void 0!==t.attrName),this._hasPositionSelector=this.segments.some(t=>void 0!==t.position)}_parse(t){const e=[];let s=0,i="";for(;s<t.length;)t[s]===this.separator?s+1<t.length&&t[s+1]===this.separator?(i.trim()&&(e.push(this._parseSegment(i.trim())),i=""),e.push({type:"deep-wildcard"}),s+=2):(i.trim()&&e.push(this._parseSegment(i.trim())),i="",s++):(i+=t[s],s++);return i.trim()&&e.push(this._parseSegment(i.trim())),e}_parseSegment(t){const e={type:"tag"};let s=null,i=t;const n=t.match(/^([^\[]+)(\[[^\]]*\])(.*)$/);if(n&&(i=n[1]+n[3],n[2])){const t=n[2].slice(1,-1);t&&(s=t)}let r,h,a=i;if(i.includes("::")){const e=i.indexOf("::");if(r=i.substring(0,e).trim(),a=i.substring(e+2).trim(),!r)throw new Error(`Invalid namespace in pattern: ${t}`)}let p=null;if(a.includes(":")){const t=a.lastIndexOf(":"),e=a.substring(0,t).trim(),s=a.substring(t+1).trim();["first","last","odd","even"].includes(s)||/^nth\(\d+\)$/.test(s)?(h=e,p=s):h=a}else h=a;if(!h)throw new Error(`Invalid segment pattern: ${t}`);if(e.tag=h,r&&(e.namespace=r),s)if(s.includes("=")){const t=s.indexOf("=");e.attrName=s.substring(0,t).trim(),e.attrValue=s.substring(t+1).trim()}else e.attrName=s.trim();if(p){const t=p.match(/^nth\((\d+)\)$/);t?(e.position="nth",e.positionValue=parseInt(t[1],10)):e.position=p}return e}get length(){return this.segments.length}hasDeepWildcard(){return this._hasDeepWildcard}hasAttributeCondition(){return this._hasAttributeCondition}hasPositionSelector(){return this._hasPositionSelector}toString(){return this.pattern}}class i{constructor(t){this._matcher=t}get separator(){return this._matcher.separator}getCurrentTag(){const t=this._matcher.path;return t.length>0?t[t.length-1].tag:void 0}getCurrentNamespace(){const t=this._matcher.path;return t.length>0?t[t.length-1].namespace:void 0}getAttrValue(t){const e=this._matcher.path;if(0!==e.length)return e[e.length-1].values?.[t]}hasAttr(t){const e=this._matcher.path;if(0===e.length)return!1;const s=e[e.length-1];return void 0!==s.values&&t in s.values}getPosition(){const t=this._matcher.path;return 0===t.length?-1:t[t.length-1].position??0}getCounter(){const t=this._matcher.path;return 0===t.length?-1:t[t.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this._matcher.path.length}toString(t,e=!0){return this._matcher.toString(t,e)}toArray(){return this._matcher.path.map(t=>t.tag)}matches(t){return this._matcher.matches(t)}matchesAny(t){return t.matchesAny(this._matcher)}}class n{constructor(t={}){this.separator=t.separator||".",this.path=[],this.siblingStacks=[],this._pathStringCache=null,this._view=new i(this)}push(t,e=null,s=null){this._pathStringCache=null,this.path.length>0&&(this.path[this.path.length-1].values=void 0);const i=this.path.length;this.siblingStacks[i]||(this.siblingStacks[i]=new Map);const n=this.siblingStacks[i],r=s?`${s}:${t}`:t,h=n.get(r)||0;let a=0;for(const t of n.values())a+=t;n.set(r,h+1);const p={tag:t,position:a,counter:h};null!=s&&(p.namespace=s),null!=e&&(p.values=e),this.path.push(p)}pop(){if(0===this.path.length)return;this._pathStringCache=null;const t=this.path.pop();return this.siblingStacks.length>this.path.length+1&&(this.siblingStacks.length=this.path.length+1),t}updateCurrent(t){if(this.path.length>0){const e=this.path[this.path.length-1];null!=t&&(e.values=t)}}getCurrentTag(){return this.path.length>0?this.path[this.path.length-1].tag:void 0}getCurrentNamespace(){return this.path.length>0?this.path[this.path.length-1].namespace:void 0}getAttrValue(t){if(0!==this.path.length)return this.path[this.path.length-1].values?.[t]}hasAttr(t){if(0===this.path.length)return!1;const e=this.path[this.path.length-1];return void 0!==e.values&&t in e.values}getPosition(){return 0===this.path.length?-1:this.path[this.path.length-1].position??0}getCounter(){return 0===this.path.length?-1:this.path[this.path.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this.path.length}toString(t,e=!0){const s=t||this.separator;if(s===this.separator&&!0===e){if(null!==this._pathStringCache)return this._pathStringCache;const t=this.path.map(t=>t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s);return this._pathStringCache=t,t}return this.path.map(t=>e&&t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s)}toArray(){return this.path.map(t=>t.tag)}reset(){this._pathStringCache=null,this.path=[],this.siblingStacks=[]}matches(t){const e=t.segments;return 0!==e.length&&(t.hasDeepWildcard()?this._matchWithDeepWildcard(e):this._matchSimple(e))}_matchSimple(t){if(this.path.length!==t.length)return!1;for(let e=0;e<t.length;e++)if(!this._matchSegment(t[e],this.path[e],e===this.path.length-1))return!1;return!0}_matchWithDeepWildcard(t){let e=this.path.length-1,s=t.length-1;for(;s>=0&&e>=0;){const i=t[s];if("deep-wildcard"===i.type){if(s--,s<0)return!0;const i=t[s];let n=!1;for(let t=e;t>=0;t--)if(this._matchSegment(i,this.path[t],t===this.path.length-1)){e=t-1,s--,n=!0;break}if(!n)return!1}else{if(!this._matchSegment(i,this.path[e],e===this.path.length-1))return!1;e--,s--}}return s<0}_matchSegment(t,e,s){if("*"!==t.tag&&t.tag!==e.tag)return!1;if(void 0!==t.namespace&&"*"!==t.namespace&&t.namespace!==e.namespace)return!1;if(void 0!==t.attrName){if(!s)return!1;if(!e.values||!(t.attrName in e.values))return!1;if(void 0!==t.attrValue&&String(e.values[t.attrName])!==String(t.attrValue))return!1}if(void 0!==t.position){if(!s)return!1;const i=e.counter??0;if("first"===t.position&&0!==i)return!1;if("odd"===t.position&&i%2!=1)return!1;if("even"===t.position&&i%2!=0)return!1;if("nth"===t.position&&i!==t.positionValue)return!1}return!0}matchesAny(t){return t.matchesAny(this)}snapshot(){return{path:this.path.map(t=>({...t})),siblingStacks:this.siblingStacks.map(t=>new Map(t))}}restore(t){this._pathStringCache=null,this.path=t.path.map(t=>({...t})),this.siblingStacks=t.siblingStacks.map(t=>new Map(t))}readOnly(){return this._view}}class r{constructor(){this._byDepthAndTag=new Map,this._wildcardByDepth=new Map,this._deepWildcards=[],this._patterns=new Set,this._sealed=!1}add(t){if(this._sealed)throw new TypeError("ExpressionSet is sealed. Create a new ExpressionSet to add more expressions.");if(this._patterns.has(t.pattern))return this;if(this._patterns.add(t.pattern),t.hasDeepWildcard())return this._deepWildcards.push(t),this;const e=t.length,s=t.segments[t.segments.length-1],i=s?.tag;if(i&&"*"!==i){const s=`${e}:${i}`;this._byDepthAndTag.has(s)||this._byDepthAndTag.set(s,[]),this._byDepthAndTag.get(s).push(t)}else this._wildcardByDepth.has(e)||this._wildcardByDepth.set(e,[]),this._wildcardByDepth.get(e).push(t);return this}addAll(t){for(const e of t)this.add(e);return this}has(t){return this._patterns.has(t.pattern)}get size(){return this._patterns.size}seal(){return this._sealed=!0,this}get isSealed(){return this._sealed}matchesAny(t){return null!==this.findMatch(t)}findMatch(t){const e=t.getDepth(),s=`${e}:${t.getCurrentTag()}`,i=this._byDepthAndTag.get(s);if(i)for(let e=0;e<i.length;e++)if(t.matches(i[e]))return i[e];const n=this._wildcardByDepth.get(e);if(n)for(let e=0;e<n.length;e++)if(t.matches(n[e]))return n[e];for(let e=0;e<this._deepWildcards.length;e++)if(t.matches(this._deepWildcards[e]))return this._deepWildcards[e];return null}}const h={Expression:s,Matcher:n,ExpressionSet:r};return e})());
2
2
  //# sourceMappingURL=pem.min.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"./lib/pem.min.js","mappings":"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","sources":["webpack://pem/webpack/universalModuleDefinition","webpack://pem/webpack/bootstrap","webpack://pem/webpack/runtime/define property getters","webpack://pem/webpack/runtime/hasOwnProperty shorthand","webpack://pem/webpack/runtime/make namespace object","webpack://pem/./src/Expression.js","webpack://pem/./src/Matcher.js","webpack://pem/./src/ExpressionSet.js","webpack://pem/./src/index.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"pem\"] = factory();\n\telse\n\t\troot[\"pem\"] = factory();\n})(this, () => {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/**\n * Expression - Parses and stores a tag pattern expression\n * \n * Patterns are parsed once and stored in an optimized structure for fast matching.\n * \n * @example\n * const expr = new Expression(\"root.users.user\");\n * const expr2 = new Expression(\"..user[id]:first\");\n * const expr3 = new Expression(\"root/users/user\", { separator: '/' });\n */\nexport default class Expression {\n /**\n * Create a new Expression\n * @param {string} pattern - Pattern string (e.g., \"root.users.user\", \"..user[id]\")\n * @param {Object} options - Configuration options\n * @param {string} options.separator - Path separator (default: '.')\n */\n constructor(pattern, options = {}) {\n this.pattern = pattern;\n this.separator = options.separator || '.';\n this.segments = this._parse(pattern);\n\n // Cache expensive checks for performance (O(1) instead of O(n))\n this._hasDeepWildcard = this.segments.some(seg => seg.type === 'deep-wildcard');\n this._hasAttributeCondition = this.segments.some(seg => seg.attrName !== undefined);\n this._hasPositionSelector = this.segments.some(seg => seg.position !== undefined);\n }\n\n /**\n * Parse pattern string into segments\n * @private\n * @param {string} pattern - Pattern to parse\n * @returns {Array} Array of segment objects\n */\n _parse(pattern) {\n const segments = [];\n\n // Split by separator but handle \"..\" specially\n let i = 0;\n let currentPart = '';\n\n while (i < pattern.length) {\n if (pattern[i] === this.separator) {\n // Check if next char is also separator (deep wildcard)\n if (i + 1 < pattern.length && pattern[i + 1] === this.separator) {\n // Flush current part if any\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n currentPart = '';\n }\n // Add deep wildcard\n segments.push({ type: 'deep-wildcard' });\n i += 2; // Skip both separators\n } else {\n // Regular separator\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n }\n currentPart = '';\n i++;\n }\n } else {\n currentPart += pattern[i];\n i++;\n }\n }\n\n // Flush remaining part\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n }\n\n return segments;\n }\n\n /**\n * Parse a single segment\n * @private\n * @param {string} part - Segment string (e.g., \"user\", \"ns::user\", \"user[id]\", \"ns::user:first\")\n * @returns {Object} Segment object\n */\n _parseSegment(part) {\n const segment = { type: 'tag' };\n\n // NEW NAMESPACE SYNTAX (v2.0):\n // ============================\n // Namespace uses DOUBLE colon (::)\n // Position uses SINGLE colon (:)\n // \n // Examples:\n // \"user\" → tag\n // \"user:first\" → tag + position\n // \"user[id]\" → tag + attribute\n // \"user[id]:first\" → tag + attribute + position\n // \"ns::user\" → namespace + tag\n // \"ns::user:first\" → namespace + tag + position\n // \"ns::user[id]\" → namespace + tag + attribute\n // \"ns::user[id]:first\" → namespace + tag + attribute + position\n // \"ns::first\" → namespace + tag named \"first\" (NO ambiguity!)\n //\n // This eliminates all ambiguity:\n // :: = namespace separator\n // : = position selector\n // [] = attributes\n\n // Step 1: Extract brackets [attr] or [attr=value]\n let bracketContent = null;\n let withoutBrackets = part;\n\n const bracketMatch = part.match(/^([^\\[]+)(\\[[^\\]]*\\])(.*)$/);\n if (bracketMatch) {\n withoutBrackets = bracketMatch[1] + bracketMatch[3];\n if (bracketMatch[2]) {\n const content = bracketMatch[2].slice(1, -1);\n if (content) {\n bracketContent = content;\n }\n }\n }\n\n // Step 2: Check for namespace (double colon ::)\n let namespace = undefined;\n let tagAndPosition = withoutBrackets;\n\n if (withoutBrackets.includes('::')) {\n const nsIndex = withoutBrackets.indexOf('::');\n namespace = withoutBrackets.substring(0, nsIndex).trim();\n tagAndPosition = withoutBrackets.substring(nsIndex + 2).trim(); // Skip ::\n\n if (!namespace) {\n throw new Error(`Invalid namespace in pattern: ${part}`);\n }\n }\n\n // Step 3: Parse tag and position (single colon :)\n let tag = undefined;\n let positionMatch = null;\n\n if (tagAndPosition.includes(':')) {\n const colonIndex = tagAndPosition.lastIndexOf(':'); // Use last colon for position\n const tagPart = tagAndPosition.substring(0, colonIndex).trim();\n const posPart = tagAndPosition.substring(colonIndex + 1).trim();\n\n // Verify position is a valid keyword\n const isPositionKeyword = ['first', 'last', 'odd', 'even'].includes(posPart) ||\n /^nth\\(\\d+\\)$/.test(posPart);\n\n if (isPositionKeyword) {\n tag = tagPart;\n positionMatch = posPart;\n } else {\n // Not a valid position keyword, treat whole thing as tag\n tag = tagAndPosition;\n }\n } else {\n tag = tagAndPosition;\n }\n\n if (!tag) {\n throw new Error(`Invalid segment pattern: ${part}`);\n }\n\n segment.tag = tag;\n if (namespace) {\n segment.namespace = namespace;\n }\n\n // Step 4: Parse attributes\n if (bracketContent) {\n if (bracketContent.includes('=')) {\n const eqIndex = bracketContent.indexOf('=');\n segment.attrName = bracketContent.substring(0, eqIndex).trim();\n segment.attrValue = bracketContent.substring(eqIndex + 1).trim();\n } else {\n segment.attrName = bracketContent.trim();\n }\n }\n\n // Step 5: Parse position selector\n if (positionMatch) {\n const nthMatch = positionMatch.match(/^nth\\((\\d+)\\)$/);\n if (nthMatch) {\n segment.position = 'nth';\n segment.positionValue = parseInt(nthMatch[1], 10);\n } else {\n segment.position = positionMatch;\n }\n }\n\n return segment;\n }\n\n /**\n * Get the number of segments\n * @returns {number}\n */\n get length() {\n return this.segments.length;\n }\n\n /**\n * Check if expression contains deep wildcard\n * @returns {boolean}\n */\n hasDeepWildcard() {\n return this._hasDeepWildcard;\n }\n\n /**\n * Check if expression has attribute conditions\n * @returns {boolean}\n */\n hasAttributeCondition() {\n return this._hasAttributeCondition;\n }\n\n /**\n * Check if expression has position selectors\n * @returns {boolean}\n */\n hasPositionSelector() {\n return this._hasPositionSelector;\n }\n\n /**\n * Get string representation\n * @returns {string}\n */\n toString() {\n return this.pattern;\n }\n}","import ExpressionSet from \"./ExpressionSet.js\";\n/**\n * Matcher - Tracks current path in XML/JSON tree and matches against Expressions\n * \n * The matcher maintains a stack of nodes representing the current path from root to\n * current tag. It only stores attribute values for the current (top) node to minimize\n * memory usage. Sibling tracking is used to auto-calculate position and counter.\n * \n * @example\n * const matcher = new Matcher();\n * matcher.push(\"root\", {});\n * matcher.push(\"users\", {});\n * matcher.push(\"user\", { id: \"123\", type: \"admin\" });\n * \n * const expr = new Expression(\"root.users.user\");\n * matcher.matches(expr); // true\n */\n\n/**\n * Names of methods that mutate Matcher state.\n * Any attempt to call these on a read-only view throws a TypeError.\n * @type {Set<string>}\n */\nconst MUTATING_METHODS = new Set(['push', 'pop', 'reset', 'updateCurrent', 'restore']);\n\nexport default class Matcher {\n /**\n * Create a new Matcher\n * @param {Object} options - Configuration options\n * @param {string} options.separator - Default path separator (default: '.')\n */\n constructor(options = {}) {\n this.separator = options.separator || '.';\n this.path = [];\n this.siblingStacks = [];\n // Each path node: { tag: string, values: object, position: number, counter: number }\n // values only present for current (last) node\n // Each siblingStacks entry: Map<tagName, count> tracking occurrences at each level\n this._pathStringCache = null;\n this._frozenPathCache = null; // cache for readOnly().path\n this._frozenSiblingsCache = null; // cache for readOnly().siblingStacks\n }\n\n /**\n * Push a new tag onto the path\n * @param {string} tagName - Name of the tag\n * @param {Object} attrValues - Attribute key-value pairs for current node (optional)\n * @param {string} namespace - Namespace for the tag (optional)\n */\n push(tagName, attrValues = null, namespace = null) {\n //invalidate cache\n this._pathStringCache = null;\n this._frozenPathCache = null;\n this._frozenSiblingsCache = null;\n // Remove values from previous current node (now becoming ancestor)\n if (this.path.length > 0) {\n const prev = this.path[this.path.length - 1];\n prev.values = undefined;\n }\n\n // Get or create sibling tracking for current level\n const currentLevel = this.path.length;\n if (!this.siblingStacks[currentLevel]) {\n this.siblingStacks[currentLevel] = new Map();\n }\n\n const siblings = this.siblingStacks[currentLevel];\n\n // Create a unique key for sibling tracking that includes namespace\n const siblingKey = namespace ? `${namespace}:${tagName}` : tagName;\n\n // Calculate counter (how many times this tag appeared at this level)\n const counter = siblings.get(siblingKey) || 0;\n\n // Calculate position (total children at this level so far)\n let position = 0;\n for (const count of siblings.values()) {\n position += count;\n }\n\n // Update sibling count for this tag\n siblings.set(siblingKey, counter + 1);\n\n // Create new node\n const node = {\n tag: tagName,\n position: position,\n counter: counter\n };\n\n // Store namespace if provided\n if (namespace !== null && namespace !== undefined) {\n node.namespace = namespace;\n }\n\n // Store values only for current node\n if (attrValues !== null && attrValues !== undefined) {\n node.values = attrValues;\n }\n\n this.path.push(node);\n }\n\n /**\n * Pop the last tag from the path\n * @returns {Object|undefined} The popped node\n */\n pop() {\n if (this.path.length === 0) return undefined;\n //invalidate cache\n this._pathStringCache = null;\n this._frozenPathCache = null;\n this._frozenSiblingsCache = null;\n const node = this.path.pop();\n\n // Clean up sibling tracking for levels deeper than current\n // After pop, path.length is the new depth\n // We need to clean up siblingStacks[path.length + 1] and beyond\n if (this.siblingStacks.length > this.path.length + 1) {\n this.siblingStacks.length = this.path.length + 1;\n }\n\n return node;\n }\n\n /**\n * Update current node's attribute values\n * Useful when attributes are parsed after push\n * @param {Object} attrValues - Attribute values\n */\n updateCurrent(attrValues) {\n if (this.path.length > 0) {\n const current = this.path[this.path.length - 1];\n if (attrValues !== null && attrValues !== undefined) {\n current.values = attrValues;\n this._frozenPathCache = null;\n }\n }\n }\n\n /**\n * Get current tag name\n * @returns {string|undefined}\n */\n getCurrentTag() {\n return this.path.length > 0 ? this.path[this.path.length - 1].tag : undefined;\n }\n\n /**\n * Get current namespace\n * @returns {string|undefined}\n */\n getCurrentNamespace() {\n return this.path.length > 0 ? this.path[this.path.length - 1].namespace : undefined;\n }\n\n /**\n * Get current node's attribute value\n * @param {string} attrName - Attribute name\n * @returns {*} Attribute value or undefined\n */\n getAttrValue(attrName) {\n if (this.path.length === 0) return undefined;\n const current = this.path[this.path.length - 1];\n return current.values?.[attrName];\n }\n\n /**\n * Check if current node has an attribute\n * @param {string} attrName - Attribute name\n * @returns {boolean}\n */\n hasAttr(attrName) {\n if (this.path.length === 0) return false;\n const current = this.path[this.path.length - 1];\n return current.values !== undefined && attrName in current.values;\n }\n\n /**\n * Get current node's sibling position (child index in parent)\n * @returns {number}\n */\n getPosition() {\n if (this.path.length === 0) return -1;\n return this.path[this.path.length - 1].position ?? 0;\n }\n\n /**\n * Get current node's repeat counter (occurrence count of this tag name)\n * @returns {number}\n */\n getCounter() {\n if (this.path.length === 0) return -1;\n return this.path[this.path.length - 1].counter ?? 0;\n }\n\n /**\n * Get current node's sibling index (alias for getPosition for backward compatibility)\n * @returns {number}\n * @deprecated Use getPosition() or getCounter() instead\n */\n getIndex() {\n return this.getPosition();\n }\n\n /**\n * Get current path depth\n * @returns {number}\n */\n getDepth() {\n return this.path.length;\n }\n\n /**\n * Get path as string\n * @param {string} separator - Optional separator (uses default if not provided)\n * @param {boolean} includeNamespace - Whether to include namespace in output (default: true)\n * @returns {string}\n */\n toString(separator, includeNamespace = true) {\n const sep = separator || this.separator;\n const isDefault = (sep === this.separator && includeNamespace === true);\n\n if (isDefault) {\n if (this._pathStringCache !== null && this._pathStringCache !== undefined) {\n return this._pathStringCache;\n }\n const result = this.path.map(n =>\n (includeNamespace && n.namespace) ? `${n.namespace}:${n.tag}` : n.tag\n ).join(sep);\n this._pathStringCache = result;\n return result;\n }\n\n // Non-default separator or includeNamespace=false: don't cache (rare case)\n return this.path.map(n =>\n (includeNamespace && n.namespace) ? `${n.namespace}:${n.tag}` : n.tag\n ).join(sep);\n }\n\n /**\n * Get path as array of tag names\n * @returns {string[]}\n */\n toArray() {\n return this.path.map(n => n.tag);\n }\n\n /**\n * Reset the path to empty\n */\n reset() {\n //invalidate cache\n this._pathStringCache = null;\n this._frozenPathCache = null;\n this._frozenSiblingsCache = null;\n this.path = [];\n this.siblingStacks = [];\n }\n\n /**\n * Match current path against an Expression\n * @param {Expression} expression - The expression to match against\n * @returns {boolean} True if current path matches the expression\n */\n matches(expression) {\n const segments = expression.segments;\n\n if (segments.length === 0) {\n return false;\n }\n\n // Handle deep wildcard patterns\n if (expression.hasDeepWildcard()) {\n return this._matchWithDeepWildcard(segments);\n }\n\n // Simple path matching (no deep wildcards)\n return this._matchSimple(segments);\n }\n\n /**\n * Match simple path (no deep wildcards)\n * @private\n */\n _matchSimple(segments) {\n // Path must be same length as segments\n if (this.path.length !== segments.length) {\n return false;\n }\n\n // Match each segment bottom-to-top\n for (let i = 0; i < segments.length; i++) {\n const segment = segments[i];\n const node = this.path[i];\n const isCurrentNode = (i === this.path.length - 1);\n\n if (!this._matchSegment(segment, node, isCurrentNode)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Match path with deep wildcards\n * @private\n */\n _matchWithDeepWildcard(segments) {\n let pathIdx = this.path.length - 1; // Start from current node (bottom)\n let segIdx = segments.length - 1; // Start from last segment\n\n while (segIdx >= 0 && pathIdx >= 0) {\n const segment = segments[segIdx];\n\n if (segment.type === 'deep-wildcard') {\n // \"..\" matches zero or more levels\n segIdx--;\n\n if (segIdx < 0) {\n // Pattern ends with \"..\", always matches\n return true;\n }\n\n // Find where next segment matches in the path\n const nextSeg = segments[segIdx];\n let found = false;\n\n for (let i = pathIdx; i >= 0; i--) {\n const isCurrentNode = (i === this.path.length - 1);\n if (this._matchSegment(nextSeg, this.path[i], isCurrentNode)) {\n pathIdx = i - 1;\n segIdx--;\n found = true;\n break;\n }\n }\n\n if (!found) {\n return false;\n }\n } else {\n // Regular segment\n const isCurrentNode = (pathIdx === this.path.length - 1);\n if (!this._matchSegment(segment, this.path[pathIdx], isCurrentNode)) {\n return false;\n }\n pathIdx--;\n segIdx--;\n }\n }\n\n // All segments must be consumed\n return segIdx < 0;\n }\n\n /**\n * Match a single segment against a node\n * @private\n * @param {Object} segment - Segment from Expression\n * @param {Object} node - Node from path\n * @param {boolean} isCurrentNode - Whether this is the current (last) node\n * @returns {boolean}\n */\n _matchSegment(segment, node, isCurrentNode) {\n // Match tag name (* is wildcard)\n if (segment.tag !== '*' && segment.tag !== node.tag) {\n return false;\n }\n\n // Match namespace if specified in segment\n if (segment.namespace !== undefined) {\n // Segment has namespace - node must match it\n if (segment.namespace !== '*' && segment.namespace !== node.namespace) {\n return false;\n }\n }\n // If segment has no namespace, it matches nodes with or without namespace\n\n // Match attribute name (check if node has this attribute)\n // Can only check for current node since ancestors don't have values\n if (segment.attrName !== undefined) {\n if (!isCurrentNode) {\n // Can't check attributes for ancestor nodes (values not stored)\n return false;\n }\n\n if (!node.values || !(segment.attrName in node.values)) {\n return false;\n }\n\n // Match attribute value (only possible for current node)\n if (segment.attrValue !== undefined) {\n const actualValue = node.values[segment.attrName];\n // Both should be strings\n if (String(actualValue) !== String(segment.attrValue)) {\n return false;\n }\n }\n }\n\n // Match position (only for current node)\n if (segment.position !== undefined) {\n if (!isCurrentNode) {\n // Can't check position for ancestor nodes\n return false;\n }\n\n const counter = node.counter ?? 0;\n\n if (segment.position === 'first' && counter !== 0) {\n return false;\n } else if (segment.position === 'odd' && counter % 2 !== 1) {\n return false;\n } else if (segment.position === 'even' && counter % 2 !== 0) {\n return false;\n } else if (segment.position === 'nth') {\n if (counter !== segment.positionValue) {\n return false;\n }\n }\n }\n\n return true;\n }\n\n /**\n * Match any expression in the given set against the current path.\n * @param {ExpressionSet} exprSet - The set of expressions to match against.\n * @returns {boolean} - True if any expression in the set matches the current path, false otherwise.\n */\n matchesAny(exprSet) {\n return exprSet.matchesAny(this);\n }\n\n /**\n * Create a snapshot of current state\n * @returns {Object} State snapshot\n */\n snapshot() {\n return {\n path: this.path.map(node => ({ ...node })),\n siblingStacks: this.siblingStacks.map(map => new Map(map))\n };\n }\n\n /**\n * Restore state from snapshot\n * @param {Object} snapshot - State snapshot\n */\n restore(snapshot) {\n //invalidate cache\n this._pathStringCache = null;\n this._frozenPathCache = null;\n this._frozenSiblingsCache = null;\n this.path = snapshot.path.map(node => ({ ...node }));\n this.siblingStacks = snapshot.siblingStacks.map(map => new Map(map));\n }\n\n /**\n * Return a read-only view of this matcher.\n *\n * The returned object exposes all query/inspection methods but throws a\n * TypeError if any state-mutating method is called (`push`, `pop`, `reset`,\n * `updateCurrent`, `restore`). Property reads (e.g. `.path`, `.separator`)\n * are allowed but the returned arrays/objects are frozen so callers cannot\n * mutate internal state through them either.\n *\n * @returns {ReadOnlyMatcher} A proxy that forwards read operations and blocks writes.\n *\n * @example\n * const matcher = new Matcher();\n * matcher.push(\"root\", {});\n *\n * const ro = matcher.readOnly();\n * ro.matches(expr); // ✓ works\n * ro.getCurrentTag(); // ✓ works\n * ro.push(\"child\", {}); // ✗ throws TypeError\n * ro.reset(); // ✗ throws TypeError\n */\n readOnly() {\n const self = this;\n\n return new Proxy(self, {\n get(target, prop, receiver) {\n // Block mutating methods\n if (MUTATING_METHODS.has(prop)) {\n return () => {\n throw new TypeError(\n `Cannot call '${prop}' on a read-only Matcher. ` +\n `Obtain a writable instance to mutate state.`\n );\n };\n }\n\n // Return cached frozen copy of path — rebuilt only after push/pop/updateCurrent/reset/restore\n if (prop === 'path') {\n if (target._frozenPathCache === null) {\n target._frozenPathCache = Object.freeze(\n target.path.map(node => Object.freeze({ ...node }))\n );\n }\n return target._frozenPathCache;\n }\n\n // Return cached frozen copy of siblingStacks — rebuilt only after push/pop/reset/restore\n if (prop === 'siblingStacks') {\n if (target._frozenSiblingsCache === null) {\n target._frozenSiblingsCache = Object.freeze(\n target.siblingStacks.map(map => Object.freeze(new Map(map)))\n );\n }\n return target._frozenSiblingsCache;\n }\n\n const value = Reflect.get(target, prop, receiver);\n\n // Bind methods so `this` inside them still refers to the real Matcher\n if (typeof value === 'function') {\n return value.bind(target);\n }\n\n return value;\n },\n\n // Prevent any property assignment on the read-only view\n set(_target, prop) {\n throw new TypeError(\n `Cannot set property '${String(prop)}' on a read-only Matcher.`\n );\n },\n\n // Prevent property deletion\n deleteProperty(_target, prop) {\n throw new TypeError(\n `Cannot delete property '${String(prop)}' from a read-only Matcher.`\n );\n }\n });\n }\n}","/**\n * ExpressionSet - An indexed collection of Expressions for efficient bulk matching\n *\n * Instead of iterating all expressions on every tag, ExpressionSet pre-indexes\n * them at insertion time by depth and terminal tag name. At match time, only\n * the relevant bucket is evaluated — typically reducing checks from O(E) to O(1)\n * lookup plus O(small bucket) matches.\n *\n * Three buckets are maintained:\n * - `_byDepthAndTag` — exact depth + exact tag name (tightest, used first)\n * - `_wildcardByDepth` — exact depth + wildcard tag `*` (depth-matched only)\n * - `_deepWildcards` — expressions containing `..` (cannot be depth-indexed)\n *\n * @example\n * import { Expression, ExpressionSet } from 'fast-xml-tagger';\n *\n * // Build once at config time\n * const stopNodes = new ExpressionSet();\n * stopNodes.add(new Expression('root.users.user'));\n * stopNodes.add(new Expression('root.config.setting'));\n * stopNodes.add(new Expression('..script'));\n *\n * // Query on every tag — hot path\n * if (stopNodes.matchesAny(matcher)) { ... }\n */\nexport default class ExpressionSet {\n constructor() {\n /** @type {Map<string, import('./Expression.js').default[]>} depth:tag → expressions */\n this._byDepthAndTag = new Map();\n\n /** @type {Map<number, import('./Expression.js').default[]>} depth → wildcard-tag expressions */\n this._wildcardByDepth = new Map();\n\n /** @type {import('./Expression.js').default[]} expressions containing deep wildcard (..) */\n this._deepWildcards = [];\n\n /** @type {Set<string>} pattern strings already added — used for deduplication */\n this._patterns = new Set();\n\n /** @type {boolean} whether the set is sealed against further additions */\n this._sealed = false;\n }\n\n /**\n * Add an Expression to the set.\n * Duplicate patterns (same pattern string) are silently ignored.\n *\n * @param {import('./Expression.js').default} expression - A pre-constructed Expression instance\n * @returns {this} for chaining\n * @throws {TypeError} if called after seal()\n *\n * @example\n * set.add(new Expression('root.users.user'));\n * set.add(new Expression('..script'));\n */\n add(expression) {\n if (this._sealed) {\n throw new TypeError(\n 'ExpressionSet is sealed. Create a new ExpressionSet to add more expressions.'\n );\n }\n\n // Deduplicate by pattern string\n if (this._patterns.has(expression.pattern)) return this;\n this._patterns.add(expression.pattern);\n\n if (expression.hasDeepWildcard()) {\n this._deepWildcards.push(expression);\n return this;\n }\n\n const depth = expression.length;\n const lastSeg = expression.segments[expression.segments.length - 1];\n const tag = lastSeg?.tag;\n\n if (!tag || tag === '*') {\n // Can index by depth but not by tag\n if (!this._wildcardByDepth.has(depth)) this._wildcardByDepth.set(depth, []);\n this._wildcardByDepth.get(depth).push(expression);\n } else {\n // Tightest bucket: depth + tag\n const key = `${depth}:${tag}`;\n if (!this._byDepthAndTag.has(key)) this._byDepthAndTag.set(key, []);\n this._byDepthAndTag.get(key).push(expression);\n }\n\n return this;\n }\n\n /**\n * Add multiple expressions at once.\n *\n * @param {import('./Expression.js').default[]} expressions - Array of Expression instances\n * @returns {this} for chaining\n *\n * @example\n * set.addAll([\n * new Expression('root.users.user'),\n * new Expression('root.config.setting'),\n * ]);\n */\n addAll(expressions) {\n for (const expr of expressions) this.add(expr);\n return this;\n }\n\n /**\n * Check whether a pattern string is already present in the set.\n *\n * @param {import('./Expression.js').default} expression\n * @returns {boolean}\n */\n has(expression) {\n return this._patterns.has(expression.pattern);\n }\n\n /**\n * Number of expressions in the set.\n * @type {number}\n */\n get size() {\n return this._patterns.size;\n }\n\n /**\n * Seal the set against further modifications.\n * Useful to prevent accidental mutations after config is built.\n * Calling add() or addAll() on a sealed set throws a TypeError.\n *\n * @returns {this}\n */\n seal() {\n this._sealed = true;\n return this;\n }\n\n /**\n * Whether the set has been sealed.\n * @type {boolean}\n */\n get isSealed() {\n return this._sealed;\n }\n\n /**\n * Test whether the matcher's current path matches any expression in the set.\n *\n * Evaluation order (cheapest → most expensive):\n * 1. Exact depth + tag bucket — O(1) lookup, typically 0–2 expressions\n * 2. Depth-only wildcard bucket — O(1) lookup, rare\n * 3. Deep-wildcard list — always checked, but usually small\n *\n * @param {import('./Matcher.js').default} matcher - Matcher instance (or readOnly view)\n * @returns {boolean} true if any expression matches the current path\n *\n * @example\n * if (stopNodes.matchesAny(matcher)) {\n * // handle stop node\n * }\n */\n matchesAny(matcher) {\n const depth = matcher.getDepth();\n const tag = matcher.getCurrentTag();\n\n // 1. Tightest bucket — most expressions live here\n const exactKey = `${depth}:${tag}`;\n const exactBucket = this._byDepthAndTag.get(exactKey);\n if (exactBucket) {\n for (let i = 0; i < exactBucket.length; i++) {\n if (matcher.matches(exactBucket[i])) return true;\n }\n }\n\n // 2. Depth-matched wildcard-tag expressions\n const wildcardBucket = this._wildcardByDepth.get(depth);\n if (wildcardBucket) {\n for (let i = 0; i < wildcardBucket.length; i++) {\n if (matcher.matches(wildcardBucket[i])) return true;\n }\n }\n\n // 3. Deep wildcards — cannot be pre-filtered by depth or tag\n for (let i = 0; i < this._deepWildcards.length; i++) {\n if (matcher.matches(this._deepWildcards[i])) return true;\n }\n\n return false;\n }\n}\n","/**\n * fast-xml-tagger - XML/JSON path matching library\n * \n * Provides efficient path tracking and pattern matching for XML/JSON parsers.\n * \n * @example\n * import { Expression, Matcher } from 'fast-xml-tagger';\n * \n * // Create expression (parse once)\n * const expr = new Expression(\"root.users.user[id]\");\n * \n * // Create matcher (track path)\n * const matcher = new Matcher();\n * matcher.push(\"root\", [], {}, 0);\n * matcher.push(\"users\", [], {}, 0);\n * matcher.push(\"user\", [\"id\", \"type\"], { id: \"123\", type: \"admin\" }, 0);\n * \n * // Match\n * if (matcher.matches(expr)) {\n * console.log(\"Match found!\");\n * }\n */\n\nimport Expression from './Expression.js';\nimport Matcher from './Matcher.js';\nimport ExpressionSet from './ExpressionSet.js';\n\nexport { Expression, Matcher, ExpressionSet };\nexport default { Expression, Matcher, ExpressionSet };\n"],"names":["root","factory","exports","module","define","amd","this","__webpack_require__","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","Expression","constructor","pattern","options","separator","segments","_parse","_hasDeepWildcard","some","seg","type","_hasAttributeCondition","undefined","attrName","_hasPositionSelector","position","i","currentPart","length","trim","push","_parseSegment","part","segment","bracketContent","withoutBrackets","bracketMatch","match","content","slice","namespace","tag","tagAndPosition","includes","nsIndex","indexOf","substring","Error","positionMatch","colonIndex","lastIndexOf","tagPart","posPart","test","eqIndex","attrValue","nthMatch","positionValue","parseInt","hasDeepWildcard","hasAttributeCondition","hasPositionSelector","toString","MUTATING_METHODS","Set","Matcher","path","siblingStacks","_pathStringCache","_frozenPathCache","_frozenSiblingsCache","tagName","attrValues","values","currentLevel","Map","siblings","siblingKey","counter","count","set","node","pop","updateCurrent","current","getCurrentTag","getCurrentNamespace","getAttrValue","hasAttr","getPosition","getCounter","getIndex","getDepth","includeNamespace","sep","result","map","n","join","toArray","reset","matches","expression","_matchWithDeepWildcard","_matchSimple","isCurrentNode","_matchSegment","pathIdx","segIdx","nextSeg","found","actualValue","String","matchesAny","exprSet","snapshot","restore","readOnly","Proxy","target","receiver","has","TypeError","freeze","Reflect","bind","_target","deleteProperty","ExpressionSet","_byDepthAndTag","_wildcardByDepth","_deepWildcards","_patterns","_sealed","add","depth","lastSeg","addAll","expressions","expr","size","seal","isSealed","matcher","exactKey","exactBucket","wildcardBucket"],"sourceRoot":""}
1
+ {"version":3,"file":"./lib/pem.min.js","mappings":"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","sources":["webpack://pem/webpack/universalModuleDefinition","webpack://pem/webpack/bootstrap","webpack://pem/webpack/runtime/define property getters","webpack://pem/webpack/runtime/hasOwnProperty shorthand","webpack://pem/webpack/runtime/make namespace object","webpack://pem/./src/Expression.js","webpack://pem/./src/Matcher.js","webpack://pem/./src/ExpressionSet.js","webpack://pem/./src/index.js"],"sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"pem\"] = factory();\n\telse\n\t\troot[\"pem\"] = factory();\n})(this, () => {\nreturn ","// The require scope\nvar __webpack_require__ = {};\n\n","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","/**\n * Expression - Parses and stores a tag pattern expression\n * \n * Patterns are parsed once and stored in an optimized structure for fast matching.\n * \n * @example\n * const expr = new Expression(\"root.users.user\");\n * const expr2 = new Expression(\"..user[id]:first\");\n * const expr3 = new Expression(\"root/users/user\", { separator: '/' });\n */\nexport default class Expression {\n /**\n * Create a new Expression\n * @param {string} pattern - Pattern string (e.g., \"root.users.user\", \"..user[id]\")\n * @param {Object} options - Configuration options\n * @param {string} options.separator - Path separator (default: '.')\n */\n constructor(pattern, options = {}, data) {\n this.pattern = pattern;\n this.separator = options.separator || '.';\n this.segments = this._parse(pattern);\n this.data = data;\n // Cache expensive checks for performance (O(1) instead of O(n))\n this._hasDeepWildcard = this.segments.some(seg => seg.type === 'deep-wildcard');\n this._hasAttributeCondition = this.segments.some(seg => seg.attrName !== undefined);\n this._hasPositionSelector = this.segments.some(seg => seg.position !== undefined);\n }\n\n /**\n * Parse pattern string into segments\n * @private\n * @param {string} pattern - Pattern to parse\n * @returns {Array} Array of segment objects\n */\n _parse(pattern) {\n const segments = [];\n\n // Split by separator but handle \"..\" specially\n let i = 0;\n let currentPart = '';\n\n while (i < pattern.length) {\n if (pattern[i] === this.separator) {\n // Check if next char is also separator (deep wildcard)\n if (i + 1 < pattern.length && pattern[i + 1] === this.separator) {\n // Flush current part if any\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n currentPart = '';\n }\n // Add deep wildcard\n segments.push({ type: 'deep-wildcard' });\n i += 2; // Skip both separators\n } else {\n // Regular separator\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n }\n currentPart = '';\n i++;\n }\n } else {\n currentPart += pattern[i];\n i++;\n }\n }\n\n // Flush remaining part\n if (currentPart.trim()) {\n segments.push(this._parseSegment(currentPart.trim()));\n }\n\n return segments;\n }\n\n /**\n * Parse a single segment\n * @private\n * @param {string} part - Segment string (e.g., \"user\", \"ns::user\", \"user[id]\", \"ns::user:first\")\n * @returns {Object} Segment object\n */\n _parseSegment(part) {\n const segment = { type: 'tag' };\n\n // NEW NAMESPACE SYNTAX (v2.0):\n // ============================\n // Namespace uses DOUBLE colon (::)\n // Position uses SINGLE colon (:)\n // \n // Examples:\n // \"user\" → tag\n // \"user:first\" → tag + position\n // \"user[id]\" → tag + attribute\n // \"user[id]:first\" → tag + attribute + position\n // \"ns::user\" → namespace + tag\n // \"ns::user:first\" → namespace + tag + position\n // \"ns::user[id]\" → namespace + tag + attribute\n // \"ns::user[id]:first\" → namespace + tag + attribute + position\n // \"ns::first\" → namespace + tag named \"first\" (NO ambiguity!)\n //\n // This eliminates all ambiguity:\n // :: = namespace separator\n // : = position selector\n // [] = attributes\n\n // Step 1: Extract brackets [attr] or [attr=value]\n let bracketContent = null;\n let withoutBrackets = part;\n\n const bracketMatch = part.match(/^([^\\[]+)(\\[[^\\]]*\\])(.*)$/);\n if (bracketMatch) {\n withoutBrackets = bracketMatch[1] + bracketMatch[3];\n if (bracketMatch[2]) {\n const content = bracketMatch[2].slice(1, -1);\n if (content) {\n bracketContent = content;\n }\n }\n }\n\n // Step 2: Check for namespace (double colon ::)\n let namespace = undefined;\n let tagAndPosition = withoutBrackets;\n\n if (withoutBrackets.includes('::')) {\n const nsIndex = withoutBrackets.indexOf('::');\n namespace = withoutBrackets.substring(0, nsIndex).trim();\n tagAndPosition = withoutBrackets.substring(nsIndex + 2).trim(); // Skip ::\n\n if (!namespace) {\n throw new Error(`Invalid namespace in pattern: ${part}`);\n }\n }\n\n // Step 3: Parse tag and position (single colon :)\n let tag = undefined;\n let positionMatch = null;\n\n if (tagAndPosition.includes(':')) {\n const colonIndex = tagAndPosition.lastIndexOf(':'); // Use last colon for position\n const tagPart = tagAndPosition.substring(0, colonIndex).trim();\n const posPart = tagAndPosition.substring(colonIndex + 1).trim();\n\n // Verify position is a valid keyword\n const isPositionKeyword = ['first', 'last', 'odd', 'even'].includes(posPart) ||\n /^nth\\(\\d+\\)$/.test(posPart);\n\n if (isPositionKeyword) {\n tag = tagPart;\n positionMatch = posPart;\n } else {\n // Not a valid position keyword, treat whole thing as tag\n tag = tagAndPosition;\n }\n } else {\n tag = tagAndPosition;\n }\n\n if (!tag) {\n throw new Error(`Invalid segment pattern: ${part}`);\n }\n\n segment.tag = tag;\n if (namespace) {\n segment.namespace = namespace;\n }\n\n // Step 4: Parse attributes\n if (bracketContent) {\n if (bracketContent.includes('=')) {\n const eqIndex = bracketContent.indexOf('=');\n segment.attrName = bracketContent.substring(0, eqIndex).trim();\n segment.attrValue = bracketContent.substring(eqIndex + 1).trim();\n } else {\n segment.attrName = bracketContent.trim();\n }\n }\n\n // Step 5: Parse position selector\n if (positionMatch) {\n const nthMatch = positionMatch.match(/^nth\\((\\d+)\\)$/);\n if (nthMatch) {\n segment.position = 'nth';\n segment.positionValue = parseInt(nthMatch[1], 10);\n } else {\n segment.position = positionMatch;\n }\n }\n\n return segment;\n }\n\n /**\n * Get the number of segments\n * @returns {number}\n */\n get length() {\n return this.segments.length;\n }\n\n /**\n * Check if expression contains deep wildcard\n * @returns {boolean}\n */\n hasDeepWildcard() {\n return this._hasDeepWildcard;\n }\n\n /**\n * Check if expression has attribute conditions\n * @returns {boolean}\n */\n hasAttributeCondition() {\n return this._hasAttributeCondition;\n }\n\n /**\n * Check if expression has position selectors\n * @returns {boolean}\n */\n hasPositionSelector() {\n return this._hasPositionSelector;\n }\n\n /**\n * Get string representation\n * @returns {string}\n */\n toString() {\n return this.pattern;\n }\n}","import ExpressionSet from \"./ExpressionSet.js\";\n\n/**\n * MatcherView - A lightweight read-only view over a Matcher's internal state.\n *\n * Created once by Matcher and reused across all callbacks. Holds a direct\n * reference to the parent Matcher so it always reflects current parser state\n * with zero copying or freezing overhead.\n *\n * Users receive this via {@link Matcher#readOnly} or directly from parser\n * callbacks. It exposes all query and matching methods but has no mutation\n * methods — misuse is caught at the TypeScript level rather than at runtime.\n *\n * @example\n * const matcher = new Matcher();\n * const view = matcher.readOnly();\n *\n * matcher.push(\"root\", {});\n * view.getCurrentTag(); // \"root\"\n * view.getDepth(); // 1\n */\nexport class MatcherView {\n /**\n * @param {Matcher} matcher - The parent Matcher instance to read from.\n */\n constructor(matcher) {\n this._matcher = matcher;\n }\n\n /**\n * Get the path separator used by the parent matcher.\n * @returns {string}\n */\n get separator() {\n return this._matcher.separator;\n }\n\n /**\n * Get current tag name.\n * @returns {string|undefined}\n */\n getCurrentTag() {\n const path = this._matcher.path;\n return path.length > 0 ? path[path.length - 1].tag : undefined;\n }\n\n /**\n * Get current namespace.\n * @returns {string|undefined}\n */\n getCurrentNamespace() {\n const path = this._matcher.path;\n return path.length > 0 ? path[path.length - 1].namespace : undefined;\n }\n\n /**\n * Get current node's attribute value.\n * @param {string} attrName\n * @returns {*}\n */\n getAttrValue(attrName) {\n const path = this._matcher.path;\n if (path.length === 0) return undefined;\n return path[path.length - 1].values?.[attrName];\n }\n\n /**\n * Check if current node has an attribute.\n * @param {string} attrName\n * @returns {boolean}\n */\n hasAttr(attrName) {\n const path = this._matcher.path;\n if (path.length === 0) return false;\n const current = path[path.length - 1];\n return current.values !== undefined && attrName in current.values;\n }\n\n /**\n * Get current node's sibling position (child index in parent).\n * @returns {number}\n */\n getPosition() {\n const path = this._matcher.path;\n if (path.length === 0) return -1;\n return path[path.length - 1].position ?? 0;\n }\n\n /**\n * Get current node's repeat counter (occurrence count of this tag name).\n * @returns {number}\n */\n getCounter() {\n const path = this._matcher.path;\n if (path.length === 0) return -1;\n return path[path.length - 1].counter ?? 0;\n }\n\n /**\n * Get current node's sibling index (alias for getPosition).\n * @returns {number}\n * @deprecated Use getPosition() or getCounter() instead\n */\n getIndex() {\n return this.getPosition();\n }\n\n /**\n * Get current path depth.\n * @returns {number}\n */\n getDepth() {\n return this._matcher.path.length;\n }\n\n /**\n * Get path as string.\n * @param {string} [separator] - Optional separator (uses default if not provided)\n * @param {boolean} [includeNamespace=true]\n * @returns {string}\n */\n toString(separator, includeNamespace = true) {\n return this._matcher.toString(separator, includeNamespace);\n }\n\n /**\n * Get path as array of tag names.\n * @returns {string[]}\n */\n toArray() {\n return this._matcher.path.map(n => n.tag);\n }\n\n /**\n * Match current path against an Expression.\n * @param {Expression} expression\n * @returns {boolean}\n */\n matches(expression) {\n return this._matcher.matches(expression);\n }\n\n /**\n * Match any expression in the given set against the current path.\n * @param {ExpressionSet} exprSet\n * @returns {boolean}\n */\n matchesAny(exprSet) {\n return exprSet.matchesAny(this._matcher);\n }\n}\n\n/**\n * Matcher - Tracks current path in XML/JSON tree and matches against Expressions.\n *\n * The matcher maintains a stack of nodes representing the current path from root to\n * current tag. It only stores attribute values for the current (top) node to minimize\n * memory usage. Sibling tracking is used to auto-calculate position and counter.\n *\n * Use {@link Matcher#readOnly} to obtain a {@link MatcherView} safe to pass to\n * user callbacks — it always reflects current state with no Proxy overhead.\n *\n * @example\n * const matcher = new Matcher();\n * matcher.push(\"root\", {});\n * matcher.push(\"users\", {});\n * matcher.push(\"user\", { id: \"123\", type: \"admin\" });\n *\n * const expr = new Expression(\"root.users.user\");\n * matcher.matches(expr); // true\n */\nexport default class Matcher {\n /**\n * Create a new Matcher.\n * @param {Object} [options={}]\n * @param {string} [options.separator='.'] - Default path separator\n */\n constructor(options = {}) {\n this.separator = options.separator || '.';\n this.path = [];\n this.siblingStacks = [];\n // Each path node: { tag, values, position, counter, namespace? }\n // values only present for current (last) node\n // Each siblingStacks entry: Map<tagName, count> tracking occurrences at each level\n this._pathStringCache = null;\n this._view = new MatcherView(this);\n }\n\n /**\n * Push a new tag onto the path.\n * @param {string} tagName\n * @param {Object|null} [attrValues=null]\n * @param {string|null} [namespace=null]\n */\n push(tagName, attrValues = null, namespace = null) {\n this._pathStringCache = null;\n\n // Remove values from previous current node (now becoming ancestor)\n if (this.path.length > 0) {\n this.path[this.path.length - 1].values = undefined;\n }\n\n // Get or create sibling tracking for current level\n const currentLevel = this.path.length;\n if (!this.siblingStacks[currentLevel]) {\n this.siblingStacks[currentLevel] = new Map();\n }\n\n const siblings = this.siblingStacks[currentLevel];\n\n // Create a unique key for sibling tracking that includes namespace\n const siblingKey = namespace ? `${namespace}:${tagName}` : tagName;\n\n // Calculate counter (how many times this tag appeared at this level)\n const counter = siblings.get(siblingKey) || 0;\n\n // Calculate position (total children at this level so far)\n let position = 0;\n for (const count of siblings.values()) {\n position += count;\n }\n\n // Update sibling count for this tag\n siblings.set(siblingKey, counter + 1);\n\n // Create new node\n const node = {\n tag: tagName,\n position: position,\n counter: counter\n };\n\n if (namespace !== null && namespace !== undefined) {\n node.namespace = namespace;\n }\n\n if (attrValues !== null && attrValues !== undefined) {\n node.values = attrValues;\n }\n\n this.path.push(node);\n }\n\n /**\n * Pop the last tag from the path.\n * @returns {Object|undefined} The popped node\n */\n pop() {\n if (this.path.length === 0) return undefined;\n this._pathStringCache = null;\n\n const node = this.path.pop();\n\n if (this.siblingStacks.length > this.path.length + 1) {\n this.siblingStacks.length = this.path.length + 1;\n }\n\n return node;\n }\n\n /**\n * Update current node's attribute values.\n * Useful when attributes are parsed after push.\n * @param {Object} attrValues\n */\n updateCurrent(attrValues) {\n if (this.path.length > 0) {\n const current = this.path[this.path.length - 1];\n if (attrValues !== null && attrValues !== undefined) {\n current.values = attrValues;\n }\n }\n }\n\n /**\n * Get current tag name.\n * @returns {string|undefined}\n */\n getCurrentTag() {\n return this.path.length > 0 ? this.path[this.path.length - 1].tag : undefined;\n }\n\n /**\n * Get current namespace.\n * @returns {string|undefined}\n */\n getCurrentNamespace() {\n return this.path.length > 0 ? this.path[this.path.length - 1].namespace : undefined;\n }\n\n /**\n * Get current node's attribute value.\n * @param {string} attrName\n * @returns {*}\n */\n getAttrValue(attrName) {\n if (this.path.length === 0) return undefined;\n return this.path[this.path.length - 1].values?.[attrName];\n }\n\n /**\n * Check if current node has an attribute.\n * @param {string} attrName\n * @returns {boolean}\n */\n hasAttr(attrName) {\n if (this.path.length === 0) return false;\n const current = this.path[this.path.length - 1];\n return current.values !== undefined && attrName in current.values;\n }\n\n /**\n * Get current node's sibling position (child index in parent).\n * @returns {number}\n */\n getPosition() {\n if (this.path.length === 0) return -1;\n return this.path[this.path.length - 1].position ?? 0;\n }\n\n /**\n * Get current node's repeat counter (occurrence count of this tag name).\n * @returns {number}\n */\n getCounter() {\n if (this.path.length === 0) return -1;\n return this.path[this.path.length - 1].counter ?? 0;\n }\n\n /**\n * Get current node's sibling index (alias for getPosition).\n * @returns {number}\n * @deprecated Use getPosition() or getCounter() instead\n */\n getIndex() {\n return this.getPosition();\n }\n\n /**\n * Get current path depth.\n * @returns {number}\n */\n getDepth() {\n return this.path.length;\n }\n\n /**\n * Get path as string.\n * @param {string} [separator] - Optional separator (uses default if not provided)\n * @param {boolean} [includeNamespace=true]\n * @returns {string}\n */\n toString(separator, includeNamespace = true) {\n const sep = separator || this.separator;\n const isDefault = (sep === this.separator && includeNamespace === true);\n\n if (isDefault) {\n if (this._pathStringCache !== null) {\n return this._pathStringCache;\n }\n const result = this.path.map(n =>\n (n.namespace) ? `${n.namespace}:${n.tag}` : n.tag\n ).join(sep);\n this._pathStringCache = result;\n return result;\n }\n\n return this.path.map(n =>\n (includeNamespace && n.namespace) ? `${n.namespace}:${n.tag}` : n.tag\n ).join(sep);\n }\n\n /**\n * Get path as array of tag names.\n * @returns {string[]}\n */\n toArray() {\n return this.path.map(n => n.tag);\n }\n\n /**\n * Reset the path to empty.\n */\n reset() {\n this._pathStringCache = null;\n this.path = [];\n this.siblingStacks = [];\n }\n\n /**\n * Match current path against an Expression.\n * @param {Expression} expression\n * @returns {boolean}\n */\n matches(expression) {\n const segments = expression.segments;\n\n if (segments.length === 0) {\n return false;\n }\n\n if (expression.hasDeepWildcard()) {\n return this._matchWithDeepWildcard(segments);\n }\n\n return this._matchSimple(segments);\n }\n\n /**\n * @private\n */\n _matchSimple(segments) {\n if (this.path.length !== segments.length) {\n return false;\n }\n\n for (let i = 0; i < segments.length; i++) {\n if (!this._matchSegment(segments[i], this.path[i], i === this.path.length - 1)) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * @private\n */\n _matchWithDeepWildcard(segments) {\n let pathIdx = this.path.length - 1;\n let segIdx = segments.length - 1;\n\n while (segIdx >= 0 && pathIdx >= 0) {\n const segment = segments[segIdx];\n\n if (segment.type === 'deep-wildcard') {\n segIdx--;\n\n if (segIdx < 0) {\n return true;\n }\n\n const nextSeg = segments[segIdx];\n let found = false;\n\n for (let i = pathIdx; i >= 0; i--) {\n if (this._matchSegment(nextSeg, this.path[i], i === this.path.length - 1)) {\n pathIdx = i - 1;\n segIdx--;\n found = true;\n break;\n }\n }\n\n if (!found) {\n return false;\n }\n } else {\n if (!this._matchSegment(segment, this.path[pathIdx], pathIdx === this.path.length - 1)) {\n return false;\n }\n pathIdx--;\n segIdx--;\n }\n }\n\n return segIdx < 0;\n }\n\n /**\n * @private\n */\n _matchSegment(segment, node, isCurrentNode) {\n if (segment.tag !== '*' && segment.tag !== node.tag) {\n return false;\n }\n\n if (segment.namespace !== undefined) {\n if (segment.namespace !== '*' && segment.namespace !== node.namespace) {\n return false;\n }\n }\n\n if (segment.attrName !== undefined) {\n if (!isCurrentNode) {\n return false;\n }\n\n if (!node.values || !(segment.attrName in node.values)) {\n return false;\n }\n\n if (segment.attrValue !== undefined) {\n if (String(node.values[segment.attrName]) !== String(segment.attrValue)) {\n return false;\n }\n }\n }\n\n if (segment.position !== undefined) {\n if (!isCurrentNode) {\n return false;\n }\n\n const counter = node.counter ?? 0;\n\n if (segment.position === 'first' && counter !== 0) {\n return false;\n } else if (segment.position === 'odd' && counter % 2 !== 1) {\n return false;\n } else if (segment.position === 'even' && counter % 2 !== 0) {\n return false;\n } else if (segment.position === 'nth' && counter !== segment.positionValue) {\n return false;\n }\n }\n\n return true;\n }\n\n /**\n * Match any expression in the given set against the current path.\n * @param {ExpressionSet} exprSet\n * @returns {boolean}\n */\n matchesAny(exprSet) {\n return exprSet.matchesAny(this);\n }\n\n /**\n * Create a snapshot of current state.\n * @returns {Object}\n */\n snapshot() {\n return {\n path: this.path.map(node => ({ ...node })),\n siblingStacks: this.siblingStacks.map(map => new Map(map))\n };\n }\n\n /**\n * Restore state from snapshot.\n * @param {Object} snapshot\n */\n restore(snapshot) {\n this._pathStringCache = null;\n this.path = snapshot.path.map(node => ({ ...node }));\n this.siblingStacks = snapshot.siblingStacks.map(map => new Map(map));\n }\n\n /**\n * Return the read-only {@link MatcherView} for this matcher.\n *\n * The same instance is returned on every call — no allocation occurs.\n * It always reflects the current parser state and is safe to pass to\n * user callbacks without risk of accidental mutation.\n *\n * @returns {MatcherView}\n *\n * @example\n * const view = matcher.readOnly();\n * // pass view to callbacks — it stays in sync automatically\n * view.matches(expr); // ✓\n * view.getCurrentTag(); // ✓\n * // view.push(...) // ✗ method does not exist — caught by TypeScript\n */\n readOnly() {\n return this._view;\n }\n}","/**\n * ExpressionSet - An indexed collection of Expressions for efficient bulk matching\n *\n * Instead of iterating all expressions on every tag, ExpressionSet pre-indexes\n * them at insertion time by depth and terminal tag name. At match time, only\n * the relevant bucket is evaluated — typically reducing checks from O(E) to O(1)\n * lookup plus O(small bucket) matches.\n *\n * Three buckets are maintained:\n * - `_byDepthAndTag` — exact depth + exact tag name (tightest, used first)\n * - `_wildcardByDepth` — exact depth + wildcard tag `*` (depth-matched only)\n * - `_deepWildcards` — expressions containing `..` (cannot be depth-indexed)\n *\n * @example\n * import { Expression, ExpressionSet } from 'fast-xml-tagger';\n *\n * // Build once at config time\n * const stopNodes = new ExpressionSet();\n * stopNodes.add(new Expression('root.users.user'));\n * stopNodes.add(new Expression('root.config.setting'));\n * stopNodes.add(new Expression('..script'));\n *\n * // Query on every tag — hot path\n * if (stopNodes.matchesAny(matcher)) { ... }\n */\nexport default class ExpressionSet {\n constructor() {\n /** @type {Map<string, import('./Expression.js').default[]>} depth:tag → expressions */\n this._byDepthAndTag = new Map();\n\n /** @type {Map<number, import('./Expression.js').default[]>} depth → wildcard-tag expressions */\n this._wildcardByDepth = new Map();\n\n /** @type {import('./Expression.js').default[]} expressions containing deep wildcard (..) */\n this._deepWildcards = [];\n\n /** @type {Set<string>} pattern strings already added — used for deduplication */\n this._patterns = new Set();\n\n /** @type {boolean} whether the set is sealed against further additions */\n this._sealed = false;\n }\n\n /**\n * Add an Expression to the set.\n * Duplicate patterns (same pattern string) are silently ignored.\n *\n * @param {import('./Expression.js').default} expression - A pre-constructed Expression instance\n * @returns {this} for chaining\n * @throws {TypeError} if called after seal()\n *\n * @example\n * set.add(new Expression('root.users.user'));\n * set.add(new Expression('..script'));\n */\n add(expression) {\n if (this._sealed) {\n throw new TypeError(\n 'ExpressionSet is sealed. Create a new ExpressionSet to add more expressions.'\n );\n }\n\n // Deduplicate by pattern string\n if (this._patterns.has(expression.pattern)) return this;\n this._patterns.add(expression.pattern);\n\n if (expression.hasDeepWildcard()) {\n this._deepWildcards.push(expression);\n return this;\n }\n\n const depth = expression.length;\n const lastSeg = expression.segments[expression.segments.length - 1];\n const tag = lastSeg?.tag;\n\n if (!tag || tag === '*') {\n // Can index by depth but not by tag\n if (!this._wildcardByDepth.has(depth)) this._wildcardByDepth.set(depth, []);\n this._wildcardByDepth.get(depth).push(expression);\n } else {\n // Tightest bucket: depth + tag\n const key = `${depth}:${tag}`;\n if (!this._byDepthAndTag.has(key)) this._byDepthAndTag.set(key, []);\n this._byDepthAndTag.get(key).push(expression);\n }\n\n return this;\n }\n\n /**\n * Add multiple expressions at once.\n *\n * @param {import('./Expression.js').default[]} expressions - Array of Expression instances\n * @returns {this} for chaining\n *\n * @example\n * set.addAll([\n * new Expression('root.users.user'),\n * new Expression('root.config.setting'),\n * ]);\n */\n addAll(expressions) {\n for (const expr of expressions) this.add(expr);\n return this;\n }\n\n /**\n * Check whether a pattern string is already present in the set.\n *\n * @param {import('./Expression.js').default} expression\n * @returns {boolean}\n */\n has(expression) {\n return this._patterns.has(expression.pattern);\n }\n\n /**\n * Number of expressions in the set.\n * @type {number}\n */\n get size() {\n return this._patterns.size;\n }\n\n /**\n * Seal the set against further modifications.\n * Useful to prevent accidental mutations after config is built.\n * Calling add() or addAll() on a sealed set throws a TypeError.\n *\n * @returns {this}\n */\n seal() {\n this._sealed = true;\n return this;\n }\n\n /**\n * Whether the set has been sealed.\n * @type {boolean}\n */\n get isSealed() {\n return this._sealed;\n }\n\n /**\n * Test whether the matcher's current path matches any expression in the set.\n *\n * Evaluation order (cheapest → most expensive):\n * 1. Exact depth + tag bucket — O(1) lookup, typically 0–2 expressions\n * 2. Depth-only wildcard bucket — O(1) lookup, rare\n * 3. Deep-wildcard list — always checked, but usually small\n *\n * @param {import('./Matcher.js').default} matcher - Matcher instance (or readOnly view)\n * @returns {boolean} true if any expression matches the current path\n *\n * @example\n * if (stopNodes.matchesAny(matcher)) {\n * // handle stop node\n * }\n */\n matchesAny(matcher) {\n return this.findMatch(matcher) !== null;\n }\n /**\n * Find and return the first Expression that matches the matcher's current path.\n *\n * Uses the same evaluation order as matchesAny (cheapest → most expensive):\n * 1. Exact depth + tag bucket\n * 2. Depth-only wildcard bucket\n * 3. Deep-wildcard list\n *\n * @param {import('./Matcher.js').default} matcher - Matcher instance (or readOnly view)\n * @returns {import('./Expression.js').default | null} the first matching Expression, or null\n *\n * @example\n * const expr = stopNodes.findMatch(matcher);\n * if (expr) {\n * // access expr.config, expr.pattern, etc.\n * }\n */\n findMatch(matcher) {\n const depth = matcher.getDepth();\n const tag = matcher.getCurrentTag();\n\n // 1. Tightest bucket — most expressions live here\n const exactKey = `${depth}:${tag}`;\n const exactBucket = this._byDepthAndTag.get(exactKey);\n if (exactBucket) {\n for (let i = 0; i < exactBucket.length; i++) {\n if (matcher.matches(exactBucket[i])) return exactBucket[i];\n }\n }\n\n // 2. Depth-matched wildcard-tag expressions\n const wildcardBucket = this._wildcardByDepth.get(depth);\n if (wildcardBucket) {\n for (let i = 0; i < wildcardBucket.length; i++) {\n if (matcher.matches(wildcardBucket[i])) return wildcardBucket[i];\n }\n }\n\n // 3. Deep wildcards — cannot be pre-filtered by depth or tag\n for (let i = 0; i < this._deepWildcards.length; i++) {\n if (matcher.matches(this._deepWildcards[i])) return this._deepWildcards[i];\n }\n\n return null;\n }\n}\n","/**\n * fast-xml-tagger - XML/JSON path matching library\n * \n * Provides efficient path tracking and pattern matching for XML/JSON parsers.\n * \n * @example\n * import { Expression, Matcher } from 'fast-xml-tagger';\n * \n * // Create expression (parse once)\n * const expr = new Expression(\"root.users.user[id]\");\n * \n * // Create matcher (track path)\n * const matcher = new Matcher();\n * matcher.push(\"root\", [], {}, 0);\n * matcher.push(\"users\", [], {}, 0);\n * matcher.push(\"user\", [\"id\", \"type\"], { id: \"123\", type: \"admin\" }, 0);\n * \n * // Match\n * if (matcher.matches(expr)) {\n * console.log(\"Match found!\");\n * }\n */\n\nimport Expression from './Expression.js';\nimport Matcher from './Matcher.js';\nimport ExpressionSet from './ExpressionSet.js';\n\nexport { Expression, Matcher, ExpressionSet };\nexport default { Expression, Matcher, ExpressionSet };\n"],"names":["root","factory","exports","module","define","amd","this","__webpack_require__","definition","key","o","Object","defineProperty","enumerable","get","obj","prop","prototype","hasOwnProperty","call","Symbol","toStringTag","value","Expression","constructor","pattern","options","data","separator","segments","_parse","_hasDeepWildcard","some","seg","type","_hasAttributeCondition","undefined","attrName","_hasPositionSelector","position","i","currentPart","length","trim","push","_parseSegment","part","segment","bracketContent","withoutBrackets","bracketMatch","match","content","slice","namespace","tag","tagAndPosition","includes","nsIndex","indexOf","substring","Error","positionMatch","colonIndex","lastIndexOf","tagPart","posPart","test","eqIndex","attrValue","nthMatch","positionValue","parseInt","hasDeepWildcard","hasAttributeCondition","hasPositionSelector","toString","MatcherView","matcher","_matcher","getCurrentTag","path","getCurrentNamespace","getAttrValue","values","hasAttr","current","getPosition","getCounter","counter","getIndex","getDepth","includeNamespace","toArray","map","n","matches","expression","matchesAny","exprSet","Matcher","siblingStacks","_pathStringCache","_view","tagName","attrValues","currentLevel","Map","siblings","siblingKey","count","set","node","pop","updateCurrent","sep","result","join","reset","_matchWithDeepWildcard","_matchSimple","_matchSegment","pathIdx","segIdx","nextSeg","found","isCurrentNode","String","snapshot","restore","readOnly","ExpressionSet","_byDepthAndTag","_wildcardByDepth","_deepWildcards","_patterns","Set","_sealed","add","TypeError","has","depth","lastSeg","addAll","expressions","expr","size","seal","isSealed","findMatch","exactKey","exactBucket","wildcardBucket"],"sourceRoot":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "path-expression-matcher",
3
- "version": "1.3.0",
3
+ "version": "1.5.0",
4
4
  "description": "Efficient path tracking and pattern matching for XML/JSON parsers",
5
5
  "main": "./lib/pem.cjs",
6
6
  "type": "module",
package/src/Expression.js CHANGED
@@ -15,11 +15,11 @@ export default class Expression {
15
15
  * @param {Object} options - Configuration options
16
16
  * @param {string} options.separator - Path separator (default: '.')
17
17
  */
18
- constructor(pattern, options = {}) {
18
+ constructor(pattern, options = {}, data) {
19
19
  this.pattern = pattern;
20
20
  this.separator = options.separator || '.';
21
21
  this.segments = this._parse(pattern);
22
-
22
+ this.data = data;
23
23
  // Cache expensive checks for performance (O(1) instead of O(n))
24
24
  this._hasDeepWildcard = this.segments.some(seg => seg.type === 'deep-wildcard');
25
25
  this._hasAttributeCondition = this.segments.some(seg => seg.attrName !== undefined);