diff --git a/src/component.ts b/src/component.ts index 848eea3..18db150 100644 --- a/src/component.ts +++ b/src/component.ts @@ -44,3 +44,9 @@ export interface Component
{ } ): HTMLElement; } + +export const Fragment: Component<{}> = ({ children }) => ({ + tag: "#fragment", + attributes: {}, + children: children || [], +}); diff --git a/src/index.ts b/src/index.ts index 2e5606b..bb1676f 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -export { HTMLElement, Component } from "./component"; +export { HTMLElement, Component, Fragment } from "./component"; export { UserConfig as Config } from "./config"; export { createElement } from "./create-element"; export * from "./jsx"; diff --git a/src/render.ts b/src/render.ts index ef0917f..174461f 100644 --- a/src/render.ts +++ b/src/render.ts @@ -42,6 +42,10 @@ const renderElement = (elem: Element): string => { }; const startTag = (elem: HTMLElement): string => { + if (elem.tag === "#fragment") { + return ""; + } + let output = `<${escapeHtml(elem.tag)}`; for (const [attrName, attrValue] of Object.entries(elem.attributes)) { @@ -68,7 +72,12 @@ const startTag = (elem: HTMLElement): string => { return output; }; -const endTag = (elem: HTMLElement): string => `${escapeHtml(elem.tag)}>`; +const endTag = (elem: HTMLElement): string => { + if (elem.tag === "#fragment") { + return ""; + } + return `${escapeHtml(elem.tag)}>`; +}; /** * Render a complete HTML page from an HTMLElement. Note that the root element @@ -78,7 +87,17 @@ const endTag = (elem: HTMLElement): string => `${escapeHtml(elem.tag)}>`; * * @return Fully rendered HTML document as a string. */ -export const renderPage = (rootElem: HTMLElement): string => { +export const renderPage = (rootElem: Element): string => { + if (rootElem == undefined) { + throw new Error(`root page element cannot be null`); + } + if (typeof rootElem !== "object" || !("tag" in rootElem)) { + throw new Error( + `root page element must be a valid HTMLElement, got ${JSON.stringify( + rootElem + )}` + ); + } if (rootElem.tag.toLowerCase() !== "html") { throw new Error( `attempted to render page with non-HTML root element ${rootElem.tag}` diff --git a/test/test-suites/rendering.tsx b/test/test-suites/rendering.tsx index b4cb3b2..ef567dd 100644 --- a/test/test-suites/rendering.tsx +++ b/test/test-suites/rendering.tsx @@ -3,7 +3,7 @@ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ -import { Component, createElement } from "../../dist"; +import { Component, createElement, Fragment } from "../../dist"; import { renderPage } from "../../dist/render"; import { testSuite } from "../lib"; @@ -103,4 +103,18 @@ testSuite("renderPage", ({ test, expect }) => { "There are