UNPKG

marko

Version:

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

171 lines (134 loc) 5.13 kB
"use strict"; // eslint-disable-next-line no-constant-binary-expression var componentLookup = require("@internal/components-util")._n_; var req = require("@internal/require"); var makeRenderable = require("../../renderable"); var getComponentsContext = require("../ComponentsContext").T_; var modernRenderer = require("../renderer"); var resolveComponentKey = modernRenderer.aZ_; module.exports = function defineRenderer(renderingLogic) { var renderer = renderingLogic.renderer; if (renderer && renderer.b__) { return renderer; } var template = renderingLogic.template; if (typeof template === "string") { template = req(template); } if (template && template.default) { template = template.default; } if (!renderer) { var getInitialProps; var getTemplateData; var getInitialState; var getWidgetConfig; var getInitialBody; if (renderingLogic) { getInitialProps = renderingLogic.getInitialProps; getTemplateData = renderingLogic.getTemplateData; getInitialState = renderingLogic.getInitialState; getWidgetConfig = renderingLogic.getWidgetConfig; getInitialBody = renderingLogic.getInitialBody; } // Create a renderer function that takes care of translating // the input properties to a view state. Also, this renderer // takes care of re-using existing components. renderer = function renderer(input, out) { var componentsContext = getComponentsContext(out); var globalComponentsContext = componentsContext.p_; var component = globalComponentsContext.aB_; var isReceivingNewInput = !component || component._j_; var parentComponentDef; if (component) { component._j_ = false; } // Render the template associated with the component using the final template // data that we constructed var newProps = input; var widgetConfig; var widgetState; var widgetBody; var id; if (!component && componentLookup) { var key = out.ac_; if ( (parentComponentDef = componentsContext.o_) && key != null) { id = resolveComponentKey(key.toString(), parentComponentDef); } else if (parentComponentDef) { id = parentComponentDef.aQ_(); } else { id = globalComponentsContext.aQ_(); } component = componentLookup[id]; } if (isReceivingNewInput) { // If we do not have state then we need to go through the process // of converting the input to a widget state, or simply normalizing // the input using getInitialProps if (getInitialProps) { // This optional method is used to normalize input state newProps = getInitialProps(newProps, out) || {}; } if (getInitialState) { // This optional method is used to derive the widget state // from the input properties widgetState = getInitialState(newProps, out); } if (getInitialBody) { // If we have widget a widget body then pass it to the template // so that it is available to the widget tag and can be inserted // at the w-body marker widgetBody = getInitialBody(newProps, out); } else { // Default to using the nested content as the widget body // getInitialBody was not implemented widgetBody = newProps.renderBody; } } else if (component) { newProps = newProps || component.O_; widgetBody = component.___; widgetState = component.aE_; widgetConfig = component.widgetConfig; } // Use getTemplateData(state, props, out) to get the template // data. If that method is not provided then just use the // the state (if provided) or the input data. var templateData = clone( getTemplateData ? getTemplateData(widgetState, newProps, out) : widgetState || newProps ); if (isReceivingNewInput && getWidgetConfig) { // If getWidgetConfig() was implemented then use that to // get the widget config. The widget config will be passed // to the widget constructor. If rendered on the server the // widget config will be serialized. widgetConfig = getWidgetConfig(newProps, out); } // eslint-disable-next-line no-constant-condition templateData.widgetProps = newProps; widgetBody && (templateData.renderBody = widgetBody); widgetState && (templateData.widgetState = widgetState); widgetConfig && (templateData.widgetConfig = widgetConfig); template._(templateData, out, id, renderingLogic); }; } renderer.b__ = true; renderer.createOut = template ? template.createOut : renderingLogic.createOut; renderer.template = template; makeRenderable(renderer, renderer); renderer.render = renderer.render.bind(renderer); return renderer; }; function clone(src) { var result = {}; if (src) { for (var key in src) { result[key] = src[key]; } } return result; }