UNPKG

marko

Version:

Optimized runtime for Marko templates.

297 lines (296 loc) • 14.8 kB
import { $ as _attr_style_items, $t as insertBranchBefore, A as _attr_input_value, An as Params, B as _controllable_select, Bn as Global, Bt as _hoist_resume, C as _attr_details_or_dialog_open_script, Cn as _assert_hoist, Ct as _resumed, D as _attr_input_checkedValue_script, Dn as Clone, Dt as initEmbedded, E as _attr_input_checkedValue_default, Et as init, F as _attr_select_value, Ft as _el_read, G as _attr_class, Gt as _or, Ht as _if_closure, I as _attr_select_value_default, It as _for_closure, J as _attr_class_names, Jn as TagVariable, Jt as _script, K as _attr_class_item, Kt as _return, L as _attr_select_value_script, Lt as _for_selector, M as _attr_input_value_default, Mn as Setup, Mt as _closure, N as _attr_input_value_dynamic_default, Nt as _closure_get, O as _attr_input_checked_default, On as Lazy, Ot as ready, P as _attr_input_value_script, Pt as _const, Q as _attr_style_item, Qt as destroyBranch, R as _controllable_input, Rn as EndNode, Rt as _global_read, S as _attr_details_or_dialog_open_default, Sn as _assert_class_toggles, St as _el, T as _attr_input_checkedValue, Tn as _call, Tt as getRegisteredWithScope, Ut as _let, V as _controllable_textarea, Vn as Load, Vt as _id, W as _attr, Wt as _let_change, X as _attr_nonce, Xt as _var_change, Y as _attr_content, Yt as _var, Z as _attr_style, Zt as _assert_init, _ as patchDynamicTag, _n as runId, _t as _return_setup, a as _for_in, an as $signal, at as _html, b as startAwait, bn as forTo, bt as setupBranch, c as _for_to, ct as _style_shell, d as _for_until_unkeyed, dn as queueAsyncRender, dt as _to_text, en as removeAndDestroyBranch, et as _attrs, f as _if, fn as queueEffect, ft as insertChildNodes, gn as runEffects, gt as _content_resume, hn as run, ht as _content_closures, i as _dynamic_tag_content, in as _on, it as _attrs_script, j as _attr_input_value_attribute_default, jt as _child_setup, k as _attr_input_checked_script, kn as Owner, kt as readyFailed, l as _for_to_unkeyed, lt as _text, m as _try, mn as rendering, mt as _content, n as _await_promise, nt as _attrs_partial, o as _for_of, on as $signalReset, ot as _lifecycle, p as _show, pn as queueRender, pt as toInsertNode, q as _attr_class_items, qn as StartNode, qt as _return_change, r as _dynamic_tag, rt as _attrs_partial_content, s as _for_of_unkeyed, st as _style_rule_item, t as _await_content, tn as syncGen, tt as _attrs_content, u as _for_until, un as prepareEffects, ut as _text_content, v as renderCatch, vn as forIn, vt as createAndSetupBranch, w as _attr_input_checked, wn as _hoist_read_error, wt as _var_resume, x as _attr_details_or_dialog_open, xn as forUntil, xt as _dynamic_tag_var_resume, yn as forOf, yt as createBranch, z as _controllable_open, zt as _hoist } from "./dom-o9jQjchF.mjs"; //#region src/common/attr-tag.ts const empty = []; const rest = Symbol("Attribute Tag"); function attrTag(attrs) { attrs[Symbol.iterator] = attrTagIterator; attrs[rest] = empty; return attrs; } function attrTags(first, attrs) { if (first) { if (first[rest] === empty) first[rest] = [attrs]; else first[rest].push(attrs); return first; } return attrTag(attrs); } function* attrTagIterator() { yield this; yield* this[rest]; } //#endregion //#region src/common/compat-meta.ts const SET_SCOPE_REGISTER_ID = "$compat_setScope"; const RENDER_BODY_ID = "$compat_renderBody"; //#endregion //#region src/dom/compat.ts const classIdToBranch = /* @__PURE__ */ new Map(); let classEventResolver; const scopesByRender = /* @__PURE__ */ new WeakMap(); const getRenderScopes = ($global) => { init($global.runtimeId); const render = self[$global.runtimeId]?.[$global.renderId]; let scopes = render && scopesByRender.get(render); if (render && !scopes) scopesByRender.set(render, scopes = {}); return scopes; }; const compat = { patchDynamicTag, queueEffect, init(warp10Noop) { _resumed[SET_SCOPE_REGISTER_ID] = (scope) => { getRenderScopes(scope[Global])[scope["#Id"]] = scope; if (scope.m5c) classIdToBranch.set(scope.m5c, scope); if (classEventResolver) for (const key in scope) { const resolved = classEventResolver(scope[key], scope); if (resolved !== scope[key]) scope[key] = resolved; } }; _resumed[RENDER_BODY_ID] = warp10Noop; }, setClassEventResolver(fn) { classEventResolver = fn; }, resumeClassFunction(id, build) { _resumed[id] = build; }, getScope($global, scopeId) { return getRenderScopes($global)?.[scopeId]; }, setRendererId(renderer, id) { renderer["id"] = id; }, isRenderer(renderer) { return renderer[Clone]; }, getStartNode(branch) { return branch[StartNode]; }, getEndNode(branch) { return branch[EndNode]; }, setScopeNodes(branch, startNode, endNode) { branch[StartNode] = startNode; branch[EndNode] = endNode; }, runComponentEffects() { if (this.effects) runEffects(this.effects); }, runComponentDestroy() { if (this.scope) destroyBranch(this.scope); }, resolveRegistered(value, $global) { if (Array.isArray(value) && typeof value[0] === "string") return getRegisteredWithScope(value[0], getRenderScopes($global)?.[value[1]]); return value; }, createRenderer(params, clone) { const renderer = _content("", 0, 0, 0, params)(); renderer[Clone] = (branch) => { const cloned = clone(); branch[StartNode] = cloned.startNode; branch[EndNode] = cloned.endNode; }; return renderer; }, render(out, component, renderer, args) { init(out.global.runtimeId); let branch = component.scope; let created = 0; if (!branch && (branch = classIdToBranch.get(component.id))) { component.scope = branch; classIdToBranch.delete(component.id); } if (args[0] && typeof args[0] === "object" && "renderBody" in args[0]) { const input = args[0]; const normalizedInput = args[0] = {}; for (const key in input) normalizedInput[key === "renderBody" ? "content" : key] = input[key]; } const renderBranch = () => { if (!branch) { created = 1; branch = component.scope = createAndSetupBranch(out.global, renderer, renderer[Owner], document.body); } renderer[Params]?.(branch, renderer._ ? args[0] : args); }; component.effects = rendering ? renderBranch() : prepareEffects(renderBranch); if (created) return toInsertNode(branch[StartNode], branch[EndNode]); } }; //#endregion //#region src/dom/template.ts const _template = (id, template, walks, setup, inputSignal) => { const renderer = _content(id, template, walks, setup, inputSignal)(); renderer.mount = mount; renderer._ = renderer; renderer.render = () => { throw new Error(`render() is not implemented for the DOM compilation of a Marko template`); }; return _resumed[id] = renderer; }; function mount(input = {}, reference, position) { let branch; let parentNode = reference; let nextSibling = null; let { $global } = input; if ($global) { ({$global, ...input} = input); $global = { runtimeId: "M", renderId: "_", ...$global }; if (!String($global.runtimeId).match(/^[_a-z][_a-z0-9]*$/i)) throw new Error(`Invalid runtimeId: "${$global.runtimeId}". The runtimeId must start with a letter or underscore and only contain letters, numbers, and underscores.`); if (!String($global.renderId).match(/^[_a-z][_a-z0-9]*$/i)) throw new Error(`Invalid renderId: "${$global.renderId}". The renderId must start with a letter or underscore and only contain letters, numbers, and underscores.`); } else $global = { runtimeId: "M", renderId: "_" }; switch (position) { case "beforebegin": parentNode = reference.parentNode; nextSibling = reference; break; case "afterbegin": nextSibling = reference.firstChild; break; case "afterend": parentNode = reference.parentNode; nextSibling = reference.nextSibling; } let curValue; const args = this[Params]; const effects = prepareEffects(() => { branch = createBranch($global, this, void 0, parentNode); branch[TagVariable] = (newValue) => { curValue = newValue; }; this[Setup]?.(branch); args?.(branch, input); }); insertChildNodes(parentNode, nextSibling, branch[StartNode], branch[EndNode]); runEffects(effects); return { get value() { return curValue; }, set value(newValue) { _var_change(branch, newValue); }, update(newInput = {}) { if (args) { if (newInput.$global) ({$global, ...newInput} = newInput); runEffects(prepareEffects(() => { args(branch, newInput); })); } }, destroy() { removeAndDestroyBranch(branch); } }; } //#endregion //#region src/dom/load.ts const noop = (_) => 0; function _load_template(id, load) { let pending; const lazyTemplate = _template(id, 0, 0, (branch) => { const awaitCounter = startAwait(branch); branch[Load] ||= /* @__PURE__ */ new Map(); (pending ||= load()).then((renderer) => { Object.assign(lazyTemplate, renderer); queueAsyncRender(branch, (branch) => insertLoaded(renderer, branch, branch[StartNode], awaitCounter)); }, loadFailed(branch, awaitCounter)); }, _load_signal(() => (pending ||= load()).then((r) => ({ _: r["params"] || noop })))); lazyTemplate[Lazy] = 1; return lazyTemplate; } function _load_setup(load) { let pending; let renderer; const insertCached = (child, marker) => insertLoaded(renderer, child, marker); return (owner, child, marker) => { if (renderer) queueRender(child, insertCached, -1, marker); else { const awaitCounter = startAwait(owner); child[Load] ||= /* @__PURE__ */ new Map(); (pending ||= load()).then((mod) => { renderer ||= _content("", ...mod._)(); queueAsyncRender(child, (child) => insertLoaded(renderer, child, marker, awaitCounter)); }, loadFailed(child, awaitCounter)); } }; } function insertLoaded(renderer, branch, marker, awaitCounter) { const parent = () => marker.parentNode, values = branch[Load], clone = () => { syncGen(branch); renderer[Clone](branch, parent().namespaceURI); branch[Load] = 0; }, insert = () => { insertBranchBefore(branch, parent(), marker); marker.remove(); awaitCounter?.c(); }; let remaining; if (remaining = values?.size) { awaitCounter ||= startAwait(branch); const fail = loadFailed(branch, awaitCounter); values.forEach(([, apply], promise) => promise.then((mod) => (apply._ = mod._) && !--remaining && queueAsyncRender(branch, (branch) => { clone(); renderer["setup"]?.(branch); values.forEach(([value, apply]) => apply(branch, value)); insert(); }), (error) => remaining > 0 && (remaining = 0, fail(error)))); } else { clone(); setupBranch(renderer, branch); insert(); } } function loadFailed(scope, awaitCounter) { return (error) => { if (awaitCounter) { if (awaitCounter.m) awaitCounter.i = 0; else if (awaitCounter.i) awaitCounter.c(); } queueAsyncRender(scope, renderCatch, error); }; } function _load_signal(load) { let pending; const apply = (scope, value) => { pending ||= load(); if (scope["#Load"] || !("#Load" in scope) && scope["#Gen"] === runId) (scope[Load] ||= /* @__PURE__ */ new Map()).set(pending, [value, apply]); else if (apply._) apply._(scope, value); else pending.then((mod) => queueAsyncRender(scope, apply._ = mod._, value), noop); }; return apply; } function _load_visible_trigger(selector, options) { let pending; let el; return (load) => () => (pending ||= new Promise((resolve) => (el = getSelectorOrResolve(selector, resolve)) && new IntersectionObserver((entries, io) => entries.some((entry) => entry.isIntersecting) && resolve(io.disconnect()), options).observe(el))).then(load); } function _load_idle_trigger(options) { let pending; return (load) => () => (pending ||= new Promise((resolve) => (self.requestIdleCallback || resolve)(resolve, options))).then(load); } function _load_event_trigger(event, selector) { let pending; return (load) => () => (pending ||= new Promise((resolve) => getSelectorOrResolve(selector, resolve)?.addEventListener(event, resolve, { once: true }))).then(load); } function _load_media_trigger(query) { let pending; let mql; return (load) => () => (pending ||= new Promise((resolve) => (mql = matchMedia(query)).matches ? resolve() : mql.addEventListener("change", resolve, { once: true }))).then(load); } function _load_race_trigger(...triggers) { let pending; return (load) => () => (pending ||= Promise.race(triggers.map((t) => t(noop)()))).then(load); } function getSelectorOrResolve(selector, resolve) { return document.querySelector(selector) || (console.warn(`A lazy load trigger could not find an element matching "${selector}". The module was loaded immediately.`), resolve()); } //#endregion export { $signal, $signalReset, _assert_class_toggles, _assert_hoist, _assert_init, _attr, _attr_class, _attr_class_item, _attr_class_items, _attr_class_names, _attr_content, _attr_details_or_dialog_open as _attr_details_open, _attr_details_or_dialog_open as _attr_dialog_open, _attr_details_or_dialog_open_default as _attr_details_open_default, _attr_details_or_dialog_open_default as _attr_dialog_open_default, _attr_details_or_dialog_open_script as _attr_details_open_script, _attr_details_or_dialog_open_script as _attr_dialog_open_script, _attr_input_checked, _attr_input_checkedValue, _attr_input_checkedValue_default, _attr_input_checkedValue_script, _attr_input_checked_default, _attr_input_checked_script, _attr_input_value, _attr_input_value as _attr_textarea_value, _attr_input_value_attribute_default, _attr_input_value_default, _attr_input_value_default as _attr_textarea_value_default, _attr_input_value_dynamic_default, _attr_input_value_script, _attr_input_value_script as _attr_textarea_value_script, _attr_nonce, _attr_select_value, _attr_select_value_default, _attr_select_value_script, _attr_style, _attr_style_item, _attr_style_items, _attrs, _attrs_content, _attrs_partial, _attrs_partial_content, _attrs_script, _await_content, _await_promise, _call, _child_setup, _closure, _closure_get, _const, _content, _content_closures, _content_resume, _controllable_input, _controllable_open, _controllable_select, _controllable_textarea, _dynamic_tag, _dynamic_tag_content, _dynamic_tag_var_resume, _el, _el_read, _for_closure, _for_in, _for_of, _for_of_unkeyed, _for_selector, _for_to, _for_to_unkeyed, _for_until, _for_until_unkeyed, _global_read, _hoist, _hoist_read_error, _hoist_resume, _html, _id, _if, _if_closure, _let, _let_change, _lifecycle, _load_event_trigger, _load_idle_trigger, _load_media_trigger, _load_race_trigger, _load_setup, _load_signal, _load_template, _load_visible_trigger, _on, _or, _resumed, _return, _return_change, _return_setup, _script, _show, _style_rule_item, _style_shell, _template, _text, _text_content, _to_text, _try, _var, _var_change, _var_resume, attrTag, attrTags, compat, forIn, forOf, forTo, forUntil, init, initEmbedded, ready, readyFailed, run };