cspell 8.4.0 → 8.5.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
@@ -150,6 +150,8 @@ Options:
150
150
  --file-list <path or stdin> Specify a list of files to be spell checked. The
151
151
  list is filtered against the glob file patterns.
152
152
  Note: the format is 1 file path per line.
153
+ --file [file...] Specify files to spell check. They are filtered
154
+ by the [globs...].
153
155
  --no-issues Do not show the spelling errors.
154
156
  --no-progress Turn off progress messages
155
157
  --no-summary Turn off summary message in console.
@@ -202,6 +204,13 @@ More Examples:
202
204
  cspell . --reporter ./<path>/reporter.cjs
203
205
  Use a custom reporter. See API for details.
204
206
 
207
+ cspell "*.md" --exclude CHANGELOG.md --files README.md CHANGELOG.md
208
+ Spell check only check "README.md" but NOT "CHANGELOG.md".
209
+
210
+ cspell "/*.md" --no-must-find-files --files $FILES
211
+ Only spell check the "/*.md" files in $FILES,
212
+ where $FILES is a shell variable that contains the list of files.
213
+
205
214
  References:
206
215
  https://cspell.org
207
216
  https://github.com/streetsidesoftware/cspell
@@ -37,15 +37,20 @@ More Examples:
37
37
  cspell . --reporter ./<path>/reporter.cjs
38
38
  Use a custom reporter. See API for details.
39
39
 
40
+ cspell "*.md" --exclude CHANGELOG.md --files README.md CHANGELOG.md
41
+ Spell check only check "README.md" but NOT "CHANGELOG.md".
42
+
43
+ cspell "/*.md" --no-must-find-files --files $FILES
44
+ Only spell check the "/*.md" files in $FILES,
45
+ where $FILES is a shell variable that contains the list of files.
46
+
40
47
  References:
41
48
  https://cspell.org
42
49
  https://github.com/streetsidesoftware/cspell
43
50
  `;
44
51
  function collect(value, previous) {
45
- if (!previous) {
46
- return [value];
47
- }
48
- return previous.concat([value]);
52
+ const values = Array.isArray(value) ? value : [value];
53
+ return previous ? [...previous, ...values] : values;
49
54
  }
50
55
  export function commandLint(prog) {
51
56
  const spellCheckCommand = prog.command('lint', { isDefault: true });
@@ -55,42 +60,51 @@ export function commandLint(prog) {
55
60
  .option('-v, --verbose', 'Display more information about the files being checked and the configuration.')
56
61
  .option('--locale <locale>', 'Set language locales. i.e. "en,fr" for English and French, or "en-GB" for British English.')
57
62
  .option('--language-id <language>', 'Force programming language for unknown extensions. i.e. "php" or "scala"')
58
- .addOption(new CommanderOption('--languageId <language>', 'Force programming language for unknown extensions. i.e. "php" or "scala"').hideHelp())
63
+ .addOption(crOpt('--languageId <language>', 'Force programming language for unknown extensions. i.e. "php" or "scala"').hideHelp())
59
64
  .option('--words-only', 'Only output the words not found in the dictionaries.')
60
- .addOption(new CommanderOption('--wordsOnly', 'Only output the words not found in the dictionaries.').hideHelp())
65
+ .addOption(crOpt('--wordsOnly', 'Only output the words not found in the dictionaries.').hideHelp())
61
66
  .option('-u, --unique', 'Only output the first instance of a word not found in the dictionaries.')
62
67
  .option('-e, --exclude <glob>', 'Exclude files matching the glob pattern. This option can be used multiple times to add multiple globs. ', collect)
68
+ // .option('--include <glob>', 'Include files matching the glob pattern. This option can be used multiple times.', collect)
63
69
  .option('--file-list <path or stdin>', 'Specify a list of files to be spell checked.' +
64
70
  ' The list is filtered against the glob file patterns.' +
65
71
  ' Note: the format is 1 file path per line.', collect)
72
+ .option('--file [file...]', 'Specify files to spell check. They are filtered by the [globs...].', collect)
73
+ .addOption(crOpt('--files [file...]', 'Files to spell check.', collect).hideHelp())
66
74
  .option('--no-issues', 'Do not show the spelling errors.')
67
75
  .option('--no-progress', 'Turn off progress messages')
68
76
  .option('--no-summary', 'Turn off summary message in console.')
69
77
  .option('-s, --silent', 'Silent mode, suppress error messages.')
70
78
  .option('--no-exit-code', 'Do not return an exit code if issues are found.')
71
- .addOption(new CommanderOption('--quiet', 'Only show spelling issues or errors.').implies({
79
+ .addOption(crOpt('--quiet', 'Only show spelling issues or errors.').implies({
72
80
  summary: false,
73
81
  progress: false,
74
82
  }))
75
83
  .option('--fail-fast', 'Exit after first file with an issue or error.')
76
- .addOption(new CommanderOption('--no-fail-fast', 'Process all files even if there is an error.').hideHelp())
84
+ .addOption(crOpt('--no-fail-fast', 'Process all files even if there is an error.').hideHelp())
77
85
  .option('-r, --root <root folder>', 'Root directory, defaults to current directory.')
78
- .addOption(new CommanderOption('--relative', 'Issues are displayed relative to the root.').default(true).hideHelp())
86
+ .addOption(crOpt('--relative', 'Issues are displayed relative to the root.').default(true).hideHelp())
79
87
  .option('--no-relative', 'Issues are displayed with absolute path instead of relative to the root.')
80
88
  .option('--show-context', 'Show the surrounding text around an issue.')
81
89
  .option('--show-suggestions', 'Show spelling suggestions.')
82
- .addOption(new CommanderOption('--no-show-suggestions', 'Do not show spelling suggestions or fixes.').default(undefined))
83
- .addOption(new CommanderOption('--must-find-files', 'Error if no files are found.').default(true).hideHelp())
90
+ .addOption(crOpt('--no-show-suggestions', 'Do not show spelling suggestions or fixes.').default(undefined))
91
+ .addOption(crOpt('--must-find-files', 'Error if no files are found.').default(true).hideHelp())
84
92
  .option('--no-must-find-files', 'Do not error if no files are found.')
93
+ // The --filter-files option is still under design review.
94
+ // .option('--filter-files', 'Use the `files` configuration to filter files found.')
95
+ // .option(
96
+ // '--no-filter-files',
97
+ // 'Do NOT use the `files` configuration to filter files (Only applies to --files options).',
98
+ // )
85
99
  // The following options are planned features
86
100
  // .option('-w, --watch', 'Watch for any changes to the matching files and report any errors')
87
101
  // .option('--force', 'Force the exit value to always be 0')
88
- .addOption(new CommanderOption('--legacy', 'Legacy output').hideHelp())
89
- .addOption(new CommanderOption('--local <local>', 'Deprecated -- Use: --locale').hideHelp())
102
+ .addOption(crOpt('--legacy', 'Legacy output').hideHelp())
103
+ .addOption(crOpt('--local <local>', 'Deprecated -- Use: --locale').hideHelp())
90
104
  .option('--cache', 'Use cache to only check changed files.')
91
105
  .option('--no-cache', 'Do not use cache.')
92
106
  .option('--cache-reset', 'Reset the cache file.')
93
- .addOption(new CommanderOption('--cache-strategy <strategy>', 'Strategy to use for detecting changed files.').choices([
107
+ .addOption(crOpt('--cache-strategy <strategy>', 'Strategy to use for detecting changed files.').choices([
94
108
  'metadata',
95
109
  'content',
96
110
  ]))
@@ -103,26 +117,31 @@ export function commandLint(prog) {
103
117
  .option('--no-validate-directives', 'Do not validate in-document CSpell directives.')
104
118
  .option('--no-color', 'Turn off color.')
105
119
  .option('--color', 'Force color.')
106
- .addOption(new CommanderOption('--default-configuration', 'Load the default configuration and dictionaries.').hideHelp())
107
- .addOption(new CommanderOption('--no-default-configuration', 'Do not load the default configuration and dictionaries.'))
120
+ .addOption(crOpt('--default-configuration', 'Load the default configuration and dictionaries.').hideHelp())
121
+ .addOption(crOpt('--no-default-configuration', 'Do not load the default configuration and dictionaries.'))
108
122
  .option('--debug', 'Output information useful for debugging cspell.json files.')
109
123
  .option('--reporter <module|path>', 'Specify one or more reporters to use.', collect)
110
- .addOption(new CommanderOption('--skip-validation', 'Collect and process documents, but do not spell check.')
124
+ .addOption(crOpt('--skip-validation', 'Collect and process documents, but do not spell check.')
111
125
  .implies({ cache: false })
112
126
  .hideHelp())
113
- .addOption(new CommanderOption('--issues-summary-report', 'Output a summary of issues found.').hideHelp())
127
+ .addOption(crOpt('--issues-summary-report', 'Output a summary of issues found.').hideHelp())
128
+ // Planned options
129
+ // .option('--dictionary <dictionary name>', 'Enable a dictionary by name.', collect)
130
+ // .option('--no-dictionary <dictionary name>', 'Disable a dictionary by name.', collect)
131
+ // .option('--import', 'Import a configuration file.', collect)
114
132
  .usage(usage)
115
133
  .addHelpText('after', advanced)
116
134
  .arguments('[globs...]')
117
135
  .action(async (fileGlobs, options) => {
136
+ // console.error('lint: %o', { fileGlobs, options });
118
137
  const useExitCode = options.exitCode ?? true;
119
138
  if (options.skipValidation) {
120
139
  options.cache = false;
121
140
  }
122
141
  App.parseApplicationFeatureFlags(options.flag);
123
- const { mustFindFiles, fileList } = options;
142
+ const { mustFindFiles, fileList, files, file } = options;
124
143
  const result = await App.lint(fileGlobs, options);
125
- if (!fileGlobs.length && !result.files && !result.errors && !fileList) {
144
+ if (!fileGlobs.length && !result.files && !result.errors && !fileList && !files?.length && !file?.length) {
126
145
  spellCheckCommand.outputHelp();
127
146
  throw new CheckFailed('outputHelp', 1);
128
147
  }
@@ -137,4 +156,22 @@ export function commandLint(prog) {
137
156
  });
138
157
  return spellCheckCommand;
139
158
  }
159
+ /**
160
+ * Create Option - a helper function to create a commander option.
161
+ * @param name - the name of the option
162
+ * @param description - the description of the option
163
+ * @param parseArg - optional function to parse the argument
164
+ * @param defaultValue - optional default value
165
+ * @returns CommanderOption
166
+ */
167
+ function crOpt(name, description, parseArg, defaultValue) {
168
+ const option = new CommanderOption(name, description);
169
+ if (parseArg) {
170
+ option.argParser(parseArg);
171
+ }
172
+ if (defaultValue !== undefined) {
173
+ option.default(defaultValue);
174
+ }
175
+ return option;
176
+ }
140
177
  //# sourceMappingURL=commandLint.js.map
@@ -37,15 +37,20 @@ More Examples:
37
37
  cspell . --reporter ./<path>/reporter.cjs
38
38
  Use a custom reporter. See API for details.
39
39
 
40
+ cspell "*.md" --exclude CHANGELOG.md --files README.md CHANGELOG.md
41
+ Spell check only check "README.md" but NOT "CHANGELOG.md".
42
+
43
+ cspell "/*.md" --no-must-find-files --files $FILES
44
+ Only spell check the "/*.md" files in $FILES,
45
+ where $FILES is a shell variable that contains the list of files.
46
+
40
47
  References:
41
48
  https://cspell.org
42
49
  https://github.com/streetsidesoftware/cspell
43
50
  `;
44
51
  function collect(value, previous) {
45
- if (!previous) {
46
- return [value];
47
- }
48
- return previous.concat([value]);
52
+ const values = Array.isArray(value) ? value : [value];
53
+ return previous ? [...previous, ...values] : values;
49
54
  }
50
55
  export function commandLint(prog) {
51
56
  const spellCheckCommand = prog.command('lint', { isDefault: true });
@@ -55,42 +60,51 @@ export function commandLint(prog) {
55
60
  .option('-v, --verbose', 'Display more information about the files being checked and the configuration.')
56
61
  .option('--locale <locale>', 'Set language locales. i.e. "en,fr" for English and French, or "en-GB" for British English.')
57
62
  .option('--language-id <language>', 'Force programming language for unknown extensions. i.e. "php" or "scala"')
58
- .addOption(new CommanderOption('--languageId <language>', 'Force programming language for unknown extensions. i.e. "php" or "scala"').hideHelp())
63
+ .addOption(crOpt('--languageId <language>', 'Force programming language for unknown extensions. i.e. "php" or "scala"').hideHelp())
59
64
  .option('--words-only', 'Only output the words not found in the dictionaries.')
60
- .addOption(new CommanderOption('--wordsOnly', 'Only output the words not found in the dictionaries.').hideHelp())
65
+ .addOption(crOpt('--wordsOnly', 'Only output the words not found in the dictionaries.').hideHelp())
61
66
  .option('-u, --unique', 'Only output the first instance of a word not found in the dictionaries.')
62
67
  .option('-e, --exclude <glob>', 'Exclude files matching the glob pattern. This option can be used multiple times to add multiple globs. ', collect)
68
+ // .option('--include <glob>', 'Include files matching the glob pattern. This option can be used multiple times.', collect)
63
69
  .option('--file-list <path or stdin>', 'Specify a list of files to be spell checked.' +
64
70
  ' The list is filtered against the glob file patterns.' +
65
71
  ' Note: the format is 1 file path per line.', collect)
72
+ .option('--file [file...]', 'Specify files to spell check. They are filtered by the [globs...].', collect)
73
+ .addOption(crOpt('--files [file...]', 'Files to spell check.', collect).hideHelp())
66
74
  .option('--no-issues', 'Do not show the spelling errors.')
67
75
  .option('--no-progress', 'Turn off progress messages')
68
76
  .option('--no-summary', 'Turn off summary message in console.')
69
77
  .option('-s, --silent', 'Silent mode, suppress error messages.')
70
78
  .option('--no-exit-code', 'Do not return an exit code if issues are found.')
71
- .addOption(new CommanderOption('--quiet', 'Only show spelling issues or errors.').implies({
79
+ .addOption(crOpt('--quiet', 'Only show spelling issues or errors.').implies({
72
80
  summary: false,
73
81
  progress: false,
74
82
  }))
75
83
  .option('--fail-fast', 'Exit after first file with an issue or error.')
76
- .addOption(new CommanderOption('--no-fail-fast', 'Process all files even if there is an error.').hideHelp())
84
+ .addOption(crOpt('--no-fail-fast', 'Process all files even if there is an error.').hideHelp())
77
85
  .option('-r, --root <root folder>', 'Root directory, defaults to current directory.')
78
- .addOption(new CommanderOption('--relative', 'Issues are displayed relative to the root.').default(true).hideHelp())
86
+ .addOption(crOpt('--relative', 'Issues are displayed relative to the root.').default(true).hideHelp())
79
87
  .option('--no-relative', 'Issues are displayed with absolute path instead of relative to the root.')
80
88
  .option('--show-context', 'Show the surrounding text around an issue.')
81
89
  .option('--show-suggestions', 'Show spelling suggestions.')
82
- .addOption(new CommanderOption('--no-show-suggestions', 'Do not show spelling suggestions or fixes.').default(undefined))
83
- .addOption(new CommanderOption('--must-find-files', 'Error if no files are found.').default(true).hideHelp())
90
+ .addOption(crOpt('--no-show-suggestions', 'Do not show spelling suggestions or fixes.').default(undefined))
91
+ .addOption(crOpt('--must-find-files', 'Error if no files are found.').default(true).hideHelp())
84
92
  .option('--no-must-find-files', 'Do not error if no files are found.')
93
+ // The --filter-files option is still under design review.
94
+ // .option('--filter-files', 'Use the `files` configuration to filter files found.')
95
+ // .option(
96
+ // '--no-filter-files',
97
+ // 'Do NOT use the `files` configuration to filter files (Only applies to --files options).',
98
+ // )
85
99
  // The following options are planned features
86
100
  // .option('-w, --watch', 'Watch for any changes to the matching files and report any errors')
87
101
  // .option('--force', 'Force the exit value to always be 0')
88
- .addOption(new CommanderOption('--legacy', 'Legacy output').hideHelp())
89
- .addOption(new CommanderOption('--local <local>', 'Deprecated -- Use: --locale').hideHelp())
102
+ .addOption(crOpt('--legacy', 'Legacy output').hideHelp())
103
+ .addOption(crOpt('--local <local>', 'Deprecated -- Use: --locale').hideHelp())
90
104
  .option('--cache', 'Use cache to only check changed files.')
91
105
  .option('--no-cache', 'Do not use cache.')
92
106
  .option('--cache-reset', 'Reset the cache file.')
93
- .addOption(new CommanderOption('--cache-strategy <strategy>', 'Strategy to use for detecting changed files.').choices([
107
+ .addOption(crOpt('--cache-strategy <strategy>', 'Strategy to use for detecting changed files.').choices([
94
108
  'metadata',
95
109
  'content',
96
110
  ]))
@@ -103,26 +117,31 @@ export function commandLint(prog) {
103
117
  .option('--no-validate-directives', 'Do not validate in-document CSpell directives.')
104
118
  .option('--no-color', 'Turn off color.')
105
119
  .option('--color', 'Force color.')
106
- .addOption(new CommanderOption('--default-configuration', 'Load the default configuration and dictionaries.').hideHelp())
107
- .addOption(new CommanderOption('--no-default-configuration', 'Do not load the default configuration and dictionaries.'))
120
+ .addOption(crOpt('--default-configuration', 'Load the default configuration and dictionaries.').hideHelp())
121
+ .addOption(crOpt('--no-default-configuration', 'Do not load the default configuration and dictionaries.'))
108
122
  .option('--debug', 'Output information useful for debugging cspell.json files.')
109
123
  .option('--reporter <module|path>', 'Specify one or more reporters to use.', collect)
110
- .addOption(new CommanderOption('--skip-validation', 'Collect and process documents, but do not spell check.')
124
+ .addOption(crOpt('--skip-validation', 'Collect and process documents, but do not spell check.')
111
125
  .implies({ cache: false })
112
126
  .hideHelp())
113
- .addOption(new CommanderOption('--issues-summary-report', 'Output a summary of issues found.').hideHelp())
127
+ .addOption(crOpt('--issues-summary-report', 'Output a summary of issues found.').hideHelp())
128
+ // Planned options
129
+ // .option('--dictionary <dictionary name>', 'Enable a dictionary by name.', collect)
130
+ // .option('--no-dictionary <dictionary name>', 'Disable a dictionary by name.', collect)
131
+ // .option('--import', 'Import a configuration file.', collect)
114
132
  .usage(usage)
115
133
  .addHelpText('after', advanced)
116
134
  .arguments('[globs...]')
117
135
  .action(async (fileGlobs, options) => {
136
+ // console.error('lint: %o', { fileGlobs, options });
118
137
  const useExitCode = options.exitCode ?? true;
119
138
  if (options.skipValidation) {
120
139
  options.cache = false;
121
140
  }
122
141
  App.parseApplicationFeatureFlags(options.flag);
123
- const { mustFindFiles, fileList } = options;
142
+ const { mustFindFiles, fileList, files, file } = options;
124
143
  const result = await App.lint(fileGlobs, options);
125
- if (!fileGlobs.length && !result.files && !result.errors && !fileList) {
144
+ if (!fileGlobs.length && !result.files && !result.errors && !fileList && !files?.length && !file?.length) {
126
145
  spellCheckCommand.outputHelp();
127
146
  throw new CheckFailed('outputHelp', 1);
128
147
  }
@@ -137,4 +156,22 @@ export function commandLint(prog) {
137
156
  });
138
157
  return spellCheckCommand;
139
158
  }
159
+ /**
160
+ * Create Option - a helper function to create a commander option.
161
+ * @param name - the name of the option
162
+ * @param description - the description of the option
163
+ * @param parseArg - optional function to parse the argument
164
+ * @param defaultValue - optional default value
165
+ * @returns CommanderOption
166
+ */
167
+ function crOpt(name, description, parseArg, defaultValue) {
168
+ const option = new CommanderOption(name, description);
169
+ if (parseArg) {
170
+ option.argParser(parseArg);
171
+ }
172
+ if (defaultValue !== undefined) {
173
+ option.default(defaultValue);
174
+ }
175
+ return option;
176
+ }
140
177
  //# sourceMappingURL=commandLint.mjs.map
@@ -4,6 +4,7 @@ import type { GlobSrcInfo } from '../util/glob.mjs';
4
4
  import type { FinalizedReporter } from '../util/reporters.mjs';
5
5
  interface Deprecated {
6
6
  fileLists?: LinterOptions['fileList'];
7
+ local?: LinterOptions['locale'];
7
8
  }
8
9
  export declare class LintRequest {
9
10
  readonly fileGlobs: string[];
@@ -17,6 +18,7 @@ export declare class LintRequest {
17
18
  readonly showContext: number;
18
19
  readonly enableGlobDot: boolean | undefined;
19
20
  readonly fileLists: string[];
21
+ readonly files: string[] | undefined;
20
22
  constructor(fileGlobs: string[], options: LinterOptions & Deprecated, reporter: FinalizedReporter);
21
23
  }
22
24
  export {};
@@ -4,6 +4,7 @@ import type { GlobSrcInfo } from '../util/glob.js';
4
4
  import type { FinalizedReporter } from '../util/reporters.js';
5
5
  interface Deprecated {
6
6
  fileLists?: LinterOptions['fileList'];
7
+ local?: LinterOptions['locale'];
7
8
  }
8
9
  export declare class LintRequest {
9
10
  readonly fileGlobs: string[];
@@ -17,6 +18,7 @@ export declare class LintRequest {
17
18
  readonly showContext: number;
18
19
  readonly enableGlobDot: boolean | undefined;
19
20
  readonly fileLists: string[];
21
+ readonly files: string[] | undefined;
20
22
  constructor(fileGlobs: string[], options: LinterOptions & Deprecated, reporter: FinalizedReporter);
21
23
  }
22
24
  export {};
@@ -13,6 +13,7 @@ export class LintRequest {
13
13
  showContext;
14
14
  enableGlobDot;
15
15
  fileLists;
16
+ files;
16
17
  constructor(fileGlobs, options, reporter) {
17
18
  this.fileGlobs = fileGlobs;
18
19
  this.options = options;
@@ -20,13 +21,27 @@ export class LintRequest {
20
21
  this.root = path.resolve(options.root || process.cwd());
21
22
  this.configFile = options.config;
22
23
  this.excludes = calcExcludeGlobInfo(this.root, options.exclude);
23
- this.locale = options.locale || '';
24
+ this.locale = options.locale ?? options.local ?? '';
24
25
  this.enableGlobDot = options.dot;
25
26
  // this.uniqueFilter = options.unique ? util.uniqueFilterFnGenerator((issue: Issue) => issue.text) : () => true;
26
27
  this.uniqueFilter = () => true;
27
28
  this.showContext =
28
29
  options.showContext === true ? defaultContextRange : options.showContext ? options.showContext : 0;
29
30
  this.fileLists = (options.fileList ?? options.fileLists) || [];
31
+ this.files = mergeFiles(options.file, options.files);
30
32
  }
31
33
  }
34
+ function mergeFiles(a, b) {
35
+ const files = merge(a, b);
36
+ if (!files)
37
+ return undefined;
38
+ return [...new Set(files.flatMap((a) => a.split('\n').map((a) => a.trim())).filter((a) => !!a))];
39
+ }
40
+ function merge(a, b) {
41
+ if (!a)
42
+ return b;
43
+ if (!b)
44
+ return a;
45
+ return [...a, ...b];
46
+ }
32
47
  //# sourceMappingURL=LintRequest.js.map
@@ -13,6 +13,7 @@ export class LintRequest {
13
13
  showContext;
14
14
  enableGlobDot;
15
15
  fileLists;
16
+ files;
16
17
  constructor(fileGlobs, options, reporter) {
17
18
  this.fileGlobs = fileGlobs;
18
19
  this.options = options;
@@ -20,13 +21,27 @@ export class LintRequest {
20
21
  this.root = path.resolve(options.root || process.cwd());
21
22
  this.configFile = options.config;
22
23
  this.excludes = calcExcludeGlobInfo(this.root, options.exclude);
23
- this.locale = options.locale || '';
24
+ this.locale = options.locale ?? options.local ?? '';
24
25
  this.enableGlobDot = options.dot;
25
26
  // this.uniqueFilter = options.unique ? util.uniqueFilterFnGenerator((issue: Issue) => issue.text) : () => true;
26
27
  this.uniqueFilter = () => true;
27
28
  this.showContext =
28
29
  options.showContext === true ? defaultContextRange : options.showContext ? options.showContext : 0;
29
30
  this.fileLists = (options.fileList ?? options.fileLists) || [];
31
+ this.files = mergeFiles(options.file, options.files);
30
32
  }
31
33
  }
34
+ function mergeFiles(a, b) {
35
+ const files = merge(a, b);
36
+ if (!files)
37
+ return undefined;
38
+ return [...new Set(files.flatMap((a) => a.split('\n').map((a) => a.trim())).filter((a) => !!a))];
39
+ }
40
+ function merge(a, b) {
41
+ if (!a)
42
+ return b;
43
+ if (!b)
44
+ return a;
45
+ return [...a, ...b];
46
+ }
32
47
  //# sourceMappingURL=LintRequest.mjs.map
@@ -1,4 +1,4 @@
1
- import { isAsyncIterable, operators, opFilter, pipeAsync, pipeSync } from '@cspell/cspell-pipe';
1
+ import { isAsyncIterable, operators, opFilter, pipeAsync } from '@cspell/cspell-pipe';
2
2
  import { opMap, pipe } from '@cspell/cspell-pipe/sync';
3
3
  import { MessageTypes } from '@cspell/cspell-types';
4
4
  import chalk from 'chalk';
@@ -12,7 +12,7 @@ import { npmPackage } from '../../lib/pkgInfo.cjs';
12
12
  import { getFeatureFlags } from '../featureFlags/index.js';
13
13
  import { calcCacheSettings, createCache } from '../util/cache/index.js';
14
14
  import { CheckFailed, toApplicationError, toError } from '../util/errors.js';
15
- import { fileInfoToDocument, filenameToUri, findFiles, isBinaryFile, isNotDir, readConfig, readFileInfo, readFileListFiles, } from '../util/fileHelper.js';
15
+ import { fileInfoToDocument, filenameToUri, findFiles, isBinaryFile, isFile, isNotDir, readConfig, readFileInfo, readFileListFiles, resolveFilename, } from '../util/fileHelper.js';
16
16
  import { buildGlobMatcher, extractGlobsFromMatcher, extractPatterns, normalizeFileOrGlobsToRoot, normalizeGlobsToRoot, } from '../util/glob.js';
17
17
  import { prefetchIterable } from '../util/prefetch.js';
18
18
  import { loadReporters, mergeReporters } from '../util/reporters.js';
@@ -288,7 +288,7 @@ export async function runLint(cfg) {
288
288
  const globInfo = await determineGlobs(configInfo, cfg);
289
289
  const { fileGlobs, excludeGlobs } = globInfo;
290
290
  const hasFileLists = !!cfg.fileLists.length;
291
- if (!fileGlobs.length && !hasFileLists) {
291
+ if (!fileGlobs.length && !hasFileLists && !cfg.files?.length) {
292
292
  // Nothing to do.
293
293
  return runResult();
294
294
  }
@@ -339,7 +339,7 @@ async function determineGlobs(configInfo, cfg) {
339
339
  const gitignoreRoots = cfg.options.gitignoreRoot ?? configInfo.config.gitignoreRoot;
340
340
  const gitIgnore = useGitignore ? await generateGitIgnore(gitignoreRoots) : undefined;
341
341
  const cliGlobs = cfg.fileGlobs;
342
- const allGlobs = cliGlobs.length ? cliGlobs : configInfo.config.files || [];
342
+ const allGlobs = (cliGlobs.length && cliGlobs) || (cfg.options.filterFiles !== false && configInfo.config.files) || [];
343
343
  const combinedGlobs = await normalizeFileOrGlobsToRoot(allGlobs, cfg.root);
344
344
  const cliExcludeGlobs = extractPatterns(cfg.excludes).map((p) => p.glob);
345
345
  const normalizedExcludes = normalizeGlobsToRoot(cliExcludeGlobs, cfg.root, true);
@@ -370,14 +370,19 @@ async function determineFilesToCheck(configInfo, cfg, reporter, globInfo) {
370
370
  if (enableGlobDot !== undefined) {
371
371
  globOptions.dot = enableGlobDot;
372
372
  }
373
- const filterFiles = opFilter(filterFilesFn(globMatcher));
374
- const foundFiles = await (hasFileLists
375
- ? useFileLists(fileLists, allGlobs, root, enableGlobDot)
376
- : findFiles(fileGlobs, globOptions));
373
+ const opFilterExcludedFiles = opFilter(filterOutExcludedFilesFn(globMatcher));
374
+ const includeFilter = createIncludeFileFilterFn(allGlobs, root, enableGlobDot);
375
+ const rawCliFiles = cfg.files?.map((file) => resolveFilename(file, root)).filter(includeFilter);
376
+ const cliFiles = cfg.options.mustFindFiles
377
+ ? rawCliFiles
378
+ : rawCliFiles && pipeAsync(rawCliFiles, opFilterAsync(isFile));
379
+ const foundFiles = hasFileLists
380
+ ? concatAsyncIterables(cliFiles, await useFileLists(fileLists, includeFilter))
381
+ : cliFiles || (await findFiles(fileGlobs, globOptions));
377
382
  const filtered = gitIgnore ? await gitIgnore.filterOutIgnored(foundFiles) : foundFiles;
378
383
  const files = isAsyncIterable(filtered)
379
- ? pipeAsync(filtered, filterFiles)
380
- : [...pipeSync(filtered, filterFiles)];
384
+ ? pipeAsync(filtered, opFilterExcludedFiles)
385
+ : [...pipe(filtered, opFilterExcludedFiles)];
381
386
  return files;
382
387
  }
383
388
  function isExcluded(filename, globMatcherExclude) {
@@ -393,7 +398,7 @@ async function determineFilesToCheck(configInfo, cfg, reporter, globInfo) {
393
398
  }
394
399
  return r.matched;
395
400
  }
396
- function filterFilesFn(globMatcherExclude) {
401
+ function filterOutExcludedFilesFn(globMatcherExclude) {
397
402
  const patterns = globMatcherExclude.patterns;
398
403
  const excludeInfo = patterns
399
404
  .map(extractGlobSource)
@@ -475,15 +480,27 @@ async function generateGitIgnore(roots) {
475
480
  }
476
481
  return new GitIgnore(root?.map((p) => path.resolve(p)));
477
482
  }
478
- async function useFileLists(fileListFiles, includeGlobPatterns, root, dot) {
479
- includeGlobPatterns = includeGlobPatterns.length ? includeGlobPatterns : ['**'];
483
+ async function useFileLists(fileListFiles, filterFiles) {
484
+ const files = readFileListFiles(fileListFiles);
485
+ return pipeAsync(files, opFilter(filterFiles), opFilterAsync(isNotDir));
486
+ }
487
+ function createIncludeFileFilterFn(includeGlobPatterns, root, dot) {
488
+ if (!includeGlobPatterns?.length) {
489
+ return () => true;
490
+ }
491
+ const patterns = includeGlobPatterns.map((g) => (g === '.' ? '/**' : g));
480
492
  const options = { root, mode: 'include' };
481
493
  if (dot !== undefined) {
482
494
  options.dot = dot;
483
495
  }
484
- const globMatcher = new GlobMatcher(includeGlobPatterns, options);
485
- const filterFiles = (file) => globMatcher.match(file);
486
- const files = readFileListFiles(fileListFiles);
487
- return pipeAsync(files, opFilter(filterFiles), opFilterAsync(isNotDir));
496
+ const globMatcher = new GlobMatcher(patterns, options);
497
+ return (file) => globMatcher.match(file);
498
+ }
499
+ async function* concatAsyncIterables(...iterables) {
500
+ for (const iter of iterables) {
501
+ if (!iter)
502
+ continue;
503
+ yield* iter;
504
+ }
488
505
  }
489
506
  //# sourceMappingURL=lint.js.map
@@ -1,4 +1,4 @@
1
- import { isAsyncIterable, operators, opFilter, pipeAsync, pipeSync } from '@cspell/cspell-pipe';
1
+ import { isAsyncIterable, operators, opFilter, pipeAsync } from '@cspell/cspell-pipe';
2
2
  import { opMap, pipe } from '@cspell/cspell-pipe/sync';
3
3
  import { MessageTypes } from '@cspell/cspell-types';
4
4
  import chalk from 'chalk';
@@ -12,7 +12,7 @@ import { npmPackage } from '../../lib/pkgInfo.cjs';
12
12
  import { getFeatureFlags } from '../featureFlags/index.mjs';
13
13
  import { calcCacheSettings, createCache } from '../util/cache/index.mjs';
14
14
  import { CheckFailed, toApplicationError, toError } from '../util/errors.mjs';
15
- import { fileInfoToDocument, filenameToUri, findFiles, isBinaryFile, isNotDir, readConfig, readFileInfo, readFileListFiles, } from '../util/fileHelper.mjs';
15
+ import { fileInfoToDocument, filenameToUri, findFiles, isBinaryFile, isFile, isNotDir, readConfig, readFileInfo, readFileListFiles, resolveFilename, } from '../util/fileHelper.mjs';
16
16
  import { buildGlobMatcher, extractGlobsFromMatcher, extractPatterns, normalizeFileOrGlobsToRoot, normalizeGlobsToRoot, } from '../util/glob.mjs';
17
17
  import { prefetchIterable } from '../util/prefetch.mjs';
18
18
  import { loadReporters, mergeReporters } from '../util/reporters.mjs';
@@ -288,7 +288,7 @@ export async function runLint(cfg) {
288
288
  const globInfo = await determineGlobs(configInfo, cfg);
289
289
  const { fileGlobs, excludeGlobs } = globInfo;
290
290
  const hasFileLists = !!cfg.fileLists.length;
291
- if (!fileGlobs.length && !hasFileLists) {
291
+ if (!fileGlobs.length && !hasFileLists && !cfg.files?.length) {
292
292
  // Nothing to do.
293
293
  return runResult();
294
294
  }
@@ -339,7 +339,7 @@ async function determineGlobs(configInfo, cfg) {
339
339
  const gitignoreRoots = cfg.options.gitignoreRoot ?? configInfo.config.gitignoreRoot;
340
340
  const gitIgnore = useGitignore ? await generateGitIgnore(gitignoreRoots) : undefined;
341
341
  const cliGlobs = cfg.fileGlobs;
342
- const allGlobs = cliGlobs.length ? cliGlobs : configInfo.config.files || [];
342
+ const allGlobs = (cliGlobs.length && cliGlobs) || (cfg.options.filterFiles !== false && configInfo.config.files) || [];
343
343
  const combinedGlobs = await normalizeFileOrGlobsToRoot(allGlobs, cfg.root);
344
344
  const cliExcludeGlobs = extractPatterns(cfg.excludes).map((p) => p.glob);
345
345
  const normalizedExcludes = normalizeGlobsToRoot(cliExcludeGlobs, cfg.root, true);
@@ -370,14 +370,19 @@ async function determineFilesToCheck(configInfo, cfg, reporter, globInfo) {
370
370
  if (enableGlobDot !== undefined) {
371
371
  globOptions.dot = enableGlobDot;
372
372
  }
373
- const filterFiles = opFilter(filterFilesFn(globMatcher));
374
- const foundFiles = await (hasFileLists
375
- ? useFileLists(fileLists, allGlobs, root, enableGlobDot)
376
- : findFiles(fileGlobs, globOptions));
373
+ const opFilterExcludedFiles = opFilter(filterOutExcludedFilesFn(globMatcher));
374
+ const includeFilter = createIncludeFileFilterFn(allGlobs, root, enableGlobDot);
375
+ const rawCliFiles = cfg.files?.map((file) => resolveFilename(file, root)).filter(includeFilter);
376
+ const cliFiles = cfg.options.mustFindFiles
377
+ ? rawCliFiles
378
+ : rawCliFiles && pipeAsync(rawCliFiles, opFilterAsync(isFile));
379
+ const foundFiles = hasFileLists
380
+ ? concatAsyncIterables(cliFiles, await useFileLists(fileLists, includeFilter))
381
+ : cliFiles || (await findFiles(fileGlobs, globOptions));
377
382
  const filtered = gitIgnore ? await gitIgnore.filterOutIgnored(foundFiles) : foundFiles;
378
383
  const files = isAsyncIterable(filtered)
379
- ? pipeAsync(filtered, filterFiles)
380
- : [...pipeSync(filtered, filterFiles)];
384
+ ? pipeAsync(filtered, opFilterExcludedFiles)
385
+ : [...pipe(filtered, opFilterExcludedFiles)];
381
386
  return files;
382
387
  }
383
388
  function isExcluded(filename, globMatcherExclude) {
@@ -393,7 +398,7 @@ async function determineFilesToCheck(configInfo, cfg, reporter, globInfo) {
393
398
  }
394
399
  return r.matched;
395
400
  }
396
- function filterFilesFn(globMatcherExclude) {
401
+ function filterOutExcludedFilesFn(globMatcherExclude) {
397
402
  const patterns = globMatcherExclude.patterns;
398
403
  const excludeInfo = patterns
399
404
  .map(extractGlobSource)
@@ -475,15 +480,27 @@ async function generateGitIgnore(roots) {
475
480
  }
476
481
  return new GitIgnore(root?.map((p) => path.resolve(p)));
477
482
  }
478
- async function useFileLists(fileListFiles, includeGlobPatterns, root, dot) {
479
- includeGlobPatterns = includeGlobPatterns.length ? includeGlobPatterns : ['**'];
483
+ async function useFileLists(fileListFiles, filterFiles) {
484
+ const files = readFileListFiles(fileListFiles);
485
+ return pipeAsync(files, opFilter(filterFiles), opFilterAsync(isNotDir));
486
+ }
487
+ function createIncludeFileFilterFn(includeGlobPatterns, root, dot) {
488
+ if (!includeGlobPatterns?.length) {
489
+ return () => true;
490
+ }
491
+ const patterns = includeGlobPatterns.map((g) => (g === '.' ? '/**' : g));
480
492
  const options = { root, mode: 'include' };
481
493
  if (dot !== undefined) {
482
494
  options.dot = dot;
483
495
  }
484
- const globMatcher = new GlobMatcher(includeGlobPatterns, options);
485
- const filterFiles = (file) => globMatcher.match(file);
486
- const files = readFileListFiles(fileListFiles);
487
- return pipeAsync(files, opFilter(filterFiles), opFilterAsync(isNotDir));
496
+ const globMatcher = new GlobMatcher(patterns, options);
497
+ return (file) => globMatcher.match(file);
498
+ }
499
+ async function* concatAsyncIterables(...iterables) {
500
+ for (const iter of iterables) {
501
+ if (!iter)
502
+ continue;
503
+ yield* iter;
504
+ }
488
505
  }
489
506
  //# sourceMappingURL=lint.mjs.map
@@ -52,8 +52,24 @@ export interface LinterOptions extends BaseOptions, Omit<CacheOptions, 'version'
52
52
  * List of files that contains the paths to files to be spell checked.
53
53
  * The files in the lists will be filtered against the glob patterns.
54
54
  * - an entry of `stdin` means to read the file list from **`stdin`**
55
+ * The resulting files are filtered against the `files` globs found in the configuration.
55
56
  */
56
57
  fileList?: string[] | undefined;
58
+ /**
59
+ * List of file paths to spell check. These can be relative or absolute
60
+ * paths, but not Globs. Relative paths are relative to {@link LinterOptions.root}.
61
+ * The files are combined with the file paths read from {@link LinterOptions.fileList}.
62
+ * These files are filtered against the `files` globs found in the configuration.
63
+ */
64
+ files?: string[] | undefined;
65
+ /**
66
+ * Alias of {@link LinterOptions.files}.
67
+ */
68
+ file?: string[] | undefined;
69
+ /**
70
+ * Use the `files` configuration to filter the files found.
71
+ */
72
+ filterFiles?: boolean | undefined;
57
73
  /**
58
74
  * Files must be found and processed otherwise it is considered an error.
59
75
  */
@@ -52,8 +52,24 @@ export interface LinterOptions extends BaseOptions, Omit<CacheOptions, 'version'
52
52
  * List of files that contains the paths to files to be spell checked.
53
53
  * The files in the lists will be filtered against the glob patterns.
54
54
  * - an entry of `stdin` means to read the file list from **`stdin`**
55
+ * The resulting files are filtered against the `files` globs found in the configuration.
55
56
  */
56
57
  fileList?: string[] | undefined;
58
+ /**
59
+ * List of file paths to spell check. These can be relative or absolute
60
+ * paths, but not Globs. Relative paths are relative to {@link LinterOptions.root}.
61
+ * The files are combined with the file paths read from {@link LinterOptions.fileList}.
62
+ * These files are filtered against the `files` globs found in the configuration.
63
+ */
64
+ files?: string[] | undefined;
65
+ /**
66
+ * Alias of {@link LinterOptions.files}.
67
+ */
68
+ file?: string[] | undefined;
69
+ /**
70
+ * Use the `files` configuration to filter the files found.
71
+ */
72
+ filterFiles?: boolean | undefined;
57
73
  /**
58
74
  * Files must be found and processed otherwise it is considered an error.
59
75
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cspell",
3
- "version": "8.4.0",
3
+ "version": "8.5.0",
4
4
  "description": "A Spelling Checker for Code!",
5
5
  "funding": "https://github.com/streetsidesoftware/cspell?sponsor=1",
6
6
  "bin": {
@@ -81,17 +81,17 @@
81
81
  },
82
82
  "homepage": "https://streetsidesoftware.github.io/cspell/",
83
83
  "dependencies": {
84
- "@cspell/cspell-json-reporter": "8.4.0",
85
- "@cspell/cspell-pipe": "8.4.0",
86
- "@cspell/cspell-types": "8.4.0",
87
- "@cspell/dynamic-import": "8.4.0",
84
+ "@cspell/cspell-json-reporter": "8.5.0",
85
+ "@cspell/cspell-pipe": "8.5.0",
86
+ "@cspell/cspell-types": "8.5.0",
87
+ "@cspell/dynamic-import": "8.5.0",
88
88
  "chalk": "^5.3.0",
89
89
  "chalk-template": "^1.1.0",
90
90
  "commander": "^12.0.0",
91
- "cspell-gitignore": "8.4.0",
92
- "cspell-glob": "8.4.0",
93
- "cspell-io": "8.4.0",
94
- "cspell-lib": "8.4.0",
91
+ "cspell-gitignore": "8.5.0",
92
+ "cspell-glob": "8.5.0",
93
+ "cspell-io": "8.5.0",
94
+ "cspell-lib": "8.5.0",
95
95
  "fast-glob": "^3.3.2",
96
96
  "fast-json-stable-stringify": "^2.1.0",
97
97
  "file-entry-cache": "^8.0.0",
@@ -107,9 +107,9 @@
107
107
  "@types/file-entry-cache": "^5.0.4",
108
108
  "@types/glob": "^8.1.0",
109
109
  "@types/micromatch": "^4.0.6",
110
- "@types/semver": "^7.5.7",
110
+ "@types/semver": "^7.5.8",
111
111
  "micromatch": "^4.0.5",
112
112
  "minimatch": "^9.0.3"
113
113
  },
114
- "gitHead": "f9ad457ca2102c6642c377417a95a4415f5ec3d8"
114
+ "gitHead": "098601b2e007bebf9e5ae894bed9a50559a102ed"
115
115
  }