File Coverage

blib/lib/Parse/BBCode/HTML.pm
Criterion Covered Total %
statement 27 27 100.0
branch 6 6 100.0
condition n/a
subroutine 8 8 100.0
pod 3 3 100.0
total 44 44 100.0


line stmt bran cond sub pod time code
1             package Parse::BBCode::HTML;
2             $Parse::BBCode::HTML::VERSION = '0.15';
3 14     14   79 use strict;
  14         24  
  14         891  
4 14     14   72 use warnings;
  14         26  
  14         460  
5 14     14   73 use Carp qw(croak carp);
  14         27  
  14         1083  
6 14     14   12469 use URI::Escape;
  14         19590  
  14         1034  
7 14     14   94 use base 'Exporter';
  14         26  
  14         30195  
8             our @EXPORT_OK = qw/ &defaults &default_escapes &optional /;
9              
10             my $email_valid = 0;
11             eval {
12             require
13             Email::Valid;
14             };
15             $email_valid = 1 unless $@;
16              
17             my %colors = (
18             aqua => 1,
19             black => 1,
20             blue => 1,
21             fuchsia => 1,
22             gray => 1,
23             grey => 1,
24             green => 1,
25             lime => 1,
26             maroon => 1,
27             navy => 1,
28             olive => 1,
29             purple => 1,
30             red => 1,
31             silver => 1,
32             teal => 1,
33             white => 1,
34             yellow => 1,
35             );
36              
37             my %default_tags = (
38             'b' => '%s',
39             'i' => '%s',
40             'u' => '%s',
41             'img' => '[%{html}s]',
42             'url' => 'url:%s',
43             'email' => 'url:%s',
44             'size' => '%s',
45             'color' => '%s',
46             'list' => {
47             parse => 1,
48             class => 'block',
49             code => sub {
50             my ($parser, $attr, $content, $attribute_fallback, $tag) = @_;
51             $$content =~ s/^\n+//;
52             $$content =~ s/\n+\z//;
53             my $type = "ul";
54             my $style = '';
55             if ($attr) {
56             if ($attr eq '1') {
57             $type = "ol";
58             }
59             elsif ($attr eq 'a') {
60             $type = "ol";
61             $style = ' style="list-style-type: lower-alpha"';
62             }
63             }
64             return "<$type$style>$$content";
65             },
66             },
67             '*' => {
68             parse => 1,
69             code => sub {
70             my ($parser, $attr, $content, $attribute_fallback, $tag, $info) = @_;
71             $$content =~ s/\n+\z//;
72             if ($info->{stack}->[-2] eq 'list') {
73             return "
  • $$content
  • ",
    74             }
    75             return Parse::BBCode::escape_html($tag->raw_text);
    76             },
    77             close => 0,
    78             class => 'block',
    79             },
    80             'quote' => {
    81             code => sub {
    82             my ($parser, $attr, $content) = @_;
    83             my $title = 'Quote';
    84             if ($attr) {
    85             $title = Parse::BBCode::escape_html($attr);
    86             }
    87             return <<"EOM";
    88            
    $title:
    89            
    $$content
    90             EOM
    91             },
    92             parse => 1,
    93             class => 'block',
    94             },
    95             'code' => {
    96             code => sub {
    97             my ($parser, $attr, $content) = @_;
    98             my $title = 'Code';
    99             if ($attr) {
    100             $title = Parse::BBCode::escape_html($attr);
    101             }
    102             $content = Parse::BBCode::escape_html($$content);
    103             return <<"EOM";
    104            
    $title:
    105            
    $content
    106             EOM
    107             },
    108             parse => 0,
    109             class => 'block',
    110             },
    111             'noparse' => '%{html}s',
    112             );
    113             my %optional_tags = (
    114             'html' => '%{noescape}s',
    115             );
    116              
    117             my %default_escapes = (
    118             html => sub {
    119             Parse::BBCode::escape_html($_[2]),
    120             },
    121             uri => sub {
    122             uri_escape($_[2]),
    123             },
    124             link => sub {
    125             my ($p, $tag, $var) = @_;
    126             if ($var =~ m{^ (?: [a-z]+:// | / ) \S+ \z}ix) {
    127             # allow proto:// and absolute links /
    128             }
    129             else {
    130             # invalid
    131             return;
    132             }
    133             $var = Parse::BBCode::escape_html($var);
    134             return $var;
    135             },
    136             email => $email_valid ? sub {
    137             my ($p, $tag, $var) = @_;
    138             # extracts the address part of the email or undef
    139             my $valid = Email::Valid->address($var);
    140             return $valid ? Parse::BBCode::escape_html($valid) : '';
    141             } : sub {
    142             my ($p, $tag, $var) = @_;
    143             $var = Parse::BBCode::escape_html($var);
    144             },
    145             htmlcolor => sub {
    146             my $color = $_[2];
    147             ($color =~ m/^(?:#[0-9a-fA-F]{6})\z/ || exists $colors{lc $color})
    148             ? $color : 'inherit'
    149             },
    150             num => sub {
    151             $_[2] =~ m/^[0-9]+\z/ ? $_[2] : 0;
    152             },
    153             );
    154              
    155              
    156             sub defaults {
    157 13     13 1 1479 my ($class, @keys) = @_;
    158             return @keys
    159 13 100       318 ? (map { $_ => $default_tags{$_} } grep { defined $default_tags{$_} } @keys)
      2         26  
      2         7  
    160             : %default_tags;
    161             }
    162              
    163             sub default_escapes {
    164 36     36 1 90 my ($class, @keys) = @_;
    165             return @keys
    166 36 100       343 ? (map { $_ => $default_escapes{$_} } grep { defined $default_escapes{$_} } @keys)
      3         15  
      3         8  
    167             : %default_escapes;
    168             }
    169              
    170             sub optional {
    171 2     2 1 44 my ($class, @keys) = @_;
    172             return @keys
    173 2 100       10 ? (map { $_ => $optional_tags{$_} } grep { defined $optional_tags{$_} } @keys)
      1         8  
      1         4  
    174             : %optional_tags;
    175             }
    176              
    177              
    178              
    179             1;
    180              
    181             __END__