File Coverage

blib/lib/Pod/From/GoogleWiki.pm
Criterion Covered Total %
statement 141 145 97.2
branch 58 70 82.8
condition 12 17 70.5
subroutine 17 17 100.0
pod 0 5 0.0
total 228 254 89.7


line stmt bran cond sub pod time code
1             package Pod::From::GoogleWiki;
2            
3 6     6   203300 use warnings;
  6         19  
  6         538  
4 6     6   203 use strict;
  6         12  
  6         1216  
5 6     6   33 use vars qw/$VERSION/;
  6         16  
  6         1656  
6             $VERSION = '0.07';
7            
8 6     6   5354 use Text::SimpleTable;
  6         12830  
  6         22654  
9            
10             sub new {
11 5     5 0 82 my $class = shift;
12 5         14 my $self = { @_ };
13            
14 5 50       24 unless ( exists $self->{tags} ) {
15             $self->{tags} = {
16 8     8   50 strong => sub { "B<$_[0]>" },
17 7     7   39 italic => sub { "I<$_[0]>" },
18 3     3   21 strike => sub { "C<--$_[0]-->" },
19 1     1   4 superscript => sub { "($_[0])" },
20 1     1   4 subscript => sub { "($_[0])" },
21 2     2   12 inline => sub { "C<$_[0]>" },
22 1     1   8 inline_code => sub { "C<<<$_[0]>>>" },
23             strong_tag => qr/\*(.+?)\*/,
24             italic_tag => qr/_(.+?)_/,
25             strike_tag => qr/\~\~(.+?)\~\~/,
26             superscript_tag => qr/\^(.+?)\^/,
27             subscript_tag => qr/\,\,(.+?)\,\,/,
28             inline_tag => qr/\`(.+?)\`/,
29             inline_code_tag => qr/\{\{\{(.+?)\}\}\}/,
30            
31             link => sub {
32 9     9   16 my $link = shift;
33 9 100       30 return $link if ($link =~ /\]$/); # for [text link], deal later
34 8         31 ($link, my $title) = split(/\s+/, $link, 2);
35 8         10 my $output;
36             # it's an image
37 8 100 100     63 if ($link =~ /\.(jpe?g|png|bmp|gif)$/is
      66        
38             or ($title and $title =~ /\.(jpe?g|png|bmp|gif)$/is) ) {
39 2         6 $output = "=begin html\n\n";
40 2 100       5 if ($title) {
41 1         4 $output .= "\n\n";
42             } else {
43 1         4 $output .= "\n\n";
44             }
45 2         3 $output .= "=end html\n";
46             } else {
47 6 100       17 if ($title) {
48             # for [http://search.cpan.org/perldoc?Pod::From::GoogleWiki Pod::From::GoogleWiki]
49 2 100       8 if ($link eq "http://search.cpan.org/perldoc?$title") {
50 1         5 $output = "L<$title>";
51             } else {
52 1         4 $output = "L<$link|$title>";
53             }
54             } else {
55 4         562 $output = "L<$link>";
56             }
57             }
58 8         36 return $output;
59             },
60            
61 5         297 schemas => [ qw( http https ftp mailto gopher ) ],
62             };
63             }
64            
65 5         28 return bless $self => $class;
66             }
67            
68             sub wiki2pod {
69 16     16 0 7115 my ($self, $text) = @_;
70            
71             # rest block_mark
72 16         53 $self->{_block_mark} = {};
73            
74 16         36 my $tags = $self->{tags};
75            
76 16         47 my $output = ''; my $do_last_line = 1;
  16         44  
77 16         222 my @lines = split(/\r?\n/, $text);
78 16         58 foreach my $line_no ( 0 .. $#lines ) {
79 92         129 my $line = $lines[$line_no];
80 92 100       209 my $pre_line = ($line_no > 0) ? $lines[ $line_no - 1 ] : '';
81            
82             # skip some lines
83 92 50 66     281 next if (not $output and $line =~ /^\#/); # like #labels
84            
85             # 1, code
86 92 100       502 if ( $line =~ /^\}\}\}$/ ) {
    100          
    100          
87 2         5 $self->{_block_mark}->{is_code} = 0;
88 2         3 $do_last_line = 0;
89 2 50       14 $output .= "\n" unless ($output =~ /\n{2,}$/);
90 2         5 next;
91             } elsif ( $line =~ /^\{\{\{$/) {
92 2         7 $self->{_block_mark}->{is_code} = 1;
93 2 100       10 $output .= "\n" unless ($output =~ /\n{2,}$/);
94 2         4 next;
95             } elsif ( $self->{_block_mark}->{is_code} ) {
96 8 50       31 $output .= " $line\n" and next;
97             }
98            
99             # 2, table
100 80 100       294 if ( $line =~ /^\|\|(.*?)\|\|$/) {
    50          
101 6 100       16 if ( $self->{_block_mark}->{in_table} ) {
102 5         6 push @{ $self->{_block_mark}->{trs} }, $self->format_line($line);
  5         13  
103             } else {
104 1         3 $self->{_block_mark}->{in_table} = 1;
105 1         4 $self->{_block_mark}->{trs} = [ $self->format_line($line) ];
106             }
107 6 100       16 if ($line_no == $#lines) { # if that's last line
108 1         3 $self->{_block_mark}->{in_table} = 0;
109 1         1 my @trs = @{ $self->{_block_mark}->{trs} };
  1         5  
110 1 50       5 $output .= $self->make_table( @trs ) and next;
111             } else {
112 5         10 next;
113             }
114             } elsif ( $self->{_block_mark}->{in_table} ) {
115 0         0 $self->{_block_mark}->{in_table} = 0;
116 0         0 my @trs = @{ $self->{_block_mark}->{trs} };
  0         0  
117 0 0       0 $output .= $self->make_table( @trs ) and next;
118             }
119            
120 74 100       250 if ($line =~ /^\s*$/) { # blank line
121 12         19 $do_last_line = 1;
122 12         238 $self->{_block_mark}->{in_list} = 0;
123 12 50       41 $output .= "\n" and next;
124             }
125            
126             # 2, header
127 62 100       167 if ($line =~ /^(=+)\s+(.*?)\s+\1\s*$/) {
128 10         26 my $h_level = length($1);
129 10         24 my $text = $self->format_line($2);
130 10         17 $do_last_line = 0;
131 10 100       52 $output .= "\n" unless ($output =~ /\n{2,}$/);
132 10 50       50 $output .= "=head$h_level $text\n" and next;
133             }
134            
135             # 3, list into code needs a newline in front
136 52 100       179 if ($line =~ /^\s+[\*|\#]/) {
137 31 100       80 unless ( $self->{_block_mark}->{in_list} ) {
138 5 100       754 if ($output !~ /\n{2,}$/) {
139 4         8 $output .= "\n";
140             }
141             }
142 31         53 $self->{_block_mark}->{in_list} = 1;
143             }
144 52 100       147 if ($line !~ /^\s+/) {
145 18 100 66     950 if ($self->{_block_mark}->{in_list} and $output !~ /\n{2,}$/) {
146 1         2 $output .= "\n";
147             }
148 18         56 $self->{_block_mark}->{in_list} = 0;
149             }
150            
151             # at last
152 52         106 $output .= $self->format_line($line) . "\n";
153 52         646 $do_last_line = 1;
154             }
155            
156 16 100       324 if ($do_last_line) {
157 14         34 my $last_line = 0;
158 14         656 while ($text =~ s/\n$//isg) {
159 10         40 $last_line++;
160             }
161 14         52 $output =~ s/\n$//isg;
162 14         286 $output .= "\n" x $last_line;
163             }
164            
165             # if list into code, last we need a newline after
166 16 100 66     76 if ($self->{_block_mark}->{in_list} and $output !~ /\n{2,}$/) {
167 3         9 $output .= "\n";
168             }
169            
170 16         68 return $output;
171             }
172            
173             sub format_line {
174 68     68 0 108 my ($self, $line) = @_;
175            
176 68         96 my $tags = $self->{tags};
177            
178 68         147 foreach my $type (qw/strong italic strike superscript subscript inline inline_code/) {
179 476         1326 my $sym = $tags->{"${type}_tag"};
180 476         599 my $pod_sym = $tags->{$type};
181 476         1423 $line =~ s/$sym/$pod_sym->($1)/eg;
  23         46  
182             }
183            
184             # deal with link
185 68         101 my $schemas = join('|', @{$tags->{schemas}});
  68         203  
186 68         7109 $line =~ s!(^|\s+)(($schemas):\S+)!$1 . $tags->{link}->($2)!egi;
  4         12  
187            
188 68         190 while (my @pieces = $self->find_innermost_balanced_pair( $line, '[', ']' ) ) {
189 5 50       10 my ($tag, $before, $after) = map { defined $_ ? $_ : '' } @pieces;
  15         74  
190 5   50     17 my $extended = $tags->{link}->( $tag ) || '';
191 5         23 $line = $before . $extended . $after;
192             };
193            
194 68         225 return $line;
195             }
196            
197             sub make_table {
198 1     1 0 4 my ($self, @trs) = @_;
199            
200 1         2 @trs = map { $_ =~ s/^\|\|(.*?)\|\|$/$1/isg; $_ } @trs;
  6         28  
  6         16  
201            
202 1         3 my $first_line = shift @trs;
203 1         9 my @cols = split(/\s*\|\|\s*/, $first_line);
204 1         2 @cols = map { [ length($_), $_ ] } @cols;
  3         7  
205            
206 1         11 my $t = Text::SimpleTable->new(@cols);
207 1         87 foreach my $tr (@trs) {
208 5         1400 $t->row( split(/\s*\|\|\s*/, $tr) );
209             }
210 1         63 return $t->draw;
211             }
212            
213             sub find_innermost_balanced_pair {
214 73     73 0 125 my ($self, $text, $open, $close) = @_;
215            
216 73         134 my $start_pos = rindex( $text, $open );
217 73 100       312 return if $start_pos == -1;
218            
219 5         12 my $end_pos = index( $text, $close, $start_pos );
220 5 50       13 return if $end_pos == -1;
221            
222 5         9 my $open_length = length( $open );
223 5         8 my $close_length = length( $close );
224 5         9 my $close_pos = $end_pos + $close_length;
225 5         10 my $enclosed_length = $close_pos - $start_pos;
226            
227 5         11 my $enclosed_atom = substr( $text, $start_pos, $enclosed_length );
228 5         33 return substr( $enclosed_atom, $open_length, 0 - $close_length ),
229             substr( $text, 0, $start_pos ),
230             substr( $text, $close_pos );
231             }
232            
233             1;
234             __END__