File Coverage

blib/lib/CSS/Struct/Output.pm
Criterion Covered Total %
statement 129 129 100.0
branch 38 38 100.0
condition 15 15 100.0
subroutine 24 24 100.0
pod 4 4 100.0
total 210 210 100.0


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