@herb-tools/core 0.7.4 → 0.8.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.
@@ -7,8 +7,16 @@
7
7
  class Position {
8
8
  line;
9
9
  column;
10
- static from(position) {
11
- return new Position(position.line, position.column);
10
+ static from(positionOrLine, column) {
11
+ if (typeof positionOrLine === "number") {
12
+ return new Position(positionOrLine, column);
13
+ }
14
+ else {
15
+ return new Position(positionOrLine.line, positionOrLine.column);
16
+ }
17
+ }
18
+ static get zero() {
19
+ return new Position(0, 0);
12
20
  }
13
21
  constructor(line, column) {
14
22
  this.line = line;
@@ -34,10 +42,20 @@
34
42
  class Location {
35
43
  start;
36
44
  end;
37
- static from(location) {
38
- const start = Position.from(location.start);
39
- const end = Position.from(location.end);
40
- return new Location(start, end);
45
+ static from(locationOrLine, column, endLine, endColumn) {
46
+ if (typeof locationOrLine === "number") {
47
+ const start = Position.from(locationOrLine, column);
48
+ const end = Position.from(endLine, endColumn);
49
+ return new Location(start, end);
50
+ }
51
+ else {
52
+ const start = Position.from(locationOrLine.start);
53
+ const end = Position.from(locationOrLine.end);
54
+ return new Location(start, end);
55
+ }
56
+ }
57
+ static get zero() {
58
+ return new Location(Position.zero, Position.zero);
41
59
  }
42
60
  constructor(start, end) {
43
61
  this.start = start;
@@ -69,8 +87,16 @@
69
87
  class Range {
70
88
  start;
71
89
  end;
72
- static from(range) {
73
- return new Range(range[0], range[1]);
90
+ static from(rangeOrStart, end) {
91
+ if (typeof rangeOrStart === "number") {
92
+ return new Range(rangeOrStart, end);
93
+ }
94
+ else {
95
+ return new Range(rangeOrStart[0], rangeOrStart[1]);
96
+ }
97
+ }
98
+ static get zero() {
99
+ return new Range(0, 0);
74
100
  }
75
101
  constructor(start, end) {
76
102
  this.start = start;
@@ -135,7 +161,7 @@
135
161
  }
136
162
 
137
163
  // NOTE: This file is generated by the templates/template.rb script and should not
138
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.7.4/templates/javascript/packages/core/src/errors.ts.erb
164
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.0/templates/javascript/packages/core/src/errors.ts.erb
139
165
  class HerbError {
140
166
  type;
141
167
  message;
@@ -560,6 +586,84 @@
560
586
  return output;
561
587
  }
562
588
  }
589
+ class ERBControlFlowScopeError extends HerbError {
590
+ keyword;
591
+ static from(data) {
592
+ return new ERBControlFlowScopeError({
593
+ type: data.type,
594
+ message: data.message,
595
+ location: Location.from(data.location),
596
+ keyword: data.keyword,
597
+ });
598
+ }
599
+ constructor(props) {
600
+ super(props.type, props.message, props.location);
601
+ this.keyword = props.keyword;
602
+ }
603
+ toJSON() {
604
+ return {
605
+ ...super.toJSON(),
606
+ type: "ERB_CONTROL_FLOW_SCOPE_ERROR",
607
+ keyword: this.keyword,
608
+ };
609
+ }
610
+ toMonacoDiagnostic() {
611
+ return {
612
+ line: this.location.start.line,
613
+ column: this.location.start.column,
614
+ endLine: this.location.end.line,
615
+ endColumn: this.location.end.column,
616
+ message: this.message,
617
+ severity: 'error'
618
+ };
619
+ }
620
+ treeInspect() {
621
+ let output = "";
622
+ output += `@ ERBControlFlowScopeError ${this.location.treeInspectWithLabel()}\n`;
623
+ output += `├── message: "${this.message}"\n`;
624
+ output += `└── keyword: ${JSON.stringify(this.keyword)}\n`;
625
+ return output;
626
+ }
627
+ }
628
+ class MissingERBEndTagError extends HerbError {
629
+ keyword;
630
+ static from(data) {
631
+ return new MissingERBEndTagError({
632
+ type: data.type,
633
+ message: data.message,
634
+ location: Location.from(data.location),
635
+ keyword: data.keyword,
636
+ });
637
+ }
638
+ constructor(props) {
639
+ super(props.type, props.message, props.location);
640
+ this.keyword = props.keyword;
641
+ }
642
+ toJSON() {
643
+ return {
644
+ ...super.toJSON(),
645
+ type: "MISSINGERB_END_TAG_ERROR",
646
+ keyword: this.keyword,
647
+ };
648
+ }
649
+ toMonacoDiagnostic() {
650
+ return {
651
+ line: this.location.start.line,
652
+ column: this.location.start.column,
653
+ endLine: this.location.end.line,
654
+ endColumn: this.location.end.column,
655
+ message: this.message,
656
+ severity: 'error'
657
+ };
658
+ }
659
+ treeInspect() {
660
+ let output = "";
661
+ output += `@ MissingERBEndTagError ${this.location.treeInspectWithLabel()}\n`;
662
+ output += `├── message: "${this.message}"\n`;
663
+ output += `└── keyword: ${JSON.stringify(this.keyword)}\n`;
664
+ return output;
665
+ }
666
+ }
563
667
  function fromSerializedError(error) {
564
668
  switch (error.type) {
565
669
  case "UNEXPECTED_ERROR": return UnexpectedError.from(error);
@@ -571,6 +675,8 @@
571
675
  case "VOID_ELEMENT_CLOSING_TAG_ERROR": return VoidElementClosingTagError.from(error);
572
676
  case "UNCLOSED_ELEMENT_ERROR": return UnclosedElementError.from(error);
573
677
  case "RUBY_PARSE_ERROR": return RubyParseError.from(error);
678
+ case "ERB_CONTROL_FLOW_SCOPE_ERROR": return ERBControlFlowScopeError.from(error);
679
+ case "MISSINGERB_END_TAG_ERROR": return MissingERBEndTagError.from(error);
574
680
  default:
575
681
  throw new Error(`Unknown node type: ${error.type}`);
576
682
  }
@@ -592,7 +698,7 @@
592
698
  }
593
699
 
594
700
  // NOTE: This file is generated by the templates/template.rb script and should not
595
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.7.4/templates/javascript/packages/core/src/nodes.ts.erb
701
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.0/templates/javascript/packages/core/src/nodes.ts.erb
596
702
  class Node {
597
703
  type;
598
704
  location;
@@ -2845,7 +2951,7 @@
2845
2951
  }
2846
2952
 
2847
2953
  // NOTE: This file is generated by the templates/template.rb script and should not
2848
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.7.4/templates/javascript/packages/core/src/node-type-guards.ts.erb
2954
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.0/templates/javascript/packages/core/src/node-type-guards.ts.erb
2849
2955
  /**
2850
2956
  * Type guard functions for AST nodes.
2851
2957
  * These functions provide type checking by combining both instanceof
@@ -3466,7 +3572,7 @@
3466
3572
  * Checks if a node is an ERB output node (generates content: <%= %> or <%== %>)
3467
3573
  */
3468
3574
  function isERBOutputNode(node) {
3469
- if (!isNode(node, ERBContentNode))
3575
+ if (!isERBNode(node))
3470
3576
  return false;
3471
3577
  if (!node.tag_opening?.value)
3472
3578
  return false;
@@ -3738,8 +3844,184 @@
3738
3844
  };
3739
3845
  }
3740
3846
 
3847
+ /*
3848
+ * The following code is derived from the "js-levenshtein" repository,
3849
+ * Copyright (c) 2017 Gustaf Andersson (https://github.com/gustf/js-levenshtein)
3850
+ * Licensed under the MIT License (https://github.com/gustf/js-levenshtein/blob/master/LICENSE).
3851
+ *
3852
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
3853
+ * of this software and associated documentation files (the "Software"), to deal
3854
+ * in the Software without restriction, including without limitation the rights
3855
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
3856
+ * copies of the Software, and to permit persons to whom the Software is
3857
+ * furnished to do so, subject to the following conditions:
3858
+ *
3859
+ * The above copyright notice and this permission notice shall be included in all
3860
+ * copies or substantial portions of the Software.
3861
+ *
3862
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3863
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3864
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3865
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3866
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3867
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
3868
+ * SOFTWARE.
3869
+ *
3870
+ * https://github.com/marcoroth/stimulus-lsp/blob/52268d4a4d06504dde6cb81f505a23b5db5d5759/server/src/levenshtein.ts
3871
+ *
3872
+ */
3873
+ function levenshtein(a, b) {
3874
+ function _min(d0, d1, d2, bx, ay) {
3875
+ return d0 < d1 || d2 < d1 ? (d0 > d2 ? d2 + 1 : d0 + 1) : bx === ay ? d1 : d1 + 1;
3876
+ }
3877
+ if (a === b) {
3878
+ return 0;
3879
+ }
3880
+ if (a.length > b.length) {
3881
+ const tmp = a;
3882
+ a = b;
3883
+ b = tmp;
3884
+ }
3885
+ let la = a.length;
3886
+ let lb = b.length;
3887
+ while (la > 0 && a.charCodeAt(la - 1) === b.charCodeAt(lb - 1)) {
3888
+ la--;
3889
+ lb--;
3890
+ }
3891
+ let offset = 0;
3892
+ while (offset < la && a.charCodeAt(offset) === b.charCodeAt(offset)) {
3893
+ offset++;
3894
+ }
3895
+ la -= offset;
3896
+ lb -= offset;
3897
+ if (la === 0 || lb < 3) {
3898
+ return lb;
3899
+ }
3900
+ let x = 0;
3901
+ let y;
3902
+ let d0;
3903
+ let d1;
3904
+ let d2;
3905
+ let d3;
3906
+ let dd;
3907
+ let dy;
3908
+ let ay;
3909
+ let bx0;
3910
+ let bx1;
3911
+ let bx2;
3912
+ let bx3;
3913
+ const vector = [];
3914
+ for (y = 0; y < la; y++) {
3915
+ vector.push(y + 1);
3916
+ vector.push(a.charCodeAt(offset + y));
3917
+ }
3918
+ const len = vector.length - 1;
3919
+ for (; x < lb - 3;) {
3920
+ bx0 = b.charCodeAt(offset + (d0 = x));
3921
+ bx1 = b.charCodeAt(offset + (d1 = x + 1));
3922
+ bx2 = b.charCodeAt(offset + (d2 = x + 2));
3923
+ bx3 = b.charCodeAt(offset + (d3 = x + 3));
3924
+ dd = x += 4;
3925
+ for (y = 0; y < len; y += 2) {
3926
+ dy = vector[y];
3927
+ ay = vector[y + 1];
3928
+ d0 = _min(dy, d0, d1, bx0, ay);
3929
+ d1 = _min(d0, d1, d2, bx1, ay);
3930
+ d2 = _min(d1, d2, d3, bx2, ay);
3931
+ dd = _min(d2, d3, dd, bx3, ay);
3932
+ vector[y] = dd;
3933
+ d3 = d2;
3934
+ d2 = d1;
3935
+ d1 = d0;
3936
+ d0 = dy;
3937
+ }
3938
+ }
3939
+ for (; x < lb;) {
3940
+ bx0 = b.charCodeAt(offset + (d0 = x));
3941
+ dd = ++x;
3942
+ for (y = 0; y < len; y += 2) {
3943
+ dy = vector[y];
3944
+ vector[y] = dd = _min(dy, d0, dd, bx0, vector[y + 1]);
3945
+ d0 = dy;
3946
+ }
3947
+ }
3948
+ return dd;
3949
+ }
3950
+
3951
+ /**
3952
+ * Ranks a list of strings by their Levenshtein distance from the input string.
3953
+ * Items are sorted in ascending order by distance, with closer matches first.
3954
+ *
3955
+ * @param input - The string to compare against
3956
+ * @param list - The list of strings to rank
3957
+ * @returns An array of objects containing the item and its distance score, sorted by score
3958
+ */
3959
+ function rank(input, list) {
3960
+ return list.map(item => {
3961
+ const score = levenshtein(input.toLowerCase(), item.toLowerCase());
3962
+ return { item, score };
3963
+ }).sort((a, b) => a.score - b.score);
3964
+ }
3965
+ /**
3966
+ * Finds the closest matching string from a list using Levenshtein distance.
3967
+ * Performs case-insensitive comparison.
3968
+ *
3969
+ * @param input - The string to match against
3970
+ * @param list - The list of candidate strings to search
3971
+ * @param threshold - Maximum Levenshtein distance to consider a match. If undefined, returns the closest match regardless of distance.
3972
+ * @returns The closest matching string from the list, or null if the list is empty or no match is within the threshold
3973
+ *
3974
+ * @example
3975
+ * ```ts
3976
+ * didyoumean('speling', ['spelling', 'writing', 'reading']) // Returns 'spelling'
3977
+ * didyoumean('test', []) // Returns null
3978
+ * didyoumean('speling', ['spelling', 'writing', 'reading'], 2) // Returns 'spelling' (distance: 1)
3979
+ * didyoumean('xyz', ['spelling', 'writing', 'reading'], 2) // Returns null (all distances > 2)
3980
+ * ```
3981
+ */
3982
+ function didyoumean(input, list, threshold) {
3983
+ if (list.length === 0)
3984
+ return null;
3985
+ const scores = rank(input, list);
3986
+ if (scores.length === 0)
3987
+ return null;
3988
+ const closest = scores[0];
3989
+ if (threshold !== undefined && closest.score > threshold)
3990
+ return null;
3991
+ return closest.item;
3992
+ }
3993
+ /**
3994
+ * Returns all strings from a list ranked by their Levenshtein distance from the input string.
3995
+ * Performs case-insensitive comparison. Results are sorted with closest matches first.
3996
+ *
3997
+ * @param input - The string to match against
3998
+ * @param list - The list of candidate strings to rank
3999
+ * @param threshold - Maximum Levenshtein distance to include in results. If undefined, returns all ranked results.
4000
+ * @returns An array of ranked results with items and scores, or an empty array if the list is empty or no matches are within the threshold
4001
+ *
4002
+ * @example
4003
+ * ```ts
4004
+ * didyoumeanRanked('speling', ['spelling', 'writing', 'reading'])
4005
+ * // Returns [{ item: 'spelling', score: 1 }, { item: 'reading', score: 5 }, { item: 'writing', score: 6 }]
4006
+ *
4007
+ * didyoumeanRanked('speling', ['spelling', 'writing', 'reading'], 2)
4008
+ * // Returns [{ item: 'spelling', score: 1 }]
4009
+ *
4010
+ * didyoumeanRanked('test', []) // Returns []
4011
+ * ```
4012
+ */
4013
+ function didyoumeanRanked(input, list, threshold) {
4014
+ if (list.length === 0)
4015
+ return [];
4016
+ const scores = rank(input, list);
4017
+ if (threshold !== undefined) {
4018
+ return scores.filter(result => result.score <= threshold);
4019
+ }
4020
+ return scores;
4021
+ }
4022
+
3741
4023
  var name = "@herb-tools/core";
3742
- var version = "0.7.4";
4024
+ var version = "0.8.0";
3743
4025
  var packageJSON = {
3744
4026
  name: name,
3745
4027
  version: version};
@@ -3962,7 +4244,7 @@
3962
4244
  }
3963
4245
 
3964
4246
  // NOTE: This file is generated by the templates/template.rb script and should not
3965
- // be modified manually. See /Users/marcoroth/Development/herb-release-0.7.4/templates/javascript/packages/core/src/visitor.ts.erb
4247
+ // be modified manually. See /Users/marcoroth/Development/herb-release-0.8.0/templates/javascript/packages/core/src/visitor.ts.erb
3966
4248
  class Visitor {
3967
4249
  visit(node) {
3968
4250
  if (!node)
@@ -3975,97 +4257,151 @@
3975
4257
  visitChildNodes(node) {
3976
4258
  node.compactChildNodes().forEach(node => node.accept(this));
3977
4259
  }
4260
+ visitNode(_node) {
4261
+ // Default implementation does nothing
4262
+ }
4263
+ visitERBNode(_node) {
4264
+ // Default implementation does nothing
4265
+ }
3978
4266
  visitDocumentNode(node) {
4267
+ this.visitNode(node);
3979
4268
  this.visitChildNodes(node);
3980
4269
  }
3981
4270
  visitLiteralNode(node) {
4271
+ this.visitNode(node);
3982
4272
  this.visitChildNodes(node);
3983
4273
  }
3984
4274
  visitHTMLOpenTagNode(node) {
4275
+ this.visitNode(node);
3985
4276
  this.visitChildNodes(node);
3986
4277
  }
3987
4278
  visitHTMLCloseTagNode(node) {
4279
+ this.visitNode(node);
3988
4280
  this.visitChildNodes(node);
3989
4281
  }
3990
4282
  visitHTMLElementNode(node) {
4283
+ this.visitNode(node);
3991
4284
  this.visitChildNodes(node);
3992
4285
  }
3993
4286
  visitHTMLAttributeValueNode(node) {
4287
+ this.visitNode(node);
3994
4288
  this.visitChildNodes(node);
3995
4289
  }
3996
4290
  visitHTMLAttributeNameNode(node) {
4291
+ this.visitNode(node);
3997
4292
  this.visitChildNodes(node);
3998
4293
  }
3999
4294
  visitHTMLAttributeNode(node) {
4295
+ this.visitNode(node);
4000
4296
  this.visitChildNodes(node);
4001
4297
  }
4002
4298
  visitHTMLTextNode(node) {
4299
+ this.visitNode(node);
4003
4300
  this.visitChildNodes(node);
4004
4301
  }
4005
4302
  visitHTMLCommentNode(node) {
4303
+ this.visitNode(node);
4006
4304
  this.visitChildNodes(node);
4007
4305
  }
4008
4306
  visitHTMLDoctypeNode(node) {
4307
+ this.visitNode(node);
4009
4308
  this.visitChildNodes(node);
4010
4309
  }
4011
4310
  visitXMLDeclarationNode(node) {
4311
+ this.visitNode(node);
4012
4312
  this.visitChildNodes(node);
4013
4313
  }
4014
4314
  visitCDATANode(node) {
4315
+ this.visitNode(node);
4015
4316
  this.visitChildNodes(node);
4016
4317
  }
4017
4318
  visitWhitespaceNode(node) {
4319
+ this.visitNode(node);
4018
4320
  this.visitChildNodes(node);
4019
4321
  }
4020
4322
  visitERBContentNode(node) {
4323
+ this.visitNode(node);
4324
+ this.visitERBNode(node);
4021
4325
  this.visitChildNodes(node);
4022
4326
  }
4023
4327
  visitERBEndNode(node) {
4328
+ this.visitNode(node);
4329
+ this.visitERBNode(node);
4024
4330
  this.visitChildNodes(node);
4025
4331
  }
4026
4332
  visitERBElseNode(node) {
4333
+ this.visitNode(node);
4334
+ this.visitERBNode(node);
4027
4335
  this.visitChildNodes(node);
4028
4336
  }
4029
4337
  visitERBIfNode(node) {
4338
+ this.visitNode(node);
4339
+ this.visitERBNode(node);
4030
4340
  this.visitChildNodes(node);
4031
4341
  }
4032
4342
  visitERBBlockNode(node) {
4343
+ this.visitNode(node);
4344
+ this.visitERBNode(node);
4033
4345
  this.visitChildNodes(node);
4034
4346
  }
4035
4347
  visitERBWhenNode(node) {
4348
+ this.visitNode(node);
4349
+ this.visitERBNode(node);
4036
4350
  this.visitChildNodes(node);
4037
4351
  }
4038
4352
  visitERBCaseNode(node) {
4353
+ this.visitNode(node);
4354
+ this.visitERBNode(node);
4039
4355
  this.visitChildNodes(node);
4040
4356
  }
4041
4357
  visitERBCaseMatchNode(node) {
4358
+ this.visitNode(node);
4359
+ this.visitERBNode(node);
4042
4360
  this.visitChildNodes(node);
4043
4361
  }
4044
4362
  visitERBWhileNode(node) {
4363
+ this.visitNode(node);
4364
+ this.visitERBNode(node);
4045
4365
  this.visitChildNodes(node);
4046
4366
  }
4047
4367
  visitERBUntilNode(node) {
4368
+ this.visitNode(node);
4369
+ this.visitERBNode(node);
4048
4370
  this.visitChildNodes(node);
4049
4371
  }
4050
4372
  visitERBForNode(node) {
4373
+ this.visitNode(node);
4374
+ this.visitERBNode(node);
4051
4375
  this.visitChildNodes(node);
4052
4376
  }
4053
4377
  visitERBRescueNode(node) {
4378
+ this.visitNode(node);
4379
+ this.visitERBNode(node);
4054
4380
  this.visitChildNodes(node);
4055
4381
  }
4056
4382
  visitERBEnsureNode(node) {
4383
+ this.visitNode(node);
4384
+ this.visitERBNode(node);
4057
4385
  this.visitChildNodes(node);
4058
4386
  }
4059
4387
  visitERBBeginNode(node) {
4388
+ this.visitNode(node);
4389
+ this.visitERBNode(node);
4060
4390
  this.visitChildNodes(node);
4061
4391
  }
4062
4392
  visitERBUnlessNode(node) {
4393
+ this.visitNode(node);
4394
+ this.visitERBNode(node);
4063
4395
  this.visitChildNodes(node);
4064
4396
  }
4065
4397
  visitERBYieldNode(node) {
4398
+ this.visitNode(node);
4399
+ this.visitERBNode(node);
4066
4400
  this.visitChildNodes(node);
4067
4401
  }
4068
4402
  visitERBInNode(node) {
4403
+ this.visitNode(node);
4404
+ this.visitERBNode(node);
4069
4405
  this.visitChildNodes(node);
4070
4406
  }
4071
4407
  }
@@ -4079,6 +4415,7 @@
4079
4415
  exports.ERBCaseMatchNode = ERBCaseMatchNode;
4080
4416
  exports.ERBCaseNode = ERBCaseNode;
4081
4417
  exports.ERBContentNode = ERBContentNode;
4418
+ exports.ERBControlFlowScopeError = ERBControlFlowScopeError;
4082
4419
  exports.ERBElseNode = ERBElseNode;
4083
4420
  exports.ERBEndNode = ERBEndNode;
4084
4421
  exports.ERBEnsureNode = ERBEnsureNode;
@@ -4108,6 +4445,7 @@
4108
4445
  exports.LiteralNode = LiteralNode;
4109
4446
  exports.Location = Location;
4110
4447
  exports.MissingClosingTagError = MissingClosingTagError;
4448
+ exports.MissingERBEndTagError = MissingERBEndTagError;
4111
4449
  exports.MissingOpeningTagError = MissingOpeningTagError;
4112
4450
  exports.NODE_TYPE_GUARDS = NODE_TYPE_GUARDS;
4113
4451
  exports.Node = Node;
@@ -4130,6 +4468,8 @@
4130
4468
  exports._TYPECHECK = _TYPECHECK;
4131
4469
  exports.areAllOfType = areAllOfType;
4132
4470
  exports.convertToUTF8 = convertToUTF8;
4471
+ exports.didyoumean = didyoumean;
4472
+ exports.didyoumeanRanked = didyoumeanRanked;
4133
4473
  exports.ensureLibHerbBackend = ensureLibHerbBackend;
4134
4474
  exports.ensureString = ensureString;
4135
4475
  exports.filterCDATANodes = filterCDATANodes;
@@ -4228,6 +4568,7 @@
4228
4568
  exports.isToken = isToken;
4229
4569
  exports.isWhitespaceNode = isWhitespaceNode;
4230
4570
  exports.isXMLDeclarationNode = isXMLDeclarationNode;
4571
+ exports.levenshtein = levenshtein;
4231
4572
  exports.splitNodesAroundLocation = splitNodesAroundLocation;
4232
4573
  exports.splitNodesAroundPosition = splitNodesAroundPosition;
4233
4574
  exports.toMonacoDiagnostic = toMonacoDiagnostic;