File Coverage

blib/lib/HTML/FormatMarkdown.pm
Criterion Covered Total %
statement 137 147 93.2
branch 31 52 59.6
condition 1 2 50.0
subroutine 30 30 100.0
pod 0 26 0.0
total 199 257 77.4


line stmt bran cond sub pod time code
1             package HTML::FormatMarkdown;
2              
3             # ABSTRACT: Format HTML as Markdown
4              
5              
6 2     2   2018 use 5.006_001;
  2         8  
7 2     2   13 use strict;
  2         3  
  2         66  
8 2     2   25 use warnings;
  2         5  
  2         107  
9              
10 2     2   802 use parent 'HTML::Formatter';
  2         499  
  2         19  
11              
12             our $VERSION = '2.16'; # VERSION
13             our $AUTHORITY = 'cpan:NIGELM'; # AUTHORITY
14              
15             sub default_values {
16 6     6 0 25 ( shift->SUPER::default_values(),
17             lm => 0,
18             rm => 70,
19             );
20             }
21              
22             sub configure {
23 2     2 0 6 my ( $self, $hash ) = @_;
24              
25 2         9 my $lm = $self->{lm};
26 2         5 my $rm = $self->{rm};
27              
28 2 50       7 $lm = delete $hash->{lm} if exists $hash->{lm};
29 2 50       7 $lm = delete $hash->{leftmargin} if exists $hash->{leftmargin};
30 2 50       6 $rm = delete $hash->{rm} if exists $hash->{rm};
31 2 50       4 $rm = delete $hash->{rightmargin} if exists $hash->{rightmargin};
32              
33 2         4 my $width = $rm - $lm;
34 2 50       13 if ( $width < 1 ) {
35 0 0       0 warn "Bad margins, ignored" if $^W;
36 0         0 return;
37             }
38 2 50       5 if ( $width < 20 ) {
39 0 0       0 warn "Page probably too narrow" if $^W;
40             }
41              
42 2         7 for ( keys %$hash ) {
43 0 0       0 warn "Unknown configure option '$_'" if $^W;
44             }
45              
46 2         3 $self->{lm} = $lm;
47 2         2 $self->{rm} = $rm;
48 2         4 $self;
49             }
50              
51             sub begin {
52 4     4 0 6 my $self = shift;
53              
54 4         20 $self->SUPER::begin();
55 4         7 $self->{maxpos} = 0;
56 4         7 $self->{curpos} = 0; # current output position.
57             }
58              
59             sub end {
60 4     4 0 9 shift->collect("\n");
61             }
62              
63             sub header_start {
64 2     2 0 4 my ( $self, $level ) = @_;
65              
66 2         8 $self->vspace(1);
67 2         9 $self->out( '#' x $level . ' ' );
68 2         6 1;
69             }
70              
71             sub header_end {
72 2     2 0 3 my ( $self, $level ) = @_;
73              
74 2         7 $self->out( ' ' . '#' x $level );
75 2         7 $self->vspace(1);
76             }
77              
78             sub bullet {
79 4     4 0 45 my $self = shift;
80              
81 4         15 $self->SUPER::bullet( $_[0] . ' ' );
82              
83             }
84              
85             sub hr_start {
86 1     1 0 2 my $self = shift;
87              
88 1         2 $self->vspace(1);
89 1         2 $self->out('- - -');
90 1         3 $self->vspace(1);
91             }
92              
93             sub img_start {
94 1     1 0 2 my ( $self, $node ) = @_;
95              
96 1   50     4 my $alt = $node->attr('alt') || '';
97 1         23 my $src = $node->attr('src');
98              
99 1         9 $self->out("![$alt]($src)");
100             }
101              
102             sub a_start {
103 2     2 0 5 my ( $self, $node ) = @_;
104              
105             # ignore named anchors
106 2 50       8 if ( $node->attr('name') ) {
    50          
107 0         0 1;
108             }
109             elsif ( $node->attr('href') =~ /^#/ ) {
110 0         0 1;
111             }
112             else {
113 2         42 $self->out("[");
114 2         5 1;
115             }
116             }
117              
118             sub a_end {
119 2     2 0 5 my ( $self, $node ) = @_;
120              
121 2 50       6 if ( $node->attr('name') ) {
    50          
122 0         0 return;
123             }
124             elsif ( my $href = $node->attr('href') ) {
125 2 50       43 if ( $href =~ /^#/ ) {
126 0         0 return;
127             }
128 2         8 $self->out("]($href)");
129             }
130             }
131              
132 1     1 0 2 sub b_start { shift->out("**") }
133 1     1 0 8 sub b_end { shift->out("**") }
134 1     1 0 3 sub i_start { shift->out("*") }
135 1     1 0 3 sub i_end { shift->out("*") }
136              
137             sub tt_start {
138 1     1 0 3 my $self = shift;
139              
140 1 50       4 if ( $self->{pre} ) {
141 0         0 return 1;
142             }
143             else {
144 1         25 $self->out("`");
145             }
146             }
147              
148             sub tt_end {
149 1     1 0 3 my $self = shift;
150              
151 1 50       4 if ( $self->{pre} ) {
152 0         0 return;
153             }
154             else {
155 1         2 $self->out("`");
156             }
157             }
158              
159             sub blockquote_start {
160 1     1 0 12 my $self = shift;
161              
162 1         2 $self->{blockquote}++;
163 1         3 $self->vspace(1);
164 1         4 $self->adjust_rm(-4);
165              
166 1         2 1;
167             }
168              
169             sub blockquote_end {
170 1     1 0 2 my $self = shift;
171              
172 1         1 $self->{blockquote}--;
173 1         3 $self->vspace(1);
174 1         7 $self->adjust_rm(+4);
175              
176             }
177              
178             sub blockquote_out {
179 1     1 0 2 my ( $self, $text ) = @_;
180              
181 1         2 $self->nl;
182 1         2 $self->goto_lm;
183              
184 1         1 my $line = "> ";
185 1         2 $self->{curpos} += 2;
186              
187 1         13 foreach my $word ( split /\s/, $text ) {
188 30         34 $line .= "$word ";
189 30 100       49 if ( ( $self->{curpos} + length($line) ) > $self->{rm} ) {
190 4         9 $self->collect($line);
191 4         8 $self->nl;
192 4         5 $self->goto_lm;
193 4         4 $line = "> ";
194 4         5 $self->{curpos} += 2;
195             }
196             }
197              
198 1         5 $self->collect($line);
199 1         2 $self->nl;
200              
201             }
202              
203             # Quoted from HTML::FormatText
204             sub pre_out {
205 1     1 0 2 my $self = shift;
206              
207 1 50       5 if ( defined $self->{vspace} ) {
208 1 50       3 if ( $self->{out} ) {
209 1         6 $self->nl() while $self->{vspace}-- >= 0;
210 1         2 $self->{vspace} = undef;
211             }
212             }
213              
214 1         3 my $indent = ' ' x $self->{lm};
215 1         3 $indent .= ' ' x 4;
216 1         2 my $pre = shift;
217 1         5 $pre =~ s/^/$indent/mg;
218 1         3 $self->collect($pre);
219 1         3 $self->{out}++;
220             }
221              
222             sub out {
223 862     862 0 630 my $self = shift;
224 862         688 my $text = shift;
225              
226 862 100       1677 if ( $text =~ /^\s*$/ ) {
227 423         318 $self->{hspace} = 1;
228 423         644 return;
229             }
230              
231 439 100       634 if ( defined $self->{vspace} ) {
232 27 100       45 if ( $self->{out} ) {
233 25         71 $self->nl while $self->{vspace}-- >= 0;
234             }
235 27         36 $self->goto_lm;
236 27         32 $self->{vspace} = undef;
237 27         29 $self->{hspace} = 0;
238             }
239              
240 439 100       585 if ( $self->{hspace} ) {
241 393 100       540 if ( $self->{curpos} + length($text) > $self->{rm} ) {
242              
243             # word will not fit on line; do a line break
244 46         55 $self->nl;
245 46         62 $self->goto_lm;
246             }
247             else {
248              
249             # word fits on line; use a space
250 347         532 $self->collect(' ');
251 347         312 ++$self->{curpos};
252             }
253 393         330 $self->{hspace} = 0;
254             }
255              
256 439         671 $self->collect($text);
257 439         407 my $pos = $self->{curpos} += length $text;
258 439 100       624 $self->{maxpos} = $pos if $self->{maxpos} < $pos;
259 439         701 $self->{'out'}++;
260             }
261              
262             sub goto_lm {
263 90     90 0 70 my $self = shift;
264              
265 90         72 my $pos = $self->{curpos};
266 90         68 my $lm = $self->{lm};
267 90 100       147 if ( $pos < $lm ) {
268 78         69 $self->{curpos} = $lm;
269 78         189 $self->collect( " " x ( $lm - $pos ) );
270             }
271             }
272              
273             sub nl {
274 102     102 0 83 my $self = shift;
275              
276 102         78 $self->{'out'}++;
277 102         85 $self->{curpos} = 0;
278 102         161 $self->collect("\n");
279             }
280              
281             sub adjust_lm {
282 12     12 0 13 my $self = shift;
283              
284 12         14 $self->{lm} += $_[0];
285 12         15 $self->goto_lm;
286             }
287              
288             sub adjust_rm {
289 2     2 0 5 shift->{rm} += $_[0];
290             }
291              
292             1;
293              
294             __END__