@herb-tools/linter 0.4.2 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +221 -10
- package/dist/herb-lint.js +817 -292
- package/dist/herb-lint.js.map +1 -1
- package/dist/index.cjs +360 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +355 -83
- package/dist/index.js.map +1 -1
- package/dist/package.json +4 -4
- package/dist/src/cli/argument-parser.js +28 -18
- package/dist/src/cli/argument-parser.js.map +1 -1
- package/dist/src/cli/file-processor.js +21 -17
- package/dist/src/cli/file-processor.js.map +1 -1
- package/dist/src/cli/formatters/detailed-formatter.js +9 -9
- package/dist/src/cli/formatters/detailed-formatter.js.map +1 -1
- package/dist/src/cli/formatters/github-actions-formatter.js +50 -0
- package/dist/src/cli/formatters/github-actions-formatter.js.map +1 -0
- package/dist/src/cli/formatters/index.js +2 -0
- package/dist/src/cli/formatters/index.js.map +1 -1
- package/dist/src/cli/formatters/json-formatter.js +58 -0
- package/dist/src/cli/formatters/json-formatter.js.map +1 -0
- package/dist/src/cli/formatters/simple-formatter.js +15 -15
- package/dist/src/cli/formatters/simple-formatter.js.map +1 -1
- package/dist/src/cli/output-manager.js +120 -0
- package/dist/src/cli/output-manager.js.map +1 -0
- package/dist/src/cli/summary-reporter.js +22 -22
- package/dist/src/cli/summary-reporter.js.map +1 -1
- package/dist/src/cli.js +41 -26
- package/dist/src/cli.js.map +1 -1
- package/dist/src/default-rules.js +8 -0
- package/dist/src/default-rules.js.map +1 -1
- package/dist/src/linter.js +37 -6
- package/dist/src/linter.js.map +1 -1
- package/dist/src/rules/erb-no-empty-tags.js +5 -4
- package/dist/src/rules/erb-no-empty-tags.js.map +1 -1
- package/dist/src/rules/erb-no-output-control-flow.js +5 -4
- package/dist/src/rules/erb-no-output-control-flow.js.map +1 -1
- package/dist/src/rules/erb-prefer-image-tag-helper.js +93 -0
- package/dist/src/rules/erb-prefer-image-tag-helper.js.map +1 -0
- package/dist/src/rules/erb-require-whitespace-inside-tags.js +5 -4
- package/dist/src/rules/erb-require-whitespace-inside-tags.js.map +1 -1
- package/dist/src/rules/erb-requires-trailing-newline.js +22 -0
- package/dist/src/rules/erb-requires-trailing-newline.js.map +1 -0
- package/dist/src/rules/html-anchor-require-href.js +5 -4
- package/dist/src/rules/html-anchor-require-href.js.map +1 -1
- package/dist/src/rules/html-aria-attribute-must-be-valid.js +5 -4
- package/dist/src/rules/html-aria-attribute-must-be-valid.js.map +1 -1
- package/dist/src/rules/html-aria-level-must-be-valid.js +27 -0
- package/dist/src/rules/html-aria-level-must-be-valid.js.map +1 -0
- package/dist/src/rules/html-aria-role-heading-requires-level.js +5 -4
- package/dist/src/rules/html-aria-role-heading-requires-level.js.map +1 -1
- package/dist/src/rules/html-aria-role-must-be-valid.js +5 -4
- package/dist/src/rules/html-aria-role-must-be-valid.js.map +1 -1
- package/dist/src/rules/html-attribute-double-quotes.js +5 -4
- package/dist/src/rules/html-attribute-double-quotes.js.map +1 -1
- package/dist/src/rules/html-attribute-values-require-quotes.js +5 -4
- package/dist/src/rules/html-attribute-values-require-quotes.js.map +1 -1
- package/dist/src/rules/html-boolean-attributes-no-value.js +5 -4
- package/dist/src/rules/html-boolean-attributes-no-value.js.map +1 -1
- package/dist/src/rules/html-img-require-alt.js +5 -4
- package/dist/src/rules/html-img-require-alt.js.map +1 -1
- package/dist/src/rules/html-no-block-inside-inline.js +7 -6
- package/dist/src/rules/html-no-block-inside-inline.js.map +1 -1
- package/dist/src/rules/html-no-duplicate-attributes.js +5 -4
- package/dist/src/rules/html-no-duplicate-attributes.js.map +1 -1
- package/dist/src/rules/html-no-duplicate-ids.js +5 -4
- package/dist/src/rules/html-no-duplicate-ids.js.map +1 -1
- package/dist/src/rules/html-no-empty-headings.js +5 -4
- package/dist/src/rules/html-no-empty-headings.js.map +1 -1
- package/dist/src/rules/html-no-nested-links.js +5 -4
- package/dist/src/rules/html-no-nested-links.js.map +1 -1
- package/dist/src/rules/html-tag-name-lowercase.js +5 -4
- package/dist/src/rules/html-tag-name-lowercase.js.map +1 -1
- package/dist/src/rules/index.js +3 -0
- package/dist/src/rules/index.js.map +1 -1
- package/dist/src/rules/parser-no-errors.js +18 -0
- package/dist/src/rules/parser-no-errors.js.map +1 -0
- package/dist/src/rules/rule-utils.js +125 -2
- package/dist/src/rules/rule-utils.js.map +1 -1
- package/dist/src/rules/svg-tag-name-capitalization.js +5 -4
- package/dist/src/rules/svg-tag-name-capitalization.js.map +1 -1
- package/dist/src/types.js +15 -1
- package/dist/src/types.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/cli/argument-parser.d.ts +2 -1
- package/dist/types/cli/file-processor.d.ts +6 -5
- package/dist/types/cli/formatters/base-formatter.d.ts +2 -2
- package/dist/types/cli/formatters/detailed-formatter.d.ts +2 -2
- package/dist/types/cli/formatters/github-actions-formatter.d.ts +12 -0
- package/dist/types/cli/formatters/index.d.ts +2 -0
- package/dist/types/cli/formatters/json-formatter.d.ts +42 -0
- package/dist/types/cli/formatters/simple-formatter.d.ts +2 -2
- package/dist/types/cli/output-manager.d.ts +31 -0
- package/dist/types/cli/summary-reporter.d.ts +3 -3
- package/dist/types/cli.d.ts +3 -1
- package/dist/types/linter.d.ts +20 -5
- package/dist/types/rules/erb-no-empty-tags.d.ts +5 -4
- package/dist/types/rules/erb-no-output-control-flow.d.ts +5 -4
- package/dist/types/rules/erb-prefer-image-tag-helper.d.ts +7 -0
- package/dist/types/rules/erb-require-whitespace-inside-tags.d.ts +5 -4
- package/dist/types/rules/erb-requires-trailing-newline.d.ts +6 -0
- package/dist/types/rules/html-anchor-require-href.d.ts +5 -4
- package/dist/types/rules/html-aria-attribute-must-be-valid.d.ts +5 -4
- package/dist/types/rules/html-aria-level-must-be-valid.d.ts +7 -0
- package/dist/types/rules/html-aria-role-heading-requires-level.d.ts +5 -4
- package/dist/types/rules/html-aria-role-must-be-valid.d.ts +5 -4
- package/dist/types/rules/html-attribute-double-quotes.d.ts +5 -4
- package/dist/types/rules/html-attribute-values-require-quotes.d.ts +5 -4
- package/dist/types/rules/html-boolean-attributes-no-value.d.ts +5 -4
- package/dist/types/rules/html-img-require-alt.d.ts +5 -4
- package/dist/types/rules/html-no-block-inside-inline.d.ts +5 -4
- package/dist/types/rules/html-no-duplicate-attributes.d.ts +5 -4
- package/dist/types/rules/html-no-duplicate-ids.d.ts +5 -4
- package/dist/types/rules/html-no-empty-headings.d.ts +5 -4
- package/dist/types/rules/html-no-nested-links.d.ts +5 -4
- package/dist/types/rules/html-tag-name-lowercase.d.ts +5 -4
- package/dist/types/rules/index.d.ts +3 -0
- package/dist/types/rules/parser-no-errors.d.ts +8 -0
- package/dist/types/rules/rule-utils.d.ts +73 -4
- package/dist/types/rules/svg-tag-name-capitalization.d.ts +5 -4
- package/dist/types/src/cli/argument-parser.d.ts +2 -1
- package/dist/types/src/cli/file-processor.d.ts +6 -5
- package/dist/types/src/cli/formatters/base-formatter.d.ts +2 -2
- package/dist/types/src/cli/formatters/detailed-formatter.d.ts +2 -2
- package/dist/types/src/cli/formatters/github-actions-formatter.d.ts +12 -0
- package/dist/types/src/cli/formatters/index.d.ts +2 -0
- package/dist/types/src/cli/formatters/json-formatter.d.ts +42 -0
- package/dist/types/src/cli/formatters/simple-formatter.d.ts +2 -2
- package/dist/types/src/cli/output-manager.d.ts +31 -0
- package/dist/types/src/cli/summary-reporter.d.ts +3 -3
- package/dist/types/src/cli.d.ts +3 -1
- package/dist/types/src/linter.d.ts +20 -5
- package/dist/types/src/rules/erb-no-empty-tags.d.ts +5 -4
- package/dist/types/src/rules/erb-no-output-control-flow.d.ts +5 -4
- package/dist/types/src/rules/erb-prefer-image-tag-helper.d.ts +7 -0
- package/dist/types/src/rules/erb-require-whitespace-inside-tags.d.ts +5 -4
- package/dist/types/src/rules/erb-requires-trailing-newline.d.ts +6 -0
- package/dist/types/src/rules/html-anchor-require-href.d.ts +5 -4
- package/dist/types/src/rules/html-aria-attribute-must-be-valid.d.ts +5 -4
- package/dist/types/src/rules/html-aria-level-must-be-valid.d.ts +7 -0
- package/dist/types/src/rules/html-aria-role-heading-requires-level.d.ts +5 -4
- package/dist/types/src/rules/html-aria-role-must-be-valid.d.ts +5 -4
- package/dist/types/src/rules/html-attribute-double-quotes.d.ts +5 -4
- package/dist/types/src/rules/html-attribute-values-require-quotes.d.ts +5 -4
- package/dist/types/src/rules/html-boolean-attributes-no-value.d.ts +5 -4
- package/dist/types/src/rules/html-img-require-alt.d.ts +5 -4
- package/dist/types/src/rules/html-no-block-inside-inline.d.ts +5 -4
- package/dist/types/src/rules/html-no-duplicate-attributes.d.ts +5 -4
- package/dist/types/src/rules/html-no-duplicate-ids.d.ts +5 -4
- package/dist/types/src/rules/html-no-empty-headings.d.ts +5 -4
- package/dist/types/src/rules/html-no-nested-links.d.ts +5 -4
- package/dist/types/src/rules/html-tag-name-lowercase.d.ts +5 -4
- package/dist/types/src/rules/index.d.ts +3 -0
- package/dist/types/src/rules/parser-no-errors.d.ts +8 -0
- package/dist/types/src/rules/rule-utils.d.ts +73 -4
- package/dist/types/src/rules/svg-tag-name-capitalization.d.ts +5 -4
- package/dist/types/src/types.d.ts +50 -7
- package/dist/types/types.d.ts +50 -7
- package/docs/rules/README.md +5 -1
- package/docs/rules/erb-prefer-image-tag-helper.md +65 -0
- package/docs/rules/erb-requires-trailing-newline.md +37 -0
- package/docs/rules/html-anchor-require-href.md +1 -1
- package/docs/rules/html-aria-level-must-be-valid.md +37 -0
- package/docs/rules/parser-no-errors.md +84 -0
- package/package.json +4 -4
- package/src/cli/argument-parser.ts +33 -19
- package/src/cli/file-processor.ts +27 -21
- package/src/cli/formatters/base-formatter.ts +2 -2
- package/src/cli/formatters/detailed-formatter.ts +9 -9
- package/src/cli/formatters/github-actions-formatter.ts +70 -0
- package/src/cli/formatters/index.ts +2 -0
- package/src/cli/formatters/json-formatter.ts +107 -0
- package/src/cli/formatters/simple-formatter.ts +15 -15
- package/src/cli/output-manager.ts +143 -0
- package/src/cli/summary-reporter.ts +24 -24
- package/src/cli.ts +48 -31
- package/src/default-rules.ts +8 -0
- package/src/linter.ts +42 -8
- package/src/rules/erb-no-empty-tags.ts +7 -6
- package/src/rules/erb-no-output-control-flow.ts +8 -6
- package/src/rules/erb-prefer-image-tag-helper.ts +124 -0
- package/src/rules/erb-require-whitespace-inside-tags.ts +7 -6
- package/src/rules/erb-requires-trailing-newline.ts +29 -0
- package/src/rules/html-anchor-require-href.ts +7 -6
- package/src/rules/html-aria-attribute-must-be-valid.ts +7 -7
- package/src/rules/html-aria-level-must-be-valid.ts +42 -0
- package/src/rules/html-aria-role-heading-requires-level.ts +7 -6
- package/src/rules/html-aria-role-must-be-valid.ts +7 -6
- package/src/rules/html-attribute-double-quotes.ts +7 -6
- package/src/rules/html-attribute-values-require-quotes.ts +7 -6
- package/src/rules/html-boolean-attributes-no-value.ts +7 -6
- package/src/rules/html-img-require-alt.ts +7 -6
- package/src/rules/html-no-block-inside-inline.ts +9 -8
- package/src/rules/html-no-duplicate-attributes.ts +7 -6
- package/src/rules/html-no-duplicate-ids.ts +7 -7
- package/src/rules/html-no-empty-headings.ts +7 -6
- package/src/rules/html-no-nested-links.ts +7 -6
- package/src/rules/html-tag-name-lowercase.ts +7 -6
- package/src/rules/index.ts +3 -0
- package/src/rules/parser-no-errors.ts +25 -0
- package/src/rules/rule-utils.ts +156 -4
- package/src/rules/svg-tag-name-capitalization.ts +7 -6
- package/src/types.ts +61 -7
|
@@ -1,29 +1,29 @@
|
|
|
1
1
|
import { colorize } from "@herb-tools/highlighter";
|
|
2
2
|
import { BaseFormatter } from "./base-formatter.js";
|
|
3
3
|
export class SimpleFormatter extends BaseFormatter {
|
|
4
|
-
async format(
|
|
5
|
-
if (
|
|
4
|
+
async format(allOffenses) {
|
|
5
|
+
if (allOffenses.length === 0)
|
|
6
6
|
return;
|
|
7
|
-
const
|
|
8
|
-
for (const { filename,
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
7
|
+
const groupedOffenses = new Map();
|
|
8
|
+
for (const { filename, offense } of allOffenses) {
|
|
9
|
+
const offenses = groupedOffenses.get(filename) || [];
|
|
10
|
+
offenses.push(offense);
|
|
11
|
+
groupedOffenses.set(filename, offenses);
|
|
12
12
|
}
|
|
13
|
-
for (const [filename,
|
|
13
|
+
for (const [filename, offenses] of groupedOffenses) {
|
|
14
14
|
console.log("");
|
|
15
|
-
this.formatFile(filename,
|
|
15
|
+
this.formatFile(filename, offenses);
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
|
-
formatFile(filename,
|
|
18
|
+
formatFile(filename, offenses) {
|
|
19
19
|
console.log(`${colorize(filename, "cyan")}:`);
|
|
20
|
-
for (const
|
|
21
|
-
const isError =
|
|
20
|
+
for (const offense of offenses) {
|
|
21
|
+
const isError = offense.severity === "error";
|
|
22
22
|
const severity = isError ? colorize("✗", "brightRed") : colorize("⚠", "brightYellow");
|
|
23
|
-
const rule = colorize(`(${
|
|
24
|
-
const locationString = `${
|
|
23
|
+
const rule = colorize(`(${offense.code})`, "blue");
|
|
24
|
+
const locationString = `${offense.location.start.line}:${offense.location.start.column}`;
|
|
25
25
|
const paddedLocation = locationString.padEnd(4); // Pad to 4 characters for alignment
|
|
26
|
-
console.log(` ${colorize(paddedLocation, "gray")} ${severity} ${
|
|
26
|
+
console.log(` ${colorize(paddedLocation, "gray")} ${severity} ${offense.message} ${rule}`);
|
|
27
27
|
}
|
|
28
28
|
console.log("");
|
|
29
29
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simple-formatter.js","sourceRoot":"","sources":["../../../../src/cli/formatters/simple-formatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAKnD,MAAM,OAAO,eAAgB,SAAQ,aAAa;IAChD,KAAK,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"simple-formatter.js","sourceRoot":"","sources":["../../../../src/cli/formatters/simple-formatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AAKnD,MAAM,OAAO,eAAgB,SAAQ,aAAa;IAChD,KAAK,CAAC,MAAM,CAAC,WAA4B;QACvC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC;YAAE,OAAM;QAEpC,MAAM,eAAe,GAAG,IAAI,GAAG,EAAwB,CAAA;QAEvD,KAAK,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,WAAW,EAAE,CAAC;YAChD,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAA;YACpD,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;YACtB,eAAe,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;QACzC,CAAC;QAED,KAAK,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,IAAI,eAAe,EAAE,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;YACf,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;QACrC,CAAC;IACH,CAAC;IAED,UAAU,CAAC,QAAgB,EAAE,QAAsB;QACjD,OAAO,CAAC,GAAG,CAAC,GAAG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC,GAAG,CAAC,CAAA;QAE7C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAA;YAC5C,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC,CAAA;YACrF,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,OAAO,CAAC,IAAI,GAAG,EAAE,MAAM,CAAC,CAAA;YAClD,MAAM,cAAc,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,CAAA;YACxF,MAAM,cAAc,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA,CAAC,oCAAoC;YAEpF,OAAO,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC,IAAI,QAAQ,IAAI,OAAO,CAAC,OAAO,IAAI,IAAI,EAAE,CAAC,CAAA;QAC7F,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IACjB,CAAC;CACF"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { SummaryReporter } from "./summary-reporter.js";
|
|
2
|
+
import { SimpleFormatter, DetailedFormatter, GitHubActionsFormatter } from "./formatters/index.js";
|
|
3
|
+
export class OutputManager {
|
|
4
|
+
summaryReporter = new SummaryReporter();
|
|
5
|
+
/**
|
|
6
|
+
* Output successful lint results
|
|
7
|
+
*/
|
|
8
|
+
async outputResults(results, options) {
|
|
9
|
+
const { allOffenses, files, totalErrors, totalWarnings, filesWithOffenses, ruleCount, ruleOffenses } = results;
|
|
10
|
+
if (options.formatOption === "github") {
|
|
11
|
+
const formatter = new GitHubActionsFormatter();
|
|
12
|
+
await formatter.format(allOffenses);
|
|
13
|
+
}
|
|
14
|
+
else if (options.formatOption === "json") {
|
|
15
|
+
const output = {
|
|
16
|
+
offenses: allOffenses.map(({ filename, offense }) => ({
|
|
17
|
+
filename,
|
|
18
|
+
message: offense.message,
|
|
19
|
+
location: offense.location.toJSON(),
|
|
20
|
+
severity: offense.severity,
|
|
21
|
+
code: offense.code,
|
|
22
|
+
source: offense.source
|
|
23
|
+
})),
|
|
24
|
+
summary: {
|
|
25
|
+
filesChecked: files.length,
|
|
26
|
+
filesWithOffenses,
|
|
27
|
+
totalErrors,
|
|
28
|
+
totalWarnings,
|
|
29
|
+
totalOffenses: totalErrors + totalWarnings,
|
|
30
|
+
ruleCount
|
|
31
|
+
},
|
|
32
|
+
timing: null,
|
|
33
|
+
completed: true,
|
|
34
|
+
clean: totalErrors === 0 && totalWarnings === 0,
|
|
35
|
+
message: null
|
|
36
|
+
};
|
|
37
|
+
const duration = Date.now() - options.startTime;
|
|
38
|
+
output.timing = options.showTiming ? {
|
|
39
|
+
startTime: options.startDate.toISOString(),
|
|
40
|
+
duration: duration
|
|
41
|
+
} : null;
|
|
42
|
+
console.log(JSON.stringify(output, null, 2));
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
const formatter = options.formatOption === "simple"
|
|
46
|
+
? new SimpleFormatter()
|
|
47
|
+
: new DetailedFormatter(options.theme, options.wrapLines, options.truncateLines);
|
|
48
|
+
await formatter.format(allOffenses, files.length === 1);
|
|
49
|
+
this.summaryReporter.displayMostViolatedRules(ruleOffenses);
|
|
50
|
+
this.summaryReporter.displaySummary({
|
|
51
|
+
files,
|
|
52
|
+
totalErrors,
|
|
53
|
+
totalWarnings,
|
|
54
|
+
filesWithOffenses,
|
|
55
|
+
ruleCount,
|
|
56
|
+
startTime: options.startTime,
|
|
57
|
+
startDate: options.startDate,
|
|
58
|
+
showTiming: options.showTiming,
|
|
59
|
+
ruleOffenses
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Output informational message (like "no files found")
|
|
65
|
+
*/
|
|
66
|
+
outputInfo(message, options) {
|
|
67
|
+
if (options.formatOption === "github") {
|
|
68
|
+
// GitHub Actions format doesn't output anything for info messages
|
|
69
|
+
}
|
|
70
|
+
else if (options.formatOption === "json") {
|
|
71
|
+
const output = {
|
|
72
|
+
offenses: [],
|
|
73
|
+
summary: {
|
|
74
|
+
filesChecked: 0,
|
|
75
|
+
filesWithOffenses: 0,
|
|
76
|
+
totalErrors: 0,
|
|
77
|
+
totalWarnings: 0,
|
|
78
|
+
totalOffenses: 0,
|
|
79
|
+
ruleCount: 0
|
|
80
|
+
},
|
|
81
|
+
timing: null,
|
|
82
|
+
completed: false,
|
|
83
|
+
clean: null,
|
|
84
|
+
message
|
|
85
|
+
};
|
|
86
|
+
const duration = Date.now() - options.startTime;
|
|
87
|
+
output.timing = options.showTiming ? {
|
|
88
|
+
startTime: options.startDate.toISOString(),
|
|
89
|
+
duration: duration
|
|
90
|
+
} : null;
|
|
91
|
+
console.log(JSON.stringify(output, null, 2));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
console.log(message);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Output error message
|
|
99
|
+
*/
|
|
100
|
+
outputError(message, options) {
|
|
101
|
+
if (options.formatOption === "github") {
|
|
102
|
+
console.log(`::error::${message}`);
|
|
103
|
+
}
|
|
104
|
+
else if (options.formatOption === "json") {
|
|
105
|
+
const output = {
|
|
106
|
+
offenses: [],
|
|
107
|
+
summary: null,
|
|
108
|
+
timing: null,
|
|
109
|
+
completed: false,
|
|
110
|
+
clean: null,
|
|
111
|
+
message
|
|
112
|
+
};
|
|
113
|
+
console.log(JSON.stringify(output, null, 2));
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
console.error(message);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=output-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output-manager.js","sourceRoot":"","sources":["../../../src/cli/output-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,22 +4,22 @@ export class SummaryReporter {
|
|
|
4
4
|
return count === 1 ? singular : (plural || `${singular}s`);
|
|
5
5
|
}
|
|
6
6
|
displaySummary(data) {
|
|
7
|
-
const { files, totalErrors, totalWarnings,
|
|
7
|
+
const { files, totalErrors, totalWarnings, filesWithOffenses, ruleCount, startTime, startDate, showTiming } = data;
|
|
8
8
|
console.log("\n");
|
|
9
9
|
console.log(` ${colorize("Summary:", "bold")}`);
|
|
10
10
|
// Calculate padding for alignment
|
|
11
|
-
const labelWidth = 12; // Width for the longest label "
|
|
11
|
+
const labelWidth = 12; // Width for the longest label "Offenses"
|
|
12
12
|
const pad = (label) => label.padEnd(labelWidth);
|
|
13
13
|
// Checked summary
|
|
14
14
|
console.log(` ${colorize(pad("Checked"), "gray")} ${colorize(`${files.length} ${this.pluralize(files.length, "file")}`, "cyan")}`);
|
|
15
15
|
// Files summary (for multiple files)
|
|
16
16
|
if (files.length > 1) {
|
|
17
17
|
const filesChecked = files.length;
|
|
18
|
-
const filesClean = filesChecked -
|
|
18
|
+
const filesClean = filesChecked - filesWithOffenses;
|
|
19
19
|
let filesSummary = "";
|
|
20
20
|
let shouldDim = false;
|
|
21
|
-
if (
|
|
22
|
-
filesSummary = `${colorize(colorize(`${
|
|
21
|
+
if (filesWithOffenses > 0) {
|
|
22
|
+
filesSummary = `${colorize(colorize(`${filesWithOffenses} with offenses`, "brightRed"), "bold")} | ${colorize(colorize(`${filesClean} clean`, "green"), "bold")} ${colorize(colorize(`(${filesChecked} total)`, "gray"), "dim")}`;
|
|
23
23
|
}
|
|
24
24
|
else {
|
|
25
25
|
filesSummary = `${colorize(colorize(`${filesChecked} clean`, "green"), "bold")} ${colorize(colorize(`(${filesChecked} total)`, "gray"), "dim")}`;
|
|
@@ -32,8 +32,8 @@ export class SummaryReporter {
|
|
|
32
32
|
console.log(` ${colorize(pad("Files"), "gray")} ${filesSummary}`);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
-
//
|
|
36
|
-
let
|
|
35
|
+
// Offenses summary with file count
|
|
36
|
+
let offensesSummary = "";
|
|
37
37
|
const parts = [];
|
|
38
38
|
// Build the main part with errors and warnings
|
|
39
39
|
if (totalErrors > 0) {
|
|
@@ -47,19 +47,19 @@ export class SummaryReporter {
|
|
|
47
47
|
parts.push(colorize(colorize(`${totalWarnings} ${this.pluralize(totalWarnings, "warning")}`, "green"), "bold"));
|
|
48
48
|
}
|
|
49
49
|
if (parts.length === 0) {
|
|
50
|
-
|
|
50
|
+
offensesSummary = colorize(colorize("0 offenses", "green"), "bold");
|
|
51
51
|
}
|
|
52
52
|
else {
|
|
53
|
-
|
|
53
|
+
offensesSummary = parts.join(" | ");
|
|
54
54
|
// Add total count and file count
|
|
55
55
|
let detailText = "";
|
|
56
|
-
const
|
|
57
|
-
if (
|
|
58
|
-
detailText = `${
|
|
56
|
+
const totalOffenses = totalErrors + totalWarnings;
|
|
57
|
+
if (filesWithOffenses > 0) {
|
|
58
|
+
detailText = `${totalOffenses} ${this.pluralize(totalOffenses, "offense")} across ${filesWithOffenses} ${this.pluralize(filesWithOffenses, "file")}`;
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
offensesSummary += ` ${colorize(colorize(`(${detailText})`, "gray"), "dim")}`;
|
|
61
61
|
}
|
|
62
|
-
console.log(` ${colorize(pad("
|
|
62
|
+
console.log(` ${colorize(pad("Offenses"), "gray")} ${offensesSummary}`);
|
|
63
63
|
// Timing information (if enabled)
|
|
64
64
|
if (showTiming) {
|
|
65
65
|
const duration = Date.now() - startTime;
|
|
@@ -68,28 +68,28 @@ export class SummaryReporter {
|
|
|
68
68
|
console.log(` ${colorize(pad("Duration"), "gray")} ${colorize(`${duration}ms`, "cyan")} ${colorize(colorize(`(${ruleCount} ${this.pluralize(ruleCount, "rule")})`, "gray"), "dim")}`);
|
|
69
69
|
}
|
|
70
70
|
// Success message for all files clean
|
|
71
|
-
if (
|
|
71
|
+
if (filesWithOffenses === 0 && files.length > 1) {
|
|
72
72
|
console.log("");
|
|
73
73
|
console.log(` ${colorize("✓", "brightGreen")} ${colorize("All files are clean!", "green")}`);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
|
-
displayMostViolatedRules(
|
|
77
|
-
if (
|
|
76
|
+
displayMostViolatedRules(ruleOffenses, limit = 5) {
|
|
77
|
+
if (ruleOffenses.size === 0)
|
|
78
78
|
return;
|
|
79
|
-
const allRules = Array.from(
|
|
79
|
+
const allRules = Array.from(ruleOffenses.entries()).sort((a, b) => b[1].count - a[1].count);
|
|
80
80
|
const displayedRules = allRules.slice(0, limit);
|
|
81
81
|
const remainingRules = allRules.slice(limit);
|
|
82
|
-
const title =
|
|
82
|
+
const title = ruleOffenses.size <= limit ? "Rule offenses:" : "Most frequent rule offenses:";
|
|
83
83
|
console.log(` ${colorize(title, "bold")}`);
|
|
84
84
|
for (const [rule, data] of displayedRules) {
|
|
85
85
|
const fileCount = data.files.size;
|
|
86
|
-
const countText = `(${data.count} ${this.pluralize(data.count, "
|
|
86
|
+
const countText = `(${data.count} ${this.pluralize(data.count, "offense")} in ${fileCount} ${this.pluralize(fileCount, "file")})`;
|
|
87
87
|
console.log(` ${colorize(rule, "gray")} ${colorize(colorize(countText, "gray"), "dim")}`);
|
|
88
88
|
}
|
|
89
89
|
if (remainingRules.length > 0) {
|
|
90
|
-
const
|
|
90
|
+
const remainingOffenseCount = remainingRules.reduce((sum, [_, data]) => sum + data.count, 0);
|
|
91
91
|
const remainingRuleCount = remainingRules.length;
|
|
92
|
-
console.log(colorize(colorize(`\n ...and ${remainingRuleCount} more ${this.pluralize(remainingRuleCount, "rule")} with ${
|
|
92
|
+
console.log(colorize(colorize(`\n ...and ${remainingRuleCount} more ${this.pluralize(remainingRuleCount, "rule")} with ${remainingOffenseCount} ${this.pluralize(remainingOffenseCount, "offense")}`, "gray"), "dim"));
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"summary-reporter.js","sourceRoot":"","sources":["../../../src/cli/summary-reporter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAclD,MAAM,OAAO,eAAe;IAClB,SAAS,CAAC,KAAa,EAAE,QAAgB,EAAE,MAAe;QAChE,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,IAAI,GAAG,QAAQ,GAAG,CAAC,CAAA;IAC5D,CAAC;IAED,cAAc,CAAC,IAAiB;QAC9B,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,
|
|
1
|
+
{"version":3,"file":"summary-reporter.js","sourceRoot":"","sources":["../../../src/cli/summary-reporter.ts"],"names":[],"mappings":"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"}
|
package/dist/src/cli.js
CHANGED
|
@@ -2,48 +2,63 @@ import { glob } from "glob";
|
|
|
2
2
|
import { Herb } from "@herb-tools/node-wasm";
|
|
3
3
|
import { ArgumentParser } from "./cli/argument-parser.js";
|
|
4
4
|
import { FileProcessor } from "./cli/file-processor.js";
|
|
5
|
-
import {
|
|
6
|
-
import { SummaryReporter } from "./cli/summary-reporter.js";
|
|
5
|
+
import { OutputManager } from "./cli/output-manager.js";
|
|
7
6
|
export class CLI {
|
|
8
7
|
argumentParser = new ArgumentParser();
|
|
9
8
|
fileProcessor = new FileProcessor();
|
|
10
|
-
|
|
9
|
+
outputManager = new OutputManager();
|
|
10
|
+
exitWithError(message, formatOption, exitCode = 1) {
|
|
11
|
+
this.outputManager.outputError(message, {
|
|
12
|
+
formatOption,
|
|
13
|
+
theme: 'auto',
|
|
14
|
+
wrapLines: false,
|
|
15
|
+
truncateLines: false,
|
|
16
|
+
showTiming: false,
|
|
17
|
+
startTime: 0,
|
|
18
|
+
startDate: new Date()
|
|
19
|
+
});
|
|
20
|
+
process.exit(exitCode);
|
|
21
|
+
}
|
|
22
|
+
exitWithInfo(message, formatOption, exitCode = 0, timingData) {
|
|
23
|
+
const outputOptions = {
|
|
24
|
+
formatOption,
|
|
25
|
+
theme: 'auto',
|
|
26
|
+
wrapLines: false,
|
|
27
|
+
truncateLines: false,
|
|
28
|
+
showTiming: timingData?.showTiming ?? false,
|
|
29
|
+
startTime: timingData?.startTime ?? Date.now(),
|
|
30
|
+
startDate: timingData?.startDate ?? new Date()
|
|
31
|
+
};
|
|
32
|
+
this.outputManager.outputInfo(message, outputOptions);
|
|
33
|
+
process.exit(exitCode);
|
|
34
|
+
}
|
|
11
35
|
async run() {
|
|
12
36
|
const startTime = Date.now();
|
|
13
37
|
const startDate = new Date();
|
|
14
38
|
const { pattern, formatOption, showTiming, theme, wrapLines, truncateLines } = this.argumentParser.parse(process.argv);
|
|
39
|
+
const outputOptions = {
|
|
40
|
+
formatOption,
|
|
41
|
+
theme,
|
|
42
|
+
wrapLines,
|
|
43
|
+
truncateLines,
|
|
44
|
+
showTiming,
|
|
45
|
+
startTime,
|
|
46
|
+
startDate
|
|
47
|
+
};
|
|
15
48
|
try {
|
|
16
49
|
await Herb.load();
|
|
17
50
|
const files = await glob(pattern);
|
|
18
51
|
if (files.length === 0) {
|
|
19
|
-
|
|
20
|
-
process.exit(0);
|
|
52
|
+
this.exitWithInfo(`No files found matching pattern: ${pattern}`, formatOption, 0, { startTime, startDate, showTiming });
|
|
21
53
|
}
|
|
22
|
-
const results = await this.fileProcessor.processFiles(files);
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
? new SimpleFormatter()
|
|
26
|
-
: new DetailedFormatter(theme, wrapLines, truncateLines);
|
|
27
|
-
await formatter.format(allDiagnostics, files.length === 1);
|
|
28
|
-
this.summaryReporter.displayMostViolatedRules(ruleViolations);
|
|
29
|
-
this.summaryReporter.displaySummary({
|
|
30
|
-
files,
|
|
31
|
-
totalErrors,
|
|
32
|
-
totalWarnings,
|
|
33
|
-
filesWithViolations: filesWithIssues,
|
|
34
|
-
ruleCount,
|
|
35
|
-
startTime,
|
|
36
|
-
startDate,
|
|
37
|
-
showTiming,
|
|
38
|
-
ruleViolations
|
|
39
|
-
});
|
|
40
|
-
if (totalErrors > 0) {
|
|
54
|
+
const results = await this.fileProcessor.processFiles(files, formatOption);
|
|
55
|
+
await this.outputManager.outputResults({ ...results, files }, outputOptions);
|
|
56
|
+
if (results.totalErrors > 0) {
|
|
41
57
|
process.exit(1);
|
|
42
58
|
}
|
|
43
59
|
}
|
|
44
60
|
catch (error) {
|
|
45
|
-
|
|
46
|
-
process.exit(1);
|
|
61
|
+
this.exitWithError(`Error: ${error}`, formatOption);
|
|
47
62
|
}
|
|
48
63
|
}
|
|
49
64
|
}
|
package/dist/src/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAA;AAC5C,OAAO,EAAE,cAAc,
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { ERBNoEmptyTagsRule } from "./rules/erb-no-empty-tags.js";
|
|
2
2
|
import { ERBNoOutputControlFlowRule } from "./rules/erb-no-output-control-flow.js";
|
|
3
|
+
import { ERBPreferImageTagHelperRule } from "./rules/erb-prefer-image-tag-helper.js";
|
|
4
|
+
import { ERBRequiresTrailingNewlineRule } from "./rules/erb-requires-trailing-newline.js";
|
|
3
5
|
import { ERBRequireWhitespaceRule } from "./rules/erb-require-whitespace-inside-tags.js";
|
|
4
6
|
import { HTMLAnchorRequireHrefRule } from "./rules/html-anchor-require-href.js";
|
|
5
7
|
import { HTMLAriaAttributeMustBeValid } from "./rules/html-aria-attribute-must-be-valid.js";
|
|
8
|
+
import { HTMLAriaLevelMustBeValidRule } from "./rules/html-aria-level-must-be-valid.js";
|
|
6
9
|
import { HTMLAriaRoleHeadingRequiresLevelRule } from "./rules/html-aria-role-heading-requires-level.js";
|
|
7
10
|
import { HTMLAriaRoleMustBeValidRule } from "./rules/html-aria-role-must-be-valid.js";
|
|
8
11
|
import { HTMLAttributeDoubleQuotesRule } from "./rules/html-attribute-double-quotes.js";
|
|
@@ -15,13 +18,17 @@ import { HTMLNoDuplicateIdsRule } from "./rules/html-no-duplicate-ids.js";
|
|
|
15
18
|
import { HTMLNoEmptyHeadingsRule } from "./rules/html-no-empty-headings.js";
|
|
16
19
|
import { HTMLNoNestedLinksRule } from "./rules/html-no-nested-links.js";
|
|
17
20
|
import { HTMLTagNameLowercaseRule } from "./rules/html-tag-name-lowercase.js";
|
|
21
|
+
import { ParserNoErrorsRule } from "./rules/parser-no-errors.js";
|
|
18
22
|
import { SVGTagNameCapitalizationRule } from "./rules/svg-tag-name-capitalization.js";
|
|
19
23
|
export const defaultRules = [
|
|
20
24
|
ERBNoEmptyTagsRule,
|
|
21
25
|
ERBNoOutputControlFlowRule,
|
|
26
|
+
ERBPreferImageTagHelperRule,
|
|
27
|
+
ERBRequiresTrailingNewlineRule,
|
|
22
28
|
ERBRequireWhitespaceRule,
|
|
23
29
|
HTMLAnchorRequireHrefRule,
|
|
24
30
|
HTMLAriaAttributeMustBeValid,
|
|
31
|
+
HTMLAriaLevelMustBeValidRule,
|
|
25
32
|
HTMLAriaRoleHeadingRequiresLevelRule,
|
|
26
33
|
HTMLAriaRoleMustBeValidRule,
|
|
27
34
|
HTMLAttributeDoubleQuotesRule,
|
|
@@ -34,6 +41,7 @@ export const defaultRules = [
|
|
|
34
41
|
HTMLNoEmptyHeadingsRule,
|
|
35
42
|
HTMLNoNestedLinksRule,
|
|
36
43
|
HTMLTagNameLowercaseRule,
|
|
44
|
+
ParserNoErrorsRule,
|
|
37
45
|
SVGTagNameCapitalizationRule,
|
|
38
46
|
];
|
|
39
47
|
//# sourceMappingURL=default-rules.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default-rules.js","sourceRoot":"","sources":["../../src/default-rules.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAA;AAClF,OAAO,EAAE,wBAAwB,EAAE,MAAM,+CAA+C,CAAA;AACxF,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAA;AAC/E,OAAO,EAAE,4BAA4B,EAAE,MAAM,8CAA8C,CAAA;AAC3F,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,oCAAoC,EAAE,MAAM,iDAAiD,CAAA;AACtG,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAA;AAC9F,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,uFAAuF;AACvF,OAAO,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAA;AACvF,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAA;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAC7E,OAAO,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAA;AAErF,MAAM,CAAC,MAAM,YAAY,GAAgB;IACvC,kBAAkB;IAClB,0BAA0B;IAC1B,wBAAwB;IACxB,yBAAyB;IACzB,4BAA4B;IAC5B,oCAAoC;IACpC,2BAA2B;IAC3B,6BAA6B;IAC7B,oCAAoC;IACpC,gCAAgC;IAChC,qBAAqB;IACrB,+BAA+B;IAC/B,6BAA6B;IAC7B,sBAAsB;IACtB,uBAAuB;IACvB,qBAAqB;IACrB,wBAAwB;IACxB,4BAA4B;CAC7B,CAAA"}
|
|
1
|
+
{"version":3,"file":"default-rules.js","sourceRoot":"","sources":["../../src/default-rules.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACjE,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAA;AAClF,OAAO,EAAE,2BAA2B,EAAE,MAAM,wCAAwC,CAAA;AACpF,OAAO,EAAE,8BAA8B,EAAE,MAAM,0CAA0C,CAAA;AACzF,OAAO,EAAE,wBAAwB,EAAE,MAAM,+CAA+C,CAAA;AACxF,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAA;AAC/E,OAAO,EAAE,4BAA4B,EAAE,MAAM,8CAA8C,CAAA;AAC3F,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,oCAAoC,EAAE,MAAM,iDAAiD,CAAA;AACtG,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAA;AAC9F,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,uFAAuF;AACvF,OAAO,EAAE,6BAA6B,EAAE,MAAM,yCAAyC,CAAA;AACvF,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,EAAE,uBAAuB,EAAE,MAAM,mCAAmC,CAAA;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAAE,4BAA4B,EAAE,MAAM,wCAAwC,CAAA;AAErF,MAAM,CAAC,MAAM,YAAY,GAAgB;IACvC,kBAAkB;IAClB,0BAA0B;IAC1B,2BAA2B;IAC3B,8BAA8B;IAC9B,wBAAwB;IACxB,yBAAyB;IACzB,4BAA4B;IAC5B,4BAA4B;IAC5B,oCAAoC;IACpC,2BAA2B;IAC3B,6BAA6B;IAC7B,oCAAoC;IACpC,gCAAgC;IAChC,qBAAqB;IACrB,+BAA+B;IAC/B,6BAA6B;IAC7B,sBAAsB;IACtB,uBAAuB;IACvB,qBAAqB;IACrB,wBAAwB;IACxB,kBAAkB;IAClB,4BAA4B;CAC7B,CAAA"}
|
package/dist/src/linter.js
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { defaultRules } from "./default-rules.js";
|
|
2
2
|
export class Linter {
|
|
3
3
|
rules;
|
|
4
|
+
herb;
|
|
4
5
|
offenses;
|
|
5
6
|
/**
|
|
6
7
|
* Creates a new Linter instance.
|
|
7
|
-
* @param
|
|
8
|
+
* @param herb - The Herb backend instance for parsing and lexing
|
|
9
|
+
* @param rules - Array of rule classes (Parser/AST or Lexer) to use. If not provided, uses default rules.
|
|
8
10
|
*/
|
|
9
|
-
constructor(rules) {
|
|
11
|
+
constructor(herb, rules) {
|
|
12
|
+
this.herb = herb;
|
|
10
13
|
this.rules = rules !== undefined ? rules : this.getDefaultRules();
|
|
11
14
|
this.offenses = [];
|
|
12
15
|
}
|
|
@@ -20,11 +23,39 @@ export class Linter {
|
|
|
20
23
|
getRuleCount() {
|
|
21
24
|
return this.rules.length;
|
|
22
25
|
}
|
|
23
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Type guard to check if a rule is a LexerRule
|
|
28
|
+
*/
|
|
29
|
+
isLexerRule(rule) {
|
|
30
|
+
return rule.constructor.type === "lexer";
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Type guard to check if a rule is a SourceRule
|
|
34
|
+
*/
|
|
35
|
+
isSourceRule(rule) {
|
|
36
|
+
return rule.constructor.type === "source";
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Lint source code using Parser/AST, Lexer, and Source rules.
|
|
40
|
+
* @param source - The source code to lint
|
|
41
|
+
* @param context - Optional context for linting (e.g., fileName for distinguishing files vs snippets)
|
|
42
|
+
*/
|
|
43
|
+
lint(source, context) {
|
|
24
44
|
this.offenses = [];
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
45
|
+
const parseResult = this.herb.parse(source);
|
|
46
|
+
const lexResult = this.herb.lex(source);
|
|
47
|
+
for (const RuleClass of this.rules) {
|
|
48
|
+
const rule = new RuleClass();
|
|
49
|
+
let ruleOffenses;
|
|
50
|
+
if (this.isLexerRule(rule)) {
|
|
51
|
+
ruleOffenses = rule.check(lexResult, context);
|
|
52
|
+
}
|
|
53
|
+
else if (this.isSourceRule(rule)) {
|
|
54
|
+
ruleOffenses = rule.check(source, context);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
ruleOffenses = rule.check(parseResult, context);
|
|
58
|
+
}
|
|
28
59
|
this.offenses.push(...ruleOffenses);
|
|
29
60
|
}
|
|
30
61
|
const errors = this.offenses.filter(offense => offense.severity === "error").length;
|
package/dist/src/linter.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"linter.js","sourceRoot":"","sources":["../../src/linter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAKjD,MAAM,OAAO,MAAM;IACT,KAAK,CAAa;IAClB,QAAQ,CAAe;IAE/B
|
|
1
|
+
{"version":3,"file":"linter.js","sourceRoot":"","sources":["../../src/linter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAKjD,MAAM,OAAO,MAAM;IACT,KAAK,CAAa;IAClB,IAAI,CAAa;IACjB,QAAQ,CAAe;IAE/B;;;;OAIG;IACH,YAAY,IAAiB,EAAE,KAAmB;QAChD,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,KAAK,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,EAAE,CAAA;QACjE,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;IACpB,CAAC;IAED;;;OAGG;IACK,eAAe;QACrB,OAAO,YAAY,CAAA;IACrB,CAAC;IAED,YAAY;QACV,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAA;IAC1B,CAAC;IAED;;OAEG;IACK,WAAW,CAAC,IAAU;QAC5B,OAAQ,IAAI,CAAC,WAAmB,CAAC,IAAI,KAAK,OAAO,CAAA;IACnD,CAAC;IAED;;OAEG;IACK,YAAY,CAAC,IAAU;QAC7B,OAAQ,IAAI,CAAC,WAAmB,CAAC,IAAI,KAAK,QAAQ,CAAA;IACpD,CAAC;IAED;;;;OAIG;IACH,IAAI,CAAC,MAAc,EAAE,OAA8B;QACjD,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;QAElB,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;QAC3C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAA;QAEvC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACnC,MAAM,IAAI,GAAG,IAAI,SAAS,EAAE,CAAA;YAE5B,IAAI,YAA2B,CAAA;YAE/B,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;gBAC3B,YAAY,GAAI,IAAkB,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAA;YAC9D,CAAC;iBAAM,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;gBACnC,YAAY,GAAI,IAAmB,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YAC5D,CAAC;iBAAM,CAAC;gBACN,YAAY,GAAI,IAAmB,CAAC,KAAK,CAAC,WAAW,EAAE,OAAO,CAAC,CAAA;YACjE,CAAC;YAED,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,CAAA;QACrC,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM,CAAA;QACnF,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM,CAAA;QAEvF,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,MAAM;YACN,QAAQ;SACT,CAAA;IACH,CAAC;CACF"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BaseRuleVisitor } from "./rule-utils.js";
|
|
2
|
+
import { ParserRule } from "../types.js";
|
|
2
3
|
class ERBNoEmptyTagsVisitor extends BaseRuleVisitor {
|
|
3
4
|
visitERBContentNode(node) {
|
|
4
5
|
this.visitChildNodes(node);
|
|
@@ -12,11 +13,11 @@ class ERBNoEmptyTagsVisitor extends BaseRuleVisitor {
|
|
|
12
13
|
this.addOffense("ERB tag should not be empty. Remove empty ERB tags or add content.", node.location, "error");
|
|
13
14
|
}
|
|
14
15
|
}
|
|
15
|
-
export class ERBNoEmptyTagsRule {
|
|
16
|
+
export class ERBNoEmptyTagsRule extends ParserRule {
|
|
16
17
|
name = "erb-no-empty-tags";
|
|
17
|
-
check(
|
|
18
|
-
const visitor = new ERBNoEmptyTagsVisitor(this.name);
|
|
19
|
-
visitor.visit(
|
|
18
|
+
check(result, context) {
|
|
19
|
+
const visitor = new ERBNoEmptyTagsVisitor(this.name, context);
|
|
20
|
+
visitor.visit(result.value);
|
|
20
21
|
return visitor.offenses;
|
|
21
22
|
}
|
|
22
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"erb-no-empty-tags.js","sourceRoot":"","sources":["../../../src/rules/erb-no-empty-tags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"erb-no-empty-tags.js","sourceRoot":"","sources":["../../../src/rules/erb-no-empty-tags.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAIxC,MAAM,qBAAsB,SAAQ,eAAe;IACjD,mBAAmB,CAAC,IAAoB;QACtC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;QAE1B,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,IAAI,CAAA;QAErC,IAAI,CAAC,OAAO;YAAE,OAAM;QACpB,IAAI,WAAW,EAAE,KAAK,KAAK,EAAE;YAAE,OAAM;QACrC,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC;YAAE,OAAM;QAE3C,IAAI,CAAC,UAAU,CACb,oEAAoE,EACpE,IAAI,CAAC,QAAQ,EACb,OAAO,CACR,CAAA;IACH,CAAC;CACF;AAED,MAAM,OAAO,kBAAmB,SAAQ,UAAU;IAChD,IAAI,GAAG,mBAAmB,CAAA;IAE1B,KAAK,CAAC,MAAmB,EAAE,OAA8B;QACvD,MAAM,OAAO,GAAG,IAAI,qBAAqB,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAE7D,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAE3B,OAAO,OAAO,CAAC,QAAQ,CAAA;IACzB,CAAC;CACF"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BaseRuleVisitor } from "./rule-utils.js";
|
|
2
|
+
import { ParserRule } from "../types.js";
|
|
2
3
|
class ERBNoOutputControlFlowRuleVisitor extends BaseRuleVisitor {
|
|
3
4
|
visitERBIfNode(node) {
|
|
4
5
|
this.checkOutputControlFlow(node);
|
|
@@ -36,11 +37,11 @@ class ERBNoOutputControlFlowRuleVisitor extends BaseRuleVisitor {
|
|
|
36
37
|
return;
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
|
-
export class ERBNoOutputControlFlowRule {
|
|
40
|
+
export class ERBNoOutputControlFlowRule extends ParserRule {
|
|
40
41
|
name = "erb-no-output-control-flow";
|
|
41
|
-
check(
|
|
42
|
-
const visitor = new ERBNoOutputControlFlowRuleVisitor(this.name);
|
|
43
|
-
visitor.visit(
|
|
42
|
+
check(result, context) {
|
|
43
|
+
const visitor = new ERBNoOutputControlFlowRuleVisitor(this.name, context);
|
|
44
|
+
visitor.visit(result.value);
|
|
44
45
|
return visitor.offenses;
|
|
45
46
|
}
|
|
46
47
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"erb-no-output-control-flow.js","sourceRoot":"","sources":["../../../src/rules/erb-no-output-control-flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"erb-no-output-control-flow.js","sourceRoot":"","sources":["../../../src/rules/erb-no-output-control-flow.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAGjD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAGxC,MAAM,iCAAkC,SAAQ,eAAe;IAC7D,cAAc,CAAC,IAAe;QAC5B,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;IAC5B,CAAC;IAED,kBAAkB,CAAC,IAAmB;QACpC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;IAC5B,CAAC;IAED,gBAAgB,CAAC,IAAiB;QAChC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;IAC5B,CAAC;IAED,eAAe,CAAC,IAAgB;QAC9B,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAA;QACjC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAA;IAC5B,CAAC;IAEO,sBAAsB,CAAC,YAAkE;QAC/F,MAAM,OAAO,GAAG,YAAY,CAAC,WAAW,CAAC;QACzC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAM;QACR,CAAC;QAED,IAAI,OAAO,CAAC,KAAK,KAAK,KAAK,EAAC,CAAC;YAC3B,IAAI,gBAAgB,GAAW,YAAY,CAAC,IAAI,CAAA;YAEhD,IAAI,YAAY,CAAC,IAAI,KAAK,iBAAiB;gBAAE,gBAAgB,GAAG,IAAI,CAAA;YACpE,IAAI,YAAY,CAAC,IAAI,KAAK,mBAAmB;gBAAE,gBAAgB,GAAG,MAAM,CAAA;YACxE,IAAI,YAAY,CAAC,IAAI,KAAK,kBAAkB;gBAAE,gBAAgB,GAAG,KAAK,CAAA;YACtE,IAAI,YAAY,CAAC,IAAI,KAAK,qBAAqB;gBAAE,gBAAgB,GAAG,QAAQ,CAAA;YAE5E,IAAI,CAAC,UAAU,CACb,kCAAkC,gBAAgB,oDAAoD,gBAAgB,oBAAoB,EAC1I,OAAO,CAAC,QAAQ,EAChB,OAAO,CACR,CAAA;QACH,CAAC;QAED,OAAM;IACR,CAAC;CACF;AAED,MAAM,OAAO,0BAA2B,SAAQ,UAAU;IACxD,IAAI,GAAG,4BAA4B,CAAA;IAEnC,KAAK,CAAC,MAAmB,EAAE,OAA8B;QACvD,MAAM,OAAO,GAAG,IAAI,iCAAiC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAEzE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;QAE3B,OAAO,OAAO,CAAC,QAAQ,CAAA;IACzB,CAAC;CACF"}
|