cspell-dictionary 6.27.0 → 6.28.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.
@@ -134,6 +134,13 @@ export interface SpellingDictionary extends DictionaryInfo {
134
134
  suggest(word: string, suggestOptions: SuggestOptions): SuggestionResult[];
135
135
  genSuggestions(collector: SuggestionCollector, suggestOptions: SuggestOptions): void;
136
136
  mapWord(word: string): string;
137
+ /**
138
+ * Generates all possible word combinations by applying `repMap`.
139
+ * This acts a bit like brace expansions in globs.
140
+ * @param word - the word to map
141
+ * @returns array of adjusted words.
142
+ */
143
+ remapWord?: (word: string) => string[];
137
144
  readonly size: number;
138
145
  readonly isDictionaryCaseSensitive: boolean;
139
146
  getErrors?(): Error[];
@@ -11,6 +11,7 @@ export declare class SpellingDictionaryFromTrie implements SpellingDictionary {
11
11
  readonly knownWords: Set<string>;
12
12
  readonly unknownWords: Set<string>;
13
13
  readonly mapWord: (word: string) => string;
14
+ readonly remapWord: (word: string) => string[];
14
15
  readonly type = "SpellingDictionaryFromTrie";
15
16
  readonly isDictionaryCaseSensitive: boolean;
16
17
  readonly containsNoSuggestWords: boolean;
@@ -41,7 +42,7 @@ export declare class SpellingDictionaryFromTrie implements SpellingDictionary {
41
42
  * @returns SpellingDictionary
42
43
  */
43
44
  export declare function createSpellingDictionaryFromTrieFile(data: Iterable<string> | string, name: string, source: string, options: SpellingDictionaryOptions): SpellingDictionary;
44
- declare function outerWordForms(word: string, mapWord: (word: string) => string): Set<string>;
45
+ declare function outerWordForms(word: string, mapWord: (word: string) => string[]): Set<string>;
45
46
  export declare const __testing__: {
46
47
  outerWordForms: typeof outerWordForms;
47
48
  };
@@ -48,6 +48,7 @@ class SpellingDictionaryFromTrie {
48
48
  return this.trie.isForbiddenWord(word);
49
49
  });
50
50
  this.mapWord = (0, repMap_1.createMapper)(options.repMap, options.dictionaryInformation?.ignore);
51
+ this.remapWord = (0, repMap_1.createRepMapper)(options.repMap, options.dictionaryInformation?.ignore);
51
52
  this.isDictionaryCaseSensitive = options.caseSensitive ?? !trie.isLegacy;
52
53
  this.containsNoSuggestWords = options.noSuggest || false;
53
54
  this._size = size || 0;
@@ -89,7 +90,7 @@ class SpellingDictionaryFromTrie {
89
90
  return { useCompounds, ignoreCase };
90
91
  }
91
92
  findAnyForm(word, useCompounds, ignoreCase) {
92
- const outerForms = outerWordForms(word, this.mapWord);
93
+ const outerForms = outerWordForms(word, this.remapWord ? this.remapWord : (word) => [this.mapWord(word)]);
93
94
  for (const form of outerForms) {
94
95
  const r = this._findAnyForm(form, useCompounds, ignoreCase);
95
96
  if (r)
@@ -193,7 +194,7 @@ function findCache(fn, size = 2000) {
193
194
  return find;
194
195
  }
195
196
  function outerWordForms(word, mapWord) {
196
- const forms = (0, sync_1.pipe)([word], (0, sync_1.opConcatMap)((word) => [word, word.normalize('NFC'), word.normalize('NFD')]), (0, sync_1.opConcatMap)((word) => [word, mapWord(word)]));
197
+ const forms = (0, sync_1.pipe)([word], (0, sync_1.opConcatMap)((word) => [word, word.normalize('NFC'), word.normalize('NFD')]), (0, sync_1.opConcatMap)((word) => [word, ...mapWord(word)]));
197
198
  return new Set(forms);
198
199
  }
199
200
  exports.__testing__ = { outerWordForms };
@@ -1,11 +1,27 @@
1
1
  import type { CharacterSet, ReplaceMap } from '@cspell/cspell-types';
2
2
  export type ReplaceMapper = (src: string) => string;
3
3
  export declare function createMapper(repMap: ReplaceMap | undefined, ignoreCharset?: string): ReplaceMapper;
4
- declare function charsetToRepMap(charset: CharacterSet | undefined, replaceWith?: string): ReplaceMap | undefined;
4
+ declare function charsetToRepMapRegEx(charset: CharacterSet | undefined, replaceWith?: string): ReplaceMap | undefined;
5
5
  declare function createMapperRegExp(repMap: ReplaceMap): RegExp;
6
+ interface RepTrieNode {
7
+ rep?: string[];
8
+ children?: Record<string, RepTrieNode>;
9
+ }
10
+ interface Edit {
11
+ b: number;
12
+ e: number;
13
+ r: string;
14
+ }
15
+ export declare function createRepMapper(repMap: ReplaceMap | undefined, ignoreCharset?: string): (word: string) => string[];
16
+ declare function applyEdits(word: string, edits: Edit[]): string[];
17
+ declare function calcAllEdits(root: RepTrieNode, word: string): Edit[];
18
+ declare function createTrie(repMap: ReplaceMap | undefined, ignoreCharset?: string): RepTrieNode;
6
19
  export declare const __testing__: {
7
- charsetToRepMap: typeof charsetToRepMap;
20
+ charsetToRepMap: typeof charsetToRepMapRegEx;
8
21
  createMapperRegExp: typeof createMapperRegExp;
22
+ createTrie: typeof createTrie;
23
+ calcAllEdits: typeof calcAllEdits;
24
+ applyEdits: typeof applyEdits;
9
25
  };
10
26
  export {};
11
27
  //# sourceMappingURL=repMap.d.ts.map
@@ -1,12 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.__testing__ = exports.createMapper = void 0;
3
+ exports.__testing__ = exports.createRepMapper = exports.createMapper = void 0;
4
+ const cspell_trie_lib_1 = require("cspell-trie-lib");
4
5
  const regexHelper_1 = require("./regexHelper");
6
+ const util_1 = require("./util");
5
7
  function createMapper(repMap, ignoreCharset) {
6
8
  if (!repMap && !ignoreCharset)
7
9
  return (a) => a;
8
10
  repMap = repMap || [];
9
- const charsetMap = charsetToRepMap(ignoreCharset);
11
+ const charsetMap = charsetToRepMapRegEx(ignoreCharset);
10
12
  if (charsetMap) {
11
13
  repMap = repMap.concat(charsetMap);
12
14
  }
@@ -25,7 +27,7 @@ function createMapper(repMap, ignoreCharset) {
25
27
  };
26
28
  }
27
29
  exports.createMapper = createMapper;
28
- function charsetToRepMap(charset, replaceWith = '') {
30
+ function charsetToRepMapRegEx(charset, replaceWith = '') {
29
31
  if (!charset)
30
32
  return undefined;
31
33
  return charset
@@ -33,6 +35,17 @@ function charsetToRepMap(charset, replaceWith = '') {
33
35
  .map((chars) => `[${chars.replace(/[\][\\]/g, '\\$&')}]`)
34
36
  .map((map) => [map, replaceWith]);
35
37
  }
38
+ function charsetToRepMap(charset, replaceWith = '') {
39
+ if (!charset)
40
+ return undefined;
41
+ return charset
42
+ .split('|')
43
+ .flatMap((chars) => [...(0, cspell_trie_lib_1.expandCharacterSet)(chars)])
44
+ .map((char) => [char, replaceWith]);
45
+ }
46
+ function expandReplaceMap(repMap) {
47
+ return repMap.flatMap(([from, replaceWith]) => from.split('|').map((w) => [w, replaceWith]));
48
+ }
36
49
  function createMapperRegExp(repMap) {
37
50
  const filteredMap = repMap.filter(([match, _]) => !!match);
38
51
  if (!filteredMap.length) {
@@ -58,8 +71,88 @@ function createMapperRegExp(repMap) {
58
71
  const regEx = new RegExp(regExStr, 'g');
59
72
  return regEx;
60
73
  }
74
+ function createRepMapper(repMap, ignoreCharset) {
75
+ if (!repMap && !ignoreCharset)
76
+ return (word) => [word];
77
+ const trie = createTrie(repMap, ignoreCharset);
78
+ // const root = createTrie(repMap, ignoreCharset);
79
+ return (word) => {
80
+ const edits = calcAllEdits(trie, word);
81
+ return applyEdits(word, edits);
82
+ };
83
+ }
84
+ exports.createRepMapper = createRepMapper;
85
+ function applyEdits(word, edits) {
86
+ if (!edits.length)
87
+ return [word];
88
+ // Prepare
89
+ const letterEdits = [];
90
+ for (let i = 0; i < word.length; ++i) {
91
+ letterEdits[i] = { edits: [{ b: i, e: i + 1, r: word[i] }], suffixes: [] };
92
+ }
93
+ letterEdits[word.length] = { edits: [], suffixes: [''] };
94
+ // Add edits
95
+ for (const edit of edits) {
96
+ const le = letterEdits[edit.b];
97
+ le.edits.push(edit);
98
+ }
99
+ // Apply edits in reverse
100
+ for (let i = word.length - 1; i >= 0; --i) {
101
+ const le = letterEdits[i];
102
+ const sfx = le.suffixes;
103
+ for (const edit of le.edits) {
104
+ const pfx = edit.r;
105
+ const nSfx = letterEdits[edit.e].suffixes;
106
+ for (const s of nSfx) {
107
+ sfx.push(pfx + s);
108
+ }
109
+ }
110
+ }
111
+ const results = new Set(letterEdits[0].suffixes);
112
+ return [...results];
113
+ }
114
+ function calcAllEdits(root, word) {
115
+ const edits = [];
116
+ function walk(node, b, e) {
117
+ if (node.rep) {
118
+ node.rep.forEach((r) => edits.push({ b, e, r }));
119
+ }
120
+ if (e === word.length || !node.children)
121
+ return;
122
+ const n = node.children[word[e]];
123
+ if (!n)
124
+ return;
125
+ walk(n, b, e + 1);
126
+ }
127
+ for (let i = 0; i < word.length; ++i) {
128
+ walk(root, i, i);
129
+ }
130
+ return edits;
131
+ }
132
+ function createTrie(repMap, ignoreCharset) {
133
+ const combined = [repMap, charsetToRepMap(ignoreCharset)].filter(util_1.isDefined).flatMap((a) => a);
134
+ const expanded = expandReplaceMap(combined);
135
+ const trieRoot = Object.create(null);
136
+ expanded.forEach(([match, replaceWith]) => addToTrie(trieRoot, match, replaceWith));
137
+ return trieRoot;
138
+ }
139
+ function addToTrie(node, match, replaceWith) {
140
+ while (match) {
141
+ const children = node.children || (node.children = Object.create(null));
142
+ const k = match[0];
143
+ const childNode = children[k] || (children[k] = Object.create(null));
144
+ node = childNode;
145
+ match = match.slice(1);
146
+ }
147
+ const s = new Set(node.rep || []);
148
+ s.add(replaceWith);
149
+ node.rep = [...s];
150
+ }
61
151
  exports.__testing__ = {
62
- charsetToRepMap,
152
+ charsetToRepMap: charsetToRepMapRegEx,
63
153
  createMapperRegExp,
154
+ createTrie,
155
+ calcAllEdits,
156
+ applyEdits,
64
157
  };
65
158
  //# sourceMappingURL=repMap.js.map
package/package.json CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "cspell-dictionary",
3
- "version": "6.27.0",
3
+ "version": "6.28.0",
4
4
  "description": "A spelling dictionary library useful for checking words and getting suggestions.",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
7
7
  "files": [
8
8
  "dist",
9
+ "!**/*.tsbuildInfo",
9
10
  "!**/__mocks__",
10
11
  "!**/*.test.*",
11
12
  "!**/*.spec.*",
@@ -13,7 +14,6 @@
13
14
  ],
14
15
  "scripts": {
15
16
  "build": "tsc -p .",
16
- "build-dev": "tsc -p tsconfig.dev.json",
17
17
  "watch": "tsc -p . -w",
18
18
  "clean": "shx rm -rf dist temp coverage .tsbuildinfo",
19
19
  "clean-build": "pnpm run clean && pnpm run build",
@@ -43,11 +43,11 @@
43
43
  "ts-jest": "^29.0.5"
44
44
  },
45
45
  "dependencies": {
46
- "@cspell/cspell-pipe": "6.27.0",
47
- "@cspell/cspell-types": "6.27.0",
48
- "cspell-trie-lib": "6.27.0",
46
+ "@cspell/cspell-pipe": "6.28.0",
47
+ "@cspell/cspell-types": "6.28.0",
48
+ "cspell-trie-lib": "6.28.0",
49
49
  "fast-equals": "^4.0.3",
50
- "gensequence": "^4.0.3"
50
+ "gensequence": "^5.0.2"
51
51
  },
52
- "gitHead": "b0e31c7ba91ba467d5fd9c66f238bb5d899f4833"
52
+ "gitHead": "1c314413e76908e5fbf61fd2555726112b177c0e"
53
53
  }