UNPKG

google-closure-library

Version:
252 lines (232 loc) 9.81 kB
/** * @license * Copyright The Closure Library Authors. * SPDX-License-Identifier: Apache-2.0 */ /** * @fileoverview Provides a soy renderer that allows registration of * injected data ("globals") that will be passed into the rendered * templates. */ goog.module('goog.soy.Renderer'); goog.module.declareLegacyNamespace(); const InjectedDataSupplier = goog.requireType('goog.soy.InjectedDataSupplier'); const SafeHtml = goog.requireType('goog.html.SafeHtml'); const SafeStyleSheet = goog.requireType('goog.html.SafeStyleSheet'); const SanitizedContent = goog.require('goog.soy.data.SanitizedContent'); const SanitizedContentKind = goog.require('goog.soy.data.SanitizedContentKind'); const SanitizedCss = goog.requireType('goog.soy.data.SanitizedCss'); const SanitizedHtml = goog.requireType('goog.soy.data.SanitizedHtml'); const SanitizedUri = goog.requireType('goog.soy.data.SanitizedUri'); const asserts = goog.require('goog.asserts'); const dom = goog.require('goog.dom'); const soy = goog.require('goog.soy'); /** * Creates a new soy renderer. Note that the renderer will only be * guaranteed to work correctly within the document scope provided in * the DOM helper. */ class Renderer { /** * @param {?InjectedDataSupplier=} injectedDataSupplier A supplier that * provides an injected data. * @param {?dom.DomHelper=} domHelper Optional DOM helper; defaults to that * provided by `dom.getDomHelper()`. */ constructor(injectedDataSupplier = undefined, domHelper = undefined) { /** @private @const {!dom.DomHelper} */ this.dom_ = domHelper || dom.getDomHelper(); /** @private @const {?InjectedDataSupplier} */ this.supplier_ = injectedDataSupplier || null; } /** * Renders a Soy template into a single node or a document fragment. * Delegates to `soy.renderAsFragment`. * @param {function(ARG_TYPES, ?soy.CompatibleIj=): *} template The Soy * template defining the element's content. * @param {ARG_TYPES=} templateData The data for the template. * @return {!Node} The resulting node or document fragment. * @template ARG_TYPES */ renderAsFragment(template, templateData = undefined) { const node = soy.renderAsFragment( template, templateData, this.getInjectedData_(), this.dom_); this.handleRender(node, SanitizedContentKind.HTML); return node; } /** * Renders a Soy template into a single node. If the rendered HTML * string represents a single node, then that node is returned. * Otherwise, a DIV element is returned containing the rendered nodes. * Delegates to `soy.renderAsElement`. * @param {function(ARG_TYPES, ?soy.CompatibleIj=): *} template The Soy * template defining the element's content. * @param {ARG_TYPES=} templateData The data for the template. * @return {!Element} Rendered template contents, wrapped in a parent DIV * element if necessary. * @template ARG_TYPES */ renderAsElement(template, templateData = undefined) { const element = soy.renderAsElement( template, templateData, this.getInjectedData_(), this.dom_); this.handleRender(element, SanitizedContentKind.HTML); return element; } /** * Renders a Soy template and then set the output string as the * innerHTML of the given element. Delegates to `soy.renderElement`. * @param {?Element} element The element whose content we are rendering. * @param {function(ARG_TYPES, ?soy.CompatibleIj=): *} template The Soy * template defining the element's content. * @param {ARG_TYPES=} templateData The data for the template. * @template ARG_TYPES */ renderElement(element, template, templateData = undefined) { soy.renderElement(element, template, templateData, this.getInjectedData_()); this.handleRender(element, SanitizedContentKind.HTML); } /** * Renders a Soy template and returns the output string. * If the template is strict, it must be of kind HTML. To render strict * templates of other kinds, use `renderText` (for `kind="text"`) or * `renderStrictOfKind`. * @param {function(ARG_TYPES, ?Object<string, *>=): *} template The Soy * template to render. * @param {ARG_TYPES=} templateData The data for the template. * @return {string} The return value of rendering the template directly. * @template ARG_TYPES */ render(template, templateData = undefined) { const result = template(templateData || {}, this.getInjectedData_()); asserts.assert( !(result instanceof SanitizedContent) || result.contentKind === SanitizedContentKind.HTML, 'render was called with a strict template of kind other than "html"' + ' (consider using renderText or renderStrict)'); const contentKind = result instanceof SanitizedContent ? result.contentKind : null; this.handleRender(null /* node */, contentKind); return String(result); } /** * Renders a strict Soy template of kind="text" and returns the output string. * It is an error to use renderText on templates of kinds other than "text". * @param {function(ARG_TYPES, ?Object<string,*>=): string} template The Soy * template to render. * @param {ARG_TYPES=} templateData The data for the template. * @return {string} The return value of rendering the template directly. * @template ARG_TYPES */ renderText(template, templateData = undefined) { return soy.renderAsText(template, templateData, this.getInjectedData_()); } /** * Renders a strict Soy HTML template and returns the output SanitizedHtml * object. * @param {function(ARG_TYPES, ?Object<string,*>=): * !SanitizedHtml} template The Soy template to render. * @param {ARG_TYPES=} templateData The data for the template. * @return {!SanitizedHtml} * @template ARG_TYPES */ renderStrict(template, templateData = undefined) { return this.renderStrictOfKind( template, templateData, SanitizedContentKind.HTML); } /** * Renders a strict Soy template and returns the output SanitizedUri object. * @param {function(ARG_TYPES, ?Object<string, *>=): * !SanitizedUri} template The Soy template to render. * @param {ARG_TYPES=} templateData The data for the template. * @return {!SanitizedUri} * @template ARG_TYPES */ renderStrictUri(template, templateData = undefined) { return this.renderStrictOfKind( template, templateData, SanitizedContentKind.URI); } /** * Renders a strict Soy template and returns the output SanitizedContent * object. * @param {function(ARG_TYPES, ?Object<string, *>=): RETURN_TYPE} template The * Soy template to render. * @param {ARG_TYPES=} templateData The data for the template. * @param {?SanitizedContentKind=} kind The output kind to assert. If null, * the template must be of kind="html" (i.e., kind defaults to * SanitizedContentKind.HTML). * @return {RETURN_TYPE} The SanitizedContent object. This return type is * generic based on the return type of the template, such as * soy.data.SanitizedHtml. * @template ARG_TYPES, RETURN_TYPE */ renderStrictOfKind(template, templateData = undefined, kind = undefined) { const result = template(templateData || {}, this.getInjectedData_()); asserts.assertInstanceof( result, SanitizedContent, 'renderStrict cannot be called on a text soy template'); asserts.assert( result.contentKind === (kind || SanitizedContentKind.HTML), 'renderStrict was called with the wrong kind of template'); this.handleRender(null /* node */, result.contentKind); return result; } /** * Renders a strict Soy template of kind="html" and returns the result as * a SafeHtml object. * Rendering a template that is not a strict template of kind="html" results * in a runtime error. * @param {function(ARG_TYPES, ?Object<string, *>=): * !SanitizedHtml} template The Soy template to render. * @param {ARG_TYPES=} templateData The data for the template. * @return {!SafeHtml} * @template ARG_TYPES */ renderSafeHtml(template, templateData = undefined) { const result = this.renderStrict(template, templateData); // Convert from SanitizedHtml to SafeHtml. return result.toSafeHtml(); } /** * Renders a strict Soy template of kind="css" and returns the result as * a SafeStyleSheet object. * Rendering a template that is not a strict template of kind="css" results in * a runtime and compile-time error. * @param {function(ARG_TYPES, ?Object<string, *>=): * !SanitizedCss} template The Soy template to render. * @param {ARG_TYPES=} templateData The data for the template. * @return {!SafeStyleSheet} * @template ARG_TYPES */ renderSafeStyleSheet(template, templateData = undefined) { const result = this.renderStrictOfKind( template, templateData, SanitizedContentKind.CSS); return result.toSafeStyleSheet(); } /** * @return {!dom.DomHelper} * @protected */ getDom() { return this.dom_; } /** * Observes rendering of non-text templates by this renderer. * @param {?Node} node Relevant node, if available. The node may or may not be * in the document, depending on whether Soy is creating an element or * writing into an existing one. * @param {?SanitizedContentKind} kind of the template, or null if it was not * strict. * @protected */ handleRender(node, kind) {} /** * Creates the injectedParams map if necessary and calls the configuration * service to prepopulate it. * @return {?} The injected params. * @private */ getInjectedData_() { return this.supplier_ ? this.supplier_.getData() : {}; } } exports = Renderer;