Skip to content

Commit

Permalink
updated CSS4 selectors in Mojo::DOM::CSS with changes from the latest…
Browse files Browse the repository at this point in the history
… editor's draft
  • Loading branch information
kraih committed Nov 1, 2011
1 parent e96b38c commit a1422fe
Show file tree
Hide file tree
Showing 3 changed files with 99 additions and 104 deletions.
2 changes: 2 additions & 0 deletions Changes
@@ -1,6 +1,8 @@
This file documents the revision history for Perl extension Mojolicious.

2.21 2011-11-01 00:00:00
- Updated CSS4 selectors in Mojo::DOM::CSS with changes from the
latest editor's draft.
- Improved Mojo::ByteStream to generate most Mojo::Util based methods
automatically.

Expand Down
17 changes: 5 additions & 12 deletions lib/Mojo/DOM/CSS.pm
Expand Up @@ -107,7 +107,7 @@ sub _compile {
$element =~ s/$ELEMENT_RE// and $tag = $self->_unescape($+{element});

# Subject
$selector->[0] = 'subject' if $tag =~ s/^\$//;
$selector->[0] = 'subject' if $tag =~ s/^\?//;

# Tag
$tag = '*' unless $tag;
Expand Down Expand Up @@ -209,14 +209,7 @@ sub _element {
$first-- if $first > 0;

# Next sibling
if ($siblings) {

# Last sibling
unless ($current = shift @$siblings) {
$siblings = undef;
return;
}
}
if ($siblings) { return unless $current = shift @$siblings }

# Next parent
else {
Expand Down Expand Up @@ -682,16 +675,16 @@ An C<E> element whose attributes match all following attribute selectors.
my $links = $css->select('a[foo^="b"][foo$="ar"]');
=head2 C<E $F G>
=head2 C<E ?F G>
An C<F> element descendant of an C<E> element and ancestor of a C<G> element.
my $wrappers = $css->select('$div.wrapper > :checked');
my $wrappers = $css->select('?div.wrapper > :checked');
By default, the subjects of a selector are the elements represented by the
last compound selector.
In CSS4 however the subject can be explicitly identified by prepending a
dollar sign to one of the compound selectors.
question mark to one of the compound selectors.
Note that the CSS4 spec is still a work in progress, so this selector might
change without warning!
Expand Down
184 changes: 92 additions & 92 deletions t/mojo/dom.t
Expand Up @@ -595,27 +595,27 @@ $dom = Mojo::DOM->new->parse(<<EOF);
<input type="submit" value="Ok!" />
</form>
EOF
is($dom->find(':root')->[0]->type, 'form', 'right type');
is($dom->find('*:root')->[0]->type, 'form', 'right type');
is($dom->find('form:root')->[0]->type, 'form', 'right type');
is($dom->find(':root')->[1], undef, 'no result');
is($dom->find(':checked')->[0]->attrs->{name}, 'groovy', 'right name');
is($dom->find('option:checked')->[0]->attrs->{value}, 'e', 'right value');
is($dom->find(':checked')->[1]->text, 'E', 'right text');
is($dom->find('*:checked')->[1]->text, 'E', 'right text');
is($dom->find(':checked[value="e"]')->[0]->text, 'E', 'right text');
is($dom->find('*:checked[value="e"]')->[0]->text, 'E', 'right text');
is($dom->find('option:checked[value="e"]')->[0]->text, 'E', 'right text');
is($dom->at('optgroup option:checked[value="e"]')->text, 'E', 'right text');
is($dom->at('select option:checked[value="e"]')->text, 'E', 'right text');
is($dom->at('select :checked[value="e"]')->text, 'E', 'right text');
is($dom->at('optgroup > :checked[value="e"]')->text, 'E', 'right text');
is($dom->at('select *:checked[value="e"]')->text, 'E', 'right text');
is($dom->at('optgroup > *:checked[value="e"]')->text, 'E', 'right text');
is($dom->find(':checked[value="e"]')->[1], undef, 'no result');
is($dom->find(':empty')->[0]->attrs->{name}, 'user', 'right name');
is($dom->find('input:empty')->[0]->attrs->{name}, 'user', 'right name');
is($dom->at(':empty[type^="ch"]')->attrs->{name}, 'groovy', 'right name');
is $dom->find(':root')->[0]->type, 'form', 'right type';
is $dom->find('*:root')->[0]->type, 'form', 'right type';
is $dom->find('form:root')->[0]->type, 'form', 'right type';
is $dom->find(':root')->[1], undef, 'no result';
is $dom->find(':checked')->[0]->attrs->{name}, 'groovy', 'right name';
is $dom->find('option:checked')->[0]->attrs->{value}, 'e', 'right value';
is $dom->find(':checked')->[1]->text, 'E', 'right text';
is $dom->find('*:checked')->[1]->text, 'E', 'right text';
is $dom->find(':checked[value="e"]')->[0]->text, 'E', 'right text';
is $dom->find('*:checked[value="e"]')->[0]->text, 'E', 'right text';
is $dom->find('option:checked[value="e"]')->[0]->text, 'E', 'right text';
is $dom->at('optgroup option:checked[value="e"]')->text, 'E', 'right text';
is $dom->at('select option:checked[value="e"]')->text, 'E', 'right text';
is $dom->at('select :checked[value="e"]')->text, 'E', 'right text';
is $dom->at('optgroup > :checked[value="e"]')->text, 'E', 'right text';
is $dom->at('select *:checked[value="e"]')->text, 'E', 'right text';
is $dom->at('optgroup > *:checked[value="e"]')->text, 'E', 'right text';
is $dom->find(':checked[value="e"]')->[1], undef, 'no result';
is $dom->find(':empty')->[0]->attrs->{name}, 'user', 'right name';
is $dom->find('input:empty')->[0]->attrs->{name}, 'user', 'right name';
is $dom->at(':empty[type^="ch"]')->attrs->{name}, 'groovy', 'right name';

# More pseudo classes
$dom = Mojo::DOM->new->parse(<<EOF);
Expand All @@ -639,14 +639,14 @@ is_deeply \@li, [qw/A C E G/], 'found all odd li elements';
@li = ();
$dom->find('li:nth-last-child(odd)')->each(sub { push @li, shift->text });
is_deeply \@li, [qw/B D F H/], 'found all odd li elements';
is($dom->find(':nth-child(odd)')->[0]->type, 'ul', 'right type');
is($dom->find(':nth-child(odd)')->[1]->text, 'A', 'right text');
is($dom->find(':nth-child(1)')->[0]->type, 'ul', 'right type');
is($dom->find(':nth-child(1)')->[1]->text, 'A', 'right text');
is($dom->find(':nth-last-child(odd)')->[0]->type, 'ul', 'right type');
is($dom->find(':nth-last-child(odd)')->[-1]->text, 'H', 'right text');
is($dom->find(':nth-last-child(1)')->[0]->type, 'ul', 'right type');
is($dom->find(':nth-last-child(1)')->[1]->text, 'H', 'right text');
is $dom->find(':nth-child(odd)')->[0]->type, 'ul', 'right type';
is $dom->find(':nth-child(odd)')->[1]->text, 'A', 'right text';
is $dom->find(':nth-child(1)')->[0]->type, 'ul', 'right type';
is $dom->find(':nth-child(1)')->[1]->text, 'A', 'right text';
is $dom->find(':nth-last-child(odd)')->[0]->type, 'ul', 'right type';
is $dom->find(':nth-last-child(odd)')->[-1]->text, 'H', 'right text';
is $dom->find(':nth-last-child(1)')->[0]->type, 'ul', 'right type';
is $dom->find(':nth-last-child(1)')->[1]->text, 'H', 'right text';
@li = ();
$dom->find('li:nth-child(2n+1)')->each(sub { push @li, shift->text });
is_deeply \@li, [qw/A C E G/], 'found all odd li elements';
Expand Down Expand Up @@ -889,41 +889,41 @@ $dom = Mojo::DOM->new->parse(<<EOF);
<p id="☃">F</p>
<div>G</div>
EOF
is($dom->at('li ~ p')->text, 'B', 'right text');
is($dom->at('li + p')->text, 'B', 'right text');
is($dom->at('h1 ~ p ~ p')->text, 'F', 'right text');
is($dom->at('h1 + p ~ p')->text, 'F', 'right text');
is($dom->at('h1 ~ p + p')->text, 'F', 'right text');
is($dom->at('h1 + p + p')->text, 'F', 'right text');
is($dom->at('ul > li ~ li')->text, 'C', 'right text');
is($dom->at('ul li ~ li')->text, 'C', 'right text');
is($dom->at('ul li li'), undef, 'no result');
is($dom->at('ul ~ li ~ li'), undef, 'no result');
is($dom->at('ul + li ~ li'), undef, 'no result');
is($dom->at('ul > li + li'), undef, 'no result');
is($dom->at('h1 ~ div')->text, 'G', 'right text');
is($dom->at('h1 + div'), undef, 'no result');
is($dom->at('p + div')->text, 'G', 'right text');
is($dom->at('ul + h1 + p + p + div')->text, 'G', 'right text');
is($dom->at('ul + h1 ~ p + div')->text, 'G', 'right text');
is($dom->at('h1 ~ #♥')->text, 'E', 'right text');
is($dom->at('h1 + #♥')->text, 'E', 'right text');
is($dom->at('#♥ ~ #☃')->text, 'F', 'right text');
is($dom->at('#♥ + #☃')->text, 'F', 'right text');
is($dom->at('#♥ > #☃'), undef, 'no result');
is($dom->at('#♥ #☃'), undef, 'no result');
is($dom->at('#♥ + #☃ + :nth-last-child(1)')->text, 'G', 'right text');
is($dom->at('#♥ ~ #☃ + :nth-last-child(1)')->text, 'G', 'right text');
is($dom->at('#♥ + #☃ ~ :nth-last-child(1)')->text, 'G', 'right text');
is($dom->at('#♥ ~ #☃ ~ :nth-last-child(1)')->text, 'G', 'right text');
is($dom->at('#♥ + :nth-last-child(2)')->text, 'F', 'right text');
is($dom->at('#♥ ~ :nth-last-child(2)')->text, 'F', 'right text');
is($dom->at('#♥ + #☃ + *:nth-last-child(1)')->text, 'G', 'right text');
is($dom->at('#♥ ~ #☃ + *:nth-last-child(1)')->text, 'G', 'right text');
is($dom->at('#♥ + #☃ ~ *:nth-last-child(1)')->text, 'G', 'right text');
is($dom->at('#♥ ~ #☃ ~ *:nth-last-child(1)')->text, 'G', 'right text');
is($dom->at('#♥ + *:nth-last-child(2)')->text, 'F', 'right text');
is($dom->at('#♥ ~ *:nth-last-child(2)')->text, 'F', 'right text');
is $dom->at('li ~ p')->text, 'B', 'right text';
is $dom->at('li + p')->text, 'B', 'right text';
is $dom->at('h1 ~ p ~ p')->text, 'F', 'right text';
is $dom->at('h1 + p ~ p')->text, 'F', 'right text';
is $dom->at('h1 ~ p + p')->text, 'F', 'right text';
is $dom->at('h1 + p + p')->text, 'F', 'right text';
is $dom->at('ul > li ~ li')->text, 'C', 'right text';
is $dom->at('ul li ~ li')->text, 'C', 'right text';
is $dom->at('ul li li'), undef, 'no result';
is $dom->at('ul ~ li ~ li'), undef, 'no result';
is $dom->at('ul + li ~ li'), undef, 'no result';
is $dom->at('ul > li + li'), undef, 'no result';
is $dom->at('h1 ~ div')->text, 'G', 'right text';
is $dom->at('h1 + div'), undef, 'no result';
is $dom->at('p + div')->text, 'G', 'right text';
is $dom->at('ul + h1 + p + p + div')->text, 'G', 'right text';
is $dom->at('ul + h1 ~ p + div')->text, 'G', 'right text';
is $dom->at('h1 ~ #♥')->text, 'E', 'right text';
is $dom->at('h1 + #♥')->text, 'E', 'right text';
is $dom->at('#♥ ~ #☃')->text, 'F', 'right text';
is $dom->at('#♥ + #☃')->text, 'F', 'right text';
is $dom->at('#♥ > #☃'), undef, 'no result';
is $dom->at('#♥ #☃'), undef, 'no result';
is $dom->at('#♥ + #☃ + :nth-last-child(1)')->text, 'G', 'right text';
is $dom->at('#♥ ~ #☃ + :nth-last-child(1)')->text, 'G', 'right text';
is $dom->at('#♥ + #☃ ~ :nth-last-child(1)')->text, 'G', 'right text';
is $dom->at('#♥ ~ #☃ ~ :nth-last-child(1)')->text, 'G', 'right text';
is $dom->at('#♥ + :nth-last-child(2)')->text, 'F', 'right text';
is $dom->at('#♥ ~ :nth-last-child(2)')->text, 'F', 'right text';
is $dom->at('#♥ + #☃ + *:nth-last-child(1)')->text, 'G', 'right text';
is $dom->at('#♥ ~ #☃ + *:nth-last-child(1)')->text, 'G', 'right text';
is $dom->at('#♥ + #☃ ~ *:nth-last-child(1)')->text, 'G', 'right text';
is $dom->at('#♥ ~ #☃ ~ *:nth-last-child(1)')->text, 'G', 'right text';
is $dom->at('#♥ + *:nth-last-child(2)')->text, 'F', 'right text';
is $dom->at('#♥ ~ *:nth-last-child(2)')->text, 'F', 'right text';

# Adding nodes
$dom = Mojo::DOM->new->parse(<<EOF);
Expand Down Expand Up @@ -1855,36 +1855,36 @@ $dom = Mojo::DOM->new(<<EOF);
</div>
</div>
EOF
is $dom->find('div > $div > a')->[0]->{id}, 'b', 'right attribute';
is $dom->find('div > $div > a')->[1]->{id}, 'c', 'right attribute';
is $dom->find('div > $div > a')->[2], undef, 'no result';
is $dom->find('div > $div > a')->size, 2, 'right number of elements';
is $dom->find('div $div a')->[0]->{id}, 'b', 'right attribute';
is $dom->find('div $div a')->[1]->{id}, 'c', 'right attribute';
is $dom->find('div $div a')->[2], undef, 'no result';
is $dom->find('div $div a')->size, 2, 'right number of elements';
is $dom->find('.wrapper > $ > [href]')->[0]->{id}, 'b', 'right attribute';
is $dom->find('.wrapper > $ > [href]')->[1]->{id}, 'c', 'right attribute';
is $dom->find('.wrapper $ > [href]')->[2], undef, 'no result';
is $dom->find('.wrapper $ > [href]')->size, 2, 'right number of elements';
is $dom->find('#a > $ [href]')->[0]->{id}, 'b', 'right attribute';
is $dom->find('#a > $ [href]')->[1]->{id}, 'c', 'right attribute';
is $dom->find('#a > $ [href]')->[2], undef, 'no result';
is $dom->find('#a > $ [href]')->size, 2, 'right number of elements';
is $dom->find('$div div a')->[0]->{id}, 'a', 'right attribute';
is $dom->find('$div div a')->[1], undef, 'no result';
is $dom->find('$div div a')->size, 1, 'right number of elements';
is $dom->find('div div $a')->[0]->{href}, 'http://kraih.com',
is $dom->find('div > ?div > a')->[0]->{id}, 'b', 'right attribute';
is $dom->find('div > ?div > a')->[1]->{id}, 'c', 'right attribute';
is $dom->find('div > ?div > a')->[2], undef, 'no result';
is $dom->find('div > ?div > a')->size, 2, 'right number of elements';
is $dom->find('div ?div a')->[0]->{id}, 'b', 'right attribute';
is $dom->find('div ?div a')->[1]->{id}, 'c', 'right attribute';
is $dom->find('div ?div a')->[2], undef, 'no result';
is $dom->find('div ?div a')->size, 2, 'right number of elements';
is $dom->find('.wrapper > ? > [href]')->[0]->{id}, 'b', 'right attribute';
is $dom->find('.wrapper > ? > [href]')->[1]->{id}, 'c', 'right attribute';
is $dom->find('.wrapper ? > [href]')->[2], undef, 'no result';
is $dom->find('.wrapper ? > [href]')->size, 2, 'right number of elements';
is $dom->find('#a > ? [href]')->[0]->{id}, 'b', 'right attribute';
is $dom->find('#a > ? [href]')->[1]->{id}, 'c', 'right attribute';
is $dom->find('#a > ? [href]')->[2], undef, 'no result';
is $dom->find('#a > ? [href]')->size, 2, 'right number of elements';
is $dom->find('?div div a')->[0]->{id}, 'a', 'right attribute';
is $dom->find('?div div a')->[1], undef, 'no result';
is $dom->find('?div div a')->size, 1, 'right number of elements';
is $dom->find('div div ?a')->[0]->{href}, 'http://kraih.com',
'right attribute';
is $dom->find('div div $a')->[0]->text, 'Kraih', 'right text';
is $dom->find('div div $a')->[1]->{href}, 'http://mojolicio.us',
is $dom->find('div div ?a')->[0]->text, 'Kraih', 'right text';
is $dom->find('div div ?a')->[1]->{href}, 'http://mojolicio.us',
'right attribute';
is $dom->find('div div $a')->[1]->text, 'Mojolicious', 'right text';
is $dom->find('div div $a')->[2], undef, 'no result';
is $dom->find('div div $a')->size, 2, 'right number of elements';
is $dom->find('$[class] > div')->[0]->{id}, 'a', 'right attribute';
is $dom->find('$[class] > div')->[2], undef, 'no result';
is $dom->find('$[class] > div')->size, 1, 'right number of elements';
is $dom->find('div div ?a')->[1]->text, 'Mojolicious', 'right text';
is $dom->find('div div ?a')->[2], undef, 'no result';
is $dom->find('div div ?a')->size, 2, 'right number of elements';
is $dom->find('?[class] > div')->[0]->{id}, 'a', 'right attribute';
is $dom->find('?[class] > div')->[2], undef, 'no result';
is $dom->find('?[class] > div')->size, 1, 'right number of elements';

# Preformatted text
$dom = Mojo::DOM->new(<<EOF);
Expand Down

0 comments on commit a1422fe

Please sign in to comment.