Skip to content

Commit

Permalink
MM-6593
Browse files Browse the repository at this point in the history
merge in changes from CPAN contributor Sebastian Paaske Torholm <spt@jobindex.dk> to add rudimentary support for
pseudo-selectors.

Add tests provided by contributor.

Update manifest

Update changelog
  • Loading branch information
kamelkev committed Aug 8, 2012
1 parent ad7c916 commit de749c0
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 4 deletions.
8 changes: 8 additions & 0 deletions ChangeLog
Expand Up @@ -48,8 +48,16 @@
* Added skipping for '* html' hack sequence frequently used by IE6, should return nothing

0.07 2010-11-02 Kevin Kamel <kamelkev@mailermailer.com>

* Merge in specificity calculation. This code was ripped out of CSS::Inliner, HTML::Query is a more
appropriate place to do this calculation.
* Added optimizations so that the specificity calculation doesn't need a tree in order to operate
nor does it need a prior query to have occurred.
* Merge in tests from CSS::Inliner for specificity calculations

0.08 2012-08-01 Kevin Kamel <kamelkev@mailermailer.com>
* Added patch from Sebastian Paaske Torholm <spt@jobindex.dk>
- Adds support for -child pseudo-classes including proper specificity calculation
- Adds tests for verifying specificity calculation and proper selection of -child pseudo classes
* Updated documentation with sections for pseudo-classes and psuedo-elements detailing
current support for those features.
2 changes: 2 additions & 0 deletions MANIFEST
Expand Up @@ -10,12 +10,14 @@ t/duplicate.t
t/element.t
t/iterative.t
t/multioperand.t
t/pseudoclasses.t
t/query.t
t/specificity.t
t/universal.t
t/html/acidtest.html
t/html/combinator.html
t/html/multioperator.html
t/html/pseudoclasses.html
t/html/test1.html
t/html/test2.html
t/html/test3.html
Expand Down
76 changes: 74 additions & 2 deletions lib/HTML/Query.pm
Expand Up @@ -271,6 +271,20 @@ sub query {
push( @args, $attribute => qr/.*/ );
}
}
# and/or one or more pseudo-classes
if ($query =~ / \G : ([\w\-]+) /cgx) {
my $pseudoclass = $1;
$specificity += 10;

if ($pseudoclass eq 'first-child') {
push( @args, sub { ! grep { ref $_ } $_[0]->left() } );
} elsif ($pseudoclass eq 'last-child') {
push( @args, sub { ! grep { ref $_ } $_[0]->right() } );
} else {
warn "Pseudoclass :$pseudoclass not supported";
next;
}
}

# keep going until this particular expression is fully processed
last unless scalar(@args) > $work;
Expand Down Expand Up @@ -1092,9 +1106,67 @@ with the C<+> character.
@elems = $query->query('img + span')->get_elements();
=head2 Combining Selectors
=head2 Pseudo-classes
You can combine basic and hierarchical selectors into a single query
W3C CSS 2 and CSS 3 specifications define new concepts of pseudo-classes to
permit formatting based on information that lies outside the document tree.
See the following link for the most recent spec:
L<http://www.w3.org/TR/css3-selectors/#pseudo-classes>
HTML::Query currently has limited support for CSS 2, and no support for CSS 3.
Patches are *highly* encouraged to help add support here.
=head3 -child pseudo-classes
If you want to return child elements within a certain position then -child
pseudo-classes (:first-child, :last-child) are what you're looking for.
@elems = $query->query('table td:first-child')->get_elements;
=head3 Link pseudo-classes: :link and :visited
Unsupported.
The :link pseudo-class is to be implemented, currently unsupported.
It is not possible to locate :visited outside of a browser context due to it's
dynamic nature.
=head3 Dynamic pseudo-classes
Unsupported.
It is not possible to locate these classes(:hover, :active, :focus) outside
of a browser context due to their dynamic nature.
=head3 Language pseudo-class
Unsupported.
Functionality for the :lang psuedo-class is largely replicated by using an
attribute selector for lang combined with a universal selector query.
If this is insufficient I'd love to see a patch adding support for it.
=head3 Other pseudo-classes
W3C CSS 3 added a number of new behaviors that need support. At
this time there is no support for them, but we should work on adding support.
Patches are very welcome.
=head2 Pseudo-elements
W3C CSS 2 and CSS 3 specification defines new concepts of pseudo-elements to
permit formatting based on information that lies outside the document tree.
See the following link for the most recent spec:
L<http://www.w3.org/TR/css3-selectors/#pseudo-elements>
At this time there is no support for pseudo-elements, but we are working
on adding support.
Patches are very welcome.
=head2 Combining Selectors
Expand Down
24 changes: 24 additions & 0 deletions t/html/pseudoclasses.html
@@ -0,0 +1,24 @@
<html>
<head>
<script type="text/javascript" src="/utilities/smush.bin?scripts=swfobject.js,jquery/jquery-1.7.2.min.js,general.js"></script>
</head>
<body>
<table>
<tr>
<td>1,1</td>
<td>1,2</td>
<td>1,3</td>
</tr>
<tr>
<td>2,1</td>
<td>2,2</td>
<td>2,3</td>
</tr>
<tr>
<td>3,1</td>
<td>3,2</td>
<td>3,3</td>
</tr>
</table>
</body>
</html>
42 changes: 42 additions & 0 deletions t/pseudoclasses.t
@@ -0,0 +1,42 @@
use strict;
use warnings;
use lib qw( ./lib ../lib );
use HTML::TreeBuilder;
use Badger::Filesystem '$Bin Dir';
use Badger::Test
tests => 10,
debug => 'HTML::Query',
args => \@ARGV;

use HTML::Query 'Query';

our $Query = 'HTML::Query';
our $Builder = 'HTML::TreeBuilder';
our $test_dir = Dir($Bin);
our $html_dir = $test_dir->dir('html')->must_exist;
our $pseudo = $html_dir->file('pseudoclasses.html')->must_exist;

my ($query, $tree);

$tree = $Builder->new;
$tree->parse_file( $pseudo->absolute );

ok( $tree, 'parsed tree for test file: ' . $pseudo->name );
$query = Query $tree;
ok( $query, 'created query' );

my $test1 = $query->query('table td:first-child');
is( $test1->size, 3, 'test1 - size' );
is( join(" | ", $test1->as_trimmed_text), "1,1 | 2,1 | 3,1", 'test1 - text');

my $test2 = $query->query('table td:last-child');
is( $test2->size, 3, 'test2 - size' );
is( join(" | ", $test2->as_trimmed_text), "1,3 | 2,3 | 3,3", 'test2 - text');

my $test3 = $query->query('table tr:first-child td');
is( $test3->size, 3, 'test3 - size' );
is( join(" | ", $test3->as_trimmed_text), "1,1 | 1,2 | 1,3", 'test3 - text');

my $test4 = $query->query('table tr:last-child td');
is( $test4->size, 3, 'test4 - size' );
is( join(" | ", $test4->as_trimmed_text), "3,1 | 3,2 | 3,3", 'test4 - text');
5 changes: 3 additions & 2 deletions t/specificity.t
Expand Up @@ -14,7 +14,7 @@ use warnings;
use lib qw( ./lib ../lib );
use Badger::Filesystem '$Bin Dir';
use Badger::Test
tests => 23,
tests => 24,
debug => 'HTML::Query',
args => \@ARGV;

Expand Down Expand Up @@ -44,7 +44,8 @@ my %rules = (
"*" => 0,
"div#id-one div p>em" => 104,
"html#simple body#internal" => 202,
"body#internal" => 101
"body#internal" => 101,
"div:first-child" => 11,
);

foreach my $rule (keys %rules) {
Expand Down

0 comments on commit de749c0

Please sign in to comment.