feat: improve api
This commit is contained in:
parent
f7d94d9010
commit
1b21c2d796
8 changed files with 101 additions and 61 deletions
2
lib/lang.d.ts
vendored
2
lib/lang.d.ts
vendored
|
@ -3,3 +3,5 @@ export declare type Nullable<T> = T | null;
|
||||||
export declare type Nilable<T> = T | Nil;
|
export declare type Nilable<T> = T | Nil;
|
||||||
export declare type Nil = null | undefined;
|
export declare type Nil = null | undefined;
|
||||||
export declare function isBool(v: unknown): v is boolean;
|
export declare function isBool(v: unknown): v is boolean;
|
||||||
|
export declare function isStr(v: unknown): v is string;
|
||||||
|
export declare function intoArr<T>(v: T | T[]): T[];
|
||||||
|
|
|
@ -4,3 +4,9 @@ export function isNil(v) {
|
||||||
export function isBool(v) {
|
export function isBool(v) {
|
||||||
return typeof v === "boolean";
|
return typeof v === "boolean";
|
||||||
}
|
}
|
||||||
|
export function isStr(v) {
|
||||||
|
return typeof v === "string";
|
||||||
|
}
|
||||||
|
export function intoArr(v) {
|
||||||
|
return Array.isArray(v) ? v : [v];
|
||||||
|
}
|
||||||
|
|
20
lib/nodes.d.ts
vendored
20
lib/nodes.d.ts
vendored
|
@ -1,26 +1,28 @@
|
||||||
import { Nil, Nilable } from "./lang.js";
|
import { Nil, Nilable } from "./lang.js";
|
||||||
export declare type AnyNode = TextNode | Elem | Frag | Nil | false;
|
export declare function Et(tagName: string, ...texts: string[]): Elem;
|
||||||
export declare class TextNode extends String {
|
export declare function Ea(tagName: string, attrs?: ElemAttrs, children?: AnyNode | AnyNode[]): Elem;
|
||||||
}
|
export declare function E(tagName: string, children: AnyNode | AnyNode[]): Elem;
|
||||||
export declare function F(...children: AnyNode[]): Frag;
|
export declare function F(...children: AnyNode[]): Frag;
|
||||||
|
export declare type AnyNode = TextNode | Elem | Frag | Nil | false;
|
||||||
|
export declare type TextNode = string;
|
||||||
export declare class Frag {
|
export declare class Frag {
|
||||||
#private;
|
#private;
|
||||||
constructor();
|
constructor();
|
||||||
get children(): Nilable<AnyNode[]>;
|
get children(): Nilable<AnyNode[]>;
|
||||||
withText(text: string): this;
|
withText(texts: TextNode | TextNode[]): this;
|
||||||
addText(text: string): void;
|
addText(texts: TextNode | TextNode[]): void;
|
||||||
withChildren(...nodes: AnyNode[]): this;
|
withChildren(nodes: AnyNode | AnyNode[]): this;
|
||||||
|
addChildren(nodes: AnyNode | AnyNode[]): void;
|
||||||
addChild(node: AnyNode): void;
|
addChild(node: AnyNode): void;
|
||||||
}
|
}
|
||||||
export declare function E(tagName: string, attrs: ElemAttrs, ...children: AnyNode[]): Elem;
|
|
||||||
export declare type ElemAttrs = Record<string, unknown>;
|
export declare type ElemAttrs = Record<string, unknown>;
|
||||||
export declare class Elem extends Frag {
|
export declare class Elem extends Frag {
|
||||||
#private;
|
#private;
|
||||||
constructor(tagName: string);
|
constructor(tagName: string);
|
||||||
get tagName(): string;
|
get tagName(): string;
|
||||||
get attrs(): Record<string, unknown>;
|
get attrs(): Record<string, unknown>;
|
||||||
withAttrs(attrs: Record<string, unknown>): Elem;
|
withAttrs(attrs: ElemAttrs): Elem;
|
||||||
withAttr(name: string, value: unknown): Elem;
|
addAttrs(attrs: ElemAttrs): void;
|
||||||
addAttr(name: string, value: unknown): void;
|
addAttr(name: string, value: unknown): void;
|
||||||
addChild(node: AnyNode): void;
|
addChild(node: AnyNode): void;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,20 @@
|
||||||
import { isNil } from "./lang.mjs";
|
import { intoArr, isNil } from "./lang.mjs";
|
||||||
export class TextNode extends String {
|
export function Et(tagName, ...texts) {
|
||||||
|
return new Elem(tagName).withText(texts);
|
||||||
|
}
|
||||||
|
export function Ea(tagName, attrs, children) {
|
||||||
|
const el = new Elem(tagName);
|
||||||
|
if (attrs)
|
||||||
|
el.addAttrs(attrs);
|
||||||
|
if (children)
|
||||||
|
el.addChildren(children);
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
export function E(tagName, children) {
|
||||||
|
return new Elem(tagName).withChildren(children);
|
||||||
}
|
}
|
||||||
export function F(...children) {
|
export function F(...children) {
|
||||||
return new Frag().withChildren(...children);
|
return new Frag().withChildren(children);
|
||||||
}
|
}
|
||||||
export class Frag {
|
export class Frag {
|
||||||
#children;
|
#children;
|
||||||
|
@ -12,26 +24,28 @@ export class Frag {
|
||||||
get children() {
|
get children() {
|
||||||
return this.#children;
|
return this.#children;
|
||||||
}
|
}
|
||||||
withText(text) {
|
withText(texts) {
|
||||||
this.addText(text);
|
this.addText(texts);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
addText(text) {
|
addText(texts) {
|
||||||
this.addChild(new TextNode(text));
|
this.addChildren(intoArr(texts)
|
||||||
|
.map((t) => t.trim())
|
||||||
|
.join(" "));
|
||||||
}
|
}
|
||||||
withChildren(...nodes) {
|
withChildren(nodes) {
|
||||||
nodes.forEach((n) => this.addChild(n));
|
this.addChildren(nodes);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
addChildren(nodes) {
|
||||||
|
intoArr(nodes).forEach((n) => this.addChild(n));
|
||||||
|
}
|
||||||
addChild(node) {
|
addChild(node) {
|
||||||
if (isNil(this.#children))
|
if (isNil(this.#children))
|
||||||
this.#children = [];
|
this.#children = [];
|
||||||
this.#children.push(node);
|
this.#children.push(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export function E(tagName, attrs, ...children) {
|
|
||||||
return new Elem(tagName).withAttrs(attrs).withChildren(...children);
|
|
||||||
}
|
|
||||||
export class Elem extends Frag {
|
export class Elem extends Frag {
|
||||||
#tagName;
|
#tagName;
|
||||||
#attrs;
|
#attrs;
|
||||||
|
@ -49,12 +63,11 @@ export class Elem extends Frag {
|
||||||
return this.#attrs;
|
return this.#attrs;
|
||||||
}
|
}
|
||||||
withAttrs(attrs) {
|
withAttrs(attrs) {
|
||||||
Object.entries(attrs).forEach(([key, value]) => this.addAttr(key, value));
|
this.addAttrs(attrs);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
withAttr(name, value) {
|
addAttrs(attrs) {
|
||||||
this.addAttr(name, value);
|
Object.entries(attrs).forEach(([key, value]) => this.addAttr(key, value));
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
addAttr(name, value) {
|
addAttr(name, value) {
|
||||||
this.#attrs[name] = value;
|
this.#attrs[name] = value;
|
||||||
|
|
10
lib/str.mjs
10
lib/str.mjs
|
@ -1,16 +1,12 @@
|
||||||
import { isBool, isNil } from "./lang.mjs";
|
import { isBool, isNil, isStr } from "./lang.mjs";
|
||||||
import { Elem, TextNode } from "./nodes.mjs";
|
import { Elem } from "./nodes.mjs";
|
||||||
export class StrRenderer {
|
export class StrRenderer {
|
||||||
render(node) {
|
render(node) {
|
||||||
return encodeNode(node);
|
return encodeNode(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function encodeAnyNode(node) {
|
function encodeAnyNode(node) {
|
||||||
return !node
|
return !node ? null : isStr(node) ? encodeTextNode(node) : encodeNode(node);
|
||||||
? null
|
|
||||||
: node instanceof TextNode
|
|
||||||
? encodeTextNode(node)
|
|
||||||
: encodeNode(node);
|
|
||||||
}
|
}
|
||||||
function encodeTextNode(node) {
|
function encodeTextNode(node) {
|
||||||
return String(node);
|
return String(node);
|
||||||
|
|
|
@ -11,3 +11,11 @@ export type Nil = null | undefined;
|
||||||
export function isBool(v: unknown): v is boolean {
|
export function isBool(v: unknown): v is boolean {
|
||||||
return typeof v === "boolean";
|
return typeof v === "boolean";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isStr(v: unknown): v is string {
|
||||||
|
return typeof v === "string";
|
||||||
|
}
|
||||||
|
|
||||||
|
export function intoArr<T>(v: T | T[]): T[] {
|
||||||
|
return Array.isArray(v) ? v : [v];
|
||||||
|
}
|
||||||
|
|
|
@ -1,13 +1,31 @@
|
||||||
import { isNil, Nil, Nilable } from "./lang.mjs";
|
import { intoArr, isNil, Nil, Nilable } from "./lang.mjs";
|
||||||
|
|
||||||
export type AnyNode = TextNode | Elem | Frag | Nil | false;
|
export function Et(tagName: string, ...texts: string[]): Elem {
|
||||||
|
return new Elem(tagName).withText(texts);
|
||||||
|
}
|
||||||
|
|
||||||
export class TextNode extends String {}
|
export function Ea(
|
||||||
|
tagName: string,
|
||||||
|
attrs?: ElemAttrs,
|
||||||
|
children?: AnyNode | AnyNode[]
|
||||||
|
): Elem {
|
||||||
|
const el = new Elem(tagName);
|
||||||
|
if (attrs) el.addAttrs(attrs);
|
||||||
|
if (children) el.addChildren(children);
|
||||||
|
return el;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function E(tagName: string, children: AnyNode | AnyNode[]): Elem {
|
||||||
|
return new Elem(tagName).withChildren(children);
|
||||||
|
}
|
||||||
|
|
||||||
export function F(...children: AnyNode[]): Frag {
|
export function F(...children: AnyNode[]): Frag {
|
||||||
return new Frag().withChildren(...children);
|
return new Frag().withChildren(children);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type AnyNode = TextNode | Elem | Frag | Nil | false;
|
||||||
|
export type TextNode = string;
|
||||||
|
|
||||||
export class Frag {
|
export class Frag {
|
||||||
#children: Nilable<AnyNode[]>;
|
#children: Nilable<AnyNode[]>;
|
||||||
|
|
||||||
|
@ -19,34 +37,34 @@ export class Frag {
|
||||||
return this.#children;
|
return this.#children;
|
||||||
}
|
}
|
||||||
|
|
||||||
withText(text: string): this {
|
withText(texts: TextNode | TextNode[]): this {
|
||||||
this.addText(text);
|
this.addText(texts);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
addText(text: string): void {
|
addText(texts: TextNode | TextNode[]): void {
|
||||||
this.addChild(new TextNode(text));
|
this.addChildren(
|
||||||
|
intoArr(texts)
|
||||||
|
.map((t) => t.trim())
|
||||||
|
.join(" ")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
withChildren(...nodes: AnyNode[]): this {
|
withChildren(nodes: AnyNode | AnyNode[]): this {
|
||||||
nodes.forEach((n) => this.addChild(n));
|
this.addChildren(nodes);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addChildren(nodes: AnyNode | AnyNode[]): void {
|
||||||
|
intoArr(nodes).forEach((n) => this.addChild(n));
|
||||||
|
}
|
||||||
|
|
||||||
addChild(node: AnyNode): void {
|
addChild(node: AnyNode): void {
|
||||||
if (isNil(this.#children)) this.#children = [];
|
if (isNil(this.#children)) this.#children = [];
|
||||||
this.#children.push(node);
|
this.#children.push(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function E(
|
|
||||||
tagName: string,
|
|
||||||
attrs: ElemAttrs,
|
|
||||||
...children: AnyNode[]
|
|
||||||
): Elem {
|
|
||||||
return new Elem(tagName).withAttrs(attrs).withChildren(...children);
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ElemAttrs = Record<string, unknown>;
|
export type ElemAttrs = Record<string, unknown>;
|
||||||
|
|
||||||
export class Elem extends Frag {
|
export class Elem extends Frag {
|
||||||
|
@ -69,14 +87,13 @@ export class Elem extends Frag {
|
||||||
return this.#attrs;
|
return this.#attrs;
|
||||||
}
|
}
|
||||||
|
|
||||||
withAttrs(attrs: Record<string, unknown>): Elem {
|
withAttrs(attrs: ElemAttrs): Elem {
|
||||||
Object.entries(attrs).forEach(([key, value]) => this.addAttr(key, value));
|
this.addAttrs(attrs);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
withAttr(name: string, value: unknown): Elem {
|
addAttrs(attrs: ElemAttrs): void {
|
||||||
this.addAttr(name, value);
|
Object.entries(attrs).forEach(([key, value]) => this.addAttr(key, value));
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addAttr(name: string, value: unknown): void {
|
addAttr(name: string, value: unknown): void {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Renderer } from "./types.mjs";
|
import { Renderer } from "./types.mjs";
|
||||||
import { isBool, isNil, Nilable, Nullable } from "./lang.mjs";
|
import { isBool, isNil, isStr, Nilable, Nullable } from "./lang.mjs";
|
||||||
import { AnyNode, Elem, ElemAttrs, Frag, TextNode } from "./nodes.mjs";
|
import { AnyNode, Elem, ElemAttrs, Frag, TextNode } from "./nodes.mjs";
|
||||||
|
|
||||||
export class StrRenderer implements Renderer<string> {
|
export class StrRenderer implements Renderer<string> {
|
||||||
|
@ -9,11 +9,7 @@ export class StrRenderer implements Renderer<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
function encodeAnyNode(node: AnyNode): Nullable<string> {
|
function encodeAnyNode(node: AnyNode): Nullable<string> {
|
||||||
return !node
|
return !node ? null : isStr(node) ? encodeTextNode(node) : encodeNode(node);
|
||||||
? null
|
|
||||||
: node instanceof TextNode
|
|
||||||
? encodeTextNode(node)
|
|
||||||
: encodeNode(node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function encodeTextNode(node: TextNode): string {
|
function encodeTextNode(node: TextNode): string {
|
||||||
|
|
Reference in a new issue