File Coverage

blib/lib/Locale/TextDomain/OO/Extract/HTML.pm
Criterion Covered Total %
statement 53 54 98.1
branch 2 4 50.0
condition 2 5 40.0
subroutine 10 10 100.0
pod 3 3 100.0
total 70 76 92.1


line stmt bran cond sub pod time code
1             package Locale::TextDomain::OO::Extract::HTML; ## no critic (TidyCode MainComplexity)
2            
3 2     2   242077 use strict;
  2         5  
  2         110  
4 2     2   12 use warnings;
  2         4  
  2         125  
5 2     2   711 use Moo;
  2         9650  
  2         14  
6 2     2   3745 use MooX::Types::MooseLike::Base qw(ArrayRef Str);
  2         13715  
  2         207  
7 2     2   618 use namespace::autoclean;
  2         22836  
  2         27  
8            
9             our $VERSION = '2.017';
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   8 my $self = shift;
27            
28 3         8 my %filter_of = map { $_ => 1 } @{ $self->filter };
  3         135  
  3         82  
29             my $list_if = sub {
30 9     9   24 my ( $key, @list ) = @_;
31             my $condition
32             = $filter_of{all} && ! $filter_of{"!$key"}
33 9   33     50 || $filter_of{$key};
34 9 50       63 return $condition ? @list : ();
35 3         22 };
36 3         24 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     18 $with_bracket ||= '(?!)';
45            
46 3         263 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 8 my $self = shift;
288            
289 3         64 my $content_ref = $self->content_ref;
290            
291 3         20 ${$content_ref} =~ s{ \r? \n }{\n}xmsg;
  3         84  
292 3         7 ${$content_ref} =~ s{ }{
  3         13  
293 0         0 join q{}, $1 =~ m{ ( \n ) }xmsg
294             }xmsge;
295            
296 3         8 return $self;
297             }
298            
299             sub stack_item_mapping {
300 32     32 1 38 my $self = shift;
301            
302 32         44 my $match = $_->{match};
303 32 50       38 @{$match}
  32         51  
304             or return;
305            
306 32         34 while ( my $string = shift @{$match} ) {
  64         130  
307 32         103 $string =~ s{ \s+ \z }{}xms;
308 32         53 $string =~ s{ \A \s+ }{}xms;
309 32         156 my ( $msgctxt, $msgid )
310             = $string =~ m{ \A (?: ( .*? ) \s* \Q{CONTEXT_SEPARATOR}\E )? \s* ( .* ) \z }xms;
311             $self->add_message({
312 32         526 reference => ( sprintf '%s:%s', $self->filename, $_->{line_number} ),
313             msgctxt => $msgctxt,
314             msgid => $msgid,
315             });
316             }
317            
318 32         73 return;
319             }
320            
321             sub extract {
322 3     3 1 3658 my $self = shift;
323            
324 3         15 $self->start_rule( $self->_filtered_start_rule );
325 3         239 $self->rules($rules);
326 3         146 $self->preprocess;
327 3         19 $self->SUPER::extract;
328 3         6 for ( @{ $self->stack } ) {
  3         45  
329 32         72 $self->stack_item_mapping;
330             }
331            
332 3         26 return $self;
333             }
334            
335             __PACKAGE__->meta->make_immutable;
336            
337             1;
338            
339             __END__