cspell 8.5.0 → 8.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,8 @@
1
+ import * as path from 'node:path';
2
+ import { format } from 'node:util';
1
3
  import chalk from 'chalk';
2
4
  import chalkTemplate from 'chalk-template';
3
5
  import { isSpellingDictionaryLoadError } from 'cspell-lib';
4
- import * as path from 'path';
5
6
  import { URI } from 'vscode-uri';
6
7
  import { uniqueFilterFnGenerator } from './util/util.js';
7
8
  const templateIssue = `{green $filename}:{yellow $row:$col} - $message ({red $text}) $quickFix`;
@@ -11,7 +12,14 @@ const templateIssueWithContext = `{green $filename}:{yellow $row:$col} $padRowCo
11
12
  const templateIssueWithContextWithSuggestions = `{green $filename}:{yellow $row:$col} $padRowCol- $message ({red $text})$padContext -- {gray $contextLeft}{red {underline $text}}{gray $contextRight}\n\t Suggestions: {yellow [$suggestions]}`;
12
13
  const templateIssueLegacy = `${chalk.green('$filename')}[$row, $col]: $message: ${chalk.red('$text')}`;
13
14
  const templateIssueWordsOnly = '$text';
14
- function genIssueEmitter(template, uniqueIssues) {
15
+ /**
16
+ *
17
+ * @param template - The template to use for the issue.
18
+ * @param uniqueIssues - If true, only unique issues will be reported.
19
+ * @param reportedIssuesCollection - optional collection to store reported issues.
20
+ * @returns issueEmitter function
21
+ */
22
+ function genIssueEmitter(template, uniqueIssues, reportedIssuesCollection) {
15
23
  const uniqueFilter = uniqueIssues ? uniqueFilterFnGenerator((issue) => issue.text) : () => true;
16
24
  const defaultWidth = 10;
17
25
  let maxWidth = defaultWidth;
@@ -24,15 +32,11 @@ function genIssueEmitter(template, uniqueIssues) {
24
32
  uri = issue.uri;
25
33
  }
26
34
  maxWidth = Math.max(maxWidth * 0.999, issue.text.length, 10);
27
- console.log(formatIssue(template, issue, Math.ceil(maxWidth)));
35
+ const issueText = formatIssue(template, issue, Math.ceil(maxWidth));
36
+ reportedIssuesCollection?.push(issueText);
37
+ console.log(issueText);
28
38
  };
29
39
  }
30
- function errorEmitter(message, error) {
31
- if (isSpellingDictionaryLoadError(error)) {
32
- error = error.cause;
33
- }
34
- console.error(chalk.red(message), error.toString());
35
- }
36
40
  function nullEmitter() {
37
41
  /* empty */
38
42
  }
@@ -114,18 +118,42 @@ export function getReporter(options, config) {
114
118
  fn(r);
115
119
  };
116
120
  }
121
+ const issuesCollection = progress ? [] : undefined;
122
+ const errorCollection = [];
123
+ function errorEmitter(message, error) {
124
+ if (isSpellingDictionaryLoadError(error)) {
125
+ error = error.cause;
126
+ }
127
+ const errorText = format(chalk.red(message), error.toString());
128
+ errorCollection?.push(errorText);
129
+ console.error(errorText);
130
+ }
117
131
  const resultEmitter = (result) => {
118
132
  if (!fileGlobs.length && !result.files) {
119
133
  return;
120
134
  }
121
- if (result.cachedFiles) {
122
- console.error('CSpell\x3a Files checked: %d (%d from cache), Issues found: %d in %d files', result.files, result.cachedFiles, result.issues, result.filesWithIssues.size);
123
- return;
135
+ const { files, issues, cachedFiles, filesWithIssues, errors } = result;
136
+ const numFilesWithIssues = filesWithIssues.size;
137
+ if (issuesCollection?.length || errorCollection?.length) {
138
+ console.error('-------------------------------------------');
139
+ }
140
+ if (issuesCollection?.length) {
141
+ console.error('Issues found:');
142
+ issuesCollection.forEach((issue) => console.error(issue));
143
+ }
144
+ const cachedFilesText = cachedFiles ? ` (${cachedFiles} from cache)` : '';
145
+ const withErrorsText = errors ? ` with ${errors} error${errors === 1 ? '' : 's'}` : '';
146
+ const numFilesWidthIssuesText = numFilesWithIssues === 1 ? '1 file' : `${numFilesWithIssues} files`;
147
+ const summaryMessage = `CSpell\x3a Files checked: ${files}${cachedFilesText}, Issues found: ${issues} in ${numFilesWidthIssuesText}${withErrorsText}.`;
148
+ console.error(summaryMessage);
149
+ if (errorCollection?.length && issues > 5) {
150
+ console.error('-------------------------------------------');
151
+ console.error('Errors:');
152
+ errorCollection.forEach((error) => console.error(error));
124
153
  }
125
- console.error('CSpell\x3a Files checked: %d, Issues found: %d in %d files', result.files, result.issues, result.filesWithIssues.size);
126
154
  };
127
155
  return {
128
- issue: relativeIssue(silent || !issues ? nullEmitter : genIssueEmitter(issueTemplate, uniqueIssues)),
156
+ issue: relativeIssue(silent || !issues ? nullEmitter : genIssueEmitter(issueTemplate, uniqueIssues, issuesCollection)),
129
157
  error: silent ? nullEmitter : errorEmitter,
130
158
  info: infoEmitter,
131
159
  debug: emitters.Debug,
@@ -1,7 +1,8 @@
1
+ import * as path from 'node:path';
2
+ import { format } from 'node:util';
1
3
  import chalk from 'chalk';
2
4
  import chalkTemplate from 'chalk-template';
3
5
  import { isSpellingDictionaryLoadError } from 'cspell-lib';
4
- import * as path from 'path';
5
6
  import { URI } from 'vscode-uri';
6
7
  import { uniqueFilterFnGenerator } from './util/util.mjs';
7
8
  const templateIssue = `{green $filename}:{yellow $row:$col} - $message ({red $text}) $quickFix`;
@@ -11,7 +12,14 @@ const templateIssueWithContext = `{green $filename}:{yellow $row:$col} $padRowCo
11
12
  const templateIssueWithContextWithSuggestions = `{green $filename}:{yellow $row:$col} $padRowCol- $message ({red $text})$padContext -- {gray $contextLeft}{red {underline $text}}{gray $contextRight}\n\t Suggestions: {yellow [$suggestions]}`;
12
13
  const templateIssueLegacy = `${chalk.green('$filename')}[$row, $col]: $message: ${chalk.red('$text')}`;
13
14
  const templateIssueWordsOnly = '$text';
14
- function genIssueEmitter(template, uniqueIssues) {
15
+ /**
16
+ *
17
+ * @param template - The template to use for the issue.
18
+ * @param uniqueIssues - If true, only unique issues will be reported.
19
+ * @param reportedIssuesCollection - optional collection to store reported issues.
20
+ * @returns issueEmitter function
21
+ */
22
+ function genIssueEmitter(template, uniqueIssues, reportedIssuesCollection) {
15
23
  const uniqueFilter = uniqueIssues ? uniqueFilterFnGenerator((issue) => issue.text) : () => true;
16
24
  const defaultWidth = 10;
17
25
  let maxWidth = defaultWidth;
@@ -24,15 +32,11 @@ function genIssueEmitter(template, uniqueIssues) {
24
32
  uri = issue.uri;
25
33
  }
26
34
  maxWidth = Math.max(maxWidth * 0.999, issue.text.length, 10);
27
- console.log(formatIssue(template, issue, Math.ceil(maxWidth)));
35
+ const issueText = formatIssue(template, issue, Math.ceil(maxWidth));
36
+ reportedIssuesCollection?.push(issueText);
37
+ console.log(issueText);
28
38
  };
29
39
  }
30
- function errorEmitter(message, error) {
31
- if (isSpellingDictionaryLoadError(error)) {
32
- error = error.cause;
33
- }
34
- console.error(chalk.red(message), error.toString());
35
- }
36
40
  function nullEmitter() {
37
41
  /* empty */
38
42
  }
@@ -114,18 +118,42 @@ export function getReporter(options, config) {
114
118
  fn(r);
115
119
  };
116
120
  }
121
+ const issuesCollection = progress ? [] : undefined;
122
+ const errorCollection = [];
123
+ function errorEmitter(message, error) {
124
+ if (isSpellingDictionaryLoadError(error)) {
125
+ error = error.cause;
126
+ }
127
+ const errorText = format(chalk.red(message), error.toString());
128
+ errorCollection?.push(errorText);
129
+ console.error(errorText);
130
+ }
117
131
  const resultEmitter = (result) => {
118
132
  if (!fileGlobs.length && !result.files) {
119
133
  return;
120
134
  }
121
- if (result.cachedFiles) {
122
- console.error('CSpell\x3a Files checked: %d (%d from cache), Issues found: %d in %d files', result.files, result.cachedFiles, result.issues, result.filesWithIssues.size);
123
- return;
135
+ const { files, issues, cachedFiles, filesWithIssues, errors } = result;
136
+ const numFilesWithIssues = filesWithIssues.size;
137
+ if (issuesCollection?.length || errorCollection?.length) {
138
+ console.error('-------------------------------------------');
139
+ }
140
+ if (issuesCollection?.length) {
141
+ console.error('Issues found:');
142
+ issuesCollection.forEach((issue) => console.error(issue));
143
+ }
144
+ const cachedFilesText = cachedFiles ? ` (${cachedFiles} from cache)` : '';
145
+ const withErrorsText = errors ? ` with ${errors} error${errors === 1 ? '' : 's'}` : '';
146
+ const numFilesWidthIssuesText = numFilesWithIssues === 1 ? '1 file' : `${numFilesWithIssues} files`;
147
+ const summaryMessage = `CSpell\x3a Files checked: ${files}${cachedFilesText}, Issues found: ${issues} in ${numFilesWidthIssuesText}${withErrorsText}.`;
148
+ console.error(summaryMessage);
149
+ if (errorCollection?.length && issues > 5) {
150
+ console.error('-------------------------------------------');
151
+ console.error('Errors:');
152
+ errorCollection.forEach((error) => console.error(error));
124
153
  }
125
- console.error('CSpell\x3a Files checked: %d, Issues found: %d in %d files', result.files, result.issues, result.filesWithIssues.size);
126
154
  };
127
155
  return {
128
- issue: relativeIssue(silent || !issues ? nullEmitter : genIssueEmitter(issueTemplate, uniqueIssues)),
156
+ issue: relativeIssue(silent || !issues ? nullEmitter : genIssueEmitter(issueTemplate, uniqueIssues, issuesCollection)),
129
157
  error: silent ? nullEmitter : errorEmitter,
130
158
  info: infoEmitter,
131
159
  debug: emitters.Debug,
@@ -296,7 +296,7 @@ export async function runLint(cfg) {
296
296
  checkGlobs(fileGlobs, reporter);
297
297
  reporter.info(`Config Files Found:\n ${configInfo.source}\n`, MessageTypes.Info);
298
298
  const configErrors = await countConfigErrors(configInfo);
299
- if (configErrors)
299
+ if (configErrors && cfg.options.exitCode !== false)
300
300
  return runResult({ errors: configErrors });
301
301
  // Get Exclusions from the config files.
302
302
  const { root } = cfg;
@@ -296,7 +296,7 @@ export async function runLint(cfg) {
296
296
  checkGlobs(fileGlobs, reporter);
297
297
  reporter.info(`Config Files Found:\n ${configInfo.source}\n`, MessageTypes.Info);
298
298
  const configErrors = await countConfigErrors(configInfo);
299
- if (configErrors)
299
+ if (configErrors && cfg.options.exitCode !== false)
300
300
  return runResult({ errors: configErrors });
301
301
  // Get Exclusions from the config files.
302
302
  const { root } = cfg;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cspell",
3
- "version": "8.5.0",
3
+ "version": "8.6.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.5.0",
85
- "@cspell/cspell-pipe": "8.5.0",
86
- "@cspell/cspell-types": "8.5.0",
87
- "@cspell/dynamic-import": "8.5.0",
84
+ "@cspell/cspell-json-reporter": "8.6.0",
85
+ "@cspell/cspell-pipe": "8.6.0",
86
+ "@cspell/cspell-types": "8.6.0",
87
+ "@cspell/dynamic-import": "8.6.0",
88
88
  "chalk": "^5.3.0",
89
89
  "chalk-template": "^1.1.0",
90
90
  "commander": "^12.0.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",
91
+ "cspell-gitignore": "8.6.0",
92
+ "cspell-glob": "8.6.0",
93
+ "cspell-io": "8.6.0",
94
+ "cspell-lib": "8.6.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",
@@ -111,5 +111,5 @@
111
111
  "micromatch": "^4.0.5",
112
112
  "minimatch": "^9.0.3"
113
113
  },
114
- "gitHead": "098601b2e007bebf9e5ae894bed9a50559a102ed"
114
+ "gitHead": "78eadb48e8ab400f4fcd159344c5b15968d7ab2e"
115
115
  }