File Coverage

blib/lib/Tags/Output/Raw.pm
Criterion Covered Total %
statement 179 180 99.4
branch 51 52 98.0
condition 17 20 85.0
subroutine 24 24 100.0
pod 2 2 100.0
total 273 278 98.2


line stmt bran cond sub pod time code
1             package Tags::Output::Raw;
2              
3 22     22   165967 use base qw(Tags::Output);
  22         159  
  22         8940  
4 22     22   135 use strict;
  22         42  
  22         402  
5 22     22   98 use warnings;
  22         45  
  22         486  
6              
7 22     22   122 use Error::Pure qw(err);
  22         39  
  22         771  
8 22     22   164 use List::MoreUtils qw(none);
  22         37  
  22         165  
9 22     22   13828 use Readonly;
  22         41  
  22         932  
10 22     22   8672 use Tags::Utils::Preserve;
  22         48  
  22         657  
11 22     22   7471 use Tags::Utils qw(encode_attr_entities encode_char_entities);
  22         51  
  22         413  
12              
13             # Constants.
14             Readonly::Scalar my $EMPTY_STR => q{};
15             Readonly::Scalar my $LAST_INDEX => -1;
16             Readonly::Scalar my $SPACE => q{ };
17              
18             our $VERSION = 0.12;
19              
20             # Finalize Tags output.
21             sub finalize {
22 5     5 1 1243 my $self = shift;
23              
24             # XML mode.
25 5 100       23 if ($self->{'xml'}) {
26              
27             # Add ending of all opened tags.
28 1         2 while (@{$self->{'printed_tags'}}) {
  2         7  
29 1         5 $self->put(['e', $self->{'printed_tags'}->[0]]);
30             }
31              
32             # SGML mode.
33             } else {
34              
35             # Flush tmp code.
36 4 100       8 if (scalar @{$self->{'tmp_code'}}) {
  4         20  
37 3         10 $self->_flush_tmp('>');
38             }
39 4         12 $self->{'printed_tags'} = [];
40             }
41 5         11 return;
42             }
43              
44             # Resets internal variables.
45             sub reset {
46 76     76 1 25163 my $self = shift;
47              
48             # Comment flag.
49 76         117 $self->{'comment_flag'} = 0;
50              
51             # Flush code.
52 76         248 $self->_reset_flush;
53              
54             # Tmp code.
55 76         143 $self->{'tmp_code'} = [];
56 76         117 $self->{'tmp_comment_code'} = [];
57              
58             # Printed tags.
59 76         126 $self->{'printed_tags'} = [];
60              
61             # Preserved object.
62             $self->{'preserve_obj'} = Tags::Utils::Preserve->new(
63 76         316 'preserved' => $self->{'preserved'},
64             );
65              
66 76         235 return;
67             }
68              
69             # Check parameters to rigth values.
70             sub _check_params {
71 50     50   72 my $self = shift;
72              
73             # Check params from SUPER.
74 50         170 $self->SUPER::_check_params();
75              
76             # Check 'attr_delimeter'.
77 48 100 100     145 if ($self->{'attr_delimeter'} ne q{"}
78             && $self->{'attr_delimeter'} ne q{'}) {
79              
80 1         4 err "Bad attribute delimeter '$self->{'attr_delimeter'}'.";
81             }
82              
83 47         67 return;
84             }
85              
86             # Default parameters.
87             sub _default_parameters {
88 52     52   84 my $self = shift;
89              
90             # Default parameters from SUPER.
91 52         224 $self->SUPER::_default_parameters();
92              
93             # Attribute callback.
94 52         108 $self->{'attr_callback'} = \&encode_attr_entities;
95              
96             # Attribute delimeter.
97 52         92 $self->{'attr_delimeter'} = q{"};
98              
99             # CDATA callback.
100 52         80 $self->{'cdata_callback'} = undef;
101              
102             # Data callback.
103 52         92 $self->{'data_callback'} = \&encode_char_entities;
104              
105             # No data callback.
106 52         110 $self->{'no_data_callback'} = ['script', 'style'];
107              
108             # No simple tags.
109 52         99 $self->{'no_simple'} = [];
110              
111             # Preserved tags.
112 52         88 $self->{'preserved'} = [];
113              
114             # Raw data callback.
115 52         117 $self->{'raw_callback'} = undef;
116              
117             # XML output.
118 52         85 $self->{'xml'} = 0;
119              
120 52         80 return;
121             }
122              
123             # Flush $self->{'tmp_code'}.
124             sub _flush_tmp {
125 83     83   124 my ($self, $string) = @_;
126              
127             # Added string.
128 83         100 push @{$self->{'tmp_code'}}, $string;
  83         132  
129              
130             # Detect preserve mode.
131 83         234 my ($pre, $pre_pre) = $self->{'preserve_obj'}->get;
132 83 100 66     201 if ($pre && ! $pre_pre) {
133 4         4 push @{$self->{'tmp_code'}}, "\n";
  4         6  
134             }
135              
136             # Flush comment code before tag.
137 83 100 100     232 if ($self->{'comment_flag'} == 0
138 81         234 && scalar @{$self->{'tmp_comment_code'}}) {
139              
140             $self->{'flush_code'} .= join $EMPTY_STR,
141 3         4 @{$self->{'tmp_comment_code'}},
142 3         4 @{$self->{'tmp_code'}};
  3         7  
143              
144             # After tag.
145             } else {
146             $self->{'flush_code'} .= join $EMPTY_STR,
147 80         109 @{$self->{'tmp_code'}},
148 80         132 @{$self->{'tmp_comment_code'}};
  80         191  
149             }
150              
151             # Resets tmp_codes.
152 83         136 $self->{'tmp_code'} = [];
153 83         117 $self->{'tmp_comment_code'} = [];
154              
155 83         129 return;
156             }
157              
158             # Attributes.
159             sub _put_attribute {
160 29     29   48 my ($self, $attr, $value) = @_;
161              
162             # Check to 'tmp_code'.
163 29 100       34 if (! @{$self->{'tmp_code'}}) {
  29         61  
164 1         4 err 'Bad tag type \'a\'.';
165             }
166              
167             # Check to pairs in XML mode.
168 28 50 66     83 if ($self->{'xml'} && ! defined $value) {
169 0         0 err "In XML mode must be a attribute '$attr' value.";
170             }
171              
172             # Process data callback.
173 28         51 my @attr = ($attr);
174 28 100       42 if (defined $value) {
175 27         40 push @attr, $value;
176             }
177 28         68 $self->_process_callback(\@attr, 'attr_callback');
178              
179             # Process attribute.
180 28         43 my $full_attr = $attr[0];
181 28 100       53 if (defined $attr[1]) {
182             $full_attr .= q{=}.$self->{'attr_delimeter'}.
183 27         66 $attr[1].$self->{'attr_delimeter'};
184             }
185 28         34 push @{$self->{'tmp_code'}}, $SPACE, $full_attr;
  28         51  
186              
187             # Reset comment flag.
188 28         39 $self->{'comment_flag'} = 0;
189              
190 28         64 return;
191             }
192              
193             # Begin of tag.
194             sub _put_begin_of_tag {
195 84     84   146 my ($self, $tag) = @_;
196              
197             # Flush tmp code.
198 84 100       540 if (scalar @{$self->{'tmp_code'}}) {
  84         215  
199 15         35 $self->_flush_tmp('>');
200             }
201              
202             # TODO Add checking of XML element name.
203             # if ($self->{'xml'} && _check(element_name)) {
204             # err 'This is not XML format.';
205             # }
206              
207             # Push begin of tag to tmp code.
208 84         113 push @{$self->{'tmp_code'}}, "<$tag";
  84         219  
209              
210             # Added tag to printed tags.
211 84         121 unshift @{$self->{'printed_tags'}}, $tag;
  84         167  
212              
213 84         224 $self->{'preserve_obj'}->begin($tag);
214              
215 84         161 return;
216             }
217              
218             # CData.
219             sub _put_cdata {
220 4     4   11 my ($self, @cdata) = @_;
221              
222             # Flush tmp code.
223 4 100       5 if (scalar @{$self->{'tmp_code'}}) {
  4         12  
224 3         8 $self->_flush_tmp('>');
225             }
226              
227             # Added begin of cdata section.
228 4         11 unshift @cdata, '
229              
230             # Check to bad cdata.
231 4 100       27 if (join($EMPTY_STR, @cdata) =~ /]]>$/ms) {
232 1         6 err 'Bad CDATA data.'
233             }
234              
235             # Added end of cdata section.
236 3         7 push @cdata, ']]>';
237              
238             # Process data callback.
239 3         15 $self->_process_callback(\@cdata, 'cdata_callback');
240              
241             # To flush code.
242 3         7 $self->{'flush_code'} .= join $EMPTY_STR, @cdata;
243              
244 3         12 return;
245             }
246              
247             # Comment.
248             sub _put_comment {
249 9     9   15 my ($self, @comments) = @_;
250              
251             # Comment string.
252 9         15 unshift @comments, '';
255             } else {
256 8         10 push @comments, '-->';
257             }
258              
259             # Process comment.
260 9         17 my $comment = join $EMPTY_STR, @comments;
261 9 100       13 if (scalar @{$self->{'tmp_code'}}) {
  9         14  
262 5         18 push @{$self->{'tmp_comment_code'}}, $comment;
  5         10  
263              
264             # Flag, that means comment is last.
265 5         7 $self->{'comment_flag'} = 1;
266             } else {
267 4         39 $self->{'flush_code'} .= $comment;
268             }
269              
270 9         24 return;
271             }
272              
273             # Data.
274             sub _put_data {
275 34     34   58 my ($self, @character_data) = @_;
276              
277             # Flush tmp code.
278 34 100       40 if (scalar @{$self->{'tmp_code'}}) {
  34         77  
279 32         63 $self->_flush_tmp('>');
280             }
281              
282             # Process data callback.
283 34 100   67   113 if (none { $_ eq $self->{'printed_tags'}->[0] } @{$self->{'no_data_callback'}}) {
  67         125  
  34         118  
284 33         85 $self->_process_callback(\@character_data, 'data_callback');
285             }
286              
287             # To flush code.
288 34         150 $self->{'flush_code'} .= join $EMPTY_STR, @character_data;
289              
290 34         78 return;
291             }
292              
293             # End of tag.
294             sub _put_end_of_tag {
295 78     78   132 my ($self, $tag) = @_;
296              
297 78 100       184 if ($self->{'xml'}) {
298 48         59 my $printed = shift @{$self->{'printed_tags'}};
  48         96  
299 48 100       138 if (! defined $printed) {
    100          
300 1         6 err "Ending bad tag: '$tag' doesn't begin.";
301             } elsif ($printed ne $tag) {
302 1         13 err "Ending bad tag: '$tag' in block of ".
303             "tag '$printed'.";
304             }
305             }
306              
307             # Tag can be simple.
308 76 100 66     186 if ($self->{'xml'} && (! scalar @{$self->{'no_simple'}}
      100        
309 1     1   4 || none { $_ eq $tag } @{$self->{'no_simple'}})) {
310              
311 45 100       151 if (scalar @{$self->{'tmp_code'}}) {
  45         85  
312 13 100 100     15 if (scalar @{$self->{'tmp_comment_code'}}
  13         46  
313             && $self->{'comment_flag'} == 1) {
314              
315 2         19 $self->_flush_tmp('>');
316 2         4 $self->{'flush_code'} .= "";
317             } else {
318 11         23 $self->_flush_tmp(' />');
319             }
320             } else {
321 32         69 $self->{'flush_code'} .= "";
322             }
323              
324             # Tag cannot be simple.
325             } else {
326 31 100       37 if (scalar @{$self->{'tmp_code'}}) {
  31         84  
327 10         27 $self->_flush_tmp('>');
328             }
329 31         73 $self->{'flush_code'} .= "";
330             }
331 76         215 $self->{'preserve_obj'}->end($tag);
332              
333 76         148 return;
334             }
335              
336             # Instruction.
337             sub _put_instruction {
338 3     3   38 my ($self, $target, $code) = @_;
339              
340             # Flush tmp code.
341 3 100       6 if (scalar @{$self->{'tmp_code'}}) {
  3         7  
342 1         3 $self->_flush_tmp('>');
343             }
344              
345             # To flush code.
346 3         8 $self->{'flush_code'} .= '
347 3 100       4 if ($code) {
348 2         5 $self->{'flush_code'} .= $SPACE.$code;
349             }
350 3         4 $self->{'flush_code'} .= '?>';
351              
352 3         8 return;
353             }
354              
355             # Raw data.
356             sub _put_raw {
357 11     11   21 my ($self, @raw_data) = @_;
358              
359             # Flush tmp code.
360 11 100       12 if (scalar @{$self->{'tmp_code'}}) {
  11         21  
361 6         12 $self->_flush_tmp('>');
362             }
363              
364             # Process data callback.
365 11         35 $self->_process_callback(\@raw_data, 'raw_callback');
366              
367             # To flush code.
368 11         58 $self->{'flush_code'} .= join $EMPTY_STR, @raw_data;
369              
370 11         22 return;
371             }
372              
373             # Reset flush code.
374             sub _reset_flush {
375 88     88   110 my $self = shift;
376              
377 88         141 $self->{'flush_code'} = $EMPTY_STR;
378              
379 88         112 return;
380             }
381              
382             1;
383              
384             __END__