cspell 7.0.2 → 7.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (125) hide show
  1. package/README.md +1 -1
  2. package/dist/esm/app.d.ts +5 -0
  3. package/dist/esm/app.js +45 -0
  4. package/dist/esm/app.mjs +1 -0
  5. package/dist/esm/application.d.ts +16 -0
  6. package/dist/esm/application.js +88 -0
  7. package/dist/esm/application.mjs +1 -0
  8. package/dist/esm/cli-reporter.d.ts +16 -0
  9. package/dist/esm/cli-reporter.js +218 -0
  10. package/dist/esm/cli-reporter.mjs +1 -0
  11. package/dist/esm/commandCheck.d.ts +3 -0
  12. package/dist/esm/commandCheck.js +48 -0
  13. package/dist/esm/commandCheck.mjs +1 -0
  14. package/dist/esm/commandLink.d.ts +3 -0
  15. package/dist/esm/commandLink.js +47 -0
  16. package/dist/esm/commandLink.mjs +1 -0
  17. package/dist/esm/commandLint.d.ts +3 -0
  18. package/dist/esm/commandLint.js +127 -0
  19. package/dist/esm/commandLint.mjs +5 -1
  20. package/dist/esm/commandSuggestion.d.ts +3 -0
  21. package/dist/esm/commandSuggestion.js +61 -0
  22. package/dist/esm/commandSuggestion.mjs +1 -0
  23. package/dist/esm/commandTrace.d.ts +3 -0
  24. package/dist/esm/commandTrace.js +60 -0
  25. package/dist/esm/commandTrace.mjs +1 -0
  26. package/dist/esm/emitters/DictionaryPathFormat.d.ts +3 -0
  27. package/dist/esm/emitters/DictionaryPathFormat.js +12 -0
  28. package/dist/esm/emitters/DictionaryPathFormat.mjs +1 -0
  29. package/dist/esm/emitters/suggestionsEmitter.d.ts +13 -0
  30. package/dist/esm/emitters/suggestionsEmitter.js +77 -0
  31. package/dist/esm/emitters/suggestionsEmitter.mjs +1 -0
  32. package/dist/esm/emitters/traceEmitter.d.ts +21 -0
  33. package/dist/esm/emitters/traceEmitter.js +141 -0
  34. package/dist/esm/emitters/traceEmitter.mjs +1 -0
  35. package/dist/esm/featureFlags/featureFlags.d.ts +4 -0
  36. package/dist/esm/featureFlags/featureFlags.js +20 -0
  37. package/dist/esm/featureFlags/featureFlags.mjs +1 -0
  38. package/dist/esm/featureFlags/index.d.ts +2 -0
  39. package/dist/esm/featureFlags/index.js +2 -0
  40. package/dist/esm/featureFlags/index.mjs +1 -0
  41. package/dist/esm/index.d.ts +5 -0
  42. package/dist/esm/index.js +4 -0
  43. package/dist/esm/index.mjs +1 -0
  44. package/dist/esm/link.d.ts +8 -0
  45. package/dist/esm/link.js +39 -0
  46. package/dist/esm/link.mjs +1 -0
  47. package/dist/esm/lint/LintRequest.d.ts +23 -0
  48. package/dist/esm/lint/LintRequest.js +21 -0
  49. package/dist/esm/lint/LintRequest.mjs +1 -0
  50. package/dist/esm/lint/index.d.ts +3 -0
  51. package/dist/esm/lint/index.js +3 -0
  52. package/dist/esm/lint/index.mjs +1 -0
  53. package/dist/esm/lint/lint.d.ts +4 -0
  54. package/dist/esm/lint/lint.js +469 -0
  55. package/dist/esm/lint/lint.mjs +1 -0
  56. package/dist/esm/options.d.ts +178 -0
  57. package/dist/esm/options.js +8 -0
  58. package/dist/esm/options.mjs +1 -0
  59. package/dist/esm/repl/index.d.ts +18 -0
  60. package/dist/esm/repl/index.js +47 -0
  61. package/dist/esm/repl/index.mjs +1 -0
  62. package/dist/esm/util/InMemoryReporter.d.ts +28 -0
  63. package/dist/esm/util/InMemoryReporter.js +43 -0
  64. package/dist/esm/util/InMemoryReporter.mjs +1 -0
  65. package/dist/esm/util/async.d.ts +3 -0
  66. package/dist/esm/util/async.js +4 -0
  67. package/dist/esm/util/async.mjs +1 -0
  68. package/dist/esm/util/cache/CSpellLintResultCache.d.ts +20 -0
  69. package/dist/esm/util/cache/CSpellLintResultCache.js +2 -0
  70. package/dist/esm/util/cache/CSpellLintResultCache.mjs +1 -0
  71. package/dist/esm/util/cache/CacheOptions.d.ts +34 -0
  72. package/dist/esm/util/cache/CacheOptions.js +2 -0
  73. package/dist/esm/util/cache/CacheOptions.mjs +1 -0
  74. package/dist/esm/util/cache/DiskCache.d.ts +63 -0
  75. package/dist/esm/util/cache/DiskCache.js +207 -0
  76. package/dist/esm/util/cache/DiskCache.mjs +1 -0
  77. package/dist/esm/util/cache/DummyCache.d.ts +11 -0
  78. package/dist/esm/util/cache/DummyCache.js +18 -0
  79. package/dist/esm/util/cache/DummyCache.mjs +1 -0
  80. package/dist/esm/util/cache/ObjectCollection.d.ts +17 -0
  81. package/dist/esm/util/cache/ObjectCollection.js +131 -0
  82. package/dist/esm/util/cache/ObjectCollection.mjs +1 -0
  83. package/dist/esm/util/cache/createCache.d.ts +31 -0
  84. package/dist/esm/util/cache/createCache.js +69 -0
  85. package/dist/esm/util/cache/createCache.mjs +1 -0
  86. package/dist/esm/util/cache/fileEntryCache.d.ts +9 -0
  87. package/dist/esm/util/cache/fileEntryCache.js +79 -0
  88. package/dist/esm/util/cache/fileEntryCache.mjs +1 -0
  89. package/dist/esm/util/cache/index.d.ts +4 -0
  90. package/dist/esm/util/cache/index.js +2 -0
  91. package/dist/esm/util/cache/index.mjs +1 -0
  92. package/dist/esm/util/constants.d.ts +6 -0
  93. package/dist/esm/util/constants.js +5 -0
  94. package/dist/esm/util/constants.mjs +1 -0
  95. package/dist/esm/util/errors.d.ts +23 -0
  96. package/dist/esm/util/errors.js +51 -0
  97. package/dist/esm/util/errors.mjs +1 -0
  98. package/dist/esm/util/fileHelper.d.ts +63 -0
  99. package/dist/esm/util/fileHelper.js +182 -0
  100. package/dist/esm/util/fileHelper.mjs +1 -0
  101. package/dist/esm/util/glob.d.ts +45 -0
  102. package/dist/esm/util/glob.js +137 -0
  103. package/dist/esm/util/glob.mjs +1 -0
  104. package/dist/esm/util/prefetch.d.ts +2 -0
  105. package/dist/esm/util/prefetch.js +16 -0
  106. package/dist/esm/util/prefetch.mjs +1 -0
  107. package/dist/esm/util/reporters.d.ts +14 -0
  108. package/dist/esm/util/reporters.js +62 -0
  109. package/dist/esm/util/reporters.mjs +1 -0
  110. package/dist/esm/util/stdin.d.ts +2 -0
  111. package/dist/esm/util/stdin.js +5 -0
  112. package/dist/esm/util/stdin.mjs +1 -0
  113. package/dist/esm/util/table.d.ts +10 -0
  114. package/dist/esm/util/table.js +32 -0
  115. package/dist/esm/util/table.mjs +1 -0
  116. package/dist/esm/util/timer.d.ts +8 -0
  117. package/dist/esm/util/timer.js +11 -0
  118. package/dist/esm/util/timer.mjs +1 -0
  119. package/dist/esm/util/types.d.ts +7 -0
  120. package/dist/esm/util/types.js +5 -0
  121. package/dist/esm/util/types.mjs +1 -0
  122. package/dist/esm/util/util.d.ts +13 -0
  123. package/dist/esm/util/util.js +45 -0
  124. package/dist/esm/util/util.mjs +1 -0
  125. package/package.json +11 -13
package/README.md CHANGED
@@ -150,7 +150,7 @@ Options:
150
150
  --no-progress Turn off progress messages
151
151
  --no-summary Turn off summary message in console.
152
152
  -s, --silent Silent mode, suppress error messages.
153
- --quiet An alias of --silent
153
+ --quiet Only show spelling issues or errors.
154
154
  --fail-fast Exit after first file with an issue or error.
155
155
  -r, --root <root folder> Root directory, defaults to current directory.
156
156
  --relative Issues are displayed relative to root.
@@ -0,0 +1,5 @@
1
+ import type { Command } from 'commander';
2
+ export { LinterCliOptions as Options } from './options.js';
3
+ export { CheckFailed } from './util/errors.js';
4
+ export declare function run(command?: Command, argv?: string[]): Promise<void>;
5
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1,45 @@
1
+ import { Option as CommanderOption, program } from 'commander';
2
+ import { satisfies as semverSatisfies } from 'semver';
3
+ import { npmPackage } from '../lib/pkgInfo.cjs';
4
+ import { commandCheck } from './commandCheck.js';
5
+ import { commandLink } from './commandLink.js';
6
+ import { commandLint } from './commandLint.js';
7
+ import { commandSuggestion } from './commandSuggestion.js';
8
+ import { commandTrace } from './commandTrace.js';
9
+ import { ApplicationError } from './util/errors.js';
10
+ export { CheckFailed } from './util/errors.js';
11
+ export async function run(command, argv) {
12
+ const prog = command || program;
13
+ const args = argv || process.argv;
14
+ prog.exitOverride();
15
+ prog.version(npmPackage.version).description('Spelling Checker for Code').name('cspell');
16
+ if (!semverSatisfies(process.versions.node, npmPackage.engines.node)) {
17
+ throw new ApplicationError(`Unsupported NodeJS version (${process.versions.node}); ${npmPackage.engines.node} is required`);
18
+ }
19
+ const optionFlags = new CommanderOption('-f,--flag <flag:value>', 'Declare an execution flag value')
20
+ .hideHelp()
21
+ .argParser((value, prev) => prev?.concat(value) || [value]);
22
+ commandLint(prog).addOption(optionFlags);
23
+ commandTrace(prog).addOption(optionFlags);
24
+ commandCheck(prog).addOption(optionFlags);
25
+ commandSuggestion(prog).addOption(optionFlags);
26
+ commandLink(prog);
27
+ /*
28
+ program
29
+ .command('init')
30
+ .description('(Alpha) Initialize a cspell.json file.')
31
+ .option('-o, --output <cspell.json>', 'define where to write file.')
32
+ .option('--extends <cspell.json>', 'extend an existing cspell.json file.')
33
+ .action((options: InitOptions) => {
34
+ showHelp = false;
35
+ CSpellApplication.createInit(options).then(
36
+ () => process.exit(0),
37
+ () => process.exit(1)
38
+ );
39
+ console.log('Init');
40
+ });
41
+ */
42
+ prog.exitOverride();
43
+ await prog.parseAsync(args);
44
+ }
45
+ //# sourceMappingURL=app.js.map
package/dist/esm/app.mjs CHANGED
@@ -42,3 +42,4 @@ export async function run(command, argv) {
42
42
  prog.exitOverride();
43
43
  await prog.parseAsync(args);
44
44
  }
45
+ //# sourceMappingURL=app.mjs.map
@@ -0,0 +1,16 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import type { CSpellReporter, RunResult } from '@cspell/cspell-types';
3
+ import type { CheckTextInfo, FeatureFlags, TraceResult } from 'cspell-lib';
4
+ import type { TimedSuggestionsForWordResult } from './emitters/suggestionsEmitter.js';
5
+ import type { BaseOptions, LegacyOptions, LinterCliOptions, SuggestionOptions, TraceOptions } from './options.js';
6
+ export type { TraceResult } from 'cspell-lib';
7
+ export { IncludeExcludeFlag } from 'cspell-lib';
8
+ export type AppError = NodeJS.ErrnoException;
9
+ export declare function lint(fileGlobs: string[], options: LinterCliOptions, reporter?: CSpellReporter): Promise<RunResult>;
10
+ export declare function trace(words: string[], options: TraceOptions): AsyncIterableIterator<TraceResult[]>;
11
+ export type CheckTextResult = CheckTextInfo;
12
+ export declare function checkText(filename: string, options: BaseOptions & LegacyOptions): Promise<CheckTextResult>;
13
+ export declare function suggestions(words: string[], options: SuggestionOptions): AsyncIterable<TimedSuggestionsForWordResult>;
14
+ export declare function createInit(): Promise<void>;
15
+ export declare function parseApplicationFeatureFlags(flags: string[] | undefined): FeatureFlags;
16
+ //# sourceMappingURL=application.d.ts.map
@@ -0,0 +1,88 @@
1
+ import { opMap, opTap, pipeAsync, toAsyncIterable } from '@cspell/cspell-pipe';
2
+ import { checkTextDocument, getDefaultSettings, getGlobalSettings, mergeSettings, SuggestionError, suggestionsForWords, traceWordsAsync, } from 'cspell-lib';
3
+ import { getReporter } from './cli-reporter.js';
4
+ import { getFeatureFlags, parseFeatureFlags } from './featureFlags/index.js';
5
+ import { LintRequest, runLint } from './lint/index.js';
6
+ import { fixLegacy } from './options.js';
7
+ import { simpleRepl } from './repl/index.js';
8
+ import { fileInfoToDocument, readConfig, readFileInfo } from './util/fileHelper.js';
9
+ import { finalizeReporter } from './util/reporters.js';
10
+ import { readStdin } from './util/stdin.js';
11
+ import { getTimeMeasurer } from './util/timer.js';
12
+ import * as util from './util/util.js';
13
+ export { IncludeExcludeFlag } from 'cspell-lib';
14
+ export function lint(fileGlobs, options, reporter) {
15
+ options = fixLegacy(options);
16
+ const cfg = new LintRequest(fileGlobs, options, finalizeReporter(reporter) ?? getReporter({ ...options, fileGlobs }));
17
+ return runLint(cfg);
18
+ }
19
+ export async function* trace(words, options) {
20
+ options = fixLegacy(options);
21
+ const iWords = options.stdin ? toAsyncIterable(words, readStdin()) : words;
22
+ const { languageId, locale, allowCompoundWords, ignoreCase } = options;
23
+ const configFile = await readConfig(options.config, undefined);
24
+ const loadDefault = options.defaultConfiguration ?? configFile.config.loadDefaultConfiguration ?? true;
25
+ const config = mergeSettings(getDefaultSettings(loadDefault), getGlobalSettings(), configFile.config);
26
+ yield* traceWordsAsync(iWords, config, util.clean({ languageId, locale, ignoreCase, allowCompoundWords }));
27
+ }
28
+ export async function checkText(filename, options) {
29
+ options = fixLegacy(options);
30
+ const fileInfo = await readFileInfo(filename);
31
+ const { locale, languageId, validateDirectives } = options;
32
+ const doc = fileInfoToDocument(fileInfo, languageId, locale);
33
+ const checkOptions = {
34
+ configFile: options.config,
35
+ validateDirectives,
36
+ };
37
+ const settingsFromCommandLine = util.clean({
38
+ languageId,
39
+ language: locale,
40
+ loadDefaultConfiguration: options.defaultConfiguration,
41
+ });
42
+ return checkTextDocument(doc, util.clean({ ...checkOptions }), settingsFromCommandLine);
43
+ }
44
+ export async function* suggestions(words, options) {
45
+ options = fixLegacy(options);
46
+ const configFile = await readConfig(options.config, undefined);
47
+ let timer;
48
+ function tapStart() {
49
+ timer = getTimeMeasurer();
50
+ }
51
+ function mapStart(v) {
52
+ tapStart();
53
+ return v;
54
+ }
55
+ function mapEnd(v) {
56
+ const elapsedTimeMs = timer?.();
57
+ return elapsedTimeMs ? { ...v, elapsedTimeMs } : v;
58
+ }
59
+ const iWords = options.repl
60
+ ? pipeAsync(toAsyncIterable(words, simpleRepl()), opTap(tapStart))
61
+ : options.useStdin
62
+ ? pipeAsync(toAsyncIterable(words, readStdin()), opTap(tapStart))
63
+ : words.map(mapStart);
64
+ try {
65
+ const results = pipeAsync(suggestionsForWords(iWords, util.clean({ ...options }), configFile.config), opMap(mapEnd));
66
+ yield* results;
67
+ }
68
+ catch (e) {
69
+ if (!(e instanceof SuggestionError))
70
+ throw e;
71
+ console.error(e.message);
72
+ process.exitCode = 1;
73
+ }
74
+ }
75
+ export function createInit() {
76
+ return Promise.reject();
77
+ }
78
+ function registerApplicationFeatureFlags() {
79
+ const ff = getFeatureFlags();
80
+ const flags = [{ name: 'timer', description: 'Display elapsed time for command.' }];
81
+ flags.forEach((flag) => ff.register(flag));
82
+ return ff;
83
+ }
84
+ export function parseApplicationFeatureFlags(flags) {
85
+ const ff = registerApplicationFeatureFlags();
86
+ return parseFeatureFlags(flags, ff);
87
+ }
88
+ //# sourceMappingURL=application.js.map
@@ -85,3 +85,4 @@ export function parseApplicationFeatureFlags(flags) {
85
85
  const ff = registerApplicationFeatureFlags();
86
86
  return parseFeatureFlags(flags, ff);
87
87
  }
88
+ //# sourceMappingURL=application.mjs.map
@@ -0,0 +1,16 @@
1
+ import type { Issue } from '@cspell/cspell-types';
2
+ import type { LinterCliOptions } from './options.js';
3
+ import type { FinalizedReporter } from './util/reporters.js';
4
+ export interface ReporterIssue extends Issue {
5
+ filename: string;
6
+ }
7
+ export interface ReporterOptions extends Pick<LinterCliOptions, 'debug' | 'issues' | 'legacy' | 'progress' | 'relative' | 'root' | 'showContext' | 'showSuggestions' | 'silent' | 'summary' | 'verbose' | 'wordsOnly'> {
8
+ fileGlobs: string[];
9
+ }
10
+ export declare function getReporter(options: ReporterOptions): FinalizedReporter;
11
+ declare function formatIssue(templateStr: string, issue: ReporterIssue, maxIssueTextWidth: number): string;
12
+ export declare const __testing__: {
13
+ formatIssue: typeof formatIssue;
14
+ };
15
+ export {};
16
+ //# sourceMappingURL=cli-reporter.d.ts.map
@@ -0,0 +1,218 @@
1
+ import chalk from 'chalk';
2
+ import chalkTemplate from 'chalk-template';
3
+ import { isSpellingDictionaryLoadError } from 'cspell-lib';
4
+ import * as path from 'path';
5
+ import { URI } from '../lib/uri.cjs';
6
+ const templateIssue = `{green $filename}:{yellow $row:$col} - $message ({red $text}) $quickFix`;
7
+ const templateIssueNoFix = `{green $filename}:{yellow $row:$col} - $message ({red $text})`;
8
+ const templateIssueWithSuggestions = `{green $filename}:{yellow $row:$col} - $message ({red $text}) Suggestions: {yellow [$suggestions]}`;
9
+ const templateIssueWithContext = `{green $filename}:{yellow $row:$col} $padRowCol- $message ({red $text})$padContext -- {gray $contextLeft}{red {underline $text}}{gray $contextRight}`;
10
+ const templateIssueWithContextWithSuggestions = `{green $filename}:{yellow $row:$col} $padRowCol- $message ({red $text})$padContext -- {gray $contextLeft}{red {underline $text}}{gray $contextRight}\n\t Suggestions: {yellow [$suggestions]}`;
11
+ const templateIssueLegacy = `${chalk.green('$filename')}[$row, $col]: $message: ${chalk.red('$text')}`;
12
+ const templateIssueWordsOnly = '$text';
13
+ function genIssueEmitter(template) {
14
+ const defaultWidth = 10;
15
+ let maxWidth = defaultWidth;
16
+ let uri;
17
+ return function issueEmitter(issue) {
18
+ if (uri !== issue.uri) {
19
+ maxWidth = defaultWidth;
20
+ uri = issue.uri;
21
+ }
22
+ maxWidth = Math.max(maxWidth * 0.999, issue.text.length, 10);
23
+ console.log(formatIssue(template, issue, Math.ceil(maxWidth)));
24
+ };
25
+ }
26
+ function errorEmitter(message, error) {
27
+ if (isSpellingDictionaryLoadError(error)) {
28
+ error = error.cause;
29
+ }
30
+ console.error(chalk.red(message), error.toString());
31
+ }
32
+ function nullEmitter() {
33
+ /* empty */
34
+ }
35
+ function relativeFilename(filename, cwd = process.cwd()) {
36
+ const rel = path.relative(cwd, filename);
37
+ if (rel.startsWith('..'))
38
+ return filename;
39
+ return '.' + path.sep + rel;
40
+ }
41
+ function relativeUriFilename(uri, fsPathRoot) {
42
+ const fsPath = URI.parse(uri).fsPath;
43
+ const rel = path.relative(fsPathRoot, fsPath);
44
+ if (rel.startsWith('..'))
45
+ return fsPath;
46
+ return '.' + path.sep + rel;
47
+ }
48
+ function reportProgress(p) {
49
+ if (p.type === 'ProgressFileComplete') {
50
+ return reportProgressFileComplete(p);
51
+ }
52
+ if (p.type === 'ProgressFileBegin') {
53
+ return reportProgressFileBegin(p);
54
+ }
55
+ }
56
+ function reportProgressFileBegin(p) {
57
+ const fc = '' + p.fileCount;
58
+ const fn = (' '.repeat(fc.length) + p.fileNum).slice(-fc.length);
59
+ const idx = fn + '/' + fc;
60
+ const filename = chalk.gray(relativeFilename(p.filename));
61
+ process.stderr.write(`\r${idx} ${filename}`);
62
+ }
63
+ function reportProgressFileComplete(p) {
64
+ const time = reportTime(p.elapsedTimeMs, !!p.cached);
65
+ const skipped = p.processed === false ? ' skipped' : '';
66
+ const hasErrors = p.numErrors ? chalk.red ` X` : '';
67
+ console.error(` ${time}${skipped}${hasErrors}`);
68
+ }
69
+ function reportTime(elapsedTimeMs, cached) {
70
+ if (cached)
71
+ return chalk.green('cached');
72
+ if (elapsedTimeMs === undefined)
73
+ return '-';
74
+ const color = elapsedTimeMs < 1000 ? chalk.white : elapsedTimeMs < 2000 ? chalk.yellow : chalk.redBright;
75
+ return color(elapsedTimeMs.toFixed(2) + 'ms');
76
+ }
77
+ export function getReporter(options) {
78
+ const issueTemplate = options.wordsOnly
79
+ ? templateIssueWordsOnly
80
+ : options.legacy
81
+ ? templateIssueLegacy
82
+ : options.showContext
83
+ ? options.showSuggestions
84
+ ? templateIssueWithContextWithSuggestions
85
+ : templateIssueWithContext
86
+ : options.showSuggestions
87
+ ? templateIssueWithSuggestions
88
+ : options.showSuggestions === false
89
+ ? templateIssueNoFix
90
+ : templateIssue;
91
+ const { fileGlobs, silent, summary, issues, progress, verbose, debug } = options;
92
+ const emitters = {
93
+ Debug: !silent && debug ? (s) => console.info(chalk.cyan(s)) : nullEmitter,
94
+ Info: !silent && verbose ? (s) => console.info(chalk.yellow(s)) : nullEmitter,
95
+ Warning: (s) => console.info(chalk.yellow(s)),
96
+ };
97
+ function infoEmitter(message, msgType) {
98
+ emitters[msgType]?.(message);
99
+ }
100
+ const root = URI.file(options.root || process.cwd());
101
+ const fsPathRoot = root.fsPath;
102
+ function relativeIssue(fn) {
103
+ const fnFilename = options.relative
104
+ ? (uri) => relativeUriFilename(uri, fsPathRoot)
105
+ : (uri) => URI.parse(uri).fsPath;
106
+ return (i) => {
107
+ const filename = i.uri ? fnFilename(i.uri) : '';
108
+ const r = { ...i, filename };
109
+ fn(r);
110
+ };
111
+ }
112
+ const resultEmitter = (result) => {
113
+ if (!fileGlobs.length && !result.files) {
114
+ return;
115
+ }
116
+ if (result.cachedFiles) {
117
+ 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);
118
+ return;
119
+ }
120
+ console.error('CSpell\x3a Files checked: %d, Issues found: %d in %d files', result.files, result.issues, result.filesWithIssues.size);
121
+ };
122
+ return {
123
+ issue: relativeIssue(silent || !issues ? nullEmitter : genIssueEmitter(issueTemplate)),
124
+ error: silent ? nullEmitter : errorEmitter,
125
+ info: infoEmitter,
126
+ debug: emitters.Debug,
127
+ progress: !silent && progress ? reportProgress : nullEmitter,
128
+ result: !silent && summary ? resultEmitter : nullEmitter,
129
+ };
130
+ }
131
+ function formatIssue(templateStr, issue, maxIssueTextWidth) {
132
+ function clean(t) {
133
+ return t.replace(/\s+/, ' ');
134
+ }
135
+ const { uri = '', filename, row, col, text, context, offset } = issue;
136
+ const contextLeft = clean(context.text.slice(0, offset - context.offset));
137
+ const contextRight = clean(context.text.slice(offset + text.length - context.offset));
138
+ const contextFull = clean(context.text);
139
+ const padContext = ' '.repeat(Math.max(maxIssueTextWidth - text.length, 0));
140
+ const rowText = row.toString();
141
+ const colText = col.toString();
142
+ const padRowCol = ' '.repeat(Math.max(1, 8 - (rowText.length + colText.length)));
143
+ const suggestions = formatSuggestions(issue);
144
+ const msg = issue.message || (issue.isFlagged ? 'Forbidden word' : 'Unknown word');
145
+ const message = issue.isFlagged ? `{yellow ${msg}}` : msg;
146
+ const substitutions = {
147
+ $col: colText,
148
+ $contextFull: contextFull,
149
+ $contextLeft: contextLeft,
150
+ $contextRight: contextRight,
151
+ $filename: filename,
152
+ $padContext: padContext,
153
+ $padRowCol: padRowCol,
154
+ $row: rowText,
155
+ $suggestions: suggestions,
156
+ $text: text,
157
+ $uri: uri,
158
+ $quickFix: formatQuickFix(issue),
159
+ };
160
+ const t = template(templateStr.replace(/\$message/g, message));
161
+ return substitute(chalkTemplate(t), substitutions).trimEnd();
162
+ }
163
+ function formatSuggestions(issue) {
164
+ if (issue.suggestionsEx) {
165
+ return issue.suggestionsEx
166
+ .map((sug) => sug.isPreferred
167
+ ? chalk.italic(chalk.bold(sug.wordAdjustedToMatchCase || sug.word)) + '*'
168
+ : sug.wordAdjustedToMatchCase || sug.word)
169
+ .join(', ');
170
+ }
171
+ if (issue.suggestions) {
172
+ return issue.suggestions.join(', ');
173
+ }
174
+ return '';
175
+ }
176
+ function formatQuickFix(issue) {
177
+ if (!issue.suggestionsEx?.length)
178
+ return '';
179
+ const preferred = issue.suggestionsEx
180
+ .filter((sug) => sug.isPreferred)
181
+ .map((sug) => sug.wordAdjustedToMatchCase || sug.word);
182
+ if (!preferred.length)
183
+ return '';
184
+ const fixes = preferred.map((w) => chalk.italic(chalk.yellow(w)));
185
+ return `fix: (${fixes.join(', ')})`;
186
+ }
187
+ class TS extends Array {
188
+ constructor(s) {
189
+ super(s);
190
+ this.raw = [s];
191
+ }
192
+ }
193
+ function template(s) {
194
+ return new TS(s);
195
+ }
196
+ function substitute(text, substitutions) {
197
+ const subs = [];
198
+ for (const [match, replaceWith] of Object.entries(substitutions)) {
199
+ const len = match.length;
200
+ for (let i = text.indexOf(match); i >= 0; i = text.indexOf(match, i + 1)) {
201
+ subs.push([i, i + len, replaceWith]);
202
+ }
203
+ }
204
+ subs.sort((a, b) => a[0] - b[0]);
205
+ let i = 0;
206
+ function sub(r) {
207
+ const [a, b, t] = r;
208
+ const prefix = text.slice(i, a);
209
+ i = b;
210
+ return prefix + t;
211
+ }
212
+ const parts = subs.map(sub);
213
+ return parts.join('') + text.slice(i);
214
+ }
215
+ export const __testing__ = {
216
+ formatIssue,
217
+ };
218
+ //# sourceMappingURL=cli-reporter.js.map
@@ -215,3 +215,4 @@ function substitute(text, substitutions) {
215
215
  export const __testing__ = {
216
216
  formatIssue,
217
217
  };
218
+ //# sourceMappingURL=cli-reporter.mjs.map
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function commandCheck(prog: Command): Command;
3
+ //# sourceMappingURL=commandCheck.d.ts.map
@@ -0,0 +1,48 @@
1
+ import chalk from 'chalk';
2
+ import { Option as CommanderOption } from 'commander';
3
+ import * as App from './application.js';
4
+ import { checkText } from './application.js';
5
+ import { CheckFailed } from './util/errors.js';
6
+ export function commandCheck(prog) {
7
+ return prog
8
+ .command('check <files...>')
9
+ .description('Spell check file(s) and display the result. The full file is displayed in color.')
10
+ .option('-c, --config <cspell.json>', 'Configuration file to use. By default cspell looks for cspell.json in the current directory.')
11
+ .option('--validate-directives', 'Validate in-document CSpell directives.')
12
+ .option('--no-validate-directives', 'Do not validate in-document CSpell directives.')
13
+ .option('--no-color', 'Turn off color.')
14
+ .option('--color', 'Force color')
15
+ .addOption(new CommanderOption('--default-configuration', 'Load the default configuration and dictionaries.').hideHelp())
16
+ .addOption(new CommanderOption('--no-default-configuration', 'Do not load the default configuration and dictionaries.'))
17
+ .action(async (files, options) => {
18
+ App.parseApplicationFeatureFlags(options.flag);
19
+ let issueCount = 0;
20
+ for (const filename of files) {
21
+ console.log(chalk.yellowBright(`Check file: ${filename}`));
22
+ console.log();
23
+ try {
24
+ const result = await checkText(filename, options);
25
+ for (const item of result.items) {
26
+ const fn = item.flagIE === App.IncludeExcludeFlag.EXCLUDE
27
+ ? chalk.gray
28
+ : item.isError
29
+ ? chalk.red
30
+ : chalk.whiteBright;
31
+ const t = fn(item.text);
32
+ process.stdout.write(t);
33
+ issueCount += item.isError ? 1 : 0;
34
+ }
35
+ console.log();
36
+ }
37
+ catch (e) {
38
+ console.error(`File not found "${filename}"`);
39
+ throw new CheckFailed('File not found', 1);
40
+ }
41
+ console.log();
42
+ }
43
+ if (issueCount) {
44
+ throw new CheckFailed('Issues found', 1);
45
+ }
46
+ });
47
+ }
48
+ //# sourceMappingURL=commandCheck.js.map
@@ -45,3 +45,4 @@ export function commandCheck(prog) {
45
45
  }
46
46
  });
47
47
  }
48
+ //# sourceMappingURL=commandCheck.mjs.map
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function commandLink(prog: Command): Command;
3
+ //# sourceMappingURL=commandLink.d.ts.map
@@ -0,0 +1,47 @@
1
+ import { addPathsToGlobalImports, addPathsToGlobalImportsResultToTable, listGlobalImports, listGlobalImportsResultToTable, removePathsFromGlobalImports, } from './link.js';
2
+ import { CheckFailed } from './util/errors.js';
3
+ import { tableToLines } from './util/table.js';
4
+ export function commandLink(prog) {
5
+ const linkCommand = prog
6
+ .command('link')
7
+ .description('Link dictionaries and other settings to the cspell global config.');
8
+ linkCommand
9
+ .command('list', { isDefault: true })
10
+ .alias('ls')
11
+ .description('List currently linked configurations.')
12
+ .action(() => {
13
+ const imports = listGlobalImports();
14
+ const table = listGlobalImportsResultToTable(imports.list);
15
+ tableToLines(table).forEach((line) => console.log(line));
16
+ return;
17
+ });
18
+ linkCommand
19
+ .command('add <dictionaries...>')
20
+ .alias('a')
21
+ .description('Add dictionaries any other settings to the cspell global config.')
22
+ .action((dictionaries) => {
23
+ const r = addPathsToGlobalImports(dictionaries);
24
+ const table = addPathsToGlobalImportsResultToTable(r);
25
+ console.log('Adding:');
26
+ tableToLines(table).forEach((line) => console.log(line));
27
+ if (r.error) {
28
+ throw new CheckFailed(r.error, 1);
29
+ }
30
+ return;
31
+ });
32
+ linkCommand
33
+ .command('remove <paths...>')
34
+ .alias('r')
35
+ .description('Remove matching paths / packages from the global config.')
36
+ .action((dictionaries) => {
37
+ const r = removePathsFromGlobalImports(dictionaries);
38
+ console.log('Removing:');
39
+ if (r.error) {
40
+ throw new CheckFailed(r.error, 1);
41
+ }
42
+ r.removed.map((f) => console.log(f));
43
+ return;
44
+ });
45
+ return linkCommand;
46
+ }
47
+ //# sourceMappingURL=commandLink.js.map
@@ -44,3 +44,4 @@ export function commandLink(prog) {
44
44
  });
45
45
  return linkCommand;
46
46
  }
47
+ //# sourceMappingURL=commandLink.mjs.map
@@ -0,0 +1,3 @@
1
+ import type { Command } from 'commander';
2
+ export declare function commandLint(prog: Command): Command;
3
+ //# sourceMappingURL=commandLint.d.ts.map