use of com.google.template.soy.soytree.HtmlAttributeValueNode in project closure-templates by google.
the class GenIncrementalDomCodeVisitor method maybeGetKeyNodeValue.
/**
* Gets the 'key' for an element to use in Incremental DOM to be used in the {@code
* incrementalDom.elementOpen} or {@code incrementalDom.elementVoid} calls.
*
* <pre>
* <div key="test" /div>
* </pre>
*
* generates
*
* <pre>
* incrementalDom.elementVoid('div', 'test')
* </pre>
*
* @param parentNode The SoyNode representing the parent.
* @return A string containing the JavaScript expression to retrieve the key, or null if the
* parent has no attribute child.
*/
@Nullable
private CodeChunk.WithValue maybeGetKeyNodeValue(HtmlOpenTagNode parentNode) {
// TODO(lukes): it seems like we should be able to support conditional keys
HtmlAttributeNode keyAttr = parentNode.getDirectAttributeNamed(KEY_ATTRIBUTE_NAME);
if (keyAttr != null) {
List<CodeChunk.WithValue> chunks = ImmutableList.of();
if (keyAttr.hasValue()) {
// TODO(lukes): add a dedicated method for this to HtmlAttributeNode? if there is a value
// it should _always_ be an HtmlAttributeValueNode
HtmlAttributeValueNode value = (HtmlAttributeValueNode) keyAttr.getChild(1);
// TODO(lukes): this limitation is arbitrary. fix it.
checkState(isComputableAsJsExprsVisitor.execOnChildren(value), "Attribute values that cannot be evalutated to simple expressions is not yet" + " supported for Incremental DOM code generation");
chunks = genJsExprsVisitor.execOnChildren(value);
}
// to be string (RawTextNode or PrintNode)
return CodeChunkUtils.concatChunksForceString(chunks);
}
return null;
}
use of com.google.template.soy.soytree.HtmlAttributeValueNode in project closure-templates by google.
the class ContentSecurityPolicyNonceInjectionPass method createCspInjection.
/**
* Generates an AST fragment that looks like: {if $ij.csp_nonce}nonce="{$ij.csp_nonce}"{/if}
*
* @param insertionLocation The location where it is being inserted
* @param nodeIdGen The id generator to use
*/
private static IfNode createCspInjection(SourceLocation insertionLocation, IdGenerator nodeIdGen) {
IfNode ifNode = new IfNode(nodeIdGen.genId(), insertionLocation);
IfCondNode ifCondNode = new IfCondNode(nodeIdGen.genId(), insertionLocation, "if", referenceCspNonce(insertionLocation));
ifNode.addChild(ifCondNode);
HtmlAttributeNode nonceAttribute = new HtmlAttributeNode(nodeIdGen.genId(), insertionLocation, insertionLocation.getBeginPoint());
ifCondNode.addChild(nonceAttribute);
nonceAttribute.addChild(new RawTextNode(nodeIdGen.genId(), "nonce", insertionLocation));
HtmlAttributeValueNode attributeValue = new HtmlAttributeValueNode(nodeIdGen.genId(), insertionLocation, HtmlAttributeValueNode.Quotes.DOUBLE);
nonceAttribute.addChild(attributeValue);
// NOTE: we do not need to insert any print directives here, unlike the old implementation since
// we are running before the autoescaper, so the escaper should insert whatever print directives
// are appropriate.
PrintNode printNode = new PrintNode(nodeIdGen.genId(), insertionLocation, // Implicit. {$ij.csp_nonce} not {print $ij.csp_nonce}
true, /* isImplicit= */
referenceCspNonce(insertionLocation), /* attributes= */
ImmutableList.of(), ErrorReporter.exploding());
attributeValue.addChild(printNode);
return ifNode;
}
use of com.google.template.soy.soytree.HtmlAttributeValueNode in project closure-templates by google.
the class HtmlRewritePassTest method testAttributes.
@Test
public void testAttributes() {
TemplateNode node = runPass("<div class=\"foo\"></div>");
assertThatSourceString(node).isEqualTo("<div class=\"foo\"></div>");
String structure = "" + "HTML_OPEN_TAG_NODE\n" + " RAW_TEXT_NODE\n" + " HTML_ATTRIBUTE_NODE\n" + " RAW_TEXT_NODE\n" + " HTML_ATTRIBUTE_VALUE_NODE\n" + " RAW_TEXT_NODE\n" + "HTML_CLOSE_TAG_NODE\n" + " RAW_TEXT_NODE\n" + "";
assertThatASTString(node).isEqualTo(structure);
// test alternate quotation marks
node = runPass("<div class='foo'></div>");
assertThatSourceString(node).isEqualTo("<div class='foo'></div>");
assertThatASTString(node).isEqualTo(structure);
node = runPass("<div class=foo></div>");
assertThatSourceString(node).isEqualTo("<div class=foo></div>");
assertThatASTString(node).isEqualTo(structure);
// This is a tricky case, according to the spec the '/' belongs to the attribute, not the tag
node = runPass("<input class=foo/>");
assertThatSourceString(node).isEqualTo("<input class=foo/>");
HtmlOpenTagNode openTag = (HtmlOpenTagNode) node.getChild(0);
assertThat(openTag.isSelfClosing()).isFalse();
HtmlAttributeValueNode attributeValue = (HtmlAttributeValueNode) ((HtmlAttributeNode) openTag.getChild(1)).getChild(1);
assertThat(attributeValue.getQuotes()).isEqualTo(HtmlAttributeValueNode.Quotes.NONE);
assertThat(((RawTextNode) attributeValue.getChild(0)).getRawText()).isEqualTo("foo/");
}
use of com.google.template.soy.soytree.HtmlAttributeValueNode in project closure-templates by google.
the class VeLogInstrumentationVisitor method visitHtmlAttributeNode.
/**
* For HtmlAttributeNode that has a logging function as its value, replace the logging function
* with its place holder, and append a new data attribute that contains all the desired
* information that are used later by the runtime library.
*/
@Override
protected void visitHtmlAttributeNode(HtmlAttributeNode node) {
// Skip attributes that do not have a value.
if (!node.hasValue()) {
return;
}
SourceLocation insertionLocation = node.getSourceLocation();
for (FunctionNode function : SoyTreeUtils.getAllNodesOfType(node, FunctionNode.class)) {
if (!(function.getSoyFunction() instanceof LoggingFunction)) {
continue;
}
FunctionNode funcNode = new FunctionNode(VeLogJsSrcLoggingFunction.INSTANCE, insertionLocation);
funcNode.addChild(new StringNode(function.getFunctionName(), QuoteStyle.SINGLE, insertionLocation));
funcNode.addChild(new ListLiteralNode(function.getChildren(), insertionLocation));
StandaloneNode attributeName = node.getChild(0);
if (attributeName instanceof RawTextNode) {
// If attribute name is a plain text, directly pass it as a function argument.
funcNode.addChild(new StringNode(((RawTextNode) attributeName).getRawText(), QuoteStyle.SINGLE, insertionLocation));
} else {
// Otherwise wrap the print node or call node into a let block, and use the let variable
// as a function argument.
String varName = "soy_logging_function_attribute_" + counter;
LetContentNode letNode = LetContentNode.forVariable(nodeIdGen.genId(), attributeName.getSourceLocation(), varName, null);
// Adds a let var which references to the original attribute name, and move the name to
// the let block.
node.replaceChild(attributeName, new PrintNode(nodeIdGen.genId(), insertionLocation, /* isImplicit= */
true, /* expr= */
new VarRefNode(varName, insertionLocation, false, letNode.getVar()), /* attributes= */
ImmutableList.of(), ErrorReporter.exploding()));
letNode.addChild(attributeName);
node.getParent().addChild(node.getParent().getChildIndex(node), letNode);
funcNode.addChild(new VarRefNode(varName, insertionLocation, false, letNode.getVar()));
}
funcNode.addChild(new IntegerNode(counter++, insertionLocation));
PrintNode loggingFunctionAttribute = new PrintNode(nodeIdGen.genId(), insertionLocation, /* isImplicit= */
true, /* expr= */
funcNode, /* attributes= */
ImmutableList.of(), ErrorReporter.exploding());
// Append the logging function attribute to its parent
int appendIndex = node.getParent().getChildIndex(node) + 1;
node.getParent().addChild(appendIndex, loggingFunctionAttribute);
// Replace the original attribute value to the placeholder.
HtmlAttributeValueNode placeHolder = new HtmlAttributeValueNode(nodeIdGen.genId(), insertionLocation, Quotes.DOUBLE);
placeHolder.addChild(new RawTextNode(nodeIdGen.genId(), ((LoggingFunction) function.getSoyFunction()).getPlaceholder(), insertionLocation));
node.replaceChild(node.getChild(1), placeHolder);
// logging function in a html attribute value.
break;
}
visitChildren(node);
}
use of com.google.template.soy.soytree.HtmlAttributeValueNode in project closure-templates by google.
the class GenIncrementalDomCodeVisitor method getAttributeValues.
private List<CodeChunk.WithValue> getAttributeValues(HtmlAttributeNode node) {
if (!node.hasValue()) {
// the runtime knows to create an attribute.
return ImmutableList.of(LITERAL_EMPTY_STRING);
}
HtmlAttributeValueNode value = (HtmlAttributeValueNode) node.getChild(1);
if (!isComputableAsJsExprsVisitor.execOnChildren(value)) {
String outputVar = "html_attribute_" + node.getId();
getJsCodeBuilder().pushOutputVar(outputVar).setOutputVarInited();
SanitizedContentKind prev = getJsCodeBuilder().getContentKind();
getJsCodeBuilder().setContentKind(SanitizedContentKind.TEXT);
CodeChunk appends = visitChildrenReturningCodeChunk(value);
getJsCodeBuilder().popOutputVar();
getJsCodeBuilder().setContentKind(prev);
return ImmutableList.of(CodeChunk.id(outputVar).withInitialStatements(ImmutableList.<CodeChunk>of(VariableDeclaration.builder(outputVar).setRhs(CodeChunk.LITERAL_EMPTY_STRING).build(), appends)));
}
return genJsExprsVisitor.execOnChildren(value);
}
Aggregations