Преглед на файлове

LibWeb: Support the :last-of-type CSS selector :^)

Andreas Kling преди 4 години
родител
ревизия
1d065aa51b

+ 12 - 0
Base/res/html/misc/last-of-type.html

@@ -0,0 +1,12 @@
+<style>
+article :last-of-type {
+  background-color: orange;
+}
+</style>
+<article>
+  <div>This `div` is first.</div>
+  <div>This <span>nested `span` is last</span>!</div>
+  <div>This <em>nested `em` is first</em>, but this <em>nested `em` is last</em>!</div>
+  <b>This `b` qualifies!</b>
+  <div>This is the final `div`!</div>
+</article>

+ 1 - 0
Base/res/html/misc/welcome.html

@@ -38,6 +38,7 @@ span#loadtime {
     <p>This page loaded in <b><span id="loadtime"></span></b> ms</p>
     <p>Some small test pages:</p>
     <ul>
+        <li><a href="last-of-type.html">CSS :last-of-type selector</a></li>
         <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>

+ 2 - 0
Userland/Libraries/LibWeb/CSS/Parser/DeprecatedCSSParser.cpp

@@ -556,6 +556,8 @@ public:
                 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("last-of-type")) {
+                simple_selector.pseudo_class = CSS::Selector::SimpleSelector::PseudoClass::LastOfType;
             } 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")) {

+ 1 - 0
Userland/Libraries/LibWeb/CSS/Selector.h

@@ -55,6 +55,7 @@ public:
             Empty,
             Root,
             FirstOfType,
+            LastOfType,
         };
         PseudoClass pseudo_class { PseudoClass::None };
 

+ 6 - 0
Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp

@@ -96,6 +96,12 @@ static bool matches(const CSS::Selector::SimpleSelector& component, const DOM::E
                 return false;
         }
         break;
+    case CSS::Selector::SimpleSelector::PseudoClass::LastOfType:
+        for (auto* sibling = element.next_element_sibling(); sibling; sibling = sibling->next_element_sibling()) {
+            if (sibling->tag_name() == element.tag_name())
+                return false;
+        }
+        break;
     }
 
     switch (component.attribute_match_type) {

+ 3 - 0
Userland/Libraries/LibWeb/Dump.cpp

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