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