add possibility to wrap node

This commit is contained in:
Dmitriy Pleshevskiy 2022-05-22 22:47:17 +03:00
parent f1d6a2e989
commit c3014d690b
4 changed files with 32 additions and 15 deletions

3
.gitignore vendored
View File

@ -1,8 +1,5 @@
/*
# editors
!/.vscode
# makefile
!/makefile

View File

@ -1,3 +0,0 @@
{
"editor.tabSize": 2
}

View File

@ -1,5 +1,6 @@
import { assertEquals } from "testing/asserts.ts";
import { E, F, TextNode } from "../core/node.ts";
import { TextNode } from "../core/node.ts";
import { E, F } from "./node.ts";
import { StrRenderer } from "./str.ts";
@ -131,3 +132,15 @@ Deno.test({
assertEquals(res, "<!doctype html><body></body>");
},
});
Deno.test({
name: "should wrap node",
fn: () => {
const layout = E("body", [], []);
const ren = new StrRenderer({ wrapNode: (node) => E("html", [], [node]) });
const res = ren.render(layout);
assertEquals(res, "<!doctype html><html><body></body></html>");
},
});

View File

@ -14,27 +14,37 @@ import { Renderer } from "./types.ts";
interface StrRendererOpts {
doctype?: string;
forceRenderDoctype?: boolean;
wrapNode?: (node: AnyNode) => AnyNode;
}
export class StrRenderer implements Renderer<string> {
#opts: StrRendererOpts;
#doctype: string;
#forceRenderDoctype: boolean;
#wrapNode: (node: AnyNode) => AnyNode;
constructor(opts?: StrRendererOpts) {
this.#opts = opts ?? {};
this.#doctype = opts?.doctype ?? "html";
this.#forceRenderDoctype = opts?.forceRenderDoctype ?? false;
this.#wrapNode = opts?.wrapNode ?? identity;
}
render(node: AnyNode): string {
const shouldRenderDoctype = this.#opts.forceRenderDoctype ||
(isElem(node) && node.tagName === "html");
const wrappedNode = this.#wrapNode(node);
const shouldRenderDoctype = this.#forceRenderDoctype ||
(isElem(wrappedNode) && wrappedNode.tagName === "html");
return concat([
shouldRenderDoctype && encodeDoctype(this.#opts.doctype),
encodeAnyNode(node),
shouldRenderDoctype && encodeDoctype(this.#doctype),
encodeAnyNode(wrappedNode),
]);
}
}
function encodeDoctype(value?: string): string {
return `<!doctype ${value ?? "html"}>`;
function identity<T>(val: T): T {
return val;
}
function encodeDoctype(value: string): string {
return `<!doctype ${value}>`;
}
function encodeAnyNode(node: AnyNode): string {