cspell-lib 8.9.0 → 8.10.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.
@@ -1,5 +1,5 @@
1
1
  import type { Uri } from '../util/Uri.js';
2
2
  import type { Document } from './Document.js';
3
3
  export declare function isBinaryDoc(document: Document): boolean;
4
- export declare function isBinaryFile(filename: Uri | URL | string, languageId?: string | string[]): boolean;
4
+ export declare function isBinaryFile(filename: Uri | URL | string, languageId?: string | string[], text?: string): boolean;
5
5
  //# sourceMappingURL=isBinaryDoc.d.ts.map
@@ -1,10 +1,10 @@
1
- import { isGenerated, isGeneratedFile } from '../LanguageIds.js';
1
+ import { getLanguagesForBasename, isGenerated } from '../LanguageIds.js';
2
2
  import { basename, toUri } from '../util/Uri.js';
3
3
  import { normalizeLanguageIds } from './normalizeLanguageIds.js';
4
4
  export function isBinaryDoc(document) {
5
- return isBinaryFile(toUri(document.uri), document.languageId);
5
+ return isBinaryFile(toUri(document.uri), document.languageId, document.text);
6
6
  }
7
- export function isBinaryFile(filename, languageId) {
7
+ export function isBinaryFile(filename, languageId, text) {
8
8
  const filenameUri = toUri(filename);
9
9
  if (languageId) {
10
10
  const ids = normalizeLanguageIds(languageId);
@@ -12,6 +12,10 @@ export function isBinaryFile(filename, languageId) {
12
12
  return isGenerated(ids);
13
13
  }
14
14
  const file = basename(filenameUri);
15
- return isGeneratedFile(file);
15
+ const ids = getLanguagesForBasename(file);
16
+ if (ids.length)
17
+ return isGenerated(ids);
18
+ // Unknown file type, check the content.
19
+ return text?.slice(0, 1024).includes('\u0000') || false;
16
20
  }
17
21
  //# sourceMappingURL=isBinaryDoc.js.map
@@ -1,4 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import type { TextDocument } from '../Models/TextDocument.js';
3
2
  import type { Document, DocumentWithText } from './Document.js';
4
3
  export declare function fileToDocument(file: string): Document;
@@ -216,7 +216,7 @@ export const languageExtensionDefinitions = [
216
216
  },
217
217
  {
218
218
  id: 'video',
219
- extensions: ['.mov', '.mpg'],
219
+ extensions: ['.mov', '.mpg', '.mpeg', '.mp4', '.avi', '.wmv', '.mkv', '.flv'],
220
220
  format: 'Binary',
221
221
  },
222
222
  {
@@ -1,5 +1,6 @@
1
1
  import type { CSpellUserSettings, ImportFileRef } from '@cspell/cspell-types';
2
2
  import type { CSpellConfigFile, CSpellConfigFileReaderWriter } from 'cspell-config-lib';
3
+ import { CSpellConfigFileInMemory } from 'cspell-config-lib';
3
4
  import type { VFileSystem } from '../../../fileSystem.js';
4
5
  import { AutoResolveCache } from '../../../util/AutoResolve.js';
5
6
  import { FileResolver } from '../../../util/resolveFile.js';
@@ -55,6 +56,13 @@ export interface IConfigLoader {
55
56
  * The loader caches configuration files for performance. This method clears the cache.
56
57
  */
57
58
  clearCachedSettingsFiles(): void;
59
+ /**
60
+ * Resolve and merge the settings from the imports.
61
+ * This will create a virtual configuration file that is used to resolve the settings.
62
+ * @param settings - settings to resolve imports for
63
+ * @param filename - the path / URL to the settings file. Used to resolve imports.
64
+ */
65
+ resolveSettingsImports(settings: CSpellUserSettings, filename: string | URL): Promise<CSpellSettingsI>;
58
66
  /**
59
67
  * Resolve imports and merge.
60
68
  * @param cfgFile - configuration file.
@@ -91,6 +99,7 @@ export declare class ConfigLoader implements IConfigLoader {
91
99
  protected cachedConfigFiles: Map<string, CSpellConfigFile>;
92
100
  protected cachedPendingConfigFile: AutoResolveCache<string, Promise<Error | CSpellConfigFile>>;
93
101
  protected cachedMergedConfig: WeakMap<CSpellConfigFile, CacheMergeConfigFileWithImports>;
102
+ protected cachedCSpellConfigFileInMemory: WeakMap<import("@cspell/cspell-types").CSpellSettings, Map<string, CSpellConfigFileInMemory>>;
94
103
  protected globalSettings: CSpellSettingsI | undefined;
95
104
  protected cspellConfigFileReaderWriter: CSpellConfigFileReaderWriter;
96
105
  protected configSearch: ConfigSearch;
@@ -111,6 +120,12 @@ export declare class ConfigLoader implements IConfigLoader {
111
120
  getGlobalSettings(): CSpellSettingsI;
112
121
  getGlobalSettingsAsync(): Promise<CSpellSettingsI>;
113
122
  clearCachedSettingsFiles(): void;
123
+ /**
124
+ * Resolve and merge the settings from the imports.
125
+ * @param settings - settings to resolve imports for
126
+ * @param filename - the path / URL to the settings file. Used to resolve imports.
127
+ */
128
+ resolveSettingsImports(settings: CSpellUserSettings, filename: string | URL): Promise<CSpellSettingsI>;
114
129
  protected init(): Promise<void>;
115
130
  protected prefetchGlobalSettingsAsync(): Promise<void>;
116
131
  protected resolveDefaultConfig(): Promise<URL>;
@@ -146,8 +161,8 @@ export declare function createConfigLoader(fs?: VFileSystem): IConfigLoader;
146
161
  export declare function getDefaultConfigLoaderInternal(): ConfigLoaderInternal;
147
162
  export declare class ConfigurationLoaderError extends Error {
148
163
  readonly configurationFile?: string | undefined;
149
- readonly relativeTo?: string | URL | undefined;
150
- constructor(message: string, configurationFile?: string | undefined, relativeTo?: string | URL | undefined, cause?: unknown);
164
+ readonly relativeTo?: (string | URL) | undefined;
165
+ constructor(message: string, configurationFile?: string | undefined, relativeTo?: (string | URL) | undefined, cause?: unknown);
151
166
  }
152
167
  export declare class ConfigurationLoaderFailedToResolveError extends ConfigurationLoaderError {
153
168
  readonly configurationFile: string;
@@ -8,7 +8,7 @@ import { srcDirectory } from '../../../../lib-cjs/index.cjs';
8
8
  import { onClearCache } from '../../../events/index.js';
9
9
  import { getVirtualFS } from '../../../fileSystem.js';
10
10
  import { createCSpellSettingsInternal as csi } from '../../../Models/CSpellSettingsInternalDef.js';
11
- import { AutoResolveCache } from '../../../util/AutoResolve.js';
11
+ import { autoResolve, AutoResolveCache, autoResolveWeak } from '../../../util/AutoResolve.js';
12
12
  import { logError, logWarning } from '../../../util/logger.js';
13
13
  import { FileResolver } from '../../../util/resolveFile.js';
14
14
  import { envToTemplateVars } from '../../../util/templates.js';
@@ -62,6 +62,7 @@ export class ConfigLoader {
62
62
  cachedConfigFiles = new Map();
63
63
  cachedPendingConfigFile = new AutoResolveCache();
64
64
  cachedMergedConfig = new WeakMap();
65
+ cachedCSpellConfigFileInMemory = new WeakMap();
65
66
  globalSettings;
66
67
  cspellConfigFileReaderWriter;
67
68
  configSearch;
@@ -147,8 +148,18 @@ export class ConfigLoader {
147
148
  this.cachedPendingConfigFile.clear();
148
149
  this.cspellConfigFileReaderWriter.clearCachedFiles();
149
150
  this.cachedMergedConfig = new WeakMap();
151
+ this.cachedCSpellConfigFileInMemory = new WeakMap();
150
152
  this.prefetchGlobalSettingsAsync();
151
153
  }
154
+ /**
155
+ * Resolve and merge the settings from the imports.
156
+ * @param settings - settings to resolve imports for
157
+ * @param filename - the path / URL to the settings file. Used to resolve imports.
158
+ */
159
+ resolveSettingsImports(settings, filename) {
160
+ const settingsFile = this.createCSpellConfigFile(filename, settings);
161
+ return this.mergeConfigFileWithImports(settingsFile, settings);
162
+ }
152
163
  init() {
153
164
  this.onReady = Promise.all([this.prefetchGlobalSettingsAsync(), this.resolveDefaultConfig()]).then(() => undefined);
154
165
  return this.onReady;
@@ -321,7 +332,8 @@ export class ConfigLoader {
321
332
  return finalizeSettings;
322
333
  }
323
334
  createCSpellConfigFile(filename, settings) {
324
- return new CSpellConfigFileInMemory(toFileURL(filename), settings);
335
+ const map = autoResolveWeak(this.cachedCSpellConfigFileInMemory, settings, () => new Map());
336
+ return autoResolve(map, filename, () => new CSpellConfigFileInMemory(toFileURL(filename), settings));
325
337
  }
326
338
  dispose() {
327
339
  while (this.toDispose.length) {
@@ -1,3 +1,4 @@
1
+ import type { CSpellSettings } from '@cspell/cspell-types';
1
2
  import type { CSpellConfigFile } from 'cspell-config-lib';
2
3
  import type { IConfigLoader } from './configLoader.js';
3
4
  import type { PnPSettingsOptional } from './PnPSettings.js';
@@ -16,6 +17,13 @@ export declare function searchForConfig(searchFrom: URL | string | undefined, pn
16
17
  * @returns normalized CSpellSettings
17
18
  */
18
19
  export declare function loadConfig(file: string, pnpSettings?: PnPSettingsOptional): Promise<CSpellSettingsI>;
20
+ /**
21
+ * Resolve the imports in the settings file.
22
+ * @param settings - settings to resolve imports for
23
+ * @param filename - the filename of the settings file, use cwd if not available.
24
+ * @returns
25
+ */
26
+ export declare function resolveSettingsImports(settings: CSpellSettings, filename: string | URL): Promise<CSpellSettingsI>;
19
27
  export declare function readConfigFile(filename: string | URL, relativeTo?: string | URL): Promise<CSpellConfigFile>;
20
28
  /**
21
29
  * Might throw if the settings have not yet been loaded.
@@ -22,6 +22,15 @@ export function searchForConfig(searchFrom, pnpSettings = defaultPnPSettings) {
22
22
  export async function loadConfig(file, pnpSettings) {
23
23
  return gcl().readSettingsAsync(file, undefined, pnpSettings);
24
24
  }
25
+ /**
26
+ * Resolve the imports in the settings file.
27
+ * @param settings - settings to resolve imports for
28
+ * @param filename - the filename of the settings file, use cwd if not available.
29
+ * @returns
30
+ */
31
+ export async function resolveSettingsImports(settings, filename) {
32
+ return gcl().resolveSettingsImports(settings, filename);
33
+ }
25
34
  export async function readConfigFile(filename, relativeTo) {
26
35
  const result = await gcl().readConfigFile(filename, relativeTo);
27
36
  if (result instanceof Error) {
@@ -1,6 +1,6 @@
1
1
  export { __testing__, ConfigLoader, createConfigLoader, defaultFileName, loadPnP, sectionCSpell, } from './configLoader.js';
2
2
  export { defaultConfigFilenames } from './configLocations.js';
3
- export { clearCachedSettingsFiles, getCachedFileSize, getDefaultConfigLoader, getGlobalSettings, getGlobalSettingsAsync, loadConfig, readRawSettings, searchForConfig, } from './defaultConfigLoader.js';
3
+ export { clearCachedSettingsFiles, getCachedFileSize, getDefaultConfigLoader, getGlobalSettings, getGlobalSettingsAsync, loadConfig, readRawSettings, resolveSettingsImports, searchForConfig, } from './defaultConfigLoader.js';
4
4
  export { extractImportErrors, ImportFileRefWithError } from './extractImportErrors.js';
5
5
  export { readSettings } from './readSettings.js';
6
6
  export { readSettingsFiles } from './readSettingsFiles.js';
@@ -1,6 +1,6 @@
1
1
  export { __testing__, ConfigLoader, createConfigLoader, defaultFileName, loadPnP, sectionCSpell, } from './configLoader.js';
2
2
  export { defaultConfigFilenames } from './configLocations.js';
3
- export { clearCachedSettingsFiles, getCachedFileSize, getDefaultConfigLoader, getGlobalSettings, getGlobalSettingsAsync, loadConfig, readRawSettings, searchForConfig, } from './defaultConfigLoader.js';
3
+ export { clearCachedSettingsFiles, getCachedFileSize, getDefaultConfigLoader, getGlobalSettings, getGlobalSettingsAsync, loadConfig, readRawSettings, resolveSettingsImports, searchForConfig, } from './defaultConfigLoader.js';
4
4
  export { extractImportErrors } from './extractImportErrors.js';
5
5
  export { readSettings } from './readSettings.js';
6
6
  export { readSettingsFiles } from './readSettingsFiles.js';
@@ -11,16 +11,16 @@ export declare function normalizeDictionaryDefs(settings: NormalizeDictionaryDef
11
11
  languageSettings: import("../../../util/types.js").RemoveUndefined<{
12
12
  dictionaryDefinitions: import("../../../Models/CSpellSettingsInternalDef.js").DictionaryDefinitionInternalWithSource[] | undefined;
13
13
  languageId: import("@cspell/cspell-types").MatchingFileType;
14
- locale?: string | string[];
15
- local?: string | string[];
14
+ locale?: import("@cspell/cspell-types").LocaleId | import("@cspell/cspell-types").LocaleId[];
15
+ local?: import("@cspell/cspell-types").LocaleId | import("@cspell/cspell-types").LocaleId[];
16
16
  id?: string;
17
17
  name?: string;
18
18
  description?: string;
19
19
  enabled?: boolean;
20
20
  allowCompoundWords?: boolean;
21
21
  caseSensitive?: boolean;
22
- dictionaries?: string[];
23
- noSuggestDictionaries?: string[];
22
+ dictionaries?: import("@cspell/cspell-types").DictionaryReference[];
23
+ noSuggestDictionaries?: import("@cspell/cspell-types").DictionaryReference[];
24
24
  ignoreRegExpList?: import("@cspell/cspell-types").RegExpPatternList;
25
25
  includeRegExpList?: import("@cspell/cspell-types").RegExpPatternList;
26
26
  patterns?: import("@cspell/cspell-types").RegExpPatternDefinition[];
@@ -28,7 +28,7 @@ export declare function normalizeDictionaryDefs(settings: NormalizeDictionaryDef
28
28
  flagWords?: string[];
29
29
  ignoreWords?: string[];
30
30
  suggestWords?: string[];
31
- parser?: string;
31
+ parser?: import("@cspell/cspell-types").ParserName;
32
32
  }>[] | undefined;
33
33
  }>;
34
34
  type NormalizeOverrides = Pick<CSpellUserSettings, 'globRoot' | 'overrides'>;
@@ -37,7 +37,7 @@ export const regExPhpHereDoc = /<<<['"]?(\w+)['"]?[\s\S]+?^\1;/gm;
37
37
  export const regExString = /(?:(['"]).*?(?<![^\\]\\(\\\\)*)\1)|(?:`[\s\S]*?(?<![^\\]\\(\\\\)*)`)/g;
38
38
  // Note: the C Style Comments incorrectly considers '/*' and '//' inside of strings as comments.
39
39
  export const regExCStyleComments = /(?<!\w:)(?:\/\/.*)|(?:\/\*[\s\S]*?\*\/)/g;
40
- export const rexExPythonStyleComments = /#.*|(?:('''|""")[^\1]+?\1)/gm;
40
+ export const rexExPythonStyleComments = /#.*|(?:('''|""")[\s\S]+?\1)/gm;
41
41
  export const regExEmail = /<?\b[\w.\-+]{1,128}@\w{1,63}(\.\w{1,63}){1,4}\b>?/gi;
42
42
  export const regExRepeatedChar = /^(\w)\1{3,}$/i;
43
43
  export const regExSha = /\bsha\d+-[a-z0-9+/]{25,}={0,3}/gi;
@@ -1,7 +1,7 @@
1
1
  export { calcOverrideSettings } from './calcOverrideSettings.js';
2
2
  export { checkFilenameMatchesGlob } from './checkFilenameMatchesGlob.js';
3
3
  export { currentSettingsFileVersion, ENV_CSPELL_GLOB_ROOT } from './constants.js';
4
- export { clearCachedSettingsFiles, createConfigLoader, defaultConfigFilenames, defaultFileName, extractImportErrors, getCachedFileSize, getDefaultConfigLoader, getGlobalSettings, getGlobalSettingsAsync, loadConfig, loadPnP, readRawSettings, readSettings, readSettingsFiles, searchForConfig, sectionCSpell, } from './Controller/configLoader/index.js';
4
+ export { clearCachedSettingsFiles, createConfigLoader, defaultConfigFilenames, defaultFileName, extractImportErrors, getCachedFileSize, getDefaultConfigLoader, getGlobalSettings, getGlobalSettingsAsync, loadConfig, loadPnP, readRawSettings, readSettings, readSettingsFiles, resolveSettingsImports, searchForConfig, sectionCSpell, } from './Controller/configLoader/index.js';
5
5
  export { ImportError } from './Controller/ImportError.js';
6
6
  export type { ConfigurationDependencies, ImportFileRefWithError } from './CSpellSettingsServer.js';
7
7
  export { extractDependencies, finalizeSettings, getSources, mergeInDocSettings, mergeSettings, } from './CSpellSettingsServer.js';
@@ -1,7 +1,7 @@
1
1
  export { calcOverrideSettings } from './calcOverrideSettings.js';
2
2
  export { checkFilenameMatchesGlob } from './checkFilenameMatchesGlob.js';
3
3
  export { currentSettingsFileVersion, ENV_CSPELL_GLOB_ROOT } from './constants.js';
4
- export { clearCachedSettingsFiles, createConfigLoader, defaultConfigFilenames, defaultFileName, extractImportErrors, getCachedFileSize, getDefaultConfigLoader, getGlobalSettings, getGlobalSettingsAsync, loadConfig, loadPnP, readRawSettings, readSettings, readSettingsFiles, searchForConfig, sectionCSpell, } from './Controller/configLoader/index.js';
4
+ export { clearCachedSettingsFiles, createConfigLoader, defaultConfigFilenames, defaultFileName, extractImportErrors, getCachedFileSize, getDefaultConfigLoader, getGlobalSettings, getGlobalSettingsAsync, loadConfig, loadPnP, readRawSettings, readSettings, readSettingsFiles, resolveSettingsImports, searchForConfig, sectionCSpell, } from './Controller/configLoader/index.js';
5
5
  export { ImportError } from './Controller/ImportError.js';
6
6
  export { extractDependencies, finalizeSettings, getSources, mergeInDocSettings, mergeSettings, } from './CSpellSettingsServer.js';
7
7
  export { defaultSettingsLoader, getDefaultBundledSettingsAsync, getDefaultSettings } from './DefaultSettings.js';
@@ -1,4 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  import type { CSpellSettingsWithSourceTrace, CSpellUserSettings } from '@cspell/cspell-types';
3
2
  import type { Document, DocumentWithText } from './Document/index.js';
4
3
  import type { Uri } from './util/Uri.js';
@@ -39,6 +39,17 @@ export async function spellCheckDocument(document, options, settings) {
39
39
  try {
40
40
  const timer = createPerfTimer('loadFile');
41
41
  const doc = await resolveDocument(document).finally(() => timer.end());
42
+ if (isBinaryDoc(doc)) {
43
+ return {
44
+ document,
45
+ options,
46
+ settingsUsed: settings,
47
+ localConfigFilepath: undefined,
48
+ issues: [],
49
+ checked: false,
50
+ errors: undefined,
51
+ };
52
+ }
42
53
  const result = await spellCheckFullDocument(doc, options, settings);
43
54
  const perf = result.perf || {};
44
55
  perf.loadTimeMs = timer.elapsed;
@@ -25,6 +25,11 @@ export interface DocumentValidatorOptions extends ValidateTextOptions {
25
25
  * @defaultValue undefined
26
26
  */
27
27
  noConfigSearch?: boolean;
28
+ /**
29
+ * If `settings: CSpellUserSettings` contains imports, they will be resolved using this path.
30
+ * If not set, the current working directory will be used.
31
+ */
32
+ resolveImportsRelativeTo?: string | URL;
28
33
  }
29
34
  type PerfTimings = Record<string, number>;
30
35
  export declare class DocumentValidator {
@@ -1,10 +1,12 @@
1
1
  import assert from 'node:assert';
2
+ import { pathToFileURL } from 'node:url';
2
3
  import { opConcatMap, opMap, pipeSync } from '@cspell/cspell-pipe/sync';
3
4
  import { IssueType } from '@cspell/cspell-types';
5
+ import { toFileURL } from '@cspell/url';
4
6
  import { getGlobMatcherForExcluding } from '../globs/getGlobMatcher.js';
5
7
  import { updateTextDocument } from '../Models/TextDocument.js';
6
8
  import { createPerfTimer } from '../perf/index.js';
7
- import { finalizeSettings, loadConfig, mergeSettings, searchForConfig } from '../Settings/index.js';
9
+ import { finalizeSettings, loadConfig, mergeSettings, resolveSettingsImports, searchForConfig, } from '../Settings/index.js';
8
10
  import { validateInDocumentSettings } from '../Settings/InDocSettings.js';
9
11
  import { getDictionaryInternal } from '../SpellingDictionary/index.js';
10
12
  import { calcSuggestionAdjustedToToMatchCase } from '../suggestions.js';
@@ -60,7 +62,11 @@ export class DocumentValidator {
60
62
  async _prepareAsync() {
61
63
  assert(!this._ready);
62
64
  const timer = createPerfTimer('_prepareAsync');
63
- const { options, settings } = this;
65
+ const { options, settings: rawSettings } = this;
66
+ const resolveImportsRelativeTo = toFileURL(options.resolveImportsRelativeTo || pathToFileURL('./virtual.settings.json'));
67
+ const settings = rawSettings.import?.length
68
+ ? await resolveSettingsImports(rawSettings, resolveImportsRelativeTo)
69
+ : rawSettings;
64
70
  const useSearchForConfig = (!options.noConfigSearch && !settings.noConfigSearch) || options.noConfigSearch === false;
65
71
  const pLocalConfig = options.configFile
66
72
  ? loadConfig(options.configFile, settings)
@@ -2,15 +2,25 @@ import type { CSpellSettingsWithSourceTrace } from '@cspell/cspell-types';
2
2
  import type { SpellingDictionaryCollection } from '../SpellingDictionary/index.js';
3
3
  type Href = string;
4
4
  export interface DictionaryTraceResult {
5
+ /** The word being traced. */
5
6
  word: string;
6
7
  found: boolean;
8
+ /** The word found. */
7
9
  foundWord: string | undefined;
10
+ /** Indicates that the word is flagged. */
8
11
  forbidden: boolean;
12
+ /** The would should not show up in suggestions, but is considered correct. */
9
13
  noSuggest: boolean;
14
+ /** The name of the dictionary. */
10
15
  dictName: string;
16
+ /** The path/href to dictionary file. */
11
17
  dictSource: string;
18
+ /** Suggested changes to the word. */
19
+ preferredSuggestions?: string[] | undefined;
20
+ /** href to the config file referencing the dictionary. */
12
21
  configSource: Href | undefined;
13
- errors: Error[] | undefined;
22
+ /** Errors */
23
+ errors?: Error[] | undefined;
14
24
  }
15
25
  export interface WordSplits {
16
26
  word: string;
@@ -5,7 +5,7 @@ import { uniqueFn } from '../util/util.js';
5
5
  import { split } from '../util/wordSplitter.js';
6
6
  export function traceWord(word, dictCollection, config) {
7
7
  const opts = {
8
- ignoreCase: true,
8
+ ignoreCase: config.ignoreCase ?? true,
9
9
  useCompounds: config.allowCompoundWords || false,
10
10
  };
11
11
  const splits = split({ text: word, offset: 0 }, 0, checkWord);
@@ -35,6 +35,7 @@ export function traceWord(word, dictCollection, config) {
35
35
  */
36
36
  function unpackDictionaryFindResult(found, config) {
37
37
  const { word, dict, findResult } = found;
38
+ const dictPreferred = getPreferred(dict, word);
38
39
  const baseResult = {
39
40
  word,
40
41
  found: !!findResult?.found,
@@ -44,6 +45,7 @@ function unpackDictionaryFindResult(found, config) {
44
45
  dictName: dict.name,
45
46
  dictSource: dict.source,
46
47
  configSource: undefined,
48
+ preferredSuggestions: dictPreferred,
47
49
  errors: normalizeErrors(dict.getErrors?.()),
48
50
  };
49
51
  const configFieldName = mapSpecialDictionaryNamesToSettings.get(dict.name);
@@ -68,7 +70,8 @@ function unpackDictionaryFindResult(found, config) {
68
70
  const cfg = { [configFieldName]: src[configFieldName] };
69
71
  const cfgDict = createCollection(getInlineConfigDictionaries(cfg), dict.name, configSource);
70
72
  const findResult = cfgDict.find(word, opts);
71
- if (!findResult?.found)
73
+ const preferredSuggestions = getPreferred(cfgDict, word);
74
+ if (!findResult?.found && !preferredSuggestions)
72
75
  continue;
73
76
  const result = {
74
77
  word,
@@ -79,24 +82,21 @@ function unpackDictionaryFindResult(found, config) {
79
82
  dictName: dict.name,
80
83
  dictSource: configSource,
81
84
  configSource,
85
+ preferredSuggestions,
82
86
  errors: normalizeErrors(dict.getErrors?.()),
83
87
  };
84
88
  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
89
  }
95
90
  return results.length ? results : [baseResult];
96
91
  }
97
92
  function normalizeErrors(errors) {
98
93
  return errors?.length ? errors : undefined;
99
94
  }
95
+ function getPreferred(dict, word) {
96
+ const sugs = dict.getPreferredSuggestions?.(word);
97
+ const preferred = sugs?.length ? sugs.filter((s) => s.isPreferred).map((s) => s.word) : undefined;
98
+ return preferred;
99
+ }
100
100
  class CTraceResult extends Array {
101
101
  splits = [];
102
102
  constructor(...items) {
@@ -1,17 +1,9 @@
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';
4
- export interface TraceResult {
5
- word: string;
6
- found: boolean;
7
- foundWord: string | undefined;
8
- forbidden: boolean;
9
- noSuggest: boolean;
10
- dictName: string;
11
- dictSource: string;
3
+ import type { DictionaryTraceResult, WordSplits } from './textValidation/traceWord.js';
4
+ export interface TraceResult extends DictionaryTraceResult {
5
+ /** True if the dictionary is currently active. */
12
6
  dictActive: boolean;
13
- configSource: string;
14
- errors: Error[] | undefined;
15
7
  }
16
8
  export interface TraceOptions {
17
9
  languageId?: LanguageId | LanguageId[];
@@ -1,4 +1,3 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
1
  declare function getTypeOf(t: unknown): "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function";
3
2
  export declare function isErrnoException(e: unknown): e is NodeJS.ErrnoException;
4
3
  export declare function isError(e: unknown): e is Error;
@@ -1,6 +1,6 @@
1
1
  import type { VFileSystem } from '../fileSystem.js';
2
2
  type EntryType = 'file' | 'directory' | '!file' | '!directory';
3
- export type FindUpFileSystem = Pick<VFileSystem, 'stat'>;
3
+ export type FindUpFileSystem = Pick<VFileSystem, 'findUp'>;
4
4
  export interface FindUpURLOptions {
5
5
  type?: EntryType;
6
6
  stopAt?: URL;
@@ -1,44 +1,6 @@
1
1
  import { getVirtualFS } from '../fileSystem.js';
2
2
  export async function findUpFromUrl(name, from, options = {}) {
3
- const { type: entryType = 'file', stopAt, fs = getVirtualFS().fs } = options;
4
- let dir = new URL('.', from);
5
- const root = new URL('/', dir);
6
- const predicate = makePredicate(fs, name, entryType);
7
- const stopAtDir = stopAt || root;
8
- let last = '';
9
- while (dir.href !== last) {
10
- const found = await predicate(dir);
11
- if (found !== undefined)
12
- return found;
13
- last = dir.href;
14
- if (dir.href === root.href || dir.href === stopAtDir.href)
15
- break;
16
- dir = new URL('..', dir);
17
- }
18
- return undefined;
19
- }
20
- function makePredicate(fs, name, entryType) {
21
- if (typeof name === 'function')
22
- return name;
23
- const checkStat = entryType === 'file' || entryType === '!file' ? 'isFile' : 'isDirectory';
24
- const checkValue = entryType.startsWith('!') ? false : true;
25
- function checkName(dir, name) {
26
- const f = new URL(name, dir);
27
- return fs
28
- .stat(f)
29
- .then((stats) => ((stats.isUnknown() || stats[checkStat]() === checkValue) && f) || undefined)
30
- .catch(() => undefined);
31
- }
32
- if (!Array.isArray(name))
33
- return (dir) => checkName(dir, name);
34
- return async (dir) => {
35
- const pending = name.map((n) => checkName(dir, n));
36
- for (const p of pending) {
37
- const found = await p;
38
- if (found)
39
- return found;
40
- }
41
- return undefined;
42
- };
3
+ const fs = options.fs ?? getVirtualFS().fs;
4
+ return fs.findUp(name, from, options);
43
5
  }
44
6
  //# sourceMappingURL=findUpFromUrl.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cspell-lib",
3
- "version": "8.9.0",
3
+ "version": "8.10.0",
4
4
  "description": "A library of useful functions used across various cspell tools.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -59,21 +59,21 @@
59
59
  },
60
60
  "homepage": "https://github.com/streetsidesoftware/cspell#readme",
61
61
  "dependencies": {
62
- "@cspell/cspell-bundled-dicts": "8.9.0",
63
- "@cspell/cspell-pipe": "8.9.0",
64
- "@cspell/cspell-resolver": "8.9.0",
65
- "@cspell/cspell-types": "8.9.0",
66
- "@cspell/dynamic-import": "8.9.0",
67
- "@cspell/strong-weak-map": "8.9.0",
68
- "@cspell/url": "8.9.0",
62
+ "@cspell/cspell-bundled-dicts": "8.10.0",
63
+ "@cspell/cspell-pipe": "8.10.0",
64
+ "@cspell/cspell-resolver": "8.10.0",
65
+ "@cspell/cspell-types": "8.10.0",
66
+ "@cspell/dynamic-import": "8.10.0",
67
+ "@cspell/strong-weak-map": "8.10.0",
68
+ "@cspell/url": "8.10.0",
69
69
  "clear-module": "^4.1.2",
70
70
  "comment-json": "^4.2.3",
71
- "cspell-config-lib": "8.9.0",
72
- "cspell-dictionary": "8.9.0",
73
- "cspell-glob": "8.9.0",
74
- "cspell-grammar": "8.9.0",
75
- "cspell-io": "8.9.0",
76
- "cspell-trie-lib": "8.9.0",
71
+ "cspell-config-lib": "8.10.0",
72
+ "cspell-dictionary": "8.10.0",
73
+ "cspell-glob": "8.10.0",
74
+ "cspell-grammar": "8.10.0",
75
+ "cspell-io": "8.10.0",
76
+ "cspell-trie-lib": "8.10.0",
77
77
  "env-paths": "^3.0.0",
78
78
  "fast-equals": "^5.0.1",
79
79
  "gensequence": "^7.0.0",
@@ -101,5 +101,5 @@
101
101
  "leaked-handles": "^5.2.0",
102
102
  "lorem-ipsum": "^2.0.8"
103
103
  },
104
- "gitHead": "33c513cf848a61fb1ebcea1b9c67505a31447411"
104
+ "gitHead": "a5dde6ae7e2ac86ac956220d4b8c39a0e58e1bc6"
105
105
  }