File Coverage

blib/lib/Moonshine/Parser/HTML.pm
Criterion Covered Total %
statement 57 57 100.0
branch 11 12 91.6
condition n/a
subroutine 12 12 100.0
pod 6 6 100.0
total 86 87 98.8


line stmt bran cond sub pod time code
1             package Moonshine::Parser::HTML;
2              
3 3     3   350078 use strict;
  3         6  
  3         112  
4 3     3   15 use warnings;
  3         7  
  3         177  
5              
6 3     3   19 use base qw/HTML::Parser/;
  3         18  
  3         2158  
7              
8 3     3   21848 use Moonshine::Element;
  3         152515  
  3         1819  
9              
10             =head1 NAME
11              
12             Moonshine::Parser::HTML - Parse html into a Moonshine::Element object.
13              
14             =head1 VERSION
15              
16             Version 0.07
17              
18             =cut
19              
20             our $VERSION = '0.07';
21              
22             sub new {
23 6     6 1 590278 my $class = shift;
24 6         43 my $self = bless {
25             elements => [ ],
26             closed => [ ],
27             base_element => undef,
28             }, $class;
29 6         49 $self->SUPER::init(@_);
30             }
31              
32             =head1 SYNOPSIS
33              
34             use Moonshine::Parser::HTML;
35              
36             my $parser = Moonshine::Parser::HTML:->new();
37             my $moonshine_element = $parser->parse($html);
38              
39             =head1 SUBROUTINES/METHODS
40              
41             =head2 parse
42              
43             Parse html string into a Moonshine::Element Object.
44              
45             =cut
46              
47             sub parse {
48 8     8 1 920 my ( $self, $data ) = @_;
49            
50 8         169 $self->SUPER::parse($data);
51              
52 8         68 return $self->{base_element};
53             }
54              
55             =head2 parse_file
56              
57             Parse a file that contains html into a Moonshine::Element.
58              
59             =cut
60              
61             sub parse_file {
62 3     3 1 321 my ( $self, $file ) = @_;
63              
64 3         17 $self->SUPER::parse_file($file);
65              
66 3         33 return $self->{base_element};
67             }
68              
69             sub start {
70 62     62 1 188 my ( $self, $tag, $attr) = @_;
71 62         157 my $closed = delete $attr->{'/'};
72            
73 62         273 $attr->{tag} = lc $tag;
74 62         162 $attr->{data} = [ ];
75            
76 62         107 my $element;
77 62 100       171 if ( my $current_element = $self->_current_element ) {
78 55         164 $element = $current_element->add_child($attr);
79             }
80             else {
81 7         76 $element = Moonshine::Element->new($attr);
82 7 100       17696 if ( my $base_element = $self->{base_element} ) {
83             my $action =
84             $self->_is_closed( $base_element->{guid} )
85 1 50       14 ? 'add_after_element'
86             : 'add_child';
87 1         7 $base_element->$action($element);
88             }
89             else {
90 6         16 $self->{base_element} = $element;
91             }
92             }
93 62 100       145099 push @{ $self->{elements} }, $element
  61         814  
94             unless $closed;
95             }
96              
97             sub text {
98 100     100 1 435 my ( $self, $text ) = @_;
99 100 100       775 if ( $text =~ m{\S+}xms ) {
100 27         80 my $element = $self->_current_element;
101 27         208 $text =~ s{^\s+|\s+$}{}g;
102            
103 27 100       95 if ($element->has_children) {
104 1         11 my $data = $element->children;
105 1         8 push @{ $element->{data} }, @{ $data };
  1         3  
  1         3  
106 1         4 $element->children([]);
107             }
108            
109 27         346 $element->data($text);
110             }
111             }
112              
113             sub end {
114 61     61 1 571 my ( $self, $tag, $origtext ) = @_;
115 61         103 my $close = pop @{ $self->{elements} };
  61         155  
116 61         120 push @{ $self->{closed} }, $close->{guid};
  61         347  
117             }
118              
119             sub _current_element {
120 89     89   152 my $count = scalar @{ $_[0]->{elements} };
  89         273  
121 89         386 return $_[0]->{elements}[ $count - 1 ];
122             }
123              
124             sub _is_closed {
125 1     1   2 return grep { $_ =~ m/^$_[1]$/ } @{ $_[0]->{closed} };
  1         27  
  1         4  
126             }
127              
128             =head1 AUTHOR
129              
130             Robert Acock, C<< >>
131              
132             =head1 BUGS
133              
134             Please report any bugs or feature requests to C, or through
135             the web interface at L. I will be notified, and then you'll
136             automatically be notified of progress on your bug as I make changes.
137              
138             =head1 SUPPORT
139              
140             You can find documentation for this module with the perldoc command.
141              
142             perldoc Moonshine::Parser
143              
144             You can also look for information at:
145              
146             =over 4
147              
148             =item * RT: CPAN's request tracker (report bugs here)
149              
150             L
151              
152             =item * Search CPAN
153              
154             L
155              
156             =back
157              
158             =head1 ACKNOWLEDGEMENTS
159              
160             =head1 LICENSE AND COPYRIGHT
161              
162             Copyright 2017->2025 Robert Acock.
163              
164             This program is free software; you can redistribute it and/or modify it
165             under the terms of the the Artistic License (2.0). You may obtain a
166             copy of the full license at:
167              
168             L
169              
170             Any use, modification, and distribution of the Standard or Modified
171             Versions is governed by this Artistic License. By using, modifying or
172             distributing the Package, you accept this license. Do not use, modify,
173             or distribute the Package, if you do not accept this license.
174              
175             If your Modified Version has been derived from a Modified Version made
176             by someone other than you, you are nevertheless required to ensure that
177             your Modified Version complies with the requirements of this license.
178              
179             This license does not grant you the right to use any trademark, service
180             mark, tradename, or logo of the Copyright Holder.
181              
182             This license includes the non-exclusive, worldwide, free-of-charge
183             patent license to make, have made, use, offer to sell, sell, import and
184             otherwise transfer the Package with respect to any patent claims
185             licensable by the Copyright Holder that are necessarily infringed by the
186             Package. If you institute patent litigation (including a cross-claim or
187             counterclaim) against any party alleging that the Package constitutes
188             direct or contributory patent infringement, then this Artistic License
189             to you shall terminate on the date that such litigation is filed.
190              
191             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
192             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
193             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
194             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
195             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
196             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
197             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
198             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
199              
200             =cut
201              
202             1; # End of Moonshine::Parser