Skip to content

Commit 0c28fda

Browse files
authored
Merge pull request #2032 from mauke/dom-nth-child
Fix :nth-child selector
2 parents f0a090d + 7718452 commit 0c28fda

File tree

2 files changed

+26
-23
lines changed

2 files changed

+26
-23
lines changed

lib/Mojo/DOM/CSS.pm

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -117,11 +117,8 @@ sub _compile {
117117
# ":nth-*" (with An+B notation)
118118
$args = _equation($args) if $name =~ /^nth-/;
119119

120-
# ":first-*" (rewrite to ":nth-*")
121-
($name, $args) = ("nth-$1", [0, 1]) if $name =~ /^first-(.+)$/;
122-
123-
# ":last-*" (rewrite to ":nth-*")
124-
($name, $args) = ("nth-$name", [-1, 1]) if $name =~ /^last-/;
120+
# ":first-*", ":last-*" (rewrite to ":nth-(last-)*")
121+
($name, $args) = ("nth-$+", [0, 1]) if $name =~ /^(?:first-(.+)|(last-.+))$/;
125122

126123
push @$last, ['pc', $name, $args];
127124
}
@@ -144,7 +141,7 @@ sub _equation {
144141
return [0, 0] unless my $equation = shift;
145142

146143
# "even"
147-
return [2, 2] if $equation =~ /^\s*even\s*$/i;
144+
return [2, 0] if $equation =~ /^\s*even\s*$/i;
148145

149146
# "odd"
150147
return [2, 1] if $equation =~ /^\s*odd\s*$/i;
@@ -241,13 +238,16 @@ sub _pc {
241238
if (ref $args) {
242239
my $type = $class eq 'nth-of-type' || $class eq 'nth-last-of-type' ? $current->[1] : undef;
243240
my @siblings = @{_siblings($current, $type)};
244-
@siblings = reverse @siblings if $class eq 'nth-last-child' || $class eq 'nth-last-of-type';
245-
241+
my $index;
246242
for my $i (0 .. $#siblings) {
247-
next if (my $result = $args->[0] * $i + $args->[1]) < 1;
248-
return undef unless my $sibling = $siblings[$result - 1];
249-
return 1 if $sibling eq $current;
243+
$index = $i, last if $siblings[$i] eq $current;
250244
}
245+
$index = $#siblings - $index if $class eq 'nth-last-child' || $class eq 'nth-last-of-type';
246+
$index++;
247+
248+
my $delta = $index - $args->[1];
249+
return 1 if $delta == 0;
250+
return $args->[0] != 0 && ($delta < 0) == ($args->[0] < 0) && $delta % $args->[0] == 0;
251251
}
252252

253253
# Everything else

t/mojo/dom.t

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,28 +1040,28 @@ EOF
10401040
is_deeply \@li, ['F'], 'found third last li element';
10411041
@li = ();
10421042
$dom->find('li:nth-child(1n+0)')->each(sub { push @li, shift->text });
1043-
is_deeply \@li, [qw(A B C D E F G)], 'found all li elements';
1043+
is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements';
10441044
@li = ();
10451045
$dom->find('li:nth-child(1n-0)')->each(sub { push @li, shift->text });
1046-
is_deeply \@li, [qw(A B C D E F G)], 'found all li elements';
1046+
is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements';
10471047
@li = ();
10481048
$dom->find('li:nth-child(n+0)')->each(sub { push @li, shift->text });
1049-
is_deeply \@li, [qw(A B C D E F G)], 'found all li elements';
1049+
is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements';
10501050
@li = ();
10511051
$dom->find('li:nth-child(n)')->each(sub { push @li, shift->text });
1052-
is_deeply \@li, [qw(A B C D E F G)], 'found all li elements';
1052+
is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements';
10531053
@li = ();
10541054
$dom->find('li:nth-child(n+0)')->each(sub { push @li, shift->text });
1055-
is_deeply \@li, [qw(A B C D E F G)], 'found all li elements';
1055+
is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements';
10561056
@li = ();
10571057
$dom->find('li:NTH-CHILD(N+0)')->each(sub { push @li, shift->text });
1058-
is_deeply \@li, [qw(A B C D E F G)], 'found all li elements';
1058+
is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements';
10591059
@li = ();
10601060
$dom->find('li:Nth-Child(N+0)')->each(sub { push @li, shift->text });
1061-
is_deeply \@li, [qw(A B C D E F G)], 'found all li elements';
1061+
is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements';
10621062
@li = ();
10631063
$dom->find('li:nth-child(n)')->each(sub { push @li, shift->text });
1064-
is_deeply \@li, [qw(A B C D E F G)], 'found all li elements';
1064+
is_deeply \@li, [qw(A B C D E F G H)], 'found all li elements';
10651065
@li = ();
10661066
$dom->find('li:nth-child(0n+1)')->each(sub { push @li, shift->text });
10671067
is_deeply \@li, [qw(A)], 'found first li element';
@@ -1102,19 +1102,19 @@ EOF
11021102
is_deeply \@e, [qw(A E H)], 'found all odd li elements';
11031103
@e = ();
11041104
$dom->find('ul li:not(:first-child, :last-child)')->each(sub { push @e, shift->text });
1105-
is_deeply \@e, [qw(C E F H)], 'found all odd li elements';
1105+
is_deeply \@e, [qw(C E F H)], 'found all li elements but first/last';
11061106
@e = ();
11071107
$dom->find('ul li:is(:first-child, :last-child)')->each(sub { push @e, shift->text });
1108-
is_deeply \@e, [qw(A I)], 'found all odd li elements';
1108+
is_deeply \@e, [qw(A I)], 'found first/last li elements';
11091109
@e = ();
11101110
$dom->find('li:nth-last-of-type( odd )')->each(sub { push @e, shift->text });
1111-
is_deeply \@e, [qw(C F I)], 'found all odd li elements';
1111+
is_deeply \@e, [qw(C F I)], 'found all odd li elements (counting from end)';
11121112
@e = ();
11131113
$dom->find('p:nth-of-type(odd)')->each(sub { push @e, shift->text });
11141114
is_deeply \@e, [qw(B G)], 'found all odd p elements';
11151115
@e = ();
11161116
$dom->find('p:nth-last-of-type(odd)')->each(sub { push @e, shift->text });
1117-
is_deeply \@e, [qw(B G)], 'found all odd li elements';
1117+
is_deeply \@e, [qw(B G)], 'found all odd p elements (counting from end)';
11181118
@e = ();
11191119
$dom->find('ul :nth-child(1)')->each(sub { push @e, shift->text });
11201120
is_deeply \@e, ['A'], 'found first child';
@@ -1193,6 +1193,9 @@ EOF
11931193
@e = ();
11941194
$dom->find('div div:only-of-type')->each(sub { push @e, shift->text });
11951195
is_deeply \@e, [qw(J K)], 'found only child';
1196+
@e = ();
1197+
$dom->find('div :nth-child(-n+2)')->each(sub { push @e, shift->text });
1198+
is_deeply \@e, [qw(J Mojo! K)], 'found first two children of each div';
11961199
};
11971200

11981201
subtest 'Links' => sub {

0 commit comments

Comments
 (0)