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