diff --git a/lib/str.mjs b/lib/str.mjs index 451da25..6adb48b 100644 --- a/lib/str.mjs +++ b/lib/str.mjs @@ -18,27 +18,24 @@ function encodeTextNode(node) { function encodeNode(node) { const encodedChildren = isNil(node.children) ? undefined - : node.children.map(encodeAnyNode).filter((c) => Boolean(c)); + : node.children.map(encodeAnyNode); return node instanceof Elem ? encodeHtmlElement(node.tagName, node.attrs, encodedChildren) : encodeHtmlFragment(encodedChildren); } function encodeHtmlFragment(children) { - return children?.join("") ?? ""; + return concat(children ?? []); } function encodeHtmlElement(tagName, attrs, children) { - const open = `<${tagName} ${encodeAttrs(attrs)}>`; + const open = `<${join(" ", [tagName, encodeAttrs(attrs)])}>`; if (isNil(children)) return open; - return `${open}${children.join("")}`; + return `${open}${concat(children)}`; } function encodeAttrs(attrs) { if (!attrs) - return ""; - return Object.entries(attrs) - .map(([key, value]) => encodeAttr(key, value)) - .filter(Boolean) - .join(" "); + return null; + return join(" ", Object.entries(attrs).map(([key, value]) => encodeAttr(key, value))); } function encodeAttr(key, value) { if (isNil(value)) @@ -47,3 +44,9 @@ function encodeAttr(key, value) { return value ? key : null; return `${key}="${value}"`; } +function concat(arr) { + return join("", arr); +} +function join(sep, arr) { + return arr.filter(Boolean).join(sep); +} diff --git a/src/str.mts b/src/str.mts index fd69ce8..ea859a9 100644 --- a/src/str.mts +++ b/src/str.mts @@ -1,6 +1,6 @@ import { Renderer } from "./types.mjs"; -import { isBool, isNil, Nullable } from "./lang.mjs"; -import { AnyNode, Elem, Frag, TextNode } from "./nodes.mjs"; +import { isBool, isNil, Nilable, Nullable } from "./lang.mjs"; +import { AnyNode, Elem, ElemAttrs, Frag, TextNode } from "./nodes.mjs"; export class StrRenderer implements Renderer { render(node: Elem): string { @@ -23,33 +23,33 @@ function encodeTextNode(node: TextNode): string { function encodeNode(node: Elem | Frag): string { const encodedChildren = isNil(node.children) ? undefined - : node.children.map(encodeAnyNode).filter((c): c is string => Boolean(c)); + : node.children.map(encodeAnyNode); return node instanceof Elem ? encodeHtmlElement(node.tagName, node.attrs, encodedChildren) : encodeHtmlFragment(encodedChildren); } -function encodeHtmlFragment(children?: string[]): string { - return children?.join("") ?? ""; +function encodeHtmlFragment(children?: Nilable[]): string { + return concat(children ?? []); } function encodeHtmlElement( tagName: string, - attrs?: Record, - children?: string[] + attrs?: ElemAttrs, + children?: Nilable[] ): string { - const open = `<${tagName} ${encodeAttrs(attrs)}>`; + const open = `<${join(" ", [tagName, encodeAttrs(attrs)])}>`; if (isNil(children)) return open; - return `${open}${children.join("")}`; + return `${open}${concat(children)}`; } -function encodeAttrs(attrs?: Record): Nullable { - if (!attrs) return ""; +function encodeAttrs(attrs?: ElemAttrs): Nullable { + if (!attrs) return null; - return Object.entries(attrs) - .map(([key, value]) => encodeAttr(key, value)) - .filter(Boolean) - .join(" "); + return join( + " ", + Object.entries(attrs).map(([key, value]) => encodeAttr(key, value)) + ); } function encodeAttr(key: string, value: unknown): Nullable { @@ -57,3 +57,11 @@ function encodeAttr(key: string, value: unknown): Nullable { if (isBool(value)) return value ? key : null; return `${key}="${value}"`; } + +function concat(arr: Nilable[]): string { + return join("", arr); +} + +function join(sep: string, arr: Nilable[]): string { + return arr.filter(Boolean).join(sep); +}