cspell-lib 9.0.1 → 9.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/Models/CSpellSettingsInternalDef.d.ts +7 -2
- package/dist/lib/Models/CSpellSettingsInternalDef.js +3 -0
- package/dist/lib/Models/ValidationResult.d.ts +1 -1
- package/dist/lib/Settings/Controller/configLoader/configLoader.d.ts +14 -6
- package/dist/lib/Settings/Controller/configLoader/configLoader.js +38 -15
- package/dist/lib/Settings/Controller/configLoader/configSearch.d.ts +1 -1
- package/dist/lib/Settings/Controller/configLoader/configSearch.js +8 -5
- package/dist/lib/Settings/Controller/configLoader/defaultConfigLoader.d.ts +4 -3
- package/dist/lib/Settings/Controller/configLoader/defaultConfigLoader.js +3 -4
- package/dist/lib/Settings/Controller/configLoader/normalizeRawSettings.d.ts +1 -0
- package/dist/lib/Settings/DictionarySettings.js +2 -1
- package/dist/lib/SpellingDictionary/DictionaryController/DictionaryLoader.d.ts +1 -0
- package/dist/lib/SpellingDictionary/DictionaryController/DictionaryLoader.js +14 -8
- package/dist/lib/spellCheckFile.d.ts +1 -1
- package/dist/lib/textValidation/ValidationTypes.d.ts +3 -6
- package/dist/lib/textValidation/docValidator.js +12 -2
- package/dist/lib/textValidation/lineValidatorFactory.js +35 -12
- package/dist/lib/textValidation/settingsToValidateOptions.js +1 -0
- package/dist/lib/util/findUpFromUrl.d.ts +1 -1
- package/package.json +16 -16
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AdvancedCSpellSettingsWithSourceTrace, CSpellSettingsWithSourceTrace, DictionaryDefinition, DictionaryDefinitionAugmented, DictionaryDefinitionCustom, DictionaryDefinitionInline, DictionaryDefinitionPreferred, Parser } from '@cspell/cspell-types';
|
|
1
|
+
import type { AdvancedCSpellSettingsWithSourceTrace, CSpellSettingsWithSourceTrace, DictionaryDefinition, DictionaryDefinitionAugmented, DictionaryDefinitionCustom, DictionaryDefinitionInline, DictionaryDefinitionPreferred, DictionaryDefinitionSimple, Parser } from '@cspell/cspell-types';
|
|
2
2
|
import type { WeightMap } from 'cspell-trie-lib';
|
|
3
3
|
import type { OptionalOrUndefined } from '../util/types.js';
|
|
4
4
|
export declare const SymbolCSpellSettingsInternal: unique symbol;
|
|
@@ -13,11 +13,15 @@ export interface CSpellSettingsInternalFinalized extends CSpellSettingsInternal
|
|
|
13
13
|
includeRegExpList: RegExp[];
|
|
14
14
|
}
|
|
15
15
|
type DictionaryDefinitionCustomUniqueFields = Omit<DictionaryDefinitionCustom, keyof DictionaryDefinitionPreferred>;
|
|
16
|
-
export type DictionaryDefinitionInternal = DictionaryFileDefinitionInternal | DictionaryDefinitionInlineInternal;
|
|
16
|
+
export type DictionaryDefinitionInternal = DictionaryFileDefinitionInternal | DictionaryDefinitionInlineInternal | DictionaryDefinitionSimpleInternal;
|
|
17
17
|
export type DictionaryDefinitionInlineInternal = DictionaryDefinitionInline & {
|
|
18
18
|
/** The path to the config file that contains this dictionary definition */
|
|
19
19
|
readonly __source?: string | undefined;
|
|
20
20
|
};
|
|
21
|
+
export type DictionaryDefinitionSimpleInternal = DictionaryDefinitionSimple & {
|
|
22
|
+
/** The path to the config file that contains this dictionary definition */
|
|
23
|
+
readonly __source?: string | undefined;
|
|
24
|
+
};
|
|
21
25
|
export interface DictionaryFileDefinitionInternal extends Readonly<DictionaryDefinitionPreferred>, Readonly<Partial<DictionaryDefinitionCustomUniqueFields>>, Readonly<DictionaryDefinitionAugmented> {
|
|
22
26
|
/**
|
|
23
27
|
* Optional weight map used to improve suggestions.
|
|
@@ -36,5 +40,6 @@ export declare function cleanCSpellSettingsInternal(parts?: OptionalOrUndefined<
|
|
|
36
40
|
export declare function createCSpellSettingsInternal(parts?: OptionalOrUndefined<Partial<CSpellSettingsInternal>>): CSpellSettingsInternal;
|
|
37
41
|
export declare function isCSpellSettingsInternal(cs: CSpellSettingsInternal | CSpellSettingsWithSourceTrace | OptionalOrUndefined<CSpellSettingsInternal | CSpellSettingsWithSourceTrace>): cs is CSpellSettingsInternal;
|
|
38
42
|
export declare function isDictionaryDefinitionInlineInternal(def: DictionaryDefinitionInternal | DictionaryDefinitionInline | DictionaryDefinition): def is DictionaryDefinitionInlineInternal;
|
|
43
|
+
export declare function isDictionaryFileDefinitionInternal(def: DictionaryDefinitionInternal | DictionaryDefinitionInline | DictionaryDefinition): def is DictionaryFileDefinitionInternal;
|
|
39
44
|
export {};
|
|
40
45
|
//# sourceMappingURL=CSpellSettingsInternalDef.d.ts.map
|
|
@@ -17,4 +17,7 @@ export function isDictionaryDefinitionInlineInternal(def) {
|
|
|
17
17
|
const defInline = def;
|
|
18
18
|
return !!(defInline.words || defInline.flagWords || defInline.ignoreWords || defInline.suggestWords);
|
|
19
19
|
}
|
|
20
|
+
export function isDictionaryFileDefinitionInternal(def) {
|
|
21
|
+
return !!(def.path || def.file);
|
|
22
|
+
}
|
|
20
23
|
//# sourceMappingURL=CSpellSettingsInternalDef.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Issue, TextOffset as TextOffsetRW } from '@cspell/cspell-types';
|
|
2
|
-
export interface ValidationResult extends TextOffsetRW, Pick<Issue, 'message' | 'issueType'> {
|
|
2
|
+
export interface ValidationResult extends TextOffsetRW, Pick<Issue, 'message' | 'issueType' | 'hasPreferredSuggestions' | 'hasSimpleSuggestions'> {
|
|
3
3
|
line: TextOffsetRW;
|
|
4
4
|
isFlagged?: boolean | undefined;
|
|
5
5
|
isFound?: boolean | undefined;
|
|
@@ -5,6 +5,7 @@ import { AutoResolveCache } from '../../../util/AutoResolve.js';
|
|
|
5
5
|
import { FileResolver } from '../../../util/resolveFile.js';
|
|
6
6
|
import type { LoaderResult } from '../pnpLoader.js';
|
|
7
7
|
import { ConfigSearch } from './configSearch.js';
|
|
8
|
+
import { StopSearchAt } from './defaultConfigLoader.js';
|
|
8
9
|
import { normalizeCacheSettings } from './normalizeRawSettings.js';
|
|
9
10
|
import type { PnPSettingsOptional } from './PnPSettings.js';
|
|
10
11
|
import type { CSpellSettingsI, CSpellSettingsWST } from './types.js';
|
|
@@ -27,6 +28,11 @@ interface ImportedConfigEntry {
|
|
|
27
28
|
/** Set of all references used to catch circular references */
|
|
28
29
|
referencedSet: Set<string>;
|
|
29
30
|
}
|
|
31
|
+
export interface SearchForConfigFileOptions {
|
|
32
|
+
stopSearchAt?: StopSearchAt;
|
|
33
|
+
}
|
|
34
|
+
export interface SearchForConfigOptions extends SearchForConfigFileOptions, PnPSettingsOptional {
|
|
35
|
+
}
|
|
30
36
|
interface CacheMergeConfigFileWithImports {
|
|
31
37
|
pnpSettings: PnPSettingsOptional | undefined;
|
|
32
38
|
referencedBy: string[] | undefined;
|
|
@@ -45,10 +51,10 @@ export interface IConfigLoader {
|
|
|
45
51
|
/**
|
|
46
52
|
* This is an alias for `searchForConfigFile` and `mergeConfigFileWithImports`.
|
|
47
53
|
* @param searchFrom the directory / file URL to start searching from.
|
|
48
|
-
* @param
|
|
54
|
+
* @param options - Optional settings including stop location and Yarn PnP configuration.
|
|
49
55
|
* @returns the resulting settings
|
|
50
56
|
*/
|
|
51
|
-
searchForConfig(searchFrom: URL | string | undefined,
|
|
57
|
+
searchForConfig(searchFrom: URL | string | undefined, options?: SearchForConfigOptions): Promise<CSpellSettingsI | undefined>;
|
|
52
58
|
resolveConfigFileLocation(filenameOrURL: string | URL, relativeTo?: string | URL): Promise<URL | undefined>;
|
|
53
59
|
getGlobalSettingsAsync(): Promise<CSpellSettingsI>;
|
|
54
60
|
/**
|
|
@@ -89,6 +95,7 @@ export interface IConfigLoader {
|
|
|
89
95
|
setIsTrusted(isTrusted: boolean): void;
|
|
90
96
|
}
|
|
91
97
|
export declare class ConfigLoader implements IConfigLoader {
|
|
98
|
+
#private;
|
|
92
99
|
readonly fs: VFileSystem;
|
|
93
100
|
readonly templateVariables: Record<string, string>;
|
|
94
101
|
onReady: Promise<void>;
|
|
@@ -108,20 +115,21 @@ export declare class ConfigLoader implements IConfigLoader {
|
|
|
108
115
|
protected globalSettings: CSpellSettingsI | undefined;
|
|
109
116
|
protected cspellConfigFileReaderWriter: CSpellConfigFileReaderWriter;
|
|
110
117
|
protected configSearch: ConfigSearch;
|
|
118
|
+
protected stopSearchAtCache: WeakMap<SearchForConfigFileOptions, URL[] | undefined>;
|
|
111
119
|
protected toDispose: {
|
|
112
120
|
dispose: () => void;
|
|
113
121
|
}[];
|
|
114
122
|
readSettingsAsync(filename: string | URL, relativeTo?: string | URL, pnpSettings?: PnPSettingsOptional): Promise<CSpellSettingsI>;
|
|
115
123
|
readConfigFile(filenameOrURL: string | URL, relativeTo?: string | URL): Promise<CSpellConfigFile | Error>;
|
|
116
|
-
searchForConfigFileLocation(searchFrom: URL | string | undefined): Promise<URL | undefined>;
|
|
117
|
-
searchForConfigFile(searchFrom: URL | string | undefined): Promise<CSpellConfigFile | undefined>;
|
|
124
|
+
searchForConfigFileLocation(searchFrom: URL | string | undefined, stopSearchAt?: URL[] | undefined): Promise<URL | undefined>;
|
|
125
|
+
searchForConfigFile(searchFrom: URL | string | undefined, stopSearchAt?: URL[]): Promise<CSpellConfigFile | undefined>;
|
|
118
126
|
/**
|
|
119
127
|
*
|
|
120
128
|
* @param searchFrom the directory / file URL to start searching from.
|
|
121
|
-
* @param
|
|
129
|
+
* @param options - Optional settings including stop location and Yarn PnP configuration.
|
|
122
130
|
* @returns the resulting settings
|
|
123
131
|
*/
|
|
124
|
-
searchForConfig(searchFrom: URL | string | undefined,
|
|
132
|
+
searchForConfig(searchFrom: URL | string | undefined, options?: SearchForConfigOptions): Promise<CSpellSettingsI | undefined>;
|
|
125
133
|
getGlobalSettings(): CSpellSettingsI;
|
|
126
134
|
getGlobalSettingsAsync(): Promise<CSpellSettingsI>;
|
|
127
135
|
clearCachedSettingsFiles(): void;
|
|
@@ -67,6 +67,7 @@ export class ConfigLoader {
|
|
|
67
67
|
globalSettings;
|
|
68
68
|
cspellConfigFileReaderWriter;
|
|
69
69
|
configSearch;
|
|
70
|
+
stopSearchAtCache = new WeakMap();
|
|
70
71
|
toDispose = [];
|
|
71
72
|
async readSettingsAsync(filename, relativeTo, pnpSettings) {
|
|
72
73
|
await this.onReady;
|
|
@@ -99,18 +100,12 @@ export class ConfigLoader {
|
|
|
99
100
|
}
|
|
100
101
|
});
|
|
101
102
|
}
|
|
102
|
-
async searchForConfigFileLocation(searchFrom) {
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
!isUrlLike(searchFrom) &&
|
|
106
|
-
url.protocol === 'file:' && // check to see if it is a directory
|
|
107
|
-
(await isDirectory(this.fs, url))) {
|
|
108
|
-
return this.configSearch.searchForConfig(addTrailingSlash(url));
|
|
109
|
-
}
|
|
110
|
-
return this.configSearch.searchForConfig(url);
|
|
103
|
+
async searchForConfigFileLocation(searchFrom, stopSearchAt) {
|
|
104
|
+
const searchFromURL = (await this.#normalizeDirURL(searchFrom)) || cwdURL();
|
|
105
|
+
return this.configSearch.searchForConfig(searchFromURL, stopSearchAt);
|
|
111
106
|
}
|
|
112
|
-
async searchForConfigFile(searchFrom) {
|
|
113
|
-
const location = await this.searchForConfigFileLocation(searchFrom);
|
|
107
|
+
async searchForConfigFile(searchFrom, stopSearchAt) {
|
|
108
|
+
const location = await this.searchForConfigFileLocation(searchFrom, stopSearchAt);
|
|
114
109
|
if (!location)
|
|
115
110
|
return undefined;
|
|
116
111
|
const file = await this.readConfigFile(location);
|
|
@@ -119,14 +114,15 @@ export class ConfigLoader {
|
|
|
119
114
|
/**
|
|
120
115
|
*
|
|
121
116
|
* @param searchFrom the directory / file URL to start searching from.
|
|
122
|
-
* @param
|
|
117
|
+
* @param options - Optional settings including stop location and Yarn PnP configuration.
|
|
123
118
|
* @returns the resulting settings
|
|
124
119
|
*/
|
|
125
|
-
async searchForConfig(searchFrom,
|
|
126
|
-
const
|
|
120
|
+
async searchForConfig(searchFrom, options) {
|
|
121
|
+
const stopAt = await this.#extractStopSearchAtURLs(options);
|
|
122
|
+
const configFile = await this.searchForConfigFile(searchFrom, stopAt);
|
|
127
123
|
if (!configFile)
|
|
128
124
|
return undefined;
|
|
129
|
-
return this.mergeConfigFileWithImports(configFile,
|
|
125
|
+
return this.mergeConfigFileWithImports(configFile, options);
|
|
130
126
|
}
|
|
131
127
|
getGlobalSettings() {
|
|
132
128
|
assert(this.globalSettings, 'Global settings not loaded');
|
|
@@ -386,6 +382,33 @@ export class ConfigLoader {
|
|
|
386
382
|
this.configSearch = new ConfigSearch(searchPlaces, isTrusted ? trustedSearch : unTrustedSearch, this.fs);
|
|
387
383
|
this.cspellConfigFileReaderWriter.setUntrustedExtensions(isTrusted ? [] : defaultJsExtensions);
|
|
388
384
|
}
|
|
385
|
+
async #extractStopSearchAtURLs(options) {
|
|
386
|
+
if (!options?.stopSearchAt)
|
|
387
|
+
return undefined;
|
|
388
|
+
if (this.stopSearchAtCache.has(options)) {
|
|
389
|
+
return this.stopSearchAtCache.get(options);
|
|
390
|
+
}
|
|
391
|
+
const rawStops = Array.isArray(options.stopSearchAt) ? options.stopSearchAt : [options.stopSearchAt];
|
|
392
|
+
const stopURLs = await Promise.all(rawStops.map((s) => this.#normalizeDirURL(s)));
|
|
393
|
+
this.stopSearchAtCache.set(options, stopURLs);
|
|
394
|
+
return stopURLs;
|
|
395
|
+
}
|
|
396
|
+
async #normalizeDirURL(input) {
|
|
397
|
+
if (!input)
|
|
398
|
+
return undefined;
|
|
399
|
+
const url = toFileURL(input, cwdURL());
|
|
400
|
+
if (url.pathname.endsWith('/'))
|
|
401
|
+
return url;
|
|
402
|
+
if (input instanceof URL)
|
|
403
|
+
return new URL('.', url);
|
|
404
|
+
if (typeof input === 'string' &&
|
|
405
|
+
!isUrlLike(input) &&
|
|
406
|
+
url.protocol === 'file:' &&
|
|
407
|
+
(await isDirectory(this.fs, url))) {
|
|
408
|
+
return addTrailingSlash(url);
|
|
409
|
+
}
|
|
410
|
+
return new URL('.', url);
|
|
411
|
+
}
|
|
389
412
|
}
|
|
390
413
|
class ConfigLoaderInternal extends ConfigLoader {
|
|
391
414
|
constructor(vfs) {
|
|
@@ -7,7 +7,7 @@ export declare class ConfigSearch {
|
|
|
7
7
|
* @param fs - The file system to use.
|
|
8
8
|
*/
|
|
9
9
|
constructor(searchPlaces: readonly string[], allowedExtensionsByProtocol: Map<string, readonly string[]>, fs: VFileSystem);
|
|
10
|
-
searchForConfig(searchFromURL: URL): Promise<URL | undefined>;
|
|
10
|
+
searchForConfig(searchFromURL: URL, stopSearchAtURL?: URL[]): Promise<URL | undefined>;
|
|
11
11
|
clearCache(): void;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
@@ -19,15 +19,18 @@ export class ConfigSearch {
|
|
|
19
19
|
constructor(searchPlaces, allowedExtensionsByProtocol, fs) {
|
|
20
20
|
this.#scanner = new DirConfigScanner(searchPlaces, allowedExtensionsByProtocol, fs);
|
|
21
21
|
}
|
|
22
|
-
searchForConfig(searchFromURL) {
|
|
23
|
-
const dirUrl = searchFromURL.pathname.endsWith('/') ? searchFromURL : new URL('
|
|
24
|
-
|
|
22
|
+
async searchForConfig(searchFromURL, stopSearchAtURL) {
|
|
23
|
+
const dirUrl = searchFromURL.pathname.endsWith('/') ? searchFromURL : new URL('./', searchFromURL);
|
|
24
|
+
const stopDirUrls = stopSearchAtURL
|
|
25
|
+
? stopSearchAtURL.map((url) => (url.pathname.endsWith('/') ? url : new URL('./', url)))
|
|
26
|
+
: undefined;
|
|
27
|
+
return this.#findUp(dirUrl, stopDirUrls);
|
|
25
28
|
}
|
|
26
29
|
clearCache() {
|
|
27
30
|
this.#searchCache.clear();
|
|
28
31
|
this.#scanner.clearCache();
|
|
29
32
|
}
|
|
30
|
-
#findUp(fromDir) {
|
|
33
|
+
#findUp(fromDir, stopDirUrls) {
|
|
31
34
|
const searchDirCache = this.#searchCache;
|
|
32
35
|
const cached = searchDirCache.get(fromDir.href);
|
|
33
36
|
if (cached) {
|
|
@@ -39,7 +42,7 @@ export class ConfigSearch {
|
|
|
39
42
|
visit(dir);
|
|
40
43
|
return this.#scanner.scanDirForConfigFile(dir);
|
|
41
44
|
};
|
|
42
|
-
result = findUpFromUrl(predicate, fromDir, { type: 'file' });
|
|
45
|
+
result = findUpFromUrl(predicate, fromDir, { type: 'file', ...(stopDirUrls && { stopAt: stopDirUrls }) });
|
|
43
46
|
searchDirCache.set(fromDir.href, result);
|
|
44
47
|
visited.forEach((dir) => searchDirCache.set(dir.href, result));
|
|
45
48
|
return result;
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import type { CSpellSettings } from '@cspell/cspell-types';
|
|
2
2
|
import type { CSpellConfigFile, ICSpellConfigFile } from 'cspell-config-lib';
|
|
3
|
-
import type { IConfigLoader } from './configLoader.js';
|
|
3
|
+
import type { IConfigLoader, SearchForConfigOptions } from './configLoader.js';
|
|
4
4
|
import type { PnPSettingsOptional } from './PnPSettings.js';
|
|
5
5
|
import type { CSpellSettingsI, CSpellSettingsWST } from './types.js';
|
|
6
6
|
export type { CSpellConfigFile, ICSpellConfigFile } from 'cspell-config-lib';
|
|
7
|
+
export type StopSearchAt = URL | string | (URL | string)[] | undefined;
|
|
7
8
|
/**
|
|
8
9
|
*
|
|
9
10
|
* @param searchFrom the directory / file to start searching from.
|
|
10
|
-
* @param
|
|
11
|
+
* @param options - Optional settings including stop location and Yarn PnP configuration.
|
|
11
12
|
* @returns the resulting settings
|
|
12
13
|
*/
|
|
13
|
-
export declare function searchForConfig(searchFrom: URL | string | undefined,
|
|
14
|
+
export declare function searchForConfig(searchFrom: URL | string | undefined, options?: SearchForConfigOptions): Promise<CSpellSettingsI | undefined>;
|
|
14
15
|
/**
|
|
15
16
|
* Load a CSpell configuration files.
|
|
16
17
|
* @param file - path or package reference to load.
|
|
@@ -2,16 +2,15 @@ import { toError } from '../../../util/errors.js';
|
|
|
2
2
|
import { toFileUrl } from '../../../util/url.js';
|
|
3
3
|
import { getDefaultConfigLoaderInternal } from './configLoader.js';
|
|
4
4
|
import { configErrorToRawSettings, configToRawSettings } from './configToRawSettings.js';
|
|
5
|
-
import { defaultPnPSettings } from './PnPSettings.js';
|
|
6
5
|
const gcl = getDefaultConfigLoaderInternal;
|
|
7
6
|
/**
|
|
8
7
|
*
|
|
9
8
|
* @param searchFrom the directory / file to start searching from.
|
|
10
|
-
* @param
|
|
9
|
+
* @param options - Optional settings including stop location and Yarn PnP configuration.
|
|
11
10
|
* @returns the resulting settings
|
|
12
11
|
*/
|
|
13
|
-
export function searchForConfig(searchFrom,
|
|
14
|
-
return gcl().searchForConfig(searchFrom,
|
|
12
|
+
export function searchForConfig(searchFrom, options) {
|
|
13
|
+
return gcl().searchForConfig(searchFrom, options);
|
|
15
14
|
}
|
|
16
15
|
/**
|
|
17
16
|
* Load a CSpell configuration files.
|
|
@@ -29,6 +29,7 @@ export declare function normalizeDictionaryDefs(settings: NormalizeDictionaryDef
|
|
|
29
29
|
ignoreWords?: string[];
|
|
30
30
|
suggestWords?: string[];
|
|
31
31
|
parser?: import("@cspell/cspell-types").ParserName;
|
|
32
|
+
unknownWords?: import("@cspell/cspell-types").UnknownWordsChoices | undefined;
|
|
32
33
|
}>[] | undefined;
|
|
33
34
|
}>;
|
|
34
35
|
type NormalizeOverrides = Pick<CSpellUserSettings, 'globRoot' | 'overrides'>;
|
|
@@ -103,7 +103,7 @@ class _DictionaryDefinitionInternalWithSource {
|
|
|
103
103
|
this.__source = sourceURL.href;
|
|
104
104
|
// this bit of assignment is to have the compiler help use if any new fields are added.
|
|
105
105
|
const defAll = def;
|
|
106
|
-
const { path: relPath = '', file = '', addWords, description, dictionaryInformation, type, repMap, noSuggest, ignoreForbiddenWords, scope, useCompounds, } = defAll;
|
|
106
|
+
const { path: relPath = '', file = '', addWords, description, dictionaryInformation, type, repMap, noSuggest, ignoreForbiddenWords, scope, supportNonStrictSearches, useCompounds, } = defAll;
|
|
107
107
|
const defaultPath = sourceURL;
|
|
108
108
|
const filePath = fixDicPath(relPath, file);
|
|
109
109
|
const name = determineName(filePath, def);
|
|
@@ -119,6 +119,7 @@ class _DictionaryDefinitionInternalWithSource {
|
|
|
119
119
|
repMap,
|
|
120
120
|
noSuggest,
|
|
121
121
|
ignoreForbiddenWords,
|
|
122
|
+
supportNonStrictSearches,
|
|
122
123
|
scope,
|
|
123
124
|
useCompounds,
|
|
124
125
|
};
|
|
@@ -2,7 +2,7 @@ import { opConcatMap, opFilter, opMap, pipe } from '@cspell/cspell-pipe/sync';
|
|
|
2
2
|
import { StrongWeakMap } from '@cspell/strong-weak-map';
|
|
3
3
|
import { createFailedToLoadDictionary, createInlineSpellingDictionary, createSpellingDictionary, createSpellingDictionaryFromTrieFile, } from 'cspell-dictionary';
|
|
4
4
|
import { compareStats, toFileURL, urlBasename } from 'cspell-io';
|
|
5
|
-
import { isDictionaryDefinitionInlineInternal } from '../../Models/CSpellSettingsInternalDef.js';
|
|
5
|
+
import { isDictionaryDefinitionInlineInternal, isDictionaryFileDefinitionInternal, } from '../../Models/CSpellSettingsInternalDef.js';
|
|
6
6
|
import { AutoResolveWeakCache, AutoResolveWeakWeakCache } from '../../util/AutoResolve.js';
|
|
7
7
|
import { toError } from '../../util/errors.js';
|
|
8
8
|
import { SimpleCache } from '../../util/simpleCache.js';
|
|
@@ -37,14 +37,17 @@ export class DictionaryLoader {
|
|
|
37
37
|
if (isDictionaryDefinitionInlineInternal(def)) {
|
|
38
38
|
return Promise.resolve(this.loadInlineDict(def));
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
if (isDictionaryFileDefinitionInternal(def)) {
|
|
41
|
+
const { key, entry } = this.getCacheEntry(def);
|
|
42
|
+
if (entry) {
|
|
43
|
+
return entry.pending.then(([dictionary]) => dictionary);
|
|
44
|
+
}
|
|
45
|
+
const loadedEntry = this.loadEntry(def.path, def);
|
|
46
|
+
this.setCacheEntry(key, loadedEntry, def);
|
|
47
|
+
this.keepAliveCache.set(def, loadedEntry);
|
|
48
|
+
return loadedEntry.pending.then(([dictionary]) => dictionary);
|
|
43
49
|
}
|
|
44
|
-
|
|
45
|
-
this.setCacheEntry(key, loadedEntry, def);
|
|
46
|
-
this.keepAliveCache.set(def, loadedEntry);
|
|
47
|
-
return loadedEntry.pending.then(([dictionary]) => dictionary);
|
|
50
|
+
return Promise.resolve(this.loadSimpleDict(def));
|
|
48
51
|
}
|
|
49
52
|
/**
|
|
50
53
|
* Check to see if any of the cached dictionaries have changed. If one has changed, reload it.
|
|
@@ -138,6 +141,9 @@ export class DictionaryLoader {
|
|
|
138
141
|
loadInlineDict(def) {
|
|
139
142
|
return this.inlineDictionaryCache.get(def, (def) => createInlineSpellingDictionary(def, def.__source || 'memory'));
|
|
140
143
|
}
|
|
144
|
+
loadSimpleDict(def) {
|
|
145
|
+
return createInlineSpellingDictionary({ name: def.name, words: [] }, def.__source || 'memory');
|
|
146
|
+
}
|
|
141
147
|
calcKey(def) {
|
|
142
148
|
const path = def.path;
|
|
143
149
|
const loaderType = determineType(toFileURL(path), def);
|
|
@@ -3,7 +3,7 @@ import { ICSpellConfigFile } from 'cspell-config-lib';
|
|
|
3
3
|
import type { Document, DocumentWithText } from './Document/index.js';
|
|
4
4
|
import type { Uri } from './util/IUri.js';
|
|
5
5
|
import type { ValidateTextOptions, ValidationIssue } from './validator.js';
|
|
6
|
-
export interface SpellCheckFileOptions extends ValidateTextOptions {
|
|
6
|
+
export interface SpellCheckFileOptions extends ValidateTextOptions, Pick<CSpellUserSettings, 'unknownWords'> {
|
|
7
7
|
/**
|
|
8
8
|
* Optional path to a configuration file.
|
|
9
9
|
* If given, it will be used instead of searching for a configuration file.
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type { MappedText, TextOffset as TextOffsetRW } from '@cspell/cspell-types';
|
|
2
|
-
import type { ExtendedSuggestion } from '../Models/Suggestion.js';
|
|
1
|
+
import type { Issue, MappedText, ReportingConfiguration, TextOffset as TextOffsetRW } from '@cspell/cspell-types';
|
|
3
2
|
import type { ValidationIssue } from '../Models/ValidationIssue.js';
|
|
4
3
|
export type { TextOffset as TextOffsetRW } from '@cspell/cspell-types';
|
|
5
4
|
export type TextOffsetRO = Readonly<TextOffsetRW>;
|
|
6
|
-
export interface ValidationOptions extends IncludeExcludeOptions {
|
|
5
|
+
export interface ValidationOptions extends IncludeExcludeOptions, ReportingConfiguration {
|
|
7
6
|
maxNumberOfProblems?: number;
|
|
8
7
|
maxDuplicateProblems?: number;
|
|
9
8
|
minWordLength?: number;
|
|
@@ -35,10 +34,8 @@ export interface LineSegment {
|
|
|
35
34
|
/** A segment of text from the line, the offset is relative to the beginning of the document. */
|
|
36
35
|
segment: TextOffsetRO;
|
|
37
36
|
}
|
|
38
|
-
export interface MappedTextValidationResult extends MappedText {
|
|
39
|
-
isFlagged?: boolean | undefined;
|
|
37
|
+
export interface MappedTextValidationResult extends MappedText, Pick<Issue, 'hasSimpleSuggestions' | 'hasPreferredSuggestions' | 'isFlagged' | 'suggestionsEx'> {
|
|
40
38
|
isFound?: boolean | undefined;
|
|
41
|
-
suggestionsEx?: ExtendedSuggestion[] | undefined;
|
|
42
39
|
}
|
|
43
40
|
export type TextValidatorFn = (text: MappedText) => Iterable<MappedTextValidationResult>;
|
|
44
41
|
//# sourceMappingURL=ValidationTypes.d.ts.map
|
|
@@ -174,14 +174,24 @@ export class DocumentValidator {
|
|
|
174
174
|
const document = this._document;
|
|
175
175
|
let line = undefined;
|
|
176
176
|
function mapToIssue(issue) {
|
|
177
|
-
const { range, text, isFlagged, isFound, suggestionsEx } = issue;
|
|
177
|
+
const { range, text, isFlagged, isFound, suggestionsEx, hasPreferredSuggestions, hasSimpleSuggestions } = issue;
|
|
178
178
|
const offset = range[0];
|
|
179
179
|
const length = range[1] - range[0];
|
|
180
180
|
assert(!line || line.offset <= offset);
|
|
181
181
|
if (!line || line.offset + line.text.length <= offset) {
|
|
182
182
|
line = document.lineAt(offset);
|
|
183
183
|
}
|
|
184
|
-
return {
|
|
184
|
+
return {
|
|
185
|
+
text,
|
|
186
|
+
offset,
|
|
187
|
+
line,
|
|
188
|
+
length,
|
|
189
|
+
isFlagged,
|
|
190
|
+
isFound,
|
|
191
|
+
suggestionsEx,
|
|
192
|
+
hasPreferredSuggestions,
|
|
193
|
+
hasSimpleSuggestions,
|
|
194
|
+
};
|
|
185
195
|
}
|
|
186
196
|
const issues = [...pipeSync(segmenter(parsedText), opConcatMap(textValidator.validate), opMap(mapToIssue))];
|
|
187
197
|
if (!this.options.generateSuggestions) {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import assert from 'node:assert';
|
|
2
2
|
import { opConcatMap, opFilter, pipe } from '@cspell/cspell-pipe/sync';
|
|
3
|
-
import { defaultCSpellSettings } from '@cspell/cspell-types';
|
|
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 { autoResolve } from '../util/AutoResolve.js';
|
|
6
7
|
import { extractPossibleWordsFromTextOffset, extractText, extractWordsFromTextOffset, splitWordWithOffset, } from '../util/text.js';
|
|
7
8
|
import { regExpCamelCaseWordBreaksWithEnglishSuffix } from '../util/textRegex.js';
|
|
8
9
|
import { split } from '../util/wordSplitter.js';
|
|
@@ -12,7 +13,7 @@ import { isWordValidWithEscapeRetry } from './isWordValid.js';
|
|
|
12
13
|
import { mapRangeBackToOriginalPos } from './parsedText.js';
|
|
13
14
|
const MIN_HEX_SEQUENCE_LENGTH = 8;
|
|
14
15
|
export function lineValidatorFactory(sDict, options) {
|
|
15
|
-
const { minWordLength = defaultMinWordLength, flagWords = [], allowCompoundWords = false, ignoreCase = true, ignoreRandomStrings = defaultCSpellSettings.ignoreRandomStrings, minRandomLength = defaultCSpellSettings.minRandomLength, } = options;
|
|
16
|
+
const { minWordLength = defaultMinWordLength, flagWords = [], allowCompoundWords = false, ignoreCase = true, ignoreRandomStrings = defaultCSpellSettings.ignoreRandomStrings, minRandomLength = defaultCSpellSettings.minRandomLength, unknownWords = unknownWordsChoices.ReportAll, } = options;
|
|
16
17
|
const hasWordOptions = {
|
|
17
18
|
ignoreCase,
|
|
18
19
|
useCompounds: allowCompoundWords || undefined, // let the dictionaries decide on useCompounds if allow is false
|
|
@@ -61,8 +62,23 @@ export function lineValidatorFactory(sDict, options) {
|
|
|
61
62
|
function isWordIgnored(word) {
|
|
62
63
|
return calcIgnored(getWordInfo(word));
|
|
63
64
|
}
|
|
64
|
-
|
|
65
|
-
|
|
65
|
+
const cacheGetPreferredSuggestions = new Map();
|
|
66
|
+
function getPreferredSuggestions(word) {
|
|
67
|
+
return autoResolve(cacheGetPreferredSuggestions, word, () => dictCol.getPreferredSuggestions(word));
|
|
68
|
+
}
|
|
69
|
+
const cacheHasSimpleSuggestions = new Map();
|
|
70
|
+
function hasSimpleSuggestions(word) {
|
|
71
|
+
return autoResolve(cacheHasSimpleSuggestions, word, () => {
|
|
72
|
+
const sugs = dictCol.suggest(word, {
|
|
73
|
+
numSuggestions: 1,
|
|
74
|
+
compoundMethod: 0,
|
|
75
|
+
includeTies: false,
|
|
76
|
+
ignoreCase,
|
|
77
|
+
timeout: 100,
|
|
78
|
+
numChanges: 1.8, // Only consider very simple changes (1 edit distance plus case changes)
|
|
79
|
+
});
|
|
80
|
+
return !!sugs.length;
|
|
81
|
+
});
|
|
66
82
|
}
|
|
67
83
|
function isWordFlagged(wo) {
|
|
68
84
|
return calcFlagged(getWordInfo(wo.text));
|
|
@@ -72,10 +88,17 @@ export function lineValidatorFactory(sDict, options) {
|
|
|
72
88
|
return word;
|
|
73
89
|
}
|
|
74
90
|
function annotateIssue(issue) {
|
|
75
|
-
const sugs =
|
|
76
|
-
if (sugs
|
|
77
|
-
issue.
|
|
91
|
+
const sugs = getPreferredSuggestions(issue.text);
|
|
92
|
+
if (!sugs?.length) {
|
|
93
|
+
issue.hasPreferredSuggestions = sugs !== undefined ? false : undefined;
|
|
94
|
+
if (unknownWords === unknownWordsChoices.ReportSimple) {
|
|
95
|
+
issue.hasSimpleSuggestions = hasSimpleSuggestions(issue.text);
|
|
96
|
+
}
|
|
97
|
+
return issue;
|
|
78
98
|
}
|
|
99
|
+
issue.suggestionsEx = sugs;
|
|
100
|
+
issue.hasPreferredSuggestions = true;
|
|
101
|
+
issue.hasSimpleSuggestions = true;
|
|
79
102
|
return issue;
|
|
80
103
|
}
|
|
81
104
|
const isFlaggedOrMinLength = (wo) => wo.text.length >= minWordLength || !!wo.isFlagged;
|
|
@@ -274,14 +297,14 @@ export function lineValidatorFactory(sDict, options) {
|
|
|
274
297
|
if (!mismatches.length)
|
|
275
298
|
return mismatches;
|
|
276
299
|
const hexSequences = !ignoreRandomStrings
|
|
277
|
-
?
|
|
300
|
+
? undefined
|
|
278
301
|
: extractHexSequences(possibleWord.text, MIN_HEX_SEQUENCE_LENGTH)
|
|
279
302
|
.filter(
|
|
280
303
|
// Only consider hex sequences that are all upper case or all lower case and contain a `-` or a digit.
|
|
281
304
|
(w) => (w.text === w.text.toLowerCase() || w.text === w.text.toUpperCase()) &&
|
|
282
305
|
/[\d-]/.test(w.text))
|
|
283
306
|
.map((w) => ((w.offset += possibleWord.offset), w));
|
|
284
|
-
if (hexSequences
|
|
307
|
+
if (hexSequences?.length) {
|
|
285
308
|
mismatches = filterExcludedTextOffsets(mismatches, hexSequences);
|
|
286
309
|
}
|
|
287
310
|
if (mismatches.length) {
|
|
@@ -330,10 +353,10 @@ export function textValidatorFactory(dict, options) {
|
|
|
330
353
|
const segment = { text, offset: 0 };
|
|
331
354
|
const lineSegment = { line: segment, segment };
|
|
332
355
|
function mapBackToOriginSimple(vr) {
|
|
333
|
-
const { text, offset, isFlagged, isFound, suggestionsEx } = vr;
|
|
356
|
+
const { text, offset, isFlagged, isFound, suggestionsEx, hasPreferredSuggestions, hasSimpleSuggestions } = vr;
|
|
334
357
|
const r = mapRangeBackToOriginalPos([offset, offset + text.length], map);
|
|
335
358
|
const range = [r[0] + srcOffset, r[1] + srcOffset];
|
|
336
|
-
return { text, range, isFlagged, isFound, suggestionsEx };
|
|
359
|
+
return { text, range, isFlagged, isFound, suggestionsEx, hasPreferredSuggestions, hasSimpleSuggestions };
|
|
337
360
|
}
|
|
338
361
|
return [...lineValidatorFn(lineSegment)].map(mapBackToOriginSimple);
|
|
339
362
|
}
|
|
@@ -343,7 +366,7 @@ export function textValidatorFactory(dict, options) {
|
|
|
343
366
|
};
|
|
344
367
|
}
|
|
345
368
|
function filterExcludedTextOffsets(issues, excluded) {
|
|
346
|
-
if (!excluded
|
|
369
|
+
if (!excluded?.length)
|
|
347
370
|
return issues;
|
|
348
371
|
const keep = [];
|
|
349
372
|
let i = 0;
|
|
@@ -4,6 +4,7 @@ export function settingsToValidateOptions(settings) {
|
|
|
4
4
|
ignoreCase: !(settings.caseSensitive ?? false),
|
|
5
5
|
ignoreRandomStrings: settings.ignoreRandomStrings,
|
|
6
6
|
minRandomLength: settings.minRandomLength,
|
|
7
|
+
unknownWords: settings.unknownWords || 'report-all',
|
|
7
8
|
};
|
|
8
9
|
return opt;
|
|
9
10
|
}
|
|
@@ -3,7 +3,7 @@ type EntryType = 'file' | 'directory' | '!file' | '!directory';
|
|
|
3
3
|
export type FindUpFileSystem = Pick<VFileSystem, 'findUp'>;
|
|
4
4
|
export interface FindUpURLOptions {
|
|
5
5
|
type?: EntryType;
|
|
6
|
-
stopAt?: URL;
|
|
6
|
+
stopAt?: URL | URL[];
|
|
7
7
|
fs?: FindUpFileSystem;
|
|
8
8
|
}
|
|
9
9
|
export type FindUpPredicate = (dir: URL) => URL | undefined | Promise<URL | undefined>;
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"access": "public",
|
|
5
5
|
"provenance": true
|
|
6
6
|
},
|
|
7
|
-
"version": "9.0
|
|
7
|
+
"version": "9.1.0",
|
|
8
8
|
"description": "A library of useful functions used across various cspell tools.",
|
|
9
9
|
"type": "module",
|
|
10
10
|
"sideEffects": false,
|
|
@@ -64,22 +64,22 @@
|
|
|
64
64
|
},
|
|
65
65
|
"homepage": "https://github.com/streetsidesoftware/cspell/tree/main/packages/cspell-lib#readme",
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@cspell/cspell-bundled-dicts": "9.0
|
|
68
|
-
"@cspell/cspell-pipe": "9.0
|
|
69
|
-
"@cspell/cspell-resolver": "9.0
|
|
70
|
-
"@cspell/cspell-types": "9.0
|
|
71
|
-
"@cspell/dynamic-import": "9.0
|
|
72
|
-
"@cspell/filetypes": "9.0
|
|
73
|
-
"@cspell/strong-weak-map": "9.0
|
|
74
|
-
"@cspell/url": "9.0
|
|
67
|
+
"@cspell/cspell-bundled-dicts": "9.1.0",
|
|
68
|
+
"@cspell/cspell-pipe": "9.1.0",
|
|
69
|
+
"@cspell/cspell-resolver": "9.1.0",
|
|
70
|
+
"@cspell/cspell-types": "9.1.0",
|
|
71
|
+
"@cspell/dynamic-import": "9.1.0",
|
|
72
|
+
"@cspell/filetypes": "9.1.0",
|
|
73
|
+
"@cspell/strong-weak-map": "9.1.0",
|
|
74
|
+
"@cspell/url": "9.1.0",
|
|
75
75
|
"clear-module": "^4.1.2",
|
|
76
76
|
"comment-json": "^4.2.5",
|
|
77
|
-
"cspell-config-lib": "9.0
|
|
78
|
-
"cspell-dictionary": "9.0
|
|
79
|
-
"cspell-glob": "9.0
|
|
80
|
-
"cspell-grammar": "9.0
|
|
81
|
-
"cspell-io": "9.0
|
|
82
|
-
"cspell-trie-lib": "9.0
|
|
77
|
+
"cspell-config-lib": "9.1.0",
|
|
78
|
+
"cspell-dictionary": "9.1.0",
|
|
79
|
+
"cspell-glob": "9.1.0",
|
|
80
|
+
"cspell-grammar": "9.1.0",
|
|
81
|
+
"cspell-io": "9.1.0",
|
|
82
|
+
"cspell-trie-lib": "9.1.0",
|
|
83
83
|
"env-paths": "^3.0.0",
|
|
84
84
|
"fast-equals": "^5.2.2",
|
|
85
85
|
"gensequence": "^7.0.0",
|
|
@@ -108,5 +108,5 @@
|
|
|
108
108
|
"lorem-ipsum": "^2.0.8",
|
|
109
109
|
"perf-insight": "^1.2.0"
|
|
110
110
|
},
|
|
111
|
-
"gitHead": "
|
|
111
|
+
"gitHead": "a7ed42a31debbc86faa4a4ac2c686bdffe5b26b6"
|
|
112
112
|
}
|