Framework-free JSX syntax in pure JS using HTM and native DOM creation.
Este script no debería instalarse directamente. Es una biblioteca que utilizan otros scripts mediante la meta-directiva de inclusión // @require https://update.greasyfork.org/scripts/591770/1905406/Vanilla%20HTM.js
// ==UserScript== // @name Vanilla HTM // @namespace Violentmonkey Scripts // @version 1.0.0 // @require https://cdn.jsdelivr.net/npm/[email protected]/mini/index.umd.js // @grant none // @author Paesss // @description Framework-free JSX syntax in pure JS using HTM and native DOM creation. // ==/UserScript== (function (global) { "use strict"; const SVG_NS = "http://www.w3.org/2000/svg"; // Standard SVG tags requiring the SVG namespace const SVG_TAGS = new Set([ "svg", "path", "circle", "rect", "line", "polyline", "polygon", "ellipse", "g", "use", "text", "tspan", "symbol", "defs", "clipPath", "mask", "pattern", "marker", "foreignObject", ]); /** * Appends dynamic children into a parent DOM container */ function appendChildren(parent, children) { for (let i = 0; i < children.length; i++) { const child = children[i]; if (child == null || child === false || child === true) { continue; } if (Array.isArray(child)) { appendChildren(parent, child); } else if (child instanceof Node) { parent.appendChild(child); } else { parent.appendChild(document.createTextNode(String(child))); } } } /** * Enhanced Hyperscript factory function */ function h(tag, props, ...children) { // 1. Functional Components if (typeof tag === "function") { const normalizedProps = Object.assign({}, props); normalizedProps.children = children.length === 1 ? children[0] : children; return tag(normalizedProps); } // 2. Document Fragments (<>...</>) if (!tag) { const fragment = document.createDocumentFragment(); appendChildren(fragment, children); return fragment; } // 3. Namespace Resolution (SVG Support) const isSvg = typeof tag === "string" && SVG_TAGS.has(tag); const el = isSvg ? document.createElementNS(SVG_NS, tag) : document.createElement(tag); // 4. Property & Attribute Binding if (props) { for (let key in props) { const val = props[key]; if (val === undefined || val === null) continue; // Ref Callback / Object if (key === "ref") { if (typeof val === "function") val(el); else if (val && typeof val === "object") val.current = el; continue; } // Forced Property Set (.value, .checked, etc.) if (key.charCodeAt(0) === 46 /* '.' */) { el[key.slice(1)] = val; continue; } // Event Listeners (e.g. onClick, onInput) if ( key.charCodeAt(0) === 111 /* 'o' */ && key.charCodeAt(1) === 110 /* 'n' */ ) { const eventName = key.slice(2).toLowerCase(); el.addEventListener(eventName, val); continue; } // Attribute Normalization let attrName = key; if (key === "className") attrName = "class"; else if (key === "htmlFor") attrName = "for"; // Style Props (Object or String) if (key === "style") { if (typeof val === "object" && val !== null) { Object.assign(el.style, val); } else { el.style.cssText = String(val); } continue; } // Dataset Attributes if (key === "dataset" && typeof val === "object") { Object.assign(el.dataset, val); continue; } // Boolean Attributes if (typeof val === "boolean") { if (val) { el.setAttribute(attrName, ""); if (attrName in el) el[attrName] = true; } else { el.removeAttribute(attrName); if (attrName in el) el[attrName] = false; } continue; } // Standard Properties vs Attributes if ( attrName in el && !isSvg && attrName !== "list" && attrName !== "form" ) { try { el[attrName] = val; } catch { el.setAttribute(attrName, String(val)); } } else { el.setAttribute(attrName, String(val)); } } } // 5. Append Children appendChildren(el, children); return el; } // Bind HTM to the hyperscript factory on the global scope global.html = typeof htm !== "undefined" ? htm.bind(h) : null; })( // Universal Global Scope Resolution typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof self !== "undefined" ? self : this || {} );