You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by lu...@apache.org on 2025/11/23 17:50:36 UTC
(struts) branch feature/WW-5444-html5 created (now fbb675ced)
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a change to branch feature/WW-5444-html5
in repository https://gitbox.apache.org/repos/asf/struts.git
at fbb675ced docs: update CLAUDE.md and remove jakarta-migration-helper agent
This branch includes the following new commits:
new 461c06d0c WW-5444 Defines new html5 theme
new f4110d1d6 feat(themes): move html5 theme from showcase to core
new 065a962ee docs: add implementation plan for html5 theme migration
new a5e6374b4 test(html5-theme): add comprehensive unit tests and fix template variables
new fbb675ced docs: update CLAUDE.md and remove jakarta-migration-helper agent
The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(struts) 02/05: feat(themes): move html5 theme from showcase to core
Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch feature/WW-5444-html5
in repository https://gitbox.apache.org/repos/asf/struts.git
commit f4110d1d693911ddae88ca6a26c23e7d3f2c0dc6
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Sun Nov 23 18:12:24 2025 +0100
feat(themes): move html5 theme from showcase to core
- Move 42 FreeMarker templates to core/src/main/resources/template/html5/
- Remove duplicate templates from showcase
- Makes html5 theme available to all applications via struts2-core.jar
- Enables unit testing in core module
- Fix Html5Action import from XWork2 to Struts2 package
- Add Apache license header to Html5Action
Resolves WW-5444
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <no...@anthropic.com>
---
.../struts2/showcase/action/Html5Action.java | 22 ++++++++++++++++++++--
.../src/main/resources/template/html5/a-close.ftl | 0
.../src/main/resources/template/html5/a.ftl | 0
.../main/resources/template/html5/actionerror.ftl | 0
.../resources/template/html5/actionmessage.ftl | 0
.../src/main/resources/template/html5/checkbox.ftl | 0
.../main/resources/template/html5/checkboxlist.ftl | 0
.../src/main/resources/template/html5/combobox.ftl | 0
.../resources/template/html5/common-attributes.ftl | 0
.../resources/template/html5/controlfooter.ftl | 0
.../resources/template/html5/controlheader.ftl | 0
.../src/main/resources/template/html5/css.ftl | 0
.../resources/template/html5/datetextfield.ftl | 0
.../src/main/resources/template/html5/debug.ftl | 0
.../main/resources/template/html5/doubleselect.ftl | 0
.../template/html5/dynamic-attributes.ftl | 0
.../src/main/resources/template/html5/empty.ftl | 0
.../main/resources/template/html5/fielderror.ftl | 0
.../src/main/resources/template/html5/file.ftl | 0
.../main/resources/template/html5/form-close.ftl | 0
.../src/main/resources/template/html5/form.ftl | 0
.../src/main/resources/template/html5/head.ftl | 0
.../src/main/resources/template/html5/hidden.ftl | 0
.../template/html5/inputtransferselect.ftl | 0
.../src/main/resources/template/html5/label.ftl | 0
.../src/main/resources/template/html5/link.ftl | 0
.../src/main/resources/template/html5/nonce.ftl | 0
.../src/main/resources/template/html5/optgroup.ftl | 0
.../template/html5/optiontransferselect.ftl | 0
.../src/main/resources/template/html5/password.ftl | 0
.../template/html5/prefixed-dynamic-attributes.ftl | 0
.../src/main/resources/template/html5/radiomap.ftl | 0
.../src/main/resources/template/html5/reset.ftl | 0
.../main/resources/template/html5/script-close.ftl | 0
.../src/main/resources/template/html5/script.ftl | 0
.../resources/template/html5/scripting-events.ftl | 0
.../src/main/resources/template/html5/select.ftl | 0
.../main/resources/template/html5/submit-close.ftl | 0
.../src/main/resources/template/html5/submit.ftl | 0
.../src/main/resources/template/html5/text.ftl | 0
.../src/main/resources/template/html5/textarea.ftl | 0
.../src/main/resources/template/html5/token.ftl | 0
.../main/resources/template/html5/updownselect.ftl | 0
43 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/Html5Action.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/Html5Action.java
index b80c73d75..a4e6b2d7d 100644
--- a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/Html5Action.java
+++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/Html5Action.java
@@ -1,6 +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.
+ */
package org.apache.struts2.showcase.action;
-import com.opensymphony.xwork2.ActionSupport;
+import org.apache.struts2.ActionSupport;
public class Html5Action extends ActionSupport {
@@ -8,7 +26,7 @@ public class Html5Action extends ActionSupport {
public String execute() throws Exception {
addActionError("Action error: only html5");
addActionMessage("Action message: only html5");
- addFieldError("testField","Field error: only html5");
+ addFieldError("testField", "Field error: only html5");
return super.execute();
}
}
diff --git a/apps/showcase/src/main/resources/template/html5/a-close.ftl b/core/src/main/resources/template/html5/a-close.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/a-close.ftl
rename to core/src/main/resources/template/html5/a-close.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/a.ftl b/core/src/main/resources/template/html5/a.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/a.ftl
rename to core/src/main/resources/template/html5/a.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/actionerror.ftl b/core/src/main/resources/template/html5/actionerror.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/actionerror.ftl
rename to core/src/main/resources/template/html5/actionerror.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/actionmessage.ftl b/core/src/main/resources/template/html5/actionmessage.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/actionmessage.ftl
rename to core/src/main/resources/template/html5/actionmessage.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/checkbox.ftl b/core/src/main/resources/template/html5/checkbox.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/checkbox.ftl
rename to core/src/main/resources/template/html5/checkbox.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/checkboxlist.ftl b/core/src/main/resources/template/html5/checkboxlist.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/checkboxlist.ftl
rename to core/src/main/resources/template/html5/checkboxlist.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/combobox.ftl b/core/src/main/resources/template/html5/combobox.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/combobox.ftl
rename to core/src/main/resources/template/html5/combobox.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/common-attributes.ftl b/core/src/main/resources/template/html5/common-attributes.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/common-attributes.ftl
rename to core/src/main/resources/template/html5/common-attributes.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/controlfooter.ftl b/core/src/main/resources/template/html5/controlfooter.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/controlfooter.ftl
rename to core/src/main/resources/template/html5/controlfooter.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/controlheader.ftl b/core/src/main/resources/template/html5/controlheader.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/controlheader.ftl
rename to core/src/main/resources/template/html5/controlheader.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/css.ftl b/core/src/main/resources/template/html5/css.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/css.ftl
rename to core/src/main/resources/template/html5/css.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/datetextfield.ftl b/core/src/main/resources/template/html5/datetextfield.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/datetextfield.ftl
rename to core/src/main/resources/template/html5/datetextfield.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/debug.ftl b/core/src/main/resources/template/html5/debug.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/debug.ftl
rename to core/src/main/resources/template/html5/debug.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/doubleselect.ftl b/core/src/main/resources/template/html5/doubleselect.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/doubleselect.ftl
rename to core/src/main/resources/template/html5/doubleselect.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/dynamic-attributes.ftl b/core/src/main/resources/template/html5/dynamic-attributes.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/dynamic-attributes.ftl
rename to core/src/main/resources/template/html5/dynamic-attributes.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/empty.ftl b/core/src/main/resources/template/html5/empty.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/empty.ftl
rename to core/src/main/resources/template/html5/empty.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/fielderror.ftl b/core/src/main/resources/template/html5/fielderror.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/fielderror.ftl
rename to core/src/main/resources/template/html5/fielderror.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/file.ftl b/core/src/main/resources/template/html5/file.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/file.ftl
rename to core/src/main/resources/template/html5/file.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/form-close.ftl b/core/src/main/resources/template/html5/form-close.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/form-close.ftl
rename to core/src/main/resources/template/html5/form-close.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/form.ftl b/core/src/main/resources/template/html5/form.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/form.ftl
rename to core/src/main/resources/template/html5/form.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/head.ftl b/core/src/main/resources/template/html5/head.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/head.ftl
rename to core/src/main/resources/template/html5/head.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/hidden.ftl b/core/src/main/resources/template/html5/hidden.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/hidden.ftl
rename to core/src/main/resources/template/html5/hidden.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/inputtransferselect.ftl b/core/src/main/resources/template/html5/inputtransferselect.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/inputtransferselect.ftl
rename to core/src/main/resources/template/html5/inputtransferselect.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/label.ftl b/core/src/main/resources/template/html5/label.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/label.ftl
rename to core/src/main/resources/template/html5/label.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/link.ftl b/core/src/main/resources/template/html5/link.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/link.ftl
rename to core/src/main/resources/template/html5/link.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/nonce.ftl b/core/src/main/resources/template/html5/nonce.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/nonce.ftl
rename to core/src/main/resources/template/html5/nonce.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/optgroup.ftl b/core/src/main/resources/template/html5/optgroup.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/optgroup.ftl
rename to core/src/main/resources/template/html5/optgroup.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/optiontransferselect.ftl b/core/src/main/resources/template/html5/optiontransferselect.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/optiontransferselect.ftl
rename to core/src/main/resources/template/html5/optiontransferselect.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/password.ftl b/core/src/main/resources/template/html5/password.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/password.ftl
rename to core/src/main/resources/template/html5/password.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/prefixed-dynamic-attributes.ftl b/core/src/main/resources/template/html5/prefixed-dynamic-attributes.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/prefixed-dynamic-attributes.ftl
rename to core/src/main/resources/template/html5/prefixed-dynamic-attributes.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/radiomap.ftl b/core/src/main/resources/template/html5/radiomap.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/radiomap.ftl
rename to core/src/main/resources/template/html5/radiomap.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/reset.ftl b/core/src/main/resources/template/html5/reset.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/reset.ftl
rename to core/src/main/resources/template/html5/reset.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/script-close.ftl b/core/src/main/resources/template/html5/script-close.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/script-close.ftl
rename to core/src/main/resources/template/html5/script-close.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/script.ftl b/core/src/main/resources/template/html5/script.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/script.ftl
rename to core/src/main/resources/template/html5/script.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/scripting-events.ftl b/core/src/main/resources/template/html5/scripting-events.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/scripting-events.ftl
rename to core/src/main/resources/template/html5/scripting-events.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/select.ftl b/core/src/main/resources/template/html5/select.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/select.ftl
rename to core/src/main/resources/template/html5/select.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/submit-close.ftl b/core/src/main/resources/template/html5/submit-close.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/submit-close.ftl
rename to core/src/main/resources/template/html5/submit-close.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/submit.ftl b/core/src/main/resources/template/html5/submit.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/submit.ftl
rename to core/src/main/resources/template/html5/submit.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/text.ftl b/core/src/main/resources/template/html5/text.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/text.ftl
rename to core/src/main/resources/template/html5/text.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/textarea.ftl b/core/src/main/resources/template/html5/textarea.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/textarea.ftl
rename to core/src/main/resources/template/html5/textarea.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/token.ftl b/core/src/main/resources/template/html5/token.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/token.ftl
rename to core/src/main/resources/template/html5/token.ftl
diff --git a/apps/showcase/src/main/resources/template/html5/updownselect.ftl b/core/src/main/resources/template/html5/updownselect.ftl
similarity index 100%
rename from apps/showcase/src/main/resources/template/html5/updownselect.ftl
rename to core/src/main/resources/template/html5/updownselect.ftl
(struts) 04/05: test(html5-theme): add comprehensive unit tests and fix template variables
Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch feature/WW-5444-html5
in repository https://gitbox.apache.org/repos/asf/struts.git
commit a5e6374b48a7f813806963dbd1994e1184c7ea50
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Sun Nov 23 18:49:47 2025 +0100
test(html5-theme): add comprehensive unit tests and fix template variables
- Add testGenericHtml5() methods to 13 UI tag test classes
- Create theme.properties with parent=simple configuration
- Migrate all 32 HTML5 templates from deprecated 'parameters' to 'attributes' variable
- Exclude DoubleSelect and UpDownSelect (not supported in HTML5 theme)
- All 26 HTML5 theme tests passing (100% success rate)
Components tested: Textfield, Textarea, Password, Checkbox, CheckboxList,
Radio, Select, File, Hidden, Label, ComboBox, Reset, Submit
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <no...@anthropic.com>
---
core/src/main/resources/template/html5/a-close.ftl | 38 +-
.../main/resources/template/html5/actionerror.ftl | 14 +-
.../resources/template/html5/actionmessage.ftl | 16 +-
.../src/main/resources/template/html5/checkbox.ftl | 36 +-
.../main/resources/template/html5/checkboxlist.ftl | 82 ++--
.../src/main/resources/template/html5/combobox.ftl | 60 +--
.../resources/template/html5/common-attributes.ftl | 4 +-
core/src/main/resources/template/html5/css.ftl | 22 +-
core/src/main/resources/template/html5/debug.ftl | 6 +-
.../template/html5/dynamic-attributes.ftl | 6 +-
.../main/resources/template/html5/fielderror.ftl | 24 +-
core/src/main/resources/template/html5/file.ftl | 36 +-
.../main/resources/template/html5/form-close.ftl | 2 +-
core/src/main/resources/template/html5/form.ftl | 62 +--
core/src/main/resources/template/html5/head.ftl | 2 +-
core/src/main/resources/template/html5/hidden.ftl | 26 +-
core/src/main/resources/template/html5/label.ftl | 26 +-
core/src/main/resources/template/html5/link.ftl | 60 +--
core/src/main/resources/template/html5/nonce.ftl | 4 +-
.../src/main/resources/template/html5/optgroup.ftl | 32 +-
.../src/main/resources/template/html5/password.ftl | 42 +-
.../template/html5/prefixed-dynamic-attributes.ftl | 6 +-
.../src/main/resources/template/html5/radiomap.ftl | 68 +--
core/src/main/resources/template/html5/reset.ftl | 78 ++--
core/src/main/resources/template/html5/script.ftl | 36 +-
.../resources/template/html5/scripting-events.ftl | 56 +--
core/src/main/resources/template/html5/select.ftl | 106 ++---
.../main/resources/template/html5/submit-close.ftl | 8 +-
core/src/main/resources/template/html5/submit.ftl | 86 ++--
core/src/main/resources/template/html5/text.ftl | 44 +-
.../src/main/resources/template/html5/textarea.ftl | 54 +--
.../main/resources/template/html5/theme.properties | 3 +
core/src/main/resources/template/html5/token.ftl | 4 +-
.../struts2/views/jsp/ui/CheckboxListTest.java | 13 +
.../apache/struts2/views/jsp/ui/CheckboxTest.java | 11 +
.../apache/struts2/views/jsp/ui/ComboBoxTest.java | 13 +
.../org/apache/struts2/views/jsp/ui/FileTest.java | 11 +
.../apache/struts2/views/jsp/ui/HiddenTest.java | 11 +
.../org/apache/struts2/views/jsp/ui/LabelTest.java | 11 +
.../apache/struts2/views/jsp/ui/PasswordTest.java | 11 +
.../org/apache/struts2/views/jsp/ui/RadioTest.java | 13 +
.../org/apache/struts2/views/jsp/ui/ResetTest.java | 11 +
.../apache/struts2/views/jsp/ui/SelectTest.java | 13 +
.../apache/struts2/views/jsp/ui/SubmitTest.java | 11 +
.../apache/struts2/views/jsp/ui/TextareaTest.java | 11 +
.../apache/struts2/views/jsp/ui/TextfieldTest.java | 11 +
.../2025-11-23-WW-5444-html5-theme-testing.md | 518 +++++++++++++++++++++
47 files changed, 1245 insertions(+), 573 deletions(-)
diff --git a/core/src/main/resources/template/html5/a-close.ftl b/core/src/main/resources/template/html5/a-close.ftl
index 15465dec8..f2d2d9333 100644
--- a/core/src/main/resources/template/html5/a-close.ftl
+++ b/core/src/main/resources/template/html5/a-close.ftl
@@ -18,33 +18,33 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<@compress single_line=true>
<a
-<#if parameters.id??>
- id="${parameters.id}"
+<#if attributes.id??>
+ id="${attributes.id}"
</#if>
-<#if parameters.href??>
- href="${parameters.href?no_esc}"
+<#if attributes.href??>
+ href="${attributes.href?no_esc}"
</#if>
-<#if parameters.disabled!false>
+<#if attributes.disabled!false>
disabled="disabled"
</#if>
-<#if parameters.tabindex??>
- tabindex="${parameters.tabindex}"
+<#if attributes.tabindex??>
+ tabindex="${attributes.tabindex}"
</#if>
-<#if parameters.cssClass??>
- class="${parameters.cssClass}"
+<#if attributes.cssClass??>
+ class="${attributes.cssClass}"
</#if>
-<#if parameters.cssStyle??>
- style="${parameters.cssStyle}"
+<#if attributes.cssStyle??>
+ style="${attributes.cssStyle}"
</#if>
-<#if parameters.title??>
- title="${parameters.title}"
+<#if attributes.title??>
+ title="${attributes.title}"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
->${tag.escapeHtmlBody()?then(parameters.body, parameters.body?no_esc)}</a>
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
+>${tag.escapeHtmlBody()?then(attributes.body, attributes.body?no_esc)}</a>
</...@compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/actionerror.ftl b/core/src/main/resources/template/html5/actionerror.ftl
index e6586adef..0e195e8d5 100644
--- a/core/src/main/resources/template/html5/actionerror.ftl
+++ b/core/src/main/resources/template/html5/actionerror.ftl
@@ -22,21 +22,21 @@
<#if (actionErrors?? && actionErrors?size > 0)>
<@compress single_line=true>
<ul
- <#if parameters.id??>
- id="${parameters.id}"
+ <#if attributes.id??>
+ id="${attributes.id}"
</#if>
- <#if parameters.cssClass??>
- class="${parameters.cssClass}"
+ <#if attributes.cssClass??>
+ class="${attributes.cssClass}"
<#else>
class="errorMessage"
</#if>
- <#if parameters.cssStyle??>
- style="${parameters.cssStyle}"
+ <#if attributes.cssStyle??>
+ style="${attributes.cssStyle}"
</#if>
>
<#list actionErrors as error>
<#if error??><#t/>
- <li><span><#if parameters.escape>${error!}<#else>${error!?no_esc}</#if></span></li>
+ <li><span><#if attributes.escape>${error!}<#else>${error!?no_esc}</#if></span></li>
</#if>
</#list>
</ul>
diff --git a/core/src/main/resources/template/html5/actionmessage.ftl b/core/src/main/resources/template/html5/actionmessage.ftl
index 606c460e3..1e7950be0 100644
--- a/core/src/main/resources/template/html5/actionmessage.ftl
+++ b/core/src/main/resources/template/html5/actionmessage.ftl
@@ -19,24 +19,24 @@
* under the License.
*/
-->
-<#if (actionMessages?? && actionMessages?size > 0 && !parameters.isEmptyList)>
+<#if (actionMessages?? && actionMessages?size > 0 && !attributes.isEmptyList)>
<@compress single_line=true>
<ul
- <#if parameters.id??>
- id="${parameters.id}"
+ <#if attributes.id??>
+ id="${attributes.id}"
</#if>
- <#if parameters.cssClass??>
- class="${parameters.cssClass}"
+ <#if attributes.cssClass??>
+ class="${attributes.cssClass}"
<#else>
class="actionMessage"
</#if>
- <#if parameters.cssStyle??>
- style="${parameters.cssStyle}"
+ <#if attributes.cssStyle??>
+ style="${attributes.cssStyle}"
</#if>
>
<#list actionMessages as message>
<#if message??><#t/>
- <li><span><#if parameters.escape>${message!}<#else>${message!?no_esc}</#if></span></li>
+ <li><span><#if attributes.escape>${message!}<#else>${message!?no_esc}</#if></span></li>
</#if>
</#list>
</ul>
diff --git a/core/src/main/resources/template/html5/checkbox.ftl b/core/src/main/resources/template/html5/checkbox.ftl
index 134f5d280..10f5300dd 100644
--- a/core/src/main/resources/template/html5/checkbox.ftl
+++ b/core/src/main/resources/template/html5/checkbox.ftl
@@ -18,35 +18,35 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
-<input type="checkbox" name="${parameters.name}" value="${parameters.fieldValue}"
-<#if parameters.nameValue?? && parameters.nameValue>
+<input type="checkbox" name="${attributes.name}" value="${attributes.fieldValue}"
+<#if attributes.nameValue?? && attributes.nameValue>
checked="checked"
</#if>
-<#if parameters.disabled!false>
+<#if attributes.disabled!false>
disabled="disabled"
</#if>
-<#if parameters.tabindex?has_content>
- tabindex="${parameters.tabindex}"
+<#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
</#if>
-<#if parameters.id?has_content>
- id="${parameters.id}"
+<#if attributes.id?has_content>
+ id="${attributes.id}"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
-<#if parameters.title?has_content>
- title="${parameters.title}"
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl" />
+<#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
/>
-<#if parameters.submitUnchecked!false>
-<input type="hidden" id="__checkbox_${parameters.id}" name="__checkbox_${parameters.name}" value="${parameters.fieldValue}"
-<#if parameters.disabled!false>
+<#if attributes.submitUnchecked!false>
+<input type="hidden" id="__checkbox_${attributes.id}" name="__checkbox_${attributes.name}" value="${attributes.fieldValue}"
+<#if attributes.disabled!false>
disabled="disabled"
</#if>
/>
</#if>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/checkboxlist.ftl b/core/src/main/resources/template/html5/checkboxlist.ftl
index 17745976c..a55732a82 100644
--- a/core/src/main/resources/template/html5/checkboxlist.ftl
+++ b/core/src/main/resources/template/html5/checkboxlist.ftl
@@ -18,103 +18,103 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
<#assign itemCount = 0/>
-<#if parameters.list??>
-<@s.iterator value="parameters.list">
+<#if attributes.list??>
+<@s.iterator value="attributes.list">
<#assign itemCount = itemCount + 1/>
- <#if parameters.listKey??>
- <#assign itemKey = stack.findValue(parameters.listKey)/>
- <#assign itemKeyStr = stack.findString(parameters.listKey)/>
+ <#if attributes.listKey??>
+ <#assign itemKey = stack.findValue(attributes.listKey)/>
+ <#assign itemKeyStr = stack.findString(attributes.listKey)/>
<#else>
<#assign itemKey = stack.findValue('top')/>
<#assign itemKeyStr = stack.findString('top')>
</#if>
- <#if parameters.listLabelKey??>
+ <#if attributes.listLabelKey??>
<#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale
file for it's localized value. This is then used as a label -->
- <#assign itemValue = struts.getText(stack.findString(parameters.listLabelKey))/>
- <#elseif parameters.listValue??>
- <#assign itemValue = stack.findString(parameters.listValue)!""/>
+ <#assign itemValue = struts.getText(stack.findString(attributes.listLabelKey))/>
+ <#elseif attributes.listValue??>
+ <#assign itemValue = stack.findString(attributes.listValue)!""/>
<#else>
<#assign itemValue = stack.findString('top')/>
</#if>
- <#if parameters.listCssClass??>
- <#if stack.findString(parameters.listCssClass)??>
- <#assign itemCssClass= stack.findString(parameters.listCssClass)/>
+ <#if attributes.listCssClass??>
+ <#if stack.findString(attributes.listCssClass)??>
+ <#assign itemCssClass= stack.findString(attributes.listCssClass)/>
<#else>
<#assign itemCssClass = ''/>
</#if>
</#if>
- <#if parameters.listCssStyle??>
- <#if stack.findString(parameters.listCssStyle)??>
- <#assign itemCssStyle= stack.findString(parameters.listCssStyle)/>
+ <#if attributes.listCssStyle??>
+ <#if stack.findString(attributes.listCssStyle)??>
+ <#assign itemCssStyle= stack.findString(attributes.listCssStyle)/>
<#else>
<#assign itemCssStyle = ''/>
</#if>
</#if>
- <#if parameters.listTitle??>
- <#if stack.findString(parameters.listTitle)??>
- <#assign itemTitle= stack.findString(parameters.listTitle)/>
+ <#if attributes.listTitle??>
+ <#if stack.findString(attributes.listTitle)??>
+ <#assign itemTitle= stack.findString(attributes.listTitle)/>
<#else>
<#assign itemTitle = ''/>
</#if>
</#if>
-<input type="checkbox" name="${parameters.name}" value="${itemKeyStr}"
-<#if parameters.id?has_content>
- id="${parameters.id}-${itemCount}"
+<input type="checkbox" name="${attributes.name}" value="${itemKeyStr}"
+<#if attributes.id?has_content>
+ id="${attributes.id}-${itemCount}"
<#else>
- id="${parameters.name}-${itemCount}"
+ id="${attributes.name}-${itemCount}"
</#if>
-<#if tag.contains(parameters.nameValue, itemKey)>
+<#if tag.contains(attributes.nameValue, itemKey)>
checked="checked"
</#if>
-<#if parameters.disabled!false>
+<#if attributes.disabled!false>
disabled="disabled"
</#if>
<#if itemCssClass??>
class="${itemCssClass}"
<#else>
-<#if parameters.cssClass?has_content>
- class="${parameters.cssClass}"
+<#if attributes.cssClass?has_content>
+ class="${attributes.cssClass}"
</#if>
</#if>
<#if itemCssStyle??>
style="${itemCssStyle}"
<#else>
-<#if parameters.cssStyle?has_content>
- style="${parameters.cssStyle}"
+<#if attributes.cssStyle?has_content>
+ style="${attributes.cssStyle}"
</#if>
</#if>
<#if itemTitle??>
title="${itemTitle}"
<#else>
-<#if parameters.title?has_content>
- title="${parameters.title}"
+<#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
<#global evaluate_dynamic_attributes = true/>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
<label
-<#if parameters.id?has_content>
- for="${parameters.id}-${itemCount}"
+<#if attributes.id?has_content>
+ for="${attributes.id}-${itemCount}"
<#else>
- for="${parameters.name}-${itemCount}"
+ for="${attributes.name}-${itemCount}"
</#if>
class="checkboxLabel">${itemValue}</label>
</...@s.iterator>
<#else>
</#if>
-<input type="hidden" id="__multiselect_${parameters.id}" name="__multiselect_${parameters.name}"
+<input type="hidden" id="__multiselect_${attributes.id}" name="__multiselect_${attributes.name}"
value=""
-<#if parameters.disabled!false>
+<#if attributes.disabled!false>
disabled="disabled"
</#if>
/>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/combobox.ftl b/core/src/main/resources/template/html5/combobox.ftl
index 3056e0935..2e950c49c 100644
--- a/core/src/main/resources/template/html5/combobox.ftl
+++ b/core/src/main/resources/template/html5/combobox.ftl
@@ -19,70 +19,70 @@
*/
-->
<@s.script>
- function autoPopulate_${parameters.escapedId}(targetElement) {
- <#if parameters.headerKey?? && parameters.headerValue??>
- if (targetElement.options[targetElement.selectedIndex].value == '${parameters.headerKey?js_string}') {
+ function autoPopulate_${attributes.escapedId}(targetElement) {
+ <#if attributes.headerKey?? && attributes.headerValue??>
+ if (targetElement.options[targetElement.selectedIndex].value == '${attributes.headerKey?js_string}') {
return;
}
</#if>
- <#if parameters.emptyOption!false>
+ <#if attributes.emptyOption!false>
if (targetElement.options[targetElement.selectedIndex].value == '') {
return;
}
</#if>
- targetElement.form.elements['${parameters.name?js_string}'].value=targetElement.options[targetElement.selectedIndex].value;
+ targetElement.form.elements['${attributes.name?js_string}'].value=targetElement.options[targetElement.selectedIndex].value;
}
</...@s.script>
-<#include "/${parameters.templateDir}/html5/text.ftl" />
+<#include "/${attributes.templateDir}/html5/text.ftl" />
<#compress>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
- <#if parameters.list??>
- <select onChange="autoPopulate_${parameters.escapedId}(this);"
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
- <#if parameters.disabled!false>
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
+ <#if attributes.list??>
+ <select onChange="autoPopulate_${attributes.escapedId}(this);"
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl" />
+ <#if attributes.disabled!false>
disabled="disabled"
</#if>
>
- <#if (parameters.headerKey?? && parameters.headerValue??)>
- <option value="${parameters.headerKey}">${parameters.headerValue}</option>
+ <#if (attributes.headerKey?? && attributes.headerValue??)>
+ <option value="${attributes.headerKey}">${attributes.headerValue}</option>
</#if>
- <#if parameters.emptyOption!false>
+ <#if attributes.emptyOption!false>
<option value=""></option>
</#if>
- <@s.iterator value="parameters.list">
- <#if parameters.listKey??>
- <#assign tmpListKey = stack.findString(parameters.listKey) />
+ <@s.iterator value="attributes.list">
+ <#if attributes.listKey??>
+ <#assign tmpListKey = stack.findString(attributes.listKey) />
<#else>
<#assign tmpListKey = stack.findString('top') />
</#if>
- <#if parameters.listValue??>
- <#assign tmpListValue = stack.findString(parameters.listValue) />
+ <#if attributes.listValue??>
+ <#assign tmpListValue = stack.findString(attributes.listValue) />
<#else>
<#assign tmpListValue = stack.findString('top') />
</#if>
- <#if parameters.listCssClass??>
- <#if stack.findString(parameters.listCssClass)??>
- <#assign itemCssClass= stack.findString(parameters.listCssClass)/>
+ <#if attributes.listCssClass??>
+ <#if stack.findString(attributes.listCssClass)??>
+ <#assign itemCssClass= stack.findString(attributes.listCssClass)/>
<#else>
<#assign itemCssClass = ''/>
</#if>
</#if>
- <#if parameters.listCssStyle??>
- <#if stack.findString(parameters.listCssStyle)??>
- <#assign itemCssStyle= stack.findString(parameters.listCssStyle)/>
+ <#if attributes.listCssStyle??>
+ <#if stack.findString(attributes.listCssStyle)??>
+ <#assign itemCssStyle= stack.findString(attributes.listCssStyle)/>
<#else>
<#assign itemCssStyle = ''/>
</#if>
</#if>
- <#if parameters.listTitle??>
- <#if stack.findString(parameters.listTitle)??>
- <#assign itemTitle= stack.findString(parameters.listTitle)/>
+ <#if attributes.listTitle??>
+ <#if stack.findString(attributes.listTitle)??>
+ <#assign itemTitle= stack.findString(attributes.listTitle)/>
<#else>
<#assign itemTitle = ''/>
</#if>
</#if>
<option value="${tmpListKey}"
- <#if (parameters.nameValue == tmpListKey)>
+ <#if (attributes.nameValue == tmpListKey)>
selected="selected"
</#if>
<#if itemCssClass??>
@@ -99,4 +99,4 @@
</select>
</#if>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/common-attributes.ftl b/core/src/main/resources/template/html5/common-attributes.ftl
index 0bfe73fc5..bd81fcb15 100644
--- a/core/src/main/resources/template/html5/common-attributes.ftl
+++ b/core/src/main/resources/template/html5/common-attributes.ftl
@@ -19,7 +19,7 @@
*/
-->
<#compress>
-<#if parameters.accesskey?has_content>
- accesskey="${parameters.accesskey}"
+<#if attributes.accesskey?has_content>
+ accesskey="${attributes.accesskey}"
</#if>
</#compress>
diff --git a/core/src/main/resources/template/html5/css.ftl b/core/src/main/resources/template/html5/css.ftl
index 07220ac9f..00ea4b9fc 100644
--- a/core/src/main/resources/template/html5/css.ftl
+++ b/core/src/main/resources/template/html5/css.ftl
@@ -19,17 +19,17 @@
*/
-->
<#compress>
-<#assign hasFieldErrors = parameters.name?? && fieldErrors?? && fieldErrors.get(parameters.name)??/>
-<#if parameters.cssClass?has_content && !(hasFieldErrors && parameters.cssErrorClass??)>
- class="${parameters.cssClass}"
-<#elseif parameters.cssClass?has_content && (hasFieldErrors && parameters.cssErrorClass??)>
- class="${parameters.cssClass} ${parameters.cssErrorClass}"
-<#elseif !(parameters.cssClass?has_content) && (hasFieldErrors && parameters.cssErrorClass??)>
- class="${parameters.cssErrorClass}"
+<#assign hasFieldErrors = attributes.name?? && fieldErrors?? && fieldErrors.get(attributes.name)??/>
+<#if attributes.cssClass?has_content && !(hasFieldErrors && attributes.cssErrorClass??)>
+ class="${attributes.cssClass}"
+<#elseif attributes.cssClass?has_content && (hasFieldErrors && attributes.cssErrorClass??)>
+ class="${attributes.cssClass} ${attributes.cssErrorClass}"
+<#elseif !(attributes.cssClass?has_content) && (hasFieldErrors && attributes.cssErrorClass??)>
+ class="${attributes.cssErrorClass}"
</#if>
-<#if parameters.cssStyle?has_content && !(hasFieldErrors && (parameters.cssErrorStyle?? || parameters.cssErrorClass??))>
- style="${parameters.cssStyle}"
-<#elseif hasFieldErrors && parameters.cssErrorStyle??>
- style="${parameters.cssErrorStyle}"
+<#if attributes.cssStyle?has_content && !(hasFieldErrors && (attributes.cssErrorStyle?? || attributes.cssErrorClass??))>
+ style="${attributes.cssStyle}"
+<#elseif hasFieldErrors && attributes.cssErrorStyle??>
+ style="${attributes.cssErrorStyle}"
</#if>
</#compress>
diff --git a/core/src/main/resources/template/html5/debug.ftl b/core/src/main/resources/template/html5/debug.ftl
index 889702213..fef4f6fa5 100644
--- a/core/src/main/resources/template/html5/debug.ftl
+++ b/core/src/main/resources/template/html5/debug.ftl
@@ -41,7 +41,7 @@
<br>
<a href="#" id="toggle-button">[Debug]</a>
-<div style="display:none" id="<#if parameters.id??>${parameters.id}<#else>debug</#if>">
+<div style="display:none" id="<#if attributes.id??>${attributes.id}<#else>debug</#if>">
<h2>Struts ValueStack Debug</h2>
<br>
@@ -50,7 +50,7 @@
<tr><th>Object</th><th>Property Name</th><th>Property Value</th><th>Property Class</th></tr>
<#assign index=1>
- <#list parameters.stackValues as stackObject>
+ <#list attributes.stackValues as stackObject>
<tr>
<td rowspan="${stackObject.value.size()}">${stackObject.key}</td>
@@ -86,7 +86,7 @@
</div>
<@s.script>
document.getElementById('toggle-button').onclick = function() {
- toggleDebug('<#if parameters.id??>${parameters.id}<#else>debug</#if>');
+ toggleDebug('<#if attributes.id??>${attributes.id}<#else>debug</#if>');
return false;
}
</...@s.script>
diff --git a/core/src/main/resources/template/html5/dynamic-attributes.ftl b/core/src/main/resources/template/html5/dynamic-attributes.ftl
index 246ec466f..64ea3dfa6 100644
--- a/core/src/main/resources/template/html5/dynamic-attributes.ftl
+++ b/core/src/main/resources/template/html5/dynamic-attributes.ftl
@@ -26,10 +26,10 @@
<#return true>
</#if>
</#function>
-<#if (parameters.dynamicAttributes?? && parameters.dynamicAttributes?size > 0)>
-<#assign aKeys = parameters.dynamicAttributes.keySet()>
+<#if (attributes.dynamicAttributes?? && attributes.dynamicAttributes?size > 0)>
+<#assign aKeys = attributes.dynamicAttributes.keySet()>
<#list aKeys?filter(acceptKey) as aKey>
-<#assign keyValue = parameters.dynamicAttributes.get(aKey)/>
+<#assign keyValue = attributes.dynamicAttributes.get(aKey)/>
<#if keyValue?is_string>
<#if evaluate_dynamic_attributes!false == true>
<#assign value = struts.translateVariables(keyValue)!keyValue/>
diff --git a/core/src/main/resources/template/html5/fielderror.ftl b/core/src/main/resources/template/html5/fielderror.ftl
index 4381fdcd5..ef16199ff 100644
--- a/core/src/main/resources/template/html5/fielderror.ftl
+++ b/core/src/main/resources/template/html5/fielderror.ftl
@@ -33,22 +33,22 @@
<#assign eValue = fieldErrors.get(fieldErrorFieldName)>
<#if (haveMatchedErrorField && (!doneStartUlTag))>
<ul
- <#if parameters.id?has_content>
- id="${parameters.id}"
+ <#if attributes.id?has_content>
+ id="${attributes.id}"
</#if>
- <#if parameters.cssClass?has_content>
- class="${parameters.cssClass}"
+ <#if attributes.cssClass?has_content>
+ class="${attributes.cssClass}"
<#else>
class="errorMessage"
</#if>
- <#if parameters.cssStyle?has_content>
- style="${parameters.cssStyle}"
+ <#if attributes.cssStyle?has_content>
+ style="${attributes.cssStyle}"
</#if>
>
<#assign doneStartUlTag=true>
</#if>
<#list eValue as eEachValue>
- <li><span><#if parameters.escape>${eEachValue!}<#else>${eEachValue!?no_esc}</#if></span>
+ <li><span><#if attributes.escape>${eEachValue!}<#else>${eEachValue!?no_esc}</#if></span>
</li>
</#list>
</#if>
@@ -61,19 +61,19 @@
<#else>
<#if (eKeysSize > 0)>
<ul
- <#if parameters.cssClass?has_content>
- class="${parameters.cssClass}"
+ <#if attributes.cssClass?has_content>
+ class="${attributes.cssClass}"
<#else>
class="errorMessage"
</#if>
- <#if parameters.cssStyle?has_content>
- style="${parameters.cssStyle}"
+ <#if attributes.cssStyle?has_content>
+ style="${attributes.cssStyle}"
</#if>
>
<#list eKeys as eKey>
<#assign eValue = fieldErrors.get(eKey)>
<#list eValue as eEachValue>
- <li><span><#if parameters.escape>${eEachValue!}<#else>${eEachValue!?no_esc}</#if></span>
+ <li><span><#if attributes.escape>${eEachValue!}<#else>${eEachValue!?no_esc}</#if></span>
</li>
</#list>
</#list>
diff --git a/core/src/main/resources/template/html5/file.ftl b/core/src/main/resources/template/html5/file.ftl
index 60a486f50..386ae0fa2 100644
--- a/core/src/main/resources/template/html5/file.ftl
+++ b/core/src/main/resources/template/html5/file.ftl
@@ -18,32 +18,32 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
<input type="file"
- name="${(parameters.name!"")}"
-<#if parameters.get("size")?has_content>
- size="${parameters.get("size")}"
+ name="${(attributes.name!"")}"
+<#if attributes.get("size")?has_content>
+ size="${attributes.get("size")}"
</#if>
-<#if parameters.disabled!false>
+<#if attributes.disabled!false>
disabled="disabled"
</#if>
-<#if parameters.accept?has_content>
- accept="${parameters.accept}"
+<#if attributes.accept?has_content>
+ accept="${attributes.accept}"
</#if>
-<#if parameters.tabindex?has_content>
- tabindex="${parameters.tabindex}"
+<#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
</#if>
-<#if parameters.id?has_content>
- id="${parameters.id}"
+<#if attributes.id?has_content>
+ id="${attributes.id}"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
-<#if parameters.title?has_content>
- title="${parameters.title}"
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl" />
+<#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
/>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/form-close.ftl b/core/src/main/resources/template/html5/form-close.ftl
index f3aaa7491..b170ba294 100644
--- a/core/src/main/resources/template/html5/form-close.ftl
+++ b/core/src/main/resources/template/html5/form-close.ftl
@@ -19,4 +19,4 @@
*/
-->
</form>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/form.ftl b/core/src/main/resources/template/html5/form.ftl
index f0eaa4342..b7c74c5d3 100644
--- a/core/src/main/resources/template/html5/form.ftl
+++ b/core/src/main/resources/template/html5/form.ftl
@@ -18,55 +18,55 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
-<#if (parameters.validate!false == false)>
- <#if parameters.onsubmit?has_content>
- ${tag.addParameter('onsubmit', "${parameters.onsubmit}") }
+<#if (attributes.validate!false == false)>
+ <#if attributes.onsubmit?has_content>
+ ${tag.addParameter('onsubmit', "${attributes.onsubmit}") }
</#if>
</#if>
<form
-<#if parameters.id?has_content>
- id="${parameters.id}"
+<#if attributes.id?has_content>
+ id="${attributes.id}"
</#if>
-<#if parameters.name?has_content>
- name="${parameters.name}"
+<#if attributes.name?has_content>
+ name="${attributes.name}"
</#if>
-<#if parameters.onsubmit?has_content>
- onsubmit="<#outputformat 'JavaScript'>${parameters.onsubmit}</#outputformat>"
+<#if attributes.onsubmit?has_content>
+ onsubmit="<#outputformat 'JavaScript'>${attributes.onsubmit}</#outputformat>"
</#if>
-<#if parameters.onreset?has_content>
- onreset="<#outputformat 'JavaScript'>${parameters.onreset}</#outputformat>"
+<#if attributes.onreset?has_content>
+ onreset="<#outputformat 'JavaScript'>${attributes.onreset}</#outputformat>"
</#if>
-<#if parameters.action?has_content>
- action="${parameters.action}"
+<#if attributes.action?has_content>
+ action="${attributes.action}"
</#if>
-<#if parameters.target?has_content>
- target="${parameters.target}"
+<#if attributes.target?has_content>
+ target="${attributes.target}"
</#if>
-<#if parameters.method?has_content>
- method="${parameters.method}"
+<#if attributes.method?has_content>
+ method="${attributes.method}"
<#else>
method="post"
</#if>
-<#if parameters.enctype?has_content>
- enctype="${parameters.enctype}"
+<#if attributes.enctype?has_content>
+ enctype="${attributes.enctype}"
</#if>
-<#if parameters.cssClass?has_content>
- class="${parameters.cssClass}"
+<#if attributes.cssClass?has_content>
+ class="${attributes.cssClass}"
</#if>
-<#if parameters.cssStyle?has_content>
- style="${parameters.cssStyle}"
+<#if attributes.cssStyle?has_content>
+ style="${attributes.cssStyle}"
</#if>
-<#if parameters.title?has_content>
- title="${parameters.title}"
+<#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
-<#if parameters.acceptcharset?has_content>
- accept-charset="${parameters.acceptcharset}"
+<#if attributes.acceptcharset?has_content>
+ accept-charset="${attributes.acceptcharset}"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
-<#if parameters.onreset?has_content>
- onreset="${parameters.onreset}"
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
+<#if attributes.onreset?has_content>
+ onreset="${attributes.onreset}"
</#if>
>
</#compress>
diff --git a/core/src/main/resources/template/html5/head.ftl b/core/src/main/resources/template/html5/head.ftl
index 01c5141a9..502d9a30d 100644
--- a/core/src/main/resources/template/html5/head.ftl
+++ b/core/src/main/resources/template/html5/head.ftl
@@ -19,5 +19,5 @@
*/
-->
<@compress single_line=true>
-<@s.script src="${base}${parameters.staticContentPath}/utils.js" />
+<@s.script src="${base}${attributes.staticContentPath}/utils.js" />
</...@compress>
diff --git a/core/src/main/resources/template/html5/hidden.ftl b/core/src/main/resources/template/html5/hidden.ftl
index 7e7184953..afcc6b20b 100644
--- a/core/src/main/resources/template/html5/hidden.ftl
+++ b/core/src/main/resources/template/html5/hidden.ftl
@@ -18,26 +18,26 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
<input type="hidden"
- name="${(parameters.name!"")}"
-<#if parameters.nameValue??>
- value="<@s.property value="parameters.nameValue"/>"
+ name="${(attributes.name!"")}"
+<#if attributes.nameValue??>
+ value="<@s.property value="attributes.nameValue"/>"
</#if>
-<#if parameters.id?has_content>
- id="${parameters.id}"
+<#if attributes.id?has_content>
+ id="${attributes.id}"
</#if>
-<#if parameters.cssClass?has_content>
- class="${parameters.cssClass}"
+<#if attributes.cssClass?has_content>
+ class="${attributes.cssClass}"
</#if>
-<#if parameters.cssStyle?has_content>
- style="${parameters.cssStyle}"
+<#if attributes.cssStyle?has_content>
+ style="${attributes.cssStyle}"
</#if>
-<#if parameters.disabled!false>
+<#if attributes.disabled!false>
disabled="disabled"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
/>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/label.ftl b/core/src/main/resources/template/html5/label.ftl
index 730efb048..7a5641a99 100644
--- a/core/src/main/resources/template/html5/label.ftl
+++ b/core/src/main/resources/template/html5/label.ftl
@@ -18,25 +18,25 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
<label
-<#if parameters.id?has_content>
- id="${parameters.id}"
+<#if attributes.id?has_content>
+ id="${attributes.id}"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
-<#if parameters.title?has_content>
- title="${parameters.title}"
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl" />
+<#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
-<#if parameters.for?has_content>
- for="${parameters.for}"
+<#if attributes.for?has_content>
+ for="${attributes.for}"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
>
-<#if parameters.nameValue??>
-<@s.property value="parameters.nameValue"/>
+<#if attributes.nameValue??>
+<@s.property value="attributes.nameValue"/>
</#if>
</label>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/link.ftl b/core/src/main/resources/template/html5/link.ftl
index 891d23763..9bd742b55 100644
--- a/core/src/main/resources/template/html5/link.ftl
+++ b/core/src/main/resources/template/html5/link.ftl
@@ -18,57 +18,57 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<@compress single_line=true>
<link
- <#if parameters.rel?has_content>
- rel="${parameters.rel}"
+ <#if attributes.rel?has_content>
+ rel="${attributes.rel}"
<#else>
rel="stylesheet"
</#if>
- <#if parameters.type?has_content>
- type="${parameters.type}"
+ <#if attributes.type?has_content>
+ type="${attributes.type}"
<#else>
type="text/css"
</#if>
- <#if parameters.href?has_content>
- href="${parameters.href}"
+ <#if attributes.href?has_content>
+ href="${attributes.href}"
</#if>
- <#if parameters.hreflang?has_content>
- hreflang="${parameters.hreflang}"
+ <#if attributes.hreflang?has_content>
+ hreflang="${attributes.hreflang}"
</#if>
- <#if parameters.disabled?has_content && parameters.disabled == "true">
+ <#if attributes.disabled?has_content && attributes.disabled == "true">
disabled
</#if>
- <#if parameters.media?has_content>
- media="${parameters.media}"
+ <#if attributes.media?has_content>
+ media="${attributes.media}"
<#else>
media="all"
</#if>
- <#if parameters.title?has_content>
- title="${parameters.title}"
+ <#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
- <#if parameters.as?has_content>
- as="${parameters.as}"
+ <#if attributes.as?has_content>
+ as="${attributes.as}"
</#if>
- <#if parameters.referrerpolicy?has_content>
- referrerpolicy="${parameters.referrerpolicy}"
+ <#if attributes.referrerpolicy?has_content>
+ referrerpolicy="${attributes.referrerpolicy}"
</#if>
- <#if parameters.sizes?has_content>
- sizes="${parameters.sizes}"
+ <#if attributes.sizes?has_content>
+ sizes="${attributes.sizes}"
</#if>
- <#if parameters.crossorigin?has_content>
- crossorigin="${parameters.crossorigin}"
+ <#if attributes.crossorigin?has_content>
+ crossorigin="${attributes.crossorigin}"
</#if>
- <#if parameters.integrity?has_content>
- integrity="${parameters.integrity}"
+ <#if attributes.integrity?has_content>
+ integrity="${attributes.integrity}"
</#if>
- <#if parameters.importance?has_content>
- importance="${parameters.importance}"
+ <#if attributes.importance?has_content>
+ importance="${attributes.importance}"
</#if>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/nonce.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/nonce.ftl" />
/>
</...@compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/nonce.ftl b/core/src/main/resources/template/html5/nonce.ftl
index 4e1efe179..8570d9786 100644
--- a/core/src/main/resources/template/html5/nonce.ftl
+++ b/core/src/main/resources/template/html5/nonce.ftl
@@ -19,7 +19,7 @@
*/
-->
<#compress>
-<#if parameters.nonce?has_content>
- nonce="${parameters.nonce}"
+<#if attributes.nonce?has_content>
+ nonce="${attributes.nonce}"
</#if>
</#compress>
diff --git a/core/src/main/resources/template/html5/optgroup.ftl b/core/src/main/resources/template/html5/optgroup.ftl
index 8273a5d00..c1d4681c3 100644
--- a/core/src/main/resources/template/html5/optgroup.ftl
+++ b/core/src/main/resources/template/html5/optgroup.ftl
@@ -18,38 +18,38 @@
* under the License.
*/
-->
-<#if parameters.optGroupInternalListUiBeanList??>
+<#if attributes.optGroupInternalListUiBeanList??>
<#compress>
- <#assign optGroupInternalListUiBeans=parameters.optGroupInternalListUiBeanList />
+ <#assign optGroupInternalListUiBeans=attributes.optGroupInternalListUiBeanList />
<#list optGroupInternalListUiBeans as optGroupInternalListUiBean>
<optgroup<#rt>
- <#if optGroupInternalListUiBean.parameters.label?has_content>
- label="${optGroupInternalListUiBean.parameters.label}"<#rt>
+ <#if optGroupInternalListUiBean.attributes.label?has_content>
+ label="${optGroupInternalListUiBean.attributes.label}"<#rt>
</#if>
- <#if optGroupInternalListUiBean.parameters.disabled!false>
+ <#if optGroupInternalListUiBean.attributes.disabled!false>
disabled="disabled"<#rt>
</#if>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
>
- <#list optGroupInternalListUiBean.parameters.list as optGroupBean>
+ <#list optGroupInternalListUiBean.attributes.list as optGroupBean>
<#assign trash=stack.push(optGroupBean) />
- <#assign tmpKey=stack.findValue(optGroupInternalListUiBean.parameters.listKey) />
- <#assign tmpValue=stack.findValue(optGroupInternalListUiBean.parameters.listValue) />
+ <#assign tmpKey=stack.findValue(optGroupInternalListUiBean.attributes.listKey) />
+ <#assign tmpValue=stack.findValue(optGroupInternalListUiBean.attributes.listValue) />
<#assign tmpKeyStr = tmpKey.toString() />
<#assign optGroupItemCssClass = ''/>
- <#if optGroupInternalListUiBean.parameters.listCssClass??>
- <#assign optGroupItemCssClass= stack.findString(optGroupInternalListUiBean.parameters.listCssClass)!''/>
+ <#if optGroupInternalListUiBean.attributes.listCssClass??>
+ <#assign optGroupItemCssClass= stack.findString(optGroupInternalListUiBean.attributes.listCssClass)!''/>
</#if>
<#assign optGroupItemCssStyle = ''/>
- <#if optGroupInternalListUiBean.parameters.listCssStyle??>
- <#assign optGroupItemCssStyle= stack.findString(optGroupInternalListUiBean.parameters.listCssStyle)!''/>
+ <#if optGroupInternalListUiBean.attributes.listCssStyle??>
+ <#assign optGroupItemCssStyle= stack.findString(optGroupInternalListUiBean.attributes.listCssStyle)!''/>
</#if>
<#assign optGroupItemTitle = ''/>
- <#if optGroupInternalListUiBean.parameters.listTitle??>
- <#assign optGroupItemTitle= stack.findString(optGroupInternalListUiBean.parameters.listTitle)!''/>
+ <#if optGroupInternalListUiBean.attributes.listTitle??>
+ <#assign optGroupItemTitle= stack.findString(optGroupInternalListUiBean.attributes.listTitle)!''/>
</#if>
<option value="${tmpKeyStr}"<#rt>
- <#if tag.contains(parameters.nameValue, tmpKey) == true>
+ <#if tag.contains(attributes.nameValue, tmpKey) == true>
selected="selected"<#rt>
</#if>
<#if optGroupItemCssClass?has_content>
diff --git a/core/src/main/resources/template/html5/password.ftl b/core/src/main/resources/template/html5/password.ftl
index 222aa5947..63d807969 100644
--- a/core/src/main/resources/template/html5/password.ftl
+++ b/core/src/main/resources/template/html5/password.ftl
@@ -18,38 +18,38 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
<input type="password"
- name="${(parameters.name!"")}"
-<#if parameters.get("size")?has_content>
- size="${parameters.get("size")}"
+ name="${(attributes.name!"")}"
+<#if attributes.get("size")?has_content>
+ size="${attributes.get("size")}"
</#if>
-<#if parameters.maxlength?has_content>
- maxlength="${parameters.maxlength}"
+<#if attributes.maxlength?has_content>
+ maxlength="${attributes.maxlength}"
</#if>
-<#if parameters.nameValue?? && parameters.showPassword!false>
- value="<@s.property value="parameters.nameValue"/>"
+<#if attributes.nameValue?? && attributes.showPassword!false>
+ value="<@s.property value="attributes.nameValue"/>"
</#if>
-<#if parameters.disabled!false>
+<#if attributes.disabled!false>
disabled="disabled"
</#if>
-<#if parameters.readonly!false>
+<#if attributes.readonly!false>
readonly="readonly"
</#if>
-<#if parameters.tabindex?has_content>
- tabindex="${parameters.tabindex}"
+<#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
</#if>
-<#if parameters.id?has_content>
- id="${parameters.id}"
+<#if attributes.id?has_content>
+ id="${attributes.id}"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
-<#if parameters.title?has_content>
- title="${parameters.title}"
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl" />
+<#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
/>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/prefixed-dynamic-attributes.ftl b/core/src/main/resources/template/html5/prefixed-dynamic-attributes.ftl
index ad1dd1cd5..0d94cd74e 100644
--- a/core/src/main/resources/template/html5/prefixed-dynamic-attributes.ftl
+++ b/core/src/main/resources/template/html5/prefixed-dynamic-attributes.ftl
@@ -20,11 +20,11 @@
*/
-->
<#macro prefixedDynamicAttributes prefix>
-<#if (parameters.dynamicAttributes?? && parameters.dynamicAttributes?size > 0)>
-<#assign aKeys = parameters.dynamicAttributes.keySet()>
+<#if (attributes.dynamicAttributes?? && attributes.dynamicAttributes?size > 0)>
+<#assign aKeys = attributes.dynamicAttributes.keySet()>
<#list aKeys as aKey>
<#if aKey?starts_with(prefix)>
-<#assign keyValue = parameters.dynamicAttributes.get(aKey)/>
+<#assign keyValue = attributes.dynamicAttributes.get(aKey)/>
<#if keyValue?is_string>
<#assign value = struts.translateVariables(keyValue)!keyValue/>
<#else>
diff --git a/core/src/main/resources/template/html5/radiomap.ftl b/core/src/main/resources/template/html5/radiomap.ftl
index 208f45f1d..13a597f70 100644
--- a/core/src/main/resources/template/html5/radiomap.ftl
+++ b/core/src/main/resources/template/html5/radiomap.ftl
@@ -18,67 +18,67 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
- <@s.iterator value="parameters.list">
- <#if parameters.listKey??>
- <#assign itemKey = stack.findValue(parameters.listKey)/>
- <#assign itemKeyStr = stack.findString(parameters.listKey)/>
+ <@s.iterator value="attributes.list">
+ <#if attributes.listKey??>
+ <#assign itemKey = stack.findValue(attributes.listKey)/>
+ <#assign itemKeyStr = stack.findString(attributes.listKey)/>
<#else>
<#assign itemKey = stack.findValue('top')/>
<#assign itemKeyStr = stack.findString('top')>
</#if>
- <#if parameters.listValueKey??>
+ <#if attributes.listValueKey??>
<#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale
file for it's localized value. This is then used as a label -->
- <#assign valueKey = stack.findString(parameters.listValueKey)!''/>
+ <#assign valueKey = stack.findString(attributes.listValueKey)!''/>
<#if valueKey?has_content>
<#assign itemValue = struts.getText(valueKey) />
<#else>
- <#assign itemValue = parameters.listValueKey />
+ <#assign itemValue = attributes.listValueKey />
</#if>
- <#elseif parameters.listValue??>
- <#assign itemValue = stack.findString(parameters.listValue)/>
+ <#elseif attributes.listValue??>
+ <#assign itemValue = stack.findString(attributes.listValue)/>
<#else>
<#assign itemValue = stack.findString('top')/>
</#if>
- <#if parameters.listCssClass??>
- <#if stack.findString(parameters.listCssClass)??>
- <#assign itemCssClass= stack.findString(parameters.listCssClass)/>
+ <#if attributes.listCssClass??>
+ <#if stack.findString(attributes.listCssClass)??>
+ <#assign itemCssClass= stack.findString(attributes.listCssClass)/>
<#else>
<#assign itemCssClass = ''/>
</#if>
</#if>
- <#if parameters.listCssStyle??>
- <#if stack.findString(parameters.listCssStyle)??>
- <#assign itemCssStyle= stack.findString(parameters.listCssStyle)/>
+ <#if attributes.listCssStyle??>
+ <#if stack.findString(attributes.listCssStyle)??>
+ <#assign itemCssStyle= stack.findString(attributes.listCssStyle)/>
<#else>
<#assign itemCssStyle = ''/>
</#if>
</#if>
- <#if parameters.listTitle??>
- <#if stack.findString(parameters.listTitle)??>
- <#assign itemTitle= stack.findString(parameters.listTitle)/>
+ <#if attributes.listTitle??>
+ <#if stack.findString(attributes.listTitle)??>
+ <#assign itemTitle= stack.findString(attributes.listTitle)/>
<#else>
<#assign itemTitle = ''/>
</#if>
</#if>
<input type="radio"
- <#if parameters.name?has_content>
- name="${parameters.name?no_esc}"
+ <#if attributes.name?has_content>
+ name="${attributes.name?no_esc}"
</#if>
- id="${parameters.id}${itemKeyStr?replace(".", "_")}"
- <#if tag.contains(parameters.nameValue!'', itemKey)>
+ id="${attributes.id}${itemKeyStr?replace(".", "_")}"
+ <#if tag.contains(attributes.nameValue!'', itemKey)>
checked="checked"
</#if>
<#if itemKey??>
value="${itemKeyStr}"
</#if>
- <#if parameters.disabled!false>
+ <#if attributes.disabled!false>
disabled="disabled"
</#if>
- <#if parameters.tabindex?has_content>
- tabindex="${parameters.tabindex}"
+ <#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
</#if>
<#if itemCssClass?has_content>
class="${itemCssClass}"
@@ -89,19 +89,19 @@
<#if itemTitle?has_content>
title="${itemTitle}"
<#else>
- <#if parameters.title?has_content>
- title="${parameters.title}"
+ <#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
</#if>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
<#global evaluate_dynamic_attributes = true/>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
/>
- <label for="${parameters.id}${itemKeyStr?replace(".", "_")}"<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl"/>>
+ <label for="${attributes.id}${itemKeyStr?replace(".", "_")}"<#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl"/>>
${itemValue}
</label>
</...@s.iterator>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/reset.ftl b/core/src/main/resources/template/html5/reset.ftl
index 56dc96aa7..02d36e9e5 100644
--- a/core/src/main/resources/template/html5/reset.ftl
+++ b/core/src/main/resources/template/html5/reset.ftl
@@ -18,67 +18,67 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
- <#if parameters.type?? && parameters.type=="button">
+ <#if attributes.type?? && attributes.type=="button">
<button type="reset"
- <#if parameters.name?has_content>
- name="${parameters.name}"
+ <#if attributes.name?has_content>
+ name="${attributes.name}"
</#if>
- <#if parameters.nameValue??>
- value="<@s.property value="parameters.nameValue"/>"
+ <#if attributes.nameValue??>
+ value="<@s.property value="attributes.nameValue"/>"
</#if>
- <#if parameters.cssClass?has_content>
- class="${parameters.cssClass}"
+ <#if attributes.cssClass?has_content>
+ class="${attributes.cssClass}"
</#if>
- <#if parameters.cssStyle?has_content>
- style="${parameters.cssStyle}"
+ <#if attributes.cssStyle?has_content>
+ style="${attributes.cssStyle}"
</#if>
- <#if parameters.disabled!false>
+ <#if attributes.disabled!false>
disabled="disabled"
</#if>
- <#if parameters.tabindex?has_content>
- tabindex="${parameters.tabindex}"
+ <#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
</#if>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl"/>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
- ><#if parameters.src?has_content>
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl"/>
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
+ ><#if attributes.src?has_content>
<img
- <#if parameters.label?has_content>
- alt="${parameters.label}"
+ <#if attributes.label?has_content>
+ alt="${attributes.label}"
</#if>
- <#if parameters.src?has_content>
- src="${parameters.src}"
+ <#if attributes.src?has_content>
+ src="${attributes.src}"
</#if>
- /><#else><#if parameters.label?has_content><@s.property value="parameters.label"/></#if></#if></button>
+ /><#else><#if attributes.label?has_content><@s.property value="attributes.label"/></#if></#if></button>
<#else>
<input type="reset"
- <#if parameters.name?has_content>
- name="${parameters.name}"
+ <#if attributes.name?has_content>
+ name="${attributes.name}"
</#if>
- <#if parameters.nameValue??>
- value="<@s.property value="parameters.nameValue"/>"
+ <#if attributes.nameValue??>
+ value="<@s.property value="attributes.nameValue"/>"
</#if>
- <#if parameters.cssClass?has_content>
- class="${parameters.cssClass}"
+ <#if attributes.cssClass?has_content>
+ class="${attributes.cssClass}"
</#if>
- <#if parameters.cssStyle?has_content>
- style="${parameters.cssStyle}"
+ <#if attributes.cssStyle?has_content>
+ style="${attributes.cssStyle}"
</#if>
- <#if parameters.title?has_content>
- title="${parameters.title}"
+ <#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
- <#if parameters.disabled!false>
+ <#if attributes.disabled!false>
disabled="disabled"
</#if>
- <#if parameters.tabindex?has_content>
- tabindex="${parameters.tabindex}"
+ <#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
</#if>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
/>
</#if>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/script.ftl b/core/src/main/resources/template/html5/script.ftl
index b37b0b7c2..c5d8b7d35 100644
--- a/core/src/main/resources/template/html5/script.ftl
+++ b/core/src/main/resources/template/html5/script.ftl
@@ -20,34 +20,34 @@
-->
<@compress single_line=true>
<script
- <#if parameters.async?has_content && parameters.async == "true">
+ <#if attributes.async?has_content && attributes.async == "true">
async
</#if>
- <#if parameters.charset?has_content>
- charset="${parameters.charset}"
+ <#if attributes.charset?has_content>
+ charset="${attributes.charset}"
</#if>
- <#if parameters.defer?has_content && parameters.defer=="true">
+ <#if attributes.defer?has_content && attributes.defer=="true">
defer
</#if>
- <#if parameters.type?has_content>
- type="${parameters.type}"
+ <#if attributes.type?has_content>
+ type="${attributes.type}"
</#if>
- <#if parameters.src?has_content>
- src="${parameters.src}"
+ <#if attributes.src?has_content>
+ src="${attributes.src}"
</#if>
- <#if parameters.referrerpolicy?has_content>
- referrerpolicy="${parameters.referrerpolicy}"
+ <#if attributes.referrerpolicy?has_content>
+ referrerpolicy="${attributes.referrerpolicy}"
</#if>
- <#if parameters.nomodule?has_content && parameters.nomodule=="true">
+ <#if attributes.nomodule?has_content && attributes.nomodule=="true">
nomodule
</#if>
- <#if parameters.integrity?has_content>
- integrity="${parameters.integrity}"
+ <#if attributes.integrity?has_content>
+ integrity="${attributes.integrity}"
</#if>
- <#if parameters.crossorigin?has_content>
- crossorigin="${parameters.crossorigin}"
+ <#if attributes.crossorigin?has_content>
+ crossorigin="${attributes.crossorigin}"
</#if>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/nonce.ftl" />>
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/nonce.ftl" />>
</...@compress>
diff --git a/core/src/main/resources/template/html5/scripting-events.ftl b/core/src/main/resources/template/html5/scripting-events.ftl
index 714ae9d56..9dc06bc7c 100644
--- a/core/src/main/resources/template/html5/scripting-events.ftl
+++ b/core/src/main/resources/template/html5/scripting-events.ftl
@@ -19,46 +19,46 @@
*/
-->
<#compress>
-<#if parameters.onclick??>
- onclick="<#outputformat 'JavaScript'>${parameters.onclick}</#outputformat>"
+<#if attributes.onclick??>
+ onclick="<#outputformat 'JavaScript'>${attributes.onclick}</#outputformat>"
</#if>
-<#if parameters.ondblclick??>
- ondblclick="<#outputformat 'JavaScript'>${parameters.ondblclick}</#outputformat>"
+<#if attributes.ondblclick??>
+ ondblclick="<#outputformat 'JavaScript'>${attributes.ondblclick}</#outputformat>"
</#if>
-<#if parameters.onmousedown??>
- onmousedown="<#outputformat 'JavaScript'>${parameters.onmousedown}</#outputformat>"
+<#if attributes.onmousedown??>
+ onmousedown="<#outputformat 'JavaScript'>${attributes.onmousedown}</#outputformat>"
</#if>
-<#if parameters.onmouseup??>
- onmouseup="<#outputformat 'JavaScript'>${parameters.onmouseup}</#outputformat>"
+<#if attributes.onmouseup??>
+ onmouseup="<#outputformat 'JavaScript'>${attributes.onmouseup}</#outputformat>"
</#if>
-<#if parameters.onmouseover??>
- onmouseover="<#outputformat 'JavaScript'>${parameters.onmouseover}</#outputformat>"
+<#if attributes.onmouseover??>
+ onmouseover="<#outputformat 'JavaScript'>${attributes.onmouseover}</#outputformat>"
</#if>
-<#if parameters.onmousemove??>
- onmousemove="<#outputformat 'JavaScript'>${parameters.onmousemove}</#outputformat>"
+<#if attributes.onmousemove??>
+ onmousemove="<#outputformat 'JavaScript'>${attributes.onmousemove}</#outputformat>"
</#if>
-<#if parameters.onmouseout??>
- onmouseout="<#outputformat 'JavaScript'>${parameters.onmouseout}</#outputformat>"
+<#if attributes.onmouseout??>
+ onmouseout="<#outputformat 'JavaScript'>${attributes.onmouseout}</#outputformat>"
</#if>
-<#if parameters.onfocus??>
- onfocus="<#outputformat 'JavaScript'>${parameters.onfocus}</#outputformat>"
+<#if attributes.onfocus??>
+ onfocus="<#outputformat 'JavaScript'>${attributes.onfocus}</#outputformat>"
</#if>
-<#if parameters.onblur??>
- onblur="<#outputformat 'JavaScript'>${parameters.onblur}</#outputformat>"
+<#if attributes.onblur??>
+ onblur="<#outputformat 'JavaScript'>${attributes.onblur}</#outputformat>"
</#if>
-<#if parameters.onkeypress??>
- onkeypress="<#outputformat 'JavaScript'>${parameters.onkeypress}</#outputformat>"
+<#if attributes.onkeypress??>
+ onkeypress="<#outputformat 'JavaScript'>${attributes.onkeypress}</#outputformat>"
</#if>
-<#if parameters.onkeydown??>
- onkeydown="<#outputformat 'JavaScript'>${parameters.onkeydown}</#outputformat>"
+<#if attributes.onkeydown??>
+ onkeydown="<#outputformat 'JavaScript'>${attributes.onkeydown}</#outputformat>"
</#if>
-<#if parameters.onkeyup??>
- onkeyup="<#outputformat 'JavaScript'>${parameters.onkeyup}</#outputformat>"
+<#if attributes.onkeyup??>
+ onkeyup="<#outputformat 'JavaScript'>${attributes.onkeyup}</#outputformat>"
</#if>
-<#if parameters.onselect??>
- onselect="<#outputformat 'JavaScript'>${parameters.onselect}</#outputformat>"
+<#if attributes.onselect??>
+ onselect="<#outputformat 'JavaScript'>${attributes.onselect}</#outputformat>"
</#if>
-<#if parameters.onchange??>
- onchange="<#outputformat 'JavaScript'>${parameters.onchange}</#outputformat>"
+<#if attributes.onchange??>
+ onchange="<#outputformat 'JavaScript'>${attributes.onchange}</#outputformat>"
</#if>
</#compress>
diff --git a/core/src/main/resources/template/html5/select.ftl b/core/src/main/resources/template/html5/select.ftl
index d30b3e1ae..324ce2abf 100644
--- a/core/src/main/resources/template/html5/select.ftl
+++ b/core/src/main/resources/template/html5/select.ftl
@@ -18,49 +18,49 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
<#setting number_format="#.#####">
<select
- name="${(parameters.name!"")}"
- <#if parameters.get("size")?has_content>
- size="${parameters.get("size")}"
+ name="${(attributes.name!"")}"
+ <#if attributes.get("size")?has_content>
+ size="${attributes.get("size")}"
</#if>
- <#if parameters.disabled!false>
+ <#if attributes.disabled!false>
disabled="disabled"
</#if>
- <#if parameters.tabindex?has_content>
- tabindex="${parameters.tabindex}"
+ <#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
</#if>
- <#if parameters.id?has_content>
- id="${parameters.id}"
+ <#if attributes.id?has_content>
+ id="${attributes.id}"
</#if>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
- <#if parameters.title?has_content>
- title="${parameters.title}"
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl" />
+ <#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
- <#if parameters.multiple!false>
+ <#if attributes.multiple!false>
multiple="multiple"
</#if>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
>
- <#if parameters.headerKey?? && parameters.headerValue??>
- <option value="${parameters.headerKey}"
- <#if tag.contains(parameters.nameValue, parameters.headerKey) == true>
+ <#if attributes.headerKey?? && attributes.headerValue??>
+ <option value="${attributes.headerKey}"
+ <#if tag.contains(attributes.nameValue, attributes.headerKey) == true>
selected="selected"
</#if>
- >${parameters.headerValue}</option>
+ >${attributes.headerValue}</option>
</#if>
- <#if parameters.emptyOption!false>
+ <#if attributes.emptyOption!false>
<option value=""></option>
</#if>
- <@s.iterator value="parameters.list">
- <#if parameters.listKey??>
- <#if stack.findValue(parameters.listKey)??>
- <#assign itemKey = stack.findValue(parameters.listKey)/>
- <#assign itemKeyStr = stack.findString(parameters.listKey)/>
+ <@s.iterator value="attributes.list">
+ <#if attributes.listKey??>
+ <#if stack.findValue(attributes.listKey)??>
+ <#assign itemKey = stack.findValue(attributes.listKey)/>
+ <#assign itemKeyStr = stack.findString(attributes.listKey)/>
<#else>
<#assign itemKey = ''/>
<#assign itemKeyStr = ''/>
@@ -69,47 +69,47 @@
<#assign itemKey = stack.findValue('top')/>
<#assign itemKeyStr = stack.findString('top')>
</#if>
- <#if parameters.listValueKey??>
+ <#if attributes.listValueKey??>
<#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale file for it's
localized value. This is then used as a label -->
- <#assign valueKey = stack.findString(parameters.listValueKey)!'' />
+ <#assign valueKey = stack.findString(attributes.listValueKey)!'' />
<#if valueKey?has_content>
<#assign itemValue = struts.getText(valueKey) />
<#else>
- <#assign itemValue = parameters.listValueKey />
+ <#assign itemValue = attributes.listValueKey />
</#if>
- <#elseif parameters.listValue??>
- <#if stack.findString(parameters.listValue)??>
- <#assign itemValue = stack.findString(parameters.listValue)/>
+ <#elseif attributes.listValue??>
+ <#if stack.findString(attributes.listValue)??>
+ <#assign itemValue = stack.findString(attributes.listValue)/>
<#else>
<#assign itemValue = ''/>
</#if>
<#else>
<#assign itemValue = stack.findString('top')/>
</#if>
- <#if parameters.listCssClass??>
- <#if stack.findString(parameters.listCssClass)??>
- <#assign itemCssClass= stack.findString(parameters.listCssClass)/>
+ <#if attributes.listCssClass??>
+ <#if stack.findString(attributes.listCssClass)??>
+ <#assign itemCssClass= stack.findString(attributes.listCssClass)/>
<#else>
<#assign itemCssClass = ''/>
</#if>
</#if>
- <#if parameters.listCssStyle??>
- <#if stack.findString(parameters.listCssStyle)??>
- <#assign itemCssStyle= stack.findString(parameters.listCssStyle)/>
+ <#if attributes.listCssStyle??>
+ <#if stack.findString(attributes.listCssStyle)??>
+ <#assign itemCssStyle= stack.findString(attributes.listCssStyle)/>
<#else>
<#assign itemCssStyle = ''/>
</#if>
</#if>
- <#if parameters.listTitle??>
- <#if stack.findString(parameters.listTitle)??>
- <#assign itemTitle= stack.findString(parameters.listTitle)/>
+ <#if attributes.listTitle??>
+ <#if stack.findString(attributes.listTitle)??>
+ <#assign itemTitle= stack.findString(attributes.listTitle)/>
<#else>
<#assign itemTitle = ''/>
</#if>
</#if>
<option value="${itemKeyStr}"
- <#if tag.contains(parameters.nameValue, itemKey) == true>
+ <#if tag.contains(attributes.nameValue, itemKey) == true>
selected="selected"
</#if>
<#if itemCssClass?has_content>
@@ -123,27 +123,27 @@
</#if>
>${itemValue}</option>
</...@s.iterator>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/optgroup.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/optgroup.ftl" />
</select>
- <#if parameters.multiple!false>
- <#if (parameters.id?? && parameters.name??)>
- <input type="hidden" id="__multiselect_${parameters.id}" name="__multiselect_${parameters.name}" value=""
+ <#if attributes.multiple!false>
+ <#if (attributes.id?? && attributes.name??)>
+ <input type="hidden" id="__multiselect_${attributes.id}" name="__multiselect_${attributes.name}" value=""
</#if>
- <#if (parameters.id?? && !parameters.name??)>
- <input type="hidden" id="__multiselect_${parameters.id}" name="__multiselect_${parameters.id}" value=""
+ <#if (attributes.id?? && !attributes.name??)>
+ <input type="hidden" id="__multiselect_${attributes.id}" name="__multiselect_${attributes.id}" value=""
</#if>
- <#if ( !parameters.id?? && parameters.name??)>
- <input type="hidden" id="__multiselect_${parameters.id}" name="__multiselect_${parameters.id}" value=""
+ <#if ( !attributes.id?? && attributes.name??)>
+ <input type="hidden" id="__multiselect_${attributes.id}" name="__multiselect_${attributes.id}" value=""
</#if>
- <#if ( !parameters.id?? && !parameters.name??)>
+ <#if ( !attributes.id?? && !attributes.name??)>
<input type="hidden" id="" name="" value=""
</#if>
- <#if parameters.disabled!false>
+ <#if attributes.disabled!false>
disabled="disabled"
</#if>
/>
</#if>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/submit-close.ftl b/core/src/main/resources/template/html5/submit-close.ftl
index 1211a060c..3b243d2c9 100644
--- a/core/src/main/resources/template/html5/submit-close.ftl
+++ b/core/src/main/resources/template/html5/submit-close.ftl
@@ -19,11 +19,11 @@
*/
-->
<#compress>
-<#if parameters.type?? && parameters.type=="button">
-<#if parameters.body?length gt 0>${tag.escapeHtmlBody()?then(parameters.body, parameters.body?no_esc)}<#elseif parameters.label??><@s.property value="parameters.label"/></#if>
+<#if attributes.type?? && attributes.type=="button">
+<#if attributes.body?length gt 0>${tag.escapeHtmlBody()?then(attributes.body, attributes.body?no_esc)}<#elseif attributes.label??><@s.property value="attributes.label"/></#if>
</button>
<#else>
-${tag.escapeHtmlBody()?then(parameters.body, parameters.body?no_esc)}
+${tag.escapeHtmlBody()?then(attributes.body, attributes.body?no_esc)}
</#if>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/submit.ftl b/core/src/main/resources/template/html5/submit.ftl
index e3d60452c..d691c090c 100644
--- a/core/src/main/resources/template/html5/submit.ftl
+++ b/core/src/main/resources/template/html5/submit.ftl
@@ -18,77 +18,77 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
-<#if parameters.type?? && parameters.type=="button">
+<#if attributes.type?? && attributes.type=="button">
<button type="submit"
- <#if parameters.id?has_content>
- id="${parameters.id}"
+ <#if attributes.id?has_content>
+ id="${attributes.id}"
</#if>
- <#if parameters.name?has_content>
- name="${parameters.name}"
+ <#if attributes.name?has_content>
+ name="${attributes.name}"
</#if>
- <#if parameters.nameValue??>
- value="<@s.property value="parameters.nameValue"/>"
+ <#if attributes.nameValue??>
+ value="<@s.property value="attributes.nameValue"/>"
</#if>
- <#if parameters.disabled!false>
+ <#if attributes.disabled!false>
disabled="disabled"
</#if>
- <#if parameters.cssClass?has_content>
- class="${parameters.cssClass}"
+ <#if attributes.cssClass?has_content>
+ class="${attributes.cssClass}"
</#if>
- <#if parameters.cssStyle?has_content>
- style="${parameters.cssStyle}"
+ <#if attributes.cssStyle?has_content>
+ style="${attributes.cssStyle}"
</#if>
- <#if parameters.title?has_content>
- title="${parameters.title}"
+ <#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
- <#if parameters.tabindex?has_content>
- tabindex="${parameters.tabindex}"
+ <#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
</#if>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl"/>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl"/>
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
>
<#else>
-<#if parameters.type?? && parameters.type=="image">
+<#if attributes.type?? && attributes.type=="image">
<input type="image"
- <#if parameters.label?has_content>
- alt="${parameters.label}"
+ <#if attributes.label?has_content>
+ alt="${attributes.label}"
</#if>
- <#if parameters.src?has_content>
- src="${parameters.src}"
+ <#if attributes.src?has_content>
+ src="${attributes.src}"
</#if>
<#else>
<input type="submit"
- <#if parameters.nameValue?has_content>
- value="<@s.property value="parameters.nameValue"/>"
+ <#if attributes.nameValue?has_content>
+ value="<@s.property value="attributes.nameValue"/>"
</#if>
</#if>
- <#if parameters.id?has_content>
- id="${parameters.id}"
+ <#if attributes.id?has_content>
+ id="${attributes.id}"
</#if>
- <#if parameters.name?has_content>
- name="${parameters.name}"
+ <#if attributes.name?has_content>
+ name="${attributes.name}"
</#if>
- <#if parameters.disabled!false>
+ <#if attributes.disabled!false>
disabled="disabled"
</#if>
- <#if parameters.cssClass?has_content>
- class="${parameters.cssClass}"
+ <#if attributes.cssClass?has_content>
+ class="${attributes.cssClass}"
</#if>
- <#if parameters.cssStyle?has_content>
- style="${parameters.cssStyle}"
+ <#if attributes.cssStyle?has_content>
+ style="${attributes.cssStyle}"
</#if>
- <#if parameters.title?has_content>
- title="${parameters.title}"
+ <#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
- <#if parameters.tabindex?has_content>
- tabindex="${parameters.tabindex}"
+ <#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
</#if>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
>
</#if>
</#compress>
diff --git a/core/src/main/resources/template/html5/text.ftl b/core/src/main/resources/template/html5/text.ftl
index 53b0535bb..7ac956deb 100644
--- a/core/src/main/resources/template/html5/text.ftl
+++ b/core/src/main/resources/template/html5/text.ftl
@@ -18,39 +18,39 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
<input
- type="${(parameters.type!"text")}"
- name="${(parameters.name!"")}"
-<#if parameters.get("size")?has_content>
- size="${parameters.get("size")}"
+ type="${(attributes.type!"text")}"
+ name="${(attributes.name!"")}"
+<#if attributes.get("size")?has_content>
+ size="${attributes.get("size")}"
</#if>
-<#if parameters.maxlength?has_content>
- maxlength="${parameters.maxlength}"
+<#if attributes.maxlength?has_content>
+ maxlength="${attributes.maxlength}"
</#if>
-<#if parameters.nameValue??>
- value="${parameters.nameValue}"
+<#if attributes.nameValue??>
+ value="${attributes.nameValue}"
</#if>
-<#if parameters.disabled!false>
+<#if attributes.disabled!false>
disabled="disabled"
</#if>
-<#if parameters.readonly!false>
+<#if attributes.readonly!false>
readonly="readonly"
</#if>
-<#if parameters.tabindex?has_content>
- tabindex="${parameters.tabindex}"
+<#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
</#if>
-<#if parameters.id?has_content>
- id="${parameters.id}"
+<#if attributes.id?has_content>
+ id="${attributes.id}"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
-<#if parameters.title?has_content>
- title="${parameters.title}"
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl" />
+<#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
/>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/textarea.ftl b/core/src/main/resources/template/html5/textarea.ftl
index 4fc24f322..9866b72c8 100644
--- a/core/src/main/resources/template/html5/textarea.ftl
+++ b/core/src/main/resources/template/html5/textarea.ftl
@@ -18,48 +18,48 @@
* under the License.
*/
-->
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
<#compress>
<textarea
- name="${(parameters.name!"")}"
-<#if parameters.cols?has_content>
- cols="${(parameters.cols!"")}"
+ name="${(attributes.name!"")}"
+<#if attributes.cols?has_content>
+ cols="${(attributes.cols!"")}"
</#if>
- <#if parameters.rows?has_content>
- rows="${(parameters.rows!"")}"
+ <#if attributes.rows?has_content>
+ rows="${(attributes.rows!"")}"
</#if>
- <#if parameters.wrap?has_content>
- wrap="${parameters.wrap}"
+ <#if attributes.wrap?has_content>
+ wrap="${attributes.wrap}"
</#if>
- <#if parameters.disabled!false>
+ <#if attributes.disabled!false>
disabled="disabled"
</#if>
- <#if parameters.readonly!false>
+ <#if attributes.readonly!false>
readonly="readonly"
</#if>
- <#if parameters.tabindex?has_content>
- tabindex="${parameters.tabindex}"
+ <#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
</#if>
- <#if parameters.id?has_content>
- id="${parameters.id}"
+ <#if attributes.id?has_content>
+ id="${attributes.id}"
</#if>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
- <#if parameters.title?has_content>
- title="${parameters.title}"
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl" />
+ <#if attributes.title?has_content>
+ title="${attributes.title}"
</#if>
- <#if parameters.maxlength?has_content>
- maxlength="${parameters.maxlength}"
+ <#if attributes.maxlength?has_content>
+ maxlength="${attributes.maxlength}"
</#if>
- <#if parameters.minlength?has_content>
- minlength="${parameters.minlength}"
+ <#if attributes.minlength?has_content>
+ minlength="${attributes.minlength}"
</#if>
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
- <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/scripting-events.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/common-attributes.ftl" />
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
>
-<#if parameters.nameValue??>
- <@s.property value="parameters.nameValue"/>
+<#if attributes.nameValue??>
+ <@s.property value="attributes.nameValue"/>
</#if>
</textarea>
</#compress>
-<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/theme.properties b/core/src/main/resources/template/html5/theme.properties
new file mode 100644
index 000000000..6625ab56f
--- /dev/null
+++ b/core/src/main/resources/template/html5/theme.properties
@@ -0,0 +1,3 @@
+# HTML5 Theme Configuration
+# Inherits from the simple theme for base functionality
+parent = simple
diff --git a/core/src/main/resources/template/html5/token.ftl b/core/src/main/resources/template/html5/token.ftl
index d063bbbb5..1ecc66ec3 100644
--- a/core/src/main/resources/template/html5/token.ftl
+++ b/core/src/main/resources/template/html5/token.ftl
@@ -18,5 +18,5 @@
* under the License.
*/
-->
-<input type="hidden" name="${parameters.tokenNameField!""}" value="${parameters.name!""}" />
-<input type="hidden" name="${parameters.name!""}" value="${parameters.token!""}" />
\ No newline at end of file
+<input type="hidden" name="${attributes.tokenNameField!""}" value="${attributes.name!""}" />
+<input type="hidden" name="${attributes.name!""}" value="${attributes.token!""}" />
\ No newline at end of file
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxListTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxListTest.java
index 0ea404aa1..050dbdbb1 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxListTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxListTest.java
@@ -59,6 +59,19 @@ public class CheckboxListTest extends AbstractUITagTest {
verifyGenericProperties(tag, "xhtml", new String[]{"tabindex","cssClass","cssStyle","id"});
}
+ public void testGenericHtml5() throws Exception {
+ CheckboxListTag tag = new CheckboxListTag();
+ prepareTagGeneric(tag);
+ verifyGenericProperties(tag, "html5", new String[]{"tabindex","cssClass","cssStyle","id"});
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ CheckboxListTag tag = new CheckboxListTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ prepareTagGeneric(tag);
+ verifyGenericProperties(tag, "html5", new String[]{"tabindex","cssClass","cssStyle","id"});
+ }
+
private void prepareTagGeneric(CheckboxListTag tag) {
TestAction testAction = (TestAction) action;
Collection<String> collection = new ArrayList<String>(2);
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java
index e9375ae42..e7da044ca 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java
@@ -53,6 +53,17 @@ public class CheckboxTest extends AbstractUITagTest {
verifyGenericProperties(tag, "xhtml", null);
}
+ public void testGenericHtml5() throws Exception {
+ CheckboxTag tag = new CheckboxTag();
+ verifyGenericProperties(tag, "html5", null);
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ CheckboxTag tag = new CheckboxTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ verifyGenericProperties(tag, "html5", null);
+ }
+
public void testChecked() throws Exception {
TestAction testAction = (TestAction) action;
testAction.setFoo("true");
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java
index e21ca40bc..03721c9d0 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/ComboBoxTest.java
@@ -44,6 +44,19 @@ public class ComboBoxTest extends AbstractUITagTest {
verifyGenericProperties(tag, "xhtml", null);
}
+ public void testGenericHtml5() throws Exception {
+ ComboBoxTag tag = new ComboBoxTag();
+ prepareTagGeneric(tag);
+ verifyGenericProperties(tag, "html5", null);
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ ComboBoxTag tag = new ComboBoxTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ prepareTagGeneric(tag);
+ verifyGenericProperties(tag, "html5", null);
+ }
+
private void prepareTagGeneric(ComboBoxTag tag) {
TestAction testAction = (TestAction) action;
ArrayList collection = new ArrayList();
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/FileTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/FileTest.java
index d5a296c7f..301d6c5c5 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/FileTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/FileTest.java
@@ -113,4 +113,15 @@ public class FileTest extends AbstractUITagTest {
FileTag tag = new FileTag();
verifyGenericProperties(tag, "xhtml", null);
}
+
+ public void testGenericHtml5() throws Exception {
+ FileTag tag = new FileTag();
+ verifyGenericProperties(tag, "html5", null);
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ FileTag tag = new FileTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ verifyGenericProperties(tag, "html5", null);
+ }
}
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java
index 7b8044c31..5363ed145 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/HiddenTest.java
@@ -280,4 +280,15 @@ public class HiddenTest extends AbstractUITagTest {
HiddenTag tag = new HiddenTag();
verifyGenericProperties(tag, "xhtml", null);
}
+
+ public void testGenericHtml5() throws Exception {
+ HiddenTag tag = new HiddenTag();
+ verifyGenericProperties(tag, "html5", null);
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ HiddenTag tag = new HiddenTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ verifyGenericProperties(tag, "html5", null);
+ }
}
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java
index 7bc5a7c54..0409695bc 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/LabelTest.java
@@ -209,6 +209,17 @@ public class LabelTest extends AbstractUITagTest {
verifyGenericProperties(tag, "xhtml", null);
}
+ public void testGenericHtml5() throws Exception {
+ LabelTag tag = new LabelTag();
+ verifyGenericProperties(tag, "html5", null);
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ LabelTag tag = new LabelTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ verifyGenericProperties(tag, "html5", null);
+ }
+
public void testWithKeyNoValueFromStack() throws Exception {
TestAction testAction = (TestAction) action;
final String key = "labelKey";
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/PasswordTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/PasswordTest.java
index a4d5cf236..098bb8ca8 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/PasswordTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/PasswordTest.java
@@ -84,4 +84,15 @@ public class PasswordTest extends AbstractUITagTest {
PasswordTag tag = new PasswordTag();
verifyGenericProperties(tag, "xhtml", new String[]{"value"});
}
+
+ public void testGenericHtml5() throws Exception {
+ PasswordTag tag = new PasswordTag();
+ verifyGenericProperties(tag, "html5", new String[]{"value"});
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ PasswordTag tag = new PasswordTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ verifyGenericProperties(tag, "html5", new String[]{"value"});
+ }
}
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/RadioTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/RadioTest.java
index 47a5caad7..bc86a9909 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/RadioTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/RadioTest.java
@@ -553,6 +553,19 @@ public class RadioTest extends AbstractUITagTest {
verifyGenericProperties(tag, "xhtml", new String[]{"id", "value"});
}
+ public void testGenericHtml5() throws Exception {
+ RadioTag tag = new RadioTag();
+ prepareTagGeneric(tag);
+ verifyGenericProperties(tag, "html5", new String[]{"id", "value"});
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ RadioTag tag = new RadioTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ prepareTagGeneric(tag);
+ verifyGenericProperties(tag, "html5", new String[]{"id", "value"});
+ }
+
public void testDynamicAttributes() throws Exception {
TestAction testAction = (TestAction) action;
testAction.setFoo("bar");
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/ResetTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/ResetTest.java
index c297b86cc..c5b2091e7 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/ResetTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/ResetTest.java
@@ -584,4 +584,15 @@ public class ResetTest extends AbstractUITagTest {
ResetTag tag = new ResetTag();
verifyGenericProperties(tag, "xhtml", null);
}
+
+ public void testGenericHtml5() throws Exception {
+ ResetTag tag = new ResetTag();
+ verifyGenericProperties(tag, "html5", null);
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ ResetTag tag = new ResetTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ verifyGenericProperties(tag, "html5", null);
+ }
}
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java
index a087da478..91575a3cf 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java
@@ -1059,6 +1059,19 @@ public class SelectTest extends AbstractUITagTest {
verifyGenericProperties(tag, "xhtml", new String[]{"value"});
}
+ public void testGenericHtml5() throws Exception {
+ SelectTag tag = new SelectTag();
+ prepareTagGeneric(tag);
+ verifyGenericProperties(tag, "html5", new String[]{"value"});
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ SelectTag tag = new SelectTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ prepareTagGeneric(tag);
+ verifyGenericProperties(tag, "html5", new String[]{"value"});
+ }
+
public void testMultipleOn() throws Exception {
SelectTag tag = new SelectTag();
tag.setPageContext(pageContext);
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java
index e5c8299d2..1f44ffc6b 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/SubmitTest.java
@@ -649,6 +649,17 @@ public class SubmitTest extends AbstractUITagTest {
verifyGenericProperties(tag, "xhtml", null);
}
+ public void testGenericHtml5() throws Exception {
+ SubmitTag tag = new SubmitTag();
+ verifyGenericProperties(tag, "html5", null);
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ SubmitTag tag = new SubmitTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ verifyGenericProperties(tag, "html5", null);
+ }
+
/**
* Test that by default submit tag body is HTML-escaped.
*/
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/TextareaTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/TextareaTest.java
index c83086255..5fa79095f 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/TextareaTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/TextareaTest.java
@@ -152,4 +152,15 @@ public class TextareaTest extends AbstractUITagTest {
TextareaTag tag = new TextareaTag();
verifyGenericProperties(tag, "xhtml", new String[] {"value"});
}
+
+ public void testGenericHtml5() throws Exception {
+ TextareaTag tag = new TextareaTag();
+ verifyGenericProperties(tag, "html5", new String[] {"value"});
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ TextareaTag tag = new TextareaTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ verifyGenericProperties(tag, "html5", new String[] {"value"});
+ }
}
diff --git a/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java b/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java
index ad28ee4bd..fc2dfa8a7 100644
--- a/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java
+++ b/core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java
@@ -59,6 +59,17 @@ public class TextfieldTest extends AbstractUITagTest {
verifyGenericProperties(tag, "xhtml", null);
}
+ public void testGenericHtml5() throws Exception {
+ TextFieldTag tag = new TextFieldTag();
+ verifyGenericProperties(tag, "html5", null);
+ }
+
+ public void testGenericHtml5_clearTagStateSet() throws Exception {
+ TextFieldTag tag = new TextFieldTag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ verifyGenericProperties(tag, "html5", null);
+ }
+
public void testErrors() throws Exception {
TestAction testAction = (TestAction) action;
testAction.setFoo("bar");
diff --git a/thoughts/shared/research/2025-11-23-WW-5444-html5-theme-testing.md b/thoughts/shared/research/2025-11-23-WW-5444-html5-theme-testing.md
new file mode 100644
index 000000000..9c2408d4e
--- /dev/null
+++ b/thoughts/shared/research/2025-11-23-WW-5444-html5-theme-testing.md
@@ -0,0 +1,518 @@
+---
+date: 2025-11-23T17:48:30+01:00
+topic: "HTML5 Theme Implementation and Testing Approach"
+tags: [research, html5-theme, testing, ui-tags, themes, WW-5444]
+status: complete
+git_commit: 461c06d0c5afde260fdb0f32038a32f2af5bb42e
+git_branch: feature/WW-5444-html5
+---
+
+# Research: HTML5 Theme Implementation and Testing Approach
+
+**Date**: 2025-11-23T17:48:30+01:00
+**Branch**: feature/WW-5444-html5
+**Jira**: [WW-5444](https://issues.apache.org/jira/browse/WW-5444)
+
+## Research Question
+
+What testing is needed for the HTML5 theme implementation in Apache Struts, and how should it be approached based on existing theme testing patterns?
+
+## Summary
+
+The HTML5 theme has been implemented with 45 FreeMarker templates in the showcase application for easier manual testing. Analysis of existing theme testing patterns reveals a well-established infrastructure in `AbstractUITagTest` that should be replicated for html5 theme validation. The theme currently lives in `apps/showcase` but should eventually move to `core/` for production distribution.
+
+**Key Findings:**
+- HTML5 theme has 45 templates but NO unit tests yet
+- Existing themes (simple, xhtml, css_xhtml) use `verifyGenericProperties()` for testing
+- Test pattern is straightforward: add `testGenericHtml5()` to each UI tag test class
+- Production themes belong in `core/src/main/resources/template/`, not `apps/showcase`
+- No historical documentation exists in thoughts/ directory about theme testing
+
+## Detailed Findings
+
+### Current HTML5 Theme Implementation
+
+**Location**: `apps/showcase/src/main/resources/template/html5/`
+
+**45 FreeMarker Templates:**
+- Form elements: `form.ftl`, `form-close.ftl`, `text.ftl`, `textarea.ftl`, `password.ftl`, `checkbox.ftl`, `checkboxlist.ftl`, `radiomap.ftl`, `select.ftl`, `file.ftl`, `hidden.ftl`, `token.ftl`
+- Complex components: `combobox.ftl`, `doubleselect.ftl`, `inputtransferselect.ftl`, `optiontransferselect.ftl`, `updownselect.ftl`, `optgroup.ftl`
+- Display components: `actionerror.ftl`, `actionmessage.ftl`, `fielderror.ftl`, `label.ftl`
+- Navigation: `a.ftl`, `a-close.ftl`, `link.ftl`, `submit.ftl`, `submit-close.ftl`, `reset.ftl`
+- Utilities: `head.ftl`, `script.ftl`, `script-close.ftl`, `debug.ftl`, `css.ftl`, `nonce.ftl`, `datetextfield.ftl`
+- Structural: `controlheader.ftl`, `controlfooter.ftl`, `empty.ftl`
+- Attribute handling: `common-attributes.ftl`, `dynamic-attributes.ftl`, `prefixed-dynamic-attributes.ftl`, `scripting-events.ftl`
+
+**Supporting Files:**
+- Java: `apps/showcase/src/main/java/org/apache/struts2/showcase/action/Html5Action.java`
+- JSP: `apps/showcase/src/main/webapp/WEB-INF/html5/index.jsp`
+- Config: `apps/showcase/src/main/resources/struts.xml` (lines 163-167)
+
+**Key Features:**
+- Clean HTML5 markup without table-based layouts
+- Empty control headers/footers (no wrapping divs)
+- Support for HTML5 input types via TextField component
+- Bootstrap CSS integration
+- CSP nonce attribute support
+
+### Theme Testing Infrastructure
+
+**Core Testing Class**: `core/src/test/java/org/apache/struts2/views/jsp/AbstractUITagTest.java`
+
+This class provides the foundation for all UI tag testing with two primary testing approaches:
+
+#### 1. Generic Property Testing
+
+**Method**: `verifyGenericProperties(AbstractUITag tag, String theme, String[] exclude)`
+
+Tests that all standard HTML attributes render correctly for a given theme:
+- Sets 15+ generic properties (id, name, cssClass, cssStyle, title, disabled, tabindex, value, onclick, ondblclick, etc.)
+- Adds dynamic attribute test (`data-id="id-random"`)
+- Renders tag with specified theme
+- Verifies each property appears correctly in HTML output
+- Checks for FreeMarker template errors
+
+**Property Test Coverage** (Lines 110-133):
+```java
+protected Map<String, PropertyHolder> initializedGenericTagTestProperties() {
+ Map<String, PropertyHolder> result = new HashMap<>();
+ new PropertyHolder("name", "someName").addToMap(result);
+ new PropertyHolder("id", "someId").addToMap(result);
+ new PropertyHolder("cssClass", "cssClass1", "class=\"cssClass1\"").addToMap(result);
+ new PropertyHolder("cssStyle", "cssStyle1", "style=\"cssStyle1\"").addToMap(result);
+ new PropertyHolder("title", "someTitle").addToMap(result);
+ new PropertyHolder("disabled", "true", "disabled=\"disabled\"").addToMap(result);
+ new PropertyHolder("tabindex", "99").addToMap(result);
+ new PropertyHolder("value", "someValue").addToMap(result);
+ // ... event handlers (onclick, ondblclick, onmousedown, etc.)
+ return result;
+}
+```
+
+#### 2. Specific Output Testing
+
+**Method**: `verify(URL url)`
+
+Compares rendered output against expected `.txt` files:
+- Loads expected HTML from resource file
+- Normalizes both actual and expected output (removes whitespace differences)
+- Performs exact string comparison
+- Provides detailed error messages on mismatch
+
+**Expected File Location**: `core/src/test/resources/org/apache/struts2/views/jsp/ui/{TagName}-{N}.txt`
+
+### Existing Theme Test Patterns
+
+**Simple Theme Tests** (from TextfieldTest.java):
+```java
+public void testGenericSimple() throws Exception {
+ TextFieldTag tag = new TextFieldTag();
+ verifyGenericProperties(tag, "simple", null);
+}
+```
+
+**XHTML Theme Tests**:
+```java
+public void testGenericXhtml() throws Exception {
+ TextFieldTag tag = new TextFieldTag();
+ verifyGenericProperties(tag, "xhtml", null);
+}
+```
+
+**With Property Exclusions** (RadioTest.java):
+```java
+public void testGenericSimple() throws Exception {
+ RadioTag tag = new RadioTag();
+ verifyGenericProperties(tag, "simple", new String[]{"id", "value"});
+ // Excludes "id" and "value" as radio buttons handle them differently
+}
+```
+
+### Theme Template Location Patterns
+
+**Production Themes** → `core/src/main/resources/template/`
+- **simple**: 47 templates (base theme, no parent)
+- **xhtml**: 30 templates (parent = simple)
+- **css_xhtml**: 13 templates (parent = xhtml)
+
+**Demo/Showcase Themes** → `apps/showcase/src/main/resources/template/`
+- **html5**: 45 templates (currently here)
+- **ajaxErrorContainers**: 4 templates
+
+**Theme Inheritance Pattern**:
+```
+simple (root)
+ ↓
+xhtml (parent = simple)
+ ↓
+css_xhtml (parent = xhtml)
+```
+
+Defined via `theme.properties` with `parent = <parent-theme>` property.
+
+**Key Pattern Rule**: Production-ready themes MUST be in `core/` to be packaged with struts2-core.jar and available to all applications.
+
+### Integration Testing Pattern
+
+**Example from Showcase**: `apps/showcase/src/test/java/it/org/apache/struts2/showcase/UITagExampleTest.java`
+
+Uses HtmlUnit to test complete form workflows:
+```java
+@Test
+public void testInputForm() throws Exception {
+ try (final WebClient webClient = new WebClient()) {
+ final HtmlPage page = webClient.getPage(
+ ParameterUtils.getBaseUrl() + "/tags/ui/example!input.action"
+ );
+
+ final HtmlForm form = page.getFormByName("exampleSubmit");
+ final HtmlTextInput textField = form.getInputByName("name");
+ // ... interact with form elements
+
+ final HtmlSubmitInput button = form.getInputByValue("Submit");
+ final HtmlPage page2 = button.click();
+
+ // Verify results
+ Assert.assertEquals("name", page2.getElementById("name").asNormalizedText());
+ }
+}
+```
+
+## Code References
+
+### HTML5 Theme Implementation
+- `apps/showcase/src/main/resources/template/html5/*.ftl` - All 45 FreeMarker templates
+- `apps/showcase/src/main/java/org/apache/struts2/showcase/action/Html5Action.java` - Demo action
+- `apps/showcase/src/main/webapp/WEB-INF/html5/index.jsp` - Demo page
+- `apps/showcase/src/main/resources/struts.xml:163-167` - Configuration
+
+### Testing Infrastructure
+- `core/src/test/java/org/apache/struts2/views/jsp/AbstractUITagTest.java:155-174` - verifyGenericProperties() method
+- `core/src/test/java/org/apache/struts2/views/jsp/AbstractUITagTest.java:110-133` - Generic property definitions
+- `core/src/test/java/org/apache/struts2/views/jsp/AbstractUITagTest.java:201-230` - verify() method for output comparison
+- `core/src/test/resources/org/apache/struts2/views/jsp/ui/` - Expected output files
+
+### Example Test Classes
+- `core/src/test/java/org/apache/struts2/views/jsp/ui/TextfieldTest.java` - Comprehensive test examples
+- `core/src/test/java/org/apache/struts2/views/jsp/ui/PasswordTest.java:78-86` - Theme test pattern
+- `core/src/test/java/org/apache/struts2/views/jsp/ui/CheckboxTest.java` - Checkbox-specific tests
+- `core/src/test/java/org/apache/struts2/views/jsp/ui/SelectTest.java` - Select/dropdown tests
+
+### Integration Tests
+- `apps/showcase/src/test/java/it/org/apache/struts2/showcase/UITagExampleTest.java` - HtmlUnit integration test example
+
+## Testing Recommendations
+
+### Priority 1: Unit Tests for Generic Properties (High Priority)
+
+Add `testGenericHtml5()` method to each UI tag test class:
+
+**Files to modify** (in `core/src/test/java/org/apache/struts2/views/jsp/ui/`):
+1. `TextfieldTest.java`
+2. `TextareaTest.java`
+3. `PasswordTest.java`
+4. `CheckboxTest.java`
+5. `CheckboxListTest.java`
+6. `RadioTest.java`
+7. `SelectTest.java`
+8. `FileTest.java`
+9. `HiddenTest.java`
+10. `LabelTest.java`
+11. `FormTagTest.java`
+12. `SubmitTest.java`
+13. `ResetTest.java`
+14. `AnchorTagTest.java`
+15. `ActionErrorTagTest.java`
+16. `ActionMessageTagTest.java`
+17. `FieldErrorTagTest.java`
+18. `DoubleSelectTest.java`
+19. `ComboBoxTest.java`
+20. `UpDownSelectTagTest.java`
+21. `InputTransferSelectTagTest.java`
+22. `OptionTransferSelectTagTest.java`
+
+**Pattern to add**:
+```java
+public void testGenericHtml5() throws Exception {
+ <TagName>Tag tag = new <TagName>Tag();
+ verifyGenericProperties(tag, "html5", null);
+}
+
+public void testGenericHtml5_clearTagStateSet() throws Exception {
+ <TagName>Tag tag = new <TagName>Tag();
+ tag.setPerformClearTagStateForTagPoolingServers(true);
+ verifyGenericProperties(tag, "html5", null);
+}
+```
+
+**Exclusions to consider**:
+- Radio/Checkbox: Exclude "id" and "value" (handled differently)
+- Hidden: Exclude properties that don't apply to hidden fields
+- Token: Minimal properties apply
+
+**Effort**: ~2-3 lines per test class × 22 classes = **minimal implementation effort**
+
+**Benefit**: Ensures all 45 templates render correctly with standard HTML attributes
+
+### Priority 2: Integration Tests in Showcase (Medium Priority)
+
+**Create**: `apps/showcase/src/test/java/it/org/apache/struts2/showcase/Html5TagExampleTest.java`
+
+**Test Coverage**:
+1. Basic form rendering with html5 theme
+2. All input types render correctly
+3. Error messages display properly (actionerror, actionmessage, fielderror)
+4. Dynamic attributes work (data-*, aria-*)
+5. Submit workflow completes successfully
+6. No table-based layout in output
+
+**Example structure**:
+```java
+public class Html5TagExampleTest {
+ @Test
+ public void testHtml5FormRendering() throws Exception {
+ try (final WebClient webClient = new WebClient()) {
+ final HtmlPage page = webClient.getPage(
+ ParameterUtils.getBaseUrl() + "/html5/index.action"
+ );
+
+ // Verify clean HTML5 markup
+ assertFalse(page.asXml().contains("<table"));
+
+ // Test error display
+ assertNotNull(page.getElementById("actionErrors"));
+
+ // Verify Bootstrap compatibility
+ assertTrue(page.asXml().contains("class=\""));
+ }
+ }
+}
+```
+
+**Effort**: 1-2 integration test methods
+
+**Benefit**: End-to-end validation that theme works in real application context
+
+### Priority 3: Expand Showcase Demo (Medium Priority)
+
+**Enhance**: `apps/showcase/src/main/webapp/WEB-INF/html5/index.jsp`
+
+**Add demonstrations for**:
+1. All form input types (text, password, checkbox, radio, select, textarea, file, hidden)
+2. Complex components (doubleselect, combobox, updownselect, etc.)
+3. Error handling scenarios (fielderror, actionerror, actionmessage)
+4. Dynamic attributes (data-*, aria-*)
+5. HTML5 input types (email, url, number, date, etc.)
+6. Submit/reset buttons
+7. Links and anchors
+8. Label positioning
+
+**Benefit**: Visual validation during development, documentation for users
+
+### Priority 4: Template Relocation Decision (High Priority)
+
+**Question**: Should html5 theme move from `apps/showcase` to `core`?
+
+**Options**:
+
+**Option A: Move to core/** (Recommended for production theme)
+- **Location**: `core/src/main/resources/template/html5/`
+- **Pros**:
+ - Available to all Struts applications
+ - Shipped with struts2-core.jar
+ - Consistent with simple/xhtml/css_xhtml
+- **Cons**:
+ - Commits to maintaining it
+ - Increases core artifact size slightly
+
+**Option B: Keep in showcase** (Recommended for experimental theme)
+- **Location**: `apps/showcase/src/main/resources/template/html5/`
+- **Pros**:
+ - Easy to experiment and iterate
+ - Doesn't affect core framework
+ - Users can copy templates to their apps
+- **Cons**:
+ - Not available in struts2-core.jar
+ - Users must manually add templates
+ - Inconsistent with other themes
+
+**Recommendation**: If html5 theme is meant to be production-ready and recommended for new applications, move to `core/`. If it's experimental or an example, keep in showcase.
+
+**Implementation**: If moving to core, also move:
+- Templates: `apps/showcase/src/main/resources/template/html5/` → `core/src/main/resources/template/html5/`
+- Tests: Create unit tests in `core/src/test/java/org/apache/struts2/views/jsp/ui/*Test.java`
+- Update showcase to use core's html5 theme instead of local copy
+
+### Priority 5: HTML5 Validation Testing (Low-Medium Priority)
+
+**Tools to use**:
+- W3C HTML5 Validator (via API or library)
+- HtmlUnit for semantic validation
+- Accessibility checkers (ARIA attributes, semantic tags)
+
+**What to validate**:
+1. Valid HTML5 markup (no deprecated elements)
+2. Proper attribute handling (data-*, aria-*, etc.)
+3. Semantic HTML structure where appropriate
+4. No table-based layouts (unless data tables)
+5. Accessibility compliance (labels, ARIA)
+
+**Example test**:
+```java
+@Test
+public void testHtml5ValidMarkup() throws Exception {
+ // Render form with html5 theme
+ FormTag form = new FormTag();
+ form.setTheme("html5");
+ // ... configure
+ form.doStartTag();
+ form.doEndTag();
+
+ String output = writer.toString();
+
+ // Verify no table layout
+ assertFalse(output.contains("<table"));
+ assertFalse(output.contains("class=\"tdLabel\""));
+
+ // Verify HTML5 elements
+ assertTrue(output.matches(".*<form[^>]*>.*"));
+
+ // No deprecated attributes
+ assertFalse(output.contains("align="));
+ assertFalse(output.contains("border="));
+}
+```
+
+### Priority 6: Documentation (Medium Priority)
+
+**Create**:
+1. **User Guide**: How to use html5 theme in applications
+ - Migration guide from xhtml/simple to html5
+ - Bootstrap CSS integration examples
+ - HTML5 input type usage
+
+2. **Developer Guide**: How html5 theme works
+ - Template structure
+ - Differences from xhtml theme
+ - Customization points
+
+3. **Testing Guide**: How to test themes
+ - Unit test pattern
+ - Integration test approach
+ - Expected output file creation
+
+**Location**: Consider adding to `core/src/site/` for Maven site generation
+
+## Architecture Insights
+
+### Theme Testing Architecture
+
+The Struts theme testing architecture demonstrates several key design patterns:
+
+1. **Template Method Pattern**: `AbstractUITagTest` provides template methods like `verifyGenericProperties()` that subclasses call with theme-specific parameters
+
+2. **Resource-Based Verification**: Expected output files as resources allow platform-independent testing without hardcoded strings in test code
+
+3. **Normalization Strategy**: Whitespace normalization makes tests resilient to formatting differences while still catching real HTML changes
+
+4. **Property Holder Pattern**: Encapsulates test data (name, value, expectation) for declarative property testing
+
+5. **Theme Inheritance**: FreeMarker template resolution with fallback supports theme hierarchies (css_xhtml → xhtml → simple)
+
+### HTML5 Theme Design Decisions
+
+1. **No Control Wrappers**: Empty `controlheader.ftl` and `controlfooter.ftl` provide clean HTML without extra divs, unlike xhtml theme's table-based layout
+
+2. **Bootstrap Compatibility**: Clean markup designed to work with Bootstrap CSS classes without framework-specific markup
+
+3. **HTML5 Input Types**: TextField component supports HTML5 input types (email, url, number, etc.) via type attribute
+
+4. **CSP Support**: Includes `nonce.ftl` for Content Security Policy nonce attribute handling
+
+5. **Dynamic Attributes**: Full support for data-* and aria-* attributes via `dynamic-attributes.ftl`
+
+### Testing Infrastructure Design
+
+1. **Separation of Concerns**: Generic property tests separate from specific behavior tests
+
+2. **Reusable Test Infrastructure**: `AbstractUITagTest` provides shared testing utilities for all UI tag tests
+
+3. **Theme Parameterization**: Same test can validate multiple themes by changing theme parameter
+
+4. **Exclusion Mechanism**: Allows tags to exclude properties that don't apply (e.g., hidden field doesn't render visible properties)
+
+5. **Integration with Maven**: Test resources use classpath resolution for portability
+
+## Open Questions
+
+1. **Production Readiness**: Is html5 theme ready for production (core/) or still experimental (showcase/)?
+
+2. **Theme Properties**: Should html5 theme have a `theme.properties` file defining inheritance (e.g., `parent = simple`)?
+
+3. **Default Theme**: Should html5 become the default theme for new Struts applications (replacing xhtml)?
+
+4. **Backward Compatibility**: How to handle applications migrating from xhtml to html5 theme?
+
+5. **CSS Framework Integration**: Should html5 theme include optional CSS for Bootstrap, Tailwind, or remain unopinionated?
+
+6. **Component Coverage**: Are all 45 templates necessary, or should some inherit from simple theme?
+
+7. **Form Layout**: Should html5 theme include layout options (inline, horizontal, vertical) like Bootstrap forms?
+
+8. **Error Positioning**: How should field errors be positioned in html5 theme compared to xhtml theme's table-based approach?
+
+## Next Steps
+
+### Immediate Actions (Before PR)
+
+1. **Add unit tests**: Implement `testGenericHtml5()` in all UI tag test classes
+2. **Run test suite**: Execute `mvn test -DskipAssembly` to verify all tests pass
+3. **Decide location**: Determine if html5 theme should move to core/ or stay in showcase/
+4. **Create integration test**: Add `Html5TagExampleTest.java` for end-to-end validation
+
+### Short-term Actions (Before Release)
+
+1. **Expand showcase demo**: Add comprehensive examples to index.jsp
+2. **HTML5 validation**: Verify all templates produce valid HTML5 markup
+3. **Documentation**: Create user guide for html5 theme usage
+4. **Performance testing**: Compare rendering performance vs xhtml theme
+
+### Long-term Considerations
+
+1. **Default theme discussion**: Consider making html5 the recommended/default theme
+2. **Migration tooling**: Create utilities to help migrate from xhtml to html5
+3. **CSS framework integration**: Evaluate official integrations with popular CSS frameworks
+4. **Accessibility audit**: Ensure WCAG compliance for all components
+
+## Testing Effort Estimation
+
+**Unit Tests**:
+- 22 test classes × 2 methods each = 44 test methods
+- ~2-3 lines per method
+- **Effort**: 2-3 hours
+
+**Integration Tests**:
+- 1 test class with 3-5 test methods
+- **Effort**: 2-4 hours
+
+**Expected Output Files** (if needed for specific tests):
+- 0 files needed for generic property tests
+- Optional for specific behavior tests
+- **Effort**: Variable, only if specific behavior needs validation
+
+**Total Estimated Effort**: **4-7 hours** for comprehensive test coverage
+
+## References
+
+### Jira Issues
+- [WW-5444](https://issues.apache.org/jira/browse/WW-5444) - Implement a new html5 theme
+
+### Related Code
+- Theme rendering: `core/src/main/java/org/apache/struts2/components/UIBean.java`
+- Template engine: `core/src/main/java/org/apache/struts2/components/template/`
+- FreeMarker templates: `core/src/main/resources/template/`
+
+### Maven Commands
+- Run tests: `mvn test -DskipAssembly`
+- Build showcase: `mvn clean install` (from apps/showcase/)
+- Full build: `mvn clean install` (from project root)
(struts) 05/05: docs: update CLAUDE.md and remove jakarta-migration-helper agent
Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch feature/WW-5444-html5
in repository https://gitbox.apache.org/repos/asf/struts.git
commit fbb675cedfc2ffa81696c510eb224252343c6d7f
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Sun Nov 23 18:49:58 2025 +0100
docs: update CLAUDE.md and remove jakarta-migration-helper agent
- Update CLAUDE.md with current project guidelines
- Update test-runner agent documentation
- Remove deprecated jakarta-migration-helper agent
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <no...@anthropic.com>
---
.claude/agents/jakarta-migration-helper.md | 484 -----------------------------
.claude/agents/test-runner.md | 2 +-
CLAUDE.md | 3 +-
3 files changed, 2 insertions(+), 487 deletions(-)
diff --git a/.claude/agents/jakarta-migration-helper.md b/.claude/agents/jakarta-migration-helper.md
deleted file mode 100644
index 2ea97dc01..000000000
--- a/.claude/agents/jakarta-migration-helper.md
+++ /dev/null
@@ -1,484 +0,0 @@
----
-name: jakarta-migration-helper
-description: Use this agent to analyze and assist with Jakarta EE migration for Apache Struts projects, including namespace conversions, dependency updates, compatibility analysis, and migration planning. Examples: <example>Context: Team needs to migrate from javax to jakarta namespaces. user: 'Help us migrate our Struts project to Jakarta EE' assistant: 'I'll use the jakarta-migration-helper agent to analyze your project and provide a comprehensive migration plan.' <commentary>The user [...]
-model: sonnet
-color: cyan
----
-
-# Apache Struts Jakarta EE Migration Helper
-
-## Identity
-You are a specialized migration expert for transitioning Apache Struts projects from Java EE (javax) to Jakarta EE (jakarta) namespaces. You have comprehensive knowledge of the migration process, compatibility requirements, dependency changes, and potential issues that arise during the transition.
-
-## Core Migration Expertise
-
-### 1. Jakarta EE Migration Scope
-- **Namespace Transformation**: `javax.*` to `jakarta.*` package conversions
-- **Dependency Updates**: Maven/Gradle dependency version updates
-- **API Compatibility**: Analysis of breaking changes and compatibility issues
-- **Plugin Migration**: Struts plugin compatibility with Jakarta EE
-- **Build Configuration**: Build tool configuration updates
-- **Testing Strategy**: Migration testing and validation approaches
-
-### 2. Struts-Specific Migration Areas
-- **Core Framework**: Struts core Jakarta compatibility
-- **Servlet API**: Servlet 5.0+ and Jakarta Servlet API
-- **JSP/JSTL**: Jakarta Pages and Jakarta Standard Tag Library
-- **Bean Validation**: Jakarta Bean Validation migration
-- **CDI Integration**: Jakarta CDI compatibility
-- **Plugin Ecosystem**: Plugin-by-plugin migration analysis
-
-### 3. Migration Planning and Execution
-- **Impact Assessment**: Comprehensive analysis of migration scope
-- **Dependency Mapping**: Mapping of javax to jakarta dependencies
-- **Risk Analysis**: Identification of migration risks and mitigation strategies
-- **Phased Migration**: Planning incremental migration approaches
-- **Compatibility Testing**: Validation strategies for migrated code
-
-## Migration Discovery and Analysis
-
-### 1. Current State Assessment
-```bash
-# Find javax package usage
-grep -r "javax\." --include="*.java" . | grep -v target | wc -l
-grep -r "import javax\." --include="*.java" . | head -20
-
-# Check for Jakarta usage (if any)
-grep -r "jakarta\." --include="*.java" . | grep -v target
-
-# Analyze servlet API usage
-grep -r "javax.servlet" --include="*.java" .
-grep -r "HttpServlet" --include="*.java" .
-
-# Check JSP/JSTL usage
-find . -name "*.jsp" -exec grep -l "javax.servlet" {} \;
-find . -name "*.jsp" -exec grep -l "http://java.sun.com/jsp/jstl" {} \;
-```
-
-### 2. Dependency Analysis
-```bash
-# Check Maven dependencies
-grep -r "javax\." pom.xml */pom.xml
-grep -r "servlet-api" pom.xml */pom.xml
-grep -r "jsp-api" pom.xml */pom.xml
-
-# Check for Jakarta dependencies (existing)
-grep -r "jakarta\." pom.xml */pom.xml
-
-# Analyze plugin dependencies
-find plugins -name "pom.xml" -exec grep -l "javax" {} \;
-```
-
-### 3. Configuration Analysis
-```bash
-# Check web.xml for servlet API references
-find . -name "web.xml" -exec grep -l "javax.servlet" {} \;
-
-# Check struts configuration for Jakarta-specific settings
-grep -r "jakarta" --include="*.xml" --include="*.properties" .
-
-# Analyze plugin configurations
-find . -name "struts-plugin.xml" -exec grep -l "javax" {} \;
-```
-
-## Migration Transformation Patterns
-
-### 1. Package Namespace Changes
-**Core Servlet API:**
-```java
-// BEFORE (javax)
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.ServletException;
-import javax.servlet.annotation.WebServlet;
-
-// AFTER (jakarta)
-import jakarta.servlet.http.HttpServlet;
-import jakarta.servlet.http.HttpServletRequest;
-import jakarta.servlet.http.HttpServletResponse;
-import jakarta.servlet.ServletException;
-import jakarta.servlet.annotation.WebServlet;
-```
-
-**JSP and JSTL:**
-```jsp
-<!-- BEFORE (javax) -->
-<%@ page import="javax.servlet.http.HttpSession" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-
-<!-- AFTER (jakarta) -->
-<%@ page import="jakarta.servlet.http.HttpSession" %>
-<%@ taglib uri="jakarta.tags.core" prefix="c" %>
-```
-
-**Bean Validation:**
-```java
-// BEFORE (javax)
-import javax.validation.constraints.NotNull;
-import javax.validation.constraints.Size;
-import javax.validation.Valid;
-
-// AFTER (jakarta)
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Size;
-import jakarta.validation.Valid;
-```
-
-### 2. Dependency Mapping
-**Maven Dependency Transformations:**
-```xml
-<!-- BEFORE (javax) -->
-<dependency>
- <groupId>javax.servlet</groupId>
- <artifactId>javax.servlet-api</artifactId>
- <version>4.0.1</version>
-</dependency>
-
-<dependency>
- <groupId>javax.servlet.jsp</groupId>
- <artifactId>javax.servlet.jsp-api</artifactId>
- <version>2.3.3</version>
-</dependency>
-
-<!-- AFTER (jakarta) -->
-<dependency>
- <groupId>jakarta.servlet</groupId>
- <artifactId>jakarta.servlet-api</artifactId>
- <version>5.0.0</version>
-</dependency>
-
-<dependency>
- <groupId>jakarta.servlet.jsp</groupId>
- <artifactId>jakarta.servlet.jsp-api</artifactId>
- <version>3.0.0</version>
-</dependency>
-```
-
-**Bean Validation Migration:**
-```xml
-<!-- BEFORE (javax) -->
-<dependency>
- <groupId>javax.validation</groupId>
- <artifactId>validation-api</artifactId>
- <version>2.0.1.Final</version>
-</dependency>
-
-<!-- AFTER (jakarta) -->
-<dependency>
- <groupId>jakarta.validation</groupId>
- <artifactId>jakarta.validation-api</artifactId>
- <version>3.0.0</version>
-</dependency>
-```
-
-### 3. Configuration Updates
-**web.xml Schema Updates:**
-```xml
-<!-- BEFORE (javax) -->
-<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
- http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
- version="4.0">
-
-<!-- AFTER (jakarta) -->
-<web-app xmlns="https://jakarta.ee/xml/ns/jakartaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee
- https://jakarta.ee/xml/ns/jakartaee/web-app_5_0.xsd"
- version="5.0">
-```
-
-## Struts-Specific Migration Considerations
-
-### 1. Core Framework Compatibility
-**Struts Version Requirements:**
-- Struts 6.0.0+ supports both javax and jakarta namespaces
-- Struts 7.0.0+ is jakarta-native
-- Plugin compatibility varies by version
-
-**Framework Integration Points:**
-```java
-// Struts ActionSupport with Jakarta
-public class MyAction extends ActionSupport {
- // Jakarta servlet API integration
- private jakarta.servlet.http.HttpServletRequest request;
- private jakarta.servlet.http.HttpServletResponse response;
-}
-```
-
-### 2. Plugin Migration Analysis
-**Plugin Compatibility Matrix:**
-- **struts2-spring-plugin**: Requires Spring 6.0+ for Jakarta
-- **struts2-tiles-plugin**: Requires Tiles 3.1+ for Jakarta
-- **struts2-json-plugin**: Generally compatible
-- **struts2-convention-plugin**: Requires updates for annotation scanning
-- **struts2-bean-validation-plugin**: Requires Jakarta Bean Validation
-
-### 3. Custom Component Migration
-**Interceptor Migration:**
-```java
-// BEFORE (javax)
-public class MyInterceptor extends AbstractInterceptor {
- @Override
- public String intercept(ActionInvocation invocation) throws Exception {
- javax.servlet.http.HttpServletRequest request =
- ServletActionContext.getRequest();
- // Implementation
- }
-}
-
-// AFTER (jakarta)
-public class MyInterceptor extends AbstractInterceptor {
- @Override
- public String intercept(ActionInvocation invocation) throws Exception {
- jakarta.servlet.http.HttpServletRequest request =
- ServletActionContext.getRequest();
- // Implementation
- }
-}
-```
-
-## Migration Planning Framework
-
-### 1. Pre-Migration Assessment
-**Scope Analysis:**
-- Count of javax package references
-- Dependency inventory and versions
-- Plugin compatibility assessment
-- Custom component analysis
-- Third-party library compatibility
-
-**Risk Assessment:**
-- Breaking changes identification
-- Compatibility matrix validation
-- Testing strategy requirements
-- Rollback planning
-
-### 2. Migration Strategy Options
-**Option 1: Big Bang Migration**
-- Complete migration in single effort
-- Requires comprehensive testing
-- Higher risk but faster completion
-
-**Option 2: Incremental Migration**
-- Module-by-module migration
-- Parallel javax/jakarta support
-- Lower risk but longer timeline
-
-**Option 3: Hybrid Approach**
-- Core framework first
-- Plugin migration second
-- Custom components last
-
-### 3. Implementation Phases
-**Phase 1: Preparation**
-- Dependency analysis completion
-- Compatibility verification
-- Test suite preparation
-- Environment setup
-
-**Phase 2: Core Migration**
-- Framework dependency updates
-- Core package namespace changes
-- Basic functionality validation
-
-**Phase 3: Plugin Migration**
-- Plugin-by-plugin migration
-- Configuration updates
-- Integration testing
-
-**Phase 4: Validation and Testing**
-- Comprehensive testing
-- Performance validation
-- Security testing
-- User acceptance testing
-
-## Migration Tools and Automation
-
-### 1. Automated Transformation Tools
-**Eclipse Migration Toolkit:**
-```bash
-# Use Eclipse Migration Toolkit for automated transformation
-# Configure for javax to jakarta package migration
-```
-
-**Maven Migration Plugin:**
-```xml
-<plugin>
- <groupId>org.apache.tomcat.maven</groupId>
- <artifactId>jakartaee-migration-maven-plugin</artifactId>
- <version>1.0.0</version>
- <configuration>
- <source>src/main/java</source>
- <target>target/migrated</target>
- </configuration>
-</plugin>
-```
-
-**Custom Migration Scripts:**
-```bash
-# Automated package replacement
-find . -name "*.java" -exec sed -i 's/javax\.servlet/jakarta.servlet/g' {} \;
-find . -name "*.java" -exec sed -i 's/javax\.validation/jakarta.validation/g' {} \;
-
-# JSP taglib updates
-find . -name "*.jsp" -exec sed -i 's/http:\/\/java\.sun\.com\/jsp\/jstl/jakarta.tags/g' {} \;
-```
-
-### 2. Validation Tools
-**Build Validation:**
-```bash
-# Ensure no javax references remain
-grep -r "import javax\." --include="*.java" . | grep -v target
-
-# Validate Jakarta imports
-grep -r "import jakarta\." --include="*.java" . | wc -l
-
-# Check for mixed usage (should be avoided)
-files_with_both=$(grep -l "javax\." --include="*.java" . | xargs grep -l "jakarta\.")
-```
-
-## Output Format
-
-Structure migration analysis results as:
-
-```
-## Jakarta EE Migration Analysis Report
-
-### Migration Scope Assessment
-- **javax References**: [number] found
-- **Affected Files**: [number] requiring changes
-- **Dependencies**: [number] requiring updates
-- **Migration Complexity**: [low/medium/high]
-
-### Current State Analysis
-#### Package Usage
-- **javax.servlet**: [number] references
-- **javax.validation**: [number] references
-- **javax.jsp**: [number] references
-- **Other javax packages**: [list]
-
-#### Dependency Analysis
-- **Maven Dependencies**: [number] requiring updates
-- **Plugin Dependencies**: [number] with compatibility issues
-- **Third-party Libraries**: [number] requiring validation
-
-### Struts-Specific Considerations
-#### Framework Compatibility
-- **Current Struts Version**: [version]
-- **Jakarta Support**: [native/transitional/unsupported]
-- **Recommended Target**: [Struts version for migration]
-
-#### Plugin Compatibility
-- **Compatible Plugins**: [list]
-- **Requires Updates**: [list with version requirements]
-- **Migration Blockers**: [list of incompatible plugins]
-
-### Migration Strategy Recommendation
-- **Recommended Approach**: [big bang/incremental/hybrid]
-- **Estimated Effort**: [time estimate]
-- **Risk Level**: [low/medium/high]
-
-### Migration Roadmap
-#### Phase 1: Preparation ([duration])
-- [ ] Update Struts framework to Jakarta-compatible version
-- [ ] Verify third-party library compatibility
-- [ ] Prepare test environment
-
-#### Phase 2: Core Migration ([duration])
-- [ ] Update Maven dependencies
-- [ ] Transform package imports
-- [ ] Update configuration files
-
-#### Phase 3: Plugin Migration ([duration])
-- [ ] Migrate compatible plugins
-- [ ] Update plugin configurations
-- [ ] Replace incompatible plugins
-
-#### Phase 4: Validation ([duration])
-- [ ] Execute migration tests
-- [ ] Perform integration testing
-- [ ] Validate performance and security
-
-### Transformation Guide
-#### Package Transformations
-- `javax.servlet.*` → `jakarta.servlet.*`
-- `javax.validation.*` → `jakarta.validation.*`
-- `javax.servlet.jsp.*` → `jakarta.servlet.jsp.*`
-
-#### Dependency Updates
-[Detailed before/after dependency mappings]
-
-#### Configuration Changes
-[Specific configuration file updates needed]
-
-### Risk Analysis
-#### High-Risk Items
-- [Items requiring careful attention]
-
-#### Medium-Risk Items
-- [Items requiring validation]
-
-#### Compatibility Concerns
-- [Third-party dependencies with unknown Jakarta support]
-
-### Testing Strategy
-#### Pre-Migration Testing
-- [ ] Baseline functionality testing
-- [ ] Performance benchmarking
-- [ ] Security validation
-
-#### Post-Migration Testing
-- [ ] Functionality regression testing
-- [ ] Performance comparison
-- [ ] Security re-validation
-- [ ] Integration testing
-
-### Rollback Plan
-- [Detailed rollback strategy if migration fails]
-- [Backup and restore procedures]
-- [Dependency rollback mappings]
-
-### Tools and Resources
-- **Migration Tools**: [recommended tools]
-- **Documentation**: [relevant Jakarta EE migration guides]
-- **Community Support**: [forums and resources]
-```
-
-## Jakarta EE Migration Best Practices
-
-### 1. Incremental Validation
-- Test each migration phase independently
-- Maintain parallel environments during transition
-- Validate functionality at each step
-- Monitor performance throughout migration
-
-### 2. Compatibility Management
-- Use Maven dependency management for version control
-- Implement feature toggles for gradual rollout
-- Maintain backward compatibility where possible
-- Plan for legacy system integration
-
-### 3. Team Coordination
-- Provide training on Jakarta EE changes
-- Establish migration coding standards
-- Implement code review processes
-- Document migration decisions and rationale
-
-## Framework Evolution Considerations
-
-### 1. Long-term Strategy
-- Plan for post-migration framework updates
-- Consider cloud-native deployment implications
-- Evaluate microservices architecture opportunities
-- Assess container orchestration compatibility
-
-### 2. Continuous Migration
-- Establish processes for ongoing dependency updates
-- Monitor Jakarta EE specification evolution
-- Plan for future framework version migrations
-- Maintain migration expertise within the team
-
-Remember: Jakarta EE migration is not just a namespace change—it's an opportunity to modernize your Struts application architecture and improve long-term maintainability. Always validate thoroughly and plan for the unexpected.
\ No newline at end of file
diff --git a/.claude/agents/test-runner.md b/.claude/agents/test-runner.md
index dfc1bdb48..20a1e3458 100644
--- a/.claude/agents/test-runner.md
+++ b/.claude/agents/test-runner.md
@@ -1,6 +1,6 @@
---
name: test-runner
-description: Use this agent to intelligently execute and analyze Apache Struts tests using Maven, with specialized knowledge of Struts testing patterns, coverage analysis, and security testing. Examples: <example>Context: Developer wants to run tests after implementing a new feature. user: 'Can you run the tests for my changes?' assistant: 'I'll use the test-runner agent to execute the relevant tests and analyze the results.' <commentary>The user needs test execution and analysis, which [...]
+description: Use this agent to intelligently execute and analyze Apache Struts tests using Maven, with specialized knowledge of Struts testing patterns, coverage analysis, and security testing. Examples: <example>Context: Developer wants to run tests after implementing a new feature. user: 'Can you run the tests for my changes?' assistant: 'I willll use the test-runner agent to execute the relevant tests and analyze the results.' <commentary>The user needs test execution and analysis, wh [...]
model: sonnet
color: green
---
diff --git a/CLAUDE.md b/CLAUDE.md
index 6f324f0d8..36124995d 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -159,10 +159,9 @@ mvn test -DskipAssembly
### Specialized Agents
- `security-analyzer` - OGNL injection scanning, CVE detection
-- `test-runner` - Maven test execution and coverage analysis
+- `test-runner` - Maven test execution and coverage analysis, use this agent to RUN the tests
- `code-quality-checker` - JavaDoc compliance, pattern consistency
- `config-validator` - struts.xml validation, interceptor analysis
-- `jakarta-migration-helper` - Jakarta EE migration assistance
- `codebase-analyzer` - Project structure and architecture analysis
- `codebase-locator` - Code and file location assistance
- `codebase-pattern-finder` - Pattern examples and usage
(struts) 01/05: WW-5444 Defines new html5 theme
Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch feature/WW-5444-html5
in repository https://gitbox.apache.org/repos/asf/struts.git
commit 461c06d0c5afde260fdb0f32038a32f2af5bb42e
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Sat Jul 20 08:16:15 2024 +0200
WW-5444 Defines new html5 theme
---
.../struts2/showcase/action/Html5Action.java | 14 ++
apps/showcase/src/main/resources/struts.xml | 6 +
.../src/main/resources/template/html5/a-close.ftl | 50 +++++++
.../src/main/resources/template/html5/a.ftl | 20 +++
.../main/resources/template/html5/actionerror.ftl | 44 ++++++
.../resources/template/html5/actionmessage.ftl | 44 ++++++
.../src/main/resources/template/html5/checkbox.ftl | 52 +++++++
.../main/resources/template/html5/checkboxlist.ftl | 120 +++++++++++++++++
.../src/main/resources/template/html5/combobox.ftl | 102 ++++++++++++++
.../resources/template/html5/common-attributes.ftl | 25 ++++
.../resources/template/html5/controlfooter.ftl | 20 +++
.../resources/template/html5/controlheader.ftl | 20 +++
.../src/main/resources/template/html5/css.ftl | 35 +++++
.../resources/template/html5/datetextfield.ftl | 21 +++
.../src/main/resources/template/html5/debug.ftl | 92 +++++++++++++
.../main/resources/template/html5/doubleselect.ftl | 21 +++
.../template/html5/dynamic-attributes.ftl | 45 +++++++
.../src/main/resources/template/html5/empty.ftl | 20 +++
.../main/resources/template/html5/fielderror.ftl | 84 ++++++++++++
.../src/main/resources/template/html5/file.ftl | 49 +++++++
.../main/resources/template/html5/form-close.ftl | 22 +++
.../src/main/resources/template/html5/form.ftl | 72 ++++++++++
.../src/main/resources/template/html5/head.ftl | 23 ++++
.../src/main/resources/template/html5/hidden.ftl | 43 ++++++
.../template/html5/inputtransferselect.ftl | 21 +++
.../src/main/resources/template/html5/label.ftl | 42 ++++++
.../src/main/resources/template/html5/link.ftl | 74 ++++++++++
.../src/main/resources/template/html5/nonce.ftl | 25 ++++
.../src/main/resources/template/html5/optgroup.ftl | 71 ++++++++++
.../template/html5/optiontransferselect.ftl | 21 +++
.../src/main/resources/template/html5/password.ftl | 55 ++++++++
.../template/html5/prefixed-dynamic-attributes.ftl | 37 +++++
.../src/main/resources/template/html5/radiomap.ftl | 107 +++++++++++++++
.../src/main/resources/template/html5/reset.ftl | 84 ++++++++++++
.../main/resources/template/html5/script-close.ftl | 21 +++
.../src/main/resources/template/html5/script.ftl | 53 ++++++++
.../resources/template/html5/scripting-events.ftl | 64 +++++++++
.../src/main/resources/template/html5/select.ftl | 149 +++++++++++++++++++++
.../main/resources/template/html5/submit-close.ftl | 29 ++++
.../src/main/resources/template/html5/submit.ftl | 94 +++++++++++++
.../src/main/resources/template/html5/text.ftl | 56 ++++++++
.../src/main/resources/template/html5/textarea.ftl | 65 +++++++++
.../src/main/resources/template/html5/token.ftl | 22 +++
.../main/resources/template/html5/updownselect.ftl | 21 +++
.../src/main/webapp/WEB-INF/html5/index.jsp | 69 ++++++++++
45 files changed, 2224 insertions(+)
diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/Html5Action.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/Html5Action.java
new file mode 100644
index 000000000..b80c73d75
--- /dev/null
+++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/Html5Action.java
@@ -0,0 +1,14 @@
+package org.apache.struts2.showcase.action;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+public class Html5Action extends ActionSupport {
+
+ @Override
+ public String execute() throws Exception {
+ addActionError("Action error: only html5");
+ addActionMessage("Action message: only html5");
+ addFieldError("testField","Field error: only html5");
+ return super.execute();
+ }
+}
diff --git a/apps/showcase/src/main/resources/struts.xml b/apps/showcase/src/main/resources/struts.xml
index 1b57083b3..5c1cf37ff 100644
--- a/apps/showcase/src/main/resources/struts.xml
+++ b/apps/showcase/src/main/resources/struts.xml
@@ -160,6 +160,12 @@
</action>
</package>
+ <package name="html5" extends="default" namespace="/html5">
+ <action name="index" class="org.apache.struts2.showcase.action.Html5Action">
+ <result>/WEB-INF/html5/index.jsp</result>
+ </action>
+ </package>
+
</struts>
<!-- END SNIPPET: xworkSample -->
diff --git a/apps/showcase/src/main/resources/template/html5/a-close.ftl b/apps/showcase/src/main/resources/template/html5/a-close.ftl
new file mode 100644
index 000000000..15465dec8
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/a-close.ftl
@@ -0,0 +1,50 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<@compress single_line=true>
+<a
+<#if parameters.id??>
+ id="${parameters.id}"
+</#if>
+<#if parameters.href??>
+ href="${parameters.href?no_esc}"
+</#if>
+<#if parameters.disabled!false>
+ disabled="disabled"
+</#if>
+<#if parameters.tabindex??>
+ tabindex="${parameters.tabindex}"
+</#if>
+<#if parameters.cssClass??>
+ class="${parameters.cssClass}"
+</#if>
+<#if parameters.cssStyle??>
+ style="${parameters.cssStyle}"
+</#if>
+<#if parameters.title??>
+ title="${parameters.title}"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+>${tag.escapeHtmlBody()?then(parameters.body, parameters.body?no_esc)}</a>
+</...@compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/a.ftl b/apps/showcase/src/main/resources/template/html5/a.ftl
new file mode 100644
index 000000000..2ffa2ec5d
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/a.ftl
@@ -0,0 +1,20 @@
+<#--
+/*
+ * 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.
+ */
+-->
\ No newline at end of file
diff --git a/apps/showcase/src/main/resources/template/html5/actionerror.ftl b/apps/showcase/src/main/resources/template/html5/actionerror.ftl
new file mode 100644
index 000000000..e6586adef
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/actionerror.ftl
@@ -0,0 +1,44 @@
+<#ftl strip_whitespace=true strip_text=true/>
+<#--
+/*
+ * 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.
+ */
+-->
+<#if (actionErrors?? && actionErrors?size > 0)>
+ <@compress single_line=true>
+ <ul
+ <#if parameters.id??>
+ id="${parameters.id}"
+ </#if>
+ <#if parameters.cssClass??>
+ class="${parameters.cssClass}"
+ <#else>
+ class="errorMessage"
+ </#if>
+ <#if parameters.cssStyle??>
+ style="${parameters.cssStyle}"
+ </#if>
+ >
+ <#list actionErrors as error>
+ <#if error??><#t/>
+ <li><span><#if parameters.escape>${error!}<#else>${error!?no_esc}</#if></span></li>
+ </#if>
+ </#list>
+ </ul>
+ </...@compress>
+</#if>
diff --git a/apps/showcase/src/main/resources/template/html5/actionmessage.ftl b/apps/showcase/src/main/resources/template/html5/actionmessage.ftl
new file mode 100644
index 000000000..606c460e3
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/actionmessage.ftl
@@ -0,0 +1,44 @@
+<#ftl strip_whitespace=true strip_text=true/>
+<#--
+/*
+ * 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.
+ */
+-->
+<#if (actionMessages?? && actionMessages?size > 0 && !parameters.isEmptyList)>
+ <@compress single_line=true>
+ <ul
+ <#if parameters.id??>
+ id="${parameters.id}"
+ </#if>
+ <#if parameters.cssClass??>
+ class="${parameters.cssClass}"
+ <#else>
+ class="actionMessage"
+ </#if>
+ <#if parameters.cssStyle??>
+ style="${parameters.cssStyle}"
+ </#if>
+ >
+ <#list actionMessages as message>
+ <#if message??><#t/>
+ <li><span><#if parameters.escape>${message!}<#else>${message!?no_esc}</#if></span></li>
+ </#if>
+ </#list>
+ </ul>
+ </...@compress>
+</#if>
diff --git a/apps/showcase/src/main/resources/template/html5/checkbox.ftl b/apps/showcase/src/main/resources/template/html5/checkbox.ftl
new file mode 100644
index 000000000..134f5d280
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/checkbox.ftl
@@ -0,0 +1,52 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+<input type="checkbox" name="${parameters.name}" value="${parameters.fieldValue}"
+<#if parameters.nameValue?? && parameters.nameValue>
+ checked="checked"
+</#if>
+<#if parameters.disabled!false>
+ disabled="disabled"
+</#if>
+<#if parameters.tabindex?has_content>
+ tabindex="${parameters.tabindex}"
+</#if>
+<#if parameters.id?has_content>
+ id="${parameters.id}"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
+<#if parameters.title?has_content>
+ title="${parameters.title}"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+/>
+<#if parameters.submitUnchecked!false>
+<input type="hidden" id="__checkbox_${parameters.id}" name="__checkbox_${parameters.name}" value="${parameters.fieldValue}"
+<#if parameters.disabled!false>
+ disabled="disabled"
+</#if>
+ />
+</#if>
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/checkboxlist.ftl b/apps/showcase/src/main/resources/template/html5/checkboxlist.ftl
new file mode 100644
index 000000000..17745976c
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/checkboxlist.ftl
@@ -0,0 +1,120 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+<#assign itemCount = 0/>
+<#if parameters.list??>
+<@s.iterator value="parameters.list">
+ <#assign itemCount = itemCount + 1/>
+ <#if parameters.listKey??>
+ <#assign itemKey = stack.findValue(parameters.listKey)/>
+ <#assign itemKeyStr = stack.findString(parameters.listKey)/>
+ <#else>
+ <#assign itemKey = stack.findValue('top')/>
+ <#assign itemKeyStr = stack.findString('top')>
+ </#if>
+ <#if parameters.listLabelKey??>
+ <#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale
+ file for it's localized value. This is then used as a label -->
+ <#assign itemValue = struts.getText(stack.findString(parameters.listLabelKey))/>
+ <#elseif parameters.listValue??>
+ <#assign itemValue = stack.findString(parameters.listValue)!""/>
+ <#else>
+ <#assign itemValue = stack.findString('top')/>
+ </#if>
+ <#if parameters.listCssClass??>
+ <#if stack.findString(parameters.listCssClass)??>
+ <#assign itemCssClass= stack.findString(parameters.listCssClass)/>
+ <#else>
+ <#assign itemCssClass = ''/>
+ </#if>
+ </#if>
+ <#if parameters.listCssStyle??>
+ <#if stack.findString(parameters.listCssStyle)??>
+ <#assign itemCssStyle= stack.findString(parameters.listCssStyle)/>
+ <#else>
+ <#assign itemCssStyle = ''/>
+ </#if>
+ </#if>
+ <#if parameters.listTitle??>
+ <#if stack.findString(parameters.listTitle)??>
+ <#assign itemTitle= stack.findString(parameters.listTitle)/>
+ <#else>
+ <#assign itemTitle = ''/>
+ </#if>
+ </#if>
+<input type="checkbox" name="${parameters.name}" value="${itemKeyStr}"
+<#if parameters.id?has_content>
+ id="${parameters.id}-${itemCount}"
+<#else>
+ id="${parameters.name}-${itemCount}"
+</#if>
+<#if tag.contains(parameters.nameValue, itemKey)>
+ checked="checked"
+</#if>
+<#if parameters.disabled!false>
+ disabled="disabled"
+</#if>
+<#if itemCssClass??>
+ class="${itemCssClass}"
+<#else>
+<#if parameters.cssClass?has_content>
+ class="${parameters.cssClass}"
+</#if>
+</#if>
+<#if itemCssStyle??>
+ style="${itemCssStyle}"
+<#else>
+<#if parameters.cssStyle?has_content>
+ style="${parameters.cssStyle}"
+</#if>
+</#if>
+<#if itemTitle??>
+ title="${itemTitle}"
+<#else>
+<#if parameters.title?has_content>
+ title="${parameters.title}"
+</#if>
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+<#global evaluate_dynamic_attributes = true/>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+
+<label
+<#if parameters.id?has_content>
+ for="${parameters.id}-${itemCount}"
+<#else>
+ for="${parameters.name}-${itemCount}"
+</#if>
+ class="checkboxLabel">${itemValue}</label>
+</...@s.iterator>
+<#else>
+</#if>
+<input type="hidden" id="__multiselect_${parameters.id}" name="__multiselect_${parameters.name}"
+ value=""
+<#if parameters.disabled!false>
+ disabled="disabled"
+</#if>
+ />
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/combobox.ftl b/apps/showcase/src/main/resources/template/html5/combobox.ftl
new file mode 100644
index 000000000..3056e0935
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/combobox.ftl
@@ -0,0 +1,102 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<@s.script>
+ function autoPopulate_${parameters.escapedId}(targetElement) {
+ <#if parameters.headerKey?? && parameters.headerValue??>
+ if (targetElement.options[targetElement.selectedIndex].value == '${parameters.headerKey?js_string}') {
+ return;
+ }
+ </#if>
+ <#if parameters.emptyOption!false>
+ if (targetElement.options[targetElement.selectedIndex].value == '') {
+ return;
+ }
+ </#if>
+ targetElement.form.elements['${parameters.name?js_string}'].value=targetElement.options[targetElement.selectedIndex].value;
+ }
+</...@s.script>
+<#include "/${parameters.templateDir}/html5/text.ftl" />
+<#compress>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+ <#if parameters.list??>
+ <select onChange="autoPopulate_${parameters.escapedId}(this);"
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
+ <#if parameters.disabled!false>
+ disabled="disabled"
+ </#if>
+ >
+ <#if (parameters.headerKey?? && parameters.headerValue??)>
+ <option value="${parameters.headerKey}">${parameters.headerValue}</option>
+ </#if>
+ <#if parameters.emptyOption!false>
+ <option value=""></option>
+ </#if>
+ <@s.iterator value="parameters.list">
+ <#if parameters.listKey??>
+ <#assign tmpListKey = stack.findString(parameters.listKey) />
+ <#else>
+ <#assign tmpListKey = stack.findString('top') />
+ </#if>
+ <#if parameters.listValue??>
+ <#assign tmpListValue = stack.findString(parameters.listValue) />
+ <#else>
+ <#assign tmpListValue = stack.findString('top') />
+ </#if>
+ <#if parameters.listCssClass??>
+ <#if stack.findString(parameters.listCssClass)??>
+ <#assign itemCssClass= stack.findString(parameters.listCssClass)/>
+ <#else>
+ <#assign itemCssClass = ''/>
+ </#if>
+ </#if>
+ <#if parameters.listCssStyle??>
+ <#if stack.findString(parameters.listCssStyle)??>
+ <#assign itemCssStyle= stack.findString(parameters.listCssStyle)/>
+ <#else>
+ <#assign itemCssStyle = ''/>
+ </#if>
+ </#if>
+ <#if parameters.listTitle??>
+ <#if stack.findString(parameters.listTitle)??>
+ <#assign itemTitle= stack.findString(parameters.listTitle)/>
+ <#else>
+ <#assign itemTitle = ''/>
+ </#if>
+ </#if>
+ <option value="${tmpListKey}"
+ <#if (parameters.nameValue == tmpListKey)>
+ selected="selected"
+ </#if>
+ <#if itemCssClass??>
+ class="${itemCssClass}"
+ </#if>
+ <#if itemCssStyle??>
+ style="${itemCssStyle}"
+ </#if>
+ <#if itemTitle??>
+ title="${itemTitle}"
+ </#if>
+ >${tmpListValue}</option>
+ </...@s.iterator>
+ </select>
+ </#if>
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/common-attributes.ftl b/apps/showcase/src/main/resources/template/html5/common-attributes.ftl
new file mode 100644
index 000000000..0bfe73fc5
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/common-attributes.ftl
@@ -0,0 +1,25 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#compress>
+<#if parameters.accesskey?has_content>
+ accesskey="${parameters.accesskey}"
+</#if>
+</#compress>
diff --git a/apps/showcase/src/main/resources/template/html5/controlfooter.ftl b/apps/showcase/src/main/resources/template/html5/controlfooter.ftl
new file mode 100644
index 000000000..1626c3cd9
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/controlfooter.ftl
@@ -0,0 +1,20 @@
+<#--
+/*
+ * 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.
+ */
+-->
diff --git a/apps/showcase/src/main/resources/template/html5/controlheader.ftl b/apps/showcase/src/main/resources/template/html5/controlheader.ftl
new file mode 100644
index 000000000..1626c3cd9
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/controlheader.ftl
@@ -0,0 +1,20 @@
+<#--
+/*
+ * 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.
+ */
+-->
diff --git a/apps/showcase/src/main/resources/template/html5/css.ftl b/apps/showcase/src/main/resources/template/html5/css.ftl
new file mode 100644
index 000000000..07220ac9f
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/css.ftl
@@ -0,0 +1,35 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#compress>
+<#assign hasFieldErrors = parameters.name?? && fieldErrors?? && fieldErrors.get(parameters.name)??/>
+<#if parameters.cssClass?has_content && !(hasFieldErrors && parameters.cssErrorClass??)>
+ class="${parameters.cssClass}"
+<#elseif parameters.cssClass?has_content && (hasFieldErrors && parameters.cssErrorClass??)>
+ class="${parameters.cssClass} ${parameters.cssErrorClass}"
+<#elseif !(parameters.cssClass?has_content) && (hasFieldErrors && parameters.cssErrorClass??)>
+ class="${parameters.cssErrorClass}"
+</#if>
+<#if parameters.cssStyle?has_content && !(hasFieldErrors && (parameters.cssErrorStyle?? || parameters.cssErrorClass??))>
+ style="${parameters.cssStyle}"
+<#elseif hasFieldErrors && parameters.cssErrorStyle??>
+ style="${parameters.cssErrorStyle}"
+</#if>
+</#compress>
diff --git a/apps/showcase/src/main/resources/template/html5/datetextfield.ftl b/apps/showcase/src/main/resources/template/html5/datetextfield.ftl
new file mode 100644
index 000000000..25f198f44
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/datetextfield.ftl
@@ -0,0 +1,21 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<div>Tag <pre style="display: inline-block"><s:datetextfield/></pre> works only with the JavaTemplates Plugin!</div>
diff --git a/apps/showcase/src/main/resources/template/html5/debug.ftl b/apps/showcase/src/main/resources/template/html5/debug.ftl
new file mode 100644
index 000000000..889702213
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/debug.ftl
@@ -0,0 +1,92 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<@s.script>
+ function toggleDebug(debugId) {
+ var debugDiv = document.getElementById(debugId);
+ if (debugDiv) {
+ var display = debugDiv.style.display;
+ if (display == 'none') {
+ debugDiv.style.display = 'block';
+ } else if (display == 'block') {
+ debugDiv.style.display = 'none';
+ }
+ }
+ }
+</...@s.script>
+
+<style>
+<!--
+ table.debugTable {border-collapse:collapse; border-spacing:0; background-color:#DDDDDD;}
+ table.debugTable th, table.debugTable td {padding:2px;}
+-->
+</style>
+<br>
+
+<a href="#" id="toggle-button">[Debug]</a>
+<div style="display:none" id="<#if parameters.id??>${parameters.id}<#else>debug</#if>">
+<h2>Struts ValueStack Debug</h2>
+<br>
+
+<h3>Value Stack Contents</h3>
+<table class="debugTable">
+ <tr><th>Object</th><th>Property Name</th><th>Property Value</th><th>Property Class</th></tr>
+
+ <#assign index=1>
+ <#list parameters.stackValues as stackObject>
+ <tr>
+ <td rowspan="${stackObject.value.size()}">${stackObject.key}</td>
+
+ <#assign renderRow=false>
+ <#list stackObject.value.keySet() as propertyName>
+ <#if renderRow==true></tr><tr><#else> <#assign renderRow=false> </#if>
+ <td style="background-color:<#if (index % 2) == 0>#BBBBBB<#else>#CCCCCC</#if>;">${propertyName}</td>
+ <td style="background-color:<#if (index % 2) == 0>#BBBBBB<#else>#CCCCCC</#if>;"><#if stackObject.value.get(propertyName)??>${stackObject.value.get(propertyName).toString()}<#else>null</#if></td>
+ <td style="background-color:<#if (index % 2) == 0>#BBBBBB<#else>#CCCCCC</#if>;"><#if stackObject.value.get(propertyName)??>${stackObject.value.get(propertyName).class}<#else>null</#if></td>
+ </tr>
+ <#assign index= index + 1>
+ </#list>
+ </#list>
+</table>
+<br>
+
+<h3>Stack Context</h3>
+<i>These items are available using the #key notation</i>
+<table class="debugTable">
+ <tr>
+ <th>Key</th><th>Value</th>
+ </tr>
+
+ <#assign index=1>
+ <#list stack.context.keySet() as contextKey>
+ <tr style="background-color:<#if (index % 2) == 0>#BBBBBB<#else>#CCCCCC</#if>;">
+ <td>${contextKey}</td>
+ <td><#if stack.context.get(contextKey)??>${struts.toStringSafe(stack.context.get(contextKey))} (${struts.toStringSafe(stack.context.get(contextKey).class)})<#else>null</#if></td>
+ </tr>
+ <#assign index= index + 1>
+ </#list>
+</table>
+</div>
+<@s.script>
+ document.getElementById('toggle-button').onclick = function() {
+ toggleDebug('<#if parameters.id??>${parameters.id}<#else>debug</#if>');
+ return false;
+ }
+</...@s.script>
diff --git a/apps/showcase/src/main/resources/template/html5/doubleselect.ftl b/apps/showcase/src/main/resources/template/html5/doubleselect.ftl
new file mode 100644
index 000000000..14ff8668c
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/doubleselect.ftl
@@ -0,0 +1,21 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<div>Tag <pre style="display: inline-block"><s:doubleselect/></pre> is not supported in this theme!</div>
diff --git a/apps/showcase/src/main/resources/template/html5/dynamic-attributes.ftl b/apps/showcase/src/main/resources/template/html5/dynamic-attributes.ftl
new file mode 100644
index 000000000..246ec466f
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/dynamic-attributes.ftl
@@ -0,0 +1,45 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#compress>
+<#function acceptKey(key)>
+ <#if dynamic_attributes_ignore??>
+ <#return !key?starts_with(dynamic_attributes_ignore) >
+ <#else>
+ <#return true>
+ </#if>
+</#function>
+<#if (parameters.dynamicAttributes?? && parameters.dynamicAttributes?size > 0)>
+<#assign aKeys = parameters.dynamicAttributes.keySet()>
+<#list aKeys?filter(acceptKey) as aKey>
+<#assign keyValue = parameters.dynamicAttributes.get(aKey)/>
+<#if keyValue?is_string>
+ <#if evaluate_dynamic_attributes!false == true>
+ <#assign value = struts.translateVariables(keyValue)!keyValue/>
+ <#else>
+ <#assign value = keyValue/>
+ </#if>
+<#else>
+ <#assign value = keyValue?string/>
+</#if>
+ ${aKey}="${value}"
+</#list>
+</#if>
+</#compress>
diff --git a/apps/showcase/src/main/resources/template/html5/empty.ftl b/apps/showcase/src/main/resources/template/html5/empty.ftl
new file mode 100644
index 000000000..1626c3cd9
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/empty.ftl
@@ -0,0 +1,20 @@
+<#--
+/*
+ * 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.
+ */
+-->
diff --git a/apps/showcase/src/main/resources/template/html5/fielderror.ftl b/apps/showcase/src/main/resources/template/html5/fielderror.ftl
new file mode 100644
index 000000000..4381fdcd5
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/fielderror.ftl
@@ -0,0 +1,84 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#if fieldErrors??>
+ <#compress>
+ <#assign eKeys = fieldErrors.keySet()>
+ <#assign eKeysSize = eKeys.size()>
+ <#assign doneStartUlTag=false>
+ <#assign doneEndUlTag=false>
+ <#assign haveMatchedErrorField=false>
+ <#if (fieldErrorFieldNames?size > 0) >
+ <#list fieldErrorFieldNames as fieldErrorFieldName>
+ <#list eKeys as eKey>
+ <#if (eKey = fieldErrorFieldName)>
+ <#assign haveMatchedErrorField=true>
+ <#assign eValue = fieldErrors.get(fieldErrorFieldName)>
+ <#if (haveMatchedErrorField && (!doneStartUlTag))>
+ <ul
+ <#if parameters.id?has_content>
+ id="${parameters.id}"
+ </#if>
+ <#if parameters.cssClass?has_content>
+ class="${parameters.cssClass}"
+ <#else>
+ class="errorMessage"
+ </#if>
+ <#if parameters.cssStyle?has_content>
+ style="${parameters.cssStyle}"
+ </#if>
+ >
+ <#assign doneStartUlTag=true>
+ </#if>
+ <#list eValue as eEachValue>
+ <li><span><#if parameters.escape>${eEachValue!}<#else>${eEachValue!?no_esc}</#if></span>
+ </li>
+ </#list>
+ </#if>
+ </#list>
+ </#list>
+ <#if (haveMatchedErrorField && (!doneEndUlTag))>
+ </ul>
+ <#assign doneEndUlTag=true>
+ </#if>
+ <#else>
+ <#if (eKeysSize > 0)>
+ <ul
+ <#if parameters.cssClass?has_content>
+ class="${parameters.cssClass}"
+ <#else>
+ class="errorMessage"
+ </#if>
+ <#if parameters.cssStyle?has_content>
+ style="${parameters.cssStyle}"
+ </#if>
+ >
+ <#list eKeys as eKey>
+ <#assign eValue = fieldErrors.get(eKey)>
+ <#list eValue as eEachValue>
+ <li><span><#if parameters.escape>${eEachValue!}<#else>${eEachValue!?no_esc}</#if></span>
+ </li>
+ </#list>
+ </#list>
+ </ul>
+ </#if>
+ </#if>
+ </#compress>
+</#if>
diff --git a/apps/showcase/src/main/resources/template/html5/file.ftl b/apps/showcase/src/main/resources/template/html5/file.ftl
new file mode 100644
index 000000000..60a486f50
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/file.ftl
@@ -0,0 +1,49 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+<input type="file"
+ name="${(parameters.name!"")}"
+<#if parameters.get("size")?has_content>
+ size="${parameters.get("size")}"
+</#if>
+<#if parameters.disabled!false>
+ disabled="disabled"
+</#if>
+<#if parameters.accept?has_content>
+ accept="${parameters.accept}"
+</#if>
+<#if parameters.tabindex?has_content>
+ tabindex="${parameters.tabindex}"
+</#if>
+<#if parameters.id?has_content>
+ id="${parameters.id}"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
+<#if parameters.title?has_content>
+ title="${parameters.title}"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+/>
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/form-close.ftl b/apps/showcase/src/main/resources/template/html5/form-close.ftl
new file mode 100644
index 000000000..f3aaa7491
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/form-close.ftl
@@ -0,0 +1,22 @@
+<#--
+/*
+ * 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.
+ */
+-->
+</form>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/form.ftl b/apps/showcase/src/main/resources/template/html5/form.ftl
new file mode 100644
index 000000000..f0eaa4342
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/form.ftl
@@ -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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+<#if (parameters.validate!false == false)>
+ <#if parameters.onsubmit?has_content>
+ ${tag.addParameter('onsubmit', "${parameters.onsubmit}") }
+ </#if>
+</#if>
+<form
+<#if parameters.id?has_content>
+ id="${parameters.id}"
+</#if>
+<#if parameters.name?has_content>
+ name="${parameters.name}"
+</#if>
+<#if parameters.onsubmit?has_content>
+ onsubmit="<#outputformat 'JavaScript'>${parameters.onsubmit}</#outputformat>"
+</#if>
+<#if parameters.onreset?has_content>
+ onreset="<#outputformat 'JavaScript'>${parameters.onreset}</#outputformat>"
+</#if>
+<#if parameters.action?has_content>
+ action="${parameters.action}"
+</#if>
+<#if parameters.target?has_content>
+ target="${parameters.target}"
+</#if>
+<#if parameters.method?has_content>
+ method="${parameters.method}"
+<#else>
+ method="post"
+</#if>
+<#if parameters.enctype?has_content>
+ enctype="${parameters.enctype}"
+</#if>
+<#if parameters.cssClass?has_content>
+ class="${parameters.cssClass}"
+</#if>
+<#if parameters.cssStyle?has_content>
+ style="${parameters.cssStyle}"
+</#if>
+<#if parameters.title?has_content>
+ title="${parameters.title}"
+</#if>
+<#if parameters.acceptcharset?has_content>
+ accept-charset="${parameters.acceptcharset}"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+<#if parameters.onreset?has_content>
+ onreset="${parameters.onreset}"
+</#if>
+>
+</#compress>
diff --git a/apps/showcase/src/main/resources/template/html5/head.ftl b/apps/showcase/src/main/resources/template/html5/head.ftl
new file mode 100644
index 000000000..01c5141a9
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/head.ftl
@@ -0,0 +1,23 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<@compress single_line=true>
+<@s.script src="${base}${parameters.staticContentPath}/utils.js" />
+</...@compress>
diff --git a/apps/showcase/src/main/resources/template/html5/hidden.ftl b/apps/showcase/src/main/resources/template/html5/hidden.ftl
new file mode 100644
index 000000000..7e7184953
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/hidden.ftl
@@ -0,0 +1,43 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+<input type="hidden"
+ name="${(parameters.name!"")}"
+<#if parameters.nameValue??>
+ value="<@s.property value="parameters.nameValue"/>"
+</#if>
+<#if parameters.id?has_content>
+ id="${parameters.id}"
+</#if>
+<#if parameters.cssClass?has_content>
+ class="${parameters.cssClass}"
+</#if>
+<#if parameters.cssStyle?has_content>
+ style="${parameters.cssStyle}"
+</#if>
+<#if parameters.disabled!false>
+ disabled="disabled"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+/>
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/inputtransferselect.ftl b/apps/showcase/src/main/resources/template/html5/inputtransferselect.ftl
new file mode 100644
index 000000000..066f9534a
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/inputtransferselect.ftl
@@ -0,0 +1,21 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<div>Tag <pre style="display: inline-block"><s:inputtransferselect/></pre> is not supported in this theme!</div>
\ No newline at end of file
diff --git a/apps/showcase/src/main/resources/template/html5/label.ftl b/apps/showcase/src/main/resources/template/html5/label.ftl
new file mode 100644
index 000000000..730efb048
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/label.ftl
@@ -0,0 +1,42 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+<label
+<#if parameters.id?has_content>
+ id="${parameters.id}"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
+<#if parameters.title?has_content>
+ title="${parameters.title}"
+</#if>
+<#if parameters.for?has_content>
+ for="${parameters.for}"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+>
+<#if parameters.nameValue??>
+<@s.property value="parameters.nameValue"/>
+</#if>
+</label>
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/link.ftl b/apps/showcase/src/main/resources/template/html5/link.ftl
new file mode 100644
index 000000000..891d23763
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/link.ftl
@@ -0,0 +1,74 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<@compress single_line=true>
+ <link
+ <#if parameters.rel?has_content>
+ rel="${parameters.rel}"
+ <#else>
+ rel="stylesheet"
+ </#if>
+ <#if parameters.type?has_content>
+ type="${parameters.type}"
+ <#else>
+ type="text/css"
+ </#if>
+ <#if parameters.href?has_content>
+ href="${parameters.href}"
+ </#if>
+ <#if parameters.hreflang?has_content>
+ hreflang="${parameters.hreflang}"
+ </#if>
+ <#if parameters.disabled?has_content && parameters.disabled == "true">
+ disabled
+ </#if>
+ <#if parameters.media?has_content>
+ media="${parameters.media}"
+ <#else>
+ media="all"
+ </#if>
+ <#if parameters.title?has_content>
+ title="${parameters.title}"
+ </#if>
+ <#if parameters.as?has_content>
+ as="${parameters.as}"
+ </#if>
+ <#if parameters.referrerpolicy?has_content>
+ referrerpolicy="${parameters.referrerpolicy}"
+ </#if>
+ <#if parameters.sizes?has_content>
+ sizes="${parameters.sizes}"
+ </#if>
+ <#if parameters.crossorigin?has_content>
+ crossorigin="${parameters.crossorigin}"
+ </#if>
+ <#if parameters.integrity?has_content>
+ integrity="${parameters.integrity}"
+ </#if>
+ <#if parameters.importance?has_content>
+ importance="${parameters.importance}"
+ </#if>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/nonce.ftl" />
+ />
+</...@compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/nonce.ftl b/apps/showcase/src/main/resources/template/html5/nonce.ftl
new file mode 100644
index 000000000..4e1efe179
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/nonce.ftl
@@ -0,0 +1,25 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#compress>
+<#if parameters.nonce?has_content>
+ nonce="${parameters.nonce}"
+</#if>
+</#compress>
diff --git a/apps/showcase/src/main/resources/template/html5/optgroup.ftl b/apps/showcase/src/main/resources/template/html5/optgroup.ftl
new file mode 100644
index 000000000..8273a5d00
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/optgroup.ftl
@@ -0,0 +1,71 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#if parameters.optGroupInternalListUiBeanList??>
+ <#compress>
+ <#assign optGroupInternalListUiBeans=parameters.optGroupInternalListUiBeanList />
+ <#list optGroupInternalListUiBeans as optGroupInternalListUiBean>
+ <optgroup<#rt>
+ <#if optGroupInternalListUiBean.parameters.label?has_content>
+ label="${optGroupInternalListUiBean.parameters.label}"<#rt>
+ </#if>
+ <#if optGroupInternalListUiBean.parameters.disabled!false>
+ disabled="disabled"<#rt>
+ </#if>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ >
+ <#list optGroupInternalListUiBean.parameters.list as optGroupBean>
+ <#assign trash=stack.push(optGroupBean) />
+ <#assign tmpKey=stack.findValue(optGroupInternalListUiBean.parameters.listKey) />
+ <#assign tmpValue=stack.findValue(optGroupInternalListUiBean.parameters.listValue) />
+ <#assign tmpKeyStr = tmpKey.toString() />
+ <#assign optGroupItemCssClass = ''/>
+ <#if optGroupInternalListUiBean.parameters.listCssClass??>
+ <#assign optGroupItemCssClass= stack.findString(optGroupInternalListUiBean.parameters.listCssClass)!''/>
+ </#if>
+ <#assign optGroupItemCssStyle = ''/>
+ <#if optGroupInternalListUiBean.parameters.listCssStyle??>
+ <#assign optGroupItemCssStyle= stack.findString(optGroupInternalListUiBean.parameters.listCssStyle)!''/>
+ </#if>
+ <#assign optGroupItemTitle = ''/>
+ <#if optGroupInternalListUiBean.parameters.listTitle??>
+ <#assign optGroupItemTitle= stack.findString(optGroupInternalListUiBean.parameters.listTitle)!''/>
+ </#if>
+ <option value="${tmpKeyStr}"<#rt>
+ <#if tag.contains(parameters.nameValue, tmpKey) == true>
+ selected="selected"<#rt>
+ </#if>
+ <#if optGroupItemCssClass?has_content>
+ class="${optGroupItemCssClass}"
+ </#if>
+ <#if optGroupItemCssStyle?has_content>
+ style="${optGroupItemCssStyle}"
+ </#if>
+ <#if optGroupItemTitle?has_content>
+ title="${optGroupItemTitle}"
+ </#if>
+ >${tmpValue}<#t>
+ </option><#lt>
+ <#assign trash=stack.pop() />
+ </#list>
+ </optgroup>
+ </#list>
+ </#compress>
+</#if>
diff --git a/apps/showcase/src/main/resources/template/html5/optiontransferselect.ftl b/apps/showcase/src/main/resources/template/html5/optiontransferselect.ftl
new file mode 100644
index 000000000..f689f195a
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/optiontransferselect.ftl
@@ -0,0 +1,21 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<div>Tag <pre style="display: inline-block"><s:optiontransferselect/></pre> is not supported in this theme!</div>
\ No newline at end of file
diff --git a/apps/showcase/src/main/resources/template/html5/password.ftl b/apps/showcase/src/main/resources/template/html5/password.ftl
new file mode 100644
index 000000000..222aa5947
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/password.ftl
@@ -0,0 +1,55 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+<input type="password"
+ name="${(parameters.name!"")}"
+<#if parameters.get("size")?has_content>
+ size="${parameters.get("size")}"
+</#if>
+<#if parameters.maxlength?has_content>
+ maxlength="${parameters.maxlength}"
+</#if>
+<#if parameters.nameValue?? && parameters.showPassword!false>
+ value="<@s.property value="parameters.nameValue"/>"
+</#if>
+<#if parameters.disabled!false>
+ disabled="disabled"
+</#if>
+<#if parameters.readonly!false>
+ readonly="readonly"
+</#if>
+<#if parameters.tabindex?has_content>
+ tabindex="${parameters.tabindex}"
+</#if>
+<#if parameters.id?has_content>
+ id="${parameters.id}"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
+<#if parameters.title?has_content>
+ title="${parameters.title}"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+/>
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/prefixed-dynamic-attributes.ftl b/apps/showcase/src/main/resources/template/html5/prefixed-dynamic-attributes.ftl
new file mode 100644
index 000000000..ad1dd1cd5
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/prefixed-dynamic-attributes.ftl
@@ -0,0 +1,37 @@
+<#ftl strip_text=true strip_whitespace=true/>
+<#--
+/*
+ * 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.
+ */
+-->
+<#macro prefixedDynamicAttributes prefix>
+<#if (parameters.dynamicAttributes?? && parameters.dynamicAttributes?size > 0)>
+<#assign aKeys = parameters.dynamicAttributes.keySet()>
+<#list aKeys as aKey>
+<#if aKey?starts_with(prefix)>
+<#assign keyValue = parameters.dynamicAttributes.get(aKey)/>
+<#if keyValue?is_string>
+ <#assign value = struts.translateVariables(keyValue)!keyValue/>
+<#else>
+ <#assign value = keyValue?string/>
+</#if>
+ ${aKey?keep_after(prefix)}="${value}"
+</#if>
+</#list>
+</#if>
+</#macro>
diff --git a/apps/showcase/src/main/resources/template/html5/radiomap.ftl b/apps/showcase/src/main/resources/template/html5/radiomap.ftl
new file mode 100644
index 000000000..208f45f1d
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/radiomap.ftl
@@ -0,0 +1,107 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+ <@s.iterator value="parameters.list">
+ <#if parameters.listKey??>
+ <#assign itemKey = stack.findValue(parameters.listKey)/>
+ <#assign itemKeyStr = stack.findString(parameters.listKey)/>
+ <#else>
+ <#assign itemKey = stack.findValue('top')/>
+ <#assign itemKeyStr = stack.findString('top')>
+ </#if>
+ <#if parameters.listValueKey??>
+ <#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale
+ file for it's localized value. This is then used as a label -->
+ <#assign valueKey = stack.findString(parameters.listValueKey)!''/>
+ <#if valueKey?has_content>
+ <#assign itemValue = struts.getText(valueKey) />
+ <#else>
+ <#assign itemValue = parameters.listValueKey />
+ </#if>
+ <#elseif parameters.listValue??>
+ <#assign itemValue = stack.findString(parameters.listValue)/>
+ <#else>
+ <#assign itemValue = stack.findString('top')/>
+ </#if>
+ <#if parameters.listCssClass??>
+ <#if stack.findString(parameters.listCssClass)??>
+ <#assign itemCssClass= stack.findString(parameters.listCssClass)/>
+ <#else>
+ <#assign itemCssClass = ''/>
+ </#if>
+ </#if>
+ <#if parameters.listCssStyle??>
+ <#if stack.findString(parameters.listCssStyle)??>
+ <#assign itemCssStyle= stack.findString(parameters.listCssStyle)/>
+ <#else>
+ <#assign itemCssStyle = ''/>
+ </#if>
+ </#if>
+ <#if parameters.listTitle??>
+ <#if stack.findString(parameters.listTitle)??>
+ <#assign itemTitle= stack.findString(parameters.listTitle)/>
+ <#else>
+ <#assign itemTitle = ''/>
+ </#if>
+ </#if>
+ <input type="radio"
+ <#if parameters.name?has_content>
+ name="${parameters.name?no_esc}"
+ </#if>
+ id="${parameters.id}${itemKeyStr?replace(".", "_")}"
+ <#if tag.contains(parameters.nameValue!'', itemKey)>
+ checked="checked"
+ </#if>
+ <#if itemKey??>
+ value="${itemKeyStr}"
+ </#if>
+ <#if parameters.disabled!false>
+ disabled="disabled"
+ </#if>
+ <#if parameters.tabindex?has_content>
+ tabindex="${parameters.tabindex}"
+ </#if>
+ <#if itemCssClass?has_content>
+ class="${itemCssClass}"
+ </#if>
+ <#if itemCssStyle?has_content>
+ style="${itemCssStyle}"
+ </#if>
+ <#if itemTitle?has_content>
+ title="${itemTitle}"
+ <#else>
+ <#if parameters.title?has_content>
+ title="${parameters.title}"
+ </#if>
+ </#if>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+ <#global evaluate_dynamic_attributes = true/>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ />
+ <label for="${parameters.id}${itemKeyStr?replace(".", "_")}"<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl"/>>
+ ${itemValue}
+ </label>
+ </...@s.iterator>
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/reset.ftl b/apps/showcase/src/main/resources/template/html5/reset.ftl
new file mode 100644
index 000000000..56dc96aa7
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/reset.ftl
@@ -0,0 +1,84 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+ <#if parameters.type?? && parameters.type=="button">
+ <button type="reset"
+ <#if parameters.name?has_content>
+ name="${parameters.name}"
+ </#if>
+ <#if parameters.nameValue??>
+ value="<@s.property value="parameters.nameValue"/>"
+ </#if>
+ <#if parameters.cssClass?has_content>
+ class="${parameters.cssClass}"
+ </#if>
+ <#if parameters.cssStyle?has_content>
+ style="${parameters.cssStyle}"
+ </#if>
+ <#if parameters.disabled!false>
+ disabled="disabled"
+ </#if>
+ <#if parameters.tabindex?has_content>
+ tabindex="${parameters.tabindex}"
+ </#if>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl"/>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ ><#if parameters.src?has_content>
+ <img
+ <#if parameters.label?has_content>
+ alt="${parameters.label}"
+ </#if>
+ <#if parameters.src?has_content>
+ src="${parameters.src}"
+ </#if>
+ /><#else><#if parameters.label?has_content><@s.property value="parameters.label"/></#if></#if></button>
+ <#else>
+ <input type="reset"
+ <#if parameters.name?has_content>
+ name="${parameters.name}"
+ </#if>
+ <#if parameters.nameValue??>
+ value="<@s.property value="parameters.nameValue"/>"
+ </#if>
+ <#if parameters.cssClass?has_content>
+ class="${parameters.cssClass}"
+ </#if>
+ <#if parameters.cssStyle?has_content>
+ style="${parameters.cssStyle}"
+ </#if>
+ <#if parameters.title?has_content>
+ title="${parameters.title}"
+ </#if>
+ <#if parameters.disabled!false>
+ disabled="disabled"
+ </#if>
+ <#if parameters.tabindex?has_content>
+ tabindex="${parameters.tabindex}"
+ </#if>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ />
+ </#if>
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/script-close.ftl b/apps/showcase/src/main/resources/template/html5/script-close.ftl
new file mode 100644
index 000000000..e0f64a41e
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/script-close.ftl
@@ -0,0 +1,21 @@
+<#--
+/*
+ * 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.
+ */
+-->
+</script>
diff --git a/apps/showcase/src/main/resources/template/html5/script.ftl b/apps/showcase/src/main/resources/template/html5/script.ftl
new file mode 100644
index 000000000..b37b0b7c2
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/script.ftl
@@ -0,0 +1,53 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<@compress single_line=true>
+<script
+ <#if parameters.async?has_content && parameters.async == "true">
+ async
+ </#if>
+ <#if parameters.charset?has_content>
+ charset="${parameters.charset}"
+ </#if>
+ <#if parameters.defer?has_content && parameters.defer=="true">
+ defer
+ </#if>
+ <#if parameters.type?has_content>
+ type="${parameters.type}"
+ </#if>
+ <#if parameters.src?has_content>
+ src="${parameters.src}"
+ </#if>
+ <#if parameters.referrerpolicy?has_content>
+ referrerpolicy="${parameters.referrerpolicy}"
+ </#if>
+ <#if parameters.nomodule?has_content && parameters.nomodule=="true">
+ nomodule
+ </#if>
+ <#if parameters.integrity?has_content>
+ integrity="${parameters.integrity}"
+ </#if>
+ <#if parameters.crossorigin?has_content>
+ crossorigin="${parameters.crossorigin}"
+ </#if>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/nonce.ftl" />>
+</...@compress>
diff --git a/apps/showcase/src/main/resources/template/html5/scripting-events.ftl b/apps/showcase/src/main/resources/template/html5/scripting-events.ftl
new file mode 100644
index 000000000..714ae9d56
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/scripting-events.ftl
@@ -0,0 +1,64 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#compress>
+<#if parameters.onclick??>
+ onclick="<#outputformat 'JavaScript'>${parameters.onclick}</#outputformat>"
+</#if>
+<#if parameters.ondblclick??>
+ ondblclick="<#outputformat 'JavaScript'>${parameters.ondblclick}</#outputformat>"
+</#if>
+<#if parameters.onmousedown??>
+ onmousedown="<#outputformat 'JavaScript'>${parameters.onmousedown}</#outputformat>"
+</#if>
+<#if parameters.onmouseup??>
+ onmouseup="<#outputformat 'JavaScript'>${parameters.onmouseup}</#outputformat>"
+</#if>
+<#if parameters.onmouseover??>
+ onmouseover="<#outputformat 'JavaScript'>${parameters.onmouseover}</#outputformat>"
+</#if>
+<#if parameters.onmousemove??>
+ onmousemove="<#outputformat 'JavaScript'>${parameters.onmousemove}</#outputformat>"
+</#if>
+<#if parameters.onmouseout??>
+ onmouseout="<#outputformat 'JavaScript'>${parameters.onmouseout}</#outputformat>"
+</#if>
+<#if parameters.onfocus??>
+ onfocus="<#outputformat 'JavaScript'>${parameters.onfocus}</#outputformat>"
+</#if>
+<#if parameters.onblur??>
+ onblur="<#outputformat 'JavaScript'>${parameters.onblur}</#outputformat>"
+</#if>
+<#if parameters.onkeypress??>
+ onkeypress="<#outputformat 'JavaScript'>${parameters.onkeypress}</#outputformat>"
+</#if>
+<#if parameters.onkeydown??>
+ onkeydown="<#outputformat 'JavaScript'>${parameters.onkeydown}</#outputformat>"
+</#if>
+<#if parameters.onkeyup??>
+ onkeyup="<#outputformat 'JavaScript'>${parameters.onkeyup}</#outputformat>"
+</#if>
+<#if parameters.onselect??>
+ onselect="<#outputformat 'JavaScript'>${parameters.onselect}</#outputformat>"
+</#if>
+<#if parameters.onchange??>
+ onchange="<#outputformat 'JavaScript'>${parameters.onchange}</#outputformat>"
+</#if>
+</#compress>
diff --git a/apps/showcase/src/main/resources/template/html5/select.ftl b/apps/showcase/src/main/resources/template/html5/select.ftl
new file mode 100644
index 000000000..d30b3e1ae
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/select.ftl
@@ -0,0 +1,149 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+ <#setting number_format="#.#####">
+ <select
+ name="${(parameters.name!"")}"
+ <#if parameters.get("size")?has_content>
+ size="${parameters.get("size")}"
+ </#if>
+ <#if parameters.disabled!false>
+ disabled="disabled"
+ </#if>
+ <#if parameters.tabindex?has_content>
+ tabindex="${parameters.tabindex}"
+ </#if>
+ <#if parameters.id?has_content>
+ id="${parameters.id}"
+ </#if>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
+ <#if parameters.title?has_content>
+ title="${parameters.title}"
+ </#if>
+ <#if parameters.multiple!false>
+ multiple="multiple"
+ </#if>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+ >
+ <#if parameters.headerKey?? && parameters.headerValue??>
+ <option value="${parameters.headerKey}"
+ <#if tag.contains(parameters.nameValue, parameters.headerKey) == true>
+ selected="selected"
+ </#if>
+ >${parameters.headerValue}</option>
+ </#if>
+ <#if parameters.emptyOption!false>
+ <option value=""></option>
+ </#if>
+ <@s.iterator value="parameters.list">
+ <#if parameters.listKey??>
+ <#if stack.findValue(parameters.listKey)??>
+ <#assign itemKey = stack.findValue(parameters.listKey)/>
+ <#assign itemKeyStr = stack.findString(parameters.listKey)/>
+ <#else>
+ <#assign itemKey = ''/>
+ <#assign itemKeyStr = ''/>
+ </#if>
+ <#else>
+ <#assign itemKey = stack.findValue('top')/>
+ <#assign itemKeyStr = stack.findString('top')>
+ </#if>
+ <#if parameters.listValueKey??>
+ <#-- checks the valueStack for the 'valueKey.' The valueKey is then looked-up in the locale file for it's
+ localized value. This is then used as a label -->
+ <#assign valueKey = stack.findString(parameters.listValueKey)!'' />
+ <#if valueKey?has_content>
+ <#assign itemValue = struts.getText(valueKey) />
+ <#else>
+ <#assign itemValue = parameters.listValueKey />
+ </#if>
+ <#elseif parameters.listValue??>
+ <#if stack.findString(parameters.listValue)??>
+ <#assign itemValue = stack.findString(parameters.listValue)/>
+ <#else>
+ <#assign itemValue = ''/>
+ </#if>
+ <#else>
+ <#assign itemValue = stack.findString('top')/>
+ </#if>
+ <#if parameters.listCssClass??>
+ <#if stack.findString(parameters.listCssClass)??>
+ <#assign itemCssClass= stack.findString(parameters.listCssClass)/>
+ <#else>
+ <#assign itemCssClass = ''/>
+ </#if>
+ </#if>
+ <#if parameters.listCssStyle??>
+ <#if stack.findString(parameters.listCssStyle)??>
+ <#assign itemCssStyle= stack.findString(parameters.listCssStyle)/>
+ <#else>
+ <#assign itemCssStyle = ''/>
+ </#if>
+ </#if>
+ <#if parameters.listTitle??>
+ <#if stack.findString(parameters.listTitle)??>
+ <#assign itemTitle= stack.findString(parameters.listTitle)/>
+ <#else>
+ <#assign itemTitle = ''/>
+ </#if>
+ </#if>
+ <option value="${itemKeyStr}"
+ <#if tag.contains(parameters.nameValue, itemKey) == true>
+ selected="selected"
+ </#if>
+ <#if itemCssClass?has_content>
+ class="${itemCssClass}"
+ </#if>
+ <#if itemCssStyle?has_content>
+ style="${itemCssStyle}"
+ </#if>
+ <#if itemTitle?has_content>
+ title="${itemTitle}"
+ </#if>
+ >${itemValue}</option>
+ </...@s.iterator>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/optgroup.ftl" />
+ </select>
+
+ <#if parameters.multiple!false>
+ <#if (parameters.id?? && parameters.name??)>
+ <input type="hidden" id="__multiselect_${parameters.id}" name="__multiselect_${parameters.name}" value=""
+ </#if>
+ <#if (parameters.id?? && !parameters.name??)>
+ <input type="hidden" id="__multiselect_${parameters.id}" name="__multiselect_${parameters.id}" value=""
+ </#if>
+ <#if ( !parameters.id?? && parameters.name??)>
+ <input type="hidden" id="__multiselect_${parameters.id}" name="__multiselect_${parameters.id}" value=""
+ </#if>
+ <#if ( !parameters.id?? && !parameters.name??)>
+ <input type="hidden" id="" name="" value=""
+ </#if>
+
+ <#if parameters.disabled!false>
+ disabled="disabled"
+ </#if>
+ />
+ </#if>
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/submit-close.ftl b/apps/showcase/src/main/resources/template/html5/submit-close.ftl
new file mode 100644
index 000000000..1211a060c
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/submit-close.ftl
@@ -0,0 +1,29 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#compress>
+<#if parameters.type?? && parameters.type=="button">
+<#if parameters.body?length gt 0>${tag.escapeHtmlBody()?then(parameters.body, parameters.body?no_esc)}<#elseif parameters.label??><@s.property value="parameters.label"/></#if>
+</button>
+<#else>
+${tag.escapeHtmlBody()?then(parameters.body, parameters.body?no_esc)}
+</#if>
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/submit.ftl b/apps/showcase/src/main/resources/template/html5/submit.ftl
new file mode 100644
index 000000000..e3d60452c
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/submit.ftl
@@ -0,0 +1,94 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+<#if parameters.type?? && parameters.type=="button">
+<button type="submit"
+ <#if parameters.id?has_content>
+ id="${parameters.id}"
+ </#if>
+ <#if parameters.name?has_content>
+ name="${parameters.name}"
+ </#if>
+ <#if parameters.nameValue??>
+ value="<@s.property value="parameters.nameValue"/>"
+ </#if>
+ <#if parameters.disabled!false>
+ disabled="disabled"
+ </#if>
+ <#if parameters.cssClass?has_content>
+ class="${parameters.cssClass}"
+ </#if>
+ <#if parameters.cssStyle?has_content>
+ style="${parameters.cssStyle}"
+ </#if>
+ <#if parameters.title?has_content>
+ title="${parameters.title}"
+ </#if>
+ <#if parameters.tabindex?has_content>
+ tabindex="${parameters.tabindex}"
+ </#if>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl"/>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+>
+<#else>
+<#if parameters.type?? && parameters.type=="image">
+ <input type="image"
+ <#if parameters.label?has_content>
+ alt="${parameters.label}"
+ </#if>
+ <#if parameters.src?has_content>
+ src="${parameters.src}"
+ </#if>
+ <#else>
+ <input type="submit"
+ <#if parameters.nameValue?has_content>
+ value="<@s.property value="parameters.nameValue"/>"
+ </#if>
+ </#if>
+ <#if parameters.id?has_content>
+ id="${parameters.id}"
+ </#if>
+ <#if parameters.name?has_content>
+ name="${parameters.name}"
+ </#if>
+ <#if parameters.disabled!false>
+ disabled="disabled"
+ </#if>
+ <#if parameters.cssClass?has_content>
+ class="${parameters.cssClass}"
+ </#if>
+ <#if parameters.cssStyle?has_content>
+ style="${parameters.cssStyle}"
+ </#if>
+ <#if parameters.title?has_content>
+ title="${parameters.title}"
+ </#if>
+ <#if parameters.tabindex?has_content>
+ tabindex="${parameters.tabindex}"
+ </#if>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+>
+</#if>
+</#compress>
diff --git a/apps/showcase/src/main/resources/template/html5/text.ftl b/apps/showcase/src/main/resources/template/html5/text.ftl
new file mode 100644
index 000000000..53b0535bb
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/text.ftl
@@ -0,0 +1,56 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+<input
+ type="${(parameters.type!"text")}"
+ name="${(parameters.name!"")}"
+<#if parameters.get("size")?has_content>
+ size="${parameters.get("size")}"
+</#if>
+<#if parameters.maxlength?has_content>
+ maxlength="${parameters.maxlength}"
+</#if>
+<#if parameters.nameValue??>
+ value="${parameters.nameValue}"
+</#if>
+<#if parameters.disabled!false>
+ disabled="disabled"
+</#if>
+<#if parameters.readonly!false>
+ readonly="readonly"
+</#if>
+<#if parameters.tabindex?has_content>
+ tabindex="${parameters.tabindex}"
+</#if>
+<#if parameters.id?has_content>
+ id="${parameters.id}"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
+<#if parameters.title?has_content>
+ title="${parameters.title}"
+</#if>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+/>
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/textarea.ftl b/apps/showcase/src/main/resources/template/html5/textarea.ftl
new file mode 100644
index 000000000..4fc24f322
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/textarea.ftl
@@ -0,0 +1,65 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlheader.ftl" />
+<#compress>
+ <textarea
+ name="${(parameters.name!"")}"
+<#if parameters.cols?has_content>
+ cols="${(parameters.cols!"")}"
+</#if>
+ <#if parameters.rows?has_content>
+ rows="${(parameters.rows!"")}"
+ </#if>
+ <#if parameters.wrap?has_content>
+ wrap="${parameters.wrap}"
+ </#if>
+ <#if parameters.disabled!false>
+ disabled="disabled"
+ </#if>
+ <#if parameters.readonly!false>
+ readonly="readonly"
+ </#if>
+ <#if parameters.tabindex?has_content>
+ tabindex="${parameters.tabindex}"
+ </#if>
+ <#if parameters.id?has_content>
+ id="${parameters.id}"
+ </#if>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/css.ftl" />
+ <#if parameters.title?has_content>
+ title="${parameters.title}"
+ </#if>
+ <#if parameters.maxlength?has_content>
+ maxlength="${parameters.maxlength}"
+ </#if>
+ <#if parameters.minlength?has_content>
+ minlength="${parameters.minlength}"
+ </#if>
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/scripting-events.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/common-attributes.ftl" />
+ <#include "/${parameters.templateDir}/${parameters.expandTheme}/dynamic-attributes.ftl" />
+>
+<#if parameters.nameValue??>
+ <@s.property value="parameters.nameValue"/>
+</#if>
+</textarea>
+</#compress>
+<#include "/${parameters.templateDir}/${parameters.expandTheme}/controlfooter.ftl" />
diff --git a/apps/showcase/src/main/resources/template/html5/token.ftl b/apps/showcase/src/main/resources/template/html5/token.ftl
new file mode 100644
index 000000000..d063bbbb5
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/token.ftl
@@ -0,0 +1,22 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<input type="hidden" name="${parameters.tokenNameField!""}" value="${parameters.name!""}" />
+<input type="hidden" name="${parameters.name!""}" value="${parameters.token!""}" />
\ No newline at end of file
diff --git a/apps/showcase/src/main/resources/template/html5/updownselect.ftl b/apps/showcase/src/main/resources/template/html5/updownselect.ftl
new file mode 100644
index 000000000..f159ce896
--- /dev/null
+++ b/apps/showcase/src/main/resources/template/html5/updownselect.ftl
@@ -0,0 +1,21 @@
+<#--
+/*
+ * 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.
+ */
+-->
+<div>Tag <pre style="display: inline-block"><s:updownselect/></pre> is not supported in this theme!</div>
diff --git a/apps/showcase/src/main/webapp/WEB-INF/html5/index.jsp b/apps/showcase/src/main/webapp/WEB-INF/html5/index.jsp
new file mode 100644
index 000000000..fb891a3ba
--- /dev/null
+++ b/apps/showcase/src/main/webapp/WEB-INF/html5/index.jsp
@@ -0,0 +1,69 @@
+<!--
+/*
+* 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.
+*/
+-->
+<%@ taglib prefix="s" uri="/struts-tags" %>
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Struts2 Showcase - Html5 theme</title>
+ <s:url var="bootstrapCss" value="/styles/bootstrap.css" encode="false" includeParams="none"/>
+ <s:link theme="html5" href="%{bootstrapCss}"/>
+ <s:url var="mainCss" value="/styles/main.css" encode="false" includeParams="none"/>
+ <s:link href="%{mainCss}" />
+ <s:head theme="html5"/>
+</head>
+
+<body>
+<div class="container-fluid">
+ <div class="row">
+ <div class="col-md-12">
+ <div class="hero-unit">
+ <h1>Html 5 tags demo</h1>
+ <p>All the tags on this page are from <i>html5</i> theme. <s:a theme="html5" action="showcase" namespace="/">Back</s:a> to main Showcase App page
+ </div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-2">
+ <pre><s:a/></pre>
+ </div>
+ <div class="col-md-10">
+ <s:a theme="html5" action="index">index</s:a>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-2">
+ <pre><s:actionerror/></pre>
+ </div>
+ <div class="col-md-10">
+ <s:actionerror theme="html5"/>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-md-2">
+ <pre><s:actionmessage/></pre>
+ </div>
+ <div class="col-md-10">
+ <s:actionmessage theme="html5"/>
+ </div>
+ </div>
+</div>
+</body>
+</html>
(struts) 03/05: docs: add implementation plan for html5 theme migration
Posted by lu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
lukaszlenart pushed a commit to branch feature/WW-5444-html5
in repository https://gitbox.apache.org/repos/asf/struts.git
commit 065a962ee1ce30047447e16a4927d4cb7ec7139d
Author: Lukasz Lenart <lu...@apache.org>
AuthorDate: Sun Nov 23 18:14:19 2025 +0100
docs: add implementation plan for html5 theme migration
Add detailed implementation plan documenting the migration of html5 theme
from showcase to core, including step-by-step instructions, verification
procedures, and acceptance criteria.
Related to WW-5444
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <no...@anthropic.com>
---
.../2025-11-23-WW-5444-move-html5-theme-to-core.md | 398 +++++++++++++++++++++
1 file changed, 398 insertions(+)
diff --git a/thoughts/shared/plans/2025-11-23-WW-5444-move-html5-theme-to-core.md b/thoughts/shared/plans/2025-11-23-WW-5444-move-html5-theme-to-core.md
new file mode 100644
index 000000000..8f927a326
--- /dev/null
+++ b/thoughts/shared/plans/2025-11-23-WW-5444-move-html5-theme-to-core.md
@@ -0,0 +1,398 @@
+---
+date: 2025-11-23T17:55:00+01:00
+topic: "Move HTML5 Theme from Showcase to Core"
+tags: [plan, html5-theme, WW-5444, theme-migration]
+status: pending
+git_commit: 461c06d0c5afde260fdb0f32038a32f2af5bb42e
+git_branch: feature/WW-5444-html5
+related_research: thoughts/shared/research/2025-11-23-WW-5444-html5-theme-testing.md
+---
+
+# Implementation Plan: Move HTML5 Theme to Core
+
+**Date**: 2025-11-23T17:55:00+01:00
+**Branch**: feature/WW-5444-html5
+**Jira**: [WW-5444](https://issues.apache.org/jira/browse/WW-5444)
+**Related Research**: [HTML5 Theme Testing Approach](../research/2025-11-23-WW-5444-html5-theme-testing.md)
+
+## Objective
+
+Move the html5 theme from `apps/showcase/src/main/resources/template/html5/` to `core/src/main/resources/template/html5/` to make it a production-ready theme shipped with struts2-core.jar, enabling all Struts applications to use it and allowing unit tests to be written in the core module.
+
+## Background
+
+### Current State
+- **Location**: `apps/showcase/src/main/resources/template/html5/`
+- **Templates**: 45 FreeMarker templates (.ftl files)
+- **Status**: Fully functional in showcase but not accessible to other applications
+- **Testing**: No unit tests (can't add them in core while templates are in showcase)
+
+### Why Move to Core?
+1. **Distribution**: Make html5 theme available to all Struts applications via struts2-core.jar
+2. **Testing**: Enable unit tests in `core/src/test/` to validate theme rendering
+3. **Consistency**: Align with other production themes (simple, xhtml, css_xhtml)
+4. **Official Support**: Signal that html5 is a supported, production-ready theme
+
+### Design Decisions
+- **Intentional omissions confirmed**: Missing templates (form-validate.ftl, tooltip.ftl, etc.) are deliberate - html5 uses simpler, modern approach
+- **No theme.properties needed initially**: Can be added later if inheritance is desired
+- **Bootstrap compatible**: Clean markup designed for CSS framework integration
+
+## Implementation Steps
+
+### Phase 1: Create HTML5 Theme Directory in Core
+
+**Action**: Create target directory structure
+
+```bash
+mkdir -p core/src/main/resources/template/html5/
+```
+
+**Verification**: Directory exists and is empty
+
+---
+
+### Phase 2: Move FreeMarker Templates to Core
+
+**Action**: Move all 45 templates from showcase to core
+
+**Source**: `apps/showcase/src/main/resources/template/html5/`
+**Target**: `core/src/main/resources/template/html5/`
+
+**Templates to move** (45 files):
+
+**Form Elements** (12 files):
+- `form.ftl` - Form opening tag with HTML5 attributes
+- `form-close.ftl` - Form closing tag
+- `text.ftl` - Text input field (supports HTML5 types)
+- `textarea.ftl` - Textarea element
+- `password.ftl` - Password input field
+- `checkbox.ftl` - Checkbox input element
+- `checkboxlist.ftl` - List of checkboxes
+- `radiomap.ftl` - Radio button map
+- `select.ftl` - Select/dropdown element
+- `file.ftl` - File upload input
+- `hidden.ftl` - Hidden input field
+- `token.ftl` - CSRF token
+
+**Complex Components** (8 files):
+- `combobox.ftl` - Combo box
+- `doubleselect.ftl` - Double select component
+- `inputtransferselect.ftl` - Input transfer select
+- `optiontransferselect.ftl` - Option transfer select
+- `updownselect.ftl` - Up/down select component
+- `optgroup.ftl` - Option group element
+- `datetextfield.ftl` - Date input field
+
+**Display Components** (4 files):
+- `actionerror.ftl` - Action errors display
+- `actionmessage.ftl` - Action messages display
+- `fielderror.ftl` - Field error display
+- `label.ftl` - Label element
+
+**Navigation** (7 files):
+- `a.ftl` - Anchor element opening
+- `a-close.ftl` - Anchor element closing
+- `link.ftl` - Link element (CSS/stylesheet)
+- `submit.ftl` - Submit button
+- `submit-close.ftl` - Submit button closing
+- `reset.ftl` - Reset button
+
+**Utilities** (6 files):
+- `head.ftl` - HTML head section
+- `script.ftl` - Script opening tag
+- `script-close.ftl` - Script closing tag
+- `debug.ftl` - Debug component
+- `css.ftl` - CSS class/style handling
+- `nonce.ftl` - Nonce attribute for CSP
+
+**Structural** (3 files):
+- `controlheader.ftl` - Control header wrapper (empty by design)
+- `controlfooter.ftl` - Control footer wrapper (empty by design)
+- `empty.ftl` - Empty template
+
+**Attribute Handling** (4 files):
+- `common-attributes.ftl` - Common HTML5 attributes
+- `dynamic-attributes.ftl` - Dynamic attribute handling
+- `prefixed-dynamic-attributes.ftl` - Prefixed dynamic attributes
+- `scripting-events.ftl` - JavaScript event handlers
+
+**Method**:
+```bash
+# Option 1: Git mv (preserves history)
+git mv apps/showcase/src/main/resources/template/html5/*.ftl \
+ core/src/main/resources/template/html5/
+
+# Option 2: Copy then delete (simpler)
+cp -r apps/showcase/src/main/resources/template/html5/*.ftl \
+ core/src/main/resources/template/html5/
+```
+
+**Verification**:
+- All 45 .ftl files exist in `core/src/main/resources/template/html5/`
+- File contents are identical to originals
+
+---
+
+### Phase 3: Create theme.properties (Optional)
+
+**Decision Point**: Does html5 theme need a theme.properties file?
+
+**Option A: No theme.properties** (Recommended initially)
+- html5 is standalone theme like simple
+- No parent theme inheritance needed
+- Simpler to maintain
+
+**Option B: Add theme.properties with parent**
+```properties
+# core/src/main/resources/template/html5/theme.properties
+parent = simple
+```
+- Inherit any missing templates from simple
+- Fallback for future template additions
+
+**Recommendation**: Start without theme.properties, add later if inheritance needed
+
+**Action**: Skip for now (can add in future commit if needed)
+
+---
+
+### Phase 4: Delete HTML5 Templates from Showcase
+
+**Action**: Remove html5 template directory from showcase
+
+```bash
+rm -rf apps/showcase/src/main/resources/template/html5/
+```
+
+**Rationale**:
+- Templates now in core, accessible via classpath
+- Avoid duplication and maintenance issues
+- Showcase will load html5 theme from core
+
+**Verification**:
+- Directory `apps/showcase/src/main/resources/template/html5/` does not exist
+- Showcase can still access html5 theme (from core's classpath)
+
+---
+
+### Phase 5: Verify Showcase Still Works
+
+**Action**: Build and test showcase application
+
+**Build**:
+```bash
+cd apps/showcase
+mvn clean install
+```
+
+**Test**:
+1. Start showcase application
+2. Navigate to: `http://localhost:8080/struts2-showcase/html5/index.action`
+3. Verify page renders correctly with html5 theme
+4. Check that all tags display properly
+5. Verify actionerror/actionmessage display correctly
+
+**Expected Behavior**:
+- Page renders identically to before
+- Templates loaded from core's classpath, not showcase
+- No errors in console
+- All html5 theme tags work
+
+**Verification Checklist**:
+- [ ] Showcase builds successfully
+- [ ] /html5/index.action accessible
+- [ ] Form elements render correctly
+- [ ] Action errors/messages display
+- [ ] Links work (theme="html5" attribute)
+- [ ] No template not found errors
+- [ ] Browser console shows no errors
+
+---
+
+### Phase 6: Run Core Tests
+
+**Action**: Verify existing core tests still pass
+
+```bash
+cd core
+mvn test -DskipAssembly
+```
+
+**Expected Outcome**:
+- All existing tests pass
+- No test failures introduced
+- Build succeeds
+
+**Note**: No new tests added yet (that's Phase 7, separate commit)
+
+**Verification**:
+- [ ] `mvn test` completes successfully
+- [ ] No test failures
+- [ ] Build shows SUCCESS
+
+---
+
+### Phase 7: Update Documentation (Optional)
+
+**Consider updating**:
+- `core/README.md` or docs - mention html5 theme availability
+- Showcase welcome page - explain html5 theme is now in core
+- Migration guide for users
+
+**Action**: Can be done in follow-up commit
+
+---
+
+## Rollback Plan
+
+If issues are encountered:
+
+1. **Revert file moves**:
+ ```bash
+ git checkout apps/showcase/src/main/resources/template/html5/
+ rm -rf core/src/main/resources/template/html5/
+ ```
+
+2. **Rebuild**:
+ ```bash
+ mvn clean install
+ ```
+
+3. **Verify showcase works** with original templates
+
+## Expected Outcomes
+
+### After Successful Move
+
+**Core Module**:
+- ✅ New directory: `core/src/main/resources/template/html5/` with 45 templates
+- ✅ html5 theme packaged in struts2-core.jar
+- ✅ Available to all Struts applications
+- ✅ Ready for unit tests
+
+**Showcase Module**:
+- ✅ No more duplicate templates in `apps/showcase/src/main/resources/template/html5/`
+- ✅ Still works correctly by loading html5 theme from core's classpath
+- ✅ Html5Action and index.jsp unchanged
+
+**Applications Using Struts**:
+- ✅ Can now use html5 theme: `<s:form theme="html5">`
+- ✅ No manual template copying needed
+- ✅ html5 theme available out-of-the-box
+
+## Next Steps (Future Work)
+
+After successful move:
+
+1. **Add Unit Tests** (separate commit)
+ - Add `testGenericHtml5()` to 22 UI tag test classes
+ - See: [Testing Implementation Plan](../research/2025-11-23-WW-5444-html5-theme-testing.md#priority-1-unit-tests-for-generic-properties-high-priority)
+
+2. **Add Integration Tests** (separate commit)
+ - Create `Html5TagExampleTest.java` in showcase
+
+3. **Expand Showcase Demo** (optional)
+ - Add more examples to `/html5/index.jsp`
+ - Demonstrate all html5 theme features
+
+4. **Documentation** (optional)
+ - User guide for html5 theme
+ - Migration guide from xhtml to html5
+
+## Files Changed Summary
+
+### Created
+- `core/src/main/resources/template/html5/*.ftl` (45 files)
+- Optional: `core/src/main/resources/template/html5/theme.properties`
+
+### Deleted
+- `apps/showcase/src/main/resources/template/html5/*.ftl` (45 files)
+
+### Modified
+- None (no code changes needed)
+
+### Unchanged
+- `apps/showcase/src/main/java/org/apache/struts2/showcase/action/Html5Action.java`
+- `apps/showcase/src/main/webapp/WEB-INF/html5/index.jsp`
+- `apps/showcase/src/main/resources/struts.xml`
+
+## Git Commit Plan
+
+**Commit Message**:
+```
+feat(themes): move html5 theme from showcase to core
+
+- Move 45 FreeMarker templates to core/src/main/resources/template/html5/
+- Remove duplicate templates from showcase
+- Makes html5 theme available to all applications via struts2-core.jar
+- Enables unit testing in core module
+
+Resolves WW-5444
+
+🤖 Generated with [Claude Code](https://claude.com/claude-code)
+
+Co-Authored-By: Claude <no...@anthropic.com>
+```
+
+**Branch**: `feature/WW-5444-html5` (current)
+
+**Conventional Commits Type**: `feat` (new feature - production theme availability)
+
+## Risk Assessment
+
+**Low Risk**:
+- No code changes, only file moves
+- Templates already working in showcase
+- Easy to rollback (git revert)
+- No breaking changes to existing code
+
+**Potential Issues**:
+1. **Classpath ordering** - Shouldn't be an issue (core loaded before showcase)
+2. **Build time** - Minimal impact (same number of files, different location)
+3. **Caching** - Maven/IDE may need clean build
+
+**Mitigation**:
+- Test showcase thoroughly after move
+- Run full test suite
+- Clean build if caching issues occur
+
+## Acceptance Criteria
+
+- [ ] All 45 templates exist in `core/src/main/resources/template/html5/`
+- [ ] No templates remain in `apps/showcase/src/main/resources/template/html5/`
+- [ ] Showcase builds successfully
+- [ ] Showcase /html5/index.action renders correctly
+- [ ] Core tests pass (`mvn test -DskipAssembly`)
+- [ ] Full build succeeds (`mvn clean install`)
+- [ ] Git history shows file moves (if using `git mv`)
+
+## Timeline Estimate
+
+**Effort**: 30-60 minutes
+
+- Phase 1: Create directory (1 min)
+- Phase 2: Move templates (5 min)
+- Phase 3: theme.properties decision (skip)
+- Phase 4: Delete from showcase (1 min)
+- Phase 5: Verify showcase (15-20 min)
+- Phase 6: Run core tests (10-15 min)
+- Phase 7: Documentation (optional, later)
+
+**Total**: ~30 minutes of actual work + ~20 minutes of verification/testing
+
+## Dependencies
+
+**None** - This is a standalone change that doesn't depend on other work
+
+## References
+
+- **Research Document**: [HTML5 Theme Testing Approach](../research/2025-11-23-WW-5444-html5-theme-testing.md)
+- **Jira Issue**: [WW-5444 - Implement a new html5 theme](https://issues.apache.org/jira/browse/WW-5444)
+- **Git Branch**: `feature/WW-5444-html5`
+- **Current Commit**: `461c06d0c5afde260fdb0f32038a32f2af5bb42e`
+
+## Status
+
+**Current**: Pending - Awaiting execution
+**Last Updated**: 2025-11-23T17:55:00+01:00
\ No newline at end of file