File Coverage

blib/lib/Aozora2Epub/Epub.pm
Criterion Covered Total %
statement 44 116 37.9
branch 0 14 0.0
condition 1 6 16.6
subroutine 14 29 48.2
pod 1 13 7.6
total 60 178 33.7


line stmt bran cond sub pod time code
1             package Aozora2Epub::Epub;
2 4     4   27 use strict;
  4         9  
  4         155  
3 4     4   48 use warnings;
  4         8  
  4         190  
4 4     4   23 use utf8;
  4         6  
  4         28  
5 4     4   2415 use File::ShareDir qw(dist_dir);
  4         128145  
  4         280  
6 4     4   45 use Path::Tiny;
  4         53  
  4         270  
7 4     4   2573 use Text::Xslate qw/mark_raw/;
  4         57529  
  4         396  
8 4     4   2487 use UUID qw/uuid/;
  4         6038  
  4         18  
9 4     4   2719 use HTTP::Date qw/time2isoz/;
  4         22493  
  4         401  
10 4     4   33 use File::Find qw//;
  4         6  
  4         115  
11 4     4   3212 use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
  4         290354  
  4         820  
12 4     4   40 use Aozora2Epub::CachedGet;
  4         12  
  4         299  
13 4     4   26 use Aozora2Epub::Gensym;
  4         31  
  4         235  
14 4     4   25 use base qw/Class::Accessor/;
  4         9  
  4         588  
15             __PACKAGE__->mk_accessors(qw/assets/);
16              
17             our $VERSION = "0.05";
18              
19             sub new {
20 37     37 1 111 my $class = shift;
21              
22 37   33     514 my $tmpdir = ($ENV{EPUB_TMP_DIR} || Path::Tiny->tempdir);
23 37         31357 my $sharedir = path(dist_dir('Aozora2Epub'), 'basic');
24 37         3631 my $tx = Text::Xslate->new();
25 37         12964 return bless {
26             tmpdir=>$tmpdir,
27             sharedir=>$sharedir,
28             xslate=>$tx,
29             assets=>[],
30             }, $class;
31             }
32              
33             sub dest_file {
34 0     0 0   my ($self, @path) = @_;
35 0           my $dest = path($self->{tmpdir}, @path);
36 0           my $dir = path($dest->dirname);
37 0 0         $dir->is_dir or $dir->mkdir;
38 0           return $dest;
39             }
40              
41             sub copy {
42 0     0 0   my ($self, $file) = @_;
43 0           my $dest = $self->dest_file($file);
44 0           path($self->{sharedir}, $file)->copy($dest);
45             }
46              
47             sub slurp {
48 0     0 0   my ($self, $file) = @_;
49 0           return path($self->{sharedir}, $file)->slurp_utf8;
50             }
51              
52             sub render_to {
53 0     0 0   my ($self, $template, $to, $args) = @_;
54 0           my $dest = $self->dest_file($to);
55 0           my $text = $self->{xslate}->render_string($self->slurp($template), $args);
56 0           $dest->spew_utf8($text);
57             }
58              
59             sub render {
60 0     0 0   my ($self, $template, $args) = @_;
61 0           $self->render_to($template, $template, $args);
62             }
63              
64             sub write_string {
65 0     0 0   my ($self, $bin, $to) = @_;
66 0           my $dest = $self->dest_file($to);
67 0           $dest->spew({binmode => ":raw"}, $bin);
68             }
69              
70             sub files_in_dir {
71 0     0 0   my $dir = shift;
72 0           my @files;
73 0 0 0 0     File::Find::find(sub { push @files, $File::Find::name unless -d || /^\./ },
74 0           $dir);
75 0           return \@files;
76             }
77              
78             sub save {
79 0     0 0   my ($self, $epub_path) = @_;
80              
81 0           my $zip_error;
82 0     0     Archive::Zip::setErrorHandler( sub { $zip_error = shift } );
  0            
83 0           my $zip = Archive::Zip->new();
84 0           my $dir = $self->{tmpdir};
85 0           my $files = files_in_dir($dir);
86 0           for my $file (@$files) {
87 0           my $relative_path = $file;
88 0           $relative_path =~ s{^$dir/}{};
89 0 0         $zip->addFile($file, $relative_path)
90             or die "Error adding file $file to zip: not a readable plain file";
91             }
92              
93 0 0         unless ($zip->writeToFileNamed($epub_path) == AZ_OK) {
94 0           die 'Error writing zip file: ', $zip_error;
95             }
96             }
97              
98             sub add_gaiji {
99 0     0 0   my ($self, $bin, $path) = @_;
100 0           $self->write_string($bin, "EPUB/gaiji/$path");
101 0           push @{$self->assets}, "gaiji/$path";
  0            
102             }
103              
104             sub add_image {
105 0     0 0   my ($self, $bin, $path) = @_;
106 0           $self->write_string($bin, "EPUB/images/$path");
107 0           push @{$self->assets}, "images/$path";
  0            
108             }
109              
110             sub _add_name_to_array {
111 0     0     my $array = shift;
112             return [ map {
113 0           {
114 0           name => gensym,
115             value => $_
116             }
117             } @$array ];
118             }
119              
120             sub set_cover {
121 0     0 0   my ($self, $cover_jpg) = @_;
122 0           path($cover_jpg)->copy($self->dest_file('EPUB/cover.jpg'));
123 0           $self->{has_coverpage} = 1;
124             }
125              
126             sub build_from_doc {
127 0     0 0   my ($self, $doc) = @_;
128              
129 0           $self->{doc} = $doc;
130              
131 0           my $toc = $doc->toc;
132 0           my $resnum = 0;
133             my $args = {
134             has_coverpage => $self->{has_coverpage},
135             uuid => uuid(),
136             title => $self->{doc}->title,
137             author => $self->{doc}->author,
138             date => time2isoz(time),
139             sections => $self->{doc}->toc,
140             has_sections => (@$toc ? 1 : 0),
141             files => $self->{doc}->files,
142             has_okuzuke => $doc->bib_info,
143             bib_info => mark_raw($self->{doc}->bib_info),
144 0 0         notation_notes => mark_raw($self->{doc}->notation_notes),
145             assets => _add_name_to_array($self->assets),
146             };
147              
148 0           $self->copy("mimetype");
149 0           $self->copy("META-INF/container.xml");
150 0           $self->copy("META-INF/com.apple.ibooks.display-options.xml");
151 0           $self->copy("EPUB/styles/style.css");
152              
153 0           $self->render("EPUB/content.opf", $args);
154 0           $self->render("EPUB/nav.xhtml", $args);
155 0           $self->render("EPUB/toc.ncx", $args);
156 0           $self->render("EPUB/toc.xhtml", $args);
157 0 0         if ($self->{has_coverpage}) {
158 0           $self->render("EPUB/text/cover_page.xhtml", $args);
159             }
160 0           $self->render("EPUB/text/title_page.xhtml", $args);
161 0 0         if ($args->{has_okuzuke}) {
162 0           $self->render("EPUB/text/okuzuke.xhtml", $args);
163             }
164              
165 0           for my $f (@{$args->{files}}) {
  0            
166             $self->render_to("EPUB/text/file.xhtml", "EPUB/text/$f->{name}.xhtml",
167             {
168             name => $f->{name},
169 0           content => mark_raw($f->as_html),
170             } );
171             }
172             }
173              
174             1;
175             __END__