File Coverage

blib/lib/HTML/TableContent.pm
Criterion Covered Total %
statement 147 158 93.0
branch 23 28 82.1
condition 3 5 60.0
subroutine 23 25 92.0
pod 18 18 100.0
total 214 234 91.4


line stmt bran cond sub pod time code
1             package HTML::TableContent;
2              
3 18     18   249294 use Carp qw/croak carp/;
  18         44  
  18         909  
4 18     18   7445 use Moo;
  18         176071  
  18         90  
5              
6 18     18   29273 use HTML::TableContent::Parser;
  18         70  
  18         586  
7 18     18   149 use HTML::TableContent::Table;
  18         41  
  18         23445  
8              
9             our $VERSION = '0.18';
10              
11             has parser => (
12             is => 'rw',
13             lazy => 1,
14             default => sub { return HTML::TableContent::Parser->new() },
15             );
16              
17             has tables => (
18             is => 'rw',
19             lazy => 1,
20             default => sub { [] },
21             );
22              
23 97     97 1 160 sub all_tables { return @{ $_[0]->tables }; }
  97         2040  
24              
25             sub add_table {
26 9     9 1 1294 my $table = HTML::TableContent::Table->new($_[1]);
27 9         116 push @{ $_[0]->tables }, $table;
  9         143  
28 9         77 return $table;
29             }
30              
31 3     3 1 2395 sub add_caption_selectors { return push (@{ $_[0]->parser->caption_selectors }, @{ $_[1] }); }
  3         60  
  3         13  
32              
33 61     61 1 1868 sub get_table { return $_[0]->tables->[ $_[1] ]; }
34              
35 55     55 1 25321 sub get_first_table { return $_[0]->get_table(0); }
36              
37 0     0 1 0 sub get_last_table { return $_[0]->get_table($_[0]->table_count - 1); }
38              
39 3     3 1 1000 sub clear_table { return splice @{ $_[0]->tables }, $_[1], 1; }
  3         55  
40              
41 1     1 1 479 sub clear_first_table { return shift @{ $_[0]->tables }; }
  1         23  
42              
43 1     1 1 518 sub clear_last_table { return $_[0]->clear_table( $_[0]->table_count - 1 ); }
44              
45 141     141 1 18045 sub table_count { return scalar @{ $_[0]->tables }; }
  141         2868  
46              
47             sub filter_tables {
48 31     31 1 11962 my ( $self, %args ) = @_;
49              
50 31         91 my $tables = [];
51              
52 31         76 my @headers = ();
53 31 100       116 if ( defined $args{headers} ) {
    50          
54 29         57 push @headers, @{ $args{headers} };
  29         97  
55             }
56             elsif ( defined $args{header} ) {
57 2         5 push @headers, $args{header};
58             }
59              
60 31         101 foreach my $table ( $self->all_tables ) {
61 61 100       424 if ( $table->header_exists(@headers) ) {
62 49         238 $table->_filter_headers(@headers);
63 49         89 push @{$tables}, $table;
  49         119  
64             }
65             }
66              
67 31 50 33     137 if ( $args{flex} && !scalar @{$tables} ) {
  0         0  
68 0         0 carp 'none of the passed headers exist in any of the tables aborting filter - %s',
69             join q{ }, @headers;
70 0         0 return;
71             }
72              
73 31         462 return $self->tables($tables);
74             }
75              
76             sub headers_spec {
77 56     56 1 26456 my $self = shift;
78              
79 56         135 my $headers = {};
80 56         189 for my $table ( $self->all_tables ) {
81 106         688 for ( $table->all_headers ) { $headers->{ $_->lc_text }++ }
  250         1312  
82             }
83              
84 56         254 return $headers;
85             }
86              
87             sub headers_exist {
88 2     2 1 10 my ( $self, @headers ) = @_;
89              
90 2         6 my $header_spec = $self->headers_spec;
91              
92 2 50       5 for (@headers) { return 1 if $header_spec->{ lc $_ } }
  2         19  
93              
94 0         0 return 0;
95             }
96              
97             sub raw {
98 10     10 1 1458 my $self = shift;
99              
100 10         35 my @tables = map { $_->raw } $self->all_tables;
  12         335  
101 10         42 return \@tables;
102             }
103              
104             sub render {
105 0     0 1 0 my $self = shift;
106              
107 0         0 my @tables = map { $_->render } $self->all_tables;
  0         0  
108 0         0 my $html = sprintf '%s' x @tables, @tables;
109 0         0 return $html;
110             }
111              
112             sub parse {
113 61     61 1 112298 my ( $self, $data ) = @_;
114              
115 61         751 $data =~ s/\<\!--|--\!\>//g;
116 61         1110 $self->parser->clear_current_tables;
117 61         21188 my $current_tables = $self->parser->parse($data);
118 61         457 push @{ $self->tables }, @{$current_tables};
  61         945  
  61         162  
119 61         358 return $current_tables;
120             }
121              
122             sub parse_file {
123 61     61 1 54987 my ( $self, $file ) = @_;
124              
125 61         1027 $self->parser->clear_current_tables;
126 61         11225 my $current_tables = $self->parser->parse_file($file);
127 61         520 push @{ $self->tables }, @{$current_tables};
  61         959  
  61         178  
128 61         349 return $current_tables;
129             }
130              
131             sub create_table {
132 8     8 1 3940 my ($self, $options) = @_;
133              
134 8   100     77 my $table_options = delete $options->{table} || { };
135              
136 8         44 my $table = $self->add_table($table_options);
137            
138 8 100       30 if ( exists $options->{aoa} ) {
    50          
139 3         13 $table = $self->_create_from_aoa($table, $options);
140             }
141             elsif ( exists $options->{aoh} ) {
142 5         17 $table = $self->_create_from_aoh($table, $options);
143             }
144             else {
145 0         0 croak 'create_tables currently requires an array of arrays or an array of hashes representing the data.';
146             }
147              
148 8         48 return $table;
149             }
150              
151             sub _create_from_aoh {
152 5     5   13 my ($self, $table, $options) = @_;
153              
154 5         10 my $aoh = $options->{aoh};
155 5         11 my @headers = keys %{ $aoh->[0] };
  5         20  
156            
157 5 50       16 if (my $order = $options->{order}){
158 5         12 my @heads = ( );
159 5         8 foreach my $header (@{ $order }) {
  5         12  
160 12         24 push @heads, grep { $_ =~ m/$header/ixms } @headers;
  36         157  
161             }
162 5         15 @headers = @heads;
163             }
164              
165 5 100       18 unless ( defined $options->{no_headers} ) {
166 4         9 for (@headers) {
167 9         27 my $header_options = $self->_create_options('header', $options);
168 9         20 $header_options->{text} = $_;
169 9         32 $table->add_header($header_options);
170             }
171 4         16 @headers = $table->all_headers;
172             }
173              
174 5         31 foreach my $hash ( @{ $aoh } ) {
  5         11  
175 17         70 $options->{cells} = $options->{rows}->[0]->{cells};
176 17         40 my $row_options = $self->_create_options('row', $options);
177 17         54 my $row = $table->add_row($row_options);
178 17         36 for (@headers) {
179 39 100       198 my $text = defined $options->{no_headers} ? $_ : $_->text;
180 39         103 my $cell_options = $self->_create_options('cell', $options);
181 39         83 $cell_options->{text} = $hash->{$text};
182 39         109 my $cell = $row->add_cell($cell_options);
183 39 100       108 unless ( defined $options->{no_headers} ) {
184 30         64 $cell->header($_);
185 30         40 push @{ $_->cells }, $cell;
  30         423  
186             }
187             }
188             }
189              
190 5         34 return $table;
191             }
192              
193             sub _create_from_aoa {
194 3     3   11 my ($self, $table, $options) = @_;
195              
196 3         5 my @aoa = @{ $options->{aoa}};
  3         11  
197              
198 3 100       12 unless ( defined $options->{no_headers} ) {
199 2         4 my $headers = shift @aoa;
200              
201 2         4 foreach my $header ( @{ $headers }) {
  2         6  
202 6         17 my $header_options = $self->_create_options('header', $options);
203              
204 6         13 $header_options->{text} = $header;
205 6         23 $table->add_header($header_options);
206             }
207             }
208              
209 3         10 for my $array ( @aoa ) {
210 9         24 $options->{cells} = $options->{rows}->[0]->{cells};
211 9         20 my $row_options = $self->_create_options('row', $options);
212 9         28 my $row = $table->add_row($row_options);
213            
214 9         15 for my $text ( @{ $array } ) {
  9         39  
215 27         67 my $cell_options = $self->_create_options('cell', $options);
216            
217 27         54 $cell_options->{text} = $text;
218            
219 27         78 my $cell = $row->add_cell($cell_options);
220 27         80 $table->parse_to_column($cell);
221             }
222             }
223              
224 3         9 return $table;
225             }
226              
227             sub _create_options {
228 107     107   206 my ($self, $element, $options) = @_;
229              
230 107         177 my $element_options = { };
231            
232 107 100       271 if ( my $base = $options->{$element} ) {
233 54         81 for ( keys %{ $base } ) {
  54         123  
234 54         122 $element_options->{$_} = $base->{$_};
235             }
236             }
237              
238 107         197 my $elements = $element . 's';
239              
240 107 100       244 if ( my $custom = $options->{$elements} ) {
241 44         76 my $first = shift @{ $options->{$elements} };
  44         84  
242 44         70 for ( keys %{ $first } ) {
  44         104  
243 34         65 $element_options->{$_} = $first->{$_};
244             }
245             }
246              
247 107         215 return $element_options;
248             }
249              
250             __PACKAGE__->meta->make_immutable;
251              
252             1;
253              
254             __END__