use of com.google.template.soy.soytree.RawTextNode in project closure-templates by google.
the class AddHtmlCommentsForDebugPass method createSoyDebug.
/**
* Generates an AST fragment that looks like:
*
* <p>{@code {if debugSoyTemplateInfo()}<!--dta_of...-->{/if}}
*
* @param insertionLocation The location where it is being inserted
* @param nodeIdGen The id generator to use
* @param htmlComment The content of the HTML comment
*/
private IfNode createSoyDebug(SourceLocation insertionLocation, IdGenerator nodeIdGen, String htmlComment) {
IfNode ifNode = new IfNode(nodeIdGen.genId(), insertionLocation);
FunctionNode funcNode = new FunctionNode(DebugSoyTemplateInfoFunction.INSTANCE, insertionLocation);
funcNode.setType(BoolType.getInstance());
IfCondNode ifCondNode = new IfCondNode(nodeIdGen.genId(), insertionLocation, "if", funcNode);
HtmlCommentNode htmlCommentNode = new HtmlCommentNode(nodeIdGen.genId(), insertionLocation);
// We need to escape the input HTML comments, in cases the file location contains "-->".
htmlCommentNode.addChild(new RawTextNode(nodeIdGen.genId(), htmlEscaper().escape(htmlComment), insertionLocation));
ifCondNode.addChild(htmlCommentNode);
ifNode.addChild(ifCondNode);
return ifNode;
}
use of com.google.template.soy.soytree.RawTextNode in project closure-templates by google.
the class CombineConsecutiveRawTextNodesPass method visit.
private void visit(ParentSoyNode<?> node) {
// The raw text node at the beginning of the current sequence
int start = -1;
int lastNonEmptyRawTextNode = -1;
int i = 0;
for (; i < node.numChildren(); i++) {
SoyNode child = node.getChild(i);
if (child instanceof RawTextNode) {
RawTextNode childAsRawText = (RawTextNode) child;
if (start == -1) {
// drop empty raw text nodes at the prefix
if (childAsRawText.getRawText().isEmpty()) {
node.removeChild(i);
i--;
} else {
// mark the beginning of a sequence of nonempty raw text
start = i;
lastNonEmptyRawTextNode = i;
}
} else {
if (!childAsRawText.getRawText().isEmpty()) {
lastNonEmptyRawTextNode = i;
}
}
} else {
i = mergeRange(node, start, lastNonEmptyRawTextNode, i);
// reset
start = -1;
if (child instanceof ParentSoyNode) {
// recurse
visit((ParentSoyNode<?>) child);
}
// else do nothing since it cannot contain raw text nodes
}
}
mergeRange(node, start, lastNonEmptyRawTextNode, i);
}
use of com.google.template.soy.soytree.RawTextNode in project closure-templates by google.
the class CombineConsecutiveRawTextNodesPass method mergeRange.
// There is no generic type we could give to ParentSoyNode that wouldn't require unchecked casts
// either here or in our caller. This is safe however since we are only adding or removing
// RawTextNodes and if we can remove a RawTextNode, we can also add one.
@SuppressWarnings("unchecked")
private int mergeRange(ParentSoyNode<?> parent, int start, int lastNonEmptyRawTextNode, int end) {
checkArgument(start < end);
if (start == -1 || end == start + 1) {
return end;
}
// general case, there are N rawtextnodes to merge where n > 1
// merge all the nodes together, then drop all the raw text nodes from the end
RawTextNode newNode = RawTextNode.concat((List<RawTextNode>) parent.getChildren().subList(start, lastNonEmptyRawTextNode + 1));
((ParentSoyNode) parent).replaceChild(start, newNode);
for (int i = end - 1; i > start; i--) {
parent.removeChild(i);
}
return start + 1;
}
use of com.google.template.soy.soytree.RawTextNode in project closure-templates by google.
the class GenIncrementalDomCodeVisitor method visitHtmlAttributeNode.
/**
* Visits the {@link HtmlAttributeNode}. The attribute nodes will typically be children of the
* corresponding {@link HtmlOpenTagNode} or in a let/param of kind attributes, e.g.
*
* <pre>
* {let $attrs kind="attributes"}
* attr="value"
* {/let}
* </pre>
*
* This method prints the attribute declaration calls. For example, given
*
* <pre>
* <div {if $condition}attr="value"{/if}>
* </pre>
*
* it would print the call to {@code incrementalDom.attr}, resulting in:
*
* <pre>
* if (condition) {
* IncrementalDom.attr(attr, "value");
* }
* </pre>
*/
@Override
protected void visitHtmlAttributeNode(HtmlAttributeNode node) {
IncrementalDomCodeBuilder jsCodeBuilder = getJsCodeBuilder();
if (node.hasValue() || node.getChild(0).getKind() == Kind.RAW_TEXT_NODE) {
// This cast is safe because the HtmlContextVisitor enforces it, or the above condition
// checked
RawTextNode attrName = (RawTextNode) node.getChild(0);
jsCodeBuilder.append(INCREMENTAL_DOM_ATTR.call(stringLiteral(attrName.getRawText()), CodeChunkUtils.concatChunksForceString(getAttributeValues(node))));
} else {
// visit dynamic children
visitChildren(node);
}
}
use of com.google.template.soy.soytree.RawTextNode in project closure-templates by google.
the class TemplateParserTest method testParseMsgStmtWithPlural.
// -----------------------------------------------------------------------------------------------
// Tests for plural/select messages.
@Test
public void testParseMsgStmtWithPlural() throws Exception {
String templateBody = "{@param num_people : ?}{@param person : ?}{@param place : ?}\n" + " {msg desc=\"A sample plural message\"}\n" + " {plural $num_people offset=\"1\"}\n" + " {case 0}I see no one in {$place}.\n" + " {case 1}I see {$person} in {$place}.\n" + " {case 2}I see {$person} and one other person in {$place}.\n" + " {default}I see {$person} and {remainder($num_people)} " + "other people in {$place}.\n" + " {/plural}" + " {/msg}\n";
List<StandaloneNode> nodes = parseTemplateContent(templateBody, FAIL).getChildren();
assertEquals(1, nodes.size());
MsgNode mn = ((MsgFallbackGroupNode) nodes.get(0)).getChild(0);
assertEquals(1, mn.numChildren());
assertEquals("A sample plural message", mn.getDesc());
MsgPluralNode pn = (MsgPluralNode) mn.getChild(0);
assertEquals("$num_people", pn.getExpr().toSourceString());
assertEquals(1, pn.getOffset());
// 3 cases and default
assertEquals(4, pn.numChildren());
// Case 0
MsgPluralCaseNode cn0 = (MsgPluralCaseNode) pn.getChild(0);
assertEquals(3, cn0.numChildren());
assertEquals(0, cn0.getCaseNumber());
RawTextNode rtn01 = (RawTextNode) cn0.getChild(0);
assertEquals("I see no one in ", rtn01.getRawText());
MsgPlaceholderNode phn01 = (MsgPlaceholderNode) cn0.getChild(1);
assertEquals("{$place}", phn01.toSourceString());
RawTextNode rtn02 = (RawTextNode) cn0.getChild(2);
assertEquals(".", rtn02.getRawText());
// Case 1
MsgPluralCaseNode cn1 = (MsgPluralCaseNode) pn.getChild(1);
assertEquals(5, cn1.numChildren());
assertEquals(1, cn1.getCaseNumber());
RawTextNode rtn11 = (RawTextNode) cn1.getChild(0);
assertEquals("I see ", rtn11.getRawText());
MsgPlaceholderNode phn11 = (MsgPlaceholderNode) cn1.getChild(1);
assertEquals("{$person}", phn11.toSourceString());
RawTextNode rtn12 = (RawTextNode) cn1.getChild(2);
assertEquals(" in ", rtn12.getRawText());
MsgPlaceholderNode phn12 = (MsgPlaceholderNode) cn1.getChild(3);
assertEquals("{$place}", phn12.toSourceString());
RawTextNode rtn13 = (RawTextNode) cn1.getChild(4);
assertEquals(".", rtn13.getRawText());
// Case 2
MsgPluralCaseNode cn2 = (MsgPluralCaseNode) pn.getChild(2);
assertEquals(5, cn2.numChildren());
assertEquals(2, cn2.getCaseNumber());
RawTextNode rtn21 = (RawTextNode) cn2.getChild(0);
assertEquals("I see ", rtn21.getRawText());
MsgPlaceholderNode phn21 = (MsgPlaceholderNode) cn2.getChild(1);
assertEquals("{$person}", phn21.toSourceString());
RawTextNode rtn22 = (RawTextNode) cn2.getChild(2);
assertEquals(" and one other person in ", rtn22.getRawText());
MsgPlaceholderNode phn22 = (MsgPlaceholderNode) cn2.getChild(3);
assertEquals("{$place}", phn22.toSourceString());
RawTextNode rtn23 = (RawTextNode) cn2.getChild(4);
assertEquals(".", rtn23.getRawText());
// Default
MsgPluralDefaultNode dn = (MsgPluralDefaultNode) pn.getChild(3);
assertEquals(7, dn.numChildren());
RawTextNode rtnd1 = (RawTextNode) dn.getChild(0);
assertEquals("I see ", rtnd1.getRawText());
MsgPlaceholderNode phnd1 = (MsgPlaceholderNode) dn.getChild(1);
assertEquals("{$person}", phnd1.toSourceString());
RawTextNode rtnd2 = (RawTextNode) dn.getChild(2);
assertEquals(" and ", rtnd2.getRawText());
MsgPlaceholderNode phnd2 = (MsgPlaceholderNode) dn.getChild(3);
assertEquals("{$num_people - 1}", phnd2.toSourceString());
RawTextNode rtnd3 = (RawTextNode) dn.getChild(4);
assertEquals(" other people in ", rtnd3.getRawText());
MsgPlaceholderNode phnd3 = (MsgPlaceholderNode) dn.getChild(5);
assertEquals("{$place}", phnd3.toSourceString());
RawTextNode rtnd4 = (RawTextNode) dn.getChild(6);
assertEquals(".", rtnd4.getRawText());
}
Aggregations