| blib/lib/Text/YAWikiFormater.pm | |||
|---|---|---|---|
| Criterion | Covered | Total | % |
| statement | 203 | 259 | 78.3 |
| branch | 76 | 118 | 64.4 |
| condition | 18 | 54 | 33.3 |
| subroutine | 16 | 20 | 80.0 |
| pod | 7 | 7 | 100.0 |
| total | 320 | 458 | 69.8 |
| line | stmt | bran | cond | sub | pod | time | code |
|---|---|---|---|---|---|---|---|
| 1 | package Text::YAWikiFormater; | ||||||
| 2 | |||||||
| 3 | 4 | 4 | 115131 | use 5.006; | |||
| 4 | 15 | ||||||
| 4 | 148 | ||||||
| 4 | 4 | 4 | 23 | use strict; | |||
| 4 | 8 | ||||||
| 4 | 134 | ||||||
| 5 | 4 | 4 | 30 | use warnings; | |||
| 4 | 85 | ||||||
| 4 | 134 | ||||||
| 6 | |||||||
| 7 | 4 | 4 | 4466 | use HTML::Entities qw(encode_entities); | |||
| 4 | 527403 | ||||||
| 4 | 401 | ||||||
| 8 | 4 | 4 | 5368 | use JSON qw(from_json); | |||
| 4 | 73539 | ||||||
| 4 | 22 | ||||||
| 9 | |||||||
| 10 | our $VERSION = '0.50'; | ||||||
| 11 | |||||||
| 12 | my %plugins = ( | ||||||
| 13 | toc => \&_handle_toc, | ||||||
| 14 | image => \&_handle_image, | ||||||
| 15 | |||||||
| 16 | restore_code_block => \&_restore_code_block, | ||||||
| 17 | ); | ||||||
| 18 | |||||||
| 19 | my %namespaces = ( | ||||||
| 20 | wp => { prefix => 'http://en.wikipedia.org/', category=>':' }, | ||||||
| 21 | gs => { prefix => 'http://www.google.com/search?q=' }, | ||||||
| 22 | ); | ||||||
| 23 | |||||||
| 24 | my %closed = ( | ||||||
| 25 | b => qr{(?:(? | ||||||
| 26 | i => qr{(? | ||||||
| 27 | u => qr{__}, | ||||||
| 28 | del => qr{(? | ||||||
| 29 | tt => qw{''}, | ||||||
| 30 | |||||||
| 31 | heads => [qr[^(?=!{1,6}\s)]msix, qr[$]msix, \&_header_id, undef,"\n"], | ||||||
| 32 | |||||||
| 33 | code => [qr[^\{\{\{$]msix,qr[^\}\}\}$]msix, \&_escape_code], | ||||||
| 34 | |||||||
| 35 | blockquote => [qr{^>\s}msix, qr{^(?!>)}msix, qr{^>\s}msix, '',"\n"], | ||||||
| 36 | |||||||
| 37 | lists => [qr{^(?=[\*\#]+\s)}msix, qr{(?:^(?![\*\#\s])|\z)}msix, \&_do_lists], | ||||||
| 38 | |||||||
| 39 | links => [qr{(?=\[\[)}, qr{(?<=\]\])},\&_do_links], | ||||||
| 40 | links2 => [qr{\s(?=http://)}, qr{\s},\&_do_links], | ||||||
| 41 | |||||||
| 42 | br => [qr{^(?=$)}msix, qr[$]msix, sub { " ",'',''}], |
||||||
| 43 | |||||||
| 44 | comments => [qr{/\*}msix, qr{\*/}msix, sub{ '','',''}], | ||||||
| 45 | ); | ||||||
| 46 | |||||||
| 47 | my %nonclosed = ( | ||||||
| 48 | hr => qr{^[-\*]{3,}\s*?$}msix, | ||||||
| 49 | ); | ||||||
| 50 | |||||||
| 51 | my @do_first = qw( code lists ); | ||||||
| 52 | |||||||
| 53 | sub new { | ||||||
| 54 | 4 | 4 | 1 | 25 | my $class = shift; | ||
| 55 | |||||||
| 56 | 4 | 17 | my $self = bless { @_ }, $class; | ||||
| 57 | |||||||
| 58 | 4 | 50 | 22 | die "body is a mandatory parameter" unless $self->{body}; | |||
| 59 | |||||||
| 60 | 4 | 13 | return $self; | ||||
| 61 | } | ||||||
| 62 | |||||||
| 63 | sub urls { | ||||||
| 64 | 2 | 2 | 1 | 6 | my $self= shift; | ||
| 65 | 2 | 4 | my $body = $self->{body}; | ||||
| 66 | |||||||
| 67 | 2 | 50 | 6 | return unless $body; | |||
| 68 | |||||||
| 69 | 2 | 28 | my @links = $body =~m{(\[\[(?:\S[^\|\]]*)(?:\|(?:[^\]]+))?\]\])}g; | ||||
| 70 | 2 | 14 | push @links, $body =~m{\s(https?://\S+)\s}g; | ||||
| 71 | |||||||
| 72 | 2 | 50 | 16 | my $links = $self->{_links} ||= {}; | |||
| 73 | |||||||
| 74 | LINK: | ||||||
| 75 | 2 | 5 | for my $lnk ( @links ) { | ||||
| 76 | 13 | 50 | 26 | next if $links->{$lnk}; | |||
| 77 | |||||||
| 78 | 13 | 50 | 56 | my $hlnk = $links->{$lnk} ||= {}; | |||
| 79 | |||||||
| 80 | 13 | 100 | 33 | if ($lnk =~ m{\Ahttps?://}) { | |||
| 81 | 2 | 9 | %$hlnk = ( title => $lnk, href => $lnk, _class => 'external' ); | ||||
| 82 | 2 | 8 | next LINK; | ||||
| 83 | } | ||||||
| 84 | |||||||
| 85 | 11 | 45 | ($lnk) = $lnk =~ m{\A\[\[(.*)\]\]\z}g; | ||||
| 86 | 11 | 53 | my ($label,$link) = split qr{\|}, $lnk, 2; | ||||
| 87 | 11 | 100 | 44 | unless ($link) { | |||
| 88 | 6 | 7 | $link = $label; | ||||
| 89 | 6 | 100 | 25 | if ( $link =~ m{.*[\>\:]([^\>]+)\z} ) { | |||
| 90 | 4 | 9 | $label = $1; | ||||
| 91 | } | ||||||
| 92 | } | ||||||
| 93 | |||||||
| 94 | 11 | 18 | $hlnk->{title} = $label; | ||||
| 95 | 11 | 14 | $hlnk->{original_to} = $link; | ||||
| 96 | 11 | 100 | 26 | if ($link =~ m{\Ahttps?://} ) { | |||
| 97 | 1 | 2 | $hlnk->{_class} = 'external'; | ||||
| 98 | 1 | 2 | $hlnk->{href} = $link; | ||||
| 99 | 1 | 3 | next LINK; | ||||
| 100 | } | ||||||
| 101 | |||||||
| 102 | 10 | 16 | my ($base,$categ) = ('','/'); | ||||
| 103 | 10 | 100 | 24 | if ( $link =~ m{\A(\w+):} ) { | |||
| 104 | 2 | 8 | my ($namespace,$lnk) = split qr{:}, $link, 2; | ||||
| 105 | 2 | 4 | $link = $lnk; | ||||
| 106 | 2 | 50 | 6 | if ( my $nmsp = $namespaces{ $namespace } ){ | |||
| 107 | 2 | 50 | 4 | if (ref $nmsp eq 'HASH' ) { | |||
| 0 | |||||||
| 108 | 2 | 50 | 7 | $base = $nmsp->{prefix} if $nmsp->{prefix}; | |||
| 109 | 2 | 50 | 6 | $categ = $nmsp->{category} if $nmsp->{category}; | |||
| 110 | } elsif (ref $nmsp eq 'CODE') { | ||||||
| 111 | 0 | 0 | ($base, $categ, $lnk) = $nmsp->($namespace,$link); | ||||
| 112 | 0 | 0 | 0 | 0 | if ( $lnk and $lnk =~ m{\Ahttps?://} ) { | ||
| 0 | |||||||
| 113 | 0 | 0 | $hlnk->{href} = $lnk; | ||||
| 114 | 0 | 0 | $hlnk->{_class}='external'; | ||||
| 115 | 0 | 0 | next LINK; | ||||
| 116 | } elsif ( $lnk ) { | ||||||
| 117 | 0 | 0 | $link = $lnk; | ||||
| 118 | } | ||||||
| 119 | } | ||||||
| 120 | |||||||
| 121 | } else { | ||||||
| 122 | 0 | 0 | warn "Unknow namespace: $namespace on $lnk\n"; | ||||
| 123 | } | ||||||
| 124 | } | ||||||
| 125 | |||||||
| 126 | 10 | 50 | 16 | if ( $categ ) { | |||
| 127 | 10 | 20 | $link =~ s{\>}{$categ}g; | ||||
| 128 | } | ||||||
| 129 | 10 | 100 | 21 | if ( $base ) { | |||
| 130 | 2 | 4 | $link = $base.$link; | ||||
| 131 | } | ||||||
| 132 | 10 | 100 | 21 | unless ( $link =~ m{\Ahttps?://} ) { | |||
| 133 | 8 | 17 | $link = urify( $link ); | ||||
| 134 | } | ||||||
| 135 | 10 | 27 | $hlnk->{href} = $link; | ||||
| 136 | } | ||||||
| 137 | |||||||
| 138 | 2 | 100 | 10 | return wantarray ? %{$self->{_links}} : $self->{_links}; | |||
| 1 | 9 | ||||||
| 139 | } | ||||||
| 140 | |||||||
| 141 | sub urify { | ||||||
| 142 | 8 | 8 | 1 | 9 | my $link = shift; | ||
| 143 | 8 | 50 | 28 | my $reg = shift || "^\\w\\-\\/\\s\\#"; | |||
| 144 | |||||||
| 145 | 8 | 100 | 22 | $link =~ s{\s*>\s*}{/}g unless $link =~ m{/}; | |||
| 146 | |||||||
| 147 | 8 | 24 | $link = encode_entities( $link, $reg ); | ||||
| 148 | 8 | 650 | $link =~ s{\s+}{-}g; | ||||
| 149 | 8 | 28 | while (my ($ent)=$link=~/\&(\#?\w+);/) { | ||||
| 150 | 0 | 0 | 0 | my $ec=$ent=~/(acute|grave|circ|uml|ring|slash|tilde|cedil)$/i? | |||
| 151 | substr($ent,0,1):'_'; | ||||||
| 152 | 0 | 0 | $link=~s/\&$ent;/$ec/ig; | ||||
| 153 | } | ||||||
| 154 | 8 | 13 | $link="\L$link"; | ||||
| 155 | 8 | 11 | $link=~s/\_+$//g; | ||||
| 156 | 8 | 22 | $link=~s/\_+/\_/g; | ||||
| 157 | |||||||
| 158 | 8 | 18 | return $link; | ||||
| 159 | } | ||||||
| 160 | |||||||
| 161 | sub set_links { | ||||||
| 162 | 0 | 0 | 1 | 0 | my ($self, $links) = @_; | ||
| 163 | |||||||
| 164 | 0 | 0 | $self->{_links} = $links; | ||||
| 165 | |||||||
| 166 | 0 | 0 | return; | ||||
| 167 | } | ||||||
| 168 | |||||||
| 169 | sub format { | ||||||
| 170 | 3 | 3 | 1 | 12 | my $self = shift; | ||
| 171 | 3 | 8 | my $body = $self->{body}; | ||||
| 172 | |||||||
| 173 | 3 | 5 | delete $self->{__headers}; | ||||
| 174 | 3 | 6 | delete $self->{__toc}; | ||||
| 175 | |||||||
| 176 | 3 | 7 | my %done = (); | ||||
| 177 | |||||||
| 178 | 3 | 8 | $body =~ s{&}{&}g; | ||||
| 179 | 3 | 8 | $body =~ s{<}{<}g; | ||||
| 180 | 3 | 15 | $body =~ s{>}{>}g; | ||||
| 181 | |||||||
| 182 | # closed tags | ||||||
| 183 | 3 | 19 | for my $tag ( @do_first, keys %closed ) { | ||||
| 184 | 45 | 100 | 204 | next if $done{ $tag }++; | |||
| 185 | |||||||
| 186 | 24 | 51 | my ($re1, $re2, $re3, $re4, $re5, $re6) | ||||
| 187 | = ref $closed{ $tag } eq 'ARRAY' | ||||||
| 188 | 39 | 100 | 99 | ? @{ $closed{ $tag } } | |||
| 189 | : ( $closed{ $tag } ); | ||||||
| 190 | |||||||
| 191 | 39 | 100 | 73 | if (!$re2) { | |||
| 192 | 15 | 16 | my $in = 0; | ||||
| 193 | 15 | 144 | while ( $body =~ m{$re1}msix ) { | ||||
| 194 | 10 | 100 | 23 | my $tg = $in ? "$tag>" :"<$tag>"; | |||
| 195 | 10 | 75 | $body=~s{$re1}{$tg}msix; | ||||
| 196 | 10 | 153 | $in = 1 - $in; | ||||
| 197 | } | ||||||
| 198 | 15 | 50 | 43 | $body.="$tag>" if $in; | |||
| 199 | } else { | ||||||
| 200 | 24 | 663 | while ($body =~ m{$re1(.*?)$re2}msix) { | ||||
| 201 | 29 | 54 | my $in = $1; | ||||
| 202 | 29 | 59 | my ($t1,$t2) = ("<$tag>","$tag>"); | ||||
| 203 | 29 | 100 | 80 | if (ref $re3 eq 'Regexp') { | |||
| 50 | |||||||
| 204 | 4 | 50 | 10 | $re4 //= ''; | |||
| 205 | 4 | 45 | $in =~ s{ $re3 }{$re4}msixg; | ||||
| 206 | } elsif (ref $re3 eq 'CODE') { | ||||||
| 207 | 25 | 44 | ($t1,$in,$t2) = $re3->($self, $t1, $in, $t2); | ||||
| 208 | } | ||||||
| 209 | 29 | 100 | 77 | $re5 //= ''; | |||
| 210 | 29 | 669 | $body =~ s{$re1(.*?)$re2}{$t1$in$t2$re5}smxi; | ||||
| 211 | } | ||||||
| 212 | } | ||||||
| 213 | } | ||||||
| 214 | |||||||
| 215 | 3 | 13 | for my $tag ( keys %nonclosed ) { | ||||
| 216 | 3 | 7 | my ($re1) = ($nonclosed{ $tag } ); | ||||
| 217 | |||||||
| 218 | 3 | 61 | $body =~ s{ $re1 }{<$tag />}msixg; | ||||
| 219 | } | ||||||
| 220 | |||||||
| 221 | 3 | 44 | while ($body =~ m[(? | ||||
| 222 | 2 | 7 | my ($plugin, $params) = ($1,$2); | ||||
| 223 | 2 | 5 | $params = _parse_plugin_params($params); | ||||
| 224 | |||||||
| 225 | 2 | 4 | my $res = ''; | ||||
| 226 | 2 | 50 | 7 | if ( $plugins{$plugin} ){ | |||
| 227 | 2 | 50 | 6 | $res = $plugins{ $plugin }->( $self, $plugin, $params ) // ''; | |||
| 228 | } | ||||||
| 229 | |||||||
| 230 | 2 | 23 | $body =~ s[(? | ||||
| 231 | } | ||||||
| 232 | |||||||
| 233 | 3 | 43 | while ($body =~ m[\/\+\+(\w+)(?:[:\s*](.+))?\+\+\/]msix) { | ||||
| 234 | 1 | 3 | my ($plugin, $params) = ($1,$2); | ||||
| 235 | 1 | 4 | $params=~s{\A\s*}{}; | ||||
| 236 | 1 | 6 | my @params = split qr{\s*,\s*}, $params; | ||||
| 237 | |||||||
| 238 | 1 | 5 | my $res = ''; | ||||
| 239 | 1 | 50 | 4 | if ( $plugins{$plugin} ){ | |||
| 240 | 1 | 50 | 6 | $res = $plugins{ $plugin }->( $self, $plugin, @params ) // ''; | |||
| 241 | } | ||||||
| 242 | |||||||
| 243 | 1 | 40 | $body =~ s[\/\+\+(\w+)(?:[:\s*](.+))?\+\+\/][$res]msix; | ||||
| 244 | } | ||||||
| 245 | |||||||
| 246 | 3 | 15 | return $body; | ||||
| 247 | } | ||||||
| 248 | |||||||
| 249 | sub register_namespace { | ||||||
| 250 | 0 | 0 | 1 | 0 | my $class = shift; | ||
| 251 | |||||||
| 252 | 0 | 0 | my ($namespace, $info, $override) = @_; | ||||
| 253 | |||||||
| 254 | 0 | 0 | 0 | 0 | $namespaces{ $namespace } = $info | ||
| 255 | if $override or !$namespaces{ $namespace }; | ||||||
| 256 | } | ||||||
| 257 | |||||||
| 258 | sub register_plugin { | ||||||
| 259 | 0 | 0 | 1 | 0 | my $class = shift; | ||
| 260 | |||||||
| 261 | 0 | 0 | my ($pluginname, $pluginref, $override) = @_; | ||||
| 262 | |||||||
| 263 | 0 | 0 | 0 | 0 | $plugins{ $pluginname } = $pluginref | ||
| 264 | if $override or !$plugins{ $pluginname }; | ||||||
| 265 | } | ||||||
| 266 | |||||||
| 267 | sub _header_id { | ||||||
| 268 | 0 | 0 | 0 | my $self = shift; | |||
| 269 | 0 | 0 | 0 | my $headers = $self->{__headers} ||= {}; | |||
| 270 | 0 | 0 | 0 | my $headnames = $self->{__headnames} ||= {}; | |||
| 271 | 0 | 0 | 0 | my $toc = $self->{__toc} ||= []; | |||
| 272 | 0 | 0 | my ($t1, $in, $t2) = @_; | ||||
| 273 | |||||||
| 274 | 0 | 0 | my ($type) = $in =~ m{^(!{1,6})\s}; | ||||
| 275 | 0 | 0 | $in =~ s{^!*\s}{}; | ||||
| 276 | |||||||
| 277 | 0 | 0 | $t1 = 'h'.length($type); | ||||
| 278 | 0 | 0 | $t2 = "$t1>"; | ||||
| 279 | 0 | 0 | $t1 = "<$t1>"; | ||||
| 280 | |||||||
| 281 | 0 | 0 | my $id = urify($in, "^\\w\\-\\s"); | ||||
| 282 | |||||||
| 283 | 0 | 0 | 0 | if ($headers->{$id}) { | |||
| 284 | 0 | 0 | my $cnt = 1; | ||||
| 285 | 0 | 0 | $cnt++ while $headers->{"${id}_$cnt"}; | ||||
| 286 | 0 | 0 | $id .= "_$cnt"; | ||||
| 287 | } | ||||||
| 288 | |||||||
| 289 | 0 | 0 | $headnames->{$id} = $in; | ||||
| 290 | 0 | 0 | $headers->{$id} = substr($t1, 2, 1); | ||||
| 291 | 0 | 0 | push @$toc, $id; | ||||
| 292 | |||||||
| 293 | 0 | 0 | substr($t1, -1, 0, " id='$id'"); | ||||
| 294 | |||||||
| 295 | 0 | 0 | return $t1, $in, $t2; | ||||
| 296 | } | ||||||
| 297 | |||||||
| 298 | sub _escape_code { | ||||||
| 299 | 1 | 1 | 2 | my $self = shift; | |||
| 300 | |||||||
| 301 | 1 | 2 | my ($t1, $in, $t2) = @_; | ||||
| 302 | |||||||
| 303 | 1 | 6 | $in=~s{\n}{ \n}gs; |
||||
| 304 | |||||||
| 305 | 1 | 3 | $self->{__codecnt}++; | ||||
| 306 | 1 | 4 | $self->{__codeblock}->{$self->{__codecnt}} = $in; | ||||
| 307 | |||||||
| 308 | 1 | 5 | return '',"/++restore_code_block: $self->{__codecnt}++/", ''; | ||||
| 309 | } | ||||||
| 310 | |||||||
| 311 | sub _do_lists { | ||||||
| 312 | 1 | 1 | 2 | my $self = shift; | |||
| 313 | |||||||
| 314 | 1 | 2 | my ($t1, $in, $t2) = @_; | ||||
| 315 | |||||||
| 316 | 1 | 9 | my @lines = split qr{\n}ms, $in; | ||||
| 317 | 1 | 5 | $in = ''; | ||||
| 318 | 1 | 2 | my $cl = ''; | ||||
| 319 | 1 | 1 | my $item; | ||||
| 320 | 1 | 3 | for my $ln (@lines) { | ||||
| 321 | 6 | 50 | 34 | if ( $ln !~ m{^\s} ) { | |||
| 322 | 6 | 100 | 13 | if ($item) { | |||
| 323 | 5 | 13 | $in .= " |
||||
| 324 | 5 | 7 | $item = ''; | ||||
| 325 | } | ||||||
| 326 | 6 | 28 | my ($nl,$l) = $ln =~ m{^([\*\#]+)\s+(.*)$}; | ||||
| 327 | 6 | 9 | $ln = $l; | ||||
| 328 | 6 | 7 | my $close = ''; | ||||
| 329 | 6 | 7 | my $start = -1; | ||||
| 330 | 6 | 100 | 15 | if ($nl ne $cl) { | |||
| 331 | 5 | 14 | for my $i (0..length($cl)-1) { | ||||
| 332 | 8 | 100 | 100 | 38 | next if !$close and substr($cl,$i,1) eq substr($nl, $i, 1); | ||
| 333 | 4 | 100 | 10 | $start = $i unless $close; | |||
| 334 | 4 | 100 | 17 | $close = (substr($cl,$i,1) eq '#' ? "" : "").$close; | |||
| 335 | } | ||||||
| 336 | 5 | 100 | 12 | $start = length($cl) if $start == -1; | |||
| 337 | 5 | 100 | 12 | $in.=$close."\n" if $close; | |||
| 338 | 5 | 11 | for my $i ($start..length($nl)-1) { | ||||
| 339 | 5 | 100 | 19 | $in.= substr($nl, $i, 1) eq '#'?"
|
|||
| 340 | } | ||||||
| 341 | 5 | 10 | $cl = $nl; | ||||
| 342 | } | ||||||
| 343 | } | ||||||
| 344 | 6 | 11 | $item .= $ln; | ||||
| 345 | } | ||||||
| 346 | 1 | 50 | 4 | if ($item) { | |||
| 347 | 1 | 4 | $in .= " |
||||
| 348 | } | ||||||
| 349 | 1 | 50 | 4 | if ($cl) { | |||
| 350 | 1 | 5 | for my $i (reverse 0..length($cl)-1) { | ||||
| 351 | 1 | 50 | 6 | $in.=substr($cl,$i,1) eq '#' ? "" : ""; | |||
| 352 | } | ||||||
| 353 | 1 | 2 | $in.="\n"; | ||||
| 354 | } | ||||||
| 355 | |||||||
| 356 | 1 | 5 | return '',$in,''; | ||||
| 357 | } | ||||||
| 358 | |||||||
| 359 | sub _do_links { | ||||||
| 360 | 4 | 4 | 33 | my $self = shift; | |||
| 361 | |||||||
| 362 | 4 | 9 | my (undef, $link, undef) = @_; | ||||
| 363 | |||||||
| 364 | 4 | 100 | 66 | 25 | $self->urls() unless $self->{_links} and $self->{_links}->{$link}; | ||
| 365 | |||||||
| 366 | 4 | 50 | 13 | my $lnk = $self->{_links}->{$link} || {}; | |||
| 367 | |||||||
| 368 | 4 | 5 | my ($t1,$t2) = ('',''); | ||||
| 369 | |||||||
| 370 | 4 | 8 | $t1 = " | ||||
| 371 | 4 | 100 | 25 | my $class = $lnk->{class} || $lnk->{_class} || ''; | |||
| 372 | 4 | 100 | 10 | if ( $class ) { | |||
| 373 | 1 | 4 | $t1.=" class='$class'"; | ||||
| 374 | } | ||||||
| 375 | 4 | 6 | $t1.='>'; | ||||
| 376 | |||||||
| 377 | 4 | 15 | return $t1, $lnk->{title}, $t2; | ||||
| 378 | } | ||||||
| 379 | |||||||
| 380 | sub _handle_toc { | ||||||
| 381 | 1 | 1 | 2 | my ($self) = shift; | |||
| 382 | |||||||
| 383 | 1 | 2 | my $toc = $self->{__toc}; | ||||
| 384 | 1 | 2 | my $headers = $self->{__headers}; | ||||
| 385 | 1 | 2 | my $headnames = $self->{__headnames}; | ||||
| 386 | |||||||
| 387 | 1 | 2 | my $res = "\n"; | ||||
| 388 | 1 | 2 | for my $head (@$toc) { | ||||
| 389 | 0 | 0 | $res.='*'x$headers->{$head}; | ||||
| 390 | |||||||
| 391 | 0 | 0 | $res.=' '; | ||||
| 392 | 0 | 0 | $res.='[['.$headnames->{$head}.'|#'.$head."]]\n"; | ||||
| 393 | } | ||||||
| 394 | 1 | 3 | $res.="\n"; | ||||
| 395 | |||||||
| 396 | 1 | 4 | my $wf = (ref $self)->new(body => $res); | ||||
| 397 | 1 | 10 | $res = $wf->format(); | ||||
| 398 | |||||||
| 399 | 1 | 3 | $res = " $res "; |
||||
| 400 | |||||||
| 401 | 1 | 10 | return $res; | ||||
| 402 | } | ||||||
| 403 | |||||||
| 404 | sub _handle_image { | ||||||
| 405 | 1 | 1 | 2 | my ($self, $plugin, $params) = @_; | |||
| 406 | 1 | 3 | my $src; | ||||
| 407 | |||||||
| 408 | 1 | 50 | 3 | if (ref $params eq 'ARRAY') { | |||
| 409 | 1 | 2 | $src = shift @$params; | ||||
| 410 | 1 | 50 | 33 | 5 | if (@$params and ref $params->[0] eq 'HASH') { | ||
| 411 | 0 | 0 | $params = $params->[0]; | ||||
| 412 | } else { | ||||||
| 413 | 1 | 2 | $params = { @$params }; | ||||
| 414 | } | ||||||
| 415 | } else { | ||||||
| 416 | 0 | 0 | $src = delete $params->{src}; | ||||
| 417 | } | ||||||
| 418 | |||||||
| 419 | 1 | 50 | 2 | return '' unless $src; | |||
| 420 | |||||||
| 421 | 1 | 50 | 33 | 8 | if ($src =~ m{\Ahttps?://} and $self->{image_filter}) { | ||
| 50 | |||||||
| 422 | 0 | 0 | $src = $self->{image_filter}->($src, $params); | ||||
| 423 | } elsif ($self->{image_mapper}) { | ||||||
| 424 | 0 | 0 | $src = $self->{image_mapper}->($src, $params); | ||||
| 425 | } | ||||||
| 426 | |||||||
| 427 | 1 | 50 | 6 | return '' unless $src; | |||
| 428 | |||||||
| 429 | 1 | 3 | my $res = " | ||||
| 430 | 1 | 50 | 4 | if ( $params->{size} ) { | |||
| 431 | 0 | 0 | my ($w,$h) = $params->{size} =~ m{\A\d+x\d+\z}; | ||||
| 432 | |||||||
| 433 | 0 | 0 | 0 | 0 | if ($w and $h) { | ||
| 434 | 0 | 0 | 0 | $params->{width} ||= $w; | |||
| 435 | 0 | 0 | 0 | $params->{height} ||= $h; | |||
| 436 | 0 | 0 | delete $params->{size}; | ||||
| 437 | } | ||||||
| 438 | } | ||||||
| 439 | 1 | 2 | for my $attr ( qw(alt title heigth width) ) { | ||||
| 440 | 4 | 50 | 10 | next unless $params->{ $attr }; | |||
| 441 | 0 | 0 | my $av = $params->{ $attr }; | ||||
| 442 | 0 | 0 | $av =~ s{&}{&}g; | ||||
| 443 | 0 | 0 | $av =~ s{<}{>}g; | ||||
| 444 | 0 | 0 | $av =~ s{>}{<}g; | ||||
| 445 | 0 | 0 | $av =~ s{'}{'}g; | ||||
| 446 | 0 | 0 | $res.=" $attr='$av'"; | ||||
| 447 | } | ||||||
| 448 | |||||||
| 449 | 1 | 28 | $res.=' />'; | ||||
| 450 | |||||||
| 451 | #MAYBETODO: support for caption, to allow to frame the images | ||||||
| 452 | # and add a legend under the image. | ||||||
| 453 | |||||||
| 454 | 1 | 5 | return $res; | ||||
| 455 | } | ||||||
| 456 | |||||||
| 457 | sub _restore_code_block { | ||||||
| 458 | 1 | 1 | 3 | my ($self, $plugin, $block) = @_; | |||
| 459 | |||||||
| 460 | 1 | 3 | my $res = $self->{__codeblock}->{$block}; | ||||
| 461 | |||||||
| 462 | 1 | 7 | return "$res"; |
||||
| 463 | } | ||||||
| 464 | |||||||
| 465 | sub _parse_plugin_params { | ||||||
| 466 | 2 | 2 | 3 | my $paramstr = shift; | |||
| 467 | |||||||
| 468 | 2 | 100 | 8 | return [] unless $paramstr; | |||
| 469 | |||||||
| 470 | 1 | 50 | 5 | unless ($paramstr =~ m(\A\s*[\{\[]) ) { | |||
| 471 | 1 | 3 | $paramstr = '['.$paramstr.']'; | ||||
| 472 | } | ||||||
| 473 | |||||||
| 474 | 1 | 50 | 3 | my $params = eval { | |||
| 475 | 1 | 6 | from_json( $paramstr, { utf8 => 1 }) | ||||
| 476 | } or do print STDERR "Error Parsing params: $paramstr ==> $@\n"; | ||||||
| 477 | #MAYBETODO: export this error somehow? silent it? | ||||||
| 478 | # exporting it may be useful - specially while previewing | ||||||
| 479 | # the result. | ||||||
| 480 | |||||||
| 481 | 1 | 45 | return $params; | ||||
| 482 | } | ||||||
| 483 | |||||||
| 484 | 1; | ||||||
| 485 | __END__ |