Skip to content

Commit

Permalink
added ancestors method to Mojo::DOM
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Aug 8, 2013
1 parent b43248e commit b8307fd
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 12 deletions.
1 change: 1 addition & 0 deletions Changes
@@ -1,5 +1,6 @@

4.24 2013-08-08
- Added ancestors method to Mojo::DOM.
- Fixed bug where Mojo::IOLoop::Stream timeout was not always available.

4.23 2013-08-01
Expand Down
39 changes: 31 additions & 8 deletions lib/Mojo/DOM.pm
Expand Up @@ -38,6 +38,13 @@ sub new {

sub all_text { shift->_content(1, @_) }

sub ancestors {
my $self = shift;
my $xml = $self->xml;
return Mojo::Collection->new(map { $self->new->tree($_)->xml($xml) }
@{$self->_ancestors});
}

sub append { shift->_add(1, @_) }

sub append_content {
Expand Down Expand Up @@ -162,14 +169,8 @@ sub replace_content {

sub root {
my $self = shift;

my $root = $self->tree;
while ($root->[0] eq 'tag') {
last unless my $parent = $root->[3];
$root = $parent;
}

return $self->new->tree($root)->xml($self->xml);
return $self unless my $tree = $self->_ancestors(1)->[-1];
return $self->new->tree($tree)->xml($self->xml);
}

sub strip {
Expand Down Expand Up @@ -238,6 +239,18 @@ sub _add {
return $self;
}

sub _ancestors {
my ($self, $root) = @_;

my @ancestors;
my $parent = $self->tree;
push @ancestors, $parent
while ($parent->[0] eq 'tag') && ($parent = $parent->[3]);
pop @ancestors unless $root;

return \@ancestors;
}

sub _content {
my $tree = shift->tree;
return _text(_elements($tree), shift, _trim($tree, @_));
Expand Down Expand Up @@ -454,6 +467,16 @@ enabled by default.
# "foo\nbarbaz\n"
$dom->parse("<div>foo\n<p>bar</p>baz\n</div>")->div->all_text(0);
=head2 ancestors
my $collection = $dom->ancestors;
Return a L<Mojo::Collection> object containing the ancestors of this element
as L<Mojo::DOM> objects, similar to C<children>.
# Show type of random ancestor element
say $dom->ancestors->shuffle->first->type;
=head2 append
$dom = $dom->append('<p>Hi!</p>');
Expand Down
8 changes: 4 additions & 4 deletions lib/Mojo/DOM/HTML.pm
Expand Up @@ -217,16 +217,16 @@ sub _render {
return $tree->[1] if $e eq 'raw';

# DOCTYPE
return "<!DOCTYPE" . $tree->[1] . ">" if $e eq 'doctype';
return '<!DOCTYPE' . $tree->[1] . '>' if $e eq 'doctype';

# Comment
return "<!--" . $tree->[1] . "-->" if $e eq 'comment';
return '<!--' . $tree->[1] . '-->' if $e eq 'comment';

# CDATA
return "<![CDATA[" . $tree->[1] . "]]>" if $e eq 'cdata';
return '<![CDATA[' . $tree->[1] . ']]>' if $e eq 'cdata';

# Processing instruction
return "<?" . $tree->[1] . "?>" if $e eq 'pi';
return '<?' . $tree->[1] . '?>' if $e eq 'pi';

# Start tag
my $start = $e eq 'root' ? 1 : 2;
Expand Down
10 changes: 10 additions & 0 deletions t/mojo/dom.t
Expand Up @@ -132,6 +132,9 @@ is $dom->next, undef, 'no siblings';
is $dom->previous, undef, 'no siblings';
is $dom->at('foo > a')->next, undef, 'no next sibling';
is $dom->at('foo > simple')->previous, undef, 'no previous sibling';
is_deeply [$dom->at('simple')->ancestors->pluck('type')->each], ['foo'],
'right results';
ok !$dom->at('simple')->ancestors->first->xml, 'XML mode not active';

# Class and ID
$dom = Mojo::DOM->new->parse('<div id="id" class="class">a</div>');
Expand Down Expand Up @@ -172,6 +175,10 @@ $dom->find('p')->each(sub { push @p, $_->attr('id') });
is_deeply \@p, [qw(foo bar)], 'found all p elements';
my $ids = [qw(container header logo buttons buttons content)];
is_deeply \@div, $ids, 'found all div elements';
is_deeply [$dom->at('p')->ancestors->pluck('type')->each],
[qw(div div div body html)], 'right results';
is_deeply [$dom->at('html')->ancestors->each], [], 'no results';
is_deeply [$dom->ancestors->each], [], 'no results';

# Script tag
$dom = Mojo::DOM->new->parse(<<EOF);
Expand Down Expand Up @@ -411,6 +418,8 @@ $dom = Mojo::DOM->new->parse(<<EOF);
EOF
ok $dom->xml, 'XML mode detected';
is $dom->find('rss')->[0]->attr('version'), '2.0', 'right version';
is_deeply [$dom->at('title')->ancestors->pluck('type')->each],
[qw(channel rss)], 'right results';
is $dom->at('extension')->attr('foo:id'), 'works', 'right id';
like $dom->at('#works')->text, qr/\[awesome\]\]/, 'right text';
like $dom->at('[id="works"]')->text, qr/\[awesome\]\]/, 'right text';
Expand All @@ -424,6 +433,7 @@ ok $dom->at('rss')->xml, 'XML mode active';
ok $dom->at('extension')->parent->xml, 'XML mode active';
ok $dom->at('extension')->root->xml, 'XML mode active';
ok $dom->children('rss')->first->xml, 'XML mode active';
ok $dom->at('title')->ancestors->first->xml, 'XML mode active';

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

0 comments on commit b8307fd

Please sign in to comment.