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   692 use 5.008001;
  1         3  
  1         34  
3 1     1   5 use strict;
  1         1  
  1         33  
4 1     1   14 use warnings;
  1         1  
  1         30  
5 1     1   477 use parent 'HTML::WikiConverter';
  1         250  
  1         5  
6             use Params::Validate ':types';
7              
8             our $VERSION = "0.03";
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]";
110             }
111             return "[$text|$url]";
112             }
113              
114             sub get_relative_url {
115             my ( $self, $url ) = @_;
116             return unless $self->base_uri;
117             $self->base_uri =~ m{/([^/]*)$};
118             my $path = $1 || '';
119             my $re_tmp = '(' . quotemeta($path) . '(/[^/]+)?(\?.*)?)$';
120             my $re = qr($re_tmp);
121             $url =~ /$re/ or return;
122             return $2 ? $1 : $3;
123             }
124              
125             sub extract_wiki_page {
126             my ( $self, $url ) = @_;
127             my $re_tmp = quotemeta( $self->base_uri ) . '\?page=([^&]+)$';
128             my $re = qr($re_tmp);
129             return $url =~ /$re/ && $1;
130             }
131              
132             sub _br {
133             my ( $self, $node, $rules ) = @_;
134              
135             # print $node->dump;
136             # print $node->right->dump;
137             if ( $node->right and $node->right->tag eq '~text' ) {
138             $node->right->{text} =~ s/\A\s+//msx;
139             $node->right->{text} =~ s/\s+\z//msx;
140              
141             # warn join ':', $node->lineage_tag_names;
142             }
143             return "\n";
144             }
145              
146             sub postprocess_output {
147             my ( $self, $outref ) = @_;
148             $$outref =~ s/^""""(?!")/""/gmx; # nested blockquote change to plain blockquote
149             $$outref =~ s/^([\*\+]+)\s+/$1/gmx; # delete space on li start
150             }
151              
152             sub preprocess_node {
153             my ( $self, $node ) = @_;
154             $self->strip_aname($node) if defined $node->tag and $node->tag eq 'a';
155             $self->caption2para($node) if defined $node->tag and $node->tag eq 'caption';
156             if ( $node->tag
157             and $node->tag eq 'br'
158             and $node->right
159             and $node->right->tag
160             and $node->right->tag eq 'pre'
161             and $node->parent->tag
162             and $node->parent->tag eq 'p' )
163             {
164             $node->parent->replace_with_content();
165             }
166             }
167              
168              
169             1;
170             __END__