clarity-pattern-parser 11.0.26 → 11.0.28

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -850,10 +850,11 @@ class Reference {
850
850
  get startedOnIndex() {
851
851
  return this._firstIndex;
852
852
  }
853
- constructor(name) {
853
+ constructor(name, referencePatternName) {
854
854
  this._id = `reference-${idIndex$7++}`;
855
855
  this._type = "reference";
856
856
  this._name = name;
857
+ this._referencePatternName = referencePatternName || name;
857
858
  this._parent = null;
858
859
  this._pattern = null;
859
860
  this._cachedPattern = null;
@@ -912,9 +913,9 @@ class Reference {
912
913
  pattern = this._cachedPattern;
913
914
  }
914
915
  if (pattern === null) {
915
- throw new Error(`Couldn't find '${this._name}' pattern within tree.`);
916
+ throw new Error(`Couldn't find '${this._referencePatternName}' pattern within tree.`);
916
917
  }
917
- const clonedPattern = pattern.clone();
918
+ const clonedPattern = pattern.clone(this._name);
918
919
  clonedPattern.parent = this;
919
920
  this._pattern = clonedPattern;
920
921
  this._children = [this._pattern];
@@ -928,7 +929,7 @@ class Reference {
928
929
  pattern = pattern.parent;
929
930
  continue;
930
931
  }
931
- const foundPattern = pattern.getPatternWithinContext(this.name);
932
+ const foundPattern = pattern.getPatternWithinContext(this._referencePatternName);
932
933
  if (foundPattern != null && this._isValidPattern(foundPattern)) {
933
934
  return foundPattern;
934
935
  }
@@ -936,7 +937,7 @@ class Reference {
936
937
  }
937
938
  const root = this._getRoot();
938
939
  return findPattern(root, (pattern) => {
939
- return pattern.name === this._name && this._isValidPattern(pattern);
940
+ return pattern.name === this._referencePatternName && this._isValidPattern(pattern);
940
941
  });
941
942
  }
942
943
  _isValidPattern(pattern) {
@@ -995,7 +996,7 @@ class Reference {
995
996
  return null;
996
997
  }
997
998
  clone(name = this._name) {
998
- const clone = new Reference(name);
999
+ const clone = new Reference(name, this._referencePatternName);
999
1000
  clone._id = this._id;
1000
1001
  // Optimize future clones, by caching the pattern we already found.
1001
1002
  if (this._pattern != null) {
@@ -1617,6 +1618,12 @@ class Repeat {
1617
1618
  get startedOnIndex() {
1618
1619
  return this._repeatPattern.startedOnIndex;
1619
1620
  }
1621
+ get pattern() {
1622
+ return this._pattern;
1623
+ }
1624
+ get options() {
1625
+ return this._options;
1626
+ }
1620
1627
  constructor(name, pattern, options = {}) {
1621
1628
  this._id = `repeat-${idIndex$3++}`;
1622
1629
  this._pattern = pattern;
@@ -2678,6 +2685,9 @@ class Expression {
2678
2685
  get binaryPatterns() {
2679
2686
  return this._binaryPatterns;
2680
2687
  }
2688
+ get originalPatterns() {
2689
+ return this._originalPatterns;
2690
+ }
2681
2691
  get startedOnIndex() {
2682
2692
  return this._firstIndex;
2683
2693
  }
@@ -3589,8 +3599,8 @@ class Grammar {
3589
3599
  const aliasPattern = this._getPattern(aliasName);
3590
3600
  // This solves the problem for an alias pointing to a reference.
3591
3601
  if (aliasPattern.type === "reference") {
3592
- const sequence = new Sequence(name, [aliasPattern]);
3593
- this._parseContext.patternsByName.set(name, sequence);
3602
+ const reference = new Reference(name, aliasName);
3603
+ this._parseContext.patternsByName.set(name, reference);
3594
3604
  }
3595
3605
  else {
3596
3606
  const alias = aliasPattern.clone(name);
@@ -3858,6 +3868,435 @@ function patterns(strings, ...values) {
3858
3868
  return result;
3859
3869
  }
3860
3870
 
3871
+ const { expression } = patterns `
3872
+ number = /[+-]?(\\d+(\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?/
3873
+ spaces = /\\s+/
3874
+ single-quote-string-literal = /'(?:\\\\.|[^'\\\\])*'/
3875
+ name = /[a-zA-Z_-]+[a-zA-Z0-9_-]*/
3876
+ comma = /\\s*,\\s*/
3877
+ wild-card = "*"
3878
+ equal = "="
3879
+ not-equal = "!="
3880
+ starts-with = "^="
3881
+ ends-with = "$="
3882
+ contains = "*="
3883
+ greater-than-or-equal = ">="
3884
+ less-than-or-equal = "<="
3885
+ greater-than = ">"
3886
+ less-than = "<"
3887
+ operators = equal |
3888
+ not-equal |
3889
+ starts-with |
3890
+ ends-with |
3891
+ contains |
3892
+ greater-than-or-equal |
3893
+ less-than-or-equal |
3894
+ greater-than |
3895
+ less-than
3896
+
3897
+ attribute-name = name
3898
+ value = name
3899
+ attribute-value = single-quote-string-literal | number | value
3900
+ attribute-selector = "[" + spaces? + attribute-name + spaces? + operators + spaces? + attribute-value + "]"
3901
+
3902
+ adjacent = spaces? + "+" + spaces?
3903
+ after = spaces? + "~" + spaces?
3904
+ direct-child = spaces? + ">" + spaces?
3905
+ descendant = spaces
3906
+
3907
+ combinators = adjacent | after | direct-child | descendant
3908
+ name-selector = name-selector-expression + attribute-selector
3909
+ name-selector-expression = name-selector | name
3910
+ node-selector = wild-card | attribute-selector | name-selector-expression
3911
+ or-selector = (node-selector, comma){2}
3912
+
3913
+ selector-expression = expression + combinators + expression
3914
+ expression = selector-expression | or-selector | node-selector
3915
+ `;
3916
+ const selectorParser = expression;
3917
+
3918
+ const combinatorMap = {
3919
+ "adjacent": true,
3920
+ "after": true,
3921
+ "descendant": true,
3922
+ "direct-child": true
3923
+ };
3924
+ const operatorMap = {
3925
+ "equal": true,
3926
+ "not-equal": true,
3927
+ "starts-with": true,
3928
+ "ends-with": true,
3929
+ "contains": true,
3930
+ "greater-than-or-equal": true,
3931
+ "less-than-or-equal": true,
3932
+ "greater-than": true,
3933
+ "less-than": true
3934
+ };
3935
+ class Selector {
3936
+ constructor(selector) {
3937
+ this._selectedNodes = [];
3938
+ this._combinator = null;
3939
+ const result = selectorParser.exec(selector);
3940
+ if (result.ast == null) {
3941
+ const message = generateErrorMessage(selectorParser, result.cursor);
3942
+ throw new Error(`[Invalid Selector] ${message}`);
3943
+ }
3944
+ this._selectorAst = result.ast;
3945
+ }
3946
+ find(nodes) {
3947
+ this._selectedNodes = nodes;
3948
+ const ast = this._selectorAst;
3949
+ ast.walkUp((node) => {
3950
+ this._process(node);
3951
+ });
3952
+ return this._selectedNodes;
3953
+ }
3954
+ filter(nodes) {
3955
+ if (nodes.length < 1) {
3956
+ return [];
3957
+ }
3958
+ const nodeMap = new Map();
3959
+ nodes.forEach(n => nodeMap.set(n, n));
3960
+ this._selectedNodes = [nodes[0].findRoot()];
3961
+ const ast = this._selectorAst;
3962
+ ast.walkUp((node) => {
3963
+ this._process(node);
3964
+ });
3965
+ return this._selectedNodes.filter(n => nodeMap.has(n));
3966
+ }
3967
+ not(nodes) {
3968
+ if (nodes.length < 1) {
3969
+ return [];
3970
+ }
3971
+ this._selectedNodes = [nodes[0].findRoot()];
3972
+ const ast = this._selectorAst;
3973
+ ast.walkUp((node) => {
3974
+ this._process(node);
3975
+ });
3976
+ const selectedNodeMap = new Map();
3977
+ this._selectedNodes.forEach(n => selectedNodeMap.set(n, n));
3978
+ return nodes.filter(n => !selectedNodeMap.has(n));
3979
+ }
3980
+ parents(nodes) {
3981
+ if (nodes.length < 1) {
3982
+ return [];
3983
+ }
3984
+ this._selectedNodes = [nodes[0].findRoot()];
3985
+ const ast = this._selectorAst;
3986
+ ast.walkUp((node) => {
3987
+ this._process(node);
3988
+ });
3989
+ const result = new Set();
3990
+ const ancestorMap = new Map();
3991
+ this._selectedNodes.forEach(n => ancestorMap.set(n, true));
3992
+ nodes.forEach(n => {
3993
+ const ancestor = n.findAncestor(a => ancestorMap.has(a));
3994
+ if (ancestor != null) {
3995
+ result.add(ancestor);
3996
+ }
3997
+ });
3998
+ return Array.from(result);
3999
+ }
4000
+ _process(ast) {
4001
+ const nodeName = ast.name;
4002
+ if (nodeName === "wild-card") {
4003
+ this._selectedNodes = this._processWildCard();
4004
+ }
4005
+ else if (nodeName === "or-selector") {
4006
+ this._selectedNodes = this._processOrSelector(ast);
4007
+ }
4008
+ else if (nodeName === "name-selector" || (nodeName === "name" && (ast.parent == null || ast.parent.name === "selector-expression"))) {
4009
+ this._selectedNodes = this._processNameSelector(ast);
4010
+ }
4011
+ else if (nodeName === "attribute-selector" && (ast.parent == null || ast.parent.name === "selector-expression")) {
4012
+ this._selectedNodes = this._processAttributeSelector(ast);
4013
+ }
4014
+ else if (combinatorMap[nodeName]) {
4015
+ this._combinator = nodeName;
4016
+ }
4017
+ else if (nodeName === "selector-expression") {
4018
+ this._combinator = null;
4019
+ }
4020
+ }
4021
+ _processWildCard() {
4022
+ return this._selectedNodes.map(n => {
4023
+ return this._selectWithCombinator(n, () => true);
4024
+ }).flat();
4025
+ }
4026
+ _processOrSelector(ast) {
4027
+ const selectorNodes = ast.children.filter(n => n.name !== "comma");
4028
+ const set = new Set();
4029
+ const selectors = selectorNodes.map(n => new Selector(n.toString()));
4030
+ selectors.map(s => {
4031
+ return s.find(this._selectedNodes.slice());
4032
+ }).flat().forEach((node) => {
4033
+ set.add(node);
4034
+ });
4035
+ return Array.from(set);
4036
+ }
4037
+ _processNameSelector(ast) {
4038
+ if (ast.children.length > 1) {
4039
+ return this._selectedNodes.map(n => {
4040
+ const name = ast.children[0].value;
4041
+ return this._selectWithCombinator(n, (node) => {
4042
+ return node.name === name && this._isAttributeMatch(node, ast);
4043
+ });
4044
+ }).flat();
4045
+ }
4046
+ else {
4047
+ return this._selectedNodes.map(n => {
4048
+ return this._selectWithCombinator(n, (node) => node.name === ast.value);
4049
+ }).flat();
4050
+ }
4051
+ }
4052
+ _processAttributeSelector(ast) {
4053
+ return this._selectedNodes.map(n => {
4054
+ return this._selectWithCombinator(n, (node) => {
4055
+ return this._isAttributeMatch(node, ast);
4056
+ });
4057
+ }).flat();
4058
+ }
4059
+ _selectWithCombinator(node, predicate) {
4060
+ if (this._combinator === "adjacent") {
4061
+ const sibling = node.nextSibling();
4062
+ if (sibling == null) {
4063
+ return [];
4064
+ }
4065
+ if (predicate(sibling)) {
4066
+ return [sibling];
4067
+ }
4068
+ else {
4069
+ return [];
4070
+ }
4071
+ }
4072
+ else if (this._combinator === "after") {
4073
+ const parent = node.parent;
4074
+ if (parent == null) {
4075
+ return [];
4076
+ }
4077
+ const index = parent.findChildIndex(node);
4078
+ const after = parent.children.slice(index + 1);
4079
+ return after.filter(predicate);
4080
+ }
4081
+ else if (this._combinator === "direct-child") {
4082
+ return node.children.filter(predicate);
4083
+ }
4084
+ else if (this._combinator === "descendant" || this._combinator == null) {
4085
+ return node.findAll(predicate);
4086
+ }
4087
+ else {
4088
+ return [];
4089
+ }
4090
+ }
4091
+ _isAttributeMatch(node, ast) {
4092
+ const name = this._getAttributeName(ast);
4093
+ const operator = this._getAttributeOperator(ast);
4094
+ const value = this._getAttributeValue(ast);
4095
+ const anyNode = node;
4096
+ if (anyNode[name] == null) {
4097
+ return false;
4098
+ }
4099
+ if (operator === "equal") {
4100
+ return anyNode[name] === value;
4101
+ }
4102
+ else if (operator === "not-equal") {
4103
+ return anyNode[name] !== value;
4104
+ }
4105
+ else if (operator === "starts-with") {
4106
+ return anyNode[name].toString().startsWith(value);
4107
+ }
4108
+ else if (operator === "ends-with") {
4109
+ return anyNode[name].toString().endsWith(value);
4110
+ }
4111
+ else if (operator === "contains") {
4112
+ return anyNode[name].toString().includes(value);
4113
+ }
4114
+ else if (operator === "greater-than-or-equal") {
4115
+ return anyNode[name] >= value;
4116
+ }
4117
+ else if (operator === "less-than-or-equal") {
4118
+ return anyNode[name] <= value;
4119
+ }
4120
+ else if (operator === "greater-than") {
4121
+ return anyNode[name] > value;
4122
+ }
4123
+ else if (operator === "less-than") {
4124
+ return anyNode[name] < value;
4125
+ }
4126
+ return false;
4127
+ }
4128
+ _getAttributeName(ast) {
4129
+ return ast.find(n => n.name === "attribute-name").value;
4130
+ }
4131
+ _getAttributeValue(ast) {
4132
+ let valueNode = ast.find(n => n.name === "single-quote-string-literal");
4133
+ if (valueNode != null) {
4134
+ return valueNode.value.slice(1, -1);
4135
+ }
4136
+ else {
4137
+ valueNode = ast.find(n => n.name === "value");
4138
+ }
4139
+ if (valueNode != null) {
4140
+ return valueNode.value;
4141
+ }
4142
+ else {
4143
+ valueNode = ast.find(n => n.name === "number");
4144
+ }
4145
+ return valueNode.value;
4146
+ }
4147
+ _getAttributeOperator(ast) {
4148
+ return ast.find(n => operatorMap[n.name]).name;
4149
+ }
4150
+ }
4151
+
4152
+ class Query {
4153
+ constructor(context, prevQuery = null) {
4154
+ this._context = context;
4155
+ this._prevQuery = prevQuery;
4156
+ }
4157
+ toArray() {
4158
+ return this._context.slice();
4159
+ }
4160
+ // Modifiers
4161
+ append(visitor) {
4162
+ this._context.forEach(n => {
4163
+ const parent = n.parent;
4164
+ if (parent == null) {
4165
+ return;
4166
+ }
4167
+ const newNode = visitor(n);
4168
+ n.appendChild(newNode);
4169
+ });
4170
+ return this;
4171
+ }
4172
+ prepend(visitor) {
4173
+ this._context.forEach(n => {
4174
+ const parent = n.parent;
4175
+ if (parent == null) {
4176
+ return;
4177
+ }
4178
+ const newNode = visitor(n);
4179
+ n.insertBefore(newNode, n.children[0]);
4180
+ });
4181
+ return this;
4182
+ }
4183
+ after(visitor) {
4184
+ this._context.forEach(n => {
4185
+ const parent = n.parent;
4186
+ if (parent == null) {
4187
+ return;
4188
+ }
4189
+ const index = parent.findChildIndex(n);
4190
+ const newNode = visitor(n);
4191
+ parent.spliceChildren(index + 1, 0, newNode);
4192
+ });
4193
+ return this;
4194
+ }
4195
+ before(visitor) {
4196
+ this._context.forEach(n => {
4197
+ const parent = n.parent;
4198
+ if (parent == null) {
4199
+ return;
4200
+ }
4201
+ const index = parent.findChildIndex(n);
4202
+ const newNode = visitor(n);
4203
+ parent.spliceChildren(index, 0, newNode);
4204
+ });
4205
+ return this;
4206
+ }
4207
+ replaceWith(visitor) {
4208
+ this._context.forEach(n => {
4209
+ const newNode = visitor(n);
4210
+ n.replaceWith(newNode);
4211
+ });
4212
+ return this;
4213
+ }
4214
+ compact() {
4215
+ this._context.forEach(n => {
4216
+ n.compact();
4217
+ });
4218
+ return this;
4219
+ }
4220
+ setValue(value) {
4221
+ this.replaceWith((n) => {
4222
+ return Node.createValueNode(n.type, n.name, value);
4223
+ });
4224
+ return this;
4225
+ }
4226
+ normalize() {
4227
+ const first = this._context[0];
4228
+ if (first != null) {
4229
+ first.findRoot().normalize();
4230
+ }
4231
+ }
4232
+ remove() {
4233
+ this._context.forEach(n => {
4234
+ n.remove();
4235
+ });
4236
+ return this;
4237
+ }
4238
+ // Filters from the currently matched nodes
4239
+ slice(start, end) {
4240
+ return new Query(this._context.slice(start, end));
4241
+ }
4242
+ filter(selectorString) {
4243
+ const selector = new Selector(selectorString);
4244
+ const newContext = selector.filter(this._context);
4245
+ return new Query(newContext, this);
4246
+ }
4247
+ // Selects out of all descedants of currently matched nodes
4248
+ find(selectorString) {
4249
+ const selector = new Selector(selectorString);
4250
+ const newContext = selector.find(this._context);
4251
+ return new Query(newContext, this);
4252
+ }
4253
+ // Remove nodes from the set of matched nodes.
4254
+ not(selectorString) {
4255
+ const selector = new Selector(selectorString);
4256
+ const newContext = selector.not(this._context);
4257
+ return new Query(newContext, this);
4258
+ }
4259
+ // Select the parent of currently matched nodes
4260
+ parent() {
4261
+ const parents = this._context.map(n => n.parent);
4262
+ const result = new Set();
4263
+ parents.forEach((n) => {
4264
+ if (n != null) {
4265
+ result.add(n);
4266
+ }
4267
+ });
4268
+ return new Query(Array.from(result), this);
4269
+ }
4270
+ // Select the ancestors of currently matched nodes
4271
+ parents(selectorString) {
4272
+ const selector = new Selector(selectorString);
4273
+ const newContext = selector.parents(this._context);
4274
+ const result = new Set();
4275
+ newContext.forEach((n) => {
4276
+ if (n != null) {
4277
+ result.add(n);
4278
+ }
4279
+ });
4280
+ return new Query(Array.from(result), this);
4281
+ }
4282
+ first() {
4283
+ return new Query(this._context.slice(0, 1), this);
4284
+ }
4285
+ last() {
4286
+ return new Query(this._context.slice(-1), this);
4287
+ }
4288
+ // Pop query stack
4289
+ end() {
4290
+ if (this._prevQuery) {
4291
+ return this._prevQuery;
4292
+ }
4293
+ return this;
4294
+ }
4295
+ length() {
4296
+ return this._context.length;
4297
+ }
4298
+ }
4299
+
3861
4300
  exports.AutoComplete = AutoComplete;
3862
4301
  exports.Context = Context;
3863
4302
  exports.Cursor = Cursor;
@@ -3870,10 +4309,12 @@ exports.Not = Not;
3870
4309
  exports.Optional = Optional;
3871
4310
  exports.Options = Options;
3872
4311
  exports.ParseError = ParseError;
4312
+ exports.Query = Query;
3873
4313
  exports.Reference = Reference;
3874
4314
  exports.Regex = Regex;
3875
4315
  exports.Repeat = Repeat;
3876
4316
  exports.RightAssociated = RightAssociated;
4317
+ exports.Selector = Selector;
3877
4318
  exports.Sequence = Sequence;
3878
4319
  exports.compact = compact;
3879
4320
  exports.grammar = grammar;