cspell-lib 8.2.4 → 8.3.1
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/esm/Settings/Controller/configLoader/configLoader.d.ts +9 -0
- package/dist/esm/Settings/Controller/configLoader/configLoader.js +36 -5
- package/dist/esm/Settings/Controller/configLoader/configSearch.d.ts +8 -1
- package/dist/esm/Settings/Controller/configLoader/configSearch.js +20 -3
- package/dist/esm/Settings/DefaultSettings.js +1 -1
- package/dist/esm/Settings/constants.d.ts +1 -0
- package/dist/esm/Settings/constants.js +1 -0
- package/dist/esm/SpellingDictionary/Dictionaries.d.ts +11 -0
- package/dist/esm/SpellingDictionary/Dictionaries.js +17 -6
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/textValidation/ValidationTypes.d.ts +1 -0
- package/dist/esm/textValidation/docValidator.d.ts +1 -10
- package/dist/esm/textValidation/docValidator.js +2 -23
- package/dist/esm/textValidation/lineValidatorFactory.js +1 -1
- package/dist/esm/textValidation/traceWord.d.ts +27 -0
- package/dist/esm/textValidation/traceWord.js +106 -0
- package/dist/esm/trace.d.ts +5 -1
- package/dist/esm/trace.js +16 -21
- package/package.json +14 -14
|
@@ -49,6 +49,7 @@ export interface IConfigLoader {
|
|
|
49
49
|
* @returns the resulting settings
|
|
50
50
|
*/
|
|
51
51
|
searchForConfig(searchFrom: URL | string | undefined, pnpSettings?: PnPSettingsOptional): Promise<CSpellSettingsI | undefined>;
|
|
52
|
+
resolveConfigFileLocation(filenameOrURL: string | URL, relativeTo?: string | URL): Promise<URL | undefined>;
|
|
52
53
|
getGlobalSettingsAsync(): Promise<CSpellSettingsI>;
|
|
53
54
|
/**
|
|
54
55
|
* The loader caches configuration files for performance. This method clears the cache.
|
|
@@ -71,12 +72,15 @@ export interface IConfigLoader {
|
|
|
71
72
|
*/
|
|
72
73
|
dispose(): void;
|
|
73
74
|
getStats(): Readonly<Record<string, Readonly<Record<string, number>>>>;
|
|
75
|
+
readonly isTrusted: boolean;
|
|
76
|
+
setIsTrusted(isTrusted: boolean): void;
|
|
74
77
|
}
|
|
75
78
|
export declare class ConfigLoader implements IConfigLoader {
|
|
76
79
|
readonly fs: VFileSystem;
|
|
77
80
|
readonly templateVariables: Record<string, string>;
|
|
78
81
|
onReady: Promise<void>;
|
|
79
82
|
readonly fileResolver: FileResolver;
|
|
83
|
+
private _isTrusted;
|
|
80
84
|
/**
|
|
81
85
|
* Use `createConfigLoader`
|
|
82
86
|
* @param virtualFs - virtual file system to use.
|
|
@@ -107,7 +111,9 @@ export declare class ConfigLoader implements IConfigLoader {
|
|
|
107
111
|
getGlobalSettings(): CSpellSettingsI;
|
|
108
112
|
getGlobalSettingsAsync(): Promise<CSpellSettingsI>;
|
|
109
113
|
clearCachedSettingsFiles(): void;
|
|
114
|
+
protected init(): Promise<void>;
|
|
110
115
|
protected prefetchGlobalSettingsAsync(): Promise<void>;
|
|
116
|
+
protected resolveDefaultConfig(): Promise<URL>;
|
|
111
117
|
protected importSettings(fileRef: ImportFileRef, pnpSettings: PnPSettingsOptional | undefined, backReferences: string[]): ImportedConfigEntry;
|
|
112
118
|
private setupPnp;
|
|
113
119
|
mergeConfigFileWithImports(cfgFile: CSpellConfigFile, pnpSettings: PnPSettingsOptional | undefined, referencedBy?: string[] | undefined): Promise<CSpellSettingsI>;
|
|
@@ -124,7 +130,10 @@ export declare class ConfigLoader implements IConfigLoader {
|
|
|
124
130
|
cacheMergeListUnique: Readonly<import("../../../util/AutoResolve.js").CacheStats>;
|
|
125
131
|
cacheMergeLists: Readonly<import("../../../util/AutoResolve.js").CacheStats>;
|
|
126
132
|
};
|
|
133
|
+
resolveConfigFileLocation(filenameOrURL: string | URL, relativeTo: string | URL): Promise<URL | undefined>;
|
|
127
134
|
private resolveFilename;
|
|
135
|
+
get isTrusted(): boolean;
|
|
136
|
+
setIsTrusted(isTrusted: boolean): void;
|
|
128
137
|
}
|
|
129
138
|
declare class ConfigLoaderInternal extends ConfigLoader {
|
|
130
139
|
constructor(vfs: VFileSystem);
|
|
@@ -4,6 +4,7 @@ import { isUrlLike, toFileURL } from 'cspell-io';
|
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import { fileURLToPath, pathToFileURL } from 'url';
|
|
6
6
|
import { URI, Utils as UriUtils } from 'vscode-uri';
|
|
7
|
+
import { srcDirectory } from '../../../../lib-cjs/index.cjs';
|
|
7
8
|
import { onClearCache } from '../../../events/index.js';
|
|
8
9
|
import { getVirtualFS } from '../../../fileSystem.js';
|
|
9
10
|
import { createCSpellSettingsInternal as csi } from '../../../Models/CSpellSettingsInternalDef.js';
|
|
@@ -12,7 +13,7 @@ import { logError, logWarning } from '../../../util/logger.js';
|
|
|
12
13
|
import { FileResolver } from '../../../util/resolveFile.js';
|
|
13
14
|
import { envToTemplateVars } from '../../../util/templates.js';
|
|
14
15
|
import { addTrailingSlash, cwdURL, resolveFileWithURL, toFilePathOrHref, windowsDriveLetterToUpper, } from '../../../util/url.js';
|
|
15
|
-
import { configSettingsFileVersion0_1, configSettingsFileVersion0_2, currentSettingsFileVersion, ENV_CSPELL_GLOB_ROOT, } from '../../constants.js';
|
|
16
|
+
import { configSettingsFileVersion0_1, configSettingsFileVersion0_2, currentSettingsFileVersion, defaultConfigFileModuleRef, ENV_CSPELL_GLOB_ROOT, } from '../../constants.js';
|
|
16
17
|
import { getMergeStats, mergeSettings } from '../../CSpellSettingsServer.js';
|
|
17
18
|
import { getGlobalConfig } from '../../GlobalSettings.js';
|
|
18
19
|
import { ImportError } from '../ImportError.js';
|
|
@@ -28,11 +29,19 @@ const setOfSupportedConfigVersions = Object.freeze(new Set(supportedCSpellConfig
|
|
|
28
29
|
export const sectionCSpell = 'cSpell';
|
|
29
30
|
export const defaultFileName = 'cspell.json';
|
|
30
31
|
let defaultConfigLoader = undefined;
|
|
32
|
+
const defaultExtensions = ['.json', '.yaml', '.yml', '.jsonc'];
|
|
33
|
+
const defaultJsExtensions = ['.js', '.cjs', '.mjs'];
|
|
34
|
+
const trustedSearch = new Map([
|
|
35
|
+
['*', defaultExtensions],
|
|
36
|
+
['file:', [...defaultExtensions, ...defaultJsExtensions]],
|
|
37
|
+
]);
|
|
38
|
+
const unTrustedSearch = new Map([['*', defaultExtensions]]);
|
|
31
39
|
export class ConfigLoader {
|
|
32
40
|
fs;
|
|
33
41
|
templateVariables;
|
|
34
42
|
onReady;
|
|
35
43
|
fileResolver;
|
|
44
|
+
_isTrusted = true;
|
|
36
45
|
/**
|
|
37
46
|
* Use `createConfigLoader`
|
|
38
47
|
* @param virtualFs - virtual file system to use.
|
|
@@ -40,10 +49,10 @@ export class ConfigLoader {
|
|
|
40
49
|
constructor(fs, templateVariables = envToTemplateVars(process.env)) {
|
|
41
50
|
this.fs = fs;
|
|
42
51
|
this.templateVariables = templateVariables;
|
|
43
|
-
this.configSearch = new ConfigSearch(searchPlaces, fs);
|
|
52
|
+
this.configSearch = new ConfigSearch(searchPlaces, trustedSearch, fs);
|
|
44
53
|
this.cspellConfigFileReaderWriter = createReaderWriter(undefined, undefined, createIO(fs));
|
|
45
54
|
this.fileResolver = new FileResolver(fs, this.templateVariables);
|
|
46
|
-
this.onReady = this.
|
|
55
|
+
this.onReady = this.init();
|
|
47
56
|
this.subscribeToEvents();
|
|
48
57
|
}
|
|
49
58
|
subscribeToEvents() {
|
|
@@ -140,10 +149,19 @@ export class ConfigLoader {
|
|
|
140
149
|
this.cachedMergedConfig = new WeakMap();
|
|
141
150
|
this.prefetchGlobalSettingsAsync();
|
|
142
151
|
}
|
|
143
|
-
|
|
144
|
-
this.onReady = this.
|
|
152
|
+
init() {
|
|
153
|
+
this.onReady = Promise.all([this.prefetchGlobalSettingsAsync(), this.resolveDefaultConfig()]).then(() => undefined);
|
|
145
154
|
return this.onReady;
|
|
146
155
|
}
|
|
156
|
+
async prefetchGlobalSettingsAsync() {
|
|
157
|
+
await this.getGlobalSettingsAsync().catch((e) => logError(e));
|
|
158
|
+
}
|
|
159
|
+
async resolveDefaultConfig() {
|
|
160
|
+
const r = await this.fileResolver.resolveFile(defaultConfigFileModuleRef, srcDirectory);
|
|
161
|
+
const url = toFileURL(r.filename);
|
|
162
|
+
this.cspellConfigFileReaderWriter.setTrustedUrls([new URL('../..', url)]);
|
|
163
|
+
return url;
|
|
164
|
+
}
|
|
147
165
|
importSettings(fileRef, pnpSettings, backReferences) {
|
|
148
166
|
const url = toFileURL(fileRef.filename);
|
|
149
167
|
const cacheKey = url.href;
|
|
@@ -318,6 +336,10 @@ export class ConfigLoader {
|
|
|
318
336
|
getStats() {
|
|
319
337
|
return { ...getMergeStats() };
|
|
320
338
|
}
|
|
339
|
+
async resolveConfigFileLocation(filenameOrURL, relativeTo) {
|
|
340
|
+
const r = await this.fileResolver.resolveFile(filenameOrURL, relativeTo);
|
|
341
|
+
return r.found ? toFileURL(r.filename) : undefined;
|
|
342
|
+
}
|
|
321
343
|
async resolveFilename(filename, relativeTo) {
|
|
322
344
|
if (filename instanceof URL)
|
|
323
345
|
return { filename: toFilePathOrHref(filename) };
|
|
@@ -332,6 +354,15 @@ export class ConfigLoader {
|
|
|
332
354
|
error: r.found ? undefined : new Error(`Failed to resolve file: "${filename}"`),
|
|
333
355
|
};
|
|
334
356
|
}
|
|
357
|
+
get isTrusted() {
|
|
358
|
+
return this._isTrusted;
|
|
359
|
+
}
|
|
360
|
+
setIsTrusted(isTrusted) {
|
|
361
|
+
this._isTrusted = isTrusted;
|
|
362
|
+
this.clearCachedSettingsFiles();
|
|
363
|
+
this.configSearch = new ConfigSearch(searchPlaces, isTrusted ? trustedSearch : unTrustedSearch, this.fs);
|
|
364
|
+
this.cspellConfigFileReaderWriter.setUntrustedExtensions(isTrusted ? [] : defaultJsExtensions);
|
|
365
|
+
}
|
|
335
366
|
}
|
|
336
367
|
class ConfigLoaderInternal extends ConfigLoader {
|
|
337
368
|
constructor(vfs) {
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import type { VFileSystem } from '../../../fileSystem.js';
|
|
2
2
|
export declare class ConfigSearch {
|
|
3
3
|
readonly searchPlaces: readonly string[];
|
|
4
|
+
readonly allowedExtensionsByProtocol: Map<string, readonly string[]>;
|
|
4
5
|
private fs;
|
|
5
6
|
private searchCache;
|
|
6
7
|
private searchDirCache;
|
|
7
|
-
|
|
8
|
+
private searchPlacesByProtocol;
|
|
9
|
+
/**
|
|
10
|
+
* @param searchPlaces - The list of file names to search for.
|
|
11
|
+
* @param allowedExtensionsByProtocol - Map of allowed extensions by protocol, '*' is used to match all protocols.
|
|
12
|
+
* @param fs - The file system to use.
|
|
13
|
+
*/
|
|
14
|
+
constructor(searchPlaces: readonly string[], allowedExtensionsByProtocol: Map<string, readonly string[]>, fs: VFileSystem);
|
|
8
15
|
searchForConfig(searchFromURL: URL): Promise<URL | undefined>;
|
|
9
16
|
clearCache(): void;
|
|
10
17
|
private findUpConfigPath;
|
|
@@ -1,15 +1,25 @@
|
|
|
1
|
+
import { extname } from 'node:path/posix';
|
|
1
2
|
import { urlBasename } from 'cspell-io';
|
|
2
3
|
import { createAutoResolveCache } from '../../../util/AutoResolve.js';
|
|
3
4
|
import { findUpFromUrl } from '../../../util/findUpFromUrl.js';
|
|
4
5
|
export class ConfigSearch {
|
|
5
6
|
searchPlaces;
|
|
7
|
+
allowedExtensionsByProtocol;
|
|
6
8
|
fs;
|
|
7
9
|
searchCache = new Map();
|
|
8
10
|
searchDirCache = new Map();
|
|
9
|
-
|
|
11
|
+
searchPlacesByProtocol;
|
|
12
|
+
/**
|
|
13
|
+
* @param searchPlaces - The list of file names to search for.
|
|
14
|
+
* @param allowedExtensionsByProtocol - Map of allowed extensions by protocol, '*' is used to match all protocols.
|
|
15
|
+
* @param fs - The file system to use.
|
|
16
|
+
*/
|
|
17
|
+
constructor(searchPlaces, allowedExtensionsByProtocol, fs) {
|
|
10
18
|
this.searchPlaces = searchPlaces;
|
|
19
|
+
this.allowedExtensionsByProtocol = allowedExtensionsByProtocol;
|
|
11
20
|
this.fs = fs;
|
|
12
|
-
this.
|
|
21
|
+
this.searchPlacesByProtocol = setupSearchPlacesByProtocol(searchPlaces, allowedExtensionsByProtocol);
|
|
22
|
+
this.searchPlaces = this.searchPlacesByProtocol.get('*') || searchPlaces;
|
|
13
23
|
}
|
|
14
24
|
searchForConfig(searchFromURL) {
|
|
15
25
|
const dirUrl = new URL('.', searchFromURL);
|
|
@@ -105,7 +115,8 @@ export class ConfigSearch {
|
|
|
105
115
|
const hasFile = this.fs.getCapabilities(dir).readDirectory
|
|
106
116
|
? this.createHasFileDirSearch()
|
|
107
117
|
: this.createHasFileStatCheck();
|
|
108
|
-
|
|
118
|
+
const searchPlaces = this.searchPlacesByProtocol.get(dir.protocol) || this.searchPlaces;
|
|
119
|
+
for (const searchPlace of searchPlaces) {
|
|
109
120
|
const file = new URL(searchPlace, dir);
|
|
110
121
|
const found = await hasFile(file);
|
|
111
122
|
if (found) {
|
|
@@ -118,6 +129,12 @@ export class ConfigSearch {
|
|
|
118
129
|
return undefined;
|
|
119
130
|
}
|
|
120
131
|
}
|
|
132
|
+
function setupSearchPlacesByProtocol(searchPlaces, allowedExtensionsByProtocol) {
|
|
133
|
+
const map = new Map([...allowedExtensionsByProtocol.entries()]
|
|
134
|
+
.map(([k, v]) => [k, new Set(v)])
|
|
135
|
+
.map(([protocol, exts]) => [protocol, searchPlaces.filter((url) => exts.has(extname(url)))]));
|
|
136
|
+
return map;
|
|
137
|
+
}
|
|
121
138
|
async function checkPackageJson(fs, filename) {
|
|
122
139
|
try {
|
|
123
140
|
const file = await fs.readFile(filename);
|
|
@@ -3,11 +3,11 @@ import { srcDirectory } from '../../lib-cjs/index.cjs';
|
|
|
3
3
|
import { createCSpellSettingsInternal } from '../Models/CSpellSettingsInternalDef.js';
|
|
4
4
|
import { PatternRegExp } from '../Models/PatternRegExp.js';
|
|
5
5
|
import { resolveFile } from '../util/resolveFile.js';
|
|
6
|
+
import { defaultConfigFileModuleRef } from './constants.js';
|
|
6
7
|
import { readSettings } from './Controller/configLoader/index.js';
|
|
7
8
|
import { mergeSettings } from './CSpellSettingsServer.js';
|
|
8
9
|
import * as LanguageSettings from './LanguageSettings.js';
|
|
9
10
|
import * as RegPat from './RegExpPatterns.js';
|
|
10
|
-
const defaultConfigFileModuleRef = '@cspell/cspell-bundled-dicts/cspell-default.json';
|
|
11
11
|
// Do not use require.resolve because webpack will mess it up.
|
|
12
12
|
const defaultConfigFile = () => resolveConfigModule(defaultConfigFileModuleRef);
|
|
13
13
|
const regExpSpellCheckerDisable = [
|
|
@@ -2,4 +2,5 @@ export declare const configSettingsFileVersion0_1 = "0.1";
|
|
|
2
2
|
export declare const configSettingsFileVersion0_2 = "0.2";
|
|
3
3
|
export declare const currentSettingsFileVersion = "0.2";
|
|
4
4
|
export declare const ENV_CSPELL_GLOB_ROOT = "CSPELL_GLOB_ROOT";
|
|
5
|
+
export declare const defaultConfigFileModuleRef = "@cspell/cspell-bundled-dicts/cspell-default.json";
|
|
5
6
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -2,4 +2,5 @@ export const configSettingsFileVersion0_1 = '0.1';
|
|
|
2
2
|
export const configSettingsFileVersion0_2 = '0.2';
|
|
3
3
|
export const currentSettingsFileVersion = configSettingsFileVersion0_2;
|
|
4
4
|
export const ENV_CSPELL_GLOB_ROOT = 'CSPELL_GLOB_ROOT';
|
|
5
|
+
export const defaultConfigFileModuleRef = '@cspell/cspell-bundled-dicts/cspell-default.json';
|
|
5
6
|
//# sourceMappingURL=constants.js.map
|
|
@@ -1,6 +1,17 @@
|
|
|
1
|
+
import type { CSpellSettings } from '@cspell/cspell-types';
|
|
1
2
|
import type { SpellingDictionary, SpellingDictionaryCollection } from 'cspell-dictionary';
|
|
2
3
|
import type { CSpellSettingsInternal, DictionaryDefinitionInternal } from '../Models/CSpellSettingsInternalDef.js';
|
|
3
4
|
export declare function loadDictionaryDefs(defsToLoad: DictionaryDefinitionInternal[]): Promise<SpellingDictionary>[];
|
|
4
5
|
export declare function refreshDictionaryCache(maxAge?: number): Promise<void>;
|
|
5
6
|
export declare function getDictionaryInternal(settings: CSpellSettingsInternal): Promise<SpellingDictionaryCollection>;
|
|
7
|
+
export declare const specialDictionaryNames: {
|
|
8
|
+
readonly words: "[words]";
|
|
9
|
+
readonly userWords: "[userWords]";
|
|
10
|
+
readonly flagWords: "[flagWords]";
|
|
11
|
+
readonly ignoreWords: "[ignoreWords]";
|
|
12
|
+
readonly suggestWords: "[suggestWords]";
|
|
13
|
+
};
|
|
14
|
+
export type DictionaryNameFields = keyof typeof specialDictionaryNames;
|
|
15
|
+
export declare const mapSpecialDictionaryNamesToSettings: Map<string, DictionaryNameFields>;
|
|
16
|
+
export declare function getInlineConfigDictionaries(settings: CSpellSettings): SpellingDictionary[];
|
|
6
17
|
//# sourceMappingURL=Dictionaries.d.ts.map
|
|
@@ -13,29 +13,40 @@ export async function getDictionaryInternal(settings) {
|
|
|
13
13
|
const spellDictionaries = await Promise.all(loadDictionaryDefs(calcDictionaryDefsToLoad(settings)));
|
|
14
14
|
return _getDictionaryInternal(settings, spellDictionaries);
|
|
15
15
|
}
|
|
16
|
-
|
|
16
|
+
export const specialDictionaryNames = {
|
|
17
|
+
words: '[words]',
|
|
18
|
+
userWords: '[userWords]',
|
|
19
|
+
flagWords: '[flagWords]',
|
|
20
|
+
ignoreWords: '[ignoreWords]',
|
|
21
|
+
suggestWords: '[suggestWords]',
|
|
22
|
+
};
|
|
23
|
+
export const mapSpecialDictionaryNamesToSettings = new Map(Object.entries(specialDictionaryNames).map(([k, v]) => [v, k]));
|
|
24
|
+
export function getInlineConfigDictionaries(settings) {
|
|
17
25
|
const { words = emptyWords, userWords = emptyWords, flagWords = emptyWords, ignoreWords = emptyWords, suggestWords = emptyWords, } = settings;
|
|
18
|
-
const settingsWordsDictionary = createSpellingDictionary(words,
|
|
26
|
+
const settingsWordsDictionary = createSpellingDictionary(words, specialDictionaryNames.words, 'From Settings `words`', {
|
|
19
27
|
caseSensitive: true,
|
|
20
28
|
weightMap: undefined,
|
|
21
29
|
});
|
|
22
30
|
const settingsUserWordsDictionary = userWords.length
|
|
23
|
-
? createSpellingDictionary(userWords,
|
|
31
|
+
? createSpellingDictionary(userWords, specialDictionaryNames.userWords, 'From Settings `userWords`', {
|
|
24
32
|
caseSensitive: true,
|
|
25
33
|
weightMap: undefined,
|
|
26
34
|
})
|
|
27
35
|
: undefined;
|
|
28
|
-
const ignoreWordsDictionary = createIgnoreWordsDictionary(ignoreWords,
|
|
29
|
-
const flagWordsDictionary = createForbiddenWordsDictionary(flagWords,
|
|
36
|
+
const ignoreWordsDictionary = createIgnoreWordsDictionary(ignoreWords, specialDictionaryNames.ignoreWords, 'From Settings `ignoreWords`');
|
|
37
|
+
const flagWordsDictionary = createForbiddenWordsDictionary(flagWords, specialDictionaryNames.flagWords, 'From Settings `flagWords`');
|
|
30
38
|
const suggestWordsDictionary = createSuggestDictionary(suggestWords, '[suggestWords]', 'From Settings `suggestWords`');
|
|
31
39
|
const dictionaries = [
|
|
32
|
-
...spellDictionaries,
|
|
33
40
|
settingsWordsDictionary,
|
|
34
41
|
settingsUserWordsDictionary,
|
|
35
42
|
ignoreWordsDictionary,
|
|
36
43
|
flagWordsDictionary,
|
|
37
44
|
suggestWordsDictionary,
|
|
38
45
|
].filter(isDefined);
|
|
46
|
+
return dictionaries;
|
|
47
|
+
}
|
|
48
|
+
function _getDictionaryInternal(settings, spellDictionaries) {
|
|
49
|
+
const dictionaries = [...spellDictionaries, ...getInlineConfigDictionaries(settings)];
|
|
39
50
|
return createCollection(dictionaries, 'dictionary collection');
|
|
40
51
|
}
|
|
41
52
|
//# sourceMappingURL=Dictionaries.js.map
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export { CompoundWordsMethod, createSpellingDictionary, createCollection as crea
|
|
|
16
16
|
export type { SuggestedWord, SuggestionOptions, SuggestionsForWordResult } from './suggestions.js';
|
|
17
17
|
export { SuggestionError, suggestionsForWord, suggestionsForWords } from './suggestions.js';
|
|
18
18
|
export { DocumentValidator, DocumentValidatorOptions, shouldCheckDocument } from './textValidation/index.js';
|
|
19
|
-
export type { TraceOptions, TraceResult } from './trace.js';
|
|
19
|
+
export type { TraceOptions, TraceResult, TraceWordResult } from './trace.js';
|
|
20
20
|
export { traceWords, traceWordsAsync } from './trace.js';
|
|
21
21
|
export { getLogger, Logger, setLogger } from './util/logger.js';
|
|
22
22
|
export { resolveFile } from './util/resolveFile.js';
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { MappedText, TextOffset as TextOffsetRW } from '@cspell/cspell-types';
|
|
2
2
|
import type { ExtendedSuggestion } from '../Models/Suggestion.js';
|
|
3
3
|
import type { ValidationIssue } from '../Models/ValidationIssue.js';
|
|
4
|
+
export type { TextOffset as TextOffsetRW } from '@cspell/cspell-types';
|
|
4
5
|
export type TextOffsetRO = Readonly<TextOffsetRW>;
|
|
5
6
|
export interface ValidationOptions extends IncludeExcludeOptions {
|
|
6
7
|
maxNumberOfProblems?: number;
|
|
@@ -77,16 +77,7 @@ export declare class DocumentValidator {
|
|
|
77
77
|
* @returns MatchRanges of text to include.
|
|
78
78
|
*/
|
|
79
79
|
getCheckedTextRanges(): MatchRange[];
|
|
80
|
-
traceWord(word: string):
|
|
81
|
-
word: string;
|
|
82
|
-
found: boolean;
|
|
83
|
-
foundWord: string | undefined;
|
|
84
|
-
forbidden: boolean;
|
|
85
|
-
noSuggest: boolean;
|
|
86
|
-
dictName: string;
|
|
87
|
-
dictSource: string;
|
|
88
|
-
errors: Error[] | undefined;
|
|
89
|
-
}[];
|
|
80
|
+
traceWord(word: string): import("./traceWord.js").TraceResult;
|
|
90
81
|
private defaultParser;
|
|
91
82
|
private _checkParsedText;
|
|
92
83
|
private addPossibleError;
|
|
@@ -11,13 +11,13 @@ import { calcSuggestionAdjustedToToMatchCase } from '../suggestions.js';
|
|
|
11
11
|
import { catchPromiseError, toError } from '../util/errors.js';
|
|
12
12
|
import { AutoCache } from '../util/simpleCache.js';
|
|
13
13
|
import { uriToFilePath } from '../util/Uri.js';
|
|
14
|
-
import { toFilePathOrHref } from '../util/url.js';
|
|
15
14
|
import { defaultMaxDuplicateProblems, defaultMaxNumberOfProblems } from './defaultConstants.js';
|
|
16
15
|
import { determineTextDocumentSettings } from './determineTextDocumentSettings.js';
|
|
17
16
|
import { textValidatorFactory } from './lineValidatorFactory.js';
|
|
18
17
|
import { createMappedTextSegmenter } from './parsedText.js';
|
|
19
18
|
import { settingsToValidateOptions } from './settingsToValidateOptions.js';
|
|
20
19
|
import { calcTextInclusionRanges } from './textValidator.js';
|
|
20
|
+
import { traceWord } from './traceWord.js';
|
|
21
21
|
const ERROR_NOT_PREPARED = 'Validator Must be prepared before calling this function.';
|
|
22
22
|
export class DocumentValidator {
|
|
23
23
|
settings;
|
|
@@ -248,25 +248,7 @@ export class DocumentValidator {
|
|
|
248
248
|
}
|
|
249
249
|
traceWord(word) {
|
|
250
250
|
assert(this._preparations, ERROR_NOT_PREPARED);
|
|
251
|
-
|
|
252
|
-
const config = this._preparations.config;
|
|
253
|
-
const opts = {
|
|
254
|
-
ignoreCase: true,
|
|
255
|
-
allowCompoundWords: config.allowCompoundWords || false,
|
|
256
|
-
};
|
|
257
|
-
const trace = dictCollection.dictionaries
|
|
258
|
-
.map((dict) => ({ dict, findResult: dict.find(word, opts) }))
|
|
259
|
-
.map(({ dict, findResult }) => ({
|
|
260
|
-
word,
|
|
261
|
-
found: !!findResult?.found,
|
|
262
|
-
foundWord: findResult?.found || undefined,
|
|
263
|
-
forbidden: findResult?.forbidden || false,
|
|
264
|
-
noSuggest: findResult?.noSuggest || false,
|
|
265
|
-
dictName: dict.name,
|
|
266
|
-
dictSource: toFilePathOrHref(dict.source),
|
|
267
|
-
errors: normalizeErrors(dict.getErrors?.()),
|
|
268
|
-
}));
|
|
269
|
-
return trace;
|
|
251
|
+
return traceWord(word, this._preparations.dictionary, this._preparations.config);
|
|
270
252
|
}
|
|
271
253
|
defaultParser() {
|
|
272
254
|
return pipeSync(this.document.getLines(), opMap((line) => {
|
|
@@ -409,7 +391,4 @@ function recordPerfTime(timings, name) {
|
|
|
409
391
|
function timePromise(timings, name, p) {
|
|
410
392
|
return p.finally(recordPerfTime(timings, name));
|
|
411
393
|
}
|
|
412
|
-
function normalizeErrors(errors) {
|
|
413
|
-
return errors?.length ? errors : undefined;
|
|
414
|
-
}
|
|
415
394
|
//# sourceMappingURL=docValidator.js.map
|
|
@@ -88,7 +88,7 @@ export function lineValidatorFactory(sDict, options) {
|
|
|
88
88
|
};
|
|
89
89
|
return [vr];
|
|
90
90
|
}
|
|
91
|
-
const mismatches = toArray(pipe(Text.extractWordsFromTextOffset(possibleWord), opFilter(filterAlreadyChecked), opMap((wo) => (
|
|
91
|
+
const mismatches = toArray(pipe(Text.extractWordsFromTextOffset(possibleWord), opFilter((wo) => filterAlreadyChecked(wo)), opMap((wo) => ((wo.line = lineSegment.line), wo)), opMap(annotateIsFlagged), opFilter(rememberFilter((wo) => wo.text.length >= minWordLength || !!wo.isFlagged)), opConcatMap(checkFullWord)));
|
|
92
92
|
if (mismatches.length) {
|
|
93
93
|
// Try the more expensive word splitter
|
|
94
94
|
const splitResult = split(lineSegment.segment, possibleWord.offset, splitterIsValid);
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { CSpellSettingsWithSourceTrace } from '@cspell/cspell-types';
|
|
2
|
+
import type { SpellingDictionaryCollection } from '../SpellingDictionary/index.js';
|
|
3
|
+
type Href = string;
|
|
4
|
+
export interface DictionaryTraceResult {
|
|
5
|
+
word: string;
|
|
6
|
+
found: boolean;
|
|
7
|
+
foundWord: string | undefined;
|
|
8
|
+
forbidden: boolean;
|
|
9
|
+
noSuggest: boolean;
|
|
10
|
+
dictName: string;
|
|
11
|
+
dictSource: string;
|
|
12
|
+
configSource: Href | undefined;
|
|
13
|
+
errors: Error[] | undefined;
|
|
14
|
+
}
|
|
15
|
+
export interface WordSplits {
|
|
16
|
+
word: string;
|
|
17
|
+
found: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface TraceResult extends Array<DictionaryTraceResult> {
|
|
20
|
+
splits?: readonly WordSplits[];
|
|
21
|
+
}
|
|
22
|
+
export interface TraceOptions extends Pick<CSpellSettingsWithSourceTrace, 'source' | 'allowCompoundWords'> {
|
|
23
|
+
ignoreCase?: boolean;
|
|
24
|
+
}
|
|
25
|
+
export declare function traceWord(word: string, dictCollection: SpellingDictionaryCollection, config: TraceOptions): TraceResult;
|
|
26
|
+
export {};
|
|
27
|
+
//# sourceMappingURL=traceWord.d.ts.map
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { getSources } from '../Settings/index.js';
|
|
2
|
+
import { createCollection, getInlineConfigDictionaries, mapSpecialDictionaryNamesToSettings, } from '../SpellingDictionary/index.js';
|
|
3
|
+
import { toFileUrl } from '../util/url.js';
|
|
4
|
+
import { uniqueFn } from '../util/util.js';
|
|
5
|
+
import { split } from '../util/wordSplitter.js';
|
|
6
|
+
export function traceWord(word, dictCollection, config) {
|
|
7
|
+
const opts = {
|
|
8
|
+
ignoreCase: true,
|
|
9
|
+
useCompounds: config.allowCompoundWords || false,
|
|
10
|
+
};
|
|
11
|
+
const splits = split({ text: word, offset: 0 }, 0, checkWord);
|
|
12
|
+
const wfSplits = splits.words.map((s) => ({ word: s.text, found: s.isFound }));
|
|
13
|
+
const unique = uniqueFn((w) => w.word + '|' + w.found);
|
|
14
|
+
const wsFound = { word, found: dictCollection.has(word, opts) };
|
|
15
|
+
const wordSplits = wfSplits.find((s) => s.word === word) ? wfSplits : [wsFound, ...wfSplits];
|
|
16
|
+
const traces = wordSplits
|
|
17
|
+
.filter(unique)
|
|
18
|
+
.map((s) => s.word)
|
|
19
|
+
.flatMap((word) => dictCollection.dictionaries.map((dict) => ({ dict, word })))
|
|
20
|
+
.map(({ dict, word }) => ({ dict, findResult: dict.find(word, opts), word }))
|
|
21
|
+
.flatMap((r) => unpackDictionaryFindResult(r, config));
|
|
22
|
+
const r = new CTraceResult(...traces);
|
|
23
|
+
r.splits = wordSplits;
|
|
24
|
+
return r;
|
|
25
|
+
function checkWord(wo) {
|
|
26
|
+
return dictCollection.has(wo.text, opts);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Map FindInDictResult to DictionaryTraceResult
|
|
31
|
+
* If the word was found in a dictionary based upon a config field setting, then find the source config.
|
|
32
|
+
* @param found - a word found in a dictionary
|
|
33
|
+
* @param config - the trace config
|
|
34
|
+
* @returns DictionaryTraceResult[]
|
|
35
|
+
*/
|
|
36
|
+
function unpackDictionaryFindResult(found, config) {
|
|
37
|
+
const { word, dict, findResult } = found;
|
|
38
|
+
const baseResult = {
|
|
39
|
+
word,
|
|
40
|
+
found: !!findResult?.found,
|
|
41
|
+
foundWord: findResult?.found || undefined,
|
|
42
|
+
forbidden: findResult?.forbidden || false,
|
|
43
|
+
noSuggest: findResult?.noSuggest || false,
|
|
44
|
+
dictName: dict.name,
|
|
45
|
+
dictSource: dict.source,
|
|
46
|
+
configSource: undefined,
|
|
47
|
+
errors: normalizeErrors(dict.getErrors?.()),
|
|
48
|
+
};
|
|
49
|
+
const configFieldName = mapSpecialDictionaryNamesToSettings.get(dict.name);
|
|
50
|
+
if (!findResult?.found || !configFieldName || !config.source) {
|
|
51
|
+
return [baseResult];
|
|
52
|
+
}
|
|
53
|
+
const opts = {
|
|
54
|
+
ignoreCase: true,
|
|
55
|
+
useCompounds: config.allowCompoundWords || false,
|
|
56
|
+
};
|
|
57
|
+
const sources = getSources(config);
|
|
58
|
+
const results = [];
|
|
59
|
+
for (const src of sources) {
|
|
60
|
+
if (!src[configFieldName] ||
|
|
61
|
+
!Array.isArray(src[configFieldName]) ||
|
|
62
|
+
!src[configFieldName]?.length ||
|
|
63
|
+
!src.source?.filename) {
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// We found a possible config, build a dictionary result for it.
|
|
67
|
+
const configSource = toFileUrl(src.source.filename).href;
|
|
68
|
+
const cfg = { [configFieldName]: src[configFieldName] };
|
|
69
|
+
const cfgDict = createCollection(getInlineConfigDictionaries(cfg), dict.name, configSource);
|
|
70
|
+
const findResult = cfgDict.find(word, opts);
|
|
71
|
+
if (!findResult?.found)
|
|
72
|
+
continue;
|
|
73
|
+
const result = {
|
|
74
|
+
word,
|
|
75
|
+
found: !!findResult?.found,
|
|
76
|
+
foundWord: findResult?.found || undefined,
|
|
77
|
+
forbidden: findResult?.forbidden || false,
|
|
78
|
+
noSuggest: findResult?.noSuggest || false,
|
|
79
|
+
dictName: dict.name,
|
|
80
|
+
dictSource: configSource,
|
|
81
|
+
configSource,
|
|
82
|
+
errors: normalizeErrors(dict.getErrors?.()),
|
|
83
|
+
};
|
|
84
|
+
results.push(result);
|
|
85
|
+
// console.log('unpackDictFindResult %o', {
|
|
86
|
+
// id: src.id,
|
|
87
|
+
// name: src.name,
|
|
88
|
+
// filename: src.source?.filename,
|
|
89
|
+
// configFieldName,
|
|
90
|
+
// findResult,
|
|
91
|
+
// cfg,
|
|
92
|
+
// result,
|
|
93
|
+
// });
|
|
94
|
+
}
|
|
95
|
+
return results.length ? results : [baseResult];
|
|
96
|
+
}
|
|
97
|
+
function normalizeErrors(errors) {
|
|
98
|
+
return errors?.length ? errors : undefined;
|
|
99
|
+
}
|
|
100
|
+
class CTraceResult extends Array {
|
|
101
|
+
splits = [];
|
|
102
|
+
constructor(...items) {
|
|
103
|
+
super(...items);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
//# sourceMappingURL=traceWord.js.map
|
package/dist/esm/trace.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { CSpellSettings, LocaleId } from '@cspell/cspell-types';
|
|
2
2
|
import type { LanguageId } from './LanguageIds.js';
|
|
3
|
+
import type { WordSplits } from './textValidation/traceWord.js';
|
|
3
4
|
export interface TraceResult {
|
|
4
5
|
word: string;
|
|
5
6
|
found: boolean;
|
|
@@ -18,6 +19,9 @@ export interface TraceOptions {
|
|
|
18
19
|
ignoreCase?: boolean;
|
|
19
20
|
allowCompoundWords?: boolean;
|
|
20
21
|
}
|
|
22
|
+
export interface TraceWordResult extends Array<TraceResult> {
|
|
23
|
+
splits: readonly WordSplits[];
|
|
24
|
+
}
|
|
21
25
|
export declare function traceWords(words: string[], settings: CSpellSettings, options: TraceOptions | undefined): Promise<TraceResult[]>;
|
|
22
|
-
export declare function traceWordsAsync(words: Iterable<string> | AsyncIterable<string>, settings: CSpellSettings, options: TraceOptions | undefined): AsyncIterableIterator<
|
|
26
|
+
export declare function traceWordsAsync(words: Iterable<string> | AsyncIterable<string>, settings: CSpellSettings, options: TraceOptions | undefined): AsyncIterableIterator<TraceWordResult>;
|
|
23
27
|
//# sourceMappingURL=trace.d.ts.map
|
package/dist/esm/trace.js
CHANGED
|
@@ -3,6 +3,7 @@ import { toInternalSettings } from './Settings/CSpellSettingsServer.js';
|
|
|
3
3
|
import { finalizeSettings, mergeSettings } from './Settings/index.js';
|
|
4
4
|
import { calcSettingsForLanguageId } from './Settings/LanguageSettings.js';
|
|
5
5
|
import { getDictionaryInternal, refreshDictionaryCache } from './SpellingDictionary/index.js';
|
|
6
|
+
import { traceWord } from './textValidation/traceWord.js';
|
|
6
7
|
import { toFilePathOrHref } from './util/url.js';
|
|
7
8
|
import * as util from './util/util.js';
|
|
8
9
|
export async function traceWords(words, settings, options) {
|
|
@@ -37,33 +38,27 @@ export async function* traceWordsAsync(words, settings, options) {
|
|
|
37
38
|
await refreshDictionaryCache();
|
|
38
39
|
const { config, dicts, activeDictionaries } = await finalize(settings);
|
|
39
40
|
const setOfActiveDicts = new Set(activeDictionaries);
|
|
40
|
-
const opts = util.clean({ ignoreCase, useCompounds: config.allowCompoundWords });
|
|
41
|
-
function normalizeErrors(errors) {
|
|
42
|
-
if (!errors?.length)
|
|
43
|
-
return undefined;
|
|
44
|
-
return errors;
|
|
45
|
-
}
|
|
46
41
|
function processWord(word) {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
noSuggest: findResult?.noSuggest || false,
|
|
55
|
-
dictName: dict.name,
|
|
56
|
-
dictSource: dictSourceToFilename(dict.source),
|
|
57
|
-
dictActive: setOfActiveDicts.has(dict.name),
|
|
58
|
-
configSource: config.name || '',
|
|
59
|
-
errors: normalizeErrors(dict.getErrors?.()),
|
|
42
|
+
const results = traceWord(word, dicts, { ...config, ignoreCase });
|
|
43
|
+
const r = results.map((r) => ({
|
|
44
|
+
...r,
|
|
45
|
+
dictActive: setOfActiveDicts.has(r.dictName),
|
|
46
|
+
dictSource: toFilePathOrHref(r.dictSource),
|
|
47
|
+
configSource: r.configSource || config.name || '',
|
|
48
|
+
splits: results.splits,
|
|
60
49
|
}));
|
|
50
|
+
const tr = new CTraceResult(...r);
|
|
51
|
+
results.splits && tr.splits.push(...results.splits);
|
|
52
|
+
return tr;
|
|
61
53
|
}
|
|
62
54
|
for await (const word of words) {
|
|
63
55
|
yield processWord(word);
|
|
64
56
|
}
|
|
65
57
|
}
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
class CTraceResult extends Array {
|
|
59
|
+
splits = [];
|
|
60
|
+
constructor(...items) {
|
|
61
|
+
super(...items);
|
|
62
|
+
}
|
|
68
63
|
}
|
|
69
64
|
//# sourceMappingURL=trace.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cspell-lib",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.3.1",
|
|
4
4
|
"description": "A library of useful functions used across various cspell tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -57,21 +57,21 @@
|
|
|
57
57
|
},
|
|
58
58
|
"homepage": "https://github.com/streetsidesoftware/cspell#readme",
|
|
59
59
|
"dependencies": {
|
|
60
|
-
"@cspell/cspell-bundled-dicts": "8.
|
|
61
|
-
"@cspell/cspell-pipe": "8.
|
|
62
|
-
"@cspell/cspell-resolver": "8.
|
|
63
|
-
"@cspell/cspell-types": "8.
|
|
64
|
-
"@cspell/dynamic-import": "8.
|
|
65
|
-
"@cspell/strong-weak-map": "8.
|
|
60
|
+
"@cspell/cspell-bundled-dicts": "8.3.1",
|
|
61
|
+
"@cspell/cspell-pipe": "8.3.1",
|
|
62
|
+
"@cspell/cspell-resolver": "8.3.1",
|
|
63
|
+
"@cspell/cspell-types": "8.3.1",
|
|
64
|
+
"@cspell/dynamic-import": "8.3.1",
|
|
65
|
+
"@cspell/strong-weak-map": "8.3.1",
|
|
66
66
|
"clear-module": "^4.1.2",
|
|
67
67
|
"comment-json": "^4.2.3",
|
|
68
68
|
"configstore": "^6.0.0",
|
|
69
|
-
"cspell-config-lib": "8.
|
|
70
|
-
"cspell-dictionary": "8.
|
|
71
|
-
"cspell-glob": "8.
|
|
72
|
-
"cspell-grammar": "8.
|
|
73
|
-
"cspell-io": "8.
|
|
74
|
-
"cspell-trie-lib": "8.
|
|
69
|
+
"cspell-config-lib": "8.3.1",
|
|
70
|
+
"cspell-dictionary": "8.3.1",
|
|
71
|
+
"cspell-glob": "8.3.1",
|
|
72
|
+
"cspell-grammar": "8.3.1",
|
|
73
|
+
"cspell-io": "8.3.1",
|
|
74
|
+
"cspell-trie-lib": "8.3.1",
|
|
75
75
|
"fast-equals": "^5.0.1",
|
|
76
76
|
"gensequence": "^6.0.0",
|
|
77
77
|
"import-fresh": "^3.3.0",
|
|
@@ -95,5 +95,5 @@
|
|
|
95
95
|
"cspell-dict-nl-nl": "^1.1.2",
|
|
96
96
|
"lorem-ipsum": "^2.0.8"
|
|
97
97
|
},
|
|
98
|
-
"gitHead": "
|
|
98
|
+
"gitHead": "7136c39fd5f47c2acd44bec0bede924e55e1a107"
|
|
99
99
|
}
|