diff --git a/Libraries/LibWeb/HTML/CustomElements/CustomElementName.cpp b/Libraries/LibWeb/HTML/CustomElements/CustomElementName.cpp
index 340fc51f3f1..ad6464839ae 100644
--- a/Libraries/LibWeb/HTML/CustomElements/CustomElementName.cpp
+++ b/Libraries/LibWeb/HTML/CustomElements/CustomElementName.cpp
@@ -1,42 +1,53 @@
/*
* Copyright (c) 2023, Srikavin Ramkumar
+ * Copyright (c) 2025, Sam Atkins
*
* SPDX-License-Identifier: BSD-2-Clause
*/
-#include
#include
+#include
#include
namespace Web::HTML {
-// https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-core-concepts:prod-pcenchar
-static bool is_pcen_char(u32 code_point)
-{
- return code_point == '-'
- || code_point == '.'
- || (code_point >= '0' && code_point <= '9')
- || code_point == '_'
- || (code_point >= 'a' && code_point <= 'z')
- || code_point == 0xb7
- || (code_point >= 0xc0 && code_point <= 0xd6)
- || (code_point >= 0xd8 && code_point <= 0xf6)
- || (code_point >= 0xf8 && code_point <= 0x37d)
- || (code_point >= 0x37f && code_point <= 0x1fff)
- || (code_point >= 0x200c && code_point <= 0x200d)
- || (code_point >= 0x203f && code_point <= 0x2040)
- || (code_point >= 0x2070 && code_point <= 0x218f)
- || (code_point >= 0x2c00 && code_point <= 0x2fef)
- || (code_point >= 0x3001 && code_point <= 0xD7ff)
- || (code_point >= 0xf900 && code_point <= 0xfdcf)
- || (code_point >= 0xfdf0 && code_point <= 0xfffd)
- || (code_point >= 0x10000 && code_point <= 0xeffff);
-}
-
// https://html.spec.whatwg.org/multipage/custom-elements.html#valid-custom-element-name
-bool is_valid_custom_element_name(StringView name)
+bool is_valid_custom_element_name(String const& name)
{
- // name must not be any of the following:
+ // A string name is a valid custom element name if all of the following are true:
+ // - name is a valid element local name;
+ if (!DOM::is_valid_element_local_name(name))
+ return false;
+
+ // - name's 0th code point is an ASCII lower alpha;
+ auto code_points = Utf8View { name };
+ if (auto first = code_points.begin(); first.done() || !is_ascii_lower_alpha(*first))
+ return false;
+
+ // - name does not contain any ASCII upper alphas;
+ // - name contains a U+002D (-); and
+ bool contains_ascii_upper_alpha = false;
+ bool contains_hyphen = false;
+ for (auto code_point : code_points) {
+ if (is_ascii_upper_alpha(code_point)) {
+ contains_ascii_upper_alpha = true;
+ break;
+ }
+ if (code_point == '-')
+ contains_hyphen = true;
+ }
+ if (contains_ascii_upper_alpha || !contains_hyphen)
+ return false;
+
+ // - name is not one of the following:
+ // - "annotation-xml"
+ // - "color-profile"
+ // - "font-face"
+ // - "font-face-src"
+ // - "font-face-uri"
+ // - "font-face-format"
+ // - "font-face-name"
+ // - "missing-glyph"
if (name.is_one_of(
"annotation-xml"sv,
"color-profile"sv,
@@ -49,28 +60,7 @@ bool is_valid_custom_element_name(StringView name)
return false;
}
- // name must match the PotentialCustomElementName production:
- // PotentialCustomElementName ::=
- // [a-z] (PCENChar)* '-' (PCENChar)*
-
- auto code_points = Utf8View { name };
- auto it = code_points.begin();
-
- if (code_points.is_empty() || *it < 'a' || *it > 'z')
- return false;
-
- ++it;
-
- bool found_hyphen = false;
-
- for (; it != code_points.end(); ++it) {
- if (!is_pcen_char(*it))
- return false;
- if (*it == '-')
- found_hyphen = true;
- }
-
- return found_hyphen;
+ return true;
}
}
diff --git a/Libraries/LibWeb/HTML/CustomElements/CustomElementName.h b/Libraries/LibWeb/HTML/CustomElements/CustomElementName.h
index b16ea325cdd..a8090565452 100644
--- a/Libraries/LibWeb/HTML/CustomElements/CustomElementName.h
+++ b/Libraries/LibWeb/HTML/CustomElements/CustomElementName.h
@@ -1,15 +1,21 @@
/*
* Copyright (c) 2023, Srikavin Ramkumar
+ * Copyright (c) 2025, Sam Atkins
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
-#include
+#include
namespace Web::HTML {
-bool is_valid_custom_element_name(StringView name);
+bool is_valid_custom_element_name(String const& name);
+
+inline bool is_valid_custom_element_name(FlyString const& name)
+{
+ return is_valid_custom_element_name(name.to_string());
+}
}
diff --git a/Tests/LibWeb/Text/expected/wpt-import/custom-elements/registries/valid-custom-element-names.txt b/Tests/LibWeb/Text/expected/wpt-import/custom-elements/registries/valid-custom-element-names.txt
new file mode 100644
index 00000000000..4dc28b04921
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/wpt-import/custom-elements/registries/valid-custom-element-names.txt
@@ -0,0 +1,6 @@
+Harness status: OK
+
+Found 1 tests
+
+1 Pass
+Pass valid-custom-element-names
\ No newline at end of file
diff --git a/Tests/LibWeb/Text/input/wpt-import/custom-elements/registries/valid-custom-element-names.html b/Tests/LibWeb/Text/input/wpt-import/custom-elements/registries/valid-custom-element-names.html
new file mode 100644
index 00000000000..4bd33c79099
--- /dev/null
+++ b/Tests/LibWeb/Text/input/wpt-import/custom-elements/registries/valid-custom-element-names.html
@@ -0,0 +1,138 @@
+
+
+
+
+
+
+