-
-
Notifications
You must be signed in to change notification settings - Fork 84
/
IgnoreWordsDictionary.ts
128 lines (114 loc) · 4.11 KB
/
IgnoreWordsDictionary.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import { opFilter, opMap, pipe } from '@cspell/cspell-pipe/sync';
import { CompoundWordsMethod, parseDictionaryLines, SuggestionResult } from 'cspell-trie-lib';
import {
FindResult,
HasOptions,
SearchOptions,
SpellingDictionary,
SpellingDictionaryOptions,
SuggestOptions,
} from './SpellingDictionary';
import * as Defaults from './defaults';
import { createSpellingDictionary } from './createSpellingDictionary';
const NormalizeForm = 'NFC' as const;
class IgnoreWordsDictionary implements SpellingDictionary {
private dict: Set<string>;
private dictNonStrict: Set<string>;
readonly containsNoSuggestWords = true;
readonly options: SpellingDictionaryOptions = {};
readonly type = 'forbidden';
constructor(readonly name: string, readonly source: string, words: Iterable<string>) {
this.dict = new Set(words);
this.dictNonStrict = new Set(
pipe(
this.dict,
opFilter((w) => w.startsWith('~')),
opMap((w) => w.slice(1))
)
);
}
/**
* A Forbidden word list does not "have" valid words.
* Therefore it always returns false.
* @param _word - the word
* @param _options - options
* @returns always false
*/
has(word: string, options?: HasOptions): boolean {
const nWord = word.normalize(NormalizeForm);
if (this.dict.has(nWord)) return true;
const lcWord = nWord.toLowerCase();
if (this.dict.has(lcWord)) return true;
const ignoreCase = options?.ignoreCase ?? Defaults.ignoreCase;
return ignoreCase && (this.dictNonStrict.has(nWord) || this.dictNonStrict.has(lcWord));
}
/** A more detailed search for a word, might take longer than `has` */
find(word: string, options?: SearchOptions): FindResult | undefined {
const nWord = word.normalize(NormalizeForm);
if (this.dict.has(nWord)) return { found: nWord, forbidden: false, noSuggest: true };
const lcWord = nWord.toLowerCase();
if (this.dict.has(lcWord)) return { found: lcWord, forbidden: false, noSuggest: true };
const ignoreCase = options?.ignoreCase ?? Defaults.ignoreCase;
if (!ignoreCase) return undefined;
if (this.dictNonStrict.has(nWord)) return { found: nWord, forbidden: false, noSuggest: true };
return (this.dictNonStrict.has(lcWord) && { found: lcWord, forbidden: false, noSuggest: true }) || undefined;
}
isForbidden(_word: string): boolean {
return false;
}
isNoSuggestWord(word: string, options: HasOptions): boolean {
return this.has(word, options);
}
suggest(
word: string,
numSuggestions?: number,
compoundMethod?: CompoundWordsMethod,
numChanges?: number,
ignoreCase?: boolean
): SuggestionResult[];
suggest(word: string, suggestOptions: SuggestOptions): SuggestionResult[];
suggest() {
return [];
}
genSuggestions(): void {
return;
}
mapWord(word: string): string {
return word;
}
get size() {
return this.dict.size;
}
readonly isDictionaryCaseSensitive: boolean = true;
getErrors?(): Error[] {
return [];
}
}
/**
* Create a dictionary where all words are to be ignored.
* Ignored words override forbidden words.
* @param wordList - list of words
* @param name - name of dictionary
* @param source - dictionary source
* @returns
*/
export function createIgnoreWordsDictionary(
wordList: readonly string[],
name: string,
source: string
): SpellingDictionary {
const testSpecialCharacters = /[*+]/;
const words = [...parseDictionaryLines(wordList, { stripCaseAndAccents: true })].map((w) =>
w.normalize(NormalizeForm)
);
const hasSpecial = words.findIndex((word) => testSpecialCharacters.test(word)) >= 0;
if (hasSpecial) {
return createSpellingDictionary(words, name, source, {
caseSensitive: true,
noSuggest: true,
weightMap: undefined,
supportNonStrictSearches: true,
});
}
return new IgnoreWordsDictionary(name, source, words);
}