cspell-lib 10.3.4 → 10.3.6
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/Transform/SourceMap.js +3 -2
- package/dist/lib/Transform/SubstitutionTransformer.js +2 -3
- package/dist/lib/spellCheckFile.d.ts +4 -0
- package/dist/lib/spellCheckFile.js +3 -4
- package/dist/lib/textValidation/checkText.js +0 -3
- package/dist/lib/textValidation/docValidator.d.ts +16 -21
- package/dist/lib/textValidation/docValidator.js +31 -20
- package/dist/lib/textValidation/docValidatorPreparations.d.ts +74 -0
- package/dist/lib/textValidation/docValidatorPreparations.js +63 -0
- package/dist/lib/textValidation/lineValidatorFactory.js +23 -11
- package/dist/lib/util/text.d.ts +7 -0
- package/dist/lib/util/text.js +16 -0
- package/package.json +53 -54
|
@@ -335,9 +335,10 @@ function advanceCursors(cursor1, cursor2, target) {
|
|
|
335
335
|
assert(cursor1.p1 === cursor2.p0, 'The shared edge must match between the two cursors.');
|
|
336
336
|
if (cursor1.linear && cursor2.linear) {
|
|
337
337
|
const p = Math.min(cursor1.end1, cursor2.end0);
|
|
338
|
+
// Both segments are linear, so all three positions advance by the same amount from the current position.
|
|
338
339
|
const dB = p - cursor1.p1;
|
|
339
|
-
const pA = cursor1.
|
|
340
|
-
const pC = cursor2.
|
|
340
|
+
const pA = cursor1.p0 + dB;
|
|
341
|
+
const pC = cursor2.p1 + dB;
|
|
341
342
|
const dA = pA - cursor1.p0;
|
|
342
343
|
const dC = pC - cursor2.p1;
|
|
343
344
|
cursor1.p0 = pA;
|
|
@@ -95,9 +95,8 @@ function buildDefinitionMap(defs) {
|
|
|
95
95
|
* @returns
|
|
96
96
|
*/
|
|
97
97
|
export function createSubstitutionTransformer(info) {
|
|
98
|
-
const {
|
|
99
|
-
|
|
100
|
-
: {};
|
|
98
|
+
const { substitutions, substitutionDefinitions } = info;
|
|
99
|
+
const { subMap, missing } = substitutions ? calcSubMap(substitutions, substitutionDefinitions ?? []) : {};
|
|
101
100
|
return {
|
|
102
101
|
transformer: new SubstitutionTransformer(subMap),
|
|
103
102
|
missing: missing && missing.length > 0 ? missing : undefined,
|
|
@@ -25,6 +25,10 @@ export interface SpellCheckFileOptions extends ValidateTextOptions, Pick<CSpellU
|
|
|
25
25
|
* @defaultValue undefined
|
|
26
26
|
*/
|
|
27
27
|
noConfigSearch?: boolean;
|
|
28
|
+
/**
|
|
29
|
+
* If true, the document will be checked even if it would normally be excluded.
|
|
30
|
+
*/
|
|
31
|
+
forceCheck?: boolean;
|
|
28
32
|
}
|
|
29
33
|
export interface SpellCheckFileOptionsRPC extends SpellCheckFileOptions {
|
|
30
34
|
measurePerf?: boolean;
|
|
@@ -123,15 +123,14 @@ async function spellCheckFullDocument(document, options, settingsOrConfigFile) {
|
|
|
123
123
|
const docValOptions = options;
|
|
124
124
|
const docValidator = await DocumentValidator.create(doc, docValOptions, settingsOrConfigFile).finally(() => timerPrepare.end());
|
|
125
125
|
Object.assign(perf, Object.fromEntries(Object.entries(docValidator.perfTiming).map(([k, v]) => ['_' + k, v])));
|
|
126
|
-
const prep = docValidator._getPreparations();
|
|
127
126
|
if (docValidator.errors.length) {
|
|
128
|
-
const settingsUsed =
|
|
127
|
+
const settingsUsed = docValidator._getLocalConfig() ||
|
|
129
128
|
(satisfiesCSpellConfigFile(settingsOrConfigFile) ? settingsOrConfigFile.settings : settingsOrConfigFile);
|
|
130
129
|
return {
|
|
131
130
|
document,
|
|
132
131
|
options,
|
|
133
132
|
settingsUsed,
|
|
134
|
-
localConfigFilepath:
|
|
133
|
+
localConfigFilepath: docValidator._getLocalConfigFilepath(),
|
|
135
134
|
issues: [],
|
|
136
135
|
checked: false,
|
|
137
136
|
errors: docValidator.errors,
|
|
@@ -148,7 +147,7 @@ async function spellCheckFullDocument(document, options, settingsOrConfigFile) {
|
|
|
148
147
|
document,
|
|
149
148
|
options,
|
|
150
149
|
settingsUsed: docValidator.getFinalizedDocSettings(),
|
|
151
|
-
localConfigFilepath:
|
|
150
|
+
localConfigFilepath: docValidator._getLocalConfigFilepath(),
|
|
152
151
|
issues,
|
|
153
152
|
checked: docValidator.shouldCheckDocument(),
|
|
154
153
|
errors: undefined,
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import assert from 'node:assert';
|
|
2
1
|
import { resolveDocumentToTextDocument } from '../Document/resolveDocument.js';
|
|
3
2
|
import { isTextDocument } from '../Models/TextDocument.js';
|
|
4
3
|
import * as Settings from '../Settings/index.js';
|
|
@@ -57,8 +56,6 @@ export async function genCheckText(docValidator) {
|
|
|
57
56
|
docValidator.recordCheckedRanges = true;
|
|
58
57
|
await docValidator.prepare();
|
|
59
58
|
const issues = docValidator.checkDocument(true);
|
|
60
|
-
const preparations = docValidator._getPreparations();
|
|
61
|
-
assert(preparations);
|
|
62
59
|
return genResult(docValidator.document.text, issues, docValidator.getRangesChecked());
|
|
63
60
|
}
|
|
64
61
|
function genResult(text, issues, includeRanges) {
|
|
@@ -1,13 +1,12 @@
|
|
|
1
|
-
import type { CSpellUserSettings,
|
|
1
|
+
import type { CSpellUserSettings, ParsedText } from '@cspell/cspell-types';
|
|
2
2
|
import type { ICSpellConfigFile } from 'cspell-config-lib';
|
|
3
3
|
import type { ExtendedSuggestion } from '../Models/Suggestion.js';
|
|
4
4
|
import type { TextDocument, TextDocumentRef } from '../Models/TextDocument.js';
|
|
5
5
|
import type { ValidationIssue } from '../Models/ValidationIssue.js';
|
|
6
|
-
import type { CSpellSettingsInternal,
|
|
7
|
-
import type { SpellingDictionaryCollection } from '../SpellingDictionary/index.js';
|
|
6
|
+
import type { CSpellSettingsInternal, ImportFileRefWithError } from '../Settings/index.js';
|
|
8
7
|
import type { WordSuggestion } from '../suggestions.js';
|
|
9
|
-
import type { MatchRange, SimpleRange
|
|
10
|
-
import type {
|
|
8
|
+
import type { MatchRange, SimpleRange } from '../Transform/index.js';
|
|
9
|
+
import type { Preparations } from './docValidatorPreparations.js';
|
|
11
10
|
import type { TraceResult } from './traceWord.js';
|
|
12
11
|
import type { ValidateTextOptions } from './ValidateTextOptions.js';
|
|
13
12
|
export interface DocumentValidatorOptions extends ValidateTextOptions {
|
|
@@ -117,8 +116,20 @@ export declare class DocumentValidator {
|
|
|
117
116
|
shouldCheckDocument(): boolean;
|
|
118
117
|
/**
|
|
119
118
|
* Internal `cspell-lib` use.
|
|
119
|
+
* @deprecated Will be removed in a future major version. Use {@link _getLocalConfig} and
|
|
120
|
+
* {@link _getLocalConfigFilepath} instead.
|
|
120
121
|
*/
|
|
121
122
|
_getPreparations(): Preparations | undefined;
|
|
123
|
+
/**
|
|
124
|
+
* Internal `cspell-lib` use.
|
|
125
|
+
* @returns the config file found for the document, if any.
|
|
126
|
+
*/
|
|
127
|
+
_getLocalConfig(): CSpellUserSettings | undefined;
|
|
128
|
+
/**
|
|
129
|
+
* Internal `cspell-lib` use.
|
|
130
|
+
* @returns the path of the config file found for the document, if any.
|
|
131
|
+
*/
|
|
132
|
+
_getLocalConfigFilepath(): string | undefined;
|
|
122
133
|
/**
|
|
123
134
|
* Get the calculated ranges of text that should be included in the spell checking.
|
|
124
135
|
*
|
|
@@ -132,22 +143,6 @@ export declare class DocumentValidator {
|
|
|
132
143
|
set recordCheckedRanges(value: boolean);
|
|
133
144
|
}
|
|
134
145
|
declare function sanitizeSuggestion(sug: WordSuggestion): ExtendedSuggestion;
|
|
135
|
-
interface Preparations {
|
|
136
|
-
/** loaded config */
|
|
137
|
-
config: CSpellSettingsInternal;
|
|
138
|
-
dictionary: SpellingDictionaryCollection;
|
|
139
|
-
/** configuration after applying in-doc settings */
|
|
140
|
-
docSettings: CSpellSettingsInternal;
|
|
141
|
-
finalSettings: CSpellSettingsInternalFinalized;
|
|
142
|
-
includeRanges: MatchRange[];
|
|
143
|
-
textValidator: TextValidator;
|
|
144
|
-
segmenter: (texts: MappedText) => Iterable<MappedText>;
|
|
145
|
-
shouldCheck: boolean;
|
|
146
|
-
validateOptions: TextValidationFactoryOptions;
|
|
147
|
-
localConfig: CSpellUserSettings | undefined;
|
|
148
|
-
localConfigFilepath: string | undefined;
|
|
149
|
-
transformer: TextTransformer;
|
|
150
|
-
}
|
|
151
146
|
interface ShouldCheckDocumentResult {
|
|
152
147
|
/** possible errors found while loading configuration. */
|
|
153
148
|
errors: Error[];
|
|
@@ -10,13 +10,14 @@ import { extractImportErrors, finalizeSettings, loadConfig, mergeSettings, resol
|
|
|
10
10
|
import { validateInDocumentSettings } from '../Settings/InDocSettings.js';
|
|
11
11
|
import { getDictionaryInternal } from '../SpellingDictionary/index.js';
|
|
12
12
|
import { calcSuggestionAdjustedToToMatchCase } from '../suggestions.js';
|
|
13
|
-
import { chainTransformers, createIntlSegmentTextTransformer,
|
|
13
|
+
import { chainTransformers, createIntlSegmentTextTransformer, createSoftWordBreakTextTransformer, createSubstitutionTransformer, } from '../Transform/index.js';
|
|
14
14
|
import { catchPromiseError, toError } from '../util/errors.js';
|
|
15
15
|
import { AutoCache } from '../util/simpleCache.js';
|
|
16
16
|
import { uriToFilePath } from '../util/Uri.js';
|
|
17
17
|
import { cleanValidationIssue } from './cleanValidationIssue.js';
|
|
18
18
|
import { defaultMaxDuplicateProblems, defaultMaxNumberOfProblems } from './defaultConstants.js';
|
|
19
19
|
import { determineTextDocumentSettings } from './determineTextDocumentSettings.js';
|
|
20
|
+
import { DocumentValidatorPreparations } from './docValidatorPreparations.js';
|
|
20
21
|
import { textValidatorFactory } from './lineValidatorFactory.js';
|
|
21
22
|
import { settingsToValidateOptions } from './settingsToValidateOptions.js';
|
|
22
23
|
import { calcTextInclusionRanges } from './textValidator.js';
|
|
@@ -108,22 +109,18 @@ export class DocumentValidator {
|
|
|
108
109
|
recShouldCheckTime();
|
|
109
110
|
const recFinalizeTime = recordPerfTime(this.perfTiming, '_finalizeSettings');
|
|
110
111
|
const finalSettings = finalizeSettings(docSettings);
|
|
111
|
-
const { transformer, validateOptions,
|
|
112
|
+
const { transformer, validateOptions, calcIncludeRanges, textValidator } = this.#calcSharedPrep(finalSettings, dict);
|
|
112
113
|
recFinalizeTime();
|
|
113
|
-
this._preparations = {
|
|
114
|
-
config,
|
|
114
|
+
this._preparations = new DocumentValidatorPreparations(config, localConfig, localConfig?.__importRef?.filename, {
|
|
115
115
|
dictionary: dict,
|
|
116
116
|
docSettings,
|
|
117
117
|
finalSettings,
|
|
118
118
|
shouldCheck,
|
|
119
119
|
validateOptions,
|
|
120
|
-
includeRanges,
|
|
121
|
-
segmenter,
|
|
122
120
|
textValidator,
|
|
123
|
-
localConfig,
|
|
124
|
-
localConfigFilepath: localConfig?.__importRef?.filename,
|
|
125
121
|
transformer,
|
|
126
|
-
|
|
122
|
+
calcIncludeRanges,
|
|
123
|
+
});
|
|
127
124
|
this._ready = true;
|
|
128
125
|
this._preparationTime = timer.elapsed;
|
|
129
126
|
this.perfTiming.prepTime = this._preparationTime;
|
|
@@ -138,19 +135,17 @@ export class DocumentValidator {
|
|
|
138
135
|
const stopMeasure = measurePerf('DocumentValidator._updatePrep');
|
|
139
136
|
const shouldCheck = docSettings.enabled ?? true;
|
|
140
137
|
const finalSettings = finalizeSettings(docSettings);
|
|
141
|
-
const { transformer, validateOptions,
|
|
142
|
-
|
|
143
|
-
...prep,
|
|
138
|
+
const { transformer, validateOptions, calcIncludeRanges, textValidator } = this.#calcSharedPrep(finalSettings, dict);
|
|
139
|
+
prep.update({
|
|
144
140
|
dictionary: dict,
|
|
145
141
|
docSettings,
|
|
146
142
|
finalSettings,
|
|
147
143
|
shouldCheck,
|
|
148
144
|
validateOptions,
|
|
149
|
-
includeRanges,
|
|
150
|
-
segmenter,
|
|
151
145
|
textValidator,
|
|
152
146
|
transformer,
|
|
153
|
-
|
|
147
|
+
calcIncludeRanges,
|
|
148
|
+
});
|
|
154
149
|
this._preparationTime = timer.elapsed;
|
|
155
150
|
stopMeasure();
|
|
156
151
|
}
|
|
@@ -169,10 +164,10 @@ export class DocumentValidator {
|
|
|
169
164
|
const validateOptions = { ...settingsToValidateOptions(finalSettings), transformer };
|
|
170
165
|
// Avoid excluding text ranges that have a full substitution applied.
|
|
171
166
|
const rangeTransformer = finalSettings.substitutions?.length ? sub.transformer : undefined;
|
|
172
|
-
const
|
|
173
|
-
const
|
|
167
|
+
const text = this._document.text;
|
|
168
|
+
const calcIncludeRanges = () => calcTextInclusionRanges(text, validateOptions, rangeTransformer);
|
|
174
169
|
const textValidator = textValidatorFactory(dict, validateOptions);
|
|
175
|
-
return {
|
|
170
|
+
return { textValidator, calcIncludeRanges, validateOptions, transformer };
|
|
176
171
|
}
|
|
177
172
|
/**
|
|
178
173
|
* The amount of time in ms to prepare for validation.
|
|
@@ -415,10 +410,26 @@ export class DocumentValidator {
|
|
|
415
410
|
}
|
|
416
411
|
/**
|
|
417
412
|
* Internal `cspell-lib` use.
|
|
413
|
+
* @deprecated Will be removed in a future major version. Use {@link _getLocalConfig} and
|
|
414
|
+
* {@link _getLocalConfigFilepath} instead.
|
|
418
415
|
*/
|
|
419
416
|
_getPreparations() {
|
|
420
417
|
return this._preparations;
|
|
421
418
|
}
|
|
419
|
+
/**
|
|
420
|
+
* Internal `cspell-lib` use.
|
|
421
|
+
* @returns the config file found for the document, if any.
|
|
422
|
+
*/
|
|
423
|
+
_getLocalConfig() {
|
|
424
|
+
return this._preparations?.localConfig;
|
|
425
|
+
}
|
|
426
|
+
/**
|
|
427
|
+
* Internal `cspell-lib` use.
|
|
428
|
+
* @returns the path of the config file found for the document, if any.
|
|
429
|
+
*/
|
|
430
|
+
_getLocalConfigFilepath() {
|
|
431
|
+
return this._preparations?.localConfigFilepath;
|
|
432
|
+
}
|
|
422
433
|
/**
|
|
423
434
|
* Get the calculated ranges of text that should be included in the spell checking.
|
|
424
435
|
*
|
|
@@ -509,11 +520,11 @@ export async function shouldCheckDocument(doc, options, settings) {
|
|
|
509
520
|
const config = mergeSettings(settings, localConfig);
|
|
510
521
|
const matcher = getGlobMatcherForExcluding(localConfig?.ignorePaths);
|
|
511
522
|
// eslint-disable-next-line unicorn/prefer-regexp-test
|
|
512
|
-
if (matcher.match(uriToFilePath(doc.uri))) {
|
|
523
|
+
if (!options.forceCheck && matcher.match(uriToFilePath(doc.uri))) {
|
|
513
524
|
return { errors, shouldCheck: false, settings: localConfig, reason: 'Excluded by ignorePaths.' };
|
|
514
525
|
}
|
|
515
526
|
const docSettings = await determineTextDocumentSettings(doc, config);
|
|
516
|
-
const shouldCheck = docSettings.enabled ?? true;
|
|
527
|
+
const shouldCheck = options.forceCheck || (docSettings.enabled ?? true);
|
|
517
528
|
const reason = shouldCheck ? undefined : 'Excluded by overrides or languageSettings.';
|
|
518
529
|
return { errors, shouldCheck, settings: docSettings, reason };
|
|
519
530
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import type { CSpellUserSettings, MappedText } from '@cspell/cspell-types';
|
|
2
|
+
import type { CSpellSettingsInternal, CSpellSettingsInternalFinalized } from '../Settings/index.js';
|
|
3
|
+
import type { SpellingDictionaryCollection } from '../SpellingDictionary/index.js';
|
|
4
|
+
import type { MatchRange, TextTransformer } from '../Transform/index.js';
|
|
5
|
+
import type { TextValidationFactoryOptions, TextValidator } from './lineValidatorFactory.js';
|
|
6
|
+
/**
|
|
7
|
+
* What a `DocumentValidator` needs to spell check its document.
|
|
8
|
+
*/
|
|
9
|
+
export interface Preparations {
|
|
10
|
+
/** loaded config */
|
|
11
|
+
config: CSpellSettingsInternal;
|
|
12
|
+
dictionary: SpellingDictionaryCollection;
|
|
13
|
+
/** configuration after applying in-doc settings */
|
|
14
|
+
docSettings: CSpellSettingsInternal;
|
|
15
|
+
finalSettings: CSpellSettingsInternalFinalized;
|
|
16
|
+
includeRanges: MatchRange[];
|
|
17
|
+
textValidator: TextValidator;
|
|
18
|
+
segmenter: (texts: MappedText) => Iterable<MappedText>;
|
|
19
|
+
shouldCheck: boolean;
|
|
20
|
+
validateOptions: TextValidationFactoryOptions;
|
|
21
|
+
localConfig: CSpellUserSettings | undefined;
|
|
22
|
+
localConfigFilepath: string | undefined;
|
|
23
|
+
transformer: TextTransformer;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* The preparations that depend on the document's settings. They are replaced when the document changes.
|
|
27
|
+
*/
|
|
28
|
+
export interface DocumentSettingsPreparations {
|
|
29
|
+
dictionary: SpellingDictionaryCollection;
|
|
30
|
+
/** configuration after applying in-doc settings */
|
|
31
|
+
docSettings: CSpellSettingsInternal;
|
|
32
|
+
finalSettings: CSpellSettingsInternalFinalized;
|
|
33
|
+
shouldCheck: boolean;
|
|
34
|
+
validateOptions: TextValidationFactoryOptions;
|
|
35
|
+
textValidator: TextValidator;
|
|
36
|
+
transformer: TextTransformer;
|
|
37
|
+
/**
|
|
38
|
+
* Runs every ignore pattern over the whole document, so it is only called once the include ranges are needed.
|
|
39
|
+
*/
|
|
40
|
+
calcIncludeRanges: () => MatchRange[];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The include ranges, and the segmenter built from them, are calculated on first use. A document that
|
|
44
|
+
* is never checked never pays for them.
|
|
45
|
+
*/
|
|
46
|
+
export declare class DocumentValidatorPreparations implements Preparations {
|
|
47
|
+
#private;
|
|
48
|
+
readonly config: CSpellSettingsInternal;
|
|
49
|
+
readonly localConfig: CSpellUserSettings | undefined;
|
|
50
|
+
readonly localConfigFilepath: string | undefined;
|
|
51
|
+
dictionary: SpellingDictionaryCollection;
|
|
52
|
+
/** configuration after applying in-doc settings */
|
|
53
|
+
docSettings: CSpellSettingsInternal;
|
|
54
|
+
finalSettings: CSpellSettingsInternalFinalized;
|
|
55
|
+
shouldCheck: boolean;
|
|
56
|
+
validateOptions: TextValidationFactoryOptions;
|
|
57
|
+
textValidator: TextValidator;
|
|
58
|
+
transformer: TextTransformer;
|
|
59
|
+
/**
|
|
60
|
+
* @param config - loaded config
|
|
61
|
+
* @param localConfig - the config file found for the document, if any.
|
|
62
|
+
* @param localConfigFilepath - the path of `localConfig`.
|
|
63
|
+
* @param prep - the preparations that depend on the document's settings.
|
|
64
|
+
*/
|
|
65
|
+
constructor(config: CSpellSettingsInternal, localConfig: CSpellUserSettings | undefined, localConfigFilepath: string | undefined, prep: DocumentSettingsPreparations);
|
|
66
|
+
/**
|
|
67
|
+
* Replace the preparations that depend on the document's settings. The include ranges are
|
|
68
|
+
* calculated again on next use.
|
|
69
|
+
*/
|
|
70
|
+
update(prep: DocumentSettingsPreparations): void;
|
|
71
|
+
get includeRanges(): MatchRange[];
|
|
72
|
+
get segmenter(): (texts: MappedText) => Iterable<MappedText>;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=docValidatorPreparations.d.ts.map
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { createMappedTextSegmenter } from '../Transform/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* The include ranges, and the segmenter built from them, are calculated on first use. A document that
|
|
4
|
+
* is never checked never pays for them.
|
|
5
|
+
*/
|
|
6
|
+
export class DocumentValidatorPreparations {
|
|
7
|
+
config;
|
|
8
|
+
localConfig;
|
|
9
|
+
localConfigFilepath;
|
|
10
|
+
dictionary;
|
|
11
|
+
/** configuration after applying in-doc settings */
|
|
12
|
+
docSettings;
|
|
13
|
+
finalSettings;
|
|
14
|
+
shouldCheck;
|
|
15
|
+
validateOptions;
|
|
16
|
+
textValidator;
|
|
17
|
+
transformer;
|
|
18
|
+
#calcIncludeRanges;
|
|
19
|
+
#includeRanges;
|
|
20
|
+
#segmenter;
|
|
21
|
+
/**
|
|
22
|
+
* @param config - loaded config
|
|
23
|
+
* @param localConfig - the config file found for the document, if any.
|
|
24
|
+
* @param localConfigFilepath - the path of `localConfig`.
|
|
25
|
+
* @param prep - the preparations that depend on the document's settings.
|
|
26
|
+
*/
|
|
27
|
+
constructor(config, localConfig, localConfigFilepath, prep) {
|
|
28
|
+
this.config = config;
|
|
29
|
+
this.localConfig = localConfig;
|
|
30
|
+
this.localConfigFilepath = localConfigFilepath;
|
|
31
|
+
this.dictionary = prep.dictionary;
|
|
32
|
+
this.docSettings = prep.docSettings;
|
|
33
|
+
this.finalSettings = prep.finalSettings;
|
|
34
|
+
this.shouldCheck = prep.shouldCheck;
|
|
35
|
+
this.validateOptions = prep.validateOptions;
|
|
36
|
+
this.textValidator = prep.textValidator;
|
|
37
|
+
this.transformer = prep.transformer;
|
|
38
|
+
this.#calcIncludeRanges = prep.calcIncludeRanges;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Replace the preparations that depend on the document's settings. The include ranges are
|
|
42
|
+
* calculated again on next use.
|
|
43
|
+
*/
|
|
44
|
+
update(prep) {
|
|
45
|
+
this.dictionary = prep.dictionary;
|
|
46
|
+
this.docSettings = prep.docSettings;
|
|
47
|
+
this.finalSettings = prep.finalSettings;
|
|
48
|
+
this.shouldCheck = prep.shouldCheck;
|
|
49
|
+
this.validateOptions = prep.validateOptions;
|
|
50
|
+
this.textValidator = prep.textValidator;
|
|
51
|
+
this.transformer = prep.transformer;
|
|
52
|
+
this.#calcIncludeRanges = prep.calcIncludeRanges;
|
|
53
|
+
this.#includeRanges = undefined;
|
|
54
|
+
this.#segmenter = undefined;
|
|
55
|
+
}
|
|
56
|
+
get includeRanges() {
|
|
57
|
+
return (this.#includeRanges ??= this.#calcIncludeRanges());
|
|
58
|
+
}
|
|
59
|
+
get segmenter() {
|
|
60
|
+
return (this.#segmenter ??= createMappedTextSegmenter(this.includeRanges));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=docValidatorPreparations.js.map
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import assert from 'node:assert';
|
|
2
1
|
import { opConcatMap, opFilter, pipe } from '@cspell/cspell-pipe/sync';
|
|
3
2
|
import { defaultCSpellSettings, unknownWordsChoices } from '@cspell/cspell-types';
|
|
4
3
|
import { createCachingDictionary } from 'cspell-dictionary';
|
|
5
4
|
import * as RxPat from '../Settings/RegExpPatterns.js';
|
|
6
5
|
import { mapRangeBackToOriginalPos } from '../Transform/index.js';
|
|
7
6
|
import { autoResolve } from '../util/AutoResolve.js';
|
|
8
|
-
import { extractPossibleWordsFromTextOffset, extractText, extractWordsFromTextOffset, splitWordWithOffset, } from '../util/text.js';
|
|
7
|
+
import { extractPossibleWordsFromTextOffset, extractText, extractWordsFromTextOffset, numCharacters, splitWordWithOffset, } from '../util/text.js';
|
|
9
8
|
import { regExpCamelCaseWordBreaksWithEnglishSuffix } from '../util/textRegex.js';
|
|
10
9
|
import { split } from '../util/wordSplitter/index.js';
|
|
11
10
|
import { defaultMinWordLength } from './defaultConstants.js';
|
|
@@ -131,22 +130,31 @@ export function lineValidatorFactory(sDict, options) {
|
|
|
131
130
|
return issue;
|
|
132
131
|
}
|
|
133
132
|
const regExUpperCaseWithTrailingCommonEnglishSuffix = /^([\p{Lu}\p{M}]{2,})['’]?(?:s|ing|ies|es|ings|ize|ed|ning)$/u; // cspell:disable-line
|
|
134
|
-
|
|
133
|
+
// Sticky: test the text at `lastIndex` without creating substrings.
|
|
134
|
+
const regExpIsLetterBefore = /(?<=\p{L})/uy;
|
|
135
|
+
const regExpIsLetterAt = /\p{L}/uy;
|
|
135
136
|
const fn = (lineSegment) => {
|
|
136
137
|
const line = lineSegment.line;
|
|
138
|
+
/**
|
|
139
|
+
* A short word is ok if it stands alone in the line, i.e. it is not next to other letters.
|
|
140
|
+
*/
|
|
137
141
|
function isWordTooShort(word, ignoreSuffix = false) {
|
|
138
|
-
|
|
142
|
+
const tLen = word.text.length;
|
|
143
|
+
const wLen = word.length ?? tLen;
|
|
144
|
+
if (tLen >= minWordLength * 2 || numCharacters(word.text) >= minWordLength)
|
|
145
|
+
return false;
|
|
146
|
+
// A word joined across soft hyphens does not stand alone in the line.
|
|
147
|
+
if (wLen !== tLen)
|
|
139
148
|
return false;
|
|
140
149
|
const offset = word.offset - line.offset;
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
const hasLetterPrefix = !!prefix.length && regExpIsLetter.test(prefix[prefix.length - 1]);
|
|
150
|
+
regExpIsLetterBefore.lastIndex = offset;
|
|
151
|
+
const hasLetterPrefix = regExpIsLetterBefore.test(line.text);
|
|
144
152
|
if (hasLetterPrefix)
|
|
145
153
|
return false;
|
|
146
154
|
if (ignoreSuffix)
|
|
147
155
|
return true;
|
|
148
|
-
|
|
149
|
-
const hasLetterSuffix =
|
|
156
|
+
regExpIsLetterAt.lastIndex = offset + wLen;
|
|
157
|
+
const hasLetterSuffix = regExpIsLetterAt.test(line.text);
|
|
150
158
|
return !hasLetterSuffix;
|
|
151
159
|
}
|
|
152
160
|
function splitterIsValid(word) {
|
|
@@ -173,6 +181,9 @@ export function lineValidatorFactory(sDict, options) {
|
|
|
173
181
|
return false;
|
|
174
182
|
if (check.isFound)
|
|
175
183
|
return true;
|
|
184
|
+
// A word joined across soft hyphens does not stand alone in the line.
|
|
185
|
+
if (tWord.length !== undefined && tWord.length !== tWord.text.length)
|
|
186
|
+
return false;
|
|
176
187
|
if (isWordTooShort(v, true))
|
|
177
188
|
return true;
|
|
178
189
|
return false;
|
|
@@ -374,8 +385,9 @@ export function textValidatorFactory(dict, options) {
|
|
|
374
385
|
const segment = { text, offset: 0 };
|
|
375
386
|
const lineSegment = { line: segment, segment };
|
|
376
387
|
function mapBackToOriginSimple(vr) {
|
|
377
|
-
const { text, offset, isFlagged, isFound, suggestionsEx, hasPreferredSuggestions, hasSimpleSuggestions } = vr;
|
|
378
|
-
const
|
|
388
|
+
const { text, length, offset, isFlagged, isFound, suggestionsEx, hasPreferredSuggestions, hasSimpleSuggestions, } = vr;
|
|
389
|
+
const wLen = length ?? text.length;
|
|
390
|
+
const r = mapRangeBackToOriginalPos([offset, offset + wLen], map);
|
|
379
391
|
const range = [r[0] + srcOffset, r[1] + srcOffset];
|
|
380
392
|
return {
|
|
381
393
|
text,
|
package/dist/lib/util/text.d.ts
CHANGED
|
@@ -52,6 +52,13 @@ export declare function textOffset(text: string, offset?: number): TextOffset;
|
|
|
52
52
|
export declare function extractText(textOffset: TextOffset, startPos: number, endPos: number): string;
|
|
53
53
|
export declare function calculateTextDocumentOffsets<T extends TextOffset>(uri: string | Uri | URL, doc: string, wordOffsets: T[]): (TextDocumentOffset & T)[];
|
|
54
54
|
export declare function removeAccents(text: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* Count the number of characters (Unicode code points) in a string.
|
|
57
|
+
* Surrogate pairs count as one character. Same result as `[...text].length`, without creating an array.
|
|
58
|
+
* @param text - the string to count.
|
|
59
|
+
* @returns the number of characters.
|
|
60
|
+
*/
|
|
61
|
+
export declare function numCharacters(text: string): number;
|
|
55
62
|
export declare const __testing__: {
|
|
56
63
|
regExWords: RegExp;
|
|
57
64
|
regExWordsAndDigits: RegExp;
|
package/dist/lib/util/text.js
CHANGED
|
@@ -204,6 +204,22 @@ export function removeAccents(text) {
|
|
|
204
204
|
regExAccents.lastIndex = 0;
|
|
205
205
|
return text.normalize('NFD').replace(regExAccents, '');
|
|
206
206
|
}
|
|
207
|
+
/**
|
|
208
|
+
* Count the number of characters (Unicode code points) in a string.
|
|
209
|
+
* Surrogate pairs count as one character. Same result as `[...text].length`, without creating an array.
|
|
210
|
+
* @param text - the string to count.
|
|
211
|
+
* @returns the number of characters.
|
|
212
|
+
*/
|
|
213
|
+
export function numCharacters(text) {
|
|
214
|
+
const len = text.length;
|
|
215
|
+
let n = 0;
|
|
216
|
+
for (let i = 0; i < len; ++i, ++n) {
|
|
217
|
+
// A code point above 0xFFFF is a surrogate pair, skip the second half.
|
|
218
|
+
if ((text.codePointAt(i) || 0) > 0xffff)
|
|
219
|
+
++i;
|
|
220
|
+
}
|
|
221
|
+
return n;
|
|
222
|
+
}
|
|
207
223
|
export const __testing__ = {
|
|
208
224
|
regExWords: regExWords,
|
|
209
225
|
regExWordsAndDigits: regExWordsAndDigits,
|
package/package.json
CHANGED
|
@@ -1,15 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cspell-lib",
|
|
3
|
+
"version": "10.3.6",
|
|
4
|
+
"description": "A library of useful functions used across various cspell tools.",
|
|
3
5
|
"publishConfig": {
|
|
4
6
|
"access": "public",
|
|
5
7
|
"provenance": true
|
|
6
8
|
},
|
|
7
|
-
"
|
|
8
|
-
"
|
|
9
|
-
|
|
9
|
+
"homepage": "https://github.com/streetsidesoftware/cspell/tree/main/packages/cspell-lib#readme",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/streetsidesoftware/cspell.git",
|
|
13
|
+
"directory": "packages/cspell-lib"
|
|
14
|
+
},
|
|
15
|
+
"bugs": {
|
|
16
|
+
"url": "https://github.com/streetsidesoftware/cspell/issues?q=is%3Aissue%20state%3Aopen%20label%3Acspell-lib"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"spell",
|
|
20
|
+
"checker",
|
|
21
|
+
"code",
|
|
22
|
+
"camel",
|
|
23
|
+
"case",
|
|
24
|
+
"spelling",
|
|
25
|
+
"spell checker",
|
|
26
|
+
"spelling checker",
|
|
27
|
+
"lint"
|
|
28
|
+
],
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"author": "Jason Dent",
|
|
10
31
|
"sideEffects": false,
|
|
11
|
-
"
|
|
12
|
-
"module": "dist/index.js",
|
|
32
|
+
"type": "module",
|
|
13
33
|
"exports": {
|
|
14
34
|
".": {
|
|
15
35
|
"import": "./dist/index.js"
|
|
@@ -27,6 +47,8 @@
|
|
|
27
47
|
"import": "./dist/cspell-rpc/client.js"
|
|
28
48
|
}
|
|
29
49
|
},
|
|
50
|
+
"module": "dist/index.js",
|
|
51
|
+
"types": "dist/index.d.ts",
|
|
30
52
|
"files": [
|
|
31
53
|
"dist",
|
|
32
54
|
"!**/*.tsbuildInfo",
|
|
@@ -38,59 +60,37 @@
|
|
|
38
60
|
"!**/*.map"
|
|
39
61
|
],
|
|
40
62
|
"scripts": {
|
|
41
|
-
"clean": "shx rm -rf dist temp coverage \"*.tsbuildInfo\"",
|
|
42
|
-
"clean-build": "pnpm clean && pnpm build",
|
|
43
63
|
"build": "tsc -p . && pnpm run build:api",
|
|
44
64
|
"build:api": "tsdown",
|
|
45
|
-
"
|
|
65
|
+
"clean": "shx rm -rf dist temp coverage \"*.tsbuildInfo\"",
|
|
66
|
+
"clean-build": "pnpm clean && pnpm build",
|
|
46
67
|
"coverage": "vitest run --coverage --pool=forks",
|
|
47
|
-
"test-watch": "vitest",
|
|
48
68
|
"prepublishOnly": "pnpm run clean-build",
|
|
49
69
|
"test": "vitest run --pool=forks",
|
|
50
|
-
"test:update-snapshot": "vitest run -u",
|
|
51
70
|
"test:perf": "NODE_ENV=production insight --file \"**/*.perf.{mjs,js}\"",
|
|
71
|
+
"test:perf:prof": "NODE_ENV=production node --cpu-prof ../../node_modules/perf-insight/bin.mjs --file \"dist/**/*.perf.{mjs,js}\" -t 1000",
|
|
52
72
|
"test:perf:ts": "NODE_ENV=production insight --file \"**/*.perf.{mts,ts}\" ",
|
|
53
|
-
"test:
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"type": "git",
|
|
57
|
-
"url": "https://github.com/streetsidesoftware/cspell.git",
|
|
58
|
-
"directory": "packages/cspell-lib"
|
|
59
|
-
},
|
|
60
|
-
"keywords": [
|
|
61
|
-
"spell",
|
|
62
|
-
"checker",
|
|
63
|
-
"code",
|
|
64
|
-
"camel",
|
|
65
|
-
"case",
|
|
66
|
-
"spelling",
|
|
67
|
-
"spell checker",
|
|
68
|
-
"spelling checker",
|
|
69
|
-
"lint"
|
|
70
|
-
],
|
|
71
|
-
"author": "Jason Dent",
|
|
72
|
-
"license": "MIT",
|
|
73
|
-
"bugs": {
|
|
74
|
-
"url": "https://github.com/streetsidesoftware/cspell/labels/cspell-lib"
|
|
73
|
+
"test:update-snapshot": "vitest run -u",
|
|
74
|
+
"test-watch": "vitest",
|
|
75
|
+
"watch": "tsc -p . --watch"
|
|
75
76
|
},
|
|
76
|
-
"homepage": "https://github.com/streetsidesoftware/cspell/tree/main/packages/cspell-lib#readme",
|
|
77
77
|
"dependencies": {
|
|
78
|
-
"@cspell/cspell-bundled-dicts": "10.3.
|
|
79
|
-
"@cspell/cspell-performance-monitor": "10.3.
|
|
80
|
-
"@cspell/cspell-pipe": "10.3.
|
|
81
|
-
"@cspell/cspell-resolver": "10.3.
|
|
82
|
-
"@cspell/cspell-types": "10.3.
|
|
83
|
-
"@cspell/dynamic-import": "10.3.
|
|
84
|
-
"@cspell/filetypes": "10.3.
|
|
85
|
-
"@cspell/rpc": "10.3.
|
|
86
|
-
"@cspell/strong-weak-map": "10.3.
|
|
87
|
-
"@cspell/url": "10.3.
|
|
88
|
-
"cspell-config-lib": "10.3.
|
|
89
|
-
"cspell-dictionary": "10.3.
|
|
90
|
-
"cspell-glob": "10.3.
|
|
91
|
-
"cspell-grammar": "10.3.
|
|
92
|
-
"cspell-io": "10.3.
|
|
93
|
-
"cspell-trie-lib": "10.3.
|
|
78
|
+
"@cspell/cspell-bundled-dicts": "10.3.6",
|
|
79
|
+
"@cspell/cspell-performance-monitor": "10.3.6",
|
|
80
|
+
"@cspell/cspell-pipe": "10.3.6",
|
|
81
|
+
"@cspell/cspell-resolver": "10.3.6",
|
|
82
|
+
"@cspell/cspell-types": "10.3.6",
|
|
83
|
+
"@cspell/dynamic-import": "10.3.6",
|
|
84
|
+
"@cspell/filetypes": "10.3.6",
|
|
85
|
+
"@cspell/rpc": "10.3.6",
|
|
86
|
+
"@cspell/strong-weak-map": "10.3.6",
|
|
87
|
+
"@cspell/url": "10.3.6",
|
|
88
|
+
"cspell-config-lib": "10.3.6",
|
|
89
|
+
"cspell-dictionary": "10.3.6",
|
|
90
|
+
"cspell-glob": "10.3.6",
|
|
91
|
+
"cspell-grammar": "10.3.6",
|
|
92
|
+
"cspell-io": "10.3.6",
|
|
93
|
+
"cspell-trie-lib": "10.3.6",
|
|
94
94
|
"env-paths": "^4.0.0",
|
|
95
95
|
"gensequence": "^8.0.8",
|
|
96
96
|
"import-fresh": "^4.0.0",
|
|
@@ -99,11 +99,7 @@
|
|
|
99
99
|
"vscode-uri": "^3.2.0",
|
|
100
100
|
"xdg-basedir": "^5.1.0"
|
|
101
101
|
},
|
|
102
|
-
"engines": {
|
|
103
|
-
"node": ">=22.18.0"
|
|
104
|
-
},
|
|
105
102
|
"devDependencies": {
|
|
106
|
-
"@cspell/cspell-tools": "10.3.4",
|
|
107
103
|
"@cspell/dict-cpp": "^7.1.0",
|
|
108
104
|
"@cspell/dict-csharp": "^4.0.8",
|
|
109
105
|
"@cspell/dict-css": "^4.1.2",
|
|
@@ -123,5 +119,8 @@
|
|
|
123
119
|
"lorem-ipsum": "^3.0.0",
|
|
124
120
|
"perf-insight": "^2.0.1"
|
|
125
121
|
},
|
|
126
|
-
"
|
|
122
|
+
"engines": {
|
|
123
|
+
"node": ">=22.18.0"
|
|
124
|
+
},
|
|
125
|
+
"gitHead": "8559198ccfcac2f745911db1ffe2ee62c17cba49"
|
|
127
126
|
}
|