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");
