Preserve camelCase for known svg elements (#3875)

* Fix SVG element casing to preserve camelCase names

SVG elements like feDropShadow were incorrectly converted to lowercase,
breaking their functionality. Now properly preserves casing for known
SVG elements while normalizing regular HTML elements.

Fixes svg filter rendering issue where filters would not display.

* Preserve camelCase for all elements per worldsender's suggestion

* Remove accidentally committed test files

* add pixel color test

* remove extra comments and screenshot tests for now

* adjust lint warning message

---------

Co-authored-by: Martin Molzer <WorldSEnder@users.noreply.github.com>
This commit is contained in:
Siyuan Yan 2025-10-22 20:44:43 +09:00 committed by GitHub
parent bb031eb68f
commit 0c986740ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 12 additions and 7 deletions

View File

@ -370,17 +370,20 @@ impl ToTokens for HtmlElement {
tokens.extend(match &name {
TagName::Lit(dashedname) => {
let name_span = dashedname.span();
let name = dashedname.to_ascii_lowercase_string();
let name = dashedname.to_string();
let lowercase_name = dashedname.to_ascii_lowercase_string();
if !is_normalised_element_name(&dashedname.to_string()) {
emit_warning!(
name_span.clone(),
format!(
"The tag '{dashedname}' is not matching its normalized form '{name}'. If you want \
to keep this form, change this to a dynamic tag `@{{\"{dashedname}\"}}`."
"The tag '{dashedname}' is not matching its normalized form '{lowercase_name}' \
and is not a recognized SVG or MathML element. If you want to keep this name, \
you can use the dynamic tag `@{{\"{dashedname}\"}}` to silence this warning."
)
)
}
let node = match &*name {
// Use lowercase for compile-time checks but preserve original casing in output
let node = match &*lowercase_name {
"input" => {
let value = value();
let checked = checked();

View File

@ -1,4 +1,4 @@
warning: The tag 'tExTAreA' is not matching its normalized form 'textarea'. If you want to keep this form, change this to a dynamic tag `@{"tExTAreA"}`.
warning: The tag 'tExTAreA' is not matching its normalized form 'textarea' and is not a recognized SVG or MathML element. If you want to keep this name, you can use the dynamic tag `@{"tExTAreA"}` to silence this warning.
--> tests/html_lints/fail.rs:17:10
|
17 | <tExTAreA />

View File

@ -152,8 +152,9 @@ impl VTag {
/// Creates a new [VTag] instance with `tag` name (cannot be changed later in DOM).
pub fn new(tag: impl Into<AttrValue>) -> Self {
let tag = tag.into();
let lowercase_tag = tag.to_ascii_lowercase();
Self::new_base(
match &*tag.to_ascii_lowercase() {
match &*lowercase_tag {
"input" => VTagInner::Input(Default::default()),
"textarea" => VTagInner::Textarea(Default::default()),
_ => VTagInner::Other {
@ -531,7 +532,8 @@ mod feat_ssr {
let _ = w.write_str("</textarea>");
}
VTagInner::Other { tag, children } => {
if !VOID_ELEMENTS.contains(&tag.as_ref()) {
let lowercase_tag = tag.to_ascii_lowercase();
if !VOID_ELEMENTS.contains(&lowercase_tag.as_ref()) {
children
.render_into_stream(w, parent_scope, hydratable, tag.into())
.await;