-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjsx-runtime.ts
More file actions
80 lines (66 loc) · 2.49 KB
/
jsx-runtime.ts
File metadata and controls
80 lines (66 loc) · 2.49 KB
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
export const JSXRuntime = {
factory(type: string | JSX.Component, props: Record<string, any> | null, ...children: JSX.RawChildren[]): JSX.Element {
if(typeof type !== "string") {
return type({ children, ...props });
}
const element = document.createElement(type);
for(let key in props) {
let isSet = false;
for (const plugin of PropPlugins) {
if(plugin.filter(key)) {
plugin.assign(element, key, props[key]);
isSet = true;
break;
}
}
if(isSet) continue;
element.setAttribute(key, props[key]);
}
element.append(...JSXRuntime.buildChildren(children));
return element;
},
fragment({ children }: JSX.Properties): DocumentFragment {
const fragment = document.createDocumentFragment();
fragment.append(...JSXRuntime.buildChildren(children));
return fragment;
},
fragmentFactory(props: JSX.Properties): DocumentFragment {
console.warn("DEPRECATED: 'JSXRuntime.fragmentFactory' is deprecated. Use 'JSXRuntime.fragment' instead.");
return JSXRuntime.fragment(props);
},
buildChildren(children: JSX.RawChildren): JSX.HTMLAppendableList {
const flatChildren = JSXRuntime.flatten(children);
return flatChildren.map(child => (
child instanceof Node ? child :
typeof child === "boolean" ? undefined :
child === null ? undefined :
typeof child === "undefined" ? undefined :
child.toString()
)).filter(node => typeof node !== "undefined");
},
flatten(children: JSX.RawChildren): JSX.ChildArray {
return (children instanceof Array ? children : [children]).flat(Infinity);
}
}
const PropPlugins: JSXPropertyPlugin[] = [
{
filter: key => /^on:[A-z]+$/.test(key),
assign(element, key, value) {
element.addEventListener(key.match(/^on:([A-z]+)$/)?.[1] as string, value);
}
},
{
filter: key => key === "style",
assign(element, _key, value) {
for(let prop in value) {
element.style[
prop as keyof Omit<CSSStyleDeclaration, "length" | "parentRule">
] = value[prop];
}
},
}
]
declare interface JSXPropertyPlugin {
filter: (key: string) => boolean;
assign: (element: JSX.Element, key: string, value: any) => void;
}