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