File Coverage

blib/lib/EBook/MOBI.pm
Criterion Covered Total %
statement 109 123 88.6
branch 24 32 75.0
condition 10 17 58.8
subroutine 22 24 91.6
pod 14 15 93.3
total 179 211 84.8


line stmt bran cond sub pod time code
1             package EBook::MOBI;
2              
3 8     8   243772 use strict;
  8         19  
  8         344  
4 8     8   46 use warnings;
  8         18  
  8         404  
5              
6             our $VERSION = 0.7;
7              
8             # needed CPAN stuff
9 8     8   20812 use File::Temp qw(tempfile);
  8         226357  
  8         631  
10 8     8   76 use Carp;
  8         18  
  8         471  
11              
12             # needed local stuff
13 8     8   6524 use EBook::MOBI::Driver::POD;
  8         33  
  8         599  
14 8     8   5881 use EBook::MOBI::Mhtml2Mobi;
  8         35  
  8         25871  
15              
16             # Constructor of this class
17             sub new {
18 9     9 0 11524 my $self = shift;
19 9         137 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         37 bless($ref, $self);
38 9         37 return $ref;
39             }
40              
41             sub reset {
42 13     13 1 17148 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 13         249 $self->{CONST } = '6_--TOC-_thisStringShouldNeverOccurInInput',
57              
58             $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   26 my ($self,$msg) = @_;
81              
82 15 50       48 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         3 $self->{title} = shift;
91             }
92              
93             sub set_author {
94 1     1 1 5 my $self = shift;
95              
96 1         2 $self->{author} = shift;
97             }
98              
99             sub set_filename {
100 3     3 1 752 my $self = shift;
101              
102 3         17 $self->{filename} = shift;
103             }
104              
105             sub set_encoding {
106 7     7 1 43 my $self = shift;
107 7         17 my $encoding = shift;
108              
109 7 100       25 if (! $self->_encoding_to_codepage($encoding))
110             {
111 1         180 croak "Encoding $encoding is not supported by EPub::MOBI";
112             }
113              
114 6         41 $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   21 my $self = shift;
123 10         17 my $encoding = shift;
124              
125 10 100       129 if ($encoding =~ /iso-8859-1|ascii/i)
    100          
126             {
127 2         6 return 1252;
128             }
129             elsif ($encoding =~ /utf-*8/i)
130             {
131 7         30 return 65001;
132             }
133             else
134             {
135 1         4 return undef;
136             }
137             }
138              
139             sub add_mhtml_content {
140 7     7 1 58 my ($self, $html) = @_;
141              
142 7         36 $self->{html_data} .= $html;
143             }
144              
145             sub add_content {
146 12     12 1 3121 my $self = shift;
147 12         44 my %args = @_;
148            
149 12   50     56 my $data = $args{data} || 0;
150 12   50     87 my $pagemode = $args{pagemode} || 0;
151 12   50     97 my $head0_mode = $args{head0_mode} || 0;
152 12   66     60 my $driver = $args{driver} || $self->{default_driver};
153 12   100     52 my $driver_opt = $args{driver_options} || 0;
154              
155             # we load a plugin to convert the input to mobi format
156 12         23 my $parser;
157 12         85 (my $require_name = $driver . ".pm") =~ s{::}{/}g;
158 12         25 eval {
159 12         867 require $require_name;
160 12         476 $parser = $driver->new();
161             };
162 12 50       46 die "Problems with plugin $driver at $require_name: $@" if $@;
163              
164             # pass some settings
165 12 50       46 if ($self->{ref_to_debug_sub}) {
166 0         0 $parser->debug_on($self->{ref_to_debug_sub});
167             }
168 12 100       58 if ($driver_opt) {
169 5         22 $parser->set_options($driver_opt);
170             }
171              
172 12         58 my $output = $parser->parse($data);
173              
174 12         180 $self->{html_data} .= $output;
175             }
176              
177             sub add_pagebreak {
178 2     2 1 9 my ($self) = @_;
179              
180 2         9 $self->{html_data} .= '' . "\n";
181             }
182              
183             sub add_toc_once {
184 5     5 1 29 my ($self, $label) = @_;
185              
186 5 100       25 $self->{toc_label} = $label if $label;
187 5         11 $self->{toc_set} = 1;
188 5         16 $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         15 $self->{html_data} .= "\n";
192             }
193              
194             sub make {
195 18     18 1 305 my ($self) = @_;
196              
197 18 100 66     162 if (exists $self->{toc_set} and $self->{toc_set}) {
198 5         20 $self->_generate_toc();
199             }
200             else {
201 13         36 my $tmp = $self->{html_data};
202 13         65 $self->{html_data} = "
203            
204            
205            
206             " . $tmp . "\n\n";
207             }
208             }
209              
210             sub print_mhtml {
211 15     15 1 90 my ($self, $arg) = @_;
212              
213 15 50       55 unless ($arg) {
214 0         0 print $self->{html_data};
215             }
216              
217 15         74 return $self->{html_data};
218             }
219              
220             sub save {
221 3     3 1 22 my ($self) = @_;
222              
223 3         30 my $mobi = EBook::MOBI::Mhtml2Mobi->new();
224 3 50       19 $mobi->debug_on($self->{ref_to_debug_sub})
225             if ($self->{ref_to_debug_sub});
226              
227 3         14 my $codepage = $self->_encoding_to_codepage($self->{encoding});
228              
229 3         25 $mobi->pack( $self->{html_data},
230             $self->{filename},
231             $self->{author},
232             $self->{title},
233             $codepage,
234             $self->{header_opts},
235             );
236             }
237              
238             sub _generate_toc {
239 5     5   11 my $self = shift;
240              
241 5 50 33     37 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         20 $self->_debug("generating TOC...");
249 5         10 $self->{toc_done} = 1;
250             }
251              
252 5         57 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       188 if ($line =~ m/^

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

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

    $self->{toc_label}

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

      \n$self->{html_toc}<\/ul><\/p>\n";
    263              
    264 5         67 $self->{html_data} =~ s/$self->{CONST}/$toc/;
    265              
    266 5         14 my $tmp = $self->{html_data};
    267 5         34 $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         11 my $chars = 0;
    278 5         13 my $data_copy = $self->{html_data};
    279 5         60 foreach my $line (split("\n", $data_copy)) {
    280              
    281 137 100       379 if ($line =~ m/^

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

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