File Coverage

blib/lib/IRC/Formatting/HTML/Input.pm
Criterion Covered Total %
statement 80 86 93.0
branch 47 66 71.2
condition 25 30 83.3
subroutine 10 10 100.0
pod 0 2 0.0
total 162 194 83.5


line stmt bran cond sub pod time code
1             package IRC::Formatting::HTML::Input;
2              
3 4     4   21 use warnings;
  4         9  
  4         141  
4 4     4   21 use strict;
  4         6  
  4         126  
5              
6 4     4   19 use IRC::Formatting::HTML::Common;
  4         7  
  4         1485  
7 4     4   5083 use HTML::Parser ();
  4         31420  
  4         5058  
8              
9             my $p = HTML::Parser->new(api_version => 3,
10             text_h => [\&_text, 'dtext'],
11             start_h => [\&_tag_start, 'tagname, attr'],
12             end_h => [\&_tag_end, 'tagname']);
13              
14             my $nbsp = chr(160);
15             my @states;
16             my $irctext = "";
17              
18             sub parse {
19 16     16 0 30 $irctext = "";
20 16         36 _reset();
21 16         31 my $html = shift;
22 16         42 $html =~ s/\n//;
23 16         176 $p->parse($html);
24 16         60 $p->eof;
25 16         34 $irctext =~ s/\n{2,}/\n/;
26 16         296 $irctext =~ s/^\n+//;
27 16         33 $irctext =~ s/\n+$//;
28 16         61 return $irctext;
29             }
30              
31             sub _reset {
32 16     16   290 @states = ({
33             b => 0,
34             i => 0,
35             u => 0,
36             fg => "",
37             bg => "",
38             });
39             }
40              
41             sub _text {
42 29     29   54 my $text = shift;
43 29         85 $text =~ s/$nbsp/ /g;
44 29 50 33     250 $irctext .= $text if defined $text and length $text;
45             }
46              
47             sub clone {
48 25     25 0 35 my $state = $states[0];
49             return {
50 25         144 b => $state->{b},
51             i => $state->{i},
52             u => $state->{u},
53             fg => $state->{fg},
54             bg => $state->{bg},
55             };
56             }
57              
58             sub _tag_start {
59 25     25   48 my ($tag, $attr) = @_;
60              
61 25         52 my $state = clone();
62              
63 25 100 66     252 if ($tag eq "br" or $tag eq "p" or $tag eq "div" or $tag =~ /^h[\dr]$/) {
      100        
      100        
64 3         7 $irctext .= "\n";
65             }
66              
67 25 100       67 if ($attr->{style}) {
68 7 100       58 if ($attr->{style} =~ /(?:^|;\s*)color:\s*([^;"]+)/) {
69 5         20 my $color = IRC::Formatting::HTML::Common::html_color_to_irc($1);
70 5 50       16 if ($color) {
71 5         12 $state->{fg} = $color;
72 5         10 $irctext .= $COLOR.$color;
73 5 50       20 $irctext .=",$state->{bg}" if length $state->{bg};
74             }
75             }
76 7 100       29 if ($attr->{style} =~ /font-weight:\s*bold/) {
77 1 50       6 $irctext .= $BOLD unless $state->{b};
78 1         2 $state->{b} = 1;
79             }
80 7 50       25 if ($attr->{style} =~ /font-style:\s*italic/) {
81 0 0       0 $irctext .= $INVERSE unless $state->{i};
82 0         0 $state->{i} = 1;
83             }
84 7 50       21 if ($attr->{style} =~ /text-decoration:\s*underline/) {
85 0 0       0 $irctext .= $UNDERLINE unless $state->{u};
86 0         0 $state->{u} = 1;
87             }
88 7 100       29 if ($attr->{style} =~ /background-color:\s*([^;"]+)/) {
89 3         10 my $color = IRC::Formatting::HTML::Common::html_color_to_irc($1);
90 3 100       11 if ($color) {
91 2         6 $state->{bg} = $color;
92 2 100       9 my $fg = length $state->{fg} ? $state->{fg} : "01";
93 2         8 $irctext .= $COLOR."$fg,$color";
94             }
95             }
96             }
97              
98 25 100       66 if ($attr->{color}) {
99 4         16 my $color = IRC::Formatting::HTML::Common::html_color_to_irc($attr->{color});
100 4 50       13 if ($color) {
101 4         11 $state->{fg} = $color;
102 4         8 $irctext .= $COLOR.$color;
103 4 50       15 $irctext .=",$state->{bg}" if length $state->{bg};
104             }
105             }
106              
107 25 100 66     253 if ($tag eq "strong" or $tag eq "b" or $tag =~ /^h\d$/) {
    100 100        
    100 66        
108 6 50       20 $irctext .= $BOLD unless $state->{b};
109 6         13 $state->{b} = 1;
110             } elsif ($tag eq "em" or $tag eq "i") {
111 4 50       13 $irctext .= $INVERSE unless $state->{i};
112 4         7 $state->{i} = 1;
113             } elsif ($tag eq "u") {
114 2 50       9 $irctext .= $UNDERLINE unless $state->{u};
115 2         4 $state->{u} = 1;
116             }
117              
118 25         336 unshift @states, $state;
119             }
120              
121             sub _tag_end {
122 25     25   40 my $tag = shift;
123              
124 25         33 my $prev = shift @states;
125 25         35 my $next = $states[0];
126              
127 25 100       129 $irctext .= $BOLD if $next->{b} ne $prev->{b};
128 25 100       72 $irctext .= $INVERSE if $next->{i} ne $prev->{i};
129 25 100       69 $irctext .= $UNDERLINE if $next->{u} ne $prev->{u};
130              
131 25 100 100     121 if ($next->{fg} ne $prev->{fg} or $next->{bg} ne $prev->{bg}) {
132 11         134 $irctext .= $COLOR;
133              
134 11         23 my ($fg, $bg) = ("","");
135            
136 11 100       33 if (length $next->{fg}) {
137 3         6 $fg = $next->{fg};
138             }
139 11 50       30 if (length $next->{bg}) {
140 0         0 $bg = $next->{bg};
141 0 0       0 $fg = "01" unless length $fg;
142             }
143              
144 11         16 $irctext .= $fg;
145 11 50       31 $irctext .= ",$bg" if length $bg;
146             }
147              
148 25 100 100     268 if ($tag eq "p" or $tag eq "div" or $tag =~ /^h[\dr]$/) {
      100        
149 3         15 $irctext .= "\n";
150             }
151             }
152              
153             1