File Coverage

blib/lib/HTML/Template/Convert/TT.pm
Criterion Covered Total %
statement 90 105 85.7
branch 51 74 68.9
condition 14 19 73.6
subroutine 4 5 80.0
pod 0 3 0.0
total 159 206 77.1


line stmt bran cond sub pod time code
1             package HTML::Template::Convert::TT;
2              
3 6     6   164718 use strict;
  6         15  
  6         235  
4 6     6   31 use warnings;
  6         12  
  6         18551  
5              
6             require Exporter;
7              
8             our @ISA = qw(Exporter);
9             our %EXPORT_TAGS = ( 'all' => [ qw(
10            
11             ) ] );
12              
13             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
14              
15             our @EXPORT = qw(
16             convert
17             print_params
18             );
19              
20             our $VERSION = '0.04';
21              
22              
23             sub parse_opts {
24 35     35 0 55 my $argsref = shift;
25 35         57 my $options = shift;
26 35         68 for (my $x = 0; $x < @{$argsref}; $x += 2) {
  60         167  
27 25 50       37 defined(${$argsref}[($x + 1)]) or croak(
  25         70  
28             "function called with odd number of option parameters - should be of the form option => value");
29 25         36 $options->{lc(${$argsref}[$x])} = ${$argsref}[($x + 1)];
  25         65  
  25         44  
30             }
31 35         70 return $options;
32             }
33             sub convert {
34 35     35 0 505305 my $source;
35 35         74 my $fname = shift;
36 35 50       107 if(ref($fname)) {
37 0         0 $source = $fname;
38             }
39             else {
40 35 50       1369 open FH, $fname or die $!;
41             # read whole file
42 35         121 undef $/;
43 35         780 $source = ;
44             }
45 35         575 my @chunk = split /(?=<)/, $source;
46 35         381 close FH;
47 35         77 my $opts = {};
48 35         161 %$opts = (
49             loop_context_vars => 0,
50             generate_params => 0,
51             );
52 35         135 $opts = parse_opts([@_], $opts);
53 35         63 my $text;
54 35         50 my ($tag, $test);
55 0         0 my @stack;
56 35         204 my %push= (
57             VAR => 0,
58             LOOP => 1,
59             INCLUDE => 0,
60             IF => 1,
61             ELSE => 0,
62             UNLESS => 1
63             );
64 35         49 my %ctx_vars;
65 35         147 @ctx_vars{qw/__first__ __last__ __counter__/} = qw/loop.first loop.last loop.count/;
66 35         99 $ctx_vars{__odd__} = 'loop.count mod 2';
67 35         63 $ctx_vars{__inner__} = '1 - (loop.first + loop.last - loop.first*loop.last)';
68 35         64 my $gen_params = {};
69 35         89 for(@chunk) {
70 456         478 my ($name, $default, %escape);
71 456 100       2010 if (/^<
    100          
72             (?:!--\s*)?
73             (?:
74             (?i:TMPL_
75             (VAR|LOOP|INCLUDE|IF|UNLESS|ELSE) # $1
76             )
77             \s*
78             )
79              
80             (.*?) # parameters
81              
82             (?:--)?>
83             (.*) # $3
84             /sx) {
85 121         324 my ($tag, $rest) = (uc $1, $3);
86 121         237 $_ = $2;
87 121         310 pos = 0;
88 121         631 while (/\G
89             (?i:
90             \b
91             (DEFAULT|NAME|ESCAPE)
92             \s*=\s*
93            
94             )?
95             (?:
96             "([^"]+)"
97             |
98             '([^']+)'
99             |
100             ([^\s]+)
101             )
102             \s*
103             /xgc)
104             {
105 147 100       475 my $val = defined $2? $2: defined $3? $3: $4;
    100          
106 147         8371 chomp $val;
107 147 100 100     595 if (defined $1 and uc $1 ne 'NAME') {
108 30 100       68 if(uc $1 eq 'DEFAULT') {
109 18 50       36 die "DEFAULT parameter has already defined" if defined $default;
110 18         57 $default = $val;
111             }
112             else {
113 12 50       57 die "Invalid ESCAPE parameter" unless
114             $val =~ /0|1|html|url|js|none/i;
115 12         99 $escape{lc $val} = 1;
116             }
117             }
118             else {
119 117 50       213 die "NAME parameter has already defined" if defined $name;
120 117         355 $name = $val;
121             }
122             }
123 121         157 my $case_name = $name;
124             #$name = lc $name;
125 121 100 66     854 $name = $ctx_vars{lc $name} if exists $ctx_vars{lc $name} and $opts->{loop_context_vars};
126 121 50       256 die "Invalid parameter syntax($1)". pos if /\G(.+)/g;
127 121 100       305 push @stack, $tag if $push{$tag};
128 121 100 100     350 if ($tag eq 'VAR') {
    100          
    100          
    100          
129 77 100       176 $text .= "[% DEFAULT $name = '$default' %]"
130             if defined $default;
131              
132 77         131 my $filter = '';
133 77 100 100     405 $filter .= " | html | replace('\\\'', '\'')"
134             if exists $escape{html} or exists $escape{1};
135 77 100       151 $filter .= " | uri" if exists $escape{url};
136 77 100       151 $filter .=
137             " | replace('\\'', '\\\\\\'')".
138             " | replace('\"', '\\\"')".
139             " | replace('\\n', '\\\\n')".
140             " | replace('\\r', '\\\\r')"
141             if exists $escape{js};
142             #$name = 'loop.count' if $opts->{loop_context_vars} and $name eq '__counter__';
143 77 50       153 die "Empty 'NAME' parameter" if $name eq '';
144 77         151 $text .= "[% $name$filter %]";
145 77         199 $gen_params->{$name} = $name;
146             }
147             elsif ($tag eq 'LOOP') {
148 17 50 50     209 $text .= "[% FOREACH $name %]"
149             if $name or
150             die "Empty 'NAME' parameter";
151 17         71 my $sub_params = { 'parent hash' => $gen_params, 'child name' => $name };
152 17         33 $gen_params = $sub_params;
153             }
154             elsif ($tag eq 'INCLUDE') {
155 11 50 50     89 $text .= convert($case_name, %$opts)
156             if $name or die "Empty 'NAME' parameter";
157 11 50       35 %$gen_params = (%$gen_params, %${$opts->{gen_params}}) if ref $opts->{gen_params};
  0         0  
158             }
159             elsif ($tag eq 'IF' or $tag eq 'UNLESS') {
160 12 50       28 die "Empty 'NAME' parameter" if $name eq '';
161 12         31 $text .= "[% $tag $name %]";
162             }
163             else { # ELSE TAG
164 4 50 33     48 die "ELSE tag without IF/UNLESS first"
165             unless
166             @stack and
167             $stack[$#stack] =~ /IF|UNLESS/;
168 4         8 $text .= '[% ELSE %]';
169              
170             }
171 121         274 $text .= $rest;
172             }
173             elsif (/^<(?:!--\s*)?\/TMPL_(LOOP|IF|UNLESS)\s*(?:--)?>(.*)/si) {
174 29         55 $tag = uc $1;
175 29 50       71 die "/TMPL_$tag tag without TMPL_$tag first"
176             unless @stack;
177 29 50       71 die "Unexpected /TMPL_$tag tag "
178             unless $tag = pop @stack;
179 29         63 $text .= "[% END %]$2";
180 29 100       98 if(uc $tag eq 'LOOP') {
181 17         27 my $sub_param = $gen_params;
182 17         47 $gen_params = $sub_param->{'parent hash'};
183 17         32 my $key = $$sub_param{'child name'};
184 17         34 delete $$sub_param{'parent hash'};
185 17         30 delete $$sub_param{'child name'};
186 17         71 $gen_params->{$key} = [ $sub_param ];
187             }
188             }
189             else {
190 306 50       674 die "Syntax error in TMPL_* tag"
191             if /^<(?:!--\s*)\/?TMPL_/i;
192 306         584 $text .= $_;
193             }
194             }
195              
196 35 50       107 ${$opts->{gen_params}} = $gen_params if ref $opts->{gen_params};
  0         0  
197 35         340 return $text;
198             }
199              
200             sub print_params {
201 0     0 0   $\ = "\n";
202 0           my $hash = shift;
203 0           my $outline = shift;
204 0 0         $outline = '' unless defined $outline;
205              
206 0           for(keys %$hash) {
207 0           my $val = $$hash{$_};
208 0 0         if(ref($val) eq 'ARRAY') {
209 0           print "$outline$_ =>";
210 0           print_params($_, $outline."\t") for(@$val);
211             }
212             else {
213 0           print "$outline'$_'";
214             }
215             }
216 0 0         undef $\ unless $outline;
217             }
218              
219             # Preloaded methods go here.
220              
221             1;
222             __END__