Skip to content

Commit

Permalink
RELNOTES:Add an API to conditionally render soy using IDOM constructs.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 505208412
Change-Id: I200c809555e5f4e3d600e111344980898f044413
  • Loading branch information
iteriani authored and Copybara-Service committed Jan 27, 2023
1 parent 827a9d5 commit 35dc68a
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 6 deletions.
1 change: 1 addition & 0 deletions closure/goog/soy/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ closure_js_library(
lenient = True,
deps = [
"//closure/goog/asserts",
"//closure/goog/dom:safe",
"//closure/goog/html:safehtml",
"//closure/goog/html:safescript",
"//closure/goog/html:safestyle",
Expand Down
11 changes: 11 additions & 0 deletions closure/goog/soy/data.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ goog.provide('goog.soy.data.SanitizedUri');

goog.require('goog.Uri');
goog.require('goog.asserts');
goog.require('goog.dom.safe');
goog.require('goog.html.SafeHtml');
goog.require('goog.html.SafeScript');
goog.require('goog.html.SafeStyle');
Expand All @@ -33,6 +34,10 @@ goog.require('goog.html.uncheckedconversions');
goog.require('goog.i18n.bidi.Dir');
goog.require('goog.string.Const');

goog.scope(() => {

const SafeHtml = goog.html.SafeHtml;
const safe = goog.dom.safe;

/**
* A type of textual content.
Expand Down Expand Up @@ -163,6 +168,11 @@ goog.soy.data.SanitizedContent.prototype.toSafeHtml = function() {
this.toString());
};

/** @type {(function((!Element|!ShadowRoot)): void)|undefined} */
goog.soy.data.SanitizedContent.prototype.renderElement;

/** @type {(function(): !Element)|undefined} */
goog.soy.data.SanitizedContent.prototype.renderAsElement;

/**
* Converts sanitized content of kind URI into SafeUrl without modification.
Expand Down Expand Up @@ -544,3 +554,4 @@ goog.soy.data.SanitizedCss.prototype.toSafeStyleSheet = function() {
'value.'),
value);
};
});
32 changes: 26 additions & 6 deletions closure/goog/soy/soy.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ exports.TextTemplate = TextTemplate;
* @template ARG_TYPES
*/
function renderHtml(element, templateResult) {
if (templateResult && templateResult.renderElement) {
templateResult.renderElement(asserts.assert(element));
return;
}
safe.unsafeSetInnerHtmlDoNotUseOrElse(
asserts.assert(element), ensureTemplateOutputHtml(templateResult));
}
Expand All @@ -101,8 +105,13 @@ exports.renderHtml = renderHtml;
*/
function renderElement(
element, template, templateData = undefined, injectedData = undefined) {
const html = ensureTemplateOutputHtml(
const output = /** @type {?SanitizedContent} */ (
template(templateData || defaultTemplateData, injectedData));
if (output && output.renderElement && element) {
output.renderElement(element);
return;
}
const html = ensureTemplateOutputHtml(output);
safe.unsafeSetInnerHtmlDoNotUseOrElse(asserts.assert(element), html);
}
exports.renderElement = renderElement;
Expand All @@ -127,7 +136,11 @@ function renderAsFragment(
template, templateData = undefined, injectedData = undefined,
domHelper = undefined) {
const dom = domHelper || googDom.getDomHelper();
const output = template(templateData || defaultTemplateData, injectedData);
const output = /** @type {?SanitizedContent} */ (
template(templateData || defaultTemplateData, injectedData));
if (output && output.renderAsElement) {
return output.renderAsElement();
}
const html = ensureTemplateOutputHtml(output);
assertFirstTagValid(html.getTypedStringValue());
return dom.safeHtmlToNode(html);
Expand Down Expand Up @@ -182,10 +195,17 @@ exports.convertToElement = convertToElement;
*/
function convertToElementInternal(templateResult, domHelper = undefined) {
const dom = domHelper || googDom.getDomHelper();
const wrapper = dom.createElement(TagName.DIV);
const html = ensureTemplateOutputHtml(templateResult);
assertFirstTagValid(html.getTypedStringValue());
safe.unsafeSetInnerHtmlDoNotUseOrElse(wrapper, html);
let wrapper;
if (templateResult &&
(/** @type {!SanitizedContent} */ (templateResult)).renderAsElement) {
wrapper =
(/** @type {!SanitizedContent} */ (templateResult)).renderAsElement();
} else {
wrapper = dom.createElement(TagName.DIV);
const html = ensureTemplateOutputHtml(templateResult);
assertFirstTagValid(html.getTypedStringValue());
safe.unsafeSetInnerHtmlDoNotUseOrElse(wrapper, html);
}

// If the template renders as a single element, return it.
if (wrapper.childNodes.length == 1) {
Expand Down

0 comments on commit 35dc68a

Please sign in to comment.