@herb-tools/linter 0.4.3 → 0.6.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 +216 -19
- package/dist/herb-lint.js +5559 -1860
- package/dist/herb-lint.js.map +1 -1
- package/dist/index.cjs +722 -187
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +714 -189
- package/dist/index.js.map +1 -1
- package/dist/package.json +4 -4
- package/dist/src/cli/argument-parser.js +28 -22
- package/dist/src/cli/argument-parser.js.map +1 -1
- package/dist/src/cli/file-processor.js +19 -13
- 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 +22 -0
- package/dist/src/default-rules.js.map +1 -1
- package/dist/src/linter.js +29 -4
- package/dist/src/linter.js.map +1 -1
- package/dist/src/rules/erb-no-empty-tags.js +2 -2
- package/dist/src/rules/erb-no-empty-tags.js.map +1 -1
- package/dist/src/rules/erb-no-output-control-flow.js +2 -2
- package/dist/src/rules/erb-no-output-control-flow.js.map +1 -1
- package/dist/src/rules/erb-no-silent-tag-in-attribute-name.js +26 -0
- package/dist/src/rules/erb-no-silent-tag-in-attribute-name.js.map +1 -0
- package/dist/src/rules/erb-prefer-image-tag-helper.js +2 -6
- package/dist/src/rules/erb-prefer-image-tag-helper.js.map +1 -1
- package/dist/src/rules/erb-require-whitespace-inside-tags.js +2 -2
- package/dist/src/rules/erb-require-whitespace-inside-tags.js.map +1 -1
- package/dist/src/rules/erb-requires-trailing-newline.js.map +1 -1
- package/dist/src/rules/html-anchor-require-href.js +2 -2
- package/dist/src/rules/html-anchor-require-href.js.map +1 -1
- package/dist/src/rules/html-aria-attribute-must-be-valid.js +13 -12
- package/dist/src/rules/html-aria-attribute-must-be-valid.js.map +1 -1
- package/dist/src/rules/html-aria-label-is-well-formatted.js +33 -0
- package/dist/src/rules/html-aria-label-is-well-formatted.js.map +1 -0
- package/dist/src/rules/html-aria-level-must-be-valid.js +28 -6
- package/dist/src/rules/html-aria-level-must-be-valid.js.map +1 -1
- package/dist/src/rules/html-aria-role-heading-requires-level.js +9 -15
- 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 -5
- package/dist/src/rules/html-aria-role-must-be-valid.js.map +1 -1
- package/dist/src/rules/html-attribute-double-quotes.js +16 -6
- package/dist/src/rules/html-attribute-double-quotes.js.map +1 -1
- package/dist/src/rules/html-attribute-equals-spacing.js +24 -0
- package/dist/src/rules/html-attribute-equals-spacing.js.map +1 -0
- package/dist/src/rules/html-attribute-values-require-quotes.js +21 -10
- package/dist/src/rules/html-attribute-values-require-quotes.js.map +1 -1
- package/dist/src/rules/html-avoid-both-disabled-and-aria-disabled.js +47 -0
- package/dist/src/rules/html-avoid-both-disabled-and-aria-disabled.js.map +1 -0
- package/dist/src/rules/html-boolean-attributes-no-value.js +11 -4
- package/dist/src/rules/html-boolean-attributes-no-value.js.map +1 -1
- package/dist/src/rules/html-iframe-has-title.js +39 -0
- package/dist/src/rules/html-iframe-has-title.js.map +1 -0
- package/dist/src/rules/html-img-require-alt.js +2 -6
- package/dist/src/rules/html-img-require-alt.js.map +1 -1
- package/dist/src/rules/html-navigation-has-label.js +43 -0
- package/dist/src/rules/html-navigation-has-label.js.map +1 -0
- package/dist/src/rules/html-no-aria-hidden-on-focusable.js +67 -0
- package/dist/src/rules/html-no-aria-hidden-on-focusable.js.map +1 -0
- package/dist/src/rules/html-no-block-inside-inline.js +4 -4
- package/dist/src/rules/html-no-block-inside-inline.js.map +1 -1
- package/dist/src/rules/html-no-duplicate-attributes.js +24 -27
- package/dist/src/rules/html-no-duplicate-attributes.js.map +1 -1
- package/dist/src/rules/html-no-duplicate-ids.js +4 -4
- package/dist/src/rules/html-no-duplicate-ids.js.map +1 -1
- package/dist/src/rules/html-no-empty-headings.js +2 -23
- package/dist/src/rules/html-no-empty-headings.js.map +1 -1
- package/dist/src/rules/html-no-nested-links.js +2 -2
- package/dist/src/rules/html-no-nested-links.js.map +1 -1
- package/dist/src/rules/html-no-positive-tab-index.js +21 -0
- package/dist/src/rules/html-no-positive-tab-index.js.map +1 -0
- package/dist/src/rules/html-no-self-closing.js +22 -0
- package/dist/src/rules/html-no-self-closing.js.map +1 -0
- package/dist/src/rules/html-no-title-attribute.js +27 -0
- package/dist/src/rules/html-no-title-attribute.js.map +1 -0
- package/dist/src/rules/html-tag-name-lowercase.js +37 -25
- package/dist/src/rules/html-tag-name-lowercase.js.map +1 -1
- package/dist/src/rules/index.js +10 -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 +176 -22
- package/dist/src/rules/rule-utils.js.map +1 -1
- package/dist/src/rules/svg-tag-name-capitalization.js +2 -10
- package/dist/src/rules/svg-tag-name-capitalization.js.map +1 -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/index.d.ts +4 -0
- 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/rules/erb-no-empty-tags.d.ts +2 -2
- package/dist/types/rules/erb-no-output-control-flow.d.ts +2 -2
- package/dist/types/rules/erb-no-silent-tag-in-attribute-name.d.ts +7 -0
- package/dist/types/rules/erb-prefer-image-tag-helper.d.ts +2 -2
- package/dist/types/rules/erb-require-whitespace-inside-tags.d.ts +2 -2
- package/dist/types/rules/html-anchor-require-href.d.ts +2 -2
- package/dist/types/rules/html-aria-attribute-must-be-valid.d.ts +2 -2
- package/dist/types/rules/html-aria-label-is-well-formatted.d.ts +7 -0
- package/dist/types/rules/html-aria-level-must-be-valid.d.ts +2 -2
- package/dist/types/rules/html-aria-role-heading-requires-level.d.ts +2 -2
- package/dist/types/rules/html-aria-role-must-be-valid.d.ts +2 -2
- package/dist/types/rules/html-attribute-double-quotes.d.ts +2 -2
- package/dist/types/rules/html-attribute-equals-spacing.d.ts +7 -0
- package/dist/types/rules/html-attribute-values-require-quotes.d.ts +2 -2
- package/dist/types/rules/html-avoid-both-disabled-and-aria-disabled.d.ts +7 -0
- package/dist/types/rules/html-boolean-attributes-no-value.d.ts +2 -2
- package/dist/types/rules/html-iframe-has-title.d.ts +7 -0
- package/dist/types/rules/html-img-require-alt.d.ts +2 -2
- package/dist/types/rules/html-navigation-has-label.d.ts +7 -0
- package/dist/types/rules/html-no-aria-hidden-on-focusable.d.ts +7 -0
- package/dist/types/rules/html-no-block-inside-inline.d.ts +2 -2
- package/dist/types/rules/html-no-duplicate-attributes.d.ts +2 -2
- package/dist/types/rules/html-no-duplicate-ids.d.ts +2 -2
- package/dist/types/rules/html-no-empty-headings.d.ts +2 -2
- package/dist/types/rules/html-no-nested-links.d.ts +2 -2
- package/dist/types/rules/html-no-positive-tab-index.d.ts +7 -0
- package/dist/types/rules/html-no-self-closing.d.ts +7 -0
- package/dist/types/rules/html-no-title-attribute.d.ts +7 -0
- package/dist/types/rules/html-tag-name-lowercase.d.ts +3 -2
- package/dist/types/rules/index.d.ts +10 -0
- package/dist/types/rules/parser-no-errors.d.ts +8 -0
- package/dist/types/rules/rule-utils.d.ts +107 -13
- package/dist/types/rules/svg-tag-name-capitalization.d.ts +2 -2
- 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/rules/erb-no-empty-tags.d.ts +2 -2
- package/dist/types/src/rules/erb-no-output-control-flow.d.ts +2 -2
- package/dist/types/src/rules/erb-no-silent-tag-in-attribute-name.d.ts +7 -0
- package/dist/types/src/rules/erb-prefer-image-tag-helper.d.ts +2 -2
- package/dist/types/src/rules/erb-require-whitespace-inside-tags.d.ts +2 -2
- package/dist/types/src/rules/html-anchor-require-href.d.ts +2 -2
- package/dist/types/src/rules/html-aria-attribute-must-be-valid.d.ts +2 -2
- package/dist/types/src/rules/html-aria-label-is-well-formatted.d.ts +7 -0
- package/dist/types/src/rules/html-aria-level-must-be-valid.d.ts +2 -2
- package/dist/types/src/rules/html-aria-role-heading-requires-level.d.ts +2 -2
- package/dist/types/src/rules/html-aria-role-must-be-valid.d.ts +2 -2
- package/dist/types/src/rules/html-attribute-double-quotes.d.ts +2 -2
- package/dist/types/src/rules/html-attribute-equals-spacing.d.ts +7 -0
- package/dist/types/src/rules/html-attribute-values-require-quotes.d.ts +2 -2
- package/dist/types/src/rules/html-avoid-both-disabled-and-aria-disabled.d.ts +7 -0
- package/dist/types/src/rules/html-boolean-attributes-no-value.d.ts +2 -2
- package/dist/types/src/rules/html-iframe-has-title.d.ts +7 -0
- package/dist/types/src/rules/html-img-require-alt.d.ts +2 -2
- package/dist/types/src/rules/html-navigation-has-label.d.ts +7 -0
- package/dist/types/src/rules/html-no-aria-hidden-on-focusable.d.ts +7 -0
- package/dist/types/src/rules/html-no-block-inside-inline.d.ts +2 -2
- package/dist/types/src/rules/html-no-duplicate-attributes.d.ts +2 -2
- package/dist/types/src/rules/html-no-duplicate-ids.d.ts +2 -2
- package/dist/types/src/rules/html-no-empty-headings.d.ts +2 -2
- package/dist/types/src/rules/html-no-nested-links.d.ts +2 -2
- package/dist/types/src/rules/html-no-positive-tab-index.d.ts +7 -0
- package/dist/types/src/rules/html-no-self-closing.d.ts +7 -0
- package/dist/types/src/rules/html-no-title-attribute.d.ts +7 -0
- package/dist/types/src/rules/html-tag-name-lowercase.d.ts +3 -2
- package/dist/types/src/rules/index.d.ts +10 -0
- package/dist/types/src/rules/parser-no-errors.d.ts +8 -0
- package/dist/types/src/rules/rule-utils.d.ts +107 -13
- package/dist/types/src/rules/svg-tag-name-capitalization.d.ts +2 -2
- package/dist/types/src/types.d.ts +27 -3
- package/dist/types/types.d.ts +27 -3
- package/docs/rules/README.md +13 -2
- package/docs/rules/erb-no-silent-tag-in-attribute-name.md +34 -0
- package/docs/rules/html-aria-label-is-well-formatted.md +49 -0
- package/docs/rules/html-attribute-equals-spacing.md +35 -0
- package/docs/rules/html-avoid-both-disabled-and-aria-disabled.md +48 -0
- package/docs/rules/html-iframe-has-title.md +43 -0
- package/docs/rules/html-navigation-has-label.md +61 -0
- package/docs/rules/html-no-aria-hidden-on-focusable.md +54 -0
- package/docs/rules/html-no-positive-tab-index.md +55 -0
- package/docs/rules/html-no-self-closing.md +65 -0
- package/docs/rules/html-no-title-attribute.md +69 -0
- package/docs/rules/html-tag-name-lowercase.md +16 -3
- package/docs/rules/parser-no-errors.md +84 -0
- package/package.json +4 -4
- package/src/cli/argument-parser.ts +33 -24
- package/src/cli/file-processor.ts +25 -17
- 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 +22 -0
- package/src/linter.ts +30 -4
- package/src/rules/erb-no-empty-tags.ts +3 -3
- package/src/rules/erb-no-output-control-flow.ts +3 -3
- package/src/rules/erb-no-silent-tag-in-attribute-name.ts +40 -0
- package/src/rules/erb-prefer-image-tag-helper.ts +4 -9
- package/src/rules/erb-require-whitespace-inside-tags.ts +3 -3
- package/src/rules/erb-requires-trailing-newline.ts +2 -0
- package/src/rules/html-anchor-require-href.ts +3 -3
- package/src/rules/html-aria-attribute-must-be-valid.ts +29 -33
- package/src/rules/html-aria-label-is-well-formatted.ts +59 -0
- package/src/rules/html-aria-level-must-be-valid.ts +40 -7
- package/src/rules/html-aria-role-heading-requires-level.ts +18 -30
- package/src/rules/html-aria-role-must-be-valid.ts +7 -7
- package/src/rules/html-attribute-double-quotes.ts +23 -8
- package/src/rules/html-attribute-equals-spacing.ts +41 -0
- package/src/rules/html-attribute-values-require-quotes.ts +32 -12
- package/src/rules/html-avoid-both-disabled-and-aria-disabled.ts +66 -0
- package/src/rules/html-boolean-attributes-no-value.ts +19 -6
- package/src/rules/html-iframe-has-title.ts +62 -0
- package/src/rules/html-img-require-alt.ts +4 -9
- package/src/rules/html-navigation-has-label.ts +64 -0
- package/src/rules/html-no-aria-hidden-on-focusable.ts +90 -0
- package/src/rules/html-no-block-inside-inline.ts +5 -5
- package/src/rules/html-no-duplicate-attributes.ts +30 -30
- package/src/rules/html-no-duplicate-ids.ts +6 -5
- package/src/rules/html-no-empty-headings.ts +4 -33
- package/src/rules/html-no-nested-links.ts +3 -3
- package/src/rules/html-no-positive-tab-index.ts +33 -0
- package/src/rules/html-no-self-closing.ts +36 -0
- package/src/rules/html-no-title-attribute.ts +42 -0
- package/src/rules/html-tag-name-lowercase.ts +44 -31
- package/src/rules/index.ts +10 -0
- package/src/rules/parser-no-errors.ts +25 -0
- package/src/rules/rule-utils.ts +260 -39
- package/src/rules/svg-tag-name-capitalization.ts +4 -11
- package/src/types.ts +30 -3
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { BaseFormatter } from "./base-formatter.js";
|
|
2
|
+
export class JSONFormatter extends BaseFormatter {
|
|
3
|
+
async format(allOffenses) {
|
|
4
|
+
const jsonOffenses = allOffenses.map(({ filename, offense }) => ({
|
|
5
|
+
filename,
|
|
6
|
+
message: offense.message,
|
|
7
|
+
location: offense.location.toJSON(),
|
|
8
|
+
severity: offense.severity,
|
|
9
|
+
code: offense.code,
|
|
10
|
+
source: offense.source
|
|
11
|
+
}));
|
|
12
|
+
const output = {
|
|
13
|
+
offenses: jsonOffenses,
|
|
14
|
+
summary: null,
|
|
15
|
+
timing: null,
|
|
16
|
+
completed: true,
|
|
17
|
+
clean: jsonOffenses.length === 0,
|
|
18
|
+
message: null
|
|
19
|
+
};
|
|
20
|
+
console.log(JSON.stringify(output, null, 2));
|
|
21
|
+
}
|
|
22
|
+
async formatWithSummary(allOffenses, options) {
|
|
23
|
+
const jsonOffenses = allOffenses.map(({ filename, offense }) => ({
|
|
24
|
+
filename,
|
|
25
|
+
message: offense.message,
|
|
26
|
+
location: offense.location.toJSON(),
|
|
27
|
+
severity: offense.severity,
|
|
28
|
+
code: offense.code,
|
|
29
|
+
source: offense.source
|
|
30
|
+
}));
|
|
31
|
+
const summary = {
|
|
32
|
+
filesChecked: options.files.length,
|
|
33
|
+
filesWithOffenses: options.filesWithOffenses,
|
|
34
|
+
totalErrors: options.totalErrors,
|
|
35
|
+
totalWarnings: options.totalWarnings,
|
|
36
|
+
totalOffenses: options.totalErrors + options.totalWarnings,
|
|
37
|
+
ruleCount: options.ruleCount
|
|
38
|
+
};
|
|
39
|
+
const output = {
|
|
40
|
+
offenses: jsonOffenses,
|
|
41
|
+
summary,
|
|
42
|
+
timing: null,
|
|
43
|
+
completed: true,
|
|
44
|
+
clean: options.totalErrors === 0 && options.totalWarnings === 0,
|
|
45
|
+
message: null
|
|
46
|
+
};
|
|
47
|
+
const duration = Date.now() - options.startTime;
|
|
48
|
+
output.timing = options.showTiming ? {
|
|
49
|
+
startTime: options.startDate.toISOString(),
|
|
50
|
+
duration: duration
|
|
51
|
+
} : null;
|
|
52
|
+
console.log(JSON.stringify(output, null, 2));
|
|
53
|
+
}
|
|
54
|
+
formatFile(_filename, _offenses) {
|
|
55
|
+
// Not used in JSON formatter, everything is handled in format()
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=json-formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"json-formatter.js","sourceRoot":"","sources":["../../../../src/cli/formatters/json-formatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AA2CnD,MAAM,OAAO,aAAc,SAAQ,aAAa;IAC9C,KAAK,CAAC,MAAM,CAAC,WAA4B;QACvC,MAAM,YAAY,GAAkB,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;YAC9E,QAAQ;YACR,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE;YACnC,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC,CAAA;QAEH,MAAM,MAAM,GAAe;YACzB,QAAQ,EAAE,YAAY;YACtB,OAAO,EAAE,IAAI;YACb,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,YAAY,CAAC,MAAM,KAAK,CAAC;YAChC,OAAO,EAAE,IAAI;SACd,CAAA;QAED,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IAC9C,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,WAA4B,EAAE,OAA0B;QAC9E,MAAM,YAAY,GAAkB,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC;YAC9E,QAAQ;YACR,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE;YACnC,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAC,CAAA;QAEH,MAAM,OAAO,GAAgB;YAC3B,YAAY,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM;YAClC,iBAAiB,EAAE,OAAO,CAAC,iBAAiB;YAC5C,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,aAAa,EAAE,OAAO,CAAC,WAAW,GAAG,OAAO,CAAC,aAAa;YAC1D,SAAS,EAAE,OAAO,CAAC,SAAS;SAC7B,CAAA;QAED,MAAM,MAAM,GAAe;YACzB,QAAQ,EAAE,YAAY;YACtB,OAAO;YACP,MAAM,EAAE,IAAI;YACZ,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,OAAO,CAAC,WAAW,KAAK,CAAC,IAAI,OAAO,CAAC,aAAa,KAAK,CAAC;YAC/D,OAAO,EAAE,IAAI;SACd,CAAA;QAED,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,SAAS,CAAA;QAC/C,MAAM,CAAC,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;YACnC,SAAS,EAAE,OAAO,CAAC,SAAS,CAAC,WAAW,EAAE;YAC1C,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC,CAAC,IAAI,CAAA;QAER,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAA;IAC9C,CAAC;IAED,UAAU,CAAC,SAAiB,EAAE,SAAuB;QACnD,gEAAgE;IAClE,CAAC;CACF"}
|
|
@@ -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,45 +1,67 @@
|
|
|
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 { ERBNoSilentTagInAttributeNameRule } from "./rules/erb-no-silent-tag-in-attribute-name.js";
|
|
3
4
|
import { ERBPreferImageTagHelperRule } from "./rules/erb-prefer-image-tag-helper.js";
|
|
4
5
|
import { ERBRequiresTrailingNewlineRule } from "./rules/erb-requires-trailing-newline.js";
|
|
5
6
|
import { ERBRequireWhitespaceRule } from "./rules/erb-require-whitespace-inside-tags.js";
|
|
6
7
|
import { HTMLAnchorRequireHrefRule } from "./rules/html-anchor-require-href.js";
|
|
7
8
|
import { HTMLAriaAttributeMustBeValid } from "./rules/html-aria-attribute-must-be-valid.js";
|
|
9
|
+
import { HTMLAriaLabelIsWellFormattedRule } from "./rules/html-aria-label-is-well-formatted.js";
|
|
8
10
|
import { HTMLAriaLevelMustBeValidRule } from "./rules/html-aria-level-must-be-valid.js";
|
|
9
11
|
import { HTMLAriaRoleHeadingRequiresLevelRule } from "./rules/html-aria-role-heading-requires-level.js";
|
|
10
12
|
import { HTMLAriaRoleMustBeValidRule } from "./rules/html-aria-role-must-be-valid.js";
|
|
11
13
|
import { HTMLAttributeDoubleQuotesRule } from "./rules/html-attribute-double-quotes.js";
|
|
14
|
+
import { HTMLAttributeEqualsSpacingRule } from "./rules/html-attribute-equals-spacing.js";
|
|
12
15
|
import { HTMLAttributeValuesRequireQuotesRule } from "./rules/html-attribute-values-require-quotes.js";
|
|
16
|
+
import { HTMLAvoidBothDisabledAndAriaDisabledRule } from "./rules/html-avoid-both-disabled-and-aria-disabled.js";
|
|
13
17
|
import { HTMLBooleanAttributesNoValueRule } from "./rules/html-boolean-attributes-no-value.js";
|
|
18
|
+
import { HTMLIframeHasTitleRule } from "./rules/html-iframe-has-title.js";
|
|
14
19
|
import { HTMLImgRequireAltRule } from "./rules/html-img-require-alt.js";
|
|
20
|
+
import { HTMLNavigationHasLabelRule } from "./rules/html-navigation-has-label.js";
|
|
21
|
+
import { HTMLNoAriaHiddenOnFocusableRule } from "./rules/html-no-aria-hidden-on-focusable.js";
|
|
15
22
|
// import { HTMLNoBlockInsideInlineRule } from "./rules/html-no-block-inside-inline.js"
|
|
16
23
|
import { HTMLNoDuplicateAttributesRule } from "./rules/html-no-duplicate-attributes.js";
|
|
17
24
|
import { HTMLNoDuplicateIdsRule } from "./rules/html-no-duplicate-ids.js";
|
|
18
25
|
import { HTMLNoEmptyHeadingsRule } from "./rules/html-no-empty-headings.js";
|
|
19
26
|
import { HTMLNoNestedLinksRule } from "./rules/html-no-nested-links.js";
|
|
27
|
+
import { HTMLNoPositiveTabIndexRule } from "./rules/html-no-positive-tab-index.js";
|
|
28
|
+
import { HTMLNoSelfClosingRule } from "./rules/html-no-self-closing.js";
|
|
29
|
+
import { HTMLNoTitleAttributeRule } from "./rules/html-no-title-attribute.js";
|
|
20
30
|
import { HTMLTagNameLowercaseRule } from "./rules/html-tag-name-lowercase.js";
|
|
31
|
+
import { ParserNoErrorsRule } from "./rules/parser-no-errors.js";
|
|
21
32
|
import { SVGTagNameCapitalizationRule } from "./rules/svg-tag-name-capitalization.js";
|
|
22
33
|
export const defaultRules = [
|
|
23
34
|
ERBNoEmptyTagsRule,
|
|
24
35
|
ERBNoOutputControlFlowRule,
|
|
36
|
+
ERBNoSilentTagInAttributeNameRule,
|
|
25
37
|
ERBPreferImageTagHelperRule,
|
|
26
38
|
ERBRequiresTrailingNewlineRule,
|
|
27
39
|
ERBRequireWhitespaceRule,
|
|
28
40
|
HTMLAnchorRequireHrefRule,
|
|
29
41
|
HTMLAriaAttributeMustBeValid,
|
|
42
|
+
HTMLAriaLabelIsWellFormattedRule,
|
|
30
43
|
HTMLAriaLevelMustBeValidRule,
|
|
31
44
|
HTMLAriaRoleHeadingRequiresLevelRule,
|
|
32
45
|
HTMLAriaRoleMustBeValidRule,
|
|
33
46
|
HTMLAttributeDoubleQuotesRule,
|
|
47
|
+
HTMLAttributeEqualsSpacingRule,
|
|
34
48
|
HTMLAttributeValuesRequireQuotesRule,
|
|
49
|
+
HTMLAvoidBothDisabledAndAriaDisabledRule,
|
|
35
50
|
HTMLBooleanAttributesNoValueRule,
|
|
51
|
+
HTMLIframeHasTitleRule,
|
|
36
52
|
HTMLImgRequireAltRule,
|
|
53
|
+
HTMLNavigationHasLabelRule,
|
|
54
|
+
HTMLNoAriaHiddenOnFocusableRule,
|
|
37
55
|
// HTMLNoBlockInsideInlineRule,
|
|
38
56
|
HTMLNoDuplicateAttributesRule,
|
|
39
57
|
HTMLNoDuplicateIdsRule,
|
|
40
58
|
HTMLNoEmptyHeadingsRule,
|
|
41
59
|
HTMLNoNestedLinksRule,
|
|
60
|
+
HTMLNoPositiveTabIndexRule,
|
|
61
|
+
HTMLNoSelfClosingRule,
|
|
62
|
+
HTMLNoTitleAttributeRule,
|
|
42
63
|
HTMLTagNameLowercaseRule,
|
|
64
|
+
ParserNoErrorsRule,
|
|
43
65
|
SVGTagNameCapitalizationRule,
|
|
44
66
|
];
|
|
45
67
|
//# 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,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,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,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,iCAAiC,EAAE,MAAM,gDAAgD,CAAA;AAClG,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,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,gCAAgC,EAAE,MAAM,6CAA6C,CAAA;AAC9F,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAA;AACzE,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAA;AACjF,OAAO,EAAE,+BAA+B,EAAE,MAAM,6CAA6C,CAAA;AAC7F,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,0BAA0B,EAAE,MAAM,uCAAuC,CAAA;AAClF,OAAO,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,oCAAoC,CAAA;AAC7E,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,iCAAiC;IACjC,2BAA2B;IAC3B,8BAA8B;IAC9B,wBAAwB;IACxB,yBAAyB;IACzB,4BAA4B;IAC5B,gCAAgC;IAChC,4BAA4B;IAC5B,oCAAoC;IACpC,2BAA2B;IAC3B,6BAA6B;IAC7B,8BAA8B;IAC9B,oCAAoC;IACpC,wCAAwC;IACxC,gCAAgC;IAChC,sBAAsB;IACtB,qBAAqB;IACrB,0BAA0B;IAC1B,+BAA+B;IAC/B,+BAA+B;IAC/B,6BAA6B;IAC7B,sBAAsB;IACtB,uBAAuB;IACvB,qBAAqB;IACrB,0BAA0B;IAC1B,qBAAqB;IACrB,wBAAwB;IACxB,wBAAwB;IACxB,kBAAkB;IAClB,4BAA4B;CAC7B,CAAA"}
|
package/dist/src/linter.js
CHANGED
|
@@ -42,19 +42,44 @@ export class Linter {
|
|
|
42
42
|
*/
|
|
43
43
|
lint(source, context) {
|
|
44
44
|
this.offenses = [];
|
|
45
|
-
const parseResult = this.herb.parse(source);
|
|
45
|
+
const parseResult = this.herb.parse(source, { track_whitespace: true });
|
|
46
46
|
const lexResult = this.herb.lex(source);
|
|
47
47
|
for (const RuleClass of this.rules) {
|
|
48
48
|
const rule = new RuleClass();
|
|
49
|
+
let isEnabled = true;
|
|
49
50
|
let ruleOffenses;
|
|
50
51
|
if (this.isLexerRule(rule)) {
|
|
51
|
-
|
|
52
|
+
if (rule.isEnabled) {
|
|
53
|
+
isEnabled = rule.isEnabled(lexResult, context);
|
|
54
|
+
}
|
|
55
|
+
if (isEnabled) {
|
|
56
|
+
ruleOffenses = rule.check(lexResult, context);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
ruleOffenses = [];
|
|
60
|
+
}
|
|
52
61
|
}
|
|
53
62
|
else if (this.isSourceRule(rule)) {
|
|
54
|
-
|
|
63
|
+
if (rule.isEnabled) {
|
|
64
|
+
isEnabled = rule.isEnabled(source, context);
|
|
65
|
+
}
|
|
66
|
+
if (isEnabled) {
|
|
67
|
+
ruleOffenses = rule.check(source, context);
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
ruleOffenses = [];
|
|
71
|
+
}
|
|
55
72
|
}
|
|
56
73
|
else {
|
|
57
|
-
|
|
74
|
+
if (rule.isEnabled) {
|
|
75
|
+
isEnabled = rule.isEnabled(parseResult, context);
|
|
76
|
+
}
|
|
77
|
+
if (isEnabled) {
|
|
78
|
+
ruleOffenses = rule.check(parseResult, context);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
ruleOffenses = [];
|
|
82
|
+
}
|
|
58
83
|
}
|
|
59
84
|
this.offenses.push(...ruleOffenses);
|
|
60
85
|
}
|