@jjrawlins/cdk-diff-pr-github-action 1.9.15 → 1.9.16
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/.jsii +3 -3
- package/cdkdiffprgithubaction/jsii/jsii.go +2 -2
- package/cdkdiffprgithubaction/version +1 -1
- package/lib/CdkDiffIamTemplate.js +2 -2
- package/lib/CdkDiffIamTemplateStackSet.js +2 -2
- package/lib/CdkDiffStackWorkflow.js +1 -1
- package/lib/CdkDriftDetectionWorkflow.js +1 -1
- package/lib/CdkDriftIamTemplate.js +2 -2
- package/node_modules/@aws-sdk/client-cloudformation/package.json +12 -12
- package/node_modules/@aws-sdk/core/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-env/package.json +2 -2
- package/node_modules/@aws-sdk/credential-provider-http/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-ini/package.json +9 -9
- package/node_modules/@aws-sdk/credential-provider-login/package.json +3 -3
- package/node_modules/@aws-sdk/credential-provider-node/package.json +7 -7
- package/node_modules/@aws-sdk/credential-provider-process/package.json +2 -2
- package/node_modules/@aws-sdk/credential-provider-sso/package.json +4 -4
- package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +3 -3
- package/node_modules/@aws-sdk/middleware-user-agent/package.json +2 -2
- package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/cognito-identity/CognitoIdentity.js +1 -1
- package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/cognito-identity/CognitoIdentity.d.ts +2 -2
- package/node_modules/@aws-sdk/nested-clients/package.json +11 -11
- package/node_modules/@aws-sdk/region-config-resolver/package.json +2 -2
- package/node_modules/@aws-sdk/token-providers/package.json +3 -3
- package/node_modules/@aws-sdk/util-user-agent-node/package.json +2 -2
- package/node_modules/@aws-sdk/xml-builder/package.json +2 -2
- package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/CHANGELOG.md +7 -0
- package/node_modules/fast-xml-parser/lib/fxbuilder.min.js +2 -0
- package/node_modules/fast-xml-parser/lib/fxbuilder.min.js.map +1 -0
- package/node_modules/fast-xml-parser/lib/fxp.cjs +1 -0
- package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/lib/fxp.d.cts +20 -12
- package/node_modules/fast-xml-parser/lib/fxp.min.js +2 -0
- package/node_modules/fast-xml-parser/lib/fxp.min.js.map +1 -0
- package/node_modules/fast-xml-parser/lib/fxparser.min.js +2 -0
- package/node_modules/fast-xml-parser/lib/fxparser.min.js.map +1 -0
- package/node_modules/fast-xml-parser/lib/pem.d.cts +148 -0
- package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/package.json +3 -3
- package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/fxp.d.ts +13 -11
- package/node_modules/fast-xml-parser/src/pem.d.ts +135 -0
- package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlparser/DocTypeReader.js +26 -17
- package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlparser/OptionsBuilder.js +6 -6
- package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlparser/OrderedObjParser.js +22 -16
- package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlparser/XMLParser.js +2 -2
- package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlparser/node2json.js +10 -11
- package/node_modules/path-expression-matcher/README.md +98 -13
- package/node_modules/path-expression-matcher/lib/pem.cjs +1 -1
- package/node_modules/path-expression-matcher/lib/pem.d.cts +188 -0
- package/node_modules/path-expression-matcher/lib/pem.min.js +1 -1
- package/node_modules/path-expression-matcher/lib/pem.min.js.map +1 -1
- package/node_modules/path-expression-matcher/package.json +2 -2
- package/node_modules/path-expression-matcher/src/Matcher.js +84 -0
- package/node_modules/path-expression-matcher/src/index.d.ts +152 -0
- package/package.json +2 -2
- package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxbuilder.min.js +0 -2
- package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxbuilder.min.js.map +0 -1
- package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxp.cjs +0 -1
- package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxp.min.js +0 -2
- package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxp.min.js.map +0 -1
- package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxparser.min.js +0 -2
- package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxparser.min.js.map +0 -1
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/LICENSE +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/README.md +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/lib/fxvalidator.min.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/lib/fxvalidator.min.js.map +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/cli/cli.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/cli/man.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/cli/read.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/fxp.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/ignoreAttributes.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/util.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/CharsSymbol.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/EntitiesParser.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/OptionsBuilder.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/OutputBuilders/BaseOutputBuilder.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/OutputBuilders/JsArrBuilder.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/OutputBuilders/JsMinArrBuilder.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/OutputBuilders/JsObjBuilder.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/OutputBuilders/ParserOptionsBuilder.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/Report.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/TagPath.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/TagPathMatcher.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/XMLParser.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/Xml2JsParser.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/XmlPartReader.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/XmlSpecialTagsReader.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/inputSource/BufferSource.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/inputSource/StringSource.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/EntitiesParser.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/booleanParser.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/booleanParserExt.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/currency.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/join.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/number.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/trim.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/validator.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlbuilder/json2xml.js +0 -0
- /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlparser/xmlNode.js +0 -0
|
@@ -113,6 +113,10 @@ export default class OrderedObjParser {
|
|
|
113
113
|
// Initialize path matcher for path-expression-matcher
|
|
114
114
|
this.matcher = new Matcher();
|
|
115
115
|
|
|
116
|
+
// Live read-only proxy of matcher — PEM creates and caches this internally.
|
|
117
|
+
// All user callbacks receive this instead of the mutable matcher.
|
|
118
|
+
this.readonlyMatcher = this.matcher.readOnly();
|
|
119
|
+
|
|
116
120
|
// Flag to track if current node is a stop node (optimization)
|
|
117
121
|
this.isCurrentNodeStopNode = false;
|
|
118
122
|
|
|
@@ -225,7 +229,7 @@ function buildAttributesMap(attrStr, jPath, tagName) {
|
|
|
225
229
|
if (this.options.trimValues) {
|
|
226
230
|
parsedVal = parsedVal.trim();
|
|
227
231
|
}
|
|
228
|
-
parsedVal = this.replaceEntitiesValue(parsedVal, tagName,
|
|
232
|
+
parsedVal = this.replaceEntitiesValue(parsedVal, tagName, this.readonlyMatcher);
|
|
229
233
|
rawAttrsForMatcher[attrName] = parsedVal;
|
|
230
234
|
}
|
|
231
235
|
}
|
|
@@ -240,7 +244,7 @@ function buildAttributesMap(attrStr, jPath, tagName) {
|
|
|
240
244
|
const attrName = this.resolveNameSpace(matches[i][1]);
|
|
241
245
|
|
|
242
246
|
// Convert jPath to string if needed for ignoreAttributesFn
|
|
243
|
-
const jPathStr = this.options.jPath ? jPath.toString() :
|
|
247
|
+
const jPathStr = this.options.jPath ? jPath.toString() : this.readonlyMatcher;
|
|
244
248
|
if (this.ignoreAttributesFn(attrName, jPathStr)) {
|
|
245
249
|
continue
|
|
246
250
|
}
|
|
@@ -259,10 +263,10 @@ function buildAttributesMap(attrStr, jPath, tagName) {
|
|
|
259
263
|
if (this.options.trimValues) {
|
|
260
264
|
oldVal = oldVal.trim();
|
|
261
265
|
}
|
|
262
|
-
oldVal = this.replaceEntitiesValue(oldVal, tagName,
|
|
266
|
+
oldVal = this.replaceEntitiesValue(oldVal, tagName, this.readonlyMatcher);
|
|
263
267
|
|
|
264
|
-
// Pass jPath string or
|
|
265
|
-
const jPathOrMatcher = this.options.jPath ? jPath.toString() :
|
|
268
|
+
// Pass jPath string or readonlyMatcher based on options.jPath setting
|
|
269
|
+
const jPathOrMatcher = this.options.jPath ? jPath.toString() : this.readonlyMatcher;
|
|
266
270
|
const newVal = this.options.attributeValueProcessor(attrName, oldVal, jPathOrMatcher);
|
|
267
271
|
if (newVal === null || newVal === undefined) {
|
|
268
272
|
//don't parse
|
|
@@ -329,7 +333,7 @@ const parseXml = function (xmlData) {
|
|
|
329
333
|
tagName = transformTagName(this.options.transformTagName, tagName, "", this.options).tagName;
|
|
330
334
|
|
|
331
335
|
if (currentNode) {
|
|
332
|
-
textData = this.saveTextToParentTag(textData, currentNode, this.
|
|
336
|
+
textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
|
|
333
337
|
}
|
|
334
338
|
|
|
335
339
|
//check if last tag of nested tag was unpaired tag
|
|
@@ -354,7 +358,7 @@ const parseXml = function (xmlData) {
|
|
|
354
358
|
let tagData = readTagExp(xmlData, i, false, "?>");
|
|
355
359
|
if (!tagData) throw new Error("Pi Tag is not closed.");
|
|
356
360
|
|
|
357
|
-
textData = this.saveTextToParentTag(textData, currentNode, this.
|
|
361
|
+
textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
|
|
358
362
|
if ((this.options.ignoreDeclaration && tagData.tagName === "?xml") || this.options.ignorePiTags) {
|
|
359
363
|
//do nothing
|
|
360
364
|
} else {
|
|
@@ -365,7 +369,7 @@ const parseXml = function (xmlData) {
|
|
|
365
369
|
if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent) {
|
|
366
370
|
childNode[":@"] = this.buildAttributesMap(tagData.tagExp, this.matcher, tagData.tagName);
|
|
367
371
|
}
|
|
368
|
-
this.addChild(currentNode, childNode, this.
|
|
372
|
+
this.addChild(currentNode, childNode, this.readonlyMatcher, i);
|
|
369
373
|
}
|
|
370
374
|
|
|
371
375
|
|
|
@@ -375,7 +379,7 @@ const parseXml = function (xmlData) {
|
|
|
375
379
|
if (this.options.commentPropName) {
|
|
376
380
|
const comment = xmlData.substring(i + 4, endIndex - 2);
|
|
377
381
|
|
|
378
|
-
textData = this.saveTextToParentTag(textData, currentNode, this.
|
|
382
|
+
textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
|
|
379
383
|
|
|
380
384
|
currentNode.add(this.options.commentPropName, [{ [this.options.textNodeName]: comment }]);
|
|
381
385
|
}
|
|
@@ -388,9 +392,9 @@ const parseXml = function (xmlData) {
|
|
|
388
392
|
const closeIndex = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2;
|
|
389
393
|
const tagExp = xmlData.substring(i + 9, closeIndex);
|
|
390
394
|
|
|
391
|
-
textData = this.saveTextToParentTag(textData, currentNode, this.
|
|
395
|
+
textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
|
|
392
396
|
|
|
393
|
-
let val = this.parseTextData(tagExp, currentNode.tagname, this.
|
|
397
|
+
let val = this.parseTextData(tagExp, currentNode.tagname, this.readonlyMatcher, true, false, true, true);
|
|
394
398
|
if (val == undefined) val = "";
|
|
395
399
|
|
|
396
400
|
//cdata should be set even if it is 0 length string
|
|
@@ -422,6 +426,8 @@ const parseXml = function (xmlData) {
|
|
|
422
426
|
if (this.options.strictReservedNames &&
|
|
423
427
|
(tagName === this.options.commentPropName
|
|
424
428
|
|| tagName === this.options.cdataPropName
|
|
429
|
+
|| tagName === this.options.textNodeName
|
|
430
|
+
|| tagName === this.options.attributesGroupName
|
|
425
431
|
)) {
|
|
426
432
|
throw new Error(`Invalid tag name: ${tagName}`);
|
|
427
433
|
}
|
|
@@ -430,7 +436,7 @@ const parseXml = function (xmlData) {
|
|
|
430
436
|
if (currentNode && textData) {
|
|
431
437
|
if (currentNode.tagname !== '!xml') {
|
|
432
438
|
//when nested tag is found
|
|
433
|
-
textData = this.saveTextToParentTag(textData, currentNode, this.
|
|
439
|
+
textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher, false);
|
|
434
440
|
}
|
|
435
441
|
}
|
|
436
442
|
|
|
@@ -520,7 +526,7 @@ const parseXml = function (xmlData) {
|
|
|
520
526
|
this.matcher.pop(); // Pop the stop node tag
|
|
521
527
|
this.isCurrentNodeStopNode = false; // Reset flag
|
|
522
528
|
|
|
523
|
-
this.addChild(currentNode, childNode, this.
|
|
529
|
+
this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
|
|
524
530
|
} else {
|
|
525
531
|
//selfClosing tag
|
|
526
532
|
if (isSelfClosing) {
|
|
@@ -530,7 +536,7 @@ const parseXml = function (xmlData) {
|
|
|
530
536
|
if (prefixedAttrs) {
|
|
531
537
|
childNode[":@"] = prefixedAttrs;
|
|
532
538
|
}
|
|
533
|
-
this.addChild(currentNode, childNode, this.
|
|
539
|
+
this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
|
|
534
540
|
this.matcher.pop(); // Pop self-closing tag
|
|
535
541
|
this.isCurrentNodeStopNode = false; // Reset flag
|
|
536
542
|
}
|
|
@@ -539,7 +545,7 @@ const parseXml = function (xmlData) {
|
|
|
539
545
|
if (prefixedAttrs) {
|
|
540
546
|
childNode[":@"] = prefixedAttrs;
|
|
541
547
|
}
|
|
542
|
-
this.addChild(currentNode, childNode, this.
|
|
548
|
+
this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
|
|
543
549
|
this.matcher.pop(); // Pop unpaired tag
|
|
544
550
|
this.isCurrentNodeStopNode = false; // Reset flag
|
|
545
551
|
i = result.closeIndex;
|
|
@@ -557,7 +563,7 @@ const parseXml = function (xmlData) {
|
|
|
557
563
|
if (prefixedAttrs) {
|
|
558
564
|
childNode[":@"] = prefixedAttrs;
|
|
559
565
|
}
|
|
560
|
-
this.addChild(currentNode, childNode, this.
|
|
566
|
+
this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
|
|
561
567
|
currentNode = childNode;
|
|
562
568
|
}
|
|
563
569
|
textData = "";
|
|
@@ -35,7 +35,7 @@ export default class XMLParser {
|
|
|
35
35
|
orderedObjParser.addExternalEntities(this.externalEntities);
|
|
36
36
|
const orderedResult = orderedObjParser.parseXml(xmlData);
|
|
37
37
|
if (this.options.preserveOrder || orderedResult === undefined) return orderedResult;
|
|
38
|
-
else return prettify(orderedResult, this.options, orderedObjParser.matcher);
|
|
38
|
+
else return prettify(orderedResult, this.options, orderedObjParser.matcher, orderedObjParser.readonlyMatcher);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
/**
|
|
@@ -68,4 +68,4 @@ export default class XMLParser {
|
|
|
68
68
|
static getMetaDataSymbol() {
|
|
69
69
|
return XmlNode.getMetaDataSymbol();
|
|
70
70
|
}
|
|
71
|
-
}
|
|
71
|
+
}
|
|
@@ -35,18 +35,17 @@ function stripAttributePrefix(attrs, prefix) {
|
|
|
35
35
|
* @param {Matcher} matcher - Path matcher instance
|
|
36
36
|
* @returns
|
|
37
37
|
*/
|
|
38
|
-
export default function prettify(node, options, matcher) {
|
|
39
|
-
return compress(node, options, matcher);
|
|
38
|
+
export default function prettify(node, options, matcher, readonlyMatcher) {
|
|
39
|
+
return compress(node, options, matcher, readonlyMatcher);
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
/**
|
|
43
|
-
*
|
|
44
43
|
* @param {array} arr
|
|
45
44
|
* @param {object} options
|
|
46
45
|
* @param {Matcher} matcher - Path matcher instance
|
|
47
46
|
* @returns object
|
|
48
47
|
*/
|
|
49
|
-
function compress(arr, options, matcher) {
|
|
48
|
+
function compress(arr, options, matcher, readonlyMatcher) {
|
|
50
49
|
let text;
|
|
51
50
|
const compressedObj = {}; //This is intended to be a plain object
|
|
52
51
|
for (let i = 0; i < arr.length; i++) {
|
|
@@ -69,11 +68,11 @@ function compress(arr, options, matcher) {
|
|
|
69
68
|
continue;
|
|
70
69
|
} else if (tagObj[property]) {
|
|
71
70
|
|
|
72
|
-
let val = compress(tagObj[property], options, matcher);
|
|
71
|
+
let val = compress(tagObj[property], options, matcher, readonlyMatcher);
|
|
73
72
|
const isLeaf = isLeafTag(val, options);
|
|
74
73
|
|
|
75
74
|
if (tagObj[":@"]) {
|
|
76
|
-
assignAttributes(val, tagObj[":@"],
|
|
75
|
+
assignAttributes(val, tagObj[":@"], readonlyMatcher, options);
|
|
77
76
|
} else if (Object.keys(val).length === 1 && val[options.textNodeName] !== undefined && !options.alwaysCreateTextNode) {
|
|
78
77
|
val = val[options.textNodeName];
|
|
79
78
|
} else if (Object.keys(val).length === 0) {
|
|
@@ -95,8 +94,8 @@ function compress(arr, options, matcher) {
|
|
|
95
94
|
//TODO: if a node is not an array, then check if it should be an array
|
|
96
95
|
//also determine if it is a leaf node
|
|
97
96
|
|
|
98
|
-
// Pass jPath string or
|
|
99
|
-
const jPathOrMatcher = options.jPath ?
|
|
97
|
+
// Pass jPath string or readonlyMatcher based on options.jPath setting
|
|
98
|
+
const jPathOrMatcher = options.jPath ? readonlyMatcher.toString() : readonlyMatcher;
|
|
100
99
|
if (options.isArray(property, jPathOrMatcher, isLeaf)) {
|
|
101
100
|
compressedObj[property] = [val];
|
|
102
101
|
} else {
|
|
@@ -128,7 +127,7 @@ function propName(obj) {
|
|
|
128
127
|
}
|
|
129
128
|
}
|
|
130
129
|
|
|
131
|
-
function assignAttributes(obj, attrMap,
|
|
130
|
+
function assignAttributes(obj, attrMap, readonlyMatcher, options) {
|
|
132
131
|
if (attrMap) {
|
|
133
132
|
const keys = Object.keys(attrMap);
|
|
134
133
|
const len = keys.length; //don't make it inline
|
|
@@ -143,8 +142,8 @@ function assignAttributes(obj, attrMap, matcher, options) {
|
|
|
143
142
|
// For attributes, we need to create a temporary path
|
|
144
143
|
// Pass jPath string or matcher based on options.jPath setting
|
|
145
144
|
const jPathOrMatcher = options.jPath
|
|
146
|
-
?
|
|
147
|
-
:
|
|
145
|
+
? readonlyMatcher.toString() + "." + rawAttrName
|
|
146
|
+
: readonlyMatcher;
|
|
148
147
|
|
|
149
148
|
if (options.isArray(atrrName, jPathOrMatcher, true, true)) {
|
|
150
149
|
obj[atrrName] = [attrMap[atrrName]];
|
|
@@ -346,6 +346,57 @@ Restore from a snapshot.
|
|
|
346
346
|
matcher.restore(snapshot);
|
|
347
347
|
```
|
|
348
348
|
|
|
349
|
+
#### Read-Only Access
|
|
350
|
+
|
|
351
|
+
##### `readOnly()`
|
|
352
|
+
|
|
353
|
+
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`.
|
|
354
|
+
|
|
355
|
+
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.
|
|
356
|
+
|
|
357
|
+
```javascript
|
|
358
|
+
const ro = matcher.readOnly();
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
**What works on the read-only view:**
|
|
362
|
+
|
|
363
|
+
```javascript
|
|
364
|
+
ro.matches(expr) // ✓ pattern matching
|
|
365
|
+
ro.getCurrentTag() // ✓ current tag name
|
|
366
|
+
ro.getCurrentNamespace() // ✓ current namespace
|
|
367
|
+
ro.getAttrValue("id") // ✓ attribute value
|
|
368
|
+
ro.hasAttr("id") // ✓ attribute presence check
|
|
369
|
+
ro.getPosition() // ✓ sibling position
|
|
370
|
+
ro.getCounter() // ✓ occurrence counter
|
|
371
|
+
ro.getDepth() // ✓ path depth
|
|
372
|
+
ro.toString() // ✓ path as string
|
|
373
|
+
ro.toArray() // ✓ path as array
|
|
374
|
+
ro.snapshot() // ✓ snapshot (can be used to restore the real matcher)
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
**What throws a `TypeError`:**
|
|
378
|
+
|
|
379
|
+
```javascript
|
|
380
|
+
ro.push("child", {}) // ✗ TypeError: Cannot call 'push' on a read-only Matcher
|
|
381
|
+
ro.pop() // ✗ TypeError: Cannot call 'pop' on a read-only Matcher
|
|
382
|
+
ro.reset() // ✗ TypeError: Cannot call 'reset' on a read-only Matcher
|
|
383
|
+
ro.updateCurrent({}) // ✗ TypeError: Cannot call 'updateCurrent' on a read-only Matcher
|
|
384
|
+
ro.restore(snapshot) // ✗ TypeError: Cannot call 'restore' on a read-only Matcher
|
|
385
|
+
ro.separator = '/' // ✗ TypeError: Cannot set property on a read-only Matcher
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
**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()`.
|
|
389
|
+
|
|
390
|
+
```javascript
|
|
391
|
+
const matcher = new Matcher();
|
|
392
|
+
const ro = matcher.readOnly();
|
|
393
|
+
|
|
394
|
+
matcher.push("root");
|
|
395
|
+
ro.getDepth(); // 1 — immediately reflects the push
|
|
396
|
+
matcher.push("users");
|
|
397
|
+
ro.getDepth(); // 2 — still live
|
|
398
|
+
```
|
|
399
|
+
|
|
349
400
|
## 💡 Usage Examples
|
|
350
401
|
|
|
351
402
|
### Example 1: XML Parser with stopNodes
|
|
@@ -481,7 +532,53 @@ const expr = new Expression("root.item:first");
|
|
|
481
532
|
console.log(matcher.matches(expr)); // false (counter=1, not 0)
|
|
482
533
|
```
|
|
483
534
|
|
|
484
|
-
### Example
|
|
535
|
+
### Example 8: Passing a Read-Only Matcher to External Consumers
|
|
536
|
+
|
|
537
|
+
When passing the matcher into callbacks, plugins, or other code you don't control, use `readOnly()` to prevent accidental state corruption.
|
|
538
|
+
|
|
539
|
+
```javascript
|
|
540
|
+
import { Expression, Matcher } from 'path-expression-matcher';
|
|
541
|
+
|
|
542
|
+
const matcher = new Matcher();
|
|
543
|
+
|
|
544
|
+
const adminExpr = new Expression("..user[type=admin]");
|
|
545
|
+
|
|
546
|
+
function parseTag(tagName, attrs, onTag) {
|
|
547
|
+
matcher.push(tagName, attrs);
|
|
548
|
+
|
|
549
|
+
// Pass a read-only view — consumer can inspect but not mutate
|
|
550
|
+
onTag(matcher.readOnly());
|
|
551
|
+
|
|
552
|
+
matcher.pop();
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
// Safe consumer — can only read
|
|
556
|
+
function myPlugin(ro) {
|
|
557
|
+
if (ro.matches(adminExpr)) {
|
|
558
|
+
console.log("Admin at path:", ro.toString());
|
|
559
|
+
console.log("Depth:", ro.getDepth());
|
|
560
|
+
console.log("ID:", ro.getAttrValue("id"));
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// ro.push(...) or ro.reset() here would throw TypeError,
|
|
565
|
+
// so the parser's state is always safe.
|
|
566
|
+
parseTag("user", { id: "1", type: "admin" }, myPlugin);
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
**Combining with `snapshot()`:** A snapshot taken via the read-only view can still be used to restore the real matcher.
|
|
570
|
+
|
|
571
|
+
```javascript
|
|
572
|
+
const matcher = new Matcher();
|
|
573
|
+
matcher.push("root");
|
|
574
|
+
matcher.push("users");
|
|
575
|
+
|
|
576
|
+
const ro = matcher.readOnly();
|
|
577
|
+
const snap = ro.snapshot(); // ✓ snapshot works on read-only view
|
|
578
|
+
|
|
579
|
+
matcher.push("user"); // continue parsing...
|
|
580
|
+
matcher.restore(snap); // restore to "root.users" using the snapshot
|
|
581
|
+
```
|
|
485
582
|
|
|
486
583
|
```javascript
|
|
487
584
|
const matcher = new Matcher();
|
|
@@ -614,18 +711,6 @@ const parser = new XMLParser({
|
|
|
614
711
|
});
|
|
615
712
|
```
|
|
616
713
|
|
|
617
|
-
## 🧪 Testing
|
|
618
|
-
|
|
619
|
-
```bash
|
|
620
|
-
npm test
|
|
621
|
-
```
|
|
622
|
-
|
|
623
|
-
All 77 tests covering:
|
|
624
|
-
- Pattern parsing (exact, wildcards, attributes, position)
|
|
625
|
-
- Path tracking (push, pop, update)
|
|
626
|
-
- Pattern matching (all combinations)
|
|
627
|
-
- Edge cases and error conditions
|
|
628
|
-
|
|
629
714
|
## 📄 License
|
|
630
715
|
|
|
631
716
|
MIT
|
|
@@ -1 +1 @@
|
|
|
1
|
-
(()=>{"use strict";var t={d:(e,s)=>{for(var
|
|
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,Matcher:()=>i,default:()=>r});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=[]}push(t,e=null,s=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;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;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;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.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}snapshot(){return{path:this.path.map(t=>({...t})),siblingStacks:this.siblingStacks.map(t=>new Map(t))}}restore(t){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.`)};const i=Reflect.get(t,e,s);return"path"===e||"siblingStacks"===e?Object.freeze(Array.isArray(i)?i.map(t=>t instanceof Map?Object.freeze(new Map(t)):Object.freeze({...t})):i):"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.`)}})}}const r={Expression:s,Matcher:i};module.exports=e})();
|
|
@@ -69,6 +69,17 @@ declare interface Segment {
|
|
|
69
69
|
* const { Expression } = require('path-expression-matcher');
|
|
70
70
|
* const expr = new Expression("root.users.user");
|
|
71
71
|
* const expr2 = new Expression("..user[id]:first");
|
|
72
|
+
* const expr3 = new Expression("root/users/user", { separator: '/' });
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* Pattern Syntax:
|
|
76
|
+
* - `root.users.user` - Match exact path
|
|
77
|
+
* - `..user` - Match "user" at any depth (deep wildcard)
|
|
78
|
+
* - `user[id]` - Match user tag with "id" attribute
|
|
79
|
+
* - `user[id=123]` - Match user tag where id="123"
|
|
80
|
+
* - `user:first` - Match first occurrence of user tag
|
|
81
|
+
* - `ns::user` - Match user tag with namespace "ns"
|
|
82
|
+
* - `ns::user[id]:first` - Combine namespace, attribute, and position
|
|
72
83
|
* ```
|
|
73
84
|
*/
|
|
74
85
|
declare class Expression {
|
|
@@ -177,6 +188,153 @@ declare interface MatcherSnapshot {
|
|
|
177
188
|
siblingStacks: Map<string, number>[];
|
|
178
189
|
}
|
|
179
190
|
|
|
191
|
+
/**
|
|
192
|
+
* ReadOnlyMatcher - A safe, read-only view over a {@link Matcher} instance.
|
|
193
|
+
*
|
|
194
|
+
* Returned by {@link Matcher.readOnly}. Exposes all query and inspection
|
|
195
|
+
* methods but **throws a `TypeError`** if any state-mutating method is called
|
|
196
|
+
* (`push`, `pop`, `reset`, `updateCurrent`, `restore`). Direct property
|
|
197
|
+
* writes are also blocked.
|
|
198
|
+
*
|
|
199
|
+
* Pass this to consumers that only need to inspect or match the current path
|
|
200
|
+
* so they cannot accidentally corrupt the parser state.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```javascript
|
|
204
|
+
* const matcher = new Matcher();
|
|
205
|
+
* matcher.push("root", {});
|
|
206
|
+
* matcher.push("users", {});
|
|
207
|
+
* matcher.push("user", { id: "123" });
|
|
208
|
+
*
|
|
209
|
+
* const ro: ReadOnlyMatcher = matcher.readOnly();
|
|
210
|
+
*
|
|
211
|
+
* ro.matches(expr); // ✓ works
|
|
212
|
+
* ro.getCurrentTag(); // ✓ "user"
|
|
213
|
+
* ro.getDepth(); // ✓ 3
|
|
214
|
+
* ro.push("child", {}); // ✗ TypeError: Cannot call 'push' on a read-only Matcher
|
|
215
|
+
* ro.reset(); // ✗ TypeError: Cannot call 'reset' on a read-only Matcher
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
declare interface ReadOnlyMatcher {
|
|
219
|
+
/**
|
|
220
|
+
* Default path separator (read-only)
|
|
221
|
+
*/
|
|
222
|
+
readonly separator: string;
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Current path stack (each node is a frozen copy)
|
|
226
|
+
*/
|
|
227
|
+
readonly path: ReadonlyArray<Readonly<PathNode>>;
|
|
228
|
+
|
|
229
|
+
// ── Query methods ───────────────────────────────────────────────────────────
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Get current tag name
|
|
233
|
+
* @returns Current tag name or undefined if path is empty
|
|
234
|
+
*/
|
|
235
|
+
getCurrentTag(): string | undefined;
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Get current namespace
|
|
239
|
+
* @returns Current namespace or undefined if not present or path is empty
|
|
240
|
+
*/
|
|
241
|
+
getCurrentNamespace(): string | undefined;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Get current node's attribute value
|
|
245
|
+
* @param attrName - Attribute name
|
|
246
|
+
* @returns Attribute value or undefined
|
|
247
|
+
*/
|
|
248
|
+
getAttrValue(attrName: string): any;
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Check if current node has an attribute
|
|
252
|
+
* @param attrName - Attribute name
|
|
253
|
+
*/
|
|
254
|
+
hasAttr(attrName: string): boolean;
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Get current node's sibling position (child index in parent)
|
|
258
|
+
* @returns Position index or -1 if path is empty
|
|
259
|
+
*/
|
|
260
|
+
getPosition(): number;
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Get current node's repeat counter (occurrence count of this tag name)
|
|
264
|
+
* @returns Counter value or -1 if path is empty
|
|
265
|
+
*/
|
|
266
|
+
getCounter(): number;
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Get current node's sibling index (alias for getPosition for backward compatibility)
|
|
270
|
+
* @returns Index or -1 if path is empty
|
|
271
|
+
* @deprecated Use getPosition() or getCounter() instead
|
|
272
|
+
*/
|
|
273
|
+
getIndex(): number;
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Get current path depth
|
|
277
|
+
* @returns Number of nodes in the path
|
|
278
|
+
*/
|
|
279
|
+
getDepth(): number;
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* Get path as string
|
|
283
|
+
* @param separator - Optional separator (uses default if not provided)
|
|
284
|
+
* @param includeNamespace - Whether to include namespace in output
|
|
285
|
+
* @returns Path string (e.g., "root.users.user" or "ns:root.ns:users.user")
|
|
286
|
+
*/
|
|
287
|
+
toString(separator?: string, includeNamespace?: boolean): string;
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Get path as array of tag names
|
|
291
|
+
* @returns Array of tag names
|
|
292
|
+
*/
|
|
293
|
+
toArray(): string[];
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Match current path against an Expression
|
|
297
|
+
* @param expression - The expression to match against
|
|
298
|
+
* @returns True if current path matches the expression
|
|
299
|
+
*/
|
|
300
|
+
matches(expression: Expression): boolean;
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Create a snapshot of current state
|
|
304
|
+
* @returns State snapshot that can be restored later
|
|
305
|
+
*/
|
|
306
|
+
snapshot(): MatcherSnapshot;
|
|
307
|
+
|
|
308
|
+
// ── Blocked mutating methods ────────────────────────────────────────────────
|
|
309
|
+
// These are present in the type so callers get a compile-time error with a
|
|
310
|
+
// helpful message instead of a silent "property does not exist" error.
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* @throws {TypeError} Always – mutation is not allowed on a read-only view.
|
|
314
|
+
*/
|
|
315
|
+
push(tagName: string, attrValues?: Record<string, any> | null, namespace?: string | null): never;
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* @throws {TypeError} Always – mutation is not allowed on a read-only view.
|
|
319
|
+
*/
|
|
320
|
+
pop(): never;
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* @throws {TypeError} Always – mutation is not allowed on a read-only view.
|
|
324
|
+
*/
|
|
325
|
+
updateCurrent(attrValues: Record<string, any>): never;
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* @throws {TypeError} Always – mutation is not allowed on a read-only view.
|
|
329
|
+
*/
|
|
330
|
+
reset(): never;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* @throws {TypeError} Always – mutation is not allowed on a read-only view.
|
|
334
|
+
*/
|
|
335
|
+
restore(snapshot: MatcherSnapshot): never;
|
|
336
|
+
}
|
|
337
|
+
|
|
180
338
|
/**
|
|
181
339
|
* Matcher - Tracks current path in XML/JSON tree and matches against Expressions
|
|
182
340
|
*
|
|
@@ -191,6 +349,12 @@ declare interface MatcherSnapshot {
|
|
|
191
349
|
* matcher.push("root", {});
|
|
192
350
|
* matcher.push("users", {});
|
|
193
351
|
* matcher.push("user", { id: "123", type: "admin" });
|
|
352
|
+
*
|
|
353
|
+
* const expr = new Expression("root.users.user");
|
|
354
|
+
* matcher.matches(expr); // true
|
|
355
|
+
*
|
|
356
|
+
* matcher.pop();
|
|
357
|
+
* matcher.matches(expr); // false
|
|
194
358
|
* ```
|
|
195
359
|
*/
|
|
196
360
|
declare class Matcher {
|
|
@@ -215,6 +379,13 @@ declare class Matcher {
|
|
|
215
379
|
* @param tagName - Name of the tag
|
|
216
380
|
* @param attrValues - Attribute key-value pairs for current node (optional)
|
|
217
381
|
* @param namespace - Namespace for the tag (optional)
|
|
382
|
+
*
|
|
383
|
+
* @example
|
|
384
|
+
* ```javascript
|
|
385
|
+
* matcher.push("user", { id: "123", type: "admin" });
|
|
386
|
+
* matcher.push("user", { id: "456" }, "ns");
|
|
387
|
+
* matcher.push("container", null);
|
|
388
|
+
* ```
|
|
218
389
|
*/
|
|
219
390
|
push(tagName: string, attrValues?: Record<string, any> | null, namespace?: string | null): void;
|
|
220
391
|
|
|
@@ -304,6 +475,18 @@ declare class Matcher {
|
|
|
304
475
|
* Match current path against an Expression
|
|
305
476
|
* @param expression - The expression to match against
|
|
306
477
|
* @returns True if current path matches the expression
|
|
478
|
+
*
|
|
479
|
+
* @example
|
|
480
|
+
* ```javascript
|
|
481
|
+
* const expr = new Expression("root.users.user[id]");
|
|
482
|
+
* const matcher = new Matcher();
|
|
483
|
+
*
|
|
484
|
+
* matcher.push("root");
|
|
485
|
+
* matcher.push("users");
|
|
486
|
+
* matcher.push("user", { id: "123" });
|
|
487
|
+
*
|
|
488
|
+
* matcher.matches(expr); // true
|
|
489
|
+
* ```
|
|
307
490
|
*/
|
|
308
491
|
matches(expression: Expression): boolean;
|
|
309
492
|
|
|
@@ -318,6 +501,11 @@ declare class Matcher {
|
|
|
318
501
|
* @param snapshot - State snapshot from previous snapshot() call
|
|
319
502
|
*/
|
|
320
503
|
restore(snapshot: MatcherSnapshot): void;
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Return a read-only view of this matcher.
|
|
507
|
+
*/
|
|
508
|
+
readOnly(): ReadOnlyMatcher;
|
|
321
509
|
}
|
|
322
510
|
|
|
323
511
|
declare namespace pathExpressionMatcher {
|
|
@@ -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
|
|
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,Matcher:()=>i,default:()=>r});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=[]}push(t,e=null,s=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;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;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;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.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}snapshot(){return{path:this.path.map(t=>({...t})),siblingStacks:this.siblingStacks.map(t=>new Map(t))}}restore(t){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.`)};const i=Reflect.get(t,e,s);return"path"===e||"siblingStacks"===e?Object.freeze(Array.isArray(i)?i.map(t=>t instanceof Map?Object.freeze(new Map(t)):Object.freeze({...t})):i):"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.`)}})}}const r={Expression:s,Matcher:i};return e})());
|
|
2
2
|
//# sourceMappingURL=pem.min.js.map
|