SelectorEngine.cpp 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. #include <LibHTML/CSS/SelectorEngine.h>
  2. #include <LibHTML/DOM/Document.h>
  3. #include <LibHTML/DOM/Element.h>
  4. namespace SelectorEngine {
  5. static bool matches_hover_pseudo_class(const Element& element)
  6. {
  7. auto* hovered_node = element.document().hovered_node();
  8. if (!hovered_node)
  9. return false;
  10. if (&element == hovered_node)
  11. return true;
  12. return element.is_ancestor_of(*hovered_node);
  13. }
  14. bool matches(const Selector::Component& component, const Element& element)
  15. {
  16. switch (component.pseudo_class) {
  17. case Selector::Component::PseudoClass::None:
  18. break;
  19. case Selector::Component::PseudoClass::Link:
  20. ASSERT_NOT_REACHED();
  21. break;
  22. case Selector::Component::PseudoClass::Hover:
  23. if (!matches_hover_pseudo_class(element))
  24. return false;
  25. break;
  26. }
  27. switch (component.type) {
  28. case Selector::Component::Type::Id:
  29. return component.value == element.attribute("id");
  30. case Selector::Component::Type::Class:
  31. return element.has_class(component.value);
  32. case Selector::Component::Type::TagName:
  33. return component.value == element.tag_name();
  34. default:
  35. ASSERT_NOT_REACHED();
  36. }
  37. }
  38. bool matches(const Selector& selector, int component_index, const Element& element)
  39. {
  40. auto& component = selector.components()[component_index];
  41. if (!matches(component, element))
  42. return false;
  43. switch (component.relation) {
  44. case Selector::Component::Relation::None:
  45. return true;
  46. case Selector::Component::Relation::Descendant:
  47. ASSERT(component_index != 0);
  48. for (auto* ancestor = element.parent(); ancestor; ancestor = ancestor->parent()) {
  49. if (!is<Element>(*ancestor))
  50. continue;
  51. if (matches(selector, component_index - 1, to<Element>(*ancestor)))
  52. return true;
  53. }
  54. return false;
  55. case Selector::Component::Relation::ImmediateChild:
  56. ASSERT(component_index != 0);
  57. if (!element.parent() || !is<Element>(*element.parent()))
  58. return false;
  59. return matches(selector, component_index - 1, to<Element>(*element.parent()));
  60. case Selector::Component::Relation::AdjacentSibling:
  61. ASSERT(component_index != 0);
  62. if (auto* sibling = element.previous_element_sibling())
  63. return matches(selector, component_index - 1, *sibling);
  64. return false;
  65. case Selector::Component::Relation::GeneralSibling:
  66. ASSERT(component_index != 0);
  67. for (auto* sibling = element.previous_element_sibling(); sibling; sibling = sibling->previous_element_sibling()) {
  68. if (matches(selector, component_index - 1, *sibling))
  69. return true;
  70. }
  71. return false;
  72. }
  73. ASSERT_NOT_REACHED();
  74. }
  75. bool matches(const Selector& selector, const Element& element)
  76. {
  77. ASSERT(!selector.components().is_empty());
  78. return matches(selector, selector.components().size() - 1, element);
  79. }
  80. }