use of com.google.template.soy.soytree.MsgHtmlTagNode in project closure-templates by google.
the class MsgFuncGenerator method collectVarNameListAndToPyExprMap.
/**
* Private helper to process and collect all variables used within this msg node for code
* generation.
*
* @return A Map populated with all the variables used with in this message node, using {@link
* MsgPlaceholderInitialNode#genBasePhName}.
*/
private Map<PyExpr, PyExpr> collectVarNameListAndToPyExprMap() {
Map<PyExpr, PyExpr> nodePyVarToPyExprMap = new LinkedHashMap<>();
for (Map.Entry<String, MsgSubstUnitNode> entry : msgNode.getVarNameToRepNodeMap().entrySet()) {
MsgSubstUnitNode substUnitNode = entry.getValue();
PyExpr substPyExpr = null;
if (substUnitNode instanceof MsgPlaceholderNode) {
SoyNode phInitialNode = ((AbstractParentSoyNode<?>) substUnitNode).getChild(0);
if (phInitialNode instanceof PrintNode || phInitialNode instanceof CallNode || phInitialNode instanceof RawTextNode) {
substPyExpr = PyExprUtils.concatPyExprs(genPyExprsVisitor.exec(phInitialNode)).toPyString();
}
// when the placeholder is generated by HTML tags
if (phInitialNode instanceof MsgHtmlTagNode) {
substPyExpr = PyExprUtils.concatPyExprs(genPyExprsVisitor.execOnChildren((ParentSoyNode<?>) phInitialNode)).toPyString();
}
} else if (substUnitNode instanceof MsgPluralNode) {
// Translates {@link MsgPluralNode#pluralExpr} into a Python lookup expression.
// Note that {@code pluralExpr} represents the soy expression of the {@code plural} attr,
// i.e. the {@code $numDrafts} in {@code {plural $numDrafts}...{/plural}}.
substPyExpr = translateToPyExprVisitor.exec(((MsgPluralNode) substUnitNode).getExpr());
} else if (substUnitNode instanceof MsgSelectNode) {
substPyExpr = translateToPyExprVisitor.exec(((MsgSelectNode) substUnitNode).getExpr());
}
if (substPyExpr != null) {
nodePyVarToPyExprMap.put(new PyStringExpr("'" + entry.getKey() + "'"), substPyExpr);
}
}
return nodePyVarToPyExprMap;
}
use of com.google.template.soy.soytree.MsgHtmlTagNode in project closure-templates by google.
the class TemplateParserTest method testParseMsgStmt.
@Test
public void testParseMsgStmt() throws Exception {
String templateBody = "{@param usedMb :?}{@param learnMoreUrl :?}\n" + " {msg desc=\"Tells user's quota usage.\"}\n" + " You're currently using {$usedMb} MB of your quota.{sp}\n" + " <a href=\"{$learnMoreUrl}\">Learn more</A>\n" + " <br /><br />\n" + " {/msg}\n" + " {msg meaning=\"noun\" desc=\"\" hidden=\"true\"}Archive{/msg}\n" + " {msg meaning=\"noun\" desc=\"The archive (noun).\"}Archive{/msg}\n" + " {msg meaning=\"verb\" desc=\"\"}Archive{/msg}\n" + " {msg desc=\"\"}Archive{/msg}\n";
List<StandaloneNode> nodes = parseTemplateContent(templateBody, FAIL).getChildren();
assertEquals(5, nodes.size());
MsgNode mn0 = ((MsgFallbackGroupNode) nodes.get(0)).getMsg();
assertEquals("Tells user's quota usage.", mn0.getDesc());
assertEquals(null, mn0.getMeaning());
assertEquals(false, mn0.isHidden());
assertEquals(8, mn0.numChildren());
assertEquals("You're currently using ", ((RawTextNode) mn0.getChild(0)).getRawText());
MsgPlaceholderNode mpn1 = (MsgPlaceholderNode) mn0.getChild(1);
assertEquals("$usedMb", ((PrintNode) mpn1.getChild(0)).getExpr().toSourceString());
assertEquals(" MB of your quota. ", ((RawTextNode) mn0.getChild(2)).getRawText());
MsgPlaceholderNode mpn3 = (MsgPlaceholderNode) mn0.getChild(3);
MsgHtmlTagNode mhtn3 = (MsgHtmlTagNode) mpn3.getChild(0);
assertEquals("a", mhtn3.getLcTagName());
assertEquals("START_LINK", mhtn3.genBasePhName());
assertEquals("<a href=\"{$learnMoreUrl}\">", mhtn3.toSourceString());
assertEquals(3, mhtn3.numChildren());
assertEquals("<a href=\"", ((RawTextNode) mhtn3.getChild(0)).getRawText());
assertEquals("$learnMoreUrl", ((PrintNode) mhtn3.getChild(1)).getExpr().toSourceString());
assertEquals("\">", ((RawTextNode) mhtn3.getChild(2)).getRawText());
assertEquals("Learn more", ((RawTextNode) mn0.getChild(4)).getRawText());
MsgPlaceholderNode mpn5 = (MsgPlaceholderNode) mn0.getChild(5);
MsgHtmlTagNode mhtn5 = (MsgHtmlTagNode) mpn5.getChild(0);
assertEquals("/a", mhtn5.getLcTagName());
assertEquals("END_LINK", mhtn5.genBasePhName());
assertEquals("</A>", mhtn5.toSourceString());
MsgPlaceholderNode mpn6 = (MsgPlaceholderNode) mn0.getChild(6);
MsgHtmlTagNode mhtn6 = (MsgHtmlTagNode) mpn6.getChild(0);
assertEquals("BREAK", mhtn6.genBasePhName());
assertTrue(mpn6.shouldUseSameVarNameAs((MsgPlaceholderNode) mn0.getChild(7)));
assertFalse(mpn6.shouldUseSameVarNameAs(mpn5));
assertFalse(mpn5.shouldUseSameVarNameAs(mpn3));
MsgFallbackGroupNode mfgn1 = (MsgFallbackGroupNode) nodes.get(1);
assertEquals("{msg meaning=\"noun\" desc=\"\" hidden=\"true\"}Archive{/msg}", mfgn1.toSourceString());
MsgNode mn1 = mfgn1.getMsg();
assertEquals("", mn1.getDesc());
assertEquals("noun", mn1.getMeaning());
assertEquals(true, mn1.isHidden());
assertEquals(1, mn1.numChildren());
assertEquals("Archive", ((RawTextNode) mn1.getChild(0)).getRawText());
}
use of com.google.template.soy.soytree.MsgHtmlTagNode in project closure-templates by google.
the class InsertMsgsVisitorTest method testBasicMsgsUsingMsgBundle.
@Test
public void testBasicMsgsUsingMsgBundle() {
SoyFileSetNode soyTree = SoyFileSetParserBuilder.forFileContents(BASIC_TEST_FILE_CONTENT).parse().fileSet();
TemplateNode template = (TemplateNode) SharedTestUtils.getNode(soyTree);
// Before.
assertThat(template.numChildren()).isEqualTo(5);
MsgNode msg = ((MsgFallbackGroupNode) template.getChild(2)).getChild(0);
assertThat(msg.numChildren()).isEqualTo(5);
MsgHtmlTagNode msgHtmlTag2 = (MsgHtmlTagNode) ((MsgPlaceholderNode) msg.getChild(2)).getChild(0);
assertThat(msgHtmlTag2.numChildren()).isEqualTo(3);
MsgHtmlTagNode msgHtmlTag4 = (MsgHtmlTagNode) ((MsgPlaceholderNode) msg.getChild(4)).getChild(0);
assertThat(msgHtmlTag4.numChildren()).isEqualTo(1);
assertThat(((RawTextNode) msgHtmlTag4.getChild(0)).getRawText()).isEqualTo("</a>");
// Build the translated message bundle.
List<SoyMsg> translatedMsgs = Lists.newArrayList();
// Original (en): random{{FOO}}{{START_LINK}}slimy{{END_LINK}}
// Translation (x-zz): {{START_LINK}}zslimy{{END_LINK}}{{FOO}}zrandom
translatedMsgs.add(SoyMsg.builder().setId(MsgUtils.computeMsgIdForDualFormat(msg)).setLocaleString("x-zz").setParts(ImmutableList.of(new SoyMsgPlaceholderPart("START_LINK", /* placeholderExample= */
null), SoyMsgRawTextPart.of("zslimy"), new SoyMsgPlaceholderPart("END_LINK", /* placeholderExample= */
null), new SoyMsgPlaceholderPart("FOO", /* placeholderExample= */
null), SoyMsgRawTextPart.of("zrandom"))).build());
// Note: This bundle has no translation for the message "dairy{$moo}".
SoyMsgBundle msgBundle = new SoyMsgBundleImpl("x-zz", translatedMsgs);
// Execute the visitor.
new InsertMsgsVisitor(msgBundle, FAIL).insertMsgs(template);
// After.
assertThat(template.numChildren()).isEqualTo(12);
assertThat(((PrintNode) template.getChild(0)).getExpr().toSourceString()).isEqualTo("$boo");
assertThat(((RawTextNode) template.getChild(1)).getRawText()).isEqualTo("scary ");
assertThat(((RawTextNode) template.getChild(2)).getRawText()).isEqualTo("<a href=\"");
assertThat(((PrintNode) template.getChild(3)).getExpr().toSourceString()).isEqualTo("$goo");
assertThat(((RawTextNode) template.getChild(4)).getRawText()).isEqualTo("\">");
assertThat(((RawTextNode) template.getChild(5)).getRawText()).isEqualTo("zslimy");
assertThat(((RawTextNode) template.getChild(6)).getRawText()).isEqualTo("</a>");
assertThat(((PrintNode) template.getChild(7)).getExpr().toSourceString()).isEqualTo("$foo");
assertThat(((RawTextNode) template.getChild(8)).getRawText()).isEqualTo("zrandom");
assertThat(((RawTextNode) template.getChild(9)).getRawText()).isEqualTo(" ");
assertThat(((RawTextNode) template.getChild(10)).getRawText()).isEqualTo("dairy");
assertThat(((PrintNode) template.getChild(11)).getExpr().toSourceString()).isEqualTo("$moo");
}
use of com.google.template.soy.soytree.MsgHtmlTagNode in project closure-templates by google.
the class InsertMsgsVisitor method buildReplacementNodesFromTranslation.
/**
* Private helper for visitMsgFallbackGroupNode() to build the list of replacement nodes for a
* message from its translation.
*/
private void buildReplacementNodesFromTranslation(MsgNode msg, SoyMsg translation) {
currReplacementNodes = Lists.newArrayList();
for (SoyMsgPart msgPart : translation.getParts()) {
if (msgPart instanceof SoyMsgRawTextPart) {
// Append a new RawTextNode to the currReplacementNodes list.
String rawText = ((SoyMsgRawTextPart) msgPart).getRawText();
currReplacementNodes.add(new RawTextNode(nodeIdGen.genId(), rawText, msg.getSourceLocation()));
} else if (msgPart instanceof SoyMsgPlaceholderPart) {
// Get the representative placeholder node and iterate through its contents.
String placeholderName = ((SoyMsgPlaceholderPart) msgPart).getPlaceholderName();
MsgPlaceholderNode placeholderNode = msg.getRepPlaceholderNode(placeholderName);
for (StandaloneNode contentNode : placeholderNode.getChildren()) {
// simply add the content node to the currReplacementNodes list being built.
if (contentNode instanceof MsgHtmlTagNode) {
currReplacementNodes.addAll(((MsgHtmlTagNode) contentNode).getChildren());
} else {
currReplacementNodes.add(contentNode);
}
}
} else {
throw new AssertionError();
}
}
}
use of com.google.template.soy.soytree.MsgHtmlTagNode in project closure-templates by google.
the class GenJsCodeVisitorAssistantForMsgs method genGoogMsgPlaceholder.
/**
* Returns a code chunk for the given placeholder node.
*/
protected CodeChunk.WithValue genGoogMsgPlaceholder(MsgPlaceholderNode msgPhNode) {
List<CodeChunk.WithValue> contentChunks = new ArrayList<>();
for (StandaloneNode contentNode : msgPhNode.getChildren()) {
if (contentNode instanceof MsgHtmlTagNode && !isComputableAsJsExprsVisitor.exec(contentNode)) {
// This is a MsgHtmlTagNode that is not computable as JS expressions. Visit it to
// generate code to define the 'htmlTag<n>' variable.
visit(contentNode);
contentChunks.add(id("htmlTag" + contentNode.getId()));
} else if (contentNode instanceof CallNode) {
// If the CallNode has any CallParamContentNode children that are not computable as JS
// expressions, visit them to generate code to define their respective 'param<n>' variables.
CallNode callNode = (CallNode) contentNode;
for (CallParamNode grandchild : callNode.getChildren()) {
if (grandchild instanceof CallParamContentNode && !isComputableAsJsExprsVisitor.exec(grandchild)) {
visit(grandchild);
}
}
CodeChunk.WithValue call = genCallCodeUtils.gen(callNode, templateAliases, translationContext, errorReporter);
contentChunks.add(call);
} else {
List<CodeChunk.WithValue> chunks = genJsExprsVisitor.exec(contentNode);
contentChunks.add(CodeChunkUtils.concatChunks(chunks));
}
}
return CodeChunkUtils.concatChunks(contentChunks);
}
Aggregations