fix(forms): support reserved control identifiers

Normalize raw Rust identifiers when matching generated form contracts so reserved HTML control names remain usable.

req: form/004
This commit is contained in:
slhx agent
2026-07-16 10:00:43 +02:00
parent a04773d016
commit e7211df4c5
3 changed files with 74 additions and 8 deletions
+15 -6
View File
@@ -1260,13 +1260,16 @@ fn __hemx_attr(tag: &str, attr: &str) -> Option<::std::string::String> {
out.push_str(&format!("handle_form\t{handle_ident}\t{form_ident}\n"));
}
for form in self.forms.values() {
let mut fields = BTreeMap::<&str, (bool, bool)>::new();
for control in &form.controls {
let field = fields.entry(&control.name).or_default();
field.0 |= control.required;
field.1 |= form_control_is_multiple(&control.kind);
}
for (name, (required, multiple)) in fields {
out.push_str(&format!(
"form_field\t{}\t{}\t{}\t{}\n",
form.resource.ident,
control.name,
control.required,
form_control_is_multiple(&control.kind)
"form_field\t{}\t{name}\t{required}\t{multiple}\n",
form.resource.ident
));
}
}
@@ -2594,6 +2597,7 @@ mod tests {
r#"<form data-hemx-handle="save" data-hemx-form="profile">
<input type="hidden" name="__h" value="123">
<input name="title" required>
<template h-if="alternate"><input name="title"></template>
<input name="count" type="number" min="1" max="10" step="1">
<select name="labels" multiple></select>
<input name="avatar" type="file">
@@ -2622,7 +2626,12 @@ mod tests {
let syms = std::fs::read_to_string(out.join("hemx.syms")).unwrap();
assert!(syms.contains("handle_form\tsave\tprofile\n"));
assert!(!syms.contains("form_field\tprofile\t__h\t"));
assert!(syms.contains("form_field\tprofile\ttitle\ttrue\tfalse\n"));
assert_eq!(
syms.matches("form_field\tprofile\ttitle\ttrue\tfalse\n")
.count(),
1,
"conditional controls with one submitted name are one Rust form field"
); // req: form/004 test
assert!(syms.contains("form_field\tprofile\tlabels\tfalse\ttrue\n"));
let _ = std::fs::remove_dir_all(&base);