File Coverage

blib/lib/Pod/Simple/Words.pm
Criterion Covered Total %
statement 126 139 90.6
branch 50 52 96.1
condition 3 3 100.0
subroutine 16 18 88.8
pod 4 4 100.0
total 199 216 92.1


line stmt bran cond sub pod time code
1             package Pod::Simple::Words;
2              
3 1     1   251419 use strict;
  1         8  
  1         29  
4 1     1   7 use warnings;
  1         2  
  1         22  
5 1     1   15 use 5.026;
  1         3  
6 1     1   544 use experimental qw( signatures );
  1         3568  
  1         6  
7 1     1   751 use JSON::MaybeXS qw( encode_json );
  1         6018  
  1         64  
8 1     1   521 use Text::HumanComputerWords 0.02;
  1         3629  
  1         48  
9 1     1   566 use PPI;
  1         115449  
  1         45  
10 1     1   575 use URI;
  1         4795  
  1         35  
11 1     1   7 use base qw( Pod::Simple );
  1         3  
  1         735  
12              
13             # ABSTRACT: Parse words and locations from a POD document
14             our $VERSION = '0.07'; # VERSION
15              
16              
17             __PACKAGE__->_accessorize(
18             qw( line_number in_verbatim in_head1 callback target head1 skip_section_hash link_address in_section_title splitter ),
19             );
20              
21              
22             sub new ($class)
23 17     17 1 67750 {
  17         39  
  17         27  
24 17         77 my $self = $class->SUPER::new;
25 17         409 $self->preserve_whitespace(1);
26 17         162 $self->in_verbatim(0);
27 17         124 $self->in_head1(0);
28 17         124 $self->in_section_title(0);
29 17         113 $self->head1('');
30 17         132 $self->no_errata_section(1);
31 17         116 $self->accept_targets( qw( stopwords ));
32 17         637 $self->target(undef);
33 17         118 $self->skip_section_hash({});
34 17 50       105 if(! defined $self->splitter)
35             {
36 17         168 $self->splitter(
37             Text::HumanComputerWords->new(
38             Text::HumanComputerWords->default_perl,
39             ),
40             );
41             }
42             $self->callback(sub {
43 0     0   0 my $row = encode_json \@_;
44 0         0 print "--- $row\n";
45 17         1032 });
46 17         116 $self;
47             }
48              
49              
50 1         2 sub skip_sections ($self, @sections)
51 1     1 1 8 {
  1         3  
  1         2  
52 1         6 $self->skip_section_hash->{lc $_} = 1 for @sections;
53             }
54              
55 103         153 sub _handle_element_start ($self, $tagname, $attrhash, @)
  103         163  
  103         144  
56 103     103   29302 {
  103         135  
57 103 100       401 $self->line_number($attrhash->{start_line}) if defined $attrhash->{start_line};
58              
59 103 100       825 if($tagname eq 'L')
    100          
    100          
    100          
    100          
60             {
61 9         31 my @row = ( $attrhash->{type} . "_link", $self->source_filename, $self->line_number, [undef, undef] );
62 9 100       101 if($attrhash->{type} eq 'url')
63             {
64 3         21 my $url = URI->new($attrhash->{to});
65 3 100       8991 if(defined $url->fragment)
66             {
67 1         15 $row[3]->[1] = $url->fragment;
68 1         12 $url->fragment(undef);
69             }
70 3         123 $row[3]->[0] = "$url";
71             }
72             else
73             {
74 6 100       23 $row[3]->[0] = $attrhash->{to} . '' if defined $attrhash->{to};
75 6 100       85 $row[3]->[1] = $attrhash->{section} . '' if defined $attrhash->{section};
76             }
77 9         100 $self->callback->(@row);
78 9         625 $self->link_address($attrhash->{to});
79             }
80             elsif($tagname eq 'for')
81             {
82 2         8 $self->target($attrhash->{target});
83             }
84             elsif($tagname eq 'Verbatim')
85             {
86 3         9 $self->in_verbatim($self->in_verbatim+1);
87             }
88             elsif($tagname eq 'head1')
89             {
90 19         44 $self->in_head1($self->in_head1+1);
91 19         191 $self->head1('');
92 19         108 $self->in_section_title(1);
93             }
94             elsif($tagname =~ /^head[0-9]+$/)
95             {
96 3         14 $self->in_section_title(1);
97             }
98 103         362 ();
99             }
100              
101 103         160 sub _handle_element_end ($self, $tagname, @)
  103         145  
102 103     103   2303 {
  103         127  
103 103 100       419 if($tagname eq 'Verbatim')
    100          
    100          
    100          
    100          
104             {
105 3         10 $self->in_verbatim($self->in_verbatim-1);
106             }
107             elsif($tagname eq 'head1')
108             {
109 19         41 $self->in_head1($self->in_head1-1);
110 19         191 $self->in_section_title(0);
111             }
112             elsif($tagname =~ /^head[0-9]+$/)
113             {
114 3         9 $self->in_section_title(0);
115             }
116             elsif($tagname eq 'for')
117             {
118 2         5 $self->target(undef);
119             }
120             elsif($tagname eq 'L')
121             {
122 9         23 $self->link_address(undef);
123             }
124             }
125              
126 63         82 sub _add_words ($self, $line)
127 63     63   103 {
  63         99  
  63         86  
128 63         129 foreach my $event ($self->splitter->split($line))
129             {
130 99         5904 my($type, $word) = @$event;
131 99         212 my @row = ( $type, $self->source_filename, $self->line_number, $word );
132 99         939 $self->callback->(@row);
133             }
134             }
135              
136 1         4 sub whine ($self, $line, $complaint)
  1         3  
137 1     1 1 78 {
  1         2  
  1         3  
138 1         3 my @row = ( 'error', $self->source_filename, $self->line_number, $complaint );
139 1         13 $self->callback->(@row);
140 1         18 $self->SUPER::whine($line, $complaint);
141             }
142              
143 0         0 sub scream ($self, $line, $complaint)
  0         0  
144 0     0 1 0 {
  0         0  
  0         0  
145 0         0 my @row = ( 'error', $self->source_filename, $self->line_number, $complaint );
146 0         0 $self->callback->(@row);
147 0         0 $self->SUPER::scream($line, $complaint);
148             }
149              
150 68         103 sub _handle_text ($self, $text)
151 68     68   575 {
  68         99  
  68         92  
152 68 100 100     147 return if defined $self->link_address && $self->link_address eq $text;
153              
154 66 100       565 if($self->in_section_title)
155             {
156 22         157 my @row = ( 'section', $self->source_filename, $self->line_number, $text );
157 22         222 $self->callback->(@row);
158             }
159              
160 66 100       927 if($self->in_head1)
161             {
162 19         134 $self->head1(lc $text);
163             }
164             else
165             {
166 47 100       270 return if $self->skip_section_hash->{$self->head1};
167             }
168 65 100       560 if($self->target)
    100          
169             {
170 2 50       15 if($self->target eq 'stopwords')
171             {
172 2         32 foreach my $word (split /\b{wb}/, $text)
173             {
174 10 100       76 next unless $word =~ /\w/;
175 6         17 my @row = ( 'stopword', $self->source_filename, $self->line_number, $word );
176 6         57 $self->callback->(@row);
177             }
178             }
179             }
180             elsif($self->in_verbatim)
181             {
182 3         33 my $base_line = $self->line_number;
183 3         50 my $doc = PPI::Document->new(\$text);
184 3 100       6829 foreach my $comment (($doc->find('PPI::Token::Comment') || [])->@*)
185             {
186 3         1442 $self->line_number($base_line + $comment->location->[0] - 1);
187 3         1217 $self->_add_words("$comment");
188             }
189             }
190             else
191             {
192 60 100       625 $text = lc $text if $self->in_head1;
193 60         414 while($text =~ /^(.*?)\r?\n(.*)$/)
194             {
195 0         0 $text = $2;
196 0         0 $self->_add_words($1);
197 0         0 $self->line_number($self->line_number+1);
198             }
199 60         133 $self->_add_words($text);
200             }
201 65         3797 ();
202             }
203              
204             1;
205              
206             __END__