Merge remote-tracking branch 'origin/2.3.24-gae-stabilization' into 2.3.24-stabilization
diff --git a/README b/README
index f6e2c31..dde3126 100644
--- a/README
+++ b/README
@@ -139,10 +139,10 @@
 
 - Install Ant and Ivy, if you haven't yet; see earlier.
 - From the command line, run `ant clean javacc ide-dependencies`. (Note that
-  now the "ide-dependencies" library was created. Also that
-  "build/generated-sources" was created.)
+  now the "ide-dependencies" and  "build/generated-sources" was created.)
 - Start Eclipse
-- Many developers prefer to start a new workspace (File -> "Switch workspace")
+- You may prefer to start a new workspace (File -> "Switch workspace"), but
+  it's optional.
 - Window -> Preferences
   - General -> Workspace, set the text file encoding
     to "UTF-8". (Or, you can set the same later on project level instead.)
@@ -150,7 +150,7 @@
     Select src\ide-settings\Eclipse-Mars\Formatter-profile-FreeMarker.xml
     inside the FreeMarker project directory.
     This profile uses space-only indentation policy and 120 character line
-    width, and formattings rules that are pretty much standard in modern Java.
+    width, and formatting rules that are pretty much standard in modern Java.
   - Java -> Installed JRE-s:
     Ensure that you have JDK 6 installed, and that it was added to Eclipse.
     Note that it's not JRE, but JDK.
@@ -158,16 +158,16 @@
   - In the first window popping up:
     - Change the "location" to the directory of the FreeMarker project
     - Press "Next"
-  - In the next window, you see the build path settings. Ensure that:
+  - In the next window, you see the build path settings:
     - On "Source" tab, ensure that exactly these are marked as source
-      directories:
+      directories (be careful, Eclipse doesn't auto-detect these well):
         build/generated-sources/java
         src/main/java
         src/main/resources
         src/test/java
         src/test/resources
     - On the "Libraries" tab:
-      - Delete everyhing from there, except the "JRE System Library [...]".
+      - Delete everyhing from there, except the "JRE System Library [...]"
       - Edit "JRE System Library [...]" to "Execution Environment" "JavaSE 1.6"
       - Add all jar-s that are directly under the "ide-dependencies" directory
         (use the "Add JARs..." and select all those files).
@@ -178,18 +178,19 @@
    - Press "Finish"
 - Eclipse will indicate many errors at this point; it's expected, read on.
 - Project -> Properties -> Java Compiler
-  - Set "Compiler Compliance Level" to "1.5"
+  - Set "Compiler Compliance Level" to "1.5" (you will have to uncheck
+    "Use compliance from execution environment" for that)
   - In Errors/Warnings, check in "Enable project specific settings", then set
     "Forbidden reference (access rules)" from "Error" to "Warning".
-- You will still have errors on these Java files (because different java
+- You will still have errors on these java files (because different java
   files depend on different versions of the same library, and Eclipse can't
-  handle that). Exclude them from the Build Path (in the Package Explorer,
-  right click on the problematic file -> "Build Path" -> "Exclude").
+  handle that). Exclude those java files from the Build Path (in the Package
+  Explorer, right click on the problematic file -> "Build Path" -> "Exclude").
     _Jython20*.java
     _Jython22*.java
     _FreeMarkerPageContext2.java
     FreeMarkerJspFactory2.java
-  Now you shouldn't have any errors.
+  Also, close these files if they are open. Now you shouldn't have any errors.
 - At Project -> Properties -> Java Code Style -> Formatter, check in "Enable
   project specific settings", and then select "FreeMarker" as active profile.
 - Right click on the project -> Run As -> JUnit Test
diff --git a/src/main/java/freemarker/cache/WebappTemplateLoader.java b/src/main/java/freemarker/cache/WebappTemplateLoader.java
index d4f32dc..44c40df 100644
--- a/src/main/java/freemarker/cache/WebappTemplateLoader.java
+++ b/src/main/java/freemarker/cache/WebappTemplateLoader.java
@@ -51,7 +51,7 @@
     private boolean attemptFileAccess = true;
 
     /**
-     * Creates a resource template cache that will use the specified servlet context to load the resources. It will use
+     * Creates a template loader that will use the specified servlet context to load the resources. It will use
      * the base path of <code>"/"</code> meaning templates will be resolved relative to the servlet context root
      * location.
      * 
diff --git a/src/main/java/freemarker/core/CommonTemplateMarkupOutputModel.java b/src/main/java/freemarker/core/CommonTemplateMarkupOutputModel.java
index 9d04428..3f1a43e 100644
--- a/src/main/java/freemarker/core/CommonTemplateMarkupOutputModel.java
+++ b/src/main/java/freemarker/core/CommonTemplateMarkupOutputModel.java
@@ -45,17 +45,20 @@
 
     public abstract CommonMarkupOutputFormat<MO> getOutputFormat();
 
-    /** Maybe {@code null}, but then the other field isn't {@code null}. */
+    /** Maybe {@code null}, but then {@link #getMarkupContent()} isn't {@code null}. */
     final String getPlainTextContent() {
         return plainTextContent;
     }
 
-    /** Maybe {@code null}, but then the other field isn't {@code null}. */
+    /** Maybe {@code null}, but then {@link #getPlainTextContent()} isn't {@code null}. */
     final String getMarkupContent() {
         return markupContet;
     }
 
-    /** Use only to set {@code null} field to the value calculated from the other field! */
+    /**
+     * Use only to set the value calculated from {@link #getPlainTextContent()}, when {@link #getMarkupContent()} was
+     * still {@code null}!
+     */
     final void setMarkupContet(String markupContet) {
         this.markupContet = markupContet;
     }
diff --git a/src/main/java/freemarker/core/MarkupOutputFormat.java b/src/main/java/freemarker/core/MarkupOutputFormat.java
index 0f1302c..b058591 100644
--- a/src/main/java/freemarker/core/MarkupOutputFormat.java
+++ b/src/main/java/freemarker/core/MarkupOutputFormat.java
@@ -21,13 +21,23 @@
 import java.io.IOException;
 import java.io.Writer;
 
+import freemarker.template.Configuration;
 import freemarker.template.TemplateModelException;
 
 /**
- * An {@link OutputFormat}-s that represent a "markup", which is any format where certain character sequences have
- * special meaning and thus may need escaping. (Escaping is important for FreeMarker, as typically it has to insert
- * non-markup text from the data-model into the output markup.) This class, among others, defines the operations related
- * to {@link TemplateMarkupOutputModel}-s that belong to the output format.
+ * Superclass of {@link OutputFormat}-s that represent a "markup" format, which is any format where certain character
+ * sequences have special meaning and thus may need escaping. (Escaping is important for FreeMarker, as typically it has
+ * to insert non-markup text from the data-model into the output markup. See also:
+ * {@link Configuration#setOutputFormat(OutputFormat)}.)
+ * 
+ * <p>
+ * An {@link OutputFormat} subclass always has a corresponding {@link TemplateMarkupOutputModel} subclass pair (like
+ * {@link HTMLOutputFormat} has {@link TemplateHTMLOutputModel}). The {@link OutputFormat} implements the operations
+ * related to {@link TemplateMarkupOutputModel} objects of that kind, while the {@link TemplateMarkupOutputModel} only
+ * encapsulates the data (the actual markup or text).
+ * 
+ * <p>
+ * To implement a custom output format, you may want to extend {@link CommonMarkupOutputFormat}.
  * 
  * @param <MO>
  *            The {@link TemplateMarkupOutputModel} class this output format can deal with.
@@ -105,15 +115,17 @@
     public abstract boolean isEmpty(MO mo) throws TemplateModelException;
     
     /**
-     * Tells if a string built-in that can't handle a {@link TemplateMarkupOutputModel} left operand can bypass this
-     * object as is. A typical such case would be when a {@link TemplateHTMLOutputModel} of "HTML" format bypasses
+     * Tells if a string built-in that can't handle a {@link TemplateMarkupOutputModel} left hand operand can bypass
+     * this object as is. A typical such case would be when a {@link TemplateHTMLOutputModel} of "HTML" format bypasses
      * {@code ?html}.
      */
     public abstract boolean isLegacyBuiltInBypassed(String builtInName) throws TemplateModelException;
     
     /**
      * Tells if by default auto-escaping should be on for this format. It should be {@code true} if you need to escape
-     * on most of the places where you insert values. 
+     * on most of the places where you insert values.
+     * 
+     * @see Configuration#setAutoEscapingPolicy(int)
      */
     public abstract boolean isAutoEscapedByDefault();
     
diff --git a/src/main/java/freemarker/core/OutputFormat.java b/src/main/java/freemarker/core/OutputFormat.java
index 72ea821..5f4bc60 100644
--- a/src/main/java/freemarker/core/OutputFormat.java
+++ b/src/main/java/freemarker/core/OutputFormat.java
@@ -23,7 +23,7 @@
 import freemarker.template.utility.StringUtil;
 
 /**
- * Represents an output format.
+ * Represents an output format. If you need auto-escaping, see its subclass, {@link MarkupOutputFormat}. 
  * 
  * @see Configuration#setOutputFormat(OutputFormat)
  * @see Configuration#setRegisteredCustomOutputFormats(java.util.Collection)
diff --git a/src/main/java/freemarker/core/TemplateConfiguration.java b/src/main/java/freemarker/core/TemplateConfiguration.java
index 2c89d01..50ebc8f 100644
--- a/src/main/java/freemarker/core/TemplateConfiguration.java
+++ b/src/main/java/freemarker/core/TemplateConfiguration.java
@@ -38,11 +38,11 @@
  * <p>
  * Note on the {@code locale} setting: When used with the standard template loading/caching mechanism (
  * {@link Configuration#getTemplate(String)} and its overloads), localized lookup happens before the {@code locale}
- * specified here could have effect. The {@code locale} will be only set in the template that the localized looks has
+ * specified here could have effect. The {@code locale} will be only set in the template that the localized lookup has
  * already found.
  * 
  * <p>
- * Note on encoding setting {@code encoding}: See {@link #setEncoding(String)}.
+ * Note on the encoding setting {@code encoding}: See {@link #setEncoding(String)}.
  * 
  * <p>
  * Note that the result value of the reader methods (getter and "is" methods) is usually not useful unless the value of
diff --git a/src/main/java/freemarker/core/TemplateMarkupOutputModel.java b/src/main/java/freemarker/core/TemplateMarkupOutputModel.java
index 3606379..3beead0 100644
--- a/src/main/java/freemarker/core/TemplateMarkupOutputModel.java
+++ b/src/main/java/freemarker/core/TemplateMarkupOutputModel.java
@@ -18,23 +18,23 @@
  */
 package freemarker.core;
 
-import freemarker.template.Configuration;
 import freemarker.template.TemplateModel;
 import freemarker.template.TemplateScalarModel;
 
 /**
  * "markup output" template language data-type; stores markup (some kind of "rich text" / structured format, as opposed
- * to plain text) that meant to be printed as template output. Each implementation of this type has a
- * {@link OutputFormat} subclass pair (like {@link TemplateHTMLOutputModel} has {@link HTMLOutputFormat}). This type is
- * related to the {@link Configuration#setOutputFormat(OutputFormat)} and
- * {@link Configuration#setAutoEscapingPolicy(int)} mechanism; see more there. Values of this type are exempt from
- * automatic escaping with that mechanism.
+ * to plain text) that meant to be printed as template output. This type is related to the {@link OutputFormat}
+ * mechanism. Values of this kind are exempt from {@link OutputFormat}-based automatic escaping.
  * 
  * <p>
- * Note that {@link TemplateMarkupOutputModel}-s are by design not handled like {@link TemplateScalarModel}-s, and so
+ * Each implementation of this type has a {@link OutputFormat} subclass pair, whose singleton instance is returned by
+ * {@link #getOutputFormat()}. See more about how markup output values work at {@link OutputFormat}.
+ * 
+ * <p>
+ * Note that {@link TemplateMarkupOutputModel}-s are by design not treated like {@link TemplateScalarModel}-s, and so
  * the implementations of this interface usually shouldn't implement {@link TemplateScalarModel}. (Because, operations
- * applicable on plain strings, like converting to upper case, substringing, etc., can corrupt markup.) The template
- * author should make conscious decision of passing in the markup as String by using {@code ?markup_string}.
+ * applicable on plain strings, like converting to upper case, substringing, etc., can corrupt markup.) If the template
+ * author wants to pass in the "source" of the markup as string somewhere, he should use {@code ?markup_string}.
  * 
  * @param <MO>
  *            Refers to the interface's own type, which is useful in interfaces that extend
@@ -44,6 +44,9 @@
  */
 public interface TemplateMarkupOutputModel<MO extends TemplateMarkupOutputModel<MO>> extends TemplateModel {
 
+    /**
+     * Returns the singleton {@link OutputFormat} object that implements the operations for the "markup output" value.
+     */
     MarkupOutputFormat<MO> getOutputFormat();
     
 }
diff --git a/src/main/java/freemarker/template/Configuration.java b/src/main/java/freemarker/template/Configuration.java
index 82c46b3..ec5f270 100644
--- a/src/main/java/freemarker/template/Configuration.java
+++ b/src/main/java/freemarker/template/Configuration.java
@@ -1374,12 +1374,20 @@
     }
 
     /**
-     * Sets the file system directory from which to load templates.
-     * This is equivalent to {@code setTemplateLoader(new FileTemplateLoader(dir))},
-     * so see {@link FileTemplateLoader#FileTemplateLoader(File)} for more details.
+     * Sets the file system directory from which to load templates. This is equivalent to
+     * {@code setTemplateLoader(new FileTemplateLoader(dir))}, so see
+     * {@link FileTemplateLoader#FileTemplateLoader(File)} for more details.
      * 
-     * Note that FreeMarker can load templates from non-file-system sources too. 
-     * See {@link #setTemplateLoader(TemplateLoader)} from more details.
+     * <p>
+     * Note that FreeMarker can load templates from non-file-system sources too. See
+     * {@link #setTemplateLoader(TemplateLoader)} from more details.
+     * 
+     * <p>
+     * Note that this shouldn't be used for loading templates that are coming from a WAR; use
+     * {@link #setServletContextForTemplateLoading(Object, String)} then. Servlet containers might not unpack the WAR
+     * file, in which case you clearly can't access the contained files via {@link File}. Even if the WAR is unpacked,
+     * the servlet container might not expose the location as a {@link File}.
+     * {@link #setServletContextForTemplateLoading(Object, String)} on the other hand will work in all these cases.
      */
     public void setDirectoryForTemplateLoading(File dir) throws IOException {
         TemplateLoader tl = getTemplateLoader();
@@ -1746,8 +1754,8 @@
     }
 
     /**
-     * Sets when auto-escaping should be enabled depending on the current output format; default is
-     * {@link #ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY}. Note that the default output format,
+     * Sets when auto-escaping should be enabled depending on the current {@linkplain OutputFormat output format};
+     * default is {@link #ENABLE_IF_DEFAULT_AUTO_ESCAPING_POLICY}. Note that the default output format,
      * {@link UndefinedOutputFormat}, is a non-escaping format, so there auto-escaping will be off.
      * Note that the templates can turn auto-escaping on/off locally with directives like {@code <#ftl auto_esc=...>},
      * which will ignore the policy.
@@ -1813,7 +1821,7 @@
      * Sets the default output format. Usually, you should leave this on its default, which is
      * {@link UndefinedOutputFormat#INSTANCE}, and then use standard file extensions like "ftlh" (for HTML) or "ftlx"
      * (for XML) and ensure that {@link #setRecognizeStandardFileExtensions(boolean)} is {@code true} (see more there).
-     * Where you can't use standard the file extensions, templates still can be associated to output formats with
+     * Where you can't use the standard the extensions, templates still can be associated to output formats with
      * patterns matching their name (their path) using {@link #setTemplateConfigurations(TemplateConfigurationFactory)}.
      * But if all templates will have the same output format, you may use {@link #setOutputFormat(OutputFormat)} after
      * all, to set a value like {@link HTMLOutputFormat#INSTANCE}, {@link XMLOutputFormat#INSTANCE}, etc. Also note
diff --git a/src/main/java/freemarker/template/DefaultObjectWrapper.java b/src/main/java/freemarker/template/DefaultObjectWrapper.java
index bda6f32..8753ebb 100644
--- a/src/main/java/freemarker/template/DefaultObjectWrapper.java
+++ b/src/main/java/freemarker/template/DefaultObjectWrapper.java
@@ -226,7 +226,7 @@
     }
     
     /**
-     * Called for an object that aren't considered to be of a "basic" Java type, like for an application specific type,
+     * Called for an object that isn't considered to be of a "basic" Java type, like for an application specific type,
      * or for a W3C DOM node. In its default implementation, W3C {@link Node}-s will be wrapped as {@link NodeModel}-s
      * (allows DOM tree traversal), Jython objects will be delegated to the {@code JythonWrapper}, others will be
      * wrapped using {@link BeansWrapper#wrap(Object)}.
diff --git a/src/main/java/freemarker/template/utility/StringUtil.java b/src/main/java/freemarker/template/utility/StringUtil.java
index 58d5ffb..88811f4 100644
--- a/src/main/java/freemarker/template/utility/StringUtil.java
+++ b/src/main/java/freemarker/template/utility/StringUtil.java
@@ -1331,12 +1331,12 @@
      * output. Note that for JSON, the quotation marks must be {@code "}, not {@code '}, because JSON doesn't escape
      * {@code '}.
      * 
-     * <p>The escaping rules guarantee that if the inside
-     * of the literal is from one or more touching sections of strings escaped with this, no character sequence will
-     * occur that closes the string literal or has special meaning in HTML/XML that can terminate the script section.
+     * <p>The escaping rules guarantee that if the inside of the JavaScript/JSON string literal is from one or more
+     * touching pieces that were escaped with this, no character sequence can occur that closes the
+     * JavaScript/JSON string literal, or has a meaning in HTML/XML that causes the HTML script section to be closed.
      * (If, however, the escaped section is preceded by or followed by strings from other sources, this can't be
      * guaranteed in some rare cases. Like <tt>x = "&lt;/${a?js_string}"</tt> might closes the "script"
-     * element if {@code a} is is {@code "script>"}.)
+     * element if {@code a} is {@code "script>"}.)
      * 
      * The escaped characters are:
      * 
diff --git a/src/manual/en_US/book.xml b/src/manual/en_US/book.xml
index 2e6fa99..638c695 100644
--- a/src/manual/en_US/book.xml
+++ b/src/manual/en_US/book.xml
@@ -13328,23 +13328,12 @@
           quotation marks around the inserted value; you meant to use this
           <emphasis>inside</emphasis> the string literal.</para>
 
-          <para>Both quotation mark (<literal>"</literal>) and
-          apostrophe-quoate (<literal>'</literal>) are escaped. It also
-          escapes <literal>&gt;</literal> as <literal>\&gt;</literal> (to
-          avoid <literal>&lt;/script&gt;</literal>).</para>
-
-          <para>All characters under <link linkend="gloss.UCS">UCS</link> code
-          point 0x20 will be escaped. When they have no dedicated escape
-          sequence in JavaScript (like <literal>\n</literal>,
-          <literal>\t</literal>, etc.), they will be replaced with a UNICODE
-          escape
-          (<literal>\u<replaceable>XXXX</replaceable></literal>).</para>
-
           <warning>
             <para>When inserting into a JavaScript string literal that's
             inside a HTML attribute, you also must escape the value with HTML
-            escaping. Thus, of you don't have automatic HTML escaping, this is
-            WRONG: <literal>&lt;p
+            escaping. Thus, of you don't have <link
+            linkend="pgui_config_outputformatsautoesc">automatic HTML
+            escaping</link>, this is WRONG: <literal>&lt;p
             onclick="alert('${message?js_string}')"&gt;</literal>, and this is
             good: <literal>&lt;p
             onclick="alert('${message?js_string?html}')"&gt;</literal>.</para>
@@ -13362,6 +13351,65 @@
           <programlisting role="output">&lt;script&gt;
   alert("Welcome Big Joe\'s \"right hand\"!");
 &lt;/script&gt;</programlisting>
+
+          <para>The exact escaping rules are:</para>
+
+          <itemizedlist>
+            <listitem>
+              <para><literal>"</literal> is escaped as
+              <literal>\"</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><literal>'</literal> is escaped as
+              <literal>\'</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><literal>\</literal> is escaped as
+              <literal>\\</literal></para>
+            </listitem>
+
+            <listitem>
+              <para><literal>/</literal> is escaped as <literal>\/</literal>
+              if the <literal>/</literal> is directly after
+              <literal>&lt;</literal> in the escaped string, or if it's at the
+              beginning of the escaped string</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>&gt;</literal> is escaped as
+              <literal>\&gt;</literal> if the <literal>&gt;</literal> is
+              directly after <literal>]]</literal> or <literal>--</literal> in
+              the escaped string, or if it's at the beginning of the escaped
+              string, or if there's only a <literal>]</literal> or
+              <literal>-</literal> before it at the beginning of the escaped
+              string</para>
+            </listitem>
+
+            <listitem>
+              <para><literal>&lt;</literal> is escaped as
+              <literal>\u003C</literal> if it's followed by
+              <literal>?</literal> or <literal>!</literal> in the escaped
+              string, or if it's at the end of the escaped string</para>
+            </listitem>
+
+            <listitem>
+              <para>Control characters in <link linkend="gloss.UCS">UCS</link>
+              code point ranges U+0000...U+001f and U+007f...U+009f are
+              escaped as <literal>\r</literal>, <literal>\n</literal>, etc.,
+              or as <literal>\x<replaceable>XX</replaceable></literal> where
+              there's no special escape for them in JavaScript.</para>
+            </listitem>
+
+            <listitem>
+              <para>Control characters with <link
+              linkend="gloss.UCS">UCS</link> code point U+2028 (Line
+              separator) and U+2029 (Paragraph separator) are escaped as
+              <literal>\u<replaceable>XXXX</replaceable></literal>, as they
+              are source code line-breaks in ECMAScript.</para>
+            </listitem>
+          </itemizedlist>
         </section>
 
         <section xml:id="ref_builtin_json_string">
@@ -13378,20 +13426,16 @@
           <emphasis>inside</emphasis> the string literal.</para>
 
           <para>This will not escape <literal>'</literal> characters, since
-          JSON strings must be quoted with <literal>"</literal>. It will,
-          however escape the <literal>/</literal> (slash) characters as
-          <literal>\/</literal> where they occur directly after a
-          <literal>&lt;</literal>, to avoid <literal>&lt;/script&gt;</literal>
-          and such. It will also escape the <literal>&gt;</literal> characters
-          as <literal>\u003E</literal> where they occur directly after
-          <literal>]]</literal>, to avoid exiting an XML
-          <literal>CDATA</literal> section.</para>
+          JSON strings must be quoted with <literal>"</literal>.</para>
 
-          <para>All characters under <link linkend="gloss.UCS">UCS</link> code
-          point 0x20 will be escaped. When they have no dedicated escape
-          sequence in JSON (like <literal>\n</literal>, <literal>\t</literal>,
-          etc.), they will be replaced with a UNICODE escape
-          (<literal>\u<replaceable>XXXX</replaceable></literal>).</para>
+          <para>The escaping rules are almost identical to those <link
+          linkend="ref_builtin_j_string">documented for
+          <literal>js_string</literal></link>. The differences are that
+          <literal>'</literal> is not escaped at all, that &gt; is escaped as
+          \u003E (not as \&gt;), and that
+          <literal>\u<replaceable>XXXX</replaceable></literal> escapes are
+          used instead of <literal>\x<replaceable>XX</replaceable></literal>
+          escapes.</para>
         </section>
 
         <section xml:id="ref_builtin_keep_after">
@@ -20342,19 +20386,21 @@
   &lt;/div&gt;
 &lt;/#list&gt;</programlisting>
 
-            <para>As <literal>sep</literal> is just a convenient way of
-            writing <literal>&lt;#if
-            <replaceable>item</replaceable>?has_next&gt;...&lt;/#if&gt;</literal>,
-            it can be used anywhere where there's a <literal>list</literal> or
-            <literal>items</literal> loop variable is available, and for
-            unlimited times. Also, it can have arbitrary FTL as nested
-            content.</para>
+            <para><literal>sep</literal> is just a shorthand for
+            <literal>&lt;#if
+            <replaceable>item</replaceable>?has_next&gt;...&lt;/#if&gt;</literal>.
+            Thus, it can be used anywhere where there's a
+            <literal>list</literal> or <literal>items</literal> loop variable
+            available, it can occur for multiple times, and it can have
+            arbitrary nested content.</para>
 
-            <para>The parser will check that <literal>sep</literal> is used
-            inside <literal>list <replaceable>...</replaceable> as
-            item</literal> or an <literal>items</literal> directive, so you
-            can't move <literal>sep</literal> out from the repeated part into
-            a macro or included template.</para>
+            <para>The parser ensures that <literal>sep</literal> is only used
+            on a place where there's a visible loop variable. This happens
+            earlier than the actual execution of the template. Thus, you can't
+            move <literal>sep</literal> from inside the associated
+            <literal>list</literal> or <literal>items</literal> directive into
+            a macro or included template (the parser can't know where those
+            will be called from).</para>
           </section>
 
           <section>
diff --git a/src/test/java/freemarker/core/OutputFormatTest.java b/src/test/java/freemarker/core/OutputFormatTest.java
index dc5e7d4..bab9619 100644
--- a/src/test/java/freemarker/core/OutputFormatTest.java
+++ b/src/test/java/freemarker/core/OutputFormatTest.java
@@ -944,7 +944,7 @@
     }
     
     @Test
-    public void testBannedDirectivesIsWhenAutoEscaping() throws Exception {
+    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");