mirror of
https://github.com/RGBCube/serenity
synced 2025-07-26 00:57:36 +00:00
LibHTML: Implement matching for descendant selectors
The CSS engine now correctly matches selectors like "#foo #bar #baz".
This commit is contained in:
parent
b587eb2f4d
commit
156b35742a
3 changed files with 60 additions and 5 deletions
32
Base/home/anon/www/selectors.html
Normal file
32
Base/home/anon/www/selectors.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Selector test</title>
|
||||||
|
<style>
|
||||||
|
#foo #bar #baz {
|
||||||
|
background-color: #00ff00;
|
||||||
|
}
|
||||||
|
.abc .def div {
|
||||||
|
background-color: #ffffff;
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1;
|
||||||
|
border-color: #00ff00;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="foo">
|
||||||
|
<div id="bar">
|
||||||
|
<div id="baz">
|
||||||
|
I should have a green background.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="abc">
|
||||||
|
<div class="def">
|
||||||
|
<div>hello</div>
|
||||||
|
<div>hello</div>
|
||||||
|
<div>hello</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -21,6 +21,7 @@ h1 {
|
||||||
<li><a href="lorem.html">lorem ipsum</a></li>
|
<li><a href="lorem.html">lorem ipsum</a></li>
|
||||||
<li><a href="phint.html">presentational hints</a></li>
|
<li><a href="phint.html">presentational hints</a></li>
|
||||||
<li><a href="images.html">images</a></li>
|
<li><a href="images.html">images</a></li>
|
||||||
|
<li><a href="selectors.html">selectors</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -15,12 +15,8 @@ StyleResolver::~StyleResolver()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool matches(const Selector& selector, const Element& element)
|
static bool matches(const Selector::Component& component, const Element& element)
|
||||||
{
|
{
|
||||||
// FIXME: Support compound selectors.
|
|
||||||
ASSERT(selector.components().size() == 1);
|
|
||||||
|
|
||||||
auto& component = selector.components().first();
|
|
||||||
switch (component.type) {
|
switch (component.type) {
|
||||||
case Selector::Component::Type::Id:
|
case Selector::Component::Type::Id:
|
||||||
return component.value == element.attribute("id");
|
return component.value == element.attribute("id");
|
||||||
|
@ -33,6 +29,32 @@ static bool matches(const Selector& selector, const Element& element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool matches(const Selector& selector, int component_index, const Element& element)
|
||||||
|
{
|
||||||
|
auto& component = selector.components()[component_index];
|
||||||
|
if (!matches(component, element))
|
||||||
|
return false;
|
||||||
|
if (component.relation == Selector::Component::Relation::None)
|
||||||
|
return true;
|
||||||
|
if (component.relation == Selector::Component::Relation::Descendant) {
|
||||||
|
ASSERT(component_index != 0);
|
||||||
|
for (auto* ancestor = element.parent(); ancestor; ancestor = ancestor->parent()) {
|
||||||
|
if (!ancestor->is_element())
|
||||||
|
continue;
|
||||||
|
if (matches(selector, component_index - 1, static_cast<const Element&>(*ancestor)))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool matches(const Selector& selector, const Element& element)
|
||||||
|
{
|
||||||
|
ASSERT(!selector.components().is_empty());
|
||||||
|
return matches(selector, selector.components().size() - 1, element);
|
||||||
|
}
|
||||||
|
|
||||||
static StyleSheet& default_stylesheet()
|
static StyleSheet& default_stylesheet()
|
||||||
{
|
{
|
||||||
static StyleSheet* sheet;
|
static StyleSheet* sheet;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue