cspell-trie-lib 5.15.3 → 5.18.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/TrieNode.d.ts +1 -0
- package/dist/lib/distance/distance.d.ts +2 -2
- package/dist/lib/distance/distanceAStarWeighted.d.ts +12 -0
- package/dist/lib/distance/distanceAStarWeighted.js +48 -16
- package/dist/lib/distance/formatResultEx.d.ts +5 -0
- package/dist/lib/distance/formatResultEx.js +58 -0
- package/dist/lib/distance/index.d.ts +0 -1
- package/dist/lib/distance/weightedMaps.d.ts +22 -5
- package/dist/lib/distance/weightedMaps.js +76 -49
- package/dist/lib/find.d.ts +1 -0
- package/dist/lib/find.js +2 -2
- package/dist/lib/index.d.ts +3 -1
- package/dist/lib/index.js +3 -1
- package/dist/lib/mappers/mapCosts.d.ts +6 -0
- package/dist/lib/mappers/mapCosts.js +28 -0
- package/dist/lib/mappers/mapDictionaryInfo.d.ts +4 -0
- package/dist/lib/mappers/mapDictionaryInfo.js +55 -0
- package/dist/lib/mappers/mapDictionaryInfoToWeightMap.d.ts +5 -0
- package/dist/lib/mappers/mapDictionaryInfoToWeightMap.js +19 -0
- package/dist/lib/mappers/mapHunspellInformation.d.ts +42 -0
- package/dist/lib/mappers/mapHunspellInformation.js +210 -0
- package/dist/lib/mappers/mapToSuggestionCostDef.d.ts +17 -0
- package/dist/lib/mappers/mapToSuggestionCostDef.js +124 -0
- package/dist/lib/models/DictionaryInformation.d.ts +8 -0
- package/dist/lib/models/DictionaryInformation.js +3 -0
- package/dist/lib/models/locale/index.d.ts +2 -0
- package/dist/lib/models/locale/index.js +7 -0
- package/dist/lib/models/locale/knownLocales.d.ts +3 -0
- package/dist/lib/models/locale/knownLocales.js +537 -0
- package/dist/lib/models/locale/locale.d.ts +24 -0
- package/dist/lib/models/locale/locale.js +69 -0
- package/dist/lib/models/suggestionCostsDef.d.ts +2 -0
- package/dist/lib/{distance → models}/suggestionCostsDef.js +0 -0
- package/dist/lib/suggestions/suggestCollector.js +7 -2
- package/dist/lib/trie-util.d.ts +2 -1
- package/dist/lib/trie-util.js +1 -1
- package/dist/lib/types.d.ts +60 -0
- package/dist/lib/types.js +15 -0
- package/dist/lib/utils/text.d.ts +53 -0
- package/dist/lib/utils/text.js +111 -0
- package/dist/lib/utils/util.d.ts +18 -0
- package/dist/lib/utils/util.js +43 -0
- package/package.json +5 -4
- package/dist/lib/distance/suggestionCostsDef.d.ts +0 -70
package/dist/lib/TrieNode.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { SuggestionCostMapDef } from '
|
|
1
|
+
import type { SuggestionCostMapDef } from '../models/suggestionCostsDef';
|
|
2
2
|
import type { WeightMap } from './weightedMaps';
|
|
3
|
-
export type { SuggestionCostMapDef } from '
|
|
3
|
+
export type { SuggestionCostMapDef } from '../models/suggestionCostsDef';
|
|
4
4
|
export type { WeightMap } from './weightedMaps';
|
|
5
5
|
/**
|
|
6
6
|
* Calculate the edit distance between any two words.
|
|
@@ -5,4 +5,16 @@ import { WeightMap } from './weightedMaps';
|
|
|
5
5
|
* Using basic weights, this algorithm has the same results as the Damerau-Levenshtein algorithm.
|
|
6
6
|
*/
|
|
7
7
|
export declare function distanceAStarWeighted(wordA: string, wordB: string, map: WeightMap, cost?: number): number;
|
|
8
|
+
export interface ExResult {
|
|
9
|
+
a: string;
|
|
10
|
+
b: string;
|
|
11
|
+
cost: number;
|
|
12
|
+
segments: {
|
|
13
|
+
a: string;
|
|
14
|
+
b: string;
|
|
15
|
+
c: number;
|
|
16
|
+
p: number;
|
|
17
|
+
}[];
|
|
18
|
+
}
|
|
19
|
+
export declare function distanceAStarWeightedEx(wordA: string, wordB: string, map: WeightMap, cost?: number): ExResult | undefined;
|
|
8
20
|
//# sourceMappingURL=distanceAStarWeighted.d.ts.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.distanceAStarWeighted = void 0;
|
|
3
|
+
exports.distanceAStarWeightedEx = exports.distanceAStarWeighted = void 0;
|
|
4
4
|
const PairingHeap_1 = require("../utils/PairingHeap");
|
|
5
5
|
/**
|
|
6
6
|
* Calculate the edit distance between two words using an A* algorithm.
|
|
@@ -8,45 +8,79 @@ const PairingHeap_1 = require("../utils/PairingHeap");
|
|
|
8
8
|
* Using basic weights, this algorithm has the same results as the Damerau-Levenshtein algorithm.
|
|
9
9
|
*/
|
|
10
10
|
function distanceAStarWeighted(wordA, wordB, map, cost = 100) {
|
|
11
|
+
const best = _distanceAStarWeightedEx(wordA, wordB, map, cost);
|
|
12
|
+
return best ? best.c + best.p : -1;
|
|
13
|
+
}
|
|
14
|
+
exports.distanceAStarWeighted = distanceAStarWeighted;
|
|
15
|
+
function distanceAStarWeightedEx(wordA, wordB, map, cost = 100) {
|
|
16
|
+
const best = _distanceAStarWeightedEx(wordA, wordB, map, cost);
|
|
17
|
+
if (!best)
|
|
18
|
+
return undefined;
|
|
19
|
+
const aa = '^' + wordA + '$';
|
|
20
|
+
const bb = '^' + wordB + '$';
|
|
21
|
+
const result = {
|
|
22
|
+
a: aa,
|
|
23
|
+
b: bb,
|
|
24
|
+
cost: best.c + best.p,
|
|
25
|
+
segments: [],
|
|
26
|
+
};
|
|
27
|
+
const segments = result.segments;
|
|
28
|
+
for (let n = best; n.f; n = n.f) {
|
|
29
|
+
const f = n.f;
|
|
30
|
+
const a = aa.slice(f.ai, n.ai);
|
|
31
|
+
const b = bb.slice(f.bi, n.bi);
|
|
32
|
+
const c = n.c - f.c;
|
|
33
|
+
const p = n.p - f.p;
|
|
34
|
+
segments.push({ a, b, c, p });
|
|
35
|
+
}
|
|
36
|
+
segments.reverse();
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
exports.distanceAStarWeightedEx = distanceAStarWeightedEx;
|
|
40
|
+
function _distanceAStarWeightedEx(wordA, wordB, map, cost = 100) {
|
|
11
41
|
// Add ^ and $ for begin/end detection.
|
|
12
42
|
const a = '^' + wordA + '$';
|
|
13
43
|
const b = '^' + wordB + '$';
|
|
14
44
|
const aN = a.length;
|
|
15
45
|
const bN = b.length;
|
|
16
46
|
const candidates = new PairingHeap_1.PairingHeap(compare);
|
|
17
|
-
candidates.add({ ai: 0, bi: 0, c: 0 });
|
|
47
|
+
candidates.add({ ai: 0, bi: 0, c: 0, p: 0, f: undefined });
|
|
48
|
+
/** Substitute / Replace */
|
|
18
49
|
function opSub(n) {
|
|
19
|
-
const { ai, bi, c } = n;
|
|
50
|
+
const { ai, bi, c, p } = n;
|
|
20
51
|
if (ai < aN && bi < bN) {
|
|
21
52
|
const cc = a[ai] === b[bi] ? c : c + cost;
|
|
22
|
-
candidates.add({ ai: ai + 1, bi: bi + 1, c: cc });
|
|
53
|
+
candidates.add({ ai: ai + 1, bi: bi + 1, c: cc, p, f: n });
|
|
23
54
|
}
|
|
24
55
|
}
|
|
56
|
+
/** Insert */
|
|
25
57
|
function opIns(n) {
|
|
26
|
-
const { ai, bi, c } = n;
|
|
58
|
+
const { ai, bi, c, p } = n;
|
|
27
59
|
if (bi < bN) {
|
|
28
|
-
candidates.add({ ai: ai, bi: bi + 1, c: c + cost });
|
|
60
|
+
candidates.add({ ai: ai, bi: bi + 1, c: c + cost, p, f: n });
|
|
29
61
|
}
|
|
30
62
|
}
|
|
63
|
+
/** Delete */
|
|
31
64
|
function opDel(n) {
|
|
32
|
-
const { ai, bi, c } = n;
|
|
65
|
+
const { ai, bi, c, p } = n;
|
|
33
66
|
if (ai < aN) {
|
|
34
|
-
candidates.add({ ai: ai + 1, bi: bi, c: c + cost });
|
|
67
|
+
candidates.add({ ai: ai + 1, bi: bi, c: c + cost, p, f: n });
|
|
35
68
|
}
|
|
36
69
|
}
|
|
70
|
+
/** Swap adjacent letters */
|
|
37
71
|
function opSwap(n) {
|
|
38
|
-
const { ai, bi, c } = n;
|
|
72
|
+
const { ai, bi, c, p } = n;
|
|
39
73
|
if (a[ai] === b[bi + 1] && a[ai + 1] === b[bi]) {
|
|
40
|
-
candidates.add({ ai: ai + 2, bi: bi + 2, c: c + cost });
|
|
74
|
+
candidates.add({ ai: ai + 2, bi: bi + 2, c: c + cost, p, f: n });
|
|
41
75
|
}
|
|
42
76
|
}
|
|
43
77
|
function opMap(n) {
|
|
44
|
-
const { ai, bi, c } = n;
|
|
45
|
-
const pos = { a, b, ai, bi, c };
|
|
78
|
+
const { ai, bi, c, p } = n;
|
|
79
|
+
const pos = { a, b, ai, bi, c, p };
|
|
46
80
|
const costCalculations = [map.calcInsDelCosts(pos), map.calcSwapCosts(pos), map.calcReplaceCosts(pos)];
|
|
47
81
|
costCalculations.forEach((iter) => {
|
|
48
82
|
for (const nn of iter) {
|
|
49
|
-
candidates.add(nn);
|
|
83
|
+
candidates.add({ ...nn, f: n });
|
|
50
84
|
}
|
|
51
85
|
});
|
|
52
86
|
}
|
|
@@ -61,10 +95,8 @@ function distanceAStarWeighted(wordA, wordB, map, cost = 100) {
|
|
|
61
95
|
opMap(best);
|
|
62
96
|
opSub(best);
|
|
63
97
|
}
|
|
64
|
-
|
|
65
|
-
return best ? best.c : -1;
|
|
98
|
+
return best;
|
|
66
99
|
}
|
|
67
|
-
exports.distanceAStarWeighted = distanceAStarWeighted;
|
|
68
100
|
function compare(a, b) {
|
|
69
101
|
// Choose lowest cost or farthest Manhattan distance.
|
|
70
102
|
return a.c - b.c || b.ai + b.bi - a.ai - a.bi;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { WeightMap } from '.';
|
|
2
|
+
import { ExResult } from './distanceAStarWeighted';
|
|
3
|
+
export declare function formatExResult(ex: ExResult | undefined): string;
|
|
4
|
+
export declare function formattedDistance(wordA: string, wordB: string, weightMap: WeightMap, cost?: number): string;
|
|
5
|
+
//# sourceMappingURL=formatResultEx.d.ts.map
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.formattedDistance = exports.formatExResult = void 0;
|
|
4
|
+
const distanceAStarWeighted_1 = require("./distanceAStarWeighted");
|
|
5
|
+
function pL(s, w) {
|
|
6
|
+
const strWidth = vizWidth(s);
|
|
7
|
+
const w0 = Math.max(0, w - strWidth);
|
|
8
|
+
return ' '.repeat(w0) + s;
|
|
9
|
+
}
|
|
10
|
+
function pR(s, w) {
|
|
11
|
+
const strWidth = vizWidth(s);
|
|
12
|
+
const w0 = Math.max(0, w - strWidth);
|
|
13
|
+
return s + ' '.repeat(w0);
|
|
14
|
+
}
|
|
15
|
+
function vizWidth(s) {
|
|
16
|
+
const r = s.replace(/[\u0300-\u036F\u007f-\u009f]/gu, '');
|
|
17
|
+
let i = 0;
|
|
18
|
+
for (const c of r) {
|
|
19
|
+
i += c.length;
|
|
20
|
+
}
|
|
21
|
+
return i;
|
|
22
|
+
}
|
|
23
|
+
function formatExResult(ex) {
|
|
24
|
+
if (!ex)
|
|
25
|
+
return '<undefined>';
|
|
26
|
+
const { cost, segments } = ex;
|
|
27
|
+
const asString = segments.map(({ a, b, c, p }) => ({
|
|
28
|
+
a: `<${a}>`,
|
|
29
|
+
b: `<${b}>`,
|
|
30
|
+
c: c.toString(10),
|
|
31
|
+
p: p.toString(10),
|
|
32
|
+
}));
|
|
33
|
+
asString.push({
|
|
34
|
+
a: '',
|
|
35
|
+
b: '',
|
|
36
|
+
c: ' = ' + segments.reduce((sum, { c }) => sum + c, 0).toString(10),
|
|
37
|
+
p: ' = ' + segments.reduce((sum, { p }) => sum + p, 0).toString(10),
|
|
38
|
+
});
|
|
39
|
+
const parts = asString.map(({ a, b, c, p }) => ({
|
|
40
|
+
a,
|
|
41
|
+
b,
|
|
42
|
+
c,
|
|
43
|
+
p,
|
|
44
|
+
w: Math.max(vizWidth(a), vizWidth(b), vizWidth(c), vizWidth(p)),
|
|
45
|
+
}));
|
|
46
|
+
const a = 'a: |' + parts.map(({ a, w }) => pR(a, w)).join('|') + '|';
|
|
47
|
+
const b = 'b: |' + parts.map(({ b, w }) => pR(b, w)).join('|') + '|';
|
|
48
|
+
const c = 'c: |' + parts.map(({ c, w }) => pL(c, w)).join('|') + '|';
|
|
49
|
+
const p = 'p: |' + parts.map(({ p, w }) => pL(p, w)).join('|') + '|';
|
|
50
|
+
return `<${ex.a.slice(1, -1)}> -> <${ex.b.slice(1, -1)}> (${cost})\n${[a, b, c, p].join('\n')}\n`;
|
|
51
|
+
}
|
|
52
|
+
exports.formatExResult = formatExResult;
|
|
53
|
+
function formattedDistance(wordA, wordB, weightMap, cost) {
|
|
54
|
+
const x = (0, distanceAStarWeighted_1.distanceAStarWeightedEx)(wordA, wordB, weightMap, cost);
|
|
55
|
+
return formatExResult(x);
|
|
56
|
+
}
|
|
57
|
+
exports.formattedDistance = formattedDistance;
|
|
58
|
+
//# sourceMappingURL=formatResultEx.js.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SuggestionCostMapDef } from '
|
|
1
|
+
import { SuggestionCostMapDef } from '../models/suggestionCostsDef';
|
|
2
2
|
export declare type WeightedRepMapTrie = Record<string, WeightedRepTrieNode>;
|
|
3
3
|
interface WeightedRepTrieNode {
|
|
4
4
|
/** The nested Trie nodes */
|
|
@@ -8,11 +8,24 @@ interface WeightedRepTrieNode {
|
|
|
8
8
|
/** The cost to swap */
|
|
9
9
|
swap?: number | undefined;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Costs are minimized while penalties are maximized.
|
|
13
|
+
*/
|
|
14
|
+
interface Cost {
|
|
15
|
+
/**
|
|
16
|
+
* The cost of an operation
|
|
17
|
+
* `c'' = min(c, c')`
|
|
18
|
+
*/
|
|
19
|
+
c?: number | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* The penalties applied
|
|
22
|
+
* `p'' = max(p, p')`
|
|
23
|
+
*/
|
|
24
|
+
p?: number | undefined;
|
|
25
|
+
}
|
|
26
|
+
interface TrieCost extends Cost {
|
|
12
27
|
/** nested trie nodes */
|
|
13
28
|
n?: Record<string, TrieCost>;
|
|
14
|
-
/** the cost to insert/delete */
|
|
15
|
-
c?: number | undefined;
|
|
16
29
|
}
|
|
17
30
|
interface TrieTrieCost {
|
|
18
31
|
/** nested trie nodes */
|
|
@@ -26,6 +39,7 @@ export interface CostPosition {
|
|
|
26
39
|
b: string;
|
|
27
40
|
bi: number;
|
|
28
41
|
c: number;
|
|
42
|
+
p: number;
|
|
29
43
|
}
|
|
30
44
|
export interface WeightMap {
|
|
31
45
|
readonly insDel: TrieCost;
|
|
@@ -37,15 +51,18 @@ export interface WeightMap {
|
|
|
37
51
|
}
|
|
38
52
|
export declare function createWeightMap(...defs: SuggestionCostMapDef[]): WeightMap;
|
|
39
53
|
export declare function addDefToWeightMap(map: WeightMap, def: SuggestionCostMapDef, ...defs: SuggestionCostMapDef[]): WeightMap;
|
|
54
|
+
export declare function addDefsToWeightMap(map: WeightMap, defs: SuggestionCostMapDef[]): WeightMap;
|
|
55
|
+
export declare function splitMapSubstringsIterable(map: string): Iterable<string>;
|
|
56
|
+
export declare function splitMapSubstrings(map: string): string[];
|
|
40
57
|
/**
|
|
41
58
|
* Splits a WeightedMapDef.map
|
|
42
59
|
* @param map
|
|
43
60
|
*/
|
|
44
61
|
declare function splitMap(def: Pick<SuggestionCostMapDef, 'map'>): string[][];
|
|
45
|
-
declare function splitMapSubstrings(map: string): string[];
|
|
46
62
|
interface MatchTrieCost {
|
|
47
63
|
i: number;
|
|
48
64
|
c: number;
|
|
65
|
+
p: number;
|
|
49
66
|
}
|
|
50
67
|
declare function findTrieCostPrefixes(trie: TrieCost, str: string, i: number): Iterable<MatchTrieCost>;
|
|
51
68
|
interface MatchTrieTrieCost {
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.__testing__ = exports.lookupReplaceCost = exports.prettyPrintWeightMap = exports.prettyPrintSwap = exports.prettyPrintReplace = exports.addDefToWeightMap = exports.createWeightMap = void 0;
|
|
3
|
+
exports.__testing__ = exports.lookupReplaceCost = exports.prettyPrintWeightMap = exports.prettyPrintSwap = exports.prettyPrintReplace = exports.splitMapSubstrings = exports.splitMapSubstringsIterable = exports.addDefsToWeightMap = exports.addDefToWeightMap = exports.createWeightMap = void 0;
|
|
4
4
|
function createWeightMap(...defs) {
|
|
5
5
|
const map = _createWeightMap();
|
|
6
|
-
|
|
6
|
+
addDefsToWeightMap(map, defs);
|
|
7
7
|
return map;
|
|
8
8
|
}
|
|
9
9
|
exports.createWeightMap = createWeightMap;
|
|
10
10
|
function addDefToWeightMap(map, ...defs) {
|
|
11
|
-
return
|
|
11
|
+
return addDefsToWeightMap(map, defs);
|
|
12
12
|
}
|
|
13
13
|
exports.addDefToWeightMap = addDefToWeightMap;
|
|
14
|
-
function
|
|
14
|
+
function addDefsToWeightMap(map, defs) {
|
|
15
15
|
function addSet(set, def) {
|
|
16
|
-
addSetToTrieCost(map.insDel, set, def.insDel);
|
|
17
|
-
addSetToTrieTrieCost(map.replace, set, def.replace);
|
|
18
|
-
addSetToTrieTrieCost(map.swap, set, def.swap);
|
|
16
|
+
addSetToTrieCost(map.insDel, set, def.insDel, def.penalty);
|
|
17
|
+
addSetToTrieTrieCost(map.replace, set, def.replace, def.penalty);
|
|
18
|
+
addSetToTrieTrieCost(map.swap, set, def.swap, def.penalty);
|
|
19
19
|
}
|
|
20
20
|
for (const def of defs) {
|
|
21
21
|
const mapSets = splitMap(def);
|
|
@@ -23,6 +23,7 @@ function _addDefToWeightMap(map, ...defs) {
|
|
|
23
23
|
}
|
|
24
24
|
return map;
|
|
25
25
|
}
|
|
26
|
+
exports.addDefsToWeightMap = addDefsToWeightMap;
|
|
26
27
|
function _createWeightMap() {
|
|
27
28
|
return new _WeightedMap();
|
|
28
29
|
}
|
|
@@ -33,6 +34,45 @@ function lowest(a, b) {
|
|
|
33
34
|
return a;
|
|
34
35
|
return a <= b ? a : b;
|
|
35
36
|
}
|
|
37
|
+
function highest(a, b) {
|
|
38
|
+
if (a === undefined)
|
|
39
|
+
return b;
|
|
40
|
+
if (b === undefined)
|
|
41
|
+
return a;
|
|
42
|
+
return a >= b ? a : b;
|
|
43
|
+
}
|
|
44
|
+
function normalize(s) {
|
|
45
|
+
const f = new Set([s]);
|
|
46
|
+
f.add(s.normalize('NFC'));
|
|
47
|
+
f.add(s.normalize('NFD'));
|
|
48
|
+
return f;
|
|
49
|
+
}
|
|
50
|
+
function* splitMapSubstringsIterable(map) {
|
|
51
|
+
let seq = '';
|
|
52
|
+
let mode = 0;
|
|
53
|
+
for (const char of map) {
|
|
54
|
+
if (mode && char === ')') {
|
|
55
|
+
yield* normalize(seq);
|
|
56
|
+
mode = 0;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (mode) {
|
|
60
|
+
seq += char;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (char === '(') {
|
|
64
|
+
mode = 1;
|
|
65
|
+
seq = '';
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
yield* normalize(char);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
exports.splitMapSubstringsIterable = splitMapSubstringsIterable;
|
|
72
|
+
function splitMapSubstrings(map) {
|
|
73
|
+
return [...splitMapSubstringsIterable(map)];
|
|
74
|
+
}
|
|
75
|
+
exports.splitMapSubstrings = splitMapSubstrings;
|
|
36
76
|
/**
|
|
37
77
|
* Splits a WeightedMapDef.map
|
|
38
78
|
* @param map
|
|
@@ -42,24 +82,7 @@ function splitMap(def) {
|
|
|
42
82
|
const sets = map.split('|');
|
|
43
83
|
return sets.map(splitMapSubstrings).filter((s) => s.length > 0);
|
|
44
84
|
}
|
|
45
|
-
function
|
|
46
|
-
const values = [];
|
|
47
|
-
const len = map.length;
|
|
48
|
-
for (let i = 0; i < len; ++i) {
|
|
49
|
-
const c = map[i];
|
|
50
|
-
if (c !== '(') {
|
|
51
|
-
values.push(c);
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
const s = i + 1;
|
|
55
|
-
while (map[++i] !== ')' && i < len) {
|
|
56
|
-
// empty
|
|
57
|
-
}
|
|
58
|
-
values.push(map.slice(s, i));
|
|
59
|
-
}
|
|
60
|
-
return values.map((s) => s.trim()).filter((s) => !!s);
|
|
61
|
-
}
|
|
62
|
-
function addToTrieCost(trie, str, cost) {
|
|
85
|
+
function addToTrieCost(trie, str, cost, penalties) {
|
|
63
86
|
if (!str)
|
|
64
87
|
return;
|
|
65
88
|
let t = trie;
|
|
@@ -68,31 +91,32 @@ function addToTrieCost(trie, str, cost) {
|
|
|
68
91
|
t = n[c] = n[c] || Object.create(null);
|
|
69
92
|
}
|
|
70
93
|
t.c = lowest(t.c, cost);
|
|
94
|
+
t.p = highest(t.p, penalties);
|
|
71
95
|
}
|
|
72
|
-
function addToTrieTrieCost(trie, left, right, cost) {
|
|
96
|
+
function addToTrieTrieCost(trie, left, right, cost, penalties) {
|
|
73
97
|
let t = trie;
|
|
74
98
|
for (const c of left) {
|
|
75
99
|
const n = (t.n = t.n || Object.create(null));
|
|
76
100
|
t = n[c] = n[c] || Object.create(null);
|
|
77
101
|
}
|
|
78
102
|
const trieCost = (t.t = t.t || Object.create(null));
|
|
79
|
-
addToTrieCost(trieCost, right, cost);
|
|
103
|
+
addToTrieCost(trieCost, right, cost, penalties);
|
|
80
104
|
}
|
|
81
|
-
function addSetToTrieCost(trie, set, cost) {
|
|
105
|
+
function addSetToTrieCost(trie, set, cost, penalties) {
|
|
82
106
|
if (cost === undefined)
|
|
83
107
|
return;
|
|
84
108
|
for (const str of set) {
|
|
85
|
-
addToTrieCost(trie, str, cost);
|
|
109
|
+
addToTrieCost(trie, str, cost, penalties);
|
|
86
110
|
}
|
|
87
111
|
}
|
|
88
|
-
function addSetToTrieTrieCost(trie, set, cost) {
|
|
112
|
+
function addSetToTrieTrieCost(trie, set, cost, penalties) {
|
|
89
113
|
if (cost === undefined)
|
|
90
114
|
return;
|
|
91
115
|
for (const left of set) {
|
|
92
116
|
for (const right of set) {
|
|
93
117
|
if (left === right)
|
|
94
118
|
continue;
|
|
95
|
-
addToTrieTrieCost(trie, left, right, cost);
|
|
119
|
+
addToTrieTrieCost(trie, left, right, cost, penalties);
|
|
96
120
|
}
|
|
97
121
|
}
|
|
98
122
|
}
|
|
@@ -120,24 +144,24 @@ function* walkTrieNodes(t, s) {
|
|
|
120
144
|
function* walkTrieCost(trie) {
|
|
121
145
|
for (const { s, t } of walkTrieNodes(trie, '')) {
|
|
122
146
|
if (t.c) {
|
|
123
|
-
yield { s, c: t.c };
|
|
147
|
+
yield { s, c: t.c, p: t.p };
|
|
124
148
|
}
|
|
125
149
|
}
|
|
126
150
|
}
|
|
127
151
|
function* walkTrieTrieCost(trie) {
|
|
128
152
|
for (const { s: a, t } of walkTrieNodes(trie, '')) {
|
|
129
153
|
if (t.t) {
|
|
130
|
-
for (const { s: b, c } of walkTrieCost(t.t)) {
|
|
131
|
-
yield { a, b, c };
|
|
154
|
+
for (const { s: b, c, p } of walkTrieCost(t.t)) {
|
|
155
|
+
yield { a, b, c, p };
|
|
132
156
|
}
|
|
133
157
|
}
|
|
134
158
|
}
|
|
135
159
|
}
|
|
136
160
|
function* findTrieCostPrefixes(trie, str, i) {
|
|
137
161
|
for (const n of searchTrieNodes(trie, str, i)) {
|
|
138
|
-
const c = n.t
|
|
162
|
+
const { c, p } = n.t;
|
|
139
163
|
if (c !== undefined) {
|
|
140
|
-
yield { i: n.i, c };
|
|
164
|
+
yield { i: n.i, c, p: p || 0 };
|
|
141
165
|
}
|
|
142
166
|
}
|
|
143
167
|
}
|
|
@@ -156,34 +180,34 @@ class _WeightedMap {
|
|
|
156
180
|
this.swap = {};
|
|
157
181
|
}
|
|
158
182
|
*calcInsDelCosts(pos) {
|
|
159
|
-
const { a, ai, b, bi, c } = pos;
|
|
183
|
+
const { a, ai, b, bi, c, p } = pos;
|
|
160
184
|
for (const del of findTrieCostPrefixes(this.insDel, a, ai)) {
|
|
161
|
-
yield { a, b, ai: del.i, bi, c: c + del.c };
|
|
185
|
+
yield { a, b, ai: del.i, bi, c: c + del.c, p: p + del.p };
|
|
162
186
|
}
|
|
163
187
|
for (const ins of findTrieCostPrefixes(this.insDel, b, bi)) {
|
|
164
|
-
yield { a, b, ai, bi: ins.i, c: c + ins.c };
|
|
188
|
+
yield { a, b, ai, bi: ins.i, c: c + ins.c, p: p + ins.p };
|
|
165
189
|
}
|
|
166
190
|
}
|
|
167
191
|
*calcReplaceCosts(pos) {
|
|
168
192
|
// Search for matching substrings in `a` to be replaced by
|
|
169
193
|
// matching substrings from `b`. All substrings start at their
|
|
170
194
|
// respective `ai`/`bi` positions.
|
|
171
|
-
const { a, ai, b, bi, c } = pos;
|
|
195
|
+
const { a, ai, b, bi, c, p } = pos;
|
|
172
196
|
for (const del of findTrieTrieCostPrefixes(this.replace, a, ai)) {
|
|
173
197
|
for (const ins of findTrieCostPrefixes(del.t, b, bi)) {
|
|
174
|
-
yield { a, b, ai: del.i, bi: ins.i, c: c + ins.c };
|
|
198
|
+
yield { a, b, ai: del.i, bi: ins.i, c: c + ins.c, p: p + ins.p };
|
|
175
199
|
}
|
|
176
200
|
}
|
|
177
201
|
}
|
|
178
202
|
*calcSwapCosts(pos) {
|
|
179
|
-
const { a, ai, b, bi, c } = pos;
|
|
203
|
+
const { a, ai, b, bi, c, p } = pos;
|
|
180
204
|
const swap = this.swap;
|
|
181
205
|
for (const left of findTrieTrieCostPrefixes(swap, a, ai)) {
|
|
182
206
|
for (const right of findTrieCostPrefixes(left.t, a, left.i)) {
|
|
183
207
|
const sw = a.slice(left.i, right.i) + a.slice(ai, left.i);
|
|
184
208
|
if (b.slice(bi).startsWith(sw)) {
|
|
185
209
|
const len = sw.length;
|
|
186
|
-
yield { a, b, ai: ai + len, bi: bi + len, c: c + right.c };
|
|
210
|
+
yield { a, b, ai: ai + len, bi: bi + len, c: c + right.c, p: p + right.p };
|
|
187
211
|
}
|
|
188
212
|
}
|
|
189
213
|
}
|
|
@@ -191,16 +215,18 @@ class _WeightedMap {
|
|
|
191
215
|
}
|
|
192
216
|
function prettyPrintInsDel(trie, pfx = '', indent = ' ') {
|
|
193
217
|
function* walk() {
|
|
194
|
-
for (const { s, c } of walkTrieCost(trie)) {
|
|
195
|
-
|
|
218
|
+
for (const { s, c, p } of walkTrieCost(trie)) {
|
|
219
|
+
const pm = p ? ` + ${p}` : '';
|
|
220
|
+
yield indent + `(${s}) = ${c}${pm}`;
|
|
196
221
|
}
|
|
197
222
|
}
|
|
198
223
|
return ['InsDel:', ...[...walk()].sort()].map((line) => pfx + line + '\n').join('');
|
|
199
224
|
}
|
|
200
225
|
function prettyPrintReplace(trie, pfx = '', indent = ' ') {
|
|
201
226
|
function* walk() {
|
|
202
|
-
for (const { a, b, c } of walkTrieTrieCost(trie)) {
|
|
203
|
-
|
|
227
|
+
for (const { a, b, c, p } of walkTrieTrieCost(trie)) {
|
|
228
|
+
const pm = p ? ` + ${p}` : '';
|
|
229
|
+
yield indent + `(${a}) -> (${b}) = ${c}${pm}`;
|
|
204
230
|
}
|
|
205
231
|
}
|
|
206
232
|
return ['Replace:', ...[...walk()].sort()].map((line) => pfx + line + '\n').join('');
|
|
@@ -208,8 +234,9 @@ function prettyPrintReplace(trie, pfx = '', indent = ' ') {
|
|
|
208
234
|
exports.prettyPrintReplace = prettyPrintReplace;
|
|
209
235
|
function prettyPrintSwap(trie, pfx = '', indent = ' ') {
|
|
210
236
|
function* walk() {
|
|
211
|
-
for (const { a, b, c } of walkTrieTrieCost(trie)) {
|
|
212
|
-
|
|
237
|
+
for (const { a, b, c, p } of walkTrieTrieCost(trie)) {
|
|
238
|
+
const pm = p ? ` + ${p}` : '';
|
|
239
|
+
yield indent + `(${a}) <-> (${b}) = ${c}${pm}`;
|
|
213
240
|
}
|
|
214
241
|
}
|
|
215
242
|
return ['Swap:', ...[...walk()].sort()].map((line) => pfx + line + '\n').join('');
|
package/dist/lib/find.d.ts
CHANGED
package/dist/lib/find.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.__testing__ = exports.createFindOptions = exports.isForbiddenWord = exports.isEndOfWordNode = exports.findWordExact = exports.findCompoundNode = exports.findLegacyCompound = exports.findWordNode = exports.findWord = void 0;
|
|
4
|
-
const TrieNode_1 = require("./TrieNode");
|
|
5
|
-
const trie_util_1 = require("./trie-util");
|
|
6
4
|
const constants_1 = require("./constants");
|
|
5
|
+
const trie_util_1 = require("./trie-util");
|
|
6
|
+
const TrieNode_1 = require("./TrieNode");
|
|
7
7
|
const defaultLegacyMinCompoundLength = 3;
|
|
8
8
|
const _defaultFindOptions = {
|
|
9
9
|
matchCase: false,
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export { consolidate } from './consolidate';
|
|
2
2
|
export { createWeightedMap, editDistance, editDistanceWeighted } from './distance';
|
|
3
|
-
export type {
|
|
3
|
+
export type { WeightMap } from './distance';
|
|
4
4
|
export type { FindFullResult } from './find';
|
|
5
5
|
export { ExportOptions, importTrie, serializeTrie } from './io/importExport';
|
|
6
|
+
export { mapDictionaryInformationToWeightMap } from './mappers/mapDictionaryInfoToWeightMap';
|
|
7
|
+
export type { SuggestionCostMapDef } from './models/suggestionCostsDef';
|
|
6
8
|
export { parseDictionary, parseDictionaryLines } from './SimpleDictionaryParser';
|
|
7
9
|
export { MaxCost, suggestionCollector, SuggestionCollector, SuggestionResult } from './suggestCollector';
|
|
8
10
|
export { CASE_INSENSITIVE_PREFIX, COMPOUND, COMPOUND_FIX, defaultTrieOptions, FORBID, FORBID_PREFIX, NORMALIZED, OPTIONAL_COMPOUND, OPTIONAL_COMPOUND_FIX, Trie, } from './trie';
|
package/dist/lib/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.WORD_SEPARATOR = 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.parseDictionaryLines = exports.parseDictionary = exports.serializeTrie = exports.importTrie = exports.editDistanceWeighted = exports.editDistance = exports.createWeightedMap = exports.consolidate = void 0;
|
|
3
|
+
exports.WORD_SEPARATOR = 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.parseDictionaryLines = exports.parseDictionary = exports.mapDictionaryInformationToWeightMap = exports.serializeTrie = exports.importTrie = exports.editDistanceWeighted = exports.editDistance = exports.createWeightedMap = exports.consolidate = void 0;
|
|
4
4
|
var consolidate_1 = require("./consolidate");
|
|
5
5
|
Object.defineProperty(exports, "consolidate", { enumerable: true, get: function () { return consolidate_1.consolidate; } });
|
|
6
6
|
var distance_1 = require("./distance");
|
|
@@ -10,6 +10,8 @@ Object.defineProperty(exports, "editDistanceWeighted", { enumerable: true, get:
|
|
|
10
10
|
var importExport_1 = require("./io/importExport");
|
|
11
11
|
Object.defineProperty(exports, "importTrie", { enumerable: true, get: function () { return importExport_1.importTrie; } });
|
|
12
12
|
Object.defineProperty(exports, "serializeTrie", { enumerable: true, get: function () { return importExport_1.serializeTrie; } });
|
|
13
|
+
var mapDictionaryInfoToWeightMap_1 = require("./mappers/mapDictionaryInfoToWeightMap");
|
|
14
|
+
Object.defineProperty(exports, "mapDictionaryInformationToWeightMap", { enumerable: true, get: function () { return mapDictionaryInfoToWeightMap_1.mapDictionaryInformationToWeightMap; } });
|
|
13
15
|
var SimpleDictionaryParser_1 = require("./SimpleDictionaryParser");
|
|
14
16
|
Object.defineProperty(exports, "parseDictionary", { enumerable: true, get: function () { return SimpleDictionaryParser_1.parseDictionary; } });
|
|
15
17
|
Object.defineProperty(exports, "parseDictionaryLines", { enumerable: true, get: function () { return SimpleDictionaryParser_1.parseDictionaryLines; } });
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { HunspellCosts, EditCosts } from '../models/DictionaryInformation';
|
|
2
|
+
export declare type EditCostsRequired = Required<EditCosts>;
|
|
3
|
+
export declare type HunspellCostsRequired = Required<HunspellCosts>;
|
|
4
|
+
export declare function mapHunspellCosts(costs?: HunspellCosts): HunspellCostsRequired;
|
|
5
|
+
export declare function mapEditCosts(costs?: EditCosts): EditCostsRequired;
|
|
6
|
+
//# sourceMappingURL=mapCosts.d.ts.map
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mapEditCosts = exports.mapHunspellCosts = void 0;
|
|
4
|
+
const util_1 = require("../utils/util");
|
|
5
|
+
const defaultEditCosts = {
|
|
6
|
+
accentCosts: 1,
|
|
7
|
+
baseCost: 100,
|
|
8
|
+
capsCosts: 1,
|
|
9
|
+
firstLetterPenalty: 4,
|
|
10
|
+
nonAlphabetCosts: 110,
|
|
11
|
+
};
|
|
12
|
+
const defaultHunspellCosts = {
|
|
13
|
+
...defaultEditCosts,
|
|
14
|
+
ioConvertCost: 30,
|
|
15
|
+
keyboardCost: 99,
|
|
16
|
+
mapCost: 25,
|
|
17
|
+
replaceCosts: 75,
|
|
18
|
+
tryCharCost: 100,
|
|
19
|
+
};
|
|
20
|
+
function mapHunspellCosts(costs = {}) {
|
|
21
|
+
return { ...defaultHunspellCosts, ...(0, util_1.cleanCopy)(costs) };
|
|
22
|
+
}
|
|
23
|
+
exports.mapHunspellCosts = mapHunspellCosts;
|
|
24
|
+
function mapEditCosts(costs = {}) {
|
|
25
|
+
return { ...defaultEditCosts, ...(0, util_1.cleanCopy)(costs) };
|
|
26
|
+
}
|
|
27
|
+
exports.mapEditCosts = mapEditCosts;
|
|
28
|
+
//# sourceMappingURL=mapCosts.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { DictionaryInformation } from '../models/DictionaryInformation';
|
|
2
|
+
import type { SuggestionCostMapDef } from '../models/suggestionCostsDef';
|
|
3
|
+
export declare function mapDictionaryInformation(dictInfo: DictionaryInformation): SuggestionCostMapDef[];
|
|
4
|
+
//# sourceMappingURL=mapDictionaryInfo.d.ts.map
|