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
package/LICENSE
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright (c) 2016, Vasiliki Siakka
|
|
2
|
+
|
|
3
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
8
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
9
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
10
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
11
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
12
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
13
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
# gurkencheck
|
|
2
|
+
|
|
3
|
+
[](https://github.com/sebs/gurkencheck/actions/workflows/ci.yml)
|
|
4
|
+
[](https://www.npmjs.com/package/gurkencheck)
|
|
5
|
+
|
|
6
|
+
A linter for Gherkin feature files. It reads your `.feature` files and tells you where
|
|
7
|
+
they drift from the conventions your team has agreed on.
|
|
8
|
+
|
|
9
|
+
**[Documentation](https://sebs.github.io/gurkencheck/)** — every rule has its own
|
|
10
|
+
page with an example that passes and one that fails.
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
npm install --save-dev gurkencheck
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Requires Node.js 22 or newer.
|
|
19
|
+
|
|
20
|
+
## Get started
|
|
21
|
+
|
|
22
|
+
Just run it:
|
|
23
|
+
|
|
24
|
+
```sh
|
|
25
|
+
npx gurkencheck
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
With no configuration file, gurkencheck uses its **recommended** rules: the ones that catch
|
|
29
|
+
a mistake rather than express a preference — an empty file, a scenario with no name, a
|
|
30
|
+
variable that will never be substituted. Nothing in that set depends on how you lay a file
|
|
31
|
+
out, so it should be quiet on a codebase that has never been linted.
|
|
32
|
+
|
|
33
|
+
When you want something different, create a `.gurkencheckrc` and list the rules you want. A
|
|
34
|
+
configuration file replaces the recommended set rather than adding to it, so every rule is
|
|
35
|
+
off until you switch it on:
|
|
36
|
+
|
|
37
|
+
```jsonc
|
|
38
|
+
{
|
|
39
|
+
"no-unnamed-features": "on",
|
|
40
|
+
"no-unnamed-scenarios": "on",
|
|
41
|
+
"no-trailing-spaces": "on",
|
|
42
|
+
"indentation": ["on", {"Feature": 0, "Scenario": 2, "Step": 4}]
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
With no paths given it searches the current directory for `.feature` files.
|
|
47
|
+
|
|
48
|
+
| Exit code | Meaning |
|
|
49
|
+
|---|---|
|
|
50
|
+
| `0` | Nothing worse than a warning |
|
|
51
|
+
| `1` | At least one rule set to `"on"` was broken |
|
|
52
|
+
| `2` | The linter could not run: bad arguments, or an invalid config |
|
|
53
|
+
|
|
54
|
+
Findings go to **stdout**, so `gurkencheck > report.json` and `gurkencheck | less` work.
|
|
55
|
+
Anything that stops the linter running — a bad option, an invalid config — goes to stderr.
|
|
56
|
+
|
|
57
|
+
A rule is set to `"on"`, `"warn"` or `"off"`. `"warn"` reports exactly the same findings but
|
|
58
|
+
does not fail the run — for a rule the team is working towards rather than enforcing:
|
|
59
|
+
|
|
60
|
+
```json
|
|
61
|
+
{"no-unnamed-scenarios": "on", "use-and": "warn"}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Command line
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
gurkencheck [options] <feature-files>
|
|
68
|
+
|
|
69
|
+
-f, --format <format> output format: stylish, json, junit, sarif, tap,
|
|
70
|
+
or the path to a formatter of your own
|
|
71
|
+
(default: stylish)
|
|
72
|
+
-c, --config <path> configuration file (default: .gurkencheckrc)
|
|
73
|
+
-i, --ignore <globs> comma separated globs to skip, overriding .gurkencheckignore
|
|
74
|
+
-r, --rulesdir <dir> directory of custom rules; may be given more than once
|
|
75
|
+
-l, --language <code> dialect for files with no "# language:" header
|
|
76
|
+
-h, --help show this message
|
|
77
|
+
-v, --version show the version number
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Rules
|
|
81
|
+
|
|
82
|
+
There are 33 rules you switch on, covering naming, tags, indentation, structure and size,
|
|
83
|
+
plus four that are always on because Gherkin itself refuses to read a file that breaks
|
|
84
|
+
them. Each one is documented at
|
|
85
|
+
**[sebs.github.io/gurkencheck](https://sebs.github.io/gurkencheck/)** with a
|
|
86
|
+
good and a bad example.
|
|
87
|
+
|
|
88
|
+
The configuration file is JSON and may contain comments. A rule is either a state:
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{"no-empty-file": "on"}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
or a state plus that rule's own settings:
|
|
95
|
+
|
|
96
|
+
```json
|
|
97
|
+
{"name-length": ["on", {"Feature": 70, "Scenario": 70, "Step": 70}]}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
Mistyped rule names and settings are reported before any file is read.
|
|
101
|
+
|
|
102
|
+
## Reporting to GitHub code scanning
|
|
103
|
+
|
|
104
|
+
`--format sarif` writes a SARIF 2.1.0 log, which GitHub reads directly:
|
|
105
|
+
|
|
106
|
+
```yaml
|
|
107
|
+
- run: npx gurkencheck --format sarif > gurkencheck.sarif
|
|
108
|
+
continue-on-error: true
|
|
109
|
+
|
|
110
|
+
- uses: github/codeql-action/upload-sarif@v3
|
|
111
|
+
with:
|
|
112
|
+
sarif_file: gurkencheck.sarif
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
Paths in the log are relative to the directory gurkencheck ran in, which is what code
|
|
116
|
+
scanning needs to match a finding to a file in the repository.
|
|
117
|
+
|
|
118
|
+
## Switching a rule off for one place
|
|
119
|
+
|
|
120
|
+
Write a comment in the feature file:
|
|
121
|
+
|
|
122
|
+
```gherkin
|
|
123
|
+
# gurkencheck-disable-next-line name-length
|
|
124
|
+
Scenario: A name that is long for a good reason and stays that way
|
|
125
|
+
|
|
126
|
+
# gurkencheck-disable use-and, name-length
|
|
127
|
+
... everything below here skips those two rules ...
|
|
128
|
+
# gurkencheck-enable use-and
|
|
129
|
+
|
|
130
|
+
# gurkencheck-disable-file no-trailing-spaces
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
| Directive | What it covers |
|
|
134
|
+
|---|---|
|
|
135
|
+
| `gurkencheck-disable-next-line` | The line directly below the comment |
|
|
136
|
+
| `gurkencheck-disable` | From the comment to the end of the file, or to the next `gurkencheck-enable` |
|
|
137
|
+
| `gurkencheck-enable` | Resumes the rules a `gurkencheck-disable` switched off |
|
|
138
|
+
| `gurkencheck-disable-file` | The whole file, wherever the comment appears |
|
|
139
|
+
|
|
140
|
+
Name the rules you mean, separated by commas or spaces; a directive naming no rules covers
|
|
141
|
+
all of them. Comments inside a doc string are text and are left alone. The four always-on
|
|
142
|
+
rules cannot be switched off this way — a file that breaks one of them cannot be read at
|
|
143
|
+
all, so hiding the message would leave nothing in its place.
|
|
144
|
+
|
|
145
|
+
## Feature files in another language
|
|
146
|
+
|
|
147
|
+
Gherkin is translated into dozens of languages. A file says which one it is written in with
|
|
148
|
+
a header on its first line:
|
|
149
|
+
|
|
150
|
+
```gherkin
|
|
151
|
+
# language: fr
|
|
152
|
+
Fonctionnalité: Se déconnecter
|
|
153
|
+
|
|
154
|
+
Scénario: Se déconnecter
|
|
155
|
+
Quand Ulrick se déconnecte
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
If every file in your project is written in the same language, set it once instead — with
|
|
159
|
+
`--language fr` or a `language` key in your configuration file. A header in a file always
|
|
160
|
+
wins over that setting, so a project can be mostly one language with exceptions.
|
|
161
|
+
|
|
162
|
+
## Sharing a configuration
|
|
163
|
+
|
|
164
|
+
Build on top of another configuration with `extends`. What your file says wins over what it
|
|
165
|
+
extends, and later entries in a list win over earlier ones.
|
|
166
|
+
|
|
167
|
+
```jsonc
|
|
168
|
+
{
|
|
169
|
+
"extends": "gurkencheck:recommended",
|
|
170
|
+
"indentation": ["on", {"Step": 4}],
|
|
171
|
+
"no-trailing-spaces": "off"
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
| Entry | What it means |
|
|
176
|
+
|---|---|
|
|
177
|
+
| `gurkencheck:recommended` | The built-in recommended rules |
|
|
178
|
+
| `./team/.gurkencheckrc` | Another file, resolved from the file doing the extending |
|
|
179
|
+
| `@acme/gurkencheck-config` | An installed package exporting a configuration, as JSON or as a module |
|
|
180
|
+
|
|
181
|
+
## Skipping files
|
|
182
|
+
|
|
183
|
+
Put one glob per line in a `.gurkencheckignore` file, or pass `--ignore` on the command
|
|
184
|
+
line. Without either, `node_modules` is skipped and everything else is checked.
|
|
185
|
+
|
|
186
|
+
A pattern that matches a directory skips everything below it, as in `.gitignore` and
|
|
187
|
+
`.eslintignore`, so `build` is enough and you do not have to write `build/**`. Blank lines
|
|
188
|
+
and lines starting with `#` are ignored.
|
|
189
|
+
|
|
190
|
+
## Custom formatters
|
|
191
|
+
|
|
192
|
+
Pass a path or a package name to `--format`. The module exports a function taking the
|
|
193
|
+
results; it may print the output itself, or return a string and let gurkencheck print it.
|
|
194
|
+
|
|
195
|
+
```js
|
|
196
|
+
// count.mjs
|
|
197
|
+
export default function count(results) {
|
|
198
|
+
const findings = results.reduce((total, file) => total + file.errors.length, 0);
|
|
199
|
+
return `${findings} findings in ${results.length} files`;
|
|
200
|
+
}
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
```sh
|
|
204
|
+
npx gurkencheck --format ./count.mjs
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
Each result is `{filePath, errors}`, and each error is
|
|
208
|
+
`{message, rule, line, column, severity}`. A default export, a `printResults` export, or a
|
|
209
|
+
module that is itself the function all work.
|
|
210
|
+
|
|
211
|
+
## Custom rules
|
|
212
|
+
|
|
213
|
+
Point `--rulesdir` at a directory of your own modules. Each exports an object with a
|
|
214
|
+
`name` and a `run` function, and is called once per file. CommonJS, ES modules and
|
|
215
|
+
TypeScript all work.
|
|
216
|
+
|
|
217
|
+
```js
|
|
218
|
+
// rules/no-lorem.js
|
|
219
|
+
const name = 'no-lorem';
|
|
220
|
+
|
|
221
|
+
export default {
|
|
222
|
+
name,
|
|
223
|
+
run(feature, file) {
|
|
224
|
+
if (feature === undefined) return [];
|
|
225
|
+
return feature.children
|
|
226
|
+
.filter((child) => child.scenario?.name.includes('lorem'))
|
|
227
|
+
.map((child) => ({
|
|
228
|
+
message: 'Placeholder text left in a scenario name',
|
|
229
|
+
rule: name,
|
|
230
|
+
line: child.scenario.location.line,
|
|
231
|
+
}));
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
```sh
|
|
237
|
+
npx gurkencheck --rulesdir ./rules
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
A custom rule may reuse a built-in rule's name to replace it.
|
|
241
|
+
|
|
242
|
+
`run` may also be `async` and return a promise, for a rule that has to wait for
|
|
243
|
+
something — reading a file, or asking an issue tracker whether a tag refers to a real
|
|
244
|
+
ticket. Files are checked one after another, so rules see a predictable order.
|
|
245
|
+
|
|
246
|
+
## Using it as a library
|
|
247
|
+
|
|
248
|
+
```ts
|
|
249
|
+
import {findFeatureFiles, lint, loadRules, readConfiguration} from 'gurkencheck';
|
|
250
|
+
|
|
251
|
+
const rules = await loadRules();
|
|
252
|
+
const config = readConfiguration('.gurkencheckrc', rules);
|
|
253
|
+
|
|
254
|
+
if (config.ok) {
|
|
255
|
+
const {files} = findFeatureFiles(['features']);
|
|
256
|
+
const results = await lint(files, config.configuration, rules);
|
|
257
|
+
}
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
Each error carries `message`, `rule`, `line` and, where the rule knows one, `column` —
|
|
261
|
+
both 1-based, so an editor can underline exactly the right text. Errors about a whole file
|
|
262
|
+
or a whole line, such as a missing new line at the end of the file, have no `column`.
|
|
263
|
+
|
|
264
|
+
Nothing in the library writes to the console or exits the process; that is the command
|
|
265
|
+
line's job.
|
|
266
|
+
|
|
267
|
+
## Developing
|
|
268
|
+
|
|
269
|
+
The project is TypeScript with two runtime dependencies:
|
|
270
|
+
[`@cucumber/gherkin`](https://github.com/cucumber/gherkin) and its own `@cucumber/messages`.
|
|
271
|
+
Everything else — argument parsing, globbing, JSON-with-comments, XML output, the
|
|
272
|
+
collection helpers — is plain TypeScript in `src/util`. Tests run on node's built-in test
|
|
273
|
+
runner, straight off the sources using node's type stripping, so there is no build step
|
|
274
|
+
to run before testing.
|
|
275
|
+
|
|
276
|
+
```sh
|
|
277
|
+
npm test # node --test over test/**/*.test.ts
|
|
278
|
+
npm run coverage # the same, with node's coverage reporter
|
|
279
|
+
npm run typecheck # tsc over src, test, site and scripts
|
|
280
|
+
npm run build # compile src into dist
|
|
281
|
+
npm run docs # regenerate the documentation site into docs/
|
|
282
|
+
npm run demo # lint the deliberately broken files in examples/
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Releasing
|
|
286
|
+
|
|
287
|
+
Versions are bumped and tagged locally; everything after that is a workflow.
|
|
288
|
+
|
|
289
|
+
```sh
|
|
290
|
+
npm version patch # bumps package.json, commits, and tags v0.0.4
|
|
291
|
+
git push --follow-tags
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Pushing the tag runs two workflows:
|
|
295
|
+
|
|
296
|
+
| Workflow | Trigger | What it does |
|
|
297
|
+
|---|---|---|
|
|
298
|
+
| **Release** | the tag | Checks the tag matches `package.json`, runs the tests, builds, and creates the GitHub release with the npm tarball attached |
|
|
299
|
+
| **Pages** | the tag | Builds the documentation site from that version and deploys it |
|
|
300
|
+
|
|
301
|
+
Publishing to npm is deliberately a separate step, so a release can be looked at before it
|
|
302
|
+
goes out. Run the **Publish** workflow by hand and give it the version — it checks out that
|
|
303
|
+
tag, re-runs the tests, and publishes with provenance. There is no `NPM_TOKEN` in the
|
|
304
|
+
repository: npm Trusted Publishing mints a short-lived credential for the run.
|
|
305
|
+
|
|
306
|
+
The site is not committed. `docs/` is generated during the Pages run, so the published site
|
|
307
|
+
always matches the version it was built from. Run the Pages workflow by hand with a version
|
|
308
|
+
to re-publish or to roll the site back; leave the version empty to publish from the branch
|
|
309
|
+
you run it on, which is useful for previewing a docs change.
|
|
310
|
+
|
|
311
|
+
### Adding a rule
|
|
312
|
+
|
|
313
|
+
1. Add `src/rules/<name>.ts`, exporting a default object with `name` and `run`.
|
|
314
|
+
2. Run `npm run generate:rules` to add it to the registry.
|
|
315
|
+
3. Add `test/rules/<name>/<name>.test.ts` and its fixtures.
|
|
316
|
+
4. Add an entry to `site/content.ts` and run `npm run docs`.
|
|
317
|
+
|
|
318
|
+
Steps 2 and 4 are enforced by tests, so a rule cannot ship undocumented or unregistered.
|
|
319
|
+
|
|
320
|
+
## History
|
|
321
|
+
|
|
322
|
+
gurkencheck is a fork of [gherkin-lint](https://github.com/gherkin-lint/gherkin-lint),
|
|
323
|
+
rewritten in TypeScript. See [MIGRATING.md](MIGRATING.md) if you are coming from it.
|
|
324
|
+
|
|
325
|
+
## Licence
|
|
326
|
+
|
|
327
|
+
ISC. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Configuration, RuleRegistry } from './types.ts';
|
|
2
|
+
/** The configuration file looked for when none is given on the command line. */
|
|
3
|
+
export declare const DEFAULT_CONFIG_FILE_NAME = ".gurkencheckrc";
|
|
4
|
+
/** Either a usable configuration, or the reason there isn't one. */
|
|
5
|
+
export type ConfigurationResult = {
|
|
6
|
+
ok: true;
|
|
7
|
+
configuration: Configuration;
|
|
8
|
+
source: string;
|
|
9
|
+
language?: string;
|
|
10
|
+
} | {
|
|
11
|
+
ok: false;
|
|
12
|
+
message: string;
|
|
13
|
+
details: string[];
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Reads the configuration file at `configPath`, or the default file in the
|
|
17
|
+
* working directory when no path is given. With neither, the recommended
|
|
18
|
+
* rules are used.
|
|
19
|
+
*/
|
|
20
|
+
export declare function readConfiguration(configPath: string | undefined, rules: RuleRegistry): Promise<ConfigurationResult>;
|
|
21
|
+
//# sourceMappingURL=config-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-parser.d.ts","sourceRoot":"","sources":["../src/config-parser.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAC,aAAa,EAAE,YAAY,EAAC,MAAM,YAAY,CAAC;AAG5D,gFAAgF;AAChF,eAAO,MAAM,wBAAwB,mBAAmB,CAAC;AAQzD,oEAAoE;AACpE,MAAM,MAAM,mBAAmB,GAC3B;IAAC,EAAE,EAAE,IAAI,CAAC;IAAC,aAAa,EAAE,aAAa,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAC,GAC3E;IAAC,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAC,CAAC;AA6HpD;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,KAAK,EAAE,YAAY,GAClB,OAAO,CAAC,mBAAmB,CAAC,CAqD9B"}
|
|
@@ -0,0 +1,171 @@
|
|
|
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
|
+
* Reading and validating the configuration file.
|
|
11
|
+
*/
|
|
12
|
+
import fs from 'node:fs';
|
|
13
|
+
import { createRequire } from 'node:module';
|
|
14
|
+
import path from 'node:path';
|
|
15
|
+
import { pathToFileURL } from 'node:url';
|
|
16
|
+
import { verifyConfiguration } from './config-verifier.js';
|
|
17
|
+
import { PRESETS, RECOMMENDED } from './presets.js';
|
|
18
|
+
import { stripJsonComments } from './util/json.js';
|
|
19
|
+
/** The configuration file looked for when none is given on the command line. */
|
|
20
|
+
export const DEFAULT_CONFIG_FILE_NAME = '.gurkencheckrc';
|
|
21
|
+
/** The key naming the configurations to build on top of. */
|
|
22
|
+
const EXTENDS = 'extends';
|
|
23
|
+
/** The key setting the dialect for files with no `# language:` header. */
|
|
24
|
+
const LANGUAGE = 'language';
|
|
25
|
+
class ConfigurationError extends Error {
|
|
26
|
+
}
|
|
27
|
+
function isConfigurationObject(value) {
|
|
28
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
29
|
+
}
|
|
30
|
+
function parseFile(filePath) {
|
|
31
|
+
let parsed;
|
|
32
|
+
try {
|
|
33
|
+
parsed = JSON.parse(stripJsonComments(fs.readFileSync(filePath, 'utf8')));
|
|
34
|
+
}
|
|
35
|
+
catch (thrown) {
|
|
36
|
+
throw new ConfigurationError(`Could not parse "${filePath}": ${thrown instanceof Error ? thrown.message : String(thrown)}`);
|
|
37
|
+
}
|
|
38
|
+
if (!isConfigurationObject(parsed)) {
|
|
39
|
+
throw new ConfigurationError(`"${filePath}" must hold a JSON object mapping rule names to their settings.`);
|
|
40
|
+
}
|
|
41
|
+
return parsed;
|
|
42
|
+
}
|
|
43
|
+
/** The `extends` entries of a configuration, as a list. */
|
|
44
|
+
function extendsList(configuration, source) {
|
|
45
|
+
const value = configuration[EXTENDS];
|
|
46
|
+
if (value === undefined) {
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
if (typeof value === 'string') {
|
|
50
|
+
return [value];
|
|
51
|
+
}
|
|
52
|
+
if (Array.isArray(value) && value.every((entry) => typeof entry === 'string')) {
|
|
53
|
+
return value;
|
|
54
|
+
}
|
|
55
|
+
throw new ConfigurationError(`"${EXTENDS}" in "${source}" must be a name or a list of names.`);
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Loads what one `extends` entry refers to: a built-in preset, another
|
|
59
|
+
* configuration file, or a package.
|
|
60
|
+
*
|
|
61
|
+
* Packages and relative paths are resolved from the file doing the extending,
|
|
62
|
+
* so a shared configuration installed in a project is found where you would
|
|
63
|
+
* expect and a relative path means what it looks like.
|
|
64
|
+
*/
|
|
65
|
+
async function loadExtended(specifier, fromFile) {
|
|
66
|
+
const preset = PRESETS[specifier];
|
|
67
|
+
if (preset !== undefined) {
|
|
68
|
+
return { configuration: preset, source: specifier };
|
|
69
|
+
}
|
|
70
|
+
if (specifier.startsWith('gurkencheck:')) {
|
|
71
|
+
throw new ConfigurationError(`There is no built-in configuration called "${specifier}". Available: ${Object.keys(PRESETS).join(', ')}`);
|
|
72
|
+
}
|
|
73
|
+
const from = path.resolve(fromFile);
|
|
74
|
+
if (specifier.startsWith('.') || path.isAbsolute(specifier)) {
|
|
75
|
+
const resolved = path.resolve(path.dirname(from), specifier);
|
|
76
|
+
if (!fs.existsSync(resolved)) {
|
|
77
|
+
throw new ConfigurationError(`Could not find "${specifier}", extended from "${fromFile}".`);
|
|
78
|
+
}
|
|
79
|
+
return { configuration: parseFile(resolved), source: resolved };
|
|
80
|
+
}
|
|
81
|
+
let resolved;
|
|
82
|
+
try {
|
|
83
|
+
resolved = createRequire(pathToFileURL(from)).resolve(specifier);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
throw new ConfigurationError(`Could not resolve the package "${specifier}", extended from "${fromFile}". Is it installed?`);
|
|
87
|
+
}
|
|
88
|
+
if (resolved.endsWith('.json')) {
|
|
89
|
+
return { configuration: parseFile(resolved), source: resolved };
|
|
90
|
+
}
|
|
91
|
+
const module = (await import(__rewriteRelativeImportExtension(pathToFileURL(resolved).href)));
|
|
92
|
+
const exported = module['default'] ?? module;
|
|
93
|
+
if (!isConfigurationObject(exported)) {
|
|
94
|
+
throw new ConfigurationError(`"${specifier}" does not export a configuration object.`);
|
|
95
|
+
}
|
|
96
|
+
return { configuration: exported, source: resolved };
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Flattens a configuration and everything it extends into one object. What a
|
|
100
|
+
* file says wins over what it extends, and later entries in an `extends` list
|
|
101
|
+
* win over earlier ones.
|
|
102
|
+
*/
|
|
103
|
+
async function flatten(configuration, source, seen) {
|
|
104
|
+
if (seen.has(source)) {
|
|
105
|
+
throw new ConfigurationError(`"${source}" ends up extending itself.`);
|
|
106
|
+
}
|
|
107
|
+
seen.add(source);
|
|
108
|
+
let merged = {};
|
|
109
|
+
for (const specifier of extendsList(configuration, source)) {
|
|
110
|
+
const extended = await loadExtended(specifier, source);
|
|
111
|
+
merged = { ...merged, ...(await flatten(extended.configuration, extended.source, seen)) };
|
|
112
|
+
}
|
|
113
|
+
const own = { ...configuration };
|
|
114
|
+
delete own[EXTENDS];
|
|
115
|
+
return { ...merged, ...own };
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Reads the configuration file at `configPath`, or the default file in the
|
|
119
|
+
* working directory when no path is given. With neither, the recommended
|
|
120
|
+
* rules are used.
|
|
121
|
+
*/
|
|
122
|
+
export async function readConfiguration(configPath, rules) {
|
|
123
|
+
if (configPath !== undefined) {
|
|
124
|
+
if (!fs.existsSync(configPath)) {
|
|
125
|
+
return {
|
|
126
|
+
ok: false,
|
|
127
|
+
message: `Could not find specified config file "${configPath}"`,
|
|
128
|
+
details: [],
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
if (!fs.existsSync(DEFAULT_CONFIG_FILE_NAME)) {
|
|
134
|
+
// Nothing to read, so fall back to the recommended rules rather than
|
|
135
|
+
// refusing to run. Writing a configuration file is then a way to change
|
|
136
|
+
// the defaults, not a hurdle before the first run.
|
|
137
|
+
return { ok: true, configuration: RECOMMENDED, source: 'the recommended preset' };
|
|
138
|
+
}
|
|
139
|
+
configPath = DEFAULT_CONFIG_FILE_NAME;
|
|
140
|
+
}
|
|
141
|
+
let flattened;
|
|
142
|
+
try {
|
|
143
|
+
flattened = await flatten(parseFile(configPath), configPath, new Set());
|
|
144
|
+
}
|
|
145
|
+
catch (thrown) {
|
|
146
|
+
if (thrown instanceof ConfigurationError) {
|
|
147
|
+
return {
|
|
148
|
+
ok: false,
|
|
149
|
+
message: `Could not read config file "${configPath}"`,
|
|
150
|
+
details: [thrown.message],
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
throw thrown;
|
|
154
|
+
}
|
|
155
|
+
// "language" is a setting rather than a rule, so it is taken out before the
|
|
156
|
+
// rest is checked against the rule list.
|
|
157
|
+
const { [LANGUAGE]: language, ...configuration } = flattened;
|
|
158
|
+
if (language !== undefined && typeof language !== 'string') {
|
|
159
|
+
return {
|
|
160
|
+
ok: false,
|
|
161
|
+
message: `Could not read config file "${configPath}"`,
|
|
162
|
+
details: [`"${LANGUAGE}" must be a language code, such as "fr".`],
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
const errors = verifyConfiguration(configuration, rules);
|
|
166
|
+
if (errors.length > 0) {
|
|
167
|
+
return { ok: false, message: 'Error(s) in configuration file:', details: errors };
|
|
168
|
+
}
|
|
169
|
+
return { ok: true, configuration, source: configPath, ...(language === undefined ? {} : { language }) };
|
|
170
|
+
}
|
|
171
|
+
//# sourceMappingURL=config-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-parser.js","sourceRoot":"","sources":["../src/config-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { Configuration, RuleRegistry } from './types.ts';
|
|
2
|
+
/** Returns a list of problems; an empty list means the file is usable. */
|
|
3
|
+
export declare function verifyConfiguration(configuration: Configuration, rules: RuleRegistry): string[];
|
|
4
|
+
//# sourceMappingURL=config-verifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-verifier.d.ts","sourceRoot":"","sources":["../src/config-verifier.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAC,aAAa,EAAE,YAAY,EAAC,MAAM,YAAY,CAAC;AAmD5D,0EAA0E;AAC1E,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,aAAa,EAAE,KAAK,EAAE,YAAY,GAAG,MAAM,EAAE,CA6C/F"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checking a configuration file before anything is linted, so that a typo in
|
|
3
|
+
* a rule name is reported once and clearly rather than silently ignored.
|
|
4
|
+
*/
|
|
5
|
+
import { ALWAYS_ON_RULES } from './gherkin/parse.js';
|
|
6
|
+
const STATES = ['on', 'warn', 'off'];
|
|
7
|
+
function describeAllowed(availableConfigs) {
|
|
8
|
+
if (Array.isArray(availableConfigs)) {
|
|
9
|
+
return availableConfigs.map((value) => `"${String(value)}"`).join(', ');
|
|
10
|
+
}
|
|
11
|
+
if (typeof availableConfigs === 'object' && availableConfigs !== null) {
|
|
12
|
+
return Object.keys(availableConfigs)
|
|
13
|
+
.map((key) => `"${key}"`)
|
|
14
|
+
.join(', ');
|
|
15
|
+
}
|
|
16
|
+
return '';
|
|
17
|
+
}
|
|
18
|
+
function verifySettings(ruleName, availableConfigs, settings, errors) {
|
|
19
|
+
const prefix = `Invalid rule configuration for "${ruleName}" - `;
|
|
20
|
+
if (availableConfigs === undefined) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (Array.isArray(availableConfigs)) {
|
|
24
|
+
// The rule takes one value out of a fixed list, e.g. "yes" or "no".
|
|
25
|
+
if (!availableConfigs.includes(settings)) {
|
|
26
|
+
errors.push(`${prefix}"${String(settings)}" is not one of the allowed values: ${describeAllowed(availableConfigs)}`);
|
|
27
|
+
}
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (typeof settings !== 'object' || settings === null || Array.isArray(settings)) {
|
|
31
|
+
errors.push(`${prefix}the settings should be an object with one or more of: ${describeAllowed(availableConfigs)}`);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const allowedKeys = new Set(Object.keys(availableConfigs));
|
|
35
|
+
for (const key of Object.keys(settings)) {
|
|
36
|
+
if (!allowedKeys.has(key)) {
|
|
37
|
+
errors.push(`${prefix}the rule has no setting called "${key}". Available settings: ${describeAllowed(availableConfigs)}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** Returns a list of problems; an empty list means the file is usable. */
|
|
42
|
+
export function verifyConfiguration(configuration, rules) {
|
|
43
|
+
const errors = [];
|
|
44
|
+
for (const [ruleName, ruleConfig] of Object.entries(configuration)) {
|
|
45
|
+
const rule = rules.get(ruleName);
|
|
46
|
+
const prefix = `Invalid rule configuration for "${ruleName}" - `;
|
|
47
|
+
if (rule === undefined) {
|
|
48
|
+
// The rules the parser enforces are documented alongside the rest, so
|
|
49
|
+
// people reasonably list them. Naming one is harmless; asking for it to
|
|
50
|
+
// be off is the only thing worth saying something about.
|
|
51
|
+
if (ALWAYS_ON_RULES.includes(ruleName)) {
|
|
52
|
+
const state = Array.isArray(ruleConfig) ? ruleConfig[0] : ruleConfig;
|
|
53
|
+
if (state === 'off') {
|
|
54
|
+
errors.push(`${prefix}this rule is always on. A file breaking it cannot be parsed at all, so there is nothing to switch off.`);
|
|
55
|
+
}
|
|
56
|
+
else if (!STATES.includes(state)) {
|
|
57
|
+
errors.push(`${prefix}the config should be "on", "warn" or "off"`);
|
|
58
|
+
}
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
errors.push(`Rule "${ruleName}" does not exist`);
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (!Array.isArray(ruleConfig)) {
|
|
65
|
+
if (!STATES.includes(ruleConfig)) {
|
|
66
|
+
errors.push(`${prefix}the config should be "on", "warn" or "off"`);
|
|
67
|
+
}
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (!STATES.includes(ruleConfig[0])) {
|
|
71
|
+
errors.push(`${prefix}the first part of the config should be "on", "warn" or "off"`);
|
|
72
|
+
}
|
|
73
|
+
if (ruleConfig.length !== 2) {
|
|
74
|
+
errors.push(`${prefix}the config should have exactly 2 parts: a state and the rule's settings`);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
verifySettings(ruleName, rule.availableConfigs, ruleConfig[1], errors);
|
|
78
|
+
}
|
|
79
|
+
return errors;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=config-verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-verifier.js","sourceRoot":"","sources":["../src/config-verifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** The ignore file looked for when `--ignore` is not given. */
|
|
2
|
+
export declare const DEFAULT_IGNORE_FILE_NAME = ".gurkencheckignore";
|
|
3
|
+
/** Never worth linting, and expensive to walk into. */
|
|
4
|
+
export declare const DEFAULT_IGNORED_PATTERNS: string[];
|
|
5
|
+
export interface FeatureSearch {
|
|
6
|
+
/** Matching feature files, relative to the working directory. */
|
|
7
|
+
files: string[];
|
|
8
|
+
/** Arguments that were neither a feature file, a directory nor a glob. */
|
|
9
|
+
invalidPatterns: string[];
|
|
10
|
+
}
|
|
11
|
+
/** Reads the ignore file, one glob pattern per line, ignoring blank lines. */
|
|
12
|
+
export declare function readIgnorePatterns(ignoreArgument: readonly string[] | undefined, ignoreFileName?: string): string[];
|
|
13
|
+
/**
|
|
14
|
+
* Finds the feature files named by the given patterns. With no patterns, the
|
|
15
|
+
* working directory is searched recursively.
|
|
16
|
+
*/
|
|
17
|
+
export declare function findFeatureFiles(patterns: readonly string[], ignoreArgument?: readonly string[]): FeatureSearch;
|
|
18
|
+
//# sourceMappingURL=feature-finder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"feature-finder.d.ts","sourceRoot":"","sources":["../src/feature-finder.ts"],"names":[],"mappings":"AASA,+DAA+D;AAC/D,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAE7D,uDAAuD;AACvD,eAAO,MAAM,wBAAwB,UAAsB,CAAC;AAE5D,MAAM,WAAW,aAAa;IAC5B,iEAAiE;IACjE,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,0EAA0E;IAC1E,eAAe,EAAE,MAAM,EAAE,CAAC;CAC3B;AA0BD,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAChC,cAAc,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,EAC7C,cAAc,GAAE,MAAiC,GAChD,MAAM,EAAE,CAYV;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,SAAS,MAAM,EAAE,EAC3B,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,GACjC,aAAa,CAiBf"}
|