@herb-tools/linter 0.8.6 → 0.8.8

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 (82) hide show
  1. package/README.md +54 -2
  2. package/dist/herb-lint.js +17157 -31275
  3. package/dist/herb-lint.js.map +1 -1
  4. package/dist/index.cjs +473 -2113
  5. package/dist/index.cjs.map +1 -1
  6. package/dist/index.js +468 -2115
  7. package/dist/index.js.map +1 -1
  8. package/dist/loader.cjs +6868 -11350
  9. package/dist/loader.cjs.map +1 -1
  10. package/dist/loader.js +6862 -11351
  11. package/dist/loader.js.map +1 -1
  12. package/dist/package.json +9 -8
  13. package/dist/src/cli/argument-parser.js +18 -2
  14. package/dist/src/cli/argument-parser.js.map +1 -1
  15. package/dist/src/cli/file-processor.js +1 -1
  16. package/dist/src/cli/file-processor.js.map +1 -1
  17. package/dist/src/cli.js +25 -10
  18. package/dist/src/cli.js.map +1 -1
  19. package/dist/src/custom-rule-loader.js +2 -2
  20. package/dist/src/custom-rule-loader.js.map +1 -1
  21. package/dist/src/linter.js +16 -3
  22. package/dist/src/linter.js.map +1 -1
  23. package/dist/src/rules/erb-strict-locals-comment-syntax.js +206 -0
  24. package/dist/src/rules/erb-strict-locals-comment-syntax.js.map +1 -0
  25. package/dist/src/rules/erb-strict-locals-required.js +38 -0
  26. package/dist/src/rules/erb-strict-locals-required.js.map +1 -0
  27. package/dist/src/rules/file-utils.js +21 -0
  28. package/dist/src/rules/file-utils.js.map +1 -0
  29. package/dist/src/rules/html-head-only-elements.js +2 -0
  30. package/dist/src/rules/html-head-only-elements.js.map +1 -1
  31. package/dist/src/rules/html-no-duplicate-attributes.js +91 -21
  32. package/dist/src/rules/html-no-duplicate-attributes.js.map +1 -1
  33. package/dist/src/rules/html-no-empty-headings.js +22 -36
  34. package/dist/src/rules/html-no-empty-headings.js.map +1 -1
  35. package/dist/src/rules/index.js +4 -0
  36. package/dist/src/rules/index.js.map +1 -1
  37. package/dist/src/rules/string-utils.js +72 -0
  38. package/dist/src/rules/string-utils.js.map +1 -0
  39. package/dist/src/rules.js +4 -0
  40. package/dist/src/rules.js.map +1 -1
  41. package/dist/src/types.js +6 -0
  42. package/dist/src/types.js.map +1 -1
  43. package/dist/tsconfig.tsbuildinfo +1 -1
  44. package/dist/types/cli/argument-parser.d.ts +3 -0
  45. package/dist/types/cli/file-processor.d.ts +1 -0
  46. package/dist/types/cli.d.ts +1 -1
  47. package/dist/types/linter.d.ts +5 -1
  48. package/dist/types/rules/erb-strict-locals-comment-syntax.d.ts +9 -0
  49. package/dist/types/rules/erb-strict-locals-required.d.ts +9 -0
  50. package/dist/types/rules/file-utils.d.ts +13 -0
  51. package/dist/types/rules/index.d.ts +4 -0
  52. package/dist/types/rules/string-utils.d.ts +15 -0
  53. package/dist/types/src/cli/argument-parser.d.ts +3 -0
  54. package/dist/types/src/cli/file-processor.d.ts +1 -0
  55. package/dist/types/src/cli.d.ts +1 -1
  56. package/dist/types/src/linter.d.ts +5 -1
  57. package/dist/types/src/rules/erb-strict-locals-comment-syntax.d.ts +9 -0
  58. package/dist/types/src/rules/erb-strict-locals-required.d.ts +9 -0
  59. package/dist/types/src/rules/file-utils.d.ts +13 -0
  60. package/dist/types/src/rules/index.d.ts +4 -0
  61. package/dist/types/src/rules/string-utils.d.ts +15 -0
  62. package/dist/types/src/types.d.ts +6 -0
  63. package/dist/types/types.d.ts +6 -0
  64. package/docs/rules/README.md +1 -0
  65. package/docs/rules/erb-strict-locals-comment-syntax.md +153 -0
  66. package/docs/rules/erb-strict-locals-required.md +107 -0
  67. package/package.json +9 -8
  68. package/src/cli/argument-parser.ts +21 -2
  69. package/src/cli/file-processor.ts +2 -1
  70. package/src/cli.ts +34 -11
  71. package/src/custom-rule-loader.ts +2 -2
  72. package/src/linter.ts +19 -3
  73. package/src/rules/erb-strict-locals-comment-syntax.ts +274 -0
  74. package/src/rules/erb-strict-locals-required.ts +52 -0
  75. package/src/rules/file-utils.ts +23 -0
  76. package/src/rules/html-head-only-elements.ts +1 -0
  77. package/src/rules/html-no-duplicate-attributes.ts +141 -26
  78. package/src/rules/html-no-empty-headings.ts +21 -44
  79. package/src/rules/index.ts +4 -0
  80. package/src/rules/string-utils.ts +72 -0
  81. package/src/rules.ts +4 -0
  82. package/src/types.ts +6 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"erb-strict-locals-comment-syntax.js","sourceRoot":"","sources":["../../../src/rules/erb-strict-locals-comment-syntax.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ import { SourceRule } from "../types.js";
2
+ import { Location } from "@herb-tools/core";
3
+ import { BaseSourceRuleVisitor } from "./rule-utils.js";
4
+ import { isPartialFile } from "./file-utils.js";
5
+ function hasStrictLocals(source) {
6
+ return source.includes("<%# locals:") || source.includes("<%#locals:");
7
+ }
8
+ class ERBStrictLocalsRequiredVisitor extends BaseSourceRuleVisitor {
9
+ visitSource(source) {
10
+ const isPartial = isPartialFile(this.context.fileName);
11
+ if (isPartial !== true)
12
+ return;
13
+ if (hasStrictLocals(source))
14
+ return;
15
+ const firstLineLength = source.indexOf("\n") === -1 ? source.length : source.indexOf("\n");
16
+ const location = Location.from(1, 0, 1, firstLineLength);
17
+ this.addOffense("Partial is missing a strict locals declaration. Add `<%# locals: (...) %>` at the top of the file.", location);
18
+ }
19
+ }
20
+ export class ERBStrictLocalsRequiredRule extends SourceRule {
21
+ static unsafeAutocorrectable = true;
22
+ name = "erb-strict-locals-required";
23
+ get defaultConfig() {
24
+ return {
25
+ enabled: false,
26
+ severity: "error",
27
+ };
28
+ }
29
+ check(source, context) {
30
+ const visitor = new ERBStrictLocalsRequiredVisitor(this.name, context);
31
+ visitor.visit(source);
32
+ return visitor.offenses;
33
+ }
34
+ autofix(_offense, source, _context) {
35
+ return `<%# locals: () %>\n\n${source}`;
36
+ }
37
+ }
38
+ //# sourceMappingURL=erb-strict-locals-required.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"erb-strict-locals-required.js","sourceRoot":"","sources":["../../../src/rules/erb-strict-locals-required.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAI/C,SAAS,eAAe,CAAC,MAAc;IACrC,OAAO,MAAM,CAAC,QAAQ,CAAC,aAAa,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAA;AACxE,CAAC;AAED,MAAM,8BAA+B,SAAQ,qBAAqB;IACtD,WAAW,CAAC,MAAc;QAClC,MAAM,SAAS,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAEtD,IAAI,SAAS,KAAK,IAAI;YAAE,OAAM;QAC9B,IAAI,eAAe,CAAC,MAAM,CAAC;YAAE,OAAM;QAEnC,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC1F,MAAM,QAAQ,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,eAAe,CAAC,CAAA;QAExD,IAAI,CAAC,UAAU,CACb,oGAAoG,EACpG,QAAQ,CACT,CAAA;IACH,CAAC;CACF;AAED,MAAM,OAAO,2BAA4B,SAAQ,UAAU;IACzD,MAAM,CAAC,qBAAqB,GAAG,IAAI,CAAA;IACnC,IAAI,GAAG,4BAA4B,CAAA;IAEnC,IAAI,aAAa;QACf,OAAO;YACL,OAAO,EAAE,KAAK;YACd,QAAQ,EAAE,OAAO;SAClB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,MAAc,EAAE,OAA8B;QAClD,MAAM,OAAO,GAAG,IAAI,8BAA8B,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAEtE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QAErB,OAAO,OAAO,CAAC,QAAQ,CAAA;IACzB,CAAC;IAED,OAAO,CAAC,QAAqB,EAAE,MAAc,EAAE,QAA+B;QAC5E,OAAO,wBAAwB,MAAM,EAAE,CAAA;IACzC,CAAC"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * File path and naming utilities for linter rules
3
+ */
4
+ /**
5
+ * Extracts the basename (filename) from a file path
6
+ * Works with both forward slashes and backslashes
7
+ */
8
+ export function getBasename(filePath) {
9
+ const lastSlash = Math.max(filePath.lastIndexOf("/"), filePath.lastIndexOf("\\"));
10
+ return lastSlash === -1 ? filePath : filePath.slice(lastSlash + 1);
11
+ }
12
+ /**
13
+ * Checks if a file is a Rails partial (filename starts with `_`)
14
+ * Returns null if fileName is undefined (unknown context)
15
+ */
16
+ export function isPartialFile(fileName) {
17
+ if (!fileName)
18
+ return null;
19
+ return getBasename(fileName).startsWith("_");
20
+ }
21
+ //# sourceMappingURL=file-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-utils.js","sourceRoot":"","sources":["../../../src/rules/file-utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAA;IAEjF,OAAO,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAA;AACpE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,QAA4B;IACxD,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAA;IAE1B,OAAO,WAAW,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAA;AAC9C,CAAC"}
@@ -20,6 +20,8 @@ class HeadOnlyElementsVisitor extends BaseRuleVisitor {
20
20
  return;
21
21
  if (tagName === "title" && this.insideSVG)
22
22
  return;
23
+ if (tagName === "style" && this.insideSVG)
24
+ return;
23
25
  if (tagName === "meta" && this.hasItempropAttribute(node))
24
26
  return;
25
27
  this.addOffense(`Element \`<${tagName}>\` must be placed inside the \`<head>\` tag.`, node.location);
@@ -1 +1 @@
1
- {"version":3,"file":"html-head-only-elements.js","sourceRoot":"","sources":["../../../src/rules/html-head-only-elements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAKvF,MAAM,uBAAwB,SAAQ,eAAe;IAC3C,YAAY,GAAa,EAAE,CAAA;IAEnC,oBAAoB,CAAC,IAAqB;QACxC,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,CAAA;QAC/C,IAAI,CAAC,OAAO;YAAE,OAAM;QAEpB,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAExC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC/B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;QAC1B,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,CAAA;IACzB,CAAC;IAEO,oBAAoB,CAAC,IAAqB,EAAE,OAAe;QACjE,IAAI,IAAI,CAAC,UAAU;YAAE,OAAM;QAC3B,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAM;QAC5B,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;YAAE,OAAM;QACnC,IAAI,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC,SAAS;YAAE,OAAM;QACjD,IAAI,OAAO,KAAK,MAAM,IAAI,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC;YAAE,OAAM;QAEjE,IAAI,CAAC,UAAU,CACb,cAAc,OAAO,+CAA+C,EACpE,IAAI,CAAC,QAAQ,CACd,CAAA;IACH,CAAC;IAEO,oBAAoB,CAAC,IAAqB;QAChD,OAAO,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IAChD,CAAC;IAED,IAAY,UAAU;QACpB,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC3C,CAAC;IAED,IAAY,UAAU;QACpB,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC3C,CAAC;IAED,IAAY,SAAS;QACnB,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC1C,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,UAAU;IACtD,MAAM,CAAC,eAAe,GAAG,KAAK,CAAA;IAC9B,IAAI,GAAG,yBAAyB,CAAA;IAEhC,IAAI,aAAa;QACf,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,CAAC,UAAU,EAAE,cAAc,CAAC;SACtC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,MAAmB,EAAE,OAA8B;QACvD,MAAM,OAAO,GAAG,IAAI,uBAAuB,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAE/D,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAE3B,OAAO,OAAO,CAAC,QAAQ,CAAA;IACzB,CAAC"}
1
+ {"version":3,"file":"html-head-only-elements.js","sourceRoot":"","sources":["../../../src/rules/html-head-only-elements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AACrC,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAKvF,MAAM,uBAAwB,SAAQ,eAAe;IAC3C,YAAY,GAAa,EAAE,CAAA;IAEnC,oBAAoB,CAAC,IAAqB;QACxC,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,EAAE,WAAW,EAAE,CAAA;QAC/C,IAAI,CAAC,OAAO;YAAE,OAAM;QAEpB,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAExC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QAC/B,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;QAC1B,IAAI,CAAC,YAAY,CAAC,GAAG,EAAE,CAAA;IACzB,CAAC;IAEO,oBAAoB,CAAC,IAAqB,EAAE,OAAe;QACjE,IAAI,IAAI,CAAC,UAAU;YAAE,OAAM;QAC3B,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAM;QAC5B,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;YAAE,OAAM;QACnC,IAAI,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC,SAAS;YAAE,OAAM;QACjD,IAAI,OAAO,KAAK,OAAO,IAAI,IAAI,CAAC,SAAS;YAAE,OAAM;QACjD,IAAI,OAAO,KAAK,MAAM,IAAI,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC;YAAE,OAAM;QAEjE,IAAI,CAAC,UAAU,CACb,cAAc,OAAO,+CAA+C,EACpE,IAAI,CAAC,QAAQ,CACd,CAAA;IACH,CAAC;IAEO,oBAAoB,CAAC,IAAqB;QAChD,OAAO,YAAY,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;IAChD,CAAC;IAED,IAAY,UAAU;QACpB,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC3C,CAAC;IAED,IAAY,UAAU;QACpB,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC3C,CAAC;IAED,IAAY,SAAS;QACnB,OAAO,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;IAC1C,CAAC;CACF;AAED,MAAM,OAAO,wBAAyB,SAAQ,UAAU;IACtD,MAAM,CAAC,eAAe,GAAG,KAAK,CAAA;IAC9B,IAAI,GAAG,yBAAyB,CAAA;IAEhC,IAAI,aAAa;QACf,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,CAAC,UAAU,EAAE,cAAc,CAAC;SACtC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,MAAmB,EAAE,OAA8B;QACvD,MAAM,OAAO,GAAG,IAAI,uBAAuB,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAE/D,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAE3B,OAAO,OAAO,CAAC,QAAQ,CAAA;IACzB,CAAC"}
@@ -1,33 +1,103 @@
1
1
  import { ParserRule } from "../types.js";
2
- import { AttributeVisitorMixin } from "./rule-utils.js";
3
- class NoDuplicateAttributesVisitor extends AttributeVisitorMixin {
4
- attributeNames = new Map();
2
+ import { ControlFlowTrackingVisitor, ControlFlowType, getAttributeName } from "./rule-utils.js";
3
+ class NoDuplicateAttributesVisitor extends ControlFlowTrackingVisitor {
4
+ tagAttributes = new Set();
5
+ currentBranchAttributes = new Set();
6
+ controlFlowAttributes = new Set();
5
7
  visitHTMLOpenTagNode(node) {
6
- this.attributeNames.clear();
8
+ this.tagAttributes = new Set();
9
+ this.currentBranchAttributes = new Set();
10
+ this.controlFlowAttributes = new Set();
7
11
  super.visitHTMLOpenTagNode(node);
8
- this.reportDuplicates();
9
12
  }
10
- checkStaticAttributeStaticValue({ attributeName, attributeNode }) {
11
- this.trackAttributeName(attributeName, attributeNode);
13
+ visitHTMLAttributeNode(node) {
14
+ this.checkAttribute(node);
12
15
  }
13
- checkStaticAttributeDynamicValue({ attributeName, attributeNode }) {
14
- this.trackAttributeName(attributeName, attributeNode);
16
+ onEnterControlFlow(_controlFlowType, wasAlreadyInControlFlow) {
17
+ const stateToRestore = {
18
+ previousBranchAttributes: this.currentBranchAttributes,
19
+ previousControlFlowAttributes: this.controlFlowAttributes,
20
+ };
21
+ this.currentBranchAttributes = new Set();
22
+ if (!wasAlreadyInControlFlow) {
23
+ this.controlFlowAttributes = new Set();
24
+ }
25
+ return stateToRestore;
26
+ }
27
+ onExitControlFlow(controlFlowType, wasAlreadyInControlFlow, stateToRestore) {
28
+ if (controlFlowType === ControlFlowType.CONDITIONAL && !wasAlreadyInControlFlow) {
29
+ this.controlFlowAttributes.forEach((attr) => this.tagAttributes.add(attr));
30
+ }
31
+ this.currentBranchAttributes = stateToRestore.previousBranchAttributes;
32
+ this.controlFlowAttributes = stateToRestore.previousControlFlowAttributes;
33
+ }
34
+ onEnterBranch() {
35
+ const stateToRestore = {
36
+ previousBranchAttributes: this.currentBranchAttributes,
37
+ };
38
+ if (this.isInControlFlow) {
39
+ this.currentBranchAttributes = new Set();
40
+ }
41
+ return stateToRestore;
42
+ }
43
+ onExitBranch(_stateToRestore) { }
44
+ checkAttribute(attributeNode) {
45
+ const identifier = getAttributeName(attributeNode);
46
+ if (!identifier)
47
+ return;
48
+ this.processAttributeDuplicate(identifier, attributeNode);
49
+ }
50
+ processAttributeDuplicate(identifier, attributeNode) {
51
+ if (!this.isInControlFlow) {
52
+ this.handleHTMLAttribute(identifier, attributeNode);
53
+ return;
54
+ }
55
+ if (this.currentControlFlowType === ControlFlowType.LOOP) {
56
+ this.handleLoopAttribute(identifier, attributeNode);
57
+ }
58
+ else {
59
+ this.handleConditionalAttribute(identifier, attributeNode);
60
+ }
61
+ this.currentBranchAttributes.add(identifier);
15
62
  }
16
- trackAttributeName(attributeName, attributeNode) {
17
- if (!this.attributeNames.has(attributeName)) {
18
- this.attributeNames.set(attributeName, []);
63
+ handleHTMLAttribute(identifier, attributeNode) {
64
+ if (this.tagAttributes.has(identifier)) {
65
+ this.addDuplicateAttributeOffense(identifier, attributeNode.name.location);
66
+ }
67
+ this.tagAttributes.add(identifier);
68
+ }
69
+ handleLoopAttribute(identifier, attributeNode) {
70
+ if (this.currentBranchAttributes.has(identifier)) {
71
+ this.addSameLoopIterationOffense(identifier, attributeNode.name.location);
72
+ return;
73
+ }
74
+ if (this.tagAttributes.has(identifier)) {
75
+ this.addDuplicateAttributeOffense(identifier, attributeNode.name.location);
76
+ return;
19
77
  }
20
- this.attributeNames.get(attributeName).push(attributeNode);
78
+ this.addLoopWillDuplicateOffense(identifier, attributeNode.name.location);
21
79
  }
22
- reportDuplicates() {
23
- for (const [attributeName, attributeNodes] of this.attributeNames) {
24
- if (attributeNodes.length > 1) {
25
- for (let i = 1; i < attributeNodes.length; i++) {
26
- const attributeNode = attributeNodes[i];
27
- this.addOffense(`Duplicate attribute \`${attributeName}\` found on tag. Remove the duplicate occurrence.`, attributeNode.name.location);
28
- }
29
- }
80
+ handleConditionalAttribute(identifier, attributeNode) {
81
+ if (this.currentBranchAttributes.has(identifier)) {
82
+ this.addSameBranchOffense(identifier, attributeNode.name.location);
83
+ return;
30
84
  }
85
+ if (this.tagAttributes.has(identifier)) {
86
+ this.addDuplicateAttributeOffense(identifier, attributeNode.name.location);
87
+ }
88
+ this.controlFlowAttributes.add(identifier);
89
+ }
90
+ addDuplicateAttributeOffense(identifier, location) {
91
+ this.addOffense(`Duplicate attribute \`${identifier}\`. Browsers only use the first occurrence and ignore duplicate attributes. Remove the duplicate or merge the values.`, location);
92
+ }
93
+ addSameLoopIterationOffense(identifier, location) {
94
+ this.addOffense(`Duplicate attribute \`${identifier}\` in same loop iteration. Each iteration will produce an element with duplicate attributes. Remove one or merge the values.`, location);
95
+ }
96
+ addLoopWillDuplicateOffense(identifier, location) {
97
+ this.addOffense(`Attribute \`${identifier}\` inside loop will appear multiple times on this element. Use a dynamic attribute name like \`${identifier}-<%= index %>\` or move the attribute outside the loop.`, location);
98
+ }
99
+ addSameBranchOffense(identifier, location) {
100
+ this.addOffense(`Duplicate attribute \`${identifier}\` in same branch. This branch will produce an element with duplicate attributes. Remove one or merge the values.`, location);
31
101
  }
32
102
  }
33
103
  export class HTMLNoDuplicateAttributesRule extends ParserRule {
@@ -1 +1 @@
1
- {"version":3,"file":"html-no-duplicate-attributes.js","sourceRoot":"","sources":["../../../src/rules/html-no-duplicate-attributes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,qBAAqB,EAAuE,MAAM,iBAAiB,CAAA;AAK5H,MAAM,4BAA6B,SAAQ,qBAAqB;IACtD,cAAc,GAAG,IAAI,GAAG,EAA+B,CAAA;IAE/D,oBAAoB,CAAC,IAAqB;QACxC,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAA;QAC3B,KAAK,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAA;QAChC,IAAI,CAAC,gBAAgB,EAAE,CAAA;IACzB,CAAC;IAGS,+BAA+B,CAAC,EAAE,aAAa,EAAE,aAAa,EAAoC;QAC1G,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IACvD,CAAC;IAES,gCAAgC,CAAC,EAAE,aAAa,EAAE,aAAa,EAAqC;QAC5G,IAAI,CAAC,kBAAkB,CAAC,aAAa,EAAE,aAAa,CAAC,CAAA;IACvD,CAAC;IAEO,kBAAkB,CAAC,aAAqB,EAAE,aAAgC;QAChF,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,CAAC;YAC5C,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,CAAC,CAAA;QAC5C,CAAC;QAED,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,aAAa,CAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;IAC7D,CAAC;IAEO,gBAAgB;QACtB,KAAK,MAAM,CAAC,aAAa,EAAE,cAAc,CAAC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YAClE,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;oBAC/C,MAAM,aAAa,GAAG,cAAc,CAAC,CAAC,CAAC,CAAA;oBAEvC,IAAI,CAAC,UAAU,CACb,yBAAyB,aAAa,mDAAmD,EACzF,aAAa,CAAC,IAAK,CAAC,QAAQ,CAC7B,CAAA;gBACH,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;CACF;AAED,MAAM,OAAO,6BAA8B,SAAQ,UAAU;IAC3D,IAAI,GAAG,8BAA8B,CAAA;IAErC,IAAI,aAAa;QACf,OAAO;YACL,OAAO,EAAE,IAAI;YACb,QAAQ,EAAE,OAAO;SAClB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,MAAmB,EAAE,OAA8B;QACvD,MAAM,OAAO,GAAG,IAAI,4BAA4B,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAEpE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAE3B,OAAO,OAAO,CAAC,QAAQ,CAAA;IACzB,CAAC;CACF"}
1
+ {"version":3,"file":"html-no-duplicate-attributes.js","sourceRoot":"","sources":["../../../src/rules/html-no-duplicate-attributes.ts"],"names":[],"mappings":"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"}
@@ -1,21 +1,24 @@
1
1
  import { BaseRuleVisitor, getTagName, getAttributes, findAttributeByName, getAttributeValue, HEADING_TAGS } from "./rule-utils.js";
2
+ import { isHTMLOpenTagNode, isLiteralNode, isHTMLTextNode, isHTMLElementNode } from "@herb-tools/core";
2
3
  import { ParserRule } from "../types.js";
3
4
  class NoEmptyHeadingsVisitor extends BaseRuleVisitor {
4
5
  visitHTMLElementNode(node) {
6
+ const tagName = getTagName(node.open_tag)?.toLowerCase();
7
+ if (tagName === "template")
8
+ return;
5
9
  this.checkHeadingElement(node);
6
10
  super.visitHTMLElementNode(node);
7
11
  }
8
12
  checkHeadingElement(node) {
9
- if (!node.open_tag || node.open_tag.type !== "AST_HTML_OPEN_TAG_NODE") {
13
+ if (!node.open_tag)
10
14
  return;
11
- }
12
- const openTag = node.open_tag;
13
- const tagName = getTagName(openTag);
14
- if (!tagName) {
15
+ if (!isHTMLOpenTagNode(node.open_tag))
16
+ return;
17
+ const tagName = getTagName(node.open_tag);
18
+ if (!tagName)
15
19
  return;
16
- }
17
20
  const isStandardHeading = HEADING_TAGS.has(tagName);
18
- const isAriaHeading = this.hasHeadingRole(openTag);
21
+ const isAriaHeading = this.hasHeadingRole(node.open_tag);
19
22
  if (!isStandardHeading && !isAriaHeading) {
20
23
  return;
21
24
  }
@@ -32,23 +35,14 @@ class NoEmptyHeadingsVisitor extends BaseRuleVisitor {
32
35
  }
33
36
  let hasAccessibleContent = false;
34
37
  for (const child of node.body) {
35
- if (child.type === "AST_LITERAL_NODE") {
36
- const literalNode = child;
37
- if (literalNode.content.trim().length > 0) {
38
+ if (isLiteralNode(child) || isHTMLTextNode(child)) {
39
+ if (child.content.trim().length > 0) {
38
40
  hasAccessibleContent = true;
39
41
  break;
40
42
  }
41
43
  }
42
- else if (child.type === "AST_HTML_TEXT_NODE") {
43
- const textNode = child;
44
- if (textNode.content.trim().length > 0) {
45
- hasAccessibleContent = true;
46
- break;
47
- }
48
- }
49
- else if (child.type === "AST_HTML_ELEMENT_NODE") {
50
- const elementNode = child;
51
- if (this.isElementAccessible(elementNode)) {
44
+ else if (isHTMLElementNode(child)) {
45
+ if (this.isElementAccessible(child)) {
52
46
  hasAccessibleContent = true;
53
47
  break;
54
48
  }
@@ -70,11 +64,11 @@ class NoEmptyHeadingsVisitor extends BaseRuleVisitor {
70
64
  return roleValue === "heading";
71
65
  }
72
66
  isElementAccessible(node) {
73
- if (!node.open_tag || node.open_tag.type !== "AST_HTML_OPEN_TAG_NODE") {
67
+ if (!node.open_tag)
74
68
  return true;
75
- }
76
- const openTag = node.open_tag;
77
- const attributes = getAttributes(openTag);
69
+ if (!isHTMLOpenTagNode(node.open_tag))
70
+ return true;
71
+ const attributes = getAttributes(node.open_tag);
78
72
  const ariaHiddenAttribute = findAttributeByName(attributes, "aria-hidden");
79
73
  if (ariaHiddenAttribute) {
80
74
  const ariaHiddenValue = getAttributeValue(ariaHiddenAttribute);
@@ -86,21 +80,13 @@ class NoEmptyHeadingsVisitor extends BaseRuleVisitor {
86
80
  return false;
87
81
  }
88
82
  for (const child of node.body) {
89
- if (child.type === "AST_LITERAL_NODE") {
90
- const literalNode = child;
91
- if (literalNode.content.trim().length > 0) {
92
- return true;
93
- }
94
- }
95
- else if (child.type === "AST_HTML_TEXT_NODE") {
96
- const textNode = child;
97
- if (textNode.content.trim().length > 0) {
83
+ if (isLiteralNode(child) || isHTMLTextNode(child)) {
84
+ if (child.content.trim().length > 0) {
98
85
  return true;
99
86
  }
100
87
  }
101
- else if (child.type === "AST_HTML_ELEMENT_NODE") {
102
- const elementNode = child;
103
- if (this.isElementAccessible(elementNode)) {
88
+ else if (isHTMLElementNode(child)) {
89
+ if (this.isElementAccessible(child)) {
104
90
  return true;
105
91
  }
106
92
  }
@@ -1 +1 @@
1
- {"version":3,"file":"html-no-empty-headings.js","sourceRoot":"","sources":["../../../src/rules/html-no-empty-headings.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"html-no-empty-headings.js","sourceRoot":"","sources":["../../../src/rules/html-no-empty-headings.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,6 @@
1
1
  export * from "./rule-utils.js";
2
+ export * from "./file-utils.js";
3
+ export * from "./string-utils.js";
2
4
  export * from "./herb-disable-comment-base.js";
3
5
  export * from "./erb-comment-syntax.js";
4
6
  export * from "./erb-no-case-node-children.js";
@@ -11,6 +13,8 @@ export * from "./erb-prefer-image-tag-helper.js";
11
13
  export * from "./erb-require-trailing-newline.js";
12
14
  export * from "./erb-require-whitespace-inside-tags.js";
13
15
  export * from "./erb-right-trim.js";
16
+ export * from "./erb-strict-locals-comment-syntax.js";
17
+ export * from "./erb-strict-locals-required.js";
14
18
  export * from "./herb-disable-comment-valid-rule-name.js";
15
19
  export * from "./herb-disable-comment-no-redundant-all.js";
16
20
  export * from "./herb-disable-comment-no-duplicate-rules.js";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/rules/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,gCAAgC,CAAA;AAE9C,cAAc,yBAAyB,CAAA;AACvC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,0CAA0C,CAAA;AACxD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,0CAA0C,CAAA;AACxD,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,yCAAyC,CAAA;AACvD,cAAc,qBAAqB,CAAA;AAEnC,cAAc,2CAA2C,CAAA;AACzD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,8CAA8C,CAAA;AAC5D,cAAc,yCAAyC,CAAA;AACvD,cAAc,qCAAqC,CAAA;AACnD,cAAc,uCAAuC,CAAA;AAErD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,wCAAwC,CAAA;AACtD,cAAc,oCAAoC,CAAA;AAClD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,oCAAoC,CAAA;AAClD,cAAc,2CAA2C,CAAA;AACzD,cAAc,iDAAiD,CAAA;AAC/D,cAAc,8BAA8B,CAAA;AAC5C,cAAc,uCAAuC,CAAA;AACrD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,sCAAsC,CAAA;AACpD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,uCAAuC,CAAA;AACrD,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,4BAA4B,CAAA;AAC1C,cAAc,mCAAmC,CAAA;AACjD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6CAA6C,CAAA;AAC3D,cAAc,8BAA8B,CAAA;AAE5C,cAAc,kCAAkC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/rules/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAA;AAC/B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,mBAAmB,CAAA;AACjC,cAAc,gCAAgC,CAAA;AAE9C,cAAc,yBAAyB,CAAA;AACvC,cAAc,gCAAgC,CAAA;AAC9C,cAAc,wBAAwB,CAAA;AACtC,cAAc,2BAA2B,CAAA;AACzC,cAAc,0CAA0C,CAAA;AACxD,cAAc,iCAAiC,CAAA;AAC/C,cAAc,0CAA0C,CAAA;AACxD,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,yCAAyC,CAAA;AACvD,cAAc,qBAAqB,CAAA;AACnC,cAAc,uCAAuC,CAAA;AACrD,cAAc,iCAAiC,CAAA;AAE/C,cAAc,2CAA2C,CAAA;AACzD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,8CAA8C,CAAA;AAC5D,cAAc,yCAAyC,CAAA;AACvD,cAAc,qCAAqC,CAAA;AACnD,cAAc,uCAAuC,CAAA;AAErD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,wCAAwC,CAAA;AACtD,cAAc,oCAAoC,CAAA;AAClD,cAAc,4CAA4C,CAAA;AAC1D,cAAc,mCAAmC,CAAA;AACjD,cAAc,mCAAmC,CAAA;AACjD,cAAc,oCAAoC,CAAA;AAClD,cAAc,2CAA2C,CAAA;AACzD,cAAc,iDAAiD,CAAA;AAC/D,cAAc,8BAA8B,CAAA;AAC5C,cAAc,uCAAuC,CAAA;AACrD,cAAc,8BAA8B,CAAA;AAC5C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,2BAA2B,CAAA;AACzC,cAAc,sCAAsC,CAAA;AACpD,cAAc,gCAAgC,CAAA;AAC9C,cAAc,uCAAuC,CAAA;AACrD,cAAc,kCAAkC,CAAA;AAChD,cAAc,mCAAmC,CAAA;AACjD,cAAc,4BAA4B,CAAA;AAC1C,cAAc,mCAAmC,CAAA;AACjD,cAAc,+BAA+B,CAAA;AAC7C,cAAc,6BAA6B,CAAA;AAC3C,cAAc,2BAA2B,CAAA;AACzC,cAAc,iCAAiC,CAAA;AAC/C,cAAc,2BAA2B,CAAA;AACzC,cAAc,2BAA2B,CAAA;AACzC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,6CAA6C,CAAA;AAC3D,cAAc,8BAA8B,CAAA;AAE5C,cAAc,kCAAkC,CAAA"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Checks if parentheses in a string are balanced
3
+ * Returns false if there are more closing parens than opening at any point
4
+ */
5
+ export function hasBalancedParentheses(content) {
6
+ let depth = 0;
7
+ for (const char of content) {
8
+ if (char === "(")
9
+ depth++;
10
+ if (char === ")")
11
+ depth--;
12
+ if (depth < 0)
13
+ return false;
14
+ }
15
+ return depth === 0;
16
+ }
17
+ /**
18
+ * Splits a string by commas at the top level only
19
+ * Respects nested parentheses, brackets, braces, and strings
20
+ *
21
+ * @example
22
+ * splitByTopLevelComma("a, b, c") // ["a", " b", " c"]
23
+ * splitByTopLevelComma("a, (b, c), d") // ["a", " (b, c)", " d"]
24
+ * splitByTopLevelComma('a, "b, c", d') // ["a", ' "b, c"', " d"]
25
+ */
26
+ export function splitByTopLevelComma(str) {
27
+ const result = [];
28
+ let current = "";
29
+ let parenDepth = 0;
30
+ let bracketDepth = 0;
31
+ let braceDepth = 0;
32
+ let inString = false;
33
+ let stringChar = "";
34
+ for (let i = 0; i < str.length; i++) {
35
+ const char = str[i];
36
+ const previousChar = i > 0 ? str[i - 1] : "";
37
+ if ((char === '"' || char === "'") && previousChar !== "\\") {
38
+ if (!inString) {
39
+ inString = true;
40
+ stringChar = char;
41
+ }
42
+ else if (char === stringChar) {
43
+ inString = false;
44
+ }
45
+ }
46
+ if (!inString) {
47
+ if (char === "(")
48
+ parenDepth++;
49
+ if (char === ")")
50
+ parenDepth--;
51
+ if (char === "[")
52
+ bracketDepth++;
53
+ if (char === "]")
54
+ bracketDepth--;
55
+ if (char === "{")
56
+ braceDepth++;
57
+ if (char === "}")
58
+ braceDepth--;
59
+ if (char === "," && parenDepth === 0 && bracketDepth === 0 && braceDepth === 0) {
60
+ result.push(current);
61
+ current = "";
62
+ continue;
63
+ }
64
+ }
65
+ current += char;
66
+ }
67
+ if (current) {
68
+ result.push(current);
69
+ }
70
+ return result;
71
+ }
72
+ //# sourceMappingURL=string-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"string-utils.js","sourceRoot":"","sources":["../../../src/rules/string-utils.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,OAAe;IACpD,IAAI,KAAK,GAAG,CAAC,CAAA;IAEb,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,IAAI,KAAK,GAAG;YAAE,KAAK,EAAE,CAAA;QACzB,IAAI,IAAI,KAAK,GAAG;YAAE,KAAK,EAAE,CAAA;QACzB,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO,KAAK,CAAA;IAC7B,CAAC;IAED,OAAO,KAAK,KAAK,CAAC,CAAA;AACpB,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,oBAAoB,CAAC,GAAW;IAC9C,MAAM,MAAM,GAAa,EAAE,CAAA;IAE3B,IAAI,OAAO,GAAG,EAAE,CAAA;IAChB,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,YAAY,GAAG,CAAC,CAAA;IACpB,IAAI,UAAU,GAAG,CAAC,CAAA;IAClB,IAAI,QAAQ,GAAG,KAAK,CAAA;IACpB,IAAI,UAAU,GAAG,EAAE,CAAA;IAEnB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,CAAA;QACnB,MAAM,YAAY,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;QAE5C,IAAI,CAAC,IAAI,KAAK,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,IAAI,YAAY,KAAK,IAAI,EAAE,CAAC;YAC5D,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,QAAQ,GAAG,IAAI,CAAA;gBACf,UAAU,GAAG,IAAI,CAAA;YACnB,CAAC;iBAAM,IAAI,IAAI,KAAK,UAAU,EAAE,CAAC;gBAC/B,QAAQ,GAAG,KAAK,CAAA;YAClB,CAAC;QACH,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,IAAI,IAAI,KAAK,GAAG;gBAAE,UAAU,EAAE,CAAA;YAC9B,IAAI,IAAI,KAAK,GAAG;gBAAE,UAAU,EAAE,CAAA;YAC9B,IAAI,IAAI,KAAK,GAAG;gBAAE,YAAY,EAAE,CAAA;YAChC,IAAI,IAAI,KAAK,GAAG;gBAAE,YAAY,EAAE,CAAA;YAChC,IAAI,IAAI,KAAK,GAAG;gBAAE,UAAU,EAAE,CAAA;YAC9B,IAAI,IAAI,KAAK,GAAG;gBAAE,UAAU,EAAE,CAAA;YAE9B,IAAI,IAAI,KAAK,GAAG,IAAI,UAAU,KAAK,CAAC,IAAI,YAAY,KAAK,CAAC,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;gBAC/E,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;gBACpB,OAAO,GAAG,EAAE,CAAA;gBACZ,SAAQ;YACV,CAAC;QACH,CAAC;QAED,OAAO,IAAI,IAAI,CAAA;IACjB,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACtB,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
package/dist/src/rules.js CHANGED
@@ -9,6 +9,8 @@ import { ERBPreferImageTagHelperRule } from "./rules/erb-prefer-image-tag-helper
9
9
  import { ERBRequireTrailingNewlineRule } from "./rules/erb-require-trailing-newline.js";
10
10
  import { ERBRequireWhitespaceRule } from "./rules/erb-require-whitespace-inside-tags.js";
11
11
  import { ERBRightTrimRule } from "./rules/erb-right-trim.js";
12
+ import { ERBStrictLocalsCommentSyntaxRule } from "./rules/erb-strict-locals-comment-syntax.js";
13
+ import { ERBStrictLocalsRequiredRule } from "./rules/erb-strict-locals-required.js";
12
14
  import { HerbDisableCommentValidRuleNameRule } from "./rules/herb-disable-comment-valid-rule-name.js";
13
15
  import { HerbDisableCommentNoRedundantAllRule } from "./rules/herb-disable-comment-no-redundant-all.js";
14
16
  import { HerbDisableCommentNoDuplicateRulesRule } from "./rules/herb-disable-comment-no-duplicate-rules.js";
@@ -60,6 +62,8 @@ export const rules = [
60
62
  ERBRequireTrailingNewlineRule,
61
63
  ERBRequireWhitespaceRule,
62
64
  ERBRightTrimRule,
65
+ ERBStrictLocalsCommentSyntaxRule,
66
+ ERBStrictLocalsRequiredRule,
63
67
  HerbDisableCommentValidRuleNameRule,
64
68
  HerbDisableCommentNoRedundantAllRule,
65
69
  HerbDisableCommentNoDuplicateRulesRule,
@@ -1 +1 @@
1
- {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/rules.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rules.js","sourceRoot":"","sources":["../../src/rules.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAA;AAChF,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,gDAAgD,CAAA;AACzF,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAA;AAClF,OAAO,EAAE,iCAAiC,EAAE,MAAM,gDAAgD,CAAA;AAClG,OAAO,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAA;AACpF,OAAO,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAA;AACvF,OAAO,EAAE,wBAAwB,EAAE,MAAM,+CAA+C,CAAA;AACxF,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AAC5D,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAA;AAC9F,OAAO,EAAE,2BAA2B,EAAE,MAAM,uCAAuC,CAAA;AAEnF,OAAO,EAAE,mCAAmC,EAAE,MAAM,iDAAiD,CAAA;AACrG,OAAO,EAAE,oCAAoC,EAAE,MAAM,kDAAkD,CAAA;AACvG,OAAO,EAAE,sCAAsC,EAAE,MAAM,oDAAoD,CAAA;AAC3G,OAAO,EAAE,kCAAkC,EAAE,MAAM,+CAA+C,CAAA;AAClG,OAAO,EAAE,+BAA+B,EAAE,MAAM,2CAA2C,CAAA;AAC3F,OAAO,EAAE,iCAAiC,EAAE,MAAM,6CAA6C,CAAA;AAE/F,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAA;AAC/E,OAAO,EAAE,4BAA4B,EAAE,MAAM,8CAA8C,CAAA;AAC3F,OAAO,EAAE,gCAAgC,EAAE,MAAM,8CAA8C,CAAA;AAC/F,OAAO,EAAE,4BAA4B,EAAE,MAAM,0CAA0C,CAAA;AACvF,OAAO,EAAE,oCAAoC,EAAE,MAAM,kDAAkD,CAAA;AACvG,OAAO,EAAE,2BAA2B,EAAE,MAAM,yCAAyC,CAAA;AACrF,OAAO,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAA;AACvF,OAAO,EAAE,8BAA8B,EAAE,MAAM,0CAA0C,CAAA;AACzF,OAAO,EAAE,oCAAoC,EAAE,MAAM,iDAAiD,CAAA;AACtG,OAAO,EAAE,wCAAwC,EAAE,MAAM,uDAAuD,CAAA;AAChH,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAC7E,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAA;AAC9F,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,EAAE,gCAAgC,EAAE,MAAM,4CAA4C,CAAA;AAC7F,OAAO,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAA;AACjF,OAAO,EAAE,+BAA+B,EAAE,MAAM,6CAA6C,CAAA;AAC7F,OAAO,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAA;AACpF,OAAO,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAA;AACvF,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAA;AACtF,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAA;AAC/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAA;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAA;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAA;AACtE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAC7E,OAAO,EAAE,qCAAqC,EAAE,MAAM,mDAAmD,CAAA;AACzG,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAE7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAA;AAErF,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAEhE,MAAM,CAAC,MAAM,KAAK,GAAgB;IAChC,gBAAgB;IAChB,yBAAyB;IACzB,kBAAkB;IAClB,qBAAqB;IACrB,wBAAwB;IACxB,0BAA0B;IAC1B,iCAAiC;IACjC,2BAA2B;IAC3B,6BAA6B;IAC7B,wBAAwB;IACxB,gBAAgB;IAChB,gCAAgC;IAChC,2BAA2B;IAE3B,mCAAmC;IACnC,oCAAoC;IACpC,sCAAsC;IACtC,kCAAkC;IAClC,+BAA+B;IAC/B,iCAAiC;IAEjC,yBAAyB;IACzB,4BAA4B;IAC5B,gCAAgC;IAChC,4BAA4B;IAC5B,oCAAoC;IACpC,2BAA2B;IAC3B,6BAA6B;IAC7B,8BAA8B;IAC9B,oCAAoC;IACpC,wCAAwC;IACxC,wBAAwB;IACxB,gCAAgC;IAChC,wBAAwB;IACxB,sBAAsB;IACtB,qBAAqB;IACrB,gCAAgC;IAChC,0BAA0B;IAC1B,+BAA+B;IAC/B,2BAA2B;IAC3B,6BAA6B;IAC7B,sBAAsB;IACtB,4BAA4B;IAC5B,yBAAyB;IACzB,uBAAuB;IACvB,qBAAqB;IACrB,0BAA0B;IAC1B,qBAAqB;IACrB,oBAAoB;IACpB,wBAAwB;IACxB,qCAAqC;IACrC,wBAAwB;IAExB,4BAA4B;IAE5B,kBAAkB;CACnB,CAAA"}
package/dist/src/types.js CHANGED
@@ -14,6 +14,8 @@ export class ParserRule {
14
14
  static type = "parser";
15
15
  /** Indicates whether this rule supports autofix. Defaults to false. */
16
16
  static autocorrectable = false;
17
+ /** Indicates whether this rule supports unsafe autofix (requires --fix-unsafely). Defaults to false. */
18
+ static unsafeAutocorrectable = false;
17
19
  get defaultConfig() {
18
20
  return DEFAULT_RULE_CONFIG;
19
21
  }
@@ -25,6 +27,8 @@ export class LexerRule {
25
27
  static type = "lexer";
26
28
  /** Indicates whether this rule supports autofix. Defaults to false. */
27
29
  static autocorrectable = false;
30
+ /** Indicates whether this rule supports unsafe autofix (requires --fix-unsafely). Defaults to false. */
31
+ static unsafeAutocorrectable = false;
28
32
  get defaultConfig() {
29
33
  return DEFAULT_RULE_CONFIG;
30
34
  }
@@ -42,6 +46,8 @@ export class SourceRule {
42
46
  static type = "source";
43
47
  /** Indicates whether this rule supports autofix. Defaults to false. */
44
48
  static autocorrectable = false;
49
+ /** Indicates whether this rule supports unsafe autofix (requires --fix-unsafely). Defaults to false. */
50
+ static unsafeAutocorrectable = false;
45
51
  get defaultConfig() {
46
52
  return DEFAULT_RULE_CONFIG;
47
53
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAsEA;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAmB;IACjD,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,EAAE;CACZ,CAAA;AAED;;GAEG;AACH,MAAM,OAAgB,UAAU;IAC9B,MAAM,CAAC,IAAI,GAAG,QAAiB,CAAA;IAC/B,uEAAuE;IACvE,MAAM,CAAC,eAAe,GAAG,KAAK,CAAA;IAG9B,IAAI,aAAa;QACf,OAAO,mBAAmB,CAAA;IAC5B,CAAC;;AAuBH;;GAEG;AACH,MAAM,OAAgB,SAAS;IAC7B,MAAM,CAAC,IAAI,GAAG,OAAgB,CAAA;IAC9B,uEAAuE;IACvE,MAAM,CAAC,eAAe,GAAG,KAAK,CAAA;IAG9B,IAAI,aAAa;QACf,OAAO,mBAAmB,CAAA;IAC5B,CAAC;;AAuCH;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAgB;IAC/C,QAAQ,EAAE,SAAS;IACnB,cAAc,EAAE,SAAS;IACzB,qBAAqB,EAAE,SAAS;IAChC,qBAAqB,EAAE,SAAS;CACxB,CAAA;AAEV,MAAM,OAAgB,UAAU;IAC9B,MAAM,CAAC,IAAI,GAAG,QAAiB,CAAA;IAC/B,uEAAuE;IACvE,MAAM,CAAC,eAAe,GAAG,KAAK,CAAA;IAG9B,IAAI,aAAa;QACf,OAAO,mBAAmB,CAAA;IAC5B,CAAC"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAsEA;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAmB;IACjD,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,OAAO;IACjB,OAAO,EAAE,EAAE;CACZ,CAAA;AAED;;GAEG;AACH,MAAM,OAAgB,UAAU;IAC9B,MAAM,CAAC,IAAI,GAAG,QAAiB,CAAA;IAC/B,uEAAuE;IACvE,MAAM,CAAC,eAAe,GAAG,KAAK,CAAA;IAC9B,wGAAwG;IACxG,MAAM,CAAC,qBAAqB,GAAG,KAAK,CAAA;IAGpC,IAAI,aAAa;QACf,OAAO,mBAAmB,CAAA;IAC5B,CAAC;;AAuBH;;GAEG;AACH,MAAM,OAAgB,SAAS;IAC7B,MAAM,CAAC,IAAI,GAAG,OAAgB,CAAA;IAC9B,uEAAuE;IACvE,MAAM,CAAC,eAAe,GAAG,KAAK,CAAA;IAC9B,wGAAwG;IACxG,MAAM,CAAC,qBAAqB,GAAG,KAAK,CAAA;IAGpC,IAAI,aAAa;QACf,OAAO,mBAAmB,CAAA;IAC5B,CAAC;;AAuCH;;GAEG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAgB;IAC/C,QAAQ,EAAE,SAAS;IACnB,cAAc,EAAE,SAAS;IACzB,qBAAqB,EAAE,SAAS;IAChC,qBAAqB,EAAE,SAAS;CACxB,CAAA;AAEV,MAAM,OAAgB,UAAU;IAC9B,MAAM,CAAC,IAAI,GAAG,QAAiB,CAAA;IAC/B,uEAAuE;IACvE,MAAM,CAAC,eAAe,GAAG,KAAK,CAAA;IAC9B,wGAAwG;IACxG,MAAM,CAAC,qBAAqB,GAAG,KAAK,CAAA;IAGpC,IAAI,aAAa;QACf,OAAO,mBAAmB,CAAA;IAC5B,CAAC"}
@@ -1 +1 @@
1
- {"root":["../src/cli.ts","../src/custom-rule-loader.ts","../src/herb-disable-comment-utils.ts","../src/herb-lint.ts","../src/index.ts","../src/linter-ignore.ts","../src/linter.ts","../src/loader.ts","../src/rules.ts","../src/types.ts","../src/cli/argument-parser.ts","../src/cli/file-processor.ts","../src/cli/index.ts","../src/cli/output-manager.ts","../src/cli/summary-reporter.ts","../src/cli/formatters/base-formatter.ts","../src/cli/formatters/detailed-formatter.ts","../src/cli/formatters/github-actions-formatter.ts","../src/cli/formatters/index.ts","../src/cli/formatters/json-formatter.ts","../src/cli/formatters/simple-formatter.ts","../src/rules/erb-comment-syntax.ts","../src/rules/erb-no-case-node-children.ts","../src/rules/erb-no-empty-tags.ts","../src/rules/erb-no-extra-newline.ts","../src/rules/erb-no-extra-whitespace-inside-tags.ts","../src/rules/erb-no-output-control-flow.ts","../src/rules/erb-no-silent-tag-in-attribute-name.ts","../src/rules/erb-prefer-image-tag-helper.ts","../src/rules/erb-require-trailing-newline.ts","../src/rules/erb-require-whitespace-inside-tags.ts","../src/rules/erb-right-trim.ts","../src/rules/herb-disable-comment-base.ts","../src/rules/herb-disable-comment-malformed.ts","../src/rules/herb-disable-comment-missing-rules.ts","../src/rules/herb-disable-comment-no-duplicate-rules.ts","../src/rules/herb-disable-comment-no-redundant-all.ts","../src/rules/herb-disable-comment-unnecessary.ts","../src/rules/herb-disable-comment-valid-rule-name.ts","../src/rules/html-anchor-require-href.ts","../src/rules/html-aria-attribute-must-be-valid.ts","../src/rules/html-aria-label-is-well-formatted.ts","../src/rules/html-aria-level-must-be-valid.ts","../src/rules/html-aria-role-heading-requires-level.ts","../src/rules/html-aria-role-must-be-valid.ts","../src/rules/html-attribute-double-quotes.ts","../src/rules/html-attribute-equals-spacing.ts","../src/rules/html-attribute-values-require-quotes.ts","../src/rules/html-avoid-both-disabled-and-aria-disabled.ts","../src/rules/html-body-only-elements.ts","../src/rules/html-boolean-attributes-no-value.ts","../src/rules/html-head-only-elements.ts","../src/rules/html-iframe-has-title.ts","../src/rules/html-img-require-alt.ts","../src/rules/html-input-require-autocomplete.ts","../src/rules/html-navigation-has-label.ts","../src/rules/html-no-aria-hidden-on-focusable.ts","../src/rules/html-no-block-inside-inline.ts","../src/rules/html-no-duplicate-attributes.ts","../src/rules/html-no-duplicate-ids.ts","../src/rules/html-no-duplicate-meta-names.ts","../src/rules/html-no-empty-attributes.ts","../src/rules/html-no-empty-headings.ts","../src/rules/html-no-nested-links.ts","../src/rules/html-no-positive-tab-index.ts","../src/rules/html-no-self-closing.ts","../src/rules/html-no-space-in-tag.ts","../src/rules/html-no-title-attribute.ts","../src/rules/html-no-underscores-in-attribute-names.ts","../src/rules/html-tag-name-lowercase.ts","../src/rules/index.ts","../src/rules/parser-no-errors.ts","../src/rules/rule-utils.ts","../src/rules/svg-tag-name-capitalization.ts"],"version":"5.9.3"}
1
+ {"root":["../src/cli.ts","../src/custom-rule-loader.ts","../src/herb-disable-comment-utils.ts","../src/herb-lint.ts","../src/index.ts","../src/linter-ignore.ts","../src/linter.ts","../src/loader.ts","../src/rules.ts","../src/types.ts","../src/cli/argument-parser.ts","../src/cli/file-processor.ts","../src/cli/index.ts","../src/cli/output-manager.ts","../src/cli/summary-reporter.ts","../src/cli/formatters/base-formatter.ts","../src/cli/formatters/detailed-formatter.ts","../src/cli/formatters/github-actions-formatter.ts","../src/cli/formatters/index.ts","../src/cli/formatters/json-formatter.ts","../src/cli/formatters/simple-formatter.ts","../src/rules/erb-comment-syntax.ts","../src/rules/erb-no-case-node-children.ts","../src/rules/erb-no-empty-tags.ts","../src/rules/erb-no-extra-newline.ts","../src/rules/erb-no-extra-whitespace-inside-tags.ts","../src/rules/erb-no-output-control-flow.ts","../src/rules/erb-no-silent-tag-in-attribute-name.ts","../src/rules/erb-prefer-image-tag-helper.ts","../src/rules/erb-require-trailing-newline.ts","../src/rules/erb-require-whitespace-inside-tags.ts","../src/rules/erb-right-trim.ts","../src/rules/erb-strict-locals-comment-syntax.ts","../src/rules/erb-strict-locals-required.ts","../src/rules/file-utils.ts","../src/rules/herb-disable-comment-base.ts","../src/rules/herb-disable-comment-malformed.ts","../src/rules/herb-disable-comment-missing-rules.ts","../src/rules/herb-disable-comment-no-duplicate-rules.ts","../src/rules/herb-disable-comment-no-redundant-all.ts","../src/rules/herb-disable-comment-unnecessary.ts","../src/rules/herb-disable-comment-valid-rule-name.ts","../src/rules/html-anchor-require-href.ts","../src/rules/html-aria-attribute-must-be-valid.ts","../src/rules/html-aria-label-is-well-formatted.ts","../src/rules/html-aria-level-must-be-valid.ts","../src/rules/html-aria-role-heading-requires-level.ts","../src/rules/html-aria-role-must-be-valid.ts","../src/rules/html-attribute-double-quotes.ts","../src/rules/html-attribute-equals-spacing.ts","../src/rules/html-attribute-values-require-quotes.ts","../src/rules/html-avoid-both-disabled-and-aria-disabled.ts","../src/rules/html-body-only-elements.ts","../src/rules/html-boolean-attributes-no-value.ts","../src/rules/html-head-only-elements.ts","../src/rules/html-iframe-has-title.ts","../src/rules/html-img-require-alt.ts","../src/rules/html-input-require-autocomplete.ts","../src/rules/html-navigation-has-label.ts","../src/rules/html-no-aria-hidden-on-focusable.ts","../src/rules/html-no-block-inside-inline.ts","../src/rules/html-no-duplicate-attributes.ts","../src/rules/html-no-duplicate-ids.ts","../src/rules/html-no-duplicate-meta-names.ts","../src/rules/html-no-empty-attributes.ts","../src/rules/html-no-empty-headings.ts","../src/rules/html-no-nested-links.ts","../src/rules/html-no-positive-tab-index.ts","../src/rules/html-no-self-closing.ts","../src/rules/html-no-space-in-tag.ts","../src/rules/html-no-title-attribute.ts","../src/rules/html-no-underscores-in-attribute-names.ts","../src/rules/html-tag-name-lowercase.ts","../src/rules/index.ts","../src/rules/parser-no-errors.ts","../src/rules/rule-utils.ts","../src/rules/string-utils.ts","../src/rules/svg-tag-name-capitalization.ts"],"version":"5.9.3"}
@@ -1,4 +1,5 @@
1
1
  import type { ThemeInput } from "@herb-tools/highlighter";
2
+ import type { DiagnosticSeverity } from "@herb-tools/core";
2
3
  export type FormatOption = "simple" | "detailed" | "json";
3
4
  export interface ParsedArguments {
4
5
  patterns: string[];
@@ -10,10 +11,12 @@ export interface ParsedArguments {
10
11
  truncateLines: boolean;
11
12
  useGitHubActions: boolean;
12
13
  fix: boolean;
14
+ fixUnsafe: boolean;
13
15
  ignoreDisableComments: boolean;
14
16
  force: boolean;
15
17
  init: boolean;
16
18
  loadCustomRules: boolean;
19
+ failLevel?: DiagnosticSeverity;
17
20
  }
18
21
  export declare class ArgumentParser {
19
22
  private readonly usage;
@@ -12,6 +12,7 @@ export interface ProcessingContext {
12
12
  projectPath?: string;
13
13
  pattern?: string;
14
14
  fix?: boolean;
15
+ fixUnsafe?: boolean;
15
16
  ignoreDisableComments?: boolean;
16
17
  linterConfig?: HerbConfigOptions['linter'];
17
18
  config?: Config;
@@ -17,7 +17,7 @@ export declare class CLI {
17
17
  showTiming: boolean;
18
18
  }): void;
19
19
  protected determineProjectPath(patterns: string[]): void;
20
- protected adjustPattern(pattern: string | undefined, configGlobPattern: string): string;
20
+ protected adjustPattern(pattern: string | undefined, configGlobPatterns: string[]): string;
21
21
  protected resolvePatternToFiles(pattern: string, config: Config, force: boolean): Promise<{
22
22
  files: string[];
23
23
  explicitFile: string | undefined;