clarity-pattern-parser 11.4.1 → 11.4.2

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.esm.js CHANGED
@@ -427,9 +427,10 @@ class CursorHistory {
427
427
  }
428
428
  }
429
429
 
430
+ const segmenter = new Intl.Segmenter("und", { granularity: "grapheme" });
430
431
  class Cursor {
431
432
  get text() {
432
- return this._chars.join("");
433
+ return this._text;
433
434
  }
434
435
  get isOnFirst() {
435
436
  return this._index === 0;
@@ -477,33 +478,55 @@ class Cursor {
477
478
  return this._history.error != null;
478
479
  }
479
480
  get currentChar() {
480
- return this._chars[this._index];
481
+ const index = this.getCharStartIndex(this._index);
482
+ return this.text.slice(index, index + this._charSize[index]);
481
483
  }
482
484
  constructor(text) {
483
- this._chars = [...text];
485
+ this._text = text;
486
+ this._length = text.length;
487
+ this._charSize = [];
488
+ this._charMap = [];
484
489
  this._index = 0;
485
- this._length = this._chars.length;
486
490
  this._history = new CursorHistory();
491
+ let index = 0;
492
+ for (const segment of segmenter.segment(text)) {
493
+ const size = segment.segment.length;
494
+ for (let i = 0; i < size; i++) {
495
+ this._charMap.push(index);
496
+ this._charSize.push(size);
497
+ }
498
+ index += size;
499
+ }
487
500
  }
488
501
  hasNext() {
489
- return this._index + 1 < this._length;
502
+ const index = this._charMap[this._index];
503
+ const charSize = this._charSize[index];
504
+ return index + charSize < this._length;
490
505
  }
491
506
  next() {
492
507
  if (this.hasNext()) {
493
- this._index++;
508
+ const index = this._charMap[this._index];
509
+ const size = this._charSize[index];
510
+ this.moveTo(index + size);
494
511
  }
495
512
  }
496
513
  hasPrevious() {
497
- return this._index - 1 >= 0;
514
+ var _a;
515
+ const index = this._charMap[this._index];
516
+ const previousIndex = (_a = this._charMap[index - 1]) !== null && _a !== void 0 ? _a : -1;
517
+ return previousIndex >= 0;
498
518
  }
499
519
  previous() {
520
+ var _a;
500
521
  if (this.hasPrevious()) {
501
- this._index--;
522
+ const index = this._charMap[this._index];
523
+ const previousIndex = (_a = this._charMap[index - 1]) !== null && _a !== void 0 ? _a : -1;
524
+ this.moveTo(previousIndex);
502
525
  }
503
526
  }
504
527
  moveTo(position) {
505
528
  if (position >= 0 && position < this._length) {
506
- this._index = position;
529
+ this._index = this._charMap[position];
507
530
  }
508
531
  }
509
532
  moveToFirstChar() {
@@ -515,8 +538,8 @@ class Cursor {
515
538
  getLastIndex() {
516
539
  return this._length - 1;
517
540
  }
518
- getChars(first, last) {
519
- return this._chars.slice(first, last + 1).join("");
541
+ substring(first, last) {
542
+ return this._text.slice(first, last + 1);
520
543
  }
521
544
  recordMatch(pattern, node) {
522
545
  this._history.recordMatch(pattern, node);
@@ -533,6 +556,18 @@ class Cursor {
533
556
  stopRecording() {
534
557
  this._history.stopRecording();
535
558
  }
559
+ getCharStartIndex(index) {
560
+ return this._charMap[index];
561
+ }
562
+ getCharEndIndex(index) {
563
+ var _a;
564
+ let startIndex = this.getCharStartIndex(index);
565
+ return (_a = startIndex + this._charSize[startIndex]) !== null && _a !== void 0 ? _a : 1;
566
+ }
567
+ getCharLastIndex(index) {
568
+ var _a;
569
+ return (_a = this.getCharEndIndex(index) - 1) !== null && _a !== void 0 ? _a : 0;
570
+ }
536
571
  }
537
572
 
538
573
  function execPattern(pattern, text, record = false) {
@@ -598,11 +633,9 @@ class Literal {
598
633
  this._type = "literal";
599
634
  this._name = name;
600
635
  this._token = value;
601
- this._runes = Array.from(value);
602
636
  this._parent = null;
603
637
  this._firstIndex = 0;
604
638
  this._lastIndex = 0;
605
- this._endIndex = 0;
606
639
  }
607
640
  test(text, record = false) {
608
641
  return testPattern(this, text, record);
@@ -612,6 +645,7 @@ class Literal {
612
645
  }
613
646
  parse(cursor) {
614
647
  this._firstIndex = cursor.index;
648
+ this._lastIndex = cursor.index;
615
649
  const passed = this._tryToParse(cursor);
616
650
  if (passed) {
617
651
  cursor.resolveError();
@@ -619,31 +653,28 @@ class Literal {
619
653
  cursor.recordMatch(this, node);
620
654
  return node;
621
655
  }
622
- cursor.recordErrorAt(this._firstIndex, this._endIndex, this);
656
+ cursor.recordErrorAt(this._firstIndex, this._lastIndex, this);
623
657
  return null;
624
658
  }
625
659
  _tryToParse(cursor) {
626
- let passed = false;
627
- const literalRuneLength = this._runes.length;
628
- for (let i = 0; i < literalRuneLength; i++) {
629
- const literalRune = this._runes[i];
630
- const cursorRune = cursor.currentChar;
631
- if (literalRune !== cursorRune) {
632
- this._endIndex = cursor.index;
633
- break;
634
- }
635
- if (i + 1 === literalRuneLength) {
636
- this._lastIndex = this._firstIndex + this._token.length - 1;
637
- passed = true;
638
- break;
639
- }
640
- if (!cursor.hasNext()) {
641
- this._endIndex = cursor.index + 1;
642
- break;
660
+ const token = this._token;
661
+ const compareToToken = cursor.text.slice(this._firstIndex, this._firstIndex + this._token.length);
662
+ const length = Math.min(token.length, compareToToken.length);
663
+ for (let i = 0; i < length; i++) {
664
+ if (token[i] !== compareToToken[i]) {
665
+ this._lastIndex = this._firstIndex + i;
666
+ cursor.moveTo(this._lastIndex);
667
+ return false;
643
668
  }
644
- cursor.next();
645
669
  }
646
- return passed;
670
+ if (token != compareToToken) {
671
+ this._lastIndex = this._firstIndex + compareToToken.length - 1;
672
+ cursor.moveTo(this._lastIndex);
673
+ return false;
674
+ }
675
+ this._lastIndex = this._firstIndex + this._token.length - 1;
676
+ cursor.moveTo(this._lastIndex);
677
+ return true;
647
678
  }
648
679
  _createNode() {
649
680
  return new Node("literal", this._name, this._firstIndex, this._lastIndex, undefined, this._token);
@@ -722,7 +753,7 @@ class Regex {
722
753
  this._name = name;
723
754
  this._parent = null;
724
755
  this._originalRegexString = regex;
725
- this._regex = new RegExp(`^${regex}`, "g");
756
+ this._regex = new RegExp(`^${regex}`, "gu");
726
757
  this.assertArguments();
727
758
  }
728
759
  assertArguments() {
@@ -751,7 +782,7 @@ class Regex {
751
782
  resetState(cursor) {
752
783
  this._cursor = cursor;
753
784
  this._regex.lastIndex = 0;
754
- this._substring = this._cursor.text.substr(this._cursor.index);
785
+ this._substring = this._cursor.text.slice(this._cursor.index);
755
786
  this._node = null;
756
787
  }
757
788
  tryToParse(cursor) {
@@ -766,10 +797,9 @@ class Regex {
766
797
  processResult(cursor, result) {
767
798
  const currentIndex = cursor.index;
768
799
  const match = result[0];
769
- const matchLength = [...match].length;
770
- const newIndex = currentIndex + matchLength - 1;
771
- this._node = new Node("regex", this._name, currentIndex, newIndex, undefined, result[0]);
772
- cursor.moveTo(newIndex);
800
+ const lastIndex = cursor.getCharLastIndex(currentIndex + match.length - 1);
801
+ this._node = new Node("regex", this._name, currentIndex, lastIndex, undefined, result[0]);
802
+ cursor.moveTo(lastIndex);
773
803
  cursor.recordMatch(this, this._node);
774
804
  }
775
805
  processError(cursor) {
@@ -3297,7 +3327,7 @@ class TakeUntil {
3297
3327
  }
3298
3328
  if (foundMatch) {
3299
3329
  cursor.moveTo(cursorIndex - 1);
3300
- const value = cursor.getChars(this.startedOnIndex, cursorIndex - 1);
3330
+ const value = cursor.substring(this.startedOnIndex, cursorIndex - 1);
3301
3331
  const node = Node.createValueNode(this._type, this._name, value);
3302
3332
  cursor.recordMatch(this, node);
3303
3333
  return node;
@@ -3449,7 +3479,7 @@ function generateErrorMessage(pattern, cursor) {
3449
3479
  }
3450
3480
  const lastPattern = furthestMatch.pattern;
3451
3481
  const suggestions = cleanSuggestions(lastPattern.getNextTokens());
3452
- const strUpToError = cursor.getChars(0, endIndex);
3482
+ const strUpToError = cursor.substring(0, endIndex);
3453
3483
  const lines = strUpToError.split("\n");
3454
3484
  const lastLine = lines[lines.length - 1];
3455
3485
  const line = lines.length;
@@ -4187,9 +4217,9 @@ class AutoComplete {
4187
4217
  }
4188
4218
  _createSuggestionOptionsFromErrors() {
4189
4219
  // These errored because the length of the string.
4190
- const errors = this._cursor.errors.filter(e => e.lastIndex === this._cursor.length);
4220
+ const errors = this._cursor.errors.filter(e => e.lastIndex === this._cursor.length - 1);
4191
4221
  const errorSuggestionOptions = errors.map(parseError => {
4192
- const currentText = this._cursor.getChars(parseError.startIndex, parseError.lastIndex);
4222
+ const currentText = this._cursor.substring(parseError.startIndex, parseError.lastIndex);
4193
4223
  const compositeSuggestions = this._getCompositeSuggestionsForPattern(parseError.pattern);
4194
4224
  const trimmedErrorCompositeSuggestions = this._trimSuggestionsByExistingText(currentText, compositeSuggestions);
4195
4225
  return this._createSuggestions(parseError.lastIndex, trimmedErrorCompositeSuggestions);
@@ -4245,7 +4275,7 @@ class AutoComplete {
4245
4275
  * ie. sequence pattern segments ≈ [{look}, {an example}, {phrase}]
4246
4276
  * fullText = "look an"
4247
4277
  * remove {look} segment as its already been completed by the existing text.
4248
- */
4278
+ */
4249
4279
  _filterCompletedSubSegments(currentText, compositeSuggestion) {
4250
4280
  let elementsToRemove = [];
4251
4281
  let workingText = currentText;
@@ -4348,7 +4378,7 @@ class AutoComplete {
4348
4378
  return unique;
4349
4379
  }
4350
4380
  _createSuggestions(lastIndex, compositeSuggestionList) {
4351
- let textToIndex = lastIndex === -1 ? "" : this._cursor.getChars(0, lastIndex);
4381
+ let textToIndex = lastIndex === -1 ? "" : this._cursor.substring(0, lastIndex);
4352
4382
  const options = [];
4353
4383
  for (const compositeSuggestion of compositeSuggestionList) {
4354
4384
  // concatenated for start index identification inside createSuggestion