File Coverage

blib/lib/Pod/Simple/Wiki.pm
Criterion Covered Total %
statement 119 123 96.7
branch 37 50 74.0
condition 2 4 50.0
subroutine 46 47 97.8
pod 1 1 100.0
total 205 225 91.1


line stmt bran cond sub pod time code
1             package Pod::Simple::Wiki;
2              
3             ###############################################################################
4             #
5             # Pod::Simple::Wiki - A class for creating Pod to Wiki filters.
6             #
7             #
8             # Copyright 2003-2012, John McNamara, jmcnamara@cpan.org
9             #
10             # Documentation after __END__
11             #
12              
13             # perltidy with the following options: -mbl=2 -pt=0 -nola
14              
15 39     39   20059 use strict;
  39         54  
  39         1290  
16              
17             #use Pod::Simple::Debug (5);
18 39     39   25490 use Pod::Simple;
  39         1034081  
  39         1391  
19 39     39   359 use vars qw(@ISA $VERSION);
  39         90  
  39         61922  
20              
21             @ISA = qw(Pod::Simple);
22             $VERSION = '0.18';
23              
24              
25             ###############################################################################
26             #
27             # The tag to wiki mappings.
28             #
29             my $tags = {
30             '' => "'''",
31             '' => "'''",
32             '' => "''",
33             '' => "''",
34             '' => '"',
35             '' => '"',
36             '
'  => '', 
37             '' => "\n\n",
38              
39             '

' => "\n----\n'''",

40             '' => "'''\n\n",
41             '

' => "\n'''''",

42             '' => "'''''\n\n",
43             '

' => "\n''",

44             '' => "''\n\n",
45             '

' => "\n",

46             '' => "\n\n",
47             };
48              
49              
50             ###############################################################################
51             #
52             # new()
53             #
54             # Simple constructor inheriting from Pod::Simple.
55             #
56             sub new {
57              
58 522     522 1 120909 my $class = shift;
59 522   50     1408 my $format = lc( shift || 'wiki' );
60 522 50       979 $format = 'mediawiki' if $format eq 'wikipedia';
61 522 50       933 $format = 'moinmoin' if $format eq 'moin';
62              
63 522         1035 my $module = "Pod::Simple::Wiki::" . ucfirst $format;
64              
65             # Try to load a sub-module unless the format type is 'wiki' in which
66             # case we use this, the parent, module. It's a design pattern, bitches!
67 522 100       949 if ( $format ne 'wiki' ) {
68 250         13578 eval "require $module";
69 250 50       900 die "Module $module not implemented for wiki format $format\n" if $@;
70 250         1315 return $module->new( @_ );
71             }
72              
73 272         1088 my $self = Pod::Simple->new( @_ );
74 272         5745 $self->{_wiki_text} = '';
75 272         408 $self->{_tags} = $tags;
76 272   50     1524 $self->{output_fh} ||= *STDOUT{IO};
77 272         410 $self->{_item_indent} = 0;
78 272         496 $self->{_debug} = 0;
79              
80             # Set Pod::Simple parser options
81             # - Merge contiguous text RT#60304
82 272         661 $self->merge_text( 1 );
83              
84             # - Ignore X<> (index entries) RT#60307
85 272         1949 $self->nix_X_codes( 1 );
86              
87 272         1410 bless $self, $class;
88 272         559 return $self;
89             }
90              
91              
92             ###############################################################################
93             #
94             # _debug()
95             #
96             # Sets the debug flag for some Pod::Simple::Wiki debugging. See also the
97             # Pod::Simple::Debug module.
98             #
99             sub _debug {
100              
101 0     0   0 my $self = shift;
102              
103 0         0 $self->{_debug} = $_[0];
104             }
105              
106              
107             ###############################################################################
108             #
109             # _append()
110             #
111             # Appends some text to the buffered Wiki text.
112             #
113             sub _append {
114              
115 568     568   488 my $self = shift;
116              
117 568         1358 $self->{_wiki_text} .= $_[0];
118             }
119              
120              
121             ###############################################################################
122             #
123             # _output()
124             #
125             # Appends some text to the buffered Wiki text and then emits it. Also resets
126             # the buffer.
127             #
128             sub _output {
129              
130 909     909   751 my $self = shift;
131 909         865 my $text = $_[0];
132              
133 909 100       1507 $text = '' unless defined $text;
134              
135 909         697 print { $self->{output_fh} } $self->{_wiki_text}, $text;
  909         2783  
136              
137 909         6695 $self->{_wiki_text} = '';
138             }
139              
140              
141             ###############################################################################
142             #
143             # _indent_item()
144             #
145             # Indents an "over-item" to the correct level.
146             #
147             sub _indent_item {
148              
149 37     37   31 my $self = shift;
150 37         27 my $item_type = $_[0];
151 37         28 my $item_param = $_[1];
152 37         37 my $indent_level = $self->{_item_indent};
153              
154 37 100       76 if ( $item_type eq 'bullet' ) {
    100          
    50          
155 12         29 $self->_append( "*" x $indent_level );
156              
157             # This was the way C2 Wiki used to define a bullet list
158             # $self->_append("\t" x $indent_level . '*');
159             }
160             elsif ( $item_type eq 'number' ) {
161 12         27 $self->_append( "\t" x $indent_level . $item_param );
162             }
163             elsif ( $item_type eq 'text' ) {
164 13         26 $self->_append( "\t" x $indent_level );
165             }
166             }
167              
168              
169             ###############################################################################
170             #
171             # _skip_headings()
172             #
173             # Formatting in headings doesn't look great or is ignored in some formats.
174             #
175             sub _skip_headings {
176              
177 154     154   175 my $self = shift;
178              
179 154         528 return 0;
180             }
181              
182              
183             ###############################################################################
184             #
185             # _append_tag()
186             #
187             # Add an open or close tag to the current text.
188             #
189             sub _append_tag {
190              
191 246     246   253 my $self = shift;
192 246         208 my $tag = $_[0];
193              
194 246         541 $self->_append( $self->{_tags}->{$tag} );
195             }
196              
197              
198             ###############################################################################
199             ###############################################################################
200             #
201             # The methods in the following section are required by Pod::Simple to handle
202             # Pod directives and elements.
203             #
204             # The methods _handle_element_start() _handle_element_end() and _handle_text()
205             # are called by Pod::Simple in response to Pod constructs. We use
206             # _handle_element_start() and _handle_element_end() to generate calls to more
207             # specific methods. This is basically a long-hand version of Pod::Simple::
208             # Methody with the addition of location tracking.
209             #
210              
211              
212             ###############################################################################
213             #
214             # _handle_element_start()
215             #
216             # Call a method to handle the start of a element if one has been defined.
217             # We also set a flag to indicate that we are "in" the element type.
218             #
219             sub _handle_element_start {
220              
221 1256     1256   262001 my $self = shift;
222 1256         1386 my $element = $_[0];
223              
224 1256         1343 $element =~ tr/-/_/;
225              
226 1256 50       2563 if ( $self->{_debug} ) {
227 0         0 print ' ' x $self->{_item_indent}, "<$element>\n";
228             }
229              
230 1256         2053 $self->{ "_in_" . $element }++;
231              
232 1256 100       5609 if ( my $method = $self->can( '_start_' . $element ) ) {
233 984         1959 $method->( $self, $_[1] );
234             }
235             }
236              
237              
238             ###############################################################################
239             #
240             # _handle_element_end()
241             #
242             # Call a method to handle the end of a element if one has been defined.
243             # We also set a flag to indicate that we are "out" of the element type.
244             #
245             sub _handle_element_end {
246              
247 1256     1256   30143 my $self = shift;
248 1256         1248 my $element = $_[0];
249              
250 1256         1189 $element =~ tr/-/_/;
251              
252 1256 100       4651 if ( my $method = $self->can( '_end_' . $element ) ) {
253 984         1516 $method->( $self );
254             }
255              
256 1256         1893 $self->{ "_in_" . $element }--;
257              
258 1256 50       3039 if ( $self->{_debug} ) {
259 0         0 print "\n", ' ' x $self->{_item_indent}, "\n\n";
260             }
261             }
262              
263              
264             ###############################################################################
265             #
266             # _handle_text()
267             #
268             # Perform any necessary transforms on the text. This is mainly used to escape
269             # inadvertent CamelCase words.
270             #
271             sub _handle_text {
272              
273 60     60   345 my $self = shift;
274 60         57 my $text = $_[0];
275              
276             # Split the text into tokens but maintain the whitespace
277 60         234 my @tokens = split /(\s+)/, $text;
278              
279 60         95 for ( @tokens ) {
280 250 100       427 next unless /\S/; # Ignore the whitespace
281 155 50       197 next if m[^(ht|f)tp://]; # Ignore URLs
282 155         234 s/([A-Z][a-z]+)(?=[A-Z])/$1''''''/g # Escape with 6 single quotes
283              
284             }
285              
286             # Rejoin the tokens and whitespace.
287 60         184 $self->{_wiki_text} .= join '', @tokens;
288             }
289              
290              
291             ###############################################################################
292             #
293             # Functions to deal with the I<>, B<> and C<> formatting codes.
294             #
295 40 50   40   104 sub _start_I { $_[0]->_append_tag( '' ) unless $_[0]->_skip_headings() }
296 30 50   30   65 sub _start_B { $_[0]->_append_tag( '' ) unless $_[0]->_skip_headings() }
297 11 50   11   40 sub _start_C { $_[0]->_append_tag( '' ) unless $_[0]->_skip_headings() }
298 10     10   30 sub _start_F { $_[0]->_start_I }
299              
300 40 50   40   79 sub _end_I { $_[0]->_append_tag( '' ) unless $_[0]->_skip_headings() }
301 30 50   30   52 sub _end_B { $_[0]->_append_tag( '' ) unless $_[0]->_skip_headings() }
302 11 50   11   34 sub _end_C { $_[0]->_append_tag( '' ) unless $_[0]->_skip_headings() }
303 10     10   35 sub _end_F { $_[0]->_end_I }
304              
305              
306             ###############################################################################
307             #
308             # Functions to deal with the Pod =head directives
309             #
310 14     14   158 sub _start_head1 { $_[0]->_append_tag( '

' ) }

311 9     9   32 sub _start_head2 { $_[0]->_append_tag( '

' ) }

312 9     9   27 sub _start_head3 { $_[0]->_append_tag( '

' ) }

313 9     9   28 sub _start_head4 { $_[0]->_append_tag( '

' ) }

314              
315 14     14   38 sub _end_head1 { $_[0]->_append_tag( '' ); $_[0]->_output() }
  14         65  
316 9     9   29 sub _end_head2 { $_[0]->_append_tag( '' ); $_[0]->_output() }
  9         26  
317 9     9   30 sub _end_head3 { $_[0]->_append_tag( '' ); $_[0]->_output() }
  9         21  
318 9     9   26 sub _end_head4 { $_[0]->_append_tag( '' ); $_[0]->_output() }
  9         19  
319              
320              
321             ###############################################################################
322             #
323             # Functions to deal with verbatim paragraphs. We emit the text "as is" for now.
324             # TODO: escape any Wiki formatting in text such as ''code''.
325             #
326 1     1   6 sub _start_Verbatim { $_[0]->_append_tag( '
' ) } 
327 1     1   3 sub _end_Verbatim { $_[0]->_append_tag( '' ); $_[0]->_output() }
  1         6  
328              
329              
330             ###############################################################################
331             #
332             # Functions to deal with =over ... =back regions for
333             #
334             # Bulleted lists
335             # Numbered lists
336             # Text lists
337             # Block lists
338             #
339 63     63   257 sub _start_over_bullet { $_[0]->{_item_indent}++ }
340 63     63   161 sub _start_over_number { $_[0]->{_item_indent}++ }
341 74     74   188 sub _start_over_text { $_[0]->{_item_indent}++ }
342              
343             sub _end_over_bullet {
344 63     63   92 $_[0]->{_item_indent}--;
345 63 100       201 $_[0]->_output( "\n" ) unless $_[0]->{_item_indent};
346             }
347              
348             sub _end_over_number {
349 63     63   97 $_[0]->{_item_indent}--;
350 63 100       194 $_[0]->_output( "\n" ) unless $_[0]->{_item_indent};
351             }
352              
353             sub _end_over_text {
354 74     74   106 $_[0]->{_item_indent}--;
355 74 100       218 $_[0]->_output( "\n" ) unless $_[0]->{_item_indent};
356             }
357              
358 125     125   347 sub _start_item_bullet { $_[0]->_indent_item( 'bullet' ) }
359 125     125   419 sub _start_item_number { $_[0]->_indent_item( 'number', $_[1]->{number} ) }
360 137     137   327 sub _start_item_text { $_[0]->_indent_item( 'text' ) }
361              
362 125     125   258 sub _end_item_bullet { $_[0]->_output( "\n" ) }
363 125     125   229 sub _end_item_number { $_[0]->_output( "\n" ) }
364              
365 13     13   20 sub _end_item_text { $_[0]->_output( ":\t" ) } # Format specific.
366              
367 10     10   35 sub _start_over_block { $_[0]->{_item_indent}++ }
368 10     10   27 sub _end_over_block { $_[0]->{_item_indent}-- }
369              
370              
371             ###############################################################################
372             #
373             # _start_Para()
374             #
375             # Special handling for paragraphs that are part of an "over" block.
376             #
377             sub _start_Para {
378              
379 19     19   17 my $self = shift;
380 19         18 my $indent_level = $self->{_item_indent};
381              
382 19 100       45 if ( $self->{_in_over_block} ) {
383 1         3 $self->_append( ( "\t" x $indent_level ) . " :\t" );
384             }
385             }
386              
387              
388             ###############################################################################
389             #
390             # _end_Para()
391             #
392             # Special handling for paragraphs that are part of an "over_text" block.
393             #
394             sub _end_Para {
395              
396 195     195   169 my $self = shift;
397              
398             # Only add a newline if the paragraph isn't part of a text
399 195 100       337 if ( $self->{_in_over_text} ) {
400              
401             # Do nothing in this format.
402             }
403             else {
404 96         168 $self->_output( "\n" );
405             }
406              
407 195         281 $self->_output( "\n" );
408             }
409              
410              
411             1;
412              
413              
414             __END__