UNPKG

ivi

Version:

Lightweight Embeddable Web UI Library.

145 lines 5.18 kB
import { _hN, _hE, _sN, _sE, _T, _t } from "../lib/core.js"; import { TemplateNodeType, compileTemplate } from "../template/compiler.js"; import { TEMPLATE_TYPE_HTM, TEMPLATE_TYPE_SVG } from "../template/ir.js"; import { TemplateParserError, formatError } from "../template/parser.js"; import { parseTemplate } from "./parser.js"; const DESCRIPTORS = new WeakMap(); /** * Creates template with HTML Elements. * * ### Element Syntax: * * - `<div name="value" />` - Static Attribute. * - `<div name />` - Static Attribute. * - `<div name=${expr} />` - Dynamic attribute `element.setAttribute(name, expr)`. * - `<div .name=${expr} />` - Property `element[name] = expr`. * - `<div *name=${expr} />` - Property `element[name] = expr`, diffs against a DOM value. * - `<div ~name="value" />` - Static style `<div style="name:value;">` * - `<div ~name=${expr} />` - Dynamic style `element.style.setProperty(name, expr)` * - `<div @name=${expr} />` - Event `element.addEventListener(name, expr)` * - `<div ${directive} />` - Client-Side Directive `directive(element)` * * @example * * function MyApp(content) { * return html` * <div id="App"> * <h1 class="Title">MyApp</h1> * <div>Content ${content}</div> * </div> * `; * } */ export const html = (strings, ...exprs) => { let fn = DESCRIPTORS.get(strings); if (fn === void 0) { let result; try { const tpl = parseTemplate(strings, TEMPLATE_TYPE_HTM); result = compileTemplate(tpl); } catch (e) { if (e instanceof TemplateParserError) { throw Error("Invalid template" + formatError(strings, e.message, e.staticsOffset, e.textOffset)); } throw e; } const roots = result.roots; if (roots.length === 1) { const root = prepareRootNode(roots[0], _hE, _hN); fn = (exprs) => createRootNode(root, exprs); } else { const entries = roots.map((root) => prepareRootNode(root, _hE, _hN)); fn = (exprs) => entries.map((root) => createRootNode(root, exprs)); } DESCRIPTORS.set(strings, fn); } return fn(exprs); }; /** * Creates template with SVG Elements. * * ### Element Syntax: * * - `<div name="value" />` - Static Attribute. * - `<div name />` - Static Attribute. * - `<div name=${expr} />` - Dynamic attribute `element.setAttribute(name, expr)`. * - `<div .name=${expr} />` - Property `element[name] = expr`. * - `<div *name=${expr} />` - Property `element[name] = expr`, diffs against a DOM value. * - `<div ~name="value" />` - Static style `<div style="name:value;">` * - `<div ~name=${expr} />` - Dynamic style `element.style.setProperty(name, expr)` * - `<div @name=${expr} />` - Event `element.addEventListener(name, expr)` * - `<div ${directive} />` - Client-Side Directive `directive(element)` * * @example * * function Star(content) { * return svg` * <svg height="210" width="500"> * <polygon * points="100,10 40,198 190,78 10,78 160,198" * ~fill="lime" * ~stroke="purple" * ~stroke-width="5" * ~fill-rule="nonzero" * /> * </svg> * `; * } */ export const svg = (strings, ...exprs) => { let fn = DESCRIPTORS.get(strings); if (fn === void 0) { let result; try { const tpl = parseTemplate(strings, TEMPLATE_TYPE_SVG); result = compileTemplate(tpl); } catch (e) { if (e instanceof TemplateParserError) { throw Error("Invalid template" + formatError(strings, e.message, e.staticsOffset, e.textOffset)); } throw e; } const roots = result.roots; if (roots.length === 1) { const root = prepareRootNode(roots[0], _sE, _sN); fn = (exprs) => createRootNode(root, exprs); } else { const entries = roots.map((root) => prepareRootNode(root, _hE, _hN)); fn = (exprs) => entries.map((root) => createRootNode(root, exprs)); } DESCRIPTORS.set(strings, fn); } return fn(exprs); }; const prepareRootNode = (root, createElement, cloneTemplate) => { switch (root.type) { case TemplateNodeType.Block: const template = root.template; return { map: root.exprs, descriptor: _T((typeof template === "string") ? createElement(template) : cloneTemplate(template.join("")), root.flags, root.props, root.child, root.state, root.data), }; case TemplateNodeType.Text: return root.value; case TemplateNodeType.Expr: return root.value; } }; const createRootNode = (e, exprs) => { if (typeof e === "object") { return _t(e.descriptor, e.map.map((i) => exprs[i])); } if (typeof e === "number") { return exprs[e]; } return e; }; //# sourceMappingURL=index.js.map