gurkencheck 0.0.10 → 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 +2 -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/stats/index.d.ts
CHANGED
|
@@ -18,4 +18,3 @@ export { DEFAULT_STATS_FORMAT, DEFAULT_TOP, STATS_FORMATTERS, getStatsFormatter,
|
|
|
18
18
|
export type { StatsFormatOptions, StatsFormatter } from './format/index.ts';
|
|
19
19
|
export { runStats, statsUsage } from './command.ts';
|
|
20
20
|
export type * from './types.ts';
|
|
21
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/stats/index.js
CHANGED
|
@@ -14,4 +14,3 @@ export { DEFAULT_SIMILARITY, boundedEditDistance, groupSimilar } from './similar
|
|
|
14
14
|
export { NUMBER_MARKER, PLACEHOLDER_MARKER, STRING_MARKER, countWords, normaliseStepText, } from './normalise.js';
|
|
15
15
|
export { DEFAULT_STATS_FORMAT, DEFAULT_TOP, STATS_FORMATTERS, getStatsFormatter, toJson as statisticsToJson, toMarkdown, toText, } from './format/index.js';
|
|
16
16
|
export { runStats, statsUsage } from './command.js';
|
|
17
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -35,4 +35,3 @@ export declare const NUMBER_MARKER = "0";
|
|
|
35
35
|
export declare function normaliseStepText(text: string): string;
|
|
36
36
|
/** How many words a step is made of, counted before normalisation. */
|
|
37
37
|
export declare function countWords(text: string): number;
|
|
38
|
-
//# sourceMappingURL=normalise.d.ts.map
|
package/dist/stats/normalise.js
CHANGED
|
@@ -26,16 +26,34 @@ export const STRING_MARKER = '""';
|
|
|
26
26
|
/** Stands in for a number, whatever its value. */
|
|
27
27
|
export const NUMBER_MARKER = '0';
|
|
28
28
|
const PLACEHOLDER = /<[^<>]*>/gu;
|
|
29
|
-
|
|
29
|
+
/** A double quoted string, which may hold quotes escaped with a backslash. */
|
|
30
|
+
const QUOTED = /"(?:[^"\\]|\\.)*"/gu;
|
|
30
31
|
/**
|
|
31
|
-
* A whole number or decimal standing on its own
|
|
32
|
-
* `1st` and `v2` intact, where the digits are part of a
|
|
33
|
-
* value a step definition would capture.
|
|
32
|
+
* A whole number or decimal standing on its own, with its minus sign. The
|
|
33
|
+
* word boundaries keep `1st` and `v2` intact, where the digits are part of a
|
|
34
|
+
* name rather than a value a step definition would capture.
|
|
34
35
|
*/
|
|
35
|
-
const NUMBER =
|
|
36
|
+
const NUMBER = /(?:(?<![\p{L}\p{N}_])-)?\b\d+(?:[.,]\d+)*\b/gu;
|
|
36
37
|
const WHITESPACE = /\s+/gu;
|
|
37
|
-
/**
|
|
38
|
-
|
|
38
|
+
/**
|
|
39
|
+
* The text without a full stop or exclamation mark at the end, which changes
|
|
40
|
+
* nothing, and whatever spaces and further stops sit in front of it: `I own
|
|
41
|
+
* it .` and `I own it` are one step. A text of nothing but punctuation is
|
|
42
|
+
* left as it is rather than made empty.
|
|
43
|
+
*
|
|
44
|
+
* A loop rather than a regular expression: `/[\s.!]*[.!]$/` is tried from
|
|
45
|
+
* every position in a long run of ` .`, which takes seconds on one step.
|
|
46
|
+
*/
|
|
47
|
+
function withoutTrailingPunctuation(text) {
|
|
48
|
+
if (!text.endsWith('.') && !text.endsWith('!')) {
|
|
49
|
+
return text;
|
|
50
|
+
}
|
|
51
|
+
let end = text.length;
|
|
52
|
+
while (end > 0 && /[\s.!]/u.test(text[end - 1])) {
|
|
53
|
+
end--;
|
|
54
|
+
}
|
|
55
|
+
return end === 0 ? text : text.slice(0, end);
|
|
56
|
+
}
|
|
39
57
|
/**
|
|
40
58
|
* The form of a step text used to decide whether two steps are the same one.
|
|
41
59
|
*
|
|
@@ -44,22 +62,17 @@ const TRAILING_PUNCTUATION = /[\s.!]*[.!]$/u;
|
|
|
44
62
|
* half the sentence. Cucumber's own expressions quote with `"` anyway.
|
|
45
63
|
*/
|
|
46
64
|
export function normaliseStepText(text) {
|
|
47
|
-
|
|
65
|
+
const normalised = text
|
|
48
66
|
.replace(PLACEHOLDER, PLACEHOLDER_MARKER)
|
|
49
67
|
.replace(QUOTED, STRING_MARKER)
|
|
50
68
|
.replace(NUMBER, NUMBER_MARKER)
|
|
51
69
|
.toLowerCase()
|
|
52
70
|
.replace(WHITESPACE, ' ')
|
|
53
|
-
.trim()
|
|
54
|
-
// Whatever sat in front of the full stop goes with it: `I own it .` and
|
|
55
|
-
// `I own it` are one step, and a step text ending in a space is not one
|
|
56
|
-
// anybody would recognise in the report.
|
|
57
|
-
.replace(TRAILING_PUNCTUATION, '')
|
|
58
71
|
.trim();
|
|
72
|
+
return withoutTrailingPunctuation(normalised);
|
|
59
73
|
}
|
|
60
74
|
/** How many words a step is made of, counted before normalisation. */
|
|
61
75
|
export function countWords(text) {
|
|
62
76
|
const trimmed = text.trim();
|
|
63
77
|
return trimmed === '' ? 0 : trimmed.split(WHITESPACE).length;
|
|
64
78
|
}
|
|
65
|
-
//# sourceMappingURL=normalise.js.map
|
package/dist/stats/similar.d.ts
CHANGED
package/dist/stats/similar.js
CHANGED
package/dist/stats/types.d.ts
CHANGED
package/dist/stats/types.js
CHANGED
package/dist/suppressions.d.ts
CHANGED
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
* breaks one of them cannot be read at all, so hiding the message would leave
|
|
22
22
|
* nothing but silence.
|
|
23
23
|
*/
|
|
24
|
+
import type { Feature } from '@cucumber/messages';
|
|
24
25
|
import type { RuleError } from './types.ts';
|
|
25
26
|
export interface Suppressions {
|
|
26
27
|
/** True when a directive in the file covers this error. */
|
|
@@ -28,6 +29,8 @@ export interface Suppressions {
|
|
|
28
29
|
/** True when the file carries no directives at all. */
|
|
29
30
|
readonly isEmpty: boolean;
|
|
30
31
|
}
|
|
31
|
-
/**
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
/**
|
|
33
|
+
* Reads the directives out of a feature file's lines. Given the parsed
|
|
34
|
+
* document, it is used to tell where the doc strings are.
|
|
35
|
+
*/
|
|
36
|
+
export declare function readSuppressions(lines: readonly string[], feature?: Feature): Suppressions;
|
package/dist/suppressions.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { markDocStrings } from './util/lines.js';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* A directive, then the rules it names. Whitespace or the end of the line has
|
|
4
|
+
* to follow the directive's name: `\b` would also match before a hyphen, and
|
|
5
|
+
* read `disable-nextline` as a `disable` of every rule named after it.
|
|
6
|
+
*/
|
|
7
|
+
const DIRECTIVE = /^\s*#\s*gurkencheck-(disable-next-line|disable-file|disable|enable)(?=\s|$)(.*)$/;
|
|
3
8
|
/** Stands in for "every rule" when a directive names none. */
|
|
4
9
|
const ALL_RULES = '*';
|
|
5
10
|
function parseRuleNames(rest) {
|
|
@@ -9,16 +14,25 @@ function parseRuleNames(rest) {
|
|
|
9
14
|
.filter((name) => name !== '');
|
|
10
15
|
return names.length > 0 ? names : [ALL_RULES];
|
|
11
16
|
}
|
|
12
|
-
/**
|
|
13
|
-
|
|
14
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Reads the directives out of a feature file's lines. Given the parsed
|
|
19
|
+
* document, it is used to tell where the doc strings are.
|
|
20
|
+
*/
|
|
21
|
+
export function readSuppressions(lines, feature) {
|
|
22
|
+
const inDocString = markDocStrings(lines, feature);
|
|
15
23
|
const wholeFile = new Set();
|
|
16
24
|
/** Line number -> the rules switched off on that line only. */
|
|
17
25
|
const nextLine = new Map();
|
|
18
|
-
const
|
|
19
|
-
/** Rule -> the line its still-open `disable` started on. */
|
|
20
|
-
const open = new Map();
|
|
26
|
+
const switches = [];
|
|
21
27
|
let found = false;
|
|
28
|
+
/**
|
|
29
|
+
* The first line that is neither blank nor a comment. A finding about the
|
|
30
|
+
* whole file belongs to no line, so it is taken to sit here: a `disable`
|
|
31
|
+
* written in the comments at the top of the file covers it, one further
|
|
32
|
+
* down does not.
|
|
33
|
+
*/
|
|
34
|
+
const firstContent = lines.findIndex((text) => text.trim() !== '' && !text.trim().startsWith('#'));
|
|
35
|
+
const wholeFileLine = firstContent === -1 ? lines.length + 1 : firstContent + 1;
|
|
22
36
|
lines.forEach((text, index) => {
|
|
23
37
|
if (inDocString[index] === true) {
|
|
24
38
|
return;
|
|
@@ -40,31 +54,11 @@ export function readSuppressions(lines) {
|
|
|
40
54
|
onLine.add(name);
|
|
41
55
|
nextLine.set(line + 1, onLine);
|
|
42
56
|
}
|
|
43
|
-
else if (kind === 'disable') {
|
|
44
|
-
if (!open.has(name)) {
|
|
45
|
-
open.set(name, line);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
57
|
else {
|
|
49
|
-
|
|
50
|
-
const from = open.get(name);
|
|
51
|
-
if (from !== undefined) {
|
|
52
|
-
ranges.push({ rule: name, from, to: line });
|
|
53
|
-
open.delete(name);
|
|
54
|
-
}
|
|
55
|
-
if (name === ALL_RULES) {
|
|
56
|
-
// `enable` with no names closes everything that is open.
|
|
57
|
-
for (const [openRule, openFrom] of open) {
|
|
58
|
-
ranges.push({ rule: openRule, from: openFrom, to: line });
|
|
59
|
-
}
|
|
60
|
-
open.clear();
|
|
61
|
-
}
|
|
58
|
+
switches.push({ line, off: kind === 'disable', rule: name });
|
|
62
59
|
}
|
|
63
60
|
}
|
|
64
61
|
});
|
|
65
|
-
for (const [rule, from] of open) {
|
|
66
|
-
ranges.push({ rule, from, to: Infinity });
|
|
67
|
-
}
|
|
68
62
|
const covers = (rule, candidate) => candidate === ALL_RULES || candidate === rule;
|
|
69
63
|
return {
|
|
70
64
|
isEmpty: !found,
|
|
@@ -77,8 +71,20 @@ export function readSuppressions(lines) {
|
|
|
77
71
|
if (covers(error.rule, candidate))
|
|
78
72
|
return true;
|
|
79
73
|
}
|
|
80
|
-
|
|
74
|
+
// Whatever switched this rule on or off last, above the line, decides.
|
|
75
|
+
// So `enable use-and` after a bare `disable` switches use-and back on
|
|
76
|
+
// and leaves every other rule off, and `enable` with no names switches
|
|
77
|
+
// everything back on.
|
|
78
|
+
const line = error.line === 0 ? wholeFileLine : error.line;
|
|
79
|
+
let off = false;
|
|
80
|
+
for (const change of switches) {
|
|
81
|
+
if (change.line > line)
|
|
82
|
+
break;
|
|
83
|
+
if (covers(error.rule, change.rule)) {
|
|
84
|
+
off = change.off;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return off;
|
|
81
88
|
},
|
|
82
89
|
};
|
|
83
90
|
}
|
|
84
|
-
//# sourceMappingURL=suppressions.js.map
|
package/dist/types.d.ts
CHANGED
|
@@ -89,6 +89,13 @@ export interface LintRule {
|
|
|
89
89
|
* An array lists the allowed values; an object lists the allowed keys.
|
|
90
90
|
*/
|
|
91
91
|
readonly availableConfigs?: unknown;
|
|
92
|
+
/**
|
|
93
|
+
* Checks what the configuration gives the rule beyond the types of its
|
|
94
|
+
* settings, which are checked against `availableConfigs` already: that a
|
|
95
|
+
* pattern is a regular expression, or a value one of a fixed set. Returns
|
|
96
|
+
* what is wrong, an empty list when nothing is.
|
|
97
|
+
*/
|
|
98
|
+
verifySettings?(settings: Record<string, unknown>): string[];
|
|
92
99
|
/**
|
|
93
100
|
* Returns the violations found in this file. A rule that needs to wait for
|
|
94
101
|
* something - reading a file, asking a service - may return a promise.
|
|
@@ -122,4 +129,3 @@ export interface LintRule {
|
|
|
122
129
|
}
|
|
123
130
|
/** All rules available to a run, keyed by name. */
|
|
124
131
|
export type RuleRegistry = ReadonlyMap<string, LintRule>;
|
|
125
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.js
CHANGED
package/dist/util/case.d.ts
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* Splits an identifier into words, breaking on separators, on lower-to-upper
|
|
7
7
|
* transitions and between a run of capitals and a following capitalised word
|
|
8
|
-
* (so `XMLHttpRequest` becomes `XML`, `Http`, `Request`).
|
|
8
|
+
* (so `XMLHttpRequest` becomes `XML`, `Http`, `Request`). Letters outside
|
|
9
|
+
* ASCII are letters too: `Über` is one word, not `Ber`.
|
|
9
10
|
*/
|
|
10
11
|
export declare function words(value: string): string[];
|
|
11
12
|
/** `my fancy feature` -> `My Fancy Feature` */
|
|
@@ -18,4 +19,3 @@ export declare function camelCase(value: string): string;
|
|
|
18
19
|
export declare function kebabCase(value: string): string;
|
|
19
20
|
/** `my fancy feature` -> `my_fancy_feature` */
|
|
20
21
|
export declare function snakeCase(value: string): string;
|
|
21
|
-
//# sourceMappingURL=case.d.ts.map
|
package/dist/util/case.js
CHANGED
|
@@ -2,13 +2,28 @@
|
|
|
2
2
|
* Word splitting and case conversion, as used by the `file-name` rule.
|
|
3
3
|
* Replaces lodash's `startCase`/`camelCase`/`kebabCase`/`snakeCase`.
|
|
4
4
|
*/
|
|
5
|
+
/** Capital letters, in any script. */
|
|
6
|
+
const UPPER = String.raw `\p{Lu}\p{Lt}`;
|
|
7
|
+
/**
|
|
8
|
+
* Small letters, and letters with no case at all - Japanese, Chinese, Arabic
|
|
9
|
+
* - which carry on a word the way small letters do.
|
|
10
|
+
*/
|
|
11
|
+
const LOWER = String.raw `\p{Ll}\p{Lm}\p{Lo}`;
|
|
12
|
+
const DIGIT = String.raw `\p{Nd}`;
|
|
13
|
+
const WORD = new RegExp([
|
|
14
|
+
`[${UPPER}]{2,}(?=[${UPPER}][${LOWER}]+[${DIGIT}]*|(?![${UPPER}${LOWER}${DIGIT}]))`,
|
|
15
|
+
`[${UPPER}]?[${LOWER}]+[${DIGIT}]*`,
|
|
16
|
+
`[${UPPER}]+[${DIGIT}]*`,
|
|
17
|
+
`[${DIGIT}]+`,
|
|
18
|
+
].join('|'), 'gu');
|
|
5
19
|
/**
|
|
6
20
|
* Splits an identifier into words, breaking on separators, on lower-to-upper
|
|
7
21
|
* transitions and between a run of capitals and a following capitalised word
|
|
8
|
-
* (so `XMLHttpRequest` becomes `XML`, `Http`, `Request`).
|
|
22
|
+
* (so `XMLHttpRequest` becomes `XML`, `Http`, `Request`). Letters outside
|
|
23
|
+
* ASCII are letters too: `Über` is one word, not `Ber`.
|
|
9
24
|
*/
|
|
10
25
|
export function words(value) {
|
|
11
|
-
return value.match(
|
|
26
|
+
return value.match(WORD) ?? [];
|
|
12
27
|
}
|
|
13
28
|
function upperFirst(word) {
|
|
14
29
|
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
@@ -39,4 +54,3 @@ export function snakeCase(value) {
|
|
|
39
54
|
.map((word) => word.toLowerCase())
|
|
40
55
|
.join('_');
|
|
41
56
|
}
|
|
42
|
-
//# sourceMappingURL=case.js.map
|
|
@@ -27,4 +27,3 @@ export declare function intersectionBy<T>(values: readonly T[], other: readonly
|
|
|
27
27
|
* their overrides back into the shared default config object.
|
|
28
28
|
*/
|
|
29
29
|
export declare function mergeDefaults<T>(defaults: T, override: unknown): T;
|
|
30
|
-
//# sourceMappingURL=collections.d.ts.map
|
package/dist/util/collections.js
CHANGED
package/dist/util/glob.d.ts
CHANGED
|
@@ -3,6 +3,13 @@
|
|
|
3
3
|
* slash-separated paths.
|
|
4
4
|
*/
|
|
5
5
|
export declare function globToRegExp(pattern: string): RegExp;
|
|
6
|
+
/** Escapes every character glob syntax would read, so the text matches only itself. */
|
|
7
|
+
export declare function escapeGlob(literal: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* The path a pattern names when it holds no glob syntax, with its escapes
|
|
10
|
+
* removed, or `undefined` when it is a real pattern.
|
|
11
|
+
*/
|
|
12
|
+
export declare function literalPath(pattern: string): string | undefined;
|
|
6
13
|
/**
|
|
7
14
|
* The directory a pattern's search starts from - the leading run of literal
|
|
8
15
|
* segments, resolved against `cwd`. What you would watch to be told about
|
|
@@ -13,8 +20,8 @@ export interface GlobOptions {
|
|
|
13
20
|
/** Directory that relative patterns and returned paths are relative to. */
|
|
14
21
|
cwd?: string;
|
|
15
22
|
/**
|
|
16
|
-
* Patterns whose matches are dropped from the result
|
|
17
|
-
* directory drops everything below it
|
|
23
|
+
* Patterns whose matches are dropped from the result, read as .gitignore
|
|
24
|
+
* reads them. A pattern matching a directory drops everything below it.
|
|
18
25
|
*/
|
|
19
26
|
ignore?: readonly string[];
|
|
20
27
|
}
|
|
@@ -35,4 +42,3 @@ export declare function globSync(pattern: string, options?: GlobOptions): string
|
|
|
35
42
|
* to sort: `byPathOrder` is what makes the two agree.
|
|
36
43
|
*/
|
|
37
44
|
export declare function globStream(pattern: string, options?: GlobOptions): AsyncGenerator<string>;
|
|
38
|
-
//# sourceMappingURL=glob.d.ts.map
|
package/dist/util/glob.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import fs from 'node:fs';
|
|
12
12
|
import path from 'node:path';
|
|
13
|
-
const REGEXP_SPECIAL_CHARACTERS = new Set('.+^$()|\\'.split(''));
|
|
13
|
+
const REGEXP_SPECIAL_CHARACTERS = new Set('.+^$()|\\[]{}*?'.split(''));
|
|
14
14
|
/**
|
|
15
15
|
* Translates a glob pattern into an anchored regular expression matching
|
|
16
16
|
* slash-separated paths.
|
|
@@ -61,8 +61,15 @@ export function globToRegExp(pattern) {
|
|
|
61
61
|
}
|
|
62
62
|
}
|
|
63
63
|
else if (character === '{') {
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
// A brace with nothing closing it is taken literally, as an unclosed
|
|
65
|
+
// `[` is, rather than leaving a group open in the regular expression.
|
|
66
|
+
if (findClosingBrace(pattern, index) === -1) {
|
|
67
|
+
source += '\\{';
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
braceDepth++;
|
|
71
|
+
source += '(?:';
|
|
72
|
+
}
|
|
66
73
|
}
|
|
67
74
|
else if (character === '}' && braceDepth > 0) {
|
|
68
75
|
braceDepth--;
|
|
@@ -84,6 +91,23 @@ export function globToRegExp(pattern) {
|
|
|
84
91
|
function escapeLiteral(character) {
|
|
85
92
|
return REGEXP_SPECIAL_CHARACTERS.has(character) ? `\\${character}` : character;
|
|
86
93
|
}
|
|
94
|
+
/** Where the brace opened just before `from` closes, or -1 when it never does. */
|
|
95
|
+
function findClosingBrace(pattern, from) {
|
|
96
|
+
let depth = 1;
|
|
97
|
+
for (let index = from; index < pattern.length; index++) {
|
|
98
|
+
const character = pattern[index];
|
|
99
|
+
if (character === '\\') {
|
|
100
|
+
index++;
|
|
101
|
+
}
|
|
102
|
+
else if (character === '{') {
|
|
103
|
+
depth++;
|
|
104
|
+
}
|
|
105
|
+
else if (character === '}' && --depth === 0) {
|
|
106
|
+
return index;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return -1;
|
|
110
|
+
}
|
|
87
111
|
function findClosingBracket(pattern, from) {
|
|
88
112
|
for (let index = from + 1; index < pattern.length; index++) {
|
|
89
113
|
if (pattern[index] === ']')
|
|
@@ -91,23 +115,45 @@ function findClosingBracket(pattern, from) {
|
|
|
91
115
|
}
|
|
92
116
|
return -1;
|
|
93
117
|
}
|
|
94
|
-
/**
|
|
95
|
-
function
|
|
96
|
-
return /[*?[\]{}]
|
|
118
|
+
/** Escapes every character glob syntax would read, so the text matches only itself. */
|
|
119
|
+
export function escapeGlob(literal) {
|
|
120
|
+
return literal.replace(/[*?[\]{}\\]/g, '\\$&');
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* The path a pattern names when it holds no glob syntax, with its escapes
|
|
124
|
+
* removed, or `undefined` when it is a real pattern.
|
|
125
|
+
*/
|
|
126
|
+
export function literalPath(pattern) {
|
|
127
|
+
let literal = '';
|
|
128
|
+
for (let index = 0; index < pattern.length; index++) {
|
|
129
|
+
const character = pattern[index];
|
|
130
|
+
if (character === '\\' && index + 1 < pattern.length) {
|
|
131
|
+
literal += pattern[++index];
|
|
132
|
+
}
|
|
133
|
+
else if ('*?[]{}'.includes(character)) {
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
literal += character;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return literal;
|
|
97
141
|
}
|
|
98
142
|
/**
|
|
99
143
|
* The leading run of literal segments, used as the directory to start walking
|
|
100
|
-
* from so that `a/b/**` does not scan the whole tree
|
|
144
|
+
* from so that `a/b/**` does not scan the whole tree, with its escapes
|
|
145
|
+
* removed - and what is left of the pattern after it.
|
|
101
146
|
*/
|
|
102
|
-
function
|
|
147
|
+
function splitPattern(pattern) {
|
|
103
148
|
const segments = pattern.split('/');
|
|
104
149
|
const literal = [];
|
|
105
150
|
for (const segment of segments.slice(0, -1)) {
|
|
106
|
-
|
|
151
|
+
const name = literalPath(segment);
|
|
152
|
+
if (name === undefined)
|
|
107
153
|
break;
|
|
108
|
-
literal.push(
|
|
154
|
+
literal.push(name);
|
|
109
155
|
}
|
|
110
|
-
return literal.join('/');
|
|
156
|
+
return { prefix: literal.join('/'), rest: segments.slice(literal.length).join('/') };
|
|
111
157
|
}
|
|
112
158
|
/**
|
|
113
159
|
* The directory a pattern's search starts from - the leading run of literal
|
|
@@ -115,7 +161,7 @@ function staticPrefix(pattern) {
|
|
|
115
161
|
* anything the pattern could match.
|
|
116
162
|
*/
|
|
117
163
|
export function globRoot(pattern, cwd = process.cwd()) {
|
|
118
|
-
return path.resolve(cwd,
|
|
164
|
+
return path.resolve(cwd, splitPattern(pattern.split(path.sep).join('/')).prefix);
|
|
119
165
|
}
|
|
120
166
|
function isHidden(name) {
|
|
121
167
|
return name.startsWith('.');
|
|
@@ -197,22 +243,48 @@ async function* walkStream(root) {
|
|
|
197
243
|
}
|
|
198
244
|
}
|
|
199
245
|
/**
|
|
200
|
-
*
|
|
201
|
-
*
|
|
246
|
+
* Reads an ignore pattern as .gitignore does. A pattern with no slash, other
|
|
247
|
+
* than a trailing one, matches a name at any depth; one with a slash is
|
|
248
|
+
* anchored to the working directory, whether or not it starts with `./` or
|
|
249
|
+
* `/`; a trailing slash means directories only; and a leading `!` brings back
|
|
250
|
+
* what an earlier pattern left out.
|
|
251
|
+
*/
|
|
252
|
+
function toIgnoreRule(pattern) {
|
|
253
|
+
let text = pattern.split(path.sep).join('/');
|
|
254
|
+
const negated = text.startsWith('!');
|
|
255
|
+
if (negated) {
|
|
256
|
+
text = text.slice(1);
|
|
257
|
+
}
|
|
258
|
+
const directoryOnly = text.endsWith('/');
|
|
259
|
+
text = text.replace(/\/+$/u, '').replace(/^(?:\.\/)+/u, '');
|
|
260
|
+
const anchored = text.includes('/');
|
|
261
|
+
text = text.replace(/^\/+/u, '');
|
|
262
|
+
return { matches: globToRegExp(anchored ? text : `**/${text}`), negated, directoryOnly };
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* True when the path, or any directory leading to it, is ignored.
|
|
202
266
|
*
|
|
203
267
|
* Testing the parent directories is what makes an entry like `build` or `o*e`
|
|
204
268
|
* skip the whole directory rather than only a file of that exact name. Without
|
|
205
269
|
* it an ignore file has to spell out `build/**` everywhere, which is not how
|
|
206
|
-
* .gitignore or .eslintignore behave.
|
|
270
|
+
* .gitignore or .eslintignore behave. As there, the last pattern to match a
|
|
271
|
+
* path decides, and nothing inside an ignored directory can be brought back.
|
|
207
272
|
*/
|
|
208
|
-
function isIgnored(relativePath,
|
|
209
|
-
if (
|
|
273
|
+
function isIgnored(relativePath, rules) {
|
|
274
|
+
if (rules.length === 0) {
|
|
210
275
|
return false;
|
|
211
276
|
}
|
|
212
277
|
const segments = relativePath.split('/');
|
|
213
278
|
for (let depth = 1; depth <= segments.length; depth++) {
|
|
214
279
|
const prefix = segments.slice(0, depth).join('/');
|
|
215
|
-
|
|
280
|
+
const isDirectory = depth < segments.length;
|
|
281
|
+
let ignored = false;
|
|
282
|
+
for (const rule of rules) {
|
|
283
|
+
if ((isDirectory || !rule.directoryOnly) && rule.matches.test(prefix)) {
|
|
284
|
+
ignored = !rule.negated;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (ignored) {
|
|
216
288
|
return true;
|
|
217
289
|
}
|
|
218
290
|
}
|
|
@@ -221,18 +293,35 @@ function isIgnored(relativePath, ignores) {
|
|
|
221
293
|
function newSearch(pattern, options) {
|
|
222
294
|
const cwd = options.cwd ?? process.cwd();
|
|
223
295
|
const normalisedPattern = pattern.split(path.sep).join('/');
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
//
|
|
227
|
-
//
|
|
296
|
+
const ignores = (options.ignore ?? []).map(toIgnoreRule);
|
|
297
|
+
// Matched against absolute paths, with the literal start of the pattern
|
|
298
|
+
// resolved first. Comparing the pattern as written with a path relative to
|
|
299
|
+
// cwd goes wrong whenever the two spell the same place differently -
|
|
300
|
+
// `./features/a.feature` against `features/a.feature`, or `../**` against
|
|
301
|
+
// a file below cwd, which has no `../` at all - and the search comes back
|
|
228
302
|
// empty rather than wrong, which reads as "nothing to report".
|
|
229
|
-
|
|
303
|
+
//
|
|
304
|
+
// A pattern holding no glob syntax names one path, which is looked at
|
|
305
|
+
// directly rather than searched for, so a file named on purpose is found
|
|
306
|
+
// even where a search would pass it by: a dotfile, or a symlink.
|
|
307
|
+
const literal = literalPath(normalisedPattern);
|
|
308
|
+
let searchRoot;
|
|
309
|
+
let matches;
|
|
310
|
+
if (literal !== undefined) {
|
|
311
|
+
searchRoot = path.resolve(cwd, literal);
|
|
312
|
+
matches = globToRegExp(escapeGlob(searchRoot.split(path.sep).join('/')));
|
|
313
|
+
}
|
|
314
|
+
else {
|
|
315
|
+
const { prefix, rest } = splitPattern(normalisedPattern);
|
|
316
|
+
searchRoot = path.resolve(cwd, prefix);
|
|
317
|
+
const root = searchRoot.split(path.sep).join('/').replace(/\/$/, '');
|
|
318
|
+
matches = globToRegExp(`${escapeGlob(root)}/${rest}`);
|
|
319
|
+
}
|
|
230
320
|
return {
|
|
231
|
-
searchRoot
|
|
321
|
+
searchRoot,
|
|
232
322
|
match(absolutePath) {
|
|
233
323
|
const relativePath = path.relative(cwd, absolutePath).split(path.sep).join('/');
|
|
234
|
-
|
|
235
|
-
if (!matches.test(candidate))
|
|
324
|
+
if (!matches.test(absolutePath.split(path.sep).join('/')))
|
|
236
325
|
return undefined;
|
|
237
326
|
if (isIgnored(relativePath, ignores))
|
|
238
327
|
return undefined;
|
|
@@ -304,4 +393,3 @@ function statOrUndefined(target) {
|
|
|
304
393
|
return undefined;
|
|
305
394
|
}
|
|
306
395
|
}
|
|
307
|
-
//# sourceMappingURL=glob.js.map
|
package/dist/util/json.d.ts
CHANGED
package/dist/util/json.js
CHANGED
package/dist/util/lines.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Helpers for looking at a feature file as plain text.
|
|
3
3
|
*/
|
|
4
|
+
import type { Feature } from '@cucumber/messages';
|
|
4
5
|
import type { FeatureFile } from '../types.ts';
|
|
5
6
|
/**
|
|
6
7
|
* The lines a person would see in their editor.
|
|
@@ -17,8 +18,9 @@ export declare function contentLines(file: FeatureFile): string[];
|
|
|
17
18
|
* Text inside a doc string is data belonging to the step, not part of the
|
|
18
19
|
* layout of the file, so rules about formatting have to leave it alone.
|
|
19
20
|
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
21
|
+
* Given the parsed document, the doc strings are taken from it, which is
|
|
22
|
+
* exact. Without one - a file the parser rejected - the raw lines are read
|
|
23
|
+
* instead, and a line opening with a delimiter is taken to open a doc
|
|
24
|
+
* string, which a description line starting with `"""` also does.
|
|
22
25
|
*/
|
|
23
|
-
export declare function markDocStrings(lines: readonly string[]): boolean[];
|
|
24
|
-
//# sourceMappingURL=lines.d.ts.map
|
|
26
|
+
export declare function markDocStrings(lines: readonly string[], feature?: Feature): boolean[];
|
package/dist/util/lines.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { stepContainersOf } from '../gherkin/traverse.js';
|
|
1
2
|
/**
|
|
2
3
|
* The lines a person would see in their editor.
|
|
3
4
|
*
|
|
@@ -18,11 +19,29 @@ const DOC_STRING_DELIMITERS = ['"""', '```'];
|
|
|
18
19
|
* Text inside a doc string is data belonging to the step, not part of the
|
|
19
20
|
* layout of the file, so rules about formatting have to leave it alone.
|
|
20
21
|
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
22
|
+
* Given the parsed document, the doc strings are taken from it, which is
|
|
23
|
+
* exact. Without one - a file the parser rejected - the raw lines are read
|
|
24
|
+
* instead, and a line opening with a delimiter is taken to open a doc
|
|
25
|
+
* string, which a description line starting with `"""` also does.
|
|
23
26
|
*/
|
|
24
|
-
export function markDocStrings(lines) {
|
|
27
|
+
export function markDocStrings(lines, feature) {
|
|
25
28
|
const inside = new Array(lines.length).fill(false);
|
|
29
|
+
if (feature !== undefined) {
|
|
30
|
+
for (const { node } of stepContainersOf(feature)) {
|
|
31
|
+
for (const step of node.steps) {
|
|
32
|
+
if (step.docString === undefined)
|
|
33
|
+
continue;
|
|
34
|
+
const { content, location } = step.docString;
|
|
35
|
+
const contentLines = content === '' ? 0 : content.split('\n').length;
|
|
36
|
+
// The opening delimiter, the content, and the closing delimiter.
|
|
37
|
+
const last = location.line + contentLines + 1;
|
|
38
|
+
for (let line = location.line; line <= last && line <= lines.length; line++) {
|
|
39
|
+
inside[line - 1] = true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return inside;
|
|
44
|
+
}
|
|
26
45
|
let openDelimiter;
|
|
27
46
|
lines.forEach((line, index) => {
|
|
28
47
|
const trimmed = line.trim();
|
|
@@ -42,4 +61,3 @@ export function markDocStrings(lines) {
|
|
|
42
61
|
});
|
|
43
62
|
return inside;
|
|
44
63
|
}
|
|
45
|
-
//# sourceMappingURL=lines.js.map
|