Skip to content

Commit

Permalink
Merge pull request #57 from natemoo-re/fix/svg
Browse files Browse the repository at this point in the history
Allow svg children to self-close
  • Loading branch information
natemoo-re authored Aug 29, 2023
2 parents 8732091 + 1f6f03e commit 9e1c7f1
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/smart-pumpkins-occur.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"ultrahtml": minor
---

Allow elements inside of `<svg>` to be self-closing for compactness
21 changes: 17 additions & 4 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string> {
const { name, attributes = {} } = node;
const children = await Promise.all(
Expand All @@ -398,8 +409,9 @@ async function renderElement(node: Node): Promise<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}</${node.name}>`;
}
Expand All @@ -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}</${node.name}>`;
}
Expand Down
15 changes: 15 additions & 0 deletions test/svg.test.ts
Original file line number Diff line number Diff line change
@@ -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 = `<svg><path d="0 0 0" /></svg>`;
const output = await render(parse(input));
expect(output).toEqual(input);
});
it("renderSync as self-closing", async () => {
const input = `<svg><path d="0 0 0" /></svg>`;
const output = renderSync(parse(input));
expect(output).toEqual(input);
});
});

0 comments on commit 9e1c7f1

Please sign in to comment.