File Coverage

blib/lib/HTML/Trim.pm
Criterion Covered Total %
statement 72 72 100.0
branch 14 14 100.0
condition 3 6 50.0
subroutine 18 18 100.0
pod 2 3 66.6
total 109 113 96.4


line stmt bran cond sub pod time code
1             package HTML::Trim;
2 3     3   13316 use strict;
  3         7  
  3         127  
3 3     3   15 use warnings;
  3         4  
  3         83  
4 3     3   1760 use utf8;
  3         19  
  3         19  
5             our $VERSION = '0.02';
6              
7 3     3   2838 use Exporter::Lite;
  3         2604  
  3         18  
8 3     3   5739 use HTML::Parser;
  3         29238  
  3         119  
9 3     3   2805 use Unicode::EastAsianWidth;
  3         2116  
  3         1001  
10              
11             our @EXPORT_OK = qw(htrim hvtrim);
12              
13             sub trim {
14 28     28 1 188 my ($str, $max, $delim) = @_;
15 28 100       78 if (ref $str eq __PACKAGE__) {
16 16         43 return _trim(@_);
17             }
18             __PACKAGE__->new(
19             length => sub {
20 18     18   53 length $_[0];
21             },
22             substr => sub {
23 9     9   38 substr $_[0], $_[1], $_[2];
24             }
25 12         114 )->trim($str, $max, $delim);
26             }
27             *htrim = \&trim;
28              
29             sub vtrim {
30 4     4 1 34 my ($str, $max, $delim) = @_;
31             __PACKAGE__->new(
32             length => sub {
33 7     7   9 my ($str) = @_;
34 7         9 my $ret = 0;
35              
36 7         10 local $_ = $str;
37 3     3   20 while (/(?:(\p{InFullwidth}+)|(\p{InHalfwidth}+))/g) {
  3         7  
  3         45  
  7         45  
38 7 100       3776 $ret += $1 ? length($1) * 2 : length($2);
39             }
40 7         17 $ret;
41             },
42             substr => sub {
43 4     4   6 my ($str, $offset, $limit) = @_; # ignoring offset
44 4         6 my $ret = "";
45 4         4 my $count = 0;
46              
47 4         6 local $_ = $str;
48 4         21 while (/(?:(\p{InFullwidth})|(\p{InHalfwidth}))/g) {
49 18 100       2424 $count += $1 ? length($1) * 2 : length($2);
50 18 100       32 last if $count > $limit;
51 14   66     64 $ret .= $1 || $2;
52             }
53 4         9 $ret;
54             }
55 4         40 )->trim($str, $max, $delim);
56             }
57             *hvtrim = \&vtrim;
58              
59             sub new {
60 16     16 0 63 my ($class, %opts) = @_;
61 16         115 bless {
62             length => $opts{length},
63             substr => $opts{substr}
64             }, $class;
65             }
66              
67             sub _trim {
68 16     16   29 my ($self, $str, $max, $delim) = @_;
69              
70 16         21 my $ret = "";
71 16         21 my $count = 0;
72 16         25 my $opened = [];
73              
74 16         19 my $p; $p = HTML::Parser->new(
75             api_version => 3,
76             handlers => {
77             start => [ sub {
78 13     13   25 my ($text, $tagname) = @_;
79 13 100       56 push @$opened, $tagname unless $tagname =~ /^(input|img|br)$/;;
80 13         62 $ret .= $text;
81             }, "text, tagname"],
82             end => [ sub {
83 1     1   4 my ($text, $tagname) = @_;
84 1   33     7 until (!@$opened || pop @$opened eq $tagname) { }
85 1         4 $ret .= $text;
86             }, "text, tagname"],
87             text => [ sub {
88 25     25   37 my ($text) = @_;
89 25         75 my $length += $self->{length}->($text);
90 25 100       62 if ($count + $length > $max) {
91 13         39 $ret .= $self->{substr}->($text, 0, $max - $count - 1);
92 13         39 $p->eof; # end parse immediately
93             } else {
94 12         22 $ret .= $text;
95             }
96 25         102 $count += $length
97 16         299 }, 'text'],
98             }
99             );
100 16         885 $p->parse($str);
101 16         74 $p->eof;
102              
103 16         49 while (my $tagname = pop @$opened) {
104 10         51 $ret .= sprintf('', $tagname);
105             }
106              
107 16 100       53 if ($count > $max) {
108 13         22 $ret .= $delim;
109             }
110            
111 16         102 $ret;
112             }
113              
114             1;
115             __END__