Allow custom element names in HTML tag syntax (#6676)

Co-authored-by: Laurenz <laurmaedje@gmail.com>
This commit is contained in:
枚鴉 2025-08-01 21:57:07 +09:00 committed by GitHub
parent cd1a786539
commit b825df6bbc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 77 additions and 2 deletions

View File

@ -105,8 +105,53 @@ impl HtmlTag {
bail!("tag name must not be empty");
}
if let Some(c) = string.chars().find(|&c| !charsets::is_valid_in_tag_name(c)) {
bail!("the character {} is not valid in a tag name", c.repr());
let mut has_hyphen = false;
let mut has_uppercase = false;
for c in string.chars() {
if c == '-' {
has_hyphen = true;
} else if !charsets::is_valid_in_tag_name(c) {
bail!("the character {} is not valid in a tag name", c.repr());
} else {
has_uppercase |= c.is_ascii_uppercase();
}
}
// If we encounter a hyphen, we are dealing with a custom element rather
// than a standard HTML element.
//
// A valid custom element name must:
// - Contain at least one hyphen (U+002D)
// - Start with an ASCII lowercase letter (a-z)
// - Not contain any ASCII uppercase letters (A-Z)
// - Not be one of the reserved names
// - Only contain valid characters (ASCII alphanumeric and hyphens)
//
// See https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
if has_hyphen {
if !string.starts_with(|c: char| c.is_ascii_lowercase()) {
bail!("custom element name must start with a lowercase letter");
}
if has_uppercase {
bail!("custom element name must not contain uppercase letters");
}
// These names are used in SVG and MathML. Since `html.elem` only
// supports creation of _HTML_ elements, they are forbidden.
if matches!(
string,
"annotation-xml"
| "color-profile"
| "font-face"
| "font-face-src"
| "font-face-uri"
| "font-face-format"
| "font-face-name"
| "missing-glyph"
) {
bail!("name is reserved and not valid for a custom element");
}
}
Ok(Self(PicoStr::intern(string)))

View File

@ -0,0 +1,8 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body><my-element>Hi</my-element><custom-button>Hi</custom-button><multi-word-component>Hi</multi-word-component><element->Hi</element-></body>
</html>

View File

@ -13,3 +13,25 @@ Text
val
})
#metadata("Hi") <l>
--- html-elem-custom html ---
#html.elem("my-element")[Hi]
#html.elem("custom-button")[Hi]
#html.elem("multi-word-component")[Hi]
#html.elem("element-")[Hi]
--- html-elem-invalid ---
// Error: 12-24 the character "@" is not valid in a tag name
#html.elem("my@element")
--- html-elem-custom-bad-start html ---
// Error: 12-22 custom element name must start with a lowercase letter
#html.elem("1-custom")
--- html-elem-custom-uppercase html ---
// Error: 12-21 custom element name must not contain uppercase letters
#html.elem("my-ELEM")
--- html-elem-custom-reserved html ---
// Error: 12-28 name is reserved and not valid for a custom element
#html.elem("annotation-xml")