This is an automated email from the ASF dual-hosted git repository.

lukaszlenart pushed a commit to branch 
feature/WW-5695-html5-constraint-validation
in repository https://gitbox.apache.org/repos/asf/struts.git

commit febd4c6f24f00d2d670cd01f3b4a9db959aed87c
Author: Lukasz Lenart <[email protected]>
AuthorDate: Tue Aug 25 00:04:24 2026 +0200

    WW-5695 fix(html5): stop constraints.ftl leaking a newline into every input
    
    FreeMarker only strips a line's trailing newline when that line contains
    nothing but FTL tags. The <#if>/<#list>/</#if> block was on one physical
    line together with the interpolated attribute text, so it failed that test
    and the newline was emitted on every html5 input render - including when
    struts.ui.html5.constraints is off, breaking the "changes nothing when off"
    guarantee. Reformatted to the multi-line idiom already used by the sibling
    accesskey block in common-attributes.ftl and by dynamic-attributes.ftl, with
    </#list> and </#if> alone on their own lines.
    
    Added testRendersExactMarkupWhenTheConstantIsOff, an assertEquals on the
    full rendered string (not a contains check), which is the only kind of
    assertion that can catch a stray whitespace byte; the existing suite's
    normalize() strips whitespace entirely and could not have caught this.
    Verified it discriminates: reverting constraints.ftl to the single-line form
    made it fail on the trailing newline, restoring the multi-line form made it
    pass again.
    
    Co-Authored-By: Claude Opus 5 <[email protected]>
---
 core/src/main/resources/template/html5/constraints.ftl             | 6 +++++-
 .../apache/struts2/views/jsp/ui/Html5ConstraintRenderingTest.java  | 7 +++++++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/core/src/main/resources/template/html5/constraints.ftl 
b/core/src/main/resources/template/html5/constraints.ftl
index 7ff272c30..ad86c25b0 100644
--- a/core/src/main/resources/template/html5/constraints.ftl
+++ b/core/src/main/resources/template/html5/constraints.ftl
@@ -18,4 +18,8 @@
  * under the License.
  */
 -->
-<#if attributes.constraints??><#list attributes.constraints as attributeName, 
attributeValue> ${attributeName}="${attributeValue}"<#rt/></#list></#if>
+<#if attributes.constraints??>
+<#list attributes.constraints as attributeName, attributeValue>
+ ${attributeName}="${attributeValue}"<#rt/>
+</#list>
+</#if>
diff --git 
a/core/src/test/java/org/apache/struts2/views/jsp/ui/Html5ConstraintRenderingTest.java
 
b/core/src/test/java/org/apache/struts2/views/jsp/ui/Html5ConstraintRenderingTest.java
index f101f4a8b..d8139363f 100644
--- 
a/core/src/test/java/org/apache/struts2/views/jsp/ui/Html5ConstraintRenderingTest.java
+++ 
b/core/src/test/java/org/apache/struts2/views/jsp/ui/Html5ConstraintRenderingTest.java
@@ -39,6 +39,13 @@ public class Html5ConstraintRenderingTest extends 
AbstractUITagTest {
         assertFalse("expected no minlength in: " + output, 
output.contains("minlength="));
     }
 
+    public void testRendersExactMarkupWhenTheConstantIsOff() throws Exception {
+        String output = render("false");
+
+        assertEquals("<form id=\"constraintAction\" name=\"constraintAction\" 
action=\"/constraintAction.action\" method=\"post\">"
+            + "<input type=\"text\" name=\"username\" value=\"\" 
id=\"constraintAction_username\"/></form>", output);
+    }
+
     public void testRequiredLabelDoesNotBecomeARequiredAttribute() throws 
Exception {
         String output = render("true", "username", "true");
 

Reply via email to