1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
export type component<
T extends Attribute = Attribute,
U extends node[] = node[],
R extends node = node
> = ((attr: T, ...content: U) => R)
export interface Attribute {
[key: string]: unknown,
}
export interface element<T extends string = string> {
name: T,
attr: Attribute,
content: node[],
}
export function iselement<T extends string = string>(e: unknown): e is element<T> {
return typeof e === "object" && e !== null && "name" in e;
}
export interface typed_data<T extends string = string> {
content: string,
type: T
}
export function istyped<T extends string = string>(e: unknown): e is typed_data<T> {
return typeof e === "object" && e !== null && "type" in e;
}
export type node = element | typed_data | node[] | string
export function c<
T extends Attribute = Attribute,
U extends node[] = node[],
R extends node = node
>(name: component<T, U, R>, attr: T, ...content: U): R {
return name(attr, ...content)
}
export default function t<T extends string = string>(name: T, attr?: Attribute, ...content: node[]): element<T> {
return {
name,
attr: attr ?? ({} as Attribute),
content
}
}
export function frag<T extends node[] = node[]>(_attr: Attribute, ...content: T) {
return content
}
export function join({sep = ""}: Attribute & {sep?: string}, ...content: string[]) {
return content.join(sep)
}
export function prenderdata<T extends string = string>(type: T) {
return function (content: string): typed_data<T> {
return {
content,
type
}
}
}
export function render<T extends string = string>(type: T, rendFunc: (node: element, content: string) => string) {
const data = prenderdata(type)
return function rend(Node: node): typed_data<T> {
if (Array.isArray(Node)) {
return data(Node.map(element => rend(element).content ?? "").join(""))
}
if (typeof Node == "string") {
return data(Node)
}
if (iselement(Node)) {
return data(rendFunc(Node, rend(Node.content).content))
}
if (istyped<T>(Node)) {
if (Node.type == type) {
return Node
} else {
throw new Error(Node.type + "is not valid. The type must be:" + type)
}
}
throw new TypeError("" + Node)
}
}
export function getText(node: node): string {
if (Array.isArray(node)) {
return node.map(element => getText(element) ?? "").join("")
}
if (typeof node == "string") {
return node
}
if (iselement(node)) {
return getText(node.content)
}
throw new TypeError("" + node)
}
|