1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 17:17:42 +00:00

LibWeb: Implement :nth-last-child pseudo-class

This commit is contained in:
miere43 2021-05-11 17:13:57 +03:00 committed by Linus Groh
parent e87eaa3991
commit c4bd4cbd76
4 changed files with 15 additions and 3 deletions

View file

@ -566,6 +566,9 @@ public:
} else if (pseudo_name.starts_with("nth-child", CaseSensitivity::CaseInsensitive)) { } else if (pseudo_name.starts_with("nth-child", CaseSensitivity::CaseInsensitive)) {
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::NthChild; simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::NthChild;
simple_selector.nth_child_pattern = CSS::Selector::SimpleSelector::NthChildPattern::parse(capture_selector_args(pseudo_name)); simple_selector.nth_child_pattern = CSS::Selector::SimpleSelector::NthChildPattern::parse(capture_selector_args(pseudo_name));
} else if (pseudo_name.starts_with("nth-last-child", CaseSensitivity::CaseInsensitive)) {
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::NthLastChild;
simple_selector.nth_child_pattern = CSS::Selector::SimpleSelector::NthChildPattern::parse(capture_selector_args(pseudo_name));
} else if (pseudo_name.equals_ignoring_case("before")) { } else if (pseudo_name.equals_ignoring_case("before")) {
simple_selector.pseudo_element = CSS::Selector::SimpleSelector::PseudoElement::Before; simple_selector.pseudo_element = CSS::Selector::SimpleSelector::PseudoElement::Before;
} else if (pseudo_name.equals_ignoring_case("after")) { } else if (pseudo_name.equals_ignoring_case("after")) {

View file

@ -37,6 +37,7 @@ public:
FirstOfType, FirstOfType,
LastOfType, LastOfType,
NthChild, NthChild,
NthLastChild,
}; };
PseudoClass pseudo_class { PseudoClass::None }; PseudoClass pseudo_class { PseudoClass::None };
@ -69,7 +70,7 @@ public:
}; };
// FIXME: We don't need this field on every single SimpleSelector, but it's also annoying to malloc it somewhere. // FIXME: We don't need this field on every single SimpleSelector, but it's also annoying to malloc it somewhere.
// Only used when "pseudo_class" == PseudoClass::NthChild. // Only used when "pseudo_class" is "NthChild" or "NthLastChild".
NthChildPattern nth_child_pattern; NthChildPattern nth_child_pattern;
}; };

View file

@ -83,6 +83,7 @@ static bool matches(const CSS::Selector::SimpleSelector& component, const DOM::E
} }
break; break;
case CSS::Selector::SimpleSelector::PseudoClass::NthChild: case CSS::Selector::SimpleSelector::PseudoClass::NthChild:
case CSS::Selector::SimpleSelector::PseudoClass::NthLastChild:
const auto step_size = component.nth_child_pattern.step_size; const auto step_size = component.nth_child_pattern.step_size;
const auto offset = component.nth_child_pattern.offset; const auto offset = component.nth_child_pattern.offset;
if (step_size == 0 && offset == 0) if (step_size == 0 && offset == 0)
@ -93,8 +94,12 @@ static bool matches(const CSS::Selector::SimpleSelector& component, const DOM::E
return false; return false;
int index = 1; int index = 1;
for (auto* child = parent->first_child_of_type<DOM::Element>(); child && child != &element; child = child->next_element_sibling()) { if (component.pseudo_class == CSS::Selector::SimpleSelector::PseudoClass::NthChild) {
++index; for (auto* child = parent->first_child_of_type<DOM::Element>(); child && child != &element; child = child->next_element_sibling())
++index;
} else {
for (auto* child = parent->last_child_of_type<DOM::Element>(); child && child != &element; child = child->previous_element_sibling())
++index;
} }
if (step_size < 0) { if (step_size < 0) {

View file

@ -354,6 +354,9 @@ void dump_selector(StringBuilder& builder, const CSS::Selector& selector)
case CSS::Selector::SimpleSelector::PseudoClass::NthChild: case CSS::Selector::SimpleSelector::PseudoClass::NthChild:
pseudo_class_description = "NthChild"; pseudo_class_description = "NthChild";
break; break;
case CSS::Selector::SimpleSelector::PseudoClass::NthLastChild:
pseudo_class_description = "NthLastChild";
break;
case CSS::Selector::SimpleSelector::PseudoClass::Focus: case CSS::Selector::SimpleSelector::PseudoClass::Focus:
pseudo_class_description = "Focus"; pseudo_class_description = "Focus";
break; break;