File Coverage

blib/lib/EBook/MOBI.pm
Criterion Covered Total %
statement 109 123 88.6
branch 24 32 75.0
condition 9 17 52.9
subroutine 22 24 91.6
pod 14 15 93.3
total 178 211 84.3


line stmt bran cond sub pod time code
1             package EBook::MOBI;
2              
3 8     8   150097 use strict;
  8         18  
  8         225  
4 8     8   44 use warnings;
  8         16  
  8         409  
5              
6             our $VERSION = 0.71;
7              
8             # needed CPAN stuff
9 8     8   8850 use File::Temp qw(tempfile);
  8         179412  
  8         478  
10 8     8   55 use Carp;
  8         14  
  8         388  
11              
12             # needed local stuff
13 8     8   5336 use EBook::MOBI::Driver::POD;
  8         23  
  8         443  
14 8     8   4602 use EBook::MOBI::Mhtml2Mobi;
  8         38  
  8         12195  
15              
16             # Constructor of this class
17             sub new {
18 9     9 0 6623 my $self = shift;
19 9         124 my $ref = { html_data => '',
20             html_toc => '',
21             toc_label => 'Table of Contents',
22             toc_set => 0,
23             toc_done => 0,
24              
25             filename => 'book.mobi',
26             title => 'This Book has no Title',
27             author => 'This Book has no Author',
28              
29             encoding => ':encoding(UTF-8)',
30             default_driver => 'EBook::MOBI::Driver::POD',
31              
32             CONST => '6_--TOC-_thisStringShouldNeverOccurInInput',
33              
34             ref_to_debug_sub => 0,
35             };
36              
37 9         27 bless($ref, $self);
38 9         29 return $ref;
39             }
40              
41             sub reset {
42 13     13 1 5452 my $self = shift;
43             $self->{html_data} = '',
44             $self->{html_toc } = '',
45             $self->{toc_label} = 'Table of Contents',
46             $self->{toc_set } = 0,
47             $self->{toc_done } = 0,
48              
49             $self->{filename } = 'book',
50             $self->{title } = 'This Book has no Title',
51             $self->{author } = 'This Book has no Author',
52              
53             $self->{encoding } = ':encoding(UTF-8)',
54             $self->{default_driver}= 'EBook::MOBI::Driver::POD',
55              
56             $self->{CONST } = '6_--TOC-_thisStringShouldNeverOccurInInput',
57              
58 13         122 $self->{ref_to_debug_sub} = 0,
59             }
60              
61             sub debug_on {
62 0     0 1 0 my ($self, $ref_to_debug_sub) = @_;
63              
64 0         0 $self->{ref_to_debug_sub} = $ref_to_debug_sub;
65            
66 0         0 &$ref_to_debug_sub('DEBUG mode on');
67             }
68              
69             sub debug_off {
70 0     0 1 0 my ($self) = @_;
71              
72 0 0       0 if ($self->{ref_to_debug_sub}) {
73 0         0 &{$self->{ref_to_debug_sub}}('DEBUG mode off');
  0         0  
74 0         0 $self->{ref_to_debug_sub} = 0;
75             }
76             }
77              
78             # Internal debug method
79             sub _debug {
80 15     15   23 my ($self,$msg) = @_;
81              
82 15 50       40 if ($self->{ref_to_debug_sub}) {
83 0         0 &{$self->{ref_to_debug_sub}}($msg);
  0         0  
84             }
85             }
86              
87             sub set_title {
88 1     1 1 5 my $self = shift;
89              
90 1         2 $self->{title} = shift;
91             }
92              
93             sub set_author {
94 1     1 1 5 my $self = shift;
95              
96 1         4 $self->{author} = shift;
97             }
98              
99             sub set_filename {
100 3     3 1 735 my $self = shift;
101              
102 3         14 $self->{filename} = shift;
103             }
104              
105             sub set_encoding {
106 7     7 1 38 my $self = shift;
107 7         18 my $encoding = shift;
108              
109 7 100       30 if (! $self->_encoding_to_codepage($encoding))
110             {
111 1         173 croak "Encoding $encoding is not supported by EPub::MOBI";
112             }
113              
114 6         31 $self->{encoding} = $encoding;
115             }
116              
117             sub _encoding_to_codepage
118             {
119             # Translate a Perl encoding name into a codepage value or return
120             # undef if not supported.
121              
122 10     10   20 my $self = shift;
123 10         19 my $encoding = shift;
124              
125 10 100       111 if ($encoding =~ /iso-8859-1|ascii/i)
    100          
126             {
127 2         5 return 1252;
128             }
129             elsif ($encoding =~ /utf-*8/i)
130             {
131 7         29 return 65001;
132             }
133             else
134             {
135 1         3 return undef;
136             }
137             }
138              
139             sub add_mhtml_content {
140 7     7 1 51 my ($self, $html) = @_;
141              
142 7         34 $self->{html_data} .= $html;
143             }
144              
145             sub add_content {
146 12     12 1 1564 my $self = shift;
147 12         34 my %args = @_;
148            
149 12   50     44 my $data = $args{data} || 0;
150 12   50     82 my $pagemode = $args{pagemode} || 0;
151 12   50     52 my $head0_mode = $args{head0_mode} || 0;
152 12   66     37 my $driver = $args{driver} || $self->{default_driver};
153 12   100     40 my $driver_opt = $args{driver_options} || 0;
154              
155             # we load a plugin to convert the input to mobi format
156 12         14 my $parser;
157 12         61 (my $require_name = $driver . ".pm") =~ s{::}{/}g;
158 12         23 eval {
159 12         757 require $require_name;
160 12         214 $parser = $driver->new();
161             };
162 12 50       34 die "Problems with plugin $driver at $require_name: $@" if $@;
163              
164             # pass some settings
165 12 50       36 if ($self->{ref_to_debug_sub}) {
166 0         0 $parser->debug_on($self->{ref_to_debug_sub});
167             }
168 12 100       28 if ($driver_opt) {
169 5         16 $parser->set_options($driver_opt);
170             }
171              
172 12         46 my $output = $parser->parse($data);
173              
174 12         117 $self->{html_data} .= $output;
175             }
176              
177             sub add_pagebreak {
178 2     2 1 6 my ($self) = @_;
179              
180 2         5 $self->{html_data} .= '' . "\n";
181             }
182              
183             sub add_toc_once {
184 5     5 1 20 my ($self, $label) = @_;
185              
186 5 100       16 $self->{toc_label} = $label if $label;
187 5         13 $self->{toc_set} = 1;
188 5         14 $self->{html_data} .= $self->{CONST};
189             # this newline is needed, otherwise the generation of the toc will
190             # not recognise the first

in the split function

191 5         12 $self->{html_data} .= "\n";
192             }
193              
194             sub make {
195 18     18 1 220 my ($self) = @_;
196              
197 18 100 33     104 if (exists $self->{toc_set} and $self->{toc_set}) {
198 5         16 $self->_generate_toc();
199             }
200             else {
201 13         33 my $tmp = $self->{html_data};
202 13         53 $self->{html_data} = "
203            
204            
205            
206             " . $tmp . "\n\n";
207             }
208             }
209              
210             sub print_mhtml {
211 15     15 1 67 my ($self, $arg) = @_;
212              
213 15 50       44 unless ($arg) {
214 0         0 print $self->{html_data};
215             }
216              
217 15         38 return $self->{html_data};
218             }
219              
220             sub save {
221 3     3 1 13 my ($self) = @_;
222              
223 3         30 my $mobi = EBook::MOBI::Mhtml2Mobi->new();
224             $mobi->debug_on($self->{ref_to_debug_sub})
225 3 50       15 if ($self->{ref_to_debug_sub});
226              
227 3         10 my $codepage = $self->_encoding_to_codepage($self->{encoding});
228              
229             $mobi->pack( $self->{html_data},
230             $self->{filename},
231             $self->{author},
232             $self->{title},
233             $codepage,
234             $self->{header_opts},
235 3         22 );
236             }
237              
238             sub _generate_toc {
239 5     5   8 my $self = shift;
240              
241 5 50 33     24 if (exists $self->{toc_done} and $self->{toc_done}) {
242 0         0 $self->_debug(
243             'Skipping generation of TOC, has been done earlier.');
244              
245 0         0 return 1;
246             }
247             else {
248 5         17 $self->_debug("generating TOC...");
249 5         9 $self->{toc_done} = 1;
250             }
251              
252 5         43 foreach my $line (split("\n", $self->{html_data})) {
253             # The

is only added to TOC if it is at the beginning of a line

254             # and if there is a newline directly following afterwards
255 67 100       158 if ($line =~ m/^

(.*)<\/h1>$/) {

256             $self->{html_toc} .=
257 10         35 "
  • $1
  • \n";
    258             }
    259             }
    260              
    261 5         19 my $toc = "

    $self->{toc_label}

    \n";
    262 5         11 $toc .= "

      \n$self->{html_toc}<\/ul><\/p>\n";
    263              
    264 5         65 $self->{html_data} =~ s/$self->{CONST}/$toc/;
    265              
    266 5         12 my $tmp = $self->{html_data};
    267 5         22 $self->{html_data} = "
    268            
    269            
    270             {toc_label}\" filepos=\"00000000\"/>
    271            
    272            
    273            
    274             " . $tmp . "\n\n";
    275              
    276             # now we need to calculate the positions for "filepos"
    277 5         7 my $chars = 0;
    278 5         9 my $data_copy = $self->{html_data};
    279 5         42 foreach my $line (split("\n", $data_copy)) {
    280              
    281 137 100       362 if ($line =~ m/^

    (.*)<\/h1>$/) {

        100          
    282 10         12 my $this_pos = $chars;
    283 10         25 my $fill_pos = sprintf("%08d", $this_pos);
    284 10         21 my $m = $1;
    285              
    286 10         37 $self->_debug("...ref to char $this_pos,\ttitle '$1'");
    287              
    288             $self->{html_data} =~
    289 10         146 s/
  • \Q$m\E<\/a><\/li>/
  • $m<\/a><\/li>/;
  • 290             }
    291             elsif ($line =~ /$/) {
    292 5         14 my $this_pos = $chars;
    293 5         23 my $fill_pos = sprintf("%08d", $this_pos);
    294 5         7 my $label = $self->{toc_label};
    295              
    296             $self->{html_data} =~
    297 5         76 s///;
    298             }
    299 137         172 $chars += length($line) + 1;
    300             }
    301              
    302             }
    303              
    304             1;
    305              
    306             __END__