autosuggestion
Version:
  Generates suggestions for text completion.  
129 lines • 5.15 kB
JavaScript
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};
import { Suggestion } from './suggestion';
var Node = /** @class */ (function () {
function Node(value) {
this.value = value;
this.end = false;
this.next = { char: {}, word: {}, lookup: {} };
}
Node.prototype.isLeaf = function () {
return Object.keys(this.next.char).length === 0
&& Object.keys(this.next.word).length === 0
&& Object.keys(this.next.lookup).length === 0;
};
/**
* Given an input sequence of words, a starting [[Node | node]], and
* a [[Dictionary | dictionary]], finds all valid matching paths that
* the input satisfies.
*
* #### Simple Example
* If we have a starting node which yields the following
* sub-trie,
* ```
* t - r - i - e
* \
* e - e
* ```
* and input *"tr"*, the returned node will be *"r"*.
*
* #### Advanced Example
* With a more complex starting trie,
* ```
* null - a - b - c - - d (1)
* \
* <X> - - d (2)
*
* <X>: null - a - b - c
* \
* <Y>
*
* <Y>: null - a - b - c - - d (3)
* ```
* given **"abc d"**, it wll return the **"d"** [[Node | nodes]] labeled
* _(1)_, _(2)_, _(3)_
*
* Since patterns can span multiple levels of nested contexts, we need to return
* not only the matched words (partially matched on completed words), but also the
* remainder of the match. This way, we can check for matches in parent contexts in
* case a pattern satisfies a match over an arbitrary number of contextual levels.
*/
Node.prototype.matchPattern = function (tokens) {
if (tokens.length === 0)
return [];
var matches = [];
// find matching paths from lookups
for (var _i = 0, _a = Object.entries(this.next.lookup); _i < _a.length; _i++) {
var _b = _a[_i], alias = _b[0], lookup = _b[1];
matches = matches.concat(lookup.matchPattern(tokens));
}
return matches.concat(this.matchWord(tokens));
};
Node.prototype.matchWord = function (tokens) {
var word = this.next.word[tokens[0][0]];
if (!word)
return [];
var node = word.matchChars(tokens[0]);
if (!node)
return [];
var match = { nodes: [node], remainder: tokens.slice(1) };
// (1) if there are no remainders keep searching. include match in results if it is a terminal.
// (2) if there are no remainders, return this single match (regardless of if it isa terminal).
return match.remainder.length > 0
? (node.end ? [match] : []).concat(node.matchPattern(match.remainder)) // (1)
: [match]; // (2)
};
/**
* Given an word, returns the final node which matches the complete word. null otherwise.
*/
Node.prototype.matchChars = function (word) {
if (this.value !== word[0])
return null;
var node = this;
word = word.substr(1);
while (word) {
node = node.next.char[word[0]];
if (!node)
return null;
word = word.substr(1);
}
return node;
};
Node.prototype.completePattern = function (tokens) {
var _a;
var suggestions = [];
// complete pattern in all next lookups
for (var _i = 0, _b = Object.entries(this.next.lookup); _i < _b.length; _i++) {
var _c = _b[_i], alias = _c[0], lookup = _c[1];
suggestions = suggestions.concat(lookup.completePattern(__spreadArrays(tokens, [(_a = {}, _a[lookup.value] = lookup.contexts, _a)])));
}
// complete pattern in all next words
for (var _d = 0, _e = Object.entries(this.next.word); _d < _e.length; _d++) {
var _f = _e[_d], char = _f[0], word = _f[1];
suggestions = suggestions.concat(word.completeWord(__spreadArrays(tokens, [char])));
}
return suggestions.concat(this.completeWord(tokens));
};
Node.prototype.completeWord = function (tokens) {
var suggestions = [];
// if this is an ending node, add it to suggestions
if (this.end)
suggestions.push(new Suggestion(__spreadArrays(tokens)));
var lastWord = tokens.pop() || '';
// augment the last token with the next characters
for (var _i = 0, _a = Object.values(this.next.char); _i < _a.length; _i++) {
var char = _a[_i];
var augmentedTokens = __spreadArrays(tokens, ["" + lastWord + char.value]);
suggestions = suggestions.concat(char.completePattern(augmentedTokens));
}
return suggestions;
};
return Node;
}());
export { Node };
//# sourceMappingURL=node.js.map