File Coverage

blib/lib/Tags/Output/Raw.pm
Criterion Covered Total %
statement 179 180 99.4
branch 53 54 98.1
condition 17 20 85.0
subroutine 24 24 100.0
pod 2 2 100.0
total 275 280 98.2


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