This repository has been archived by the owner on Mar 27, 2022. It is now read-only.
forked from idletea/jsx-no-react
-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathmodule.js
131 lines (103 loc) · 3.34 KB
/
module.js
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import './polyfills';
function appendChild(elem, children) {
if (!children || children === undefined) return;
if (children instanceof Array) {
children.map(child => appendChild(elem, child));
return;
}
let child = children;
if (!(child instanceof Node)) {
child = document.createTextNode(child.toString());
}
elem.appendChild(child);
}
function splitCamelCase(str) {
return str.replace(/([a-z0-9])([A-Z])/g, "$1-$2").toLowerCase();
}
function createElement(elem, attrs) {
if (typeof elem.render === "function") {
return elem.render();
}
if (elem instanceof Function) {
return elem(attrs);
}
if (elem instanceof HTMLElement) {
addAttributes(elem, attrs);
return elem;
}
const element = document.createElement(elem);
addAttributes(element, attrs);
return element;
}
export function renderBefore(elem, parent) {
if (elem.constructor === DocumentFragment)
throw new Error("renderBefore does not support top-level fragment rendering");
parent.insertAdjacentElement("beforebegin", elem);
}
export function renderPrepend(elem, parent) {
const parentFirstChild = parent.children ? parent.children[0] : null;
parent.insertBefore(elem, parentFirstChild);
}
export function render(elem, parent) {
parent.innerHTML = "";
parent.appendChild(elem);
}
export function renderAppend(elem, parent) {
parent.appendChild(elem);
}
export function renderAfter(elem, parent) {
if (elem.constructor === DocumentFragment)
throw new Error("renderAfter does not support top-level fragment rendering");
parent.insertAdjacentElement("afterend", elem);
}
function addAttributes(elem, attrs) {
if (attrs === null || attrs === undefined) attrs = {};
for (let [attr, value] of Object.entries(attrs)) {
if (value === true) elem.setAttribute(attr, attr);
else if (attr.startsWith("on") && typeof value === "function") {
elem.addEventListener(attr.substr(2).toLowerCase(), value);
} else if (value !== false && value !== null && value !== undefined) {
if (value instanceof Object) {
const modifier =
attr === "style" ? splitCamelCase : str => str.toLowerCase();
value = Object.entries(value)
.map(([key, val]) => `${modifier(key)}: ${val}`)
.join("; ");
}
if (attr === "className" && value !== "")
elem.classList.add(
...value
.toString()
.trim()
.split(" ")
);
else elem.setAttribute(attr, value.toString());
}
}
}
const createAndAppendSVG = (tag, attrs, ...children) => {
const element = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
addAttributes(element, attrs);
for (const child of children) {
const childElement = document.createElementNS('http://www.w3.org/2000/svg', child.nodeName.toLowerCase())
for (const attribute of child.attributes) {
childElement.setAttributeNS(null, attribute.nodeName, attribute.nodeValue);
}
appendChild(element, childElement);
}
return element;
}
function converter(tag, attrs, ...children) {
if (tag === "svg") {
return createAndAppendSVG(tag, attrs, ...children);
}
const elem = createElement(tag, attrs);
for (const child of children) {
appendChild(elem, child);
}
return elem;
}
export default {
Fragment: () => new DocumentFragment(),
createElement: converter
}