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.
Files changed (259) hide show
  1. package/LICENSE +13 -0
  2. package/README.md +327 -0
  3. package/dist/config-parser.d.ts +21 -0
  4. package/dist/config-parser.d.ts.map +1 -0
  5. package/dist/config-parser.js +171 -0
  6. package/dist/config-parser.js.map +1 -0
  7. package/dist/config-verifier.d.ts +4 -0
  8. package/dist/config-verifier.d.ts.map +1 -0
  9. package/dist/config-verifier.js +81 -0
  10. package/dist/config-verifier.js.map +1 -0
  11. package/dist/feature-finder.d.ts +18 -0
  12. package/dist/feature-finder.d.ts.map +1 -0
  13. package/dist/feature-finder.js +70 -0
  14. package/dist/feature-finder.js.map +1 -0
  15. package/dist/formatters/index.d.ts +23 -0
  16. package/dist/formatters/index.d.ts.map +1 -0
  17. package/dist/formatters/index.js +79 -0
  18. package/dist/formatters/index.js.map +1 -0
  19. package/dist/formatters/json.d.ts +31 -0
  20. package/dist/formatters/json.d.ts.map +1 -0
  21. package/dist/formatters/json.js +31 -0
  22. package/dist/formatters/json.js.map +1 -0
  23. package/dist/formatters/junit.d.ts +17 -0
  24. package/dist/formatters/junit.d.ts.map +1 -0
  25. package/dist/formatters/junit.js +61 -0
  26. package/dist/formatters/junit.js.map +1 -0
  27. package/dist/formatters/sarif.d.ts +6 -0
  28. package/dist/formatters/sarif.d.ts.map +1 -0
  29. package/dist/formatters/sarif.js +81 -0
  30. package/dist/formatters/sarif.js.map +1 -0
  31. package/dist/formatters/stylish.d.ts +9 -0
  32. package/dist/formatters/stylish.d.ts.map +1 -0
  33. package/dist/formatters/stylish.js +66 -0
  34. package/dist/formatters/stylish.js.map +1 -0
  35. package/dist/formatters/tap.d.ts +14 -0
  36. package/dist/formatters/tap.d.ts.map +1 -0
  37. package/dist/formatters/tap.js +45 -0
  38. package/dist/formatters/tap.js.map +1 -0
  39. package/dist/gherkin/dialects.d.ts +31 -0
  40. package/dist/gherkin/dialects.d.ts.map +1 -0
  41. package/dist/gherkin/dialects.js +40 -0
  42. package/dist/gherkin/dialects.js.map +1 -0
  43. package/dist/gherkin/keywords.d.ts +21 -0
  44. package/dist/gherkin/keywords.d.ts.map +1 -0
  45. package/dist/gherkin/keywords.js +53 -0
  46. package/dist/gherkin/keywords.js.map +1 -0
  47. package/dist/gherkin/parse.d.ts +32 -0
  48. package/dist/gherkin/parse.d.ts.map +1 -0
  49. package/dist/gherkin/parse.js +236 -0
  50. package/dist/gherkin/parse.js.map +1 -0
  51. package/dist/gherkin/traverse.d.ts +45 -0
  52. package/dist/gherkin/traverse.d.ts.map +1 -0
  53. package/dist/gherkin/traverse.js +89 -0
  54. package/dist/gherkin/traverse.js.map +1 -0
  55. package/dist/gherkin/variables.d.ts +26 -0
  56. package/dist/gherkin/variables.d.ts.map +1 -0
  57. package/dist/gherkin/variables.js +51 -0
  58. package/dist/gherkin/variables.js.map +1 -0
  59. package/dist/index.d.ts +39 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +31 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/linter.d.ts +23 -0
  64. package/dist/linter.d.ts.map +1 -0
  65. package/dist/linter.js +57 -0
  66. package/dist/linter.js.map +1 -0
  67. package/dist/logger.d.ts +16 -0
  68. package/dist/logger.d.ts.map +1 -0
  69. package/dist/logger.js +28 -0
  70. package/dist/logger.js.map +1 -0
  71. package/dist/main.d.ts +3 -0
  72. package/dist/main.d.ts.map +1 -0
  73. package/dist/main.js +144 -0
  74. package/dist/main.js.map +1 -0
  75. package/dist/presets.d.ts +19 -0
  76. package/dist/presets.d.ts.map +1 -0
  77. package/dist/presets.js +24 -0
  78. package/dist/presets.js.map +1 -0
  79. package/dist/rules/allowed-tags.d.ts +4 -0
  80. package/dist/rules/allowed-tags.d.ts.map +1 -0
  81. package/dist/rules/allowed-tags.js +34 -0
  82. package/dist/rules/allowed-tags.js.map +1 -0
  83. package/dist/rules/file-name.d.ts +4 -0
  84. package/dist/rules/file-name.d.ts.map +1 -0
  85. package/dist/rules/file-name.js +41 -0
  86. package/dist/rules/file-name.js.map +1 -0
  87. package/dist/rules/indentation.d.ts +4 -0
  88. package/dist/rules/indentation.d.ts.map +1 -0
  89. package/dist/rules/indentation.js +153 -0
  90. package/dist/rules/indentation.js.map +1 -0
  91. package/dist/rules/index.d.ts +13 -0
  92. package/dist/rules/index.d.ts.map +1 -0
  93. package/dist/rules/index.js +70 -0
  94. package/dist/rules/index.js.map +1 -0
  95. package/dist/rules/keywords-in-logical-order.d.ts +4 -0
  96. package/dist/rules/keywords-in-logical-order.d.ts.map +1 -0
  97. package/dist/rules/keywords-in-logical-order.js +37 -0
  98. package/dist/rules/keywords-in-logical-order.js.map +1 -0
  99. package/dist/rules/max-scenarios-per-file.d.ts +4 -0
  100. package/dist/rules/max-scenarios-per-file.d.ts.map +1 -0
  101. package/dist/rules/max-scenarios-per-file.js +42 -0
  102. package/dist/rules/max-scenarios-per-file.js.map +1 -0
  103. package/dist/rules/name-length.d.ts +4 -0
  104. package/dist/rules/name-length.d.ts.map +1 -0
  105. package/dist/rules/name-length.js +50 -0
  106. package/dist/rules/name-length.js.map +1 -0
  107. package/dist/rules/new-line-at-eof.d.ts +4 -0
  108. package/dist/rules/new-line-at-eof.d.ts.map +1 -0
  109. package/dist/rules/new-line-at-eof.js +30 -0
  110. package/dist/rules/new-line-at-eof.js.map +1 -0
  111. package/dist/rules/no-background-only-scenario.d.ts +4 -0
  112. package/dist/rules/no-background-only-scenario.d.ts.map +1 -0
  113. package/dist/rules/no-background-only-scenario.js +43 -0
  114. package/dist/rules/no-background-only-scenario.js.map +1 -0
  115. package/dist/rules/no-dupe-feature-names.d.ts +4 -0
  116. package/dist/rules/no-dupe-feature-names.d.ts.map +1 -0
  117. package/dist/rules/no-dupe-feature-names.js +25 -0
  118. package/dist/rules/no-dupe-feature-names.js.map +1 -0
  119. package/dist/rules/no-dupe-file-names.d.ts +4 -0
  120. package/dist/rules/no-dupe-file-names.d.ts.map +1 -0
  121. package/dist/rules/no-dupe-file-names.js +28 -0
  122. package/dist/rules/no-dupe-file-names.js.map +1 -0
  123. package/dist/rules/no-dupe-scenario-names.d.ts +4 -0
  124. package/dist/rules/no-dupe-scenario-names.d.ts.map +1 -0
  125. package/dist/rules/no-dupe-scenario-names.js +41 -0
  126. package/dist/rules/no-dupe-scenario-names.js.map +1 -0
  127. package/dist/rules/no-duplicate-tags.d.ts +4 -0
  128. package/dist/rules/no-duplicate-tags.d.ts.map +1 -0
  129. package/dist/rules/no-duplicate-tags.js +38 -0
  130. package/dist/rules/no-duplicate-tags.js.map +1 -0
  131. package/dist/rules/no-empty-background.d.ts +4 -0
  132. package/dist/rules/no-empty-background.d.ts.map +1 -0
  133. package/dist/rules/no-empty-background.js +24 -0
  134. package/dist/rules/no-empty-background.js.map +1 -0
  135. package/dist/rules/no-empty-file.d.ts +4 -0
  136. package/dist/rules/no-empty-file.d.ts.map +1 -0
  137. package/dist/rules/no-empty-file.js +12 -0
  138. package/dist/rules/no-empty-file.js.map +1 -0
  139. package/dist/rules/no-examples-in-scenarios.d.ts +4 -0
  140. package/dist/rules/no-examples-in-scenarios.d.ts.map +1 -0
  141. package/dist/rules/no-examples-in-scenarios.js +25 -0
  142. package/dist/rules/no-examples-in-scenarios.js.map +1 -0
  143. package/dist/rules/no-files-without-scenarios.d.ts +4 -0
  144. package/dist/rules/no-files-without-scenarios.d.ts.map +1 -0
  145. package/dist/rules/no-files-without-scenarios.js +18 -0
  146. package/dist/rules/no-files-without-scenarios.js.map +1 -0
  147. package/dist/rules/no-homogenous-tags.d.ts +4 -0
  148. package/dist/rules/no-homogenous-tags.d.ts.map +1 -0
  149. package/dist/rules/no-homogenous-tags.js +54 -0
  150. package/dist/rules/no-homogenous-tags.js.map +1 -0
  151. package/dist/rules/no-multiple-empty-lines.d.ts +4 -0
  152. package/dist/rules/no-multiple-empty-lines.d.ts.map +1 -0
  153. package/dist/rules/no-multiple-empty-lines.js +44 -0
  154. package/dist/rules/no-multiple-empty-lines.js.map +1 -0
  155. package/dist/rules/no-partially-commented-tag-lines.d.ts +4 -0
  156. package/dist/rules/no-partially-commented-tag-lines.d.ts.map +1 -0
  157. package/dist/rules/no-partially-commented-tag-lines.js +44 -0
  158. package/dist/rules/no-partially-commented-tag-lines.js.map +1 -0
  159. package/dist/rules/no-restricted-patterns.d.ts +4 -0
  160. package/dist/rules/no-restricted-patterns.d.ts.map +1 -0
  161. package/dist/rules/no-restricted-patterns.js +101 -0
  162. package/dist/rules/no-restricted-patterns.js.map +1 -0
  163. package/dist/rules/no-restricted-tags.d.ts +4 -0
  164. package/dist/rules/no-restricted-tags.d.ts.map +1 -0
  165. package/dist/rules/no-restricted-tags.js +35 -0
  166. package/dist/rules/no-restricted-tags.js.map +1 -0
  167. package/dist/rules/no-scenario-outlines-without-examples.d.ts +4 -0
  168. package/dist/rules/no-scenario-outlines-without-examples.d.ts.map +1 -0
  169. package/dist/rules/no-scenario-outlines-without-examples.js +29 -0
  170. package/dist/rules/no-scenario-outlines-without-examples.js.map +1 -0
  171. package/dist/rules/no-superfluous-tags.d.ts +4 -0
  172. package/dist/rules/no-superfluous-tags.d.ts.map +1 -0
  173. package/dist/rules/no-superfluous-tags.js +40 -0
  174. package/dist/rules/no-superfluous-tags.js.map +1 -0
  175. package/dist/rules/no-trailing-spaces.d.ts +4 -0
  176. package/dist/rules/no-trailing-spaces.d.ts.map +1 -0
  177. package/dist/rules/no-trailing-spaces.js +24 -0
  178. package/dist/rules/no-trailing-spaces.js.map +1 -0
  179. package/dist/rules/no-undeclared-variables.d.ts +4 -0
  180. package/dist/rules/no-undeclared-variables.d.ts.map +1 -0
  181. package/dist/rules/no-undeclared-variables.js +35 -0
  182. package/dist/rules/no-undeclared-variables.js.map +1 -0
  183. package/dist/rules/no-unnamed-features.d.ts +4 -0
  184. package/dist/rules/no-unnamed-features.d.ts.map +1 -0
  185. package/dist/rules/no-unnamed-features.js +19 -0
  186. package/dist/rules/no-unnamed-features.js.map +1 -0
  187. package/dist/rules/no-unnamed-scenarios.d.ts +4 -0
  188. package/dist/rules/no-unnamed-scenarios.d.ts.map +1 -0
  189. package/dist/rules/no-unnamed-scenarios.js +24 -0
  190. package/dist/rules/no-unnamed-scenarios.js.map +1 -0
  191. package/dist/rules/no-unused-variables.d.ts +4 -0
  192. package/dist/rules/no-unused-variables.d.ts.map +1 -0
  193. package/dist/rules/no-unused-variables.js +36 -0
  194. package/dist/rules/no-unused-variables.js.map +1 -0
  195. package/dist/rules/one-space-between-tags.d.ts +4 -0
  196. package/dist/rules/one-space-between-tags.d.ts.map +1 -0
  197. package/dist/rules/one-space-between-tags.js +36 -0
  198. package/dist/rules/one-space-between-tags.js.map +1 -0
  199. package/dist/rules/only-one-when.d.ts +4 -0
  200. package/dist/rules/only-one-when.d.ts.map +1 -0
  201. package/dist/rules/only-one-when.js +59 -0
  202. package/dist/rules/only-one-when.js.map +1 -0
  203. package/dist/rules/required-tags.d.ts +4 -0
  204. package/dist/rules/required-tags.d.ts.map +1 -0
  205. package/dist/rules/required-tags.js +36 -0
  206. package/dist/rules/required-tags.js.map +1 -0
  207. package/dist/rules/scenario-size.d.ts +4 -0
  208. package/dist/rules/scenario-size.d.ts.map +1 -0
  209. package/dist/rules/scenario-size.js +37 -0
  210. package/dist/rules/scenario-size.js.map +1 -0
  211. package/dist/rules/use-and.d.ts +4 -0
  212. package/dist/rules/use-and.d.ts.map +1 -0
  213. package/dist/rules/use-and.js +33 -0
  214. package/dist/rules/use-and.js.map +1 -0
  215. package/dist/rules.d.ts +24 -0
  216. package/dist/rules.d.ts.map +1 -0
  217. package/dist/rules.js +109 -0
  218. package/dist/rules.js.map +1 -0
  219. package/dist/suppressions.d.ts +33 -0
  220. package/dist/suppressions.d.ts.map +1 -0
  221. package/dist/suppressions.js +84 -0
  222. package/dist/suppressions.js.map +1 -0
  223. package/dist/types.d.ts +81 -0
  224. package/dist/types.d.ts.map +1 -0
  225. package/dist/types.js +2 -0
  226. package/dist/types.js.map +1 -0
  227. package/dist/util/case.d.ts +21 -0
  228. package/dist/util/case.d.ts.map +1 -0
  229. package/dist/util/case.js +42 -0
  230. package/dist/util/case.js.map +1 -0
  231. package/dist/util/collections.d.ts +30 -0
  232. package/dist/util/collections.d.ts.map +1 -0
  233. package/dist/util/collections.js +87 -0
  234. package/dist/util/collections.js.map +1 -0
  235. package/dist/util/glob.d.ts +20 -0
  236. package/dist/util/glob.d.ts.map +1 -0
  237. package/dist/util/glob.js +203 -0
  238. package/dist/util/glob.js.map +1 -0
  239. package/dist/util/json.d.ts +14 -0
  240. package/dist/util/json.d.ts.map +1 -0
  241. package/dist/util/json.js +63 -0
  242. package/dist/util/json.js.map +1 -0
  243. package/dist/util/lines.d.ts +24 -0
  244. package/dist/util/lines.d.ts.map +1 -0
  245. package/dist/util/lines.js +45 -0
  246. package/dist/util/lines.js.map +1 -0
  247. package/dist/util/location.d.ts +15 -0
  248. package/dist/util/location.d.ts.map +1 -0
  249. package/dist/util/location.js +11 -0
  250. package/dist/util/location.js.map +1 -0
  251. package/dist/util/xml.d.ts +16 -0
  252. package/dist/util/xml.d.ts.map +1 -0
  253. package/dist/util/xml.js +36 -0
  254. package/dist/util/xml.js.map +1 -0
  255. package/dist/version.d.ts +3 -0
  256. package/dist/version.d.ts.map +1 -0
  257. package/dist/version.js +24 -0
  258. package/dist/version.js.map +1 -0
  259. package/package.json +61 -0
@@ -0,0 +1,41 @@
1
+ import { scenariosOf } from '../gherkin/traverse.js';
2
+ import { at } from '../util/location.js';
3
+ const name = 'no-dupe-scenario-names';
4
+ /** Whether duplicates are looked for across all files or within each file. */
5
+ const availableConfigs = ['anywhere', 'in-feature'];
6
+ /** Scenario name -> everywhere it has already been seen. */
7
+ const seen = new Map();
8
+ const rule = {
9
+ name,
10
+ availableConfigs,
11
+ reset() {
12
+ seen.clear();
13
+ },
14
+ run(feature, file, configuration) {
15
+ if (feature === undefined) {
16
+ return [];
17
+ }
18
+ if (configuration === 'in-feature') {
19
+ seen.clear();
20
+ }
21
+ const errors = [];
22
+ for (const { scenario } of scenariosOf(feature)) {
23
+ const sighting = { file: file.relativePath, line: scenario.location.line };
24
+ const previous = seen.get(scenario.name);
25
+ if (previous === undefined) {
26
+ seen.set(scenario.name, [sighting]);
27
+ continue;
28
+ }
29
+ const where = previous.map((seenAt) => `${seenAt.file}:${seenAt.line}`).join(', ');
30
+ previous.push(sighting);
31
+ errors.push({
32
+ message: `Scenario name is already used in: ${where}`,
33
+ rule: name,
34
+ ...at(scenario.location),
35
+ });
36
+ }
37
+ return errors;
38
+ },
39
+ };
40
+ export default rule;
41
+ //# sourceMappingURL=no-dupe-scenario-names.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-dupe-scenario-names.js","sourceRoot":"","sources":["../../src/rules/no-dupe-scenario-names.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAC,EAAE,EAAC,MAAM,qBAAqB,CAAC;AAEvC,MAAM,IAAI,GAAG,wBAAwB,CAAC;AAEtC,8EAA8E;AAC9E,MAAM,gBAAgB,GAAG,CAAC,UAAU,EAAE,YAAY,CAAU,CAAC;AAO7D,4DAA4D;AAC5D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAsB,CAAC;AAE3C,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,gBAAgB;IAChB,KAAK;QACH,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IACD,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,aAAa;QAC9B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,IAAI,aAAa,KAAK,YAAY,EAAE,CAAC;YACnC,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;QAED,MAAM,MAAM,GAAgB,EAAE,CAAC;QAE/B,KAAK,MAAM,EAAC,QAAQ,EAAC,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9C,MAAM,QAAQ,GAAa,EAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,IAAI,EAAE,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAC,CAAC;YACnF,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAEzC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;gBACpC,SAAS;YACX,CAAC;YAED,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnF,QAAQ,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACxB,MAAM,CAAC,IAAI,CAAC;gBACV,OAAO,EAAE,qCAAqC,KAAK,EAAE;gBACrD,IAAI,EAAE,IAAI;gBACV,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;aACzB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintRule } from '../types.ts';
2
+ declare const rule: LintRule;
3
+ export default rule;
4
+ //# sourceMappingURL=no-duplicate-tags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-duplicate-tags.d.ts","sourceRoot":"","sources":["../../src/rules/no-duplicate-tags.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,QAAQ,EAAY,MAAM,aAAa,CAAC;AA0BrD,QAAA,MAAM,IAAI,EAAE,QAYX,CAAC;eAEa,IAAI"}
@@ -0,0 +1,38 @@
1
+ import { taggedNodesOf } from '../gherkin/traverse.js';
2
+ import { at } from '../util/location.js';
3
+ const name = 'no-duplicate-tags';
4
+ /**
5
+ * Reports every repeat of a tag, not just the first. Three copies of a tag
6
+ * are two mistakes, and being told about one at a time means running the
7
+ * linter again after each fix.
8
+ */
9
+ function checkTags(tags, errors) {
10
+ const seen = new Set();
11
+ for (const tag of tags) {
12
+ if (seen.has(tag.name)) {
13
+ errors.push({
14
+ message: `Duplicate tags are not allowed: ${tag.name}`,
15
+ rule: name,
16
+ ...at(tag.location),
17
+ });
18
+ }
19
+ else {
20
+ seen.add(tag.name);
21
+ }
22
+ }
23
+ }
24
+ const rule = {
25
+ name,
26
+ run(feature) {
27
+ if (feature === undefined) {
28
+ return [];
29
+ }
30
+ const errors = [];
31
+ for (const { node } of taggedNodesOf(feature)) {
32
+ checkTags(node.tags, errors);
33
+ }
34
+ return errors;
35
+ },
36
+ };
37
+ export default rule;
38
+ //# sourceMappingURL=no-duplicate-tags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-duplicate-tags.js","sourceRoot":"","sources":["../../src/rules/no-duplicate-tags.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAErD,OAAO,EAAC,EAAE,EAAC,MAAM,qBAAqB,CAAC;AAEvC,MAAM,IAAI,GAAG,mBAAmB,CAAC;AAEjC;;;;GAIG;AACH,SAAS,SAAS,CAAC,IAAoB,EAAE,MAAmB;IAC1D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAE/B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,MAAM,CAAC,IAAI,CAAC;gBACV,OAAO,EAAE,mCAAmC,GAAG,CAAC,IAAI,EAAE;gBACtD,IAAI,EAAE,IAAI;gBACV,GAAG,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC;aACpB,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACH,CAAC;AACH,CAAC;AAED,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,GAAG,CAAC,OAAO;QACT,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,MAAM,GAAgB,EAAE,CAAC;QAC/B,KAAK,MAAM,EAAC,IAAI,EAAC,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5C,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC/B,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintRule } from '../types.ts';
2
+ declare const rule: LintRule;
3
+ export default rule;
4
+ //# sourceMappingURL=no-empty-background.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-empty-background.d.ts","sourceRoot":"","sources":["../../src/rules/no-empty-background.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,QAAQ,EAAY,MAAM,aAAa,CAAC;AAKrD,QAAA,MAAM,IAAI,EAAE,QAkBX,CAAC;eAEa,IAAI"}
@@ -0,0 +1,24 @@
1
+ import { backgroundsOf } from '../gherkin/traverse.js';
2
+ import { at } from '../util/location.js';
3
+ const name = 'no-empty-background';
4
+ const rule = {
5
+ name,
6
+ run(feature) {
7
+ if (feature === undefined) {
8
+ return [];
9
+ }
10
+ const errors = [];
11
+ for (const { background } of backgroundsOf(feature)) {
12
+ if (background.steps.length === 0) {
13
+ errors.push({
14
+ message: 'Empty backgrounds are not allowed.',
15
+ rule: name,
16
+ ...at(background.location),
17
+ });
18
+ }
19
+ }
20
+ return errors;
21
+ },
22
+ };
23
+ export default rule;
24
+ //# sourceMappingURL=no-empty-background.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-empty-background.js","sourceRoot":"","sources":["../../src/rules/no-empty-background.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAErD,OAAO,EAAC,EAAE,EAAC,MAAM,qBAAqB,CAAC;AAEvC,MAAM,IAAI,GAAG,qBAAqB,CAAC;AAEnC,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,GAAG,CAAC,OAAO;QACT,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,MAAM,GAAgB,EAAE,CAAC;QAC/B,KAAK,MAAM,EAAC,UAAU,EAAC,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YAClD,IAAI,UAAU,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAClC,MAAM,CAAC,IAAI,CAAC;oBACV,OAAO,EAAE,oCAAoC;oBAC7C,IAAI,EAAE,IAAI;oBACV,GAAG,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC;iBAC3B,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintRule } from '../types.ts';
2
+ declare const rule: LintRule;
3
+ export default rule;
4
+ //# sourceMappingURL=no-empty-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-empty-file.d.ts","sourceRoot":"","sources":["../../src/rules/no-empty-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAI1C,QAAA,MAAM,IAAI,EAAE,QAQX,CAAC;eAEa,IAAI"}
@@ -0,0 +1,12 @@
1
+ const name = 'no-empty-file';
2
+ const rule = {
3
+ name,
4
+ run(feature) {
5
+ if (feature !== undefined) {
6
+ return [];
7
+ }
8
+ return [{ message: 'Empty feature files are disallowed', rule: name, line: 1 }];
9
+ },
10
+ };
11
+ export default rule;
12
+ //# sourceMappingURL=no-empty-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-empty-file.js","sourceRoot":"","sources":["../../src/rules/no-empty-file.ts"],"names":[],"mappings":"AAEA,MAAM,IAAI,GAAG,eAAe,CAAC;AAE7B,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,GAAG,CAAC,OAAO;QACT,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,CAAC,EAAC,OAAO,EAAE,oCAAoC,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAC,CAAC,CAAC;IAChF,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintRule } from '../types.ts';
2
+ declare const rule: LintRule;
3
+ export default rule;
4
+ //# sourceMappingURL=no-examples-in-scenarios.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-examples-in-scenarios.d.ts","sourceRoot":"","sources":["../../src/rules/no-examples-in-scenarios.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,QAAQ,EAAY,MAAM,aAAa,CAAC;AAKrD,QAAA,MAAM,IAAI,EAAE,QAqBX,CAAC;eAEa,IAAI"}
@@ -0,0 +1,25 @@
1
+ import { getNodeType } from '../gherkin/keywords.js';
2
+ import { scenariosOf } from '../gherkin/traverse.js';
3
+ import { at } from '../util/location.js';
4
+ const name = 'no-examples-in-scenarios';
5
+ const rule = {
6
+ name,
7
+ run(feature) {
8
+ if (feature === undefined) {
9
+ return [];
10
+ }
11
+ const errors = [];
12
+ for (const { scenario } of scenariosOf(feature)) {
13
+ if (getNodeType(scenario, feature.language) === 'Scenario' && scenario.examples.length > 0) {
14
+ errors.push({
15
+ message: 'Cannot use "Examples" in a "Scenario", use a "Scenario Outline" instead',
16
+ rule: name,
17
+ ...at(scenario.location),
18
+ });
19
+ }
20
+ }
21
+ return errors;
22
+ },
23
+ };
24
+ export default rule;
25
+ //# sourceMappingURL=no-examples-in-scenarios.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-examples-in-scenarios.js","sourceRoot":"","sources":["../../src/rules/no-examples-in-scenarios.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAC,WAAW,EAAC,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAC,EAAE,EAAC,MAAM,qBAAqB,CAAC;AAEvC,MAAM,IAAI,GAAG,0BAA0B,CAAC;AAExC,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,GAAG,CAAC,OAAO;QACT,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,MAAM,GAAgB,EAAE,CAAC;QAE/B,KAAK,MAAM,EAAC,QAAQ,EAAC,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9C,IAAI,WAAW,CAAC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,KAAK,UAAU,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3F,MAAM,CAAC,IAAI,CAAC;oBACV,OAAO,EAAE,yEAAyE;oBAClF,IAAI,EAAE,IAAI;oBACV,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;iBACzB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintRule } from '../types.ts';
2
+ declare const rule: LintRule;
3
+ export default rule;
4
+ //# sourceMappingURL=no-files-without-scenarios.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-files-without-scenarios.d.ts","sourceRoot":"","sources":["../../src/rules/no-files-without-scenarios.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAC,QAAQ,EAAC,MAAM,aAAa,CAAC;AAW1C,QAAA,MAAM,IAAI,EAAE,QAQX,CAAC;eAEa,IAAI"}
@@ -0,0 +1,18 @@
1
+ const name = 'no-files-without-scenarios';
2
+ function hasScenario(child) {
3
+ if (child.scenario !== undefined) {
4
+ return true;
5
+ }
6
+ return 'rule' in child && child.rule !== undefined && child.rule.children.some(hasScenario);
7
+ }
8
+ const rule = {
9
+ name,
10
+ run(feature) {
11
+ if (feature === undefined || feature.children.some(hasScenario)) {
12
+ return [];
13
+ }
14
+ return [{ message: 'Feature file does not have any Scenarios', rule: name, line: 1 }];
15
+ },
16
+ };
17
+ export default rule;
18
+ //# sourceMappingURL=no-files-without-scenarios.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-files-without-scenarios.js","sourceRoot":"","sources":["../../src/rules/no-files-without-scenarios.ts"],"names":[],"mappings":"AAGA,MAAM,IAAI,GAAG,4BAA4B,CAAC;AAE1C,SAAS,WAAW,CAAC,KAA+B;IAClD,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;AAC9F,CAAC;AAED,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,GAAG,CAAC,OAAO;QACT,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC;YAChE,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,OAAO,CAAC,EAAC,OAAO,EAAE,0CAA0C,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,EAAC,CAAC,CAAC;IACtF,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintRule } from '../types.ts';
2
+ declare const rule: LintRule;
3
+ export default rule;
4
+ //# sourceMappingURL=no-homogenous-tags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-homogenous-tags.d.ts","sourceRoot":"","sources":["../../src/rules/no-homogenous-tags.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,QAAQ,EAAY,MAAM,aAAa,CAAC;AAUrD,QAAA,MAAM,IAAI,EAAE,QAoDX,CAAC;eAEa,IAAI"}
@@ -0,0 +1,54 @@
1
+ import { scenariosOf } from '../gherkin/traverse.js';
2
+ import { intersection } from '../util/collections.js';
3
+ import { at } from '../util/location.js';
4
+ const name = 'no-homogenous-tags';
5
+ function tagNames(tags) {
6
+ return tags.map((tag) => tag.name);
7
+ }
8
+ const rule = {
9
+ name,
10
+ run(feature) {
11
+ if (feature === undefined) {
12
+ return [];
13
+ }
14
+ const errors = [];
15
+ const scenarioTags = [];
16
+ // One error per tag rather than one summary listing them all, so that
17
+ // each finding points at a single thing to fix, the way every other
18
+ // rule reports.
19
+ for (const { scenario } of scenariosOf(feature)) {
20
+ scenarioTags.push(tagNames(scenario.tags));
21
+ // "Every Examples table has this tag" says nothing when there is only
22
+ // one of them, and hoisting the tag would change what it means as soon
23
+ // as a second table is added.
24
+ if (scenario.examples.length < 2) {
25
+ continue;
26
+ }
27
+ for (const tag of intersection(scenario.examples.map((e) => tagNames(e.tags)))) {
28
+ errors.push({
29
+ message: 'Every Examples table of this Scenario Outline has the tag ' +
30
+ `${tag}, it should be defined on the Scenario Outline instead`,
31
+ rule: name,
32
+ ...at(scenario.location),
33
+ });
34
+ }
35
+ }
36
+ // Likewise, a single scenario's tags are not shared with anything. Tags
37
+ // that identify one scenario - a ticket reference, say - belong on the
38
+ // scenario, and moving them to the Feature would be wrong advice.
39
+ if (scenarioTags.length < 2) {
40
+ return errors;
41
+ }
42
+ for (const tag of intersection(scenarioTags)) {
43
+ errors.push({
44
+ message: `Every Scenario on this Feature has the tag ${tag}, ` +
45
+ 'it should be defined on the Feature instead',
46
+ rule: name,
47
+ ...at(feature.location),
48
+ });
49
+ }
50
+ return errors;
51
+ },
52
+ };
53
+ export default rule;
54
+ //# sourceMappingURL=no-homogenous-tags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-homogenous-tags.js","sourceRoot":"","sources":["../../src/rules/no-homogenous-tags.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,WAAW,EAAC,MAAM,wBAAwB,CAAC;AAEnD,OAAO,EAAC,YAAY,EAAC,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAC,EAAE,EAAC,MAAM,qBAAqB,CAAC;AAEvC,MAAM,IAAI,GAAG,oBAAoB,CAAC;AAElC,SAAS,QAAQ,CAAC,IAAoB;IACpC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,GAAG,CAAC,OAAO;QACT,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,MAAM,GAAgB,EAAE,CAAC;QAC/B,MAAM,YAAY,GAAe,EAAE,CAAC;QAEpC,sEAAsE;QACtE,oEAAoE;QACpE,gBAAgB;QAChB,KAAK,MAAM,EAAC,QAAQ,EAAC,IAAI,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;YAC9C,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;YAE3C,sEAAsE;YACtE,uEAAuE;YACvE,8BAA8B;YAC9B,IAAI,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACjC,SAAS;YACX,CAAC;YACD,KAAK,MAAM,GAAG,IAAI,YAAY,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC/E,MAAM,CAAC,IAAI,CAAC;oBACV,OAAO,EACL,4DAA4D;wBAC5D,GAAG,GAAG,wDAAwD;oBAChE,IAAI,EAAE,IAAI;oBACV,GAAG,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC;iBACzB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,wEAAwE;QACxE,uEAAuE;QACvE,kEAAkE;QAClE,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC5B,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,KAAK,MAAM,GAAG,IAAI,YAAY,CAAC,YAAY,CAAC,EAAE,CAAC;YAC7C,MAAM,CAAC,IAAI,CAAC;gBACV,OAAO,EACL,8CAA8C,GAAG,IAAI;oBACrD,6CAA6C;gBAC/C,IAAI,EAAE,IAAI;gBACV,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC;aACxB,CAAC,CAAC;QACL,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintRule } from '../types.ts';
2
+ declare const rule: LintRule;
3
+ export default rule;
4
+ //# sourceMappingURL=no-multiple-empty-lines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-multiple-empty-lines.d.ts","sourceRoot":"","sources":["../../src/rules/no-multiple-empty-lines.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,QAAQ,EAAY,MAAM,aAAa,CAAC;AAiBrD,QAAA,MAAM,IAAI,EAAE,QAiCX,CAAC;eAEa,IAAI"}
@@ -0,0 +1,44 @@
1
+ import { mergeDefaults } from '../util/collections.js';
2
+ import { contentLines, markDocStrings } from '../util/lines.js';
3
+ const name = 'no-multiple-empty-lines';
4
+ const availableConfigs = {
5
+ /** How many blank lines may sit next to each other. */
6
+ max: 1,
7
+ };
8
+ function messageFor(max) {
9
+ return max === 1
10
+ ? 'Multiple empty lines are not allowed'
11
+ : `More than ${max} empty lines in a row are not allowed`;
12
+ }
13
+ const rule = {
14
+ name,
15
+ availableConfigs,
16
+ run(_feature, file, configuration) {
17
+ const { max } = mergeDefaults(availableConfigs, configuration);
18
+ const lines = contentLines(file);
19
+ const inDocString = markDocStrings(lines);
20
+ const message = messageFor(max);
21
+ const errors = [];
22
+ let blanksInARow = 0;
23
+ lines.forEach((line, index) => {
24
+ // Blank lines inside a doc string are part of the text being quoted,
25
+ // and they do not join up runs of blank lines on either side of it.
26
+ if (inDocString[index] === true) {
27
+ blanksInARow = 0;
28
+ return;
29
+ }
30
+ if (line.trim() !== '') {
31
+ blanksInARow = 0;
32
+ return;
33
+ }
34
+ blanksInARow++;
35
+ // One error per blank line past the limit, pointing at that line.
36
+ if (blanksInARow > max) {
37
+ errors.push({ message, rule: name, line: index + 1 });
38
+ }
39
+ });
40
+ return errors;
41
+ },
42
+ };
43
+ export default rule;
44
+ //# sourceMappingURL=no-multiple-empty-lines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-multiple-empty-lines.js","sourceRoot":"","sources":["../../src/rules/no-multiple-empty-lines.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAC,YAAY,EAAE,cAAc,EAAC,MAAM,kBAAkB,CAAC;AAE9D,MAAM,IAAI,GAAG,yBAAyB,CAAC;AAEvC,MAAM,gBAAgB,GAAG;IACvB,uDAAuD;IACvD,GAAG,EAAE,CAAC;CACP,CAAC;AAEF,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG,KAAK,CAAC;QACd,CAAC,CAAC,sCAAsC;QACxC,CAAC,CAAC,aAAa,GAAG,uCAAuC,CAAC;AAC9D,CAAC;AAED,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,gBAAgB;IAChB,GAAG,CAAC,QAAQ,EAAE,IAAI,EAAE,aAAa;QAC/B,MAAM,EAAC,GAAG,EAAC,GAAG,aAAa,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;QAC7D,MAAM,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAEhC,MAAM,MAAM,GAAgB,EAAE,CAAC;QAC/B,IAAI,YAAY,GAAG,CAAC,CAAC;QAErB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YAC5B,qEAAqE;YACrE,oEAAoE;YACpE,IAAI,WAAW,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC;gBAChC,YAAY,GAAG,CAAC,CAAC;gBACjB,OAAO;YACT,CAAC;YACD,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;gBACvB,YAAY,GAAG,CAAC,CAAC;gBACjB,OAAO;YACT,CAAC;YAED,YAAY,EAAE,CAAC;YACf,kEAAkE;YAClE,IAAI,YAAY,GAAG,GAAG,EAAE,CAAC;gBACvB,MAAM,CAAC,IAAI,CAAC,EAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,EAAC,CAAC,CAAC;YACtD,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintRule } from '../types.ts';
2
+ declare const rule: LintRule;
3
+ export default rule;
4
+ //# sourceMappingURL=no-partially-commented-tag-lines.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-partially-commented-tag-lines.d.ts","sourceRoot":"","sources":["../../src/rules/no-partially-commented-tag-lines.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,QAAQ,EAAY,MAAM,aAAa,CAAC;AAoBrD,QAAA,MAAM,IAAI,EAAE,QA0BX,CAAC;eAEa,IAAI"}
@@ -0,0 +1,44 @@
1
+ import { taggedNodesOf } from '../gherkin/traverse.js';
2
+ import { atLineColumn } from '../util/location.js';
3
+ const name = 'no-partially-commented-tag-lines';
4
+ /**
5
+ * A `#` on a tag line comments out everything after it. That is easy to do by
6
+ * accident and silently disables tags, so it is worth flagging.
7
+ *
8
+ * The check reads the original source line rather than the parsed tags,
9
+ * because by the time the file is parsed the commented-out part is gone.
10
+ * Only lines the parser identified as tag lines are looked at, so a `#`
11
+ * inside a doc string is not mistaken for one.
12
+ */
13
+ function collectTagLines(tags, into) {
14
+ for (const tag of tags) {
15
+ into.add(tag.location.line);
16
+ }
17
+ }
18
+ const rule = {
19
+ name,
20
+ run(feature, file) {
21
+ if (feature === undefined) {
22
+ return [];
23
+ }
24
+ const tagLines = new Set();
25
+ for (const { node } of taggedNodesOf(feature)) {
26
+ collectTagLines(node.tags, tagLines);
27
+ }
28
+ const errors = [];
29
+ for (const line of [...tagLines].sort((a, b) => a - b)) {
30
+ const comment = file.lines[line - 1]?.indexOf('#') ?? -1;
31
+ if (comment !== -1) {
32
+ errors.push({
33
+ message: 'Partially commented tag lines not allowed',
34
+ rule: name,
35
+ // Point at the '#' itself: that is the character to remove.
36
+ ...atLineColumn(line, comment + 1),
37
+ });
38
+ }
39
+ }
40
+ return errors;
41
+ },
42
+ };
43
+ export default rule;
44
+ //# sourceMappingURL=no-partially-commented-tag-lines.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-partially-commented-tag-lines.js","sourceRoot":"","sources":["../../src/rules/no-partially-commented-tag-lines.ts"],"names":[],"mappings":"AACA,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAErD,OAAO,EAAC,YAAY,EAAC,MAAM,qBAAqB,CAAC;AAEjD,MAAM,IAAI,GAAG,kCAAkC,CAAC;AAEhD;;;;;;;;GAQG;AACH,SAAS,eAAe,CAAC,IAAoB,EAAE,IAAiB;IAC9D,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC9B,CAAC;AACH,CAAC;AAED,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,GAAG,CAAC,OAAO,EAAE,IAAI;QACf,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;QACnC,KAAK,MAAM,EAAC,IAAI,EAAC,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5C,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACvC,CAAC;QAED,MAAM,MAAM,GAAgB,EAAE,CAAC;QAC/B,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;YACvD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;YACzD,IAAI,OAAO,KAAK,CAAC,CAAC,EAAE,CAAC;gBACnB,MAAM,CAAC,IAAI,CAAC;oBACV,OAAO,EAAE,2CAA2C;oBACpD,IAAI,EAAE,IAAI;oBACV,4DAA4D;oBAC5D,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,CAAC,CAAC;iBACnC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintRule } from '../types.ts';
2
+ declare const rule: LintRule;
3
+ export default rule;
4
+ //# sourceMappingURL=no-restricted-patterns.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-restricted-patterns.d.ts","sourceRoot":"","sources":["../../src/rules/no-restricted-patterns.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAC,QAAQ,EAAY,MAAM,aAAa,CAAC;AA2DrD,QAAA,MAAM,IAAI,EAAE,QA8DX,CAAC;eAEa,IAAI"}
@@ -0,0 +1,101 @@
1
+ import { getNeutralKeyword, getNodeType } from '../gherkin/keywords.js';
2
+ import { rulesOf, stepContainersOf } from '../gherkin/traverse.js';
3
+ import { mergeDefaults } from '../util/collections.js';
4
+ import { at } from '../util/location.js';
5
+ const name = 'no-restricted-patterns';
6
+ /**
7
+ * Patterns are grouped by where they apply. `Global` applies everywhere; the
8
+ * rest apply only inside that kind of block.
9
+ */
10
+ const availableConfigs = {
11
+ Global: [],
12
+ Feature: [],
13
+ Rule: [],
14
+ Background: [],
15
+ Scenario: [],
16
+ ScenarioOutline: [],
17
+ };
18
+ /**
19
+ * A description written over several lines arrives as one string containing
20
+ * real newlines. A user who literally typed `\n` in a description gets that
21
+ * as two characters, and must not be split on. This sentinel keeps the two
22
+ * apart while splitting.
23
+ */
24
+ const ESCAPED_NEWLINE_SENTINEL = '<!gurkencheck new line sentinel!>';
25
+ /** Builds the pattern list for each block kind, keyed by neutral keyword. */
26
+ function compilePatterns(config) {
27
+ const global = config.Global.map((pattern) => new RegExp(pattern, 'i'));
28
+ const compiled = new Map();
29
+ for (const key of Object.keys(availableConfigs)) {
30
+ if (key === 'Global') {
31
+ continue;
32
+ }
33
+ const neutralKey = key.toLowerCase().replace(/ /g, '');
34
+ compiled.set(neutralKey, [
35
+ ...config[key].map((pattern) => new RegExp(pattern, 'i')),
36
+ ...global,
37
+ ]);
38
+ }
39
+ return compiled;
40
+ }
41
+ /** Splits a description into the lines it was written on. */
42
+ function toCheckableStrings(property, value) {
43
+ if (property !== 'description') {
44
+ return [value];
45
+ }
46
+ return value
47
+ .replaceAll('\\n', ESCAPED_NEWLINE_SENTINEL)
48
+ .split('\n')
49
+ .map((line) => line.replaceAll(ESCAPED_NEWLINE_SENTINEL, '\\n'));
50
+ }
51
+ const rule = {
52
+ name,
53
+ availableConfigs,
54
+ run(feature, _file, configuration) {
55
+ if (feature === undefined) {
56
+ return [];
57
+ }
58
+ const patterns = compilePatterns(mergeDefaults(availableConfigs, configuration));
59
+ const language = feature.language;
60
+ const errors = [];
61
+ const check = (node, property, value, applicable) => {
62
+ if (value === undefined || value === '') {
63
+ return;
64
+ }
65
+ const type = getNodeType(node, language);
66
+ for (const pattern of applicable) {
67
+ for (const candidate of toCheckableStrings(property, value)) {
68
+ // Names and descriptions may be padded with whitespace; steps are not.
69
+ const text = candidate.trim();
70
+ if (pattern.test(text)) {
71
+ errors.push({
72
+ message: `${type} ${property}: "${text}" matches restricted pattern "${pattern}"`,
73
+ rule: name,
74
+ ...at(node.location),
75
+ });
76
+ }
77
+ }
78
+ }
79
+ };
80
+ const patternsFor = (node) => patterns.get(getNeutralKeyword(node, language)) ?? [];
81
+ check(feature, 'name', feature.name, patternsFor(feature));
82
+ check(feature, 'description', feature.description, patternsFor(feature));
83
+ for (const featureRule of rulesOf(feature)) {
84
+ const applicable = patternsFor(featureRule);
85
+ check(featureRule, 'name', featureRule.name, applicable);
86
+ check(featureRule, 'description', featureRule.description, applicable);
87
+ }
88
+ for (const { node } of stepContainersOf(feature)) {
89
+ const applicable = patternsFor(node);
90
+ check(node, 'name', node.name, applicable);
91
+ check(node, 'description', node.description, applicable);
92
+ // Steps are checked against the patterns of the block they sit in.
93
+ for (const step of node.steps) {
94
+ check(step, 'text', step.text, applicable);
95
+ }
96
+ }
97
+ return errors;
98
+ },
99
+ };
100
+ export default rule;
101
+ //# sourceMappingURL=no-restricted-patterns.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-restricted-patterns.js","sourceRoot":"","sources":["../../src/rules/no-restricted-patterns.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { LintRule } from '../types.ts';
2
+ declare const rule: LintRule;
3
+ export default rule;
4
+ //# sourceMappingURL=no-restricted-tags.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-restricted-tags.d.ts","sourceRoot":"","sources":["../../src/rules/no-restricted-tags.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,QAAQ,EAAY,MAAM,aAAa,CAAC;AAerD,QAAA,MAAM,IAAI,EAAE,QA6BX,CAAC;eAEa,IAAI"}
@@ -0,0 +1,35 @@
1
+ import { getNodeType } from '../gherkin/keywords.js';
2
+ import { taggedNodesOf } from '../gherkin/traverse.js';
3
+ import { mergeDefaults } from '../util/collections.js';
4
+ import { at } from '../util/location.js';
5
+ const name = 'no-restricted-tags';
6
+ const availableConfigs = { tags: [], patterns: [] };
7
+ const rule = {
8
+ name,
9
+ availableConfigs,
10
+ run(feature, _file, configuration) {
11
+ if (feature === undefined) {
12
+ return [];
13
+ }
14
+ const config = mergeDefaults(availableConfigs, configuration);
15
+ const forbiddenTags = new Set(config.tags);
16
+ const forbiddenPatterns = config.patterns.map((pattern) => new RegExp(pattern));
17
+ const errors = [];
18
+ for (const { node } of taggedNodesOf(feature)) {
19
+ const nodeType = getNodeType(node, feature.language);
20
+ for (const tag of node.tags) {
21
+ const forbidden = forbiddenTags.has(tag.name) || forbiddenPatterns.some((pattern) => pattern.test(tag.name));
22
+ if (forbidden) {
23
+ errors.push({
24
+ message: `Forbidden tag ${tag.name} on ${nodeType}`,
25
+ rule: name,
26
+ ...at(tag.location),
27
+ });
28
+ }
29
+ }
30
+ }
31
+ return errors;
32
+ },
33
+ };
34
+ export default rule;
35
+ //# sourceMappingURL=no-restricted-tags.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-restricted-tags.js","sourceRoot":"","sources":["../../src/rules/no-restricted-tags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,WAAW,EAAC,MAAM,wBAAwB,CAAC;AACnD,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AAErD,OAAO,EAAC,aAAa,EAAC,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAC,EAAE,EAAC,MAAM,qBAAqB,CAAC;AAEvC,MAAM,IAAI,GAAG,oBAAoB,CAAC;AASlC,MAAM,gBAAgB,GAAyB,EAAC,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAC,CAAC;AAExE,MAAM,IAAI,GAAa;IACrB,IAAI;IACJ,gBAAgB;IAChB,GAAG,CAAC,OAAO,EAAE,KAAK,EAAE,aAAa;QAC/B,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,MAAM,GAAG,aAAa,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAAC;QAC9D,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,iBAAiB,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;QAChF,MAAM,MAAM,GAAgB,EAAE,CAAC;QAE/B,KAAK,MAAM,EAAC,IAAI,EAAC,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;YAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;YACrD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC5B,MAAM,SAAS,GACb,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;gBAC7F,IAAI,SAAS,EAAE,CAAC;oBACd,MAAM,CAAC,IAAI,CAAC;wBACV,OAAO,EAAE,iBAAiB,GAAG,CAAC,IAAI,OAAO,QAAQ,EAAE;wBACnD,IAAI,EAAE,IAAI;wBACV,GAAG,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC;qBACpB,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAC;AAEF,eAAe,IAAI,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { LintRule } from '../types.ts';
2
+ declare const rule: LintRule;
3
+ export default rule;
4
+ //# sourceMappingURL=no-scenario-outlines-without-examples.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"no-scenario-outlines-without-examples.d.ts","sourceRoot":"","sources":["../../src/rules/no-scenario-outlines-without-examples.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAC,QAAQ,EAAY,MAAM,aAAa,CAAC;AAKrD,QAAA,MAAM,IAAI,EAAE,QAyBX,CAAC;eAEa,IAAI"}