diff --git a/LibHTML/CSS/StyleResolver.cpp b/LibHTML/CSS/StyleResolver.cpp
index 07e9e636d9..15aef1ba51 100644
--- a/LibHTML/CSS/StyleResolver.cpp
+++ b/LibHTML/CSS/StyleResolver.cpp
@@ -1,5 +1,8 @@
#include
#include
+#include
+#include
+#include
StyleResolver::StyleResolver(Document& document)
: m_document(document)
@@ -10,14 +13,53 @@ StyleResolver::~StyleResolver()
{
}
+static bool matches(const Selector& selector, const Element& element)
+{
+ // FIXME: Support compound selectors.
+ ASSERT(selector.components().size() == 1);
+
+ auto& component = selector.components().first();
+ switch (component.type) {
+ case Selector::Component::Type::Id:
+ return component.value == element.attribute("id");
+ case Selector::Component::Type::Class:
+ return element.has_class(component.value);
+ case Selector::Component::Type::TagName:
+ return component.value == element.tag_name();
+ default:
+ ASSERT_NOT_REACHED();
+ }
+}
+
+NonnullRefPtrVector StyleResolver::collect_matching_rules(const Element& element) const
+{
+ NonnullRefPtrVector matching_rules;
+ for (auto& sheet : m_sheets) {
+ for (auto& rule : sheet.rules()) {
+ for (auto& selector : rule.selectors()) {
+ if (matches(selector, element)) {
+ matching_rules.append(rule);
+ break;
+ }
+ }
+ }
+ }
+ printf("Rules matching Element{%p}\n", &element);
+ for (auto& rule : matching_rules) {
+ dump_rule(rule);
+ }
+ return matching_rules;
+}
+
OwnPtr StyleResolver::resolve_document_style(const Document& document)
{
UNUSED_PARAM(document);
- return nullptr;
+ return make();
}
OwnPtr StyleResolver::resolve_element_style(const Element& element)
{
- UNUSED_PARAM(element);
- return nullptr;
+ auto style = make();
+ auto matching_rules = collect_matching_rules(element);
+ return style;
}
diff --git a/LibHTML/CSS/StyleResolver.h b/LibHTML/CSS/StyleResolver.h
index 2875d81700..a11133e0f9 100644
--- a/LibHTML/CSS/StyleResolver.h
+++ b/LibHTML/CSS/StyleResolver.h
@@ -6,6 +6,7 @@
class Document;
class Element;
+class StyleRule;
class StyleSheet;
class StyleResolver {
@@ -21,6 +22,9 @@ public:
OwnPtr resolve_element_style(const Element&);
OwnPtr resolve_document_style(const Document&);
+ NonnullRefPtrVector collect_matching_rules(const Element&) const;
+
+
private:
Document& m_document;
diff --git a/LibHTML/DOM/Element.cpp b/LibHTML/DOM/Element.cpp
index e291fc3dd0..7808170a60 100644
--- a/LibHTML/DOM/Element.cpp
+++ b/LibHTML/DOM/Element.cpp
@@ -50,6 +50,19 @@ void Element::set_attributes(Vector&& attributes)
m_attributes = move(attributes);
}
+bool Element::has_class(const StringView& class_name) const
+{
+ auto value = attribute("class");
+ if (value.is_empty())
+ return false;
+ auto parts = value.split_view(' ');
+ for (auto& part : parts) {
+ if (part == class_name)
+ return true;
+ }
+ return false;
+}
+
RefPtr Element::create_layout_node()
{
if (m_tag_name == "html")
diff --git a/LibHTML/DOM/Element.h b/LibHTML/DOM/Element.h
index 1331d20c7e..f3133656ca 100644
--- a/LibHTML/DOM/Element.h
+++ b/LibHTML/DOM/Element.h
@@ -40,6 +40,8 @@ public:
callback(attribute.name(), attribute.value());
}
+ bool has_class(const StringView&) const;
+
virtual RefPtr create_layout_node() override;
private:
diff --git a/LibHTML/Dump.cpp b/LibHTML/Dump.cpp
index e9c2a2b313..4d9632509f 100644
--- a/LibHTML/Dump.cpp
+++ b/LibHTML/Dump.cpp
@@ -67,36 +67,41 @@ void dump_tree(const LayoutNode& layout_node)
--indent;
}
+void dump_rule(const StyleRule& rule)
+{
+ printf("Rule:\n");
+ for (auto& selector : rule.selectors()) {
+ printf(" Selector:\n");
+ for (auto& component : selector.components()) {
+ const char* type_description = "Unknown";
+ switch (component.type) {
+ case Selector::Component::Type::Invalid:
+ type_description = "Invalid";
+ break;
+ case Selector::Component::Type::Id:
+ type_description = "Id";
+ break;
+ case Selector::Component::Type::Class:
+ type_description = "Class";
+ break;
+ case Selector::Component::Type::TagName:
+ type_description = "TagName";
+ break;
+ }
+ printf(" %s:%s\n", type_description, component.value.characters());
+ }
+ }
+ printf(" Declarations:\n");
+ for (auto& declaration : rule.declarations()) {
+ printf(" '%s': '%s'\n", declaration.property_name().characters(), declaration.value().to_string().characters());
+ }
+}
+
void dump_sheet(const StyleSheet& sheet)
{
printf("StyleSheet{%p}: %d rule(s)\n", &sheet, sheet.rules().size());
for (auto& rule : sheet.rules()) {
- printf("Rule:\n");
- for (auto& selector : rule.selectors()) {
- printf(" Selector:\n");
- for (auto& component : selector.components()) {
- const char* type_description = "Unknown";
- switch (component.type) {
- case Selector::Component::Type::Invalid:
- type_description = "Invalid";
- break;
- case Selector::Component::Type::Id:
- type_description = "Id";
- break;
- case Selector::Component::Type::Class:
- type_description = "Class";
- break;
- case Selector::Component::Type::TagName:
- type_description = "TagName";
- break;
- }
- printf(" %s:%s", type_description, component.value.characters());
- }
- }
- printf(" Declarations:\n");
- rule.for_each_declaration([](auto& declaration) {
- printf(" '%s': '%s'\n", declaration.property_name().characters(), declaration.value().to_string().characters());
- });
+ dump_rule(rule);
}
}
diff --git a/LibHTML/Dump.h b/LibHTML/Dump.h
index b7049f861a..546e556ba7 100644
--- a/LibHTML/Dump.h
+++ b/LibHTML/Dump.h
@@ -2,8 +2,10 @@
class Node;
class LayoutNode;
+class StyleRule;
class StyleSheet;
void dump_tree(const Node&);
void dump_tree(const LayoutNode&);
void dump_sheet(const StyleSheet&);
+void dump_rule(const StyleRule&);
diff --git a/LibHTML/test.cpp b/LibHTML/test.cpp
index c5ba6d73fd..07eed25dc1 100644
--- a/LibHTML/test.cpp
+++ b/LibHTML/test.cpp
@@ -3,6 +3,7 @@
#include
#include
#include
+#include
#include
#include
@@ -29,6 +30,17 @@ int main(int argc, char** argv)
auto doc_style = resolver.resolve_document_style(*doc);
+ Function resolve_style = [&](const ParentNode& node) {
+ node.for_each_child([&](const Node& child) {
+ if (!child.is_element())
+ return;
+ auto style = resolver.resolve_element_style(static_cast(node));
+ printf("Resolved LayoutStyle{%p} for Element{%p}\n", style.ptr(), &node);
+ resolve_style(static_cast(child));
+ });
+ };
+ resolve_style(*doc);
+
doc->build_layout_tree();
ASSERT(doc->layout_node());