File Coverage

blib/lib/Locale/TextDomain/OO/Extract/HTML.pm
Criterion Covered Total %
statement 52 53 98.1
branch 2 4 50.0
condition 2 5 40.0
subroutine 10 10 100.0
pod 3 3 100.0
total 69 75 92.0


line stmt bran cond sub pod time code
1             package Locale::TextDomain::OO::Extract::HTML; ## no critic (TidyCode MainComplexity)
2            
3 2     2   83672 use strict;
  2         13  
  2         60  
4 2     2   10 use warnings;
  2         5  
  2         79  
5 2     2   350 use Moo;
  2         8062  
  2         11  
6 2     2   1711 use MooX::Types::MooseLike::Base qw(ArrayRef Str);
  2         4965  
  2         127  
7 2     2   318 use namespace::autoclean;
  2         10227  
  2         10  
8            
9             our $VERSION = '2.011';
10            
11             extends qw(
12             Locale::TextDomain::OO::Extract::Base::RegexBasedExtractor
13             );
14             with qw(
15             Locale::TextDomain::OO::Extract::Role::File
16             );
17            
18             has filter => (
19             is => 'rw',
20             isa => ArrayRef[Str],
21             lazy => 1,
22             default => sub {[ 'all' ]},
23             );
24            
25             sub _filtered_start_rule {
26 3     3   6 my $self = shift;
27            
28 3         4 my %filter_of = map { $_ => 1 } @{ $self->filter };
  3         88  
  3         52  
29             my $list_if = sub {
30 9     9   22 my ( $key, @list ) = @_;
31             my $condition
32             = $filter_of{all} && ! $filter_of{"!$key"}
33 9   33     45 || $filter_of{$key};
34 9 50       51 return $condition ? @list : ();
35 3         18 };
36 3         22 my $with_bracket = join "\n| ", (
37             $list_if->('Gettext', qr{ ["] [^"]*? \b __ \b [^"]*? ["] }xms,
38             qr{ ['] [^']*? \b __ \b [^']*? ['] }xms),
39             $list_if->('Gettext::Loc', qr{ ["] [^"]*? \b loc_ \b [^"]*? ["] }xms,
40             qr{ ['] [^']*? \b loc_ \b [^']*? ['] }xms),
41             $list_if->('Maketext', qr{ ["] [^"]*? \b loc \b [^"]*? ["] }xms,
42             qr{ ['] [^']*? \b loc \b [^']*? ['] }xms),
43             );
44 3   50     13 $with_bracket ||= '(?!)';
45            
46 3         173 return qr{
47             [<] [^>]*?
48             \b class \s* [=] \s*
49             (?: $with_bracket )
50             }xms;
51             }
52            
53             ## no critic (ComplexRegexes)
54             my $text_rule = qr{ \s* ( [^<]+ ) }xms;
55            
56             my $rules = [
57             #
58             #
59             #
60             [
61             'begin',
62             sub {
63             my $content_ref = shift;
64            
65             my $regex = qr{
66             [<] input \b
67             ( [^>]* )
68             />
69             }xms;
70             $content_ref
71             or return $regex;
72             my ( $full_match, $inner )
73             = ${$content_ref} =~ m{ \G ( $regex ) }xms
74             or return;
75            
76             my @match = (
77             $inner =~ m{ \b placeholder \s* [=] \s* ["] ( [^"]+ ) ["] }xms,
78             $inner =~ m{ \b placeholder \s* [=] \s* ['] ( [^']+ ) ['] }xms,
79             $inner =~ m{ \b title \s* [=] \s* ["] ( [^"]+ ) ["] }xms,
80             $inner =~ m{ \b title \s* [=] \s* ['] ( [^']+ ) ['] }xms,
81             (
82             $inner =~ m{ \b type \s* [=] \s* ["] (?: submit | reset | button ) ["] }xms
83             || $inner =~ m{ \b type \s* [=] \s* ['] (?: submit | reset | button ) ['] }xms
84             )
85             ? (
86             $inner =~ m{ \b value \s* [=] \s* ["] ( [^"]+ ) ["] }xms
87             ? $1
88             : $inner =~ m{ \b value \s* [=] \s* ['] ( [^']+ ) ['] }xms
89             ? $1
90             : ()
91             )
92             : (),
93             );
94             @match
95             and return +( $full_match, @match );
96            
97             return;
98             },
99             'end',
100             ],
101             'or',
102             #
107             [
108             'begin',
109             sub {
110             my $content_ref = shift;
111            
112             my $regex = qr{
113             [<] textarea \b
114             ( [^>]* )
115             [>]
116             }xms;
117             $content_ref
118             or return $regex;
119             my ( $full_match, $inner )
120             = ${$content_ref} =~ m{ \G ( $regex ) }xms
121             or return;
122             $inner =~ m{ \b placeholder \s* [=] \s* ["] ( [^"]+ ) ["] }xms
123             and return +( $full_match, $1 );
124             $inner =~ m{ \b placeholder \s* [=] \s* ['] ( [^']+ ) ['] }xms
125             and return +( $full_match, $1 );
126            
127             return;
128             },
129             'end',
130             ],
131             'or',
132             # text to extract
133             [
134             'begin',
135             sub {
136             my $content_ref = shift;
137            
138             my $regex = qr{
139             [<] img \b
140             ( [^>]* )
141             />
142             }xms;
143             $content_ref
144             or return $regex;
145             my ( $full_match, $inner )
146             = ${$content_ref} =~ m{ \G ( $regex ) }xms
147             or return;
148            
149             my @match = (
150             $inner =~ m{ \b alt \s* [=] \s* ["] ( [^"]+ ) ["] }xms,
151             $inner =~ m{ \b alt \s* [=] \s* ['] ( [^']+ ) ['] }xms,
152             );
153             @match
154             and return +( $full_match, @match );
155            
156             return;
157             },
158             'end',
159             ],
160             'or',
161             # text_to_extract
162             [
163             'begin',
164             sub {
165             my $content_ref = shift;
166            
167             my $regex = qr{
168             [<] [a] \b
169             ( [^>]* )
170             [>]
171             ( [^<]* )
172             }xms;
173             $content_ref
174             or return $regex;
175             my ( $full_match, $inner, $text )
176             = ${$content_ref} =~ m{ \G ( $regex ) }xms
177             or return;
178            
179             my @match = (
180             $inner =~ m{ \b title \s* [=] \s* ["] ( [^"]+ ) ["] }xms,
181             $inner =~ m{ \b title \s* [=] \s* ['] ( [^']+ ) ['] }xms,
182             );
183             @match
184             and return +( $full_match, $text, @match );
185            
186             return;
187             },
188             'end',
189             ],
190             'or',
191             #
192             [
193             'begin',
194             sub {
195             my $content_ref = shift;
196            
197             my $regex = qr{
198             [<] button \b
199             ( [^>]* )
200             [>]
201             ( [^<]* )
202             }xms;
203             $content_ref
204             or return $regex;
205             my ( $full_match, $inner, $text )
206             = ${$content_ref} =~ m{ \G ( $regex ) }xms
207             or return;
208            
209             my @match = (
210             $inner =~ m{ \b title \s* [=] \s* ["] ( [^"]+ ) ["] }xms,
211             $inner =~ m{ \b title \s* [=] \s* ['] ( [^']+ ) ['] }xms,
212             );
213             @match
214             and return +( $full_match, $text, @match );
215            
216             return;
217             },
218             'end',
219             ],
220             'or',
221             # < class="... loc_|__|loc ..." ... title="text to extract" ... >text_to_extract<
222             [
223             'begin',
224             sub {
225             my $content_ref = shift;
226            
227             my $regex = qr{
228             [<] \w+ \b
229             ( [^>]* )
230             [>]
231             ( [^<]* )
232             }xms;
233             $content_ref
234             or return $regex;
235             my ( $full_match, $inner, $text )
236             = ${$content_ref} =~ m{ \G ( $regex ) }xms
237             or return;
238            
239            
240             my @match = (
241             $inner =~ m{ \b title \s* [=] \s* ["] ( [^"]+ ) ["] }xms,
242             $inner =~ m{ \b title \s* [=] \s* ['] ( [^']+ ) ['] }xms,
243             $text,
244             );
245             @match
246             and return +( $full_match, @match );
247            
248             return;
249             },
250             'end',
251             ],
252             'or',
253             # <... class="... loc_|__|loc ..." ... >text to extract<
254             [
255             'begin',
256             qr{
257             [<] [^>]*?
258             \b class \s* [=] \s* ["] [^"]*?
259             \b (?: loc_ | __ | loc ) \b
260             [^"]*? ["]
261             [^>]* [>]
262             }xms,
263             'and',
264             $text_rule,
265             'end',
266             ],
267             'or',
268             # <... class='... loc_|__|loc ...' ... >text to extract<
269             [
270             'begin',
271             qr{
272             [<] [^>]*?
273             \b class \s* [=] \s* ['] [^']*?
274             \b (?: loc_ | __ | loc ) \b
275             [^']*? [']
276             [^>]* [>]
277             }xms,
278             'and',
279             $text_rule,
280             'end',
281             ],
282             ];
283             ## use critic (ComplexRegexes)
284            
285             # remove code between
286             sub preprocess {
287 3     3 1 7 my $self = shift;
288            
289 3         44 my $content_ref = $self->content_ref;
290            
291 3         15 ${$content_ref} =~ s{ \r? \n }{\n}xmsg;
  3         64  
292 3         8 ${$content_ref} =~ s{ }{
  3         9  
293 0         0 join q{}, $1 =~ m{ ( \n ) }xmsg
294             }xmsge;
295            
296 3         6 return $self;
297             }
298            
299             sub stack_item_mapping {
300 30     30 1 44 my $self = shift;
301            
302 30         44 my $match = $_->{match};
303 30 50       41 @{$match}
  30         56  
304             or return;
305            
306 30         42 while ( my $string = shift @{$match} ) {
  60         133  
307 30         96 $string =~ s{ \s+ \z }{}xms;
308 30         161 my ( $msgctxt, $msgid )
309             = $string =~ m{ \A (?: ( .*? ) \s* \Q{CONTEXT_SEPARATOR}\E )? \s* ( .* ) \z }xms;
310             $self->add_message({
311 30         526 reference => ( sprintf '%s:%s', $self->filename, $_->{line_number} ),
312             msgctxt => $msgctxt,
313             msgid => $msgid,
314             });
315             }
316            
317 30         83 return;
318             }
319            
320             sub extract {
321 3     3 1 2300 my $self = shift;
322            
323 3         12 $self->start_rule( $self->_filtered_start_rule );
324 3         161 $self->rules($rules);
325 3         109 $self->preprocess;
326 3         14 $self->SUPER::extract;
327 3         6 for ( @{ $self->stack } ) {
  3         40  
328 30         71 $self->stack_item_mapping;
329             }
330            
331 3         23 return $self;
332             }
333            
334             __PACKAGE__->meta->make_immutable;
335            
336             1;
337            
338             __END__