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   230799 use Carp qw/croak carp/;
  18         31  
  18         811  
4 18     18   8031 use Moo;
  18         174246  
  18         74  
5              
6 18     18   24962 use HTML::TableContent::Parser;
  18         50  
  18         550  
7 18     18   105 use HTML::TableContent::Table;
  18         18  
  18         22972  
8              
9             our $VERSION = '0.17';
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 76 sub all_tables { return @{ $_[0]->tables }; }
  97         1880  
24              
25             sub add_table {
26 9     9 1 1042 my $table = HTML::TableContent::Table->new($_[1]);
27 9         71 push @{ $_[0]->tables }, $table;
  9         127  
28 9         40 return $table;
29             }
30              
31 3     3 1 1710 sub add_caption_selectors { return push (@{ $_[0]->parser->caption_selectors }, @{ $_[1] }); }
  3         56  
  3         8  
32              
33 61     61 1 1521 sub get_table { return $_[0]->tables->[ $_[1] ]; }
34              
35 55     55 1 17249 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 498 sub clear_table { return splice @{ $_[0]->tables }, $_[1], 1; }
  3         48  
40              
41 1     1 1 260 sub clear_first_table { return shift @{ $_[0]->tables }; }
  1         21  
42              
43 1     1 1 238 sub clear_last_table { return $_[0]->clear_table( $_[0]->table_count - 1 ); }
44              
45 141     141 1 13792 sub table_count { return scalar @{ $_[0]->tables }; }
  141         2804  
46              
47             sub filter_tables {
48 31     31 1 8514 my ( $self, %args ) = @_;
49              
50 31         56 my $tables = [];
51              
52 31         52 my @headers = ();
53 31 100       87 if ( defined $args{headers} ) {
    50          
54 29         36 push @headers, @{ $args{headers} };
  29         94  
55             }
56             elsif ( defined $args{header} ) {
57 2         3 push @headers, $args{header};
58             }
59              
60 31         73 foreach my $table ( $self->all_tables ) {
61 61 100       284 if ( $table->header_exists(@headers) ) {
62 49         132 $table->_filter_headers(@headers);
63 49         45 push @{$tables}, $table;
  49         73  
64             }
65             }
66              
67 31 50 33     96 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         393 return $self->tables($tables);
74             }
75              
76             sub headers_spec {
77 56     56 1 18629 my $self = shift;
78              
79 56         77 my $headers = {};
80 56         131 for my $table ( $self->all_tables ) {
81 106         445 for ( $table->all_headers ) { $headers->{ $_->lc_text }++ }
  250         783  
82             }
83              
84 56         154 return $headers;
85             }
86              
87             sub headers_exist {
88 2     2 1 6 my ( $self, @headers ) = @_;
89              
90 2         3 my $header_spec = $self->headers_spec;
91              
92 2 50       4 for (@headers) { return 1 if $header_spec->{ lc $_ } }
  2         15  
93              
94 0         0 return 0;
95             }
96              
97             sub raw {
98 10     10 1 935 my $self = shift;
99              
100 10         20 my @tables = map { $_->raw } $self->all_tables;
  12         228  
101 10         28 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 73705 my ( $self, $data ) = @_;
114              
115 61         656 $data =~ s/\<\!--|--\!\>//g;
116 61         1093 $self->parser->clear_current_tables;
117 61         15898 my $current_tables = $self->parser->parse($data);
118 61         325 push @{ $self->tables }, @{$current_tables};
  61         906  
  61         127  
119 61         299 return $current_tables;
120             }
121              
122             sub parse_file {
123 61     61 1 36804 my ( $self, $file ) = @_;
124              
125 61         922 $self->parser->clear_current_tables;
126 61         8576 my $current_tables = $self->parser->parse_file($file);
127 61         341 push @{ $self->tables }, @{$current_tables};
  61         831  
  61         108  
128 61         235 return $current_tables;
129             }
130              
131             sub create_table {
132 8     8 1 3024 my ($self, $options) = @_;
133              
134 8   100     43 my $table_options = delete $options->{table} || { };
135              
136 8         25 my $table = $self->add_table($table_options);
137            
138 8 100       21 if ( exists $options->{aoa} ) {
    50          
139 3         11 $table = $self->_create_from_aoa($table, $options);
140             }
141             elsif ( exists $options->{aoh} ) {
142 5         10 $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         36 return $table;
149             }
150              
151             sub _create_from_aoh {
152 5     5   7 my ($self, $table, $options) = @_;
153              
154 5         6 my $aoh = $options->{aoh};
155 5         6 my @headers = keys %{ $aoh->[0] };
  5         22  
156            
157 5 50       15 if (my $order = $options->{order}){
158 5         8 my @heads = ( );
159 5         5 foreach my $header (@{ $order }) {
  5         6  
160 12         14 push @heads, grep { $_ =~ m/$header/ixms } @headers;
  36         137  
161             }
162 5         13 @headers = @heads;
163             }
164              
165 5 100       13 unless ( defined $options->{no_headers} ) {
166 4         8 for (@headers) {
167 9         14 my $header_options = $self->_create_options('header', $options);
168 9         11 $header_options->{text} = $_;
169 9         23 $table->add_header($header_options);
170             }
171 4         11 @headers = $table->all_headers;
172             }
173              
174 5         19 foreach my $hash ( @{ $aoh } ) {
  5         7  
175 17         45 $options->{cells} = $options->{rows}->[0]->{cells};
176 17         25 my $row_options = $self->_create_options('row', $options);
177 17         35 my $row = $table->add_row($row_options);
178 17         25 for (@headers) {
179 39 100       123 my $text = defined $options->{no_headers} ? $_ : $_->text;
180 39         55 my $cell_options = $self->_create_options('cell', $options);
181 39         66 $cell_options->{text} = $hash->{$text};
182 39         70 my $cell = $row->add_cell($cell_options);
183 39 100       74 unless ( defined $options->{no_headers} ) {
184 30         40 $cell->header($_);
185 30         19 push @{ $_->cells }, $cell;
  30         359  
186             }
187             }
188             }
189              
190 5         21 return $table;
191             }
192              
193             sub _create_from_aoa {
194 3     3   4 my ($self, $table, $options) = @_;
195              
196 3         5 my @aoa = @{ $options->{aoa}};
  3         7  
197              
198 3 100       9 unless ( defined $options->{no_headers} ) {
199 2         3 my $headers = shift @aoa;
200              
201 2         3 foreach my $header ( @{ $headers }) {
  2         4  
202 6         10 my $header_options = $self->_create_options('header', $options);
203              
204 6         10 $header_options->{text} = $header;
205 6         16 $table->add_header($header_options);
206             }
207             }
208              
209 3         5 for my $array ( @aoa ) {
210 9         13 $options->{cells} = $options->{rows}->[0]->{cells};
211 9         18 my $row_options = $self->_create_options('row', $options);
212 9         19 my $row = $table->add_row($row_options);
213            
214 9         11 for my $text ( @{ $array } ) {
  9         36  
215 27         41 my $cell_options = $self->_create_options('cell', $options);
216            
217 27         32 $cell_options->{text} = $text;
218            
219 27         51 my $cell = $row->add_cell($cell_options);
220 27         56 $table->parse_to_column($cell);
221             }
222             }
223              
224 3         6 return $table;
225             }
226              
227             sub _create_options {
228 107     107   99 my ($self, $element, $options) = @_;
229              
230 107         94 my $element_options = { };
231            
232 107 100       171 if ( my $base = $options->{$element} ) {
233 54         46 for ( keys %{ $base } ) {
  54         76  
234 54         79 $element_options->{$_} = $base->{$_};
235             }
236             }
237              
238 107         127 my $elements = $element . 's';
239              
240 107 100       162 if ( my $custom = $options->{$elements} ) {
241 44         53 my $first = shift @{ $options->{$elements} };
  44         50  
242 44         40 for ( keys %{ $first } ) {
  44         65  
243 34         40 $element_options->{$_} = $first->{$_};
244             }
245             }
246              
247 107         128 return $element_options;
248             }
249              
250             __PACKAGE__->meta->make_immutable;
251              
252             1;
253              
254             __END__