UNPKG

marko

Version:

UI Components + streaming, async, high performance, HTML templating for Node.js and the browser.

182 lines (162 loc) 4.88 kB
"use strict"; // eslint-disable-next-line no-constant-binary-expression var complain = "MARKO_DEBUG" && require("complain"); var ComponentDef = require("../components/ComponentDef"); var ComponentsContext = require("../components/ComponentsContext"); var serializeNOOP = require("../helpers/serialize-noop"); var w10NOOP = serializeNOOP.___noop; var w10ToJSON = serializeNOOP.___toJSON; var changeCase = require("./_change-case"); var getComponentsContext = ComponentsContext.___getComponentsContext; var FLAG_WILL_RERENDER_IN_BROWSER = 1; // var FLAG_HAS_RENDER_BODY = 2; var IS_SERVER = typeof document === "undefined"; /** * Helper to render a dynamic tag */ module.exports = function dynamicTag( out, tag, getAttrs, renderBody, args, props, componentDef, key, customEvents, ) { if (tag) { if (tag.default) { tag = tag.default; } var attrs = getAttrs && getAttrs(); var component = componentDef && componentDef.___component; if (typeof tag === "string") { if (renderBody) { out.___beginElementDynamic( tag, attrs, key, componentDef, addEvents(componentDef, customEvents, props), ); renderBody(out); out.___endElement(); } else { out.___elementDynamic( tag, attrs, key, componentDef, addEvents(componentDef, customEvents, props), ); } } else { if (attrs == null) { attrs = { renderBody: renderBody }; } else if (typeof attrs === "object") { attrs = attrsToCamelCase(attrs); if (renderBody) { attrs.renderBody = renderBody; } } var renderer = tag._ || (tag.renderer ? tag.renderer.renderer || tag.renderer : tag.render); var render = (tag && tag.renderBody) || tag; // eslint-disable-next-line no-constant-condition if ("MARKO_DEBUG") { if (tag.renderer && tag.renderer.renderer) { complain( "An object with a 'renderer' was passed to the dynamic tag, but renderer was another template.", ); } } if (dynamicTag.___runtimeCompat) { renderer = dynamicTag.___runtimeCompat( renderer, render, args, out.global, ); } if (renderer) { out.c(componentDef, key, customEvents); renderer(attrs, out); out.___assignedComponentDef = null; } else { var isFn = typeof render === "function"; // eslint-disable-next-line no-constant-condition if ("MARKO_DEBUG") { if (render.safeHTML || render.toHTML) { throw new Error( "Using `<include(x)/>` or the `<${dynamic}/>` tags with a `{ safeHTML: ... }` object is no longer supported. Use the unescaped text placeholder syntax instead.", ); } } if (isFn) { var flags = componentDef ? componentDef.___flags : 0; var willRerender = flags & FLAG_WILL_RERENDER_IN_BROWSER; var isW10NOOP = render === w10NOOP; var preserve = IS_SERVER ? willRerender : isW10NOOP; out.bf(key, component, preserve); if (!isW10NOOP && isFn) { var componentsContext = getComponentsContext(out); var parentComponentDef = componentsContext.___componentDef; var globalContext = componentsContext.___globalContext; componentsContext.___componentDef = new ComponentDef( component, parentComponentDef.id + "-" + parentComponentDef.___nextKey(key), globalContext, ); render.toJSON = w10ToJSON; if (args) { render.apply(null, [out].concat(args, attrs)); } else { render(out, attrs); } componentsContext.___componentDef = parentComponentDef; } out.ef(); } else { out.error("Invalid dynamic tag value"); } } } } else if (renderBody) { out.bf( key, component, IS_SERVER && componentDef && componentDef.___flags & FLAG_WILL_RERENDER_IN_BROWSER, ); renderBody(out); out.ef(); } }; function attrsToCamelCase(attrs) { var result = {}; for (var key in attrs) { result[changeCase.___dashToCamelCase(key)] = attrs[key]; } return result; } function addEvents(componentDef, customEvents, props) { var len = customEvents ? customEvents.length : 0; if (len === 0) { return props; } var result = props || {}; var event; for (var i = len; i--; ) { event = customEvents[i]; result["on" + event[0]] = componentDef.d( event[0], event[1], event[2], event[3], ); } return result; }