diff --git a/CLAUDE.md b/CLAUDE.md
index 5f338f789a..a536f59d06 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -165,10 +165,9 @@ When running tests, use this priority order:
### 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
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 0000000000..a4e6b2d7d2
--- /dev/null
+++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/Html5Action.java
@@ -0,0 +1,32 @@
+/*
+ * 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 org.apache.struts2.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 1b57083b33..5c1cf37ff8 100644
--- a/apps/showcase/src/main/resources/struts.xml
+++ b/apps/showcase/src/main/resources/struts.xml
@@ -160,6 +160,12 @@
+
+
+ /WEB-INF/html5/index.jsp
+
+
+
diff --git a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
index b2eeaca629..e5b644ad4b 100644
--- a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
+++ b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
@@ -180,6 +180,9 @@
Component Tag Example
All the tags on this page are from html5 theme. Back to main Showcase App page
+
+
+
+
+
+
<s:a/>
+
+
+ index
+
+
+
+
+
<s:actionerror/>
+
+
+
+
+
+
+
+
<s:actionmessage/>
+
+
+
+
+
+
+
+
<s:fielderror/>
+
+
+
+
+
+
+
+
diff --git a/apps/showcase/src/main/webapp/WEB-INF/sitemesh3.xml b/apps/showcase/src/main/webapp/WEB-INF/sitemesh3.xml
index 88cd74843d..2d1dffb60b 100644
--- a/apps/showcase/src/main/webapp/WEB-INF/sitemesh3.xml
+++ b/apps/showcase/src/main/webapp/WEB-INF/sitemesh3.xml
@@ -27,4 +27,5 @@
+
\ No newline at end of file
diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/Html5TagExampleTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/Html5TagExampleTest.java
new file mode 100644
index 0000000000..10b48b5eb0
--- /dev/null
+++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/Html5TagExampleTest.java
@@ -0,0 +1,183 @@
+/*
+ * 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 it.org.apache.struts2.showcase;
+
+import org.htmlunit.WebClient;
+import org.htmlunit.html.HtmlPage;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Integration tests for HTML5 theme rendering in showcase application.
+ *
+ * Tests validate that the HTML5 theme produces clean, semantic HTML5 markup
+ * without table-based layouts and properly displays action errors, action messages,
+ * and field errors.
+ */
+public class Html5TagExampleTest {
+
+ /**
+ * Tests basic HTML5 theme rendering and page load.
+ *
+ * Verifies:
+ * - Anchor tags are rendered correctly
+ * - Links have proper href attributes
+ * - HTML5 theme attributes are applied
+ */
+ @Test
+ public void testHtml5AnchorTag() throws Exception {
+ try (final WebClient webClient = new WebClient()) {
+ webClient.getOptions().setJavaScriptEnabled(false);
+
+ final HtmlPage page = webClient.getPage(
+ ParameterUtils.getBaseUrl() + "/html5/index.action"
+ );
+
+ String pageContent = page.asNormalizedText();
+
+ // Verify anchor tag content is present
+ Assert.assertTrue("Page should contain 'index' link",
+ pageContent.contains("index"));
+
+ // Verify back link to showcase
+ Assert.assertTrue("Page should contain 'Back' link",
+ pageContent.contains("Back"));
+ }
+ }
+
+ /**
+ * Tests that HTML5 theme components are properly namespaced.
+ *
+ * Verifies:
+ * - HTML5 action is accessible under /html5 namespace
+ * - Theme-specific rendering is applied
+ * - No conflicts with other themes
+ */
+ @Test
+ public void testHtml5Namespace() throws Exception {
+ try (final WebClient webClient = new WebClient()) {
+ webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
+
+ final HtmlPage page = webClient.getPage(
+ ParameterUtils.getBaseUrl() + "/html5/index.action"
+ );
+
+ Assert.assertEquals("HTML5 action should return 200 status",
+ 200, page.getWebResponse().getStatusCode());
+
+ String pageAsXml = page.asXml();
+
+ // Verify the page uses HTML5 theme by checking for theme-specific patterns
+ // HTML5 theme should not use table-based layouts
+ Assert.assertFalse("HTML5 theme should not use table layout for errors",
+ pageAsXml.matches("(?s).*
]*>.*errorMessage.*
.*"));
+ }
+ }
+}
diff --git a/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java b/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java
index 99c1d4797f..faca26e7b2 100644
--- a/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java
+++ b/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java
@@ -127,6 +127,7 @@ public void renderTemplate(TemplateRenderingContext templateContext) throws Exce
model.put("tag", templateContext.getTag());
model.put("themeProperties", getThemeProps(templateContext.getTemplate()));
+
// the BodyContent JSP writer doesn't like it when FM flushes automatically --
// so let's just not do it (it will be flushed eventually anyway)
diff --git a/core/src/main/resources/template/html5/a-close.ftl b/core/src/main/resources/template/html5/a-close.ftl
new file mode 100644
index 0000000000..f7f352c71b
--- /dev/null
+++ b/core/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 "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
+<#compress>
+
+ id="${attributes.id}"
+#if>
+<#if attributes.href??>
+ href="${attributes.href?no_esc}"
+#if>
+<#if attributes.disabled!false>
+ disabled="disabled"
+#if>
+<#if attributes.tabindex??>
+ tabindex="${attributes.tabindex}"
+#if>
+<#if attributes.cssClass??>
+ class="${attributes.cssClass}"
+#if>
+<#if attributes.cssStyle??>
+ style="${attributes.cssStyle}"
+#if>
+<#if attributes.title??>
+ title="${attributes.title}"
+#if>
+<#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)}
+#compress>
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/controlfooter.ftl" />
diff --git a/core/src/main/resources/template/html5/a.ftl b/core/src/main/resources/template/html5/a.ftl
new file mode 100644
index 0000000000..2ffa2ec5d1
--- /dev/null
+++ b/core/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/core/src/main/resources/template/html5/actionerror.ftl b/core/src/main/resources/template/html5/actionerror.ftl
new file mode 100644
index 0000000000..ef2501c053
--- /dev/null
+++ b/core/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.
+ */
+-->
+<#compress>
+ <#if (actionErrors?? && actionErrors?size > 0)>
+
+ #if>
+#compress>
diff --git a/core/src/main/resources/template/html5/actionmessage.ftl b/core/src/main/resources/template/html5/actionmessage.ftl
new file mode 100644
index 0000000000..e9efb58b27
--- /dev/null
+++ b/core/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.
+ */
+-->
+<#compress>
+ <#if (actionMessages?? && actionMessages?size > 0 && !attributes.isEmptyList)>
+
+ #if>
+#compress>
\ No newline at end of file
diff --git a/core/src/main/resources/template/html5/checkbox.ftl b/core/src/main/resources/template/html5/checkbox.ftl
new file mode 100644
index 0000000000..10f5300dd7
--- /dev/null
+++ b/core/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 "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
+<#compress>
+
+ checked="checked"
+#if>
+<#if attributes.disabled!false>
+ disabled="disabled"
+#if>
+<#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
+#if>
+<#if attributes.id?has_content>
+ id="${attributes.id}"
+#if>
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl" />
+<#if attributes.title?has_content>
+ title="${attributes.title}"
+#if>
+<#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.submitUnchecked!false>
+
+ disabled="disabled"
+#if>
+ />
+#if>
+#compress>
+<#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
new file mode 100644
index 0000000000..a55732a82b
--- /dev/null
+++ b/core/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 "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
+<#compress>
+<#assign itemCount = 0/>
+<#if attributes.list??>
+<@s.iterator value="attributes.list">
+ <#assign itemCount = itemCount + 1/>
+ <#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 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(attributes.listLabelKey))/>
+ <#elseif attributes.listValue??>
+ <#assign itemValue = stack.findString(attributes.listValue)!""/>
+ <#else>
+ <#assign itemValue = stack.findString('top')/>
+ #if>
+ <#if attributes.listCssClass??>
+ <#if stack.findString(attributes.listCssClass)??>
+ <#assign itemCssClass= stack.findString(attributes.listCssClass)/>
+ <#else>
+ <#assign itemCssClass = ''/>
+ #if>
+ #if>
+ <#if attributes.listCssStyle??>
+ <#if stack.findString(attributes.listCssStyle)??>
+ <#assign itemCssStyle= stack.findString(attributes.listCssStyle)/>
+ <#else>
+ <#assign itemCssStyle = ''/>
+ #if>
+ #if>
+ <#if attributes.listTitle??>
+ <#if stack.findString(attributes.listTitle)??>
+ <#assign itemTitle= stack.findString(attributes.listTitle)/>
+ <#else>
+ <#assign itemTitle = ''/>
+ #if>
+ #if>
+
+ id="${attributes.id}-${itemCount}"
+<#else>
+ id="${attributes.name}-${itemCount}"
+#if>
+<#if tag.contains(attributes.nameValue, itemKey)>
+ checked="checked"
+#if>
+<#if attributes.disabled!false>
+ disabled="disabled"
+#if>
+<#if itemCssClass??>
+ class="${itemCssClass}"
+<#else>
+<#if attributes.cssClass?has_content>
+ class="${attributes.cssClass}"
+#if>
+#if>
+<#if itemCssStyle??>
+ style="${itemCssStyle}"
+<#else>
+<#if attributes.cssStyle?has_content>
+ style="${attributes.cssStyle}"
+#if>
+#if>
+<#if itemTitle??>
+ title="${itemTitle}"
+<#else>
+<#if attributes.title?has_content>
+ title="${attributes.title}"
+#if>
+#if>
+<#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 "/${attributes.templateDir}/${attributes.expandTheme}/dynamic-attributes.ftl" />
+
+
+@s.iterator>
+<#else>
+#if>
+
+ disabled="disabled"
+#if>
+ />
+#compress>
+<#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
new file mode 100644
index 0000000000..2e950c49c0
--- /dev/null
+++ b/core/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_${attributes.escapedId}(targetElement) {
+ <#if attributes.headerKey?? && attributes.headerValue??>
+ if (targetElement.options[targetElement.selectedIndex].value == '${attributes.headerKey?js_string}') {
+ return;
+ }
+ #if>
+ <#if attributes.emptyOption!false>
+ if (targetElement.options[targetElement.selectedIndex].value == '') {
+ return;
+ }
+ #if>
+ targetElement.form.elements['${attributes.name?js_string}'].value=targetElement.options[targetElement.selectedIndex].value;
+ }
+@s.script>
+<#include "/${attributes.templateDir}/html5/text.ftl" />
+<#compress>
+ <#include "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
+ <#if attributes.list??>
+
+ <#if attributes.disabled!false>
+ disabled="disabled"
+ #if>
+ >
+ <#if (attributes.headerKey?? && attributes.headerValue??)>
+
+ #if>
+ <#if attributes.emptyOption!false>
+
+ #if>
+ <@s.iterator value="attributes.list">
+ <#if attributes.listKey??>
+ <#assign tmpListKey = stack.findString(attributes.listKey) />
+ <#else>
+ <#assign tmpListKey = stack.findString('top') />
+ #if>
+ <#if attributes.listValue??>
+ <#assign tmpListValue = stack.findString(attributes.listValue) />
+ <#else>
+ <#assign tmpListValue = stack.findString('top') />
+ #if>
+ <#if attributes.listCssClass??>
+ <#if stack.findString(attributes.listCssClass)??>
+ <#assign itemCssClass= stack.findString(attributes.listCssClass)/>
+ <#else>
+ <#assign itemCssClass = ''/>
+ #if>
+ #if>
+ <#if attributes.listCssStyle??>
+ <#if stack.findString(attributes.listCssStyle)??>
+ <#assign itemCssStyle= stack.findString(attributes.listCssStyle)/>
+ <#else>
+ <#assign itemCssStyle = ''/>
+ #if>
+ #if>
+ <#if attributes.listTitle??>
+ <#if stack.findString(attributes.listTitle)??>
+ <#assign itemTitle= stack.findString(attributes.listTitle)/>
+ <#else>
+ <#assign itemTitle = ''/>
+ #if>
+ #if>
+
+ @s.iterator>
+
+ #if>
+#compress>
+<#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
new file mode 100644
index 0000000000..bd81fcb15a
--- /dev/null
+++ b/core/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 attributes.accesskey?has_content>
+ accesskey="${attributes.accesskey}"
+#if>
+#compress>
diff --git a/core/src/main/resources/template/html5/controlfooter.ftl b/core/src/main/resources/template/html5/controlfooter.ftl
new file mode 100644
index 0000000000..1626c3cd92
--- /dev/null
+++ b/core/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/core/src/main/resources/template/html5/controlheader.ftl b/core/src/main/resources/template/html5/controlheader.ftl
new file mode 100644
index 0000000000..1626c3cd92
--- /dev/null
+++ b/core/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/core/src/main/resources/template/html5/css.ftl b/core/src/main/resources/template/html5/css.ftl
new file mode 100644
index 0000000000..00ea4b9fc9
--- /dev/null
+++ b/core/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 = 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 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/datetextfield.ftl b/core/src/main/resources/template/html5/datetextfield.ftl
new file mode 100644
index 0000000000..25f198f447
--- /dev/null
+++ b/core/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.
+ */
+-->
+
Tag
<s:datetextfield/>
works only with the JavaTemplates Plugin!
diff --git a/core/src/main/resources/template/html5/debug.ftl b/core/src/main/resources/template/html5/debug.ftl
new file mode 100644
index 0000000000..fef4f6fa5c
--- /dev/null
+++ b/core/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>
+
+
+
+
+[Debug]
+
+
Struts ValueStack Debug
+
+
+
Value Stack Contents
+
+
Object
Property Name
Property Value
Property Class
+
+ <#assign index=1>
+ <#list attributes.stackValues as stackObject>
+
+<@s.script>
+ document.getElementById('toggle-button').onclick = function() {
+ toggleDebug('<#if attributes.id??>${attributes.id}<#else>debug#if>');
+ return false;
+ }
+@s.script>
diff --git a/core/src/main/resources/template/html5/doubleselect.ftl b/core/src/main/resources/template/html5/doubleselect.ftl
new file mode 100644
index 0000000000..14ff8668c7
--- /dev/null
+++ b/core/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.
+ */
+-->
+
Tag
<s:doubleselect/>
is not supported in this theme!
diff --git a/core/src/main/resources/template/html5/dynamic-attributes.ftl b/core/src/main/resources/template/html5/dynamic-attributes.ftl
new file mode 100644
index 0000000000..64ea3dfa61
--- /dev/null
+++ b/core/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 (attributes.dynamicAttributes?? && attributes.dynamicAttributes?size > 0)>
+<#assign aKeys = attributes.dynamicAttributes.keySet()>
+<#list aKeys?filter(acceptKey) as aKey>
+<#assign keyValue = attributes.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/core/src/main/resources/template/html5/empty.ftl b/core/src/main/resources/template/html5/empty.ftl
new file mode 100644
index 0000000000..1626c3cd92
--- /dev/null
+++ b/core/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/core/src/main/resources/template/html5/fielderror.ftl b/core/src/main/resources/template/html5/fielderror.ftl
new file mode 100644
index 0000000000..7bc1be01bd
--- /dev/null
+++ b/core/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.
+ */
+-->
+<#compress>
+ <#if fieldErrors??>
+ <#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))>
+
+ #if>
+ #if>
+ #if>
+#compress>
diff --git a/core/src/main/resources/template/html5/file.ftl b/core/src/main/resources/template/html5/file.ftl
new file mode 100644
index 0000000000..386ae0fa2b
--- /dev/null
+++ b/core/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 "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
+<#compress>
+
+ size="${attributes.get("size")}"
+#if>
+<#if attributes.disabled!false>
+ disabled="disabled"
+#if>
+<#if attributes.accept?has_content>
+ accept="${attributes.accept}"
+#if>
+<#if attributes.tabindex?has_content>
+ tabindex="${attributes.tabindex}"
+#if>
+<#if attributes.id?has_content>
+ id="${attributes.id}"
+#if>
+<#include "/${attributes.templateDir}/${attributes.expandTheme}/css.ftl" />
+<#if attributes.title?has_content>
+ title="${attributes.title}"
+#if>
+<#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 "/${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
new file mode 100644
index 0000000000..b170ba2941
--- /dev/null
+++ b/core/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.
+ */
+-->
+
+<#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
new file mode 100644
index 0000000000..b7c74c5d3b
--- /dev/null
+++ b/core/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 "/${attributes.templateDir}/${attributes.expandTheme}/controlheader.ftl" />
+<#compress>
+<#if (attributes.validate!false == false)>
+ <#if attributes.onsubmit?has_content>
+ ${tag.addParameter('onsubmit', "${attributes.onsubmit}") }
+ #if>
+#if>
+