You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2008/01/09 19:54:23 UTC

svn commit: r610514 - in /tapestry/tapestry5/trunk: tapestry-core/src/main/java/org/apache/tapestry/internal/parser/ tapestry-core/src/main/java/org/apache/tapestry/internal/services/ tapestry-core/src/main/resources/org/apache/tapestry/internal/servic...

Author: hlship
Date: Wed Jan  9 10:54:12 2008
New Revision: 610514

URL: http://svn.apache.org/viewvc?rev=610514&view=rev
Log:
TAPESTRY-2028: Mimimize whitespace in the output markup

Added:
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/space_preserved_in_block.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/space_preserved_in_container.tml
Modified:
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/AttributeToken.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/StartElementToken.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java
    tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
    tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/templates.apt
    tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Start.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/TemplateParserImplTest.java
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/Countdown.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/MerryChristmas.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterConflict.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/cdata.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/component.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/componentWithBody.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/componentWithParameters.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/content_within_body_element.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/empty_string_mixins_is_null.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/expansions_must_be_on_one_line.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/expansions_not_allowed_in_cdata.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/justHTML.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/multilineComment.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/multiple_expansions_on_one_line.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/namespaced_element.tml
    tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/parameter_element.tml
    tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/Stack.java
    tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/StackTest.java

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/AttributeToken.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/AttributeToken.java?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/AttributeToken.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/AttributeToken.java Wed Jan  9 10:54:12 2008
@@ -1,17 +1,17 @@
-// Copyright 2006 The Apache Software Foundation
-//
-// Licensed 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.
-
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed 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 org.apache.tapestry.internal.parser;
 
 import org.apache.tapestry.ioc.Location;
@@ -64,6 +64,12 @@
     @Override
     public String toString()
     {
-        return String.format("Attribute[%s %s=%s]", _namespaceURI, _name, _value);
+        StringBuilder builder = new StringBuilder("Attribute[");
+
+        if (_namespaceURI.length() > 0) builder.append(_namespaceURI).append(" ");
+
+        builder.append(_name).append("=").append(_value).append("]");
+
+        return builder.toString();
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/StartElementToken.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/StartElementToken.java?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/StartElementToken.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/parser/StartElementToken.java Wed Jan  9 10:54:12 2008
@@ -1,17 +1,17 @@
-// Copyright 2006 The Apache Software Foundation
-//
-// Licensed 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.
-
+// Copyright 2006 The Apache Software Foundation
+//
+// Licensed 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 org.apache.tapestry.internal.parser;
 
 import org.apache.tapestry.ioc.Location;
@@ -57,6 +57,12 @@
     @Override
     public String toString()
     {
-        return String.format("Start[%s %s]", _namespaceURI, _name);
+        StringBuilder builder = new StringBuilder("Start[");
+
+        if (_namespaceURI.length() > 0) builder.append(_namespaceURI).append(" ");
+
+        builder.append(_name).append("]");
+
+        return builder.toString();
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/ServicesMessages.java Wed Jan  9 10:54:12 2008
@@ -1,4 +1,4 @@
-// Copyright 2006, 2007 The Apache Software Foundation
+// Copyright 2006, 2007, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -389,5 +389,10 @@
     static String invalidId(String messageKey, String idValue)
     {
         return MESSAGES.format(messageKey, idValue);
+    }
+
+    static String attributeNotAllowed(String elementName)
+    {
+        return MESSAGES.format("attribute-not-allowed", elementName);
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/java/org/apache/tapestry/internal/services/TemplateParserImpl.java Wed Jan  9 10:54:12 2008
@@ -50,11 +50,28 @@
 
     private static final String ID_ATTRIBUTE_NAME = "id";
 
+    public static final String XML_NAMESPACE_URI = "http://www.w3.org/XML/1998/namespace";
+
+    /**
+     * Used as the namespace URI for Tapestry templates.
+     */
     public static final String TAPESTRY_SCHEMA_5_0_0 = "http://tapestry.apache.org/schema/tapestry_5_0_0.xsd";
 
-    private static final String ID_REGEXP = "^[a-z]\\w*$";
+    private static final Pattern ID_PATTERN = Pattern.compile("^[a-z]\\w*$", Pattern.CASE_INSENSITIVE);
+
+    /**
+     * Used when compressing whitespace.
+     */
+    private static final Pattern REDUCE_WHITESPACE_PATTERN = Pattern.compile("//s+");
+
+    // Note the use of the non-greedy modifier; this prevents the pattern from merging multiple
+    // expansions on the same text line into a single large
+    // but invalid expansion.
+
+    private static final String EXPANSION_REGEXP = "\\$\\{\\s*(.*?)\\s*}";
+
+    private static final Pattern EXPANSION_PATTERN = Pattern.compile(EXPANSION_REGEXP, Pattern.MULTILINE);
 
-    private static final Pattern ID_PATTERN = Pattern.compile(ID_REGEXP, Pattern.CASE_INSENSITIVE);
 
     private XMLReader _reader;
 
@@ -99,11 +116,19 @@
 
     private final Stack<Runnable> _endTagHandlerStack = new Stack<Runnable>();
 
-    private final Runnable _addEndElementToken = new Runnable()
+    private boolean _compressWhitespace;
+
+    private final Stack<Boolean> _compressWhitespaceStack = new Stack<Boolean>();
+
+    private final Runnable _endOfElementHandler = new Runnable()
     {
         public void run()
         {
             _tokens.add(new EndElementToken(getCurrentLocation()));
+
+            // Restore the flag to how it was before the element was parsed.
+
+            _compressWhitespace = _compressWhitespaceStack.pop();
         }
     };
 
@@ -111,16 +136,10 @@
     {
         public void run()
         {
+            _compressWhitespace = _compressWhitespaceStack.pop();
         }
     };
 
-    // Note the use of the non-greedy modifier; this prevents the pattern from merging multiple
-    // expansions on the same text line into a single large
-    // but invalid expansion.
-
-    private static final String EXPANSION_REGEXP = "\\$\\{\\s*(.*?)\\s*}";
-
-    private static final Pattern EXPANSION_PATTERN = Pattern.compile(EXPANSION_REGEXP, Pattern.MULTILINE);
 
     public TemplateParserImpl(Logger logger, Map<String, URL> configuration)
     {
@@ -144,13 +163,14 @@
         _insideBodyErrorLogged = false;
         _ignoreEvents = true;
 
-        // Stack needs a clear();
-
-        while (!_endTagHandlerStack.isEmpty()) _endTagHandlerStack.pop();
+        _endTagHandlerStack.clear();
+        _compressWhitespaceStack.clear();
     }
 
     public ComponentTemplate parseTemplate(Resource templateResource)
     {
+        _compressWhitespace = true;
+
         if (_reader == null)
         {
             try
@@ -220,6 +240,7 @@
         _textBuffer.append(ch, start, length);
     }
 
+
     /**
      * Adds tokens corresponding to the content in the text buffer. For a non-CDATA section, we also
      * search for expansions (thus we may add more than one token). Clears the text buffer.
@@ -236,6 +257,8 @@
         }
         else
         {
+            if (_compressWhitespace) text = REDUCE_WHITESPACE_PATTERN.matcher(text.trim()).replaceAll(" ");
+
             addTokensForText(text);
         }
 
@@ -246,7 +269,8 @@
      * Scans the text, using a regular expression pattern, for expansion patterns, and adds
      * appropriate tokens for what it finds.
      *
-     * @param text
+     * @param text to add as {@link org.apache.tapestry.internal.parser.TextToken}s
+     *             and {@link org.apache.tapestry.internal.parser.ExpansionToken}s
      */
     private void addTokensForText(String text)
     {
@@ -256,7 +280,9 @@
 
         // The big problem with all this code is that everything gets assigned to the
         // start of the text block, even if there are line breaks leading up to it.
-        // That's going to take a lot more work and there are bigger fish to fry.
+        // That's going to take a lot more work and there are bigger fish to fry.  In addition,
+        // TAPESTRY-2028 means that the whitespace has likely been stripped out of the text
+        // already anyway.
 
         while (matcher.find())
         {
@@ -269,9 +295,8 @@
                 _tokens.add(new TextToken(prefix, _textStartLocation));
             }
 
-            // Group 1 includes the real text of the expansion, which whitespace around the
-            // expression (but inside the curly
-            // braces) excluded.
+            // Group 1 includes the real text of the expansion, with whitespace around the
+            // expression (but inside the curly braces) excluded.
 
             String expression = matcher.group(1);
 
@@ -349,7 +374,7 @@
 
         if (localName.equalsIgnoreCase("container"))
         {
-            startContainer();
+            startContainer(localName, attributes);
             return;
         }
 
@@ -363,14 +388,35 @@
         startPossibleComponent(attributes, null, null, componentType);
     }
 
-    private void startContainer()
+    private void startContainer(String elementName, Attributes attributes)
     {
+        _compressWhitespaceStack.push(_compressWhitespace);
+
         // Neither the container nor its end tag are considered tokens, just the contents inside.
+
         _endTagHandlerStack.push(_ignoreEndElement);
+
+        for (int i = 0; i < attributes.getLength(); i++)
+        {
+            String name = attributes.getLocalName(i);
+
+            // The name will be blank for an xmlns: attribute
+
+            if (InternalUtils.isBlank(name)) continue;
+
+            String uri = attributes.getURI(i);
+            String value = attributes.getValue(i);
+
+            if (isXMLSpaceAttribute(uri, name, value)) continue;
+
+            throw new TapestryException(ServicesMessages.attributeNotAllowed(elementName), getCurrentLocation(), null);
+        }
     }
 
     private void startBlock(Attributes attributes)
     {
+        addEndOfElementHandler();
+
         String blockId = findSingleParameter("block", "id", attributes);
 
         validateId(blockId, "invalid-block-id");
@@ -378,18 +424,34 @@
         // null is ok for blockId
 
         _tokens.add(new BlockToken(blockId, getCurrentLocation()));
-        _endTagHandlerStack.push(_addEndElementToken);
+
+        // TODO: Check for an xml:space attribute
     }
 
     private void startParameter(Attributes attributes)
     {
+        addEndOfElementHandler();
+
         String parameterName = findSingleParameter("parameter", "name", attributes);
 
         if (InternalUtils.isBlank(parameterName))
             throw new TapestryException(ServicesMessages.parameterElementNameRequired(), getCurrentLocation(), null);
 
         _tokens.add(new ParameterToken(parameterName, getCurrentLocation()));
-        _endTagHandlerStack.push(_addEndElementToken);
+    }
+
+    /**
+     * Should be called *before* the _compressWhitespace is changed.
+     */
+    private void addEndOfElementHandler()
+    {
+        // Record how the flag was set at the start of the element
+
+        _compressWhitespaceStack.push(_compressWhitespace);
+
+        _endTagHandlerStack.push(_endOfElementHandler);
+
+
     }
 
     private String findSingleParameter(String elementName, String attributeName, Attributes attributes)
@@ -398,15 +460,19 @@
 
         for (int i = 0; i < attributes.getLength(); i++)
         {
+            String uri = attributes.getURI(i);
             String name = attributes.getLocalName(i);
+            String value = attributes.getValue(i);
+
+            if (isXMLSpaceAttribute(uri, name, value)) continue;
 
             if (name.equals(attributeName))
             {
-                result = attributes.getValue(i);
+                result = value;
                 continue;
             }
 
-            // Only the name attribute is allowed.
+            // Only the named attribute is allowed.
 
             throw new TapestryException(ServicesMessages.undefinedTapestryAttribute(elementName, name, attributeName),
                                         getCurrentLocation(), null);
@@ -415,6 +481,22 @@
         return result;
     }
 
+    private boolean isXMLSpaceAttribute(String uri, String name, String value)
+    {
+
+        if (uri.equals(XML_NAMESPACE_URI) && name.equals("space"))
+        {
+            // "preserve" turns off whitespace compression
+            // "default" (the other option, but we'll accept anything) turns it on (or leaves it on, more likely).
+
+            _compressWhitespace = !"preserve".equalsIgnoreCase(value);
+
+            return true;
+        }
+
+        return false;
+    }
+
     private String nullForBlank(String input)
     {
         return InternalUtils.isBlank(input) ? null : input;
@@ -430,6 +512,11 @@
     private void startPossibleComponent(Attributes attributes, String namespaceURI, String elementName,
                                         String identifiedType)
     {
+
+        // Add an end handler to match this start tag.
+
+        addEndOfElementHandler();
+
         String id = null;
         String type = identifiedType;
         String mixins = null;
@@ -476,6 +563,9 @@
                 // not part of the template's doctype for the element being instrumented.
             }
 
+
+            if (isXMLSpaceAttribute(uri, name, value)) continue;
+
             attributeTokens.add(new AttributeToken(uri, name, value, location));
         }
 
@@ -504,7 +594,6 @@
         // TODO: Is there value in having different end elements for components vs. ordinary
         // elements?
 
-        _endTagHandlerStack.push(_addEndElementToken);
     }
 
     private void validateId(String id, String messageKey)

Modified: tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/main/resources/org/apache/tapestry/internal/services/ServicesStrings.properties Wed Jan  9 10:54:12 2008
@@ -63,6 +63,7 @@
 missing-from-environment=No object of type %s is available from the Environment.  Available types are %s.
 invalid-component-event-result=An event handler for component %s returned the value %s (from method %s).  Return type %s can not be handled.  Configured return types are %s.
 undefined-tapestry-attribute=Element <%s> does not support an attribute named '%s'. The only allowed attribute name is '%s'.
+attribute-not-allowed=Element <%s> does not support any attributes.
 parameter-element-name-required=The name attribute of the <parameter> element must be specified.
 missing-application-state-persistence-strategy=No application state persistence strategy is available with name '%s'. Available strategies: %s.
 method-is-void=Method '%s' returns void (in class %s, within property expression '%s').

Modified: tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/templates.apt
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/templates.apt?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/templates.apt (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/site/apt/guide/templates.apt Wed Jan  9 10:54:12 2008
@@ -340,7 +340,63 @@
   It will write a dynamic class attribute into each \<tr\>.
         
    
+Whitespace in Templates
 
+  Tapestry strips out unnecessary whitespace from templates as they are parsed.  This includes whitespace
+  immediately before and after a start or end tag.  Inside any block of text, repeated whitespace is reduced
+  to a single space character.
+
+  If you do a view source on the rendered output, you'll see that the bulk of the rendered page is one
+  long unbroken line.
+
+  This approach has certain efficiency advantages on both the server (less processing to render the page) and on the client
+  (fewer characters to parse).  Tools such as
+  {{{http://www.getfirebug.com/}FireBug}} are useful for allowing you to view the rendered HTML on the client properly.
+
+  In rare cases, the whitespace in a template <is> significant.  Perhaps you are creating a \<pre\> (preformatted)
+  block of text, or the whitespace interacts with your stylesheet to some desired effect.
+
+  You may use the standard XML attribute <<<xml:space>>> to indicate to Tapestry whether whitespace should
+  be compressed (<<<xml:space="default">>>) or preserved (<<<xml:space="preserve">>>).  Such attributes are stripped
+  out by the template parser; they do not appear in the rendered output.
+
+  The xml: namespace prefix is built into all XML documents, there is no special configuration (as there is with the
+  Tapestry namespace).
+
+  For example:
+
+---
+  <ul class="navmenu" xml:space="preserve">
+    <li t:type="loop" t:source="pages" t:value="var:page">
+      <t:pagelink page="var:page">${var:page}</t:pagelink>
+    </li>
+  </ul>
+---
+
+  This will preserve the whitespace between the \<ul\> and \<li\> elements, and between the
+  (rendered) \<li\> elements and the nested \<a\> elements.  For example, the output may look something like:
+
+---
+  <ul>
+    <li>
+      <a href="showcart>ShowCart</a>
+    </li>
+    <li>
+      <a href="viewaccount">ViewAccount</a>
+    </li>
+  </ul>
+---
+
+  With normal whitespace compression, you would see the following rendered output:
+
+---
+  <ul><li><a href="showcart">ShowCart</a></li><li><a href="viewaccount">ViewAccount</li></ul>
+---
+
+
+  You can even put further <<<xml:space>>> attributes inside nested elements to fine-tune the control over
+  what whitespace is preserved and what is compressed.
+  
   
 
   

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Start.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Start.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Start.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/app1/Start.tml Wed Jan  9 10:54:12 2008
@@ -4,7 +4,7 @@
     <h1>Tapestry 5 Integration Application 1</h1>
 
 
-    <ul>
+    <ul xml:space="default">
         <li>
             <a t:type="PageLink" page="MerryChristmas">Count Page</a>
         </li>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/integration/IntegrationTests.java Wed Jan  9 10:54:12 2008
@@ -865,7 +865,7 @@
     {
         start("Inherited Bindings Demo");
 
-        assertTextPresent("Bound: [ value: the-bound-value, bound: true ]", "Unbound: [ value: null, bound: false ]");
+        assertTextPresent("Bound:[ value: the-bound-value, bound: true ]", "Unbound:[ value: null, bound: false ]");
     }
 
     @Test

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/TemplateParserImplTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/TemplateParserImplTest.java?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/TemplateParserImplTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/java/org/apache/tapestry/internal/services/TemplateParserImplTest.java Wed Jan  9 10:54:12 2008
@@ -274,15 +274,15 @@
 
         // Again, whitespace before and after the comment adds some tokens
 
-        assertEquals(tokens.size(), 5);
+        assertEquals(tokens.size(), 3);
 
-        CommentToken t = get(tokens, 2);
+        CommentToken token1 = get(tokens, 1);
 
         // Comments are now trimmed of leading and trailing whitespace. This may mean
         // that the output isn't precisely what's in the template, but a) its a comment
         // and b) that's pretty much true of everything in the templates.
 
-        assertEquals(t.getComment(), "Single line comment");
+        assertEquals(token1.getComment(), "Single line comment");
     }
 
     @Test
@@ -442,13 +442,13 @@
     {
         List<TemplateToken> tokens = tokens("component_with_mixins.tml");
 
-        assertEquals(tokens.size(), 6);
+        assertEquals(tokens.size(), 4);
 
-        StartComponentToken t = get(tokens, 2);
+        StartComponentToken token1 = get(tokens, 1);
 
-        assertEquals(t.getId(), "fred");
-        assertEquals(t.getComponentType(), "comp");
-        assertEquals(t.getMixins(), "Barney");
+        assertEquals(token1.getId(), "fred");
+        assertEquals(token1.getComponentType(), "comp");
+        assertEquals(token1.getMixins(), "Barney");
     }
 
     @Test
@@ -554,12 +554,12 @@
     {
         List<TemplateToken> tokens = tokens("expansions_not_allowed_in_attributes.tml");
 
-        assertEquals(tokens.size(), 4);
+        assertEquals(tokens.size(), 3);
 
-        AttributeToken t1 = get(tokens, 1);
+        AttributeToken token1 = get(tokens, 1);
 
-        assertEquals(t1.getName(), "exp");
-        assertEquals(t1.getValue(), "${not-an-expansion}");
+        assertEquals(token1.getName(), "exp");
+        assertEquals(token1.getValue(), "${not-an-expansion}");
     }
 
     @Test
@@ -583,11 +583,11 @@
     {
         List<TemplateToken> tokens = tokens("complex_component_type.tml");
 
-        assertEquals(tokens.size(), 6);
+        assertEquals(tokens.size(), 4);
 
-        StartComponentToken token2 = get(tokens, 2);
+        StartComponentToken token1 = get(tokens, 1);
 
-        assertEquals(token2.getComponentType(), "subfolder/nifty");
+        assertEquals(token1.getComponentType(), "subfolder/nifty");
     }
 
     @Test
@@ -595,17 +595,17 @@
     {
         List<TemplateToken> tokens = tokens("block_element.tml");
 
-        BlockToken token2 = get(tokens, 2);
-        assertEquals(token2.getId(), "block0");
+        BlockToken token1 = get(tokens, 1);
+        assertEquals(token1.getId(), "block0");
 
-        CommentToken token4 = get(tokens, 4);
-        assertEquals(token4.getComment(), "block0 content");
+        CommentToken token2 = get(tokens, 2);
+        assertEquals(token2.getComment(), "block0 content");
 
-        BlockToken token8 = get(tokens, 8);
-        assertNull(token8.getId());
+        BlockToken token4 = get(tokens, 4);
+        assertNull(token4.getId());
 
-        CommentToken token10 = get(tokens, 10);
-        assertEquals(token10.getComment(), "anon block content");
+        CommentToken token5 = get(tokens, 5);
+        assertEquals(token5.getComment(), "anon block content");
     }
 
     @DataProvider(name = "parse_failure_data")
@@ -729,5 +729,34 @@
         {
             assertMessageContains(ex, "Block id 'not-valid' is not valid");
         }
+    }
+
+    /**
+     * Because of common code, this covers t:block and t:parameter.
+     */
+    @Test
+    public void space_preserved_in_block() throws Exception
+    {
+        List<TemplateToken> tokens = tokens("space_preserved_in_block.tml");
+
+        TextToken token1 = get(tokens, 1);
+
+        assertEquals(token1.getText(), "\n" + "        line in the middle\n" + "    ");
+    }
+
+    /**
+     * t:container is a bit of a different code path than t:block/t:parameter
+     */
+    @Test
+    public void space_preserved_in_container() throws Exception
+    {
+        List<TemplateToken> tokens = tokens("space_preserved_in_container.tml");
+
+        TextToken token0 = get(tokens, 0);
+        assertEquals(token0.getText(), "\n" + "    ");
+
+        TextToken token2 = get(tokens, 2);
+        assertEquals(token2.getText(), "\n" + "        some text\n" + "    ");
+
     }
 }

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/Countdown.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/Countdown.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/Countdown.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/Countdown.tml Wed Jan  9 10:54:12 2008
@@ -1,11 +1,13 @@
 <html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
-    <p> This component demonstrates embedded components defined in the component class using the @Component annotation.</p>
-    <p> Countdown: <div t:id="count">
-            ${countValue}
-        </div>
+    <p>This component demonstrates embedded components defined in the component class using the @Component annotation.
     </p>
-    
-    <p>
-        Brought to you by the ${component:count} component.
+    <p>Countdown:
+        <div t:id="count" xml:space="preserve">
+            ${countValue}
+        </div>
+    </p>
+
+    <p>
+        Brought to you by the ${component:count} component.
     </p>
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/MerryChristmas.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/MerryChristmas.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/MerryChristmas.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/MerryChristmas.tml Wed Jan  9 10:54:12 2008
@@ -1,4 +1,5 @@
 <html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
-    <p> Merry Christmas: <t:loop source="1..3"> Ho! </t:loop>
+    <p>Merry Christmas:
+        <t:loop source="1..3" xml:space="preserve">Ho!</t:loop>
     </p>
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterConflict.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterConflict.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterConflict.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/ParameterConflict.tml Wed Jan  9 10:54:12 2008
@@ -1,6 +1,8 @@
-<html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
-    <p> This component demonstrates that template values are overriden by
-        bindings inside the @Component annotation, in the component class.</p>
-        
-        Output: <span t:id="echo" value="literal:TemplateValue"/>
+<html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" xml:space="preserve">
+    <p>This component demonstrates that template values are overriden by
+        bindings inside the @Component annotation, in the component class.
+    </p>
+
+    Output:
+    <span t:id="echo" value="literal:TemplateValue"/>
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/integration/app1/pages/RenderPhaseOrder.tml Wed Jan  9 10:54:12 2008
@@ -1,13 +1,13 @@
 <html t:type="Border" xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
 
-    <p>
+    <p>
         This page demonstrates the order of render phase operations. Certains later phases
         will execute in the exact opposite order from the earlier phases, to ensure
-        that output operations balance.
+        that output operations balance.
     </p>
-    
-    <p>
-      [<t:Tracer t:mixins="TracerMixin"> BODY </t:Tracer>]
+
+    <p>
+        [<t:Tracer t:mixins="TracerMixin" xml:space="preserve">BODY</t:Tracer>]
     </p>
 
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/cdata.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/cdata.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/cdata.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/cdata.tml Wed Jan  9 10:54:12 2008
@@ -1,3 +1,3 @@
-<html>
-<![CDATA[CDATA: &lt;foo&gt; &amp; &lt;bar&gt; and <baz>]]>    
+<html xml:space="preserve">
+    <![CDATA[CDATA: &lt;foo&gt; &amp; &lt;bar&gt; and <baz>]]>
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/component.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/component.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/component.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/component.tml Wed Jan  9 10:54:12 2008
@@ -1,4 +1,4 @@
-<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" xml:space="preserve">
     <t:somecomponent t:id="fred"/>
 </html>
     

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/componentWithBody.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/componentWithBody.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/componentWithBody.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/componentWithBody.tml Wed Jan  9 10:54:12 2008
@@ -1,5 +1,5 @@
-<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
-  <t:Fred t:id="fred"> 
-    fred's body 
-  </t:Fred>
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" xml:space="preserve">
+    <t:Fred t:id="fred">
+        fred's body
+    </t:Fred>
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/componentWithParameters.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/componentWithParameters.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/componentWithParameters.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/componentWithParameters.tml Wed Jan  9 10:54:12 2008
@@ -1,5 +1,5 @@
-<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
-  <t:Fred t:id="fred" cherry="bomb" align="right"> 
-        fred's body 
-  </t:Fred>
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" xml:space="preserve">
+    <t:Fred t:id="fred" cherry="bomb" align="right">
+        fred's body
+    </t:Fred>
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/content_within_body_element.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/content_within_body_element.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/content_within_body_element.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/content_within_body_element.tml Wed Jan  9 10:54:12 2008
@@ -1,7 +1,7 @@
-<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
-    <t:body>
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" xml:space="preserve">
+    <t:body>
         Some text (starts on line 2)
         <!-- A comment -->
-        <![CDATA[ CData text ]]>
+        <![CDATA[ CData text ]]>
     </t:body>
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/empty_string_mixins_is_null.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/empty_string_mixins_is_null.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/empty_string_mixins_is_null.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/empty_string_mixins_is_null.tml Wed Jan  9 10:54:12 2008
@@ -1,3 +1,3 @@
-<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" xml:space="preserve">
     <span t:id="fred" t:mixins=""/>
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/expansions_must_be_on_one_line.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/expansions_must_be_on_one_line.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/expansions_must_be_on_one_line.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/expansions_must_be_on_one_line.tml Wed Jan  9 10:54:12 2008
@@ -1,9 +1,9 @@
-<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
-    
-${expansions
-must
-be
-on a single
-line}
-    
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" xml:space="preserve">
+
+    ${expansions
+    must
+    be
+    on a single
+    line}
+
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/expansions_not_allowed_in_cdata.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/expansions_not_allowed_in_cdata.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/expansions_not_allowed_in_cdata.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/expansions_not_allowed_in_cdata.tml Wed Jan  9 10:54:12 2008
@@ -1,5 +1,5 @@
-<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
-    
-<![CDATA[${not-an-expansion}]]>
-    
-</html>
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" xml:space="preserve">
+
+    <![CDATA[${not-an-expansion}]]>
+
+</html>
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/justHTML.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/justHTML.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/justHTML.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/justHTML.tml Wed Jan  9 10:54:12 2008
@@ -1,12 +1,12 @@
-<html>
+<html xml:space="preserve">
     <head>
         <title>title</title>
     </head>
     <body>
-        <p class="important"> Tapestry rocks!
-            
-Line 2
-            
+        <p class="important">Tapestry rocks!
+
+            Line 2
+
         </p>
     </body>
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/multilineComment.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/multilineComment.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/multilineComment.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/multilineComment.tml Wed Jan  9 10:54:12 2008
@@ -1,4 +1,4 @@
-<html>
+<html xml:space="preserve">
     <!-- Line one
          Line two
          Line three -->

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/multiple_expansions_on_one_line.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/multiple_expansions_on_one_line.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/multiple_expansions_on_one_line.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/multiple_expansions_on_one_line.tml Wed Jan  9 10:54:12 2008
@@ -1,3 +1,3 @@
-<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" xml:space="preserve">
     <dd>${classLoader} [${classLoader.class.name}]</dd>
 </html>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/namespaced_element.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/namespaced_element.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/namespaced_element.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/namespaced_element.tml Wed Jan  9 10:54:12 2008
@@ -1,3 +1,3 @@
-<foo:bar xmlns:foo="http://foo.com" foo:biff="baz">
+<foo:bar xmlns:foo="http://foo.com" foo:biff="baz" xml:space="preserve">
     <gnip/>
 </foo:bar>

Modified: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/parameter_element.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/parameter_element.tml?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/parameter_element.tml (original)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/parameter_element.tml Wed Jan  9 10:54:12 2008
@@ -1,9 +1,9 @@
-<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
-    
+<html xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" xml:space="preserve">
+
     <t:mycomp t:id="foo">
         <t:parameter name="fred">
             <!-- fred content -->
         </t:parameter>
     </t:mycomp>
-    
+
 </html>

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/space_preserved_in_block.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/space_preserved_in_block.tml?rev=610514&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/space_preserved_in_block.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/space_preserved_in_block.tml Wed Jan  9 10:54:12 2008
@@ -0,0 +1,5 @@
+<t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd">
+    <t:block xml:space="preserve">
+        line in the middle
+    </t:block>
+</t:container>
\ No newline at end of file

Added: tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/space_preserved_in_container.tml
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/space_preserved_in_container.tml?rev=610514&view=auto
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/space_preserved_in_container.tml (added)
+++ tapestry/tapestry5/trunk/tapestry-core/src/test/resources/org/apache/tapestry/internal/services/space_preserved_in_container.tml Wed Jan  9 10:54:12 2008
@@ -0,0 +1,5 @@
+<t:container xmlns:t="http://tapestry.apache.org/schema/tapestry_5_0_0.xsd" xml:space="preserve">
+    <span>
+        some text
+    </span>
+</t:container>
\ No newline at end of file

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/Stack.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/Stack.java?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/Stack.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/main/java/org/apache/tapestry/ioc/util/Stack.java Wed Jan  9 10:54:12 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -57,6 +57,16 @@
     public boolean isEmpty()
     {
         return _index < 0;
+    }
+
+    /**
+     * Clears the stack, the same as popping off all elements.
+     */
+    public void clear()
+    {
+        for (int i = 0; i <= _index; i++) _items[i] = null;
+
+        _index = -1;
     }
 
     /**

Modified: tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/StackTest.java
URL: http://svn.apache.org/viewvc/tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/StackTest.java?rev=610514&r1=610513&r2=610514&view=diff
==============================================================================
--- tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/StackTest.java (original)
+++ tapestry/tapestry5/trunk/tapestry-ioc/src/test/java/org/apache/tapestry/ioc/util/StackTest.java Wed Jan  9 10:54:12 2008
@@ -1,4 +1,4 @@
-// Copyright 2007 The Apache Software Foundation
+// Copyright 2007, 2008 The Apache Software Foundation
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -91,5 +91,19 @@
         {
             assertEquals(stack.pop().intValue(), i);
         }
+    }
+
+    @Test
+    public void clear()
+    {
+        Stack<Integer> stack = newStack();
+
+        for (int i = 0; i < 10; i++) stack.push(i);
+
+        assertEquals(stack.isEmpty(), false);
+
+        stack.clear();
+
+        assertEquals(stack.isEmpty(), true);
     }
 }