gurkencheck 0.0.4
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/LICENSE +13 -0
- package/README.md +327 -0
- package/dist/config-parser.d.ts +21 -0
- package/dist/config-parser.d.ts.map +1 -0
- package/dist/config-parser.js +171 -0
- package/dist/config-parser.js.map +1 -0
- package/dist/config-verifier.d.ts +4 -0
- package/dist/config-verifier.d.ts.map +1 -0
- package/dist/config-verifier.js +81 -0
- package/dist/config-verifier.js.map +1 -0
- package/dist/feature-finder.d.ts +18 -0
- package/dist/feature-finder.d.ts.map +1 -0
- package/dist/feature-finder.js +70 -0
- package/dist/feature-finder.js.map +1 -0
- package/dist/formatters/index.d.ts +23 -0
- package/dist/formatters/index.d.ts.map +1 -0
- package/dist/formatters/index.js +79 -0
- package/dist/formatters/index.js.map +1 -0
- package/dist/formatters/json.d.ts +31 -0
- package/dist/formatters/json.d.ts.map +1 -0
- package/dist/formatters/json.js +31 -0
- package/dist/formatters/json.js.map +1 -0
- package/dist/formatters/junit.d.ts +17 -0
- package/dist/formatters/junit.d.ts.map +1 -0
- package/dist/formatters/junit.js +61 -0
- package/dist/formatters/junit.js.map +1 -0
- package/dist/formatters/sarif.d.ts +6 -0
- package/dist/formatters/sarif.d.ts.map +1 -0
- package/dist/formatters/sarif.js +81 -0
- package/dist/formatters/sarif.js.map +1 -0
- package/dist/formatters/stylish.d.ts +9 -0
- package/dist/formatters/stylish.d.ts.map +1 -0
- package/dist/formatters/stylish.js +66 -0
- package/dist/formatters/stylish.js.map +1 -0
- package/dist/formatters/tap.d.ts +14 -0
- package/dist/formatters/tap.d.ts.map +1 -0
- package/dist/formatters/tap.js +45 -0
- package/dist/formatters/tap.js.map +1 -0
- package/dist/gherkin/dialects.d.ts +31 -0
- package/dist/gherkin/dialects.d.ts.map +1 -0
- package/dist/gherkin/dialects.js +40 -0
- package/dist/gherkin/dialects.js.map +1 -0
- package/dist/gherkin/keywords.d.ts +21 -0
- package/dist/gherkin/keywords.d.ts.map +1 -0
- package/dist/gherkin/keywords.js +53 -0
- package/dist/gherkin/keywords.js.map +1 -0
- package/dist/gherkin/parse.d.ts +32 -0
- package/dist/gherkin/parse.d.ts.map +1 -0
- package/dist/gherkin/parse.js +236 -0
- package/dist/gherkin/parse.js.map +1 -0
- package/dist/gherkin/traverse.d.ts +45 -0
- package/dist/gherkin/traverse.d.ts.map +1 -0
- package/dist/gherkin/traverse.js +89 -0
- package/dist/gherkin/traverse.js.map +1 -0
- package/dist/gherkin/variables.d.ts +26 -0
- package/dist/gherkin/variables.d.ts.map +1 -0
- package/dist/gherkin/variables.js +51 -0
- package/dist/gherkin/variables.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +31 -0
- package/dist/index.js.map +1 -0
- package/dist/linter.d.ts +23 -0
- package/dist/linter.d.ts.map +1 -0
- package/dist/linter.js +57 -0
- package/dist/linter.js.map +1 -0
- package/dist/logger.d.ts +16 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +28 -0
- package/dist/logger.js.map +1 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +144 -0
- package/dist/main.js.map +1 -0
- package/dist/presets.d.ts +19 -0
- package/dist/presets.d.ts.map +1 -0
- package/dist/presets.js +24 -0
- package/dist/presets.js.map +1 -0
- package/dist/rules/allowed-tags.d.ts +4 -0
- package/dist/rules/allowed-tags.d.ts.map +1 -0
- package/dist/rules/allowed-tags.js +34 -0
- package/dist/rules/allowed-tags.js.map +1 -0
- package/dist/rules/file-name.d.ts +4 -0
- package/dist/rules/file-name.d.ts.map +1 -0
- package/dist/rules/file-name.js +41 -0
- package/dist/rules/file-name.js.map +1 -0
- package/dist/rules/indentation.d.ts +4 -0
- package/dist/rules/indentation.d.ts.map +1 -0
- package/dist/rules/indentation.js +153 -0
- package/dist/rules/indentation.js.map +1 -0
- package/dist/rules/index.d.ts +13 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +70 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/keywords-in-logical-order.d.ts +4 -0
- package/dist/rules/keywords-in-logical-order.d.ts.map +1 -0
- package/dist/rules/keywords-in-logical-order.js +37 -0
- package/dist/rules/keywords-in-logical-order.js.map +1 -0
- package/dist/rules/max-scenarios-per-file.d.ts +4 -0
- package/dist/rules/max-scenarios-per-file.d.ts.map +1 -0
- package/dist/rules/max-scenarios-per-file.js +42 -0
- package/dist/rules/max-scenarios-per-file.js.map +1 -0
- package/dist/rules/name-length.d.ts +4 -0
- package/dist/rules/name-length.d.ts.map +1 -0
- package/dist/rules/name-length.js +50 -0
- package/dist/rules/name-length.js.map +1 -0
- package/dist/rules/new-line-at-eof.d.ts +4 -0
- package/dist/rules/new-line-at-eof.d.ts.map +1 -0
- package/dist/rules/new-line-at-eof.js +30 -0
- package/dist/rules/new-line-at-eof.js.map +1 -0
- package/dist/rules/no-background-only-scenario.d.ts +4 -0
- package/dist/rules/no-background-only-scenario.d.ts.map +1 -0
- package/dist/rules/no-background-only-scenario.js +43 -0
- package/dist/rules/no-background-only-scenario.js.map +1 -0
- package/dist/rules/no-dupe-feature-names.d.ts +4 -0
- package/dist/rules/no-dupe-feature-names.d.ts.map +1 -0
- package/dist/rules/no-dupe-feature-names.js +25 -0
- package/dist/rules/no-dupe-feature-names.js.map +1 -0
- package/dist/rules/no-dupe-file-names.d.ts +4 -0
- package/dist/rules/no-dupe-file-names.d.ts.map +1 -0
- package/dist/rules/no-dupe-file-names.js +28 -0
- package/dist/rules/no-dupe-file-names.js.map +1 -0
- package/dist/rules/no-dupe-scenario-names.d.ts +4 -0
- package/dist/rules/no-dupe-scenario-names.d.ts.map +1 -0
- package/dist/rules/no-dupe-scenario-names.js +41 -0
- package/dist/rules/no-dupe-scenario-names.js.map +1 -0
- package/dist/rules/no-duplicate-tags.d.ts +4 -0
- package/dist/rules/no-duplicate-tags.d.ts.map +1 -0
- package/dist/rules/no-duplicate-tags.js +38 -0
- package/dist/rules/no-duplicate-tags.js.map +1 -0
- package/dist/rules/no-empty-background.d.ts +4 -0
- package/dist/rules/no-empty-background.d.ts.map +1 -0
- package/dist/rules/no-empty-background.js +24 -0
- package/dist/rules/no-empty-background.js.map +1 -0
- package/dist/rules/no-empty-file.d.ts +4 -0
- package/dist/rules/no-empty-file.d.ts.map +1 -0
- package/dist/rules/no-empty-file.js +12 -0
- package/dist/rules/no-empty-file.js.map +1 -0
- package/dist/rules/no-examples-in-scenarios.d.ts +4 -0
- package/dist/rules/no-examples-in-scenarios.d.ts.map +1 -0
- package/dist/rules/no-examples-in-scenarios.js +25 -0
- package/dist/rules/no-examples-in-scenarios.js.map +1 -0
- package/dist/rules/no-files-without-scenarios.d.ts +4 -0
- package/dist/rules/no-files-without-scenarios.d.ts.map +1 -0
- package/dist/rules/no-files-without-scenarios.js +18 -0
- package/dist/rules/no-files-without-scenarios.js.map +1 -0
- package/dist/rules/no-homogenous-tags.d.ts +4 -0
- package/dist/rules/no-homogenous-tags.d.ts.map +1 -0
- package/dist/rules/no-homogenous-tags.js +54 -0
- package/dist/rules/no-homogenous-tags.js.map +1 -0
- package/dist/rules/no-multiple-empty-lines.d.ts +4 -0
- package/dist/rules/no-multiple-empty-lines.d.ts.map +1 -0
- package/dist/rules/no-multiple-empty-lines.js +44 -0
- package/dist/rules/no-multiple-empty-lines.js.map +1 -0
- package/dist/rules/no-partially-commented-tag-lines.d.ts +4 -0
- package/dist/rules/no-partially-commented-tag-lines.d.ts.map +1 -0
- package/dist/rules/no-partially-commented-tag-lines.js +44 -0
- package/dist/rules/no-partially-commented-tag-lines.js.map +1 -0
- package/dist/rules/no-restricted-patterns.d.ts +4 -0
- package/dist/rules/no-restricted-patterns.d.ts.map +1 -0
- package/dist/rules/no-restricted-patterns.js +101 -0
- package/dist/rules/no-restricted-patterns.js.map +1 -0
- package/dist/rules/no-restricted-tags.d.ts +4 -0
- package/dist/rules/no-restricted-tags.d.ts.map +1 -0
- package/dist/rules/no-restricted-tags.js +35 -0
- package/dist/rules/no-restricted-tags.js.map +1 -0
- package/dist/rules/no-scenario-outlines-without-examples.d.ts +4 -0
- package/dist/rules/no-scenario-outlines-without-examples.d.ts.map +1 -0
- package/dist/rules/no-scenario-outlines-without-examples.js +29 -0
- package/dist/rules/no-scenario-outlines-without-examples.js.map +1 -0
- package/dist/rules/no-superfluous-tags.d.ts +4 -0
- package/dist/rules/no-superfluous-tags.d.ts.map +1 -0
- package/dist/rules/no-superfluous-tags.js +40 -0
- package/dist/rules/no-superfluous-tags.js.map +1 -0
- package/dist/rules/no-trailing-spaces.d.ts +4 -0
- package/dist/rules/no-trailing-spaces.d.ts.map +1 -0
- package/dist/rules/no-trailing-spaces.js +24 -0
- package/dist/rules/no-trailing-spaces.js.map +1 -0
- package/dist/rules/no-undeclared-variables.d.ts +4 -0
- package/dist/rules/no-undeclared-variables.d.ts.map +1 -0
- package/dist/rules/no-undeclared-variables.js +35 -0
- package/dist/rules/no-undeclared-variables.js.map +1 -0
- package/dist/rules/no-unnamed-features.d.ts +4 -0
- package/dist/rules/no-unnamed-features.d.ts.map +1 -0
- package/dist/rules/no-unnamed-features.js +19 -0
- package/dist/rules/no-unnamed-features.js.map +1 -0
- package/dist/rules/no-unnamed-scenarios.d.ts +4 -0
- package/dist/rules/no-unnamed-scenarios.d.ts.map +1 -0
- package/dist/rules/no-unnamed-scenarios.js +24 -0
- package/dist/rules/no-unnamed-scenarios.js.map +1 -0
- package/dist/rules/no-unused-variables.d.ts +4 -0
- package/dist/rules/no-unused-variables.d.ts.map +1 -0
- package/dist/rules/no-unused-variables.js +36 -0
- package/dist/rules/no-unused-variables.js.map +1 -0
- package/dist/rules/one-space-between-tags.d.ts +4 -0
- package/dist/rules/one-space-between-tags.d.ts.map +1 -0
- package/dist/rules/one-space-between-tags.js +36 -0
- package/dist/rules/one-space-between-tags.js.map +1 -0
- package/dist/rules/only-one-when.d.ts +4 -0
- package/dist/rules/only-one-when.d.ts.map +1 -0
- package/dist/rules/only-one-when.js +59 -0
- package/dist/rules/only-one-when.js.map +1 -0
- package/dist/rules/required-tags.d.ts +4 -0
- package/dist/rules/required-tags.d.ts.map +1 -0
- package/dist/rules/required-tags.js +36 -0
- package/dist/rules/required-tags.js.map +1 -0
- package/dist/rules/scenario-size.d.ts +4 -0
- package/dist/rules/scenario-size.d.ts.map +1 -0
- package/dist/rules/scenario-size.js +37 -0
- package/dist/rules/scenario-size.js.map +1 -0
- package/dist/rules/use-and.d.ts +4 -0
- package/dist/rules/use-and.d.ts.map +1 -0
- package/dist/rules/use-and.js +33 -0
- package/dist/rules/use-and.js.map +1 -0
- package/dist/rules.d.ts +24 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +109 -0
- package/dist/rules.js.map +1 -0
- package/dist/suppressions.d.ts +33 -0
- package/dist/suppressions.d.ts.map +1 -0
- package/dist/suppressions.js +84 -0
- package/dist/suppressions.js.map +1 -0
- package/dist/types.d.ts +81 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/util/case.d.ts +21 -0
- package/dist/util/case.d.ts.map +1 -0
- package/dist/util/case.js +42 -0
- package/dist/util/case.js.map +1 -0
- package/dist/util/collections.d.ts +30 -0
- package/dist/util/collections.d.ts.map +1 -0
- package/dist/util/collections.js +87 -0
- package/dist/util/collections.js.map +1 -0
- package/dist/util/glob.d.ts +20 -0
- package/dist/util/glob.d.ts.map +1 -0
- package/dist/util/glob.js +203 -0
- package/dist/util/glob.js.map +1 -0
- package/dist/util/json.d.ts +14 -0
- package/dist/util/json.d.ts.map +1 -0
- package/dist/util/json.js +63 -0
- package/dist/util/json.js.map +1 -0
- package/dist/util/lines.d.ts +24 -0
- package/dist/util/lines.d.ts.map +1 -0
- package/dist/util/lines.js +45 -0
- package/dist/util/lines.js.map +1 -0
- package/dist/util/location.d.ts +15 -0
- package/dist/util/location.d.ts.map +1 -0
- package/dist/util/location.js +11 -0
- package/dist/util/location.js.map +1 -0
- package/dist/util/xml.d.ts +16 -0
- package/dist/util/xml.d.ts.map +1 -0
- package/dist/util/xml.js +36 -0
- package/dist/util/xml.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +24 -0
- package/dist/version.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Turning the paths, directories and globs given on the command line into a
|
|
3
|
+
* list of feature files.
|
|
4
|
+
*/
|
|
5
|
+
import fs from 'node:fs';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { uniq } from './util/collections.js';
|
|
8
|
+
import { globSync } from './util/glob.js';
|
|
9
|
+
/** The ignore file looked for when `--ignore` is not given. */
|
|
10
|
+
export const DEFAULT_IGNORE_FILE_NAME = '.gurkencheckignore';
|
|
11
|
+
/** Never worth linting, and expensive to walk into. */
|
|
12
|
+
export const DEFAULT_IGNORED_PATTERNS = ['node_modules/**'];
|
|
13
|
+
/**
|
|
14
|
+
* Expands one command line argument into a glob that only matches feature
|
|
15
|
+
* files, or `undefined` when it does not name anything usable.
|
|
16
|
+
*/
|
|
17
|
+
function toFeatureGlob(pattern) {
|
|
18
|
+
if (pattern === '.') {
|
|
19
|
+
return '**/*.feature';
|
|
20
|
+
}
|
|
21
|
+
if (/\/\*\*$/.test(pattern)) {
|
|
22
|
+
return `${pattern}/*.feature`;
|
|
23
|
+
}
|
|
24
|
+
if (pattern.endsWith('.feature')) {
|
|
25
|
+
return pattern;
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
if (fs.statSync(pattern).isDirectory()) {
|
|
29
|
+
return path.join(pattern, '**/*.feature').split(path.sep).join('/');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Reported by the caller as an invalid pattern.
|
|
34
|
+
}
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
/** Reads the ignore file, one glob pattern per line, ignoring blank lines. */
|
|
38
|
+
export function readIgnorePatterns(ignoreArgument, ignoreFileName = DEFAULT_IGNORE_FILE_NAME) {
|
|
39
|
+
if (ignoreArgument !== undefined && ignoreArgument.length > 0) {
|
|
40
|
+
return [...ignoreArgument];
|
|
41
|
+
}
|
|
42
|
+
if (fs.existsSync(ignoreFileName)) {
|
|
43
|
+
return fs
|
|
44
|
+
.readFileSync(ignoreFileName, 'utf8')
|
|
45
|
+
.split(/\r\n|\r|\n/)
|
|
46
|
+
.map((line) => line.trim())
|
|
47
|
+
.filter((line) => line !== '' && !line.startsWith('#'));
|
|
48
|
+
}
|
|
49
|
+
return [...DEFAULT_IGNORED_PATTERNS];
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Finds the feature files named by the given patterns. With no patterns, the
|
|
53
|
+
* working directory is searched recursively.
|
|
54
|
+
*/
|
|
55
|
+
export function findFeatureFiles(patterns, ignoreArgument) {
|
|
56
|
+
const searched = patterns.length > 0 ? patterns : ['.'];
|
|
57
|
+
const ignore = readIgnorePatterns(ignoreArgument);
|
|
58
|
+
const files = [];
|
|
59
|
+
const invalidPatterns = [];
|
|
60
|
+
for (const pattern of searched) {
|
|
61
|
+
const featureGlob = toFeatureGlob(pattern);
|
|
62
|
+
if (featureGlob === undefined) {
|
|
63
|
+
invalidPatterns.push(pattern);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
files.push(...globSync(featureGlob, { ignore }));
|
|
67
|
+
}
|
|
68
|
+
return { files: uniq(files), invalidPatterns };
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=feature-finder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-finder.js","sourceRoot":"","sources":["../src/feature-finder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { FileResult } from '../types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Turns results into output.
|
|
4
|
+
*
|
|
5
|
+
* A formatter may print the output itself, or return it as a string and let
|
|
6
|
+
* the caller print it. Returning a string is usually easier to test.
|
|
7
|
+
*/
|
|
8
|
+
export type Formatter = (results: readonly FileResult[]) => void | string | Promise<void | string>;
|
|
9
|
+
/** The formats accepted by `--format` without having to be loaded. */
|
|
10
|
+
export declare const FORMATTERS: Record<string, Formatter>;
|
|
11
|
+
export declare const DEFAULT_FORMAT = "stylish";
|
|
12
|
+
/** The formatter for a built-in format name, or `undefined` for anything else. */
|
|
13
|
+
export declare function getFormatter(format: string | undefined): Formatter | undefined;
|
|
14
|
+
/**
|
|
15
|
+
* The formatter for a format name, a path, or a package.
|
|
16
|
+
*
|
|
17
|
+
* Anything that is not a built-in name is loaded as a module, resolved from
|
|
18
|
+
* `cwd` so that a formatter installed in the project is found and a relative
|
|
19
|
+
* path means what it looks like. The module may export the formatter as its
|
|
20
|
+
* default export, as `printResults`, or be the function itself.
|
|
21
|
+
*/
|
|
22
|
+
export declare function loadFormatter(format: string | undefined, cwd?: string): Promise<Formatter>;
|
|
23
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/formatters/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,aAAa,CAAC;AAO5C;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,CACtB,OAAO,EAAE,SAAS,UAAU,EAAE,KAC3B,IAAI,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,CAAC;AAE5C,sEAAsE;AACtE,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAQhD,CAAC;AAEF,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC,kFAAkF;AAClF,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAE9E;AAMD;;;;;;;GAOG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,GAAG,GAAE,MAAsB,GAC1B,OAAO,CAAC,SAAS,CAAC,CAwCpB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExtension) || function (path, preserveJsx) {
|
|
2
|
+
if (typeof path === "string" && /^\.\.?\//.test(path)) {
|
|
3
|
+
return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function (m, tsx, d, ext, cm) {
|
|
4
|
+
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : (d + ext + "." + cm.toLowerCase() + "js");
|
|
5
|
+
});
|
|
6
|
+
}
|
|
7
|
+
return path;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Output formats.
|
|
11
|
+
*/
|
|
12
|
+
import { createRequire } from 'node:module';
|
|
13
|
+
import path from 'node:path';
|
|
14
|
+
import { pathToFileURL } from 'node:url';
|
|
15
|
+
import { printResults as json } from './json.js';
|
|
16
|
+
import { printResults as junit } from './junit.js';
|
|
17
|
+
import { printResults as sarif } from './sarif.js';
|
|
18
|
+
import { printResults as stylish } from './stylish.js';
|
|
19
|
+
import { printResults as tap } from './tap.js';
|
|
20
|
+
/** The formats accepted by `--format` without having to be loaded. */
|
|
21
|
+
export const FORMATTERS = {
|
|
22
|
+
stylish,
|
|
23
|
+
json,
|
|
24
|
+
junit,
|
|
25
|
+
sarif,
|
|
26
|
+
tap,
|
|
27
|
+
// The name the JUnit report used to go by.
|
|
28
|
+
xunit: junit,
|
|
29
|
+
};
|
|
30
|
+
export const DEFAULT_FORMAT = 'stylish';
|
|
31
|
+
/** The formatter for a built-in format name, or `undefined` for anything else. */
|
|
32
|
+
export function getFormatter(format) {
|
|
33
|
+
return FORMATTERS[format ?? DEFAULT_FORMAT];
|
|
34
|
+
}
|
|
35
|
+
function asFormatter(candidate) {
|
|
36
|
+
return typeof candidate === 'function' ? candidate : undefined;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* The formatter for a format name, a path, or a package.
|
|
40
|
+
*
|
|
41
|
+
* Anything that is not a built-in name is loaded as a module, resolved from
|
|
42
|
+
* `cwd` so that a formatter installed in the project is found and a relative
|
|
43
|
+
* path means what it looks like. The module may export the formatter as its
|
|
44
|
+
* default export, as `printResults`, or be the function itself.
|
|
45
|
+
*/
|
|
46
|
+
export async function loadFormatter(format, cwd = process.cwd()) {
|
|
47
|
+
const builtIn = getFormatter(format);
|
|
48
|
+
if (builtIn !== undefined) {
|
|
49
|
+
return builtIn;
|
|
50
|
+
}
|
|
51
|
+
const specifier = format;
|
|
52
|
+
const from = path.join(path.resolve(cwd), 'noop.js');
|
|
53
|
+
let resolved;
|
|
54
|
+
if (specifier.startsWith('.') || path.isAbsolute(specifier)) {
|
|
55
|
+
resolved = path.resolve(cwd, specifier);
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
try {
|
|
59
|
+
resolved = createRequire(pathToFileURL(from)).resolve(specifier);
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
throw new Error(`Unsupported format "${specifier}". Use one of ${Object.keys(FORMATTERS).join(', ')}, ` +
|
|
63
|
+
'or the path to a formatter of your own.');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
let module;
|
|
67
|
+
try {
|
|
68
|
+
module = (await import(__rewriteRelativeImportExtension(pathToFileURL(resolved).href)));
|
|
69
|
+
}
|
|
70
|
+
catch (thrown) {
|
|
71
|
+
throw new Error(`Could not load the formatter "${specifier}": ${thrown instanceof Error ? thrown.message : String(thrown)}`);
|
|
72
|
+
}
|
|
73
|
+
const formatter = asFormatter(module['default']) ?? asFormatter(module['printResults']) ?? asFormatter(module);
|
|
74
|
+
if (formatter === undefined) {
|
|
75
|
+
throw new Error(`"${specifier}" does not export a formatter. A formatter module exports a function taking the results.`);
|
|
76
|
+
}
|
|
77
|
+
return formatter;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/formatters/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Machine readable output, in the shape eslint's JSON formatter uses.
|
|
3
|
+
*
|
|
4
|
+
* Matching eslint means the many tools already built around that shape -
|
|
5
|
+
* report viewers, annotation actions, dashboards - work without anyone
|
|
6
|
+
* writing a converter first.
|
|
7
|
+
*
|
|
8
|
+
* Results go to stdout so they can be redirected or piped. Anything that
|
|
9
|
+
* stops the linter running is written to stderr instead.
|
|
10
|
+
*/
|
|
11
|
+
import type { FileResult } from '../types.ts';
|
|
12
|
+
/** One finding, in eslint's shape. */
|
|
13
|
+
export interface JsonMessage {
|
|
14
|
+
ruleId: string;
|
|
15
|
+
severity: number;
|
|
16
|
+
message: string;
|
|
17
|
+
line: number;
|
|
18
|
+
column?: number;
|
|
19
|
+
}
|
|
20
|
+
/** One file, in eslint's shape. */
|
|
21
|
+
export interface JsonResult {
|
|
22
|
+
filePath: string;
|
|
23
|
+
messages: JsonMessage[];
|
|
24
|
+
errorCount: number;
|
|
25
|
+
warningCount: number;
|
|
26
|
+
}
|
|
27
|
+
/** Converts the results into eslint's JSON shape. */
|
|
28
|
+
export declare function toJson(results: readonly FileResult[]): JsonResult[];
|
|
29
|
+
/** Writes the results as a single line of JSON. */
|
|
30
|
+
export declare function printResults(results: readonly FileResult[]): void;
|
|
31
|
+
//# sourceMappingURL=json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/formatters/json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAC,UAAU,EAAY,MAAM,aAAa,CAAC;AAKvD,sCAAsC;AACtC,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,mCAAmC;AACnC,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAeD,qDAAqD;AACrD,wBAAgB,MAAM,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,UAAU,EAAE,CAUnE;AAED,mDAAmD;AACnD,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAEjE"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** eslint's numeric severities. */
|
|
2
|
+
const SEVERITY = { error: 2, warning: 1 };
|
|
3
|
+
function toMessage(error) {
|
|
4
|
+
const message = {
|
|
5
|
+
ruleId: error.rule,
|
|
6
|
+
severity: SEVERITY[error.severity ?? 'error'],
|
|
7
|
+
message: error.message,
|
|
8
|
+
line: error.line,
|
|
9
|
+
};
|
|
10
|
+
if (error.column !== undefined) {
|
|
11
|
+
message.column = error.column;
|
|
12
|
+
}
|
|
13
|
+
return message;
|
|
14
|
+
}
|
|
15
|
+
/** Converts the results into eslint's JSON shape. */
|
|
16
|
+
export function toJson(results) {
|
|
17
|
+
return results.map((result) => {
|
|
18
|
+
const messages = result.errors.map(toMessage);
|
|
19
|
+
return {
|
|
20
|
+
filePath: result.filePath,
|
|
21
|
+
messages,
|
|
22
|
+
errorCount: messages.filter((message) => message.severity === SEVERITY.error).length,
|
|
23
|
+
warningCount: messages.filter((message) => message.severity === SEVERITY.warning).length,
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
/** Writes the results as a single line of JSON. */
|
|
28
|
+
export function printResults(results) {
|
|
29
|
+
console.log(JSON.stringify(toJson(results)));
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/formatters/json.ts"],"names":[],"mappings":"AAYA,mCAAmC;AACnC,MAAM,QAAQ,GAAG,EAAC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAU,CAAC;AAmBjD,SAAS,SAAS,CAAC,KAAgB;IACjC,MAAM,OAAO,GAAgB;QAC3B,MAAM,EAAE,KAAK,CAAC,IAAI;QAClB,QAAQ,EAAE,QAAQ,CAAC,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC;QAC7C,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC;IACF,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC/B,OAAO,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAChC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,qDAAqD;AACrD,MAAM,UAAU,MAAM,CAAC,OAA8B;IACnD,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE;QAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC9C,OAAO;YACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,QAAQ;YACR,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,KAAK,CAAC,CAAC,MAAM;YACpF,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,KAAK,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM;SACzF,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,mDAAmD;AACnD,MAAM,UAAU,YAAY,CAAC,OAA8B;IACzD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JUnit XML, the report format CI servers such as Jenkins and TeamCity read.
|
|
3
|
+
*
|
|
4
|
+
* Each file becomes a test suite and each finding a test case, so a build
|
|
5
|
+
* shows one failing test per problem with its message and position, rather
|
|
6
|
+
* than one opaque failure per file. A file with nothing to report still
|
|
7
|
+
* contributes a passing test case, so the report says what was checked.
|
|
8
|
+
*
|
|
9
|
+
* A warning does not fail the run, so it is reported as a passing test case
|
|
10
|
+
* carrying its message, rather than as a failure the build would trip over.
|
|
11
|
+
*/
|
|
12
|
+
import type { FileResult } from '../types.ts';
|
|
13
|
+
/** Renders the results as a JUnit report. */
|
|
14
|
+
export declare function format(results: readonly FileResult[]): string;
|
|
15
|
+
/** Writes the JUnit report to stdout. */
|
|
16
|
+
export declare function printResults(results: readonly FileResult[]): void;
|
|
17
|
+
//# sourceMappingURL=junit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"junit.d.ts","sourceRoot":"","sources":["../../src/formatters/junit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAC,UAAU,EAAY,MAAM,aAAa,CAAC;AA4DvD,6CAA6C;AAC7C,wBAAgB,MAAM,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,CAe7D;AAED,yCAAyC;AACzC,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAEjE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { attributes, escapeXml, indent, XML_DECLARATION } from '../util/xml.js';
|
|
2
|
+
function severityOf(error) {
|
|
3
|
+
return error.severity ?? 'error';
|
|
4
|
+
}
|
|
5
|
+
/** `features/Login.feature` -> `features.Login`, for grouping in CI. */
|
|
6
|
+
function classNameFor(filePath) {
|
|
7
|
+
return filePath
|
|
8
|
+
.replace(/\.[^./\\]+$/, '')
|
|
9
|
+
.split(/[/\\]/)
|
|
10
|
+
.filter((part) => part !== '' && part !== '.')
|
|
11
|
+
.join('.');
|
|
12
|
+
}
|
|
13
|
+
function positionOf(error) {
|
|
14
|
+
return error.column === undefined ? `${error.line}` : `${error.line}:${error.column}`;
|
|
15
|
+
}
|
|
16
|
+
function testCase(result, error) {
|
|
17
|
+
const open = `<testcase${attributes({
|
|
18
|
+
name: `${error.rule} (${positionOf(error)})`,
|
|
19
|
+
classname: classNameFor(result.filePath),
|
|
20
|
+
})}>`;
|
|
21
|
+
const detail = escapeXml(`${result.filePath}:${positionOf(error)} (${error.rule}) ${error.message}`);
|
|
22
|
+
const body = severityOf(error) === 'warning'
|
|
23
|
+
? `<system-out>${detail}</system-out>`
|
|
24
|
+
: `<failure${attributes({ message: error.message, type: error.rule })}>${detail}</failure>`;
|
|
25
|
+
return `${open}\n${indent(body, 1)}\n</testcase>`;
|
|
26
|
+
}
|
|
27
|
+
function testSuite(result) {
|
|
28
|
+
const failures = result.errors.filter((error) => severityOf(error) === 'error').length;
|
|
29
|
+
const cases = result.errors.length > 0
|
|
30
|
+
? result.errors.map((error) => testCase(result, error))
|
|
31
|
+
: [
|
|
32
|
+
`<testcase${attributes({
|
|
33
|
+
name: result.filePath,
|
|
34
|
+
classname: classNameFor(result.filePath),
|
|
35
|
+
})}/>`,
|
|
36
|
+
];
|
|
37
|
+
const open = `<testsuite${attributes({
|
|
38
|
+
name: result.filePath,
|
|
39
|
+
tests: Math.max(result.errors.length, 1),
|
|
40
|
+
failures,
|
|
41
|
+
errors: 0,
|
|
42
|
+
skipped: 0,
|
|
43
|
+
})}>`;
|
|
44
|
+
return `${open}\n${indent(cases.join('\n'), 1)}\n</testsuite>`;
|
|
45
|
+
}
|
|
46
|
+
/** Renders the results as a JUnit report. */
|
|
47
|
+
export function format(results) {
|
|
48
|
+
const tests = results.reduce((total, result) => total + Math.max(result.errors.length, 1), 0);
|
|
49
|
+
const failures = results.reduce((total, result) => total + result.errors.filter((error) => severityOf(error) === 'error').length, 0);
|
|
50
|
+
const body = [
|
|
51
|
+
`<testsuites${attributes({ name: 'gurkencheck', tests, failures, errors: 0 })}>`,
|
|
52
|
+
...results.map((result) => indent(testSuite(result), 1)),
|
|
53
|
+
'</testsuites>',
|
|
54
|
+
].join('\n');
|
|
55
|
+
return `${XML_DECLARATION}\n${body}`;
|
|
56
|
+
}
|
|
57
|
+
/** Writes the JUnit report to stdout. */
|
|
58
|
+
export function printResults(results) {
|
|
59
|
+
console.log(format(results));
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=junit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"junit.js","sourceRoot":"","sources":["../../src/formatters/junit.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { FileResult } from '../types.ts';
|
|
2
|
+
/** Builds the SARIF log for a set of results. */
|
|
3
|
+
export declare function toSarif(results: readonly FileResult[], cwd?: string): unknown;
|
|
4
|
+
/** Writes the SARIF log to stdout. */
|
|
5
|
+
export declare function printResults(results: readonly FileResult[]): void;
|
|
6
|
+
//# sourceMappingURL=sarif.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sarif.d.ts","sourceRoot":"","sources":["../../src/formatters/sarif.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAC,UAAU,EAAY,MAAM,aAAa,CAAC;AAgDvD,iDAAiD;AACjD,wBAAgB,OAAO,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,EAAE,GAAG,GAAE,MAAsB,GAAG,OAAO,CA6B5F;AAED,sCAAsC;AACtC,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAEjE"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SARIF 2.1.0 output.
|
|
3
|
+
*
|
|
4
|
+
* SARIF is the format code scanning tools agree on, so a report in it can be
|
|
5
|
+
* uploaded to GitHub code scanning and shown inline on a pull request without
|
|
6
|
+
* anything in between.
|
|
7
|
+
*
|
|
8
|
+
* See https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html
|
|
9
|
+
*/
|
|
10
|
+
import path from 'node:path';
|
|
11
|
+
import { version } from '../version.js';
|
|
12
|
+
const SCHEMA = 'https://json.schemastore.org/sarif-2.1.0.json';
|
|
13
|
+
const SARIF_VERSION = '2.1.0';
|
|
14
|
+
const DOCUMENTATION = 'https://sebs.github.io/gurkencheck/';
|
|
15
|
+
/** SARIF's levels, which happen to line up with ours. */
|
|
16
|
+
const LEVEL = { error: 'error', warning: 'warning' };
|
|
17
|
+
function levelOf(error) {
|
|
18
|
+
return LEVEL[error.severity ?? 'error'];
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Paths relative to the working directory, with forward slashes.
|
|
22
|
+
*
|
|
23
|
+
* Code scanning matches a result to a file in the repository by this URI, so
|
|
24
|
+
* an absolute path from whichever machine ran the linter would match nothing.
|
|
25
|
+
*/
|
|
26
|
+
function uriFor(filePath, cwd) {
|
|
27
|
+
const relative = path.relative(cwd, filePath);
|
|
28
|
+
return relative.split(path.sep).join('/');
|
|
29
|
+
}
|
|
30
|
+
function toResult(result, error, cwd) {
|
|
31
|
+
const physicalLocation = {
|
|
32
|
+
artifactLocation: { uri: uriFor(result.filePath, cwd) },
|
|
33
|
+
};
|
|
34
|
+
// SARIF counts from 1, so a finding about a whole file carries no region
|
|
35
|
+
// rather than a line 0 that does not exist.
|
|
36
|
+
if (error.line > 0) {
|
|
37
|
+
const region = { startLine: error.line };
|
|
38
|
+
if (error.column !== undefined) {
|
|
39
|
+
region['startColumn'] = error.column;
|
|
40
|
+
}
|
|
41
|
+
physicalLocation['region'] = region;
|
|
42
|
+
}
|
|
43
|
+
return {
|
|
44
|
+
ruleId: error.rule,
|
|
45
|
+
level: levelOf(error),
|
|
46
|
+
message: { text: error.message },
|
|
47
|
+
locations: [{ physicalLocation }],
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/** Builds the SARIF log for a set of results. */
|
|
51
|
+
export function toSarif(results, cwd = process.cwd()) {
|
|
52
|
+
const findings = results.flatMap((result) => result.errors.map((error) => toResult(result, error, cwd)));
|
|
53
|
+
// Every rule that actually produced a finding, so the report explains what
|
|
54
|
+
// each id means and where to read about it.
|
|
55
|
+
const ruleIds = [...new Set(results.flatMap((r) => r.errors.map((error) => error.rule)))].sort();
|
|
56
|
+
return {
|
|
57
|
+
$schema: SCHEMA,
|
|
58
|
+
version: SARIF_VERSION,
|
|
59
|
+
runs: [
|
|
60
|
+
{
|
|
61
|
+
tool: {
|
|
62
|
+
driver: {
|
|
63
|
+
name: 'gurkencheck',
|
|
64
|
+
informationUri: DOCUMENTATION,
|
|
65
|
+
version: version(),
|
|
66
|
+
rules: ruleIds.map((id) => ({
|
|
67
|
+
id,
|
|
68
|
+
helpUri: `${DOCUMENTATION}rules/${id}.html`,
|
|
69
|
+
})),
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
results: findings,
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** Writes the SARIF log to stdout. */
|
|
78
|
+
export function printResults(results) {
|
|
79
|
+
console.log(JSON.stringify(toSarif(results), null, 2));
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=sarif.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sarif.js","sourceRoot":"","sources":["../../src/formatters/sarif.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { FileResult } from '../types.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Human readable output, one block per file with findings.
|
|
4
|
+
*
|
|
5
|
+
* Results go to stdout so they can be redirected or piped. Anything that
|
|
6
|
+
* stops the linter running is written to stderr instead.
|
|
7
|
+
*/
|
|
8
|
+
export declare function printResults(results: readonly FileResult[]): void;
|
|
9
|
+
//# sourceMappingURL=stylish.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stylish.d.ts","sourceRoot":"","sources":["../../src/formatters/stylish.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,UAAU,EAAY,MAAM,aAAa,CAAC;AAyDvD;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAiBjE"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { style } from '../logger.js';
|
|
2
|
+
/** `12:5` when the rule knows a column, `12` when it does not. */
|
|
3
|
+
function position(error) {
|
|
4
|
+
return error.column === undefined ? String(error.line) : `${error.line}:${error.column}`;
|
|
5
|
+
}
|
|
6
|
+
function severityOf(error) {
|
|
7
|
+
return error.severity ?? 'error';
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Formats one error as ` <position> <message> <rule>`, with the columns
|
|
11
|
+
* padded so they line up underneath each other.
|
|
12
|
+
*/
|
|
13
|
+
function formatError(error, lineWidth, messageWidth, colorize) {
|
|
14
|
+
const indent = ' ';
|
|
15
|
+
const gap = ' ';
|
|
16
|
+
const line = position(error).padEnd(lineWidth);
|
|
17
|
+
// "warning" is the longer of the two, so both line up at its width.
|
|
18
|
+
const severity = severityOf(error).padEnd('warning'.length);
|
|
19
|
+
return (indent +
|
|
20
|
+
(colorize ? style.gray(line) : line) +
|
|
21
|
+
gap +
|
|
22
|
+
(colorize ? style.severity(severityOf(error), severity) : severity) +
|
|
23
|
+
gap +
|
|
24
|
+
error.message.padEnd(messageWidth) +
|
|
25
|
+
gap +
|
|
26
|
+
(colorize ? style.gray(error.rule) : error.rule));
|
|
27
|
+
}
|
|
28
|
+
function widestLineNumber(result) {
|
|
29
|
+
return result.errors.reduce((widest, error) => Math.max(widest, position(error).length), 0);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The width to pad messages to. Messages that would push the line past the
|
|
33
|
+
* width of the terminal are left out of the calculation, so that one long
|
|
34
|
+
* message does not stretch every other line.
|
|
35
|
+
*/
|
|
36
|
+
function messageColumnWidth(result, lineWidth, consoleWidth) {
|
|
37
|
+
return result.errors.reduce((widest, error) => {
|
|
38
|
+
const unpaddedWidth = formatError(error, lineWidth, 0, false).length;
|
|
39
|
+
if (unpaddedWidth >= consoleWidth) {
|
|
40
|
+
return widest;
|
|
41
|
+
}
|
|
42
|
+
return Math.max(widest, error.message.length);
|
|
43
|
+
}, 0);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Human readable output, one block per file with findings.
|
|
47
|
+
*
|
|
48
|
+
* Results go to stdout so they can be redirected or piped. Anything that
|
|
49
|
+
* stops the linter running is written to stderr instead.
|
|
50
|
+
*/
|
|
51
|
+
export function printResults(results) {
|
|
52
|
+
const consoleWidth = process.stdout.isTTY ? process.stdout.columns : Infinity;
|
|
53
|
+
for (const result of results) {
|
|
54
|
+
if (result.errors.length === 0) {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
const lineWidth = widestLineNumber(result);
|
|
58
|
+
const messageWidth = messageColumnWidth(result, lineWidth, consoleWidth);
|
|
59
|
+
console.log(style.underline(result.filePath));
|
|
60
|
+
for (const error of result.errors) {
|
|
61
|
+
console.log(formatError(error, lineWidth, messageWidth, true));
|
|
62
|
+
}
|
|
63
|
+
console.log('\n');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=stylish.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stylish.js","sourceRoot":"","sources":["../../src/formatters/stylish.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TAP version 13 output.
|
|
3
|
+
*
|
|
4
|
+
* One test point per file, so a clean run still reports every file it looked
|
|
5
|
+
* at, which is what TAP consumers expect. Findings are carried in the YAML
|
|
6
|
+
* diagnostic block. A file is `not ok` only when it holds something that
|
|
7
|
+
* fails the run, so a file with warnings alone passes but still says why.
|
|
8
|
+
*/
|
|
9
|
+
import type { FileResult } from '../types.ts';
|
|
10
|
+
/** Renders the results as a TAP 13 stream. */
|
|
11
|
+
export declare function format(results: readonly FileResult[]): string;
|
|
12
|
+
/** Writes the TAP stream to stdout. */
|
|
13
|
+
export declare function printResults(results: readonly FileResult[]): void;
|
|
14
|
+
//# sourceMappingURL=tap.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tap.d.ts","sourceRoot":"","sources":["../../src/formatters/tap.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,EAAC,UAAU,EAAY,MAAM,aAAa,CAAC;AAqCvD,8CAA8C;AAC9C,wBAAgB,MAAM,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,MAAM,CAU7D;AAED,uCAAuC;AACvC,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,IAAI,CAEjE"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Quotes a scalar for YAML using single quotes, in which the only character
|
|
3
|
+
* needing attention is the quote itself.
|
|
4
|
+
*/
|
|
5
|
+
function quote(value) {
|
|
6
|
+
return `'${value.split("'").join("''")}'`;
|
|
7
|
+
}
|
|
8
|
+
function severityOf(error) {
|
|
9
|
+
return error.severity ?? 'error';
|
|
10
|
+
}
|
|
11
|
+
function fails(result) {
|
|
12
|
+
return result.errors.some((error) => severityOf(error) === 'error');
|
|
13
|
+
}
|
|
14
|
+
function diagnostics(result) {
|
|
15
|
+
if (result.errors.length === 0) {
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
const lines = [' ---', ' findings:'];
|
|
19
|
+
for (const error of result.errors) {
|
|
20
|
+
lines.push(` - severity: ${severityOf(error)}`);
|
|
21
|
+
lines.push(` message: ${quote(error.message)}`);
|
|
22
|
+
lines.push(` rule: ${quote(error.rule)}`);
|
|
23
|
+
lines.push(` line: ${error.line}`);
|
|
24
|
+
if (error.column !== undefined) {
|
|
25
|
+
lines.push(` column: ${error.column}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
lines.push(' ...');
|
|
29
|
+
return lines;
|
|
30
|
+
}
|
|
31
|
+
/** Renders the results as a TAP 13 stream. */
|
|
32
|
+
export function format(results) {
|
|
33
|
+
const lines = ['TAP version 13', `1..${results.length}`];
|
|
34
|
+
results.forEach((result, index) => {
|
|
35
|
+
const status = fails(result) ? 'not ok' : 'ok';
|
|
36
|
+
lines.push(`${status} ${index + 1} - ${result.filePath}`);
|
|
37
|
+
lines.push(...diagnostics(result));
|
|
38
|
+
});
|
|
39
|
+
return lines.join('\n');
|
|
40
|
+
}
|
|
41
|
+
/** Writes the TAP stream to stdout. */
|
|
42
|
+
export function printResults(results) {
|
|
43
|
+
console.log(format(results));
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=tap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tap.js","sourceRoot":"","sources":["../../src/formatters/tap.ts"],"names":[],"mappings":"AAUA;;;GAGG;AACH,SAAS,KAAK,CAAC,KAAa;IAC1B,OAAO,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC;AAC5C,CAAC;AAED,SAAS,UAAU,CAAC,KAAgB;IAClC,OAAO,KAAK,CAAC,QAAQ,IAAI,OAAO,CAAC;AACnC,CAAC;AAED,SAAS,KAAK,CAAC,MAAkB;IAC/B,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,OAAO,CAAC,CAAC;AACtE,CAAC;AAED,SAAS,WAAW,CAAC,MAAkB;IACrC,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,KAAK,GAAG,CAAC,OAAO,EAAE,aAAa,CAAC,CAAC;IACvC,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAClC,KAAK,CAAC,IAAI,CAAC,mBAAmB,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,kBAAkB,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACrD,KAAK,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,eAAe,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACxC,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC/B,KAAK,CAAC,IAAI,CAAC,iBAAiB,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACpB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,MAAM,CAAC,OAA8B;IACnD,MAAM,KAAK,GAAG,CAAC,gBAAgB,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAEzD,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QAChC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,KAAK,GAAG,CAAC,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;QAC1D,KAAK,CAAC,IAAI,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,uCAAuC;AACvC,MAAM,UAAU,YAAY,CAAC,OAA8B;IACzD,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;AAC/B,CAAC"}
|