Added some non-escaping OutputFormat-s, just for the MIME type (that for example FreemarkerServlet can utilize); Updated/fixed OutputFormat-related JavaDocs and Manual parts.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/2153e230 Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/2153e230 Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/2153e230 Branch: refs/heads/2.3 Commit: 2153e2309e49dd1f94cfd26f35377f62137e8306 Parents: d9f6b44 Author: ddekany <[email protected]> Authored: Tue Dec 22 18:13:12 2015 +0100 Committer: ddekany <[email protected]> Committed: Tue Dec 22 18:13:12 2015 +0100 ---------------------------------------------------------------------- .../java/freemarker/core/HTMLOutputFormat.java | 4 +- .../freemarker/core/PlainTextOutputFormat.java | 8 +-- .../java/freemarker/core/RTFOutputFormat.java | 4 +- .../java/freemarker/core/XHTMLOutputFormat.java | 4 +- .../java/freemarker/core/XMLOutputFormat.java | 8 +-- .../java/freemarker/template/Configuration.java | 6 +++ src/manual/en_US/book.xml | 44 +++++++++++++++- .../java/freemarker/core/CSSOutputFormat.java | 34 ++++++++++++ .../java/freemarker/core/JSONOutputFormat.java | 34 ++++++++++++ .../freemarker/core/JavaScriptOutputFormat.java | 35 +++++++++++++ .../ext/servlet/FreemarkerServletTest.java | 55 ++++++++++++++++++++ 11 files changed, 222 insertions(+), 14 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/main/java/freemarker/core/HTMLOutputFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/HTMLOutputFormat.java b/src/main/java/freemarker/core/HTMLOutputFormat.java index 2adb5af..542b33a 100644 --- a/src/main/java/freemarker/core/HTMLOutputFormat.java +++ b/src/main/java/freemarker/core/HTMLOutputFormat.java @@ -25,7 +25,9 @@ import freemarker.template.TemplateModelException; import freemarker.template.utility.StringUtil; /** - * Represents the HTML output format. + * Represents the HTML output format (MIME type "text/html", name "HTML"). This format escapes by default (via + * {@link StringUtil#XHTMLEnc(String)}). The {@code ?html}, {@code ?xhtml} and {@code ?xml} built-ins silently bypass + * template output values of the type produced by this output format ({@link TemplateHTMLOutputModel}). * * @since 2.3.24 */ http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/main/java/freemarker/core/PlainTextOutputFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/PlainTextOutputFormat.java b/src/main/java/freemarker/core/PlainTextOutputFormat.java index 4321a39..82ac31b 100644 --- a/src/main/java/freemarker/core/PlainTextOutputFormat.java +++ b/src/main/java/freemarker/core/PlainTextOutputFormat.java @@ -19,12 +19,8 @@ package freemarker.core; /** - * Represents the plain text output format. Plain text is text without any characters with special meaning. As such, it - * doesn't support escaping. - * - * <p> - * String literals in FTL expressions use this output format, which has importance when <code>${...}</code> is used - * inside them. + * Represents the plain text output format (MIME type "text/plain", name "plainText"). This format doesn't support + * escaping. This format doesn't allow mixing in template output values of other output formats. * * <p> * The main difference from {@link UndefinedOutputFormat} is that this format doesn't allow inserting values of another http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/main/java/freemarker/core/RTFOutputFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/RTFOutputFormat.java b/src/main/java/freemarker/core/RTFOutputFormat.java index 86eb103..9aef2a7 100644 --- a/src/main/java/freemarker/core/RTFOutputFormat.java +++ b/src/main/java/freemarker/core/RTFOutputFormat.java @@ -25,7 +25,9 @@ import freemarker.template.TemplateModelException; import freemarker.template.utility.StringUtil; /** - * Represents the HTML output format. + * Represents the Rich Text Format output format (MIME type "application/rtf", name "RTF"). This format escapes by + * default (via {@link StringUtil#RTFEnc(String)}). The {@code ?rtf} built-in silently bypasses template output values + * of the type produced by this output format ({@link TemplateRTFOutputModel}). * * @since 2.3.24 */ http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/main/java/freemarker/core/XHTMLOutputFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/XHTMLOutputFormat.java b/src/main/java/freemarker/core/XHTMLOutputFormat.java index e14f597..432a5ff 100644 --- a/src/main/java/freemarker/core/XHTMLOutputFormat.java +++ b/src/main/java/freemarker/core/XHTMLOutputFormat.java @@ -25,7 +25,9 @@ import freemarker.template.TemplateModelException; import freemarker.template.utility.StringUtil; /** - * Represents the XHTML output format. + * Represents the XML output format (MIME type "application/xhtml+xml", name "XHTML"). This format escapes by default + * (via {@link StringUtil#XHTMLEnc(String)}). The {@code ?xml} built-in silently bypasses template output values of the + * type produced by this output format ({@link TemplateXHTMLOutputModel}). * * @since 2.3.24 */ http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/main/java/freemarker/core/XMLOutputFormat.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/core/XMLOutputFormat.java b/src/main/java/freemarker/core/XMLOutputFormat.java index 9c45b7d..90fed02 100644 --- a/src/main/java/freemarker/core/XMLOutputFormat.java +++ b/src/main/java/freemarker/core/XMLOutputFormat.java @@ -25,7 +25,9 @@ import freemarker.template.TemplateModelException; import freemarker.template.utility.StringUtil; /** - * Represents the XML output format. + * Represents the XML output format (MIME type "application/xml", name "XML"). This format escapes by default (via + * {@link StringUtil#XMLEnc(String)}). The {@code ?html}, {@code ?xhtml} and {@code ?xml} built-ins silently bypass + * template output values of the type produced by this output format ({@link TemplateXHTMLOutputModel}). * * @since 2.3.24 */ @@ -35,11 +37,11 @@ public final class XMLOutputFormat extends CommonMarkupOutputFormat<TemplateXMLO * The only instance (singleton) of this {@link OutputFormat}. */ public static final XMLOutputFormat INSTANCE = new XMLOutputFormat(); - + private XMLOutputFormat() { // Only to decrease visibility } - + @Override public String getName() { return "XML"; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/main/java/freemarker/template/Configuration.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java index 0b9d5c3..4fd347c 100644 --- a/src/main/java/freemarker/template/Configuration.java +++ b/src/main/java/freemarker/template/Configuration.java @@ -58,10 +58,13 @@ import freemarker.cache.TemplateLookupStrategy; import freemarker.cache.TemplateNameFormat; import freemarker.cache.URLTemplateLoader; import freemarker.core.BugException; +import freemarker.core.CSSOutputFormat; import freemarker.core.CombinedMarkupOutputFormat; import freemarker.core.Configurable; import freemarker.core.Environment; import freemarker.core.HTMLOutputFormat; +import freemarker.core.JSONOutputFormat; +import freemarker.core.JavaScriptOutputFormat; import freemarker.core.MarkupOutputFormat; import freemarker.core.OutputFormat; import freemarker.core.ParseException; @@ -344,6 +347,9 @@ public class Configuration extends Configurable implements Cloneable, ParserConf STANDARD_OUTPUT_FORMATS.put(XMLOutputFormat.INSTANCE.getName(), XMLOutputFormat.INSTANCE); STANDARD_OUTPUT_FORMATS.put(RTFOutputFormat.INSTANCE.getName(), RTFOutputFormat.INSTANCE); STANDARD_OUTPUT_FORMATS.put(PlainTextOutputFormat.INSTANCE.getName(), PlainTextOutputFormat.INSTANCE); + STANDARD_OUTPUT_FORMATS.put(CSSOutputFormat.INSTANCE.getName(), CSSOutputFormat.INSTANCE); + STANDARD_OUTPUT_FORMATS.put(JavaScriptOutputFormat.INSTANCE.getName(), JavaScriptOutputFormat.INSTANCE); + STANDARD_OUTPUT_FORMATS.put(JSONOutputFormat.INSTANCE.getName(), JSONOutputFormat.INSTANCE); } public static final int AUTO_DETECT_TAG_SYNTAX = 0; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/manual/en_US/book.xml ---------------------------------------------------------------------- diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml index 4f6340a..b25ca0c 100644 --- a/src/manual/en_US/book.xml +++ b/src/manual/en_US/book.xml @@ -5383,13 +5383,42 @@ [email protected], [email protected], [email protected]</programlisting> <tr> <td><literal>plainText</literal></td> - <td>Doesn't escape. Doesn't accept markup output values from - other output formats.</td> + <td>Doesn't escape.</td> <td><literal>text/plain</literal></td> <td><literal>PlainTextOutputFormat.INSTANCE</literal></td> </tr> + + <tr> + <td><literal>JavaScript</literal></td> + + <td>Doesn't escape.</td> + + <td><literal>application/javascript</literal></td> + + <td><literal>JavaScriptOutputFormat.INSTANCE</literal></td> + </tr> + + <tr> + <td><literal>JSON</literal></td> + + <td>Doesn't escape.</td> + + <td><literal>application/json</literal></td> + + <td><literal>JSONOutputFormat.INSTANCE</literal></td> + </tr> + + <tr> + <td><literal>CSS</literal></td> + + <td>Doesn't escape.</td> + + <td><literal>text/css</literal></td> + + <td><literal>CSSOutputFormat.INSTANCE</literal></td> + </tr> </tbody> </informaltable> @@ -26482,6 +26511,17 @@ TemplateModel x = env.getVariable("x"); // get variable x</programlisting> </listitem> <listitem> + <para>Added non-escaping formats (just for the MIME type): + <literal>JavaScriptOutputFormat</literal>, + <literal>JSONOutputFormat</literal>, + <literal>CSSOutputFormat</literal>.</para> + </listitem> + + <listitem> + <para>Added JavaScriptOutput</para> + </listitem> + + <listitem> <para>Added new built-in: <literal>is_markup_output</literal>, returns <literal>true</literal> if the value is of type <quote>markup output</quote>.</para> http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/test/java/freemarker/core/CSSOutputFormat.java ---------------------------------------------------------------------- diff --git a/src/test/java/freemarker/core/CSSOutputFormat.java b/src/test/java/freemarker/core/CSSOutputFormat.java new file mode 100644 index 0000000..e60e1c5 --- /dev/null +++ b/src/test/java/freemarker/core/CSSOutputFormat.java @@ -0,0 +1,34 @@ +package freemarker.core; + +/** + * Represents the CSS output format (MIME type "text/css", name "CSS"). This format doesn't support escaping. + * + * @since 2.3.24 + */ +public class CSSOutputFormat extends OutputFormat { + + /** + * The only instance (singleton) of this {@link OutputFormat}. + */ + public static final CSSOutputFormat INSTANCE = new CSSOutputFormat(); + + private CSSOutputFormat() { + // Only to decrease visibility + } + + @Override + public String getName() { + return "CSS"; + } + + @Override + public String getMimeType() { + return "text/css"; + } + + @Override + public boolean isOutputFormatMixingAllowed() { + return false; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/test/java/freemarker/core/JSONOutputFormat.java ---------------------------------------------------------------------- diff --git a/src/test/java/freemarker/core/JSONOutputFormat.java b/src/test/java/freemarker/core/JSONOutputFormat.java new file mode 100644 index 0000000..7b0d9fe --- /dev/null +++ b/src/test/java/freemarker/core/JSONOutputFormat.java @@ -0,0 +1,34 @@ +package freemarker.core; + +/** + * Represents the JSON output format (MIME type "application/json", name "JSON"). This format doesn't support escaping. + * + * @since 2.3.24 + */ +public class JSONOutputFormat extends OutputFormat { + + /** + * The only instance (singleton) of this {@link OutputFormat}. + */ + public static final JSONOutputFormat INSTANCE = new JSONOutputFormat(); + + private JSONOutputFormat() { + // Only to decrease visibility + } + + @Override + public String getName() { + return "JSON"; + } + + @Override + public String getMimeType() { + return "application/json"; + } + + @Override + public boolean isOutputFormatMixingAllowed() { + return false; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/test/java/freemarker/core/JavaScriptOutputFormat.java ---------------------------------------------------------------------- diff --git a/src/test/java/freemarker/core/JavaScriptOutputFormat.java b/src/test/java/freemarker/core/JavaScriptOutputFormat.java new file mode 100644 index 0000000..a6375af --- /dev/null +++ b/src/test/java/freemarker/core/JavaScriptOutputFormat.java @@ -0,0 +1,35 @@ +package freemarker.core; + +/** + * Represents the JavaScript output format (MIME type "application/javascript", name "JavaScript"). This format doesn't + * support escaping. + * + * @since 2.3.24 + */ +public class JavaScriptOutputFormat extends OutputFormat { + + /** + * The only instance (singleton) of this {@link OutputFormat}. + */ + public static final JavaScriptOutputFormat INSTANCE = new JavaScriptOutputFormat(); + + private JavaScriptOutputFormat() { + // Only to decrease visibility + } + + @Override + public String getName() { + return "JavaScript"; + } + + @Override + public String getMimeType() { + return "application/javascript"; + } + + @Override + public boolean isOutputFormatMixingAllowed() { + return false; + } + +} http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/2153e230/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java b/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java index 0e9f539..396e4ca 100644 --- a/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java +++ b/src/test/java/freemarker/ext/servlet/FreemarkerServletTest.java @@ -57,6 +57,14 @@ public class FreemarkerServletTest { private static final String FOO_FTL = "foo.ftl"; private static final String FOO_SRC_UTF8_FTL = "foo-src-utf8.ftl"; private static final String FOO_OUT_UTF8_FTL = "foo-out-utf8.ftl"; + private static final String STD_OUTPUT_FORMAT_HTML_FTL = "stdOutputFormatHTML.ftl"; + private static final String STD_OUTPUT_FORMAT_XML_FTL = "stdOutputFormatXML.ftl"; + private static final String STD_OUTPUT_FORMAT_XHTML_FTL = "stdOutputFormatXHTML.ftl"; + private static final String STD_OUTPUT_FORMAT_JAVA_SCRIPT_FTL = "stdOutputFormatJavaScript.ftl"; + private static final String STD_OUTPUT_FORMAT_JSON_FTL = "stdOutputFormatJSON.ftl"; + private static final String STD_OUTPUT_FORMAT_CSS_FTL = "stdOutputFormatCSS.ftl"; + private static final String STD_OUTPUT_FORMAT_PLAIN_TEXT_FTL = "stdOutputFormatPlainText.ftl"; + private static final String STD_OUTPUT_FORMAT_RTF_FTL = "stdOutputFormatRTF.ftl"; private static final Locale DEFAULT_LOCALE = Locale.US; private static final String CFG_DEFAULT_ENCODING = "US-ASCII"; @@ -154,6 +162,42 @@ public class FreemarkerServletTest { } @Test + public void testStandardContentType() throws Exception { + assertResponseContentTypeEquals( + "text/html; charset=UTF-8", // <- expected + null, null, // <- init-params + STD_OUTPUT_FORMAT_HTML_FTL, null); // <- request + assertResponseContentTypeEquals( + "application/xhtml+xml; charset=UTF-8", // <- expected + null, null, // <- init-params + STD_OUTPUT_FORMAT_XHTML_FTL, null); // <- request + assertResponseContentTypeEquals( + "application/xml; charset=UTF-8", // <- expected + null, null, // <- init-params + STD_OUTPUT_FORMAT_XML_FTL, null); // <- request + assertResponseContentTypeEquals( + "application/javascript; charset=UTF-8", // <- expected + null, null, // <- init-params + STD_OUTPUT_FORMAT_JAVA_SCRIPT_FTL, null); // <- request + assertResponseContentTypeEquals( + "application/json; charset=UTF-8", // <- expected + null, null, // <- init-params + STD_OUTPUT_FORMAT_JSON_FTL, null); // <- request + assertResponseContentTypeEquals( + "text/css; charset=UTF-8", // <- expected + null, null, // <- init-params + STD_OUTPUT_FORMAT_CSS_FTL, null); // <- request + assertResponseContentTypeEquals( + "text/plain; charset=UTF-8", // <- expected + null, null, // <- init-params + STD_OUTPUT_FORMAT_PLAIN_TEXT_FTL, null); // <- request + assertResponseContentTypeEquals( + "application/rtf; charset=UTF-8", // <- expected + null, null, // <- init-params + STD_OUTPUT_FORMAT_RTF_FTL, null); // <- request + } + + @Test public void testResponseLocaleInitParams() throws Exception { assertTemplateLocaleEquals( DEFAULT_LOCALE, // <- expected template locale @@ -524,12 +568,23 @@ public class FreemarkerServletTest { // Override default template loader if (templatePath.equals("class://")) { StringTemplateLoader tl = new StringTemplateLoader(); + tl.putTemplate(FOO_FTL, "foo"); tl.putTemplate(FOO_SRC_UTF8_FTL, "foo"); tl.putTemplate(FOO_OUT_UTF8_FTL, "foo"); tl.putTemplate(CONTENT_TYPE_ATTR_FTL, "<#ftl attributes={ 'content_type': 'text/plain' }>foo"); tl.putTemplate(CONTENT_TYPE_ATTR_WITH_CHARSET_FTL, "<#ftl attributes={ 'content_type': 'text/plain; charset=UTF-8' }>foo"); tl.putTemplate(OUTPUT_FORMAT_HEADER_FTL, "<#ftl outputFormat='plainText'>foo"); + + tl.putTemplate(STD_OUTPUT_FORMAT_HTML_FTL, "<#ftl outputFormat='HTML'>"); + tl.putTemplate(STD_OUTPUT_FORMAT_XHTML_FTL, "<#ftl outputFormat='XHTML'>"); + tl.putTemplate(STD_OUTPUT_FORMAT_XML_FTL, "<#ftl outputFormat='XML'>"); + tl.putTemplate(STD_OUTPUT_FORMAT_JAVA_SCRIPT_FTL, "<#ftl outputFormat='JavaScript'>"); + tl.putTemplate(STD_OUTPUT_FORMAT_JSON_FTL, "<#ftl outputFormat='JSON'>"); + tl.putTemplate(STD_OUTPUT_FORMAT_CSS_FTL, "<#ftl outputFormat='CSS'>"); + tl.putTemplate(STD_OUTPUT_FORMAT_PLAIN_TEXT_FTL, "<#ftl outputFormat='plainText'>"); + tl.putTemplate(STD_OUTPUT_FORMAT_RTF_FTL, "<#ftl outputFormat='RTF'>"); + return tl; } else { return super.createTemplateLoader(templatePath);
