chore: rebuild sources
This commit is contained in:
parent
a0df5e48fa
commit
c26a095fef
3 changed files with 64 additions and 38 deletions
|
@ -1,22 +1,54 @@
|
||||||
import { isNil } from "./lang.mjs";
|
import { isNil } from "./lang.mjs";
|
||||||
export class TextNode {
|
export class TextNode extends String {
|
||||||
#text;
|
|
||||||
constructor(text) {
|
|
||||||
this.#text = text;
|
|
||||||
}
|
}
|
||||||
get text() {
|
export function F(children) {
|
||||||
return this.#text;
|
return new Frag().withChildren(children);
|
||||||
|
}
|
||||||
|
export class Frag {
|
||||||
|
#children;
|
||||||
|
constructor() {
|
||||||
|
this.#children = undefined;
|
||||||
|
}
|
||||||
|
get children() {
|
||||||
|
return this.#children;
|
||||||
|
}
|
||||||
|
withText(text) {
|
||||||
|
this.addText(text);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
addText(text) {
|
||||||
|
this.addChild(new TextNode(text));
|
||||||
|
}
|
||||||
|
maybeWithChildren(nodes) {
|
||||||
|
if (isNil(nodes))
|
||||||
|
return this;
|
||||||
|
return this.withChildren(nodes);
|
||||||
|
}
|
||||||
|
withChildren(nodes) {
|
||||||
|
nodes.forEach((n) => this.addChild(n));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
withChild(node) {
|
||||||
|
this.addChild(node);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
addChild(node) {
|
||||||
|
if (isNil(this.#children))
|
||||||
|
this.#children = [];
|
||||||
|
this.#children.push(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export class Node {
|
export function E(tagName, attrs, children) {
|
||||||
|
return new Elem(tagName).withAttrs(attrs).maybeWithChildren(children);
|
||||||
|
}
|
||||||
|
export class Elem extends Frag {
|
||||||
#tagName;
|
#tagName;
|
||||||
#attrs;
|
#attrs;
|
||||||
#children;
|
|
||||||
#isSelfClosed;
|
#isSelfClosed;
|
||||||
constructor(tagName) {
|
constructor(tagName) {
|
||||||
|
super();
|
||||||
this.#tagName = tagName;
|
this.#tagName = tagName;
|
||||||
this.#attrs = {};
|
this.#attrs = {};
|
||||||
this.#children = undefined;
|
|
||||||
this.#isSelfClosed = selfClosedTagNames.has(tagName);
|
this.#isSelfClosed = selfClosedTagNames.has(tagName);
|
||||||
}
|
}
|
||||||
get tagName() {
|
get tagName() {
|
||||||
|
@ -25,9 +57,6 @@ export class Node {
|
||||||
get attrs() {
|
get attrs() {
|
||||||
return this.#attrs;
|
return this.#attrs;
|
||||||
}
|
}
|
||||||
get children() {
|
|
||||||
return this.#children;
|
|
||||||
}
|
|
||||||
withAttrs(attrs) {
|
withAttrs(attrs) {
|
||||||
Object.entries(attrs).forEach(([key, value]) => this.addAttr(key, value));
|
Object.entries(attrs).forEach(([key, value]) => this.addAttr(key, value));
|
||||||
return this;
|
return this;
|
||||||
|
@ -39,27 +68,10 @@ export class Node {
|
||||||
addAttr(name, value) {
|
addAttr(name, value) {
|
||||||
this.#attrs[name] = value;
|
this.#attrs[name] = value;
|
||||||
}
|
}
|
||||||
withText(text) {
|
|
||||||
this.addText(text);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
addText(text) {
|
|
||||||
this.addChild(new TextNode(text));
|
|
||||||
}
|
|
||||||
withChildren(nodes) {
|
|
||||||
nodes.forEach((n) => this.addChild(n));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
withChild(node) {
|
|
||||||
this.addChild(node);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
addChild(node) {
|
addChild(node) {
|
||||||
if (this.#isSelfClosed)
|
if (this.#isSelfClosed)
|
||||||
throw new Error("You cannot add child to self closed element");
|
throw new Error("You cannot add child to self closed element");
|
||||||
if (isNil(this.#children))
|
super.addChild(node);
|
||||||
this.#children = [];
|
|
||||||
this.#children.push(node);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const selfClosedTagNames = new Set([
|
const selfClosedTagNames = new Set([
|
27
lib/str.mjs
27
lib/str.mjs
|
@ -1,20 +1,31 @@
|
||||||
import { TextNode } from "./node.mjs";
|
|
||||||
import { isBool, isNil } from "./lang.mjs";
|
import { isBool, isNil } from "./lang.mjs";
|
||||||
|
import { Elem, TextNode } from "./nodes.mjs";
|
||||||
export class StrRenderer {
|
export class StrRenderer {
|
||||||
async render(node) {
|
async render(node) {
|
||||||
return encodeNode(node);
|
return encodeNode(await node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function encodeAnyNode(node) {
|
async function encodeAnyNode(node) {
|
||||||
return node instanceof TextNode ? encodeTextNode(node) : encodeNode(node);
|
const syncNode = await node;
|
||||||
|
return syncNode instanceof TextNode
|
||||||
|
? encodeTextNode(syncNode)
|
||||||
|
: encodeNode(syncNode);
|
||||||
}
|
}
|
||||||
function encodeTextNode(node) {
|
function encodeTextNode(node) {
|
||||||
return node.text;
|
return String(node);
|
||||||
}
|
}
|
||||||
function encodeNode(node) {
|
async function encodeNode(node) {
|
||||||
return encodeHtml(node.tagName, node.attrs, node.children?.map(encodeAnyNode));
|
const encodedChildren = isNil(node.children)
|
||||||
|
? undefined
|
||||||
|
: await Promise.all(node.children.map(encodeAnyNode));
|
||||||
|
return node instanceof Elem
|
||||||
|
? encodeHtmlElement(node.tagName, node.attrs, encodedChildren)
|
||||||
|
: encodeHtmlFragment(encodedChildren);
|
||||||
}
|
}
|
||||||
function encodeHtml(tagName, attrs, children) {
|
function encodeHtmlFragment(children) {
|
||||||
|
return children?.join("") ?? "";
|
||||||
|
}
|
||||||
|
function encodeHtmlElement(tagName, attrs, children) {
|
||||||
const open = `<${tagName} ${encodeAttrs(attrs)}>`;
|
const open = `<${tagName} ${encodeAttrs(attrs)}>`;
|
||||||
if (isNil(children))
|
if (isNil(children))
|
||||||
return open;
|
return open;
|
||||||
|
|
3
makefile
3
makefile
|
@ -1,4 +1,7 @@
|
||||||
|
|
||||||
|
ts:
|
||||||
|
npx tsc
|
||||||
|
|
||||||
ts-w:
|
ts-w:
|
||||||
npx tsc-watch
|
npx tsc-watch
|
||||||
|
|
||||||
|
|
Reference in a new issue