From a208ff0267181cd5a670ad80c0444f8a8d2ebd93 Mon Sep 17 00:00:00 2001 From: Christian Oliff Date: Tue, 25 Nov 2025 13:36:42 +0900 Subject: [PATCH 1/2] Add support for disabling rules via HTML comments Introduces parsing of htmlhint-disable and htmlhint-enable comments to selectively disable rules or all rules on specific lines. Updates the Reporter to respect these disable comments, preventing messages for disabled rules. Documentation and tests updated to reflect new functionality. --- AGENTS.md | 35 ++++++ dist/core/core.js | 89 ++++++++++++- dist/core/reporter.js | 14 ++- src/core/core.ts | 115 ++++++++++++++++- src/core/reporter.ts | 23 +++- src/core/types.ts | 7 ++ test/core.spec.js | 126 +++++++++++++++++++ website/src/content/docs/configuration.md | 63 ++++++++++ website/src/content/docs/getting-started.mdx | 2 + 9 files changed, 466 insertions(+), 8 deletions(-) create mode 100644 AGENTS.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 000000000..c47f9a1ab --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,35 @@ +# Agents + + + +## Markdown Code Guide + +- Markdown should be formatted with Prettier. +- There should be a line break before the first list item. +- There should be a line break after headings. + +## YAML Code Guide + +- YML files should begin with --- on the first line. +- YML should be formatted with Prettier. + +## Communication (MANDATORY) + +- No apologies - State facts and solutions directly. +- Concise style - Professional, avoid repetition and filler. +- Single chunk edits - All file edits in one operation. +- Real file links only - No placeholder files. +- No unnecessary confirmations - Use available context. + +## Quality & Validation (MANDATORY) + +- Never assume commands worked without verification. +- 98%+ confidence threshold for definitive claims. +- Immediate re-investigation when findings don't match expectations. +- Cross-tool validation when tools fail. + +## Code Standards (MANDATORY) + +- No emojis in code or documentation. +- Only implement what's requested. +- Preserve existing structures - Don't remove unrelated code. diff --git a/dist/core/core.js b/dist/core/core.js index 293b1ccbd..19f238fbf 100644 --- a/dist/core/core.js +++ b/dist/core/core.js @@ -38,8 +38,9 @@ class HTMLHintCore { }); return ''; }); + const disabledRulesMap = this.parseDisableComments(html); const parser = new htmlparser_1.default(); - const reporter = new reporter_1.default(html, ruleset); + const reporter = new reporter_1.default(html, ruleset, disabledRulesMap); const rules = this.rules; let rule; for (const id in ruleset) { @@ -51,6 +52,90 @@ class HTMLHintCore { parser.parse(html); return reporter.messages; } + parseDisableComments(html) { + var _a; + const disabledRulesMap = {}; + const lines = html.split(/\r?\n/); + const regComment = //gi; + const comments = []; + let match; + while ((match = regComment.exec(html)) !== null) { + const beforeMatch = html.substring(0, match.index); + const lineNumber = beforeMatch.split(/\r?\n/).length; + const command = match[1].toLowerCase(); + const isNextLine = match[0].includes('-next-line'); + const rulesStr = (_a = match[2]) === null || _a === void 0 ? void 0 : _a.trim(); + comments.push({ + line: lineNumber, + command, + isNextLine, + rulesStr, + }); + } + let currentDisabledRules = null; + let isAllDisabled = false; + for (let i = 0; i < lines.length; i++) { + const line = i + 1; + const commentOnLine = comments.find((c) => c.line === line); + if (commentOnLine) { + if (commentOnLine.command === 'disable') { + if (commentOnLine.isNextLine) { + const nextLine = line + 1; + if (commentOnLine.rulesStr) { + const rules = commentOnLine.rulesStr + .split(/\s+/) + .filter((r) => r.length > 0); + if (!disabledRulesMap[nextLine]) { + disabledRulesMap[nextLine] = {}; + } + if (!disabledRulesMap[nextLine].rules) { + disabledRulesMap[nextLine].rules = new Set(); + } + rules.forEach((r) => disabledRulesMap[nextLine].rules.add(r)); + } + else { + if (!disabledRulesMap[nextLine]) { + disabledRulesMap[nextLine] = {}; + } + disabledRulesMap[nextLine].all = true; + } + } + else { + if (commentOnLine.rulesStr) { + const rules = commentOnLine.rulesStr + .split(/\s+/) + .filter((r) => r.length > 0); + currentDisabledRules = new Set(rules); + isAllDisabled = false; + } + else { + currentDisabledRules = null; + isAllDisabled = true; + } + } + } + else if (commentOnLine.command === 'enable') { + currentDisabledRules = null; + isAllDisabled = false; + } + } + if (currentDisabledRules !== null || isAllDisabled) { + if (!disabledRulesMap[line]) { + disabledRulesMap[line] = {}; + } + if (isAllDisabled && disabledRulesMap[line].all !== true) { + disabledRulesMap[line].all = true; + } + else if (currentDisabledRules) { + if (!disabledRulesMap[line].rules) { + disabledRulesMap[line].rules = new Set(); + } + currentDisabledRules.forEach((r) => disabledRulesMap[line].rules.add(r)); + } + } + } + return disabledRulesMap; + } format(arrMessages, options = {}) { const arrLogs = []; const colors = { @@ -106,4 +191,4 @@ exports.HTMLHint = new HTMLHintCore(); Object.values(HTMLRules).forEach((rule) => { exports.HTMLHint.addRule(rule); }); -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3JlL2NvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkNBQXFDO0FBa0tQLHFCQWxLdkIsb0JBQVUsQ0FrS3VCO0FBakt4Qyx5Q0FBaUM7QUFpS2IsbUJBaktiLGtCQUFRLENBaUthO0FBaEs1QixxQ0FBb0M7QUFnSzNCLDhCQUFTO0FBeEpsQixNQUFNLFlBQVk7SUFBbEI7UUFDUyxVQUFLLEdBQTJCLEVBQUUsQ0FBQTtRQUN6QixtQkFBYyxHQUFZO1lBQ3hDLG1CQUFtQixFQUFFLElBQUk7WUFDekIsZ0JBQWdCLEVBQUUsSUFBSTtZQUN0QiwwQkFBMEIsRUFBRSxJQUFJO1lBQ2hDLGVBQWUsRUFBRSxJQUFJO1lBQ3JCLFVBQVUsRUFBRSxJQUFJO1lBQ2hCLGtCQUFrQixFQUFFLElBQUk7WUFDeEIsV0FBVyxFQUFFLElBQUk7WUFDakIsZUFBZSxFQUFFLElBQUk7WUFDckIscUJBQXFCLEVBQUUsSUFBSTtZQUMzQixlQUFlLEVBQUUsSUFBSTtTQUN0QixDQUFBO0lBOEhILENBQUM7SUE1SFEsT0FBTyxDQUFDLElBQVU7UUFDdkIsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFBO0lBQzVCLENBQUM7SUFFTSxNQUFNLENBQUMsSUFBWSxFQUFFLFVBQW1CLElBQUksQ0FBQyxjQUFjO1FBQ2hFLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDdEMsT0FBTyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUE7UUFDL0IsQ0FBQztRQUdELElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUNqQiwwQ0FBMEMsRUFDMUMsQ0FBQyxHQUFHLEVBQUUsVUFBa0IsRUFBRSxFQUFFO1lBSTFCLFVBQVUsQ0FBQyxPQUFPLENBQ2hCLDJDQUEyQyxFQUMzQyxD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 \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29yZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb3JlL2NvcmUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNkNBQXFDO0FBaVJQLHFCQWpSdkIsb0JBQVUsQ0FpUnVCO0FBaFJ4Qyx5Q0FBaUM7QUFnUmIsbUJBaFJiLGtCQUFRLENBZ1JhO0FBL1E1QixxQ0FBb0M7QUErUTNCLDhCQUFTO0FBdlFsQixNQUFNLFlBQVk7SUFBbEI7UUFDUyxVQUFLLEdBQTJCLEVBQUUsQ0FBQTtRQUN6QixtQkFBYyxHQUFZO1lBQ3hDLG1CQUFtQixFQUFFLElBQUk7WUFDekIsZ0JBQWdCLEVBQUUsSUFBSTtZQUN0QiwwQkFBMEIsRUFBRSxJQUFJO1lBQ2hDLGVBQWUsRUFBRSxJQUFJO1lBQ3JCLFVBQVUsRUFBRSxJQUFJO1lBQ2hCLGtCQUFrQixFQUFFLElBQUk7WUFDeEIsV0FBVyxFQUFFLElBQUk7WUFDakIsZUFBZSxFQUFFLElBQUk7WUFDckIscUJBQXFCLEVBQUUsSUFBSTtZQUMzQixlQUFlLEVBQUUsSUFBSTtTQUN0QixDQUFBO0lBNk9ILENBQUM7SUEzT1EsT0FBTyxDQUFDLElBQVU7UUFDdkIsSUFBSSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFBO0lBQzVCLENBQUM7SUFFTSxNQUFNLENBQUMsSUFBWSxFQUFFLFVBQW1CLElBQUksQ0FBQyxjQUFjO1FBQ2hFLElBQUksTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDdEMsT0FBTyxHQUFHLElBQUksQ0FBQyxjQUFjLENBQUE7UUFDL0IsQ0FBQztRQUdELElBQUksR0FBRyxJQUFJLENBQUMsT0FBTyxDQUNqQiwwQ0FBMEMsRUFDMUMsQ0FBQyxHQUFHLEVBQUUsVUFBa0IsRUFBRSxFQUFFO1lBSTFCLFVBQVUsQ0FBQyxPQUFPLENBQ2hCLDJDQUEyQyxFQUMzQyxD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 \ No newline at end of file diff --git a/dist/core/reporter.js b/dist/core/reporter.js index 5326e2abb..896f280e7 100644 --- a/dist/core/reporter.js +++ b/dist/core/reporter.js @@ -1,13 +1,14 @@ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class Reporter { - constructor(html, ruleset) { + constructor(html, ruleset, disabledRulesMap = {}) { this.html = html; this.lines = html.split(/\r?\n/); const match = /\r?\n/.exec(html); this.brLen = match !== null ? match[0].length : 0; this.ruleset = ruleset; this.messages = []; + this.disabledRulesMap = disabledRulesMap; } info(message, line, col, rule, raw) { this.report("info", message, line, col, rule, raw); @@ -19,6 +20,15 @@ class Reporter { this.report("error", message, line, col, rule, raw); } report(type, message, line, col, rule, raw) { + const lineDisabled = this.disabledRulesMap[line]; + if (lineDisabled) { + if (lineDisabled.all === true) { + return; + } + if (lineDisabled.rules && lineDisabled.rules.has(rule.id)) { + return; + } + } const lines = this.lines; const brLen = this.brLen; let evidence = ''; @@ -53,4 +63,4 @@ class Reporter { } } exports.default = Reporter; -//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29yZS9yZXBvcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLE1BQXFCLFFBQVE7SUFPM0IsWUFBbUIsSUFBWSxFQUFFLE9BQWdCO1FBQy9DLElBQUksQ0FBQyxJQUFJLEdBQUcsSUFBSSxDQUFBO1FBQ2hCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQTtRQUNoQyxNQUFNLEtBQUssR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBRWhDLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxLQUFLLElBQUksQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ2pELElBQUksQ0FBQyxPQUFPLEdBQUcsT0FBTyxDQUFBO1FBQ3RCLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFBO0lBQ3BCLENBQUM7SUFFTSxJQUFJLENBQ1QsT0FBZSxFQUNmLElBQVksRUFDWixHQUFXLEVBQ1gsSUFBVSxFQUNWLEdBQVc7UUFFWCxJQUFJLENBQUMsTUFBTSxTQUFrQixPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUE7SUFDN0QsQ0FBQztJQUVNLElBQUksQ0FDVCxPQUFlLEVBQ2YsSUFBWSxFQUNaLEdBQVcsRUFDWCxJQUFVLEVBQ1YsR0FBVztRQUVYLElBQUksQ0FBQyxNQUFNLFlBQXFCLE9BQU8sRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQTtJQUNoRSxDQUFDO0lBRU0sS0FBSyxDQUNWLE9BQWUsRUFDZixJQUFZLEVBQ1osR0FBVyxFQUNYLElBQVUsRUFDVixHQUFXO1FBRVgsSUFBSSxDQUFDLE1BQU0sVUFBbUIsT0FBTyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFBO0lBQzlELENBQUM7SUFFTyxNQUFNLENBQ1osSUFBZ0IsRUFDaEIsT0FBZSxFQUNmLElBQVksRUFDWixHQUFXLEVBQ1gsSUFBVSxFQUNWLEdBQVc7UUFFWCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFBO1FBQ3hCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUE7UUFDeEIsSUFBSSxRQUFRLEdBQUcsRUFBRSxDQUFBO1FBQ2pCLElBQUksV0FBVyxHQUFHLENBQUMsQ0FBQTtRQUVuQixLQUFLLElBQUksQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLEVBQUUsU0FBUyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLFNBQVMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3BFLFFBQVEsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDbkIsV0FBVyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUE7WUFDN0IsSUFBSSxHQUFHLEdBQUcsV0FBVyxJQUFJLElBQUksR0FBRyxTQUFTLEVBQUUsQ0FBQztnQkFDMUMsSUFBSSxFQUFFLENBQUE7Z0JBQ04sR0FBRyxJQUFJLFdBQVcsQ0FBQTtnQkFDbEIsSUFBSSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7b0JBQ2QsR0FBRyxJQUFJLEtBQUssQ0FBQTtnQkFDZCxDQUFDO1lBQ0gsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE1BQUs7WUFDUCxDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDO1lBQ2pCLElBQUksRUFBRSxJQUFJO1lBQ1YsT0FBTyxFQUFFLE9BQU87WUFDaEIsR0FBRyxFQUFFLEdBQUc7WUFDUixRQUFRLEVBQUUsUUFBUTtZQUNsQixJQUFJLEVBQUUsSUFBSTtZQUNWLEdBQUcsRUFBRSxHQUFHO1lBQ1IsSUFBSSxFQUFFO2dCQUNKLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRTtnQkFDWCxXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVc7Z0JBQzdCLElBQUksRUFBRSw4QkFBOEIsSUFBSSxDQUFDLEVBQUUsRUFBRTthQUN0QztTQUNWLENBQUMsQ0FBQTtJQUNKLENBQUM7Q0FDRjtBQXhGRCwyQkF3RkMifQ== \ No newline at end of file +//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwb3J0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvY29yZS9yZXBvcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUVBLE1BQXFCLFFBQVE7SUFRM0IsWUFDRSxJQUFZLEVBQ1osT0FBZ0IsRUFDaEIsbUJBQXFDLEVBQUU7UUFFdkMsSUFBSSxDQUFDLElBQUksR0FBRyxJQUFJLENBQUE7UUFDaEIsSUFBSSxDQUFDLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1FBQ2hDLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7UUFFaEMsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFDakQsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUE7UUFDdEIsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUE7UUFDbEIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLGdCQUFnQixDQUFBO0lBQzFDLENBQUM7SUFFTSxJQUFJLENBQ1QsT0FBZSxFQUNmLElBQVksRUFDWixHQUFXLEVBQ1gsSUFBVSxFQUNWLEdBQVc7UUFFWCxJQUFJLENBQUMsTUFBTSxTQUFrQixPQUFPLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUE7SUFDN0QsQ0FBQztJQUVNLElBQUksQ0FDVCxPQUFlLEVBQ2YsSUFBWSxFQUNaLEdBQVcsRUFDWCxJQUFVLEVBQ1YsR0FBVztRQUVYLElBQUksQ0FBQyxNQUFNLFlBQXFCLE9BQU8sRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLENBQUMsQ0FBQTtJQUNoRSxDQUFDO0lBRU0sS0FBSyxDQUNWLE9BQWUsRUFDZixJQUFZLEVBQ1osR0FBVyxFQUNYLElBQVUsRUFDVixHQUFXO1FBRVgsSUFBSSxDQUFDLE1BQU0sVUFBbUIsT0FBTyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxDQUFBO0lBQzlELENBQUM7SUFFTyxNQUFNLENBQ1osSUFBZ0IsRUFDaEIsT0FBZSxFQUNmLElBQVksRUFDWixHQUFXLEVBQ1gsSUFBVSxFQUNWLEdBQVc7UUFHWCxNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDaEQsSUFBSSxZQUFZLEVBQUUsQ0FBQztZQUNqQixJQUFJLFlBQVksQ0FBQyxHQUFHLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBRTlCLE9BQU07WUFDUixDQUFDO1lBQ0QsSUFBSSxZQUFZLENBQUMsS0FBSyxJQUFJLFlBQVksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDO2dCQUUxRCxPQUFNO1lBQ1IsQ0FBQztRQUNILENBQUM7UUFFRCxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFBO1FBQ3hCLE1BQU0sS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUE7UUFDeEIsSUFBSSxRQUFRLEdBQUcsRUFBRSxDQUFBO1FBQ2pCLElBQUksV0FBVyxHQUFHLENBQUMsQ0FBQTtRQUVuQixLQUFLLElBQUksQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLEVBQUUsU0FBUyxHQUFHLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxHQUFHLFNBQVMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3BFLFFBQVEsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDbkIsV0FBVyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUE7WUFDN0IsSUFBSSxHQUFHLEdBQUcsV0FBVyxJQUFJLElBQUksR0FBRyxTQUFTLEVBQUUsQ0FBQztnQkFDMUMsSUFBSSxFQUFFLENBQUE7Z0JBQ04sR0FBRyxJQUFJLFdBQVcsQ0FBQTtnQkFDbEIsSUFBSSxHQUFHLEtBQUssQ0FBQyxFQUFFLENBQUM7b0JBQ2QsR0FBRyxJQUFJLEtBQUssQ0FBQTtnQkFDZCxDQUFDO1lBQ0gsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE1BQUs7WUFDUCxDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDO1lBQ2pCLElBQUksRUFBRSxJQUFJO1lBQ1YsT0FBTyxFQUFFLE9BQU87WUFDaEIsR0FBRyxFQUFFLEdBQUc7WUFDUixRQUFRLEVBQUUsUUFBUTtZQUNsQixJQUFJLEVBQUUsSUFBSTtZQUNWLEdBQUcsRUFBRSxHQUFHO1lBQ1IsSUFBSSxFQUFFO2dCQUNKLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRTtnQkFDWCxXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVc7Z0JBQzdCLElBQUksRUFBRSw4QkFBOEIsSUFBSSxDQUFDLEVBQUUsRUFBRTthQUN0QztTQUNWLENBQUMsQ0FBQTtJQUNKLENBQUM7Q0FDRjtBQTNHRCwyQkEyR0MifQ== \ No newline at end of file diff --git a/src/core/core.ts b/src/core/core.ts index f6c720404..39e0d7f80 100644 --- a/src/core/core.ts +++ b/src/core/core.ts @@ -1,7 +1,7 @@ import HTMLParser from './htmlparser' import Reporter from './reporter' import * as HTMLRules from './rules' -import { Hint, Rule, Ruleset } from './types' +import { Hint, Rule, Ruleset, DisabledRulesMap } from './types' export interface FormatOptions { colors?: boolean @@ -58,8 +58,11 @@ class HTMLHintCore { } ) + // Parse disable/enable comments + const disabledRulesMap = this.parseDisableComments(html) + const parser = new HTMLParser() - const reporter = new Reporter(html, ruleset) + const reporter = new Reporter(html, ruleset, disabledRulesMap) const rules = this.rules let rule: Rule @@ -76,6 +79,114 @@ class HTMLHintCore { return reporter.messages } + private parseDisableComments(html: string): DisabledRulesMap { + const disabledRulesMap: DisabledRulesMap = {} + const lines = html.split(/\r?\n/) + const regComment = + //gi + + // Find all disable/enable comments and their positions + const comments: Array<{ + line: number + command: string + isNextLine: boolean + rulesStr?: string + }> = [] + + let match: RegExpExecArray | null + while ((match = regComment.exec(html)) !== null) { + // Calculate line number from match position + const beforeMatch = html.substring(0, match.index) + const lineNumber = beforeMatch.split(/\r?\n/).length + const command = match[1].toLowerCase() + const isNextLine = match[0].includes('-next-line') + const rulesStr = match[2]?.trim() + + comments.push({ + line: lineNumber, + command, + isNextLine, + rulesStr, + }) + } + + // Process comments in order + let currentDisabledRules: Set | null = null + let isAllDisabled = false + + for (let i = 0; i < lines.length; i++) { + const line = i + 1 + + // Check if there's a comment on this line + const commentOnLine = comments.find((c) => c.line === line) + if (commentOnLine) { + if (commentOnLine.command === 'disable') { + if (commentOnLine.isNextLine) { + // htmlhint-disable-next-line + const nextLine = line + 1 + if (commentOnLine.rulesStr) { + // Specific rules disabled + const rules = commentOnLine.rulesStr + .split(/\s+/) + .filter((r) => r.length > 0) + if (!disabledRulesMap[nextLine]) { + disabledRulesMap[nextLine] = {} + } + if (!disabledRulesMap[nextLine].rules) { + disabledRulesMap[nextLine].rules = new Set() + } + rules.forEach((r) => disabledRulesMap[nextLine].rules!.add(r)) + } else { + // All rules disabled + if (!disabledRulesMap[nextLine]) { + disabledRulesMap[nextLine] = {} + } + disabledRulesMap[nextLine].all = true + } + } else { + // htmlhint-disable + if (commentOnLine.rulesStr) { + // Specific rules disabled + const rules = commentOnLine.rulesStr + .split(/\s+/) + .filter((r) => r.length > 0) + currentDisabledRules = new Set(rules) + isAllDisabled = false + } else { + // All rules disabled + currentDisabledRules = null + isAllDisabled = true + } + } + } else if (commentOnLine.command === 'enable') { + // htmlhint-enable + currentDisabledRules = null + isAllDisabled = false + } + } + + // Apply current disable state to this line (if not already set by next-line) + if (currentDisabledRules !== null || isAllDisabled) { + if (!disabledRulesMap[line]) { + disabledRulesMap[line] = {} + } + // Don't override if already set by next-line comment + if (isAllDisabled && disabledRulesMap[line].all !== true) { + disabledRulesMap[line].all = true + } else if (currentDisabledRules) { + if (!disabledRulesMap[line].rules) { + disabledRulesMap[line].rules = new Set() + } + currentDisabledRules.forEach((r) => + disabledRulesMap[line].rules!.add(r) + ) + } + } + } + + return disabledRulesMap + } + public format(arrMessages: Hint[], options: FormatOptions = {}) { const arrLogs: string[] = [] const colors = { diff --git a/src/core/reporter.ts b/src/core/reporter.ts index 024a82caf..eaa73b308 100644 --- a/src/core/reporter.ts +++ b/src/core/reporter.ts @@ -1,4 +1,4 @@ -import { Hint, ReportType, Rule, Ruleset } from './types' +import { Hint, ReportType, Rule, Ruleset, DisabledRulesMap } from './types' export default class Reporter { public html: string @@ -6,8 +6,13 @@ export default class Reporter { public brLen: number public ruleset: Ruleset public messages: Hint[] + private disabledRulesMap: DisabledRulesMap - public constructor(html: string, ruleset: Ruleset) { + public constructor( + html: string, + ruleset: Ruleset, + disabledRulesMap: DisabledRulesMap = {} + ) { this.html = html this.lines = html.split(/\r?\n/) const match = /\r?\n/.exec(html) @@ -15,6 +20,7 @@ export default class Reporter { this.brLen = match !== null ? match[0].length : 0 this.ruleset = ruleset this.messages = [] + this.disabledRulesMap = disabledRulesMap } public info( @@ -55,6 +61,19 @@ export default class Reporter { rule: Rule, raw: string ) { + // Check if rule is disabled for this line + const lineDisabled = this.disabledRulesMap[line] + if (lineDisabled) { + if (lineDisabled.all === true) { + // All rules disabled for this line + return + } + if (lineDisabled.rules && lineDisabled.rules.has(rule.id)) { + // This specific rule is disabled for this line + return + } + } + const lines = this.lines const brLen = this.brLen let evidence = '' diff --git a/src/core/types.ts b/src/core/types.ts index f93bdc6e2..003476994 100644 --- a/src/core/types.ts +++ b/src/core/types.ts @@ -79,3 +79,10 @@ export interface Hint { col: number rule: Rule } + +export interface DisabledRulesMap { + [line: number]: { + all?: boolean + rules?: Set + } +} diff --git a/test/core.spec.js b/test/core.spec.js index 114ad81e5..79d5168f2 100644 --- a/test/core.spec.js +++ b/test/core.spec.js @@ -80,4 +80,130 @@ describe('Core', () => { expect(/|\.\.\./.test(log)).toBe(true) expect(/t\.\.\./.test(log)).toBe(true) }) + + describe('Disable/enable comments', () => { + it('htmlhint-disable should disable all rules for following lines', () => { + const code = ` +
Lorem
+
Ipsum
` + const messages = HTMLHint.verify(code, { + 'attr-lowercase': true, + }) + expect(messages.length).toBe(0) + }) + + it('htmlhint-disable-next-line should disable all rules for next line', () => { + const code = ` +
Lorem
+
Ipsum
` + const messages = HTMLHint.verify(code, { + 'attr-lowercase': true, + }) + // Line 2 should be disabled (no errors), line 3 should have errors + expect(messages.length).toBe(0) + }) + + it('htmlhint-disable with specific rule should disable only that rule', () => { + const code = ` +
Lorem
+
Ipsum
` + const messages = HTMLHint.verify(code, { + 'attr-lowercase': true, + 'tag-pair': true, + }) + // attr-lowercase should be disabled, but tag-pair should still work + expect(messages.length).toBe(0) + }) + + it('htmlhint-disable-next-line with specific rule should disable only that rule for next line', () => { + const code = ` +
Lorem
+
Ipsum
` + const messages = HTMLHint.verify(code, { + 'attr-lowercase': true, + }) + // Line 2 should not have errors (disabled), line 3 should have errors + expect(messages.length).toBe(1) + expect(messages[0].line).toBe(3) + expect(messages[0].rule.id).toBe('attr-lowercase') + }) + + it('htmlhint-enable should re-enable rules', () => { + const code = ` +
Lorem
+
Lorem
+ +
Ipsum
` + const messages = HTMLHint.verify(code, { + 'attr-lowercase': true, + }) + // Lines 2-3 should be disabled, line 5 should have errors + expect(messages.length).toBe(1) + expect(messages[0].line).toBe(5) + expect(messages[0].rule.id).toBe('attr-lowercase') + }) + + it('htmlhint-disable should work with multiple rules', () => { + const code = ` +
Lorem
+
Ipsum
` + const messages = HTMLHint.verify(code, { + 'attr-lowercase': true, + 'tagname-lowercase': true, + }) + expect(messages.length).toBe(0) + }) + + it('htmlhint-disable-next-line should work with multiple rules', () => { + const code = ` +
Lorem
+
Ipsum
` + const messages = HTMLHint.verify(code, { + 'attr-lowercase': true, + 'tagname-lowercase': true, + }) + // Line 2 should be disabled, line 3 should have errors + // Filter to only check the rules we care about + const relevantMessages = messages.filter( + (m) => + m.rule.id === 'attr-lowercase' || m.rule.id === 'tagname-lowercase' + ) + // Line 2 should have no errors (disabled) + const line2Messages = relevantMessages.filter((m) => m.line === 2) + expect(line2Messages.length).toBe(0) + // Line 3 should have errors + const line3Messages = relevantMessages.filter((m) => m.line === 3) + expect(line3Messages.length).toBeGreaterThan(0) + expect(line3Messages.some((m) => m.rule.id === 'attr-lowercase')).toBe( + true + ) + expect(line3Messages.some((m) => m.rule.id === 'tagname-lowercase')).toBe( + true + ) + }) + + it('should still report errors when rules are not disabled', () => { + const code = `
Lorem
+
Ipsum
` + const messages = HTMLHint.verify(code, { + 'attr-lowercase': true, + }) + // Line 1 should have an error + expect(messages.length).toBe(1) + expect(messages[0].line).toBe(1) + expect(messages[0].rule.id).toBe('attr-lowercase') + }) + + it('should handle disable comments on same line as code', () => { + const code = `
Lorem
+
Ipsum
` + const messages = HTMLHint.verify(code, { + 'attr-lowercase': true, + }) + // Line 1 should have error, line 2 should be disabled + expect(messages.length).toBe(1) + expect(messages[0].line).toBe(1) + expect(messages[0].rule.id).toBe('attr-lowercase') + }) + }) }) diff --git a/website/src/content/docs/configuration.md b/website/src/content/docs/configuration.md index dff5782a0..6511869c3 100644 --- a/website/src/content/docs/configuration.md +++ b/website/src/content/docs/configuration.md @@ -33,6 +33,69 @@ Finally, rules can be specified inline directly in the HTML document: ``` +## Disabling Rules Inline + +You can disable specific rules or all rules for specific lines in your HTML using HTML comments. This is useful when you need to temporarily disable linting for a particular section of code. + +### Disable All Rules + +To disable all HTMLHint rules for the following lines until re-enabled: + + +```html + +
Lorem
+
Ipsum
+ +
Dolor
+``` + +### Disable for Next Line + +To disable all rules for just the next line: + + +```html + +
Lorem
+
Ipsum
+``` + +### Disable Specific Rules + +To disable specific rules for the following lines: + + +```html + +
Lorem
+
Ipsum
+ +
Dolor
+``` + +### Disable Specific Rules for Next Line + +To disable specific rules for just the next line: + + +```html + +
Lorem
+
Ipsum
+``` + +### Disable Multiple Rules + +You can disable multiple rules by listing them separated by spaces: + + +```html + +
Lorem
+
Ipsum
+``` + ## Example configuration file An example configuration file (with all rules disabled): diff --git a/website/src/content/docs/getting-started.mdx b/website/src/content/docs/getting-started.mdx index cbecb74ff..4c9046238 100644 --- a/website/src/content/docs/getting-started.mdx +++ b/website/src/content/docs/getting-started.mdx @@ -24,6 +24,7 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; "attr-lowercase": true, "attr-no-duplication": true, "attr-value-double-quotes": true, + "attr-value-no-duplication": true, "button-type-require": true, "doctype-first": true, "doctype-html5": true, @@ -31,6 +32,7 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; "h1-require": true, "html-lang-require": true, "id-unique": true, + "input-requires-label": true, "main-require": true, "meta-charset-require": true, "meta-description-require": true, From b298cbcc1dac809e6cfd0c346b09b71feead3e98 Mon Sep 17 00:00:00 2001 From: Christian Oliff Date: Tue, 25 Nov 2025 13:42:46 +0900 Subject: [PATCH 2/2] Update test/core.spec.js Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- test/core.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core.spec.js b/test/core.spec.js index 79d5168f2..f12634549 100644 --- a/test/core.spec.js +++ b/test/core.spec.js @@ -99,7 +99,7 @@ describe('Core', () => { const messages = HTMLHint.verify(code, { 'attr-lowercase': true, }) - // Line 2 should be disabled (no errors), line 3 should have errors + // Line 2 should be disabled (no errors), line 3 is valid (no errors) expect(messages.length).toBe(0) })