diff --git a/source/.htaccess b/source/.htaccess
index 41562793b..28cf19561 100644
--- a/source/.htaccess
+++ b/source/.htaccess
@@ -28,6 +28,10 @@ RedirectMatch \/2.*\/(.*)? http://struts.apache.org/$1
# page downloads.html was renamed to releases.html
RedirectMatch \/downloads /releases
+# page pure-java-script-client-side-validation was folded into client-side-validation as a
+# deprecated section, see WW-5694
+RedirectMatch permanent \/core\-developers\/pure\-java\-script\-client\-side\-validation(\.html)?$ /core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated
+
# always points to the most recent announce-YYYY page, no manual update needed
{% assign announcements = site.pages | where_exp: "page", "page.path contains 'announce-'" | sort: "path" -%}
RedirectMatch \/announce.html(#a[0-9]+)? {{ announcements.last.url }}$1
diff --git a/source/core-developers/ajax-client-side-validation.md b/source/core-developers/ajax-client-side-validation.md
index b9e47ed69..2f52ccff5 100644
--- a/source/core-developers/ajax-client-side-validation.md
+++ b/source/core-developers/ajax-client-side-validation.md
@@ -14,8 +14,9 @@ parent:
## Description
-AJAX-based client side validation improves upon [Pure JavaScript Client Side Validation](pure-java-script-client-side-validation)
-by using a combination of JavaScript, DOM manipulation, and remote server communication. Unlike the pure client side
+AJAX-based client side validation improves upon [Pure JavaScript Client Side Validation](client-side-validation#pure-javascript-client-side-validation-deprecated)
+(deprecated since 7.4.0 [WW-5694](https://issues.apache.org/jira/browse/WW-5694), removed in 8.0.0
+[WW-5696](https://issues.apache.org/jira/browse/WW-5696)) by using a combination of JavaScript, DOM manipulation, and remote server communication. Unlike the pure client side
implementation, AJAX-based validation communicates with the server. This means all your validation rules that worked
when submitting a form will still work within the browser.
diff --git a/source/core-developers/client-side-validation.md b/source/core-developers/client-side-validation.md
index 20a8dabad..e3a2949a5 100644
--- a/source/core-developers/client-side-validation.md
+++ b/source/core-developers/client-side-validation.md
@@ -14,57 +14,162 @@ parent:
## Basics
-The framework adds support for client-side validation on top of the standard validation framework.
+Since Struts 7.4.0, the [html5 theme](../tag-developers/html5-theme) can derive HTML5 constraint-validation
+attributes (`required`, `minlength`, `maxlength`, `pattern`, `min`, `max`) directly from a field's
+server-side [validators](validation), so the browser rejects obviously-invalid input before the form is
+even submitted. This replaces the older, generated-JavaScript validator used by the _xhtml theme_ and
+_css_xhtml theme_, which is now deprecated — see [Pure JavaScript Client Side Validation
+(deprecated)](#pure-javascript-client-side-validation-deprecated) below.
-Client-side validation can be enabled on a per-form basis by specifying `validate="true"` in the _form_ tag.
+There is also [AJAX Client Side Validation](ajax-client-side-validation), which runs the full server-side
+validation stack (including visitor validators and `validate()`) over AJAX and is unaffected by any of this.
-```jsp
-
- ...
-
-```
+## HTML5 Constraint Validation
-If a `name` for the form is not given, the action mapping name will be used as the form name. Otherwise, a correct
-`action` and `namespace` attributes must be provided to the `` tag.
+### Enabling it
-## Referencing "submitProfile" in the "/user" namespace
+HTML5 constraint validation is off by default. Turn it on with the `struts.ui.html5.constraints` constant:
-```jsp
-
- ...
-
+```properties
+struts.ui.html5.constraints=true
+```
+
+It only has an effect on fields rendered with the `html5` theme (see [Using the HTML5
+theme](../tag-developers/html5-theme#using-the-html5-theme)). There is no per-form opt-in attribute —
+unlike the deprecated JavaScript validator, this feature does not use ``. Once the
+constant is on and a field's theme is `html5`, its validators are consulted automatically.
+
+> The constant defaults to `false` so existing `html5`-theme forms keep rendering unchanged. The default is
+> expected to flip to `true` in a future major release, tracked by
+> [WW-5696](https://issues.apache.org/jira/browse/WW-5696).
+
+### The governing rule: never false-reject
+
+The mapping is deliberately conservative. A constraint is emitted only when the browser cannot reject
+input the server would have accepted. If the browser rejected something the server allows, the user would
+be stuck with a form that will not submit and no explanation why. Being conservative simply costs a field
+its client-side check — that's a harmless, quiet failure mode, so the mapping always chooses it over the
+alternative.
+
+The clearest consequence of this rule: **Struts never sets or changes an input's `type`.** A field stays
+whatever `type` the developer gave it. In particular:
+
+- Switching a field to `type="number"` would reject a value like `1234,50`, which the framework's
+ locale-aware numeric conversion happily accepts in a comma-decimal locale.
+- The browsers' `email` and `url` input grammars don't match `EmailValidator` and `UrlValidator`.
+
+So `min`/`max` range constraints are only ever added to a control the developer *already* made numeric
+(`type="number"` or `type="range"`) — Struts will never promote a plain text field into one just because
+an `int` or `double` validator is attached to it.
+
+### Mapping table
+
+| Validator | Emits | Condition |
+|---|---|---|
+| `requiredstring` | `required` | on text-entry controls (`text`, `search`, `tel`, `password`, `email`, `url`) and `textarea` |
+| `required` | `required` | only on `radio` and `file` |
+| `stringlength` | `minlength` / `maxlength` | on text-entry or `textarea`, and only if the validator has `trim="false"`; each attribute is added only if actually configured |
+| `regex` | `pattern` | on text-entry controls only, and only if `caseSensitive="true"`, `trim="false"`, the regex is ECMAScript-safe (see below), and the validator is not an `email` or `creditcard` validator (both extend `RegexFieldValidator` but carry grammars the browser does not share) |
+| `int`, `short`, `long` | `min` / `max` | only when the control is already `type="number"` or `type="range"` |
+| `double` | `min` / `max` | same as above; only inclusive bounds are emitted — exclusive bounds have no HTML equivalent and are omitted |
+| `date` | — | nothing yet; temporal `min`/`max` is deferred to a future release |
+| `email`, `url`, `creditcard` | — | never emitted |
+| `fieldexpression`, `expression`, `conversion`, visitor validators | — | never emitted |
+| any validator carrying a message | `data-msg-` | always added, including for validators that emit no constraint attribute at all |
+
+Two of these conditions are easy to miss and sharply limit how often `required`, `minlength`/`maxlength`,
+and `pattern` actually show up:
+
+**`required` is split across two validators, and they don't behave alike.** `requiredstring` fails on
+null, empty, and (by default) blank values, so it is strictly stricter than the browser's `required` — safe
+to emit on any text-entry control. Plain `required`, however, only fails on a null value, an empty array,
+or an empty collection. That means an empty text input (which submits `""`, not nothing), a `select` with
+an empty-valued option, and an **unticked checkbox** (`CheckboxInterceptor` substitutes the parameter
+`"false"` for it) all pass server-side validation while a browser `required` attribute would block them.
+Only `radio` and `file` controls omit their parameter entirely when left empty, so those are the only two
+control types where plain `required` agrees with the server — which is why the table above emits `required`
+for the `required` validator on those two types alone.
+
+**Both `minlength`/`maxlength` and `pattern` need `trim="false"`, which is not the default.** Both
+`StringLengthFieldValidator.trim` and `RegexFieldValidator.trim` default to `true`, so the server measures
+or matches the field's *trimmed* value while the HTML attribute constrains the *raw* one. A `stringlength`
+validator with `maxLength="4"` accepts `"abcd "` — it trims to four characters, which is within the limit —
+but a browser enforcing `maxlength="4"` would stop the user typing the fifth character at all. Likewise, a
+`regex` of `[a-z]+` accepts `"abc "` server-side (it trims to `"abc"` first) while the browser, matching the
+raw value, blocks it. Because of this, `minlength`/`maxlength` and `pattern` are only ever emitted
+for validators explicitly configured with `trim="false"` — which most existing `stringlength` and `regex`
+validators are not. In practice, expect both to show up rarely until applications start setting
+`trim="false"` deliberately for fields where it's safe.
+
+**ECMAScript-safe** means the regex uses only constructs that mean the same thing in Java's regex engine
+and in the browser's: literals, `\d`/`\w` and their negations, character classes without POSIX or Unicode
+property syntax, grouping, alternation, anchors, and bounded quantifiers. Notably, **`\s` and `\S` are
+excluded** — Java's `\s` is ASCII-only by default while ECMAScript's `\s` covers the wider Unicode
+whitespace set, so a pattern like `^\S+$` would accept a value containing a non-breaking space server-side
+and reject it in the browser. Any regex using a construct outside this allowlist simply gets no `pattern`
+attribute at all — it is never rejected loudly, it just quietly doesn't get a client-side check.
+
+### `data-msg-*` attributes
+
+Every validator carrying a message — even one that emits no HTML constraint attribute at all — adds a
+`data-msg-` attribute (for example `data-msg-email`, `data-msg-regex`) holding the
+validator's fully resolved, internationalized message. **Struts ships no JavaScript that reads these.**
+They exist purely as a hook: an application can write its own script to read `data-msg-*` and show
+whichever messages it wants, in whatever way it wants, including for validators (like `email` or
+`creditcard`) that never get a native browser check.
+
+### `requiredLabel` is unrelated to the `required` attribute
+
+This is a common point of confusion: the `requiredLabel` tag attribute only controls whether a visual
+marker (usually `*`) is drawn next to a field's label. It has no connection to the HTML `required`
+attribute described above, and setting `requiredLabel="true"` does not make a field required in the
+browser — the two are decided completely independently.
+
+### Extension point: `HtmlConstraintProvider`
+
+The mapping above is implemented by `StrutsHtmlConstraintProvider`, the default implementation of the
+`HtmlConstraintProvider` interface, registered under the `struts.htmlConstraintProvider` constant:
+
+```properties
+struts.htmlConstraintProvider=struts
```
-Technically, the form's action attribute can refer to a "path" that includes the namespace and action as a URI.
-But, client-side validation **requires** that the action name and namespeact to be set separately.
+An application that wants a less conservative mapping — for example, treating an `email` validator as
+`type="email"`, or emitting `pattern` for case-insensitive regexes by rewriting them — can register its own
+`HtmlConstraintProvider` implementation under this constant instead of the default. This is the escape
+hatch for every limitation described above: the framework's own mapping stays deliberately conservative,
+but nothing stops an application from replacing it with one that fits its own validators and locales.
+
+## Pure JavaScript Client Side Validation (deprecated) {#pure-javascript-client-side-validation-deprecated}
+
+> **Deprecated since Struts 7.4.0 ([WW-5694](https://issues.apache.org/jira/browse/WW-5694)), removed in
+> Struts 8.0.0 ([WW-5696](https://issues.apache.org/jira/browse/WW-5696)).** New applications should use
+> the [html5 theme's constraint validation](#html5-constraint-validation) described above instead.
-## Won't work with client-side validation!
+The `` attribute enables an older client-side validation mechanism, used by the
+_xhtml theme_ and _css_xhtml theme_. It uses 100% client-side JavaScript, generated from the same
+validation configuration used server-side, to try to reject bad input before the form is submitted:
```jsp
-
+
...
-
```
-All the usual [validation configuration](validation) steps apply to client-side validation. Client-side validation
-uses the same validation rules as server-side validation. If server-side validation doesn't work, then client-side
-validation won't work either.
+If a `name` for the form is not given, the action mapping name is used as the form name. Otherwise, a
+correct `action` and `namespace` attribute must be provided to the `` tag — client-side validation
+requires the action name and namespace to be resolvable separately, so a form whose `action` is given as a
+full URI (for example ``) will not get
+client-side validation, even though the form still works.
-## The left hand doesn't know ...
-
-> The required attribute on many _Struts Tags_ is not integrated with client-side validation! The tag attribute is used
-> by certain themes (like xhtml) to put a visual marker (usually '*') next to the field. The tag doesn't know
-> if the validation system actually "requires" the field or not.
+Because the validation logic is repeated in generated JavaScript, only a subset of validators is
+supported (`required`, `requiredstring`, `stringlength`, `regex`, `email`, `url`, `int`, `double`), it is
+not available for visitor validators at all, and — being a separate implementation of each validator's
+logic — some values the JavaScript accepts may still be rejected server-side, or vice versa. This is one of
+the reasons it is being replaced: the html5 theme's constraint validation above is derived directly from
+the real validators, rather than reimplementing them in JavaScript.
## Example
-See [Client Validation example](client-validation-example) for a complete example of client-side validation.
-
-## Client Side Validation Types
-
-There are two styles of client side validation.
-
-|[Pure JavaScript Client Side Validation](pure-java-script-client-side-validation)|Used by the _xhtml theme_ and _css_xhtml theme_|
-|-----------------------------------------------------|--------------------------------------------------|
-|[AJAX Client Side Validation](ajax-client-side-validation)|Use to used by the _ajax theme_ |
+See [Client Validation example](client-validation-example) for a complete, though now-deprecated, example
+of the JavaScript-based client-side validation described above.
diff --git a/source/core-developers/client-validation-example.md b/source/core-developers/client-validation-example.md
index 751e08121..3e3d5573a 100644
--- a/source/core-developers/client-validation-example.md
+++ b/source/core-developers/client-validation-example.md
@@ -8,6 +8,12 @@ parent:
# Client Validation Example
+> **Deprecated since Struts 7.4.0 ([WW-5694](https://issues.apache.org/jira/browse/WW-5694)), removed in
+> Struts 8.0.0 ([WW-5696](https://issues.apache.org/jira/browse/WW-5696)).** This example walks through the
+> generated-JavaScript client-side validator (``) used by the _xhtml theme_ and
+> _css_xhtml theme_. New applications should use the [html5 theme's constraint
+> validation](client-side-validation#html5-constraint-validation) instead.
+
Let's create a Client-Side validation workflow, step by step. The `validate` attribute is set to `true`.
> Note: Some themes do not support client-side validation.
diff --git a/source/core-developers/pure-java-script-client-side-validation.md b/source/core-developers/pure-java-script-client-side-validation.md
deleted file mode 100644
index 43fde3e84..000000000
--- a/source/core-developers/pure-java-script-client-side-validation.md
+++ /dev/null
@@ -1,50 +0,0 @@
----
-layout: default
-title: Pure JavaScript Client Side Validation
-parent:
- title: Client Side Validation
- url: client-side-validation
----
-
-# Pure JavaScript Client Side Validation
-{:.no_toc}
-
-* Will be replaced with the ToC, excluding a header
-{:toc}
-
-## Description
-
-Pure JavaScript client side validation is the simplest but least feature-rich type of [Client Side Validation](client-side-validation).
-This type of validation uses 100% client-side JavaScript code to try to validate the values entered by the user.
-Because the validation logic is actually repeated in the JavaScript code, it is important to understand that
-some values will be considered acceptable by the JavaScript code but will be marked as unacceptable by the server-side [Validation](validation).
-
-Only the following validators are supported:
-
-* required validator
-* requiredstring validator
-* stringlength validator
-* regex validator
-* email validator
-* url validator
-* int validator
-* double validator
-
-> JavaScript client validation is not available for visitor validations.
-
-## Error reporting
-
-Because client side validation does not talk to the server, the theme (_xhtml theme_ or _css_xhtml theme_ ) is responsible
-for properly manipulating the HTML DOM to display the error message inline. The JavaScript that is responsible for doing
-this logic is `validation.js` and can be found in each theme.
-
-> Errors are reported using the default validation message, not the internationalized version that the server-side might
-> be aware of. This is a known issue. You may want to try the [AJAX Client Side Validation](ajax-client-side-validation)
-> for messages that are fully internationalized.
-
-## Additional Validator Support
-
-If you wish to add additional validator support beyond those listed, you may override the _xhtml theme_ template
-`form-close-validate.ftl`. This file contains the JavaScript that tries to validate each user-entered value from within
-the browser. The _css_xhtml theme_ extends the _xhtml theme_ and therefore doesn't have its own `form-close-validate.ftl`
-template.
diff --git a/source/tag-developers/css-xhtml-theme.md b/source/tag-developers/css-xhtml-theme.md
index a6d3e73e0..0cd207e23 100644
--- a/source/tag-developers/css-xhtml-theme.md
+++ b/source/tag-developers/css-xhtml-theme.md
@@ -14,8 +14,10 @@ The _css_xhtml theme_ provides all the basics that the [simple theme](simple-the
[textfield](textfield-tag), [select](select-tag), etc)
- Labels for each of the HTML [Struts Tags](struts-tags), placed according to the CSS stylesheet
- [Validation](../core-developers/validation) and error reporting
-- [Pure JavaScript Client Side Validation](../core-developers/pure-java-script-client-side-validation) using 100%
- JavaScript on the browser
+- [Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
+ using 100% JavaScript on the browser — deprecated since 7.4.0
+ ([WW-5694](https://issues.apache.org/jira/browse/WW-5694)), removed in 8.0.0
+ ([WW-5696](https://issues.apache.org/jira/browse/WW-5696)); use the [html5 theme](html5-theme) instead
## Wrapping the Simple Theme
@@ -69,15 +71,17 @@ The head includes a style sheet. The contents of **styles.css** are:
### Form template
The css_xhtml [form](form-tag) template is almost exactly like the _xhtml form template_ , including support for
-[Pure JavaScript Client Side Validation](../core-developers/pure-java-script-client-side-validation). The difference
-is that instead of printing out an opening and closing `` element, there are no elements. Instead, the CSS rules
-for the individual HTML tags are assumed to handle all display logic. However, as noted, client-side validation is still
-supported.
+[Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
+(deprecated since 7.4.0 [WW-5694](https://issues.apache.org/jira/browse/WW-5694), removed in 8.0.0
+[WW-5696](https://issues.apache.org/jira/browse/WW-5696)). The difference is that instead of printing out an opening and closing
+`` element, there are no elements. Instead, the CSS rules for the individual HTML tags are assumed to handle all
+display logic. However, as noted, client-side validation is still supported.
### css_xhtml form template
The css_xhtml [form](form-tag) template is almost exactly like the _xhtml form template_ , including support for
-[Pure JavaScript Client Side Validation](../core-developers/pure-java-script-client-side-validation). The only
-difference is that instead of printing out an opening and closing `` element, there are no elements. Instead,
-the CSS rules for the individual HTML tags are assumed to handle all display logic. However, as noted, client side
-validation is still supported.
+[Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
+(deprecated since 7.4.0 [WW-5694](https://issues.apache.org/jira/browse/WW-5694), removed in 8.0.0
+[WW-5696](https://issues.apache.org/jira/browse/WW-5696)). The only difference is that instead of printing out an opening and
+closing `` element, there are no elements. Instead, the CSS rules for the individual HTML tags are assumed to
+handle all display logic. However, as noted, client side validation is still supported.
diff --git a/source/tag-developers/form-tag.md b/source/tag-developers/form-tag.md
index 52684722e..c516e3730 100644
--- a/source/tag-developers/form-tag.md
+++ b/source/tag-developers/form-tag.md
@@ -41,3 +41,10 @@ There are two flavours [Client Side Validation](../core-developers/client-side-v
are using (xhtml, ajax, etc). If you are using the [xhtml theme](xhtml-theme) or [css_xhtml theme](css-xhtml-theme),
pure client side validation will be used. Read the [Client Side Validation](../core-developers/client-side-validation)
docs for more information.
+
+> **`validate` is deprecated since Struts 7.4.0 and will be removed in 8.0.0**
+> ([WW-5694](https://issues.apache.org/jira/browse/WW-5694),
+> [WW-5696](https://issues.apache.org/jira/browse/WW-5696)). It only controls the older, generated-JavaScript
+> client-side validator used by the xhtml and css_xhtml themes. It has no effect on the [html5 theme's constraint
+> validation](../core-developers/client-side-validation#html5-constraint-validation), which applications should
+> use instead.
diff --git a/source/tag-developers/xhtml-theme.md b/source/tag-developers/xhtml-theme.md
index feb021489..50297eea9 100644
--- a/source/tag-developers/xhtml-theme.md
+++ b/source/tag-developers/xhtml-theme.md
@@ -19,8 +19,10 @@ The xhtml provides all the basics that the [simple theme](simple-theme) provides
- Labels for each of the HTML [Struts Tags](struts-tags) on the left hand side (or top, depending on
the `labelposition` attribute)
- [Validation](../core-developers/validation) and error reporting
-- [Pure JavaScript Client Side Validation](../core-developers/pure-java-script-client-side-validation) using
- 100% JavaScript on the browser
+- [Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
+ using 100% JavaScript on the browser — deprecated since 7.4.0
+ ([WW-5694](https://issues.apache.org/jira/browse/WW-5694)), removed in 8.0.0
+ ([WW-5696](https://issues.apache.org/jira/browse/WW-5696)); use the [html5 theme](html5-theme) instead
## Wrapping the Simple Theme
@@ -94,7 +96,9 @@ The head template imports a style sheet. The contents of **styles.css** are:
The xhtml form template sets up the wrapping table around all the other form elements. In addition to creating this
wrapping table, the opening and closing templates also, if the `validate` parameter is set to true, enable
-[Pure JavaScript Client Side Validation](../core-developers/pure-java-script-client-side-validation).
+[Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
+(deprecated since 7.4.0 [WW-5694](https://issues.apache.org/jira/browse/WW-5694), removed in 8.0.0
+[WW-5696](https://issues.apache.org/jira/browse/WW-5696)).
{% highlight freemarker %}
{% remote_file_content https://raw.githubusercontent.com/apache/struts/main/core/src/main/resources/template/xhtml/form.ftl %}
@@ -110,7 +114,9 @@ The closing template, `form-close.ftl`:
The xhtml form template sets up the wrapping table around all the other [xhtml theme](xhtml-theme) form elements.
In addition to creating this wrapping table, the opening and closing templates also, if the `validate` parameter is set
-to `true`, enable [Pure JavaScript Client Side Validation](../core-developers/pure-java-script-client-side-validation.htmk).
+to `true`, enable [Pure JavaScript Client Side Validation](../core-developers/client-side-validation#pure-javascript-client-side-validation-deprecated)
+(deprecated since 7.4.0 [WW-5694](https://issues.apache.org/jira/browse/WW-5694), removed in 8.0.0
+[WW-5696](https://issues.apache.org/jira/browse/WW-5696)).
See the **form.ftl** contents: