File Coverage

blib/lib/Locale/TextDomain/OO/Extract/JavaScript.pm
Criterion Covered Total %
statement 76 76 100.0
branch 23 26 88.4
condition 2 5 40.0
subroutine 11 11 100.0
pod 4 4 100.0
total 116 122 95.0


line stmt bran cond sub pod time code
1             package Locale::TextDomain::OO::Extract::JavaScript; ## no critic (TidyCode)
2            
3 2     2   94252 use strict;
  2         18  
  2         80  
4 2     2   16 use warnings;
  2         6  
  2         78  
5 2     2   371 use Moo;
  2         8886  
  2         13  
6 2     2   1808 use MooX::Types::MooseLike::Base qw(ArrayRef Str);
  2         4434  
  2         160  
7 2     2   271 use namespace::autoclean;
  2         8982  
  2         14  
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   8 my $self = shift;
27            
28 3         6 my %filter_of = map { $_ => 1 } @{ $self->filter };
  3         89  
  3         47  
29             my $list_if = sub {
30 18     18   39 my ( $key, @list ) = @_;
31             my $condition
32             = $filter_of{all} && ! $filter_of{"!$key"}
33 18   33     71 || ! $filter_of{'!all'} && $filter_of{$key};
34 18 50       55 return $condition ? @list : ();
35 3         17 };
36 3         11 my $with_bracket = join "\n| ", (
37             $list_if->('Gettext', '__? n? p? x?',
38             'n? p? gettext'),
39             $list_if->('Gettext::DomainAndCategory', '__? d? c? n? p? x?',
40             'd? c? n? p? gettext'),
41             $list_if->('Gettext::Loc', 'loc_ n? p? x?'),
42             $list_if->('Gettext::Loc::DomainAndCategory', 'loc_ d? c? n? p? x?'),
43             $list_if->('BabelFish::Loc', 'loc_b p?'),
44             $list_if->('BabelFish::Loc::DomainAndCategory', 'loc_b d? c? p?'),
45             );
46 3   50     10 $with_bracket ||= '(?!)';
47            
48 3         123 return qr{
49             \b N?
50             (?: $with_bracket ) \s* [(]
51             }xms;
52             }
53            
54             my $category_rule
55             = my $context_rule
56             = my $domain_rule
57             = my $plural_rule
58             = my $singular_rule
59             = my $text_rule
60             = [
61             [
62             # "text with 0 .. n escaped chars"
63             qr{
64             \s* ["]
65             (
66             [^\\"]* # normal text
67             (?: \\ . [^\\"]* )* # maybe followed by escaped char and normal text
68             )
69             ["]
70             }xms,
71             ],
72             'or',
73             [
74             # 'text with 0 .. n escaped chars'
75             qr{
76             \s* [']
77             (
78             [^\\']* # normal text
79             (?: \\ . [^\\']* )* # maybe followed by escaped char and normal text
80             )
81             [']
82             }xms,
83             ],
84             ];
85             my $comma_rule = qr{ \s* [,] }xms;
86             my $count_rule = qr{ \s* ( [^,)]+ ) }xms;
87             my $close_rule = qr{ \s* [,]? \s* ( [^)]* ) [)] }xms;
88            
89             my $rules = [
90             # loc_, _, __
91             [
92             'begin',
93             qr{ \b N? (?: loc_ | __? ) ( x? ) \s* [(] }xms,
94             'and',
95             $text_rule,
96             'and',
97             $close_rule,
98             'end',
99             ],
100             'or',
101             [
102             'begin',
103             qr{ \b N? (?: loc_ | __? ) ( n x? ) \s* [(] }xms,
104             'and',
105             $singular_rule,
106             'and',
107             $comma_rule,
108             'and',
109             $plural_rule,
110             'and',
111             $comma_rule,
112             'and',
113             $count_rule,
114             'and',
115             $close_rule,
116             'end',
117             ],
118             'or',
119             [
120             'begin',
121             qr{ \b N? (?: loc_ | __? ) ( p x? ) \s* [(] }xms,
122             'and',
123             $context_rule,
124             'and',
125             $comma_rule,
126             'and',
127             $text_rule,
128             'and',
129             $close_rule,
130             'end',
131             ],
132             'or',
133             [
134             'begin',
135             qr{ \b N? (?: loc_ | __? ) ( np x? ) \s* [(] }xms,
136             'and',
137             $context_rule,
138             'and',
139             $comma_rule,
140             'and',
141             $singular_rule,
142             'and',
143             $comma_rule,
144             'and',
145             $plural_rule,
146             'and',
147             $comma_rule,
148             'and',
149             $count_rule,
150             'and',
151             $close_rule,
152             'end',
153             ],
154            
155             # loc_d, _d, __d
156             'or',
157             [
158             'begin',
159             qr{ \b N? (?: loc_ | __? ) ( d x? ) \s* [(] }xms,
160             'and',
161             $domain_rule,
162             'and',
163             $comma_rule,
164             'and',
165             $text_rule,
166             'and',
167             $close_rule,
168             'end',
169             ],
170             'or',
171             [
172             'begin',
173             qr{ \b N? (?: loc_ | __? ) ( dn x? ) \s* [(] }xms,
174             'and',
175             $domain_rule,
176             'and',
177             $comma_rule,
178             'and',
179             $singular_rule,
180             'and',
181             $comma_rule,
182             'and',
183             $plural_rule,
184             'and',
185             $comma_rule,
186             'and',
187             $count_rule,
188             'and',
189             $close_rule,
190             'end',
191             ],
192             'or',
193             [
194             'begin',
195             qr{ \b N? (?: loc_ | __? ) ( dp x? ) \s* [(] }xms,
196             'and',
197             $domain_rule,
198             'and',
199             $comma_rule,
200             'and',
201             $context_rule,
202             'and',
203             $comma_rule,
204             'and',
205             $text_rule,
206             'and',
207             $close_rule,
208             'end',
209             ],
210             'or',
211             [
212             'begin',
213             qr{ \b N? (?: loc_ | __? ) ( dnp x? ) \s* [(] }xms,
214             'and',
215             $domain_rule,
216             'and',
217             $comma_rule,
218             'and',
219             $context_rule,
220             'and',
221             $comma_rule,
222             'and',
223             $singular_rule,
224             'and',
225             $comma_rule,
226             'and',
227             $plural_rule,
228             'and',
229             $comma_rule,
230             'and',
231             $count_rule,
232             'and',
233             $close_rule,
234             'end',
235             ],
236            
237             # loc_c, _c, __c
238             'or',
239             [
240             'begin',
241             qr{ \b N? (?: loc_ | __? ) ( c x? ) \s* [(] }xms,
242             'and',
243             $text_rule,
244             'and',
245             $comma_rule,
246             'and',
247             $category_rule,
248             'and',
249             $close_rule,
250             'end',
251             ],
252             'or',
253             [
254             'begin',
255             qr{ \b N? (?: loc_ | __? ) ( cn x? ) \s* [(] }xms,
256             'and',
257             $singular_rule,
258             'and',
259             $comma_rule,
260             'and',
261             $plural_rule,
262             'and',
263             $comma_rule,
264             'and',
265             $count_rule,
266             'and',
267             $comma_rule,
268             'and',
269             $category_rule,
270             'and',
271             $close_rule,
272             'end',
273             ],
274             'or',
275             [
276             'begin',
277             qr{ \b N? (?: loc_ | __? ) ( cp x? ) \s* [(] }xms,
278             'and',
279             $context_rule,
280             'and',
281             $comma_rule,
282             'and',
283             $text_rule,
284             'and',
285             $comma_rule,
286             'and',
287             $category_rule,
288             'and',
289             $close_rule,
290             'end',
291             ],
292             'or',
293             [
294             'begin',
295             qr{ \b N? (?: loc_ | __? ) ( cnp x? ) \s* [(] }xms,
296             'and',
297             $context_rule,
298             'and',
299             $comma_rule,
300             'and',
301             $singular_rule,
302             'and',
303             $comma_rule,
304             'and',
305             $plural_rule,
306             'and',
307             $comma_rule,
308             'and',
309             $count_rule,
310             'and',
311             $comma_rule,
312             'and',
313             $category_rule,
314             'and',
315             $close_rule,
316             'end',
317             ],
318            
319             # loc_dc, _dc, __dc
320             'or',
321             [
322             'begin',
323             qr{ \b N? (?: loc_ | __? ) ( dc x? ) \s* [(] }xms,
324             'and',
325             $domain_rule,
326             'and',
327             $comma_rule,
328             'and',
329             $text_rule,
330             'and',
331             $comma_rule,
332             'and',
333             $category_rule,
334             'and',
335             $close_rule,
336             'end',
337             ],
338             'or',
339             [
340             'begin',
341             qr{ \b N? (?: loc_ | __? ) ( dcn x? ) \s* [(] }xms,
342             'and',
343             $domain_rule,
344             'and',
345             $comma_rule,
346             'and',
347             $singular_rule,
348             'and',
349             $comma_rule,
350             'and',
351             $plural_rule,
352             'and',
353             $comma_rule,
354             'and',
355             $count_rule,
356             'and',
357             $comma_rule,
358             'and',
359             $category_rule,
360             'and',
361             $close_rule,
362             'end',
363             ],
364             'or',
365             [
366             'begin',
367             qr{ \b N? (?: loc_ | __? ) ( dcp x? ) \s* [(] }xms,
368             'and',
369             $domain_rule,
370             'and',
371             $comma_rule,
372             'and',
373             $context_rule,
374             'and',
375             $comma_rule,
376             'and',
377             $text_rule,
378             'and',
379             $comma_rule,
380             'and',
381             $category_rule,
382             'and',
383             $close_rule,
384             'end',
385             ],
386             'or',
387             [
388             'begin',
389             qr{ \b N? (?: loc_ | __? ) ( dcnp x? ) \s* [(] }xms,
390             'and',
391             $domain_rule,
392             'and',
393             $comma_rule,
394             'and',
395             $context_rule,
396             'and',
397             $comma_rule,
398             'and',
399             $singular_rule,
400             'and',
401             $comma_rule,
402             'and',
403             $plural_rule,
404             'and',
405             $comma_rule,
406             'and',
407             $count_rule,
408             'and',
409             $comma_rule,
410             'and',
411             $category_rule,
412             'and',
413             $close_rule,
414             'end',
415             ],
416            
417             # loc_b... (BabelFish)
418             'or',
419             [
420             'begin',
421             qr{ \b N? loc_b () \s* [(] }xms,
422             'and',
423             $text_rule,
424             'and',
425             $close_rule,
426             'end',
427             ],
428             'or',
429             # babelfish loc_bp
430             [
431             'begin',
432             qr{ \b N? loc_b ( p ) \s* [(] }xms,
433             'and',
434             $context_rule,
435             'and',
436             $comma_rule,
437             'and',
438             $text_rule,
439             'and',
440             $close_rule,
441             'end',
442             ],
443            
444             # gettext
445             'or',
446             [
447             'begin',
448             qr{ \b N? () gettext \s* [(] }xms,
449             'and',
450             $text_rule,
451             'and',
452             $close_rule,
453             'end',
454             ],
455             'or',
456             [
457             'begin',
458             qr{ \b N? ( n ) gettext \s* [(] }xms,
459             'and',
460             $singular_rule,
461             'and',
462             $comma_rule,
463             'and',
464             $plural_rule,
465             'and',
466             $comma_rule,
467             'and',
468             $count_rule,
469             'and',
470             $close_rule,
471             'end',
472             ],
473             'or',
474             [
475             'begin',
476             qr{ \b N? ( p ) gettext \s* [(] }xms,
477             'and',
478             $context_rule,
479             'and',
480             $comma_rule,
481             'and',
482             $text_rule,
483             'and',
484             $close_rule,
485             'end',
486             ],
487             'or',
488             [
489             'begin',
490             qr{ \b N? ( np ) gettext \s* [(] }xms,
491             'and',
492             $context_rule,
493             'and',
494             $comma_rule,
495             'and',
496             $singular_rule,
497             'and',
498             $comma_rule,
499             'and',
500             $plural_rule,
501             'and',
502             $comma_rule,
503             'and',
504             $count_rule,
505             'and',
506             $close_rule,
507             'end',
508             ],
509            
510             # dgettext
511             'or',
512             [
513             'begin',
514             qr{ \b N? ( d ) gettext \s* [(] }xms,
515             'and',
516             $domain_rule,
517             'and',
518             $comma_rule,
519             'and',
520             $text_rule,
521             'and',
522             $close_rule,
523             'end',
524             ],
525             'or',
526             [
527             'begin',
528             qr{ \b N? ( dn ) gettext \s* [(] }xms,
529             'and',
530             $domain_rule,
531             'and',
532             $comma_rule,
533             'and',
534             $singular_rule,
535             'and',
536             $comma_rule,
537             'and',
538             $plural_rule,
539             'and',
540             $comma_rule,
541             'and',
542             $count_rule,
543             'and',
544             $close_rule,
545             'end',
546             ],
547             'or',
548             [
549             'begin',
550             qr{ \b N? ( dp ) gettext \s* [(] }xms,
551             'and',
552             $domain_rule,
553             'and',
554             $comma_rule,
555             'and',
556             $context_rule,
557             'and',
558             $comma_rule,
559             'and',
560             $text_rule,
561             'and',
562             $close_rule,
563             'end',
564             ],
565             'or',
566             [
567             'begin',
568             qr{ \b N? ( dnp ) gettext \s* [(] }xms,
569             'and',
570             $domain_rule,
571             'and',
572             $comma_rule,
573             'and',
574             $context_rule,
575             'and',
576             $comma_rule,
577             'and',
578             $singular_rule,
579             'and',
580             $comma_rule,
581             'and',
582             $plural_rule,
583             'and',
584             $comma_rule,
585             'and',
586             $count_rule,
587             'and',
588             $close_rule,
589             'end',
590             ],
591            
592             # cgettext
593             'or',
594             [
595             'begin',
596             qr{ \b N? ( c ) gettext \s* [(] }xms,
597             'and',
598             $text_rule,
599             'and',
600             $comma_rule,
601             'and',
602             $category_rule,
603             'and',
604             $close_rule,
605             'end',
606             ],
607             'or',
608             [
609             'begin',
610             qr{ \b N? ( cn ) gettext \s* [(] }xms,
611             'and',
612             $singular_rule,
613             'and',
614             $comma_rule,
615             'and',
616             $plural_rule,
617             'and',
618             $comma_rule,
619             'and',
620             $count_rule,
621             'and',
622             $comma_rule,
623             'and',
624             $category_rule,
625             'and',
626             $close_rule,
627             'end',
628             ],
629             'or',
630             [
631             'begin',
632             qr{ \b N? ( cp ) gettext \s* [(] }xms,
633             'and',
634             $context_rule,
635             'and',
636             $comma_rule,
637             'and',
638             $text_rule,
639             'and',
640             $comma_rule,
641             'and',
642             $category_rule,
643             'and',
644             $close_rule,
645             'end',
646             ],
647             'or',
648             [
649             'begin',
650             qr{ \b N? ( cnp ) gettext \s* [(] }xms,
651             'and',
652             $context_rule,
653             'and',
654             $comma_rule,
655             'and',
656             $singular_rule,
657             'and',
658             $comma_rule,
659             'and',
660             $plural_rule,
661             'and',
662             $comma_rule,
663             'and',
664             $count_rule,
665             'and',
666             $comma_rule,
667             'and',
668             $category_rule,
669             'and',
670             $close_rule,
671             'end',
672             ],
673            
674             # dcgettext
675             'or',
676             [
677             'begin',
678             qr{ \b N? ( dc ) gettext \s* [(] }xms,
679             'and',
680             $domain_rule,
681             'and',
682             $comma_rule,
683             'and',
684             $text_rule,
685             'and',
686             $comma_rule,
687             'and',
688             $category_rule,
689             'and',
690             $close_rule,
691             'end',
692             ],
693             'or',
694             [
695             'begin',
696             qr{ \b N? ( dcn ) gettext \s* [(] }xms,
697             'and',
698             $domain_rule,
699             'and',
700             $comma_rule,
701             'and',
702             $singular_rule,
703             'and',
704             $comma_rule,
705             'and',
706             $plural_rule,
707             'and',
708             $comma_rule,
709             'and',
710             $count_rule,
711             'and',
712             $comma_rule,
713             'and',
714             $category_rule,
715             'and',
716             $close_rule,
717             'end',
718             ],
719             'or',
720             [
721             'begin',
722             qr{ \b N? ( dcp ) gettext \s* [(] }xms,
723             'and',
724             $domain_rule,
725             'and',
726             $comma_rule,
727             'and',
728             $context_rule,
729             'and',
730             $comma_rule,
731             'and',
732             $text_rule,
733             'and',
734             $comma_rule,
735             'and',
736             $category_rule,
737             'and',
738             $close_rule,
739             'end',
740             ],
741             'or',
742             [
743             'begin',
744             qr{ \b N? ( dcnp ) gettext \s* [(] }xms,
745             'and',
746             $domain_rule,
747             'and',
748             $comma_rule,
749             'and',
750             $context_rule,
751             'and',
752             $comma_rule,
753             'and',
754             $singular_rule,
755             'and',
756             $comma_rule,
757             'and',
758             $plural_rule,
759             'and',
760             $comma_rule,
761             'and',
762             $count_rule,
763             'and',
764             $comma_rule,
765             'and',
766             $category_rule,
767             'and',
768             $close_rule,
769             'end',
770             ],
771             ];
772            
773             # remove comment code
774             sub preprocess {
775 4     4 1 484 my $self = shift;
776            
777 4         55 my $content_ref = $self->content_ref;
778            
779 4         22 ${$content_ref} =~ s{ // [^\n]* $ }{}xmsg;
  4         93  
780 4         8 ${$content_ref} =~ s{
  4         76  
781             / [*] ( .*? ) [*] /
782             }
783 3         29 {
784             join q{}, $1 =~ m{ ( \n ) }xmsg;
785             }xmsge;
786 4         11
787             return $self;
788             }
789            
790 547     547 1 1556 sub interpolate_escape_sequence {
791             my ( undef, $string ) = @_;
792            
793 547 50       984 # nothing to interpolate
794             defined $string
795             or return $string;
796 547         1296
797             my %char_of = (
798             b => "\b",
799             f => "\f",
800             n => "\n",
801             r => "\r",
802             t => "\t",
803             );
804 547         880 ## no critic (ComplexRegexes)
805             $string =~ s{
806             \\
807             (?:
808             ( [bfnrt] ) # Backspace
809             # Form feed
810             # New line
811             # Carriage return
812             # Horizontal tab
813             | u ( [\dA-Fa-f]{4} ) # Unicode sequence (4 hex digits: dddd)
814             | x ( [\dA-Fa-f]{2} ) # Hexadecimal sequence (2 digits: dd)
815             | ( [0-3][0-7]{2} ) # Octal sequence (3 digits: ddd)
816             | (.) # Backslash itself
817             # Single quotation mark
818             # Double quotation mark
819             # anything else that needs no escape
820             )
821 27 100       119 }{
    100          
    100          
    100          
822             $1 ? $char_of{$1}
823             : $2 ? chr hex $2
824             : $3 ? chr hex $3
825             : $4 ? chr oct $4
826             : $5
827             }xmsge;
828             ## use critic (ComplexRegexes)
829 547         2182
830             return $string;
831             }
832            
833 189     189 1 270 sub stack_item_mapping {
834             my $self = shift;
835 189         304
836 189         239 my $match = $_->{match};
  189         311  
837 189 50       265 my $extra_parameter = shift @{$match};
  189         343  
838             @{$match}
839             or return;
840 189         265
841             my $count;
842             $self->add_message({
843             reference => ( sprintf '%s:%s', $self->filename, $_->{line_number} ),
844 88         808 domain => $extra_parameter =~ m{ d }xms
845             ? scalar $self->interpolate_escape_sequence( shift @{$match} )
846             : $self->domain,
847 90         1268 msgctxt => $extra_parameter =~ m{ p }xms
848             ? scalar $self->interpolate_escape_sequence( shift @{$match} )
849 189         1702 : undef,
850             msgid => scalar $self->interpolate_escape_sequence( shift @{$match} ),
851             msgid_plural => $extra_parameter =~ m{ n }xms
852 91         128 ? do {
  91         173  
853 91         139 my $plural = $self->interpolate_escape_sequence( shift @{$match} );
  91         148  
854 91         854 $count = shift @{$match};
855             $plural;
856             }
857             : undef,
858 88         159 category => $extra_parameter =~ m{ c }xms
859             ? scalar $self->interpolate_escape_sequence( shift @{$match} )
860 189 100       3067 : $self->category,
    100          
    100          
    100          
861 189         601 automatic => do {
  189         330  
862             my $placeholders = shift @{$match};
863 189         341 my $string = join ', ', map { ## no critic (MutatingListFunctions)
864 378 100       618 defined $_
865 280         522 ? do {
866 280         501 s{ \s+ }{ }xmsg;
867 280 100       747 s{ \s+ \z }{}xms;
868             length $_ ? $_ : ();
869             }
870             : ();
871 189         301 } ( $count, $placeholders );
872 189         1041 $string =~ s{ \A ( .{70} ) .+ \z }{$1 ...}xms;
873             $string;
874             },
875             });
876 189         612
877             return;
878             }
879            
880 3     3 1 3388 sub extract {
881             my $self = shift;
882 3         14
883 3         174 $self->start_rule( $self->_filtered_start_rule );
884 3         123 $self->rules($rules);
885 3         16 $self->preprocess;
886 3         8 $self->SUPER::extract;
  3         45  
887 189         373 for ( @{ $self->stack } ) {
888             $self->stack_item_mapping;
889             }
890 3         31
891             return $self;
892             }
893            
894             __PACKAGE__->meta->make_immutable;
895            
896             1;
897            
898             __END__