cspell 10.3.6 → 10.4.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/README.md CHANGED
@@ -19,7 +19,7 @@ Please show your support through one of the following sites:
19
19
  ## Features
20
20
 
21
21
  - Spell Checks Code -- Parses code into words before checking them against the dictionaries.
22
- - Supports CamelCase, snake\_case, and compoundwords naming styles.
22
+ - Supports CamelCase, snake_case, and compoundwords naming styles.
23
23
  - Self contained -- does not depend upon OS libraries like Hunspell or Aspell. Nor does it depend upon online services.
24
24
  - Fast -- checks 1000's of lines of code in seconds.
25
25
  - Programming Language Specific Dictionaries -- Has dedicated support for:
@@ -102,108 +102,130 @@ The `lint` command is used for spell checking files.
102
102
  cspell lint --help
103
103
  ```
104
104
 
105
+ Help, and the tables from `cspell trace` and `cspell dictionaries`, fit the width of your terminal. To use a different
106
+ width, set the `COLUMNS` environment variable:
107
+
108
+ ```sh
109
+ COLUMNS=60 cspell lint --help
110
+ ```
111
+
105
112
  ### Options
106
113
 
107
114
  <!--- @@inject: static/help-lint.txt --->
108
115
 
109
116
  ```
110
- Usage: cspell lint [options] [globs...] [file://<path> ...] [stdin[://<path>]]
117
+ Usage: cspell lint [options] [globs...] [file://<path> ...]
118
+ [stdin[://<path>]]
111
119
 
112
120
  Patterns:
113
121
  - [globs...] Glob Patterns
114
122
  - [stdin] Read from "stdin" assume text file.
115
- - [stdin://<path>] Read from "stdin", use <path> for file type and config.
123
+ - [stdin://<path>] Read stdin; <path> sets file type and config.
116
124
  - [file://<path>] Check the file at <path>
117
125
 
118
126
  Examples:
119
127
  cspell . Recursively check all files.
120
128
  cspell lint . The same as "cspell ."
121
- cspell "*.js" Check all .js files in the current directory
129
+ cspell "*.js" Check .js files in this directory
122
130
  cspell "**/*.js" Check all .js files recursively
123
131
  cspell "src/**/*.js" Only check .js under src
124
132
  cspell "**/*.txt" "**/*.js" Check both .js and .txt files.
125
133
  cspell "**/*.{txt,js,md}" Check .txt, .js, and .md files.
126
134
  cat LICENSE | cspell stdin Check stdin
127
- cspell stdin://docs/doc.md Check stdin as if it was "./docs/doc.md"
135
+ cspell stdin://docs/doc.md Check stdin as "./docs/doc.md"
128
136
 
129
137
  Check spelling
130
138
 
131
139
  Options:
132
- -c, --config <cspell.json> Configuration file to use. By default cspell
133
- looks for cspell.json in the current directory.
134
- --no-config-search Disable automatic searching for additional
135
- configuration files in parent directories. Only
136
- the specified config file (if any) will be
137
- used.
138
- --stop-config-search-at <dir> Specify a directory at which to stop searching
139
- for configuration files when walking up from
140
- the files being checked. Useful for limiting
141
- config inheritance.
142
- -v, --verbose Display more information about the files being
143
- checked. Add more than one -v for increased
144
- verbosity.
145
- --locale <locale> Set language locales. i.e. "en,fr" for English
146
- and French, or "en-GB" for British English.
140
+ -c, --config <cspell.json> Configuration file to use. By default
141
+ cspell looks for cspell.json in the
142
+ current directory.
143
+ --no-config-search Disable automatic searching for
144
+ additional configuration files in
145
+ parent directories. Only the specified
146
+ config file (if any) will be used.
147
+ --stop-config-search-at <dir> Specify a directory at which to stop
148
+ searching for configuration files when
149
+ walking up from the files being
150
+ checked. Useful for limiting config
151
+ inheritance.
152
+ -v, --verbose Display more information about the
153
+ files being checked. Add more than one
154
+ -v for increased verbosity.
155
+ --locale <locale> Set language locales. i.e. "en,fr" for
156
+ English and French, or "en-GB" for
157
+ British English.
147
158
  --language-id <file-type> Force programming language for unknown
148
159
  extensions. i.e. "php" or "scala"
149
160
  --words-only Only output the words not found in the
150
161
  dictionaries.
151
- -u, --unique Only output the first instance of a word not
152
- found in the dictionaries.
153
- -e, --exclude <glob> Exclude files matching the glob pattern. This
154
- option can be used multiple times to add
155
- multiple globs.
156
- --file-list <path or stdin> Specify a list of files to be spell checked.
157
- The list is filtered against the glob file
158
- patterns. Note: the format is 1 file path per
159
- line.
160
- --file [file...] Specify files to spell check. They are filtered
161
- by the [globs...].
162
- --force-check Force the --file or --file-list documents to be
163
- checked even if it would normally be excluded.
162
+ -u, --unique Only output the first instance of a
163
+ word not found in the dictionaries.
164
+ -e, --exclude <glob> Exclude files matching the glob
165
+ pattern. This option can be used
166
+ multiple times to add multiple globs.
167
+ --file-list <path or stdin> Specify a list of files to be spell
168
+ checked. The list is filtered against
169
+ the glob file patterns. Note: the
170
+ format is 1 file path per line.
171
+ --file [file...] Specify files to spell check. They are
172
+ filtered by the [globs...].
173
+ --force-check Force the --file or --file-list
174
+ documents to be checked even if it
175
+ would normally be excluded.
176
+ --follow-symlinks Allow checking --file and --file-list
177
+ documents referenced by symbolic links.
164
178
  --no-issues Do not show the spelling errors.
165
179
  --no-progress Turn off progress messages
166
180
  --no-summary Turn off summary message in console.
167
181
  -s, --silent Silent mode, suppress error messages.
168
- --no-exit-code Do not return an exit code if issues are found.
182
+ --no-exit-code Do not return an exit code if issues
183
+ are found.
169
184
  --quiet Only show spelling issues or errors.
170
- --fail-fast Exit after first file with an issue or error.
171
- --continue-on-error Continue processing files even if there is a
172
- configuration error.
173
- -r, --root <root folder> Root directory, defaults to current directory.
174
- --no-relative Issues are displayed with absolute path instead
175
- of relative to the root.
176
- --show-context Show the surrounding text around an issue.
185
+ --fail-fast Exit after first file with an issue or
186
+ error.
187
+ --continue-on-error Continue processing files even if there
188
+ is a configuration error.
189
+ -r, --root <root folder> Root directory, defaults to current
190
+ directory.
191
+ --no-relative Issues are displayed with absolute path
192
+ instead of relative to the root.
193
+ --show-context Show the surrounding text around an
194
+ issue.
177
195
  --show-suggestions Show spelling suggestions.
178
- --no-show-suggestions Do not show spelling suggestions or fixes.
196
+ --no-show-suggestions Do not show spelling suggestions or
197
+ fixes.
179
198
  --no-must-find-files Do not error if no files are found.
180
199
  --cache Use cache to only check changed files.
181
200
  --no-cache Do not use cache.
182
201
  --cache-reset Reset the cache file.
183
- --cache-strategy <strategy> Strategy to use for detecting changed files.
184
- (choices: "content", "metadata", default:
185
- "content")
186
- --cache-location <path> Path to the cache file or directory. (default:
187
- ".cspellcache")
188
- --dot Include files and directories starting with `.`
189
- (period) when matching globs.
190
- --gitignore Ignore files matching glob patterns found in
191
- .gitignore files.
202
+ --cache-strategy <strategy> Strategy to use for detecting changed
203
+ files. (choices: "content", "metadata",
204
+ default: "content")
205
+ --cache-location <path> Path to the cache file or directory.
206
+ (default: ".cspellcache")
207
+ --dot Include files and directories starting
208
+ with `.` (period) when matching globs.
209
+ --glob-symlinks Follow symbolic links when matching
210
+ globs.
211
+ --gitignore Ignore files matching glob patterns
212
+ found in .gitignore files.
192
213
  --no-gitignore Do NOT use .gitignore files.
193
- --gitignore-root <path> Prevent searching for .gitignore files past
194
- root.
214
+ --gitignore-root <path> Prevent searching for .gitignore files
215
+ past root.
195
216
  --validate-directives Validate in-document CSpell directives.
196
- --max-file-size <size> Prevent checking large files. i.e 1MB, 50KB,
197
- 1GB
217
+ --max-file-size <size> Prevent checking large files. i.e 1MB,
218
+ 50KB, 1GB
198
219
  --color Force color.
199
220
  --no-color Turn off color.
200
- --no-default-configuration Do not load the default configuration and
201
- dictionaries.
221
+ --no-default-configuration Do not load the default configuration
222
+ and dictionaries.
202
223
  --dictionary <name> Enable a dictionary by name.
203
224
  --disable-dictionary <name> Disable a dictionary by name.
204
225
  --reporter <module|path> Specify one or more reporters to use.
205
- --report <level> Set how unknown words are reported (choices:
206
- "all", "simple", "typos", "flagged")
226
+ --report <level> Set how unknown words are reported
227
+ (choices: "all", "simple", "typos",
228
+ "flagged")
207
229
  --issue-template [template] Use a custom issue template. See --help
208
230
  --issue-template for details.
209
231
  -h, --help display help for command
@@ -226,7 +248,7 @@ More Examples:
226
248
 
227
249
  cspell "/*.md" --no-must-find-files --files $FILES
228
250
  Only spell check the "/*.md" files in $FILES,
229
- where $FILES is a shell variable that contains the list of files.
251
+ where $FILES is a shell variable containing the list of files.
230
252
 
231
253
  cspell --help --verbose
232
254
  Show all options including hidden options.
@@ -275,26 +297,32 @@ Usage: cspell trace [options] [words...]
275
297
  Trace words -- Search for words in the configuration and dictionaries.
276
298
 
277
299
  Options:
278
- -c, --config <cspell.json> Configuration file to use. By default cspell
279
- looks for cspell.json in the current directory.
280
- --locale <locale> Set language locales. i.e. "en,fr" for English and
281
- French, or "en-GB" for British English.
282
- --language-id <language> Use programming language. i.e. "php" or "scala".
300
+ -c, --config <cspell.json> Configuration file to use. By default
301
+ cspell looks for cspell.json in the
302
+ current directory.
303
+ --locale <locale> Set language locales. i.e. "en,fr" for
304
+ English and French, or "en-GB" for British
305
+ English.
306
+ --language-id <language> Use programming language. i.e. "php" or
307
+ "scala".
283
308
  --allow-compound-words Turn on allowCompoundWords
284
309
  --no-allow-compound-words Turn off allowCompoundWords
285
- --ignore-case Ignore case and accents when searching for words.
286
- --no-ignore-case Do not ignore case and accents when searching for
310
+ --ignore-case Ignore case and accents when searching for
287
311
  words.
288
- --dictionary <name> Enable a dictionary by name. Can be used multiple
289
- times.
290
- --no-dictionary <name> Disable a dictionary by name. Can be used multiple
291
- times.
292
- --dictionary-path <format> Configure how to display the dictionary path.
293
- (choices: "hide", "short", "long", "full",
294
- default: Display most of the path.)
312
+ --no-ignore-case Do not ignore case and accents when
313
+ searching for words.
314
+ --dictionary <name> Enable a dictionary by name. Can be used
315
+ multiple times.
316
+ --no-dictionary <name> Disable a dictionary by name. Can be used
317
+ multiple times.
318
+ --dictionary-path <format> Configure how to display the dictionary
319
+ path. (choices: "hide", "short", "long",
320
+ "full", default: Display most of the
321
+ path.)
295
322
  --stdin Read words from stdin.
296
323
  --all Show all dictionaries.
297
- --only-found Show only dictionaries that have the words.
324
+ --only-found Show only dictionaries that have the
325
+ words.
298
326
  --color Force color.
299
327
  --no-color Turn off color.
300
328
  --no-default-configuration Do not load the default configuration and
@@ -343,7 +371,7 @@ CSpell needs Node 22 and above.
343
371
 
344
372
  ## How it works
345
373
 
346
- The concept is simple: split camelCase and snake\_case words before checking them against a list of known words.
374
+ The concept is simple: split camelCase and snake_case words before checking them against a list of known words.
347
375
 
348
376
  - `camelCase` -> `camel case`
349
377
  - `HTMLInput` -> `html input`
@@ -704,7 +732,7 @@ The spell checker includes a set of default dictionaries.
704
732
 
705
733
  ### General Dictionaries
706
734
 
707
- - **en\_US** - Derived from Hunspell US English words.
735
+ - **en_US** - Derived from Hunspell US English words.
708
736
  - **en-gb** - Derived from Hunspell GB English words.
709
737
  - **companies** - List of well known companies
710
738
  - **softwareTerms** - Software Terms and concepts like "coroutine", "debounce", "tree", etc.
package/dist/esm/app.d.ts CHANGED
@@ -1,18 +1,18 @@
1
- import { i as LinterCliOptions } from "./options-DlXe327y.js";
1
+ import { i as LinterCliOptions } from "./options-D5lC3IZu.js";
2
2
  import { Command } from "commander";
3
3
  //#region src/util/errors.d.ts
4
- declare class CheckFailed extends Error {
4
+ export declare class CheckFailed extends Error {
5
5
  readonly exitCode: number;
6
6
  constructor(message: string, exitCode?: number);
7
7
  }
8
- declare class ApplicationError extends Error {
8
+ export declare class ApplicationError extends Error {
9
9
  readonly exitCode: number;
10
10
  readonly cause?: Error | undefined;
11
11
  constructor(message: string, exitCode?: number, cause?: Error | undefined);
12
12
  }
13
13
  //#endregion
14
14
  //#region src/app.d.mts
15
- declare function run(command?: Command, argv?: string[]): Promise<void>;
15
+ export declare function run(command?: Command, argv?: string[]): Promise<void>;
16
16
  //#endregion
17
- export { ApplicationError, CheckFailed, type LinterCliOptions as Options, run };
17
+ export type { LinterCliOptions as Options };
18
18
  //# sourceMappingURL=app.d.ts.map
package/dist/esm/app.js CHANGED
@@ -1,4 +1,4 @@
1
- import { C as ApplicationError, S as width, T as console, _ as padLeft, a as parseApplicationFeatureFlags, b as pruneAnsiTextEnd, c as listDictionaries, d as validateUnitSize, f as unindent, g as tableToLines, i as lint, l as ReportChoicesAll, m as npmPackage, n as checkText, o as suggestions, p as DEFAULT_CACHE_LOCATION, r as createInit, s as trace, t as IncludeExcludeFlag, u as cvtLinterCliCommandOptionsToLinterCliOptions, v as padWidth, w as CheckFailed, x as pruneAnsiTextStart, y as ansiWidth } from "./application-yI9NNGsb.js";
1
+ import { C as ApplicationError, S as width, T as console, _ as padLeft, a as parseApplicationFeatureFlags, b as pruneAnsiTextEnd, c as listDictionaries, d as validateUnitSize, f as unindent, g as tableToLines, i as lint, l as ReportChoicesAll, m as npmPackage, n as checkText, o as suggestions, p as DEFAULT_CACHE_LOCATION, r as createInit, s as trace, t as IncludeExcludeFlag, u as cvtLinterCliCommandOptionsToLinterCliOptions, v as padWidth, w as CheckFailed, x as pruneAnsiTextStart, y as ansiWidth } from "./application-IkKZuulS.js";
2
2
  import { Link } from "cspell-lib";
3
3
  import chalk from "chalk";
4
4
  import * as iPath from "node:path";
@@ -97,6 +97,19 @@ function crOpt(name, description, parseArg, defaultValue) {
97
97
  return option;
98
98
  }
99
99
  //#endregion
100
+ //#region src/util/outputWidth.ts
101
+ /**
102
+ * The width to format output for.
103
+ * `COLUMNS` wins when it is a positive integer, otherwise the width of the stream if it has one.
104
+ */
105
+ function getOutputWidth(stream = process.stdout, env = process.env) {
106
+ return parseColumns(env.COLUMNS) || stream.columns || void 0;
107
+ }
108
+ function parseColumns(value) {
109
+ if (!value || !/^\s*\d+\s*$/.test(value)) return void 0;
110
+ return Number.parseInt(value, 10) || void 0;
111
+ }
112
+ //#endregion
100
113
  //#region src/emitters/helpers.ts
101
114
  function trimMidPath(s, w, sep) {
102
115
  if (s.length <= w) return s;
@@ -170,7 +183,7 @@ function calcListDictsResultsReport(results, options) {
170
183
  table: tableToLines({
171
184
  header,
172
185
  rows,
173
- terminalWidth: options.lineWidth || process.stdout.columns || maxWidth$1,
186
+ terminalWidth: options.lineWidth || getOutputWidth() || maxWidth$1,
174
187
  deliminator: " ",
175
188
  maxColumnWidths: {
176
189
  locales: 12,
@@ -337,24 +350,25 @@ function commandLink(prog) {
337
350
  //#endregion
338
351
  //#region src/commandLint.ts
339
352
  const usage = `\
340
- [options] [globs...] [file://<path> ...] [stdin[://<path>]]
353
+ [options] [globs...] [file://<path> ...]
354
+ [stdin[://<path>]]
341
355
 
342
356
  Patterns:
343
357
  - [globs...] Glob Patterns
344
358
  - [stdin] Read from "stdin" assume text file.
345
- - [stdin://<path>] Read from "stdin", use <path> for file type and config.
359
+ - [stdin://<path>] Read stdin; <path> sets file type and config.
346
360
  - [file://<path>] Check the file at <path>
347
361
 
348
362
  Examples:
349
363
  cspell . Recursively check all files.
350
364
  cspell lint . The same as "cspell ."
351
- cspell "*.js" Check all .js files in the current directory
365
+ cspell "*.js" Check .js files in this directory
352
366
  cspell "**/*.js" Check all .js files recursively
353
367
  cspell "src/**/*.js" Only check .js under src
354
368
  cspell "**/*.txt" "**/*.js" Check both .js and .txt files.
355
369
  cspell "**/*.{txt,js,md}" Check .txt, .js, and .md files.
356
370
  cat LICENSE | cspell stdin Check stdin
357
- cspell stdin://docs/doc.md Check stdin as if it was "./docs/doc.md"\
371
+ cspell stdin://docs/doc.md Check stdin as "./docs/doc.md"\
358
372
  `;
359
373
  const advanced = `
360
374
  More Examples:
@@ -375,7 +389,7 @@ More Examples:
375
389
 
376
390
  cspell "/*.md" --no-must-find-files --files $FILES
377
391
  Only spell check the "/*.md" files in $FILES,
378
- where $FILES is a shell variable that contains the list of files.
392
+ where $FILES is a shell variable containing the list of files.
379
393
 
380
394
  cspell --help --verbose
381
395
  Show all options including hidden options.
@@ -386,10 +400,10 @@ References:
386
400
  `;
387
401
  function commandLint(prog, opts) {
388
402
  const spellCheckCommand = prog.command("lint", opts);
389
- spellCheckCommand.description("Check spelling").option("-c, --config <cspell.json>", "Configuration file to use. By default cspell looks for cspell.json in the current directory.").addOption(crOpt("--config-search", "Allow searching for configuration files.", void 0).hideHelp()).option("--no-config-search", "Disable automatic searching for additional configuration files in parent directories. Only the specified config file (if any) will be used.").option("--stop-config-search-at <dir>", "Specify a directory at which to stop searching for configuration files when walking up from the files being checked. Useful for limiting config inheritance.", collect$1).option("-v, --verbose", "Display more information about the files being checked. Add more than one -v for increased verbosity.", increaseVerbosity, 0).option("--locale <locale>", "Set language locales. i.e. \"en,fr\" for English and French, or \"en-GB\" for British English.").option("--language-id <file-type>", "Force programming language for unknown extensions. i.e. \"php\" or \"scala\"").addOption(crOpt("--languageId <file-type>", "Alias of \"--language-id\". Force programming language for unknown extensions. i.e. \"php\" or \"scala\"").hideHelp()).option("--words-only", "Only output the words not found in the dictionaries.").addOption(crOpt("--wordsOnly", "Only output the words not found in the dictionaries.").hideHelp()).option("-u, --unique", "Only output the first instance of a word not found in the dictionaries.").option("-e, --exclude <glob>", "Exclude files matching the glob pattern. This option can be used multiple times to add multiple globs. ", collect$1).option("--file-list <path or stdin>", "Specify a list of files to be spell checked. The list is filtered against the glob file patterns. Note: the format is 1 file path per line.", collect$1).option("--file [file...]", "Specify files to spell check. They are filtered by the [globs...].", collect$1).addOption(crOpt("--files [file...]", "Alias of \"--file\". Files to spell check.", collect$1).hideHelp()).option("--force-check", "Force the --file or --file-list documents to be checked even if it would normally be excluded.").option("--no-issues", "Do not show the spelling errors.").option("--no-progress", "Turn off progress messages").option("--no-summary", "Turn off summary message in console.").option("-s, --silent", "Silent mode, suppress error messages.").option("--no-exit-code", "Do not return an exit code if issues are found.").addOption(crOpt("--quiet", "Only show spelling issues or errors.").implies({
403
+ spellCheckCommand.description("Check spelling").option("-c, --config <cspell.json>", "Configuration file to use. By default cspell looks for cspell.json in the current directory.").addOption(crOpt("--config-search", "Allow searching for configuration files.", void 0).hideHelp()).option("--no-config-search", "Disable automatic searching for additional configuration files in parent directories. Only the specified config file (if any) will be used.").option("--stop-config-search-at <dir>", "Specify a directory at which to stop searching for configuration files when walking up from the files being checked. Useful for limiting config inheritance.", collect$1).option("-v, --verbose", "Display more information about the files being checked. Add more than one -v for increased verbosity.", increaseVerbosity, 0).option("--locale <locale>", "Set language locales. i.e. \"en,fr\" for English and French, or \"en-GB\" for British English.").option("--language-id <file-type>", "Force programming language for unknown extensions. i.e. \"php\" or \"scala\"").addOption(crOpt("--languageId <file-type>", "Alias of \"--language-id\". Force programming language for unknown extensions. i.e. \"php\" or \"scala\"").hideHelp()).option("--words-only", "Only output the words not found in the dictionaries.").addOption(crOpt("--wordsOnly", "Only output the words not found in the dictionaries.").hideHelp()).option("-u, --unique", "Only output the first instance of a word not found in the dictionaries.").option("-e, --exclude <glob>", "Exclude files matching the glob pattern. This option can be used multiple times to add multiple globs. ", collect$1).option("--file-list <path or stdin>", "Specify a list of files to be spell checked. The list is filtered against the glob file patterns. Note: the format is 1 file path per line.", collect$1).option("--file [file...]", "Specify files to spell check. They are filtered by the [globs...].", collect$1).addOption(crOpt("--files [file...]", "Alias of \"--file\". Files to spell check.", collect$1).hideHelp()).option("--force-check", "Force the --file or --file-list documents to be checked even if it would normally be excluded.").option("--follow-symlinks", "Allow checking --file and --file-list documents referenced by symbolic links.").addOption(crOpt("--no-follow-symlinks", "Skip documents referenced by symbolic links.").default(void 0).hideHelp()).option("--no-issues", "Do not show the spelling errors.").option("--no-progress", "Turn off progress messages").option("--no-summary", "Turn off summary message in console.").option("-s, --silent", "Silent mode, suppress error messages.").option("--no-exit-code", "Do not return an exit code if issues are found.").addOption(crOpt("--quiet", "Only show spelling issues or errors.").implies({
390
404
  summary: false,
391
405
  progress: false
392
- })).option("--fail-fast", "Exit after first file with an issue or error.").addOption(crOpt("--no-fail-fast", "Process all files even if there is an error.").hideHelp()).option("--continue-on-error", "Continue processing files even if there is a configuration error.").option("-r, --root <root folder>", "Root directory, defaults to current directory.").addOption(crOpt("--relative", "Issues are displayed relative to the root.").default(true).hideHelp()).option("--no-relative", "Issues are displayed with absolute path instead of relative to the root.").option("--show-context", "Show the surrounding text around an issue.").option("--show-suggestions", "Show spelling suggestions.").addOption(crOpt("--no-show-suggestions", "Do not show spelling suggestions or fixes.").default(void 0)).addOption(crOpt("--must-find-files", "Error if no files are found.").default(true).hideHelp()).option("--no-must-find-files", "Do not error if no files are found.").addOption(crOpt("--legacy", "Legacy output").hideHelp()).addOption(crOpt("--local <local>", "Deprecated -- Use: --locale").hideHelp()).option("--cache", "Use cache to only check changed files.").option("--no-cache", "Do not use cache.").option("--cache-reset", "Reset the cache file.").addOption(crOpt("--cache-strategy <strategy>", "Strategy to use for detecting changed files.").choices(["content", "metadata"]).default("content")).option("--cache-location <path>", `Path to the cache file or directory. (default: "${DEFAULT_CACHE_LOCATION}")`).option("--dot", "Include files and directories starting with `.` (period) when matching globs.").option("--gitignore", "Ignore files matching glob patterns found in .gitignore files.").option("--no-gitignore", "Do NOT use .gitignore files.").option("--gitignore-root <path>", "Prevent searching for .gitignore files past root.", collect$1).option("--validate-directives", "Validate in-document CSpell directives.").addOption(crOpt("--no-validate-directives", "Do not validate in-document CSpell directives.").hideHelp()).option("--max-file-size <size>", "Prevent checking large files. i.e 1MB, 50KB, 1GB").addOption(crOpt("--color", "Force color.").default(void 0)).addOption(crOpt("--no-color", "Turn off color.").default(void 0)).addOption(crOpt("--default-configuration", "Load the default configuration and dictionaries.").hideHelp()).addOption(crOpt("--no-default-configuration", "Do not load the default configuration and dictionaries.")).option("--dictionary <name>", "Enable a dictionary by name.", collect$1).addOption(crOpt("--no-dictionary <name>", "Disable a dictionary by name. Can be used multiple times.", prefixCollect("!")).hideHelp()).option("--disable-dictionary <name>", "Disable a dictionary by name.", collect$1).option("--reporter <module|path>", "Specify one or more reporters to use.", collect$1).addOption(crOpt("--report <level>", "Set how unknown words are reported").choices(ReportChoicesAll)).addOption(crOpt("--skip-validation", "Collect and process documents, but do not spell check.").implies({ cache: false }).hideHelp()).addOption(crOpt("--issues-summary-report", "Output a summary of issues found.").hideHelp()).addOption(crOpt("--show-perf-summary", "Output a performance summary report.").hideHelp()).option("--issue-template [template]", "Use a custom issue template. See --help --issue-template for details.").addOption(crOpt("--debug", "Output information useful for debugging cspell.json files.").hideHelp()).usage(usage).addHelpText("after", augmentCommandHelp).arguments("[globs...]").action(action);
406
+ })).option("--fail-fast", "Exit after first file with an issue or error.").addOption(crOpt("--no-fail-fast", "Process all files even if there is an error.").hideHelp()).option("--continue-on-error", "Continue processing files even if there is a configuration error.").option("-r, --root <root folder>", "Root directory, defaults to current directory.").addOption(crOpt("--relative", "Issues are displayed relative to the root.").default(true).hideHelp()).option("--no-relative", "Issues are displayed with absolute path instead of relative to the root.").option("--show-context", "Show the surrounding text around an issue.").option("--show-suggestions", "Show spelling suggestions.").addOption(crOpt("--no-show-suggestions", "Do not show spelling suggestions or fixes.").default(void 0)).addOption(crOpt("--must-find-files", "Error if no files are found.").default(true).hideHelp()).option("--no-must-find-files", "Do not error if no files are found.").addOption(crOpt("--legacy", "Legacy output").hideHelp()).addOption(crOpt("--local <local>", "Deprecated -- Use: --locale").hideHelp()).option("--cache", "Use cache to only check changed files.").option("--no-cache", "Do not use cache.").option("--cache-reset", "Reset the cache file.").addOption(crOpt("--cache-strategy <strategy>", "Strategy to use for detecting changed files.").choices(["content", "metadata"]).default("content")).option("--cache-location <path>", `Path to the cache file or directory. (default: "${DEFAULT_CACHE_LOCATION}")`).option("--dot", "Include files and directories starting with `.` (period) when matching globs.").option("--glob-symlinks", "Follow symbolic links when matching globs.").addOption(crOpt("--no-glob-symlinks", "Do not follow symbolic links when matching globs.").default(void 0).hideHelp()).option("--gitignore", "Ignore files matching glob patterns found in .gitignore files.").option("--no-gitignore", "Do NOT use .gitignore files.").option("--gitignore-root <path>", "Prevent searching for .gitignore files past root.", collect$1).option("--validate-directives", "Validate in-document CSpell directives.").addOption(crOpt("--no-validate-directives", "Do not validate in-document CSpell directives.").hideHelp()).option("--max-file-size <size>", "Prevent checking large files. i.e 1MB, 50KB, 1GB").addOption(crOpt("--color", "Force color.").default(void 0)).addOption(crOpt("--no-color", "Turn off color.").default(void 0)).addOption(crOpt("--default-configuration", "Load the default configuration and dictionaries.").hideHelp()).addOption(crOpt("--no-default-configuration", "Do not load the default configuration and dictionaries.")).option("--dictionary <name>", "Enable a dictionary by name.", collect$1).addOption(crOpt("--no-dictionary <name>", "Disable a dictionary by name. Can be used multiple times.", prefixCollect("!")).hideHelp()).option("--disable-dictionary <name>", "Disable a dictionary by name.", collect$1).option("--reporter <module|path>", "Specify one or more reporters to use.", collect$1).addOption(crOpt("--report <level>", "Set how unknown words are reported").choices(ReportChoicesAll)).addOption(crOpt("--skip-validation", "Collect and process documents, but do not spell check.").implies({ cache: false }).hideHelp()).addOption(crOpt("--issues-summary-report", "Output a summary of issues found.").hideHelp()).addOption(crOpt("--show-perf-summary", "Output a performance summary report.").hideHelp()).option("--issue-template [template]", "Use a custom issue template. See --help --issue-template for details.").addOption(crOpt("--debug", "Output information useful for debugging cspell.json files.").hideHelp()).usage(usage).addHelpText("after", augmentCommandHelp).arguments("[globs...]").action(action);
393
407
  return spellCheckCommand;
394
408
  }
395
409
  async function action(fileGlobs, cliOptions) {
@@ -408,7 +422,12 @@ async function action(fileGlobs, cliOptions) {
408
422
  this.outputHelp();
409
423
  throw new CheckFailed("outputHelp", 1);
410
424
  }
411
- if (result.errors || mustFindFiles && !result.files) throw new CheckFailed("check failed", 1);
425
+ if (result.errors) throw new CheckFailed("check failed", 1);
426
+ const skippedFiles = result.skippedFiles || 0;
427
+ if (mustFindFiles && result.files <= skippedFiles) {
428
+ if (!options.silent) console.error(`No files found to check${skippedFiles ? ` (${skippedFiles} skipped)` : ""}.`);
429
+ throw new CheckFailed("no files found", 1);
430
+ }
412
431
  if (result.issues) throw new CheckFailed("check failed", useExitCode ? 1 : 0);
413
432
  }
414
433
  function helpIssueTemplate(opts) {
@@ -449,17 +468,29 @@ function helpIssueTemplate(opts) {
449
468
  * @returns
450
469
  */
451
470
  function augmentCommandHelp(context) {
471
+ return lintHelpAfterOptions(context.command, "Hidden Options:");
472
+ }
473
+ /**
474
+ * The extra lint help for `cspell --help`.
475
+ * The program answers `--help` before the lint options are parsed, so parse them from its arguments.
476
+ * @param context - the program's help context.
477
+ * @param lintCommand - the lint command.
478
+ */
479
+ function lintHelpForProgram(context, lintCommand) {
480
+ lintCommand.parseOptions(context.command.args);
481
+ return lintHelpAfterOptions(lintCommand, `Hidden options for "${lintCommand.name()}":`);
482
+ }
483
+ function lintHelpAfterOptions(command, hiddenOptionsHeading) {
452
484
  const output = [];
453
- const command = context.command;
454
485
  const opts = command.opts();
455
486
  const showHidden = !!opts.verbose;
456
487
  const hiddenHelp = [];
457
488
  const help = command.createHelp();
458
- help.helpWidth = process.stdout.columns || 80;
489
+ help.helpWidth = getOutputWidth() || 80;
459
490
  const hiddenOptions = command.options.filter((opt) => opt.hidden && showHidden);
460
491
  const flagColWidth = Math.max(...command.options.map((opt) => opt.flags.length), 0);
461
492
  for (const options of hiddenOptions) {
462
- if (!hiddenHelp.length) hiddenHelp.push("\nHidden Options:");
493
+ if (!hiddenHelp.length) hiddenHelp.push("\n" + hiddenOptionsHeading);
463
494
  hiddenHelp.push(help.formatItem(options.flags, flagColWidth, options.description, help));
464
495
  }
465
496
  output.push(...hiddenHelp, advanced);
@@ -592,7 +623,7 @@ function calcTraceResultsReport(word, found, results, options) {
592
623
  table: tableToLines({
593
624
  header,
594
625
  rows,
595
- terminalWidth: options.lineWidth || process.stdout.columns || maxWidth,
626
+ terminalWidth: options.lineWidth || getOutputWidth() || maxWidth,
596
627
  deliminator: " "
597
628
  }).map((line) => line.trimEnd()).join("\n"),
598
629
  errors: emitErrors(results).join("\n")
@@ -728,9 +759,15 @@ async function run(command, argv) {
728
759
  const prog = command || program;
729
760
  const args = argv || process.argv;
730
761
  prog.exitOverride();
762
+ prog.configureOutput({
763
+ getOutHelpWidth: () => getOutputWidth(process.stdout) ?? 80,
764
+ getErrHelpWidth: () => getOutputWidth(process.stderr) ?? 80
765
+ });
766
+ prog.configureHelp({ minWidthToWrap: 20 });
731
767
  prog.version(npmPackage.version).description("Spelling Checker for Code").name("cspell");
732
768
  if (!satisfies(process.versions.node, npmPackage.engines.node)) throw new ApplicationError(`Unsupported NodeJS version (${process.versions.node}); ${npmPackage.engines.node} is required`);
733
- addGlobalOptionsToAction(commandLint(prog, { isDefault: true }));
769
+ const lintCommand = addGlobalOptionsToAction(commandLint(prog, { isDefault: true }));
770
+ prog.addHelpText("after", (context) => defaultCommandOptionsHelp(context, lintCommand) + lintHelpForProgram(context, lintCommand));
734
771
  addGlobalOptionsToAction(commandTrace(prog));
735
772
  addGlobalOptionsToAction(commandCheck(prog));
736
773
  addGlobalOptionsToAction(commandSuggestion(prog));
@@ -741,6 +778,18 @@ async function run(command, argv) {
741
778
  prog.exitOverride();
742
779
  await prog.parseAsync(args);
743
780
  }
781
+ /**
782
+ * `cspell --help` is answered by the program, not the default command,
783
+ * so list the default command's options here.
784
+ */
785
+ function defaultCommandOptionsHelp(context, defaultCommand) {
786
+ const helper = defaultCommand.createHelp();
787
+ helper.prepareContext({ helpWidth: getOutputWidth(context.error ? process.stderr : process.stdout) ?? 80 });
788
+ const termWidth = helper.longestOptionTermLength(defaultCommand, helper);
789
+ const items = helper.visibleOptions(defaultCommand).filter((option) => option.long !== "--help").map((option) => helper.formatItem(helper.styleOptionTerm(helper.optionTerm(option)), termWidth, helper.styleOptionDescription(helper.optionDescription(option)), helper));
790
+ const heading = `Options for "${defaultCommand.name()}" (the default command):`;
791
+ return "\n" + helper.formatItemList(heading, items, helper).join("\n");
792
+ }
744
793
  //#endregion
745
794
  export { ApplicationError, CheckFailed, run };
746
795
 
@@ -1,4 +1,4 @@
1
- import { a as SuggestionOptions, i as LinterCliOptions, n as DictionariesOptions, o as TraceOptions, r as LegacyOptions, t as BaseOptions } from "./options-DlXe327y.js";
1
+ import { a as SuggestionOptions, i as LinterCliOptions, n as DictionariesOptions, o as TraceOptions, r as LegacyOptions, t as BaseOptions } from "./options-D5lC3IZu.js";
2
2
  import { CheckTextInfo, FeatureFlags, IncludeExcludeFlag, SuggestionsForWordResult, TraceResult, TraceWordResult } from "cspell-lib";
3
3
  import { CSpellReporter, RunResult } from "@cspell/cspell-types";
4
4
  //#region src/config/options.d.ts
@@ -106,7 +106,15 @@ interface ListDictionariesResult {
106
106
  declare function listDictionaries(options: DictionariesOptions): Promise<ListDictionariesResult[]>;
107
107
  //#endregion
108
108
  //#region src/application.d.mts
109
- type AppError = NodeJS.ErrnoException;
109
+ /**
110
+ * The same shape as `NodeJS.ErrnoException`, declared here so the published types do not need `@types/node`.
111
+ */
112
+ interface AppError extends Error {
113
+ errno?: number | undefined;
114
+ code?: string | undefined;
115
+ path?: string | undefined;
116
+ syscall?: string | undefined;
117
+ }
110
118
  declare function lint(fileGlobs: string[], options: LinterCliOptions, reporter?: CSpellReporter): Promise<RunResult>;
111
119
  declare function trace(words: string[], options: TraceOptions): AsyncIterableIterator<TraceWordResult>;
112
120
  type CheckTextResult = CheckTextInfo;
@@ -116,4 +124,4 @@ declare function createInit(options: InitOptions): Promise<void>;
116
124
  declare function parseApplicationFeatureFlags(flags: string[] | undefined): FeatureFlags;
117
125
  //#endregion
118
126
  export { checkText as a, parseApplicationFeatureFlags as c, listDictionaries as d, TraceResult as i, suggestions as l, CheckTextResult as n, createInit as o, IncludeExcludeFlag as r, lint as s, AppError as t, trace as u };
119
- //# sourceMappingURL=application-094uTsvC.d.ts.map
127
+ //# sourceMappingURL=application-CFfMlhE_.d.ts.map
@@ -24,7 +24,7 @@ import { dynamicImport } from "@cspell/dynamic-import";
24
24
  import crypto from "node:crypto";
25
25
  import streamConsumers from "node:stream/consumers";
26
26
  import { getStat, readFileText, toURL } from "cspell-io";
27
- import { glob } from "tinyglobby";
27
+ import { glob, isDynamicPattern } from "tinyglobby";
28
28
  import * as readline from "node:readline";
29
29
  import { parse, stringify } from "flatted";
30
30
  //#region src/console.ts
@@ -119,6 +119,107 @@ function toApplicationError(e, message) {
119
119
  return new ApplicationError(message ?? err.message, void 0, err);
120
120
  }
121
121
  //#endregion
122
+ //#region src/formatIssue.ts
123
+ function formatIssue(io, templateStr, issue, maxIssueTextWidth) {
124
+ function clean(t) {
125
+ return t.replace(/\s+/, " ");
126
+ }
127
+ const { uri = "", filename, row, col, text, context = issue.line, offset } = issue;
128
+ const textLen = issue.length ?? text.length;
129
+ const contextLeft = clean(context.text.slice(0, offset - context.offset));
130
+ const contextRight = clean(context.text.slice(offset + textLen - context.offset));
131
+ const contextFull = clean(context.text);
132
+ const padContext = " ".repeat(Math.max(maxIssueTextWidth - text.length, 0));
133
+ const rowText = row.toString();
134
+ const colText = col.toString();
135
+ const padRowCol = " ".repeat(Math.max(1, 8 - (rowText.length + colText.length)));
136
+ const suggestions = formatSuggestions(io, issue);
137
+ const msg = issue.message || (issue.isFlagged ? "Forbidden word" : "Unknown word");
138
+ const messageColored = issue.isFlagged ? `{yellow ${msg}}` : msg;
139
+ const substitutions = {
140
+ $col: colText,
141
+ $contextFull: contextFull,
142
+ $contextLeft: contextLeft,
143
+ $contextRight: contextRight,
144
+ $filename: filename,
145
+ $padContext: padContext,
146
+ $padRowCol: padRowCol,
147
+ $row: rowText,
148
+ $suggestions: suggestions,
149
+ $text: text,
150
+ $uri: uri,
151
+ $quickFix: formatQuickFix(io, issue),
152
+ $message: msg,
153
+ $messageColored: messageColored
154
+ };
155
+ const t = templateStr.replaceAll("$messageColored", messageColored);
156
+ return substitute(makeTemplate(io.chalk)(t), substitutions).trimEnd();
157
+ }
158
+ function formatSuggestions(io, issue) {
159
+ if (issue.suggestionsEx) return issue.suggestionsEx.map((sug) => sug.isPreferred ? io.chalk.italic(io.chalk.bold(sug.wordAdjustedToMatchCase || sug.word)) + "*" : sug.wordAdjustedToMatchCase || sug.word).join(", ");
160
+ if (issue.suggestions) return issue.suggestions.join(", ");
161
+ return "";
162
+ }
163
+ function formatQuickFix(io, issue) {
164
+ if (!issue.suggestionsEx?.length) return "";
165
+ const preferred = issue.suggestionsEx.filter((sug) => sug.isPreferred).map((sug) => sug.wordAdjustedToMatchCase || sug.word);
166
+ if (!preferred.length) return "";
167
+ return `fix: (${preferred.map((w) => io.chalk.italic(io.chalk.yellow(w))).join(", ")})`;
168
+ }
169
+ function substitute(text, substitutions) {
170
+ const subs = [];
171
+ for (const [match, replaceWith] of Object.entries(substitutions)) {
172
+ const len = match.length;
173
+ for (let i = text.indexOf(match); i >= 0; i = text.indexOf(match, i)) {
174
+ const end = i + len;
175
+ const reg = /\b/y;
176
+ reg.lastIndex = end;
177
+ if (reg.test(text)) subs.push([
178
+ i,
179
+ end,
180
+ replaceWith
181
+ ]);
182
+ i = end;
183
+ }
184
+ }
185
+ subs.sort((a, b) => a[0] - b[0]);
186
+ let i = 0;
187
+ function sub(r) {
188
+ const [a, b, t] = r;
189
+ const prefix = text.slice(i, a);
190
+ i = b;
191
+ return prefix + t;
192
+ }
193
+ return subs.map(sub).join("") + text.slice(i);
194
+ }
195
+ function checkTemplate(template) {
196
+ const chalk = new Chalk();
197
+ const chalkTemplate = makeTemplate(chalk);
198
+ const substitutions = {
199
+ $col: "<col>",
200
+ $contextFull: "<contextFull>",
201
+ $contextLeft: "<contextLeft>",
202
+ $contextRight: "<contextRight>",
203
+ $filename: "<filename>",
204
+ $padContext: "<padContext>",
205
+ $padRowCol: "<padRowCol>",
206
+ $row: "<row>",
207
+ $suggestions: "<suggestions>",
208
+ $text: "<text>",
209
+ $uri: "<uri>",
210
+ $quickFix: "<quickFix>",
211
+ $message: "<message>",
212
+ $messageColored: "<messageColored>"
213
+ };
214
+ try {
215
+ const problems = [...substitute(chalkTemplate(template), substitutions).matchAll(/\$[a-z]+/gi)].map((m) => m[0]);
216
+ if (problems.length) throw new Error(`Unresolved template variable${problems.length > 1 ? "s" : ""}: ${problems.map((v) => `'${v}'`).join(", ")}`);
217
+ return true;
218
+ } catch (e) {
219
+ return new ApplicationError(e instanceof Error ? e.message : `${e}`);
220
+ }
221
+ }
222
+ //#endregion
122
223
  //#region src/util/perfMeasurements.ts
123
224
  function getPerfMeasurements() {
124
225
  const measurements = performance.getEntriesByType("measure");
@@ -805,109 +906,10 @@ function extractNotableBySelfTimeInGroup(measurements) {
805
906
  if (highest) notable.add(highest);
806
907
  return notable;
807
908
  }
808
- function formatIssue(io, templateStr, issue, maxIssueTextWidth) {
809
- function clean(t) {
810
- return t.replace(/\s+/, " ");
811
- }
812
- const { uri = "", filename, row, col, text, context = issue.line, offset } = issue;
813
- const textLen = issue.length ?? text.length;
814
- const contextLeft = clean(context.text.slice(0, offset - context.offset));
815
- const contextRight = clean(context.text.slice(offset + textLen - context.offset));
816
- const contextFull = clean(context.text);
817
- const padContext = " ".repeat(Math.max(maxIssueTextWidth - text.length, 0));
818
- const rowText = row.toString();
819
- const colText = col.toString();
820
- const padRowCol = " ".repeat(Math.max(1, 8 - (rowText.length + colText.length)));
821
- const suggestions = formatSuggestions(io, issue);
822
- const msg = issue.message || (issue.isFlagged ? "Forbidden word" : "Unknown word");
823
- const messageColored = issue.isFlagged ? `{yellow ${msg}}` : msg;
824
- const substitutions = {
825
- $col: colText,
826
- $contextFull: contextFull,
827
- $contextLeft: contextLeft,
828
- $contextRight: contextRight,
829
- $filename: filename,
830
- $padContext: padContext,
831
- $padRowCol: padRowCol,
832
- $row: rowText,
833
- $suggestions: suggestions,
834
- $text: text,
835
- $uri: uri,
836
- $quickFix: formatQuickFix(io, issue),
837
- $message: msg,
838
- $messageColored: messageColored
839
- };
840
- const t = templateStr.replaceAll("$messageColored", messageColored);
841
- return substitute(makeTemplate(io.chalk)(t), substitutions).trimEnd();
842
- }
843
- function formatSuggestions(io, issue) {
844
- if (issue.suggestionsEx) return issue.suggestionsEx.map((sug) => sug.isPreferred ? io.chalk.italic(io.chalk.bold(sug.wordAdjustedToMatchCase || sug.word)) + "*" : sug.wordAdjustedToMatchCase || sug.word).join(", ");
845
- if (issue.suggestions) return issue.suggestions.join(", ");
846
- return "";
847
- }
848
- function formatQuickFix(io, issue) {
849
- if (!issue.suggestionsEx?.length) return "";
850
- const preferred = issue.suggestionsEx.filter((sug) => sug.isPreferred).map((sug) => sug.wordAdjustedToMatchCase || sug.word);
851
- if (!preferred.length) return "";
852
- return `fix: (${preferred.map((w) => io.chalk.italic(io.chalk.yellow(w))).join(", ")})`;
853
- }
854
- function substitute(text, substitutions) {
855
- const subs = [];
856
- for (const [match, replaceWith] of Object.entries(substitutions)) {
857
- const len = match.length;
858
- for (let i = text.indexOf(match); i >= 0; i = text.indexOf(match, i)) {
859
- const end = i + len;
860
- const reg = /\b/y;
861
- reg.lastIndex = end;
862
- if (reg.test(text)) subs.push([
863
- i,
864
- end,
865
- replaceWith
866
- ]);
867
- i = end;
868
- }
869
- }
870
- subs.sort((a, b) => a[0] - b[0]);
871
- let i = 0;
872
- function sub(r) {
873
- const [a, b, t] = r;
874
- const prefix = text.slice(i, a);
875
- i = b;
876
- return prefix + t;
877
- }
878
- return subs.map(sub).join("") + text.slice(i);
879
- }
880
909
  function assertCheckTemplate(template) {
881
910
  const r = checkTemplate(template);
882
911
  if (r instanceof Error) throw r;
883
912
  }
884
- function checkTemplate(template) {
885
- const chalk = new Chalk();
886
- const chalkTemplate = makeTemplate(chalk);
887
- const substitutions = {
888
- $col: "<col>",
889
- $contextFull: "<contextFull>",
890
- $contextLeft: "<contextLeft>",
891
- $contextRight: "<contextRight>",
892
- $filename: "<filename>",
893
- $padContext: "<padContext>",
894
- $padRowCol: "<padRowCol>",
895
- $row: "<row>",
896
- $suggestions: "<suggestions>",
897
- $text: "<text>",
898
- $uri: "<uri>",
899
- $quickFix: "<quickFix>",
900
- $message: "<message>",
901
- $messageColored: "<messageColored>"
902
- };
903
- try {
904
- const problems = [...substitute(chalkTemplate(template), substitutions).matchAll(/\$[a-z]+/gi)].map((m) => m[0]);
905
- if (problems.length) throw new Error(`Unresolved template variable${problems.length > 1 ? "s" : ""}: ${problems.map((v) => `'${v}'`).join(", ")}`);
906
- return true;
907
- } catch (e) {
908
- return new ApplicationError(e instanceof Error ? e.message : `${e}`);
909
- }
910
- }
911
913
  //#endregion
912
914
  //#region src/config/adjustConfig.ts
913
915
  async function fileExists(url) {
@@ -1200,7 +1202,9 @@ const environmentKeys = {
1200
1202
  CSPELL_ENABLE_DICTIONARY_LOG_FIELDS: "CSPELL_ENABLE_DICTIONARY_LOG_FIELDS",
1201
1203
  CSPELL_GLOB_ROOT: "CSPELL_GLOB_ROOT",
1202
1204
  CSPELL_CONFIG_PATH: "CSPELL_CONFIG_PATH",
1203
- CSPELL_DEFAULT_CONFIG_PATH: "CSPELL_DEFAULT_CONFIG_PATH"
1205
+ CSPELL_DEFAULT_CONFIG_PATH: "CSPELL_DEFAULT_CONFIG_PATH",
1206
+ CSPELL_FOLLOW_SYMLINKS: "CSPELL_FOLLOW_SYMLINKS",
1207
+ CSPELL_GLOB_SYMLINKS: "CSPELL_GLOB_SYMLINKS"
1204
1208
  };
1205
1209
  function setEnvironmentVariable(key, value) {
1206
1210
  process.env[key] = value;
@@ -1230,7 +1234,7 @@ try {
1230
1234
  const pkgDir = _dirname;
1231
1235
  const npmPackage = {
1232
1236
  name: "cspell",
1233
- version: "10.3.6",
1237
+ version: "10.4.0",
1234
1238
  engines: { node: ">=22.18.0" }
1235
1239
  };
1236
1240
  //#endregion
@@ -1465,7 +1469,7 @@ async function globP(pattern, options) {
1465
1469
  dot,
1466
1470
  ignore,
1467
1471
  absolute: true,
1468
- followSymbolicLinks: false,
1472
+ followSymbolicLinks: options?.followSymlinks ?? false,
1469
1473
  expandDirectories: false
1470
1474
  });
1471
1475
  const compare = new Intl.Collator("en").compare;
@@ -2322,6 +2326,48 @@ async function readConfigHandleError(filename) {
2322
2326
  }
2323
2327
  }
2324
2328
  //#endregion
2329
+ //#region src/util/symlinks.ts
2330
+ function createSymlinkChecker(root) {
2331
+ const rootPath = path$1.resolve(root);
2332
+ const cache = /* @__PURE__ */ new Map();
2333
+ function isSymlink(filename) {
2334
+ let found = cache.get(filename);
2335
+ if (!found) {
2336
+ found = promises.lstat(filename).then((s) => s.isSymbolicLink(), () => false);
2337
+ cache.set(filename, found);
2338
+ }
2339
+ return found;
2340
+ }
2341
+ async function isReachedThroughSymlink(filename) {
2342
+ if (filename === "stdin" || isStdinUrl(filename)) return false;
2343
+ const absFilename = path$1.resolve(rootPath, filename);
2344
+ const rel = path$1.relative(rootPath, absFilename);
2345
+ if (!rel) return false;
2346
+ if (rel === ".." || rel.startsWith(".." + path$1.sep) || path$1.isAbsolute(rel)) return isSymlink(absFilename);
2347
+ let current = rootPath;
2348
+ for (const segment of rel.split(path$1.sep)) {
2349
+ current = path$1.join(current, segment);
2350
+ if (await isSymlink(current)) return true;
2351
+ }
2352
+ return false;
2353
+ }
2354
+ async function isGlobReachedThroughSymlink(pattern) {
2355
+ const segments = pattern.split("/");
2356
+ const fixed = [];
2357
+ for (const segment of segments) {
2358
+ if (isDynamicPattern(segment)) break;
2359
+ fixed.push(segment);
2360
+ }
2361
+ const base = fixed.join("/");
2362
+ if (!base) return false;
2363
+ return isReachedThroughSymlink(path$1.resolve(rootPath, base));
2364
+ }
2365
+ return {
2366
+ isReachedThroughSymlink,
2367
+ isGlobReachedThroughSymlink
2368
+ };
2369
+ }
2370
+ //#endregion
2325
2371
  //#region src/util/timer.ts
2326
2372
  function getTimeMeasurer() {
2327
2373
  const timer = createPerfTimer("timer");
@@ -2721,13 +2767,30 @@ function prefetch(fileToProcess, cfg) {
2721
2767
  const reportIssueOptions = extractReporterIssueOptions(cfg.config);
2722
2768
  async function fetch() {
2723
2769
  const getElapsedTimeMs = getTimeMeasurer();
2770
+ if (!cfg.followSymlinks && await cfg.symlinks.isReachedThroughSymlink(filename)) {
2771
+ const skipReason = "referenced by a symbolic link, use --follow-symlinks to check it";
2772
+ if (cfg.forceCheck) return {
2773
+ skip: true,
2774
+ skipReason,
2775
+ error: new LinterError(`File ${skipReason}: "${filename}"`)
2776
+ };
2777
+ return {
2778
+ skip: true,
2779
+ skipReason: cfg.verbose ? skipReason : void 0
2780
+ };
2781
+ }
2724
2782
  const cachedResult = await cfg.cache.getCachedLintResults(filename);
2725
2783
  if (cachedResult) return { fileResult: {
2726
2784
  ...cachedResult,
2727
2785
  elapsedTimeMs: getElapsedTimeMs()
2728
2786
  } };
2729
2787
  const uri = filenameToUri(filename, cfg.root).href;
2730
- const checkResult = await shouldCheckDocument({ uri }, { forceCheck: cfg.forceCheck }, cfg.config);
2788
+ const { languageId, locale } = cfg;
2789
+ const checkResult = await shouldCheckDocument({
2790
+ uri,
2791
+ languageId,
2792
+ locale
2793
+ }, { forceCheck: cfg.forceCheck }, cfg.config);
2731
2794
  if (!checkResult.shouldCheck) return {
2732
2795
  skip: true,
2733
2796
  skipReason: checkResult.reason || "Ignored by configuration."
@@ -2759,6 +2822,11 @@ async function processFiles(files, options) {
2759
2822
  root: options.cfg.root,
2760
2823
  maxFileSize: options.cfg.maxFileSize,
2761
2824
  forceCheck: !!options.cfg.options.forceCheck,
2825
+ symlinks: options.symlinks ?? createSymlinkChecker(options.cfg.root),
2826
+ followSymlinks: !!options.followSymlinks,
2827
+ verbose: options.verboseLevel > 0,
2828
+ languageId: options.cfg.options.languageId || void 0,
2829
+ locale: options.cfg.locale || void 0,
2762
2830
  config: options.configInfo.config,
2763
2831
  cache
2764
2832
  };
@@ -2794,17 +2862,24 @@ async function processFiles(files, options) {
2794
2862
  if (fetchResult instanceof Error) throw fetchResult;
2795
2863
  const fileNum = sequence + 1;
2796
2864
  reporter.emitProgressBegin(filename, fileNum, pf.sequenceSize ?? sequence);
2797
- if (fetchResult?.skip) return {
2798
- filename,
2799
- sequence,
2800
- sequenceSize,
2801
- result: {
2865
+ if (fetchResult?.skip) {
2866
+ const result = {
2802
2867
  ...emptyResult,
2803
2868
  fileInfo: { filename },
2804
2869
  elapsedTimeMs: getElapsedTimeMs(),
2805
2870
  skippedReason: fetchResult.skipReason
2871
+ };
2872
+ if (fetchResult.error) {
2873
+ new ReportItemCollector(result).error("Linter:", fetchResult.error);
2874
+ result.errors = 1;
2806
2875
  }
2807
- };
2876
+ return {
2877
+ filename,
2878
+ sequence,
2879
+ sequenceSize,
2880
+ result
2881
+ };
2882
+ }
2808
2883
  return {
2809
2884
  filename,
2810
2885
  sequence,
@@ -2860,7 +2935,7 @@ function runResult(init = {}) {
2860
2935
  };
2861
2936
  }
2862
2937
  //#endregion
2863
- //#region \0@oxc-project+runtime@0.148.0/helpers/esm/usingCtx.js
2938
+ //#region \0@oxc-project+runtime@0.153.0/helpers/esm/usingCtx.js
2864
2939
  function _usingCtx() {
2865
2940
  var r = "function" == typeof SuppressedError ? SuppressedError : function(r, e) {
2866
2941
  var n = Error();
@@ -2969,7 +3044,8 @@ async function runLint(cfg) {
2969
3044
  ...cfg.options,
2970
3045
  version
2971
3046
  }, root);
2972
- const filesToCheck = await determineFilesToCheck(configInfo, cfg, reporter, globInfo);
3047
+ const symlinks = createSymlinkChecker(root);
3048
+ const filesToCheck = await determineFilesToCheck(configInfo, cfg, reporter, globInfo, symlinks);
2973
3049
  const processFilesOptions = {
2974
3050
  chalk,
2975
3051
  configInfo,
@@ -2979,7 +3055,9 @@ async function runLint(cfg) {
2979
3055
  configErrors,
2980
3056
  userSettings: configInfo.config,
2981
3057
  lintReporter: reporter,
2982
- cacheSettings
3058
+ cacheSettings,
3059
+ symlinks,
3060
+ followSymlinks: filesToCheck.followSymlinks
2983
3061
  };
2984
3062
  const result = await processFiles(filesToCheck.files, processFilesOptions);
2985
3063
  if (configErrorCount && cfg.options.exitCode !== false) result.errors ||= configErrorCount;
@@ -3060,10 +3138,11 @@ function filesToProcess(files) {
3060
3138
  sequenceSize
3061
3139
  }));
3062
3140
  }
3063
- async function determineFilesToCheck(configInfo, cfg, reporter, globInfo) {
3141
+ async function determineFilesToCheck(configInfo, cfg, reporter, globInfo, symlinks) {
3064
3142
  const result = {
3065
3143
  files: [],
3066
- numFiles: 0
3144
+ numFiles: 0,
3145
+ followSymlinks: false
3067
3146
  };
3068
3147
  function countFiles(fnKeep) {
3069
3148
  if (!fnKeep) return () => {
@@ -3081,6 +3160,13 @@ async function determineFilesToCheck(configInfo, cfg, reporter, globInfo) {
3081
3160
  async function determineFilesToCheckFromCliFiles() {
3082
3161
  const { fileLists } = cfg;
3083
3162
  const hasFileLists = !!fileLists.length;
3163
+ const followSymlinks = cfg.options.followSymlinks ?? truthy(getEnvironmentVariable("CSPELL_FOLLOW_SYMLINKS"));
3164
+ result.followSymlinks = followSymlinks;
3165
+ const keepSymlinks = (fn) => followSymlinks ? fn : async (file) => await symlinks.isReachedThroughSymlink(file) || fn(file);
3166
+ if (!followSymlinks) for (const fileList of fileLists) {
3167
+ if (fileList === "stdin") continue;
3168
+ if (await symlinks.isReachedThroughSymlink(path$1.resolve(fileList))) throw new ApplicationError(`Error reading file list from: "${fileList}". It is referenced by a symbolic link, use --follow-symlinks to read it.`);
3169
+ }
3084
3170
  const { gitIgnore, allGlobs, excludeGlobs, normalizedExcludes } = globInfo;
3085
3171
  const { root } = cfg;
3086
3172
  const globsToExcludeRaw = [...configInfo.config.ignorePaths || [], ...excludeGlobs];
@@ -3100,8 +3186,8 @@ async function determineFilesToCheck(configInfo, cfg, reporter, globInfo) {
3100
3186
  if (enableGlobDot !== void 0) globOptions.dot = enableGlobDot;
3101
3187
  const includeFilterCountSkipped = countFiles(cfg.options.forceCheck && !cfg.fileGlobs.length ? () => true : createIncludeFileFilterFn(allGlobs, root, enableGlobDot));
3102
3188
  const rawCliFiles = cfg.files?.map((file) => resolveFilename(file, root)).filter(includeFilterCountSkipped);
3103
- const cliFiles = cfg.options.mustFindFiles ? rawCliFiles : rawCliFiles && pipeAsync(rawCliFiles, opFilterAsync(isFile));
3104
- const foundFiles = hasFileLists ? concatAsyncIterables(cliFiles, await useFileLists(fileLists, includeFilterCountSkipped)) : cliFiles || [];
3189
+ const cliFiles = cfg.options.mustFindFiles ? rawCliFiles : rawCliFiles && pipeAsync(rawCliFiles, opFilterAsync(keepSymlinks(isFile)));
3190
+ const foundFiles = hasFileLists ? concatAsyncIterables(cliFiles, await useFileLists(fileLists, includeFilterCountSkipped, keepSymlinks(isNotDir))) : cliFiles || [];
3105
3191
  const opFilterExcludedFiles = opFilter(filterOutExcludedFilesFn(globMatcher));
3106
3192
  const filtered = !cfg.options.forceCheck && gitIgnore ? await gitIgnore.filterOutIgnored(foundFiles) : foundFiles;
3107
3193
  return isAsyncIterable(filtered) ? pipeAsync(filtered, opFilterExcludedFiles, filesToProcessAsync) : filesToProcess(pipe(filtered, opFilterExcludedFiles));
@@ -3124,8 +3210,19 @@ async function determineFilesToCheck(configInfo, cfg, reporter, globInfo) {
3124
3210
  };
3125
3211
  const enableGlobDot = cfg.enableGlobDot ?? configInfo.config.enableGlobDot;
3126
3212
  if (enableGlobDot !== void 0) globOptions.dot = enableGlobDot;
3213
+ const globSymlinks = cfg.options.globSymlinks ?? truthy(getEnvironmentVariable("CSPELL_GLOB_SYMLINKS"));
3214
+ globOptions.followSymlinks = globSymlinks;
3215
+ result.followSymlinks = globSymlinks;
3127
3216
  const opFilterExcludedFiles = opFilter(filterOutExcludedFilesFn(globMatcher));
3128
- const foundFiles = await findFiles(fileGlobs, globOptions);
3217
+ const globsToSearch = [];
3218
+ for (const glob of fileGlobs) {
3219
+ if (!globSymlinks && await symlinks.isGlobReachedThroughSymlink(glob)) {
3220
+ if (calcVerboseLevel(cfg.options) > 0) reporter.info(`Glob not searched: "${glob}" goes through a symbolic link.`, MessageTypes$1.Info);
3221
+ continue;
3222
+ }
3223
+ globsToSearch.push(glob);
3224
+ }
3225
+ const foundFiles = await findFiles(globsToSearch, globOptions);
3129
3226
  const filtered = gitIgnore ? await gitIgnore.filterOutIgnored(foundFiles) : foundFiles;
3130
3227
  return isAsyncIterable(filtered) ? pipeAsync(filtered, opFilterExcludedFiles, filesToProcessAsync, opFilter(countFiles())) : filesToProcess(pipe(filtered, opFilterExcludedFiles)).filter(countFiles());
3131
3228
  }
@@ -3192,9 +3289,9 @@ async function generateGitIgnore(roots) {
3192
3289
  }
3193
3290
  return new GitIgnore(root?.map((p) => path$1.resolve(p)));
3194
3291
  }
3195
- async function useFileLists(fileListFiles, filterFiles) {
3292
+ async function useFileLists(fileListFiles, filterFiles, filterNotDir) {
3196
3293
  const files = readFileListFiles(fileListFiles);
3197
- return pipeAsync(files, opFilter(filterFiles), opFilterAsync(isNotDir));
3294
+ return pipeAsync(files, opFilter(filterFiles), opFilterAsync(filterNotDir));
3198
3295
  }
3199
3296
  function createIncludeFileFilterFn(includeGlobPatterns, root, dot) {
3200
3297
  if (!includeGlobPatterns?.length) return () => true;
@@ -3569,4 +3666,4 @@ function parseApplicationFeatureFlags(flags) {
3569
3666
  //#endregion
3570
3667
  export { ApplicationError as C, width as S, console as T, padLeft as _, parseApplicationFeatureFlags as a, pruneAnsiTextEnd as b, listDictionaries as c, validateUnitSize as d, unindent as f, tableToLines as g, getReporter as h, lint as i, ReportChoicesAll as l, npmPackage as m, checkText as n, suggestions as o, DEFAULT_CACHE_LOCATION as p, createInit as r, trace as s, IncludeExcludeFlag as t, cvtLinterCliCommandOptionsToLinterCliOptions as u, padWidth as v, CheckFailed as w, pruneAnsiTextStart as x, ansiWidth as y };
3571
3668
 
3572
- //# sourceMappingURL=application-yI9NNGsb.js.map
3669
+ //# sourceMappingURL=application-IkKZuulS.js.map
@@ -1,2 +1,2 @@
1
- import { a as checkText, c as parseApplicationFeatureFlags, d as listDictionaries, i as TraceResult, l as suggestions, n as CheckTextResult, o as createInit, r as IncludeExcludeFlag, s as lint, t as AppError, u as trace } from "./application-094uTsvC.js";
1
+ import { a as checkText, c as parseApplicationFeatureFlags, d as listDictionaries, i as TraceResult, l as suggestions, n as CheckTextResult, o as createInit, r as IncludeExcludeFlag, s as lint, t as AppError, u as trace } from "./application-CFfMlhE_.js";
2
2
  export { AppError, CheckTextResult, IncludeExcludeFlag, type TraceResult, checkText, createInit, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace };
@@ -1,2 +1 @@
1
- import { a as parseApplicationFeatureFlags, c as listDictionaries, i as lint, n as checkText, o as suggestions, r as createInit, s as trace, t as IncludeExcludeFlag } from "./application-yI9NNGsb.js";
2
- export { IncludeExcludeFlag, checkText, createInit, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace };
1
+ export { t as IncludeExcludeFlag, n as checkText, r as createInit, i as lint, c as listDictionaries, a as parseApplicationFeatureFlags, o as suggestions, s as trace } from "./application-IkKZuulS.js";
@@ -1,12 +1,21 @@
1
- import { i as LinterCliOptions, o as TraceOptions, s as FinalizedReporter, t as BaseOptions } from "./options-DlXe327y.js";
2
- import { a as checkText, c as parseApplicationFeatureFlags, d as listDictionaries, i as TraceResult, l as suggestions, n as CheckTextResult, o as createInit, r as IncludeExcludeFlag, s as lint, t as AppError, u as trace } from "./application-094uTsvC.js";
3
- import "chalk";
1
+ import { i as LinterCliOptions, o as TraceOptions, s as FinalizedReporter, t as BaseOptions } from "./options-D5lC3IZu.js";
2
+ import { a as checkText, c as parseApplicationFeatureFlags, d as listDictionaries, i as TraceResult, l as suggestions, n as CheckTextResult, o as createInit, r as IncludeExcludeFlag, s as lint, t as AppError, u as trace } from "./application-CFfMlhE_.js";
4
3
  import { CSpellReporter, ReporterConfiguration } from "@cspell/cspell-types";
5
- import { WriteStream } from "node:tty";
6
4
  export * from "@cspell/cspell-types";
7
5
  //#region src/console.d.ts
8
6
  type Log = (format?: any, ...params: any[]) => void;
9
- type IOStream = NodeJS.WritableStream & Pick<WriteStream, "isTTY" | "rows" | "columns"> & Pick<Partial<WriteStream>, "hasColors" | "clearLine" | "getColorDepth">;
7
+ /**
8
+ * The parts of an output stream, such as `process.stdout`, that the console uses.
9
+ */
10
+ interface IOStream {
11
+ write(chunk: string): boolean;
12
+ isTTY: boolean;
13
+ rows: number;
14
+ columns: number;
15
+ hasColors?(count?: number): boolean;
16
+ clearLine?(dir: -1 | 0 | 1, callback?: () => void): boolean;
17
+ getColorDepth?(env?: object): number;
18
+ }
10
19
  interface IConsole {
11
20
  readonly log: Log;
12
21
  readonly error: Log;
@@ -43,5 +52,5 @@ interface ReporterOptions extends Pick<LinterCliOptions, "color" | "debug" | "is
43
52
  }
44
53
  declare function getReporter(options: ReporterOptions, config?: CSpellReporterConfiguration): FinalizedReporter;
45
54
  //#endregion
46
- export { AppError, type BaseOptions, type LinterCliOptions as CSpellApplicationOptions, type CSpellReporterConfiguration, type CSpellReporterModule, CheckTextResult, IncludeExcludeFlag, type TraceOptions, type TraceResult, checkText, createInit, getReporter as getDefaultReporter, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace };
55
+ export { type AppError, type BaseOptions, type LinterCliOptions as CSpellApplicationOptions, type CSpellReporterConfiguration, type CSpellReporterModule, type CheckTextResult, IncludeExcludeFlag, type TraceOptions, type TraceResult, checkText, createInit, getReporter as getDefaultReporter, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace };
47
56
  //# sourceMappingURL=index.d.ts.map
package/dist/esm/index.js CHANGED
@@ -1,3 +1,2 @@
1
- import { a as parseApplicationFeatureFlags, c as listDictionaries, h as getReporter, i as lint, n as checkText, o as suggestions, r as createInit, s as trace, t as IncludeExcludeFlag } from "./application-yI9NNGsb.js";
1
+ export { t as IncludeExcludeFlag, n as checkText, r as createInit, h as getDefaultReporter, i as lint, c as listDictionaries, a as parseApplicationFeatureFlags, o as suggestions, s as trace } from "./application-IkKZuulS.js";
2
2
  export * from "@cspell/cspell-types";
3
- export { IncludeExcludeFlag, checkText, createInit, getReporter as getDefaultReporter, lint, listDictionaries, parseApplicationFeatureFlags, suggestions, trace };
@@ -119,6 +119,23 @@ interface LinterOptions extends Omit<BaseOptions, "config">, Omit<CacheOptions,
119
119
  * Files must be found and processed otherwise it is considered an error.
120
120
  */
121
121
  mustFindFiles?: boolean;
122
+ /**
123
+ * Allow checking `--file` and `--file-list` documents referenced by symbolic links.
124
+ * By default, a file that is a symbolic link, or is in a linked directory, is skipped.
125
+ * Glob searches are controlled by {@link LinterOptions.globSymlinks}.
126
+ *
127
+ * When not set, the `CSPELL_FOLLOW_SYMLINKS` environment variable is used.
128
+ * @default false
129
+ */
130
+ followSymlinks?: boolean | undefined;
131
+ /**
132
+ * Follow symbolic links when matching globs.
133
+ * By default, glob searches skip files that are symbolic links and don't search linked directories.
134
+ *
135
+ * When not set, the `CSPELL_GLOB_SYMLINKS` environment variable is used.
136
+ * @default false
137
+ */
138
+ globSymlinks?: boolean | undefined;
122
139
  /**
123
140
  * List of dictionary names to use.
124
141
  */
@@ -407,4 +424,4 @@ interface CSpellConfigFile {
407
424
  }
408
425
  //#endregion
409
426
  export { SuggestionOptions as a, LinterCliOptions as i, DictionariesOptions as n, TraceOptions as o, LegacyOptions as r, FinalizedReporter as s, BaseOptions as t };
410
- //# sourceMappingURL=options-DlXe327y.d.ts.map
427
+ //# sourceMappingURL=options-D5lC3IZu.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cspell",
3
- "version": "10.3.6",
3
+ "version": "10.4.0",
4
4
  "description": "A Spelling Checker for Code!",
5
5
  "publishConfig": {
6
6
  "access": "public",
@@ -72,9 +72,9 @@
72
72
  "scripts": {
73
73
  "build": "tsdown && pnpm build:tsc",
74
74
  "build:readme": "pnpm build:readme:help",
75
- "build:readme:help": "pnpm build:readme:help:lint && pnpm build:readme:help:trace && inject-markdown README.md && prettier -w README.md",
76
- "build:readme:help:lint": "./bin.mjs lint --help > static/help-lint.txt",
77
- "build:readme:help:trace": "./bin.mjs trace --help > static/help-trace.txt",
75
+ "build:readme:help": "pnpm build:readme:help:lint && pnpm build:readme:help:trace && inject-markdown --allow-outside-root ../.. README.md && prettier -w README.md",
76
+ "build:readme:help:lint": "COLUMNS=72 ./bin.mjs lint --help > static/help-lint.txt",
77
+ "build:readme:help:trace": "COLUMNS=72 ./bin.mjs trace --help > static/help-trace.txt",
78
78
  "build:tsc": "tsc -p .",
79
79
  "clean": "shx rm -rf dist temp coverage \"*.tsbuildInfo\"",
80
80
  "clean-build": "pnpm run clean && pnpm run build",
@@ -90,23 +90,23 @@
90
90
  "watch:tsc": "tsc -p . -w"
91
91
  },
92
92
  "dependencies": {
93
- "@cspell/cspell-json-reporter": "10.3.6",
94
- "@cspell/cspell-performance-monitor": "10.3.6",
95
- "@cspell/cspell-pipe": "10.3.6",
96
- "@cspell/cspell-types": "10.3.6",
97
- "@cspell/cspell-worker": "10.3.6",
98
- "@cspell/dynamic-import": "10.3.6",
99
- "@cspell/url": "10.3.6",
100
- "ansi-regex": "^6.3.0",
101
- "chalk": "^6.0.0",
102
- "chalk-template": "^1.1.2",
93
+ "@cspell/cspell-json-reporter": "10.4.0",
94
+ "@cspell/cspell-performance-monitor": "10.4.0",
95
+ "@cspell/cspell-pipe": "10.4.0",
96
+ "@cspell/cspell-types": "10.4.0",
97
+ "@cspell/cspell-worker": "10.4.0",
98
+ "@cspell/dynamic-import": "10.4.0",
99
+ "@cspell/url": "10.4.0",
100
+ "ansi-regex": "^6.4.0",
101
+ "chalk": "^6.0.1",
102
+ "chalk-template": "^1.1.3",
103
103
  "commander": "^15.0.0",
104
- "cspell-config-lib": "10.3.6",
105
- "cspell-dictionary": "10.3.6",
106
- "cspell-gitignore": "10.3.6",
107
- "cspell-glob": "10.3.6",
108
- "cspell-io": "10.3.6",
109
- "cspell-lib": "10.3.6",
104
+ "cspell-config-lib": "10.4.0",
105
+ "cspell-dictionary": "10.4.0",
106
+ "cspell-gitignore": "10.4.0",
107
+ "cspell-glob": "10.4.0",
108
+ "cspell-io": "10.4.0",
109
+ "cspell-lib": "10.4.0",
110
110
  "flatted": "^3.4.4",
111
111
  "semver": "^7.8.5",
112
112
  "tinyglobby": "^0.2.17"
@@ -120,5 +120,5 @@
120
120
  "engines": {
121
121
  "node": ">=22.18.0"
122
122
  },
123
- "gitHead": "8559198ccfcac2f745911db1ffe2ee62c17cba49"
123
+ "gitHead": "7e2bbb5e866c827ac5d2cf6b84bf3e1a016d0823"
124
124
  }