File Coverage

blib/lib/CSS/Object/Format.pm
Criterion Covered Total %
statement 89 101 88.1
branch 28 60 46.6
condition 1 2 50.0
subroutine 27 32 84.3
pod 20 20 100.0
total 165 215 76.7


line stmt bran cond sub pod time code
1             ##----------------------------------------------------------------------------
2             ## CSS Object Oriented - ~/lib/CSS/Object/Format.pm
3             ## Version v0.2.0
4             ## Copyright(c) 2020 DEGUEST Pte. Ltd.
5             ## Author: Jacques Deguest <jack@deguest.jp>
6             ## Created 2020/06/21
7             ## Modified 2024/09/05
8             ## All rights reserved
9             ##
10             ## This program is free software; you can redistribute it and/or modify it
11             ## under the same terms as Perl itself.
12             ##----------------------------------------------------------------------------
13             package CSS::Object::Format;
14             BEGIN
15             {
16 6     6   38 use strict;
  6         12  
  6         272  
17 6     6   28 use warnings;
  6         10  
  6         314  
18 6     6   29 use parent qw( Module::Generic );
  6         11  
  6         30  
19 6     6   11954 our $VERSION = 'v0.2.0';
20             };
21              
22             sub init
23             {
24 57     57 1 19988 my $self = shift( @_ );
25 57         526 $self->{new_line} = "\n";
26 57         172 $self->{open_brace_on_new_line} = 1;
27 57         128 $self->{close_brace_on_new_line} = 1;
28 57         127 $self->{open_brace_and_new_line} = 1;
29 57         164 $self->{indent} = '';
30 57         178 $self->{property_separator} = "\n";
31 57         134 $self->{_init_strict_use_sub} = 1;
32 57         418 $self->SUPER::init( @_ );
33 57         17070 $self->{_params} = [qw(
34             close_brace_on_new_line
35             indent
36             new_line
37             open_brace_and_new_line
38             open_brace_on_new_line
39             property_separator
40             )];
41 57         157 return( $self );
42             }
43              
44 18     18 1 1064 sub backup_parameters { return( shift->clone ); }
45              
46 5     5 1 147 sub class { return( ref( $_[0] ) ); }
47              
48 404     404 1 164031 sub close_brace_on_new_line { return( shift->_set_get_boolean( 'close_brace_on_new_line', @_ ) ); }
49              
50             sub comment_as_string
51             {
52 43     43 1 1220 my( $self, $elem ) = @_;
53             # no overloading;
54 43 50       131 return( $self->error( "No comment object was provided." ) ) if( !defined( $elem ) );
55 43 50       140 return( $self->error( "Comment object provied is not a CSS::Object::Comment object." ) ) if( !$self->_is_a( $elem, 'CSS::Object::Comment' ) );
56 43         1434 return( '/* ' . $elem->values->join( "\n" )->scalar . ' */' );
57             }
58              
59             sub copy_parameters_from
60             {
61 22     22 1 456 my $self = shift( @_ );
62 22   50     79 my $fmt = shift( @_ ) || return( $self->error( "No formatter object was provided to copy the parameters from." ) );
63 22 50       68 return( $self->error( "Formatter object provided is actually not a formatter object." ) ) if( !$self->_is_a( $fmt, 'CSS::Object::Format' ) );
64             # my( $p, $f, $l ) = caller();
65 22         660 my $ok_params = $self->{_params};
66 22         62 for( @$ok_params )
67             {
68 132 50       106072 $self->$_( $fmt->$_ ) if( $fmt->can( $_ ) );
69             }
70 22         26018 return( $self );
71             }
72              
73             sub elements_as_string
74             {
75 326     326 1 246673 my( $self, $elems ) = @_;
76             # no overloading;
77 326 50       1227 return( $self->error( "No elements array was provided." ) ) if( !defined( $elems ) );
78 326 50       1181 return( $self->error( "Elements provided is not an array object." ) ) if( !$self->_is_a( $elems, 'Module::Generic::Array' ) );
79 326         10497 my $result = Module::Generic::Array->new;
80 326         3401 my $nl = $self->new_line->scalar;
81 326         270355 my $prop_sep = $self->property_separator->scalar;
82             ## $prop_sep .= $self->indent->scalar;
83             $elems->foreach(sub
84             {
85 267 100   267   620727 $result->push( $_->format->indent->scalar . $_->as_string . ( $_->isa( 'CSS::Object::Comment' ) ? '' : ';' ) );
86 326         286604 });
87 326         1279764 return( $result->join( $prop_sep )->scalar );
88             }
89              
90             ## sub indent { return( shift->_set_get_scalar_as_object( 'indent', @_ ) ); }
91             sub indent
92             {
93 1046     1046 1 73786 my $self = shift( @_ );
94 1046 100       2682 if( @_ )
95             {
96 161         324 my $val = shift( @_ );
97             # my( $p, $f, $l ) = caller();
98 161         632 return( $self->_set_get_scalar_as_object( 'indent', $val ) );
99             }
100 885         3002 return( $self->_set_get_scalar_as_object( 'indent' ) );
101             }
102              
103             sub keyframes_as_string
104             {
105 19     19 1 633 my( $self, $keyf ) = @_;
106 19 50       61 return( $self->error( "No keyframes rule object was provided." ) ) if( !defined( $keyf ) );
107 19 50       64 return( $self->error( "Keyframes object provided (", overload::StrVal( $keyf ), ") is not actually an CSS::Object::Rule::Keyframes" ) ) if( !$self->_is_a( $keyf, 'CSS::Object::Rule::Keyframes' ) );
108             ## no overloading;
109             ## Calling rule_as_string on each item in our stack
110 19     63   689 my $rule_str = $keyf->elements->map(sub{ $_->as_string })->join( "\n" )->scalar;
  63         57191  
111 19         19673 my $type = $keyf->type->tr( '_', '-' )->scalar;
112 19         18756 my $name = $keyf->name->scalar;
113 19         14389 my $nl = $self->new_line->scalar;
114 19 50       14766 return( '@' . "${type} ${name}" . ( $self->open_brace_on_new_line ? $nl : ' ' ) . "{" . ( $self->open_brace_and_new_line ? $nl : '' ) . $rule_str . ( $self->close_brace_on_new_line ? $nl : ' ' ) . "}" );
    50          
    50          
115             }
116              
117 732     732 1 32606 sub new_line { return( shift->_set_get_scalar_as_object( 'new_line', @_ ) ); }
118              
119 404     404 1 396846 sub open_brace_on_new_line { return( shift->_set_get_boolean( 'open_brace_on_new_line', @_ ) ); }
120              
121 404     404 1 298107 sub open_brace_and_new_line { return( shift->_set_get_boolean( 'open_brace_on_new_line', @_ ) ); }
122              
123             ## Outdated. See elements_as_string
124             sub properties_as_string
125             {
126 0     0 1 0 my( $self, $properties ) = @_;
127             # no overloading;
128 0 0       0 return( $self->error( "No properties array was provided." ) ) if( !defined( $properties ) );
129 0 0       0 return( $self->error( "Properties provided is not an array object." ) ) if( !$self->_is_a( $properties, 'Module::Generic::Array' ) );
130             # return( join( '; ', map{ $_->name . ": " . $_->values->map(sub{ $_->value->scalar })->join( '' ) } @$properties ) );
131 0     0   0 return( $properties->map(sub{ $_->name->scalar . ': ' . $_->values->map(sub{ $_->value->scalar })->join( '' )->scalar })->join( ";" )->scalar );
  0         0  
  0         0  
132             }
133              
134             sub property_as_string
135             {
136 250     250 1 7024 my( $self, $prop ) = @_;
137             # no overloading;
138 250 50       886 return( $self->error( "No property object was provided." ) ) if( !defined( $prop ) );
139 250 50       965 return( $self->error( "Property object provied is not a CSS::Object::Property object." ) ) if( !$self->_is_a( $prop, 'CSS::Object::Property' ) );
140 250         8470 my $indent = $prop->format->indent->scalar;
141 250     250   199573 return( $prop->name->scalar . ': ' . $prop->values->map(sub{ $_->as_string })->join( '' )->scalar );
  250         192112  
142             }
143              
144 422     422 1 46161 sub property_separator { return( shift->_set_get_scalar_as_object( 'property_separator', @_ ) ); }
145              
146             sub restore_parameters
147             {
148 18     18 1 1759 my $self = shift( @_ );
149 18         33 my $this = shift( @_ );
150 18 50       69 return( $self->error( "Data provided is not an hash reference." ) ) if( !$self->_is_hash( $this ) );
151 18         252 my $params = $self->{_params};
152 18         42 foreach my $p ( @$params )
153             {
154 108         78417 $self->$p( $this->{ $p } );
155             }
156 18         15946 return( $self );
157             }
158              
159             sub rule_as_string
160             {
161 323     323 1 1080 my( $self, $rule ) = @_;
162             # no overloading;
163             # my( $pack, $file, $line ) = caller;
164 323 50       988 return( $self->error( "No rule object was provided." ) ) if( !defined( $rule ) );
165 323 0       1199 return( $self->error( "Rule object provided (", overload::Overloaded( $rule ) ? overload::StrVal( $rule ) : $rule ,") is not an actual rule object." ) ) if( !$self->_is_a( $rule, 'CSS::Object::Rule' ) );
    50          
166 323         11774 my $rule_indent = $rule->format->indent->scalar;
167 323         289946 my $nl = $self->new_line->scalar;
168             ## return( $rule->selectors_as_string . ' { ' . $rule->properties_as_string . " }\n" );
169             return(
170 323 50       281820 $rule_indent . $rule->selectors_as_string .
    50          
    50          
171             ( $self->open_brace_on_new_line ? $nl : ' ' ) .
172             $rule_indent . '{' .
173             ( $self->open_brace_and_new_line ? $nl : ' ' ) .
174             $rule->elements_as_string .
175             ( $self->close_brace_on_new_line ? $nl : ' ' ) .
176             "${rule_indent}}"
177             );
178             }
179              
180             sub selectors_as_string
181             {
182 323     323 1 249106 my( $self, $selectors ) = @_;
183 323     411   2354 return( $selectors->map(sub{ $_->name->scalar })->join( ', ' )->scalar );
  411         132918  
184             }
185              
186             sub value_as_string
187             {
188 258     258 1 6018 my( $self, $val ) = @_;
189 258 50       971 return( $self->error( "No value object was provided." ) ) if( !$self->_is_a( $val, 'CSS::Object::Value' ) );
190 258 50       8576 return( $self->error( "Value object provided is not a CSS::Object::Value object." ) ) if( !$self->_is_a( $val, 'CSS::Object::Value' ) );
191             return(
192 10     10   7377 $val->comment_before->map(sub{ $_->as_string })->join( ' ' )->scalar . ( $val->comment_before->length > 0 ? ' ' : '' ) .
193             $val->value->as_string .
194 258 100   0   7168 ( $val->comment_after->length > 0 ? ' ' : '' ) . $val->comment_after->map(sub{ $_->as_string })->join( ' ' )->scalar
  0 50          
195             );
196             }
197              
198             sub values_as_string
199             {
200 0     0 1   my( $self, $values ) = @_;
201 0 0         return( $self->error( "No properties values array was provided." ) ) if( !defined( $values ) );
202 0 0         return( $self->error( "Properties values provided is not an array." ) ) if( !$self->_is_a( $values, 'Module::Generic::Array' ) );
203             ## return( join( '', map{ $_->value } @$values ) );
204             ## return( $values->map(sub{ $_->value->scalar })->join( '' )->scalar );
205 0     0     return( $values->map(sub{ $_->as_string })->join( '' )->scalar );
  0            
206             }
207              
208             1;
209             # NOTE: POD
210             __END__
211              
212             =encoding utf-8
213              
214             =head1 NAME
215              
216             CSS::Object::Format - CSS Object Oriented Stringificator
217              
218             =head1 SYNOPSIS
219              
220             use CSS::Object::Format;
221             my $format = CSS::Object::Format->new( debug => 3 ) ||
222             die( CSS::Object::Format->error );
223             my $prop = CSS::Object::Property->new(
224             format => $format,
225             debug => 3,
226             name => 'display',
227             value => 'inline-block',
228             ) || die( CSS::Object::Property->error );
229             print( $prop->as_string );
230              
231             =head1 VERSION
232              
233             v0.2.0
234              
235             =head1 DESCRIPTION
236              
237             L<CSS::Object::Format::Inline> is a CSS inline stringificator
238              
239             =head1 CONSTRUCTOR
240              
241             =head2 new
242              
243             To instantiate a new L<CSS::Object::Format> object, pass an hash reference of following parameters:
244              
245             =over 4
246              
247             =item I<debug>
248              
249             This is an integer. The bigger it is and the more verbose is the output.
250              
251             =back
252              
253             =head1 PARAMETERS
254              
255             The available parameters used to alter the formatting of the formatters are as follow. Please see each of them methods for their respective purpose and usage.
256              
257             =over 4
258              
259             =item * L</close_brace_on_new_line>
260              
261             =item * L</new_line>
262              
263             =item * L</open_brace_on_new_line>
264              
265             =item * L</open_brace_and_new_line>
266              
267             =item * L</indent>
268              
269             =item * L</property_separator>
270              
271             =back
272              
273             =head1 METHODS
274              
275             =head2 backup_parameters
276              
277             This will create a deep copy of this formatter's L</parameters> and return it.
278              
279             See L</restore_parameters>
280              
281             =head2 close_brace_on_new_line
282              
283             This takes a boolean value. If true, this will instruct the formatter to place the closing brace on a new line.
284              
285             =head2 comment_as_string
286              
287             Provided with a comment object, and this will return the comment formatted.
288              
289             =head2 copy_parameters_from
290              
291             Provided with another L<CSS::Object::Format> object, and this will copy all suitable L</parameters> to it.
292              
293             This is called from the L<format> methods in CSS element classes when a new format object is provided to the element.
294              
295             =head2 elements_as_string
296              
297             Provided with an array object (L<Module::Generic::Array>), and this will format all the elements and return a string.
298              
299             =head2 indent
300              
301             This is one of L</parameters> that sets the string to use as indent. Indent string can be provided in rule formatter or property formatter.
302              
303             This returns the current character value as a L<Module::Generic::Scalar> object.
304              
305             =head2 keyframes_as_string
306              
307             This formats the keyframe special rule and returns a string.
308              
309             =head2 new_line
310              
311             This sets or gets the new line character to be used for new lines.
312              
313             This returns the current character value as a L<Module::Generic::Scalar> object.
314              
315             =head2 open_brace_on_new_line
316              
317             This takes a boolean value. If true, this will instruct the formatter to place the opening brace on a new line.
318              
319             =head2 open_brace_and_new_line
320              
321             This takes a boolean value. If true, this will instruct the formatter to insert a new line after the opening brace.
322              
323             =head2 properties_as_string
324              
325             Provided with an array reference of a L<CSS::Object::Property> objects and this will format them and return their string representation.
326              
327             =head2 property_as_string
328              
329             Provided with a L<CSS::Object::Property> object and this will format it and return its string representation.
330              
331             =head2 property_separator
332              
333             This sets or gets the property separator. By default, this is a new line C<\n>
334              
335             If you want the formatter to put all properties on a single line, you could replace this default value with an empty string.
336              
337             This returns the current character value as a L<Module::Generic::Scalar> object.
338              
339             =head2 restore_parameters
340              
341             Provided with an hash reference, typically that created by L</backup_parameters> and this will restore this formatter's L</parameters>
342              
343             It returns our object
344              
345             =head2 rule_as_string
346              
347             Provided with a L<CSS::Object::Rule> object and this will format it and return its string representation.
348              
349             =head2 selectors_as_string
350              
351             Provided with an array reference of a L<CSS::Object::Selector> objects and this will format them and return their string representation.
352              
353             =head2 value_as_string
354              
355             Provided with a L<CSS::Object::Value> object and this will format it and return its string representation.
356              
357             =head2 values_as_string
358              
359             Provided with an array reference of a L<CSS::Object::Value> objects and this will format them and return their string representation.
360              
361             =head1 AUTHOR
362              
363             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
364              
365             =head1 SEE ALSO
366              
367             L<CSS::Object>
368              
369             =head1 COPYRIGHT & LICENSE
370              
371             Copyright (c) 2020 DEGUEST Pte. Ltd.
372              
373             You can use, copy, modify and redistribute this package and associated
374             files under the same terms as Perl itself.
375              
376             =cut