-
-
Save anonymous/a5df9f736b9e033964f4 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/Mojo/DOM/CSS.pm b/lib/Mojo/DOM/CSS.pm | |
index 88de1dc..a6f2721 100644 | |
--- a/lib/Mojo/DOM/CSS.pm | |
+++ b/lib/Mojo/DOM/CSS.pm | |
@@ -27,7 +27,9 @@ sub _ancestor { | |
my ($selectors, $current, $tree, $one, $pos) = @_; | |
while ($current = $current->[3]) { | |
- return undef if $current->[0] eq 'root' || $current eq $tree; | |
+ return undef | |
+ if ($current->[0] eq 'root' || $current eq $tree) | |
+ && !_scope($selectors->[$pos]); | |
return 1 if _combinator($selectors, $current, $tree, $pos); | |
last if $one; | |
} | |
@@ -54,7 +56,7 @@ sub _combinator { | |
# Selector | |
return undef unless my $c = $selectors->[$pos]; | |
if (ref $c) { | |
- return undef unless _selector($c, $current); | |
+ return undef unless _selector($c, $current, $tree); | |
return 1 unless $c = $selectors->[++$pos]; | |
} | |
@@ -82,8 +84,11 @@ sub _compile { | |
# Separator | |
if ($css =~ /\G\s*,\s*/gc) { push @$group, [] } | |
- # Combinator | |
- elsif ($css =~ /\G\s*([ >+~])\s*/gc) { push @$selectors, $1 } | |
+ # Combinator (and implicit ":scope") | |
+ elsif ($css =~ /\G\s*([ >+~])\s*/gc) { | |
+ push @$last, ['pc', 'scope'] unless @$last; | |
+ push @$selectors, $1; | |
+ } | |
# Class or ID | |
elsif ($css =~ /\G([.#])((?:$ESCAPE_RE\s|\\.|[^,.#:[ >~+])+)/gco) { | |
@@ -142,7 +147,10 @@ sub _match { | |
sub _name {qr/(?:^|:)\Q@{[_unescape(shift)]}\E$/} | |
sub _pc { | |
- my ($class, $args, $current) = @_; | |
+ my ($class, $args, $current, $tree) = @_; | |
+ | |
+ # ":scope" | |
+ return $current->[0] eq 'root' || $current eq $tree if $class eq 'scope'; | |
# ":empty" | |
return !grep { !_empty($_) } @$current[4 .. $#$current] if $class eq 'empty'; | |
@@ -186,6 +194,8 @@ sub _pc { | |
return undef; | |
} | |
+sub _scope { $_[0] && $_[0][0][0] eq 'pc' && $_[0][0][1] eq 'scope' } | |
+ | |
sub _select { | |
my ($one, $tree, $group) = @_; | |
@@ -203,7 +213,7 @@ sub _select { | |
} | |
sub _selector { | |
- my ($selector, $current) = @_; | |
+ my ($selector, $current, $tree) = @_; | |
for my $s (@$selector) { | |
my $type = $s->[0]; | |
@@ -215,7 +225,9 @@ sub _selector { | |
elsif ($type eq 'attr') { return undef unless _attr(@$s[1, 2], $current) } | |
# Pseudo-class | |
- elsif ($type eq 'pc') { return undef unless _pc(@$s[1, 2], $current) } | |
+ elsif ($type eq 'pc') { | |
+ return undef unless _pc(@$s[1, 2], $current, $tree); | |
+ } | |
} | |
return 1; | |
diff --git a/t/mojo/dom.t b/t/mojo/dom.t | |
index da76dee..b23dd17 100644 | |
--- a/t/mojo/dom.t | |
+++ b/t/mojo/dom.t | |
@@ -1218,6 +1218,21 @@ 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'; | |
+# Scoped selectors | |
+$dom = Mojo::DOM::->new(<<EOF); | |
+<div> | |
+ <p>One</p> | |
+ <p>Two</p> | |
+</div> | |
+<div> | |
+ <p>Three</p> | |
+ <p>Four</p> | |
+</div> | |
+EOF | |
+is $dom->at('div')->at(':scope > p')->text, 'One', 'right text'; | |
+is $dom->at('p')->at(':scope + p')->text, 'Two', 'right text'; | |
+is $dom->find('div')->last->at(':scope > p')->text, 'Three', 'right text'; | |
+ | |
# Adding nodes | |
$dom = Mojo::DOM->new(<<EOF); | |
<ul> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment