cspell-lib 9.6.4 → 9.8.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.
Files changed (39) hide show
  1. package/dist/lib/Models/ValidationIssue.d.ts +8 -1
  2. package/dist/lib/Models/ValidationIssue.js +15 -1
  3. package/dist/lib/Models/ValidationResult.d.ts +24 -3
  4. package/dist/lib/Settings/CSpellSettingsServer.js +2 -2
  5. package/dist/lib/Settings/Controller/configLoader/configLoader.d.ts +2 -2
  6. package/dist/lib/Settings/Controller/configLoader/configLoader.js +27 -6
  7. package/dist/lib/Settings/Controller/configLoader/defaultConfigLoader.d.ts +0 -1
  8. package/dist/lib/Settings/DefaultSettings.d.ts +11 -0
  9. package/dist/lib/Settings/DefaultSettings.js +14 -3
  10. package/dist/lib/Settings/constants.js +1 -0
  11. package/dist/lib/Settings/sanitizeSettings.js +6 -0
  12. package/dist/lib/Transform/SourceMap.d.ts +115 -0
  13. package/dist/lib/Transform/SourceMap.js +469 -0
  14. package/dist/lib/Transform/SubstitutionTransformer.d.ts +32 -0
  15. package/dist/lib/Transform/SubstitutionTransformer.js +121 -0
  16. package/dist/lib/Transform/TextMap.d.ts +35 -0
  17. package/dist/lib/Transform/TextMap.js +86 -0
  18. package/dist/lib/{util → Transform}/TextRange.js +6 -7
  19. package/dist/lib/Transform/index.d.ts +9 -0
  20. package/dist/lib/Transform/index.js +5 -0
  21. package/dist/lib/{textValidation → Transform}/parsedText.d.ts +5 -6
  22. package/dist/lib/{textValidation → Transform}/parsedText.js +6 -34
  23. package/dist/lib/Transform/types.d.ts +5 -0
  24. package/dist/lib/Transform/types.js +2 -0
  25. package/dist/lib/spellCheckFile.d.ts +26 -1
  26. package/dist/lib/spellCheckFile.js +21 -8
  27. package/dist/lib/textValidation/docValidator.d.ts +5 -7
  28. package/dist/lib/textValidation/docValidator.js +14 -5
  29. package/dist/lib/textValidation/index.d.ts +1 -1
  30. package/dist/lib/textValidation/lineValidatorFactory.d.ts +5 -1
  31. package/dist/lib/textValidation/lineValidatorFactory.js +5 -3
  32. package/dist/lib/textValidation/settingsToValidateOptions.js +10 -1
  33. package/dist/lib/textValidation/textValidator.d.ts +1 -1
  34. package/dist/lib/textValidation/textValidator.js +1 -1
  35. package/dist/lib/util/fileReader.d.ts +1 -1
  36. package/package.json +26 -26
  37. package/dist/lib/util/TextMap.d.ts +0 -15
  38. package/dist/lib/util/TextMap.js +0 -54
  39. /package/dist/lib/{util → Transform}/TextRange.d.ts +0 -0
@@ -0,0 +1,86 @@
1
+ import { calcOffsetInDst, calcOffsetInSrc, createSourceMapCursor, sliceSourceMapToSourceRange } from './SourceMap.js';
2
+ /**
3
+ * Extract a substring from a TextMap.
4
+ * @param textMap - A text range with an optional map
5
+ * @param extractRange - The range in the original document to extract
6
+ * @returns The TextMap covering extractRange
7
+ */
8
+ export function extractTextMapRangeOrigin(textMap, extractRange) {
9
+ const { text: srcTxt, range: srcRange } = textMap;
10
+ const [r0, r1] = srcRange;
11
+ const startOrig = Math.min(Math.max(extractRange[0], r0), r1);
12
+ const endOrig = Math.min(Math.max(extractRange[1], r0), r1);
13
+ const a = startOrig - r0;
14
+ const b = endOrig - r0;
15
+ const range = [startOrig, endOrig];
16
+ if (!textMap.map?.length) {
17
+ const text = srcTxt.slice(a, b);
18
+ return { text, range };
19
+ }
20
+ const rangeSrc = [a, b];
21
+ const [a1, b1] = calculateRangeInDest(textMap.map, rangeSrc);
22
+ const tm = {
23
+ text: srcTxt.slice(a1, b1),
24
+ range,
25
+ };
26
+ const sourceMap = sliceSourceMapToSourceRange(textMap.map, rangeSrc);
27
+ if (sourceMap?.length) {
28
+ tm.map = sourceMap;
29
+ }
30
+ return tm;
31
+ }
32
+ export function calculateRangeInDest(srcMap, rangeOrigin) {
33
+ const cursor = createSourceMapCursor(srcMap);
34
+ if (!cursor) {
35
+ return rangeOrigin;
36
+ }
37
+ const start = cursor.mapOffsetToDest(rangeOrigin[0]);
38
+ const end = cursor.mapOffsetToDest(rangeOrigin[1]);
39
+ return [start, end];
40
+ }
41
+ export function calculateRangeInSrc(srcMap, rangeOrigin) {
42
+ const cursor = createSourceMapCursor(srcMap);
43
+ if (!cursor) {
44
+ return rangeOrigin;
45
+ }
46
+ const start = cursor.mapOffsetToSrc(rangeOrigin[0]);
47
+ const end = cursor.mapOffsetToSrc(rangeOrigin[1]);
48
+ return [start, end];
49
+ }
50
+ export function calculateTextMapRangeDest(textMap, rangeOrigin) {
51
+ const { range: srcRange, map: srcMap } = textMap;
52
+ const [r0, r1] = srcRange;
53
+ const start = Math.min(Math.max(rangeOrigin[0], r0), r1) - r0;
54
+ const end = Math.min(Math.max(rangeOrigin[1], r0), r1) - r0;
55
+ const range = [start, end];
56
+ return calculateRangeInDest(srcMap, range);
57
+ }
58
+ /**
59
+ * Map an offset in the transformed text back to the original text.
60
+ * It will find the first matching position in the map.
61
+ *
62
+ * @param map - The source map to use for the mapping.
63
+ * If undefined or empty, the input offset is returned, assuming it is a 1:1 mapping.
64
+ * @param offset - the offset in the transformed text to map back to the original text
65
+ */
66
+ export function mapOffsetToSource(map, offset) {
67
+ const cursor = createSourceMapCursor(map);
68
+ return calcOffsetInSrc(cursor, offset);
69
+ }
70
+ /**
71
+ * Map an offset in the original text to the transformed text.
72
+ * It will find the first matching position in the map.
73
+ *
74
+ * @param map - The source map to use for the mapping.
75
+ * If undefined or empty, the input offset is returned, assuming it is a 1:1 mapping.
76
+ * @param offset - the offset in the original text to map to the transformed text
77
+ */
78
+ export function mapOffsetToDest(map, offset) {
79
+ const cursor = createSourceMapCursor(map);
80
+ return calcOffsetInDst(cursor, offset);
81
+ }
82
+ export function doesIntersect(textMap, rangeOrigin) {
83
+ const r = textMap.range;
84
+ return r[0] < rangeOrigin[1] && r[1] > rangeOrigin[0];
85
+ }
86
+ //# sourceMappingURL=TextMap.js.map
@@ -1,11 +1,10 @@
1
1
  function toMatchRangeWithText(m) {
2
- const index = m.index || 0;
3
- const _text = m[0];
4
- return {
5
- startPos: index,
6
- endPos: index + _text.length,
7
- text: _text,
8
- };
2
+ const range = m.indices?.[0];
3
+ const index = range?.[0] ?? (m.index || 0);
4
+ const text = m[0];
5
+ const startPos = index;
6
+ const endPos = range?.[1] ?? index + text.length;
7
+ return { startPos, endPos, text };
9
8
  }
10
9
  export function findMatchingRanges(pattern, text) {
11
10
  if (pattern.source === '.*') {
@@ -0,0 +1,9 @@
1
+ export { createMappedTextSegmenter, mapRangeBackToOriginalPos } from './parsedText.js';
2
+ export type { SourceMapCursor } from './SourceMap.js';
3
+ export { createSourceMapCursor } from './SourceMap.js';
4
+ export type { SubstitutionInfo } from './SubstitutionTransformer.js';
5
+ export { createSubstitutionTransformer, SubstitutionTransformer } from './SubstitutionTransformer.js';
6
+ export type { MatchRange } from './TextRange.js';
7
+ export { excludeRanges, extractRangeText, findMatchingRanges, findMatchingRangesForPatterns } from './TextRange.js';
8
+ export type { Offset, SimpleRange } from './types.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,5 @@
1
+ export { createMappedTextSegmenter, mapRangeBackToOriginalPos } from './parsedText.js';
2
+ export { createSourceMapCursor } from './SourceMap.js';
3
+ export { createSubstitutionTransformer, SubstitutionTransformer } from './SubstitutionTransformer.js';
4
+ export { excludeRanges, extractRangeText, findMatchingRanges, findMatchingRangesForPatterns } from './TextRange.js';
5
+ //# sourceMappingURL=index.js.map
@@ -1,11 +1,10 @@
1
- import type { MappedText } from '@cspell/cspell-types';
1
+ import type { MappedText, SourceMap } from '@cspell/cspell-types';
2
2
  import type { ValidationIssue } from '../Models/ValidationIssue.js';
3
- import type * as TextRange from '../util/TextRange.js';
4
- export type Offset = number;
5
- export type SimpleRange = readonly [Offset, Offset];
3
+ import type * as TextRange from './TextRange.js';
4
+ import type { SimpleRange } from './types.js';
6
5
  export declare function mapIssueBackToOriginalPos(mappedText: MappedText, issue: ValidationIssue): ValidationIssue;
7
- export declare function mapRangeBackToOriginalPos(offRange: SimpleRange, map: number[] | undefined): SimpleRange;
8
- export declare function mapRangeToLocal(rangeOrig: SimpleRange, map: number[] | undefined): SimpleRange;
6
+ export declare function mapRangeBackToOriginalPos(offRange: SimpleRange, map: SourceMap | undefined): SimpleRange;
7
+ export declare function mapRangeToLocal(rangeOrig: SimpleRange, map: SourceMap | undefined): SimpleRange;
9
8
  /**
10
9
  * Factory to create a segmentation function that will segment MappedText against a set of includeRanges.
11
10
  * The function produced is optimized for forward scanning. It will perform poorly for randomly ordered offsets.
@@ -1,6 +1,6 @@
1
- import { extractTextMapRangeOrigin } from '../util/TextMap.js';
1
+ import { calculateRangeInDest, calculateRangeInSrc, extractTextMapRangeOrigin } from './TextMap.js';
2
2
  export function mapIssueBackToOriginalPos(mappedText, issue) {
3
- if (!mappedText.map || mappedText.map.length === 0)
3
+ if (!mappedText.map?.length)
4
4
  return issue;
5
5
  const textOff = mapTextOffsetBackToOriginalPos(mappedText, issue);
6
6
  return {
@@ -9,7 +9,7 @@ export function mapIssueBackToOriginalPos(mappedText, issue) {
9
9
  };
10
10
  }
11
11
  function mapTextOffsetBackToOriginalPos(mappedText, textOff) {
12
- if (!mappedText.map || !mappedText.map.length)
12
+ if (!mappedText.map?.length)
13
13
  return textOff;
14
14
  const off = textOff.offset - mappedText.range[0];
15
15
  const range = mapRangeBackToOriginalPos([off, off + (textOff.length ?? textOff.text.length)], mappedText.map);
@@ -22,40 +22,12 @@ function mapTextOffsetBackToOriginalPos(mappedText, textOff) {
22
22
  export function mapRangeBackToOriginalPos(offRange, map) {
23
23
  if (!map || !map.length)
24
24
  return offRange;
25
- const [start, end] = offRange;
26
- let i = 0, j = 0, p = 1;
27
- while (p < map.length && map[p] < start) {
28
- i = map[p - 1];
29
- j = map[p];
30
- p += 2;
31
- }
32
- const iA = start - j + i;
33
- while (p < map.length && map[p] < end) {
34
- i = map[p - 1];
35
- j = map[p];
36
- p += 2;
37
- }
38
- const iB = end - j + i;
39
- return [iA, iB];
25
+ return calculateRangeInSrc(map, offRange);
40
26
  }
41
27
  export function mapRangeToLocal(rangeOrig, map) {
42
- if (!map || !map.length)
28
+ if (!map?.length)
43
29
  return rangeOrig;
44
- const [start, end] = rangeOrig;
45
- let i = 0, j = 0, p = 0;
46
- while (p < map.length && map[p] < start) {
47
- i = map[p];
48
- j = map[p + 1];
49
- p += 2;
50
- }
51
- const jA = start - i + j;
52
- while (p < map.length && map[p] < end) {
53
- i = map[p];
54
- j = map[p + 1];
55
- p += 2;
56
- }
57
- const jB = end - i + j;
58
- return [jA, jB];
30
+ return calculateRangeInDest(map, rangeOrig);
59
31
  }
60
32
  /**
61
33
  * Factory to create a segmentation function that will segment MappedText against a set of includeRanges.
@@ -0,0 +1,5 @@
1
+ import type { Range } from '@cspell/cspell-types';
2
+ export type { MappedText, Range } from '@cspell/cspell-types';
3
+ export type Offset = number;
4
+ export type SimpleRange = Readonly<Range>;
5
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -1,6 +1,7 @@
1
1
  import type { CSpellSettingsWithSourceTrace, CSpellUserSettings } from '@cspell/cspell-types';
2
2
  import type { ICSpellConfigFile } from 'cspell-config-lib';
3
3
  import type { Document, DocumentWithText } from './Document/index.js';
4
+ import type { ValidationIssueRPC } from './Models/ValidationIssue.js';
4
5
  import type { ImportFileRefWithError } from './Settings/index.js';
5
6
  import type { Uri } from './util/IUri.js';
6
7
  import type { ValidateTextOptions, ValidationIssue } from './validator.js';
@@ -25,6 +26,9 @@ export interface SpellCheckFileOptions extends ValidateTextOptions, Pick<CSpellU
25
26
  */
26
27
  noConfigSearch?: boolean;
27
28
  }
29
+ export interface SpellCheckFileOptionsRPC extends SpellCheckFileOptions {
30
+ measurePerf?: boolean;
31
+ }
28
32
  export interface SpellCheckFilePerf extends Record<string, number | undefined> {
29
33
  loadTimeMs?: number;
30
34
  prepareTimeMs?: number;
@@ -43,6 +47,26 @@ export interface SpellCheckFileResult {
43
47
  dictionaryErrors?: Map<string, Error[]> | undefined;
44
48
  perf?: SpellCheckFilePerf;
45
49
  }
50
+ interface DocumentReferenceRPC extends Pick<Document, 'uri'> {
51
+ text?: undefined;
52
+ languageId?: undefined;
53
+ locale?: undefined;
54
+ }
55
+ export interface SpellCheckFileResultRPC {
56
+ /**
57
+ * The document that was checked.
58
+ *
59
+ * **Note:** the text will be missing to avoid sending large amounts of text over the RPC channel.
60
+ * If the text is needed, the document should be reloaded using the URI.
61
+ */
62
+ document: DocumentReferenceRPC;
63
+ issues?: ValidationIssueRPC[] | undefined;
64
+ checked: boolean;
65
+ errors?: Error[] | undefined;
66
+ configErrors?: ImportFileRefWithError[] | undefined;
67
+ dictionaryErrors?: Map<string, Error[]> | undefined;
68
+ perf?: SpellCheckFilePerf | undefined;
69
+ }
46
70
  /**
47
71
  * Spell Check a file
48
72
  * @param file - absolute path to file to read and check.
@@ -63,7 +87,7 @@ export declare function spellCheckDocument(document: Document | DocumentWithText
63
87
  * @param options - options to control checking
64
88
  * @param settings - default settings to use.
65
89
  */
66
- export declare function spellCheckDocumentRPC(document: Document | DocumentWithText, options: SpellCheckFileOptions, settingsOrConfigFile: CSpellUserSettings | ICSpellConfigFile): Promise<SpellCheckFileResult>;
90
+ export declare function spellCheckDocumentRPC(document: Document | DocumentWithText, options: SpellCheckFileOptionsRPC, settingsOrConfigFile: CSpellUserSettings | ICSpellConfigFile): Promise<SpellCheckFileResultRPC>;
67
91
  export interface DetermineFinalDocumentSettingsResult {
68
92
  document: DocumentWithText;
69
93
  settings: CSpellSettingsWithSourceTrace;
@@ -81,4 +105,5 @@ export interface DetermineFinalDocumentSettingsResult {
81
105
  * @param settings - The near final settings. Should already be the combination of all configuration files.
82
106
  */
83
107
  export declare function determineFinalDocumentSettings(document: DocumentWithText, settings: CSpellUserSettings): Promise<DetermineFinalDocumentSettingsResult>;
108
+ export {};
84
109
  //# sourceMappingURL=spellCheckFile.d.ts.map
@@ -2,12 +2,11 @@ import { satisfiesCSpellConfigFile } from 'cspell-config-lib';
2
2
  import { isBinaryDoc } from './Document/isBinaryDoc.js';
3
3
  import { documentToTextDocument, resolveDocument } from './Document/resolveDocument.js';
4
4
  import { createTextDocument } from './Models/TextDocument.js';
5
+ import { toValidationIssueRPC } from './Models/ValidationIssue.js';
5
6
  import { createPerfTimer } from './perf/index.js';
6
- import { cloneSettingsForExport } from './Settings/sanitizeSettings.js';
7
7
  import { determineTextDocumentSettings } from './textValidation/determineTextDocumentSettings.js';
8
8
  import { DocumentValidator } from './textValidation/index.js';
9
9
  import { isError } from './util/errors.js';
10
- import { memoizeLastCall } from './util/memoizeLastCall.js';
11
10
  import { toUri } from './util/Uri.js';
12
11
  /**
13
12
  * Spell Check a file
@@ -75,10 +74,6 @@ export async function spellCheckDocument(document, options, settingsOrConfigFile
75
74
  };
76
75
  }
77
76
  }
78
- const memoizedCloneSettingsForExport = memoizeLastCall(cloneSettingsForExport);
79
- function sanitizeSettingsForExport(settings) {
80
- return settings ? memoizedCloneSettingsForExport(settings) : {};
81
- }
82
77
  /**
83
78
  * Spell Check a Document.
84
79
  * @param document - document to be checked. If `document.text` is `undefined` the file will be loaded
@@ -86,8 +81,26 @@ function sanitizeSettingsForExport(settings) {
86
81
  * @param settings - default settings to use.
87
82
  */
88
83
  export async function spellCheckDocumentRPC(document, options, settingsOrConfigFile) {
89
- const result = { ...(await spellCheckDocument(document, options, settingsOrConfigFile)) };
90
- result.settingsUsed = sanitizeSettingsForExport(result.settingsUsed);
84
+ const { issues, checked, errors, configErrors, dictionaryErrors, perf } = await spellCheckDocument(document, options, settingsOrConfigFile);
85
+ const result = {
86
+ document: { uri: document.uri },
87
+ checked,
88
+ };
89
+ if (issues.length) {
90
+ result.issues = issues.map(toValidationIssueRPC);
91
+ }
92
+ if (errors?.length) {
93
+ result.errors = errors;
94
+ }
95
+ if (configErrors?.length) {
96
+ result.configErrors = configErrors;
97
+ }
98
+ if (dictionaryErrors?.size) {
99
+ result.dictionaryErrors = dictionaryErrors;
100
+ }
101
+ if (perf && options.measurePerf) {
102
+ result.perf = perf;
103
+ }
91
104
  return result;
92
105
  }
93
106
  async function spellCheckFullDocument(document, options, settingsOrConfigFile) {
@@ -3,16 +3,13 @@ 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 { ImportFileRefWithError } from '../Settings/index.js';
7
- import type { CSpellSettingsInternal, CSpellSettingsInternalFinalized } from '../Settings/index.js';
6
+ import type { CSpellSettingsInternal, CSpellSettingsInternalFinalized, ImportFileRefWithError } from '../Settings/index.js';
8
7
  import type { SpellingDictionaryCollection } from '../SpellingDictionary/index.js';
9
8
  import type { WordSuggestion } from '../suggestions.js';
10
- import type { MatchRange } from '../util/TextRange.js';
11
- import type { TextValidator } from './lineValidatorFactory.js';
12
- import type { SimpleRange } from './parsedText.js';
9
+ import type { MatchRange, SimpleRange, SubstitutionTransformer } from '../Transform/index.js';
10
+ import type { TextValidationFactoryOptions, TextValidator } from './lineValidatorFactory.js';
13
11
  import type { TraceResult } from './traceWord.js';
14
12
  import type { ValidateTextOptions } from './ValidateTextOptions.js';
15
- import type { ValidationOptions } from './ValidationTypes.js';
16
13
  export interface DocumentValidatorOptions extends ValidateTextOptions {
17
14
  /**
18
15
  * Optional path to a configuration file.
@@ -129,9 +126,10 @@ interface Preparations {
129
126
  textValidator: TextValidator;
130
127
  segmenter: (texts: MappedText) => Iterable<MappedText>;
131
128
  shouldCheck: boolean;
132
- validateOptions: ValidationOptions;
129
+ validateOptions: TextValidationFactoryOptions;
133
130
  localConfig: CSpellUserSettings | undefined;
134
131
  localConfigFilepath: string | undefined;
132
+ subTransformer: SubstitutionTransformer;
135
133
  }
136
134
  interface ShouldCheckDocumentResult {
137
135
  /** possible errors found while loading configuration. */
@@ -10,6 +10,7 @@ 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 { createMappedTextSegmenter, createSubstitutionTransformer } from '../Transform/index.js';
13
14
  import { catchPromiseError, toError } from '../util/errors.js';
14
15
  import { AutoCache } from '../util/simpleCache.js';
15
16
  import { uriToFilePath } from '../util/Uri.js';
@@ -17,7 +18,6 @@ import { cleanValidationIssue } from './cleanValidationIssue.js';
17
18
  import { defaultMaxDuplicateProblems, defaultMaxNumberOfProblems } from './defaultConstants.js';
18
19
  import { determineTextDocumentSettings } from './determineTextDocumentSettings.js';
19
20
  import { textValidatorFactory } from './lineValidatorFactory.js';
20
- import { createMappedTextSegmenter } from './parsedText.js';
21
21
  import { settingsToValidateOptions } from './settingsToValidateOptions.js';
22
22
  import { calcTextInclusionRanges } from './textValidator.js';
23
23
  import { traceWord } from './traceWord.js';
@@ -101,7 +101,11 @@ export class DocumentValidator {
101
101
  recShouldCheckTime();
102
102
  const recFinalizeTime = recordPerfTime(this.perfTiming, '_finalizeSettings');
103
103
  const finalSettings = finalizeSettings(docSettings);
104
- const validateOptions = settingsToValidateOptions(finalSettings);
104
+ const sub = createSubstitutionTransformer(finalSettings);
105
+ if (sub.missing) {
106
+ this.addPossibleError(`Missing substitutions: ${sub.missing.join(', ')}`);
107
+ }
108
+ const validateOptions = { ...settingsToValidateOptions(finalSettings), transformer: sub.transformer };
105
109
  const includeRanges = calcTextInclusionRanges(this._document.text, validateOptions);
106
110
  const segmenter = createMappedTextSegmenter(includeRanges);
107
111
  const textValidator = textValidatorFactory(dict, validateOptions);
@@ -118,6 +122,7 @@ export class DocumentValidator {
118
122
  textValidator,
119
123
  localConfig,
120
124
  localConfigFilepath: localConfig?.__importRef?.filename,
125
+ subTransformer: sub.transformer,
121
126
  };
122
127
  this._ready = true;
123
128
  this._preparationTime = timer.elapsed;
@@ -133,7 +138,11 @@ export class DocumentValidator {
133
138
  const stopMeasure = measurePerf('DocumentValidator._updatePrep');
134
139
  const shouldCheck = docSettings.enabled ?? true;
135
140
  const finalSettings = finalizeSettings(docSettings);
136
- const validateOptions = settingsToValidateOptions(finalSettings);
141
+ const sub = createSubstitutionTransformer(finalSettings);
142
+ if (sub.missing) {
143
+ this.addPossibleError(`Missing substitutions: ${sub.missing.join(', ')}`);
144
+ }
145
+ const validateOptions = { ...settingsToValidateOptions(finalSettings), transformer: sub.transformer };
137
146
  const includeRanges = calcTextInclusionRanges(this._document.text, validateOptions);
138
147
  const segmenter = createMappedTextSegmenter(includeRanges);
139
148
  const textValidator = textValidatorFactory(dict, validateOptions);
@@ -322,7 +331,7 @@ export class DocumentValidator {
322
331
  addPossibleError(error) {
323
332
  if (!error)
324
333
  return;
325
- error = this.errors.push(toError(error));
334
+ this.errors.push(toError(error));
326
335
  }
327
336
  _parse() {
328
337
  assert(this._preparations, ERROR_NOT_PREPARED);
@@ -434,7 +443,7 @@ export async function shouldCheckDocument(doc, options, settings) {
434
443
  function addPossibleError(error) {
435
444
  if (!error)
436
445
  return undefined;
437
- error = errors.push(toError(error));
446
+ errors.push(toError(error));
438
447
  return undefined;
439
448
  }
440
449
  async function shouldCheck() {
@@ -1,10 +1,10 @@
1
1
  export type { ValidationIssue } from '../Models/ValidationIssue.js';
2
2
  export type { ValidationResult } from '../Models/ValidationResult.js';
3
+ export type { Offset, SimpleRange } from '../Transform/index.js';
3
4
  export type { CheckTextInfo, TextInfoItem } from './checkText.js';
4
5
  export { checkText, checkTextDocument, IncludeExcludeFlag } from './checkText.js';
5
6
  export type { DocumentValidatorOptions } from './docValidator.js';
6
7
  export { DocumentValidator, shouldCheckDocument } from './docValidator.js';
7
- export type { Offset, SimpleRange } from './parsedText.js';
8
8
  export { calcTextInclusionRanges } from './textValidator.js';
9
9
  export type { ValidateTextOptions } from './ValidateTextOptions.js';
10
10
  export type { CheckOptions, IncludeExcludeOptions, ValidationOptions } from './ValidationTypes.js';
@@ -1,4 +1,5 @@
1
1
  import type { CachingDictionary, SpellingDictionary } from 'cspell-dictionary';
2
+ import type { SubstitutionTransformer } from '../Transform/index.js';
2
3
  import type { LineValidatorFn, TextValidatorFn, ValidationOptions } from './ValidationTypes.js';
3
4
  interface LineValidator {
4
5
  fn: LineValidatorFn;
@@ -9,6 +10,9 @@ export interface TextValidator {
9
10
  validate: TextValidatorFn;
10
11
  lineValidator: LineValidator;
11
12
  }
12
- export declare function textValidatorFactory(dict: SpellingDictionary, options: ValidationOptions): TextValidator;
13
+ export interface TextValidationFactoryOptions extends ValidationOptions {
14
+ transformer: SubstitutionTransformer | undefined;
15
+ }
16
+ export declare function textValidatorFactory(dict: SpellingDictionary, options: TextValidationFactoryOptions): TextValidator;
13
17
  export {};
14
18
  //# sourceMappingURL=lineValidatorFactory.d.ts.map
@@ -3,6 +3,7 @@ import { opConcatMap, opFilter, pipe } from '@cspell/cspell-pipe/sync';
3
3
  import { defaultCSpellSettings, unknownWordsChoices } from '@cspell/cspell-types';
4
4
  import { createCachingDictionary } from 'cspell-dictionary';
5
5
  import * as RxPat from '../Settings/RegExpPatterns.js';
6
+ import { mapRangeBackToOriginalPos } from '../Transform/index.js';
6
7
  import { autoResolve } from '../util/AutoResolve.js';
7
8
  import { extractPossibleWordsFromTextOffset, extractText, extractWordsFromTextOffset, splitWordWithOffset, } from '../util/text.js';
8
9
  import { regExpCamelCaseWordBreaksWithEnglishSuffix } from '../util/textRegex.js';
@@ -10,7 +11,6 @@ import { split } from '../util/wordSplitter.js';
10
11
  import { defaultMinWordLength } from './defaultConstants.js';
11
12
  import { extractHexSequences, isRandomString } from './isRandomString.js';
12
13
  import { isWordValidWithEscapeRetry } from './isWordValid.js';
13
- import { mapRangeBackToOriginalPos } from './parsedText.js';
14
14
  const MIN_HEX_SEQUENCE_LENGTH = 8;
15
15
  export function lineValidatorFactory(sDict, options) {
16
16
  const { minWordLength = defaultMinWordLength, flagWords = [], allowCompoundWords = false, ignoreCase = true, ignoreRandomStrings = defaultCSpellSettings.ignoreRandomStrings, minRandomLength = defaultCSpellSettings.minRandomLength, unknownWords = unknownWordsChoices.ReportAll, numSuggestions, } = options;
@@ -355,8 +355,10 @@ export function lineValidatorFactory(sDict, options) {
355
355
  export function textValidatorFactory(dict, options) {
356
356
  const lineValidator = lineValidatorFactory(dict, options);
357
357
  const lineValidatorFn = lineValidator.fn;
358
+ const transformer = options.transformer;
358
359
  function validate(pText) {
359
- const { text, range: srcRange, map } = pText;
360
+ const transformedText = transformer?.transform(pText) || pText;
361
+ const { text, range: srcRange, map } = transformedText;
360
362
  const srcOffset = srcRange[0];
361
363
  const segment = { text, offset: 0 };
362
364
  const lineSegment = { line: segment, segment };
@@ -379,7 +381,7 @@ function filterExcludedTextOffsets(issues, excluded) {
379
381
  const keep = [];
380
382
  let i = 0;
381
383
  let j = 0;
382
- for (i = 0; i < issues.length && j < excluded.length; i++) {
384
+ for (; i < issues.length && j < excluded.length; i++) {
383
385
  const issue = issues[i];
384
386
  while (j < excluded.length && excluded[j].offset + excluded[j].text.length <= issue.offset) {
385
387
  j++;
@@ -1,9 +1,18 @@
1
1
  export function settingsToValidateOptions(settings) {
2
2
  const opt = {
3
- ...settings,
3
+ allowCompoundWords: settings.allowCompoundWords,
4
+ flagWords: settings.flagWords,
4
5
  ignoreCase: !(settings.caseSensitive ?? false),
5
6
  ignoreRandomStrings: settings.ignoreRandomStrings,
7
+ ignoreRegExpList: settings.ignoreRegExpList,
8
+ includeRegExpList: settings.includeRegExpList,
9
+ maxDuplicateProblems: settings.maxDuplicateProblems,
10
+ maxNumberOfProblems: settings.maxNumberOfProblems,
6
11
  minRandomLength: settings.minRandomLength,
12
+ minWordLength: settings.minWordLength,
13
+ numSuggestions: settings.numSuggestions,
14
+ suggestionNumChanges: settings.suggestionNumChanges,
15
+ suggestionsTimeout: settings.suggestionsTimeout,
7
16
  unknownWords: settings.unknownWords || 'report-all',
8
17
  };
9
18
  return opt;
@@ -1,6 +1,6 @@
1
1
  import type { SpellingDictionary } from 'cspell-dictionary';
2
2
  import type { ValidationResult } from '../Models/ValidationResult.js';
3
- import * as TextRange from '../util/TextRange.js';
3
+ import * as TextRange from '../Transform/index.js';
4
4
  import type { IncludeExcludeOptions, LineSegment, ValidationOptions } from './ValidationTypes.js';
5
5
  /**
6
6
  * @deprecated
@@ -1,6 +1,6 @@
1
1
  import { opConcatMap, opFilter, opTake, pipe } from '@cspell/cspell-pipe/sync';
2
+ import * as TextRange from '../Transform/index.js';
2
3
  import * as Text from '../util/text.js';
3
- import * as TextRange from '../util/TextRange.js';
4
4
  import { defaultMaxDuplicateProblems, defaultMaxNumberOfProblems } from './defaultConstants.js';
5
5
  import { lineValidatorFactory } from './lineValidatorFactory.js';
6
6
  /**
@@ -1,3 +1,3 @@
1
- import { type TextEncoding } from 'cspell-io';
1
+ import type { TextEncoding } from 'cspell-io';
2
2
  export declare function readLines(url: URL | string, encoding?: TextEncoding): Promise<IterableIterator<string>>;
3
3
  //# sourceMappingURL=fileReader.d.ts.map
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "access": "public",
5
5
  "provenance": true
6
6
  },
7
- "version": "9.6.4",
7
+ "version": "9.8.0",
8
8
  "description": "A library of useful functions used across various cspell tools.",
9
9
  "type": "module",
10
10
  "sideEffects": false,
@@ -46,7 +46,6 @@
46
46
  "coverage": "vitest run --coverage --pool=forks",
47
47
  "test-watch": "vitest",
48
48
  "prepublishOnly": "pnpm run clean-build",
49
- "#test": "vitest run --reporter=hanging-process --reporter=default",
50
49
  "test": "vitest run --pool=forks",
51
50
  "test:update-snapshot": "vitest run -u",
52
51
  "test:perf": "NODE_ENV=production insight --file \"**/*.perf.{mjs,js}\"",
@@ -76,23 +75,23 @@
76
75
  },
77
76
  "homepage": "https://github.com/streetsidesoftware/cspell/tree/main/packages/cspell-lib#readme",
78
77
  "dependencies": {
79
- "@cspell/cspell-bundled-dicts": "9.6.4",
80
- "@cspell/cspell-performance-monitor": "9.6.4",
81
- "@cspell/cspell-pipe": "9.6.4",
82
- "@cspell/cspell-resolver": "9.6.4",
83
- "@cspell/cspell-types": "9.6.4",
84
- "@cspell/dynamic-import": "9.6.4",
85
- "@cspell/filetypes": "9.6.4",
86
- "@cspell/rpc": "9.6.4",
87
- "@cspell/strong-weak-map": "9.6.4",
88
- "@cspell/url": "9.6.4",
78
+ "@cspell/cspell-bundled-dicts": "9.8.0",
79
+ "@cspell/cspell-performance-monitor": "9.8.0",
80
+ "@cspell/cspell-pipe": "9.8.0",
81
+ "@cspell/cspell-resolver": "9.8.0",
82
+ "@cspell/cspell-types": "9.8.0",
83
+ "@cspell/dynamic-import": "9.8.0",
84
+ "@cspell/filetypes": "9.8.0",
85
+ "@cspell/rpc": "9.8.0",
86
+ "@cspell/strong-weak-map": "9.8.0",
87
+ "@cspell/url": "9.8.0",
89
88
  "clear-module": "^4.1.2",
90
- "cspell-config-lib": "9.6.4",
91
- "cspell-dictionary": "9.6.4",
92
- "cspell-glob": "9.6.4",
93
- "cspell-grammar": "9.6.4",
94
- "cspell-io": "9.6.4",
95
- "cspell-trie-lib": "9.6.4",
89
+ "cspell-config-lib": "9.8.0",
90
+ "cspell-dictionary": "9.8.0",
91
+ "cspell-glob": "9.8.0",
92
+ "cspell-grammar": "9.8.0",
93
+ "cspell-io": "9.8.0",
94
+ "cspell-trie-lib": "9.8.0",
96
95
  "env-paths": "^4.0.0",
97
96
  "gensequence": "^8.0.8",
98
97
  "import-fresh": "^3.3.1",
@@ -105,23 +104,24 @@
105
104
  "node": ">=20"
106
105
  },
107
106
  "devDependencies": {
108
- "@cspell/cspell-tools": "9.6.4",
107
+ "@cspell/cspell-tools": "9.8.0",
109
108
  "@cspell/dict-cpp": "^7.0.2",
110
109
  "@cspell/dict-csharp": "^4.0.8",
111
- "@cspell/dict-css": "^4.0.19",
112
- "@cspell/dict-en_us": "^4.4.28",
110
+ "@cspell/dict-css": "^4.1.1",
111
+ "@cspell/dict-en_us": "^4.4.33",
113
112
  "@cspell/dict-fa-ir": "^4.0.5",
114
113
  "@cspell/dict-fr-fr": "^2.3.2",
115
- "@cspell/dict-html": "^4.0.14",
114
+ "@cspell/dict-html": "^4.0.15",
116
115
  "@cspell/dict-nl-nl": "^2.4.2",
117
- "@cspell/dict-python": "^4.2.25",
116
+ "@cspell/dict-python": "^4.2.26",
117
+ "@cspell/dictionary-bundler-plugin": "",
118
118
  "@types/configstore": "^6.0.2",
119
- "comment-json": "^4.5.1",
120
- "configstore": "^7.1.0",
119
+ "comment-json": "^4.6.2",
120
+ "configstore": "^8.0.0",
121
121
  "cspell-dict-nl-nl": "^1.1.2",
122
122
  "leaked-handles": "^5.2.0",
123
123
  "lorem-ipsum": "^2.0.8",
124
124
  "perf-insight": "^2.0.1"
125
125
  },
126
- "gitHead": "e126c7f5708d4258ada35ba1d29d18952d7f0886"
126
+ "gitHead": "c822013ce676dffb5fa5544567c25a3ae666718f"
127
127
  }
@@ -1,15 +0,0 @@
1
- import type { MappedText } from '@cspell/cspell-types';
2
- import type { Range } from '@cspell/cspell-types/Parser';
3
- /**
4
- * Extract a substring from a TextMap.
5
- * @param textMap - A text range with an optional map
6
- * @param extractRange - The range in the original document to extract
7
- * @returns The TextMap covering extractRange
8
- */
9
- export declare function extractTextMapRangeOrigin(textMap: MappedText, extractRange: Range): MappedText;
10
- interface WithRange {
11
- readonly range: Range;
12
- }
13
- export declare function doesIntersect(textMap: WithRange, rangeOrigin: Range): boolean;
14
- export {};
15
- //# sourceMappingURL=TextMap.d.ts.map