UNPKG

edgerender

Version:
235 lines 7.07 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.JsxChunk = exports.raw_html = exports.RawHtml = exports.CustomTag = exports.render_jsx = exports.Fragment = void 0; const utils_1 = require("./utils"); const styles_1 = require("./utils/styles"); const escape_1 = __importDefault(require("./utils/escape")); class Fragment { } exports.Fragment = Fragment; async function render_jsx(jsx_element) { const jsx_obj = await Promise.resolve(jsx_element); return await jsx_obj.render(); } exports.render_jsx = render_jsx; const CustomTag = ({ _tag, key, ...props }) => { return new JsxChunk(_tag, key, props); }; exports.CustomTag = CustomTag; class RawHtml { html; constructor(html) { this.html = html; } } exports.RawHtml = RawHtml; const raw_html = (html) => new RawHtml(html); exports.raw_html = raw_html; const EmptyTags = new Set([ 'area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr', ]); class JsxChunk { el; key; args; props; children; constructor(el, key = null, args) { this.el = el; this.key = key; this.args = args; const { children, ...props } = args; this.props = props; if (Array.isArray(children)) { this.children = children; } else if (typeof children == 'undefined') { this.children = []; } else { this.children = [children]; } } async render() { const { el } = this; if (typeof el == 'string') { if (el == 'html') { return '<!doctype html>\n' + (await this.render_element(el)); } else { return await this.render_element(el); } } else if (el == Fragment) { return await this.render_children(); } else { const f = el; const jsx_chunk = await Promise.resolve(f(this.args)); return await jsx_chunk.render(); } } async render_element(el) { let attrs = ''; for (const [key, value] of Object.entries(this.props)) { attrs += render_attr(key, value); } if (EmptyTags.has(el)) { // TODO error if children exist? return `<${el}${attrs}>`; } else { const children = await this.render_children(); return `<${el}${attrs}>${children}</${el}>`; } } async render_children() { return await cat_array(this.children); } toString() { return `JsxElement(${this.el}, ${JSON.stringify(this.args)})`; } } exports.JsxChunk = JsxChunk; function render_attr(name, value) { let attr_value = null; const value_type = utils_1.smart_typeof(value); if (value_type == "Null" /* Null */ || value_type == "Undefined" /* Undefined */) { attr_value = null; } else if (name == 'style') { attr_value = styles_1.render_styles(value); } else if (name == 'className') { attr_value = render_class(value, value_type); } else if (name == 'data' && value_type == "Object" /* Object */) { return render_data(value); } else if (value_type == "Boolean" /* Boolean */) { if (name.startsWith('hx')) { // things like hx-boost want the literal value "true" or "false" attr_value = value ? 'true' : 'false'; } else if (value === true) { return ` ${get_tag_name(name)}`; } else { attr_value = null; } } else { attr_value = render_attr_value(value, value_type); } if (attr_value === null) { return ''; } else { const quote = attr_value.includes('"') ? "'" : '"'; return ` ${get_tag_name(name)}=${quote}${attr_value}${quote}`; } } function render_attr_value(value, value_type) { switch (value_type) { case "String" /* String */: return escape_1.default.attr_double(value); case "RawHtml" /* RawHtml */: return value.html; default: return escape_1.default.attr_single(JSON.stringify(value)); } } function get_tag_name(name) { if (name == 'className') { return 'class'; } else if (name == 'htmlFor') { return 'for'; } else if (name.startsWith('hx')) { return styles_1.hyphenate(name); } else { return name.toLowerCase(); } } async function render_child(child) { switch (utils_1.smart_typeof(child)) { case "String" /* String */: return escape_1.default.content(child); case "JsxChunk" /* JsxChunk */: return await child.render(); case "Array" /* Array */: return await cat_array(child); case "RawHtml" /* RawHtml */: return child.html; case "Null" /* Null */: case "Undefined" /* Undefined */: return ''; case "Number" /* Number */: return child.toString(); case "Function" /* Function */: return await render_child(child()); case "Promise" /* Promise */: return await render_child((await child)); case "RegExp" /* RegExp */: return escape_1.default.content(child.toString()); default: return escape_1.default.content(JSON.stringify(child)); } } async function cat_array(child) { const results = await Promise.all(child.map(item => render_child(item))); return results.join(''); } function render_class(value, value_type) { const classNames = []; switch (value_type) { case "String" /* String */: return value; case "Array" /* Array */: for (const className of value) { if (typeof className == 'string') { classNames.push(className); } } break; case "Object" /* Object */: for (const [className, v] of Object.entries(value)) { if (v) { classNames.push(className); } } break; default: throw new TypeError(`unexpected type passed to className: "${value_type}", should be string, list or object`); } return classNames.join(' '); } function render_data(data) { let result = ''; for (const [key, value] of Object.entries(data)) { const clean_name = key.replace(/[^\w-]/g, ''); const attr_value = render_attr_value(value, utils_1.smart_typeof(value)); const quote = attr_value.includes('"') ? "'" : '"'; result += ` data-${clean_name}=${quote}${attr_value}${quote}`; } return result; } //# sourceMappingURL=jsx.js.map