diff --git a/javascript/packages/linter/src/rules/html-no-self-closing.ts b/javascript/packages/linter/src/rules/html-no-self-closing.ts index 61d65d4fe..7a1dd45be 100644 --- a/javascript/packages/linter/src/rules/html-no-self-closing.ts +++ b/javascript/packages/linter/src/rules/html-no-self-closing.ts @@ -55,6 +55,13 @@ export class HTMLNoSelfClosingRule extends ParserRule): UnboundLintOffense[] { const visitor = new NoSelfClosingVisitor(this.ruleName, context) @@ -76,8 +83,13 @@ export class HTMLNoSelfClosingRule extends ParserRule 0 && isWhitespaceNode(children[children.length - 1])) { - node.children = children.slice(0, -1) + if (children.length > 0) { + const lastChild = children[children.length - 1] + const secondToLastChild = children[children.length - 2] ?? null + + if (isWhitespaceNode(lastChild) && !this.isIndentation(secondToLastChild, lastChild)) { + node.children = children.slice(0, -1) + } } } diff --git a/javascript/packages/linter/test/autofix/html-no-self-closing.autofix.test.ts b/javascript/packages/linter/test/autofix/html-no-self-closing.autofix.test.ts index bf239e188..bf12d6f7e 100644 --- a/javascript/packages/linter/test/autofix/html-no-self-closing.autofix.test.ts +++ b/javascript/packages/linter/test/autofix/html-no-self-closing.autofix.test.ts @@ -1,3 +1,4 @@ +import dedent from "dedent" import { describe, test, expect, beforeAll } from "vitest" import { Herb } from "@herb-tools/node-wasm" import { Linter } from "../../src/linter.js" @@ -86,6 +87,40 @@ describe("html-no-self-closing autofix", () => { expect(result.fixed).toHaveLength(1) }) + test("preserves indentation of closing tag for nested void element", () => { + const input = dedent` +
+ An image +
` + const expected = dedent` +
+ An image +
` + + const linter = new Linter(Herb, [HTMLNoSelfClosingRule]) + const result = linter.autofix(input) + + expect(result.source).toBe(expected) + expect(result.fixed).toHaveLength(1) + }) + + test("drops newline before closing when /> is on its own line without indentation", () => { + const input = '' + const expected = '' + + const linter = new Linter(Herb, [HTMLNoSelfClosingRule]) + const result = linter.autofix(input) + + expect(result.source).toBe(expected) + expect(result.fixed).toHaveLength(1) + }) + test("does not affect SVG elements", () => { const input = ''