cspell-lib 5.18.5 → 5.19.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (71) hide show
  1. package/dist/LanguageIds.d.ts +1 -1
  2. package/dist/LanguageIds.js +15 -10
  3. package/dist/Models/CSpellSettingsInternalDef.d.ts +8 -2
  4. package/dist/Models/CSpellSettingsInternalDef.js +3 -2
  5. package/dist/Models/TextDocument.d.ts +52 -0
  6. package/dist/Models/TextDocument.js +73 -0
  7. package/dist/Models/Uri.d.ts +5 -0
  8. package/dist/Models/Uri.js +16 -0
  9. package/dist/Settings/CSpellSettingsServer.d.ts +11 -9
  10. package/dist/Settings/CSpellSettingsServer.js +7 -2
  11. package/dist/Settings/DefaultSettings.js +11 -2
  12. package/dist/Settings/DictionarySettings.js +7 -9
  13. package/dist/Settings/ImportError.d.ts +1 -1
  14. package/dist/Settings/InDocSettings.js +7 -2
  15. package/dist/Settings/LanguageSettings.js +5 -1
  16. package/dist/Settings/TextDocumentSettings.d.ts +2 -1
  17. package/dist/Settings/TextDocumentSettings.js +5 -1
  18. package/dist/Settings/configLoader.d.ts +11 -1
  19. package/dist/Settings/configLoader.js +54 -13
  20. package/dist/Settings/link.js +8 -3
  21. package/dist/Settings/patterns.d.ts +1 -1
  22. package/dist/Settings/patterns.js +5 -1
  23. package/dist/SpellingDictionary/Dictionaries.d.ts +2 -0
  24. package/dist/SpellingDictionary/Dictionaries.js +17 -5
  25. package/dist/SpellingDictionary/DictionaryLoader.d.ts +21 -2
  26. package/dist/SpellingDictionary/DictionaryLoader.js +179 -16
  27. package/dist/SpellingDictionary/SpellingDictionaryCollection.d.ts +0 -1
  28. package/dist/SpellingDictionary/SpellingDictionaryCollection.js +4 -10
  29. package/dist/SpellingDictionary/SpellingDictionaryFromTrie.d.ts +1 -1
  30. package/dist/SpellingDictionary/SpellingDictionaryFromTrie.js +4 -3
  31. package/dist/SpellingDictionary/SpellingDictionaryMethods.js +3 -2
  32. package/dist/SpellingDictionary/index.js +5 -1
  33. package/dist/index.d.ts +7 -4
  34. package/dist/index.js +15 -7
  35. package/dist/spellCheckFile.js +14 -51
  36. package/dist/suggestions.js +8 -4
  37. package/dist/textValidation/determineTextDocumentSettings.d.ts +17 -0
  38. package/dist/textValidation/determineTextDocumentSettings.js +63 -0
  39. package/dist/textValidation/docValidator.d.ts +50 -0
  40. package/dist/textValidation/docValidator.js +199 -0
  41. package/dist/textValidation/index.d.ts +7 -0
  42. package/dist/textValidation/index.js +12 -0
  43. package/dist/{textValidator.d.ts → textValidation/textValidator.d.ts} +20 -12
  44. package/dist/{textValidator.js → textValidation/textValidator.js} +60 -61
  45. package/dist/textValidation/validator.d.ts +32 -0
  46. package/dist/textValidation/validator.js +131 -0
  47. package/dist/trace.js +8 -4
  48. package/dist/util/Memorizer.d.ts +11 -0
  49. package/dist/util/Memorizer.js +15 -1
  50. package/dist/util/TextRange.d.ts +2 -2
  51. package/dist/util/TextRange.js +13 -19
  52. package/dist/util/errors.d.ts +8 -0
  53. package/dist/util/errors.js +15 -1
  54. package/dist/util/fileReader.d.ts +1 -0
  55. package/dist/util/fileReader.js +6 -1
  56. package/dist/util/memorizerWeak.d.ts +6 -0
  57. package/dist/util/memorizerWeak.js +44 -0
  58. package/dist/util/resolveFile.js +5 -1
  59. package/dist/util/text.d.ts +9 -10
  60. package/dist/util/text.js +10 -4
  61. package/dist/util/timer.d.ts +15 -0
  62. package/dist/util/timer.js +29 -0
  63. package/dist/util/types.d.ts +12 -0
  64. package/dist/util/util.d.ts +9 -1
  65. package/dist/util/util.js +17 -1
  66. package/dist/validator.d.ts +2 -31
  67. package/dist/validator.js +5 -124
  68. package/dist/wordListHelper.js +7 -5
  69. package/package.json +16 -14
  70. package/dist/SpellingDictionary/DictionaryLoaderTypes.d.ts +0 -1
  71. package/dist/SpellingDictionary/DictionaryLoaderTypes.js +0 -2
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -19,7 +23,7 @@ var __importStar = (this && this.__importStar) || function (mod) {
19
23
  return result;
20
24
  };
21
25
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.__testing__ = exports.extractImportErrors = exports.clearCachedSettingsFiles = exports.getCachedFileSize = exports.getGlobalSettings = exports.readSettingsFiles = exports.readRawSettings = exports.loadPnPSync = exports.loadPnP = exports.loadConfig = exports.searchForConfig = exports.readSettings = exports.defaultConfigFilenames = exports.defaultFileName = exports.sectionCSpell = void 0;
26
+ exports.__testing__ = exports.extractImportErrors = exports.clearCachedSettingsFiles = exports.getCachedFileSize = exports.getGlobalSettings = exports.readSettingsFiles = exports.readRawSettings = exports.loadPnPSync = exports.loadPnP = exports.loadConfigSync = exports.loadConfig = exports.searchForConfigSync = exports.searchForConfig = exports.readSettings = exports.defaultConfigFilenames = exports.defaultFileName = exports.sectionCSpell = void 0;
23
27
  const json = __importStar(require("comment-json"));
24
28
  const cosmiconfig_1 = require("cosmiconfig");
25
29
  const path = __importStar(require("path"));
@@ -215,16 +219,20 @@ function readSettings(filename, relativeToOrDefault, defaultValue) {
215
219
  return importSettings(ref, defaultValue, defaultValue || defaultPnPSettings);
216
220
  }
217
221
  exports.readSettings = readSettings;
218
- async function normalizeSearchForConfigResult(searchPath, searchResult, pnpSettings) {
219
- var _a;
222
+ async function normalizeSearchForConfigResultAsync(searchPath, searchResult, pnpSettings) {
220
223
  let result;
221
- let error;
222
224
  try {
223
225
  result = (await searchResult) || undefined;
224
226
  }
225
227
  catch (cause) {
226
- error = new ImportError_1.ImportError(`Failed to find config file at: "${searchPath}"`, cause);
228
+ result = new ImportError_1.ImportError(`Failed to find config file at: "${searchPath}"`, cause);
227
229
  }
230
+ return normalizeSearchForConfigResult(searchPath, result, pnpSettings);
231
+ }
232
+ function normalizeSearchForConfigResult(searchPath, searchResult, pnpSettings) {
233
+ var _a;
234
+ const error = searchResult instanceof ImportError_1.ImportError ? searchResult : undefined;
235
+ const result = searchResult instanceof ImportError_1.ImportError ? undefined : searchResult;
228
236
  const filepath = result === null || result === void 0 ? void 0 : result.filepath;
229
237
  if (filepath) {
230
238
  const cached = cachedFiles.get(filepath);
@@ -252,9 +260,20 @@ async function normalizeSearchForConfigResult(searchPath, searchResult, pnpSetti
252
260
  };
253
261
  }
254
262
  function searchForConfig(searchFrom, pnpSettings = defaultPnPSettings) {
255
- return normalizeSearchForConfigResult(searchFrom || process.cwd(), cspellConfigExplorer.search(searchFrom), pnpSettings).then((r) => (r.filepath ? r.config : undefined));
263
+ return normalizeSearchForConfigResultAsync(searchFrom || process.cwd(), cspellConfigExplorer.search(searchFrom), pnpSettings).then((r) => (r.filepath ? r.config : undefined));
256
264
  }
257
265
  exports.searchForConfig = searchForConfig;
266
+ function searchForConfigSync(searchFrom, pnpSettings = defaultPnPSettings) {
267
+ let searchResult;
268
+ try {
269
+ searchResult = cspellConfigExplorerSync.search(searchFrom) || undefined;
270
+ }
271
+ catch (err) {
272
+ searchResult = new ImportError_1.ImportError(`Failed to find config file from: "${searchFrom}"`, err);
273
+ }
274
+ return normalizeSearchForConfigResult(searchFrom || process.cwd(), searchResult, pnpSettings).config;
275
+ }
276
+ exports.searchForConfigSync = searchForConfigSync;
258
277
  /**
259
278
  * Load a CSpell configuration files.
260
279
  * @param file - path or package reference to load.
@@ -266,9 +285,30 @@ function loadConfig(file, pnpSettings = defaultPnPSettings) {
266
285
  if (cached) {
267
286
  return Promise.resolve(cached);
268
287
  }
269
- return normalizeSearchForConfigResult(file, cspellConfigExplorer.load(file), pnpSettings).then((r) => r.config);
288
+ return normalizeSearchForConfigResultAsync(file, cspellConfigExplorer.load(file), pnpSettings).then((r) => r.config);
270
289
  }
271
290
  exports.loadConfig = loadConfig;
291
+ /**
292
+ * Load a CSpell configuration files.
293
+ * @param filename - path or package reference to load.
294
+ * @param pnpSettings - PnP settings
295
+ * @returns normalized CSpellSettings
296
+ */
297
+ function loadConfigSync(filename, pnpSettings = defaultPnPSettings) {
298
+ const cached = cachedFiles.get(path.resolve(filename));
299
+ if (cached) {
300
+ return cached;
301
+ }
302
+ let searchResult;
303
+ try {
304
+ searchResult = cspellConfigExplorerSync.load(filename) || undefined;
305
+ }
306
+ catch (err) {
307
+ searchResult = new ImportError_1.ImportError(`Failed to find config file at: "${filename}"`, err);
308
+ }
309
+ return normalizeSearchForConfigResult(filename, searchResult, pnpSettings).config;
310
+ }
311
+ exports.loadConfigSync = loadConfigSync;
272
312
  function loadPnP(pnpSettings, searchFrom) {
273
313
  if (!pnpSettings.usePnP) {
274
314
  return Promise.resolve(undefined);
@@ -379,10 +419,11 @@ function toGlobDef(g, root, source) {
379
419
  return g.map((g) => toGlobDef(g, root, source));
380
420
  }
381
421
  if (typeof g === 'string') {
382
- return toGlobDef({
383
- glob: g,
384
- root,
385
- }, root, source);
422
+ const glob = { glob: g };
423
+ if (root !== undefined) {
424
+ glob.root = root;
425
+ }
426
+ return toGlobDef(glob, root, source);
386
427
  }
387
428
  if (source) {
388
429
  return { ...g, source };
@@ -446,7 +487,7 @@ function normalizeLanguageSettings(languageSettings) {
446
487
  return undefined;
447
488
  function fixLocale(s) {
448
489
  const { local: locale, ...rest } = s;
449
- return { locale, ...rest };
490
+ return util.clean({ locale, ...rest });
450
491
  }
451
492
  return languageSettings.map(fixLocale);
452
493
  }
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -22,6 +26,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
22
26
  exports.__testing__ = exports.removePathsFromGlobalImports = exports.addPathsToGlobalImports = exports.listGlobalImports = void 0;
23
27
  const fs = __importStar(require("fs"));
24
28
  const Path = __importStar(require("path"));
29
+ const util_1 = require("../util/util");
25
30
  const configLoader_1 = require("./configLoader");
26
31
  const GlobalSettings_1 = require("./GlobalSettings");
27
32
  function listGlobalImports() {
@@ -129,12 +134,12 @@ function resolveSettings(filename) {
129
134
  const ref = settings.__importRef;
130
135
  const resolvedToFilename = ref === null || ref === void 0 ? void 0 : ref.filename;
131
136
  const error = ((_a = ref === null || ref === void 0 ? void 0 : ref.error) === null || _a === void 0 ? void 0 : _a.message) || (!resolvedToFilename && 'File not Found') || undefined;
132
- return {
137
+ return (0, util_1.clean)({
133
138
  filename,
134
139
  resolvedToFilename,
135
140
  error,
136
141
  settings,
137
- };
142
+ });
138
143
  }
139
144
  function normalizeImports(imports) {
140
145
  return typeof imports === 'string' ? [imports] : imports || [];
@@ -1,3 +1,3 @@
1
1
  import type { RegExpPatternDefinition } from '@cspell/cspell-types';
2
- export declare function resolvePatterns(regExpList?: (string | RegExp)[], patternDefinitions?: RegExpPatternDefinition[]): (string | RegExp)[];
2
+ export declare function resolvePatterns(regExpList?: (string | RegExp)[], patternDefinitions?: RegExpPatternDefinition[]): RegExp[];
3
3
  //# sourceMappingURL=patterns.d.ts.map
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.resolvePatterns = void 0;
4
+ const text_1 = require("../util/text");
4
5
  const util_1 = require("../util/util");
5
6
  function resolvePatterns(regExpList = [], patternDefinitions = []) {
6
7
  const patternMap = new Map(patternDefinitions.map((def) => [def.name.toLowerCase(), def.pattern]));
@@ -22,7 +23,10 @@ function resolvePatterns(regExpList = [], patternDefinitions = []) {
22
23
  }
23
24
  }
24
25
  const patternList = regExpList.map(resolvePattern).filter(util_1.isDefined);
25
- return [...flatten(patternList)];
26
+ return [...flatten(patternList)].map(toRegExp).filter(util_1.isDefined);
26
27
  }
27
28
  exports.resolvePatterns = resolvePatterns;
29
+ function toRegExp(pattern) {
30
+ return pattern instanceof RegExp ? new RegExp(pattern) : (0, text_1.stringToRegExp)(pattern, 'gim', 'g');
31
+ }
28
32
  //# sourceMappingURL=patterns.js.map
@@ -2,6 +2,8 @@ import { CSpellSettingsInternal, DictionaryDefinitionInternal } from '../Models/
2
2
  import { SpellingDictionary } from './SpellingDictionary';
3
3
  import { SpellingDictionaryCollection } from './SpellingDictionaryCollection';
4
4
  export declare function loadDictionaryDefs(defsToLoad: DictionaryDefinitionInternal[]): Promise<SpellingDictionary>[];
5
+ export declare function loadDictionaryDefsSync(defsToLoad: DictionaryDefinitionInternal[]): SpellingDictionary[];
5
6
  export declare function refreshDictionaryCache(maxAge?: number): Promise<void>;
6
7
  export declare function getDictionaryInternal(settings: CSpellSettingsInternal): Promise<SpellingDictionaryCollection>;
8
+ export declare function getDictionaryInternalSync(settings: CSpellSettingsInternal): SpellingDictionaryCollection;
7
9
  //# sourceMappingURL=Dictionaries.d.ts.map
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getDictionaryInternal = exports.refreshDictionaryCache = exports.loadDictionaryDefs = void 0;
3
+ exports.getDictionaryInternalSync = exports.getDictionaryInternal = exports.refreshDictionaryCache = exports.loadDictionaryDefsSync = exports.loadDictionaryDefs = void 0;
4
4
  const DictionarySettings_1 = require("../Settings/DictionarySettings");
5
5
  const util_1 = require("../util/util");
6
6
  const createSpellingDictionary_1 = require("./createSpellingDictionary");
@@ -10,14 +10,27 @@ function loadDictionaryDefs(defsToLoad) {
10
10
  return defsToLoad.map((def) => (0, DictionaryLoader_1.loadDictionary)(def.path, def));
11
11
  }
12
12
  exports.loadDictionaryDefs = loadDictionaryDefs;
13
+ function loadDictionaryDefsSync(defsToLoad) {
14
+ return defsToLoad.map((def) => (0, DictionaryLoader_1.loadDictionarySync)(def.path, def));
15
+ }
16
+ exports.loadDictionaryDefsSync = loadDictionaryDefsSync;
13
17
  function refreshDictionaryCache(maxAge) {
14
18
  return (0, DictionaryLoader_1.refreshCacheEntries)(maxAge);
15
19
  }
16
20
  exports.refreshDictionaryCache = refreshDictionaryCache;
17
21
  const emptyWords = Object.freeze([]);
18
- function getDictionaryInternal(settings) {
22
+ async function getDictionaryInternal(settings) {
23
+ const spellDictionaries = await Promise.all(loadDictionaryDefs((0, DictionarySettings_1.calcDictionaryDefsToLoad)(settings)));
24
+ return _getDictionaryInternal(settings, spellDictionaries);
25
+ }
26
+ exports.getDictionaryInternal = getDictionaryInternal;
27
+ function getDictionaryInternalSync(settings) {
28
+ const spellDictionaries = loadDictionaryDefsSync((0, DictionarySettings_1.calcDictionaryDefsToLoad)(settings));
29
+ return _getDictionaryInternal(settings, spellDictionaries);
30
+ }
31
+ exports.getDictionaryInternalSync = getDictionaryInternalSync;
32
+ function _getDictionaryInternal(settings, spellDictionaries) {
19
33
  const { words = emptyWords, userWords = emptyWords, flagWords = emptyWords, ignoreWords = emptyWords } = settings;
20
- const spellDictionaries = loadDictionaryDefs((0, DictionarySettings_1.calcDictionaryDefsToLoad)(settings));
21
34
  const settingsWordsDictionary = (0, createSpellingDictionary_1.createSpellingDictionary)(words, '[words]', 'From Settings `words`', {
22
35
  caseSensitive: true,
23
36
  weightMap: undefined,
@@ -43,7 +56,6 @@ function getDictionaryInternal(settings) {
43
56
  ignoreWordsDictionary,
44
57
  flagWordsDictionary,
45
58
  ].filter(util_1.isDefined);
46
- return (0, SpellingDictionaryCollection_1.createCollectionP)(dictionaries, 'dictionary collection');
59
+ return (0, SpellingDictionaryCollection_1.createCollection)(dictionaries, 'dictionary collection');
47
60
  }
48
- exports.getDictionaryInternal = getDictionaryInternal;
49
61
  //# sourceMappingURL=Dictionaries.js.map
@@ -1,15 +1,23 @@
1
1
  import { DictionaryDefinitionInternal } from '../Models/CSpellSettingsInternalDef';
2
2
  import { SpellingDictionary } from './SpellingDictionary';
3
3
  export declare type LoadOptions = DictionaryDefinitionInternal;
4
+ declare enum LoadingState {
5
+ Loaded = 0,
6
+ Loading = 1
7
+ }
4
8
  interface CacheEntry {
5
9
  uri: string;
6
10
  options: LoadOptions;
7
11
  ts: number;
8
- state: Promise<Stats | Error>;
9
- dictionary: Promise<SpellingDictionary>;
12
+ stat: Stats | Error | undefined;
13
+ dictionary: SpellingDictionary | undefined;
14
+ pending: Promise<readonly [SpellingDictionary, Stats | Error]>;
15
+ loadingState: LoadingState;
16
+ sig: number;
10
17
  }
11
18
  export declare type LoaderType = keyof Loaders;
12
19
  export declare type Loader = (filename: string, options: LoadOptions) => Promise<SpellingDictionary>;
20
+ export declare type LoaderSync = (filename: string, options: LoadOptions) => SpellingDictionary;
13
21
  export interface Loaders {
14
22
  S: Loader;
15
23
  C: Loader;
@@ -17,7 +25,15 @@ export interface Loaders {
17
25
  W: Loader;
18
26
  default: Loader;
19
27
  }
28
+ export interface SyncLoaders {
29
+ S: LoaderSync;
30
+ C: LoaderSync;
31
+ T: LoaderSync;
32
+ W: LoaderSync;
33
+ default: LoaderSync;
34
+ }
20
35
  export declare function loadDictionary(uri: string, options: DictionaryDefinitionInternal): Promise<SpellingDictionary>;
36
+ export declare function loadDictionarySync(uri: string, options: DictionaryDefinitionInternal): SpellingDictionary;
21
37
  /**
22
38
  * Check to see if any of the cached dictionaries have changed. If one has changed, reload it.
23
39
  * @param maxAge - Only check the dictionary if it has been at least `maxAge` ms since the last check.
@@ -64,5 +80,8 @@ interface StatsBase<T> {
64
80
  birthtime: Date;
65
81
  }
66
82
  export declare type Stats = StatsBase<number>;
83
+ export declare const __testing__: {
84
+ debugLog: string[];
85
+ };
67
86
  export {};
68
87
  //# sourceMappingURL=DictionaryLoader.d.ts.map
@@ -1,7 +1,11 @@
1
1
  "use strict";
2
2
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
3
  if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
5
9
  }) : (function(o, m, k, k2) {
6
10
  if (k2 === undefined) k2 = k;
7
11
  o[k2] = m[k];
@@ -19,10 +23,12 @@ var __importStar = (this && this.__importStar) || function (mod) {
19
23
  return result;
20
24
  };
21
25
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.testing = exports.refreshCacheEntries = exports.loadDictionary = void 0;
23
- const fs_extra_1 = require("fs-extra");
26
+ exports.__testing__ = exports.testing = exports.refreshCacheEntries = exports.loadDictionarySync = exports.loadDictionary = void 0;
27
+ const fs_1 = require("fs");
24
28
  const gensequence_1 = require("gensequence");
25
29
  const path = __importStar(require("path"));
30
+ const util_1 = require("util");
31
+ const errors_1 = require("../util/errors");
26
32
  const fileReader_1 = require("../util/fileReader");
27
33
  const createSpellingDictionary_1 = require("./createSpellingDictionary");
28
34
  const SpellingDictionaryError_1 = require("./SpellingDictionaryError");
@@ -35,19 +41,63 @@ const loaders = {
35
41
  T: loadTrie,
36
42
  default: loadSimpleWordList,
37
43
  };
44
+ const loadersSync = {
45
+ S: loadSimpleWordListSync,
46
+ C: legacyWordListSync,
47
+ W: wordsPerLineWordListSync,
48
+ T: loadTrieSync,
49
+ default: loadSimpleWordListSync,
50
+ };
51
+ var LoadingState;
52
+ (function (LoadingState) {
53
+ LoadingState[LoadingState["Loaded"] = 0] = "Loaded";
54
+ LoadingState[LoadingState["Loading"] = 1] = "Loading";
55
+ })(LoadingState || (LoadingState = {}));
56
+ const debugLog = [];
57
+ const debugMode = false;
58
+ function __log(msg) {
59
+ debugMode && debugLog.push(msg);
60
+ }
38
61
  const dictionaryCache = new Map();
39
62
  function loadDictionary(uri, options) {
40
63
  const key = calcKey(uri, options);
41
64
  const entry = dictionaryCache.get(key);
42
65
  if (entry) {
43
- return entry.dictionary;
66
+ return entry.pending.then(([dictionary]) => dictionary);
44
67
  }
45
68
  const loadedEntry = loadEntry(uri, options);
46
69
  dictionaryCache.set(key, loadedEntry);
47
- return loadedEntry.dictionary;
70
+ return loadedEntry.pending.then(([dictionary]) => dictionary);
48
71
  }
49
72
  exports.loadDictionary = loadDictionary;
50
- const importantOptionKeys = ['name', 'noSuggest', 'useCompounds'];
73
+ function loadDictionarySync(uri, options) {
74
+ const key = calcKey(uri, options);
75
+ const entry = dictionaryCache.get(key);
76
+ if ((entry === null || entry === void 0 ? void 0 : entry.dictionary) && entry.loadingState === LoadingState.Loaded) {
77
+ // if (entry.options.name === 'temp') {
78
+ // __log(
79
+ // `Cache Found ${entry.options.name}; ts: ${entry.sig.toFixed(2)}; file: ${path.relative(
80
+ // process.cwd(),
81
+ // entry.uri
82
+ // )}`
83
+ // );
84
+ // }
85
+ return entry.dictionary;
86
+ }
87
+ // if (options.name === 'temp') {
88
+ // __log(
89
+ // `Cache Miss ${options.name}; ts: ${entry?.sig.toFixed(2) || Date.now()}; file: ${path.relative(
90
+ // process.cwd(),
91
+ // uri
92
+ // )}`
93
+ // );
94
+ // }
95
+ const loadedEntry = loadEntrySync(uri, options);
96
+ dictionaryCache.set(key, loadedEntry);
97
+ return loadedEntry.dictionary;
98
+ }
99
+ exports.loadDictionarySync = loadDictionarySync;
100
+ const importantOptionKeys = ['name', 'noSuggest', 'useCompounds', 'type'];
51
101
  function calcKey(uri, options) {
52
102
  const loaderType = determineType(uri, options);
53
103
  const optValues = importantOptionKeys.map((k) => { var _a; return ((_a = options[k]) === null || _a === void 0 ? void 0 : _a.toString()) || ''; });
@@ -60,21 +110,39 @@ function calcKey(uri, options) {
60
110
  * @param now - optional timestamp representing now. (Mostly used in testing)
61
111
  */
62
112
  async function refreshCacheEntries(maxAge = MAX_AGE, now = Date.now()) {
63
- await Promise.all([...dictionaryCache].map(([, entry]) => refreshEntry(entry, maxAge, now)));
113
+ await Promise.all([...dictionaryCache.values()].map((entry) => refreshEntry(entry, maxAge, now)));
64
114
  }
65
115
  exports.refreshCacheEntries = refreshCacheEntries;
66
116
  async function refreshEntry(entry, maxAge, now) {
67
117
  if (now - entry.ts >= maxAge) {
118
+ const sig = now + Math.random();
68
119
  // Write to the ts, so the next one will not do it.
120
+ entry.sig = sig;
69
121
  entry.ts = now;
70
- const pStat = (0, fs_extra_1.stat)(entry.uri).catch((e) => e);
71
- const [state, oldState] = await Promise.all([pStat, entry.state]);
72
- if (entry.ts === now && !isEqual(state, oldState)) {
122
+ const pStat = getStat(entry.uri);
123
+ const [newStat] = await Promise.all([pStat, entry.pending]);
124
+ const hasChanged = !isEqual(newStat, entry.stat);
125
+ const sigMatches = entry.sig === sig;
126
+ // if (entry.options.name === 'temp') {
127
+ // const processedAt = Date.now();
128
+ // __log(
129
+ // `Refresh ${entry.options.name}; sig: ${sig.toFixed(
130
+ // 2
131
+ // )} at ${processedAt}; Sig Matches: ${sigMatches.toString()}; changed: ${hasChanged.toString()}; file: ${path.relative(
132
+ // process.cwd(),
133
+ // entry.uri
134
+ // )}`
135
+ // );
136
+ // }
137
+ if (sigMatches && hasChanged) {
138
+ entry.loadingState = LoadingState.Loading;
73
139
  dictionaryCache.set(calcKey(entry.uri, entry.options), loadEntry(entry.uri, entry.options));
74
140
  }
75
141
  }
76
142
  }
77
143
  function isEqual(a, b) {
144
+ if (!b)
145
+ return false;
78
146
  if (isError(a)) {
79
147
  return isError(b) && a.message === b.message && a.name === b.name;
80
148
  }
@@ -82,22 +150,69 @@ function isEqual(a, b) {
82
150
  }
83
151
  function isError(e) {
84
152
  const err = e;
85
- return !!(err.name && err.message);
153
+ return !!err.message;
86
154
  }
87
155
  function loadEntry(uri, options, now = Date.now()) {
88
- const dictionary = load(uri, options).catch((e) => (0, createSpellingDictionary_1.createFailedToLoadDictionary)(new SpellingDictionaryError_1.SpellingDictionaryLoadError(uri, options, e, 'failed to load')));
89
- return {
156
+ const pDictionary = load(uri, options).catch((e) => (0, createSpellingDictionary_1.createFailedToLoadDictionary)(new SpellingDictionaryError_1.SpellingDictionaryLoadError(uri, options, e, 'failed to load')));
157
+ const pStat = getStat(uri);
158
+ const pending = Promise.all([pDictionary, pStat]);
159
+ const sig = now + Math.random();
160
+ const entry = {
90
161
  uri,
91
162
  options,
92
163
  ts: now,
93
- state: (0, fs_extra_1.stat)(uri).catch((e) => e),
94
- dictionary,
164
+ stat: undefined,
165
+ dictionary: undefined,
166
+ pending,
167
+ loadingState: LoadingState.Loading,
168
+ sig,
95
169
  };
170
+ // eslint-disable-next-line promise/catch-or-return
171
+ pending.then(([dictionary, stat]) => {
172
+ entry.stat = stat;
173
+ entry.dictionary = dictionary;
174
+ entry.loadingState = LoadingState.Loaded;
175
+ return;
176
+ });
177
+ return entry;
178
+ }
179
+ function loadEntrySync(uri, options, now = Date.now()) {
180
+ const stat = getStatSync(uri);
181
+ const sig = now + Math.random();
182
+ try {
183
+ const dictionary = loadSync(uri, options);
184
+ const pending = Promise.resolve([dictionary, stat]);
185
+ return {
186
+ uri,
187
+ options,
188
+ ts: now,
189
+ stat,
190
+ dictionary,
191
+ pending,
192
+ loadingState: LoadingState.Loaded,
193
+ sig,
194
+ };
195
+ }
196
+ catch (e) {
197
+ const error = e instanceof Error ? e : new Error((0, util_1.format)(e));
198
+ const dictionary = (0, createSpellingDictionary_1.createFailedToLoadDictionary)(new SpellingDictionaryError_1.SpellingDictionaryLoadError(uri, options, error, 'failed to load'));
199
+ const pending = Promise.resolve([dictionary, stat]);
200
+ return {
201
+ uri,
202
+ options,
203
+ ts: now,
204
+ stat,
205
+ dictionary,
206
+ pending,
207
+ loadingState: LoadingState.Loaded,
208
+ sig,
209
+ };
210
+ }
96
211
  }
97
212
  function determineType(uri, opts) {
98
213
  const t = (opts.type && opts.type in loaders && opts.type) || 'S';
99
214
  const defLoaderType = t;
100
- const defType = uri.endsWith('.trie.gz') ? 'T' : uri.endsWith('.txt.gz') ? defLoaderType : defLoaderType;
215
+ const defType = uri.endsWith('.trie.gz') ? 'T' : defLoaderType;
101
216
  const regTrieTest = /\.trie\b/i;
102
217
  return regTrieTest.test(uri) ? 'T' : defType;
103
218
  }
@@ -106,8 +221,20 @@ function load(uri, options) {
106
221
  const loader = loaders[type] || loaders.default;
107
222
  return loader(uri, options);
108
223
  }
224
+ function loadSync(uri, options) {
225
+ const type = determineType(uri, options);
226
+ const loader = loadersSync[type] || loaders.default;
227
+ return loader(uri, options);
228
+ }
109
229
  async function legacyWordList(filename, options) {
110
230
  const lines = await (0, fileReader_1.readLines)(filename);
231
+ return _legacyWordListSync(lines, filename, options);
232
+ }
233
+ function legacyWordListSync(filename, options) {
234
+ const lines = (0, fileReader_1.readLinesSync)(filename);
235
+ return _legacyWordListSync(lines, filename, options);
236
+ }
237
+ function _legacyWordListSync(lines, filename, options) {
111
238
  const words = (0, gensequence_1.genSequence)(lines)
112
239
  // Remove comments
113
240
  .map((line) => line.replace(/#.*/g, ''))
@@ -118,6 +245,13 @@ async function legacyWordList(filename, options) {
118
245
  }
119
246
  async function wordsPerLineWordList(filename, options) {
120
247
  const lines = await (0, fileReader_1.readLines)(filename);
248
+ return _wordsPerLineWordList(lines, filename, options);
249
+ }
250
+ function wordsPerLineWordListSync(filename, options) {
251
+ const lines = (0, fileReader_1.readLinesSync)(filename);
252
+ return _wordsPerLineWordList(lines, filename, options);
253
+ }
254
+ function _wordsPerLineWordList(lines, filename, options) {
121
255
  const words = (0, gensequence_1.genSequence)(lines)
122
256
  // Remove comments
123
257
  .map((line) => line.replace(/#.*/g, ''))
@@ -130,10 +264,18 @@ async function loadSimpleWordList(filename, options) {
130
264
  const lines = await (0, fileReader_1.readLines)(filename);
131
265
  return (0, createSpellingDictionary_1.createSpellingDictionary)(lines, determineName(filename, options), filename, options);
132
266
  }
267
+ function loadSimpleWordListSync(filename, options) {
268
+ const lines = (0, fileReader_1.readLinesSync)(filename);
269
+ return (0, createSpellingDictionary_1.createSpellingDictionary)(lines, determineName(filename, options), filename, options);
270
+ }
133
271
  async function loadTrie(filename, options) {
134
272
  const lines = await (0, fileReader_1.readLines)(filename);
135
273
  return (0, SpellingDictionaryFromTrie_1.createSpellingDictionaryTrie)(lines, determineName(filename, options), filename, options);
136
274
  }
275
+ function loadTrieSync(filename, options) {
276
+ const lines = (0, fileReader_1.readLinesSync)(filename);
277
+ return (0, SpellingDictionaryFromTrie_1.createSpellingDictionaryTrie)(lines, determineName(filename, options), filename, options);
278
+ }
137
279
  function determineName(filename, options) {
138
280
  return options.name || path.basename(filename);
139
281
  }
@@ -143,4 +285,25 @@ exports.testing = {
143
285
  loadEntry,
144
286
  load,
145
287
  };
288
+ function toError(e) {
289
+ if ((0, errors_1.isErrnoException)(e))
290
+ return e;
291
+ if (e instanceof Error)
292
+ return e;
293
+ return new Error((0, util_1.format)(e));
294
+ }
295
+ function getStat(uri) {
296
+ return fs_1.promises.stat(uri).catch((e) => toError(e));
297
+ }
298
+ function getStatSync(uri) {
299
+ try {
300
+ return (0, fs_1.statSync)(uri);
301
+ }
302
+ catch (e) {
303
+ return toError(e);
304
+ }
305
+ }
306
+ exports.__testing__ = {
307
+ debugLog,
308
+ };
146
309
  //# sourceMappingURL=DictionaryLoader.js.map
@@ -26,7 +26,6 @@ export declare class SpellingDictionaryCollection implements SpellingDictionary
26
26
  export declare function createCollection(dictionaries: SpellingDictionary[], name: string): SpellingDictionaryCollection;
27
27
  declare function isWordInAnyDictionary(dicts: SpellingDictionary[], word: string, options: SearchOptions): SpellingDictionary | undefined;
28
28
  declare function isWordForbiddenInAnyDictionary(dicts: SpellingDictionary[], word: string): SpellingDictionary | undefined;
29
- export declare function createCollectionP(dicts: (Promise<SpellingDictionary> | SpellingDictionary)[], name: string): Promise<SpellingDictionaryCollection>;
30
29
  export declare const __testing__: {
31
30
  isWordInAnyDictionary: typeof isWordInAnyDictionary;
32
31
  isWordForbiddenInAnyDictionary: typeof isWordForbiddenInAnyDictionary;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.__testing__ = exports.createCollectionP = exports.createCollection = exports.SpellingDictionaryCollection = void 0;
3
+ exports.__testing__ = exports.createCollection = exports.SpellingDictionaryCollection = void 0;
4
4
  const cspell_trie_lib_1 = require("cspell-trie-lib");
5
5
  const gensequence_1 = require("gensequence");
6
6
  const Settings_1 = require("../Settings");
@@ -54,23 +54,21 @@ class SpellingDictionaryCollection {
54
54
  return this._suggest(word, suggestOptions);
55
55
  }
56
56
  _suggest(word, suggestOptions) {
57
- const _suggestOptions = { ...suggestOptions };
58
- const { numSuggestions = (0, Settings_1.getDefaultSettings)().numSuggestions || SpellingDictionaryMethods_1.defaultNumSuggestions, numChanges, compoundMethod, ignoreCase, includeTies, timeout, } = suggestOptions;
59
- _suggestOptions.compoundMethod = this.options.useCompounds ? SpellingDictionary_1.CompoundWordsMethod.JOIN_WORDS : compoundMethod;
57
+ const { numSuggestions = (0, Settings_1.getDefaultSettings)().numSuggestions || SpellingDictionaryMethods_1.defaultNumSuggestions, numChanges, ignoreCase, includeTies, timeout, } = suggestOptions;
60
58
  const prefixNoCase = cspell_trie_lib_1.CASE_INSENSITIVE_PREFIX;
61
59
  const filter = (word, _cost) => {
62
60
  return ((ignoreCase || word[0] !== prefixNoCase) &&
63
61
  !this.isForbidden(word) &&
64
62
  !this.isNoSuggestWord(word, suggestOptions));
65
63
  };
66
- const collector = (0, SpellingDictionaryMethods_1.suggestionCollector)(word, {
64
+ const collector = (0, SpellingDictionaryMethods_1.suggestionCollector)(word, (0, util_1.clean)({
67
65
  numSuggestions,
68
66
  filter,
69
67
  changeLimit: numChanges,
70
68
  includeTies,
71
69
  ignoreCase,
72
70
  timeout,
73
- });
71
+ }));
74
72
  this.genSuggestions(collector, suggestOptions);
75
73
  return collector.suggestions.map((r) => ({ ...r, word: r.word }));
76
74
  }
@@ -111,10 +109,6 @@ function isNoSuggestWordInAnyDictionary(dicts, word, options) {
111
109
  function isWordForbiddenInAnyDictionary(dicts, word) {
112
110
  return (0, gensequence_1.genSequence)(dicts).first((dict) => dict.isForbidden(word));
113
111
  }
114
- function createCollectionP(dicts, name) {
115
- return Promise.all(dicts).then((dicts) => new SpellingDictionaryCollection(dicts, name));
116
- }
117
- exports.createCollectionP = createCollectionP;
118
112
  exports.__testing__ = {
119
113
  isWordInAnyDictionary,
120
114
  isWordForbiddenInAnyDictionary,
@@ -30,5 +30,5 @@ export declare class SpellingDictionaryFromTrie implements SpellingDictionary {
30
30
  genSuggestions(collector: SuggestionCollector, suggestOptions: SuggestOptions): void;
31
31
  getErrors(): Error[];
32
32
  }
33
- export declare function createSpellingDictionaryTrie(data: Iterable<string>, name: string, source: string, options: SpellingDictionaryOptions): Promise<SpellingDictionary>;
33
+ export declare function createSpellingDictionaryTrie(data: Iterable<string>, name: string, source: string, options: SpellingDictionaryOptions): SpellingDictionary;
34
34
  //# sourceMappingURL=SpellingDictionaryFromTrie.d.ts.map