From bbec8cc62e97961ffaa7462cbba23f2337bda2cd Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Mon, 28 Aug 2023 21:39:34 -0500 Subject: [PATCH 1/3] fix: allow svg elements to self-close --- src/index.ts | 21 +++++++++++++++++---- test/svg.test.ts | 15 +++++++++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) create mode 100644 test/svg.test.ts diff --git a/src/index.ts b/src/index.ts index 22cfcf3..fbd2d93 100644 --- a/src/index.ts +++ b/src/index.ts @@ -387,6 +387,17 @@ export function walkSync(node: Node, callback: VisitorSync): void { return walker.visit(node); } +function canSelfClose(node: Node): boolean { + if (node.children.length === 0) { + let n: Node | undefined = node; + while (n = n.parent) { + if (n.name === 'svg') return true; + } + } + return false; +} + + async function renderElement(node: Node): Promise { const { name, attributes = {} } = node; const children = await Promise.all( @@ -398,8 +409,9 @@ async function renderElement(node: Node): Promise { return escapeHTML(String(value)); } if (name === Fragment) return children; - if (VOID_TAGS.has(name)) { - return `<${node.name}${attrs(attributes).value}>`; + const isSelfClosing = canSelfClose(node); + if (isSelfClosing || VOID_TAGS.has(name)) { + return `<${node.name}${attrs(attributes).value}${isSelfClosing ? ' /' : ''}>`; } return `<${node.name}${attrs(attributes).value}>${children}`; } @@ -413,8 +425,9 @@ function renderElementSync(node: Node): string { return escapeHTML(String(value)); } if (name === Fragment) return children; - if (VOID_TAGS.has(name)) { - return `<${node.name}${attrs(attributes).value}>`; + const isSelfClosing = canSelfClose(node); + if (isSelfClosing || VOID_TAGS.has(name)) { + return `<${node.name}${attrs(attributes).value}${isSelfClosing ? ' /' : ''}>`; } return `<${node.name}${attrs(attributes).value}>${children}`; } diff --git a/test/svg.test.ts b/test/svg.test.ts new file mode 100644 index 0000000..b376853 --- /dev/null +++ b/test/svg.test.ts @@ -0,0 +1,15 @@ +import { parse, render, renderSync } from "../src"; +import { describe, expect, it, test } from "vitest"; + +describe("svg", () => { + it("render as self-closing", async () => { + const input = ``; + const output = await render(parse(input)); + expect(output).toEqual(input); + }); + it("renderSync as self-closing", async () => { + const input = ``; + const output = renderSync(parse(input)); + expect(output).toEqual(input); + }); +}); From 8bbaeef861f623d4928f233cc72fc3d3a05527a1 Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Mon, 28 Aug 2023 21:40:31 -0500 Subject: [PATCH 2/3] fix(#48): allow svg children to self-close --- .changeset/smart-pumpkins-occur.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/smart-pumpkins-occur.md diff --git a/.changeset/smart-pumpkins-occur.md b/.changeset/smart-pumpkins-occur.md new file mode 100644 index 0000000..74421c3 --- /dev/null +++ b/.changeset/smart-pumpkins-occur.md @@ -0,0 +1,5 @@ +--- +"ultrahtml": minor +--- + +Allow elements inside of to be self-closing for compactness From 1f6f03ec550cf9f0787b210c28bff5659ed2e4da Mon Sep 17 00:00:00 2001 From: Nate Moore Date: Mon, 28 Aug 2023 21:41:52 -0500 Subject: [PATCH 3/3] Update smart-pumpkins-occur.md --- .changeset/smart-pumpkins-occur.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/smart-pumpkins-occur.md b/.changeset/smart-pumpkins-occur.md index 74421c3..f955b3a 100644 --- a/.changeset/smart-pumpkins-occur.md +++ b/.changeset/smart-pumpkins-occur.md @@ -2,4 +2,4 @@ "ultrahtml": minor --- -Allow elements inside of to be self-closing for compactness +Allow elements inside of `` to be self-closing for compactness