File Coverage

blib/lib/Chart/Kaleido/Plotly.pm
Criterion Covered Total %
statement 66 76 86.8
branch 7 12 58.3
condition n/a
subroutine 17 24 70.8
pod 2 5 40.0
total 92 117 78.6


line stmt bran cond sub pod time code
1             package Chart::Kaleido::Plotly;
2              
3             # ABSTRACT: Export static images of Plotly charts using Kaleido
4              
5 1     1   304633 use 5.010;
  1         8  
6 1     1   5 use strict;
  1         2  
  1         19  
7 1     1   4 use warnings;
  1         2  
  1         48  
8              
9             our $VERSION = '0.010'; # VERSION
10              
11 1     1   628 use Moo;
  1         11829  
  1         8  
12             extends 'Chart::Kaleido';
13              
14 1     1   2108 use File::ShareDir;
  1         26474  
  1         51  
15 1     1   8 use JSON;
  1         2  
  1         9  
16 1     1   643 use MIME::Base64 qw(decode_base64);
  1         659  
  1         61  
17 1     1   8 use Path::Tiny;
  1         2  
  1         44  
18 1     1   487 use Safe::Isa;
  1         505  
  1         114  
19 1     1   677 use Type::Params 1.004000 qw(compile_named_oo);
  1         112422  
  1         12  
20 1     1   1063 use Types::Path::Tiny qw(File Path);
  1         36331  
  1         12  
21 1     1   716 use Types::Standard qw(Int Str Num HashRef InstanceOf Optional Undef);
  1         3  
  1         7  
22 1     1   2150 use namespace::autoclean;
  1         14324  
  1         5  
23              
24              
25             my @text_formats = qw(svg json eps);
26              
27              
28             my $default_plotlyjs = sub {
29             my $plotlyjs;
30             eval {
31             $plotlyjs = File::ShareDir::dist_file( 'Chart-Plotly',
32             'plotly.js/plotly.min.js' );
33             };
34             return $plotlyjs;
35             };
36              
37             has plotlyjs => (
38             is => 'ro',
39             isa => ( Str->plus_coercions( Undef, $default_plotlyjs ) | Undef ),
40             default => $default_plotlyjs,
41             coerce => 1,
42             );
43              
44             has [qw(mathjax topojson)] => (
45             is => 'ro',
46             isa => ( Str | Undef ),
47             coerce => 1,
48             );
49              
50             has mapbox_access_token => (
51             is => 'ro',
52             isa => ( Str | Undef ),
53             );
54              
55              
56             my $PositiveInt = Int->where( sub { $_ > 0 } );
57              
58             has default_format => (
59             is => 'ro',
60             isa => Str,
61             default => 'png',
62             );
63              
64             has default_width => (
65             is => 'ro',
66             isa => $PositiveInt,
67             default => 700,
68             );
69              
70             has default_height => (
71             is => 'ro',
72             isa => $PositiveInt,
73             default => 500,
74             );
75              
76             has '+base_args' => (
77             default => sub {
78             my $self = shift;
79             [ "plotly", @{ $self->_default_chromium_args }, "--no-sandbox" ];
80             }
81             );
82              
83 2     2 0 21 sub all_formats { [qw(png jpg jpeg webp svg pdf eps json)] }
84 0     0 0 0 sub scope_name { 'plotly' }
85 4     4 0 25 sub scope_flags { [qw(plotlyjs mathjax topojson mapbox_access_token)] }
86              
87              
88             sub transform {
89 2     2 1 6 my $self = shift;
90             state $check = compile_named_oo(
91             #<<< no perltidy
92             plot => ( HashRef | InstanceOf["Chart::Plotly::Plot"] ),
93 0     0   0 format => Optional[Str], { default => sub { $self->default_format } },
94 0     0   0 width => $PositiveInt, { default => sub { $self->default_width } },
95 0     0   0 height => $PositiveInt, { default => sub { $self->default_height} },
96 2         11 scale => Num, { default => 1 },
97             #>>>
98             );
99 2         6383 my $arg = $check->(@_);
100 2 50       83 my $plot =
101             $arg->plot->$_isa('Chart::Plotly::Plot')
102             ? $arg->plot->TO_JSON
103             : $arg->plot;
104 2         49 my $format = lc( $arg->format );
105              
106 2 50       5 unless ( grep { $_ eq $format } @{ $self->all_formats } ) {
  16         38  
  2         16  
107             die "Invalid format '$format'. Supported formats: "
108 0         0 . join( ' ', @{ $self->all_formats } );
  0         0  
109             }
110              
111 2         21 my $data = {
112             format => $format,
113             width => $arg->width,
114             height => $arg->height,
115             scale => $arg->scale,
116             data => $plot,
117             };
118              
119 2     0   22 local *PDL::TO_JSON = sub { $_[0]->unpdl };
  0         0  
120 2         23 my $resp = $self->do_transform($data);
121 2 50       20 if ( $resp->{code} != 0 ) {
122 0         0 die $resp->{message};
123             }
124 2         25 my $img = $resp->{result};
125 2 100       9 return ( grep { $_ eq $format } @text_formats )
  6         467  
126             ? $img
127             : decode_base64($img);
128             }
129              
130              
131             sub save {
132 2     2 1 4312 my $self = shift;
133             state $check = compile_named_oo(
134             #<<< no perltidy
135             file => Path,
136             plot => ( HashRef | InstanceOf["Chart::Plotly::Plot"] ),
137             format => Optional[Str],
138 0     0   0 width => $PositiveInt, { default => sub { $self->default_width } },
139 0     0   0 height => $PositiveInt, { default => sub { $self->default_height} },
140 2         21 scale => Num, { default => 1 },
141             #>>>
142             );
143 2         10562 my $arg = $check->(@_);
144 2         74 my $format = $arg->format;
145 2         11 my $file = $arg->file;
146 2 50       10 unless ($format) {
147 2 50       18 if ( $file =~ /\.([^\.]+)$/ ) {
148 2         42 $format = $1;
149             }
150             }
151 2         7 $format = lc($format);
152              
153 2         28 my $img = $self->transform(
154             plot => $arg->plot,
155             format => $format,
156             width => $arg->width,
157             height => $arg->height,
158             scale => $arg->scale
159             );
160 2         84 path($file)->append_raw( { truncate => 1 }, $img );
161             }
162              
163             1;
164              
165             __END__