2022-03-14 10:32:45 +03:00
|
|
|
import { isNil } from "./lang.mjs";
|
2022-03-16 22:25:36 +03:00
|
|
|
export class TextNode extends String {
|
|
|
|
}
|
2022-03-17 16:34:39 +03:00
|
|
|
export function F(...children) {
|
2022-03-18 22:03:01 +03:00
|
|
|
return new Frag().withChildren(...children);
|
2022-03-16 22:25:36 +03:00
|
|
|
}
|
|
|
|
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));
|
2022-03-14 10:32:45 +03:00
|
|
|
}
|
2022-03-18 22:03:01 +03:00
|
|
|
withChildren(...nodes) {
|
2022-03-16 22:25:36 +03:00
|
|
|
nodes.forEach((n) => this.addChild(n));
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
addChild(node) {
|
|
|
|
if (isNil(this.#children))
|
|
|
|
this.#children = [];
|
|
|
|
this.#children.push(node);
|
|
|
|
}
|
|
|
|
}
|
2022-03-17 16:34:39 +03:00
|
|
|
export function E(tagName, attrs, ...children) {
|
2022-03-18 22:03:01 +03:00
|
|
|
return new Elem(tagName).withAttrs(attrs).withChildren(...children);
|
2022-03-14 10:32:45 +03:00
|
|
|
}
|
2022-03-16 22:25:36 +03:00
|
|
|
export class Elem extends Frag {
|
2022-03-14 10:32:45 +03:00
|
|
|
#tagName;
|
|
|
|
#attrs;
|
|
|
|
#isSelfClosed;
|
|
|
|
constructor(tagName) {
|
2022-03-16 22:25:36 +03:00
|
|
|
super();
|
2022-03-14 10:32:45 +03:00
|
|
|
this.#tagName = tagName;
|
|
|
|
this.#attrs = {};
|
|
|
|
this.#isSelfClosed = selfClosedTagNames.has(tagName);
|
|
|
|
}
|
|
|
|
get tagName() {
|
|
|
|
return this.#tagName;
|
|
|
|
}
|
|
|
|
get attrs() {
|
|
|
|
return this.#attrs;
|
|
|
|
}
|
|
|
|
withAttrs(attrs) {
|
|
|
|
Object.entries(attrs).forEach(([key, value]) => this.addAttr(key, value));
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
withAttr(name, value) {
|
|
|
|
this.addAttr(name, value);
|
|
|
|
return this;
|
|
|
|
}
|
|
|
|
addAttr(name, value) {
|
|
|
|
this.#attrs[name] = value;
|
|
|
|
}
|
|
|
|
addChild(node) {
|
|
|
|
if (this.#isSelfClosed)
|
|
|
|
throw new Error("You cannot add child to self closed element");
|
2022-03-16 22:25:36 +03:00
|
|
|
super.addChild(node);
|
2022-03-14 10:32:45 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
const selfClosedTagNames = new Set([
|
|
|
|
"area",
|
|
|
|
"base",
|
|
|
|
"br",
|
|
|
|
"col",
|
|
|
|
"embed",
|
|
|
|
"hr",
|
|
|
|
"img",
|
|
|
|
"input",
|
|
|
|
"link",
|
|
|
|
"meta",
|
|
|
|
"param",
|
|
|
|
"source",
|
|
|
|
"track",
|
|
|
|
"wbr",
|
|
|
|
]);
|