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.
- package/README.md +1 -1
- package/dist/esm/app.d.ts +5 -0
- package/dist/esm/app.js +45 -0
- package/dist/esm/app.mjs +1 -0
- package/dist/esm/application.d.ts +16 -0
- package/dist/esm/application.js +88 -0
- package/dist/esm/application.mjs +1 -0
- package/dist/esm/cli-reporter.d.ts +16 -0
- package/dist/esm/cli-reporter.js +218 -0
- package/dist/esm/cli-reporter.mjs +1 -0
- package/dist/esm/commandCheck.d.ts +3 -0
- package/dist/esm/commandCheck.js +48 -0
- package/dist/esm/commandCheck.mjs +1 -0
- package/dist/esm/commandLink.d.ts +3 -0
- package/dist/esm/commandLink.js +47 -0
- package/dist/esm/commandLink.mjs +1 -0
- package/dist/esm/commandLint.d.ts +3 -0
- package/dist/esm/commandLint.js +127 -0
- package/dist/esm/commandLint.mjs +5 -1
- package/dist/esm/commandSuggestion.d.ts +3 -0
- package/dist/esm/commandSuggestion.js +61 -0
- package/dist/esm/commandSuggestion.mjs +1 -0
- package/dist/esm/commandTrace.d.ts +3 -0
- package/dist/esm/commandTrace.js +60 -0
- package/dist/esm/commandTrace.mjs +1 -0
- package/dist/esm/emitters/DictionaryPathFormat.d.ts +3 -0
- package/dist/esm/emitters/DictionaryPathFormat.js +12 -0
- package/dist/esm/emitters/DictionaryPathFormat.mjs +1 -0
- package/dist/esm/emitters/suggestionsEmitter.d.ts +13 -0
- package/dist/esm/emitters/suggestionsEmitter.js +77 -0
- package/dist/esm/emitters/suggestionsEmitter.mjs +1 -0
- package/dist/esm/emitters/traceEmitter.d.ts +21 -0
- package/dist/esm/emitters/traceEmitter.js +141 -0
- package/dist/esm/emitters/traceEmitter.mjs +1 -0
- package/dist/esm/featureFlags/featureFlags.d.ts +4 -0
- package/dist/esm/featureFlags/featureFlags.js +20 -0
- package/dist/esm/featureFlags/featureFlags.mjs +1 -0
- package/dist/esm/featureFlags/index.d.ts +2 -0
- package/dist/esm/featureFlags/index.js +2 -0
- package/dist/esm/featureFlags/index.mjs +1 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.js +4 -0
- package/dist/esm/index.mjs +1 -0
- package/dist/esm/link.d.ts +8 -0
- package/dist/esm/link.js +39 -0
- package/dist/esm/link.mjs +1 -0
- package/dist/esm/lint/LintRequest.d.ts +23 -0
- package/dist/esm/lint/LintRequest.js +21 -0
- package/dist/esm/lint/LintRequest.mjs +1 -0
- package/dist/esm/lint/index.d.ts +3 -0
- package/dist/esm/lint/index.js +3 -0
- package/dist/esm/lint/index.mjs +1 -0
- package/dist/esm/lint/lint.d.ts +4 -0
- package/dist/esm/lint/lint.js +469 -0
- package/dist/esm/lint/lint.mjs +1 -0
- package/dist/esm/options.d.ts +178 -0
- package/dist/esm/options.js +8 -0
- package/dist/esm/options.mjs +1 -0
- package/dist/esm/repl/index.d.ts +18 -0
- package/dist/esm/repl/index.js +47 -0
- package/dist/esm/repl/index.mjs +1 -0
- package/dist/esm/util/InMemoryReporter.d.ts +28 -0
- package/dist/esm/util/InMemoryReporter.js +43 -0
- package/dist/esm/util/InMemoryReporter.mjs +1 -0
- package/dist/esm/util/async.d.ts +3 -0
- package/dist/esm/util/async.js +4 -0
- package/dist/esm/util/async.mjs +1 -0
- package/dist/esm/util/cache/CSpellLintResultCache.d.ts +20 -0
- package/dist/esm/util/cache/CSpellLintResultCache.js +2 -0
- package/dist/esm/util/cache/CSpellLintResultCache.mjs +1 -0
- package/dist/esm/util/cache/CacheOptions.d.ts +34 -0
- package/dist/esm/util/cache/CacheOptions.js +2 -0
- package/dist/esm/util/cache/CacheOptions.mjs +1 -0
- package/dist/esm/util/cache/DiskCache.d.ts +63 -0
- package/dist/esm/util/cache/DiskCache.js +207 -0
- package/dist/esm/util/cache/DiskCache.mjs +1 -0
- package/dist/esm/util/cache/DummyCache.d.ts +11 -0
- package/dist/esm/util/cache/DummyCache.js +18 -0
- package/dist/esm/util/cache/DummyCache.mjs +1 -0
- package/dist/esm/util/cache/ObjectCollection.d.ts +17 -0
- package/dist/esm/util/cache/ObjectCollection.js +131 -0
- package/dist/esm/util/cache/ObjectCollection.mjs +1 -0
- package/dist/esm/util/cache/createCache.d.ts +31 -0
- package/dist/esm/util/cache/createCache.js +69 -0
- package/dist/esm/util/cache/createCache.mjs +1 -0
- package/dist/esm/util/cache/fileEntryCache.d.ts +9 -0
- package/dist/esm/util/cache/fileEntryCache.js +79 -0
- package/dist/esm/util/cache/fileEntryCache.mjs +1 -0
- package/dist/esm/util/cache/index.d.ts +4 -0
- package/dist/esm/util/cache/index.js +2 -0
- package/dist/esm/util/cache/index.mjs +1 -0
- package/dist/esm/util/constants.d.ts +6 -0
- package/dist/esm/util/constants.js +5 -0
- package/dist/esm/util/constants.mjs +1 -0
- package/dist/esm/util/errors.d.ts +23 -0
- package/dist/esm/util/errors.js +51 -0
- package/dist/esm/util/errors.mjs +1 -0
- package/dist/esm/util/fileHelper.d.ts +63 -0
- package/dist/esm/util/fileHelper.js +182 -0
- package/dist/esm/util/fileHelper.mjs +1 -0
- package/dist/esm/util/glob.d.ts +45 -0
- package/dist/esm/util/glob.js +137 -0
- package/dist/esm/util/glob.mjs +1 -0
- package/dist/esm/util/prefetch.d.ts +2 -0
- package/dist/esm/util/prefetch.js +16 -0
- package/dist/esm/util/prefetch.mjs +1 -0
- package/dist/esm/util/reporters.d.ts +14 -0
- package/dist/esm/util/reporters.js +62 -0
- package/dist/esm/util/reporters.mjs +1 -0
- package/dist/esm/util/stdin.d.ts +2 -0
- package/dist/esm/util/stdin.js +5 -0
- package/dist/esm/util/stdin.mjs +1 -0
- package/dist/esm/util/table.d.ts +10 -0
- package/dist/esm/util/table.js +32 -0
- package/dist/esm/util/table.mjs +1 -0
- package/dist/esm/util/timer.d.ts +8 -0
- package/dist/esm/util/timer.js +11 -0
- package/dist/esm/util/timer.mjs +1 -0
- package/dist/esm/util/types.d.ts +7 -0
- package/dist/esm/util/types.js +5 -0
- package/dist/esm/util/types.mjs +1 -0
- package/dist/esm/util/util.d.ts +13 -0
- package/dist/esm/util/util.js +45 -0
- package/dist/esm/util/util.mjs +1 -0
- 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
|
|
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.
|
package/dist/esm/app.js
ADDED
|
@@ -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
|
@@ -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
|
package/dist/esm/application.mjs
CHANGED
|
@@ -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
|
|
@@ -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
|
|
@@ -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
|
package/dist/esm/commandLink.mjs
CHANGED