File Coverage

blib/lib/CSS/Struct/Output.pm
Criterion Covered Total %
statement 132 132 100.0
branch 38 38 100.0
condition 15 15 100.0
subroutine 25 25 100.0
pod 4 4 100.0
total 214 214 100.0


line stmt bran cond sub pod time code
1             package CSS::Struct::Output;
2              
3 21     21   78156 use strict;
  21         85  
  21         667  
4 21     21   120 use warnings;
  21         42  
  21         613  
5              
6 21     21   11128 use Class::Utils qw(set_params);
  21         682094  
  21         481  
7 21     21   1695 use Error::Pure qw(err);
  21         51  
  21         937  
8 21     21   128 use List::MoreUtils qw(none);
  21         45  
  21         96  
9 21     21   14240 use Scalar::Util qw(openhandle);
  21         61  
  21         5381  
10              
11             our $VERSION = 0.05;
12              
13             # Constructor.
14             sub new {
15 39     39 1 70525 my ($class, @params) = @_;
16              
17             # Create object.
18 39         116 my $self = bless {}, $class;
19              
20             # Get default parameters.
21 39         200 $self->_default_parameters;
22              
23             # Process params.
24 39         187 set_params($self, @params);
25              
26             # Check parameters to right values.
27 36         540 $self->_check_params;
28              
29             # Reset.
30 26         122 $self->reset;
31              
32             # Object.
33 26         143 return $self;
34             }
35              
36             # Flush CSS structure in object.
37             sub flush {
38 41     41 1 347 my ($self, $reset_flag) = @_;
39 41         86 my $ouf = $self->{'output_handler'};
40 41         65 my $ret;
41 41 100       127 if (ref $self->{'flush_code'} eq 'ARRAY') {
42 9         17 $ret = join $self->{'output_sep'}, @{$self->{'flush_code'}};
  9         30  
43             } else {
44 32         65 $ret = $self->{'flush_code'};
45             }
46 41 100       107 if ($ouf) {
47 21     21   201 no warnings;
  21         71  
  21         25431  
48 6 100       15 print {$ouf} $ret or err 'Cannot write to output handler.';
  6         204  
49 4         16 undef $ret;
50             }
51              
52             # Reset.
53 39 100       102 if ($reset_flag) {
54 2         8 $self->reset;
55             }
56              
57             # Return string.
58 39         151 return $ret;
59             }
60              
61             # Put CSS structure code.
62             sub put {
63 50     50 1 16671 my ($self, @data) = @_;
64              
65             # For every data.
66 50         123 foreach my $css_structure_ar (@data) {
67              
68             # Bad data.
69 135 100       349 if (ref $css_structure_ar ne 'ARRAY') {
70 2         15 err 'Bad data.';
71             }
72              
73             # Split to type and main CSS structure.
74 133         189 my ($type, @css_struct) = @{$css_structure_ar};
  133         314  
75              
76             # At-rule.
77 133 100       563 if ($type eq 'a') {
    100          
    100          
    100          
    100          
    100          
    100          
78 2         11 $self->_check_arguments(\@css_struct, 1, 2);
79 2         7 $self->_put_at_rules(@css_struct);
80              
81             # Comment.
82             } elsif ($type eq 'c') {
83 20         46 $self->_put_comment(@css_struct);
84              
85             # Definition.
86             } elsif ($type eq 'd') {
87 24         76 $self->_check_arguments(\@css_struct, 1, 2);
88 24         70 $self->_put_definition(@css_struct);
89              
90             # End of selector.
91             } elsif ($type eq 'e') {
92 35         108 $self->_check_arguments(\@css_struct, 0, 0);
93 35         88 $self->_put_end_of_selector;
94              
95             # Instruction.
96             } elsif ($type eq 'i') {
97 3         22 $self->_check_arguments(\@css_struct, 1, 2);
98 3         10 $self->_put_instruction(@css_struct);
99              
100             # Raw data.
101             } elsif ($type eq 'r') {
102 2         8 $self->_put_raw(@css_struct);
103              
104             # Selector.
105             } elsif ($type eq 's') {
106 43         196 $self->_check_arguments(\@css_struct, 1, 1);
107 39         103 $self->_put_selector(@css_struct);
108              
109             # Other.
110             } else {
111 4 100       19 if (! $self->{'skip_bad_types'}) {
112 2         9 err 'Bad type of data.', 'type', $type;
113             }
114             }
115             }
116              
117             # Auto-flush.
118 41 100       146 if ($self->{'auto_flush'}) {
119 2         10 $self->flush;
120 2         9 $self->_reset_flush_code;
121             }
122              
123 41         110 return;
124             }
125              
126              
127             # Resets internal variables.
128             sub reset {
129 46     46 1 1570 my $self = shift;
130              
131             # Tmp code.
132 46         115 $self->{'tmp_code'} = [];
133              
134             # Flush code.
135 46         163 $self->_reset_flush_code;
136              
137             # Open selector flag.
138 46         87 $self->{'open_selector'} = 0;
139              
140 46         79 return;
141             }
142              
143             # Check arguments.
144             sub _check_arguments {
145 107     107   221 my ($self, $css_structure_ar, $min_arg_num, $max_arg_num) = @_;
146 107         144 my $arg_num = scalar @{$css_structure_ar};
  107         176  
147 107 100 100     404 if ($arg_num < $min_arg_num || $arg_num > $max_arg_num) {
148             err 'Bad number of arguments.',
149             '\'CSS::Struct\' structure',
150 4         9 join ', ', @{$css_structure_ar};
  4         20  
151             }
152 103         180 return;
153             }
154              
155             # Check to opened selector.
156             sub _check_opened_selector {
157 43     43   77 my $self = shift;
158 43 100       93 if (! $self->{'open_selector'}) {
159 1         7 err 'No opened selector.';
160             }
161 42         74 return;
162             }
163              
164             # Default parameters.
165             sub _default_parameters {
166 39     39   83 my $self = shift;
167              
168             # Auto flush flag.
169 39         158 $self->{'auto_flush'} = 0;
170              
171             # CSS comment delimeters.
172 39         124 $self->{'comment_delimeters'} = [q{/*}, q{*/}];
173              
174             # Set output handler.
175 39         100 $self->{'output_handler'} = undef;
176              
177             # Output separator.
178 39         88 $self->{'output_sep'} = "\n";
179              
180             # Skip bad 'CSS::Struct' types.
181 39         76 $self->{'skip_bad_types'} = 0;
182              
183             # Skip comments.
184 39         74 $self->{'skip_comments'} = 0;
185              
186 39         72 return;
187             }
188              
189             # Check parameters to rigth values.
190             sub _check_params {
191 36     36   78 my $self = shift;
192              
193             # Check to output handler.
194 36 100 100     248 if (defined $self->{'output_handler'}
195             && ! defined openhandle($self->{'output_handler'})) {
196              
197 2         10 err 'Output handler is bad file handler.';
198             }
199             # Check auto-flush only with output handler.
200 34 100 100     134 if ($self->{'auto_flush'} && ! defined $self->{'output_handler'}) {
201 2         9 err 'Auto-flush can\'t use without output handler.';
202             }
203              
204             # Check to comment delimeters.
205 32 100 100     379 if (ref $self->{'comment_delimeters'} ne 'ARRAY'
      100        
206 32     32   275 || (none { $_ eq $self->{'comment_delimeters'}->[0] }
207             (q{/*}, ''))) {
210              
211 6         18 err 'Bad comment delimeters.';
212             }
213              
214 26         166 return;
215             }
216              
217             # At-rules.
218             sub _put_at_rules {
219 1     1   4 my ($self, $at_rule, $value) = @_;
220 1         1 push @{$self->{'flush_code'}}, 'At-rule';
  1         3  
221 1         3 return;
222             }
223              
224             # Comment.
225             sub _put_comment {
226 1     1   3 my ($self, @comments) = @_;
227 1         2 push @{$self->{'flush_code'}}, 'Comment';
  1         2  
228 1         3 return;
229             }
230              
231             # Definition.
232             sub _put_definition {
233 8     8   17 my ($self, $key, $value) = @_;
234 8         14 push @{$self->{'flush_code'}}, 'Definition';
  8         24  
235 8         20 return;
236             }
237              
238             # End of selector.
239             sub _put_end_of_selector {
240 8     8   15 my $self = shift;
241 8         19 push @{$self->{'flush_code'}}, 'End of selector';
  8         19  
242 8         19 return;
243             }
244              
245             # Instruction.
246             sub _put_instruction {
247 1     1   2 my ($self, $target, $code) = @_;
248 1         2 push @{$self->{'flush_code'}}, 'Instruction';
  1         12  
249 1         4 return;
250             }
251              
252             # Raw data.
253             sub _put_raw {
254 1     1   4 my ($self, @raw_data) = @_;
255 1         2 push @{$self->{'flush_code'}}, 'Raw data';
  1         3  
256 1         2 return;
257             }
258              
259             # Selectors.
260             sub _put_selector {
261 8     8   27 my ($self, $selector) = @_;
262 8         12 push @{$self->{'flush_code'}}, 'Selector';
  8         24  
263 8         19 return;
264             }
265              
266             # Reset flush code.
267             sub _reset_flush_code {
268 12     12   23 my $self = shift;
269 12         33 $self->{'flush_code'} = [];
270 12         21 return;
271             }
272              
273             1;
274              
275             __END__