Skip to content

Commit a7ac95d

Browse files
committed
Fix various CSS selector equation bugs
1 parent 3d19146 commit a7ac95d

File tree

3 files changed

+32
-19
lines changed

3 files changed

+32
-19
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
This package strictly follows [Semantic Versioning](https://semver.org).
55

6+
## v2.1.1 (2023-02-06)
7+
8+
### Bug Fixes
9+
10+
* Fixed various CSS selector equation bugs.
11+
612
## v2.1.0 (2023-01-29)
713

814
### Features

src/css.ts

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ function compileEquation(values: string | undefined): [number, number] {
119119
if (values === undefined) return [0, 0];
120120

121121
// "even"
122-
if (/^\s*even\s*$/i.test(values)) return [2, 2];
122+
if (/^\s*even\s*$/i.test(values)) return [2, 0];
123123

124124
// "odd"
125125
if (/^\s*odd\s*$/i.test(values)) return [2, 1];
@@ -172,12 +172,12 @@ function compilePseudoClass(name: string, args: string): PseudoClass {
172172

173173
// ":last-child"
174174
else if (name === 'last-child') {
175-
return {type: 'pc', class: 'nth-last-child', value: [-1, 1]};
175+
return {type: 'pc', class: 'nth-last-child', value: [0, 1]};
176176
}
177177

178178
// ":last-of-type"
179179
else if (name === 'last-of-type') {
180-
return {type: 'pc', class: 'nth-last-of-type', value: [-1, 1]};
180+
return {type: 'pc', class: 'nth-last-of-type', value: [0, 1]};
181181
}
182182

183183
// ":checked", ":empty", ":only-child", ":only-of-type", ":root"
@@ -398,18 +398,21 @@ function matchPseudoClass(simple: PseudoClass, current: ElementNode, tree: Paren
398398
nodes = nodes.filter(el => (el as ElementNode).tagName === current.tagName);
399399
}
400400

401-
// ":*-last-*"
402-
if (name === 'nth-last-child' || name === 'nth-last-of-type') nodes.reverse();
403-
401+
let index = 0;
404402
for (let i = 0; i < nodes.length; i++) {
405-
const result = equation[0] * i + equation[1];
406-
if (result < 1) continue;
407-
const sibling = nodes[result - 1];
408-
if (sibling === undefined) return false;
409-
if (sibling === current) return true;
403+
if (nodes[i] !== current) continue;
404+
index = i;
405+
break;
410406
}
407+
if (name === 'nth-last-child' || name === 'nth-last-of-type') index = nodes.length - index - 1;
408+
index++;
409+
410+
const delta = index - equation[1];
411+
if (delta === 0) return true;
412+
return equation[0] !== 0 && delta < 0 === equation[0] < 0 && delta % equation[0] === 0;
411413
}
412414

415+
// Everything else
413416
return false;
414417
}
415418

test/dom.js

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -689,35 +689,35 @@ t.test('DOM', t => {
689689
);
690690
t.same(
691691
dom.find('li:nth-child(1n+0)').map(el => el.text()),
692-
['A', 'B', 'C', 'D', 'E', 'F', 'G']
692+
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
693693
);
694694
t.same(
695695
dom.find('li:nth-child(1n-0)').map(el => el.text()),
696-
['A', 'B', 'C', 'D', 'E', 'F', 'G']
696+
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
697697
);
698698
t.same(
699699
dom.find('li:nth-child(n+0)').map(el => el.text()),
700-
['A', 'B', 'C', 'D', 'E', 'F', 'G']
700+
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
701701
);
702702
t.same(
703703
dom.find('li:nth-child(n)').map(el => el.text()),
704-
['A', 'B', 'C', 'D', 'E', 'F', 'G']
704+
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
705705
);
706706
t.same(
707707
dom.find('li:nth-child(n)').map(el => el.text()),
708-
['A', 'B', 'C', 'D', 'E', 'F', 'G']
708+
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
709709
);
710710
t.same(
711711
dom.find('li:nth-child(n+0)').map(el => el.text()),
712-
['A', 'B', 'C', 'D', 'E', 'F', 'G']
712+
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
713713
);
714714
t.same(
715715
dom.find('li:nth-child(N+0)').map(el => el.text()),
716-
['A', 'B', 'C', 'D', 'E', 'F', 'G']
716+
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
717717
);
718718
t.same(
719719
dom.find('li:nth-child(N+0)').map(el => el.text()),
720-
['A', 'B', 'C', 'D', 'E', 'F', 'G']
720+
['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
721721
);
722722

723723
t.equal(dom.find('li:nth-child(0n+0)').length, 0);
@@ -897,6 +897,10 @@ t.test('DOM', t => {
897897
dom.find('div div:only-of-type').map(el => el.text()),
898898
['J', 'K']
899899
);
900+
t.same(
901+
dom.find('div :nth-child(-n+2)').map(el => el.text()),
902+
['J', 'Mojo!', 'K']
903+
);
900904

901905
t.end();
902906
});

0 commit comments

Comments
 (0)