cspell 9.1.5 → 9.2.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/esm/app.d.ts CHANGED
@@ -15,5 +15,5 @@ declare class ApplicationError extends Error {
15
15
  //#region src/app.d.mts
16
16
  declare function run(command?: Command, argv?: string[]): Promise<void>;
17
17
  //#endregion
18
- export { ApplicationError, CheckFailed, LinterCliOptions as Options, run };
18
+ export { ApplicationError, CheckFailed, type LinterCliOptions as Options, run };
19
19
  //# sourceMappingURL=app.d.ts.map
package/dist/esm/app.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ApplicationError, CheckFailed, DEFAULT_CACHE_LOCATION, IncludeExcludeFlag, ReportChoicesAll, checkText, console, createInit, lint, listDictionaries, npmPackage, parseApplicationFeatureFlags, suggestions, trace } from "./application-D-NwS6qb.js";
1
+ import { ApplicationError, CheckFailed, DEFAULT_CACHE_LOCATION, IncludeExcludeFlag, ReportChoicesAll, checkText, console, createInit, lint, listDictionaries, npmPackage, parseApplicationFeatureFlags, suggestions, trace } from "./application-_MFvh02K.js";
2
2
  import { Option, program } from "commander";
3
3
  import { satisfies } from "semver";
4
4
  import chalk from "chalk";
@@ -323,16 +323,16 @@ function decorateRowWith(row, ...decorators) {
323
323
 
324
324
  //#endregion
325
325
  //#region src/emitters/helpers.ts
326
- function trimMidPath(s, w, sep) {
326
+ function trimMidPath(s, w, sep$1) {
327
327
  if (s.length <= w) return s;
328
- const parts = s.split(sep);
328
+ const parts = s.split(sep$1);
329
329
  if (parts[parts.length - 1].length > w) return trimMid(s, w);
330
330
  function join(left$1, right$1) {
331
331
  return [
332
332
  ...parts.slice(0, left$1),
333
333
  "…",
334
334
  ...parts.slice(right$1)
335
- ].join(sep);
335
+ ].join(sep$1);
336
336
  }
337
337
  let left = 0, right = parts.length, last = "";
338
338
  for (let i = 0; i < parts.length; ++i) {
@@ -112,5 +112,5 @@ declare function suggestions(words: string[], options: SuggestionOptions): Async
112
112
  declare function createInit(options: InitOptions): Promise<void>;
113
113
  declare function parseApplicationFeatureFlags(flags: string[] | undefined): FeatureFlags;
114
114
  //#endregion
115
- export { AppError, CheckTextResult, IncludeExcludeFlag, TraceResult, checkText, createInit, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace };
116
- //# sourceMappingURL=application-DbOQYm56.d.ts.map
115
+ export { AppError, CheckTextResult, IncludeExcludeFlag, type TraceResult, checkText, createInit, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace };
116
+ //# sourceMappingURL=application-D8WjsMdV.d.ts.map
@@ -5,27 +5,25 @@ import * as cspell from "cspell-lib";
5
5
  import { ENV_CSPELL_GLOB_ROOT, IncludeExcludeFlag, SuggestionError, Text, checkTextDocument, combineTextAndLanguageSettings, createPerfTimer, extractDependencies, extractImportErrors, fileToDocument, getDefaultSettings, getDictionary, getGlobalSettingsAsync, getSystemFeatureFlags, isBinaryFile, isSpellingDictionaryLoadError, mergeSettings, setLogger, shouldCheckDocument, spellCheckDocument, suggestionsForWords, traceWordsAsync } from "cspell-lib";
6
6
  import assert from "node:assert";
7
7
  import { format, formatWithOptions } from "node:util";
8
- import { toFileDirURL, toFilePathOrHref, toFileURL, urlRelative } from "@cspell/url";
8
+ import { isUrlLike, toFileDirURL, toFilePathOrHref, toFileURL, urlRelative } from "@cspell/url";
9
9
  import { makeTemplate } from "chalk-template";
10
10
  import fs, { stat } from "node:fs/promises";
11
11
  import { MutableCSpellConfigFile, createReaderWriter, cspellConfigFileSchema, isCfgArrayNode } from "cspell-config-lib";
12
- import * as fs$1 from "node:fs";
13
- import { mkdirSync, promises } from "node:fs";
12
+ import { promises } from "node:fs";
14
13
  import { fileURLToPath } from "node:url";
15
14
  import * as path$1 from "node:path";
16
- import path, { dirname, isAbsolute, posix, relative, resolve } from "node:path";
15
+ import path, { isAbsolute, posix, relative, resolve, sep } from "node:path";
17
16
  import { opMap as opMap$1, pipe } from "@cspell/cspell-pipe/sync";
18
17
  import { IssueType, MessageTypes, unknownWordsChoices } from "@cspell/cspell-types";
19
18
  import { _debug } from "cspell-dictionary";
20
19
  import { GitIgnore, findRepoRoot } from "cspell-gitignore";
21
20
  import { GlobMatcher, fileOrGlobToGlob, workaroundPicomatchBug } from "cspell-glob";
22
- import * as crypto from "node:crypto";
21
+ import crypto from "node:crypto";
23
22
  import streamConsumers from "node:stream/consumers";
24
23
  import { readFileText, toURL } from "cspell-io";
25
24
  import { glob } from "tinyglobby";
26
25
  import * as readline from "node:readline";
27
- import { isMainThread } from "node:worker_threads";
28
- import fileEntryCache from "file-entry-cache";
26
+ import { parse, stringify } from "flatted";
29
27
  import { dynamicImport } from "@cspell/dynamic-import";
30
28
 
31
29
  //#region src/console.ts
@@ -791,7 +789,7 @@ const pkgDir = _dirname;
791
789
  //#endregion
792
790
  //#region src/pkgInfo.ts
793
791
  const name = "cspell";
794
- const version$1 = "9.1.5";
792
+ const version$1 = "9.2.0";
795
793
  const engines = { node: ">=20" };
796
794
  const npmPackage = {
797
795
  name,
@@ -813,6 +811,7 @@ const STDIN = "stdin";
813
811
  const STDINProtocol = "stdin:";
814
812
  const STDINUrlPrefix = "stdin://";
815
813
  const FileUrlPrefix = "file://";
814
+ const FileUrlAbsPrefix = "file:///";
816
815
 
817
816
  //#endregion
818
817
  //#region src/util/glob.ts
@@ -972,7 +971,7 @@ function resolveStdinUrl(url, cwd) {
972
971
  assert(url.startsWith(STDINProtocol), `Expected url to start with ${STDINProtocol}`);
973
972
  const path$2 = decodeURIComponent(url).slice(STDINProtocol.length).replace(/^\/\//, "").replace(/^\/([a-z]:)/i, "$1");
974
973
  const fileUrl = toFileURL(path$2, cwd);
975
- return fileUrl.toString().replace(/^file:/, STDINProtocol) + (path$2 ? "" : "/");
974
+ return new URL(fileUrl.toString().replace(/^file:/, STDINProtocol) + (path$2 ? "" : "/"));
976
975
  }
977
976
 
978
977
  //#endregion
@@ -1005,15 +1004,17 @@ function isBinaryFile$1(filename, cwd) {
1005
1004
  if (uri.protocol.startsWith("stdin")) return false;
1006
1005
  return isBinaryFile(uri);
1007
1006
  }
1007
+ function resolveFilenameToUrl(filename, cwd) {
1008
+ if (filename instanceof URL) return filename;
1009
+ if (filename === STDIN) return new URL(STDINUrlPrefix);
1010
+ if (filename.startsWith(FileUrlAbsPrefix)) return new URL(filename);
1011
+ const cwdUrl = toFileDirURL(cwd || process.cwd());
1012
+ if (filename.startsWith(FileUrlPrefix)) return new URL(filename.slice(FileUrlPrefix.length), cwdUrl);
1013
+ if (isStdinUrl(filename)) return resolveStdinUrl(filename, cwdUrl);
1014
+ return toFileURL(filename, cwdUrl);
1015
+ }
1008
1016
  function resolveFilename(filename, cwd) {
1009
- cwd = cwd || process.cwd();
1010
- if (filename === STDIN) return STDINUrlPrefix;
1011
- if (filename.startsWith(FileUrlPrefix)) {
1012
- const url = new URL(filename.slice(FileUrlPrefix.length), toFileDirURL(cwd));
1013
- return fileURLToPath(url);
1014
- }
1015
- if (isStdinUrl(filename)) return resolveStdinUrl(filename, cwd);
1016
- return path$1.resolve(cwd, filename);
1017
+ return toFilePathOrHref(resolveFilenameToUrl(filename, cwd));
1017
1018
  }
1018
1019
  function readFileInfo(filename, encoding = UTF8, handleNotFound = false) {
1019
1020
  filename = resolveFilename(filename);
@@ -1114,78 +1115,237 @@ function relativeToCwd(filename, cwd = process.cwd()) {
1114
1115
  }
1115
1116
 
1116
1117
  //#endregion
1117
- //#region src/util/cache/file-entry-cache.mts
1118
- function createFromFile$1(pathToCache, useChecksum) {
1119
- return fileEntryCache.createFromFile(pathToCache, useChecksum);
1118
+ //#region src/util/cache/file-entry-cache/flatCache.ts
1119
+ var FlatCache = class {
1120
+ #cache;
1121
+ constructor(cacheFilename) {
1122
+ this.cacheFilename = cacheFilename;
1123
+ this.#cache = /* @__PURE__ */ new Map();
1124
+ }
1125
+ keys() {
1126
+ return this.#cache.keys();
1127
+ }
1128
+ set(key, value) {
1129
+ this.#cache.set(key, value);
1130
+ return this;
1131
+ }
1132
+ removeKey(key) {
1133
+ this.#cache.delete(key);
1134
+ }
1135
+ get(key) {
1136
+ return this.#cache.get(key);
1137
+ }
1138
+ async load(ifFound = true) {
1139
+ this.#cache.clear();
1140
+ try {
1141
+ const content = await fs.readFile(this.cacheFilename, "utf8");
1142
+ this.#cache = new Map(Object.entries(parse(content)));
1143
+ } catch (error) {
1144
+ if (!ifFound) throw error;
1145
+ }
1146
+ return this;
1147
+ }
1148
+ async save() {
1149
+ const dir = new URL(".", this.cacheFilename);
1150
+ await fs.mkdir(dir, { recursive: true });
1151
+ const content = stringify(Object.fromEntries(this.#cache.entries()));
1152
+ await fs.writeFile(this.cacheFilename, content, "utf8");
1153
+ }
1154
+ /**
1155
+ * Clear the cache and remove the cache file from disk.
1156
+ */
1157
+ async destroy() {
1158
+ this.#cache.clear();
1159
+ try {
1160
+ await fs.unlink(this.cacheFilename);
1161
+ } catch {}
1162
+ }
1163
+ };
1164
+ /**
1165
+ *
1166
+ * @param cachefile - The location of the cache file.
1167
+ * @returns
1168
+ */
1169
+ function loadCacheFile(cachefile) {
1170
+ const cache = new FlatCache(cachefile);
1171
+ return cache.load();
1120
1172
  }
1121
1173
 
1122
1174
  //#endregion
1123
- //#region src/util/cache/fileEntryCache.ts
1124
- function createFromFile(pathToCache, useCheckSum, useRelative) {
1125
- const absPathToCache = path$1.resolve(pathToCache);
1126
- const relDir = path$1.dirname(absPathToCache);
1127
- mkdirSync(relDir, { recursive: true });
1128
- const create = wrap(() => createFromFile$1(absPathToCache, useCheckSum));
1129
- const feCache = create();
1130
- const cacheWrapper = {
1131
- get cache() {
1132
- return feCache.cache;
1133
- },
1134
- getHash(buffer) {
1135
- return feCache.getHash(buffer);
1136
- },
1137
- hasFileChanged: wrap((cwd, file) => {
1138
- return feCache.hasFileChanged(resolveFile(cwd, file));
1139
- }),
1140
- analyzeFiles: wrap((cwd, files) => {
1141
- return feCache.analyzeFiles(resolveFiles(cwd, files));
1142
- }),
1143
- getFileDescriptor: wrap((cwd, file) => {
1144
- return feCache.getFileDescriptor(resolveFile(cwd, file));
1145
- }),
1146
- getUpdatedFiles: wrap((cwd, files) => {
1147
- return feCache.getUpdatedFiles(resolveFiles(cwd, files));
1148
- }),
1149
- normalizeEntries: wrap((cwd, files) => {
1150
- return feCache.normalizeEntries(resolveFiles(cwd, files));
1151
- }),
1152
- removeEntry: wrap((cwd, file) => {
1153
- return feCache.removeEntry(resolveFile(cwd, file));
1154
- }),
1155
- deleteCacheFile() {
1156
- feCache.deleteCacheFile();
1157
- },
1158
- destroy() {
1159
- feCache.destroy();
1160
- },
1161
- reconcile: wrap((_cwd, noPrune) => {
1162
- feCache.reconcile(noPrune);
1163
- })
1164
- };
1165
- return cacheWrapper;
1166
- function resolveFile(cwd, file) {
1167
- if (!useRelative) return normalizePath(file);
1168
- const r = path$1.relative(relDir, path$1.resolve(cwd, file));
1169
- return normalizePath(r);
1170
- }
1171
- function resolveFiles(cwd, files) {
1172
- return files?.map((file) => resolveFile(cwd, file));
1173
- }
1174
- function wrap(fn) {
1175
- return (...params) => {
1176
- const cwd = process.cwd();
1177
- try {
1178
- isMainThread && process.chdir(relDir);
1179
- return fn(cwd, ...params);
1180
- } finally {
1181
- isMainThread && process.chdir(cwd);
1182
- }
1175
+ //#region src/util/cache/file-entry-cache/file-entry-cache.ts
1176
+ async function createFromFile$1(cacheFileUrl, useChecksum, currentWorkingDir) {
1177
+ const cache = await loadCacheFile(cacheFileUrl);
1178
+ const fec = new ImplFileEntryCache(cache, useChecksum ?? false, currentWorkingDir);
1179
+ await fec.removeNotFoundFiles();
1180
+ return fec;
1181
+ }
1182
+ var ImplFileEntryCache = class {
1183
+ cache;
1184
+ useChecksum;
1185
+ #normalizedEntries = /* @__PURE__ */ new Map();
1186
+ /**
1187
+ * To enable relative paths as the key with current working directory
1188
+ */
1189
+ currentWorkingDir;
1190
+ constructor(cache, useChecksum, currentWorkingDir) {
1191
+ this.cache = cache;
1192
+ this.useChecksum = useChecksum || false;
1193
+ this.currentWorkingDir = currentWorkingDir ? fileURLToPath(currentWorkingDir) : void 0;
1194
+ }
1195
+ async removeNotFoundFiles() {
1196
+ for (const fPath of this.cache.keys()) try {
1197
+ const filePath = this.resolveKeyToFile(fPath);
1198
+ await fs.stat(filePath);
1199
+ } catch (error) {
1200
+ if (isNodeError(error) && error.code === "ENOENT") this.cache.removeKey(fPath);
1201
+ }
1202
+ }
1203
+ /**
1204
+ * Given a buffer, calculate md5 hash of its content.
1205
+ * @param buffer buffer to calculate hash on
1206
+ * @return content hash digest
1207
+ */
1208
+ #getHash(buffer) {
1209
+ return crypto.createHash("md5").update(buffer).digest("hex");
1210
+ }
1211
+ async getFileDescriptor(file) {
1212
+ let fstat;
1213
+ try {
1214
+ fstat = await fs.stat(file);
1215
+ } catch (error) {
1216
+ this.#removeEntry(file);
1217
+ return {
1218
+ key: file,
1219
+ notFound: true,
1220
+ err: toError$1(error)
1221
+ };
1222
+ }
1223
+ if (this.useChecksum) return this.#getFileDescriptorUsingChecksum(file);
1224
+ return this.#getFileDescriptorUsingMtimeAndSize(file, fstat);
1225
+ }
1226
+ #getFileDescriptorUsingMtimeAndSize(file, fstat) {
1227
+ const key = this.#getFileKey(file);
1228
+ let meta = this.cache.get(key);
1229
+ const cacheExists = !!meta;
1230
+ const cSize = fstat.size;
1231
+ const cTime = fstat.mtime.getTime();
1232
+ let isDifferentDate;
1233
+ let isDifferentSize;
1234
+ if (meta) {
1235
+ isDifferentDate = cTime !== meta.mtime;
1236
+ isDifferentSize = cSize !== meta.size;
1237
+ } else meta = {
1238
+ size: cSize,
1239
+ mtime: cTime
1183
1240
  };
1241
+ const nEntry = {
1242
+ key,
1243
+ changed: !cacheExists || isDifferentDate || isDifferentSize,
1244
+ meta
1245
+ };
1246
+ this.#normalizedEntries.set(key, nEntry);
1247
+ return nEntry;
1248
+ }
1249
+ async #getFileDescriptorUsingChecksum(file) {
1250
+ const key = this.#getFileKey(file);
1251
+ let meta = this.cache.get(key);
1252
+ const cacheExists = !!meta;
1253
+ let contentBuffer;
1254
+ try {
1255
+ contentBuffer = await fs.readFile(file);
1256
+ } catch {
1257
+ contentBuffer = "";
1258
+ }
1259
+ let isDifferent = true;
1260
+ const hash = this.#getHash(contentBuffer);
1261
+ if (meta) isDifferent = hash !== meta.hash;
1262
+ else meta = { hash };
1263
+ const nEntry = {
1264
+ key,
1265
+ changed: !cacheExists || isDifferent,
1266
+ meta
1267
+ };
1268
+ this.#normalizedEntries.set(key, nEntry);
1269
+ return nEntry;
1270
+ }
1271
+ /**
1272
+ * Remove an entry from the file-entry-cache. Useful to force the file to still be considered
1273
+ * modified the next time the process is run
1274
+ */
1275
+ #removeEntry(file) {
1276
+ const key = this.#getFileKey(file);
1277
+ this.#normalizedEntries.delete(key);
1278
+ this.cache.removeKey(key);
1279
+ }
1280
+ /**
1281
+ * Deletes the cache file from the disk and clears the memory cache
1282
+ */
1283
+ async destroy() {
1284
+ this.#normalizedEntries.clear();
1285
+ await this.cache.destroy();
1286
+ }
1287
+ async #getMetaForFileUsingCheckSum(cacheEntry) {
1288
+ const filePath = this.resolveKeyToFile(cacheEntry.key);
1289
+ const contentBuffer = await fs.readFile(filePath);
1290
+ const hash = this.#getHash(contentBuffer);
1291
+ const meta = {
1292
+ ...cacheEntry.meta,
1293
+ hash
1294
+ };
1295
+ delete meta.size;
1296
+ delete meta.mtime;
1297
+ return meta;
1298
+ }
1299
+ async #getMetaForFileUsingMtimeAndSize(cacheEntry) {
1300
+ const filePath = this.resolveKeyToFile(cacheEntry.key);
1301
+ const stat$1 = await fs.stat(filePath);
1302
+ const meta = {
1303
+ ...cacheEntry.meta,
1304
+ size: stat$1.size,
1305
+ mtime: stat$1.mtime.getTime()
1306
+ };
1307
+ delete meta.hash;
1308
+ return meta;
1309
+ }
1310
+ /**
1311
+ * Sync the files and persist them to the cache
1312
+ */
1313
+ async reconcile() {
1314
+ await this.removeNotFoundFiles();
1315
+ for (const [entryKey, cacheEntry] of this.#normalizedEntries.entries()) try {
1316
+ const meta = this.useChecksum ? await this.#getMetaForFileUsingCheckSum(cacheEntry) : await this.#getMetaForFileUsingMtimeAndSize(cacheEntry);
1317
+ this.cache.set(entryKey, meta);
1318
+ } catch (error) {
1319
+ if (!isNodeError(error) || error.code !== "ENOENT") throw error;
1320
+ }
1321
+ this.cache.save();
1184
1322
  }
1323
+ resolveKeyToFile(entryKey) {
1324
+ if (this.currentWorkingDir) return path.resolve(this.currentWorkingDir, entryKey);
1325
+ return entryKey;
1326
+ }
1327
+ #getFileKey(file) {
1328
+ if (this.currentWorkingDir && path.isAbsolute(file)) return normalizePath$1(path.relative(this.currentWorkingDir, file));
1329
+ return normalizePath$1(file);
1330
+ }
1331
+ };
1332
+ function isNodeError(error) {
1333
+ return typeof error === "object" && error !== null && "code" in error;
1185
1334
  }
1186
- function normalizePath(filePath) {
1187
- if (path$1.sep === "/") return filePath;
1188
- return filePath.split(path$1.sep).join("/");
1335
+ function toError$1(error) {
1336
+ if (error instanceof Error) return error;
1337
+ if (typeof error === "string") return new Error(error);
1338
+ return new Error("Unknown error", { cause: error });
1339
+ }
1340
+ function normalizePath$1(filePath) {
1341
+ if (path.sep === "/") return filePath;
1342
+ return filePath.split(path.sep).join("/");
1343
+ }
1344
+
1345
+ //#endregion
1346
+ //#region src/util/cache/fileEntryCache.ts
1347
+ function createFromFile(cacheFileUrl, useCheckSum, useRelative) {
1348
+ return createFromFile$1(cacheFileUrl, useCheckSum, useRelative ? new URL("./", cacheFileUrl) : void 0);
1189
1349
  }
1190
1350
 
1191
1351
  //#endregion
@@ -1230,31 +1390,29 @@ const META_DATA_VERSION_SUFFIX = "-" + META_DATA_BASE_VERSION + "-" + Object.key
1230
1390
  * Caches cspell results on disk
1231
1391
  */
1232
1392
  var DiskCache = class {
1233
- cacheFileLocation;
1234
1393
  cacheDir;
1235
- fileEntryCache;
1236
1394
  dependencyCache = /* @__PURE__ */ new Map();
1237
1395
  dependencyCacheTree = {};
1238
1396
  objectCollection = new ShallowObjectCollection();
1239
1397
  ocCacheFileResult = new ShallowObjectCollection();
1240
1398
  version;
1241
- constructor(cacheFileLocation, useCheckSum, cspellVersion, useUniversalCache) {
1399
+ constructor(cacheFileLocation, useCheckSum, cspellVersion, useUniversalCache, fileEntryCache) {
1400
+ this.cacheFileLocation = cacheFileLocation;
1242
1401
  this.useCheckSum = useCheckSum;
1243
1402
  this.cspellVersion = cspellVersion;
1244
1403
  this.useUniversalCache = useUniversalCache;
1245
- this.cacheFileLocation = resolve(cacheFileLocation);
1246
- this.cacheDir = dirname(this.cacheFileLocation);
1247
- this.fileEntryCache = createFromFile(this.cacheFileLocation, useCheckSum, useUniversalCache);
1404
+ this.fileEntryCache = fileEntryCache;
1405
+ this.cacheDir = fileURLToPath(new URL("./", cacheFileLocation));
1248
1406
  this.version = calcVersion(cspellVersion);
1249
1407
  }
1250
1408
  async getCachedLintResults(filename) {
1251
1409
  filename = normalizePath(filename);
1252
- const fileDescriptor = this.fileEntryCache.getFileDescriptor(filename);
1410
+ const fileDescriptor = await this.fileEntryCache.getFileDescriptor(filename);
1253
1411
  const meta = fileDescriptor.meta;
1254
1412
  const data = meta?.data;
1255
1413
  const result = data?.r;
1256
1414
  const versionMatches = this.version === data?.v;
1257
- if (fileDescriptor.notFound || fileDescriptor.changed || !meta || !result || !versionMatches || !this.checkDependencies(data.d)) return void 0;
1415
+ if (fileDescriptor.notFound || fileDescriptor.changed || !meta || !result || !versionMatches || !await this.checkDependencies(data.d)) return void 0;
1258
1416
  const dd = { ...data };
1259
1417
  if (dd.d) dd.d = setTreeEntry(this.dependencyCacheTree, dd.d);
1260
1418
  dd.r = dd.r && this.normalizeResult(dd.r);
@@ -1269,22 +1427,22 @@ var DiskCache = class {
1269
1427
  cached
1270
1428
  };
1271
1429
  }
1272
- setCachedLintResults({ fileInfo, elapsedTimeMs: _, cached: __,...result }, dependsUponFiles) {
1273
- const fileDescriptor = this.fileEntryCache.getFileDescriptor(fileInfo.filename);
1430
+ async setCachedLintResults({ fileInfo, elapsedTimeMs: _, cached: __,...result }, dependsUponFiles) {
1431
+ const fileDescriptor = await this.fileEntryCache.getFileDescriptor(fileInfo.filename);
1274
1432
  const meta = fileDescriptor.meta;
1275
1433
  if (fileDescriptor.notFound || !meta) return;
1276
1434
  const data = this.objectCollection.get({
1277
1435
  v: this.version,
1278
1436
  r: this.normalizeResult(result),
1279
- d: this.calcDependencyHashes(dependsUponFiles)
1437
+ d: await this.calcDependencyHashes(dependsUponFiles)
1280
1438
  });
1281
1439
  meta.data = data;
1282
1440
  }
1283
- reconcile() {
1284
- this.fileEntryCache.reconcile();
1441
+ async reconcile() {
1442
+ await this.fileEntryCache.reconcile();
1285
1443
  }
1286
- reset() {
1287
- this.fileEntryCache.destroy();
1444
+ async reset() {
1445
+ await this.fileEntryCache.destroy();
1288
1446
  this.dependencyCache.clear();
1289
1447
  this.dependencyCacheTree = {};
1290
1448
  this.objectCollection = new ShallowObjectCollection();
@@ -1301,19 +1459,19 @@ var DiskCache = class {
1301
1459
  reportIssueOptions
1302
1460
  });
1303
1461
  }
1304
- calcDependencyHashes(dependsUponFiles) {
1462
+ async calcDependencyHashes(dependsUponFiles) {
1305
1463
  dependsUponFiles.sort();
1306
1464
  const c = getTreeEntry(this.dependencyCacheTree, dependsUponFiles);
1307
1465
  if (c?.d) return c.d;
1308
- const dependencies = dependsUponFiles.map((f) => this.getDependency(f));
1466
+ const dependencies = await Promise.all(dependsUponFiles.map((f) => this.getDependency(f)));
1309
1467
  return setTreeEntry(this.dependencyCacheTree, dependencies);
1310
1468
  }
1311
- checkDependency(dep) {
1469
+ async checkDependency(dep) {
1312
1470
  const depFile = this.resolveFile(dep.f);
1313
1471
  const cDep = this.dependencyCache.get(depFile);
1314
1472
  if (cDep && compDep(dep, cDep)) return true;
1315
1473
  if (cDep) return false;
1316
- const d = this.getFileDep(depFile);
1474
+ const d = await this.getFileDep(depFile);
1317
1475
  if (compDep(dep, d)) {
1318
1476
  this.dependencyCache.set(depFile, dep);
1319
1477
  return true;
@@ -1321,19 +1479,23 @@ var DiskCache = class {
1321
1479
  this.dependencyCache.set(depFile, d);
1322
1480
  return false;
1323
1481
  }
1324
- getDependency(file) {
1482
+ async getDependency(file) {
1325
1483
  const dep = this.dependencyCache.get(file);
1326
1484
  if (dep) return dep;
1327
- const d = this.getFileDep(file);
1485
+ const d = await this.getFileDep(file);
1328
1486
  this.dependencyCache.set(file, d);
1329
1487
  return d;
1330
1488
  }
1331
- getFileDep(file) {
1489
+ async getFileDep(file) {
1490
+ if (isUrlLike(file)) {
1491
+ if (!file.startsWith("file://")) return getDependencyForUrl(file);
1492
+ file = toFilePathOrHref(file);
1493
+ }
1332
1494
  assert(isAbsolute(file), `Dependency must be absolute "${file}"`);
1333
1495
  const f = this.toRelFile(file);
1334
1496
  let h;
1335
1497
  try {
1336
- const buffer = fs$1.readFileSync(file);
1498
+ const buffer = await fs.readFile(file);
1337
1499
  h = this.getHash(buffer);
1338
1500
  } catch {
1339
1501
  return { f };
@@ -1343,21 +1505,43 @@ var DiskCache = class {
1343
1505
  h
1344
1506
  };
1345
1507
  }
1346
- checkDependencies(dependencies) {
1508
+ async checkDependencies(dependencies) {
1347
1509
  if (!dependencies) return false;
1348
- for (const dep of dependencies) if (!this.checkDependency(dep)) return false;
1510
+ for (const dep of dependencies) if (!await this.checkDependency(dep)) return false;
1349
1511
  return true;
1350
1512
  }
1351
1513
  getHash(buffer) {
1352
1514
  return crypto.createHash("md5").update(buffer).digest("hex");
1353
1515
  }
1354
1516
  resolveFile(file) {
1517
+ if (isUrlLike(file)) return file;
1355
1518
  return normalizePath(resolve(this.cacheDir, file));
1356
1519
  }
1357
1520
  toRelFile(file) {
1358
1521
  return normalizePath(this.useUniversalCache ? relative(this.cacheDir, file) : file);
1359
1522
  }
1360
1523
  };
1524
+ async function getDependencyForUrl(remoteUrl) {
1525
+ const url = new URL(remoteUrl);
1526
+ try {
1527
+ const response = await fetch(url, { method: "HEAD" });
1528
+ const h = response.headers.get("etag") || response.headers.get("last-modified") || response.headers.get("content-length") || "";
1529
+ return {
1530
+ f: url.href,
1531
+ h: h ? h.trim() : ""
1532
+ };
1533
+ } catch {
1534
+ return {
1535
+ f: url.href,
1536
+ h: ""
1537
+ };
1538
+ }
1539
+ }
1540
+ async function createDiskCache(cacheFileLocation, useCheckSum, cspellVersion, useUniversalCache) {
1541
+ const fileEntryCache = await createFromFile(cacheFileLocation, useCheckSum, useUniversalCache);
1542
+ const cache = new DiskCache(cacheFileLocation, useCheckSum, cspellVersion, useUniversalCache, fileEntryCache);
1543
+ return cache;
1544
+ }
1361
1545
  function getTreeEntry(tree, keys) {
1362
1546
  let r = tree;
1363
1547
  for (const k of keys) {
@@ -1389,6 +1573,10 @@ function compDep(a, b) {
1389
1573
  function calcVersion(version$2) {
1390
1574
  return version$2 + META_DATA_VERSION_SUFFIX;
1391
1575
  }
1576
+ function normalizePath(filePath) {
1577
+ if (sep === "/") return filePath;
1578
+ return filePath.split(sep).join("/");
1579
+ }
1392
1580
 
1393
1581
  //#endregion
1394
1582
  //#region src/util/cache/DummyCache.ts
@@ -1400,13 +1588,13 @@ var DummyCache = class {
1400
1588
  return Promise.resolve(void 0);
1401
1589
  }
1402
1590
  setCachedLintResults() {
1403
- return;
1591
+ return Promise.resolve();
1404
1592
  }
1405
1593
  reconcile() {
1406
- return;
1594
+ return Promise.resolve();
1407
1595
  }
1408
1596
  reset() {
1409
- return;
1597
+ return Promise.resolve();
1410
1598
  }
1411
1599
  };
1412
1600
 
@@ -1417,14 +1605,14 @@ const versionSuffix = "";
1417
1605
  /**
1418
1606
  * Creates CSpellLintResultCache (disk cache if caching is enabled in config or dummy otherwise)
1419
1607
  */
1420
- function createCache(options) {
1608
+ async function createCache(options) {
1421
1609
  const { useCache, cacheLocation, cacheStrategy, reset } = options;
1422
- const location = path.resolve(cacheLocation);
1610
+ const location = toFileURL(cacheLocation);
1423
1611
  const useChecksum = cacheStrategy === "content";
1424
1612
  const version$2 = normalizeVersion(options.version);
1425
1613
  const useUniversal = options.cacheFormat === "universal";
1426
- const cache = useCache ? new DiskCache(location, useChecksum, version$2, useUniversal) : new DummyCache();
1427
- reset && cache.reset();
1614
+ const cache = useCache ? await createDiskCache(location, useChecksum, version$2, useUniversal) : new DummyCache();
1615
+ if (reset) await cache.reset();
1428
1616
  return cache;
1429
1617
  }
1430
1618
  async function calcCacheSettings(config, cacheOptions, root) {
@@ -1796,7 +1984,7 @@ async function runLint(cfg) {
1796
1984
  result: Promise.resolve({ skip: true })
1797
1985
  };
1798
1986
  const reportIssueOptions = extractReporterIssueOptions(configInfo.config);
1799
- async function fetch() {
1987
+ async function fetch$1() {
1800
1988
  const getElapsedTimeMs = getTimeMeasurer();
1801
1989
  const cachedResult = await cache.getCachedLintResults(filename);
1802
1990
  if (cachedResult) {
@@ -1816,7 +2004,7 @@ async function runLint(cfg) {
1816
2004
  reportIssueOptions
1817
2005
  };
1818
2006
  }
1819
- const result = fetch();
2007
+ const result = fetch$1();
1820
2008
  return {
1821
2009
  filename,
1822
2010
  result
@@ -1902,7 +2090,7 @@ async function runLint(cfg) {
1902
2090
  reporter.debug(JSON.stringify(debugCfg, void 0, 2));
1903
2091
  }
1904
2092
  const dep = calcDependencies(config);
1905
- cache.setCachedLintResults(result, dep.files);
2093
+ await cache.setCachedLintResults(result, dep.files);
1906
2094
  return result;
1907
2095
  }
1908
2096
  function mapIssue({ doc: _,...tdo }) {
@@ -1915,7 +2103,7 @@ async function runLint(cfg) {
1915
2103
  async function processFiles(files, configInfo, cacheSettings) {
1916
2104
  const fileCount = Array.isArray(files) ? files.length : void 0;
1917
2105
  const status = runResult();
1918
- const cache = createCache(cacheSettings);
2106
+ const cache = await createCache(cacheSettings);
1919
2107
  const failFast = cfg.options.failFast ?? configInfo.config.failFast ?? false;
1920
2108
  function* prefetchFiles(files$1) {
1921
2109
  const iter = prefetchIterable(pipe(files$1, opMap$1((filename) => prefetch(filename, configInfo, cache))), BATCH_SIZE);
@@ -1975,7 +2163,7 @@ async function runLint(cfg) {
1975
2163
  }
1976
2164
  status.errors += result.configErrors;
1977
2165
  }
1978
- cache.reconcile();
2166
+ await cache.reconcile();
1979
2167
  return status;
1980
2168
  }
1981
2169
  function calcDependencies(config) {
@@ -2570,4 +2758,4 @@ function parseApplicationFeatureFlags(flags) {
2570
2758
 
2571
2759
  //#endregion
2572
2760
  export { ApplicationError, CheckFailed, DEFAULT_CACHE_LOCATION, IncludeExcludeFlag, ReportChoicesAll, checkText, console, createInit, getReporter, lint, listDictionaries, npmPackage, parseApplicationFeatureFlags, suggestions, trace };
2573
- //# sourceMappingURL=application-D-NwS6qb.js.map
2761
+ //# sourceMappingURL=application-_MFvh02K.js.map
@@ -1,3 +1,3 @@
1
1
  import "./options-ChaXtdFn.js";
2
- import { AppError, CheckTextResult, IncludeExcludeFlag, TraceResult, checkText, createInit, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace } from "./application-DbOQYm56.js";
2
+ import { AppError, CheckTextResult, IncludeExcludeFlag, TraceResult, checkText, createInit, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace } from "./application-D8WjsMdV.js";
3
3
  export { AppError, CheckTextResult, IncludeExcludeFlag, TraceResult, checkText, createInit, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace };
@@ -1,3 +1,3 @@
1
- import { IncludeExcludeFlag, checkText, createInit, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace } from "./application-D-NwS6qb.js";
1
+ import { IncludeExcludeFlag, checkText, createInit, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace } from "./application-_MFvh02K.js";
2
2
 
3
3
  export { IncludeExcludeFlag, checkText, createInit, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace };
@@ -1,5 +1,5 @@
1
1
  import { BaseOptions, LinterCliOptions, TraceOptions } from "./options-ChaXtdFn.js";
2
- import { AppError, CheckTextResult, IncludeExcludeFlag, TraceResult, checkText, createInit, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace } from "./application-DbOQYm56.js";
2
+ import { AppError, CheckTextResult, IncludeExcludeFlag, TraceResult, checkText, createInit, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace } from "./application-D8WjsMdV.js";
3
3
  import "chalk";
4
4
  import { CSpellReporter, CSpellSettings, ReporterConfiguration, RunResult } from "@cspell/cspell-types";
5
5
  import { WriteStream } from "node:tty";
@@ -51,5 +51,5 @@ interface ReporterOptions extends Pick<LinterCliOptions, "color" | "debug" | "is
51
51
  }
52
52
  declare function getReporter(options: ReporterOptions, config?: CSpellReporterConfiguration): FinalizedReporter;
53
53
  //#endregion
54
- export { AppError, BaseOptions, LinterCliOptions as CSpellApplicationOptions, CSpellReporterConfiguration, CSpellReporterModule, CheckTextResult, IncludeExcludeFlag, TraceOptions, TraceResult, checkText, createInit, getReporter as getDefaultReporter, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace };
54
+ export { AppError, type BaseOptions, type LinterCliOptions as CSpellApplicationOptions, type CSpellReporterConfiguration, type CSpellReporterModule, CheckTextResult, IncludeExcludeFlag, type TraceOptions, TraceResult, checkText, createInit, getReporter as getDefaultReporter, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace };
55
55
  //# sourceMappingURL=index.d.ts.map
package/dist/esm/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { IncludeExcludeFlag, checkText, createInit, getReporter, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace } from "./application-D-NwS6qb.js";
1
+ import { IncludeExcludeFlag, checkText, createInit, getReporter, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace } from "./application-_MFvh02K.js";
2
2
 
3
3
  export * from "@cspell/cspell-types"
4
4
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cspell",
3
- "version": "9.1.5",
3
+ "version": "9.2.0",
4
4
  "description": "A Spelling Checker for Code!",
5
5
  "funding": "https://github.com/streetsidesoftware/cspell?sponsor=1",
6
6
  "bin": {
@@ -83,22 +83,22 @@
83
83
  },
84
84
  "homepage": "https://cspell.org/",
85
85
  "dependencies": {
86
- "@cspell/cspell-json-reporter": "9.1.5",
87
- "@cspell/cspell-pipe": "9.1.5",
88
- "@cspell/cspell-types": "9.1.5",
89
- "@cspell/dynamic-import": "9.1.5",
90
- "@cspell/url": "9.1.5",
86
+ "@cspell/cspell-json-reporter": "9.2.0",
87
+ "@cspell/cspell-pipe": "9.2.0",
88
+ "@cspell/cspell-types": "9.2.0",
89
+ "@cspell/dynamic-import": "9.2.0",
90
+ "@cspell/url": "9.2.0",
91
91
  "chalk": "^5.4.1",
92
92
  "chalk-template": "^1.1.0",
93
93
  "commander": "^14.0.0",
94
- "cspell-config-lib": "9.1.5",
95
- "cspell-dictionary": "9.1.5",
96
- "cspell-gitignore": "9.1.5",
97
- "cspell-glob": "9.1.5",
98
- "cspell-io": "9.1.5",
99
- "cspell-lib": "9.1.5",
94
+ "cspell-config-lib": "9.2.0",
95
+ "cspell-dictionary": "9.2.0",
96
+ "cspell-gitignore": "9.2.0",
97
+ "cspell-glob": "9.2.0",
98
+ "cspell-io": "9.2.0",
99
+ "cspell-lib": "9.2.0",
100
100
  "fast-json-stable-stringify": "^2.1.0",
101
- "file-entry-cache": "^9.1.0",
101
+ "flatted": "^3.3.3",
102
102
  "semver": "^7.7.2",
103
103
  "tinyglobby": "^0.2.14"
104
104
  },
@@ -106,12 +106,11 @@
106
106
  "node": ">=20"
107
107
  },
108
108
  "devDependencies": {
109
- "@types/file-entry-cache": "^5.0.4",
110
109
  "@types/glob": "^8.1.0",
111
110
  "@types/micromatch": "^4.0.9",
112
111
  "@types/semver": "^7.7.0",
113
112
  "micromatch": "^4.0.8",
114
113
  "minimatch": "^9.0.5"
115
114
  },
116
- "gitHead": "6303813cb5da37e88b3ccab7ce5bcf09373f5cf2"
115
+ "gitHead": "6004e6a19e11985bc61e6578846195be07365049"
117
116
  }