You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2018/03/10 20:02:43 UTC
[1/2] incubator-freemarker git commit: Added ?absoulte_template_name.
Necessary additions to the Environment and TemplateNameFormat. Some Manual
cleanups related to `.caller_template_name`.
Repository: incubator-freemarker
Updated Branches:
refs/heads/2.3 6442fd765 -> 5bfa9ac42
Added ?absoulte_template_name. Necessary additions to the Environment and TemplateNameFormat. Some Manual cleanups related to `.caller_template_name`.
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/8286a7bf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/8286a7bf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/8286a7bf
Branch: refs/heads/2.3
Commit: 8286a7bfcb402e34e67d75d50a5a2ee7c994275e
Parents: 5f821f1
Author: ddekany <dd...@apache.org>
Authored: Sat Mar 10 20:56:45 2018 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sat Mar 10 20:56:45 2018 +0100
----------------------------------------------------------------------
.../freemarker/cache/TemplateNameFormat.java | 42 +++++++-
src/main/java/freemarker/cache/_CacheAPI.java | 5 +
src/main/java/freemarker/core/BuiltIn.java | 3 +-
.../freemarker/core/BuiltInsForStringsMisc.java | 47 +++++++++
src/main/java/freemarker/core/Environment.java | 26 ++++-
src/manual/en_US/book.xml | 104 +++++++++++++++++--
.../cache/TemplateNameFormatTest.java | 23 +++-
.../core/AbsoluteTemplateNameBITest.java | 72 +++++++++++++
.../manual/AbsoluteTemplateNameBIExample.java | 31 ++++++
.../AbsoluteTemplateNameBIExample-foo.ftl | 19 ++++
.../AbsoluteTemplateNameBIExample-lib.ftl | 38 +++++++
.../dir/AbsoluteTemplateNameBIExample-foo.ftl | 19 ++++
.../dir/AbsoluteTemplateNameBIExample-main.ftl | 24 +++++
.../AbsoluteTemplateNameBIExample-main.ftl.out | 26 +++++
14 files changed, 463 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/main/java/freemarker/cache/TemplateNameFormat.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/cache/TemplateNameFormat.java b/src/main/java/freemarker/cache/TemplateNameFormat.java
index 72126bf..e076f93 100644
--- a/src/main/java/freemarker/cache/TemplateNameFormat.java
+++ b/src/main/java/freemarker/cache/TemplateNameFormat.java
@@ -59,10 +59,10 @@ public abstract class TemplateNameFormat {
* template names like {@code "classpath:foo.ftl"} interpreted as an absolute name with scheme {@code "classpath"}
* and absolute path "foo.ftl". The scheme name before the {@code ":"} can't contain {@code "/"}, or else it's
* treated as a malformed name. The scheme part can be separated either with {@code "://"} or just {@code ":"} from
- * the path. Hence, {@code myschme:/x} is normalized to {@code myschme:x}, while {@code myschme:///x} is normalized
- * to {@code myschme://x}, but {@code myschme://x} or {@code myschme:/x} aren't changed by normalization. It's up
- * the {@link TemplateLoader} to which the normalized names are passed to decide which of these scheme separation
- * conventions are valid (maybe both).</li>
+ * the path. Hence, {@code myscheme:/x} is normalized to {@code myscheme:x}, while {@code myscheme:///x} is
+ * normalized to {@code myscheme://x}, but {@code myscehme://x} or {@code myscheme:/x} aren't changed by
+ * normalization. It's up the {@link TemplateLoader} to which the normalized names are passed to decide which of
+ * these scheme separation conventions are valid (maybe both).</li>
*
* <li>{@code ":"} is not allowed in template names, except as the scheme separator (see previous point).
*
@@ -131,11 +131,21 @@ public abstract class TemplateNameFormat {
* becomes to "foo.ftl".
*
* @param name
- * The root based name. Not {@code null}.
+ * The root based name (a name that's either absolute or relative to the root). Not {@code null}.
*
* @return The normalized root based name. Not {@code null}.
*/
abstract String normalizeRootBasedName(String name) throws MalformedTemplateNameException;
+
+ /**
+ * Converts a root based name to an absolute name, which is useful if you need to pass a name to something that
+ * doesn't necessary resolve relative paths relative to the root (like the {@code #include} directive).
+ *
+ * @param name
+ * The root based name (a name that's either absolute or relative to the root). Not {@code null}.
+ */
+ // TODO [FM3] This is the kind of complication why normalized template names should just be absolute paths.
+ abstract String rootBasedNameToAbsoluteName(String name) throws MalformedTemplateNameException;
private static final class Default020300 extends TemplateNameFormat {
@Override
@@ -200,6 +210,17 @@ public abstract class TemplateNameFormat {
}
return path;
}
+
+ @Override
+ String rootBasedNameToAbsoluteName(String name) throws MalformedTemplateNameException {
+ if (name.indexOf("://") > 0) {
+ return name;
+ }
+ if (!name.startsWith("/")) {
+ return "/" + name;
+ }
+ return name;
+ }
@Override
public String toString() {
@@ -429,6 +450,17 @@ public abstract class TemplateNameFormat {
return path;
}
+
+ @Override
+ String rootBasedNameToAbsoluteName(String name) throws MalformedTemplateNameException {
+ if (findSchemeSectionEnd(name) != 0) {
+ return name;
+ }
+ if (!name.startsWith("/")) {
+ return "/" + name;
+ }
+ return name;
+ }
@Override
public String toString() {
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/main/java/freemarker/cache/_CacheAPI.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/cache/_CacheAPI.java b/src/main/java/freemarker/cache/_CacheAPI.java
index ead17de..ceedf9e 100644
--- a/src/main/java/freemarker/cache/_CacheAPI.java
+++ b/src/main/java/freemarker/cache/_CacheAPI.java
@@ -41,5 +41,10 @@ public final class _CacheAPI {
throws MalformedTemplateNameException {
return templateNameFormat.normalizeRootBasedName(name);
}
+
+ public static String rootBasedNameToAbsoluteName(TemplateNameFormat templateNameFormat, String rootBasedName)
+ throws MalformedTemplateNameException {
+ return templateNameFormat.rootBasedNameToAbsoluteName(rootBasedName);
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/main/java/freemarker/core/BuiltIn.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/BuiltIn.java b/src/main/java/freemarker/core/BuiltIn.java
index e830cb1..78b9e45 100644
--- a/src/main/java/freemarker/core/BuiltIn.java
+++ b/src/main/java/freemarker/core/BuiltIn.java
@@ -84,13 +84,14 @@ abstract class BuiltIn extends Expression implements Cloneable {
static final Set<String> CAMEL_CASE_NAMES = new TreeSet<String>();
static final Set<String> SNAKE_CASE_NAMES = new TreeSet<String>();
- static final int NUMBER_OF_BIS = 264;
+ static final int NUMBER_OF_BIS = 266;
static final HashMap<String, BuiltIn> BUILT_INS_BY_NAME = new HashMap(NUMBER_OF_BIS * 3 / 2 + 1, 1f);
static {
// Note that you must update NUMBER_OF_BIS if you add new items here!
putBI("abs", new absBI());
+ putBI("absolute_template_name", "absoluteTemplateName", new BuiltInsForStringsMisc.absolute_template_nameBI());
putBI("ancestors", new ancestorsBI());
putBI("api", new BuiltInsForMultipleTypes.apiBI());
putBI("boolean", new BuiltInsForStringsMisc.booleanBI());
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/main/java/freemarker/core/BuiltInsForStringsMisc.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/BuiltInsForStringsMisc.java b/src/main/java/freemarker/core/BuiltInsForStringsMisc.java
index e4b18a2..e1bf88b 100644
--- a/src/main/java/freemarker/core/BuiltInsForStringsMisc.java
+++ b/src/main/java/freemarker/core/BuiltInsForStringsMisc.java
@@ -20,12 +20,17 @@
package freemarker.core;
import java.io.StringReader;
+import java.util.List;
+import freemarker.template.MalformedTemplateNameException;
import freemarker.template.SimpleNumber;
import freemarker.template.Template;
import freemarker.template.TemplateBooleanModel;
import freemarker.template.TemplateException;
+import freemarker.template.TemplateMethodModelEx;
import freemarker.template.TemplateModel;
+import freemarker.template.TemplateModelException;
+import freemarker.template.TemplateScalarModel;
class BuiltInsForStringsMisc {
@@ -118,6 +123,48 @@ class BuiltInsForStringsMisc {
}
}
}
+
+ static class absolute_template_nameBI extends BuiltInForString {
+ @Override
+ TemplateModel calculateResult(String s, Environment env) throws TemplateException {
+ return new AbsoluteTemplateNameResult(s, env);
+ }
+
+ private class AbsoluteTemplateNameResult implements TemplateScalarModel, TemplateMethodModelEx {
+ private final String pathToResolve;
+ private final Environment env;
+
+ public AbsoluteTemplateNameResult(String pathToResolve, Environment env) {
+ this.pathToResolve = pathToResolve;
+ this.env = env;
+ }
+
+ public Object exec(List args) throws TemplateModelException {
+ checkMethodArgCount(args, 1);
+ return resolvePath(getStringMethodArg(args, 0));
+ }
+
+ public String getAsString() throws TemplateModelException {
+ return resolvePath(getTemplate().getName());
+ }
+
+ /**
+ * @param basePath Maybe {@code null}
+ */
+ private String resolvePath(String basePath) throws TemplateModelException {
+ try {
+ return env.rootBasedToAbsoluteTemplateName(env.toFullTemplateName(basePath, pathToResolve));
+ } catch (MalformedTemplateNameException e) {
+ throw new _TemplateModelException(e,
+ "Can't resolve ", new _DelayedJQuote(pathToResolve),
+ "to absolute template name using base ", new _DelayedJQuote(basePath),
+ "; see cause exception");
+ }
+ }
+
+ }
+
+ }
// Can't be instantiated
private BuiltInsForStringsMisc() { }
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/main/java/freemarker/core/Environment.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/Environment.java b/src/main/java/freemarker/core/Environment.java
index 6c8e202..a6eb6eb 100644
--- a/src/main/java/freemarker/core/Environment.java
+++ b/src/main/java/freemarker/core/Environment.java
@@ -2739,9 +2739,12 @@ public final class Environment extends Configurable {
/**
* Resolves a reference to a template (like the one used in {@code #include} or {@code #import}), assuming a base
- * name. This gives a full (that is, absolute), even if non-normalized template name, that could be used for
- * {@link Configuration#getTemplate(String)}. This is mostly used when a
+ * name. This gives a root based, even if non-normalized and possibly non-absolute (but then relative to the root)
+ * template name, that could be used for {@link Configuration#getTemplate(String)}. This is mostly used when a
* template refers to another template.
+ * <p>
+ * If you need to guarantee that the result is also an absolute path, then apply
+ * {@link #rootBasedToAbsoluteTemplateName(String)} on it.
*
* @param baseName
* The name to which relative {@code targetName}-s are relative to. Maybe {@code null} (happens when
@@ -2772,6 +2775,25 @@ public final class Environment extends Configurable {
return _CacheAPI.toRootBasedName(configuration.getTemplateNameFormat(), baseName, targetName);
}
+ /**
+ * Converts a root based name (a name that's either relative to the root, or is absolute), which are typically used
+ * by the API (such as for {@link Configuration#getTemplate(String)}), to an absolute name, which can be safely
+ * passed to {@code <#include path>} and such, as it won't be misinterpreted to be relative to the directory of the
+ * template. For example, {@code "foo/bar.ftl"} is converted to {@code "/foo/bar.ftl"}, while {@code "/foo/bar"} or
+ * {@code "foo://bar/baz"} remains as is, as they are already absolute names (see {@link TemplateNameFormat} for
+ * more about the format of names).
+ *
+ * <p>
+ * You only need this if the template name will be passed to {@code <#include name>}, {@code <#import name>},
+ * {@code .get_optional_template(name)} or a similar construct in a template, otherwise using non-absolute root
+ * based names is fine.
+ *
+ * @since 2.3.28
+ */
+ public String rootBasedToAbsoluteTemplateName(String rootBasedName) throws MalformedTemplateNameException {
+ return _CacheAPI.rootBasedNameToAbsoluteName(configuration.getTemplateNameFormat(), rootBasedName);
+ }
+
String renderElementToString(TemplateElement te) throws IOException, TemplateException {
Writer prevOut = out;
try {
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/manual/en_US/book.xml
----------------------------------------------------------------------
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 564898a..804cb15 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -12450,6 +12450,11 @@ grant codeBase "file:/path/to/freemarker.jar"
<listitem>
<para><link
+ linkend="ref_builtin_absolute_template_name">absolute_template_name</link></para>
+ </listitem>
+
+ <listitem>
+ <para><link
linkend="ref_builtin_ancestors">ancestors</link></para>
</listitem>
@@ -17832,6 +17837,64 @@ Sorted by name.last:
useful. If you need to use these in your normal page templates, you
may revisit the data-model so you don't need to use these.</para>
+ <section xml:id="ref_builtin_absolute_template_name">
+ <title>absolute_template_name</title>
+
+ <indexterm>
+ <primary>absolute_template_name built-in</primary>
+ </indexterm>
+
+ <para>Converts a template name to an absolute name, which can be
+ safely passed to <literal><#include
+ <replaceable>name</replaceable>></literal> or
+ <literal><#import <replaceable>name</replaceable> as
+ <replaceable>ns</replaceable>></literal> or
+ <literal>.get_optional_template(<replaceable>name</replaceable>)</literal>
+ and such in <emphasis>another</emphasis> template, as it won't be
+ misinterpreted to be relative to the directory of the template that
+ contains the <literal>include</literal>, <literal>import</literal>,
+ etc. For example, if you are in template
+ <literal>"dir/here.ftl"</literal>, then
+ <literal>"target.ftl"</literal> is converted to
+ <literal>"/dir/target.ftl"</literal> (note the initial
+ <literal>/</literal>). If now you pass this value to a template in
+ <literal>"other-dir/there.ftl"</literal>, where it's passed to the
+ <literal>include</literal> directive, then it won't be
+ misinterpreted as <literal>"other-dir/target.ftl"</literal>, like
+ <literal>"target.ftl"</literal> would have been.</para>
+
+ <para>Optionally, you can specify a root based name (a name that's
+ either relative to the template root directory, or is absolute) that
+ will be used instead of the name of the current template, like
+ <literal><replaceable>pathToConver</replaceable>?absolute_template_name(<replaceable>otherTemplateName</replaceable>)</literal>.</para>
+
+ <para>Example of an application (also uses <link
+ linkend="ref_specvar_caller_template_name"><literal>.caller_template_name</literal></link>
+ and <link
+ linkend="ref_specvar_get_optional_template"><literal>.get_optional_template</literal></link>):</para>
+
+ <programlisting role="template"><#--
+ <@smileyInclude name /> behaves like <#include name>, but prints a "(:" before the
+ template, or prints "):" instead if the template is missing.
+
+ Note that just like with #include, if name is relative, it's resolved based on the
+ directory of the caller template, not of the template that defines this macro. As
+ .get_optional_template resolves relative names based on the current template, we
+ had to convert the name to an absolute name based on the caller template before
+ passing it to it.
+-->
+<#macro smileyInclude name>
+ <#local t = .get_optional_template(
+ name<emphasis>?absolute_template_name</emphasis>(.caller_template_name))>
+ <#if t.exists>
+ (:
+ <@t.include />
+ <#else>
+ ):
+ </#if>
+</#macro></programlisting>
+ </section>
+
<section xml:id="ref_buitin_api_and_has_api">
<title>api, has_api</title>
@@ -23219,10 +23282,11 @@ There was no specific handler for node y
linkend="ref.directive.macro">macro</link> or <link
linkend="ref.directive.function">function</link> was called. It's
mostly useful if you want to resolve paths relative to the caller
- template. To serve that purpose better, if the caller template is
- nameless, this will be an empty string (not a missing value).
- Reading this variable will cause error if you aren't inside a macro
- or function call. In particular, directives and
+ template (<link linkend="ref_builtin_absolute_template_name">see an
+ example here</link>). To serve that purpose better, if the caller
+ template is nameless, this will be an empty string (not a missing
+ value). Reading this variable will cause error if you aren't inside
+ a macro or function call. In particular, directives and
<quote>methods</quote> implemented in Java will not influence the
value of this variable; it's only for macros and functions
implemented in templates. (<phrase
@@ -23232,7 +23296,7 @@ There was no specific handler for node y
object.</phrase>)</para>
</listitem>
- <listitem>
+ <listitem xml:id="ref_specvar_caller_template_name">
<para><indexterm>
<primary>current_template_name</primary>
</indexterm><literal>current_template_name</literal>: The name of
@@ -27300,6 +27364,17 @@ TemplateModel x = env.getVariable("x"); // get variable x</programlisting>
</listitem>
<listitem>
+ <para>Added new built-in,
+ <literal><replaceable>templateName</replaceable>?absolute_template_name</literal>
+ or
+ <literal><replaceable>templateName</replaceable>?absolute_template_name(<replaceable>baseName</replaceable>)</literal>,
+ which can be used to convert a relative template name to an
+ absolute template name. <link
+ linkend="ref_builtin_absolute_template_name">See more
+ here...</link></para>
+ </listitem>
+
+ <listitem>
<para>Bug fixed (<link
xlink:href="https://issues.apache.org/jira/browse/FREEMARKER-83">FREEMARKER-83</link>);
this fix is only active when <link
@@ -27336,7 +27411,24 @@ TemplateModel x = env.getVariable("x"); // get variable x</programlisting>
<listitem>
<para><literal>DirectiveCallPlace</literal> now has a
- <literal>Template getTemplate()</literal> method.</para>
+ <literal>Template getTemplate()</literal> method, so you can
+ query if from which template was your
+ <literal>TemplateDirectiveModel</literal> called. (This has
+ similar role as <literal>.caller_template_name</literal> for
+ macros/functions.)</para>
+ </listitem>
+
+ <listitem>
+ <para>Added
+ <literal>Environment.rootBasedToAbsoluteTemplateName(String)</literal>,
+ which converts the root based names typically used for the
+ FreeMarker Java API-s (such as
+ <literal>Configuration.getTemplate(name)</literal>) to an
+ absolute path, which can be safely passed to
+ <literal><#include
+ <replaceable>path</replaceable>></literal> and such, as it
+ won't be misinterpreted to be relative to the directory of the
+ template.</para>
</listitem>
<listitem>
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/test/java/freemarker/cache/TemplateNameFormatTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/cache/TemplateNameFormatTest.java b/src/test/java/freemarker/cache/TemplateNameFormatTest.java
index 5cba04c..8441d97 100644
--- a/src/test/java/freemarker/cache/TemplateNameFormatTest.java
+++ b/src/test/java/freemarker/cache/TemplateNameFormatTest.java
@@ -223,7 +223,26 @@ public class TemplateNameFormatTest {
}
@Test
- public void assertBackslashNotSpecialWith23() throws MalformedTemplateNameException, ParseException, IOException {
+ public void testRootBasedNameToAbsoluteName() throws MalformedTemplateNameException {
+ for (TemplateNameFormat tnf : new TemplateNameFormat[] {
+ TemplateNameFormat.DEFAULT_2_3_0, TemplateNameFormat.DEFAULT_2_4_0 }) {
+ assertEquals("/foo/bar", tnf.rootBasedNameToAbsoluteName("foo/bar"));
+ assertEquals("scheme://foo/bar", tnf.rootBasedNameToAbsoluteName("scheme://foo/bar"));
+ assertEquals("/foo/bar", tnf.rootBasedNameToAbsoluteName("/foo/bar"));
+ }
+
+ assertEquals("a/b://c/d", TemplateNameFormat.DEFAULT_2_3_0.rootBasedNameToAbsoluteName("a/b://c/d"));
+ // Lenient handling of malformed rootBasedName:
+ assertEquals("/a/b://c/d", TemplateNameFormat.DEFAULT_2_4_0.rootBasedNameToAbsoluteName("a/b://c/d"));
+
+ assertEquals("/b:/c/d", TemplateNameFormat.DEFAULT_2_3_0.rootBasedNameToAbsoluteName("b:/c/d"));
+ assertEquals("b:/c/d", TemplateNameFormat.DEFAULT_2_4_0.rootBasedNameToAbsoluteName("b:/c/d"));
+ assertEquals("/b:c/d", TemplateNameFormat.DEFAULT_2_3_0.rootBasedNameToAbsoluteName("b:c/d"));
+ assertEquals("b:c/d", TemplateNameFormat.DEFAULT_2_4_0.rootBasedNameToAbsoluteName("b:c/d"));
+ }
+
+ @Test
+ public void testBackslashNotSpecialWith23() throws MalformedTemplateNameException, ParseException, IOException {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_22);
MonitoredTemplateLoader tl = new MonitoredTemplateLoader();
@@ -273,7 +292,7 @@ public class TemplateNameFormatTest {
}
@Test
- public void assertBackslashNotAllowedWith24() throws MalformedTemplateNameException, ParseException, IOException {
+ public void testBackslashNotAllowedWith24() throws MalformedTemplateNameException, ParseException, IOException {
Configuration cfg = new Configuration(Configuration.VERSION_2_3_0);
cfg.setTemplateNameFormat(TemplateNameFormat.DEFAULT_2_4_0);
try {
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/test/java/freemarker/core/AbsoluteTemplateNameBITest.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/core/AbsoluteTemplateNameBITest.java b/src/test/java/freemarker/core/AbsoluteTemplateNameBITest.java
new file mode 100644
index 0000000..e4db1be
--- /dev/null
+++ b/src/test/java/freemarker/core/AbsoluteTemplateNameBITest.java
@@ -0,0 +1,72 @@
+/*
+ * 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 java.io.IOException;
+
+import org.junit.Test;
+
+import freemarker.cache.StringTemplateLoader;
+import freemarker.template.Configuration;
+import freemarker.template.TemplateException;
+import freemarker.test.TemplateTest;
+
+public class AbsoluteTemplateNameBITest extends TemplateTest {
+
+ @Override
+ protected Configuration createConfiguration() throws Exception {
+ Configuration cfg = super.createConfiguration();
+ cfg.setTemplateLoader(new StringTemplateLoader());
+ return cfg;
+ }
+
+ @Test
+ public void basicsTest() throws Exception {
+ assertOutput("${'a/b'?absolute_template_name}", "/a/b");
+ assertOutput("${'a/b/'?absolute_template_name}", "/a/b/");
+ assertOutput("${'foo://a/b'?absolute_template_name}", "foo://a/b");
+ assertOutput("${'/a/b'?absolute_template_name}", "/a/b");
+
+ assertOutputOfDirPerF("${'a/b'?absolute_template_name}", "/dir/a/b");
+ assertOutputOfDirPerF("${'a/b/'?absolute_template_name}", "/dir/a/b/");
+ assertOutputOfDirPerF("${'foo://a/b'?absolute_template_name}", "foo://a/b");
+ assertOutputOfDirPerF("${'/a/b'?absolute_template_name}", "/a/b");
+
+ for (String baseName : new String[] { "dir/f", "/dir/f", "dir/", "/dir/" }) {
+ assertOutput("${'a/b'?absolute_template_name('" + baseName + "')}", "/dir/a/b");
+ assertOutput("${'a/b/'?absolute_template_name('" + baseName + "')}", "/dir/a/b/");
+ assertOutput("${'foo://a/b'?absolute_template_name('" + baseName + "')}", "foo://a/b");
+ assertOutput("${'/a/b'?absolute_template_name('" + baseName + "')}", "/a/b");
+ }
+
+ assertOutput("${'a/b'?absolute_template_name('schema://dir/f')}", "schema://dir/a/b");
+ assertOutput("${'a/b/'?absolute_template_name('schema://dir/f')}", "schema://dir/a/b/");
+ assertOutput("${'foo://a/b'?absolute_template_name('schema://dir/f')}", "foo://a/b");
+ assertOutput("${'/a/b'?absolute_template_name('schema://dir/f')}", "schema://a/b");
+ }
+
+ private void assertOutputOfDirPerF(String ftl, String expectedOut)
+ throws IOException, TemplateException {
+ addTemplate("dir/f", ftl);
+ getConfiguration().removeTemplateFromCache("dir/f");
+ assertOutputForNamed("dir/f", expectedOut);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/test/java/freemarker/manual/AbsoluteTemplateNameBIExample.java
----------------------------------------------------------------------
diff --git a/src/test/java/freemarker/manual/AbsoluteTemplateNameBIExample.java b/src/test/java/freemarker/manual/AbsoluteTemplateNameBIExample.java
new file mode 100644
index 0000000..af8d686
--- /dev/null
+++ b/src/test/java/freemarker/manual/AbsoluteTemplateNameBIExample.java
@@ -0,0 +1,31 @@
+/*
+ * 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.manual;
+
+import org.junit.Test;
+
+public class AbsoluteTemplateNameBIExample extends ExamplesTest {
+
+ @Test
+ public void test() throws Exception {
+ assertOutputForNamed("dir/AbsoluteTemplateNameBIExample-main.ftl");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/test/resources/freemarker/manual/AbsoluteTemplateNameBIExample-foo.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/manual/AbsoluteTemplateNameBIExample-foo.ftl b/src/test/resources/freemarker/manual/AbsoluteTemplateNameBIExample-foo.ftl
new file mode 100644
index 0000000..b588cb3
--- /dev/null
+++ b/src/test/resources/freemarker/manual/AbsoluteTemplateNameBIExample-foo.ftl
@@ -0,0 +1,19 @@
+<#--
+ 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.
+-->
+/foo
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/test/resources/freemarker/manual/AbsoluteTemplateNameBIExample-lib.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/manual/AbsoluteTemplateNameBIExample-lib.ftl b/src/test/resources/freemarker/manual/AbsoluteTemplateNameBIExample-lib.ftl
new file mode 100644
index 0000000..0db6c7d
--- /dev/null
+++ b/src/test/resources/freemarker/manual/AbsoluteTemplateNameBIExample-lib.ftl
@@ -0,0 +1,38 @@
+<#--
+ 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.
+-->
+<#--
+ <@smileyInclude name /> behaves like <#include name>, but prints a "(:" before the
+ template, or prints "):" instead if the template is missing.
+
+ Note that just like with #include, if name is relative, it's resolved based on the
+ directory of the caller template, not of the template that defines this macro. As
+ .get_optional_template resolves relative names based on the current template, we
+ had to convert the name to an absolute name based on the caller template before
+ passing it to it.
+-->
+<#macro smileyInclude name>
+ <#local t = .get_optional_template(
+ name?absolute_template_name(.caller_template_name))>
+ <#if t.exists>
+ (:
+ <@t.include />
+ <#else>
+ ):
+ </#if>
+</#macro>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/test/resources/freemarker/manual/dir/AbsoluteTemplateNameBIExample-foo.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/manual/dir/AbsoluteTemplateNameBIExample-foo.ftl b/src/test/resources/freemarker/manual/dir/AbsoluteTemplateNameBIExample-foo.ftl
new file mode 100644
index 0000000..e68993c
--- /dev/null
+++ b/src/test/resources/freemarker/manual/dir/AbsoluteTemplateNameBIExample-foo.ftl
@@ -0,0 +1,19 @@
+<#--
+ 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.
+-->
+/dir/foo
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/test/resources/freemarker/manual/dir/AbsoluteTemplateNameBIExample-main.ftl
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/manual/dir/AbsoluteTemplateNameBIExample-main.ftl b/src/test/resources/freemarker/manual/dir/AbsoluteTemplateNameBIExample-main.ftl
new file mode 100644
index 0000000..311bb9a
--- /dev/null
+++ b/src/test/resources/freemarker/manual/dir/AbsoluteTemplateNameBIExample-main.ftl
@@ -0,0 +1,24 @@
+<#--
+ 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.
+-->
+<#import '/AbsoluteTemplateNameBIExample-lib.ftl' as lib>
+
+<@lib.smileyInclude 'AbsoluteTemplateNameBIExample-foo.ftl' />
+<@lib.smileyInclude '../AbsoluteTemplateNameBIExample-foo.ftl' />
+<@lib.smileyInclude '/AbsoluteTemplateNameBIExample-foo.ftl' />
+<@lib.smileyInclude 'AbsoluteTemplateNameBIExample-missing.ftl' />
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/8286a7bf/src/test/resources/freemarker/manual/dir/AbsoluteTemplateNameBIExample-main.ftl.out
----------------------------------------------------------------------
diff --git a/src/test/resources/freemarker/manual/dir/AbsoluteTemplateNameBIExample-main.ftl.out b/src/test/resources/freemarker/manual/dir/AbsoluteTemplateNameBIExample-main.ftl.out
new file mode 100644
index 0000000..9e9f175
--- /dev/null
+++ b/src/test/resources/freemarker/manual/dir/AbsoluteTemplateNameBIExample-main.ftl.out
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+ (:
+/dir/foo
+ (:
+/foo
+ (:
+/foo
+ ):
[2/2] incubator-freemarker git commit: Merge remote-tracking branch
'origin/2.3-gae' into 2.3
Posted by dd...@apache.org.
Merge remote-tracking branch 'origin/2.3-gae' into 2.3
Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/5bfa9ac4
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/5bfa9ac4
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/5bfa9ac4
Branch: refs/heads/2.3
Commit: 5bfa9ac426bbf0a03c2cd5009c03e76640a27bd6
Parents: 6442fd7 8286a7b
Author: ddekany <dd...@apache.org>
Authored: Sat Mar 10 21:01:58 2018 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sat Mar 10 21:01:58 2018 +0100
----------------------------------------------------------------------
.../freemarker/cache/TemplateNameFormat.java | 42 +++++++-
src/main/java/freemarker/cache/_CacheAPI.java | 5 +
src/main/java/freemarker/core/BuiltIn.java | 3 +-
.../freemarker/core/BuiltInsForStringsMisc.java | 47 +++++++++
src/main/java/freemarker/core/Environment.java | 26 ++++-
src/manual/en_US/book.xml | 104 +++++++++++++++++--
.../cache/TemplateNameFormatTest.java | 23 +++-
.../core/AbsoluteTemplateNameBITest.java | 72 +++++++++++++
.../manual/AbsoluteTemplateNameBIExample.java | 31 ++++++
.../AbsoluteTemplateNameBIExample-foo.ftl | 19 ++++
.../AbsoluteTemplateNameBIExample-lib.ftl | 38 +++++++
.../dir/AbsoluteTemplateNameBIExample-foo.ftl | 19 ++++
.../dir/AbsoluteTemplateNameBIExample-main.ftl | 24 +++++
.../AbsoluteTemplateNameBIExample-main.ftl.out | 26 +++++
14 files changed, 463 insertions(+), 16 deletions(-)
----------------------------------------------------------------------