From f2e2f6a1bde20e84f93196bd1389c6fa433db4b2 Mon Sep 17 00:00:00 2001 From: Jordan Atwood Date: Wed, 13 Aug 2025 12:50:41 -0700 Subject: [PATCH] feat: support linting doctype in lowercase --- packages/eslint-plugin/lib/rules/lowercase.js | 50 ++++++++++++++++++- .../tests/rules/lowercase.test.js | 21 ++++++++ .../website/src/scripts/playground/helpers.js | 2 +- 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/packages/eslint-plugin/lib/rules/lowercase.js b/packages/eslint-plugin/lib/rules/lowercase.js index 261115d3..ac741878 100644 --- a/packages/eslint-plugin/lib/rules/lowercase.js +++ b/packages/eslint-plugin/lib/rules/lowercase.js @@ -1,5 +1,10 @@ /** - * @import {Tag, StyleTag, ScriptTag} from "@html-eslint/types"; + * @import { + * Tag, + * StyleTag, + * ScriptTag, + * Doctype, + * } from "@html-eslint/types"; * @import {RuleModule} from "../types"; */ @@ -128,6 +133,48 @@ module.exports = { } } + /** + * @param {Doctype} doctype + */ + function checkDoctype(doctype) { + if (doctype.open.value !== doctype.open.value.toLowerCase()) { + context.report({ + node: doctype.open, + messageId: MESSAGE_IDS.UNEXPECTED, + data: { + name: doctype.open.value.slice(1), + }, + fix(fixer) { + return fixer.replaceTextRange(doctype.open.range, " { + if ( + attribute.value && + attribute.value.value !== attribute.value.value.toLowerCase() + ) { + context.report({ + node: attribute.value, + messageId: MESSAGE_IDS.UNEXPECTED, + data: { + name: attribute.value.value, + }, + fix(fixer) { + return fixer.replaceText( + // @ts-ignore + attribute.value, + // @ts-ignore + attribute.value.value.toLowerCase() + ); + }, + }); + } + }); + } + } + return createVisitors(context, { Tag(node) { if (node.name.toLocaleLowerCase() === "svg") { @@ -142,6 +189,7 @@ module.exports = { }, StyleTag: check, ScriptTag: check, + Doctype: checkDoctype, }); }, }; diff --git a/packages/eslint-plugin/tests/rules/lowercase.test.js b/packages/eslint-plugin/tests/rules/lowercase.test.js index 3c433ef5..18ed8532 100644 --- a/packages/eslint-plugin/tests/rules/lowercase.test.js +++ b/packages/eslint-plugin/tests/rules/lowercase.test.js @@ -52,6 +52,9 @@ ruleTester.run("lowercase", rule, { `, }, + { + code: ``, + }, { code: "
", languageOptions: { @@ -127,6 +130,24 @@ ruleTester.run("lowercase", rule, { }, ], }, + { + code: ``, + output: ``, + errors: [ + { + message: "'!DOCTYPE' is not in lowercase.", + }, + ], + }, + { + code: ``, + output: ``, + errors: [ + { + message: "'HTML' is not in lowercase.", + }, + ], + }, { code: "
", output: "
", diff --git a/packages/website/src/scripts/playground/helpers.js b/packages/website/src/scripts/playground/helpers.js index d8fb1e5b..12df457d 100644 --- a/packages/website/src/scripts/playground/helpers.js +++ b/packages/website/src/scripts/playground/helpers.js @@ -44,7 +44,7 @@ export function escapeHTML(str) { .replace(/>/g, ">"); } -export const INITIAL_HTML = html` +export const INITIAL_HTML = html`