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-2015, 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 43     43   28013 use strict;
  43         77  
  43         1149  
16              
17             #use Pod::Simple::Debug (5);
18 43     43   44567 use Pod::Simple;
  43         1530528  
  43         1377  
19 43     43   394 use vars qw(@ISA $VERSION);
  43         84  
  43         90223  
20              
21             @ISA = qw(Pod::Simple);
22             $VERSION = '0.19';
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 584     584 1 176655 my $class = shift;
59 584   50     1882 my $format = lc( shift || 'wiki' );
60 584 50       1420 $format = 'mediawiki' if $format eq 'wikipedia';
61 584 50       1320 $format = 'moinmoin' if $format eq 'moin';
62              
63 584         1377 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.
67 584 100       1380 if ( $format ne 'wiki' ) {
68 281         16313 eval "require $module";
69 281 50       1100 die "Module $module not implemented for wiki format $format\n" if $@;
70 281         1304 return $module->new( @_ );
71             }
72              
73 303         1504 my $self = Pod::Simple->new( @_ );
74 303         7333 $self->{_wiki_text} = '';
75 303         624 $self->{_tags} = $tags;
76 303   50     1949 $self->{output_fh} ||= *STDOUT{IO};
77 303         606 $self->{_item_indent} = 0;
78 303         783 $self->{_debug} = 0;
79              
80             # Set Pod::Simple parser options
81             # - Merge contiguous text RT#60304
82 303         1053 $self->merge_text( 1 );
83              
84             # - Ignore X<> (index entries) RT#60307
85 303         2746 $self->nix_X_codes( 1 );
86              
87 303         1923 bless $self, $class;
88 303         868 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 644     644   952 my $self = shift;
116              
117 644         2146 $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 1025     1025   1334 my $self = shift;
131 1025         1430 my $text = $_[0];
132              
133 1025 100       2148 $text = '' unless defined $text;
134              
135 1025         1133 print { $self->{output_fh} } $self->{_wiki_text}, $text;
  1025         3716  
136              
137 1025         9359 $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   48 my $self = shift;
150 37         42 my $item_type = $_[0];
151 37         42 my $item_param = $_[1];
152 37         52 my $indent_level = $self->{_item_indent};
153              
154 37 100       105 if ( $item_type eq 'bullet' ) {
    100          
    50          
155 12         35 $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         35 $self->_append( "\t" x $indent_level . $item_param );
162             }
163             elsif ( $item_type eq 'text' ) {
164 13         35 $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 170     170   250 my $self = shift;
178              
179 170         817 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 270     270   378 my $self = shift;
192 270         399 my $tag = $_[0];
193              
194 270         847 $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 1402     1402   423266 my $self = shift;
222 1402         2153 my $element = $_[0];
223              
224 1402         2066 $element =~ tr/-/_/;
225              
226 1402 50       3724 if ( $self->{_debug} ) {
227 0         0 print ' ' x $self->{_item_indent}, "<$element>\n";
228             }
229              
230 1402         3298 $self->{ "_in_" . $element }++;
231              
232 1402 100       7760 if ( my $method = $self->can( '_start_' . $element ) ) {
233 1099         2652 $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 1402     1402   41971 my $self = shift;
248 1402         1956 my $element = $_[0];
249              
250 1402         1911 $element =~ tr/-/_/;
251              
252 1402 100       6699 if ( my $method = $self->can( '_end_' . $element ) ) {
253 1099         2273 $method->( $self );
254             }
255              
256 1402         3097 $self->{ "_in_" . $element }--;
257              
258 1402 50       4827 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   443 my $self = shift;
274 60         82 my $text = $_[0];
275              
276             # Split the text into tokens but maintain the whitespace
277 60         253 my @tokens = split /(\s+)/, $text;
278              
279 60         116 for ( @tokens ) {
280 250 100       665 next unless /\S/; # Ignore the whitespace
281 155 50       286 next if m[^(ht|f)tp://]; # Ignore URLs
282 155         330 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         253 $self->{_wiki_text} .= join '', @tokens;
288             }
289              
290              
291             ###############################################################################
292             #
293             # Functions to deal with the I<>, B<> and C<> formatting codes.
294             #
295 44 50   44   157 sub _start_I { $_[0]->_append_tag( '' ) unless $_[0]->_skip_headings() }
296 33 50   33   100 sub _start_B { $_[0]->_append_tag( '' ) unless $_[0]->_skip_headings() }
297 12 50   12   55 sub _start_C { $_[0]->_append_tag( '' ) unless $_[0]->_skip_headings() }
298 11     11   52 sub _start_F { $_[0]->_start_I }
299              
300 44 50   44   123 sub _end_I { $_[0]->_append_tag( '' ) unless $_[0]->_skip_headings() }
301 33 50   33   129 sub _end_B { $_[0]->_append_tag( '' ) unless $_[0]->_skip_headings() }
302 12 50   12   49 sub _end_C { $_[0]->_append_tag( '' ) unless $_[0]->_skip_headings() }
303 11     11   48 sub _end_F { $_[0]->_end_I }
304              
305              
306             ###############################################################################
307             #
308             # Functions to deal with the Pod =head directives
309             #
310 15     15   182 sub _start_head1 { $_[0]->_append_tag( '

' ) }

311 10     10   38 sub _start_head2 { $_[0]->_append_tag( '

' ) }

312 10     10   39 sub _start_head3 { $_[0]->_append_tag( '

' ) }

313 10     10   42 sub _start_head4 { $_[0]->_append_tag( '

' ) }

314              
315 15     15   48 sub _end_head1 { $_[0]->_append_tag( '' ); $_[0]->_output() }
  15         86  
316 10     10   34 sub _end_head2 { $_[0]->_append_tag( '' ); $_[0]->_output() }
  10         28  
317 10     10   37 sub _end_head3 { $_[0]->_append_tag( '' ); $_[0]->_output() }
  10         26  
318 10     10   37 sub _end_head4 { $_[0]->_append_tag( '' ); $_[0]->_output() }
  10         26  
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   8 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 70     70   312 sub _start_over_bullet { $_[0]->{_item_indent}++ }
340 70     70   204 sub _start_over_number { $_[0]->{_item_indent}++ }
341 83     83   248 sub _start_over_text { $_[0]->{_item_indent}++ }
342              
343             sub _end_over_bullet {
344 70     70   119 $_[0]->{_item_indent}--;
345 70 100       258 $_[0]->_output( "\n" ) unless $_[0]->{_item_indent};
346             }
347              
348             sub _end_over_number {
349 70     70   124 $_[0]->{_item_indent}--;
350 70 100       241 $_[0]->_output( "\n" ) unless $_[0]->{_item_indent};
351             }
352              
353             sub _end_over_text {
354 83     83   134 $_[0]->{_item_indent}--;
355 83 100       287 $_[0]->_output( "\n" ) unless $_[0]->{_item_indent};
356             }
357              
358 139     139   395 sub _start_item_bullet { $_[0]->_indent_item( 'bullet' ) }
359 139     139   429 sub _start_item_number { $_[0]->_indent_item( 'number', $_[1]->{number} ) }
360 154     154   455 sub _start_item_text { $_[0]->_indent_item( 'text' ) }
361              
362 139     139   338 sub _end_item_bullet { $_[0]->_output( "\n" ) }
363 139     139   311 sub _end_item_number { $_[0]->_output( "\n" ) }
364              
365 13     13   26 sub _end_item_text { $_[0]->_output( ":\t" ) } # Format specific.
366              
367 11     11   76 sub _start_over_block { $_[0]->{_item_indent}++ }
368 11     11   30 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   26 my $self = shift;
380 19         25 my $indent_level = $self->{_item_indent};
381              
382 19 100       69 if ( $self->{_in_over_block} ) {
383 1         5 $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 223     223   336 my $self = shift;
397              
398             # Only add a newline if the paragraph isn't part of a text
399 223 100       549 if ( $self->{_in_over_text} ) {
400              
401             # Do nothing in this format.
402             }
403             else {
404 110         277 $self->_output( "\n" );
405             }
406              
407 223         485 $self->_output( "\n" );
408             }
409              
410              
411             1;
412              
413              
414             __END__