/[socialtext-import]/Pod-Simple-Wiki/lib/Pod/Simple/Wiki.pm
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Annotation of /Pod-Simple-Wiki/lib/Pod/Simple/Wiki.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (hide annotations)
Tue Nov 28 14:15:41 2006 UTC (17 years, 5 months ago) by dpavlin
File size: 20967 byte(s)
import upstream Pod-Simple-Wiki-0.05.tar.gz
1 dpavlin 3 package Pod::Simple::Wiki;
2    
3     ###############################################################################
4     #
5     # Pod::Simple::Wiki - A class for creating Pod to Wiki filters.
6     #
7     #
8     # Copyright 2003-2005, John McNamara, jmcnamara@cpan.org
9     #
10     # Documentation after __END__
11     #
12    
13     use strict;
14     #use Pod::Simple::Debug (5);
15     use Pod::Simple;
16     use vars qw(@ISA $VERSION);
17    
18     @ISA = qw(Pod::Simple);
19     $VERSION = '0.05';
20    
21     my $_debug = 0;
22    
23    
24     ###############################################################################
25     ###############################################################################
26     #
27     # The tag mappings for various Wiki text formats
28     #
29    
30     my %tags = (
31     'wiki' => {
32     '<b>' => "'''",
33     '</b>' => "'''",
34     '<i>' => "''",
35     '</i>' => "''",
36     '<tt>' => '"',
37     '</tt>' => '"',
38     '<pre>' => '',
39     '</pre>' => "\n\n",
40    
41     '<h1>' => "\n----\n'''",
42     '</h1>' => "'''\n\n",
43     '<h2>' => "\n'''''",
44     '</h2>' => "'''''\n\n",
45     '<h3>' => "\n''",
46     '</h3>' => "''\n\n",
47     '<h4>' => "\n",
48     '</h4>' => "\n\n",
49     },
50    
51     'kwiki' => {
52     '<b>' => '*',
53     '</b>' => '*',
54     '<i>' => '/',
55     '</i>' => '/',
56     '<tt>' => '[=',
57     '</tt>' => ']',
58     '<pre>' => '',
59     '</pre>' => "\n\n",
60    
61     '<h1>' => "\n----\n= ",
62     '</h1>' => " =\n\n",
63     '<h2>' => "\n== ",
64     '</h2>' => " ==\n\n",
65     '<h3>' => "\n=== ",
66     '</h3>' => " ===\n\n",
67     '<h4>' => "==== ",
68     '</h4>' => "\n\n",
69     },
70    
71     'usemod' => {
72     '<b>' => '<b>',
73     '</b>' => '</b>',
74     '<i>' => '<i>',
75     '</i>' => '</i>',
76     '<tt>' => '<tt>',
77     '</tt>' => '</tt>',
78     '<pre>' => "\n<pre>\n",
79     '</pre>' => "\n</pre>\n\n",
80    
81     '<h1>' => "\n= ",
82     '</h1>' => " =\n\n",
83     '<h2>' => "\n== ",
84     '</h2>' => " ==\n\n",
85     '<h3>' => "\n=== ",
86     '</h3>' => " ===\n",
87     '<h4>' => "\n==== ",
88     '</h4>' => " ====\n\n",
89     },
90    
91     'usemod_classic' => {
92     '<b>' => "'''",
93     '</b>' => "'''",
94     '<i>' => "''",
95     '</i>' => "''",
96     '<tt>' => '<tt>',
97     '</tt>' => '</tt>',
98     '<pre>' => "\n<pre>\n",
99     '</pre>' => "\n</pre>\n\n",
100    
101     '<h1>' => "\n= ",
102     '</h1>' => " =\n\n",
103     '<h2>' => "\n== ",
104     '</h2>' => " ==\n\n",
105     '<h3>' => "\n=== ",
106     '</h3>' => " ===\n",
107     '<h4>' => "\n==== ",
108     '</h4>' => " ====\n\n",
109     },
110    
111    
112     'twiki' => {
113     '<b>' => "*",
114     '</b>' => "*",
115     '<i>' => "_",
116     '</i>' => "_",
117     '<tt>' => '=',
118     '</tt>' => '=',
119     '<pre>' => "\n<verbatim>\n",
120     '</pre>' => "\n</verbatim>\n\n",
121    
122     '<h1>' => "---+ ",
123     '</h1>' => "\n\n",
124     '<h2>' => "---++ ",
125     '</h2>' => "\n\n",
126     '<h3>' => "---+++ ",
127     '</h3>' => "\n\n",
128     '<h4>' => "---++++ ",
129     '</h4>' => "\n\n",
130     },
131     'wikipedia' => {
132     '<b>' => "'''",
133     '</b>' => "'''",
134     '<i>' => "''",
135     '</i>' => "''",
136     '<tt>' => '<tt>',
137     '</tt>' => '</tt>',
138     '<pre>' => "\n<code>\n",
139     '</pre>' => "\n</code>\n",
140    
141     '<h1>' => "==",
142     '</h1>' => "==\n",
143     '<h2>' => "===",
144     '</h2>' => "===\n",
145     '<h3>' => "====",
146     '</h3>' => "====\n",
147     '<h4>' => "=====",
148     '</h4>' => "=====\n",
149     },
150     );
151    
152    
153     ###############################################################################
154     #
155     # new()
156     #
157     # Simple constructor inheriting from Pod::Simple.
158     #
159     sub new {
160    
161     my $class = shift;
162     my $format = lc shift || 'wiki';
163     $format = 'wikipedia' if $format eq 'mediawiki';
164     $format = 'wiki' unless exists $tags{$format};
165    
166     my $self = Pod::Simple->new(@_);
167     $self->{_wiki_text} = '';
168     $self->{_format} = $format;
169     $self->{_tags} = $tags{$format};
170     $self->{output_fh} ||= *STDOUT{IO};
171    
172     bless $self, $class;
173     return $self;
174     }
175    
176    
177     ###############################################################################
178     #
179     # _append()
180     #
181     # Appends some text to the buffered Wiki text.
182     #
183     sub _append {
184    
185     my $self = shift;
186    
187     $self->{_wiki_text} .= $_[0];
188     }
189    
190    
191     ###############################################################################
192     #
193     # _output()
194     #
195     # Appends some text to the buffered Wiki text and then emits it. Also resets
196     # the buffer.
197     #
198     sub _output {
199    
200     my $self = shift;
201     my $text = $_[0];
202    
203     $text = '' unless defined $text;
204    
205     print {$self->{output_fh}} $self->{_wiki_text}, $text;
206    
207     $self->{_wiki_text} = '';
208     }
209    
210    
211     ###############################################################################
212     #
213     # _indent_item()
214     #
215     # Indents an "over-item" to the correct level.
216     #
217     sub _indent_item {
218    
219     my $self = shift;
220     my $item_type = $_[0];
221     my $item_param = $_[1];
222     my $indent_level = $self->{_item_indent};
223    
224     if ($self->{_format} eq 'wiki') {
225    
226     if ($item_type eq 'bullet') {
227     $self->_append("*" x $indent_level);
228     # This was the way C2 Wiki used to define a bullet list
229     # $self->_append("\t" x $indent_level . '*');
230     }
231     elsif ($item_type eq 'number') {
232     $self->_append("\t" x $indent_level . $item_param);
233     }
234     elsif ($item_type eq 'text') {
235     $self->_append("\t" x $indent_level);
236     }
237     }
238     elsif ($self->{_format} eq 'kwiki') {
239    
240     if ($item_type eq 'bullet') {
241     $self->_append('*' x $indent_level . ' ');
242     }
243     elsif ($item_type eq 'number') {
244     $self->_append('0' x $indent_level . ' ');
245     }
246     elsif ($item_type eq 'text') {
247     $self->_append(";" x $indent_level . ' ');
248     }
249     }
250     elsif ($self->{_format} eq 'usemod') {
251    
252     if ($item_type eq 'bullet') {
253     $self->_append('*' x $indent_level);
254     }
255     elsif ($item_type eq 'number') {
256     $self->_append('#' x $indent_level);
257     }
258     elsif ($item_type eq 'text') {
259     $self->_append(";" x $indent_level);
260     }
261     }
262     elsif ($self->{_format} eq 'twiki') {
263    
264     if ($item_type eq 'bullet') {
265     $self->_append(' ' x $indent_level . "* ");
266     }
267     elsif ($item_type eq 'number') {
268     $self->_append(' ' x $indent_level . $item_param . ". ");
269     }
270     elsif ($item_type eq 'text') {
271     $self->_append(' ' x $indent_level . '$ ' );
272     }
273     }
274     elsif ($self->{_format} eq 'wikipedia') {
275    
276     if ($item_type eq 'bullet') {
277     $self->_append('*' x $indent_level . ' ');
278     }
279     elsif ($item_type eq 'number') {
280     $self->_append('#' x $indent_level . ' ');
281     }
282     elsif ($item_type eq 'text') {
283     $self->_append(";" x $indent_level . ' ');
284     }
285     }
286     }
287    
288    
289     ###############################################################################
290     #
291     # _skip_headings()
292     #
293     # Formatting in headings doesn't look great or is ignored in some formats.
294     #
295     sub _skip_headings {
296    
297     my $self = shift;
298    
299     return (
300     $self->{_format} eq 'kwiki' and
301     ($self->{_in_head1} or
302     $self->{_in_head2} or
303     $self->{_in_head3} or
304     $self->{_in_head4})
305     );
306     }
307    
308    
309     ###############################################################################
310     #
311     # _append_tag()
312     #
313     # Add an open or close tag to the current text.
314     #
315     sub _append_tag {
316    
317     my $self = shift;
318     my $tag = $_[0];
319    
320     $self->_append($self->{_tags}->{$tag});
321     }
322    
323    
324     ###############################################################################
325     ###############################################################################
326     #
327     # The methods in the following section are required by Pod::Simple to handle
328     # Pod directives and elements.
329     #
330     # The methods _handle_element_start() _handle_element_end() and _handle_text()
331     # are called by Pod::Simple in response to Pod constructs. We use
332     # _handle_element_start() and _handle_element_end() to generate calls to more
333     # specific methods. This is basically a long-hand version of Pod::Simple::
334     # Methody with the addition of location tracking.
335     #
336    
337    
338     ###############################################################################
339     #
340     # _handle_element_start()
341     #
342     # Call a method to handle the start of a element if one has been defined.
343     # We also set a flag to indicate that we are "in" the element type.
344     #
345     sub _handle_element_start {
346    
347     my $self = shift;
348     my $element = $_[0];
349    
350     $element =~ tr/-/_/;
351    
352     print "<$element>\n" if $_debug;
353    
354     $self->{"_in_". $element}++;
355    
356     if (my $method = $self->can('_start_' . $element)) {
357     $method->($self, $_[1]);
358     }
359     }
360    
361    
362     ###############################################################################
363     #
364     # _handle_element_end()
365     #
366     # Call a method to handle the end of a element if one has been defined.
367     # We also set a flag to indicate that we are "out" of the element type.
368     #
369     sub _handle_element_end {
370    
371     my $self = shift;
372     my $element = $_[0];
373    
374     $element =~ tr/-/_/;
375    
376     if (my $method = $self->can('_end_' . $element)) {
377     $method->($self);
378     }
379    
380     $self->{"_in_". $element}--;
381    
382     print "</$element>\n" if $_debug;
383     }
384    
385    
386     ###############################################################################
387     #
388     # _handle_text()
389     #
390     # Perform any necessary transforms on the text. This is mainly used to escape
391     # inadvertent CamelCase words.
392     #
393     sub _handle_text {
394    
395     my $self = shift;
396     my $text = $_[0];
397    
398     # Only escape CamelCase in Kwiki paragraphs
399     if ($self->{_format} eq 'kwiki' and not $self->{_in_Para}) {
400     $self->{_wiki_text} .= $text;
401     return;
402     }
403    
404     # Split the text into tokens but maintain the whitespace
405     my @tokens = split /(\s+)/, $text;
406    
407     if ($self->{_format} eq 'wiki') {
408     for (@tokens) {
409     next unless /\S/; # Ignore the whitespace
410     next if m[^(ht|f)tp://]; # Ignore URLs
411     s/([A-Z][a-z]+)(?=[A-Z])/$1''''''/g # Escape with 6 single quotes
412    
413     }
414     }
415     elsif ($self->{_format} eq 'kwiki') {
416     for (@tokens) {
417     next unless /\S/; # Ignore the whitespace
418     next if m[^(ht|f)tp://]; # Ignore URLs
419     s/([A-Z][a-z]+[A-Z]\w+)/!$1/g; # Escape with !
420     }
421     }
422     # TODO: Add usemod <nowiki> escapes
423    
424     # Rejoin the tokens and whitespace.
425     $self->{_wiki_text} .= join '', @tokens;
426     }
427    
428    
429     ###############################################################################
430     #
431     # Functions to deal with the I<>, B<> and C<> formatting codes.
432     #
433     sub _start_I {$_[0]->_append_tag('<i>') unless $_[0]->_skip_headings()}
434     sub _start_B {$_[0]->_append_tag('<b>') unless $_[0]->_skip_headings()}
435     sub _start_C {$_[0]->_append_tag('<tt>') unless $_[0]->_skip_headings()}
436     sub _start_F {$_[0]->_start_I}
437    
438     sub _end_I {$_[0]->_append_tag('</i>') unless $_[0]->_skip_headings()}
439     sub _end_B {$_[0]->_append_tag('</b>') unless $_[0]->_skip_headings()}
440     sub _end_C {$_[0]->_append_tag('</tt>') unless $_[0]->_skip_headings()}
441     sub _end_F {$_[0]->_end_I}
442    
443    
444     ###############################################################################
445     #
446     # Functions to deal with the Pod =head directives
447     #
448     sub _start_head1 {$_[0]->_append_tag('<h1>')}
449     sub _start_head2 {$_[0]->_append_tag('<h2>')}
450     sub _start_head3 {$_[0]->_append_tag('<h3>')}
451     sub _start_head4 {$_[0]->_append_tag('<h4>')}
452    
453     sub _end_head1 {$_[0]->_append_tag('</h1>'); $_[0]->_output()}
454     sub _end_head2 {$_[0]->_append_tag('</h2>'); $_[0]->_output()}
455     sub _end_head3 {$_[0]->_append_tag('</h3>'); $_[0]->_output()}
456     sub _end_head4 {$_[0]->_append_tag('</h4>'); $_[0]->_output()}
457    
458    
459     ###############################################################################
460     #
461     # Functions to deal with verbatim paragraphs. We emit the text "as is" for now.
462     # TODO: escape any Wiki formatting in text such as ''code''.
463     #
464     sub _start_Verbatim {$_[0]->_append_tag('<pre>')}
465     sub _end_Verbatim {$_[0]->_append_tag('</pre>'); $_[0]->_output()}
466    
467    
468     ###############################################################################
469     #
470     # Functions to deal with =over ... =back regions for
471     #
472     # Bulleted lists
473     # Numbered lists
474     # Text lists
475     # Block lists
476     #
477     sub _start_over_bullet {$_[0]->{_item_indent}++}
478     sub _start_over_number {$_[0]->{_item_indent}++}
479     sub _start_over_text {$_[0]->{_item_indent}++}
480    
481     sub _end_over_bullet {$_[0]->{_item_indent}--;
482     $_[0]->_output("\n") unless $_[0]->{_item_indent}}
483    
484     sub _end_over_number {$_[0]->{_item_indent}--;
485     $_[0]->_output("\n") unless $_[0]->{_item_indent}}
486    
487     sub _end_over_text {$_[0]->{_item_indent}--;
488     $_[0]->_output("\n") unless $_[0]->{_item_indent}}
489    
490     sub _start_item_bullet {$_[0]->_indent_item('bullet')}
491     sub _start_item_number {$_[0]->_indent_item('number', $_[1]->{number})}
492     sub _start_item_text {$_[0]->_indent_item('text')}
493    
494     sub _end_item_bullet {$_[0]->_output("\n")}
495     sub _end_item_number {$_[0]->_output("\n")}
496     sub _end_item_text {$_[0]->_output(":\t") if $_[0]->{_format} eq 'wiki';
497     $_[0]->_output(" ; ") if $_[0]->{_format} eq 'kwiki';
498     $_[0]->_output(":" ) if $_[0]->{_format} eq 'usemod';
499     $_[0]->_output(": " ) if $_[0]->{_format} eq 'twiki';
500     $_[0]->_output(" : ") if $_[0]->{_format} eq 'wikipedia';}
501    
502     sub _start_over_block {$_[0]->{_item_indent}++}
503     sub _end_over_block {$_[0]->{_item_indent}--}
504    
505    
506     ###############################################################################
507     #
508     # _start_Para()
509     #
510     # Special handling for paragraphs that are part of an "over" block.
511     #
512     sub _start_Para {
513    
514     my $self = shift;
515     my $indent_level = $self->{_item_indent};
516    
517     if ($self->{_in_over_block}) {
518    
519     if ($self->{_format} eq 'wiki') {
520     $self->_append(("\t" x $indent_level) . " :\t");
521     }
522     elsif ($self->{_format} eq 'usemod') {
523     $self->_append(":" x $indent_level);
524     }
525     }
526     }
527    
528    
529     ###############################################################################
530     #
531     # _end_Para()
532     #
533     # Special handling for paragraphs that are part of an "over_text" block.
534     # This is mainly required be Kwiki.
535     #
536     sub _end_Para {
537    
538     my $self = shift;
539    
540     # Only add a newline if the paragraph isn't part of a text
541     if ($self->{_in_over_text}) {
542     # Workaround for the fact that Kwiki doesn't have a definition block
543     #$self->_output("\n") if $self->{_format} eq 'kwiki';
544     }
545     else {
546     $self->_output("\n");
547     }
548    
549     $self->_output("\n")
550     }
551    
552    
553     1;
554    
555    
556     __END__
557    
558     =head1 NAME
559    
560     Pod::Simple::Wiki - A class for creating Pod to Wiki filters.
561    
562     =head1 SYNOPSIS
563    
564     To create a simple C<pod2wiki> filter:
565    
566     #!/usr/bin/perl -w
567    
568     use strict;
569     use Pod::Simple::Wiki;
570    
571    
572     my $parser = Pod::Simple::Wiki->new();
573    
574     if (defined $ARGV[0]) {
575     open IN, $ARGV[0] or die "Couldn't open $ARGV[0]: $!\n";
576     } else {
577     *IN = *STDIN;
578     }
579    
580     if (defined $ARGV[1]) {
581     open OUT, ">$ARGV[1]" or die "Couldn't open $ARGV[1]: $!\n";
582     } else {
583     *OUT = *STDOUT;
584     }
585    
586     $parser->output_fh(*OUT);
587     $parser->parse_file(*IN);
588    
589     __END__
590    
591    
592     =head1 DESCRIPTION
593    
594     The C<Pod::Simple::Wiki> module is used for converting Pod text to Wiki text.
595    
596     Pod (Plain Old Documentation) is a simple markup language used for writing Perl documentation.
597    
598     A Wiki is a user extensible web site. It uses very simple mark-up that is converted to Html.
599    
600     For an introduction to Wikis see: http://en.wikipedia.org/wiki/Wiki
601    
602    
603     =head1 METHODS
604    
605     =head2 new()
606    
607     The C<new> method is used to create a new L<Pod::Simple::Wiki> object. It is also used to set the output Wiki format.
608    
609     my $parser1 = Pod::Simple::Wiki->new('wiki');
610     my $parser2 = Pod::Simple::Wiki->new('kwiki');
611     my $parser3 = Pod::Simple::Wiki->new(); # Defaults to 'wiki'
612    
613     The currently supported formats are:
614    
615     =over 4
616    
617     =item wiki
618    
619     This is the original Wiki format as used on Ward Cunningham's Portland repository of Patterns. The formatting rules are given at http://c2.com/cgi/wiki?TextFormattingRules
620    
621     =item kwiki
622    
623     This is the format as used by Brian Ingerson's CGI::Kwiki: http://search.cpan.org/dist/CGI-Kwiki/
624    
625     =item usemod
626    
627     This is the format used by the Usemod wikis. See: http://www.usemod.com/cgi-bin/wiki.pl?WikiFormat
628    
629     =item twiki
630    
631     This is the format used by TWiki wikis. See: http://www.twiki.org/
632    
633     =item wikipedia or mediawiki
634    
635     This is the format used by Wikipedia and MediaWiki wikis. See: http://www.wikipedia.org/
636    
637     =back
638    
639     If no format is specified the parser defaults to C<wiki>.
640    
641     Any other parameters in C<new> will be passed on to the parent L<Pod::Simple> object. See L<Pod::Simple> for more details.
642    
643    
644     =head2 Other methods
645    
646     Pod::Simple::Wiki inherits all of the methods of L<Pod::Simple>. See L<Pod::Simple> for more details.
647    
648    
649     =head1 TODO
650    
651     =over 4
652    
653     =item *
654    
655     Add more code, more tests and a few more users if possible.
656    
657     =item *
658    
659     Add other Wiki formats. Send requests or patches.
660    
661     =item *
662    
663     Fix some of the C<=over> edge cases. See the TODOs in the test programs.
664    
665     =back
666    
667    
668    
669     =head1 SEE ALSO
670    
671     This module also installs a C<pod2wiki> command line utility. See C<pod2wiki --help> for details.
672    
673    
674     =head1 ACKNOWLEDGEMENTS
675    
676     Thanks to Sean M. Burke for C<Pod::Simple>. It may not be simple but sub-classing it is. C<:-)>
677    
678     Thanks to Sam Tregar for TWiki support.
679    
680     Thanks Tony Sidaway for Wikipedia/MediaWiki support.
681    
682    
683     =head1 AUTHOR
684    
685     John McNamara jmcnamara@cpan.org
686    
687    
688     =head1 COPYRIGHT
689    
690     © MMIII-MMV, John McNamara.
691    
692     All Rights Reserved. This module is free software. It may be used, redistributed and/or modified under the same terms as Perl itself.
693    

  ViewVC Help
Powered by ViewVC 1.1.26