| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package freemarker.core; |
| |
| import static org.junit.Assert.*; |
| |
| import java.io.IOException; |
| import java.io.StringWriter; |
| import java.io.Writer; |
| import java.util.Collections; |
| |
| import org.junit.Test; |
| |
| import com.google.common.collect.ImmutableList; |
| |
| import freemarker.cache.ConditionalTemplateConfigurationFactory; |
| import freemarker.cache.FileNameGlobMatcher; |
| import freemarker.cache.OrMatcher; |
| import freemarker.template.Configuration; |
| import freemarker.template.Template; |
| import freemarker.template.TemplateException; |
| import freemarker.template.TemplateModelException; |
| import freemarker.template.Version; |
| import freemarker.test.TemplateTest; |
| |
| public class OutputFormatTest extends TemplateTest { |
| |
| @Test |
| public void testOutputFormatSettingLayers() throws Exception { |
| addTemplate("t", "${.outputFormat}"); |
| addTemplate("t.xml", "${.outputFormat}"); |
| addTemplate("tWithHeader", "<#ftl outputFormat='HTML'>${.outputFormat}"); |
| |
| Configuration cfg = getConfiguration(); |
| for (OutputFormat cfgOutputFormat |
| : new OutputFormat[] { UndefinedOutputFormat.INSTANCE, RTFOutputFormat.INSTANCE } ) { |
| if (!cfgOutputFormat.equals(UndefinedOutputFormat.INSTANCE)) { |
| cfg.setOutputFormat(cfgOutputFormat); |
| } |
| |
| assertEquals(cfgOutputFormat, cfg.getOutputFormat()); |
| |
| { |
| Template t = cfg.getTemplate("t"); |
| assertEquals(cfgOutputFormat, t.getOutputFormat()); |
| assertOutput(t, t.getOutputFormat().getName()); |
| } |
| |
| { |
| Template t = cfg.getTemplate("t.xml"); |
| assertEquals(XMLOutputFormat.INSTANCE, t.getOutputFormat()); |
| assertOutput(t, t.getOutputFormat().getName()); |
| } |
| |
| { |
| Template t = cfg.getTemplate("tWithHeader"); |
| assertEquals(HTMLOutputFormat.INSTANCE, t.getOutputFormat()); |
| assertOutput(t, t.getOutputFormat().getName()); |
| } |
| |
| cfg.clearTemplateCache(); |
| } |
| } |
| |
| @Test |
| public void testStandardFileExtensions() throws Exception { |
| String commonContent = "${.outputFormat}"; |
| addTemplate("t", commonContent); |
| addTemplate("t.ftl", commonContent); |
| addTemplate("t.ftlh", commonContent); |
| addTemplate("t.FTLH", commonContent); |
| addTemplate("t.fTlH", commonContent); |
| addTemplate("t.ftlx", commonContent); |
| addTemplate("t.FTLX", commonContent); |
| addTemplate("t.fTlX", commonContent); |
| addTemplate("tWithHeader.ftlx", "<#ftl outputFormat='HTML'>" + commonContent); |
| |
| Configuration cfg = getConfiguration(); |
| for (int setupNumber = 1; setupNumber <= 5; setupNumber++) { |
| final OutputFormat cfgOutputFormat; |
| final OutputFormat ftlhOutputFormat; |
| final OutputFormat ftlxOutputFormat; |
| switch (setupNumber) { |
| case 1: |
| cfgOutputFormat = UndefinedOutputFormat.INSTANCE; |
| ftlhOutputFormat = HTMLOutputFormat.INSTANCE; |
| ftlxOutputFormat = XMLOutputFormat.INSTANCE; |
| break; |
| case 2: |
| cfgOutputFormat = RTFOutputFormat.INSTANCE; |
| cfg.setOutputFormat(cfgOutputFormat); |
| ftlhOutputFormat = HTMLOutputFormat.INSTANCE; |
| ftlxOutputFormat = XMLOutputFormat.INSTANCE; |
| break; |
| case 3: |
| cfgOutputFormat = UndefinedOutputFormat.INSTANCE; |
| cfg.unsetOutputFormat(); |
| TemplateConfiguration tcXml = new TemplateConfiguration(); |
| tcXml.setOutputFormat(XMLOutputFormat.INSTANCE); |
| cfg.setTemplateConfigurations( |
| new ConditionalTemplateConfigurationFactory( |
| new OrMatcher( |
| new FileNameGlobMatcher("*.ftlh"), |
| new FileNameGlobMatcher("*.FTLH"), |
| new FileNameGlobMatcher("*.fTlH")), |
| tcXml)); |
| ftlhOutputFormat = HTMLOutputFormat.INSTANCE; // can't be overidden |
| ftlxOutputFormat = XMLOutputFormat.INSTANCE; |
| break; |
| case 4: |
| cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_23); |
| cfgOutputFormat = UndefinedOutputFormat.INSTANCE; |
| ftlhOutputFormat = XMLOutputFormat.INSTANCE; // now gets overidden |
| ftlxOutputFormat = UndefinedOutputFormat.INSTANCE; |
| break; |
| case 5: |
| cfg.setTemplateConfigurations(null); |
| cfgOutputFormat = UndefinedOutputFormat.INSTANCE; |
| ftlhOutputFormat = UndefinedOutputFormat.INSTANCE; |
| ftlxOutputFormat = UndefinedOutputFormat.INSTANCE; |
| break; |
| default: |
| throw new AssertionError(); |
| } |
| |
| assertEquals(cfgOutputFormat, cfg.getOutputFormat()); |
| |
| { |
| Template t = cfg.getTemplate("t"); |
| assertEquals(cfgOutputFormat, t.getOutputFormat()); |
| assertOutput(t, t.getOutputFormat().getName()); |
| } |
| |
| { |
| Template t = cfg.getTemplate("t.ftl"); |
| assertEquals(cfgOutputFormat, t.getOutputFormat()); |
| assertOutput(t, t.getOutputFormat().getName()); |
| } |
| |
| for (String name : new String[] { "t.ftlh", "t.FTLH", "t.fTlH" }) { |
| Template t = cfg.getTemplate(name); |
| assertEquals(ftlhOutputFormat, t.getOutputFormat()); |
| assertOutput(t, t.getOutputFormat().getName()); |
| } |
| |
| for (String name : new String[] { "t.ftlx", "t.FTLX", "t.fTlX" }) { |
| Template t = cfg.getTemplate(name); |
| assertEquals(ftlxOutputFormat, t.getOutputFormat()); |
| assertOutput(t, t.getOutputFormat().getName()); |
| } |
| |
| { |
| Template t = cfg.getTemplate("tWithHeader.ftlx"); |
| assertEquals(HTMLOutputFormat.INSTANCE, t.getOutputFormat()); |
| assertOutput(t, t.getOutputFormat().getName()); |
| } |
| |
| cfg.clearTemplateCache(); |
| } |
| } |
| |
| @Test |
| public void testStandardFileExtensionsSettingOverriding() throws Exception { |
| addTemplate("t.ftlx", |
| "${\"'\"} ${\"'\"?esc} ${\"'\"?noEsc}"); |
| addTemplate("t.ftl", |
| "${'{}'} ${'{}'?esc} ${'{}'?noEsc}"); |
| |
| TemplateConfiguration tcHTML = new TemplateConfiguration(); |
| tcHTML.setOutputFormat(HTMLOutputFormat.INSTANCE); |
| ConditionalTemplateConfigurationFactory tcfHTML = new ConditionalTemplateConfigurationFactory( |
| new FileNameGlobMatcher("t.*"), tcHTML); |
| |
| TemplateConfiguration tcNoAutoEsc = new TemplateConfiguration(); |
| tcNoAutoEsc.setAutoEscapingPolicy(Configuration.DISABLE_AUTO_ESCAPING_POLICY); |
| ConditionalTemplateConfigurationFactory tcfNoAutoEsc = new ConditionalTemplateConfigurationFactory( |
| new FileNameGlobMatcher("t.*"), tcNoAutoEsc); |
| |
| Configuration cfg = getConfiguration(); |
| cfg.setOutputFormat(HTMLOutputFormat.INSTANCE); |
| assertOutputForNamed("t.ftlx", "' ' '"); // Can't override it |
| cfg.setTemplateConfigurations(tcfHTML); |
| assertOutputForNamed("t.ftlx", "' ' '"); // Can't override it |
| cfg.setTemplateConfigurations(tcfNoAutoEsc); |
| assertOutputForNamed("t.ftlx", "' ' '"); // Can't override it |
| |
| cfg.setTemplateConfigurations(null); |
| cfg.unsetOutputFormat(); |
| cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_23); // Extensions has no effect |
| assertErrorContainsForNamed("t.ftlx", UndefinedOutputFormat.INSTANCE.getName()); |
| cfg.setOutputFormat(HTMLOutputFormat.INSTANCE); |
| assertOutputForNamed("t.ftlx", "' ' '"); |
| cfg.setOutputFormat(XMLOutputFormat.INSTANCE); |
| assertOutputForNamed("t.ftlx", "' ' '"); |
| cfg.setTemplateConfigurations(tcfHTML); |
| assertOutputForNamed("t.ftlx", "' ' '"); |
| cfg.setTemplateConfigurations(tcfNoAutoEsc); |
| assertOutputForNamed("t.ftlx", "' ' '"); |
| |
| cfg.setRecognizeStandardFileExtensions(true); |
| cfg.setTemplateConfigurations(tcfHTML); |
| assertOutputForNamed("t.ftlx", "' ' '"); // Can't override it |
| cfg.setTemplateConfigurations(tcfNoAutoEsc); |
| assertOutputForNamed("t.ftlx", "' ' '"); // Can't override it |
| |
| cfg.setTemplateConfigurations(null); |
| cfg.unsetOutputFormat(); |
| cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_24); |
| cfg.setTemplateConfigurations(tcfHTML); |
| assertOutputForNamed("t.ftlx", "' ' '"); // Can't override it |
| cfg.setRecognizeStandardFileExtensions(false); |
| assertOutputForNamed("t.ftlx", "' ' '"); |
| } |
| |
| @Test |
| public void testStandardFileExtensionsWithConstructor() throws Exception { |
| Configuration cfg = getConfiguration(); |
| String commonFTL = "${'\\''}"; |
| { |
| Template t = new Template("foo.ftl", commonFTL, cfg); |
| assertSame(UndefinedOutputFormat.INSTANCE, t.getOutputFormat()); |
| StringWriter out = new StringWriter(); |
| t.process(null, out); |
| assertEquals("'", out.toString()); |
| } |
| { |
| Template t = new Template("foo.ftlx", commonFTL, cfg); |
| assertSame(XMLOutputFormat.INSTANCE, t.getOutputFormat()); |
| StringWriter out = new StringWriter(); |
| t.process(null, out); |
| assertEquals("'", out.toString()); |
| } |
| { |
| Template t = new Template("foo.ftlh", commonFTL, cfg); |
| assertSame(HTMLOutputFormat.INSTANCE, t.getOutputFormat()); |
| StringWriter out = new StringWriter(); |
| t.process(null, out); |
| assertEquals("'", out.toString()); |
| } |
| |
| cfg.setIncompatibleImprovements(Configuration.VERSION_2_3_23); |
| { |
| Template t = new Template("foo.ftlx", commonFTL, cfg); |
| assertSame(UndefinedOutputFormat.INSTANCE, t.getOutputFormat()); |
| StringWriter out = new StringWriter(); |
| t.process(null, out); |
| assertEquals("'", out.toString()); |
| } |
| } |
| |
| @Test |
| public void testStandardFileExtensionsFormatterImplOverriding() throws Exception { |
| addTemplate("t.ftlh", "${'a&x'}"); |
| assertOutputForNamed("t.ftlh", "a&x"); |
| getConfiguration().setRegisteredCustomOutputFormats(Collections.singleton(CustomHTMLOutputFormat.INSTANCE)); |
| assertOutputForNamed("t.ftlh", "a&X"); |
| getConfiguration().setRegisteredCustomOutputFormats(Collections.<OutputFormat>emptyList()); |
| assertOutputForNamed("t.ftlh", "a&x"); |
| } |
| |
| @Test |
| public void testAutoEscapingSettingLayers() throws Exception { |
| addTemplate("t", "${'a&b'}"); |
| addTemplate("tWithHeaderFalse", "<#ftl autoEsc=false>${'a&b'}"); |
| addTemplate("tWithHeaderTrue", "<#ftl autoEsc=true>${'a&b'}"); |
| |
| Configuration cfg = getConfiguration(); |
| |
| assertEquals(Configuration.ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY, cfg.getAutoEscapingPolicy()); |
| |
| cfg.setOutputFormat(XMLOutputFormat.INSTANCE); |
| |
| for (boolean cfgAutoEscaping : new boolean[] { true, false }) { |
| if (!cfgAutoEscaping) { |
| cfg.setAutoEscapingPolicy(Configuration.DISABLE_AUTO_ESCAPING_POLICY); |
| } |
| |
| { |
| Template t = cfg.getTemplate("t"); |
| if (cfgAutoEscaping) { |
| assertTrue(t.getAutoEscaping()); |
| assertOutput(t, "a&b"); |
| } else { |
| assertFalse(t.getAutoEscaping()); |
| assertOutput(t, "a&b"); |
| } |
| } |
| |
| { |
| Template t = cfg.getTemplate("tWithHeaderFalse"); |
| assertFalse(t.getAutoEscaping()); |
| assertOutput(t, "a&b"); |
| } |
| |
| { |
| Template t = cfg.getTemplate("tWithHeaderTrue"); |
| assertTrue(t.getAutoEscaping()); |
| assertOutput(t, "a&b"); |
| } |
| |
| cfg.clearTemplateCache(); |
| } |
| } |
| |
| @Test |
| public void testNumericalInterpolation() throws IOException, TemplateException { |
| getConfiguration().setRegisteredCustomOutputFormats(Collections.singleton(DummyOutputFormat.INSTANCE)); |
| assertOutput( |
| "<#ftl outputFormat='dummy'>#{1.5}; #{1.5; m3}; ${'a.b'}", |
| "1\\.5; 1\\.500; a\\.b"); |
| assertOutput( |
| "<#ftl outputFormat='dummy' autoEsc=false>#{1.5}; #{1.5; m3}; ${'a.b'}; ${'a.b'?esc}", |
| "1.5; 1.500; a.b; a\\.b"); |
| assertOutput("<#ftl outputFormat='plainText'>#{1.5}", "1.5"); |
| assertOutput("<#ftl outputFormat='HTML'>#{1.5}", "1.5"); |
| assertOutput("#{1.5}", "1.5"); |
| } |
| |
| @Test |
| public void testUndefinedOutputFormat() throws IOException, TemplateException { |
| assertOutput("${'a < b'}; ${htmlPlain}; ${htmlMarkup}", "a < b; a < {h'}; <p>c"); |
| assertErrorContains("${'x'?esc}", "undefined", "escaping", "?esc"); |
| assertErrorContains("${'x'?noEsc}", "undefined", "escaping", "?noEsc"); |
| } |
| |
| @Test |
| public void testPlainTextOutputFormat() throws IOException, TemplateException { |
| assertOutput("<#ftl outputFormat='plainText'>${'a < b'}; ${htmlPlain}", "a < b; a < {h'}"); |
| assertErrorContains("<#ftl outputFormat='plainText'>${htmlMarkup}", "plainText", "HTML", "conversion"); |
| assertErrorContains("<#ftl outputFormat='plainText'>${'x'?esc}", "plainText", "escaping", "?esc"); |
| assertErrorContains("<#ftl outputFormat='plainText'>${'x'?noEsc}", "plainText", "escaping", "?noEsc"); |
| } |
| |
| @Test |
| public void testAutoEscapingOnMOs() throws IOException, TemplateException { |
| for (int autoEsc = 0; autoEsc < 2; autoEsc++) { |
| String commonAutoEscFtl = "<#ftl outputFormat='HTML'>${'&'}"; |
| if (autoEsc == 0) { |
| // Cfg default is autoEscaping true |
| assertOutput(commonAutoEscFtl, "&"); |
| } else { |
| getConfiguration().setAutoEscapingPolicy(Configuration.DISABLE_AUTO_ESCAPING_POLICY); |
| assertOutput(commonAutoEscFtl, "&"); |
| } |
| |
| assertOutput( |
| "<#ftl outputFormat='RTF'>" |
| + "${rtfPlain} ${rtfMarkup} " |
| + "${htmlPlain} " |
| + "${xmlPlain}", |
| "\\\\par a & b \\par c " |
| + "a < \\{h'\\} " |
| + "a < \\{x'\\}"); |
| assertOutput( |
| "<#ftl outputFormat='HTML'>" |
| + "${htmlPlain} ${htmlMarkup} " |
| + "${xmlPlain} " |
| + "${rtfPlain}", |
| "a < {h'} <p>c " |
| + "a < {x'} " |
| + "\\par a & b"); |
| assertOutput( |
| "<#ftl outputFormat='XML'>" |
| + "${xmlPlain} ${xmlMarkup} " |
| + "${htmlPlain} " |
| + "${rtfPlain}", |
| "a < {x'} <p>c</p> " |
| + "a < {h'} " |
| + "\\par a & b"); |
| assertErrorContains("<#ftl outputFormat='RTF'>${htmlMarkup}", "output format", "RTF", "HTML"); |
| assertErrorContains("<#ftl outputFormat='RTF'>${xmlMarkup}", "output format", "RTF", "XML"); |
| assertErrorContains("<#ftl outputFormat='HTML'>${rtfMarkup}", "output format", "HTML", "RTF"); |
| assertErrorContains("<#ftl outputFormat='HTML'>${xmlMarkup}", "output format", "HTML", "XML"); |
| assertErrorContains("<#ftl outputFormat='XML'>${rtfMarkup}", "output format", "XML", "RTF"); |
| assertErrorContains("<#ftl outputFormat='XML'>${htmlMarkup}", "output format", "XML", "HTML"); |
| |
| for (int hasHeader = 0; hasHeader < 2; hasHeader++) { |
| assertOutput( |
| (hasHeader == 1 ? "<#ftl outputFormat='undefined'>" : "") |
| + "${xmlPlain} ${xmlMarkup} " |
| + "${htmlPlain} ${htmlMarkup} " |
| + "${rtfPlain} ${rtfMarkup}", |
| "a < {x'} <p>c</p> " |
| + "a < {h'} <p>c " |
| + "\\\\par a & b \\par c"); |
| } |
| } |
| } |
| |
| @Test |
| public void testStringLiteralsUseUndefinedOF() throws IOException, TemplateException { |
| String expectedOut = "& (&) &"; |
| String ftl = "<#ftl outputFormat='XML'>${'&'} ${\"(${'&'})\"?noEsc} ${'&'}"; |
| |
| assertOutput(ftl, expectedOut); |
| |
| addTemplate("t.xml", ftl); |
| assertOutputForNamed("t.xml", expectedOut); |
| } |
| |
| @Test |
| public void testUnparsedTemplate() throws IOException, TemplateException { |
| String content = "<#ftl>a<#foo>b${x}"; |
| { |
| Template t = Template.getPlainTextTemplate("x", content, getConfiguration()); |
| Writer sw = new StringWriter(); |
| t.process(null, sw); |
| assertEquals(content, sw.toString()); |
| assertEquals(UndefinedOutputFormat.INSTANCE, t.getOutputFormat()); |
| } |
| |
| { |
| getConfiguration().setOutputFormat(HTMLOutputFormat.INSTANCE); |
| Template t = Template.getPlainTextTemplate("x", content, getConfiguration()); |
| Writer sw = new StringWriter(); |
| t.process(null, sw); |
| assertEquals(content, sw.toString()); |
| assertEquals(HTMLOutputFormat.INSTANCE, t.getOutputFormat()); |
| } |
| } |
| |
| @Test |
| public void testStringLiteralInterpolation() throws IOException, TemplateException { |
| Template t = new Template(null, "<#ftl outputFormat='XML'>${'&'} ${\"(${'&'})\"?noEsc}", getConfiguration()); |
| assertEquals(XMLOutputFormat.INSTANCE, t.getOutputFormat()); |
| |
| assertOutput("${.outputFormat} ${'${.outputFormat}'} ${.outputFormat}", |
| "undefined undefined undefined"); |
| assertOutput("<#ftl outputFormat='HTML'>${.outputFormat} ${'${.outputFormat}'} ${.outputFormat}", |
| "HTML HTML HTML"); |
| assertOutput("${.outputFormat} <#outputFormat 'XML'>${'${.outputFormat}'}</#outputFormat> ${.outputFormat}", |
| "undefined XML undefined"); |
| assertOutput("${'foo ${xmlPlain}'}", "foo a < {x'}"); |
| assertOutput("${'${xmlMarkup}'}", "<p>c</p>"); |
| assertErrorContains("${'${\"x\"?esc}'}", "?esc", "undefined"); |
| assertOutput("<#ftl outputFormat='XML'>${'${xmlMarkup?esc} ${\"<\"?esc} ${\">\"} ${\"&\"?noEsc}'}", |
| "<p>c</p> < > &"); |
| } |
| |
| @Test |
| public void testStringBIsFail() { |
| assertErrorContains("<#ftl outputFormat='HTML'>${'<b>foo</b>'?esc?upperCase}", "string", "markup_output"); |
| } |
| |
| @Test |
| public void testConcatWithMOs() throws IOException, TemplateException { |
| assertOutput( |
| "${'\\'' + htmlMarkup} ${htmlMarkup + '\\''} ${htmlMarkup + htmlMarkup}", |
| "'<p>c <p>c' <p>c<p>c"); |
| assertOutput( |
| "${'\\'' + htmlPlain} ${htmlPlain + '\\''} ${htmlPlain + htmlPlain}", |
| "'a < {h'} a < {h'}' a < {h'}a < {h'}"); |
| assertErrorContains( |
| "<#ftl outputFormat='XML'>${'\\'' + htmlMarkup}", |
| "HTML", "XML", "conversion"); |
| assertErrorContains( |
| "${xmlMarkup + htmlMarkup}", |
| "HTML", "XML", "Conversion", "common"); |
| assertOutput( |
| "${xmlMarkup + htmlPlain}", |
| "<p>c</p>a < {h'}"); |
| assertOutput( |
| "${xmlPlain + htmlMarkup}", |
| "a < {x'}<p>c"); |
| assertOutput( |
| "${xmlPlain + htmlPlain}", |
| "a < {x'}a < {h'}"); |
| assertOutput( |
| "${xmlPlain + htmlPlain + '\\''}", |
| "a < {x'}a < {h'}'"); |
| assertOutput( |
| "${htmlPlain + xmlPlain + '\\''}", |
| "a < {h'}a < {x'}'"); |
| assertOutput( |
| "${xmlPlain + htmlPlain + '\\''}", |
| "a < {x'}a < {h'}'"); |
| assertOutput( |
| "<#ftl outputFormat='XML'>${htmlPlain + xmlPlain + '\\''}", |
| "a < {h'}a < {x'}'"); |
| assertOutput( |
| "<#ftl outputFormat='RTF'>${htmlPlain + xmlPlain + '\\''}", |
| "a < \\{h'\\}a < \\{x'\\}'"); |
| assertOutput( |
| "<#ftl outputFormat='XML'>${'\\'' + htmlPlain}", |
| "'a < {h'}"); |
| assertOutput( |
| "<#ftl outputFormat='HTML'>${'\\'' + htmlPlain}", |
| "'a < {h'}"); |
| assertOutput( |
| "<#ftl outputFormat='HTML'>${'\\'' + xmlPlain}", |
| "'a < {x'}"); |
| assertOutput( |
| "<#ftl outputFormat='RTF'>${'\\'' + xmlPlain}", |
| "'a < \\{x'\\}"); |
| |
| assertOutput( |
| "<#assign x = '\\''><#assign x += xmlMarkup>${x}", |
| "'<p>c</p>"); |
| assertOutput( |
| "<#assign x = xmlMarkup><#assign x += '\\''>${x}", |
| "<p>c</p>'"); |
| assertOutput( |
| "<#assign x = xmlMarkup><#assign x += htmlPlain>${x}", |
| "<p>c</p>a < {h'}"); |
| assertErrorContains( |
| "<#assign x = xmlMarkup><#assign x += htmlMarkup>${x}", |
| "HTML", "XML", "Conversion", "common"); |
| } |
| |
| @Test |
| public void testBlockAssignment() throws Exception { |
| for (String d : new String[] { "assign", "global", "local" }) { |
| String commonFTL = |
| "<#macro m>" |
| + "<#" + d + " x><p>${'&'}</#" + d + ">${x?isString?c} ${x} ${'&'} " |
| + "<#" + d + " x></#" + d + ">${x?isString?c}" |
| + "</#macro><@m />"; |
| assertOutput( |
| commonFTL, |
| "true <p>& & true"); |
| assertOutput( |
| "<#ftl outputFormat='HTML'>" + commonFTL, |
| "false <p>& & false"); |
| } |
| } |
| |
| @Test |
| public void testSpecialVariables() throws Exception { |
| String commonFTL = "${.outputFormat} ${.autoEsc?c}"; |
| |
| addTemplate("t.ftlx", commonFTL); |
| assertOutputForNamed("t.ftlx", "XML true"); |
| |
| addTemplate("t.ftlh", commonFTL); |
| assertOutputForNamed("t.ftlh", "HTML true"); |
| |
| addTemplate("t.ftl", commonFTL); |
| assertOutputForNamed("t.ftl", "undefined false"); |
| |
| addTemplate("tX.ftl", "<#ftl outputFormat='XML'>" + commonFTL); |
| addTemplate("tX.ftlx", commonFTL); |
| assertOutputForNamed("t.ftlx", "XML true"); |
| |
| addTemplate("tN.ftl", "<#ftl outputFormat='RTF' autoEsc=false>" + commonFTL); |
| assertOutputForNamed("tN.ftl", "RTF false"); |
| |
| assertOutput("${.output_format} ${.auto_esc?c}", "undefined false"); |
| } |
| |
| @Test |
| public void testEscAndNoEscBIBasics() throws IOException, TemplateException { |
| String commonFTL = "${'<x>'} ${'<x>'?esc} ${'<x>'?noEsc}"; |
| addTemplate("t.ftlh", commonFTL); |
| addTemplate("t-noAuto.ftlh", "<#ftl autoEsc=false>" + commonFTL); |
| addTemplate("t.ftl", commonFTL); |
| assertOutputForNamed("t.ftlh", "<x> <x> <x>"); |
| assertOutputForNamed("t-noAuto.ftlh", "<x> <x> <x>"); |
| assertErrorContainsForNamed("t.ftl", "output format", "undefined"); |
| } |
| |
| @Test |
| public void testEscAndNoEscBIsOnMOs() throws IOException, TemplateException { |
| String xmlHdr = "<#ftl outputFormat='XML'>"; |
| |
| assertOutput( |
| xmlHdr + "${'&'?esc?esc} ${'&'?esc?noEsc} ${'&'?noEsc?esc} ${'&'?noEsc?noEsc}", |
| "& & & &"); |
| |
| for (String bi : new String[] { "esc", "noEsc" } ) { |
| assertOutput( |
| xmlHdr + "${rtfPlain?" + bi + "}", |
| "\\par a & b"); |
| assertOutput( |
| xmlHdr + "<#setting numberFormat='0.0'>${1?" + bi + "}", |
| "1.0"); |
| assertOutput( |
| xmlHdr + "<#setting booleanFormat='&y,&n'>${true?" + bi + "}", |
| bi.equals("esc") ? "&y" : "&y"); |
| assertErrorContains( |
| xmlHdr + "${rtfMarkup?" + bi + "}", |
| "?" + bi, "output format", "RTF", "XML"); |
| assertErrorContains( |
| xmlHdr + "${noSuchVar?" + bi + "}", |
| "noSuchVar", "null or missing"); |
| assertErrorContains( |
| xmlHdr + "${[]?" + bi + "}", |
| "?" + bi, "xpected", "string", "sequence"); |
| } |
| } |
| |
| @Test |
| public void testMarkupStringBI() throws Exception { |
| assertOutput( |
| "${htmlPlain?markupString} ${htmlMarkup?markupString}", |
| "a < {h'} <p>c"); |
| assertErrorContains( |
| "${noSuchVar?markupString}", |
| "noSuchVar", "null or missing"); |
| assertErrorContains( |
| "${'x'?markupString}", |
| "xpected", "markup output", "string"); |
| } |
| |
| @Test |
| public void testOutputFormatDirective() throws Exception { |
| assertOutput( |
| "${.outputFormat}${'\\''} " |
| + "<#outputFormat 'HTML'>" |
| + "${.outputFormat}${'\\''} " |
| + "<#outputFormat 'XML'>${.outputFormat}${'\\''}</#outputFormat> " |
| + "${.outputFormat}${'\\''} " |
| + "</#outputFormat>" |
| + "${.outputFormat}${'\\''}", |
| "undefined' HTML' XML' HTML' undefined'"); |
| assertOutput( |
| "<#ftl output_format='XML'>" |
| + "${.output_format}${'\\''} " |
| + "<#outputformat 'HTML'>${.output_format}${'\\''}</#outputformat> " |
| + "${.output_format}${'\\''}", |
| "XML' HTML' XML'"); |
| |
| // Custom format: |
| assertErrorContains( |
| "<#outputFormat 'dummy'></#outputFormat>", |
| "dummy", "nregistered"); |
| getConfiguration().setRegisteredCustomOutputFormats(Collections.singleton(DummyOutputFormat.INSTANCE)); |
| assertOutput( |
| "<#outputFormat 'dummy'>${.outputFormat}</#outputFormat>", |
| "dummy"); |
| |
| // Parse-time param expression: |
| assertOutput( |
| "<#outputFormat 'plain' + 'Text'>${.outputFormat}</#outputFormat>", |
| "plainText"); |
| assertErrorContains( |
| "<#outputFormat 'plain' + someVar + 'Text'></#outputFormat>", |
| "someVar", "parse-time"); |
| assertErrorContains( |
| "<#outputFormat 'plainText'?upperCase></#outputFormat>", |
| "?upperCase", "parse-time"); |
| assertErrorContains( |
| "<#outputFormat true></#outputFormat>", |
| "string", "boolean"); |
| |
| // Naming convention: |
| assertErrorContains( |
| "<#outputFormat 'HTML'></#outputformat>", |
| "convention", "#outputFormat", "#outputformat"); |
| assertErrorContains( |
| "<#outputformat 'HTML'></#outputFormat>", |
| "convention", "#outputFormat", "#outputformat"); |
| |
| // Empty block: |
| assertOutput( |
| "${.output_format} " |
| + "<#outputformat 'HTML'></#outputformat>" |
| + "${.output_format}", |
| "undefined undefined"); |
| |
| // WS stripping: |
| assertOutput( |
| "${.output_format}\n" |
| + "<#outputformat 'HTML'>\n" |
| + " x\n" |
| + "</#outputformat>\n" |
| + "${.output_format}", |
| "undefined\n x\nundefined"); |
| } |
| |
| @Test |
| public void testAutoEscAndNoAutoEscDirectives() throws Exception { |
| assertOutput( |
| "<#ftl outputFormat='XML'>" |
| + "${.autoEsc?c}${'&'} " |
| + "<#noAutoEsc>" |
| + "${.autoEsc?c}${'&'} " |
| + "<#autoEsc>${.autoEsc?c}${'&'}</#autoEsc> " |
| + "${.autoEsc?c}${'&'} " |
| + "</#noAutoEsc>" |
| + "${.autoEsc?c}${'&'}", |
| "true& false& true& false& true&"); |
| assertOutput( |
| "<#ftl auto_esc=false output_format='XML'>" |
| + "${.auto_esc?c}${'&'} " |
| + "<#autoesc>${.auto_esc?c}${'&'}</#autoesc> " |
| + "${.auto_esc?c}${'&'}", |
| "false& true& false&"); |
| |
| // Bad came case: |
| assertErrorContains( |
| "<#noAutoesc></#noAutoesc>", |
| "Unknown directive"); |
| assertErrorContains( |
| "<#noautoEsc></#noautoEsc>", |
| "Unknown directive"); |
| |
| getConfiguration().setOutputFormat(XMLOutputFormat.INSTANCE); |
| |
| // Empty block: |
| assertOutput( |
| "${.auto_esc?c} " |
| + "<#noautoesc></#noautoesc>" |
| + "${.auto_esc?c}", |
| "true true"); |
| |
| // WS stripping: |
| assertOutput( |
| "${.auto_esc?c}\n" |
| + "<#noautoesc>\n" |
| + " x\n" |
| + "</#noautoesc>\n" |
| + "${.auto_esc?c}", |
| "true\n x\ntrue"); |
| |
| |
| // Naming convention: |
| assertErrorContains( |
| "<#autoEsc></#autoesc>", |
| "convention", "#autoEsc", "#autoesc"); |
| assertErrorContains( |
| "<#autoesc></#autoEsc>", |
| "convention", "#autoEsc", "#autoesc"); |
| assertErrorContains( |
| "<#noAutoEsc></#noautoesc>", |
| "convention", "#noAutoEsc", "#noautoesc"); |
| assertErrorContains( |
| "<#noautoesc></#noAutoEsc>", |
| "convention", "#noAutoEsc", "#noautoesc"); |
| } |
| |
| @Test |
| public void testExplicitAutoEscBannedForNonMarkup() throws Exception { |
| // While this restriction is technically unnecessary, we can catch a dangerous and probably common user |
| // misunderstanding. |
| assertErrorContains("<#ftl autoEsc=true>", "can't do escaping", "undefined"); |
| assertErrorContains("<#ftl outputFormat='plainText' autoEsc=true>", "can't do escaping", "plainText"); |
| assertErrorContains("<#ftl autoEsc=true outputFormat='plainText'>", "can't do escaping", "plainText"); |
| assertOutput("<#ftl autoEsc=true outputFormat='HTML'>", ""); |
| assertOutput("<#ftl outputFormat='HTML' autoEsc=true>", ""); |
| assertOutput("<#ftl autoEsc=false>", ""); |
| |
| assertErrorContains("<#autoEsc></#autoEsc>", "can't do escaping", "undefined"); |
| assertErrorContains("<#ftl outputFormat='plainText'><#autoEsc></#autoEsc>", "can't do escaping", "plainText"); |
| assertOutput("<#ftl outputFormat='plainText'><#outputFormat 'XML'><#autoEsc></#autoEsc></#outputFormat>", ""); |
| assertOutput("<#ftl outputFormat='HTML'><#autoEsc></#autoEsc>", ""); |
| assertOutput("<#noAutoEsc></#noAutoEsc>", ""); |
| } |
| |
| @Test |
| public void testAutoEscPolicy() throws Exception { |
| Configuration cfg = getConfiguration(); |
| cfg.setRegisteredCustomOutputFormats(ImmutableList.of( |
| SeldomEscapedOutputFormat.INSTANCE, DummyOutputFormat.INSTANCE)); |
| assertEquals(Configuration.ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY, cfg.getAutoEscapingPolicy()); |
| |
| String commonFTL = "${'.'} ${.autoEsc?c}"; |
| String notEsced = ". false"; |
| String esced = "\\. true"; |
| |
| for (int autoEscPolicy : new int[] { |
| Configuration.ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY, |
| Configuration.ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY, |
| Configuration.DISABLE_AUTO_ESCAPING_POLICY }) { |
| cfg.setAutoEscapingPolicy(autoEscPolicy); |
| |
| String sExpted = autoEscPolicy == Configuration.ENABLE_IF_SUPPORTED_AUTO_ESCAPING_POLICY ? esced : notEsced; |
| cfg.setOutputFormat(SeldomEscapedOutputFormat.INSTANCE); |
| assertOutput(commonFTL, sExpted); |
| cfg.setOutputFormat(UndefinedOutputFormat.INSTANCE); |
| assertOutput("<#ftl outputFormat='seldomEscaped'>" + commonFTL, sExpted); |
| assertOutput("<#outputFormat 'seldomEscaped'>" + commonFTL + "</#outputFormat>", sExpted); |
| |
| String dExpted = autoEscPolicy == Configuration.DISABLE_AUTO_ESCAPING_POLICY ? notEsced : esced; |
| cfg.setOutputFormat(DummyOutputFormat.INSTANCE); |
| assertOutput(commonFTL, dExpted); |
| cfg.setOutputFormat(UndefinedOutputFormat.INSTANCE); |
| assertOutput("<#ftl outputFormat='dummy'>" + commonFTL, dExpted); |
| assertOutput("<#outputFormat 'dummy'>" + commonFTL + "</#outputFormat>", dExpted); |
| |
| cfg.setOutputFormat(DummyOutputFormat.INSTANCE); |
| assertOutput( |
| commonFTL |
| + "<#outputFormat 'seldomEscaped'>" |
| + commonFTL |
| + "<#outputFormat 'dummy'>" |
| + commonFTL |
| + "</#outputFormat>" |
| + commonFTL |
| + "<#outputFormat 'plainText'>" |
| + commonFTL |
| + "</#outputFormat>" |
| + commonFTL |
| + "<#noAutoEsc>" |
| + commonFTL |
| + "</#noAutoEsc>" |
| + commonFTL |
| + "<#autoEsc>" |
| + commonFTL |
| + "</#autoEsc>" |
| + commonFTL |
| + "</#outputFormat>" |
| + commonFTL |
| + "<#noAutoEsc>" |
| + commonFTL |
| + "</#noAutoEsc>" |
| + commonFTL |
| + "<#autoEsc>" |
| + commonFTL |
| + "</#autoEsc>" |
| + commonFTL |
| , |
| dExpted |
| + sExpted |
| + dExpted |
| + sExpted |
| + notEsced |
| + sExpted |
| + notEsced |
| + sExpted |
| + esced |
| + sExpted |
| + dExpted |
| + notEsced |
| + dExpted |
| + esced |
| + dExpted); |
| } |
| } |
| |
| @Test |
| public void testDynamicParsingBIsInherticContextOutputFormat() throws Exception { |
| // Dynamic parser BI-s are supposed to use the parserConfiguration of the calling template, and ignore anything |
| // inside the calling template itself. Except, the outputFormat has to come from the calling lexical context. |
| |
| String commonFTL |
| = "Eval: ${'.outputFormat'?eval}; " |
| + "Interpret: <#assign ipd = r\"${.outputFormat} ${'{&}'}\"?interpret><@ipd/>"; |
| addTemplate("t.ftlh", commonFTL); |
| addTemplate("t2.ftlh", "<#outputFormat 'RTF'>" + commonFTL + "</#outputFormat>"); |
| |
| assertOutputForNamed( |
| "t.ftlh", |
| "Eval: HTML; Interpret: HTML {&}"); |
| assertOutputForNamed( |
| "t2.ftlh", |
| "Eval: RTF; Interpret: RTF \\{&\\}"); |
| assertOutput( |
| commonFTL, |
| "Eval: undefined; Interpret: undefined {&}"); |
| assertOutput( |
| "<#ftl outputFormat='RTF'>" + commonFTL + "\n" |
| + "<#outputFormat 'XML'>" + commonFTL + "</#outputFormat>", |
| "Eval: RTF; Interpret: RTF \\{&\\}\n" |
| + "Eval: XML; Interpret: XML {&}"); |
| |
| // parser.autoEscapingPolicy is inherited too: |
| assertOutput( |
| "<#ftl autoEsc=false outputFormat='XML'>" |
| + commonFTL + " ${'.autoEsc'?eval?c}", |
| "Eval: XML; Interpret: XML {&} false"); |
| assertOutput( |
| "<#ftl outputFormat='XML'>" |
| + "<#noAutoEsc>" + commonFTL + " ${'.autoEsc'?eval?c}</#noAutoEsc>", |
| "Eval: XML; Interpret: XML {&} false"); |
| assertOutput( |
| "<#ftl autoEsc=false outputFormat='XML'>" |
| + "<#noAutoEsc>" + commonFTL + " ${'.autoEsc'?eval?c}</#noAutoEsc>", |
| "Eval: XML; Interpret: XML {&} false"); |
| assertOutput( |
| "<#ftl autoEsc=false outputFormat='XML'>" |
| + "<#autoEsc>" + commonFTL + " ${'.autoEsc'?eval?c}</#autoEsc>", |
| "Eval: XML; Interpret: XML {&} true"); |
| assertOutput( |
| "${.outputFormat}<#assign ftl='<#ftl outputFormat=\\'RTF\\'>$\\{.outputFormat}'> <@ftl?interpret/>", |
| "undefined RTF"); |
| assertOutput( |
| "${.outputFormat}<#outputFormat 'RTF'>" |
| + "<#assign ftl='$\\{.outputFormat}'> <@ftl?interpret/> ${'.outputFormat'?eval}" |
| + "</#outputFormat>", |
| "undefined RTF RTF"); |
| } |
| |
| @Test |
| public void testBannedBIsWhenAutoEscaping() throws Exception { |
| for (String biName : new String[] { "html", "xhtml", "rtf", "xml" }) { |
| for (Version ici : new Version[] { Configuration.VERSION_2_3_0, Configuration.VERSION_2_3_24 }) { |
| getConfiguration().setIncompatibleImprovements(ici); |
| |
| String commonFTL = "${'x'?" + biName + "}"; |
| assertOutput(commonFTL, "x"); |
| assertErrorContains("<#ftl outputFormat='HTML'>" + commonFTL, |
| "?" + biName, "HTML", "double-escaping"); |
| assertErrorContains("<#ftl outputFormat='HTML'>${'${\"x\"?" + biName + "}'}", |
| "?" + biName, "HTML", "double-escaping"); |
| assertOutput("<#ftl outputFormat='plainText'>" + commonFTL, "x"); |
| assertOutput("<#ftl outputFormat='HTML' autoEsc=false>" + commonFTL, "x"); |
| assertOutput("<#ftl outputFormat='HTML'><#noAutoEsc>" + commonFTL + "</#noAutoEsc>", "x"); |
| assertOutput("<#ftl outputFormat='HTML'><#outputFormat 'plainText'>" + commonFTL + "</#outputFormat>", |
| "x"); |
| } |
| } |
| } |
| |
| @Test |
| public void testLegacyEscaperBIsBypassMOs() throws Exception { |
| assertOutput("${htmlPlain?html} ${htmlMarkup?html}", "a < {h'} <p>c"); |
| assertErrorContains("${xmlPlain?html}", "?html", "string", "markup_output", "XML"); |
| assertErrorContains("${xmlMarkup?html}", "?html", "string", "markup_output", "XML"); |
| assertErrorContains("${rtfPlain?html}", "?html", "string", "markup_output", "RTF"); |
| assertErrorContains("${rtfMarkup?html}", "?html", "string", "markup_output", "RTF"); |
| |
| assertOutput("${htmlPlain?xhtml} ${htmlMarkup?xhtml}", "a < {h'} <p>c"); |
| assertErrorContains("${xmlPlain?xhtml}", "?xhtml", "string", "markup_output", "XML"); |
| assertErrorContains("${xmlMarkup?xhtml}", "?xhtml", "string", "markup_output", "XML"); |
| assertErrorContains("${rtfPlain?xhtml}", "?xhtml", "string", "markup_output", "RTF"); |
| assertErrorContains("${rtfMarkup?xhtml}", "?xhtml", "string", "markup_output", "RTF"); |
| |
| assertOutput("${xmlPlain?xml} ${xmlMarkup?xml}", "a < {x'} <p>c</p>"); |
| assertOutput("${htmlPlain?xml} ${htmlMarkup?xml}", "a < {h'} <p>c"); |
| assertErrorContains("${rtfPlain?xml}", "?xml", "string", "markup_output", "RTF"); |
| assertErrorContains("${rtfMarkup?xml}", "?xml", "string", "markup_output", "RTF"); |
| |
| assertOutput("${rtfPlain?rtf} ${rtfMarkup?rtf}", "\\\\par a & b \\par c"); |
| assertErrorContains("${xmlPlain?rtf}", "?rtf", "string", "markup_output", "XML"); |
| assertErrorContains("${xmlMarkup?rtf}", "?rtf", "string", "markup_output", "XML"); |
| assertErrorContains("${htmlPlain?rtf}", "?rtf", "string", "markup_output", "HTML"); |
| assertErrorContains("${htmlMarkup?rtf}", "?rtf", "string", "markup_output", "HTML"); |
| } |
| |
| @Test |
| public void testBannedDirectivesWhenAutoEscaping() throws Exception { |
| String commonFTL = "<#escape x as x?html>x</#escape>"; |
| assertOutput(commonFTL, "x"); |
| assertErrorContains("<#ftl outputFormat='HTML'>" + commonFTL, "escape", "HTML", "double-escaping"); |
| assertOutput("<#ftl outputFormat='plainText'>" + commonFTL, "x"); |
| assertOutput("<#ftl outputFormat='HTML' autoEsc=false>" + commonFTL, "x"); |
| assertOutput("<#ftl outputFormat='HTML'><#noAutoEsc>" + commonFTL + "</#noAutoEsc>", "x"); |
| assertOutput("<#ftl outputFormat='HTML'><#outputFormat 'plainText'>" + commonFTL + "</#outputFormat>", "x"); |
| } |
| |
| @Test |
| public void testCombinedOutputFormats() throws Exception { |
| assertOutput( |
| "<#outputFormat 'XML{HTML}'>${'\\''}</#outputFormat>", |
| "&#39;"); |
| assertOutput( |
| "<#outputFormat 'HTML{RTF{XML}}'>${'<a=\\'{}\\' />'}</#outputFormat>", |
| "&lt;a=&apos;\\{\\}&apos; /&gt;"); |
| |
| String commonFtl = "${'\\''} <#outputFormat '{HTML}'>${'\\''}</#outputFormat>"; |
| String commonOutput = "' &#39;"; |
| assertOutput( |
| "<#outputFormat 'XML'>" + commonFtl + "</#outputFormat>", |
| commonOutput); |
| assertOutput( |
| "<#ftl outputFormat='XML'>" + commonFtl, |
| commonOutput); |
| addTemplate("t.ftlx", commonFtl); |
| assertOutputForNamed( |
| "t.ftlx", |
| commonOutput); |
| |
| assertErrorContains( |
| commonFtl, |
| ParseException.class, "{...}", "markup", UndefinedOutputFormat.INSTANCE.getName()); |
| assertErrorContains( |
| "<#ftl outputFormat='plainText'>" + commonFtl, |
| ParseException.class, "{...}", "markup", PlainTextOutputFormat.INSTANCE.getName()); |
| assertErrorContains( |
| "<#ftl outputFormat='RTF'><#outputFormat '{plainText}'></#outputFormat>", |
| ParseException.class, "{...}", "markup", PlainTextOutputFormat.INSTANCE.getName()); |
| assertErrorContains( |
| "<#ftl outputFormat='RTF'><#outputFormat '{noSuchFormat}'></#outputFormat>", |
| ParseException.class, "noSuchFormat", "registered"); |
| assertErrorContains( |
| "<#outputFormat 'noSuchFormat{HTML}'></#outputFormat>", |
| ParseException.class, "noSuchFormat", "registered"); |
| assertErrorContains( |
| "<#outputFormat 'HTML{noSuchFormat}'></#outputFormat>", |
| ParseException.class, "noSuchFormat", "registered"); |
| } |
| |
| @Test |
| public void testHasContentBI() throws Exception { |
| assertOutput("${htmlMarkup?hasContent?c} ${htmlPlain?hasContent?c}", "true true"); |
| assertOutput("<#ftl outputFormat='HTML'>${''?esc?hasContent?c} ${''?noEsc?hasContent?c}", "false false"); |
| } |
| |
| @Test |
| public void testMissingVariables() throws Exception { |
| for (String ftl : new String[] { |
| "${noSuchVar}", |
| "<#ftl outputFormat='XML'>${noSuchVar}", |
| "<#ftl outputFormat='XML'>${noSuchVar?esc}", |
| "<#ftl outputFormat='XML'>${'x'?esc + noSuchVar}" |
| }) { |
| assertErrorContains(ftl, InvalidReferenceException.class, "noSuchVar", "null or missing"); |
| } |
| } |
| |
| @Test |
| public void testIsMarkupOutputBI() throws Exception { |
| addToDataModel("m1", HTMLOutputFormat.INSTANCE.fromPlainTextByEscaping("x")); |
| addToDataModel("m2", HTMLOutputFormat.INSTANCE.fromMarkup("x")); |
| addToDataModel("s", "x"); |
| assertOutput("${m1?isMarkupOutput?c} ${m2?isMarkupOutput?c} ${s?isMarkupOutput?c}", "true true false"); |
| assertOutput("${m1?is_markup_output?c}", "true"); |
| } |
| |
| @Override |
| protected Configuration createConfiguration() throws TemplateModelException { |
| Configuration cfg = new Configuration(Configuration.VERSION_2_3_24); |
| |
| TemplateConfiguration xmlTC = new TemplateConfiguration(); |
| xmlTC.setOutputFormat(XMLOutputFormat.INSTANCE); |
| cfg.setTemplateConfigurations( |
| new ConditionalTemplateConfigurationFactory(new FileNameGlobMatcher("*.xml"), xmlTC)); |
| |
| cfg.setSharedVariable("rtfPlain", RTFOutputFormat.INSTANCE.fromPlainTextByEscaping("\\par a & b")); |
| cfg.setSharedVariable("rtfMarkup", RTFOutputFormat.INSTANCE.fromMarkup("\\par c")); |
| cfg.setSharedVariable("htmlPlain", HTMLOutputFormat.INSTANCE.fromPlainTextByEscaping("a < {h'}")); |
| cfg.setSharedVariable("htmlMarkup", HTMLOutputFormat.INSTANCE.fromMarkup("<p>c")); |
| cfg.setSharedVariable("xmlPlain", XMLOutputFormat.INSTANCE.fromPlainTextByEscaping("a < {x'}")); |
| cfg.setSharedVariable("xmlMarkup", XMLOutputFormat.INSTANCE.fromMarkup("<p>c</p>")); |
| |
| return cfg; |
| } |
| |
| } |