File Coverage

blib/lib/Text/KwikiFormatish.pm
Criterion Covered Total %
statement 245 270 90.7
branch 41 60 68.3
condition 6 7 85.7
subroutine 60 63 95.2
pod 48 48 100.0
total 400 448 89.2


line stmt bran cond sub pod time code
1             package Text::KwikiFormatish;
2 5     5   28774 use strict;
  5         10  
  5         191  
3 5     5   28 use warnings;
  5         7  
  5         264  
4              
5             our $VERSION = '1.11';
6              
7 5     5   4790 use CGI::Util qw(escape unescape);
  5         26311  
  5         553  
8              
9             =head1 NAME
10              
11             Text::KwikiFormatish - convert Kwikitext into XML-compliant HTML
12              
13             =head1 SYNOPSIS
14              
15             use Text::KwikiFormatish;
16             my $xhtml = Text::KwikiFormatish::format($text);
17              
18             =head1 DESCRIPTION
19              
20             B I module is based off of the old L formatter. Ideally, L would be written to use the new the new L formatter.
21              
22             L includes a formatter (L) for converting
23             Kwikitext (a nice form of wikitext) to HTML. Unfortunately, it isn't easy to
24             use the formatter outside the L environment. Additionally, the HTML
25             produced by the formatter isn't XHTML-1 compliant. This module aims to fix both
26             of these issues and provide an interface similar to L.
27              
28             Essentially, this module is the code from Brian Ingerson's
29             L with a C subroutine, code relating to slides
30             removed, tweaked subroutinesa, and more.
31              
32             Since the wikitext spec for input wikitext for this module differs a little
33             from the default Kwiki formatter, I thought it best to call it "Formatish"
34             instead of *the* Kwiki Format.
35              
36             =cut
37              
38 5     5   44 use vars qw($UPPER $LOWER $ALPHANUM $WORD $WIKIWORD @DEFAULTPROCESSORDER);
  5         12  
  5         21928  
39              
40             $UPPER = '\p{UppercaseLetter}';
41             $LOWER = '\p{LowercaseLetter}';
42             $ALPHANUM = '\p{Letter}\p{Number}';
43             $WORD = '\p{Letter}\p{Number}\p{ConnectorPunctuation}';
44             $WIKIWORD = "$UPPER$LOWER\\p{Number}\\p{ConnectorPunctuation}";
45              
46             @DEFAULTPROCESSORDER = qw(
47             function
48             header_1 header_2 header_3 header_4 header_5 header_6
49             escape_html
50             horizontal_line comment lists
51             code paragraph
52             named_http_link no_http_link http_link
53             no_mailto_link mailto_link
54             no_wiki_link force_wiki_link wiki_link
55             inline negation
56             bold italic underscore
57             mdash
58             table
59             );
60              
61             =head2 format()
62              
63             C takes one or two arguments, with the first always being the
64             wikitext to translate. The second is a hash of options, but currently the only
65             option supported is C in case you want to prefix wiki links with
66             sommething. For example,
67              
68             my $xml = Text::KwikiFormatish::format(
69             $text,
70             prefix => '/wiki/',
71             );
72              
73             =cut
74              
75             sub format {
76 5     5 1 3619 my ( $raw, %args ) = @_;
77              
78             # create instance of formatter
79 5         614 my $f = __PACKAGE__->new();
80              
81             # translate Text::Wikiformat args to Kwiki formatter args
82 5 50       25 $f->{_node_prefix} = $args{prefix} if exists $args{prefix};
83              
84             # do the deed
85 5         16 return $f->process($raw);
86             }
87              
88             =head1 EXTENDING
89              
90             L was designed to be subclassable so that the formatting
91             engine could be easily customized. Information on how the Kwiki formatter works
92             can be found at
93             L.
94              
95             For example, say you wanted to override the markup for strong (bold) text. You
96             decide that it would make much more sense to write strong text as C
97             bold textHEY>. You would subclass Text::KwikiFormatish and use it like so:
98              
99             package My::Formatter;
100             use base 'Text::KwikiFormatish';
101            
102             # I simply copied this from Text/KwikiFormatish.pm and tweaked it
103             sub bold {
104             my ($self, $text) = @_;
105             $text =~ s#(?$1#g;
106             return $text;
107             }
108            
109             package main;
110             my $data = join '', <>;
111             print My::Formatter->new->process( $data );
112              
113             =cut
114              
115             =head2 Administrative Methods
116              
117             =over 4
118              
119             =cut
120              
121             =item process( TEXT )
122              
123             Process the given TEXT as KwikiText and return XHTML.
124              
125             =cut
126              
127             sub process {
128 6     6 1 14 my ( $self, $wiki_text ) = @_;
129 6         13 my $array = [];
130 6         21 push @$array, $wiki_text . "\n";
131 6         15 for my $method ( $self->process_order ) {
132 168         384 $array = $self->_dispatch( $array, $method );
133             }
134 6         55 return $self->_combine_chunks($array);
135             }
136              
137             =item process_order()
138              
139             C returns a list of the formatting rules that will be applied
140             when C is called for this object. If called with a set of formatting
141             rules (names of class methods), that set of formatting rules will supercede the
142             default set.
143              
144             =cut
145              
146             sub process_order {
147 12     12 1 17 my $self = shift;
148 12 100       42 @{ $self->{'process_order'} } = @_ if (@_);
  6         54  
149 12         15 return ( @{ $self->{'process_order'} } );
  12         68  
150             }
151              
152             sub _dispatch {
153 168     168   228 my ( $self, $old_array, $method ) = @_;
154 168 50       744 return $old_array unless $self->can($method);
155 168         195 my $new_array;
156 168         260 for my $chunk (@$old_array) {
157 977 50       1671 if ( ref $chunk eq 'ARRAY' ) {
158 0         0 push @$new_array, $self->_dispatch( $chunk, $method );
159             }
160             else {
161 977 100       1437 if ( ref $chunk ) {
162 545         997 push @$new_array, $chunk;
163             }
164             else {
165 432         1239 push @$new_array, $self->$method($chunk);
166             }
167             }
168             }
169 168         561 return $new_array;
170             }
171              
172             sub _combine_chunks {
173 6     6   12 my ( $self, $chunk_array ) = @_;
174 6         14 my $formatted_text = '';
175 6         16 for my $chunk (@$chunk_array) {
176 49 100       162 $formatted_text .=
    50          
177             ( ref $chunk eq 'ARRAY' ) ? $self->_combine_chunks($chunk)
178             : ( ref $chunk ) ? $$chunk
179             : $chunk;
180             }
181 6         118 return $formatted_text;
182             }
183              
184             =item * new() - the constructor
185              
186             =cut
187              
188             sub new {
189 6     6 1 32 my ( $class, %args ) = @_;
190 6         13 my $self = {};
191 6         17 bless $self, $class;
192 6         21 my %defs = ( node_prefix => './', );
193 6         22 my %collated = ( %defs, %args );
194 6         19 foreach my $k ( keys %defs ) {
195 6         46 $self->{ "_" . $k } = $collated{$k};
196             }
197 6         34 $self->process_order(@DEFAULTPROCESSORDER);
198 6         22 $self->init(%args);
199 6         27 return $self;
200             }
201              
202             =item * init() - called by the constructor immediately after the objects creation
203              
204             =cut
205              
206 6     6 1 10 sub init { }
207              
208             =back
209              
210             =cut
211              
212             =head2 Helper Methods
213              
214             =over 4
215              
216             =item * split_method( TEXT, REGEXP, METHOD ) - calls METHOD on any matches in TEXT for groups in REGEXP
217              
218             =cut
219              
220             sub split_method {
221 273     273 1 170927 my ( $self, $text, $regexp, $method ) = @_;
222 273         325 my $i = 0;
223 273 100       1094 map { $i++ % 2 ? \$self->$method($_) : $_ } split $regexp, $text;
  307         1825  
224             }
225              
226             =item * escape_html( TEXT ) - returns TEXT with HTML entities escaped
227              
228             =cut
229              
230             sub escape_html {
231 22     22 1 30 my ( $self, $text ) = @_;
232 22         42 $text =~ s/&/&/g;
233 22         33 $text =~ s/
234 22         25 $text =~ s/>/>/g;
235 22         60 $text;
236             }
237              
238             =back
239              
240             =cut
241              
242             =head2 Formatter Methods
243              
244             These are the methods you'll probably override most often. They define the
245             regular expressions that the formatter uses to split text as well as what to do
246             with each chunk.
247              
248             Many of these methods have corrosponding C methods, which take the
249             chunk and format it as XHTML.
250              
251             =over 4
252              
253             =item * function - user-definable functions
254              
255             =cut
256              
257             sub function {
258 6     6 1 11 my ( $self, $text ) = @_;
259 6         39 $self->split_method( $text, qr{\[\&(\w+\b.*?)\]}, '_function_format', );
260             }
261              
262             sub _function_format {
263 5     5   6 my ( $self, $text ) = @_;
264 5         11 my ( $method, @args ) = split;
265 5 50       9 $self->_isa_function($method)
266             ? $self->$method(@args)
267             : "\n";
268             }
269              
270             sub _isa_function {
271 5     5   6 my ( $self, $function ) = @_;
272 5 50       7 defined { map { ( $_, 1 ) } $self->user_functions }->{$function}
  15         52  
273             and $self->can($function);
274             }
275              
276             =item * table - tabular data
277              
278             =cut
279              
280             sub table {
281 20     20 1 37 my ( $self, $text ) = @_;
282 20         23 my @array;
283 20         69 while ( $text =~ /(.*?)(^\|[^\n]*\|\n.*)/ms ) {
284 1         4 push @array, $1;
285 1         3 my $table;
286 1         4 ( $table, $text ) = $self->_parse_table($2);
287 1         4 push @array, $table;
288             }
289 20 50       57 push @array, $text if length $text;
290 20         68 return @array;
291             }
292              
293             sub _parse_table {
294 1     1   2 my ( $self, $text ) = @_;
295 1         3 my $error = '';
296 1         1 my $rows;
297 1         7 while ( $text =~ s/^(\|(.*)\|\n)// ) {
298 1         4 $error .= $1;
299 1         3 my $data = $2;
300 1         3 my $row = [];
301 1         5 for my $datum ( split /\|/, $data ) {
302 2         44 $datum =~ s/^\s*(.*?)\s*$/$1/;
303 2 50       7 if ( $datum =~ s/^<<(\S+)$// ) {
304 0         0 my $marker = $1;
305 0         0 while ( $text =~ s/^(.*\n)// ) {
306 0         0 my $line = $1;
307 0         0 $error .= $line;
308 0 0       0 if ( $line eq "$marker\n" ) {
309 0         0 $marker = '';
310 0         0 last;
311             }
312 0         0 $datum .= $line;
313             }
314 0 0       0 if ( length $marker ) {
315 0         0 return ( $error, $text );
316             }
317             }
318 2         4 push @$row, $datum;
319             }
320 1         5 push @$rows, $row;
321             }
322 1         5 return ( $self->format_table($rows), $text );
323             }
324              
325             =item * format_table - format the table data as XHTML
326              
327             =cut
328              
329             sub format_table {
330 1     1 1 2 my ( $self, $rows ) = @_;
331 1         2 my $cols = 0;
332 1         2 for (@$rows) {
333 1 50       5 $cols = @$_ if @$_ > $cols;
334             }
335 1         2 my $table = qq{\n}; \n}; \n}; \n};
336 1         2 for my $row (@$rows) {
337 1         3 $table .= qq{
338 1         5 for ( my $i = 0; $i < @$row; $i++ ) {
339 2         3 my $colspan = '';
340 2 50 66     2 if ( $i == $#{$row} and $cols - $i > 1 ) {
  2         11  
341 0         0 $colspan = ' colspan="' . ( $cols - $i ) . '"';
342             }
343 2         9 my $cell = $self->escape_html( $row->[$i] );
344 2 50       6 $cell = qq{
$cell
\n}
345             if $cell =~ /\n/;
346 2 50       5 $cell = ' ' unless length $cell;
347 2         10 $table .= qq{$cell
348             }
349 1         3 $table .= qq{
350             }
351 1         2 $table .= qq{
\n};
352 1         12 return \$table;
353             }
354              
355             =item * no_wiki_link - things that look like wikilinks but are forced not to be
356              
357             =cut
358              
359             sub no_wiki_link {
360 18     18 1 36 my ( $self, $text ) = @_;
361 18         215 $self->split_method( $text,
362             qr{!([$UPPER](?=[$WORD]*[$UPPER])(?=[$WORD]*[$LOWER])[$WORD]+)},
363             'no_wiki_link_format', );
364             }
365              
366             =item * no_wiki_link_format - typically just the text that could have been a link
367              
368             =cut
369              
370             sub no_wiki_link_format {
371 1     1 1 3 my ( $self, $text ) = @_;
372 1         4 return $text;
373             }
374              
375             =item * wiki_link - a WikiLink
376              
377             =cut
378              
379             sub wiki_link {
380 19     19 1 35 my ( $self, $text ) = @_;
381 19         209 $self->split_method( $text,
382             qr{([$UPPER](?=[$WORD]*[$UPPER])(?=[$WORD]*[$LOWER])[$WORD]+)},
383             'wiki_link_format', );
384             }
385              
386             =item * force_wiki_link - a link that normally wouldn't have been one but is forced to be
387              
388             =cut
389              
390             sub force_wiki_link {
391 19     19 1 40 my ( $self, $text ) = @_;
392 19         166 $self->split_method( $text, qr{(?
393             'wiki_link_format', );
394             }
395              
396             =item * wiki_link_format - how to format wikilinks as XHTML
397              
398             =cut
399              
400             sub wiki_link_format {
401 1     1 1 3 my ( $self, $text ) = @_;
402 1         9 my $url = $self->escape($text);
403 1         16 my $wiki_link = qq{$text};
404 1         4 return $wiki_link;
405             }
406              
407             =item * no_http_link - what normally would have been an HTTP URI, but isn't
408              
409             =cut
410              
411             sub no_http_link {
412 15     15 1 25 my ( $self, $text ) = @_;
413 15         54 $self->split_method( $text, qr{(!(?:https?|ftp|irc):\S+?)}m,
414             'no_http_link_format', );
415             }
416              
417             =item * no_http_link_format - typically just the text
418              
419             =cut
420              
421             sub no_http_link_format {
422 0     0 1 0 my ( $self, $text ) = @_;
423 0         0 $text =~ s#!##;
424 0         0 return $text;
425             }
426              
427             =item * http_link - a regular http:// hyperlink
428              
429             =cut
430              
431             sub http_link {
432 15     15 1 23 my ( $self, $text ) = @_;
433 15         55 $self->split_method( $text,
434             qr{((?:https?|ftp|irc):\S+?(?=[),.:;]?\s|$))}m,
435             'http_link_format', );
436             }
437              
438             =item * http_link_format - how to format the given link
439              
440             =cut
441              
442             sub http_link_format {
443 2     2 1 4 my ( $self, $text ) = @_;
444 2 100       22 if ( $text =~ /^http.*\.(?i:jpg|gif|jpeg|png)$/ ) {
445 1         4 return $self->img_format($text);
446             }
447             else {
448 1         2 return $self->link_format($text);
449             }
450             }
451              
452             =item * no_mailto_link - what could have been a mailto: hyperlink
453              
454             =cut
455              
456             sub no_mailto_link {
457 17     17 1 31 my ( $self, $text ) = @_;
458 5     5   5690 $self->split_method( $text,
  5         92  
  5         63  
  17         360  
459             qr{(![$ALPHANUM][$WORD\-\.]*@[$WORD][$WORD\-\.]+)}m,
460             'no_mailto_link_format', );
461             }
462              
463             =item * no_mailto_link_format - typically just text
464              
465             =cut
466              
467             sub no_mailto_link_format {
468 0     0 1 0 my ( $self, $text ) = @_;
469 0         0 $text =~ s#!##;
470 0         0 return $text;
471             }
472              
473             =item * mailto_link - a mailto: hyperlink
474              
475             =cut
476              
477             sub mailto_link {
478 17     17 1 30 my ( $self, $text ) = @_;
479 17         185 $self->split_method( $text,
480             qr{([$ALPHANUM][$WORD\-\.]*@[$WORD][$WORD\-\.]+)}m,
481             'mailto_link_format', );
482             }
483              
484             =item * mailto_link_format - how to format the mailto: link
485              
486             =cut
487              
488             sub mailto_link_format {
489 1     1 1 2 my ( $self, $text ) = @_;
490 1 50       7 my $dot = ( $text =~ s/\.$// ) ? '.' : '';
491 1         7 qq{$text$dot};
492             }
493              
494             =item * img_format - inline images
495              
496             =cut
497              
498             sub img_format {
499 1     1 1 3 my ( $self, $url ) = @_;
500 1         4 return qq{};
501             }
502              
503             =item * link_format - a helper method for named_http_link_format and http_link_format
504              
505             =cut
506              
507             sub link_format {
508 2     2 1 4 my ( $self, $text ) = @_;
509 2         29 $text =~ s/(^\s*|\s+(?=\s)|\s$)//g;
510 2         3 my $url = $text;
511 2 100       10 $url = $1 if $text =~ s/(.*?) +//;
512 2         7 $url =~ s/https?:(?!\/\/)//;
513 2         10 return qq{$text};
514             }
515              
516             =item * named_http_link - an HTTP URI with a label
517              
518             =cut
519              
520             sub named_http_link {
521 21     21 1 36 my ( $self, $text ) = @_;
522 21         81 $self->split_method( $text,
523             qr{(?
524             'named_http_link_format', );
525             }
526              
527             =item * named_http_link_format - how to format the named link
528              
529             =cut
530              
531             sub named_http_link_format {
532 1     1 1 2 my ( $self, $text ) = @_;
533 1 50       10 if ( $text =~ m#(.*)((?:https?|ftp|irc):.*)# ) {
534 1         6 $text = "$2 $1";
535             }
536 1         3 return $self->link_format($text);
537             }
538              
539             =item * inline - code samples or fixed-width font, usually
540              
541             =cut
542              
543             sub inline {
544 20     20 1 34 my ( $self, $text ) = @_;
545 20         83 $self->split_method( $text, qr{(?
546             );
547             }
548              
549             =item * inline_format - how to format inline markup
550              
551             =cut
552              
553             sub inline_format {
554 0     0 1 0 my ( $self, $text ) = @_;
555 0         0 "$text";
556             }
557              
558             =item * negation - when not to make an inline format
559              
560             =cut
561              
562             sub negation {
563 20     20 1 39 my ( $self, $text ) = @_;
564 20         31 $text =~ s#\!(?=\[)##g;
565 20         143 return $text;
566             }
567              
568             =item * bold - strong text
569              
570             =cut
571              
572             sub bold {
573 19     19 1 30 my ( $self, $text ) = @_;
574 19         132 $text =~ s#(?$1#g;
575 19         1680 return $text;
576             }
577              
578             =item * italic - emphasized text
579              
580             =cut
581              
582             sub italic {
583 20     20 1 35 my ( $self, $text ) = @_;
584 20         144 $text =~ s#(?$1#g;
585 20         2216 return $text;
586             }
587              
588             =item * underscore - if you reall, really, really feel the need to use underlined text
589              
590             =cut
591              
592             sub underscore {
593 20     20 1 36 my ( $self, $text ) = @_;
594 20         131 $text =~ s#(?$1#g;
595 20         2033 return $text;
596             }
597              
598             =item * code - usually indented text creates blocks of preformatted text
599              
600             =cut
601              
602             sub code {
603 15     15 1 23 my ( $self, $text ) = @_;
604 15         56 $self->split_method( $text, qr{(^ +[^ \n].*?\n)(?-ms:(?=[^ \n]|$))}ms,
605             'code_format', );
606             }
607              
608             =item * code_format - how to format the code blocks
609              
610             =cut
611              
612             sub code_format {
613 3     3 1 5 my ( $self, $text ) = @_;
614 3         7 $self->_code_postformat( $self->_code_preformat($text) );
615             }
616              
617             sub _code_preformat {
618 3     3   6 my ( $self, $text ) = @_;
619 3         10 my ($indent) = sort { $a <=> $b } map {length} $text =~ /^( *)\S/mg;
  0         0  
  3         20  
620 3         33 $text =~ s/^ {$indent}//gm;
621              
622             #return $self->escape_html($text); ## already done in process order
623 3         10 return $text;
624             }
625              
626             sub _code_postformat {
627 3     3   5 my ( $self, $text ) = @_;
628 3         9 return "
$text
\n";
629             }
630              
631             =item * lists - itemized or enumerated lists
632              
633             =cut
634              
635             sub lists {
636 12     12 1 20 my ( $self, $text ) = @_;
637 12         12 my $switch = 0;
638 15         18 return map {
639 12         42 my $level = 0;
640 15         18 my @tag_stack;
641 15 100       90 if ( $switch++ % 2 ) {
642 2         4 my $text = '';
643 2         12 my @lines = /(.*\n)/g;
644 2         5 for my $line (@lines) {
645 4         18 $line =~ s/^([0\*]+) //;
646 4         10 my $new_level = length($1);
647 4 100       13 my $tag = ( $1 =~ /0/ ) ? 'ol' : 'ul';
648 4 100       14 if ( $new_level > $level ) {
    50          
649 2         7 for ( 1 .. ( $new_level - $level ) ) {
650 2         4 push @tag_stack, $tag;
651 2         8 $text .= "<$tag>\n";
652             }
653 2         3 $level = $new_level;
654             }
655             elsif ( $new_level < $level ) {
656 0         0 for ( 1 .. ( $level - $new_level ) ) {
657 0         0 $tag = pop @tag_stack;
658 0         0 $text .= "\n";
659             }
660 0         0 $level = $new_level;
661             }
662 4         14 $text .= "
  • $line
  • ";
    663             }
    664 2         6 for ( 1 .. $level ) {
    665 2         8 my $tag = pop @tag_stack;
    666 2         8 $text .= "\n";
    667             }
    668 2         9 $_ = $self->lists_format($text);
    669             }
    670 15         53 $_;
    671             }
    672             split m!(^[0\*]+ .*?\n)(?=(?:[^0\*]|$))!ms, $text;
    673             }
    674              
    675             =item * lists_format - how to format the lists
    676              
    677             =cut
    678              
    679             sub lists_format {
    680 2     2 1 4 my ( $self, $text ) = @_;
    681 2         6 return $text;
    682             }
    683              
    684             =item * paragraph - normal, boring paragraphs
    685              
    686             =cut
    687              
    688             sub paragraph {
    689 17     17 1 25 my ( $self, $text ) = @_;
    690 17         26 my $switch = 0;
    691             return map {
    692 17 100       58 unless ( $switch++ % 2 )
      21         63  
    693             {
    694 16         46 $_ = $self->paragraph_format($_);
    695             }
    696 21         67 $_;
    697             }
    698             split m!(\n\s*\n)!ms, $text;
    699             }
    700              
    701             =item * paragraph_format - how to format paragraphs as XHTML
    702              
    703             =cut
    704              
    705             sub paragraph_format {
    706 16     16 1 24 my ( $self, $text ) = @_;
    707 16 100       93 return '' if $text =~ /^[\s\n]*$/;
    708 9 100       54 return $text if $text =~ /^<(o|u)l>/i;
    709 7         23 return "

    \n$text\n

    \n";
    710             }
    711              
    712             =item * horizontal_line - horizontal rules
    713              
    714             =cut
    715              
    716             sub horizontal_line {
    717 10     10 1 14 my ( $self, $text ) = @_;
    718 10         41 $self->split_method( $text, qr{^(----+)\s*$}m, 'horizontal_line_format',
    719             );
    720             }
    721              
    722             =item * horizontal_line_format - horizontal rules as XHTML
    723              
    724             =cut
    725              
    726             sub horizontal_line_format {
    727 1     1 1 2 my ($self) = @_;
    728 1         2 my $text = "
    \n";
    729 1         3 return $text;
    730             }
    731              
    732             =item * mdash - long horizontal dashes
    733              
    734             =cut
    735              
    736             sub mdash {
    737 20     20 1 30 my ( $self, $text ) = @_;
    738 20         129 $text =~ s/([$WORD])-{3}([$WORD])/$1—$2/g;
    739 20         2031 return $text;
    740             }
    741              
    742             =item * comment - text that doesn't show up in the final markup
    743              
    744             =cut
    745              
    746             sub comment {
    747 10     10 1 16 my ( $self, $text ) = @_;
    748 10         39 $self->split_method( $text, qr{^\#\#(.*)$}m, 'comment_line_format', );
    749             }
    750              
    751             =item * comment_line_format - make XML comments out of 'em
    752              
    753             =cut
    754              
    755             sub comment_line_format {
    756 2     2 1 3 my ( $self, $text ) = @_;
    757 2         10 return "\n";
    758             }
    759              
    760             =item * header_N and header_N_format - where N is a number from 1 to 6, inclusive
    761              
    762             =cut
    763              
    764             for my $num ( 1 .. 6 ) {
    765 5     5   51 no strict 'refs';
      5         13  
      5         2436  
    766             *{"header_$num"} = sub {
    767 71     71   108 my ( $self, $text ) = @_;
    768 71         882 $self->split_method( $text, qr#^={$num} (.*?)(?: =*)?\n#m,
    769             "header_${num}_format", );
    770             };
    771             *{"header_${num}_format"} = sub {
    772 10     10   16 my ( $self, $text ) = @_;
    773 10         19 $text =~ s/=+\s*$//;
    774 10         21 $text = $self->escape_html($text);
    775 10         49 return "$text\n";
    776             };
    777             }
    778              
    779             =back
    780              
    781             =cut
    782              
    783             =head2 Adding User Functions
    784              
    785             =over 4
    786              
    787             =cut
    788              
    789             =item * user_functions() - returns a list of custom markup plugins to handle
    790              
    791             The default user functions are C, C and C. In the default markup, plugins are entered in the form of C<[&name arg1 arg2 ...]>.
    792              
    793             =cut
    794              
    795             sub user_functions {
    796 5     5 1 8 qw(
    797             icon
    798             img
    799             glyph
    800             );
    801             }
    802              
    803             =item * icon - inserts the named image with a CSS class of "icon"
    804              
    805             [&icon /icons/fun.png]
    806              
    807             =cut
    808              
    809             sub icon {
    810 1     1 1 2 my ( $self, $href ) = @_;
    811 1         4 return qq( (icon) );
    812             }
    813              
    814             =item * img - inserts a regular image, with an optional title
    815              
    816             [&img some_image.jpg]
    817              
    818             [&img another_image.jpg This image will have a title attribute]
    819              
    820             =cut
    821              
    822             sub img {
    823 2     2 1 4 my ( $self, $href, @title ) = @_;
    824 2   100     8 my $title = join( ' ', @title ) || '';
    825 2         4 my $output = qq(

    826             src="$href" alt="(see caption below)" title="$title"
    827             align="middle" border="0" /> );
    828 2 100       5 $output .= @title ? "
    $title" : '';
    829 2         8 return $output . '

    ';
    830             }
    831              
    832             =item * glyph - attempts to insert an image that's aligned with the vertical middle of the text, but doesn't work due to the implementation of the parser
    833              
    834             =cut
    835              
    836             sub glyph {
    837              
    838             # FIXME - BROKEN! Plugins like to separate the paragraphs
    839 2     2 1 3 my ( $self, $href, @title ) = @_;
    840 2   100     8 my $title = join( ' ', @title ) || '*';
    841 2         8 return qq(
    842             src="$href"
    843             alt="$title" title="$title"
    844             align="middle" border="0"
    845             /> );
    846             }
    847              
    848             =back
    849              
    850             =cut
    851              
    852             =head1 DIFFERENCES FROM THE CGI::KWIKI FORMATTER
    853              
    854             =over 4
    855              
    856             =item * The output of the formatter is XML-compliant.
    857              
    858             =item * Extra equal signs at the end of headings will be removed from the output for compatibility with other wikitext formats.
    859              
    860             =item * Italicized text is marked up by two slashes instead of one. This is to prevent weirdness when writing filesystem paths in Kwikitext -- e.g., the text "Check /etc or /var or /usr/" will have unexpected results when formatted in a regular Kwiki.
    861              
    862             =item * Horizontal rules, marked by four or more hyphens, may be followed by spaces.
    863              
    864             =item * Processing order of text segments has been changed (tables are processed last)
    865              
    866             =item * Bold text is marked up as CstrongE> instead of CbE>
    867              
    868             =item * "Inline" is marked up as CcodeE> instead of CttE>
    869              
    870             =item * mdashes (really long hyphens) are created with wikitext C
    871              
    872             =item * Tables and code sections are not indented with CblockquoteE> tags
    873              
    874             =item * Comments do not have to have a space immediately following the hash
    875              
    876             =item * Patch to named_link code
    877              
    878             =item * All code pertaining to slides or Kwiki access control is removed, as neither are within the scope of this module
    879              
    880             =back
    881              
    882             =head2 Plugins
    883              
    884             I've included two plugins, C and C, to do basic image support besides the standard operation of including an image when the URL ends with a common image extension.
    885              
    886             =cut
    887              
    888             =head1 EXAMPLES
    889              
    890             Here's some kwiki text. (Compare with
    891             L.)
    892              
    893             = Level 1 Header
    894            
    895             == Level 2 with optional trailing equals ==
    896            
    897             Kwikitext provides a bit more flexibility than regular wikitext.
    898            
    899             All HTML code is . Horizontal rules are four or more hyphens:
    900            
    901             ----
    902            
    903             While you can add an mdash---like this.
    904            
    905             ##
    906             ## you can add comments in the kwikitext which appear as XML comments
    907             ##
    908            
    909             == Links
    910            
    911             === Itemized Lists
    912            
    913             * Fruit
    914             ** Oranges
    915             ** Apples
    916             * Eggs
    917             * Salad
    918            
    919             === Enumerated Lists
    920            
    921             ##
    922             ## below are zero's, not "oh's"
    923             ##
    924            
    925             0 One
    926             0 Two
    927             0 Three
    928            
    929             * Comments in the wikitext
    930             * Easier:
    931             ** Bold/strong
    932             ** Italic/emphasized
    933            
    934             == More Markup
    935            
    936             *strong or bold text*
    937            
    938             //emphasized or italic text//
    939            
    940             indented text is verbatim (good for code)
    941            
    942             == Links
    943            
    944             WikiLink
    945            
    946             !NotAWikiLink
    947            
    948             http://www.kwiki.org/
    949            
    950             [Kwiki named link http://www.kwiki.org/]
    951            
    952             == Images
    953            
    954             http://search.cpan.org/s/img/cpan_banner.png
    955            
    956             == KwikiFormatish plugins
    957            
    958             This inserts an image with the CSS class of "icon" -- good for inserting a right-aligned image for text to wrap around.
    959            
    960             [&icon /images/logo.gif]
    961            
    962             The following inserts an image with an optional caption:
    963            
    964             [&img /images/graph.gif Last Month's Earnings]
    965              
    966             =head1 AUTHOR
    967              
    968             Maintained by Ian Langworth - ian@cpan.org
    969              
    970             Based on L by L
    971             Ingerson|http://search.cpan.org/~ingy/>.
    972              
    973             Thanks to L for the
    974             C patch, related documentation and testing.
    975              
    976             Additional thanks to Mike Burns, Ari Pollak and Ricardo SIGNES for additional testing.
    977              
    978             =head1 SEE ALSO
    979              
    980             L, L, L
    981              
    982             =head1 LICENSE
    983              
    984             This is free software. You may use it and redistribute it under the same terms
    985             as perl itself.
    986              
    987             =cut
    988              
    989             1;
    990