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 @@ + + + + + + +