This repository was archived by the owner on Oct 6, 2026. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathtag.js
More file actions
72 lines (69 loc) · 2.72 KB
/
Copy pathtag.js
File metadata and controls
72 lines (69 loc) · 2.72 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
/**
* HTML Tag Scripting Function
*
* Generates new DOM element(s) from a tag, attributes
*
* @param {String} tag - tag name
* @param {Object} props - tag attributes
* @param {Object|String|Array} args - text or array of child elements
*
* @returns {HTMLElement} The created DOM element(s)
*/
export function h(tagName, props, ...children) {
const el = tagName === DocumentFragment ? document.createDocumentFragment() : document.createElement(tagName);
const isScalar = (value) => typeof value === 'string' || typeof value === 'number';
const booleanAttrs = ['disabled', 'checked', 'selected', 'hidden', 'readonly', 'required', 'open', 'autoplay', 'loop', 'muted'];
// Handle props (object or null)
if (props != null && typeof props === 'object' && !Array.isArray(props)) {
for (const [key, value] of Object.entries(props)) {
if (value == null) continue;
if (booleanAttrs.includes(key)) {
if (value === true) {
el.setAttribute(key, '');
el[key] = true;
} else if (value === false) {
el.removeAttribute(key);
el[key] = false;
}
continue;
}
if (key.startsWith('on') && typeof value === 'function') {
el.addEventListener(key.slice(2).toLowerCase(), value);
continue;
}
if (key === 'class') {
el.className = value;
continue;
}
if (key === 'style' && typeof value === 'object') {
Object.assign(el.style, value);
continue;
}
el.setAttribute(key, value);
if (key in el) {
el[key] = value;
}
}
} else if (props != null) {
// If props is not an object, treat it as a child
children.unshift(props);
}
// Handle children
for (const child of children) {
if (child == null) continue;
if (isScalar(child)) {
el.appendChild(document.createTextNode(child));
} else if (Array.isArray(child)) {
const fragment = document.createDocumentFragment();
fragment.append(...child.filter(c => c != null));
el.appendChild(fragment);
} else if (child instanceof Node) {
el.appendChild(child);
} else if (typeof child === 'boolean') {
console.warn(`Boolean child ${child} passed to h() for tag "${tagName}". Booleans are not rendered.`);
} else {
console.error(`Unsupported child type: ${typeof child} for tag "${tagName}" in h() function`);
}
}
return el;
}