File Coverage

lib/Mediawiki/POD.pm
Criterion Covered Total %
statement 92 99 92.9
branch 20 28 71.4
condition n/a
subroutine 8 9 88.8
pod 4 4 100.0
total 124 140 88.5


line stmt bran cond sub pod time code
1             package Mediawiki::POD;
2              
3             our $VERSION = '0.06';
4              
5 2     2   52968 use strict;
  2         6  
  2         66  
6 2     2   34067 use Pod::Simple::HTML;
  2         197215  
  2         87  
7 2     2   967 use Mediawiki::POD::HTML;
  2         6  
  2         2450  
8              
9             sub new
10             {
11 2     2 1 1812 my $class = shift;
12              
13 2         8 my $self = bless {}, $class;
14              
15             # some defaults
16 2         13 $self->{remove_newlines} = 1;
17 2         5 $self->{body_only} = 1;
18              
19 2         6 $self;
20             }
21              
22             sub remove_newlines
23             {
24 2     2 1 3065 my $self = shift;
25              
26 2 50       20 $self->{remove_newlines} = ( $_[0] ? 1 : 0 ) if @_ > 0;
    50          
27 2         8 $self->{remove_newlines};
28             }
29              
30             sub body_only
31             {
32 0     0 1 0 my $self = shift;
33              
34 0 0       0 $self->{body_only} = ( $_[0] ? 1 : 0 ) if @_ > 0;
    0          
35 0         0 $self->{body_only};
36             }
37              
38             sub as_html
39             {
40 5     5 1 4591 my ($self, $input) = @_;
41              
42 5         56 my $parser = Mediawiki::POD::HTML->new();
43              
44 5         8 my ($html, $headlines);
45              
46 5         47 $parser->output_string( \$html );
47              
48 5         7336 $parser->parse_string_document( $input );
49              
50             # remove form-feeds and tabs
51 5         6327 $html =~ s/[\f\t]+//g;
52              
53             # remove comments
54 5         372 $html =~ s///g;
55              
56 5 50       37 if ($self->{body_only})
57             {
58             # remove the unwanted HTML sections
59 5         152 $html =~ s/(.|\n)*<\/head>//;
60              
61 5         164 $html =~ s/<\/?(html|body).*?>//g;
62             }
63              
64             # clean up some crazy tags
65             # converting "" to "
66 5         68 $html =~ s/<(pre|code|p)\s.*?>/<$1>/g;
67              
68             # insert a class for
69 5         24 $html =~ s/ 70              
71             # make it readable again :)
72 5         22 $html =~ s/\'/'/g;
73 5         25 $html =~ s/\"/"/g;
74              
75             # remove empty paragraphs before a closing (for instance for X keywords)
76 5         21 $html =~ s/

<\/p>\n<\/div>/<\/div>/g;

77              
78             # if the last item is a keyword, we need to add a closing
79 5         22 $html =~ s/

<\/p>\s*\z/<\/div>/;

80              
81             # make '>"foo"' to '>foo'
82 5         18 $html =~ s/class="podlinkpod"\s*>"(.*?)"<\/a>/class="podlinkpod">$1<\/a>/g;
83              
84             # convert newlines between
 tags to 
85             # remove all new lines and tabs
86 5 100       35 $html = $self->_parse_output($html) if $self->{remove_newlines};
87              
88 5         50 $html = $self->_generate_toc( $parser->get_headlines() ) . $html;
89              
90             # return the result
91 5         385 $html;
92             };
93              
94             ###########################################################################
95             # We need to remove all new lines, other Mediawiki will insert spurious
96             # linebreaks. However, inside
 we need to replace them with 
97             #
so that verbatim sections render properly. A nested regexp could
98             # solve this, but is not possible. So we implement a very basic parser
99             # that recognizes three things: , , anything else.
100              
101             # This routine assumes that the
 tags are not nested. 
102              
103             sub _parse_output
104             {
105 2     2   18 my ($self, $input) = @_;
106              
107 2         12 my $in_pre = 0;
108              
109 2         13 my $qr_tag = qr/^(<\w+(.|\n)*?>)/;
110 2         9 my $qr_end_tag = qr/^(<\/\w+>)/;
111 2         11 my $qr_else = qr/^((?:.|\n)+?)(<|\z)/;
112              
113 2         4 my $last_len = 1;
114 2         8 my $output = '';
115 2         10 while (length($input) > 0)
116             {
117 183         206 $last_len = length($input);
118             # math the start of the input, and remove the matching part
119 183 100       1296 if ($input =~ $qr_tag)
    100          
120             {
121 52         391 $input =~ s/$qr_tag//;
122 52         105 my $tag = $1;
123 52         97 $tag =~ s/[\n\r\t]/ /g;
124 52         77 $output .= $tag;
125 52 100       204 if ($tag =~ /^/i)
126             {
127 1         3 $in_pre++;
128             }
129             }
130             elsif ($input =~ $qr_end_tag)
131             {
132 52         295 $input =~ s/$qr_end_tag//;
133 52         103 my $tag = $1;
134 52         98 $tag =~ s/[\n\r\t]/ /g;
135 52         87 $output .= $tag;
136 52 100       182 if ($tag =~ /^<\/pre.*?>/i)
137             {
138 1         3 $in_pre--;
139             }
140             }
141             else
142             {
143 79         1427 $input =~ s/$qr_else/$2/;
144             # remove newlines
145 79         160 my $else = $1;
146 79 100       142 if ($in_pre > 0)
147             {
148             # also remove excessive leading whitespace
149 1         8 $else =~ s/[\n\r\t]\s*/
/g;
150 1         4 $else =~ s/^\s*/ /;
151             }
152             else
153             {
154 78         389 $else =~ s/[\n\r\t]/ /g;
155             }
156 79         216 $output .= $else;
157             }
158             }
159 2         23 $output;
160             }
161              
162             sub _generate_toc
163             {
164 5     5   15 my ($self, $headlines) = @_;
165              
166 5         14 my $toc = '

Contents

';
167 5         13 $toc .= "\n
    \n";
168              
169 5         13 my $level = 1;
170 5         15 my @cur_nr = ( 0 );
171 5         15 for my $headline (@$headlines)
172             {
173 7         31 $headline =~ /^head([1-9]) (.*)/;
174              
175 7         21 my $cur_level = $1;
176 7         17 my $txt = $2;
177 7         13 my $link = $txt; $link =~ s/ /_/g; $link =~ s/"<>//g;
  7         16  
  7         14  
178             #print STDERR "$headline $cur_level $level\n";
179              
180             # we enter a scope
181 7 100       42 if ($cur_level > $level)
    50          
182             {
183 2         4 my $levels_up = $cur_level - $level;
184 2         8 for (1..$levels_up)
185             {
186 2         4 push @cur_nr, 0;
187 2         6 $toc .= '
    ';
188             }
189             }
190             elsif ($cur_level < $level)
191             {
192 0         0 my $levels_down = $level - $cur_level;
193 0         0 for (1..$levels_down)
194             {
195 0         0 pop @cur_nr;
196 0         0 $toc .= '';
197             }
198             }
199 7         15 $cur_nr[-1]++;
200 7         30 my $tnr = join ('.', @cur_nr);
201 7         32 $toc .= "
  • $tnr $txt
  • \n";
    202 7         20 $level = $cur_level;
    203             }
    204              
    205 5         16 $toc .= "
    \n";
    206 5         9 $toc .= '\n";
    209              
    210 5 100       57 $toc =~ s/[\n\r\t]/ /g if $self->{remove_newlines};
    211 5         35 $toc;
    212             }
    213              
    214             1;
    215              
    216             __END__