gurkencheck 0.0.9 → 0.1.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 +30 -11
- package/dist/config-parser.d.ts +15 -1
- package/dist/config-parser.js +58 -12
- package/dist/config-verifier.d.ts +0 -1
- package/dist/config-verifier.js +71 -3
- package/dist/diagnostics.d.ts +0 -1
- package/dist/diagnostics.js +0 -1
- package/dist/exit-codes.d.ts +0 -1
- package/dist/exit-codes.js +0 -1
- package/dist/feature-finder.d.ts +0 -1
- package/dist/feature-finder.js +29 -11
- package/dist/formatters/index.d.ts +0 -1
- package/dist/formatters/index.js +2 -3
- package/dist/formatters/json.d.ts +0 -1
- package/dist/formatters/json.js +0 -1
- package/dist/formatters/junit.d.ts +1 -13
- package/dist/formatters/junit.js +36 -11
- package/dist/formatters/sarif.d.ts +0 -1
- package/dist/formatters/sarif.js +25 -7
- package/dist/formatters/stylish.d.ts +0 -1
- package/dist/formatters/stylish.js +0 -1
- package/dist/formatters/tap.d.ts +0 -1
- package/dist/formatters/tap.js +37 -5
- package/dist/gherkin/dialects.d.ts +0 -1
- package/dist/gherkin/dialects.js +0 -1
- package/dist/gherkin/keywords.d.ts +6 -3
- package/dist/gherkin/keywords.js +10 -4
- package/dist/gherkin/parse.d.ts +0 -1
- package/dist/gherkin/parse.js +19 -7
- package/dist/gherkin/traverse.d.ts +0 -1
- package/dist/gherkin/traverse.js +0 -1
- package/dist/gherkin/variables.d.ts +12 -1
- package/dist/gherkin/variables.js +24 -6
- package/dist/index.d.ts +1 -2
- package/dist/index.js +1 -2
- package/dist/linter.d.ts +0 -1
- package/dist/linter.js +1 -2
- package/dist/logger.d.ts +0 -1
- package/dist/logger.js +0 -1
- package/dist/main.d.ts +0 -1
- package/dist/main.js +78 -27
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +0 -5
- package/dist/rules/allowed-tags.d.ts +0 -1
- package/dist/rules/allowed-tags.js +2 -1
- package/dist/rules/background-setup-only.d.ts +0 -1
- package/dist/rules/background-setup-only.js +0 -1
- package/dist/rules/file-name.d.ts +0 -1
- package/dist/rules/file-name.js +10 -1
- package/dist/rules/indentation.d.ts +0 -1
- package/dist/rules/indentation.js +24 -10
- package/dist/rules/index.d.ts +0 -1
- package/dist/rules/index.js +0 -1
- package/dist/rules/keywords-in-logical-order.d.ts +0 -1
- package/dist/rules/keywords-in-logical-order.js +0 -1
- package/dist/rules/max-scenarios-per-file.d.ts +0 -1
- package/dist/rules/max-scenarios-per-file.js +0 -1
- package/dist/rules/name-length.d.ts +0 -1
- package/dist/rules/name-length.js +5 -3
- package/dist/rules/new-line-at-eof.d.ts +0 -1
- package/dist/rules/new-line-at-eof.js +10 -2
- package/dist/rules/no-background-only-scenario.d.ts +0 -1
- package/dist/rules/no-background-only-scenario.js +0 -1
- package/dist/rules/no-dupe-feature-names.d.ts +0 -1
- package/dist/rules/no-dupe-feature-names.js +5 -1
- package/dist/rules/no-dupe-file-names.d.ts +0 -1
- package/dist/rules/no-dupe-file-names.js +0 -1
- package/dist/rules/no-dupe-scenario-names.d.ts +0 -1
- package/dist/rules/no-dupe-scenario-names.js +4 -1
- package/dist/rules/no-duplicate-tags.d.ts +0 -1
- package/dist/rules/no-duplicate-tags.js +0 -1
- package/dist/rules/no-empty-background.d.ts +0 -1
- package/dist/rules/no-empty-background.js +0 -1
- package/dist/rules/no-empty-file.d.ts +0 -1
- package/dist/rules/no-empty-file.js +0 -1
- package/dist/rules/no-examples-in-scenarios.d.ts +0 -1
- package/dist/rules/no-examples-in-scenarios.js +0 -1
- package/dist/rules/no-files-without-scenarios.d.ts +0 -1
- package/dist/rules/no-files-without-scenarios.js +0 -1
- package/dist/rules/no-homogenous-tags.d.ts +0 -1
- package/dist/rules/no-homogenous-tags.js +0 -1
- package/dist/rules/no-multiple-empty-lines.d.ts +0 -1
- package/dist/rules/no-multiple-empty-lines.js +2 -3
- package/dist/rules/no-partially-commented-tag-lines.d.ts +0 -1
- package/dist/rules/no-partially-commented-tag-lines.js +7 -5
- package/dist/rules/no-restricted-patterns.d.ts +0 -1
- package/dist/rules/no-restricted-patterns.js +64 -19
- package/dist/rules/no-restricted-tags.d.ts +0 -1
- package/dist/rules/no-restricted-tags.js +2 -1
- package/dist/rules/no-scenario-outlines-without-examples.d.ts +0 -1
- package/dist/rules/no-scenario-outlines-without-examples.js +0 -1
- package/dist/rules/no-scenarios-without-then.d.ts +0 -1
- package/dist/rules/no-scenarios-without-then.js +0 -1
- package/dist/rules/no-scenarios-without-when.d.ts +0 -1
- package/dist/rules/no-scenarios-without-when.js +0 -1
- package/dist/rules/no-superfluous-tags.d.ts +0 -1
- package/dist/rules/no-superfluous-tags.js +0 -1
- package/dist/rules/no-trailing-spaces.d.ts +0 -1
- package/dist/rules/no-trailing-spaces.js +13 -4
- package/dist/rules/no-undeclared-variables.d.ts +0 -1
- package/dist/rules/no-undeclared-variables.js +12 -11
- package/dist/rules/no-unnamed-features.d.ts +0 -1
- package/dist/rules/no-unnamed-features.js +0 -1
- package/dist/rules/no-unnamed-scenarios.d.ts +0 -1
- package/dist/rules/no-unnamed-scenarios.js +0 -1
- package/dist/rules/no-unused-variables.d.ts +0 -1
- package/dist/rules/no-unused-variables.js +0 -1
- package/dist/rules/one-space-between-tags.d.ts +0 -1
- package/dist/rules/one-space-between-tags.js +3 -2
- package/dist/rules/only-one-when.d.ts +0 -1
- package/dist/rules/only-one-when.js +5 -5
- package/dist/rules/required-tags.d.ts +0 -1
- package/dist/rules/required-tags.js +13 -3
- package/dist/rules/scenario-size.d.ts +0 -1
- package/dist/rules/scenario-size.js +0 -1
- package/dist/rules/use-and.d.ts +0 -1
- package/dist/rules/use-and.js +2 -2
- package/dist/rules.d.ts +0 -1
- package/dist/rules.js +49 -4
- package/dist/stats/collect.d.ts +0 -1
- package/dist/stats/collect.js +0 -1
- package/dist/stats/command.d.ts +0 -1
- package/dist/stats/command.js +24 -7
- package/dist/stats/format/index.d.ts +0 -1
- package/dist/stats/format/index.js +0 -1
- package/dist/stats/format/json.d.ts +0 -1
- package/dist/stats/format/json.js +0 -1
- package/dist/stats/format/markdown.d.ts +0 -1
- package/dist/stats/format/markdown.js +24 -6
- package/dist/stats/format/shared.d.ts +0 -1
- package/dist/stats/format/shared.js +0 -1
- package/dist/stats/format/text.d.ts +0 -1
- package/dist/stats/format/text.js +0 -1
- package/dist/stats/index.d.ts +0 -1
- package/dist/stats/index.js +0 -1
- package/dist/stats/normalise.d.ts +0 -1
- package/dist/stats/normalise.js +27 -14
- package/dist/stats/similar.d.ts +0 -1
- package/dist/stats/similar.js +0 -1
- package/dist/stats/types.d.ts +0 -1
- package/dist/stats/types.js +0 -1
- package/dist/suppressions.d.ts +6 -3
- package/dist/suppressions.js +36 -30
- package/dist/types.d.ts +7 -1
- package/dist/types.js +0 -1
- package/dist/util/case.d.ts +2 -2
- package/dist/util/case.js +17 -3
- package/dist/util/collections.d.ts +0 -1
- package/dist/util/collections.js +0 -1
- package/dist/util/glob.d.ts +9 -3
- package/dist/util/glob.js +115 -27
- package/dist/util/json.d.ts +0 -1
- package/dist/util/json.js +0 -1
- package/dist/util/lines.d.ts +6 -4
- package/dist/util/lines.js +22 -4
- package/dist/util/location.d.ts +8 -1
- package/dist/util/location.js +10 -1
- package/dist/util/patterns.d.ts +9 -0
- package/dist/util/patterns.js +21 -0
- package/dist/util/resolve.d.ts +6 -0
- package/dist/util/resolve.js +101 -0
- package/dist/util/stream.d.ts +0 -1
- package/dist/util/stream.js +3 -2
- package/dist/util/xml.d.ts +0 -1
- package/dist/util/xml.js +17 -3
- package/dist/version.d.ts +0 -1
- package/dist/version.js +0 -1
- package/dist/watch.d.ts +11 -1
- package/dist/watch.js +38 -3
- package/package.json +6 -2
- package/dist/config-parser.d.ts.map +0 -1
- package/dist/config-parser.js.map +0 -1
- package/dist/config-verifier.d.ts.map +0 -1
- package/dist/config-verifier.js.map +0 -1
- package/dist/diagnostics.d.ts.map +0 -1
- package/dist/diagnostics.js.map +0 -1
- package/dist/exit-codes.d.ts.map +0 -1
- package/dist/exit-codes.js.map +0 -1
- package/dist/feature-finder.d.ts.map +0 -1
- package/dist/feature-finder.js.map +0 -1
- package/dist/formatters/index.d.ts.map +0 -1
- package/dist/formatters/index.js.map +0 -1
- package/dist/formatters/json.d.ts.map +0 -1
- package/dist/formatters/json.js.map +0 -1
- package/dist/formatters/junit.d.ts.map +0 -1
- package/dist/formatters/junit.js.map +0 -1
- package/dist/formatters/sarif.d.ts.map +0 -1
- package/dist/formatters/sarif.js.map +0 -1
- package/dist/formatters/stylish.d.ts.map +0 -1
- package/dist/formatters/stylish.js.map +0 -1
- package/dist/formatters/tap.d.ts.map +0 -1
- package/dist/formatters/tap.js.map +0 -1
- package/dist/gherkin/dialects.d.ts.map +0 -1
- package/dist/gherkin/dialects.js.map +0 -1
- package/dist/gherkin/keywords.d.ts.map +0 -1
- package/dist/gherkin/keywords.js.map +0 -1
- package/dist/gherkin/parse.d.ts.map +0 -1
- package/dist/gherkin/parse.js.map +0 -1
- package/dist/gherkin/traverse.d.ts.map +0 -1
- package/dist/gherkin/traverse.js.map +0 -1
- package/dist/gherkin/variables.d.ts.map +0 -1
- package/dist/gherkin/variables.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/linter.d.ts.map +0 -1
- package/dist/linter.js.map +0 -1
- package/dist/logger.d.ts.map +0 -1
- package/dist/logger.js.map +0 -1
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/presets.d.ts.map +0 -1
- package/dist/presets.js.map +0 -1
- package/dist/rules/allowed-tags.d.ts.map +0 -1
- package/dist/rules/allowed-tags.js.map +0 -1
- package/dist/rules/background-setup-only.d.ts.map +0 -1
- package/dist/rules/background-setup-only.js.map +0 -1
- package/dist/rules/file-name.d.ts.map +0 -1
- package/dist/rules/file-name.js.map +0 -1
- package/dist/rules/indentation.d.ts.map +0 -1
- package/dist/rules/indentation.js.map +0 -1
- package/dist/rules/index.d.ts.map +0 -1
- package/dist/rules/index.js.map +0 -1
- package/dist/rules/keywords-in-logical-order.d.ts.map +0 -1
- package/dist/rules/keywords-in-logical-order.js.map +0 -1
- package/dist/rules/max-scenarios-per-file.d.ts.map +0 -1
- package/dist/rules/max-scenarios-per-file.js.map +0 -1
- package/dist/rules/name-length.d.ts.map +0 -1
- package/dist/rules/name-length.js.map +0 -1
- package/dist/rules/new-line-at-eof.d.ts.map +0 -1
- package/dist/rules/new-line-at-eof.js.map +0 -1
- package/dist/rules/no-background-only-scenario.d.ts.map +0 -1
- package/dist/rules/no-background-only-scenario.js.map +0 -1
- package/dist/rules/no-dupe-feature-names.d.ts.map +0 -1
- package/dist/rules/no-dupe-feature-names.js.map +0 -1
- package/dist/rules/no-dupe-file-names.d.ts.map +0 -1
- package/dist/rules/no-dupe-file-names.js.map +0 -1
- package/dist/rules/no-dupe-scenario-names.d.ts.map +0 -1
- package/dist/rules/no-dupe-scenario-names.js.map +0 -1
- package/dist/rules/no-duplicate-tags.d.ts.map +0 -1
- package/dist/rules/no-duplicate-tags.js.map +0 -1
- package/dist/rules/no-empty-background.d.ts.map +0 -1
- package/dist/rules/no-empty-background.js.map +0 -1
- package/dist/rules/no-empty-file.d.ts.map +0 -1
- package/dist/rules/no-empty-file.js.map +0 -1
- package/dist/rules/no-examples-in-scenarios.d.ts.map +0 -1
- package/dist/rules/no-examples-in-scenarios.js.map +0 -1
- package/dist/rules/no-files-without-scenarios.d.ts.map +0 -1
- package/dist/rules/no-files-without-scenarios.js.map +0 -1
- package/dist/rules/no-homogenous-tags.d.ts.map +0 -1
- package/dist/rules/no-homogenous-tags.js.map +0 -1
- package/dist/rules/no-multiple-empty-lines.d.ts.map +0 -1
- package/dist/rules/no-multiple-empty-lines.js.map +0 -1
- package/dist/rules/no-partially-commented-tag-lines.d.ts.map +0 -1
- package/dist/rules/no-partially-commented-tag-lines.js.map +0 -1
- package/dist/rules/no-restricted-patterns.d.ts.map +0 -1
- package/dist/rules/no-restricted-patterns.js.map +0 -1
- package/dist/rules/no-restricted-tags.d.ts.map +0 -1
- package/dist/rules/no-restricted-tags.js.map +0 -1
- package/dist/rules/no-scenario-outlines-without-examples.d.ts.map +0 -1
- package/dist/rules/no-scenario-outlines-without-examples.js.map +0 -1
- package/dist/rules/no-scenarios-without-then.d.ts.map +0 -1
- package/dist/rules/no-scenarios-without-then.js.map +0 -1
- package/dist/rules/no-scenarios-without-when.d.ts.map +0 -1
- package/dist/rules/no-scenarios-without-when.js.map +0 -1
- package/dist/rules/no-superfluous-tags.d.ts.map +0 -1
- package/dist/rules/no-superfluous-tags.js.map +0 -1
- package/dist/rules/no-trailing-spaces.d.ts.map +0 -1
- package/dist/rules/no-trailing-spaces.js.map +0 -1
- package/dist/rules/no-undeclared-variables.d.ts.map +0 -1
- package/dist/rules/no-undeclared-variables.js.map +0 -1
- package/dist/rules/no-unnamed-features.d.ts.map +0 -1
- package/dist/rules/no-unnamed-features.js.map +0 -1
- package/dist/rules/no-unnamed-scenarios.d.ts.map +0 -1
- package/dist/rules/no-unnamed-scenarios.js.map +0 -1
- package/dist/rules/no-unused-variables.d.ts.map +0 -1
- package/dist/rules/no-unused-variables.js.map +0 -1
- package/dist/rules/one-space-between-tags.d.ts.map +0 -1
- package/dist/rules/one-space-between-tags.js.map +0 -1
- package/dist/rules/only-one-when.d.ts.map +0 -1
- package/dist/rules/only-one-when.js.map +0 -1
- package/dist/rules/required-tags.d.ts.map +0 -1
- package/dist/rules/required-tags.js.map +0 -1
- package/dist/rules/scenario-size.d.ts.map +0 -1
- package/dist/rules/scenario-size.js.map +0 -1
- package/dist/rules/use-and.d.ts.map +0 -1
- package/dist/rules/use-and.js.map +0 -1
- package/dist/rules.d.ts.map +0 -1
- package/dist/rules.js.map +0 -1
- package/dist/stats/collect.d.ts.map +0 -1
- package/dist/stats/collect.js.map +0 -1
- package/dist/stats/command.d.ts.map +0 -1
- package/dist/stats/command.js.map +0 -1
- package/dist/stats/format/index.d.ts.map +0 -1
- package/dist/stats/format/index.js.map +0 -1
- package/dist/stats/format/json.d.ts.map +0 -1
- package/dist/stats/format/json.js.map +0 -1
- package/dist/stats/format/markdown.d.ts.map +0 -1
- package/dist/stats/format/markdown.js.map +0 -1
- package/dist/stats/format/shared.d.ts.map +0 -1
- package/dist/stats/format/shared.js.map +0 -1
- package/dist/stats/format/text.d.ts.map +0 -1
- package/dist/stats/format/text.js.map +0 -1
- package/dist/stats/index.d.ts.map +0 -1
- package/dist/stats/index.js.map +0 -1
- package/dist/stats/normalise.d.ts.map +0 -1
- package/dist/stats/normalise.js.map +0 -1
- package/dist/stats/similar.d.ts.map +0 -1
- package/dist/stats/similar.js.map +0 -1
- package/dist/stats/types.d.ts.map +0 -1
- package/dist/stats/types.js.map +0 -1
- package/dist/suppressions.d.ts.map +0 -1
- package/dist/suppressions.js.map +0 -1
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js.map +0 -1
- package/dist/util/case.d.ts.map +0 -1
- package/dist/util/case.js.map +0 -1
- package/dist/util/collections.d.ts.map +0 -1
- package/dist/util/collections.js.map +0 -1
- package/dist/util/glob.d.ts.map +0 -1
- package/dist/util/glob.js.map +0 -1
- package/dist/util/json.d.ts.map +0 -1
- package/dist/util/json.js.map +0 -1
- package/dist/util/lines.d.ts.map +0 -1
- package/dist/util/lines.js.map +0 -1
- package/dist/util/location.d.ts.map +0 -1
- package/dist/util/location.js.map +0 -1
- package/dist/util/stream.d.ts.map +0 -1
- package/dist/util/stream.js.map +0 -1
- package/dist/util/xml.d.ts.map +0 -1
- package/dist/util/xml.js.map +0 -1
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js.map +0 -1
- package/dist/watch.d.ts.map +0 -1
- package/dist/watch.js.map +0 -1
package/dist/presets.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
export const RECOMMENDED = {
|
|
2
|
-
'new-line-at-eof': ['on', 'yes'],
|
|
3
2
|
'no-dupe-feature-names': 'on',
|
|
4
3
|
'no-dupe-scenario-names': 'on',
|
|
5
4
|
'no-duplicate-tags': 'on',
|
|
@@ -7,18 +6,14 @@ export const RECOMMENDED = {
|
|
|
7
6
|
'no-empty-file': 'on',
|
|
8
7
|
'no-examples-in-scenarios': 'on',
|
|
9
8
|
'no-files-without-scenarios': 'on',
|
|
10
|
-
'no-multiple-empty-lines': 'on',
|
|
11
9
|
'no-partially-commented-tag-lines': 'on',
|
|
12
10
|
'no-scenario-outlines-without-examples': 'on',
|
|
13
|
-
'no-trailing-spaces': 'on',
|
|
14
11
|
'no-undeclared-variables': 'on',
|
|
15
12
|
'no-unnamed-features': 'on',
|
|
16
13
|
'no-unnamed-scenarios': 'on',
|
|
17
14
|
'no-unused-variables': 'on',
|
|
18
|
-
'one-space-between-tags': 'on',
|
|
19
15
|
};
|
|
20
16
|
/** The presets that can be named in a configuration file. */
|
|
21
17
|
export const PRESETS = {
|
|
22
18
|
'gurkencheck:recommended': RECOMMENDED,
|
|
23
19
|
};
|
|
24
|
-
//# sourceMappingURL=presets.js.map
|
|
@@ -2,11 +2,13 @@ import { getNodeType } from '../gherkin/keywords.js';
|
|
|
2
2
|
import { taggedNodesOf } from '../gherkin/traverse.js';
|
|
3
3
|
import { mergeDefaults } from '../util/collections.js';
|
|
4
4
|
import { at } from '../util/location.js';
|
|
5
|
+
import { invalidPatterns } from '../util/patterns.js';
|
|
5
6
|
const name = 'allowed-tags';
|
|
6
7
|
const availableConfigs = { tags: [], patterns: [] };
|
|
7
8
|
const rule = {
|
|
8
9
|
name,
|
|
9
10
|
availableConfigs,
|
|
11
|
+
verifySettings: (settings) => invalidPatterns('patterns', settings['patterns']),
|
|
10
12
|
run(feature, _file, configuration) {
|
|
11
13
|
if (feature === undefined) {
|
|
12
14
|
return [];
|
|
@@ -31,4 +33,3 @@ const rule = {
|
|
|
31
33
|
},
|
|
32
34
|
};
|
|
33
35
|
export default rule;
|
|
34
|
-
//# sourceMappingURL=allowed-tags.js.map
|
package/dist/rules/file-name.js
CHANGED
|
@@ -16,6 +16,16 @@ const availableConfigs = {
|
|
|
16
16
|
const rule = {
|
|
17
17
|
name,
|
|
18
18
|
availableConfigs,
|
|
19
|
+
verifySettings(settings) {
|
|
20
|
+
const style = settings['style'];
|
|
21
|
+
return style === undefined || Object.hasOwn(STYLES, style)
|
|
22
|
+
? []
|
|
23
|
+
: [
|
|
24
|
+
`"style" should be one of ${Object.keys(STYLES)
|
|
25
|
+
.map((known) => `"${known}"`)
|
|
26
|
+
.join(', ')}, not ${JSON.stringify(style)}`,
|
|
27
|
+
];
|
|
28
|
+
},
|
|
19
29
|
run(_feature, file, configuration) {
|
|
20
30
|
const { style } = mergeDefaults(availableConfigs, configuration);
|
|
21
31
|
const convert = STYLES[style];
|
|
@@ -38,4 +48,3 @@ const rule = {
|
|
|
38
48
|
},
|
|
39
49
|
};
|
|
40
50
|
export default rule;
|
|
41
|
-
//# sourceMappingURL=file-name.js.map
|
|
@@ -29,7 +29,9 @@ const availableConfigs = {
|
|
|
29
29
|
'feature tag': -1,
|
|
30
30
|
'rule tag': -1,
|
|
31
31
|
'scenario tag': -1,
|
|
32
|
+
'examples tag': -1,
|
|
32
33
|
docstring: -1,
|
|
34
|
+
datatable: -1,
|
|
33
35
|
/** One of "any", "space" or "tab". */
|
|
34
36
|
character: 'any',
|
|
35
37
|
};
|
|
@@ -43,12 +45,15 @@ function resolveConfig(configuration) {
|
|
|
43
45
|
typeof configuration['scenario tag'] === 'number'
|
|
44
46
|
? configuration['scenario tag']
|
|
45
47
|
: merged.Scenario;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
merged['examples tag'] =
|
|
49
|
+
typeof configuration['examples tag'] === 'number'
|
|
50
|
+
? configuration['examples tag']
|
|
51
|
+
: merged.Examples;
|
|
52
|
+
// A doc string or a data table belongs to its step and is conventionally
|
|
53
|
+
// indented one level further in, so unless it is set on its own it follows
|
|
54
|
+
// the step it belongs to; -1 stands for that here.
|
|
55
|
+
merged.docstring = typeof configuration['docstring'] === 'number' ? configuration['docstring'] : -1;
|
|
56
|
+
merged.datatable = typeof configuration['datatable'] === 'number' ? configuration['datatable'] : -1;
|
|
52
57
|
merged.character =
|
|
53
58
|
configuration['character'] === 'space' || configuration['character'] === 'tab'
|
|
54
59
|
? configuration['character']
|
|
@@ -58,6 +63,12 @@ function resolveConfig(configuration) {
|
|
|
58
63
|
const rule = {
|
|
59
64
|
name,
|
|
60
65
|
availableConfigs,
|
|
66
|
+
verifySettings(settings) {
|
|
67
|
+
const character = settings['character'];
|
|
68
|
+
return character === undefined || ['any', 'space', 'tab'].includes(character)
|
|
69
|
+
? []
|
|
70
|
+
: [`"character" should be "any", "space" or "tab", not ${JSON.stringify(character)}`];
|
|
71
|
+
},
|
|
61
72
|
run(feature, file, configuration) {
|
|
62
73
|
if (feature === undefined) {
|
|
63
74
|
return [];
|
|
@@ -82,11 +93,10 @@ const rule = {
|
|
|
82
93
|
});
|
|
83
94
|
}
|
|
84
95
|
};
|
|
85
|
-
const test = (location, type) => {
|
|
96
|
+
const test = (location, type, expected = config[type]) => {
|
|
86
97
|
testCharacter(location, type);
|
|
87
98
|
// Columns are 1-based, indentation is counted from 0.
|
|
88
99
|
const actual = (location.column ?? 1) - 1;
|
|
89
|
-
const expected = config[type];
|
|
90
100
|
if (actual !== expected) {
|
|
91
101
|
errors.push({
|
|
92
102
|
message: `Wrong indentation for "${type}", expected indentation level of ${expected}, but got ${actual}`,
|
|
@@ -100,8 +110,12 @@ const rule = {
|
|
|
100
110
|
// A step only uses its own keyword's setting when the user set one.
|
|
101
111
|
const type = keyword !== '' && keyword in raw ? keyword : 'Step';
|
|
102
112
|
test(step.location, type);
|
|
113
|
+
const underStep = config[type] + 2;
|
|
103
114
|
if (step.docString !== undefined) {
|
|
104
|
-
test(step.docString.location, 'docstring');
|
|
115
|
+
test(step.docString.location, 'docstring', config.docstring === -1 ? underStep : config.docstring);
|
|
116
|
+
}
|
|
117
|
+
for (const row of step.dataTable?.rows ?? []) {
|
|
118
|
+
test(row.location, 'datatable', config.datatable === -1 ? underStep : config.datatable);
|
|
105
119
|
}
|
|
106
120
|
};
|
|
107
121
|
const testTags = (tags, type) => {
|
|
@@ -125,6 +139,7 @@ const rule = {
|
|
|
125
139
|
child.scenario.steps.forEach(testStep);
|
|
126
140
|
for (const examples of child.scenario.examples) {
|
|
127
141
|
test(examples.location, 'Examples');
|
|
142
|
+
testTags(examples.tags, 'examples tag');
|
|
128
143
|
if (examples.tableHeader !== undefined) {
|
|
129
144
|
test(examples.tableHeader.location, 'example');
|
|
130
145
|
for (const row of examples.tableBody) {
|
|
@@ -150,4 +165,3 @@ const rule = {
|
|
|
150
165
|
},
|
|
151
166
|
};
|
|
152
167
|
export default rule;
|
|
153
|
-
//# sourceMappingURL=indentation.js.map
|
package/dist/rules/index.d.ts
CHANGED
package/dist/rules/index.js
CHANGED
|
@@ -20,11 +20,14 @@ const rule = {
|
|
|
20
20
|
const errors = [];
|
|
21
21
|
const test = (text, location, type) => {
|
|
22
22
|
const maximum = config[type];
|
|
23
|
+
// Characters, not the UTF-16 units .length counts: an emoji is one
|
|
24
|
+
// character to the person reading the name, not two.
|
|
25
|
+
const length = [...text].length;
|
|
23
26
|
// A limit of 0 turns the check off for that kind of name, for teams that
|
|
24
27
|
// want a limit on scenario names but not on step text, or the reverse.
|
|
25
|
-
if (maximum > 0 && text !== '' &&
|
|
28
|
+
if (maximum > 0 && text !== '' && length > maximum) {
|
|
26
29
|
errors.push({
|
|
27
|
-
message: `${type} name is too long. Length of ${
|
|
30
|
+
message: `${type} name is too long. Length of ${length} is longer than the maximum allowed: ${maximum}`,
|
|
28
31
|
rule: name,
|
|
29
32
|
...at(location),
|
|
30
33
|
});
|
|
@@ -47,4 +50,3 @@ const rule = {
|
|
|
47
50
|
},
|
|
48
51
|
};
|
|
49
52
|
export default rule;
|
|
50
|
-
//# sourceMappingURL=name-length.js.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { contentLines } from '../util/lines.js';
|
|
1
2
|
const name = 'new-line-at-eof';
|
|
2
3
|
/** Whether a trailing new line is required (`yes`) or forbidden (`no`). */
|
|
3
4
|
const availableConfigs = ['yes', 'no'];
|
|
@@ -10,6 +11,12 @@ const rule = {
|
|
|
10
11
|
availableConfigs,
|
|
11
12
|
run(_feature, file, configuration) {
|
|
12
13
|
const setting = toSetting(configuration);
|
|
14
|
+
// An empty file has no line for a new line to end, so there is nothing to
|
|
15
|
+
// require or forbid. Splitting it gives a single empty entry, which would
|
|
16
|
+
// otherwise read as a new line at the end.
|
|
17
|
+
if (file.lines.length === 1 && file.lines[0] === '') {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
13
20
|
// Splitting on line breaks leaves a trailing empty entry when the file
|
|
14
21
|
// ends with one.
|
|
15
22
|
const hasNewLineAtEof = file.lines.at(-1) === '';
|
|
@@ -23,8 +30,9 @@ const rule = {
|
|
|
23
30
|
if (message === '') {
|
|
24
31
|
return [];
|
|
25
32
|
}
|
|
26
|
-
|
|
33
|
+
// The last line of the file: the one the new line ends, or the one
|
|
34
|
+
// missing it. contentLines leaves out the empty entry after a new line.
|
|
35
|
+
return [{ message, rule: name, line: contentLines(file).length }];
|
|
27
36
|
},
|
|
28
37
|
};
|
|
29
38
|
export default rule;
|
|
30
|
-
//# sourceMappingURL=new-line-at-eof.js.map
|
|
@@ -6,6 +6,11 @@ const rule = {
|
|
|
6
6
|
if (feature === undefined) {
|
|
7
7
|
return [];
|
|
8
8
|
}
|
|
9
|
+
// A feature with no name is no-unnamed-features' finding, not a clash
|
|
10
|
+
// between every file that forgot one.
|
|
11
|
+
if (feature.name.trim() === '') {
|
|
12
|
+
return [];
|
|
13
|
+
}
|
|
9
14
|
const seen = context.state(() => new Map());
|
|
10
15
|
const sightings = seen.get(feature.name) ?? [];
|
|
11
16
|
sightings.push({ filePath: file.relativePath, at: at(feature.location) });
|
|
@@ -35,4 +40,3 @@ const rule = {
|
|
|
35
40
|
},
|
|
36
41
|
};
|
|
37
42
|
export default rule;
|
|
38
|
-
//# sourceMappingURL=no-dupe-feature-names.js.map
|
|
@@ -13,6 +13,10 @@ const rule = {
|
|
|
13
13
|
const seen = context.state(() => new Map());
|
|
14
14
|
const withinOneFile = configuration === 'in-feature';
|
|
15
15
|
for (const { scenario } of scenariosOf(feature)) {
|
|
16
|
+
// A scenario with no name is no-unnamed-scenarios' finding, not a clash.
|
|
17
|
+
if (scenario.name.trim() === '') {
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
16
20
|
// Told to look within each file, a name only clashes with the same name
|
|
17
21
|
// in the same file - so which file it is in is part of what makes a
|
|
18
22
|
// name that name. A newline cannot appear in either half, so the two
|
|
@@ -50,4 +54,3 @@ const rule = {
|
|
|
50
54
|
},
|
|
51
55
|
};
|
|
52
56
|
export default rule;
|
|
53
|
-
//# sourceMappingURL=no-dupe-scenario-names.js.map
|
|
@@ -13,10 +13,10 @@ function messageFor(max) {
|
|
|
13
13
|
const rule = {
|
|
14
14
|
name,
|
|
15
15
|
availableConfigs,
|
|
16
|
-
run(
|
|
16
|
+
run(feature, file, configuration) {
|
|
17
17
|
const { max } = mergeDefaults(availableConfigs, configuration);
|
|
18
18
|
const lines = contentLines(file);
|
|
19
|
-
const inDocString = markDocStrings(lines);
|
|
19
|
+
const inDocString = markDocStrings(lines, feature);
|
|
20
20
|
const message = messageFor(max);
|
|
21
21
|
const errors = [];
|
|
22
22
|
let blanksInARow = 0;
|
|
@@ -41,4 +41,3 @@ const rule = {
|
|
|
41
41
|
},
|
|
42
42
|
};
|
|
43
43
|
export default rule;
|
|
44
|
-
//# sourceMappingURL=no-multiple-empty-lines.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { taggedNodesOf } from '../gherkin/traverse.js';
|
|
2
|
-
import { atLineColumn } from '../util/location.js';
|
|
2
|
+
import { atLineColumn, columnOf } from '../util/location.js';
|
|
3
3
|
const name = 'no-partially-commented-tag-lines';
|
|
4
4
|
/**
|
|
5
5
|
* A `#` on a tag line comments out everything after it. That is easy to do by
|
|
@@ -27,13 +27,16 @@ const rule = {
|
|
|
27
27
|
}
|
|
28
28
|
const errors = [];
|
|
29
29
|
for (const line of [...tagLines].sort((a, b) => a - b)) {
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
// As in Gherkin itself, only a # after whitespace starts a comment;
|
|
31
|
+
// one inside a tag, as in @issue#123, is part of the tag.
|
|
32
|
+
const text = file.lines[line - 1] ?? '';
|
|
33
|
+
const comment = /\s#/u.exec(text);
|
|
34
|
+
if (comment !== null) {
|
|
32
35
|
errors.push({
|
|
33
36
|
message: 'Partially commented tag lines not allowed',
|
|
34
37
|
rule: name,
|
|
35
38
|
// Point at the '#' itself: that is the character to remove.
|
|
36
|
-
...atLineColumn(line, comment + 1),
|
|
39
|
+
...atLineColumn(line, columnOf(text, comment.index + 1)),
|
|
37
40
|
});
|
|
38
41
|
}
|
|
39
42
|
}
|
|
@@ -41,4 +44,3 @@ const rule = {
|
|
|
41
44
|
},
|
|
42
45
|
};
|
|
43
46
|
export default rule;
|
|
44
|
-
//# sourceMappingURL=no-partially-commented-tag-lines.js.map
|
|
@@ -2,6 +2,7 @@ import { getNeutralKeyword, getNodeType } from '../gherkin/keywords.js';
|
|
|
2
2
|
import { rulesOf, stepContainersOf } from '../gherkin/traverse.js';
|
|
3
3
|
import { mergeDefaults } from '../util/collections.js';
|
|
4
4
|
import { at } from '../util/location.js';
|
|
5
|
+
import { invalidPatterns } from '../util/patterns.js';
|
|
5
6
|
const name = 'no-restricted-patterns';
|
|
6
7
|
/**
|
|
7
8
|
* Patterns are grouped by where they apply. `Global` applies everywhere; the
|
|
@@ -51,51 +52,95 @@ function toCheckableStrings(property, value) {
|
|
|
51
52
|
const rule = {
|
|
52
53
|
name,
|
|
53
54
|
availableConfigs,
|
|
54
|
-
|
|
55
|
+
verifySettings: (settings) => Object.entries(settings).flatMap(([key, patterns]) => invalidPatterns(key, patterns, 'i')),
|
|
56
|
+
run(feature, file, configuration) {
|
|
55
57
|
if (feature === undefined) {
|
|
56
58
|
return [];
|
|
57
59
|
}
|
|
58
60
|
const patterns = compilePatterns(mergeDefaults(availableConfigs, configuration));
|
|
59
61
|
const language = feature.language;
|
|
60
62
|
const errors = [];
|
|
61
|
-
|
|
63
|
+
/** Reports every pattern the text matches, at the given position. */
|
|
64
|
+
const report = (type, property, text, applicable, position) => {
|
|
65
|
+
for (const pattern of applicable) {
|
|
66
|
+
if (pattern.test(text)) {
|
|
67
|
+
errors.push({
|
|
68
|
+
message: `${type} ${property}: "${text}" matches restricted pattern "${pattern}"`,
|
|
69
|
+
rule: name,
|
|
70
|
+
...position,
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
const check = (node, property, value, applicable, location = node.location) => {
|
|
62
76
|
if (value === undefined || value === '') {
|
|
63
77
|
return;
|
|
64
78
|
}
|
|
79
|
+
// Names may be padded with whitespace; steps are not.
|
|
80
|
+
report(getNodeType(node, language), property, value.trim(), applicable, at(location));
|
|
81
|
+
};
|
|
82
|
+
/**
|
|
83
|
+
* A description, line by line, each reported on the line it is written
|
|
84
|
+
* on. The description starts below the keyword line, and a comment
|
|
85
|
+
* between its lines is left out of it, so each line is looked for in the
|
|
86
|
+
* file rather than counted.
|
|
87
|
+
*/
|
|
88
|
+
const checkDescription = (node, applicable) => {
|
|
89
|
+
if (node.description === undefined || node.description === '') {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
65
92
|
const type = getNodeType(node, language);
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
}
|
|
93
|
+
let searchFrom = node.location.line;
|
|
94
|
+
for (const candidate of toCheckableStrings('description', node.description)) {
|
|
95
|
+
const text = candidate.trim();
|
|
96
|
+
if (text === '')
|
|
97
|
+
continue;
|
|
98
|
+
const index = file.lines.findIndex((line, lineIndex) => lineIndex >= searchFrom && line.trim() === text);
|
|
99
|
+
const line = index === -1 ? node.location.line : index + 1;
|
|
100
|
+
if (index !== -1)
|
|
101
|
+
searchFrom = index + 1;
|
|
102
|
+
report(type, 'description', text, applicable, { line });
|
|
78
103
|
}
|
|
79
104
|
};
|
|
80
105
|
const patternsFor = (node) => patterns.get(getNeutralKeyword(node, language)) ?? [];
|
|
81
106
|
check(feature, 'name', feature.name, patternsFor(feature));
|
|
82
|
-
|
|
107
|
+
checkDescription(feature, patternsFor(feature));
|
|
83
108
|
for (const featureRule of rulesOf(feature)) {
|
|
84
109
|
const applicable = patternsFor(featureRule);
|
|
85
110
|
check(featureRule, 'name', featureRule.name, applicable);
|
|
86
|
-
|
|
111
|
+
checkDescription(featureRule, applicable);
|
|
87
112
|
}
|
|
88
113
|
for (const { node } of stepContainersOf(feature)) {
|
|
89
114
|
const applicable = patternsFor(node);
|
|
90
115
|
check(node, 'name', node.name, applicable);
|
|
91
|
-
|
|
92
|
-
// Steps are checked against the patterns of the
|
|
116
|
+
checkDescription(node, applicable);
|
|
117
|
+
// Steps, and what they carry, are checked against the patterns of the
|
|
118
|
+
// block they sit in.
|
|
93
119
|
for (const step of node.steps) {
|
|
94
120
|
check(step, 'text', step.text, applicable);
|
|
121
|
+
for (const row of step.dataTable?.rows ?? []) {
|
|
122
|
+
for (const cell of row.cells) {
|
|
123
|
+
if (cell.value.trim() !== '') {
|
|
124
|
+
report('Step', 'data table', cell.value.trim(), applicable, at(cell.location));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (step.docString !== undefined) {
|
|
129
|
+
const { content, location } = step.docString;
|
|
130
|
+
content.split('\n').forEach((line, index) => {
|
|
131
|
+
if (line.trim() !== '') {
|
|
132
|
+
report('Step', 'doc string', line.trim(), applicable, { line: location.line + 1 + index });
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// An outline's Examples belong to it, and take its patterns.
|
|
138
|
+
for (const examples of 'examples' in node ? node.examples : []) {
|
|
139
|
+
check(examples, 'name', examples.name, applicable);
|
|
140
|
+
checkDescription(examples, applicable);
|
|
95
141
|
}
|
|
96
142
|
}
|
|
97
143
|
return errors;
|
|
98
144
|
},
|
|
99
145
|
};
|
|
100
146
|
export default rule;
|
|
101
|
-
//# sourceMappingURL=no-restricted-patterns.js.map
|