Skip to content

Commit 0510a89

Browse files
committed
vaev-engine: Refactor (first/last)-child pseudo classes to use nth-child pseudo class engine.
1 parent 1ba0b16 commit 0510a89

File tree

2 files changed

+61
-62
lines changed

2 files changed

+61
-62
lines changed

src/vaev-engine/style/matcher.cpp

Lines changed: 12 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -224,8 +224,12 @@ static bool _matchLink(Gc::Ref<Dom::Element> el) {
224224

225225
// 14.3.1. :nth-child() pseudo-class
226226
// 14.3.2. :nth-last-child() pseudo-class
227+
// 14.3.3. :first-child pseudo-class
228+
// 14.3.4. :last-child pseudo-class
227229
// https://www.w3.org/TR/selectors-4/#the-nth-child-pseudo
228230
// https://www.w3.org/TR/selectors-4/#the-nth-last-child-pseudo
231+
// https://www.w3.org/TR/selectors-4/#the-first-child-pseudo
232+
// https://www.w3.org/TR/selectors-4/#the-last-child-pseudo
229233
static bool _matchNthChild(Gc::Ref<Dom::Element> e, Pseudo::AnBofS const& anbOfS, bool isLast) {
230234
auto [anb, ofS] = anbOfS;
231235
if (ofS) {
@@ -247,36 +251,14 @@ static bool _matchNthChild(Gc::Ref<Dom::Element> e, Pseudo::AnBofS const& anbOfS
247251
}
248252
}
249253

250-
// 14.3.3. :first-child pseudo-class
251-
// https://www.w3.org/TR/selectors-4/#the-first-child-pseudo
252-
static bool _matchFirstChild(Gc::Ref<Dom::Element> e) {
253-
Gc::Ptr<Dom::Node> curr = e;
254-
while (curr->hasPreviousSibling()) {
255-
auto prev = curr->previousSibling();
256-
if (auto el = prev->is<Dom::Element>())
257-
return false;
258-
curr = prev;
259-
}
260-
return true;
261-
}
262-
263-
// 14.3.4. :last-child pseudo-class
264-
// https://www.w3.org/TR/selectors-4/#the-last-child-pseudo
265-
static bool _matchLastChild(Gc::Ref<Dom::Element> e) {
266-
Gc::Ptr<Dom::Node> curr = e;
267-
while (curr->hasNextSibling()) {
268-
auto next = curr->nextSibling();
269-
if (auto el = next->is<Dom::Element>())
270-
return false;
271-
curr = next;
272-
}
273-
return true;
274-
}
275-
276254
// 14.4.1. :nth-of-type pseudo-class
277255
// 14.4.2. :nth-last-of-type pseudo-class
256+
// 14.4.3. :first-of-type pseudo-class
257+
// 14.4.4. :last-of-type pseudo-class
278258
// https://www.w3.org/TR/selectors-4/#the-nth-of-type-pseudo
279259
// https://www.w3.org/TR/selectors-4/#the-nth-last-of-type-pseudo
260+
// https://www.w3.org/TR/selectors-4/#the-first-of-type-pseudo
261+
// https://www.w3.org/TR/selectors-4/#the-last-of-type-pseudo
280262
static bool _matchNthOfType(Gc::Ref<Dom::Element> e, AnB const& anb, bool isLast) {
281263
Gc::Ptr<Dom::Node> curr = e;
282264
auto name = e->qualifiedName;
@@ -290,38 +272,6 @@ static bool _matchNthOfType(Gc::Ref<Dom::Element> e, AnB const& anb, bool isLast
290272
return anb.match(index + 1);
291273
}
292274

293-
// 14.4.3. :first-of-type pseudo-class
294-
// https://www.w3.org/TR/selectors-4/#the-first-of-type-pseudo
295-
static bool _matchFirstOfType(Gc::Ref<Dom::Element> e) {
296-
Gc::Ptr<Dom::Node> curr = e;
297-
auto name = e->qualifiedName;
298-
299-
while (curr->hasPreviousSibling()) {
300-
auto prev = curr->previousSibling();
301-
if (auto el = prev->is<Dom::Element>())
302-
if (e->qualifiedName == name)
303-
return false;
304-
curr = prev;
305-
}
306-
return true;
307-
}
308-
309-
// 14.4.4. :last-of-type pseudo-class
310-
// https://www.w3.org/TR/selectors-4/#the-last-of-type-pseudo
311-
static bool _matchLastOfType(Gc::Ref<Dom::Element> e) {
312-
Gc::Ptr<Dom::Node> curr = e;
313-
auto name = e->qualifiedName;
314-
315-
while (curr->hasNextSibling()) {
316-
auto prev = curr->nextSibling();
317-
if (auto el = prev->is<Dom::Element>())
318-
if (e->qualifiedName == name)
319-
return false;
320-
curr = prev;
321-
}
322-
return true;
323-
}
324-
325275
static bool _match(Pseudo const& s, Gc::Ref<Dom::Element> el) {
326276
switch (s.type) {
327277
case Pseudo::LINK:
@@ -331,16 +281,16 @@ static bool _match(Pseudo const& s, Gc::Ref<Dom::Element> el) {
331281
return el->qualifiedName == Html::HTML_TAG;
332282

333283
case Pseudo::FIRST_OF_TYPE:
334-
return _matchFirstOfType(el);
284+
return _matchNthOfType(el, AnB{0, 1}, false);
335285

336286
case Pseudo::LAST_OF_TYPE:
337-
return _matchLastOfType(el);
287+
return _matchNthOfType(el, AnB{0, 1}, true);
338288

339289
case Pseudo::FIRST_CHILD:
340-
return _matchFirstChild(el);
290+
return _matchNthChild(el, Pseudo::AnBofS{AnB{0, 1}, NONE}, false);
341291

342292
case Pseudo::LAST_CHILD:
343-
return _matchLastChild(el);
293+
return _matchNthChild(el, Pseudo::AnBofS{AnB{0, 1}, NONE}, true);
344294

345295
case Pseudo::NTH_CHILD:
346296
return _matchNthChild(el, s.extra.unwrap<Pseudo::AnBofS>("unexpected missing AnB"), false);

tests/css/selectors.xhtml

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,18 @@
225225
</style>
226226
</rendering>
227227

228+
<rendering>
229+
<div class="stripe-4 red"></div>
230+
<div class="stripe-4 green"></div>
231+
<div class="stripe-4 green"></div>
232+
<div class="stripe-4 green"></div>
233+
<style>
234+
div:first-child {
235+
background-color: green !important;
236+
}
237+
</style>
238+
</rendering>
239+
228240
<rendering>
229241
<style>
230242
:nth-last-child(odd of .stripe-4) {
@@ -237,6 +249,18 @@
237249
<div class="stripe-4 red"></div>
238250
</rendering>
239251

252+
<rendering>
253+
<style>
254+
div:last-child {
255+
background-color: green !important;
256+
}
257+
</style>
258+
<div class="stripe-4 green"></div>
259+
<div class="stripe-4 green"></div>
260+
<div class="stripe-4 green"></div>
261+
<div class="stripe-4 red"></div>
262+
</rendering>
263+
240264
<rendering>
241265
<div class="stripe-4 green"></div>
242266
<div class="stripe-4 red"></div>
@@ -261,6 +285,31 @@
261285
<div class="stripe-4 red"></div>
262286
</rendering>
263287

288+
<rendering>
289+
<style>
290+
div:first-of-type {
291+
background-color: green !important;
292+
}
293+
</style>
294+
<div class="stripe-4 red"></div>
295+
<div class="stripe-4 green"></div>
296+
<div class="stripe-4 green"></div>
297+
<div class="stripe-4 green"></div>
298+
</rendering>
299+
300+
<rendering>
301+
<style>
302+
div:last-of-type {
303+
background-color: green !important;
304+
}
305+
</style>
306+
<div class="stripe-4 green"></div>
307+
<div class="stripe-4 green"></div>
308+
<div class="stripe-4 green"></div>
309+
<div class="stripe-4 red"></div>
310+
</rendering>
311+
312+
264313

265314

266315
</test>

0 commit comments

Comments
 (0)