File Coverage

blib/lib/HTML/WikiConverter/MoinMoin.pm
Criterion Covered Total %
statement 15 69 21.7
branch 0 34 0.0
condition 0 34 0.0
subroutine 5 15 33.3
pod 0 4 0.0
total 20 156 12.8


line stmt bran cond sub pod time code
1             package HTML::WikiConverter::MoinMoin;
2              
3 1     1   26550 use warnings;
  1         4  
  1         32  
4 1     1   6 use strict;
  1         2  
  1         37  
5              
6 1     1   5 use base 'HTML::WikiConverter';
  1         13  
  1         568  
7             our $VERSION = '0.54';
8              
9 1     1   1706 use Params::Validate ':types';
  1         32722  
  1         233  
10 1     1   2017 use URI;
  1         46408  
  1         5179  
11              
12             =head1 NAME
13              
14             HTML::WikiConverter::MoinMoin - Convert HTML to MoinMoin markup
15              
16             =head1 SYNOPSIS
17              
18             use HTML::WikiConverter;
19             my $wc = new HTML::WikiConverter( dialect => 'MoinMoin' );
20             print $wc->html2wiki( $html );
21              
22             =head1 DESCRIPTION
23              
24             This module contains rules for converting HTML into MoinMoin
25             markup. See L for additional usage details.
26              
27             =cut
28              
29             sub rules {
30 0     0 0   my %rules = (
31             p => { block => 1, trim => 'both', line_format => 'multi' },
32             pre => { block => 1, start => "{{{\n", end => "\n}}}" },
33              
34             i => { start => "''", end => "''", line_format => 'single' },
35             em => { alias => 'i' },
36             b => { start => "'''", end => "'''", line_format => 'single' },
37             strong => { alias => 'b' },
38             u => { start => '__', end => '__', line_format => 'single' },
39              
40             sup => { start => '^', end => '^', line_format => 'single' },
41             sub => { start => ',,', end => ',,', line_format => 'single' },
42             code => { start => '`', end => '`', line_format => 'single' },
43             tt => { alias => 'code' },
44             small => { start => '~-', end => '-~', line_format => 'single' },
45             big => { start => '~+', end => '+~', line_format => 'single' },
46              
47             a => { replace => \&_link },
48             img => { replace => \&_image },
49              
50             ul => { line_format => 'multi', block => 1, line_prefix => ' ' },
51             ol => { alias => 'ul' },
52              
53             li => { start => \&_li_start, trim => 'leading' },
54              
55             dl => { line_format => 'multi' },
56             dt => { trim => 'both', end => ':: ' },
57             dd => { trim => 'both' },
58              
59             hr => { replace => "\n----\n" },
60             br => { replace => '[[BR]]' },
61              
62             table => { block => 1, line_format => 'multi' },
63             tr => { end => "||\n", line_format => 'single' },
64             td => { start => \&_td_start, end => ' ', trim => 'both' },
65             th => { alias => 'td' },
66              
67             # (bug #40114) http://moinmo.in/HelpOnHeadlines
68             h1 => { start => '= ', end => ' =', block => 1, trim => 'both', line_format => 'single' },
69             h2 => { start => '== ', end => ' ==', block => 1, trim => 'both', line_format => 'single' },
70             h3 => { start => '=== ', end => ' ===', block => 1, trim => 'both', line_format => 'single' },
71             h4 => { start => '==== ', end => ' ====', block => 1, trim => 'both', line_format => 'single' },
72             h5 => { start => '===== ', end => ' =====', block => 1, trim => 'both', line_format => 'single' },
73             h6 => { start => '====== ', end => ' ======', block => 1, trim => 'both', line_format => 'single' },
74             );
75              
76 0           return \%rules;
77             }
78              
79             =head1 ATTRIBUTES
80              
81             In addition to the regular set of attributes recognized by the
82             L constructor, this dialect also accepts the
83             following attributes that can be passed into the C
84             constructor. See L for usage details.
85              
86             =head2 enable_anchor_macro
87              
88             Possible values: C<0>, C<1>. Enables C<[[Anchor(s)]]> formatting. See
89             L for details.
90              
91             =cut
92              
93             sub attributes { {
94 0     0 0   enable_anchor_macro => { default => 0, type => BOOLEAN }
95             } }
96              
97             my %att2prop = (
98             width => 'width',
99             bgcolor => 'background-color',
100             );
101              
102             sub _td_start {
103 0     0     my( $self, $td, $rules ) = @_;
104              
105 0           my $prefix = '||';
106              
107 0           my @style = ( );
108              
109 0 0         push @style, '|'.$td->attr('rowspan') if $td->attr('rowspan');
110 0 0         push @style, '-'.$td->attr('colspan') if $td->attr('colspan');
111              
112             # If we're the first td in the table, then include table settings
113 0 0 0       if( ! $td->parent->left && ! $td->left ) {
114 0           my $table = $td->look_up( _tag => 'table' );
115 0           my $attstr = _attrs2style( $table, qw/ width bgcolor / );
116 0 0         push @style, "tablestyle=\"$attstr\"" if $attstr;
117             }
118              
119             # If we're the first td in this tr, then include tr settings
120 0 0         if( ! $td->left ) {
121 0           my $attstr = $td->parent->attr('style');
122 0 0         push @style, "rowstyle=\"$attstr\"" if $attstr;
123             }
124              
125             # Include td settings
126 0           my $attstr = join ' ', map { "$_=\"".$td->attr($_)."\"" } grep $td->attr($_), qw/ id class style /;
  0            
127 0 0         push @style, $attstr if $attstr;
128              
129 0 0         my $opts = @style ? '<'.join(' ',@style).'>' : '';
130              
131 0           return $prefix.$opts.' ';
132             }
133              
134             sub _attrs2style {
135 0     0     my( $node, @attrs ) = @_;
136 0 0         return unless $node;
137 0           my %attrs = map { $_ => $node->attr($_) } grep $node->attr($_), @attrs;
  0            
138 0           my $attstr = join '; ', map "$att2prop{$_}:$attrs{$_}", keys %attrs;
139 0   0       return $attstr || '';
140             }
141              
142             sub _li_start {
143 0     0     my( $self, $node, $rules ) = @_;
144 0           my $bullet = '';
145 0 0         $bullet = '*' if $node->parent->tag eq 'ul';
146 0 0         $bullet = '1.' if $node->parent->tag eq 'ol';
147 0           return "\n$bullet ";
148             }
149              
150             sub _link {
151 0     0     my( $self, $node, $rules ) = @_;
152              
153             # bug #17813 requests anchors; MoinMoin:HelpOnMacros gives new
154             # "<>" syntax for anchors and other macros (this was
155             # previously "[[Anchor(name)]]" sometime prior to 2008-10-01)
156              
157             # bug #29347 requests 'id' be favored over 'name'
158 0   0       my $anchor_name = $node->attr('id') || $node->attr('name');
159 0 0 0       return sprintf( "<>\n", $anchor_name ) if $self->enable_anchor_macro and $anchor_name;
160              
161 0   0       my $url = $node->attr('href') || '';
162 0   0       my $text = $self->get_elem_contents($node) || '';
163              
164             # bug #17813
165 0 0         if( $self->_abs2rel($url) =~ /^#/ ) {
166 0           $url = $self->_abs2rel($url);
167             }
168              
169 0 0         return $url if $url eq $text;
170 0           return "[[$url|$text]]";
171             }
172              
173             sub _abs2rel {
174 0     0     my( $self, $uri ) = @_;
175 0 0         return $uri unless $self->base_uri;
176 0           return URI->new($uri)->rel($self->base_uri)->as_string;
177             }
178              
179             sub _image {
180 0     0     my( $self, $node, $rules ) = @_;
181 0   0       return $node->attr('src') || '';
182             }
183              
184             sub preprocess_node {
185 0     0 0   my( $self, $node ) = @_;
186 0   0       my $tag = $node->tag || '';
187              
188 0 0         $self->caption2para($node) if $tag eq 'caption';
189              
190             # Find something like and content here
191 0 0 0       if( $node->tag eq 'a' and ( $node->attr('name') or $node->attr('id') ) and !$node->attr('href') and $self->get_elem_contents($node) ) {
      0        
      0        
      0        
192 0   0       my $anchor_name = $node->attr('id') || $node->attr('name');
193 0           $node->preinsert( new HTML::Element('a', name => $anchor_name) );
194 0           $node->replace_with_content->delete();
195             }
196             }
197              
198             my @protocols = qw( http https mailto );
199             my $urls = '(' . join('|', @protocols) . ')';
200             my $ltrs = '\w';
201             my $gunk = '\/\#\~\:\.\?\+\=\&\%\@\!\-';
202             my $punc = '\.\:\?\-\{\(\)\}';
203             my $any = "${ltrs}${gunk}${punc}";
204             my $url_re = "\\b($urls:\[$any\]+?)(?=\[$punc\]*\[^$any\])";
205              
206             sub postprocess_output {
207 0     0 0   my( $self, $outref ) = @_;
208 0           $$outref =~ s/($url_re)\[\[BR\]\]/$1 [[BR]]/go;
209             }
210              
211             =head1 AUTHOR
212              
213             David J. Iberri, C<< >>
214              
215             =head1 BUGS
216              
217             Please report any bugs or feature requests to
218             C, or through the web
219             interface at
220             L.
221             I will be notified, and then you'll automatically be notified of
222             progress on your bug as I make changes.
223              
224             =head1 SUPPORT
225              
226             You can find documentation for this module with the perldoc command.
227              
228             perldoc HTML::WikiConverter::MoinMoin
229              
230             You can also look for information at:
231              
232             =over 4
233              
234             =item * AnnoCPAN: Annotated CPAN documentation
235              
236             L
237              
238             =item * CPAN Ratings
239              
240             L
241              
242             =item * RT: CPAN's request tracker
243              
244             L
245              
246             =item * Search CPAN
247              
248             L
249              
250             =back
251              
252             =head1 COPYRIGHT & LICENSE
253              
254             Copyright (c) David J. Iberri, all rights reserved.
255              
256             This program is free software; you can redistribute it and/or modify
257             it under the same terms as Perl itself.
258              
259             =cut
260              
261             1;