File Coverage

blib/lib/Text/Table/HTML/DataTables.pm
Criterion Covered Total %
statement 8 92 8.7
branch 0 40 0.0
condition 0 12 0.0
subroutine 3 8 37.5
pod 1 2 50.0
total 12 154 7.7


line stmt bran cond sub pod time code
1             package Text::Table::HTML::DataTables;
2              
3 1     1   392200 use 5.010001;
  1         2  
4 1     1   9 use strict;
  1         2  
  1         37  
5 1     1   6 use warnings;
  1         5  
  1         980  
6              
7             our $AUTHORITY = 'cpan:PERLANCAR'; # AUTHORITY
8             our $DATE = '2025-05-15'; # DATE
9             our $DIST = 'Text-Table-HTML-DataTables'; # DIST
10             our $VERSION = '0.013'; # VERSION
11              
12             sub _encode {
13 0     0     state $load = do { require HTML::Entities };
  0            
14 0           my $val = shift;
15             # encode_entities change 0 (false) to empty string so we need to filter the
16             # value first
17 0 0         if (!defined $val) {
    0          
18 0           "";
19             } elsif (!$val) {
20 0           "$val";
21             } else {
22 0           HTML::Entities::encode_entities($val);
23             }
24             }
25              
26             sub _escape_uri {
27 0     0     require URI::Escape;
28 0           URI::Escape::uri_escape(shift, "^A-Za-z0-9\-\._~/:"); # : for drive notation on Windows
29             }
30              
31             sub table {
32 0     0 1   require HTML::Entities;
33 0           require JSON::PP;
34              
35 0           my %params = @_;
36 0 0         my $rows = $params{rows} or die "Must provide rows!";
37 0   0       my $default_length = int($params{default_length} // 1000);
38             my $library_link_mode = $params{library_link_mode} //
39 0   0       $ENV{PERL_TEXT_TABLE_HTML_DATATABLES_OPT_LIBRARY_LINK_MODE} // 'local';
      0        
40              
41 0           my $max_index = _max_array_index($rows);
42              
43             # here we go...
44 0           my @table;
45              
46             # load css/js
47 0           push @table, "\n";
48 0           push @table, "\n";
49              
50 0 0         push @table, qq().HTML::Entities::encode_entities($params{caption}).qq(\n) if defined $params{caption};
51              
52 0           my $jquery_ver = '2.2.4';
53 0           my $datatables_ver = '1.10.22';
54 0 0         if ($library_link_mode eq 'embed') {
    0          
55 0           require File::ShareDir;
56 0           require File::Slurper;
57 0           my $dist_dir = File::ShareDir::dist_dir('Text-Table-HTML-DataTables');
58 0           my $path;
59              
60 0           $path = "$dist_dir/datatables-$datatables_ver/datatables.css";
61 0 0         -r $path or die "Can't embed $path: $!";
62 0           push @table, "\n\n\n";
63              
64 0           $path = "$dist_dir/jquery-$jquery_ver/jquery-$jquery_ver.min.js";
65 0 0         -r $path or die "Can't embed $path: $!";
66 0           push @table, "\n\n\n";
67              
68              
69 0           $path = "$dist_dir/datatables-$datatables_ver/datatables.js";
70 0 0         -r $path or die "Can't embed $path: $!";
71 0           push @table, "\n\n\n";
72              
73             } elsif ($library_link_mode eq 'local') {
74 0           require File::ShareDir;
75 0           my $dist_dir = File::ShareDir::dist_dir('Text-Table-HTML-DataTables');
76 0 0         $dist_dir =~ s!\\!/!g if $^O eq 'MSWin32';
77 0           push @table, qq(\n);
78 0           push @table, qq(\n);
79 0           push @table, qq(\n);
80             } else {
81 0           die "Unknown value for the 'library_link_mode' option: '$library_link_mode', please use one of local|embed";
82             }
83              
84 0           push @table, ''."\n\n";
96 0           push @table, "\n\n";
97              
98 0           push @table, "\n";
99 0           push @table, "\n"; \n) if defined $params{caption}; \n"; $in_header++ } \n" } \n" } ", ", \n", \n";
100 0 0         push @table, qq(
).HTML::Entities::encode_entities($params{caption}).qq(
101              
102             # then the data
103 0           my $i = -1;
104 0           foreach my $row ( @{ $rows }[0..$#$rows] ) {
  0            
105 0           $i++;
106 0           my $in_header;
107 0 0         if ($params{header_row}) {
108 0 0         if ($i == 0) { push @table, "
  0            
  0            
109 0 0         if ($i == 1) { push @table, "
  0            
110             } else {
111 0 0         if ($i == 1) { push @table, "
  0            
112             }
113             push @table, join(
114             "",
115             "
116 0           (map {(
117 0 0 0       $in_header ? "" : "",
    0          
118             _encode($row->[$_] // ''),
119             $in_header ? "" : "
120             )} 0..$max_index),
121             "
122             );
123 0 0 0       if ($i == 0 && $params{header_row}) {
124 0           push @table, "\n";
125             }
126             }
127              
128 0           push @table, "
129 0           push @table, "
\n";
130 0           push @table, "\n\n";
131              
132 0           push @table, "\n";
133              
134 0           return join("", grep {$_} @table);
  0            
135             }
136              
137             # FROM_MODULE: PERLANCAR::List::Util::PP
138             # BEGIN_BLOCK: max
139             sub max {
140 0 0   0 0   return undef unless @_; ## no critic: Subroutines::ProhibitExplicitReturnUndef
141 0           my $res = $_[0];
142 0           my $i = 0;
143 0 0         while (++$i < @_) { $res = $_[$i] if $_[$i] > $res }
  0            
144 0           $res;
145             }
146             # END_BLOCK: max
147              
148             # return highest top-index from all rows in case they're different lengths
149             sub _max_array_index {
150 0     0     my $rows = shift;
151 0           return max( map { $#$_ } @$rows );
  0            
152             }
153              
154             1;
155             # ABSTRACT: Generate HTML table with jQuery and DataTables plugin
156              
157             __END__