| blib/lib/Novel/Robot/Packer.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 45 | 84 | 53.5 |
| branch | 7 | 32 | 21.8 |
| condition | 3 | 21 | 14.2 |
| subroutine | 12 | 15 | 80.0 |
| pod | 2 | 8 | 25.0 |
| total | 69 | 160 | 43.1 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | # ABSTRACT: pack novel/bbs content to ebook | ||||||
| 2 | package Novel::Robot::Packer; | ||||||
| 3 | 2 | 2 | 20 | use strict; | |||
| 2 | 6 | ||||||
| 2 | 97 | ||||||
| 4 | 2 | 2 | 12 | use warnings; | |||
| 2 | 5 | ||||||
| 2 | 57 | ||||||
| 5 | 2 | 2 | 13 | use utf8; | |||
| 2 | 5 | ||||||
| 2 | 11 | ||||||
| 6 | 2 | 2 | 919 | use Encode::Locale; | |||
| 2 | 6061 | ||||||
| 2 | 125 | ||||||
| 7 | 2 | 2 | 14 | use Encode; | |||
| 2 | 4 | ||||||
| 2 | 153 | ||||||
| 8 | 2 | 2 | 13 | use File::Temp qw/tempfile /; | |||
| 2 | 4 | ||||||
| 2 | 88 | ||||||
| 9 | 2 | 2 | 1043 | use Template; | |||
| 2 | 38470 | ||||||
| 2 | 24 | ||||||
| 10 | |||||||
| 11 | #our $VERSION = 0.21; | ||||||
| 12 | |||||||
| 13 | sub new { | ||||||
| 14 | 2 | 2 | 1 | 98 | my ( $self, %opt ) = @_; | ||
| 15 | |||||||
| 16 | 2 | 50 | 9 | $opt{type} ||= 'html'; | |||
| 17 | |||||||
| 18 | 2 | 31 | bless {%opt}, __PACKAGE__; | ||||
| 19 | } | ||||||
| 20 | |||||||
| 21 | sub set_type { | ||||||
| 22 | 1 | 1 | 0 | 5 | my ( $self, $output, $o ) = @_; | ||
| 23 | |||||||
| 24 | 1 | 50 | 33 | 8 | if ( exists $o->{type} ) { | ||
| 50 | |||||||
| 25 | 0 | 0 | return $o->{type}; | ||||
| 26 | } elsif ( defined $output | ||||||
| 27 | and ( !exists $o->{output_scalar} ) ) { | ||||||
| 28 | 0 | 0 | ( $o->{type} ) = $output =~ m#\.([^.]+)$#; | ||||
| 29 | } else { | ||||||
| 30 | 1 | 3 | $o->{type} = 'html'; | ||||
| 31 | } | ||||||
| 32 | |||||||
| 33 | 1 | 3 | return $o->{type}; | ||||
| 34 | } | ||||||
| 35 | |||||||
| 36 | sub detect_writer_book_type { | ||||||
| 37 | 0 | 0 | 0 | 0 | my ( $self, $input, $o ) = @_; | ||
| 38 | |||||||
| 39 | 0 | 0 | $input = decode( locale => $input ); | ||||
| 40 | 0 | 0 | my ( $writer, $book, $type ) = $input =~ /([^\\\/]+?)-([^\\\/]+?)\.([^.\\\/]+)$/; | ||||
| 41 | |||||||
| 42 | 0 | 0 | 0 | $writer = $o->{writer} if ( defined $o->{writer} ); | |||
| 43 | 0 | 0 | 0 | $writer //= ''; | |||
| 44 | |||||||
| 45 | 0 | 0 | 0 | $book = $o->{book} if ( defined $o->{book} ); | |||
| 46 | 0 | 0 | 0 | $book //= ''; | |||
| 47 | |||||||
| 48 | 0 | 0 | return ( $writer, $book, $type ); | ||||
| 49 | } | ||||||
| 50 | |||||||
| 51 | sub convert_novel { | ||||||
| 52 | 0 | 0 | 0 | 0 | my ( $self, $input, $output, $o ) = @_; | ||
| 53 | |||||||
| 54 | 0 | 0 | 0 | 0 | return $input unless ( -f $input and -s $input ); | ||
| 55 | |||||||
| 56 | 0 | 0 | my ( $writer, $book, $in_type ) = $self->detect_writer_book_type( $input, $o ); | ||||
| 57 | |||||||
| 58 | 0 | 0 | 0 | if ( !defined $output ) { | |||
| 59 | 0 | 0 | $output = $input; | ||||
| 60 | 0 | 0 | $output =~ s/\.([^.]+)$/.$o->{type}/; | ||||
| 61 | } | ||||||
| 62 | 0 | 0 | 0 | return $input if ( $output eq $input ); | |||
| 63 | |||||||
| 64 | 0 | 0 | my ( $out_type ) = $output =~ m#\.([^.]+)$#; | ||||
| 65 | |||||||
| 66 | 0 | 0 | my %conv = ( | ||||
| 67 | 'authors' => $writer, | ||||||
| 68 | 'author-sort' => $writer, | ||||||
| 69 | 'title' => $book, | ||||||
| 70 | 'chapter-mark' => "none", | ||||||
| 71 | 'page-breaks-before' => "/", | ||||||
| 72 | 'max-toc-links' => 0, | ||||||
| 73 | ); | ||||||
| 74 | |||||||
| 75 | 0 | 0 | my $conv_str = join( " ", map { qq[--$_ "$conv{$_}"] } keys( %conv ) ); | ||||
| 0 | 0 | ||||||
| 76 | 0 | 0 | 0 | if ( $o->{type} =~ /\.epub$/ ) { | |||
| 0 | |||||||
| 77 | 0 | 0 | $conv_str .= " --dont-split-on-page-breaks "; | ||||
| 78 | } elsif ( $o->{type} =~ /\.mobi$/ ) { | ||||||
| 79 | 0 | 0 | $conv_str .= " --mobi-keep-original-images "; | ||||
| 80 | } | ||||||
| 81 | |||||||
| 82 | 0 | 0 | $conv_str = encode( locale => $conv_str ); | ||||
| 83 | 0 | 0 | my $cmd = qq[ebook-convert "$input" "$output" $conv_str]; | ||||
| 84 | |||||||
| 85 | #system( $cmd); | ||||||
| 86 | 0 | 0 | `$cmd`; | ||||
| 87 | |||||||
| 88 | 0 | 0 | return $output; | ||||
| 89 | } ## end sub convert_novel | ||||||
| 90 | |||||||
| 91 | sub main { | ||||||
| 92 | 1 | 1 | 1 | 22 | my ( $self, $book_ref, $o ) = @_; | ||
| 93 | |||||||
| 94 | 1 | 8 | $self->set_type( $o->{output}, $o ); | ||||
| 95 | 1 | 23 | $self->format_item_output( $book_ref, $o ); | ||||
| 96 | |||||||
| 97 | 1 | 50 | 33 | 6 | if ( $o->{type} ne 'html' and ( !exists $o->{output_scalar} ) ) { | ||
| 98 | 0 | 0 | my ( $fh, $html_f ) = tempfile( "run_novel-html-XXXXXXXXXXXXXX", TMPDIR => 1, SUFFIX => ".html" ); | ||||
| 99 | 0 | 0 | $self->process_html_template( $book_ref, $html_f, $o ); | ||||
| 100 | 0 | 0 | $self->convert_novel( $html_f, $o->{output}, { type => $o->{type}, writer => $book_ref->{writer}, book => $book_ref->{book} } ); | ||||
| 101 | } else { | ||||||
| 102 | 1 | 5 | $self->process_html_template( $book_ref, $o->{output}, $o ); | ||||
| 103 | } | ||||||
| 104 | |||||||
| 105 | 1 | 75 | return $o->{output}; | ||||
| 106 | } | ||||||
| 107 | |||||||
| 108 | sub format_item_output { | ||||||
| 109 | 1 | 1 | 0 | 3 | my ( $self, $book_ref, $o ) = @_; | ||
| 110 | 1 | 50 | 5 | if ( !$o->{output} ) { | |||
| 111 | 1 | 2 | my $html = ''; | ||||
| 112 | $o->{output} = | ||||||
| 113 | exists $o->{output_scalar} | ||||||
| 114 | 1 | 50 | 5 | ? \$html | |||
| 115 | : $self->format_default_filename( $book_ref, $o ); | ||||||
| 116 | } | ||||||
| 117 | 1 | 2 | return $o->{output}; | ||||
| 118 | } | ||||||
| 119 | |||||||
| 120 | sub format_default_filename { | ||||||
| 121 | 0 | 0 | 0 | 0 | my ( $self, $r, $o ) = @_; | ||
| 122 | |||||||
| 123 | 0 | 0 | my $item_info = ''; | ||||
| 124 | 0 | 0 | 0 | 0 | if ( exists $o->{min_item_num} and $o->{min_item_num} > 1 ) { | ||
| 0 | 0 | ||||||
| 125 | 0 | 0 | $item_info = "-$o->{min_item_num}"; | ||||
| 126 | } elsif ( exists $o->{min_page_num} and $o->{min_page_num} > 1 ) { | ||||||
| 127 | 0 | 0 | $item_info = "-$o->{min_page_num}"; | ||||
| 128 | } | ||||||
| 129 | 0 | 0 | my $f = "$r->{writer}-$r->{book}$item_info." . $o->{type}; | ||||
| 130 | 0 | 0 | $f =~ s{[\[\]/><\\`;'\$^*\(\)\%#@!"&:\?|\s^,~]}{}g; | ||||
| 131 | 0 | 0 | return encode( locale => $f ); | ||||
| 132 | } | ||||||
| 133 | |||||||
| 134 | sub process_html_template { | ||||||
| 135 | 1 | 1 | 0 | 3 | my ( $self, $book_ref, $dst, $o ) = @_; | ||
| 136 | |||||||
| 137 | my $toc = $o->{with_toc} | ||||||
| 138 | 1 | 50 | 5 | ? qq{ |
|||
| 139 | [% FOREACH r IN item_list %] | ||||||
| 140 | [% IF r.content %] |
||||||
| 141 | [% END %] | ||||||
| 142 | |||||||
| 143 | } | ||||||
| 144 | : ''; | ||||||
| 145 | |||||||
| 146 | 1 | 7 | my $txt = <<__HTML__; | ||||
| 147 | |||||||
| 148 | |||||||
| 149 | |||||||
| 150 | |||||||
| 151 | |||||||
| 152 | |||||||
| 153 | |||||||
| 154 | |
||||||
| 155 | |||||||
| 173 | |||||||
| 174 | |||||||
| 175 | |||||||
| 176 | |||||||
| 177 | $toc | ||||||
| 178 | |
||||||
| 179 | [% FOREACH r IN item_list %] | ||||||
| 180 | [% IF r.content %] | ||||||
| 181 | |
||||||
| 182 | [% r.id %]. [% r.writer %] [% r.title %] [% r.time %] |
||||||
| 183 | [% r.content %] |
||||||
| 184 | [% END %] | ||||||
| 185 | [% END %] | ||||||
| 186 | |||||||
| 187 | |||||||
| 188 | |||||||
| 189 | __HTML__ | ||||||
| 190 | 1 | 32 | my $tt = Template->new(); | ||||
| 191 | 1 | 50 | 24770 | $tt->process( \$txt, $book_ref, $dst, { binmode => ':utf8' } ) || die $tt->error(), "\n"; | |||
| 192 | 1 | 49917 | return $dst; | ||||
| 193 | } ## end sub process_html_template | ||||||
| 194 | |||||||
| 195 | 1; | ||||||
| 196 |