File Coverage

blib/lib/HTML/WikiConverter/FreeStyleWiki.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1             package HTML::WikiConverter::FreeStyleWiki;
2 1     1   658 use 5.008001;
  1         3  
  1         31  
3 1     1   4 use strict;
  1         1  
  1         30  
4 1     1   11 use warnings;
  1         1  
  1         29  
5 1     1   436 use parent 'HTML::WikiConverter';
  1         261  
  1         4  
6             use Params::Validate ':types';
7              
8             our $VERSION = "0.01";
9              
10             sub attributes {
11             +{
12             p_strict => { default => 0 },
13             escape_entities => { default => 0 },
14             preserve_tags => { default => 0, type => BOOLEAN },
15             };
16             }
17              
18             sub rules {
19             my ($self) = @_;
20             my %rules = (
21             hr => { replace => "\n----\n" },
22             br => { replace => \&_br },
23              
24             blockquote => { start => qq{\n}, block => 1, line_format => 'multi', line_prefix => q{""} },
25             p => { end => "\n", block => 1, trim => 'both', line_format => 'multi', line_prefix => '' },
26             i => { start => q{''}, end => q{''} },
27             em => { alias => 'i' },
28             b => { start => q{'''}, end => q{'''} },
29             strong => { alias => 'b' },
30             del => { start => '==', end => '==', },
31             ins => { start => '__', end => '__', },
32              
33             img => { replace => \&_image },
34             a => { replace => \&_link },
35              
36             ul => { line_format => 'multi', block => 1 },
37             ol => { alias => 'ul' },
38             dl => { line_format => 'blocks', block => 1 },
39              
40             li => { start => \&_li_start, trim => 'leading' },
41             dt => { start => '::', trim => 'both', 'end' => "\n" },
42             dd => { line_format => 'multi', line_prefix => ':::' },
43              
44             td => { start => ',', trim => 'both' },
45             th => { alias => 'td' },
46             tr => { end => "\n" },
47              
48             h1 => { start => '!!!', block => 1, trim => 'both', line_format => 'single' },
49             h2 => { start => '!!!', block => 1, trim => 'both', line_format => 'single' },
50             h3 => { start => '!!', block => 1, trim => 'both', line_format => 'single' },
51             h4 => { start => '!', block => 1, trim => 'both', line_format => 'single' },
52             h5 => { start => '!', block => 1, trim => 'both', line_format => 'single' },
53             h6 => { start => '!', block => 1, trim => 'both', line_format => 'single' },
54              
55             pre => { start => qq{\n}, end => "\n", line_format => 'multi', line_prefix => ' ' },
56             );
57              
58             if ($self->preserve_tags) {
59             for my $tag (qw/ big small tt abbr acronym cite code dfn kbd samp var sup sub /) {
60             $rules{$tag} = { preserve => 1 }
61             }
62             }
63              
64             return \%rules;
65             }
66              
67             # Calculates the prefix that will be placed before each list item.
68             # List item include ordered and unordered list items.
69             sub _li_start {
70             my ( $self, $node, $rules ) = @_;
71             my @parent_lists = $node->look_up( _tag => qr/ul|ol/ );
72             my $depth = @parent_lists;
73             if ( defined $node->{text} ) {
74             $node->{text} =~ s/\A\s+//;
75             }
76              
77             my $bullet = '';
78             $bullet = '*' if $node->parent->tag eq 'ul';
79             $bullet = '+' if $node->parent->tag eq 'ol';
80              
81             my $prefix = ($bullet) x $depth;
82             return "\n$prefix ";
83             }
84              
85             sub _image {
86             my ( $self, $node, $rules ) = @_;
87             my $url = $node->attr('src') || '';
88             if ( $url =~ m{page=([^&]*)&(?:amp;)?file=([^&]*)&(?:amp;)?action=ATTACH}msx )
89             { # ref_image plugin
90             return sprintf "{{ref_image %s,%s}}", $2, $1 if $2;
91             }
92             elsif ($url) { # image plugin
93             return sprintf "{{image %s}}", $url;
94             }
95             return '';
96             }
97              
98             sub _link {
99             my ( $self, $node, $rules ) = @_;
100             my $url = $node->attr('href') || '';
101             $url =~ s/&/&/g;
102             my $title = $self->get_wiki_page($url) || $self->extract_wiki_page($url) || '';
103             my $text = $self->get_elem_contents($node) || '';
104             return "[[$text]]" if $title eq $text;
105             return "[[$text|$title]]" if $title;
106             return $url if $url eq $text;
107              
108             if ( my $relative_url = $self->get_relative_url($url) ) {
109             return "[$text|$relative_url]" if $relative_url;
110             }
111             return "[$text|$url]";
112             }
113              
114             sub get_relative_url {
115             my ( $self, $url ) = @_;
116             $self->base_uri =~ m{/([^/]*)$};
117             my $path = $1 || '';
118             my $re_tmp = '(' . quotemeta($path) . '(/[^/]+)?(\?.*)?)$';
119             my $re = qr($re_tmp);
120             $url =~ /$re/ or return;
121             return $2 ? $1 : $3;
122             }
123              
124             sub extract_wiki_page {
125             my ( $self, $url ) = @_;
126             my $re_tmp = quotemeta( $self->base_uri ) . '\?page=([^&]+)$';
127             my $re = qr($re_tmp);
128             return $url =~ /$re/ && $1;
129             }
130              
131             sub _br {
132             my ( $self, $node, $rules ) = @_;
133              
134             # print $node->dump;
135             # print $node->right->dump;
136             if ( $node->right and $node->right->tag eq '~text' ) {
137             $node->right->{text} =~ s/\A\s+//msx;
138             $node->right->{text} =~ s/\s+\z//msx;
139              
140             # warn join ':', $node->lineage_tag_names;
141             }
142             return "\n";
143             }
144              
145             sub postprocess_output {
146             my ( $self, $outref ) = @_;
147             $$outref =~ s/^""""(?!")/""/gmx; # nested blockquote change to plain blockquote
148             $$outref =~ s/^([\*\+]+)\s+/$1/gmx; # delete space on li start
149             }
150              
151             sub preprocess_node {
152             my ( $self, $node ) = @_;
153             $self->strip_aname($node) if defined $node->tag and $node->tag eq 'a';
154             $self->caption2para($node) if defined $node->tag and $node->tag eq 'caption';
155             if ( $node->tag
156             and $node->tag eq 'br'
157             and $node->right
158             and $node->right->tag
159             and $node->right->tag eq 'pre'
160             and $node->parent->tag
161             and $node->parent->tag eq 'p' )
162             {
163             $node->parent->replace_with_content();
164             }
165             }
166              
167              
168             1;
169             __END__