Permalink
Browse files

added experimental CSS4 selector subject support to Mojo::DOM::CSS

  • Loading branch information...
1 parent 24c8131 commit d7b04a2d45972ced5366f438742e40f2c66836db @kraih committed Aug 10, 2011
Showing with 64 additions and 6 deletions.
  1. +1 −0 Changes
  2. +27 −5 lib/Mojo/DOM/CSS.pm
  3. +36 −1 t/mojo/dom.t
View
@@ -1,6 +1,7 @@
This file documents the revision history for Perl extension Mojolicious.
1.75 2011-08-09 00:00:00
+ - Added experimental CSS4 selector subject support to Mojo::DOM::CSS.
- Improved documentation.
- Fixed typos.
View
@@ -1,6 +1,8 @@
package Mojo::DOM::CSS;
use Mojo::Base -base;
+use List::Util 'first';
+
# Regex
my $CSS_ESCAPE_RE = qr/\\[^0-9a-fA-F]|\\[0-9a-fA-F]{1,6}/;
my $CSS_ATTR_RE = qr/
@@ -65,8 +67,9 @@ sub select {
# Parts
for my $part (@$pattern) {
- push(@results, $current) and last
- if $self->_element($current, $part, $tree);
+ my $result = $self->_element($current, $part, $tree);
+ push(@results, $result) and last
+ if $result && !first { $_ eq $result } @results;
}
}
}
@@ -100,10 +103,14 @@ sub _compile {
# Element
$element ||= '';
- my $tag = '*';
+ my $tag = '';
$element =~ s/$CSS_ELEMENT_RE// and $tag = $self->_unescape($1);
+ # Subject
+ $selector->[0] = 'subject' if $tag =~ s/^\$//;
+
# Tag
+ $tag = '*' unless $tag;
push @$selector, ['tag', $tag];
# Class or ID
@@ -195,7 +202,6 @@ sub _element {
}
}
- # Move on
next;
}
@@ -225,6 +231,9 @@ sub _element {
# Not a tag
return if $current->[0] ne 'tag';
+ # Subject
+ $candidate = $current if $selector->[0] eq 'subject';
+
# Compare part to element
if ($self->_selector($selector, $current)) {
$siblings = undef;
@@ -250,7 +259,7 @@ sub _element {
}
}
- return 1;
+ return $candidate;
}
# "Rock stars... is there anything they don't know?"
@@ -674,6 +683,19 @@ 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>
+
+An C<F> element descendant of an C<E> element and ancestor of an C<G>
+element.
+
+ my $checked = $css->select('$div > :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.
+Note that this selector is EXPERIMENTAL and might change without warning!
+
=head1 ATTRIBUTES
L<Mojo::DOM::CSS> implements the following attributes.
View
@@ -3,7 +3,7 @@ use Mojo::Base -strict;
use utf8;
-use Test::More tests => 608;
+use Test::More tests => 629;
# "Homer gave me a kidney: it wasn't his, I didn't need it,
# and it came postage due- but I appreciated the gesture!"
@@ -1839,3 +1839,38 @@ is "$dom", <<EOF, 'right result';
</tr>
</table>
EOF
+
+# Selector subject
+$dom = Mojo::DOM->new(<<EOF);
+<div id="a" class="wrapper">
+ <div id="b">
+ <a href="http://kraih.com">Kraih</a>
+ </div>
+ <div id="c" class="wrapper">
+ <a href="http://mojolicio.us">Mojolicious</a>
+ </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')->[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('.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('#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('$div div a')->[0]->{id}, 'a', 'right attribute';
+is $dom->find('$div div a')->[1], undef, 'no result';
+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',
+ '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('$[class] > div')->[0]->{id}, 'a', 'right attribute';
+is $dom->find('$[class] > div')->[2], undef, 'no result';

0 comments on commit d7b04a2

Please sign in to comment.