File Coverage

blib/lib/HTML/PodCodeReformat.pm
Criterion Covered Total %
statement 59 61 96.7
branch 21 24 87.5
condition 2 3 66.6
subroutine 19 19 100.0
pod 2 2 100.0
total 103 109 94.5


line stmt bran cond sub pod time code
1             ## no critic
2             package HTML::PodCodeReformat;
3             BEGIN {
4 4     4   122309 $HTML::PodCodeReformat::VERSION = '0.20000';
5             }
6             ## use critic
7              
8 4     4   35 use strict;
  4         9  
  4         170  
9 4     4   21 use warnings;
  4         8  
  4         127  
10              
11 4     4   6639 use HTML::Parser 3.00 ();
  4         55873  
  4         300  
12 4     4   43 use Carp qw(croak);
  4         7  
  4         352  
13              
14 4     4   23 use constant MAX_INDENT => 99;
  4         8  
  4         338  
15              
16 4     4   23 use base qw(Class::Accessor::Fast);
  4         9  
  4         4106  
17              
18             __PACKAGE__->mk_accessors( qw/
19             squash_blank_lines
20             line_numbers
21             _html_parser
22             _inside_pre
23             _filtered_html
24             /);
25              
26             sub new {
27 4     4 1 142 my $class = shift;
28 4 100       85 my $self = $class->SUPER::new( @_ > 1 ? { @_ } : $_[0] );
29 4         79 $self->_html_parser( $self->_build_html_parser );
30 4         526 return $self
31             }
32              
33             sub _build_html_parser {
34 4     4   11 my $self = shift;
35            
36             HTML::Parser->new(
37             unbroken_text => 1,
38            
39 784     784   12830 start_h => [ sub { $self->_tag(@_) }, 'text, tagname, "+1"' ],
40 644     644   8802 end_h => [ sub { $self->_tag(@_) }, 'text, tagname, "-1"' ],
41            
42 1087     1087   24844 text_h => [ sub { $self->_text(@_) }, 'text' ],
43 4     28   99 default_h => [ sub { $self->_append_to_output(@_) }, 'text' ]
  28         827  
44             )
45             }
46              
47             sub _tag {
48 1428     1428   2131 my ($self, $text, $tag, $incr) = @_;
49 1428 100       2722 $self->_inside_pre( $incr + $self->_inside_pre )
50             if $tag eq 'pre';
51 1428         2645 $self->_append_to_output($text)
52             }
53              
54             sub _text {
55 1087     1087   1338 my ($self, $text) = @_;
56 1087 100       2194 $self->_append_to_output(
57             $self->_inside_pre ? $self->_reformat_pre_text($text) : $text
58             )
59             }
60              
61             sub _append_to_output {
62 2543     2543   7595 my ($self, $text) = @_;
63 2543         5357 $self->_filtered_html( $self->_filtered_html . $text )
64             }
65              
66             sub _reformat_pre_text {
67 28     28   212 my ($self, $text) = @_;
68            
69 28         253 my @lines = split /\n/, $text, -1;
70 28         50 my $min_indent_width = MAX_INDENT;
71 28         60 foreach ( @lines ) {
72 446 100       1061 next if /^\s*$/; # Skip verbatim paragraph breaks
73             # as well as space-only lines.
74 344 100       890 my $indent_width = /^(\s+)/ ? length($1) : 0;
75 344 100       958 $min_indent_width = $indent_width if $indent_width < $min_indent_width
76             }
77            
78             # This test is not necessary, it's just a micro-optimization.
79 28 100       66 if ( $min_indent_width ) {
80 27         1139 s/^\s{$min_indent_width}// foreach @lines
81             }
82            
83 28 100       100 if ( $self->squash_blank_lines ) {
84 19         312 s/^\s+$// foreach @lines
85             }
86            
87 0         0 return $self->line_numbers
88 28 50       119 ? '
    ' . join( '', map { "
  1. $_
  2. " } @lines ) . '
'
89             : join "\n", @lines
90             }
91              
92             sub reformat_pre {
93 8     8 1 44958 my ($self, $input) = @_;
94            
95 8         33 $self->_init_state;
96            
97 8         53 my $type = ref $input;
98 8 100 66     62 if ( $type eq 'SCALAR' ) {
    50          
99 4         19 $self->_html_parser->parse($$input);
100 4         78 $self->_html_parser->eof
101             } elsif ( $type eq '' || $type eq 'GLOB' ) {
102 4 50       18 defined( $self->_html_parser->parse_file($input) ) or return
103             } else {
104 0         0 croak( 'Wrong input type: ', $input )
105             }
106            
107 8         136 return $self->_filtered_html
108             }
109              
110             sub _init_state {
111 8     8   19 my $self = shift;
112 8         39 $self->_filtered_html('');
113 8         70 $self->_inside_pre(0)
114             }
115              
116             1;
117              
118             __END__