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 Nil = null | undefined;
|
||||
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) {
|
||||
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";
|
||||
export declare type AnyNode = TextNode | Elem | Frag | Nil | false;
|
||||
export declare class TextNode extends String {
|
||||
}
|
||||
export declare function Et(tagName: string, ...texts: string[]): Elem;
|
||||
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 type AnyNode = TextNode | Elem | Frag | Nil | false;
|
||||
export declare type TextNode = string;
|
||||
export declare class Frag {
|
||||
#private;
|
||||
constructor();
|
||||
get children(): Nilable<AnyNode[]>;
|
||||
withText(text: string): this;
|
||||
addText(text: string): void;
|
||||
withChildren(...nodes: AnyNode[]): this;
|
||||
withText(texts: TextNode | TextNode[]): this;
|
||||
addText(texts: TextNode | TextNode[]): void;
|
||||
withChildren(nodes: AnyNode | AnyNode[]): this;
|
||||
addChildren(nodes: AnyNode | 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 class Elem extends Frag {
|
||||
#private;
|
||||
constructor(tagName: string);
|
||||
get tagName(): string;
|
||||
get attrs(): Record<string, unknown>;
|
||||
withAttrs(attrs: Record<string, unknown>): Elem;
|
||||
withAttr(name: string, value: unknown): Elem;
|
||||
withAttrs(attrs: ElemAttrs): Elem;
|
||||
addAttrs(attrs: ElemAttrs): void;
|
||||
addAttr(name: string, value: unknown): void;
|
||||
addChild(node: AnyNode): void;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,20 @@
|
|||
import { isNil } from "./lang.mjs";
|
||||
export class TextNode extends String {
|
||||
import { intoArr, isNil } from "./lang.mjs";
|
||||
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) {
|
||||
return new Frag().withChildren(...children);
|
||||
return new Frag().withChildren(children);
|
||||
}
|
||||
export class Frag {
|
||||
#children;
|
||||
|
@ -12,26 +24,28 @@ export class Frag {
|
|||
get children() {
|
||||
return this.#children;
|
||||
}
|
||||
withText(text) {
|
||||
this.addText(text);
|
||||
withText(texts) {
|
||||
this.addText(texts);
|
||||
return this;
|
||||
}
|
||||
addText(text) {
|
||||
this.addChild(new TextNode(text));
|
||||
addText(texts) {
|
||||
this.addChildren(intoArr(texts)
|
||||
.map((t) => t.trim())
|
||||
.join(" "));
|
||||
}
|
||||
withChildren(...nodes) {
|
||||
nodes.forEach((n) => this.addChild(n));
|
||||
withChildren(nodes) {
|
||||
this.addChildren(nodes);
|
||||
return this;
|
||||
}
|
||||
addChildren(nodes) {
|
||||
intoArr(nodes).forEach((n) => this.addChild(n));
|
||||
}
|
||||
addChild(node) {
|
||||
if (isNil(this.#children))
|
||||
this.#children = [];
|
||||
this.#children.push(node);
|
||||
}
|
||||
}
|
||||
export function E(tagName, attrs, ...children) {
|
||||
return new Elem(tagName).withAttrs(attrs).withChildren(...children);
|
||||
}
|
||||
export class Elem extends Frag {
|
||||
#tagName;
|
||||
#attrs;
|
||||
|
@ -49,12 +63,11 @@ export class Elem extends Frag {
|
|||
return this.#attrs;
|
||||
}
|
||||
withAttrs(attrs) {
|
||||
Object.entries(attrs).forEach(([key, value]) => this.addAttr(key, value));
|
||||
this.addAttrs(attrs);
|
||||
return this;
|
||||
}
|
||||
withAttr(name, value) {
|
||||
this.addAttr(name, value);
|
||||
return this;
|
||||
addAttrs(attrs) {
|
||||
Object.entries(attrs).forEach(([key, value]) => this.addAttr(key, value));
|
||||
}
|
||||
addAttr(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 { Elem, TextNode } from "./nodes.mjs";
|
||||
import { isBool, isNil, isStr } from "./lang.mjs";
|
||||
import { Elem } from "./nodes.mjs";
|
||||
export class StrRenderer {
|
||||
render(node) {
|
||||
return encodeNode(node);
|
||||
}
|
||||
}
|
||||
function encodeAnyNode(node) {
|
||||
return !node
|
||||
? null
|
||||
: node instanceof TextNode
|
||||
? encodeTextNode(node)
|
||||
: encodeNode(node);
|
||||
return !node ? null : isStr(node) ? encodeTextNode(node) : encodeNode(node);
|
||||
}
|
||||
function encodeTextNode(node) {
|
||||
return String(node);
|
||||
|
|
|
@ -11,3 +11,11 @@ export type Nil = null | undefined;
|
|||
export function isBool(v: unknown): v is 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 {
|
||||
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 {
|
||||
#children: Nilable<AnyNode[]>;
|
||||
|
||||
|
@ -19,34 +37,34 @@ export class Frag {
|
|||
return this.#children;
|
||||
}
|
||||
|
||||
withText(text: string): this {
|
||||
this.addText(text);
|
||||
withText(texts: TextNode | TextNode[]): this {
|
||||
this.addText(texts);
|
||||
return this;
|
||||
}
|
||||
|
||||
addText(text: string): void {
|
||||
this.addChild(new TextNode(text));
|
||||
addText(texts: TextNode | TextNode[]): void {
|
||||
this.addChildren(
|
||||
intoArr(texts)
|
||||
.map((t) => t.trim())
|
||||
.join(" ")
|
||||
);
|
||||
}
|
||||
|
||||
withChildren(...nodes: AnyNode[]): this {
|
||||
nodes.forEach((n) => this.addChild(n));
|
||||
withChildren(nodes: AnyNode | AnyNode[]): this {
|
||||
this.addChildren(nodes);
|
||||
return this;
|
||||
}
|
||||
|
||||
addChildren(nodes: AnyNode | AnyNode[]): void {
|
||||
intoArr(nodes).forEach((n) => this.addChild(n));
|
||||
}
|
||||
|
||||
addChild(node: AnyNode): void {
|
||||
if (isNil(this.#children)) this.#children = [];
|
||||
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 class Elem extends Frag {
|
||||
|
@ -69,14 +87,13 @@ export class Elem extends Frag {
|
|||
return this.#attrs;
|
||||
}
|
||||
|
||||
withAttrs(attrs: Record<string, unknown>): Elem {
|
||||
Object.entries(attrs).forEach(([key, value]) => this.addAttr(key, value));
|
||||
withAttrs(attrs: ElemAttrs): Elem {
|
||||
this.addAttrs(attrs);
|
||||
return this;
|
||||
}
|
||||
|
||||
withAttr(name: string, value: unknown): Elem {
|
||||
this.addAttr(name, value);
|
||||
return this;
|
||||
addAttrs(attrs: ElemAttrs): void {
|
||||
Object.entries(attrs).forEach(([key, value]) => this.addAttr(key, value));
|
||||
}
|
||||
|
||||
addAttr(name: string, value: unknown): void {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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";
|
||||
|
||||
export class StrRenderer implements Renderer<string> {
|
||||
|
@ -9,11 +9,7 @@ export class StrRenderer implements Renderer<string> {
|
|||
}
|
||||
|
||||
function encodeAnyNode(node: AnyNode): Nullable<string> {
|
||||
return !node
|
||||
? null
|
||||
: node instanceof TextNode
|
||||
? encodeTextNode(node)
|
||||
: encodeNode(node);
|
||||
return !node ? null : isStr(node) ? encodeTextNode(node) : encodeNode(node);
|
||||
}
|
||||
|
||||
function encodeTextNode(node: TextNode): string {
|
||||
|
|
Reference in a new issue