clarity-pattern-parser 11.3.9 → 11.3.11

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
@@ -1255,12 +1255,10 @@ class FiniteRepeat {
1255
1255
  }
1256
1256
  }
1257
1257
  }
1258
- if (this._trimDivider && this._hasDivider) {
1259
- const isDividerLastMatch = this.children.length > 1 && nodes.length > 1 && nodes[nodes.length - 1].name === this.children[1].name;
1260
- if (isDividerLastMatch) {
1261
- const node = nodes.pop();
1262
- cursor.moveTo(node.firstIndex);
1263
- }
1258
+ const endedOnDivider = this._hasDivider && nodes.length % modulo === 0;
1259
+ if (this._trimDivider && endedOnDivider) {
1260
+ const node = nodes.pop();
1261
+ cursor.moveTo(node.firstIndex);
1264
1262
  }
1265
1263
  if (matchCount < this._min) {
1266
1264
  const lastIndex = cursor.index;
@@ -1396,6 +1394,7 @@ class InfiniteRepeat {
1396
1394
  this._firstIndex = 0;
1397
1395
  this._nodes = [];
1398
1396
  this._trimDivider = options.trimDivider == null ? false : options.trimDivider;
1397
+ this._patterns = [];
1399
1398
  }
1400
1399
  _assignChildrenToParent(children) {
1401
1400
  for (const child of children) {
@@ -1411,6 +1410,7 @@ class InfiniteRepeat {
1411
1410
  parse(cursor) {
1412
1411
  this._firstIndex = cursor.index;
1413
1412
  this._nodes = [];
1413
+ this._patterns = [];
1414
1414
  const passed = this._tryToParse(cursor);
1415
1415
  if (passed) {
1416
1416
  cursor.resolveError();
@@ -1462,6 +1462,7 @@ class InfiniteRepeat {
1462
1462
  }
1463
1463
  if (repeatNode != null) {
1464
1464
  this._nodes.push(repeatNode);
1465
+ this._patterns.push(this._pattern);
1465
1466
  if (!cursor.hasNext()) {
1466
1467
  passed = true;
1467
1468
  break;
@@ -1486,6 +1487,7 @@ class InfiniteRepeat {
1486
1487
  }
1487
1488
  else {
1488
1489
  this._nodes.push(dividerNode);
1490
+ this._patterns.push(this._divider);
1489
1491
  if (!cursor.hasNext()) {
1490
1492
  passed = true;
1491
1493
  break;
@@ -1508,11 +1510,11 @@ class InfiniteRepeat {
1508
1510
  return passed;
1509
1511
  }
1510
1512
  _createNode(cursor) {
1511
- var _a;
1512
1513
  const hasDivider = this._divider != null;
1514
+ const lastPattern = this._patterns[this._patterns.length - 1];
1513
1515
  if (hasDivider &&
1514
1516
  this._trimDivider &&
1515
- this._nodes[this._nodes.length - 1].name === ((_a = this._divider) === null || _a === void 0 ? void 0 : _a.name)) {
1517
+ lastPattern === this._divider) {
1516
1518
  const dividerNode = this._nodes.pop();
1517
1519
  cursor.moveTo(dividerNode.firstIndex);
1518
1520
  }
@@ -2719,13 +2721,36 @@ class PrecedenceTree {
2719
2721
  }
2720
2722
  _compileAtomNode() {
2721
2723
  let node = this._atomNode;
2722
- if (this._prefixNode != null && this._atomNode != null) {
2723
- node = this._prefixNode.findRoot();
2724
- this._prefixPlaceholder.replaceWith(this._atomNode);
2724
+ if (this._prefixNode != null && this._postfixNode != null && this._atomNode != null) {
2725
+ let firstNode = this._prefixNode;
2726
+ let secondNode = this._postfixNode;
2727
+ let firstPlaceholder = this._prefixPlaceholder;
2728
+ let secondPlaceholder = this._postfixPlaceholder;
2729
+ const prefixName = this._prefixNode.name;
2730
+ const postfixName = this._postfixNode.name;
2731
+ const prefixPrecedence = this._getPrecedence(prefixName);
2732
+ const postfixPrecedence = this._getPrecedence(postfixName);
2733
+ // The Precedence is the index of the patterns, so its lower not higher :\
2734
+ if (prefixPrecedence > postfixPrecedence) {
2735
+ firstNode = this._postfixNode;
2736
+ secondNode = this._prefixNode;
2737
+ firstPlaceholder = this._postfixPlaceholder;
2738
+ secondPlaceholder = this._prefixPlaceholder;
2739
+ }
2740
+ node = firstNode.findRoot();
2741
+ firstPlaceholder.replaceWith(this._atomNode);
2742
+ secondPlaceholder.replaceWith(node);
2743
+ node = secondNode;
2725
2744
  }
2726
- if (this._postfixNode != null && node != null) {
2727
- this._postfixPlaceholder.replaceWith(node);
2728
- node = this._postfixNode;
2745
+ else {
2746
+ if (this._prefixNode != null && this._atomNode != null) {
2747
+ node = this._prefixNode.findRoot();
2748
+ this._prefixPlaceholder.replaceWith(this._atomNode);
2749
+ }
2750
+ if (this._postfixNode != null && node != null) {
2751
+ this._postfixPlaceholder.replaceWith(node);
2752
+ node = this._postfixNode;
2753
+ }
2729
2754
  }
2730
2755
  this._prefixNode = null;
2731
2756
  this._atomNode = null;
@@ -2833,7 +2858,7 @@ class Expression {
2833
2858
  }
2834
2859
  _organizePatterns(patterns) {
2835
2860
  const finalPatterns = [];
2836
- patterns.forEach((pattern) => {
2861
+ patterns.forEach((pattern, index) => {
2837
2862
  if (this._isAtom(pattern)) {
2838
2863
  const atom = pattern.clone();
2839
2864
  atom.parent = this;
@@ -2844,6 +2869,7 @@ class Expression {
2844
2869
  const name = this._extractName(pattern);
2845
2870
  const prefix = this._extractPrefix(pattern);
2846
2871
  prefix.parent = this;
2872
+ this._precedenceMap[name] = index;
2847
2873
  this._prefixPatterns.push(prefix);
2848
2874
  this._prefixNames.push(name);
2849
2875
  finalPatterns.push(prefix);
@@ -2852,6 +2878,7 @@ class Expression {
2852
2878
  const name = this._extractName(pattern);
2853
2879
  const postfix = this._extractPostfix(pattern);
2854
2880
  postfix.parent = this;
2881
+ this._precedenceMap[name] = index;
2855
2882
  this._postfixPatterns.push(postfix);
2856
2883
  this._postfixNames.push(name);
2857
2884
  finalPatterns.push(postfix);
@@ -2860,7 +2887,7 @@ class Expression {
2860
2887
  const name = this._extractName(pattern);
2861
2888
  const binary = this._extractBinary(pattern);
2862
2889
  binary.parent = this;
2863
- this._precedenceMap[name] = this._binaryPatterns.length;
2890
+ this._precedenceMap[name] = index;
2864
2891
  this._binaryPatterns.push(binary);
2865
2892
  this._binaryNames.push(name);
2866
2893
  if (pattern.type === "right-associated") {
@@ -3658,6 +3685,8 @@ class Grammar {
3658
3685
  return this._isRecursivePattern(name, pattern);
3659
3686
  }
3660
3687
  _isRecursivePattern(name, pattern) {
3688
+ // Because we don't know if the pattern is a sequence with a reference we have to just assume it is.
3689
+ // The better solution here would be to not have options at all and just use expresssion pattern instead.
3661
3690
  if (pattern.type === "reference") {
3662
3691
  return true;
3663
3692
  }
@@ -4009,26 +4038,30 @@ class AutoComplete {
4009
4038
  this._options = options;
4010
4039
  this._text = "";
4011
4040
  }
4041
+ suggestFor(text) {
4042
+ return this.suggestForWithCursor(new Cursor(text));
4043
+ }
4012
4044
  suggestForWithCursor(cursor) {
4013
4045
  cursor.moveTo(0);
4014
4046
  this._cursor = cursor;
4015
4047
  this._text = cursor.text;
4016
4048
  this._cursor.startRecording();
4017
4049
  if (cursor.length === 0) {
4018
- return {
4050
+ const suggestion = {
4019
4051
  isComplete: false,
4020
- options: this._createSuggestionsFromRoot(),
4052
+ options: this._createSuggestionOptionsFromMatch(),
4021
4053
  error: new ParseError(0, 0, this._pattern),
4022
4054
  errorAtIndex: 0,
4023
4055
  cursor,
4024
4056
  ast: null
4025
4057
  };
4058
+ return suggestion;
4026
4059
  }
4027
4060
  let errorAtIndex = null;
4028
4061
  let error = null;
4029
4062
  const ast = this._pattern.parse(this._cursor);
4030
4063
  const isComplete = (ast === null || ast === void 0 ? void 0 : ast.value) === this._text;
4031
- const options = this._getAllOptions();
4064
+ const options = this._getAllSuggestionsOptions();
4032
4065
  if (!isComplete && options.length > 0 && !this._cursor.hasError) {
4033
4066
  const startIndex = options.reduce((lowestIndex, o) => {
4034
4067
  return Math.min(lowestIndex, o.startIndex);
@@ -4075,14 +4108,11 @@ class AutoComplete {
4075
4108
  }
4076
4109
  return 0;
4077
4110
  }
4078
- suggestFor(text) {
4079
- return this.suggestForWithCursor(new Cursor(text));
4080
- }
4081
- _getAllOptions() {
4082
- const errorMatches = this._getOptionsFromErrors();
4083
- const leafMatches = this._cursor.leafMatches.map((m) => this._createSuggestionsFromMatch(m)).flat();
4111
+ _getAllSuggestionsOptions() {
4112
+ const errorMatchOptions = this._createSuggestionOptionsFromErrors();
4113
+ const leafMatchOptions = this._cursor.leafMatches.map((m) => this._createSuggestionOptionsFromMatch(m)).flat();
4084
4114
  const finalResults = [];
4085
- [...leafMatches, ...errorMatches].forEach(m => {
4115
+ [...leafMatchOptions, ...errorMatchOptions].forEach(m => {
4086
4116
  const index = finalResults.findIndex(f => m.text === f.text);
4087
4117
  if (index === -1) {
4088
4118
  finalResults.push(m);
@@ -4090,135 +4120,190 @@ class AutoComplete {
4090
4120
  });
4091
4121
  return finalResults;
4092
4122
  }
4093
- _getOptionsFromErrors() {
4123
+ _createSuggestionOptionsFromErrors() {
4094
4124
  // These errored because the length of the string.
4095
4125
  const errors = this._cursor.errors.filter(e => e.lastIndex === this._cursor.length);
4096
- const suggestions = errors.map(e => {
4097
- const tokens = this._getTokensForPattern(e.pattern);
4098
- const adjustedTokens = new Set();
4099
- const currentText = this._cursor.getChars(e.startIndex, e.lastIndex);
4100
- tokens.forEach((token) => {
4101
- if (token.startsWith(currentText) && token.length > currentText.length) {
4102
- const difference = token.length - currentText.length;
4103
- const suggestedText = token.slice(-difference);
4104
- adjustedTokens.add(suggestedText);
4105
- }
4106
- });
4107
- return Array.from(adjustedTokens).map(t => {
4108
- return {
4109
- text: t,
4110
- startIndex: e.lastIndex,
4111
- };
4112
- });
4113
- });
4114
- return suggestions.flat();
4115
- }
4116
- _createSuggestionsFromRoot() {
4117
- const suggestions = [];
4118
- const tokens = [...this._pattern.getTokens(), ...this._getTokensForPattern(this._pattern)];
4119
- for (const token of tokens) {
4120
- if (suggestions.findIndex(s => s.text === token) === -1) {
4121
- suggestions.push(this._createSuggestion("", token));
4122
- }
4123
- }
4124
- return suggestions;
4125
- }
4126
- _createSuggestionsFromMatch(match) {
4127
- if (match.pattern == null) {
4128
- return this._createSuggestions(-1, this._getTokensForPattern(this._pattern));
4129
- }
4130
- if (match.node != null) {
4131
- const textStartingMatch = this._text.slice(match.node.startIndex, match.node.endIndex);
4132
- const currentPatternsTokens = this._getTokensForPattern(match.pattern);
4133
- /**
4134
- * Compares tokens to current text and extracts remainder tokens
4135
- * - IE. **currentText:** *abc*, **baseToken:** *abcdef*, **trailingToken:** *def*
4136
- */
4137
- const trailingTokens = currentPatternsTokens.reduce((acc, token) => {
4138
- if (token.startsWith(textStartingMatch)) {
4139
- const sliced = token.slice(textStartingMatch.length);
4140
- if (sliced !== '') {
4141
- acc.push(sliced);
4142
- }
4143
- }
4144
- return acc;
4145
- }, []);
4126
+ const errorSuggestionOptions = errors.map(parseError => {
4127
+ const currentText = this._cursor.getChars(parseError.startIndex, parseError.lastIndex);
4128
+ const compositeSuggestions = this._getCompositeSuggestionsForPattern(parseError.pattern);
4129
+ const trimmedErrorCompositeSuggestions = this._trimSuggestionsByExistingText(currentText, compositeSuggestions);
4130
+ return this._createSuggestions(parseError.lastIndex, trimmedErrorCompositeSuggestions);
4131
+ }).flat();
4132
+ const dedupedErrorSuggestionOptions = this._deDupeCompositeSuggestions(errorSuggestionOptions);
4133
+ return dedupedErrorSuggestionOptions;
4134
+ }
4135
+ _createSuggestionOptionsFromMatch(match) {
4136
+ if ((match === null || match === void 0 ? void 0 : match.pattern) == null) {
4137
+ const compositeSuggestions = this._getCompositeSuggestionsForPattern(this._pattern);
4138
+ return this._createSuggestions(-1, compositeSuggestions);
4139
+ }
4140
+ if ((match === null || match === void 0 ? void 0 : match.node) != null) {
4141
+ const currentText = this._text.slice(match.node.startIndex, match.node.endIndex);
4142
+ /**Captures suggestions for a "completed" match pattern that still has existing possible suggestions.
4143
+ * particularly relevant when working with set/custom tokens.
4144
+ */
4145
+ const matchCompositeSuggestions = this._getCompositeSuggestionsForPattern(match.pattern);
4146
+ const trimmedMatchCompositeSuggestions = this._trimSuggestionsByExistingText(currentText, matchCompositeSuggestions);
4146
4147
  const leafPatterns = match.pattern.getNextPatterns();
4147
- const leafTokens = leafPatterns.reduce((acc, leafPattern) => {
4148
- acc.push(...this._getTokensForPattern(leafPattern));
4149
- return acc;
4150
- }, []);
4151
- const allTokens = [...trailingTokens, ...leafTokens];
4152
- return this._createSuggestions(match.node.lastIndex, allTokens);
4148
+ const leafCompositeSuggestions = leafPatterns.flatMap(leafPattern => this._getCompositeSuggestionsForPattern(leafPattern));
4149
+ const allCompositeSuggestions = [...leafCompositeSuggestions, ...trimmedMatchCompositeSuggestions,];
4150
+ const dedupedCompositeSuggestions = this._deDupeCompositeSuggestions(allCompositeSuggestions);
4151
+ return this._createSuggestions(match.node.lastIndex, dedupedCompositeSuggestions);
4153
4152
  }
4154
4153
  else {
4155
4154
  return [];
4156
4155
  }
4157
4156
  }
4158
- _getTokensForPattern(pattern) {
4159
- const augmentedTokens = this._getAugmentedTokens(pattern);
4157
+ /**
4158
+ * Compares suggestions with provided text and removes completed sub-sequences and preceding text
4159
+ * - IE. **currentText:** *abc*, **sequence:** *[{ab}{cd}{ef}*
4160
+ * - refines to {d}{ef}
4161
+ */
4162
+ _trimSuggestionsByExistingText(currentText, compositeSuggestions) {
4163
+ const trimmedSuggestions = compositeSuggestions.reduce((acc, compositeSuggestion) => {
4164
+ if (compositeSuggestion.text.startsWith(currentText)) {
4165
+ const filteredSegments = this._filterCompletedSubSegments(currentText, compositeSuggestion);
4166
+ const slicedSuggestionText = compositeSuggestion.text.slice(currentText.length);
4167
+ if (slicedSuggestionText !== '') {
4168
+ const refinedCompositeSuggestion = {
4169
+ text: slicedSuggestionText,
4170
+ suggestionSequence: filteredSegments,
4171
+ };
4172
+ acc.push(refinedCompositeSuggestion);
4173
+ }
4174
+ }
4175
+ return acc;
4176
+ }, []);
4177
+ return trimmedSuggestions;
4178
+ }
4179
+ /** Removed segments already accounted for in the existing text.
4180
+ * ie. sequence pattern segments ≈ [{look}, {an example}, {phrase}]
4181
+ * fullText = "look an"
4182
+ * remove {look} segment as its already been completed by the existing text.
4183
+ */
4184
+ _filterCompletedSubSegments(currentText, compositeSuggestion) {
4185
+ let elementsToRemove = [];
4186
+ let workingText = currentText;
4187
+ compositeSuggestion.suggestionSequence.forEach(segment => {
4188
+ /**sub segment has been completed, remove it from the sequence */
4189
+ if (workingText.startsWith(segment.text)) {
4190
+ workingText = workingText.slice(segment.text.length);
4191
+ elementsToRemove.push(segment);
4192
+ }
4193
+ });
4194
+ const filteredSegments = compositeSuggestion.suggestionSequence.filter(segment => !elementsToRemove.includes(segment));
4195
+ return filteredSegments;
4196
+ }
4197
+ _getCompositeSuggestionsForPattern(pattern) {
4198
+ const suggestionsToReturn = [];
4199
+ const leafPatterns = pattern.getPatterns();
4200
+ // for when pattern has no leafPatterns and only returns itself
4201
+ if (leafPatterns.length === 1 && leafPatterns[0].id === pattern.id) {
4202
+ const currentCustomTokens = this._getCustomTokens(pattern);
4203
+ const currentTokens = pattern.getTokens();
4204
+ const allTokens = [...currentCustomTokens, ...currentTokens];
4205
+ const leafCompositeSuggestions = allTokens.map(token => {
4206
+ const segment = {
4207
+ text: token,
4208
+ pattern: pattern,
4209
+ };
4210
+ const compositeSuggestion = {
4211
+ text: token,
4212
+ suggestionSequence: [segment],
4213
+ };
4214
+ return compositeSuggestion;
4215
+ });
4216
+ suggestionsToReturn.push(...leafCompositeSuggestions);
4217
+ }
4218
+ else {
4219
+ const currentCustomTokens = this._getCustomTokens(pattern);
4220
+ const patternsSuggestionList = currentCustomTokens.map(token => {
4221
+ const segment = {
4222
+ text: token,
4223
+ pattern: pattern,
4224
+ };
4225
+ const patternSuggestion = {
4226
+ text: token,
4227
+ suggestionSequence: [segment],
4228
+ };
4229
+ return patternSuggestion;
4230
+ });
4231
+ const leafCompositeSuggestions = leafPatterns.map(lp => this._getCompositeSuggestionsForPattern(lp)).flat();
4232
+ suggestionsToReturn.push(...patternsSuggestionList, ...leafCompositeSuggestions);
4233
+ }
4160
4234
  if (this._options.greedyPatternNames != null && this._options.greedyPatternNames.includes(pattern.name)) {
4161
4235
  const nextPatterns = pattern.getNextPatterns();
4162
- const nextPatternTokens = nextPatterns.reduce((acc, pattern) => {
4163
- acc.push(...this._getTokensForPattern(pattern));
4236
+ const nextPatternedTokensList = nextPatterns.reduce((acc, pattern) => {
4237
+ const patternedTokensList = this._getCompositeSuggestionsForPattern(pattern);
4238
+ acc.push(...patternedTokensList);
4164
4239
  return acc;
4165
4240
  }, []);
4166
- // using set to prevent duplicates
4167
- const tokens = new Set();
4168
- for (const token of augmentedTokens) {
4169
- for (const nextPatternToken of nextPatternTokens) {
4170
- tokens.add(token + nextPatternToken);
4241
+ const compositeSuggestionList = [];
4242
+ for (const currentSuggestion of suggestionsToReturn) {
4243
+ for (const nextSuggestionWithSubElements of nextPatternedTokensList) {
4244
+ const augmentedTokenWithPattern = {
4245
+ text: currentSuggestion.text + nextSuggestionWithSubElements.text,
4246
+ suggestionSequence: [...currentSuggestion.suggestionSequence, ...nextSuggestionWithSubElements.suggestionSequence],
4247
+ };
4248
+ compositeSuggestionList.push(augmentedTokenWithPattern);
4171
4249
  }
4172
4250
  }
4173
- return [...tokens];
4251
+ return compositeSuggestionList;
4174
4252
  }
4175
4253
  else {
4176
- return augmentedTokens;
4254
+ const dedupedSuggestions = this._deDupeCompositeSuggestions(suggestionsToReturn);
4255
+ return dedupedSuggestions;
4177
4256
  }
4178
4257
  }
4179
- _getAugmentedTokens(pattern) {
4180
- var _a, _b;
4258
+ _getCustomTokens(pattern) {
4259
+ var _a;
4181
4260
  const customTokensMap = this._options.customTokens || {};
4182
- const leafPatterns = pattern.getPatterns();
4183
- /** Using Set to
4184
- * - prevent duplicates
4185
- * - prevent mutation of original customTokensMap
4186
- */
4187
- const customTokensForPattern = new Set((_a = customTokensMap[pattern.name]) !== null && _a !== void 0 ? _a : []);
4188
- for (const lp of leafPatterns) {
4189
- const augmentedTokens = (_b = customTokensMap[lp.name]) !== null && _b !== void 0 ? _b : [];
4190
- const lpsCombinedTokens = [...lp.getTokens(), ...augmentedTokens];
4191
- for (const token of lpsCombinedTokens) {
4192
- customTokensForPattern.add(token);
4261
+ const customTokens = (_a = customTokensMap[pattern.name]) !== null && _a !== void 0 ? _a : [];
4262
+ const allTokens = [...customTokens];
4263
+ return allTokens;
4264
+ }
4265
+ _deDupeCompositeSuggestions(suggestions) {
4266
+ if (this._options.disableDedupe) {
4267
+ return suggestions;
4268
+ }
4269
+ const seen = new Set();
4270
+ const unique = [];
4271
+ for (const suggestion of suggestions) {
4272
+ // Create a unique key based on text and subElements
4273
+ const subElementsKey = suggestion.suggestionSequence
4274
+ .map(sub => ` ${sub.pattern.name} - ${sub.text} `)
4275
+ .sort()
4276
+ .join('|');
4277
+ const key = `${suggestion.text}|${subElementsKey}`;
4278
+ if (!seen.has(key)) {
4279
+ seen.add(key);
4280
+ unique.push(suggestion);
4193
4281
  }
4194
4282
  }
4195
- return [...customTokensForPattern];
4283
+ return unique;
4196
4284
  }
4197
- _createSuggestions(lastIndex, tokens) {
4285
+ _createSuggestions(lastIndex, compositeSuggestionList) {
4198
4286
  let textToIndex = lastIndex === -1 ? "" : this._cursor.getChars(0, lastIndex);
4199
- const suggestionStrings = [];
4200
4287
  const options = [];
4201
- for (const token of tokens) {
4288
+ for (const compositeSuggestion of compositeSuggestionList) {
4202
4289
  // concatenated for start index identification inside createSuggestion
4203
- const suggestion = textToIndex + token;
4204
- const alreadyExist = suggestionStrings.includes(suggestion);
4205
- const isSameAsText = suggestion === this._text;
4206
- if (!alreadyExist && !isSameAsText) {
4207
- suggestionStrings.push(suggestion);
4208
- const suggestionOption = this._createSuggestion(this._cursor.text, suggestion);
4209
- options.push(suggestionOption);
4210
- }
4290
+ const existingTextWithSuggestion = textToIndex + compositeSuggestion.text;
4291
+ existingTextWithSuggestion === this._text;
4292
+ const suggestionOption = this._createSuggestionOption(this._cursor.text, existingTextWithSuggestion, compositeSuggestion.suggestionSequence);
4293
+ options.push(suggestionOption);
4294
+ // }
4211
4295
  }
4212
4296
  const reducedOptions = getFurthestOptions(options);
4213
4297
  reducedOptions.sort((a, b) => a.text.localeCompare(b.text));
4214
4298
  return reducedOptions;
4215
4299
  }
4216
- _createSuggestion(fullText, suggestion) {
4300
+ _createSuggestionOption(fullText, suggestion, segments) {
4217
4301
  const furthestMatch = findMatchIndex(suggestion, fullText);
4218
4302
  const text = suggestion.slice(furthestMatch);
4219
4303
  const option = {
4220
4304
  text: text,
4221
4305
  startIndex: furthestMatch,
4306
+ suggestionSequence: segments,
4222
4307
  };
4223
4308
  return option;
4224
4309
  }