File Coverage

blib/lib/EBook/Ishmael/TextBrowserDump.pm
Criterion Covered Total %
statement 23 42 54.7
branch 0 12 0.0
condition 0 12 0.0
subroutine 8 9 88.8
pod 1 1 100.0
total 32 76 42.1


line stmt bran cond sub pod time code
1             package EBook::Ishmael::TextBrowserDump;
2 2     2   40 use 5.016;
  2         8  
3             our $VERSION = '2.03';
4 2     2   16 use strict;
  2         4  
  2         59  
5 2     2   29 use warnings;
  2         4  
  2         150  
6              
7 2     2   15 use Exporter 'import';
  2         5  
  2         195  
8             our @EXPORT = qw(browser_dump);
9              
10 2     2   15 use Encode qw(decode);
  2         4  
  2         146  
11 2     2   27 use List::Util qw(first);
  2         5  
  2         135  
12              
13 2     2   13 use File::Which;
  2         5  
  2         143  
14              
15 2     2   14 use EBook::Ishmael::ShellQuote qw(safe_qx);
  2         4  
  2         2042  
16              
17             our $CAN_DUMP = 0;
18              
19             # TODO: Is there some sort of post-processing we can do to get rid of s?
20              
21             # From links
22             my $WIDTH_MAX = 512;
23             my $WIDTH_MIN = 10;
24              
25             my @ORDER = qw(
26             lynx
27             links
28             elinks
29             w3m
30             chawan
31             pandoc
32             queequeg
33             );
34              
35             my %Browsers = (
36             'lynx' => {
37             Bins => [ qw(lynx) ],
38             Bin => undef,
39             Opts => [ qw(-dump -force_html -nolist -display_charset=utf8) ],
40             Width => '-width %d',
41             Xhtml => [ qw(-xhtml_parsing) ],
42             },
43             'links' => {
44             Bins => [ qw(links links2) ],
45             Bin => undef,
46             Opts => [ qw(-dump -force-htm -codepage utf8) ],
47             Width => '-width %d',
48             Xhtml => [],
49             },
50             'elinks' => {
51             Bins => [ qw(elinks) ],
52             Bin => undef,
53             Opts => [ qw(-dump -force-html -no-home -no-references -no-numbering
54             -dump-charset utf8) ],
55             Width => '-dump-width %d',
56             Xhtml => [],
57             },
58             'w3m' => {
59             Bins => [ qw(w3m) ],
60             Bin => undef,
61             Opts => [ qw(-dump -T text/html -O utf8) ],
62             Width => '-cols %d',
63             Xhtml => [],
64             },
65             'chawan' => {
66             Bins => [ qw(cha) ],
67             Bin => undef,
68             Opts => [ qw(-d -I utf8 -O utf8 -T text/html) ],
69             Width => "-o 'display.columns=%d'",
70             Xhtml => [],
71             },
72             'pandoc' => {
73             Bins => [ qw(pandoc) ],
74             Bin => undef,
75             Opts => [ qw(-f html -t plain -o -) ],
76             Width => "--columns %d",
77             Xhtml => [],
78             },
79             'queequeg' => {
80             Bins => [ qw(queequeg) ],
81             Bin => undef,
82             Opts => [ qw(-e utf8) ],
83             Width => '-w %d',
84             Xhtml => [],
85             },
86             );
87              
88             my $Default = undef;
89             for my $k (@ORDER) {
90             my $bin = first { which $_ } @{ $Browsers{ $k }->{Bins} };
91             next unless defined $bin;
92             $Browsers{ $k }->{Bin} = $bin;
93             $Default //= $k;
94             }
95              
96             $CAN_DUMP = defined $Default;
97              
98             unless ($CAN_DUMP) {
99             warn "No valid text browser was found installed on your system, you " .
100             "will be unable to use any feature requiring a text browser\n";
101             }
102              
103             sub browser_dump {
104              
105 0 0   0 1   unless (defined $Default) {
106 0           die "Cannot format HTML; no valid program was found on your system\n";
107             }
108              
109 0           my $file = shift;
110 0   0       my $param = shift // {};
111              
112 0   0       my $browser = $param->{browser} // $Default;
113 0   0       my $xhtml = $param->{xhtml} // 0;
114 0   0       my $width = $param->{width} // 80;
115              
116 0 0         unless (exists $Browsers{ $browser }) {
117 0           die <<"HERE";
118             '$browser' is not a valid program; the following is a list of valid programs:
119             lynx
120             links
121             elinks
122             w3m
123             chawan
124             pandoc
125             queequeg
126             HERE
127             }
128              
129 0 0         unless (defined $Browsers{ $browser }->{Bin}) {
130 0           die "'$browser' is not installed on your system\n";
131             }
132              
133 0 0 0       unless ($width >= $WIDTH_MIN and $width <= $WIDTH_MAX) {
134 0           die "Width cannot be greater than $WIDTH_MAX or less than $WIDTH_MIN\n";
135             }
136              
137             my $dump = safe_qx(
138             $Browsers{ $browser }->{Bin},
139             split(/\s+/, sprintf($Browsers{ $browser }->{Width}, $width)),
140 0           @{ $Browsers{ $browser }->{Opts} },
141 0 0         ($xhtml ? join(" ", @{ $Browsers{ $browser }->{Xhtml} }) : ()),
  0            
142             $file
143             );
144 0 0         unless ($? >> 8 == 0) {
145 0           die "Failed to dump $file with $Browsers{ $browser }->{Bin}\n";
146             }
147              
148             # We can't use 'open IN => ":encoding(UTF-8)"' because it was broken prior
149             # to 5.34, so we must manually decode :-/.
150 0           return decode('UTF-8', $dump);
151              
152             }
153              
154             1;
155              
156             =head1 NAME
157              
158             EBook::Ishmael::TextBrowserDump - Format HTML through different installed programs
159              
160             =head1 SYNOPSIS
161              
162             use EBook::Ishmael::TextBrowserDump;
163              
164             my $dump = browser_dump($file);
165              
166             =head1 DESCRIPTION
167              
168             B is a module for dumping the contents of
169             HTML files to formatted text, via programs like L. For
170             L user documentation, you should consult its manual (this is
171             developer documentation).
172              
173             B requires at least one of the following
174             programs to be installed:
175              
176             =over 4
177              
178             =item L
179              
180             =item L
181              
182             =item L
183              
184             =item L
185              
186             =item chawan
187              
188             =item L
189              
190             =item L
191              
192             =back
193              
194             =head1 SUBROUTINES
195              
196             =head2 $dump = browser_dump($file, $opt_ref)
197              
198             Subroutine that dumps the formatted text contents of C<$file> via a text
199             web browser.
200              
201             C can also be given a hash ref of options.
202              
203             =over 4
204              
205             =item browser
206              
207             The specific browser you would like to use for the dumping. See above for a list
208             of valid browsers. If not specified, defaults to the first browser
209             C finds installed on your system.
210              
211             =item xhtml
212              
213             Bool specifying whether the input file is XHTML or not. Defaults to C<0>.
214              
215             =item width
216              
217             Specify the width of the formatted text. Defaults to C<80>.
218              
219             =back
220              
221             =head1 GLOBAL VARIABLES
222              
223             =head2 $EBook::Ishmael::TextBrowserDump::CAN_DUMP
224              
225             Bool stating whether this module is able to dump or not (is a valid
226             text browser installed or not).
227              
228             =head1 AUTHOR
229              
230             Written by Samuel Young, Esamyoung12788@gmail.comE.
231              
232             This project's source can be found on its
233             L. Comments and pull
234             requests are welcome!
235              
236             =head1 COPYRIGHT
237              
238             Copyright (C) 2025-2026 Samuel Young
239              
240             This program is free software: you can redistribute it and/or modify
241             it under the terms of the GNU General Public License as published by
242             the Free Software Foundation, either version 3 of the License, or
243             (at your option) any later version.
244              
245             =head1 SEE ALSO
246              
247             L, L, L, L, L, L,
248             L,
249              
250             =cut