cspell-lib 6.29.2 → 6.30.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/cjs/Models/ValidationIssue.d.ts +2 -2
- package/dist/cjs/textValidation/ValidationTypes.d.ts +5 -3
- package/dist/cjs/textValidation/docValidator.d.ts +1 -0
- package/dist/cjs/textValidation/docValidator.js +21 -5
- package/dist/cjs/textValidation/isWordValid.d.ts +2 -1
- package/dist/cjs/textValidation/isWordValid.js +2 -3
- package/dist/cjs/textValidation/lineValidatorFactory.js +17 -8
- package/dist/cjs/textValidation/textValidator.d.ts +1 -2
- package/dist/cjs/textValidation/textValidator.js +1 -2
- package/dist/cjs/util/textRegex.js +2 -2
- package/dist/esm/Models/ValidationIssue.d.mts +2 -2
- package/dist/esm/textValidation/ValidationTypes.d.mts +5 -3
- package/dist/esm/textValidation/docValidator.d.mts +1 -0
- package/dist/esm/textValidation/docValidator.mjs +21 -5
- package/dist/esm/textValidation/isWordValid.d.mts +2 -1
- package/dist/esm/textValidation/isWordValid.mjs +2 -2
- package/dist/esm/textValidation/lineValidatorFactory.mjs +17 -8
- package/dist/esm/textValidation/textValidator.d.mts +1 -2
- package/dist/esm/textValidation/textValidator.mjs +1 -2
- package/dist/esm/util/textRegex.mjs +2 -2
- package/package.json +12 -12
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ExtendedSuggestion } from './Suggestion.js';
|
|
2
2
|
import type { ValidationResult } from './ValidationResult.js';
|
|
3
3
|
export interface ValidationIssue extends ValidationResult {
|
|
4
|
-
suggestions?: string[];
|
|
5
|
-
suggestionsEx?: ExtendedSuggestion[];
|
|
4
|
+
suggestions?: string[] | undefined;
|
|
5
|
+
suggestionsEx?: ExtendedSuggestion[] | undefined;
|
|
6
6
|
}
|
|
7
7
|
//# sourceMappingURL=ValidationIssue.d.ts.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { MappedText, TextOffset as TextOffsetRW } from '@cspell/cspell-types';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ExtendedSuggestion } from '../Models/Suggestion.js';
|
|
3
|
+
import type { ValidationIssue } from '../Models/ValidationIssue.js';
|
|
3
4
|
export type TextOffsetRO = Readonly<TextOffsetRW>;
|
|
4
5
|
export interface ValidationOptions extends IncludeExcludeOptions {
|
|
5
6
|
maxNumberOfProblems?: number;
|
|
@@ -23,8 +24,8 @@ export interface WordRangeAcc {
|
|
|
23
24
|
isIncluded: boolean;
|
|
24
25
|
rangePos: number;
|
|
25
26
|
}
|
|
26
|
-
export type
|
|
27
|
-
export type LineValidatorFn = (line: LineSegment) => Iterable<
|
|
27
|
+
export type ValidationIssueRO = Readonly<ValidationIssue>;
|
|
28
|
+
export type LineValidatorFn = (line: LineSegment) => Iterable<ValidationIssue>;
|
|
28
29
|
export interface LineSegment {
|
|
29
30
|
line: TextOffsetRO;
|
|
30
31
|
segment: TextOffsetRO;
|
|
@@ -32,6 +33,7 @@ export interface LineSegment {
|
|
|
32
33
|
export interface MappedTextValidationResult extends MappedText {
|
|
33
34
|
isFlagged?: boolean | undefined;
|
|
34
35
|
isFound?: boolean | undefined;
|
|
36
|
+
suggestionsEx?: ExtendedSuggestion[] | undefined;
|
|
35
37
|
}
|
|
36
38
|
export type TextValidatorFn = (text: MappedText) => Iterable<MappedTextValidationResult>;
|
|
37
39
|
//# sourceMappingURL=ValidationTypes.d.ts.map
|
|
@@ -83,6 +83,7 @@ export declare class DocumentValidator {
|
|
|
83
83
|
private _parse;
|
|
84
84
|
private getSuggestions;
|
|
85
85
|
private genSuggestions;
|
|
86
|
+
private adjustSuggestions;
|
|
86
87
|
getFinalizedDocSettings(): CSpellSettingsInternal;
|
|
87
88
|
/**
|
|
88
89
|
* Returns true if the final result of the configuration calculation results
|
|
@@ -196,18 +196,24 @@ class DocumentValidator {
|
|
|
196
196
|
const document = this._document;
|
|
197
197
|
let line = undefined;
|
|
198
198
|
function mapToIssue(issue) {
|
|
199
|
-
const { range, text, isFlagged, isFound } = issue;
|
|
199
|
+
const { range, text, isFlagged, isFound, suggestionsEx } = issue;
|
|
200
200
|
const offset = range[0];
|
|
201
201
|
const length = range[1] - range[0];
|
|
202
202
|
(0, assert_1.default)(!line || line.offset <= offset);
|
|
203
203
|
if (!line || line.offset + line.text.length <= offset) {
|
|
204
204
|
line = document.lineAt(offset);
|
|
205
205
|
}
|
|
206
|
-
return { text, offset, line, length, isFlagged, isFound };
|
|
206
|
+
return { text, offset, line, length, isFlagged, isFound, suggestionsEx };
|
|
207
207
|
}
|
|
208
208
|
const issues = [...(0, sync_1.pipeSync)(segmenter(parsedText), (0, sync_1.opConcatMap)(textValidator.validate), (0, sync_1.opMap)(mapToIssue))];
|
|
209
209
|
if (!this.options.generateSuggestions) {
|
|
210
|
-
return issues
|
|
210
|
+
return issues.map((issue) => {
|
|
211
|
+
if (!issue.suggestionsEx)
|
|
212
|
+
return issue;
|
|
213
|
+
const suggestionsEx = this.adjustSuggestions(issue.text, issue.suggestionsEx);
|
|
214
|
+
const suggestions = suggestionsEx.map((s) => s.word);
|
|
215
|
+
return { ...issue, suggestionsEx, suggestions };
|
|
216
|
+
});
|
|
211
217
|
}
|
|
212
218
|
const withSugs = issues.map((t) => {
|
|
213
219
|
// lazy suggestion calculation.
|
|
@@ -323,9 +329,16 @@ class DocumentValidator {
|
|
|
323
329
|
timeout: settings.suggestionsTimeout,
|
|
324
330
|
numChanges: settings.suggestionNumChanges,
|
|
325
331
|
};
|
|
326
|
-
const locale = this._preparations.config.language;
|
|
327
332
|
const rawSuggestions = dict.suggest(text, sugOptions);
|
|
328
|
-
|
|
333
|
+
return this.adjustSuggestions(text, rawSuggestions);
|
|
334
|
+
}
|
|
335
|
+
adjustSuggestions(text, rawSuggestions) {
|
|
336
|
+
(0, assert_1.default)(this._preparations, ERROR_NOT_PREPARED);
|
|
337
|
+
const settings = this._preparations.docSettings;
|
|
338
|
+
const ignoreCase = !(settings.caseSensitive ?? false);
|
|
339
|
+
const locale = this._preparations.config.language;
|
|
340
|
+
const dict = this._preparations.dictionary;
|
|
341
|
+
const sugsWithAlt = (0, suggestions_js_1.calcSuggestionAdjustedToToMatchCase)(text, rawSuggestions.map(mapSug), locale, ignoreCase, dict);
|
|
329
342
|
return sugsWithAlt.map(sanitizeSuggestion);
|
|
330
343
|
}
|
|
331
344
|
getFinalizedDocSettings() {
|
|
@@ -368,6 +381,9 @@ async function searchForDocumentConfig(document, defaultConfig, pnpSettings) {
|
|
|
368
381
|
return Promise.resolve(defaultConfig);
|
|
369
382
|
return (0, index_js_2.searchForConfig)(path_1.default.dirname((0, Uri_js_1.uriToFilePath)(uri)), pnpSettings).then((s) => s || defaultConfig);
|
|
370
383
|
}
|
|
384
|
+
function mapSug(sug) {
|
|
385
|
+
return { cost: 999, ...sug };
|
|
386
|
+
}
|
|
371
387
|
function searchForDocumentConfigSync(document, defaultConfig, pnpSettings) {
|
|
372
388
|
const { uri } = document;
|
|
373
389
|
if (uri.scheme !== 'file')
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { CachingDictionary } from 'cspell-dictionary';
|
|
2
2
|
import type { TextOffsetRO } from './ValidationTypes.js';
|
|
3
|
-
|
|
3
|
+
declare function hasWordCheck(dict: CachingDictionary, word: string): boolean;
|
|
4
4
|
export declare function isWordValidWithEscapeRetry(dict: CachingDictionary, wo: TextOffsetRO, line: TextOffsetRO): boolean;
|
|
5
5
|
export declare const __testing__: {
|
|
6
6
|
hasWordCheck: typeof hasWordCheck;
|
|
7
7
|
};
|
|
8
|
+
export {};
|
|
8
9
|
//# sourceMappingURL=isWordValid.d.ts.map
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.__testing__ = exports.isWordValidWithEscapeRetry =
|
|
3
|
+
exports.__testing__ = exports.isWordValidWithEscapeRetry = void 0;
|
|
4
4
|
function hasWordCheck(dict, word) {
|
|
5
|
-
word = word.replace(/\\/g, '');
|
|
5
|
+
word = word.includes('\\') ? word.replace(/\\/g, '') : word;
|
|
6
6
|
return dict.has(word);
|
|
7
7
|
}
|
|
8
|
-
exports.hasWordCheck = hasWordCheck;
|
|
9
8
|
function isWordValidWithEscapeRetry(dict, wo, line) {
|
|
10
9
|
const firstTry = hasWordCheck(dict, wo.text);
|
|
11
10
|
return (firstTry ||
|
|
@@ -26,7 +26,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
26
26
|
exports.textValidatorFactory = exports.lineValidatorFactory = void 0;
|
|
27
27
|
const sync_1 = require("@cspell/cspell-pipe/sync");
|
|
28
28
|
const cspell_dictionary_1 = require("cspell-dictionary");
|
|
29
|
-
const gensequence_1 = require("gensequence");
|
|
30
29
|
const RxPat = __importStar(require("../Settings/RegExpPatterns.js"));
|
|
31
30
|
const Text = __importStar(require("../util/text.js"));
|
|
32
31
|
const util_js_1 = require("../util/util.js");
|
|
@@ -60,15 +59,25 @@ function lineValidatorFactory(sDict, options) {
|
|
|
60
59
|
function isWordIgnored(word) {
|
|
61
60
|
return dictCol.isNoSuggestWord(word);
|
|
62
61
|
}
|
|
62
|
+
function getSuggestions(word) {
|
|
63
|
+
return dictCol.getPreferredSuggestions(word);
|
|
64
|
+
}
|
|
63
65
|
function isWordFlagged(word) {
|
|
64
66
|
const isIgnored = isWordIgnored(word.text);
|
|
65
67
|
const isFlagged = !isIgnored && testForFlaggedWord(word);
|
|
66
68
|
return isFlagged;
|
|
67
69
|
}
|
|
68
|
-
function
|
|
70
|
+
function annotateIsFlagged(word) {
|
|
69
71
|
word.isFlagged = isWordFlagged(word);
|
|
70
72
|
return word;
|
|
71
73
|
}
|
|
74
|
+
function annotateIssue(issue) {
|
|
75
|
+
const sugs = getSuggestions(issue.text);
|
|
76
|
+
if (sugs && sugs.length) {
|
|
77
|
+
issue.suggestionsEx = sugs;
|
|
78
|
+
}
|
|
79
|
+
return issue;
|
|
80
|
+
}
|
|
72
81
|
function checkWord(word) {
|
|
73
82
|
const isIgnored = isWordIgnored(word.text);
|
|
74
83
|
const { isFlagged = !isIgnored && testForFlaggedWord(word) } = word;
|
|
@@ -84,7 +93,7 @@ function lineValidatorFactory(sDict, options) {
|
|
|
84
93
|
if (vr.isFlagged) {
|
|
85
94
|
return [vr];
|
|
86
95
|
}
|
|
87
|
-
const codeWordResults = (0, sync_1.toArray)((0, sync_1.pipe)(Text.extractWordsFromCodeTextOffset(vr), (0, sync_1.opFilter)(filterAlreadyChecked), (0, sync_1.opMap)((t) => ({ ...t, line: vr.line })), (0, sync_1.opMap)(
|
|
96
|
+
const codeWordResults = (0, sync_1.toArray)((0, sync_1.pipe)(Text.extractWordsFromCodeTextOffset(vr), (0, sync_1.opFilter)(filterAlreadyChecked), (0, sync_1.opMap)((t) => ({ ...t, line: vr.line })), (0, sync_1.opMap)(annotateIsFlagged), (0, sync_1.opFilter)(rememberFilter((wo) => wo.text.length >= minWordLength || !!wo.isFlagged)), (0, sync_1.opMap)((wo) => (wo.isFlagged ? wo : checkWord(wo))), (0, sync_1.opFilter)(rememberFilter((wo) => wo.isFlagged || !wo.isFound)), (0, sync_1.opFilter)(rememberFilter((wo) => !RxPat.regExRepeatedChar.test(wo.text))),
|
|
88
97
|
// get back the original text.
|
|
89
98
|
(0, sync_1.opMap)((wo) => ({
|
|
90
99
|
...wo,
|
|
@@ -105,18 +114,18 @@ function lineValidatorFactory(sDict, options) {
|
|
|
105
114
|
};
|
|
106
115
|
return [vr];
|
|
107
116
|
}
|
|
108
|
-
const mismatches = (0, sync_1.toArray)((0, sync_1.pipe)(Text.extractWordsFromTextOffset(possibleWord), (0, sync_1.opFilter)(filterAlreadyChecked), (0, sync_1.opMap)((wo) => ({ ...wo, line: lineSegment.line })), (0, sync_1.opMap)(
|
|
117
|
+
const mismatches = (0, sync_1.toArray)((0, sync_1.pipe)(Text.extractWordsFromTextOffset(possibleWord), (0, sync_1.opFilter)(filterAlreadyChecked), (0, sync_1.opMap)((wo) => ({ ...wo, line: lineSegment.line })), (0, sync_1.opMap)(annotateIsFlagged), (0, sync_1.opFilter)(rememberFilter((wo) => wo.text.length >= minWordLength || !!wo.isFlagged)), (0, sync_1.opConcatMap)(checkFullWord)));
|
|
109
118
|
if (mismatches.length) {
|
|
110
119
|
// Try the more expensive word splitter
|
|
111
120
|
const splitResult = (0, wordSplitter_js_1.split)(lineSegment.segment, possibleWord.offset, splitterIsValid);
|
|
112
121
|
const nonMatching = splitResult.words.filter((w) => !w.isFound);
|
|
113
122
|
if (nonMatching.length < mismatches.length) {
|
|
114
|
-
return nonMatching.map((w) => ({ ...w, line: lineSegment.line })).map(
|
|
123
|
+
return nonMatching.map((w) => ({ ...w, line: lineSegment.line })).map(annotateIsFlagged);
|
|
115
124
|
}
|
|
116
125
|
}
|
|
117
126
|
return mismatches;
|
|
118
127
|
}
|
|
119
|
-
const checkedPossibleWords = (0,
|
|
128
|
+
const checkedPossibleWords = (0, sync_1.pipe)(Text.extractPossibleWordsFromTextOffset(lineSegment.segment), (0, sync_1.opFilter)(filterAlreadyChecked), (0, sync_1.opConcatMap)(checkPossibleWords), (0, sync_1.opMap)(annotateIssue));
|
|
120
129
|
return checkedPossibleWords;
|
|
121
130
|
};
|
|
122
131
|
return { fn, dict: dictCol };
|
|
@@ -131,10 +140,10 @@ function textValidatorFactory(dict, options) {
|
|
|
131
140
|
const segment = { text, offset: 0 };
|
|
132
141
|
const lineSegment = { line: segment, segment };
|
|
133
142
|
function mapBackToOriginSimple(vr) {
|
|
134
|
-
const { text, offset, isFlagged, isFound } = vr;
|
|
143
|
+
const { text, offset, isFlagged, isFound, suggestionsEx } = vr;
|
|
135
144
|
const r = (0, parsedText_js_1.mapRangeBackToOriginalPos)([offset, offset + text.length], map);
|
|
136
145
|
const range = [r[0] + srcOffset, r[1] + srcOffset];
|
|
137
|
-
return { text, range, isFlagged, isFound };
|
|
146
|
+
return { text, range, isFlagged, isFound, suggestionsEx };
|
|
138
147
|
}
|
|
139
148
|
return [...lineValidatorFn(lineSegment)].map(mapBackToOriginSimple);
|
|
140
149
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { SpellingDictionary } from 'cspell-dictionary';
|
|
2
|
-
import type { Sequence } from 'gensequence';
|
|
3
2
|
import type { ValidationResult } from '../Models/ValidationResult.js';
|
|
4
3
|
import * as TextRange from '../util/TextRange.js';
|
|
5
4
|
import type { IncludeExcludeOptions, LineSegment, ValidationOptions } from './ValidationTypes.js';
|
|
@@ -7,7 +6,7 @@ import type { IncludeExcludeOptions, LineSegment, ValidationOptions } from './Va
|
|
|
7
6
|
* @deprecated
|
|
8
7
|
* @deprecation Use spellCheckDocument
|
|
9
8
|
*/
|
|
10
|
-
export declare function validateText(text: string, dict: SpellingDictionary, options: ValidationOptions):
|
|
9
|
+
export declare function validateText(text: string, dict: SpellingDictionary, options: ValidationOptions): Iterable<ValidationResult>;
|
|
11
10
|
export declare function calcTextInclusionRanges(text: string, options: IncludeExcludeOptions): TextRange.MatchRange[];
|
|
12
11
|
/**
|
|
13
12
|
* Returns a mapper function that will segment a TextOffset based upon the includeRanges.
|
|
@@ -25,7 +25,6 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports._testMethods = exports.mapLineSegmentAgainstRangesFactory = exports.calcTextInclusionRanges = exports.validateText = void 0;
|
|
27
27
|
const sync_1 = require("@cspell/cspell-pipe/sync");
|
|
28
|
-
const gensequence_1 = require("gensequence");
|
|
29
28
|
const Text = __importStar(require("../util/text.js"));
|
|
30
29
|
const TextRange = __importStar(require("../util/TextRange.js"));
|
|
31
30
|
const defaultConstants_js_1 = require("./defaultConstants.js");
|
|
@@ -48,7 +47,7 @@ function validateText(text, dict, options) {
|
|
|
48
47
|
// Filter out if there is too many
|
|
49
48
|
return n <= maxDuplicateProblems;
|
|
50
49
|
}), (0, sync_1.opTake)(maxNumberOfProblems));
|
|
51
|
-
return
|
|
50
|
+
return iter;
|
|
52
51
|
}
|
|
53
52
|
exports.validateText = validateText;
|
|
54
53
|
function calcTextInclusionRanges(text, options) {
|
|
@@ -6,12 +6,12 @@ exports.regExUpperSOrIng = /([\p{Lu}\p{M}]+\\?['’]?(?:s|ing|ies|es|ings|ed|nin
|
|
|
6
6
|
exports.regExSplitWords = /(\p{Ll}\p{M}?)(\p{Lu})/gu;
|
|
7
7
|
exports.regExSplitWords2 = /(\p{Lu}\p{M}?)(\p{Lu}\p{M}?\p{Ll})/gu;
|
|
8
8
|
exports.regExWords = /\p{L}\p{M}?(?:(?:\\?['’])?\p{L}\p{M}?)*/gu;
|
|
9
|
-
exports.regExWordsAndDigits = /(?:\d+)?[\p{L}\p{M}_'’-](?:(?:\\?['’])?[\p{L}\p{M}\w'
|
|
9
|
+
exports.regExWordsAndDigits = /(?:\d+)?[\p{L}\p{M}_'’-](?:(?:\\?['’])?[\p{L}\p{M}\w'’.-])*/gu;
|
|
10
10
|
exports.regExIgnoreCharacters = /[\p{sc=Hiragana}\p{sc=Han}\p{sc=Katakana}\u30A0-\u30FF\p{sc=Hangul}]/gu;
|
|
11
11
|
exports.regExFirstUpper = /^\p{Lu}\p{M}?\p{Ll}+$/u;
|
|
12
12
|
exports.regExAllUpper = /^(?:\p{Lu}\p{M}?)+$/u;
|
|
13
13
|
exports.regExAllLower = /^(?:\p{Ll}\p{M}?)+$/u;
|
|
14
|
-
exports.regExPossibleWordBreaks = /[-_’']/g;
|
|
14
|
+
exports.regExPossibleWordBreaks = /[-_’'.]/g;
|
|
15
15
|
exports.regExMatchRegExParts = /^\s*\/([\s\S]*?)\/([gimuxy]*)\s*$/;
|
|
16
16
|
exports.regExAccents = /\p{M}/gu;
|
|
17
17
|
exports.regExEscapeCharacters = /(?<=\\)[anrvtbf]/gi;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ExtendedSuggestion } from './Suggestion.mjs';
|
|
2
2
|
import type { ValidationResult } from './ValidationResult.mjs';
|
|
3
3
|
export interface ValidationIssue extends ValidationResult {
|
|
4
|
-
suggestions?: string[];
|
|
5
|
-
suggestionsEx?: ExtendedSuggestion[];
|
|
4
|
+
suggestions?: string[] | undefined;
|
|
5
|
+
suggestionsEx?: ExtendedSuggestion[] | undefined;
|
|
6
6
|
}
|
|
7
7
|
//# sourceMappingURL=ValidationIssue.d.mts.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { MappedText, TextOffset as TextOffsetRW } from '@cspell/cspell-types';
|
|
2
|
-
import type {
|
|
2
|
+
import type { ExtendedSuggestion } from '../Models/Suggestion.mjs';
|
|
3
|
+
import type { ValidationIssue } from '../Models/ValidationIssue.mjs';
|
|
3
4
|
export type TextOffsetRO = Readonly<TextOffsetRW>;
|
|
4
5
|
export interface ValidationOptions extends IncludeExcludeOptions {
|
|
5
6
|
maxNumberOfProblems?: number;
|
|
@@ -23,8 +24,8 @@ export interface WordRangeAcc {
|
|
|
23
24
|
isIncluded: boolean;
|
|
24
25
|
rangePos: number;
|
|
25
26
|
}
|
|
26
|
-
export type
|
|
27
|
-
export type LineValidatorFn = (line: LineSegment) => Iterable<
|
|
27
|
+
export type ValidationIssueRO = Readonly<ValidationIssue>;
|
|
28
|
+
export type LineValidatorFn = (line: LineSegment) => Iterable<ValidationIssue>;
|
|
28
29
|
export interface LineSegment {
|
|
29
30
|
line: TextOffsetRO;
|
|
30
31
|
segment: TextOffsetRO;
|
|
@@ -32,6 +33,7 @@ export interface LineSegment {
|
|
|
32
33
|
export interface MappedTextValidationResult extends MappedText {
|
|
33
34
|
isFlagged?: boolean | undefined;
|
|
34
35
|
isFound?: boolean | undefined;
|
|
36
|
+
suggestionsEx?: ExtendedSuggestion[] | undefined;
|
|
35
37
|
}
|
|
36
38
|
export type TextValidatorFn = (text: MappedText) => Iterable<MappedTextValidationResult>;
|
|
37
39
|
//# sourceMappingURL=ValidationTypes.d.mts.map
|
|
@@ -83,6 +83,7 @@ export declare class DocumentValidator {
|
|
|
83
83
|
private _parse;
|
|
84
84
|
private getSuggestions;
|
|
85
85
|
private genSuggestions;
|
|
86
|
+
private adjustSuggestions;
|
|
86
87
|
getFinalizedDocSettings(): CSpellSettingsInternal;
|
|
87
88
|
/**
|
|
88
89
|
* Returns true if the final result of the configuration calculation results
|
|
@@ -190,18 +190,24 @@ export class DocumentValidator {
|
|
|
190
190
|
const document = this._document;
|
|
191
191
|
let line = undefined;
|
|
192
192
|
function mapToIssue(issue) {
|
|
193
|
-
const { range, text, isFlagged, isFound } = issue;
|
|
193
|
+
const { range, text, isFlagged, isFound, suggestionsEx } = issue;
|
|
194
194
|
const offset = range[0];
|
|
195
195
|
const length = range[1] - range[0];
|
|
196
196
|
assert(!line || line.offset <= offset);
|
|
197
197
|
if (!line || line.offset + line.text.length <= offset) {
|
|
198
198
|
line = document.lineAt(offset);
|
|
199
199
|
}
|
|
200
|
-
return { text, offset, line, length, isFlagged, isFound };
|
|
200
|
+
return { text, offset, line, length, isFlagged, isFound, suggestionsEx };
|
|
201
201
|
}
|
|
202
202
|
const issues = [...pipeSync(segmenter(parsedText), opConcatMap(textValidator.validate), opMap(mapToIssue))];
|
|
203
203
|
if (!this.options.generateSuggestions) {
|
|
204
|
-
return issues
|
|
204
|
+
return issues.map((issue) => {
|
|
205
|
+
if (!issue.suggestionsEx)
|
|
206
|
+
return issue;
|
|
207
|
+
const suggestionsEx = this.adjustSuggestions(issue.text, issue.suggestionsEx);
|
|
208
|
+
const suggestions = suggestionsEx.map((s) => s.word);
|
|
209
|
+
return { ...issue, suggestionsEx, suggestions };
|
|
210
|
+
});
|
|
205
211
|
}
|
|
206
212
|
const withSugs = issues.map((t) => {
|
|
207
213
|
// lazy suggestion calculation.
|
|
@@ -317,9 +323,16 @@ export class DocumentValidator {
|
|
|
317
323
|
timeout: settings.suggestionsTimeout,
|
|
318
324
|
numChanges: settings.suggestionNumChanges,
|
|
319
325
|
};
|
|
320
|
-
const locale = this._preparations.config.language;
|
|
321
326
|
const rawSuggestions = dict.suggest(text, sugOptions);
|
|
322
|
-
|
|
327
|
+
return this.adjustSuggestions(text, rawSuggestions);
|
|
328
|
+
}
|
|
329
|
+
adjustSuggestions(text, rawSuggestions) {
|
|
330
|
+
assert(this._preparations, ERROR_NOT_PREPARED);
|
|
331
|
+
const settings = this._preparations.docSettings;
|
|
332
|
+
const ignoreCase = !(settings.caseSensitive ?? false);
|
|
333
|
+
const locale = this._preparations.config.language;
|
|
334
|
+
const dict = this._preparations.dictionary;
|
|
335
|
+
const sugsWithAlt = calcSuggestionAdjustedToToMatchCase(text, rawSuggestions.map(mapSug), locale, ignoreCase, dict);
|
|
323
336
|
return sugsWithAlt.map(sanitizeSuggestion);
|
|
324
337
|
}
|
|
325
338
|
getFinalizedDocSettings() {
|
|
@@ -361,6 +374,9 @@ async function searchForDocumentConfig(document, defaultConfig, pnpSettings) {
|
|
|
361
374
|
return Promise.resolve(defaultConfig);
|
|
362
375
|
return searchForConfig(path.dirname(uriToFilePath(uri)), pnpSettings).then((s) => s || defaultConfig);
|
|
363
376
|
}
|
|
377
|
+
function mapSug(sug) {
|
|
378
|
+
return { cost: 999, ...sug };
|
|
379
|
+
}
|
|
364
380
|
function searchForDocumentConfigSync(document, defaultConfig, pnpSettings) {
|
|
365
381
|
const { uri } = document;
|
|
366
382
|
if (uri.scheme !== 'file')
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { CachingDictionary } from 'cspell-dictionary';
|
|
2
2
|
import type { TextOffsetRO } from './ValidationTypes.mjs';
|
|
3
|
-
|
|
3
|
+
declare function hasWordCheck(dict: CachingDictionary, word: string): boolean;
|
|
4
4
|
export declare function isWordValidWithEscapeRetry(dict: CachingDictionary, wo: TextOffsetRO, line: TextOffsetRO): boolean;
|
|
5
5
|
export declare const __testing__: {
|
|
6
6
|
hasWordCheck: typeof hasWordCheck;
|
|
7
7
|
};
|
|
8
|
+
export {};
|
|
8
9
|
//# sourceMappingURL=isWordValid.d.mts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
word = word.replace(/\\/g, '');
|
|
1
|
+
function hasWordCheck(dict, word) {
|
|
2
|
+
word = word.includes('\\') ? word.replace(/\\/g, '') : word;
|
|
3
3
|
return dict.has(word);
|
|
4
4
|
}
|
|
5
5
|
export function isWordValidWithEscapeRetry(dict, wo, line) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { opConcatMap, opFilter, opMap, pipe, toArray } from '@cspell/cspell-pipe/sync';
|
|
2
2
|
import { createCachingDictionary } from 'cspell-dictionary';
|
|
3
|
-
import { genSequence } from 'gensequence';
|
|
4
3
|
import * as RxPat from '../Settings/RegExpPatterns.mjs';
|
|
5
4
|
import * as Text from '../util/text.mjs';
|
|
6
5
|
import { clean } from '../util/util.mjs';
|
|
@@ -34,15 +33,25 @@ export function lineValidatorFactory(sDict, options) {
|
|
|
34
33
|
function isWordIgnored(word) {
|
|
35
34
|
return dictCol.isNoSuggestWord(word);
|
|
36
35
|
}
|
|
36
|
+
function getSuggestions(word) {
|
|
37
|
+
return dictCol.getPreferredSuggestions(word);
|
|
38
|
+
}
|
|
37
39
|
function isWordFlagged(word) {
|
|
38
40
|
const isIgnored = isWordIgnored(word.text);
|
|
39
41
|
const isFlagged = !isIgnored && testForFlaggedWord(word);
|
|
40
42
|
return isFlagged;
|
|
41
43
|
}
|
|
42
|
-
function
|
|
44
|
+
function annotateIsFlagged(word) {
|
|
43
45
|
word.isFlagged = isWordFlagged(word);
|
|
44
46
|
return word;
|
|
45
47
|
}
|
|
48
|
+
function annotateIssue(issue) {
|
|
49
|
+
const sugs = getSuggestions(issue.text);
|
|
50
|
+
if (sugs && sugs.length) {
|
|
51
|
+
issue.suggestionsEx = sugs;
|
|
52
|
+
}
|
|
53
|
+
return issue;
|
|
54
|
+
}
|
|
46
55
|
function checkWord(word) {
|
|
47
56
|
const isIgnored = isWordIgnored(word.text);
|
|
48
57
|
const { isFlagged = !isIgnored && testForFlaggedWord(word) } = word;
|
|
@@ -58,7 +67,7 @@ export function lineValidatorFactory(sDict, options) {
|
|
|
58
67
|
if (vr.isFlagged) {
|
|
59
68
|
return [vr];
|
|
60
69
|
}
|
|
61
|
-
const codeWordResults = toArray(pipe(Text.extractWordsFromCodeTextOffset(vr), opFilter(filterAlreadyChecked), opMap((t) => ({ ...t, line: vr.line })), opMap(
|
|
70
|
+
const codeWordResults = toArray(pipe(Text.extractWordsFromCodeTextOffset(vr), opFilter(filterAlreadyChecked), opMap((t) => ({ ...t, line: vr.line })), opMap(annotateIsFlagged), opFilter(rememberFilter((wo) => wo.text.length >= minWordLength || !!wo.isFlagged)), opMap((wo) => (wo.isFlagged ? wo : checkWord(wo))), opFilter(rememberFilter((wo) => wo.isFlagged || !wo.isFound)), opFilter(rememberFilter((wo) => !RxPat.regExRepeatedChar.test(wo.text))),
|
|
62
71
|
// get back the original text.
|
|
63
72
|
opMap((wo) => ({
|
|
64
73
|
...wo,
|
|
@@ -79,18 +88,18 @@ export function lineValidatorFactory(sDict, options) {
|
|
|
79
88
|
};
|
|
80
89
|
return [vr];
|
|
81
90
|
}
|
|
82
|
-
const mismatches = toArray(pipe(Text.extractWordsFromTextOffset(possibleWord), opFilter(filterAlreadyChecked), opMap((wo) => ({ ...wo, line: lineSegment.line })), opMap(
|
|
91
|
+
const mismatches = toArray(pipe(Text.extractWordsFromTextOffset(possibleWord), opFilter(filterAlreadyChecked), opMap((wo) => ({ ...wo, line: lineSegment.line })), opMap(annotateIsFlagged), opFilter(rememberFilter((wo) => wo.text.length >= minWordLength || !!wo.isFlagged)), opConcatMap(checkFullWord)));
|
|
83
92
|
if (mismatches.length) {
|
|
84
93
|
// Try the more expensive word splitter
|
|
85
94
|
const splitResult = split(lineSegment.segment, possibleWord.offset, splitterIsValid);
|
|
86
95
|
const nonMatching = splitResult.words.filter((w) => !w.isFound);
|
|
87
96
|
if (nonMatching.length < mismatches.length) {
|
|
88
|
-
return nonMatching.map((w) => ({ ...w, line: lineSegment.line })).map(
|
|
97
|
+
return nonMatching.map((w) => ({ ...w, line: lineSegment.line })).map(annotateIsFlagged);
|
|
89
98
|
}
|
|
90
99
|
}
|
|
91
100
|
return mismatches;
|
|
92
101
|
}
|
|
93
|
-
const checkedPossibleWords =
|
|
102
|
+
const checkedPossibleWords = pipe(Text.extractPossibleWordsFromTextOffset(lineSegment.segment), opFilter(filterAlreadyChecked), opConcatMap(checkPossibleWords), opMap(annotateIssue));
|
|
94
103
|
return checkedPossibleWords;
|
|
95
104
|
};
|
|
96
105
|
return { fn, dict: dictCol };
|
|
@@ -104,10 +113,10 @@ export function textValidatorFactory(dict, options) {
|
|
|
104
113
|
const segment = { text, offset: 0 };
|
|
105
114
|
const lineSegment = { line: segment, segment };
|
|
106
115
|
function mapBackToOriginSimple(vr) {
|
|
107
|
-
const { text, offset, isFlagged, isFound } = vr;
|
|
116
|
+
const { text, offset, isFlagged, isFound, suggestionsEx } = vr;
|
|
108
117
|
const r = mapRangeBackToOriginalPos([offset, offset + text.length], map);
|
|
109
118
|
const range = [r[0] + srcOffset, r[1] + srcOffset];
|
|
110
|
-
return { text, range, isFlagged, isFound };
|
|
119
|
+
return { text, range, isFlagged, isFound, suggestionsEx };
|
|
111
120
|
}
|
|
112
121
|
return [...lineValidatorFn(lineSegment)].map(mapBackToOriginSimple);
|
|
113
122
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { SpellingDictionary } from 'cspell-dictionary';
|
|
2
|
-
import type { Sequence } from 'gensequence';
|
|
3
2
|
import type { ValidationResult } from '../Models/ValidationResult.mjs';
|
|
4
3
|
import * as TextRange from '../util/TextRange.mjs';
|
|
5
4
|
import type { IncludeExcludeOptions, LineSegment, ValidationOptions } from './ValidationTypes.mjs';
|
|
@@ -7,7 +6,7 @@ import type { IncludeExcludeOptions, LineSegment, ValidationOptions } from './Va
|
|
|
7
6
|
* @deprecated
|
|
8
7
|
* @deprecation Use spellCheckDocument
|
|
9
8
|
*/
|
|
10
|
-
export declare function validateText(text: string, dict: SpellingDictionary, options: ValidationOptions):
|
|
9
|
+
export declare function validateText(text: string, dict: SpellingDictionary, options: ValidationOptions): Iterable<ValidationResult>;
|
|
11
10
|
export declare function calcTextInclusionRanges(text: string, options: IncludeExcludeOptions): TextRange.MatchRange[];
|
|
12
11
|
/**
|
|
13
12
|
* Returns a mapper function that will segment a TextOffset based upon the includeRanges.
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { opConcatMap, opFilter, opTake, pipe } from '@cspell/cspell-pipe/sync';
|
|
2
|
-
import { genSequence } from 'gensequence';
|
|
3
2
|
import * as Text from '../util/text.mjs';
|
|
4
3
|
import * as TextRange from '../util/TextRange.mjs';
|
|
5
4
|
import { defaultMaxDuplicateProblems, defaultMaxNumberOfProblems } from './defaultConstants.mjs';
|
|
@@ -22,7 +21,7 @@ export function validateText(text, dict, options) {
|
|
|
22
21
|
// Filter out if there is too many
|
|
23
22
|
return n <= maxDuplicateProblems;
|
|
24
23
|
}), opTake(maxNumberOfProblems));
|
|
25
|
-
return
|
|
24
|
+
return iter;
|
|
26
25
|
}
|
|
27
26
|
export function calcTextInclusionRanges(text, options) {
|
|
28
27
|
const { ignoreRegExpList = [], includeRegExpList = [] } = options;
|
|
@@ -3,12 +3,12 @@ export const regExUpperSOrIng = /([\p{Lu}\p{M}]+\\?['’]?(?:s|ing|ies|es|ings|e
|
|
|
3
3
|
export const regExSplitWords = /(\p{Ll}\p{M}?)(\p{Lu})/gu;
|
|
4
4
|
export const regExSplitWords2 = /(\p{Lu}\p{M}?)(\p{Lu}\p{M}?\p{Ll})/gu;
|
|
5
5
|
export const regExWords = /\p{L}\p{M}?(?:(?:\\?['’])?\p{L}\p{M}?)*/gu;
|
|
6
|
-
export const regExWordsAndDigits = /(?:\d+)?[\p{L}\p{M}_'’-](?:(?:\\?['’])?[\p{L}\p{M}\w'
|
|
6
|
+
export const regExWordsAndDigits = /(?:\d+)?[\p{L}\p{M}_'’-](?:(?:\\?['’])?[\p{L}\p{M}\w'’.-])*/gu;
|
|
7
7
|
export const regExIgnoreCharacters = /[\p{sc=Hiragana}\p{sc=Han}\p{sc=Katakana}\u30A0-\u30FF\p{sc=Hangul}]/gu;
|
|
8
8
|
export const regExFirstUpper = /^\p{Lu}\p{M}?\p{Ll}+$/u;
|
|
9
9
|
export const regExAllUpper = /^(?:\p{Lu}\p{M}?)+$/u;
|
|
10
10
|
export const regExAllLower = /^(?:\p{Ll}\p{M}?)+$/u;
|
|
11
|
-
export const regExPossibleWordBreaks = /[-_’']/g;
|
|
11
|
+
export const regExPossibleWordBreaks = /[-_’'.]/g;
|
|
12
12
|
export const regExMatchRegExParts = /^\s*\/([\s\S]*?)\/([gimuxy]*)\s*$/;
|
|
13
13
|
export const regExAccents = /\p{M}/gu;
|
|
14
14
|
export const regExEscapeCharacters = /(?<=\\)[anrvtbf]/gi;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cspell-lib",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.30.0",
|
|
4
4
|
"description": "A library of useful functions used across various cspell tools.",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"main": "dist/cjs/index.js",
|
|
@@ -57,19 +57,19 @@
|
|
|
57
57
|
},
|
|
58
58
|
"homepage": "https://github.com/streetsidesoftware/cspell#readme",
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@cspell/cspell-bundled-dicts": "6.
|
|
61
|
-
"@cspell/cspell-pipe": "6.
|
|
62
|
-
"@cspell/cspell-types": "6.
|
|
63
|
-
"@cspell/strong-weak-map": "6.
|
|
60
|
+
"@cspell/cspell-bundled-dicts": "6.30.0",
|
|
61
|
+
"@cspell/cspell-pipe": "6.30.0",
|
|
62
|
+
"@cspell/cspell-types": "6.30.0",
|
|
63
|
+
"@cspell/strong-weak-map": "6.30.0",
|
|
64
64
|
"clear-module": "^4.1.2",
|
|
65
65
|
"comment-json": "^4.2.3",
|
|
66
66
|
"configstore": "^5.0.1",
|
|
67
67
|
"cosmiconfig": "^8.1.0",
|
|
68
|
-
"cspell-dictionary": "6.
|
|
69
|
-
"cspell-glob": "6.
|
|
70
|
-
"cspell-grammar": "6.
|
|
71
|
-
"cspell-io": "6.
|
|
72
|
-
"cspell-trie-lib": "6.
|
|
68
|
+
"cspell-dictionary": "6.30.0",
|
|
69
|
+
"cspell-glob": "6.30.0",
|
|
70
|
+
"cspell-grammar": "6.30.0",
|
|
71
|
+
"cspell-io": "6.30.0",
|
|
72
|
+
"cspell-trie-lib": "6.30.0",
|
|
73
73
|
"fast-equals": "^4.0.3",
|
|
74
74
|
"find-up": "^5.0.0",
|
|
75
75
|
"gensequence": "^5.0.2",
|
|
@@ -92,12 +92,12 @@
|
|
|
92
92
|
"@cspell/dict-nl-nl": "^2.2.8",
|
|
93
93
|
"@cspell/dict-python": "^4.0.2",
|
|
94
94
|
"@types/configstore": "^5.0.1",
|
|
95
|
-
"@types/jest": "^29.4.
|
|
95
|
+
"@types/jest": "^29.4.4",
|
|
96
96
|
"cspell-dict-nl-nl": "^1.1.2",
|
|
97
97
|
"expect": "^29.5.0",
|
|
98
98
|
"jest": "^29.5.0",
|
|
99
99
|
"lorem-ipsum": "^2.0.8",
|
|
100
100
|
"ts-jest": "^29.0.5"
|
|
101
101
|
},
|
|
102
|
-
"gitHead": "
|
|
102
|
+
"gitHead": "9af8c211fdeeb58e2d7a2be0e72405a23fe954cc"
|
|
103
103
|
}
|