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   1130883 use Carp qw/croak carp/;
  18         197  
  18         1032  
4 18     18   10033 use Moo;
  18         209982  
  18         90  
5              
6 18     18   35350 use HTML::TableContent::Parser;
  18         69  
  18         638  
7 18     18   141 use HTML::TableContent::Table;
  18         38  
  18         34506  
8              
9             our $VERSION = '1.00';
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 153 sub all_tables { return @{ $_[0]->tables }; }
  97         2281  
24              
25             sub add_table {
26 9     9 1 1600 my $table = HTML::TableContent::Table->new($_[1]);
27 9         113 push @{ $_[0]->tables }, $table;
  9         172  
28 9         69 return $table;
29             }
30              
31 3     3 1 2761 sub add_caption_selectors { return push (@{ $_[0]->parser->caption_selectors }, @{ $_[1] }); }
  3         75  
  3         14  
32              
33 61     61 1 2046 sub get_table { return $_[0]->tables->[ $_[1] ]; }
34              
35 55     55 1 35231 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 1343 sub clear_table { return splice @{ $_[0]->tables }, $_[1], 1; }
  3         64  
40              
41 1     1 1 637 sub clear_first_table { return shift @{ $_[0]->tables }; }
  1         26  
42              
43 1     1 1 703 sub clear_last_table { return $_[0]->clear_table( $_[0]->table_count - 1 ); }
44              
45 141     141 1 20726 sub table_count { return scalar @{ $_[0]->tables }; }
  141         3457  
46              
47             sub filter_tables {
48 31     31 1 16832 my ( $self, %args ) = @_;
49              
50 31         71 my $tables = [];
51              
52 31         62 my @headers = ();
53 31 100       102 if ( defined $args{headers} ) {
    50          
54 29         47 push @headers, @{ $args{headers} };
  29         77  
55             }
56             elsif ( defined $args{header} ) {
57 2         5 push @headers, $args{header};
58             }
59              
60 31         114 foreach my $table ( $self->all_tables ) {
61 61 100       400 if ( $table->header_exists(@headers) ) {
62 49         190 $table->_filter_headers(@headers);
63 49         73 push @{$tables}, $table;
  49         122  
64             }
65             }
66              
67 31 50 33     131 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         529 return $self->tables($tables);
74             }
75              
76             sub headers_spec {
77 56     56 1 35448 my $self = shift;
78              
79 56         111 my $headers = {};
80 56         141 for my $table ( $self->all_tables ) {
81 106         662 for ( $table->all_headers ) { $headers->{ $_->lc_text }++ }
  250         1111  
82             }
83              
84 56         276 return $headers;
85             }
86              
87             sub headers_exist {
88 2     2 1 8 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         18  
93              
94 0         0 return 0;
95             }
96              
97             sub raw {
98 10     10 1 1541 my $self = shift;
99              
100 10         29 my @tables = map { $_->raw } $self->all_tables;
  12         308  
101 10         44 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 156099 my ( $self, $data ) = @_;
114              
115 61         760 $data =~ s/\<\!--|--\!\>//g;
116 61         1387 $self->parser->clear_current_tables;
117 61         23797 my $current_tables = $self->parser->parse($data);
118 61         490 push @{ $self->tables }, @{$current_tables};
  61         1008  
  61         141  
119 61         291 return $current_tables;
120             }
121              
122             sub parse_file {
123 61     61 1 80620 my ( $self, $file ) = @_;
124              
125 61         1172 $self->parser->clear_current_tables;
126 61         12373 my $current_tables = $self->parser->parse_file($file);
127 61         503 push @{ $self->tables }, @{$current_tables};
  61         1055  
  61         180  
128 61         297 return $current_tables;
129             }
130              
131             sub create_table {
132 8     8 1 4495 my ($self, $options) = @_;
133              
134 8   100     56 my $table_options = delete $options->{table} || { };
135              
136 8         62 my $table = $self->add_table($table_options);
137            
138 8 100       31 if ( exists $options->{aoa} ) {
    50          
139 3         15 $table = $self->_create_from_aoa($table, $options);
140             }
141             elsif ( exists $options->{aoh} ) {
142 5         18 $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         90 return $table;
149             }
150              
151             sub _create_from_aoh {
152 5     5   14 my ($self, $table, $options) = @_;
153              
154 5         12 my $aoh = $options->{aoh};
155 5         8 my @headers = keys %{ $aoh->[0] };
  5         24  
156            
157 5 50       23 if (my $order = $options->{order}){
158 5         10 my @heads = ( );
159 5         9 foreach my $header (@{ $order }) {
  5         17  
160 12         23 push @heads, grep { $_ =~ m/$header/ixms } @headers;
  36         210  
161             }
162 5         20 @headers = @heads;
163             }
164              
165 5 100       18 unless ( defined $options->{no_headers} ) {
166 4         8 for (@headers) {
167 9         31 my $header_options = $self->_create_options('header', $options);
168 9         23 $header_options->{text} = $_;
169 9         32 $table->add_header($header_options);
170             }
171 4         16 @headers = $table->all_headers;
172             }
173              
174 5         34 foreach my $hash ( @{ $aoh } ) {
  5         13  
175 17         85 $options->{cells} = $options->{rows}->[0]->{cells};
176 17         44 my $row_options = $self->_create_options('row', $options);
177 17         60 my $row = $table->add_row($row_options);
178 17         44 for (@headers) {
179 39 100       196 my $text = defined $options->{no_headers} ? $_ : $_->text;
180 39         98 my $cell_options = $self->_create_options('cell', $options);
181 39         151 $cell_options->{text} = $hash->{$text};
182 39         112 my $cell = $row->add_cell($cell_options);
183 39 100       113 unless ( defined $options->{no_headers} ) {
184 30         85 $cell->header($_);
185 30         40 push @{ $_->cells }, $cell;
  30         489  
186             }
187             }
188             }
189              
190 5         40 return $table;
191             }
192              
193             sub _create_from_aoa {
194 3     3   12 my ($self, $table, $options) = @_;
195              
196 3         6 my @aoa = @{ $options->{aoa}};
  3         10  
197              
198 3 100       13 unless ( defined $options->{no_headers} ) {
199 2         5 my $headers = shift @aoa;
200              
201 2         4 foreach my $header ( @{ $headers }) {
  2         6  
202 6         20 my $header_options = $self->_create_options('header', $options);
203              
204 6         15 $header_options->{text} = $header;
205 6         45 $table->add_header($header_options);
206             }
207             }
208              
209 3         11 for my $array ( @aoa ) {
210 9         24 $options->{cells} = $options->{rows}->[0]->{cells};
211 9         25 my $row_options = $self->_create_options('row', $options);
212 9         31 my $row = $table->add_row($row_options);
213            
214 9         16 for my $text ( @{ $array } ) {
  9         22  
215 27         64 my $cell_options = $self->_create_options('cell', $options);
216            
217 27         59 $cell_options->{text} = $text;
218            
219 27         76 my $cell = $row->add_cell($cell_options);
220 27         81 $table->parse_to_column($cell);
221             }
222             }
223              
224 3         12 return $table;
225             }
226              
227             sub _create_options {
228 107     107   217 my ($self, $element, $options) = @_;
229              
230 107         205 my $element_options = { };
231            
232 107 100       270 if ( my $base = $options->{$element} ) {
233 54         79 for ( keys %{ $base } ) {
  54         136  
234 54         129 $element_options->{$_} = $base->{$_};
235             }
236             }
237              
238 107         261 my $elements = $element . 's';
239              
240 107 100       238 if ( my $custom = $options->{$elements} ) {
241 44         72 my $first = shift @{ $options->{$elements} };
  44         110  
242 44         64 for ( keys %{ $first } ) {
  44         125  
243 34         74 $element_options->{$_} = $first->{$_};
244             }
245             }
246              
247 107         237 return $element_options;
248             }
249              
250             __PACKAGE__->meta->make_immutable;
251              
252             1;
253              
254             __END__