1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 21:08:12 +00:00

LibWeb: Add basic support for :lang() CSS selector

This doesn't have parsing support for multiple languages in the same
selector. Support for language subcodes is not great either. But it
does do the basics.
This commit is contained in:
Andreas Kling 2022-03-20 12:39:11 +01:00
parent 5d672717aa
commit bdd42c9b0e
4 changed files with 52 additions and 1 deletions

View file

@ -16,6 +16,34 @@
namespace Web::SelectorEngine {
// https://drafts.csswg.org/selectors-4/#the-lang-pseudo
static inline bool matches_lang_pseudo_class(DOM::Element const& element, Vector<FlyString> const& languages)
{
FlyString element_language;
for (auto const* e = &element; e; e = e->parent_element()) {
auto lang = e->attribute(HTML::AttributeNames::lang);
if (!lang.is_null()) {
element_language = lang;
break;
}
}
if (element_language.is_null())
return false;
// FIXME: This is ad-hoc. Implement a proper language range matching algorithm as recommended by BCP47.
for (auto const& language : languages) {
if (language.is_empty())
return false;
if (language == "*"sv)
return true;
if (!element_language.view().contains('-'))
return element_language.equals_ignoring_case(language);
auto parts = element_language.view().split_view('-');
return parts[0].equals_ignoring_case(language);
}
return false;
}
static inline bool matches_hover_pseudo_class(DOM::Element const& element)
{
auto* hovered_node = element.document().hovered_node();
@ -140,6 +168,8 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla
return !next_sibling_with_same_tag_name(element);
case CSS::Selector::SimpleSelector::PseudoClass::Type::OnlyOfType:
return !previous_sibling_with_same_tag_name(element) && !next_sibling_with_same_tag_name(element);
case CSS::Selector::SimpleSelector::PseudoClass::Type::Lang:
return matches_lang_pseudo_class(element, pseudo_class.languages);
case CSS::Selector::SimpleSelector::PseudoClass::Type::Disabled:
if (!element.tag_name().equals_ignoring_case(HTML::TagNames::input))
return false;