Skip to content

Commit

Permalink
LibWeb: Support the :first-of-type CSS selector :^)
Browse files Browse the repository at this point in the history
  • Loading branch information
awesomekling committed Apr 6, 2021
1 parent 4f69040 commit 0eb9a9d
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 0 deletions.
13 changes: 13 additions & 0 deletions Base/res/html/misc/first-of-type.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<style>
article :first-of-type {
background-color:pink;
}
</style>
<article>
<div>This `div is first!</div>
<div>This <span>nested `span` is first</span>!</div>
<div>This <em> nested `em` is first</em>, but this <em>nested `em` is last</em>!</div>
<div>This <span>nested `span` gets styled</span>!</div>
<b>This `b` qualifies!</b>
<div>This is the final `div`.</div>
</article>
1 change: 1 addition & 0 deletions Base/res/html/misc/welcome.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ <h1>Welcome to the Serenity Browser!</h1>
<p>This page loaded in <b><span id="loadtime"></span></b> ms</p>
<p>Some small test pages:</p>
<ul>
<li><a href="first-of-type.html">CSS :first-of-type selector</a></li>
<li><a href="background-repeat-test.html">background image with repetition rules</a></li>
<li><a href="link-over-zindex-block.html">link elements with background box placed with z-index</a></li>
<li><a href="contenteditable.html">contenteditable</a></li>
Expand Down
2 changes: 2 additions & 0 deletions Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,8 @@ class CSSParser {
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Empty;
} else if (pseudo_name.equals_ignoring_case("root")) {
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::Root;
} else if (pseudo_name.equals_ignoring_case("first-of-type")) {
simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::FirstOfType;
} else if (pseudo_name.equals_ignoring_case("before")) {
simple_selector.pseudo_element = CSS::Selector::SimpleSelector::PseudoElement::Before;
} else if (pseudo_name.equals_ignoring_case("after")) {
Expand Down
1 change: 1 addition & 0 deletions Userland/Libraries/LibWeb/CSS/Selector.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class Selector {
OnlyChild,
Empty,
Root,
FirstOfType,
};
PseudoClass pseudo_class { PseudoClass::None };

Expand Down
6 changes: 6 additions & 0 deletions Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ static bool matches(const CSS::Selector::SimpleSelector& component, const DOM::E
if (!is<HTML::HTMLElement>(element))
return false;
break;
case CSS::Selector::SimpleSelector::PseudoClass::FirstOfType:
for (auto* sibling = element.previous_element_sibling(); sibling; sibling = sibling->previous_element_sibling()) {
if (sibling->tag_name() == element.tag_name())
return false;
}
break;
}

switch (component.attribute_match_type) {
Expand Down
3 changes: 3 additions & 0 deletions Userland/Libraries/LibWeb/Dump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,9 @@ void dump_selector(StringBuilder& builder, const CSS::Selector& selector)
case CSS::Selector::SimpleSelector::PseudoClass::Root:
pseudo_class_description = "Root";
break;
case CSS::Selector::SimpleSelector::PseudoClass::FirstOfType:
pseudo_class_description = "FirstOfType";
break;
case CSS::Selector::SimpleSelector::PseudoClass::Focus:
pseudo_class_description = "Focus";
break;
Expand Down

0 comments on commit 0eb9a9d

Please sign in to comment.