cspell-trie-lib 5.18.0-alpha.0 → 5.18.3
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/lib/distance/weightedMaps.d.ts +4 -2
- package/dist/lib/distance/weightedMaps.js +14 -3
- package/dist/lib/find.d.ts +8 -7
- package/dist/lib/find.js +6 -4
- package/dist/lib/index.d.ts +2 -1
- package/dist/lib/index.js +3 -1
- package/dist/lib/mappers/mapToSuggestionCostDef.js +2 -2
- package/dist/lib/suggestCollector.d.ts +1 -1
- package/dist/lib/suggestCollector.js +2 -1
- package/dist/lib/{genSuggestionsOptions.d.ts → suggestions/genSuggestionsOptions.d.ts} +6 -1
- package/dist/lib/{genSuggestionsOptions.js → suggestions/genSuggestionsOptions.js} +1 -0
- package/dist/lib/suggestions/suggest.d.ts +2 -2
- package/dist/lib/suggestions/suggest.js +5 -5
- package/dist/lib/suggestions/suggestAStar.d.ts +1 -1
- package/dist/lib/suggestions/suggestAStar.js +2 -2
- package/dist/lib/suggestions/suggestCollector.d.ts +24 -6
- package/dist/lib/suggestions/suggestCollector.js +62 -21
- package/dist/lib/suggestions/walker/hintedWalker.d.ts +22 -0
- package/dist/lib/suggestions/walker/hintedWalker.js +109 -0
- package/dist/lib/suggestions/walker/index.d.ts +5 -0
- package/dist/lib/suggestions/walker/index.js +18 -0
- package/dist/lib/suggestions/walker/walker.d.ts +8 -0
- package/dist/lib/suggestions/walker/walker.js +43 -0
- package/dist/lib/suggestions/walker/walkerTypes.d.ts +24 -0
- package/dist/lib/suggestions/walker/walkerTypes.js +21 -0
- package/dist/lib/trie-util.js +1 -2
- package/dist/lib/trie.d.ts +1 -1
- package/dist/lib/trie.js +10 -4
- package/dist/lib/types.d.ts +9 -0
- package/dist/lib/utils/util.d.ts +13 -0
- package/dist/lib/utils/util.js +25 -1
- package/dist/lib/walker.d.ts +1 -42
- package/dist/lib/walker.js +11 -151
- package/package.json +6 -6
|
@@ -74,11 +74,13 @@ export declare function prettyPrintReplace(trie: TrieTrieCost, pfx?: string, ind
|
|
|
74
74
|
export declare function prettyPrintSwap(trie: TrieTrieCost, pfx?: string, indent?: string): string;
|
|
75
75
|
export declare function prettyPrintWeightMap(map: WeightMap): string;
|
|
76
76
|
export declare function lookupReplaceCost(map: WeightMap, a: string, b: string): undefined | number;
|
|
77
|
+
declare function normalizeDef(def: SuggestionCostMapDef): SuggestionCostMapDef;
|
|
77
78
|
export declare const __testing__: {
|
|
78
|
-
splitMap: typeof splitMap;
|
|
79
|
-
splitMapSubstrings: typeof splitMapSubstrings;
|
|
80
79
|
findTrieCostPrefixes: typeof findTrieCostPrefixes;
|
|
81
80
|
findTrieTrieCostPrefixes: typeof findTrieTrieCostPrefixes;
|
|
81
|
+
normalizeDef: typeof normalizeDef;
|
|
82
|
+
splitMap: typeof splitMap;
|
|
83
|
+
splitMapSubstrings: typeof splitMapSubstrings;
|
|
82
84
|
};
|
|
83
85
|
export {};
|
|
84
86
|
//# sourceMappingURL=weightedMaps.d.ts.map
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.__testing__ = exports.lookupReplaceCost = exports.prettyPrintWeightMap = exports.prettyPrintSwap = exports.prettyPrintReplace = exports.splitMapSubstrings = exports.splitMapSubstringsIterable = exports.addDefsToWeightMap = exports.addDefToWeightMap = exports.createWeightMap = void 0;
|
|
4
|
+
const suggestCollector_1 = require("../suggestions/suggestCollector");
|
|
5
|
+
const matchPossibleWordSeparators = /[+∙•・●]/g;
|
|
4
6
|
function createWeightMap(...defs) {
|
|
5
7
|
const map = _createWeightMap();
|
|
6
8
|
addDefsToWeightMap(map, defs);
|
|
@@ -17,7 +19,8 @@ function addDefsToWeightMap(map, defs) {
|
|
|
17
19
|
addSetToTrieTrieCost(map.replace, set, def.replace, def.penalty);
|
|
18
20
|
addSetToTrieTrieCost(map.swap, set, def.swap, def.penalty);
|
|
19
21
|
}
|
|
20
|
-
for (const
|
|
22
|
+
for (const _def of defs) {
|
|
23
|
+
const def = normalizeDef(_def);
|
|
21
24
|
const mapSets = splitMap(def);
|
|
22
25
|
mapSets.forEach((s) => addSet(s, def));
|
|
23
26
|
}
|
|
@@ -262,10 +265,18 @@ function lookupReplaceCost(map, a, b) {
|
|
|
262
265
|
return t === null || t === void 0 ? void 0 : t.c;
|
|
263
266
|
}
|
|
264
267
|
exports.lookupReplaceCost = lookupReplaceCost;
|
|
268
|
+
function normalizeDef(def) {
|
|
269
|
+
const { map, ...rest } = def;
|
|
270
|
+
return { ...rest, map: normalizeMap(map) };
|
|
271
|
+
}
|
|
272
|
+
function normalizeMap(map) {
|
|
273
|
+
return map.replace(matchPossibleWordSeparators, suggestCollector_1.DEFAULT_COMPOUNDED_WORD_SEPARATOR);
|
|
274
|
+
}
|
|
265
275
|
exports.__testing__ = {
|
|
266
|
-
splitMap,
|
|
267
|
-
splitMapSubstrings,
|
|
268
276
|
findTrieCostPrefixes,
|
|
269
277
|
findTrieTrieCostPrefixes,
|
|
278
|
+
normalizeDef,
|
|
279
|
+
splitMap,
|
|
280
|
+
splitMapSubstrings,
|
|
270
281
|
};
|
|
271
282
|
//# sourceMappingURL=weightedMaps.js.map
|
package/dist/lib/find.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { TrieNode } from './TrieNode';
|
|
1
|
+
import { TrieNode, TrieRoot } from './TrieNode';
|
|
2
2
|
import type { PartialWithUndefined } from './types';
|
|
3
|
+
declare type Root = PartialWithUndefined<TrieRoot>;
|
|
3
4
|
/**
|
|
4
5
|
* No compounding allowed.
|
|
5
6
|
*/
|
|
@@ -48,20 +49,20 @@ export interface FindFullNodeResult extends FindNodeResult, FindFullResult {
|
|
|
48
49
|
* @param word A pre normalized word use `normalizeWord` or `normalizeWordToLowercase`
|
|
49
50
|
* @param options
|
|
50
51
|
*/
|
|
51
|
-
export declare function findWord(root:
|
|
52
|
+
export declare function findWord(root: Root, word: string, options?: PartialFindOptions): FindFullResult;
|
|
52
53
|
/**
|
|
53
54
|
*
|
|
54
55
|
* @param root Trie root node. root.c contains the compound root and forbidden root.
|
|
55
56
|
* @param word A pre normalized word use `normalizeWord` or `normalizeWordToLowercase`
|
|
56
57
|
* @param options
|
|
57
58
|
*/
|
|
58
|
-
export declare function findWordNode(root:
|
|
59
|
-
export declare function findLegacyCompound(root:
|
|
60
|
-
export declare function findCompoundNode(root:
|
|
61
|
-
export declare function findWordExact(root: TrieNode | undefined, word: string): boolean;
|
|
59
|
+
export declare function findWordNode(root: Root, word: string, options?: PartialFindOptions): FindFullNodeResult;
|
|
60
|
+
export declare function findLegacyCompound(root: Root, word: string, options: FindOptions): FindFullNodeResult;
|
|
61
|
+
export declare function findCompoundNode(root: Root | undefined, word: string, compoundCharacter: string, ignoreCasePrefix: string): FindFullNodeResult;
|
|
62
|
+
export declare function findWordExact(root: Root | TrieNode | undefined, word: string): boolean;
|
|
62
63
|
export declare function isEndOfWordNode(n: TrieNode | undefined): boolean;
|
|
63
64
|
declare function findLegacyCompoundWord(roots: (TrieNode | undefined)[], word: string, minCompoundLength: number): FindResult;
|
|
64
|
-
export declare function isForbiddenWord(root: TrieNode | undefined, word: string, forbiddenPrefix: string): boolean;
|
|
65
|
+
export declare function isForbiddenWord(root: Root | TrieNode | undefined, word: string, forbiddenPrefix: string): boolean;
|
|
65
66
|
export declare function createFindOptions(options: PartialFindOptions | undefined): FindOptions;
|
|
66
67
|
export declare const __testing__: {
|
|
67
68
|
findLegacyCompoundWord: typeof findLegacyCompoundWord;
|
package/dist/lib/find.js
CHANGED
|
@@ -42,8 +42,8 @@ exports.findWordNode = findWordNode;
|
|
|
42
42
|
* @param options
|
|
43
43
|
*/
|
|
44
44
|
function _findWord(root, word, options) {
|
|
45
|
-
const {
|
|
46
|
-
return
|
|
45
|
+
const { node: _, ...result } = _findWordNode(root, word, options);
|
|
46
|
+
return result;
|
|
47
47
|
}
|
|
48
48
|
/**
|
|
49
49
|
*
|
|
@@ -52,9 +52,10 @@ function _findWord(root, word, options) {
|
|
|
52
52
|
* @param options
|
|
53
53
|
*/
|
|
54
54
|
function _findWordNode(root, word, options) {
|
|
55
|
+
var _a, _b;
|
|
55
56
|
const compoundMode = knownCompoundModes.get(options.compoundMode) || _defaultFindOptions.compoundMode;
|
|
56
|
-
const compoundPrefix = options.compoundMode === 'compound' ? options.compoundFix : '';
|
|
57
|
-
const ignoreCasePrefix = options.matchCase ? '' : options.caseInsensitivePrefix;
|
|
57
|
+
const compoundPrefix = options.compoundMode === 'compound' ? (_a = root.compoundCharacter) !== null && _a !== void 0 ? _a : options.compoundFix : '';
|
|
58
|
+
const ignoreCasePrefix = options.matchCase ? '' : (_b = root.stripCaseAndAccentsPrefix) !== null && _b !== void 0 ? _b : options.caseInsensitivePrefix;
|
|
58
59
|
function __findCompound() {
|
|
59
60
|
const f = findCompoundWord(root, word, compoundPrefix, ignoreCasePrefix);
|
|
60
61
|
const result = { ...f };
|
|
@@ -99,6 +100,7 @@ function findCompoundNode(root, word, compoundCharacter, ignoreCasePrefix) {
|
|
|
99
100
|
var _a, _b, _c;
|
|
100
101
|
// Approach - do a depth first search for the matching word.
|
|
101
102
|
const stack = [
|
|
103
|
+
// { n: root, compoundPrefix: '', cr: undefined, caseMatched: true },
|
|
102
104
|
{ n: root, compoundPrefix: ignoreCasePrefix, cr: undefined, caseMatched: true },
|
|
103
105
|
];
|
|
104
106
|
const compoundPrefix = compoundCharacter || ignoreCasePrefix;
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -6,7 +6,8 @@ export { ExportOptions, importTrie, serializeTrie } from './io/importExport';
|
|
|
6
6
|
export { mapDictionaryInformationToWeightMap } from './mappers/mapDictionaryInfoToWeightMap';
|
|
7
7
|
export type { SuggestionCostMapDef } from './models/suggestionCostsDef';
|
|
8
8
|
export { parseDictionary, parseDictionaryLines } from './SimpleDictionaryParser';
|
|
9
|
-
export {
|
|
9
|
+
export { impersonateCollector, suggestionCollector } from './suggestCollector';
|
|
10
|
+
export type { MaxCost, SuggestionCollector, SuggestionResult } from './suggestCollector';
|
|
10
11
|
export { CASE_INSENSITIVE_PREFIX, COMPOUND, COMPOUND_FIX, defaultTrieOptions, FORBID, FORBID_PREFIX, NORMALIZED, OPTIONAL_COMPOUND, OPTIONAL_COMPOUND_FIX, Trie, } from './trie';
|
|
11
12
|
export type { FindWordOptions, PartialTrieOptions, TrieOptions } from './trie';
|
|
12
13
|
export { countNodes, countWords, createTrieRoot, createTriFromList, findNode, has, insert, isCircular, isDefined, isWordTerminationNode, iterateTrie, iteratorTrieWords, mergeDefaults, mergeOptionalWithDefaults, normalizeWord, normalizeWordForCaseInsensitive, normalizeWordToLowercase, orderTrie, trieNodeToRoot, walk, } from './trie-util';
|
package/dist/lib/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.walker = exports.JOIN_SEPARATOR = exports.hintedWalker = exports.CompoundWordsMethod = exports.FLAG_WORD = exports.ChildMap = exports.TrieBuilder = exports.buildTrieFast = exports.buildTrie = exports.walk = exports.trieNodeToRoot = exports.orderTrie = exports.normalizeWordToLowercase = exports.normalizeWordForCaseInsensitive = exports.normalizeWord = exports.mergeOptionalWithDefaults = exports.mergeDefaults = exports.iteratorTrieWords = exports.iterateTrie = exports.isWordTerminationNode = exports.isDefined = exports.isCircular = exports.insert = exports.has = exports.findNode = exports.createTriFromList = exports.createTrieRoot = exports.countWords = exports.countNodes = exports.Trie = exports.OPTIONAL_COMPOUND_FIX = exports.OPTIONAL_COMPOUND = exports.NORMALIZED = exports.FORBID_PREFIX = exports.FORBID = exports.defaultTrieOptions = exports.COMPOUND_FIX = exports.COMPOUND = exports.CASE_INSENSITIVE_PREFIX = exports.suggestionCollector = exports.impersonateCollector = exports.parseDictionaryLines = exports.parseDictionary = exports.mapDictionaryInformationToWeightMap = exports.serializeTrie = exports.importTrie = exports.editDistanceWeighted = exports.editDistance = exports.createWeightedMap = exports.consolidate = void 0;
|
|
4
|
+
exports.WORD_SEPARATOR = void 0;
|
|
4
5
|
var consolidate_1 = require("./consolidate");
|
|
5
6
|
Object.defineProperty(exports, "consolidate", { enumerable: true, get: function () { return consolidate_1.consolidate; } });
|
|
6
7
|
var distance_1 = require("./distance");
|
|
@@ -16,6 +17,7 @@ var SimpleDictionaryParser_1 = require("./SimpleDictionaryParser");
|
|
|
16
17
|
Object.defineProperty(exports, "parseDictionary", { enumerable: true, get: function () { return SimpleDictionaryParser_1.parseDictionary; } });
|
|
17
18
|
Object.defineProperty(exports, "parseDictionaryLines", { enumerable: true, get: function () { return SimpleDictionaryParser_1.parseDictionaryLines; } });
|
|
18
19
|
var suggestCollector_1 = require("./suggestCollector");
|
|
20
|
+
Object.defineProperty(exports, "impersonateCollector", { enumerable: true, get: function () { return suggestCollector_1.impersonateCollector; } });
|
|
19
21
|
Object.defineProperty(exports, "suggestionCollector", { enumerable: true, get: function () { return suggestCollector_1.suggestionCollector; } });
|
|
20
22
|
var trie_1 = require("./trie");
|
|
21
23
|
Object.defineProperty(exports, "CASE_INSENSITIVE_PREFIX", { enumerable: true, get: function () { return trie_1.CASE_INSENSITIVE_PREFIX; } });
|
|
@@ -51,14 +51,14 @@ function calcFirstCharacterReplace(cs, editCost) {
|
|
|
51
51
|
...(0, cspell_pipe_1.pipeSync)((0, text_1.expandCharacterSet)(cs.characters), (0, cspell_pipe_1.opUnique)(), (0, cspell_pipe_1.opMap)((letter) => `(^${letter})`)),
|
|
52
52
|
]
|
|
53
53
|
.sort()
|
|
54
|
-
.join('');
|
|
54
|
+
.join('') + '(^)';
|
|
55
55
|
const penalty = editCost.firstLetterPenalty;
|
|
56
56
|
// Make it a bit cheaper so it will match
|
|
57
57
|
const cost = cs.cost - penalty;
|
|
58
58
|
return {
|
|
59
59
|
map: mapOfFirstLetters,
|
|
60
60
|
replace: cost,
|
|
61
|
-
penalty,
|
|
61
|
+
penalty: penalty * 2,
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
64
|
exports.calcFirstCharacterReplace = calcFirstCharacterReplace;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* This file is here to support code the referenced suggest directly and limit the exports.
|
|
3
3
|
*/
|
|
4
|
-
export { compSuggestionResults, defaultSuggestionCollectorOptions, isSuggestionResult, suggestionCollector, } from './suggestions/suggestCollector';
|
|
4
|
+
export { compSuggestionResults, defaultSuggestionCollectorOptions, impersonateCollector, isSuggestionResult, suggestionCollector, } from './suggestions/suggestCollector';
|
|
5
5
|
export type { Cost, FilterWordFn, GenerateNextParam, GenerateSuggestionResult, MaxCost, Progress, SuggestionCollector, SuggestionCollectorOptions, SuggestionGenerator, SuggestionResult, } from './suggestions/suggestCollector';
|
|
6
6
|
//# sourceMappingURL=suggestCollector.d.ts.map
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.suggestionCollector = exports.isSuggestionResult = exports.defaultSuggestionCollectorOptions = exports.compSuggestionResults = void 0;
|
|
3
|
+
exports.suggestionCollector = exports.isSuggestionResult = exports.impersonateCollector = exports.defaultSuggestionCollectorOptions = exports.compSuggestionResults = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* This file is here to support code the referenced suggest directly and limit the exports.
|
|
6
6
|
*/
|
|
7
7
|
var suggestCollector_1 = require("./suggestions/suggestCollector");
|
|
8
8
|
Object.defineProperty(exports, "compSuggestionResults", { enumerable: true, get: function () { return suggestCollector_1.compSuggestionResults; } });
|
|
9
9
|
Object.defineProperty(exports, "defaultSuggestionCollectorOptions", { enumerable: true, get: function () { return suggestCollector_1.defaultSuggestionCollectorOptions; } });
|
|
10
|
+
Object.defineProperty(exports, "impersonateCollector", { enumerable: true, get: function () { return suggestCollector_1.impersonateCollector; } });
|
|
10
11
|
Object.defineProperty(exports, "isSuggestionResult", { enumerable: true, get: function () { return suggestCollector_1.isSuggestionResult; } });
|
|
11
12
|
Object.defineProperty(exports, "suggestionCollector", { enumerable: true, get: function () { return suggestCollector_1.suggestionCollector; } });
|
|
12
13
|
//# sourceMappingURL=suggestCollector.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { WeightMap } from '
|
|
1
|
+
import { WeightMap } from '..';
|
|
2
2
|
import { CompoundWordsMethod } from './walker';
|
|
3
3
|
export interface GenSuggestionOptionsStrict {
|
|
4
4
|
/**
|
|
@@ -15,6 +15,11 @@ export interface GenSuggestionOptionsStrict {
|
|
|
15
15
|
* 3 is a good number. Above 5 can be very slow.
|
|
16
16
|
*/
|
|
17
17
|
changeLimit: number;
|
|
18
|
+
/**
|
|
19
|
+
* Inserts a compound character between compounded word segments.
|
|
20
|
+
* @default ""
|
|
21
|
+
*/
|
|
22
|
+
compoundSeparator?: string;
|
|
18
23
|
}
|
|
19
24
|
export declare type GenSuggestionOptions = Partial<GenSuggestionOptionsStrict>;
|
|
20
25
|
export interface SuggestionOptionsStrict extends GenSuggestionOptionsStrict {
|
|
@@ -17,6 +17,7 @@ const keyMapOfGenSuggestionOptionsStrict = {
|
|
|
17
17
|
changeLimit: 'changeLimit',
|
|
18
18
|
compoundMethod: 'compoundMethod',
|
|
19
19
|
ignoreCase: 'ignoreCase',
|
|
20
|
+
compoundSeparator: 'compoundSeparator',
|
|
20
21
|
};
|
|
21
22
|
const keyMapOfSuggestionOptionsStrict = {
|
|
22
23
|
...keyMapOfGenSuggestionOptionsStrict,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { GenSuggestionOptions, SuggestionOptions } from '../genSuggestionsOptions';
|
|
2
|
-
import { SuggestionGenerator, SuggestionResult } from './suggestCollector';
|
|
3
1
|
import { TrieRoot } from '../TrieNode';
|
|
2
|
+
import { GenSuggestionOptions, SuggestionOptions } from './genSuggestionsOptions';
|
|
3
|
+
import { SuggestionGenerator, SuggestionResult } from './suggestCollector';
|
|
4
4
|
export declare function suggest(root: TrieRoot | TrieRoot[], word: string, options?: SuggestionOptions): SuggestionResult[];
|
|
5
5
|
export declare function genSuggestions(root: TrieRoot | TrieRoot[], word: string, options?: GenSuggestionOptions): SuggestionGenerator;
|
|
6
6
|
export declare function genCompoundableSuggestions(root: TrieRoot, word: string, options?: GenSuggestionOptions): SuggestionGenerator;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.genCompoundableSuggestions = exports.genSuggestions = exports.suggest = void 0;
|
|
4
|
-
const
|
|
4
|
+
const trie_util_1 = require("../trie-util");
|
|
5
|
+
const genSuggestionsOptions_1 = require("./genSuggestionsOptions");
|
|
5
6
|
const orthography_1 = require("./orthography");
|
|
6
7
|
const suggestCollector_1 = require("./suggestCollector");
|
|
7
|
-
const
|
|
8
|
-
const walker_1 = require("../walker");
|
|
8
|
+
const walker_1 = require("./walker");
|
|
9
9
|
const baseCost = 100;
|
|
10
10
|
const swapCost = 75;
|
|
11
11
|
const postSwapCost = swapCost - baseCost;
|
|
@@ -18,7 +18,7 @@ function suggest(root, word, options = {}) {
|
|
|
18
18
|
const opts = (0, genSuggestionsOptions_1.createSuggestionOptions)(options);
|
|
19
19
|
const collectorOpts = (0, trie_util_1.clean)(opts);
|
|
20
20
|
const collector = (0, suggestCollector_1.suggestionCollector)(word, collectorOpts);
|
|
21
|
-
collector.collect(genSuggestions(root, word, opts));
|
|
21
|
+
collector.collect(genSuggestions(root, word, { ...opts, ...collector.genSuggestionOptions }));
|
|
22
22
|
return collector.suggestions;
|
|
23
23
|
}
|
|
24
24
|
exports.suggest = suggest;
|
|
@@ -68,7 +68,7 @@ function* genCompoundableSuggestions(root, word, options = {}) {
|
|
|
68
68
|
}
|
|
69
69
|
stack[0] = { a, b };
|
|
70
70
|
const hint = word;
|
|
71
|
-
const iWalk = (0, walker_1.hintedWalker)(root, ignoreCase, hint, compoundMethod);
|
|
71
|
+
const iWalk = (0, walker_1.hintedWalker)(root, ignoreCase, hint, compoundMethod, options.compoundSeparator);
|
|
72
72
|
let goDeeper = true;
|
|
73
73
|
for (let r = iWalk.next({ goDeeper }); !stopNow && !r.done; r = iWalk.next({ goDeeper })) {
|
|
74
74
|
const { text, node, depth } = r.value;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TrieRoot } from '../TrieNode';
|
|
2
2
|
import { SuggestionGenerator, SuggestionResult } from './suggestCollector';
|
|
3
|
-
import { GenSuggestionOptionsStrict, SuggestionOptions } from '
|
|
3
|
+
import { GenSuggestionOptionsStrict, SuggestionOptions } from './genSuggestionsOptions';
|
|
4
4
|
export declare function genCompoundableSuggestions(root: TrieRoot, word: string, options: GenSuggestionOptionsStrict): SuggestionGenerator;
|
|
5
5
|
export declare function suggest(root: TrieRoot | TrieRoot[], word: string, options: SuggestionOptions): SuggestionResult[];
|
|
6
6
|
export declare function genSuggestions(root: TrieRoot | TrieRoot[], word: string, options: GenSuggestionOptionsStrict): SuggestionGenerator;
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.genSuggestions = exports.suggest = exports.genCompoundableSuggestions = void 0;
|
|
4
|
-
const walker_1 = require("
|
|
4
|
+
const walker_1 = require("./walker");
|
|
5
5
|
const suggestCollector_1 = require("./suggestCollector");
|
|
6
6
|
const PairingHeap_1 = require("../utils/PairingHeap");
|
|
7
7
|
const orthography_1 = require("./orthography");
|
|
8
|
-
const genSuggestionsOptions_1 = require("
|
|
8
|
+
const genSuggestionsOptions_1 = require("./genSuggestionsOptions");
|
|
9
9
|
function* genCompoundableSuggestions(root, word, options) {
|
|
10
10
|
const { compoundMethod, ignoreCase, changeLimit } = options;
|
|
11
11
|
const len = word.length;
|
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
import { WeightMap } from '..';
|
|
2
|
+
import { RequireOptional } from '../types';
|
|
3
|
+
import { GenSuggestionOptions, GenSuggestionOptionsStrict } from './genSuggestionsOptions';
|
|
4
|
+
export declare const DEFAULT_COMPOUNDED_WORD_SEPARATOR = "\u2219";
|
|
2
5
|
export declare type Cost = number;
|
|
3
6
|
export declare type MaxCost = Cost;
|
|
4
|
-
export interface
|
|
7
|
+
export interface SuggestionResultBase {
|
|
8
|
+
/** The suggested word */
|
|
5
9
|
word: string;
|
|
10
|
+
/** The edit cost 100 = 1 edit */
|
|
6
11
|
cost: Cost;
|
|
7
12
|
}
|
|
13
|
+
export interface SuggestionResult extends SuggestionResultBase {
|
|
14
|
+
/** The suggested word with compound marks, generally a `•` */
|
|
15
|
+
compoundWord?: string | undefined;
|
|
16
|
+
}
|
|
8
17
|
export interface Progress {
|
|
9
18
|
type: 'progress';
|
|
10
19
|
/** Number of Completed Tasks so far */
|
|
@@ -16,7 +25,7 @@ export interface Progress {
|
|
|
16
25
|
remaining: number;
|
|
17
26
|
}
|
|
18
27
|
export declare type GenerateNextParam = MaxCost | symbol | undefined;
|
|
19
|
-
export declare type GenerateSuggestionResult =
|
|
28
|
+
export declare type GenerateSuggestionResult = SuggestionResultBase | Progress | undefined;
|
|
20
29
|
/**
|
|
21
30
|
* Ask for the next result.
|
|
22
31
|
* maxCost - sets the max cost for following suggestions
|
|
@@ -26,7 +35,7 @@ export declare type GenerateSuggestionResult = SuggestionResult | Progress | und
|
|
|
26
35
|
* The SuggestionIterator is generally the
|
|
27
36
|
*/
|
|
28
37
|
export declare type SuggestionGenerator = Generator<GenerateSuggestionResult, void, GenerateNextParam>;
|
|
29
|
-
export declare function compSuggestionResults(a:
|
|
38
|
+
export declare function compSuggestionResults(a: SuggestionResultBase, b: SuggestionResultBase): number;
|
|
30
39
|
export declare type FilterWordFn = (word: string, cost: number) => boolean;
|
|
31
40
|
export interface SuggestionCollector {
|
|
32
41
|
/**
|
|
@@ -40,7 +49,7 @@ export interface SuggestionCollector {
|
|
|
40
49
|
* if (r === collector.symbolStopProcessing) // ...stop generating suggestions.
|
|
41
50
|
*/
|
|
42
51
|
collect: (src: SuggestionGenerator, timeout?: number, filter?: FilterWordFn) => void;
|
|
43
|
-
add: (suggestion:
|
|
52
|
+
add: (suggestion: SuggestionResultBase) => SuggestionCollector;
|
|
44
53
|
readonly suggestions: SuggestionResult[];
|
|
45
54
|
readonly changeLimit: number;
|
|
46
55
|
readonly maxCost: number;
|
|
@@ -48,12 +57,13 @@ export interface SuggestionCollector {
|
|
|
48
57
|
readonly maxNumSuggestions: number;
|
|
49
58
|
readonly includesTies: boolean;
|
|
50
59
|
readonly ignoreCase: boolean;
|
|
60
|
+
readonly genSuggestionOptions: GenSuggestionOptions;
|
|
51
61
|
/**
|
|
52
62
|
* Possible value sent to the SuggestionIterator telling it to stop processing.
|
|
53
63
|
*/
|
|
54
64
|
readonly symbolStopProcessing: symbol;
|
|
55
65
|
}
|
|
56
|
-
export interface SuggestionCollectorOptions {
|
|
66
|
+
export interface SuggestionCollectorOptions extends Omit<GenSuggestionOptionsStrict, 'ignoreCase' | 'changeLimit'> {
|
|
57
67
|
/**
|
|
58
68
|
* number of best matching suggestions.
|
|
59
69
|
* @default 10
|
|
@@ -90,7 +100,15 @@ export interface SuggestionCollectorOptions {
|
|
|
90
100
|
*/
|
|
91
101
|
weightMap?: WeightMap | undefined;
|
|
92
102
|
}
|
|
93
|
-
export declare const defaultSuggestionCollectorOptions: SuggestionCollectorOptions
|
|
103
|
+
export declare const defaultSuggestionCollectorOptions: RequireOptional<SuggestionCollectorOptions>;
|
|
94
104
|
export declare function suggestionCollector(wordToMatch: string, options: SuggestionCollectorOptions): SuggestionCollector;
|
|
105
|
+
/**
|
|
106
|
+
* Impersonating a Collector, allows searching for multiple variants on the same word.
|
|
107
|
+
* The collection is still in the original collector.
|
|
108
|
+
* @param collector - collector to impersonate
|
|
109
|
+
* @param word - word to present instead of `collector.word`.
|
|
110
|
+
* @returns a SuggestionCollector
|
|
111
|
+
*/
|
|
112
|
+
export declare function impersonateCollector(collector: SuggestionCollector, word: string): SuggestionCollector;
|
|
95
113
|
export declare function isSuggestionResult(s: GenerateSuggestionResult): s is SuggestionResult;
|
|
96
114
|
//# sourceMappingURL=suggestCollector.d.ts.map
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isSuggestionResult = exports.suggestionCollector = exports.defaultSuggestionCollectorOptions = exports.compSuggestionResults = void 0;
|
|
3
|
+
exports.isSuggestionResult = exports.impersonateCollector = exports.suggestionCollector = exports.defaultSuggestionCollectorOptions = exports.compSuggestionResults = exports.DEFAULT_COMPOUNDED_WORD_SEPARATOR = void 0;
|
|
4
4
|
const __1 = require("..");
|
|
5
|
+
const weightedMaps_1 = require("../distance/weightedMaps");
|
|
5
6
|
const timer_1 = require("../utils/timer");
|
|
6
|
-
const
|
|
7
|
+
const util_1 = require("../utils/util");
|
|
8
|
+
const walker_1 = require("./walker");
|
|
7
9
|
const defaultMaxNumberSuggestions = 10;
|
|
8
10
|
const BASE_COST = 100;
|
|
9
11
|
const MAX_NUM_CHANGES = 5;
|
|
@@ -11,9 +13,12 @@ const MAX_COST_SCALE = 0.5;
|
|
|
11
13
|
// max allowed cost scale should be a bit over 50% to allow for suggestions to short words, but not too high to have too many suggestions.
|
|
12
14
|
const MAX_ALLOWED_COST_SCALE = 1.03 * MAX_COST_SCALE;
|
|
13
15
|
const collator = new Intl.Collator();
|
|
14
|
-
|
|
16
|
+
// This is a bit broken, it was supposed to also include JOIN_SEPARATOR (`+`)
|
|
17
|
+
// Add it back later.
|
|
18
|
+
const regexSeparator = new RegExp(`[${(0, util_1.regexQuote)(walker_1.WORD_SEPARATOR)}]`, 'g');
|
|
15
19
|
const wordLengthCost = [0, 50, 25, 5, 0];
|
|
16
20
|
const EXTRA_WORD_COST = 5;
|
|
21
|
+
exports.DEFAULT_COMPOUNDED_WORD_SEPARATOR = '∙';
|
|
17
22
|
/** time in ms */
|
|
18
23
|
const DEFAULT_COLLECTOR_TIMEOUT = 1000;
|
|
19
24
|
const symStopProcessing = Symbol('Collector Stop Processing');
|
|
@@ -29,12 +34,28 @@ exports.defaultSuggestionCollectorOptions = Object.freeze({
|
|
|
29
34
|
includeTies: false,
|
|
30
35
|
ignoreCase: true,
|
|
31
36
|
timeout: DEFAULT_COLLECTOR_TIMEOUT,
|
|
37
|
+
weightMap: undefined,
|
|
38
|
+
compoundSeparator: '',
|
|
39
|
+
compoundMethod: undefined,
|
|
32
40
|
});
|
|
33
41
|
function suggestionCollector(wordToMatch, options) {
|
|
34
|
-
const { filter = () => true, changeLimit = MAX_NUM_CHANGES, includeTies = false, ignoreCase = true, timeout = DEFAULT_COLLECTOR_TIMEOUT, weightMap, } = options;
|
|
42
|
+
const { filter = () => true, changeLimit = MAX_NUM_CHANGES, includeTies = false, ignoreCase = true, timeout = DEFAULT_COLLECTOR_TIMEOUT, weightMap, compoundSeparator = exports.defaultSuggestionCollectorOptions.compoundSeparator, } = options;
|
|
35
43
|
const numSuggestions = Math.max(options.numSuggestions, 0) || 0;
|
|
44
|
+
const numSugToHold = weightMap ? numSuggestions * 2 : numSuggestions;
|
|
36
45
|
const sugs = new Map();
|
|
37
46
|
let maxCost = BASE_COST * Math.min(wordToMatch.length * MAX_ALLOWED_COST_SCALE, changeLimit);
|
|
47
|
+
const useSeparator = compoundSeparator ||
|
|
48
|
+
(weightMap ? exports.DEFAULT_COMPOUNDED_WORD_SEPARATOR : exports.defaultSuggestionCollectorOptions.compoundSeparator);
|
|
49
|
+
const fnCleanWord = !useSeparator || useSeparator === compoundSeparator ? (w) => w : (0, util_1.replaceAllFactory)(useSeparator, '');
|
|
50
|
+
if (useSeparator && weightMap) {
|
|
51
|
+
(0, weightedMaps_1.addDefToWeightMap)(weightMap, { map: useSeparator, insDel: 50 });
|
|
52
|
+
}
|
|
53
|
+
const genSuggestionOptions = (0, util_1.clean)({
|
|
54
|
+
changeLimit,
|
|
55
|
+
ignoreCase,
|
|
56
|
+
compoundMethod: options.compoundMethod,
|
|
57
|
+
compoundSeparator: useSeparator,
|
|
58
|
+
});
|
|
38
59
|
let timeRemaining = timeout;
|
|
39
60
|
function dropMax() {
|
|
40
61
|
if (sugs.size < 2 || !numSuggestions) {
|
|
@@ -42,7 +63,7 @@ function suggestionCollector(wordToMatch, options) {
|
|
|
42
63
|
return;
|
|
43
64
|
}
|
|
44
65
|
const sorted = [...sugs.values()].sort(compSuggestionResults);
|
|
45
|
-
let i =
|
|
66
|
+
let i = numSugToHold - 1;
|
|
46
67
|
maxCost = sorted[i].cost;
|
|
47
68
|
for (; i < sorted.length && sorted[i].cost <= maxCost; ++i) {
|
|
48
69
|
/* empty */
|
|
@@ -57,9 +78,6 @@ function suggestionCollector(wordToMatch, options) {
|
|
|
57
78
|
(words.length - 1) * EXTRA_WORD_COST;
|
|
58
79
|
return { word: sug.word, cost: sug.cost + extraCost };
|
|
59
80
|
}
|
|
60
|
-
function handleProgress(_progress) {
|
|
61
|
-
// Do nothing.
|
|
62
|
-
}
|
|
63
81
|
function collectSuggestion(suggestion) {
|
|
64
82
|
const { word, cost } = adjustCost(suggestion);
|
|
65
83
|
if (cost <= maxCost && filter(suggestion.word, cost)) {
|
|
@@ -69,7 +87,7 @@ function suggestionCollector(wordToMatch, options) {
|
|
|
69
87
|
}
|
|
70
88
|
else {
|
|
71
89
|
sugs.set(word, { word, cost });
|
|
72
|
-
if (cost < maxCost && sugs.size >
|
|
90
|
+
if (cost < maxCost && sugs.size > numSugToHold) {
|
|
73
91
|
dropMax();
|
|
74
92
|
}
|
|
75
93
|
}
|
|
@@ -102,11 +120,24 @@ function suggestionCollector(wordToMatch, options) {
|
|
|
102
120
|
}
|
|
103
121
|
continue;
|
|
104
122
|
}
|
|
105
|
-
handleProgress(value);
|
|
106
123
|
}
|
|
107
124
|
timeRemaining -= timer.elapsed();
|
|
108
125
|
}
|
|
126
|
+
function cleanCompoundResult(sr) {
|
|
127
|
+
const { word, cost } = sr;
|
|
128
|
+
const cWord = fnCleanWord(word);
|
|
129
|
+
if (cWord !== word) {
|
|
130
|
+
return {
|
|
131
|
+
word: cWord,
|
|
132
|
+
cost,
|
|
133
|
+
compoundWord: word,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
return { ...sr };
|
|
137
|
+
}
|
|
109
138
|
function suggestions() {
|
|
139
|
+
if (numSuggestions < 1 || !sugs.size)
|
|
140
|
+
return [];
|
|
110
141
|
const NF = 'NFD';
|
|
111
142
|
const nWordToMatch = wordToMatch.normalize(NF);
|
|
112
143
|
const rawValues = [...sugs.values()];
|
|
@@ -116,10 +147,14 @@ function suggestionCollector(wordToMatch, options) {
|
|
|
116
147
|
cost: (0, __1.editDistanceWeighted)(nWordToMatch, word.normalize(NF), weightMap, 110),
|
|
117
148
|
}))
|
|
118
149
|
: rawValues;
|
|
119
|
-
const sorted = values.sort(compSuggestionResults);
|
|
120
|
-
|
|
121
|
-
|
|
150
|
+
const sorted = values.sort(compSuggestionResults).map(cleanCompoundResult);
|
|
151
|
+
let i = Math.min(sorted.length, numSuggestions) - 1;
|
|
152
|
+
const limit = includeTies ? sorted.length : Math.min(sorted.length, numSuggestions);
|
|
153
|
+
const maxCost = sorted[i].cost;
|
|
154
|
+
for (++i; i < limit && sorted[i].cost === maxCost; ++i) {
|
|
155
|
+
// loop
|
|
122
156
|
}
|
|
157
|
+
sorted.length = i;
|
|
123
158
|
return sorted;
|
|
124
159
|
}
|
|
125
160
|
const collector = {
|
|
@@ -146,21 +181,27 @@ function suggestionCollector(wordToMatch, options) {
|
|
|
146
181
|
includesTies: includeTies,
|
|
147
182
|
ignoreCase,
|
|
148
183
|
symbolStopProcessing: symStopProcessing,
|
|
184
|
+
genSuggestionOptions,
|
|
149
185
|
};
|
|
150
186
|
return collector;
|
|
151
187
|
}
|
|
152
188
|
exports.suggestionCollector = suggestionCollector;
|
|
189
|
+
/**
|
|
190
|
+
* Impersonating a Collector, allows searching for multiple variants on the same word.
|
|
191
|
+
* The collection is still in the original collector.
|
|
192
|
+
* @param collector - collector to impersonate
|
|
193
|
+
* @param word - word to present instead of `collector.word`.
|
|
194
|
+
* @returns a SuggestionCollector
|
|
195
|
+
*/
|
|
196
|
+
function impersonateCollector(collector, word) {
|
|
197
|
+
const r = Object.create(collector);
|
|
198
|
+
Object.defineProperty(r, 'word', { value: word, writable: false });
|
|
199
|
+
return r;
|
|
200
|
+
}
|
|
201
|
+
exports.impersonateCollector = impersonateCollector;
|
|
153
202
|
function isSuggestionResult(s) {
|
|
154
203
|
const r = s;
|
|
155
204
|
return (r === null || r === void 0 ? void 0 : r.cost) !== undefined && r.word != undefined;
|
|
156
205
|
}
|
|
157
206
|
exports.isSuggestionResult = isSuggestionResult;
|
|
158
|
-
/**
|
|
159
|
-
*
|
|
160
|
-
* @param text verbatim text to be inserted into a regexp
|
|
161
|
-
* @returns text that can be used in a regexp.
|
|
162
|
-
*/
|
|
163
|
-
function regexQuote(text) {
|
|
164
|
-
return text.replace(/[[\]\-+(){},|*.\\]/g, '\\$1');
|
|
165
|
-
}
|
|
166
207
|
//# sourceMappingURL=suggestCollector.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { TrieRoot } from '../../TrieNode';
|
|
2
|
+
import { CompoundWordsMethod, YieldResult } from './walkerTypes';
|
|
3
|
+
/**
|
|
4
|
+
* Ask for the next result.
|
|
5
|
+
* goDeeper of true tells the walker to go deeper in the Trie if possible. Default is true.
|
|
6
|
+
* This can be used to limit the walker's depth.
|
|
7
|
+
*/
|
|
8
|
+
export declare type HintedWalkerIterator = Generator<YieldResult, void, Hinting | undefined>;
|
|
9
|
+
export declare function hintedWalker(root: TrieRoot, ignoreCase: boolean, hint: string, compoundingMethod: CompoundWordsMethod | undefined, emitWordSeparator?: string): HintedWalkerIterator;
|
|
10
|
+
/**
|
|
11
|
+
* Walks the Trie and yields a value at each node.
|
|
12
|
+
* next(goDeeper: boolean):
|
|
13
|
+
*/
|
|
14
|
+
declare function hintedWalkerNext(root: TrieRoot, ignoreCase: boolean, hint: string, compoundingMethod: CompoundWordsMethod | undefined, emitWordSeparator?: string): HintedWalkerIterator;
|
|
15
|
+
export interface Hinting {
|
|
16
|
+
goDeeper: boolean;
|
|
17
|
+
}
|
|
18
|
+
export declare const __testing__: {
|
|
19
|
+
hintedWalkerNext: typeof hintedWalkerNext;
|
|
20
|
+
};
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=hintedWalker.d.ts.map
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.__testing__ = exports.hintedWalker = void 0;
|
|
4
|
+
const trie_util_1 = require("../../trie-util");
|
|
5
|
+
const walkerTypes_1 = require("./walkerTypes");
|
|
6
|
+
function hintedWalker(root, ignoreCase, hint, compoundingMethod, emitWordSeparator) {
|
|
7
|
+
return hintedWalkerNext(root, ignoreCase, hint, compoundingMethod, emitWordSeparator);
|
|
8
|
+
}
|
|
9
|
+
exports.hintedWalker = hintedWalker;
|
|
10
|
+
/**
|
|
11
|
+
* Walks the Trie and yields a value at each node.
|
|
12
|
+
* next(goDeeper: boolean):
|
|
13
|
+
*/
|
|
14
|
+
function* hintedWalkerNext(root, ignoreCase, hint, compoundingMethod, emitWordSeparator = '') {
|
|
15
|
+
const _compoundingMethod = compoundingMethod !== null && compoundingMethod !== void 0 ? compoundingMethod : walkerTypes_1.CompoundWordsMethod.NONE;
|
|
16
|
+
const compoundCharacter = root.compoundCharacter;
|
|
17
|
+
const noCaseCharacter = root.stripCaseAndAccentsPrefix;
|
|
18
|
+
const rawRoots = [root, ignoreCase ? root.c.get(noCaseCharacter) : undefined].filter(trie_util_1.isDefined);
|
|
19
|
+
const specialRootsPrefix = existMap([compoundCharacter, noCaseCharacter, root.forbiddenWordPrefix]);
|
|
20
|
+
function filterRoot(root) {
|
|
21
|
+
var _a;
|
|
22
|
+
const children = (_a = root.c) === null || _a === void 0 ? void 0 : _a.entries();
|
|
23
|
+
const c = children && [...children].filter(([v]) => !(v in specialRootsPrefix));
|
|
24
|
+
return {
|
|
25
|
+
c: c && new Map(c),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
const roots = rawRoots.map(filterRoot);
|
|
29
|
+
const compoundRoots = rawRoots.map((r) => { var _a; return (_a = r.c) === null || _a === void 0 ? void 0 : _a.get(compoundCharacter); }).filter(trie_util_1.isDefined);
|
|
30
|
+
const setOfCompoundRoots = new Set(compoundRoots);
|
|
31
|
+
const rootsForCompoundMethods = roots.concat(compoundRoots);
|
|
32
|
+
const compoundMethodRoots = {
|
|
33
|
+
[walkerTypes_1.CompoundWordsMethod.NONE]: [],
|
|
34
|
+
[walkerTypes_1.CompoundWordsMethod.JOIN_WORDS]: [...rootsForCompoundMethods.map((r) => [walkerTypes_1.JOIN_SEPARATOR, r])],
|
|
35
|
+
[walkerTypes_1.CompoundWordsMethod.SEPARATE_WORDS]: [...rootsForCompoundMethods.map((r) => [walkerTypes_1.WORD_SEPARATOR, r])],
|
|
36
|
+
};
|
|
37
|
+
function* children(n, hintOffset) {
|
|
38
|
+
if (n.c) {
|
|
39
|
+
const h = hint.slice(hintOffset, hintOffset + 3) + hint.slice(Math.max(0, hintOffset - 2), hintOffset);
|
|
40
|
+
const hints = new Set(h);
|
|
41
|
+
const c = n.c;
|
|
42
|
+
// First yield the hints
|
|
43
|
+
yield* [...hints]
|
|
44
|
+
.filter((a) => c.has(a))
|
|
45
|
+
.map((letter) => ({
|
|
46
|
+
letter,
|
|
47
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
48
|
+
node: c.get(letter),
|
|
49
|
+
hintOffset: hintOffset + 1,
|
|
50
|
+
}));
|
|
51
|
+
// We don't want to suggest the compound character.
|
|
52
|
+
hints.add(compoundCharacter);
|
|
53
|
+
// Then yield everything else.
|
|
54
|
+
yield* [...c]
|
|
55
|
+
.filter((a) => !hints.has(a[0]))
|
|
56
|
+
.map(([letter, node]) => ({
|
|
57
|
+
letter,
|
|
58
|
+
node,
|
|
59
|
+
hintOffset: hintOffset + 1,
|
|
60
|
+
}));
|
|
61
|
+
if (c.has(compoundCharacter) && !setOfCompoundRoots.has(n)) {
|
|
62
|
+
for (const compoundRoot of compoundRoots) {
|
|
63
|
+
for (const child of children(compoundRoot, hintOffset)) {
|
|
64
|
+
const { letter, node, hintOffset } = child;
|
|
65
|
+
yield { letter: emitWordSeparator + letter, node, hintOffset };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
if (n.f) {
|
|
71
|
+
yield* [...compoundMethodRoots[_compoundingMethod]].map(([letter, node]) => ({
|
|
72
|
+
letter: letter,
|
|
73
|
+
node,
|
|
74
|
+
hintOffset,
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
for (const root of roots) {
|
|
79
|
+
let depth = 0;
|
|
80
|
+
const stack = [];
|
|
81
|
+
const stackText = [''];
|
|
82
|
+
stack[depth] = children(root, depth);
|
|
83
|
+
let ir;
|
|
84
|
+
while (depth >= 0) {
|
|
85
|
+
while (!(ir = stack[depth].next()).done) {
|
|
86
|
+
const { letter: char, node, hintOffset } = ir.value;
|
|
87
|
+
const text = stackText[depth] + char;
|
|
88
|
+
const hinting = (yield { text, node, depth });
|
|
89
|
+
if (hinting && hinting.goDeeper) {
|
|
90
|
+
depth++;
|
|
91
|
+
stackText[depth] = text;
|
|
92
|
+
stack[depth] = children(node, hintOffset);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
depth -= 1;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function existMap(values) {
|
|
100
|
+
const m = Object.create(null);
|
|
101
|
+
for (const v of values) {
|
|
102
|
+
m[v] = true;
|
|
103
|
+
}
|
|
104
|
+
return m;
|
|
105
|
+
}
|
|
106
|
+
exports.__testing__ = {
|
|
107
|
+
hintedWalkerNext,
|
|
108
|
+
};
|
|
109
|
+
//# sourceMappingURL=hintedWalker.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
+
};
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.hintedWalker = void 0;
|
|
14
|
+
__exportStar(require("./walker"), exports);
|
|
15
|
+
var hintedWalker_1 = require("./hintedWalker");
|
|
16
|
+
Object.defineProperty(exports, "hintedWalker", { enumerable: true, get: function () { return hintedWalker_1.hintedWalker; } });
|
|
17
|
+
__exportStar(require("./walkerTypes"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { TrieNode } from '../../TrieNode';
|
|
2
|
+
import { CompoundWordsMethod, WalkerIterator } from './walkerTypes';
|
|
3
|
+
/**
|
|
4
|
+
* Walks the Trie and yields a value at each node.
|
|
5
|
+
* next(goDeeper: boolean):
|
|
6
|
+
*/
|
|
7
|
+
export declare function walker(root: TrieNode, compoundingMethod?: CompoundWordsMethod): WalkerIterator;
|
|
8
|
+
//# sourceMappingURL=walker.d.ts.map
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.walker = void 0;
|
|
4
|
+
const walkerTypes_1 = require("./walkerTypes");
|
|
5
|
+
/**
|
|
6
|
+
* Walks the Trie and yields a value at each node.
|
|
7
|
+
* next(goDeeper: boolean):
|
|
8
|
+
*/
|
|
9
|
+
function* walker(root, compoundingMethod = walkerTypes_1.CompoundWordsMethod.NONE) {
|
|
10
|
+
const roots = {
|
|
11
|
+
[walkerTypes_1.CompoundWordsMethod.NONE]: [],
|
|
12
|
+
[walkerTypes_1.CompoundWordsMethod.JOIN_WORDS]: [[walkerTypes_1.JOIN_SEPARATOR, root]],
|
|
13
|
+
[walkerTypes_1.CompoundWordsMethod.SEPARATE_WORDS]: [[walkerTypes_1.WORD_SEPARATOR, root]],
|
|
14
|
+
};
|
|
15
|
+
function* children(n) {
|
|
16
|
+
if (n.c) {
|
|
17
|
+
yield* n.c;
|
|
18
|
+
}
|
|
19
|
+
if (n.f) {
|
|
20
|
+
yield* roots[compoundingMethod];
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
let depth = 0;
|
|
24
|
+
const stack = [];
|
|
25
|
+
stack[depth] = { t: '', c: children(root) };
|
|
26
|
+
let ir;
|
|
27
|
+
while (depth >= 0) {
|
|
28
|
+
let baseText = stack[depth].t;
|
|
29
|
+
while (!(ir = stack[depth].c.next()).done) {
|
|
30
|
+
const [char, node] = ir.value;
|
|
31
|
+
const text = baseText + char;
|
|
32
|
+
const goDeeper = yield { text, node, depth };
|
|
33
|
+
if (goDeeper || goDeeper === undefined) {
|
|
34
|
+
depth++;
|
|
35
|
+
baseText = text;
|
|
36
|
+
stack[depth] = { t: text, c: children(node) };
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
depth -= 1;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
exports.walker = walker;
|
|
43
|
+
//# sourceMappingURL=walker.js.map
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { TrieNode } from '../../TrieNode';
|
|
2
|
+
export declare const JOIN_SEPARATOR = "+";
|
|
3
|
+
export declare const WORD_SEPARATOR = " ";
|
|
4
|
+
export interface YieldResult {
|
|
5
|
+
text: string;
|
|
6
|
+
node: TrieNode;
|
|
7
|
+
depth: number;
|
|
8
|
+
}
|
|
9
|
+
export declare enum CompoundWordsMethod {
|
|
10
|
+
/**
|
|
11
|
+
* Do not compound words.
|
|
12
|
+
*/
|
|
13
|
+
NONE = 0,
|
|
14
|
+
/**
|
|
15
|
+
* Create word compounds separated by spaces.
|
|
16
|
+
*/
|
|
17
|
+
SEPARATE_WORDS = 1,
|
|
18
|
+
/**
|
|
19
|
+
* Create word compounds without separation.
|
|
20
|
+
*/
|
|
21
|
+
JOIN_WORDS = 2
|
|
22
|
+
}
|
|
23
|
+
export declare type WalkerIterator = Generator<YieldResult, void, boolean | undefined>;
|
|
24
|
+
//# sourceMappingURL=walkerTypes.d.ts.map
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CompoundWordsMethod = exports.WORD_SEPARATOR = exports.JOIN_SEPARATOR = void 0;
|
|
4
|
+
exports.JOIN_SEPARATOR = '+';
|
|
5
|
+
exports.WORD_SEPARATOR = ' ';
|
|
6
|
+
var CompoundWordsMethod;
|
|
7
|
+
(function (CompoundWordsMethod) {
|
|
8
|
+
/**
|
|
9
|
+
* Do not compound words.
|
|
10
|
+
*/
|
|
11
|
+
CompoundWordsMethod[CompoundWordsMethod["NONE"] = 0] = "NONE";
|
|
12
|
+
/**
|
|
13
|
+
* Create word compounds separated by spaces.
|
|
14
|
+
*/
|
|
15
|
+
CompoundWordsMethod[CompoundWordsMethod["SEPARATE_WORDS"] = 1] = "SEPARATE_WORDS";
|
|
16
|
+
/**
|
|
17
|
+
* Create word compounds without separation.
|
|
18
|
+
*/
|
|
19
|
+
CompoundWordsMethod[CompoundWordsMethod["JOIN_WORDS"] = 2] = "JOIN_WORDS";
|
|
20
|
+
})(CompoundWordsMethod = exports.CompoundWordsMethod || (exports.CompoundWordsMethod = {}));
|
|
21
|
+
//# sourceMappingURL=walkerTypes.js.map
|
package/dist/lib/trie-util.js
CHANGED
|
@@ -171,11 +171,10 @@ exports.isCircular = isCircular;
|
|
|
171
171
|
*/
|
|
172
172
|
function mergeDefaults(value, defaultValue) {
|
|
173
173
|
const result = { ...defaultValue };
|
|
174
|
-
const allowedKeys = new Set(Object.keys(defaultValue));
|
|
175
174
|
if (value) {
|
|
176
175
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
177
176
|
for (const [k, v] of Object.entries(value)) {
|
|
178
|
-
if (
|
|
177
|
+
if (k in result) {
|
|
179
178
|
result[k] = v !== null && v !== void 0 ? v : result[k];
|
|
180
179
|
}
|
|
181
180
|
}
|
package/dist/lib/trie.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Sequence } from 'gensequence';
|
|
2
2
|
import { FindFullResult } from './find';
|
|
3
|
-
import { SuggestionOptions } from './genSuggestionsOptions';
|
|
4
3
|
import { SuggestionCollector, SuggestionResult } from './suggestCollector';
|
|
4
|
+
import { SuggestionOptions } from './suggestions/genSuggestionsOptions';
|
|
5
5
|
import { PartialTrieOptions, TrieNode, TrieOptions, TrieRoot } from './TrieNode';
|
|
6
6
|
import { CompoundWordsMethod, WalkerIterator } from './walker';
|
|
7
7
|
export { CASE_INSENSITIVE_PREFIX, COMPOUND_FIX, defaultTrieOptions, FORBID_PREFIX, OPTIONAL_COMPOUND_FIX, } from './constants';
|
package/dist/lib/trie.js
CHANGED
|
@@ -6,6 +6,7 @@ const constants_1 = require("./constants");
|
|
|
6
6
|
const find_1 = require("./find");
|
|
7
7
|
const suggest_1 = require("./suggest");
|
|
8
8
|
const trie_util_1 = require("./trie-util");
|
|
9
|
+
const util_1 = require("./utils/util");
|
|
9
10
|
const walker_1 = require("./walker");
|
|
10
11
|
var constants_2 = require("./constants");
|
|
11
12
|
Object.defineProperty(exports, "CASE_INSENSITIVE_PREFIX", { enumerable: true, get: function () { return constants_2.CASE_INSENSITIVE_PREFIX; } });
|
|
@@ -142,10 +143,15 @@ class Trie {
|
|
|
142
143
|
* The results include the word and adjusted edit cost. This is useful for merging results from multiple tries.
|
|
143
144
|
*/
|
|
144
145
|
suggestWithCost(text, options) {
|
|
146
|
+
const sep = options.compoundSeparator;
|
|
147
|
+
const adjWord = sep ? (0, util_1.replaceAllFactory)(sep, '') : (a) => a;
|
|
145
148
|
const optFilter = options.filter;
|
|
146
149
|
const filter = optFilter
|
|
147
|
-
? (word, cost) =>
|
|
148
|
-
|
|
150
|
+
? (word, cost) => {
|
|
151
|
+
const w = adjWord(word);
|
|
152
|
+
return !this.isForbiddenWord(w) && optFilter(w, cost);
|
|
153
|
+
}
|
|
154
|
+
: (word) => !this.isForbiddenWord(adjWord(word));
|
|
149
155
|
const opts = { ...options, filter };
|
|
150
156
|
return (0, suggest_1.suggest)(this.root, text, opts);
|
|
151
157
|
}
|
|
@@ -156,8 +162,8 @@ class Trie {
|
|
|
156
162
|
*/
|
|
157
163
|
genSuggestions(collector, compoundMethod) {
|
|
158
164
|
const filter = (word) => !this.isForbiddenWord(word);
|
|
159
|
-
const {
|
|
160
|
-
const suggestions = (0, suggest_1.genSuggestions)(this.root, collector.word,
|
|
165
|
+
const options = (0, trie_util_1.clean)({ compoundMethod, ...collector.genSuggestionOptions });
|
|
166
|
+
const suggestions = (0, suggest_1.genSuggestions)(this.root, collector.word, options);
|
|
161
167
|
collector.collect(suggestions, undefined, filter);
|
|
162
168
|
}
|
|
163
169
|
/**
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -52,9 +52,18 @@ export declare type NoUndefined<T> = {
|
|
|
52
52
|
export declare type OnlyOptionalOrUndefined<T> = {
|
|
53
53
|
[P in keyof T as P extends OptionalOrUndefinedKeys<T> ? P : never]: T[P];
|
|
54
54
|
};
|
|
55
|
+
/**
|
|
56
|
+
* Make fields that can be `undefined` optional
|
|
57
|
+
*/
|
|
55
58
|
export declare type MakeOptional<T> = OnlyRequired<T> & Partial<OnlyOptionalOrUndefined<T>>;
|
|
59
|
+
/**
|
|
60
|
+
* Like Required, but keeps the Optional.
|
|
61
|
+
*/
|
|
56
62
|
export declare type RemoveUndefined<T> = {
|
|
57
63
|
[P in keyof T]: Exclude<T[P], undefined>;
|
|
58
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* Make all `undefined` optional and removes the `undefined`
|
|
67
|
+
*/
|
|
59
68
|
export declare type UndefinedToOptional<T> = RemoveUndefined<MakeOptional<T>>;
|
|
60
69
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/lib/utils/util.d.ts
CHANGED
|
@@ -15,4 +15,17 @@ export declare function cleanCopy<T, U = UndefinedToOptional<T>>(t: T): U;
|
|
|
15
15
|
export declare function clean<T, U = UndefinedToOptional<T>>(t: T): U;
|
|
16
16
|
export declare function unique<T>(a: Iterable<T>): T[];
|
|
17
17
|
export declare function flatten<T>(i: Iterable<Iterable<T>>): Iterable<T>;
|
|
18
|
+
export declare function replaceAll(text: string, match: string, withText: string): string;
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @param text verbatim text to be inserted into a regexp
|
|
22
|
+
* @returns text that can be used in a regexp.
|
|
23
|
+
*/
|
|
24
|
+
export declare function regexQuote(text: string): string;
|
|
25
|
+
/**
|
|
26
|
+
* Factory to create a function that will replace all occurrences of `match` with `withText`
|
|
27
|
+
* @param match - string to match
|
|
28
|
+
* @param replaceWithText - the text to substitute.
|
|
29
|
+
*/
|
|
30
|
+
export declare function replaceAllFactory(match: string, replaceWithText: string): (text: string) => string;
|
|
18
31
|
//# sourceMappingURL=util.d.ts.map
|
package/dist/lib/utils/util.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.flatten = exports.unique = exports.clean = exports.cleanCopy = exports.isDefined = void 0;
|
|
3
|
+
exports.replaceAllFactory = exports.regexQuote = exports.replaceAll = exports.flatten = exports.unique = exports.clean = exports.cleanCopy = exports.isDefined = void 0;
|
|
4
4
|
function isDefined(a) {
|
|
5
5
|
return a !== undefined;
|
|
6
6
|
}
|
|
@@ -40,4 +40,28 @@ function* flatten(i) {
|
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
exports.flatten = flatten;
|
|
43
|
+
function replaceAll(text, match, withText) {
|
|
44
|
+
const fn = replaceAllFactory(match, withText);
|
|
45
|
+
return fn(text);
|
|
46
|
+
}
|
|
47
|
+
exports.replaceAll = replaceAll;
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
* @param text verbatim text to be inserted into a regexp
|
|
51
|
+
* @returns text that can be used in a regexp.
|
|
52
|
+
*/
|
|
53
|
+
function regexQuote(text) {
|
|
54
|
+
return text.replace(/([[\]\-+(){},|*.\\])/g, '\\$1');
|
|
55
|
+
}
|
|
56
|
+
exports.regexQuote = regexQuote;
|
|
57
|
+
/**
|
|
58
|
+
* Factory to create a function that will replace all occurrences of `match` with `withText`
|
|
59
|
+
* @param match - string to match
|
|
60
|
+
* @param replaceWithText - the text to substitute.
|
|
61
|
+
*/
|
|
62
|
+
function replaceAllFactory(match, replaceWithText) {
|
|
63
|
+
const r = RegExp(regexQuote(match), 'g');
|
|
64
|
+
return (text) => text.replace(r, replaceWithText);
|
|
65
|
+
}
|
|
66
|
+
exports.replaceAllFactory = replaceAllFactory;
|
|
43
67
|
//# sourceMappingURL=util.js.map
|
package/dist/lib/walker.d.ts
CHANGED
|
@@ -1,43 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const JOIN_SEPARATOR = "+";
|
|
3
|
-
export declare const WORD_SEPARATOR = " ";
|
|
4
|
-
export interface YieldResult {
|
|
5
|
-
text: string;
|
|
6
|
-
node: TrieNode;
|
|
7
|
-
depth: number;
|
|
8
|
-
}
|
|
9
|
-
export declare enum CompoundWordsMethod {
|
|
10
|
-
/**
|
|
11
|
-
* Do not compound words.
|
|
12
|
-
*/
|
|
13
|
-
NONE = 0,
|
|
14
|
-
/**
|
|
15
|
-
* Create word compounds separated by spaces.
|
|
16
|
-
*/
|
|
17
|
-
SEPARATE_WORDS = 1,
|
|
18
|
-
/**
|
|
19
|
-
* Create word compounds without separation.
|
|
20
|
-
*/
|
|
21
|
-
JOIN_WORDS = 2
|
|
22
|
-
}
|
|
23
|
-
export declare type WalkerIterator = Generator<YieldResult, void, boolean | undefined>;
|
|
24
|
-
/**
|
|
25
|
-
* Walks the Trie and yields a value at each node.
|
|
26
|
-
* next(goDeeper: boolean):
|
|
27
|
-
*/
|
|
28
|
-
export declare function walker(root: TrieNode, compoundingMethod?: CompoundWordsMethod): WalkerIterator;
|
|
29
|
-
export interface Hinting {
|
|
30
|
-
goDeeper: boolean;
|
|
31
|
-
}
|
|
32
|
-
/**
|
|
33
|
-
* Ask for the next result.
|
|
34
|
-
* goDeeper of true tells the walker to go deeper in the Trie if possible. Default is true.
|
|
35
|
-
* This can be used to limit the walker's depth.
|
|
36
|
-
*/
|
|
37
|
-
export declare type HintedWalkerIterator = Generator<YieldResult, void, Hinting | undefined>;
|
|
38
|
-
/**
|
|
39
|
-
* Walks the Trie and yields a value at each node.
|
|
40
|
-
* next(goDeeper: boolean):
|
|
41
|
-
*/
|
|
42
|
-
export declare function hintedWalker(root: TrieRoot, ignoreCase: boolean, hint: string, compoundingMethod: CompoundWordsMethod | undefined): HintedWalkerIterator;
|
|
1
|
+
export * from './suggestions/walker/index';
|
|
43
2
|
//# sourceMappingURL=walker.d.ts.map
|
package/dist/lib/walker.js
CHANGED
|
@@ -1,154 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
10
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
11
|
+
};
|
|
2
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
|
|
4
|
-
const trie_util_1 = require("./trie-util");
|
|
5
|
-
exports.JOIN_SEPARATOR = '+';
|
|
6
|
-
exports.WORD_SEPARATOR = ' ';
|
|
7
|
-
var CompoundWordsMethod;
|
|
8
|
-
(function (CompoundWordsMethod) {
|
|
9
|
-
/**
|
|
10
|
-
* Do not compound words.
|
|
11
|
-
*/
|
|
12
|
-
CompoundWordsMethod[CompoundWordsMethod["NONE"] = 0] = "NONE";
|
|
13
|
-
/**
|
|
14
|
-
* Create word compounds separated by spaces.
|
|
15
|
-
*/
|
|
16
|
-
CompoundWordsMethod[CompoundWordsMethod["SEPARATE_WORDS"] = 1] = "SEPARATE_WORDS";
|
|
17
|
-
/**
|
|
18
|
-
* Create word compounds without separation.
|
|
19
|
-
*/
|
|
20
|
-
CompoundWordsMethod[CompoundWordsMethod["JOIN_WORDS"] = 2] = "JOIN_WORDS";
|
|
21
|
-
})(CompoundWordsMethod = exports.CompoundWordsMethod || (exports.CompoundWordsMethod = {}));
|
|
22
|
-
/**
|
|
23
|
-
* Walks the Trie and yields a value at each node.
|
|
24
|
-
* next(goDeeper: boolean):
|
|
25
|
-
*/
|
|
26
|
-
function* walker(root, compoundingMethod = CompoundWordsMethod.NONE) {
|
|
27
|
-
const roots = {
|
|
28
|
-
[CompoundWordsMethod.NONE]: [],
|
|
29
|
-
[CompoundWordsMethod.JOIN_WORDS]: [[exports.JOIN_SEPARATOR, root]],
|
|
30
|
-
[CompoundWordsMethod.SEPARATE_WORDS]: [[exports.WORD_SEPARATOR, root]],
|
|
31
|
-
};
|
|
32
|
-
function* children(n) {
|
|
33
|
-
if (n.c) {
|
|
34
|
-
yield* n.c;
|
|
35
|
-
}
|
|
36
|
-
if (n.f) {
|
|
37
|
-
yield* roots[compoundingMethod];
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
let depth = 0;
|
|
41
|
-
const stack = [];
|
|
42
|
-
stack[depth] = { t: '', c: children(root) };
|
|
43
|
-
let ir;
|
|
44
|
-
while (depth >= 0) {
|
|
45
|
-
let baseText = stack[depth].t;
|
|
46
|
-
while (!(ir = stack[depth].c.next()).done) {
|
|
47
|
-
const [char, node] = ir.value;
|
|
48
|
-
const text = baseText + char;
|
|
49
|
-
const goDeeper = yield { text, node, depth };
|
|
50
|
-
if (goDeeper || goDeeper === undefined) {
|
|
51
|
-
depth++;
|
|
52
|
-
baseText = text;
|
|
53
|
-
stack[depth] = { t: text, c: children(node) };
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
depth -= 1;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
exports.walker = walker;
|
|
60
|
-
/**
|
|
61
|
-
* Walks the Trie and yields a value at each node.
|
|
62
|
-
* next(goDeeper: boolean):
|
|
63
|
-
*/
|
|
64
|
-
function* hintedWalker(root, ignoreCase, hint, compoundingMethod) {
|
|
65
|
-
const _compoundingMethod = compoundingMethod !== null && compoundingMethod !== void 0 ? compoundingMethod : CompoundWordsMethod.NONE;
|
|
66
|
-
const compoundCharacter = root.compoundCharacter;
|
|
67
|
-
const noCaseCharacter = root.stripCaseAndAccentsPrefix;
|
|
68
|
-
const rawRoots = [root, ignoreCase ? root.c.get(noCaseCharacter) : undefined].filter(trie_util_1.isDefined);
|
|
69
|
-
const specialRootsPrefix = existMap([compoundCharacter, noCaseCharacter, root.forbiddenWordPrefix]);
|
|
70
|
-
function filterRoot(root) {
|
|
71
|
-
var _a;
|
|
72
|
-
const children = (_a = root.c) === null || _a === void 0 ? void 0 : _a.entries();
|
|
73
|
-
const c = children && [...children].filter(([v]) => !(v in specialRootsPrefix));
|
|
74
|
-
return {
|
|
75
|
-
c: c && new Map(c),
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
const roots = rawRoots.map(filterRoot);
|
|
79
|
-
const compoundRoots = rawRoots.map((r) => { var _a; return (_a = r.c) === null || _a === void 0 ? void 0 : _a.get(compoundCharacter); }).filter(trie_util_1.isDefined);
|
|
80
|
-
const rootsForCompoundMethods = roots.concat(compoundRoots);
|
|
81
|
-
const compoundMethodRoots = {
|
|
82
|
-
[CompoundWordsMethod.NONE]: [],
|
|
83
|
-
[CompoundWordsMethod.JOIN_WORDS]: [...rootsForCompoundMethods.map((r) => [exports.JOIN_SEPARATOR, r])],
|
|
84
|
-
[CompoundWordsMethod.SEPARATE_WORDS]: [...rootsForCompoundMethods.map((r) => [exports.WORD_SEPARATOR, r])],
|
|
85
|
-
};
|
|
86
|
-
function* children(n, hintOffset) {
|
|
87
|
-
if (n.c) {
|
|
88
|
-
const h = hint.slice(hintOffset, hintOffset + 3) + hint.slice(Math.max(0, hintOffset - 2), hintOffset);
|
|
89
|
-
const hints = new Set(h);
|
|
90
|
-
const c = n.c;
|
|
91
|
-
// First yield the hints
|
|
92
|
-
yield* [...hints]
|
|
93
|
-
.filter((a) => c.has(a))
|
|
94
|
-
.map((letter) => ({
|
|
95
|
-
letter,
|
|
96
|
-
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
97
|
-
node: c.get(letter),
|
|
98
|
-
hintOffset: hintOffset + 1,
|
|
99
|
-
}));
|
|
100
|
-
// We don't want to suggest the compound character.
|
|
101
|
-
hints.add(compoundCharacter);
|
|
102
|
-
// Then yield everything else.
|
|
103
|
-
yield* [...c]
|
|
104
|
-
.filter((a) => !hints.has(a[0]))
|
|
105
|
-
.map(([letter, node]) => ({
|
|
106
|
-
letter,
|
|
107
|
-
node,
|
|
108
|
-
hintOffset: hintOffset + 1,
|
|
109
|
-
}));
|
|
110
|
-
if (c.has(compoundCharacter)) {
|
|
111
|
-
for (const compoundRoot of compoundRoots) {
|
|
112
|
-
yield* children(compoundRoot, hintOffset);
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
if (n.f) {
|
|
117
|
-
yield* [...compoundMethodRoots[_compoundingMethod]].map(([letter, node]) => ({
|
|
118
|
-
letter,
|
|
119
|
-
node,
|
|
120
|
-
hintOffset,
|
|
121
|
-
}));
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
for (const root of roots) {
|
|
125
|
-
let depth = 0;
|
|
126
|
-
const stack = [];
|
|
127
|
-
let baseText = '';
|
|
128
|
-
stack[depth] = children(root, depth);
|
|
129
|
-
let ir;
|
|
130
|
-
while (depth >= 0) {
|
|
131
|
-
while (!(ir = stack[depth].next()).done) {
|
|
132
|
-
const { letter: char, node, hintOffset } = ir.value;
|
|
133
|
-
const text = baseText + char;
|
|
134
|
-
const hinting = (yield { text, node, depth });
|
|
135
|
-
if (hinting && hinting.goDeeper) {
|
|
136
|
-
depth++;
|
|
137
|
-
baseText = text;
|
|
138
|
-
stack[depth] = children(node, hintOffset);
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
depth -= 1;
|
|
142
|
-
baseText = baseText.slice(0, -1);
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
exports.hintedWalker = hintedWalker;
|
|
147
|
-
function existMap(values) {
|
|
148
|
-
const m = Object.create(null);
|
|
149
|
-
for (const v of values) {
|
|
150
|
-
m[v] = true;
|
|
151
|
-
}
|
|
152
|
-
return m;
|
|
153
|
-
}
|
|
13
|
+
__exportStar(require("./suggestions/walker/index"), exports);
|
|
154
14
|
//# sourceMappingURL=walker.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cspell-trie-lib",
|
|
3
|
-
"version": "5.18.
|
|
3
|
+
"version": "5.18.3",
|
|
4
4
|
"description": "Trie Data Structure to support cspell.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"homepage": "https://github.com/streetsidesoftware/cspell#readme",
|
|
39
39
|
"dependencies": {
|
|
40
|
-
"@cspell/cspell-pipe": "^5.18.
|
|
40
|
+
"@cspell/cspell-pipe": "^5.18.3",
|
|
41
41
|
"fs-extra": "^10.0.0",
|
|
42
42
|
"gensequence": "^3.1.1"
|
|
43
43
|
},
|
|
@@ -45,13 +45,13 @@
|
|
|
45
45
|
"node": ">=12.13.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@cspell/cspell-types": "^5.18.
|
|
49
|
-
"@cspell/dict-en_us": "^2.1.
|
|
48
|
+
"@cspell/cspell-types": "^5.18.3",
|
|
49
|
+
"@cspell/dict-en_us": "^2.1.5",
|
|
50
50
|
"@cspell/dict-es-es": "^2.1.0",
|
|
51
51
|
"@types/fs-extra": "^9.0.13",
|
|
52
|
-
"@types/node": "^17.0.
|
|
52
|
+
"@types/node": "^17.0.14",
|
|
53
53
|
"jest": "^27.4.7",
|
|
54
54
|
"rimraf": "^3.0.2"
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "c650c8d0d58fc0398a6f745a0ad48d46f982332f"
|
|
57
57
|
}
|