File Coverage

blib/lib/CSS/Object/Rule.pm
Criterion Covered Total %
statement 82 99 82.8
branch 16 36 44.4
condition 8 20 40.0
subroutine 24 29 82.7
pod 16 17 94.1
total 146 201 72.6


line stmt bran cond sub pod time code
1             ##----------------------------------------------------------------------------
2             ## CSS Object Oriented - ~/lib/CSS/Object/Rule.pm
3             ## Version v0.1.3
4             ## Copyright(c) 2021 DEGUEST Pte. Ltd.
5             ## Author: Jacques Deguest <jack@deguest.jp>
6             ## Created 2020/06/21
7             ## Modified 2021/11/28
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::Rule;
14             BEGIN
15             {
16 6     6   3132 use strict;
  6         16  
  6         241  
17 6     6   34 use warnings;
  6         13  
  6         184  
18 6     6   32 use parent qw( CSS::Object::Element );
  6         13  
  6         37  
19 6     6   328 use Devel::Confess;
  6         14  
  6         27  
20 6     6   365 use Want ();
  6         16  
  6         154  
21             use overload (
22 6         49 '""' => 'as_string',
23             fallback => 1,
24 6     6   43 );
  6         13  
25 6     6   6832 our $VERSION = 'v0.1.3';
26             };
27              
28             sub init
29             {
30 29     29 1 3651 my $self = shift( @_ );
31 29         499 $self->{format} = '';
32 29         96 $self->{properties} = [];
33 29         92 $self->{selectors} = [];
34 29         84 $self->{_init_strict_use_sub} = 1;
35 29         201 $self->SUPER::init( @_ );
36 29         89 return( $self );
37             }
38              
39             sub add_element
40             {
41 5     5 1 18 my $self = shift( @_ );
42 5   50     31 my $elem = shift( @_ ) || return( $self->error( "No element object was provided to add to this rule." ) );
43 5 50       354 return( $self->error( "Element object provided ($elem) is not a CSS::Object::Element object." ) ) if( !$self->_is_a( $elem, 'CSS::Object::Element' ) );
44             # $self->message( 3, "Adding element object '$elem'." );
45             # $elem->format( $self->format );
46 5         114 $elem->debug( $self->debug );
47             # $self->properties->push( $prop );
48 5         217 $self->elements->push( $elem );
49 5         275 return( $self );
50             }
51              
52             sub add_property
53             {
54 40     40 1 102 my $self = shift( @_ );
55 40   50     163 my $prop = shift( @_ ) || return( $self->error( "No property object was provided to add to this rule." ) );
56 40 50       150 return( $self->error( "Property object provided ($prop) is not a CSS::Object::Property object." ) ) if( !$self->_is_a( $prop, 'CSS::Object::Property' ) );
57             # $self->message( 3, "Adding property object '$prop'." );
58             # $prop->format( $self->format );
59 40         855 $prop->debug( $self->debug );
60             # $self->properties->push( $prop );
61 40         1588 $self->elements->push( $prop );
62 40         2089 return( $self );
63             }
64              
65             sub add_selector
66             {
67 47     47 1 122 my $self = shift( @_ );
68 47   50     162 my $sel = shift( @_ ) || return( $self->error( "No selector object was provided to add to this rule." ) );
69 47 50       147 return( $self->error( "Selector object provided is not a CSS::Object::Selector object." ) ) if( !$self->_is_a( $sel, 'CSS::Object::Selector' ) );
70             # $sel->format( $self->format );
71 47         889 $sel->debug( $self->debug );
72 47         1781 $self->selectors->push( $sel );
73 47         2462 return( $self );
74             }
75              
76             sub add_to
77             {
78 9     9 1 42 my $self = shift( @_ );
79             # no overloading;
80 9   50     42 my $css = shift( @_ ) || return( $self->error( "No css object was provided to add our rule to it." ) );
81             # my $caller = ( split( /\::/, (caller(1))[3] ) )[-1];
82             # $self->message( 3, "Called from '$caller' and css object is '$css'." );
83 9 50       238 return( $self->error( "CSS object provided (", overload::StrVal( $css ), ") is not actually a CSS::Object object." ) ) if( !$self->_is_a( $css, 'CSS::Object' ) );
84 9 50       234 defined( $css->add_rule( $self ) ) || return( $self->error( "Unable to add our css rule object (", overload::StrVal( $self ), ") to main css object elements stack: ", $css->error ) );
85             # $self->message( 3, "Returning our rule object '", overload::StrVal( $self ), "'." );
86 9         90 return( $self );
87             }
88              
89             sub as_string
90             {
91 331     331 1 7681 my $self = shift( @_ );
92             # my( $p, $f, $l ) = caller;
93             # $self->message( 3, "Stringifying rule called from package $p at line $l in file $f" );
94 331   50     1230 my $format = $self->format || return( $self->error( "No formatter set to format this rule as string." ) );
95 331         7635 return( $format->rule_as_string( $self ) );
96             }
97              
98             sub comments
99             {
100 1     1 0 59326 my $self = shift( @_ );
101 1 100   4   4 return( $self->elements->map(sub{ $_->isa( 'CSS::Object::Comment' ) ? $_ : () }) );
  4         133  
102             }
103 453     453 1 175822 sub elements { return( shift->_set_get_object_array_object( 'elements', 'CSS::Object::Element', @_ ) ); }
104              
105             sub elements_as_string
106             {
107 331     331 1 10047 my $self = shift( @_ );
108 331   50     1047 my $format = $self->format || return( $self->error( "No format object set to format properties as string." ) );
109 331         6711 return( $format->elements_as_string( $self->elements ) );
110             }
111              
112             sub format
113             {
114 1425     1425 1 7445 my $self = shift( @_ );
115 1425 100       3308 if( @_ )
116             {
117             # my( $p, $f, $l ) = caller;
118             # $self->message( 3, "Rule format called in package $p at line $l in file $f" );
119 29   50     149 my $format = $self->SUPER::format( @_ ) || return( $self->pass_error );
120             # $self->message( 3, "New format set: '$format'." );
121             $self->selectors->foreach(sub
122             {
123 0 0   0   0 shift->format( $format ) || return;
124 29         158 });
125             $self->properties->foreach(sub
126             {
127 0 0   0   0 shift->format( $format ) || return;
128 29         4995 });
129 29         5735 return( $format );
130             }
131 1396         3618 return( $self->_set_get_object( 'format', 'CSS::Object::Format' ) );
132             }
133              
134             sub get_property_by_name
135             {
136 1     1 1 60 my( $self, $prop_name ) = @_;
137             # my $props = $self->properties;
138 1         6 my $arr = Module::Generic::Array->new;
139             # $self->messagef( 3, "There are %d elements in this rule.", $self->elements->length );
140             $self->elements->foreach(sub
141             {
142 4     4   220 my $elem = shift( @_ );
143             # $self->message( 3, "Checking this element '$elem'." );
144 4 50       15 next if( !$elem->isa( 'CSS::Object::Property' ) );
145             # $self->message( 3, "This element is a property with name \"", $elem->name, "\" and does it match our target \"$prop_name\" ?" );
146 4 100       13 if( $elem->name eq $prop_name )
147             {
148 1         53 $arr->push( $elem );
149             }
150 1         13 });
151 1 50       71 if( Want::want( 'OBJECT' ) )
    50          
152             {
153 0 0       0 rreturn( $arr->length > 0 ? $arr->first : Module::Generic::Null->new );
154             }
155             elsif( Want::want( 'LIST' ) )
156             {
157 0 0       0 rreturn( $arr->length > 0 ? $arr->list : () );
158             }
159             else
160             {
161 1         105 return( $arr->first );
162             }
163             }
164              
165             # Obsolete. See elements instead which has a wider scope including also comments
166             # sub properties { return( shift->_set_get_object_array_object( 'properties', 'CSS::Object::Property', @_ ) ); }
167             sub properties
168             {
169 32     32 1 59454 my $self = shift( @_ );
170 32 100   10   137 return( $self->elements->map(sub{ $self->_is_a( $_, 'CSS::Object::Property' ) ? $_ : () }) );
  10         398  
171             }
172              
173             sub properties_as_string
174             {
175 0     0 1 0 my $self = shift( @_ );
176 0   0     0 my $format = $self->format || return( $self->error( "No formatter set to format properties as string." ) );
177 0         0 return( $format->properties_as_string( $self->properties ) );
178             }
179              
180             sub remove_from
181             {
182 0     0 1 0 my $self = shift( @_ );
183 0   0     0 my $css = shift( @_ ) || return( $self->error( "No css object was provided to remove our rule from it." ) );
184             # my $caller = ( split( /\::/, (caller(1))[3] ) )[-1];
185             # $self->message( 3, "Called from '$caller' and css object is '$css'." );
186 0 0       0 return( $self->error( "CSS object provided (", overload::StrVal( $css ), ") is not actually a CSS::Object object." ) ) if( !$self->_is_a( $css, 'CSS::Object' ) );
187 0         0 $css->remove_rule( $self );
188 0         0 return( $self );
189             }
190              
191             sub remove_property
192             {
193 0     0 1 0 my $self = shift( @_ );
194 0         0 my $prop = shift( @_ );
195 0 0       0 return( $self->error( "Property object provided ($prop) is not a CSS::Object::Property object." ) ) if( !$self->_is_a( $prop, 'CSS::Object::Property' ) );
196 0         0 $self->elements->remove( $prop );
197 0         0 return( $self );
198             }
199              
200             # Array of CSS::Object::Selector objects
201 417     417 1 510493 sub selectors { return( shift->_set_get_object_array_object( 'selectors', 'CSS::Object::Property', @_ ) ); }
202              
203             sub selectors_as_string
204             {
205 328     328 1 703 my $self = shift( @_ );
206 328   50     797 my $format = $self->format || return( $self->error( "No formatter set to format selectors as string." ) );
207 328         6287 return( $format->selectors_as_string( $self->selectors ) );
208             }
209              
210             1;
211              
212             __END__
213              
214             =encoding utf-8
215              
216             =head1 NAME
217              
218             CSS::Object::Rule - CSS Object Oriented Rule
219              
220             =head1 SYNOPSIS
221              
222             use CSS::Object::Rule;
223             my $rule = CSS::Object::Rule->new( debug => 3, format => $format_object ) ||
224             die( CSS::Object::Rule->error );
225              
226             =head1 VERSION
227              
228             v0.1.3
229              
230             =head1 DESCRIPTION
231              
232             L<CSS::Object::Rule> a class containing one or more L<CSS::Object::Selector> objects and one ore more L<CSS::Object::Property> objects.
233              
234             =head1 CONSTRUCTOR
235              
236             =head2 new
237              
238             To instantiate a new L<CSS::Object::Rule> object, pass an hash reference of following parameters:
239              
240             =over 4
241              
242             =item I<debug>
243              
244             This is an integer. The bigger it is and the more verbose is the output.
245              
246             =item I<format>
247              
248             This is a L<CSS::Object::Format> object or one of its child modules.
249              
250             =back
251              
252             =head1 METHODS
253              
254             =head2 add_element
255              
256             Provided with a L<CSS::Object::Element> object and this add it to the array of L</elements> for this rule.
257              
258             =head2 add_property
259              
260             Provided with a L<CSS::Object::Property> object and this adds it to the list of properties contained in this rule.
261              
262             The object is added to the L</properties> array object, which is an L<Module::Generic::Array> object.
263              
264             =head2 add_selector
265              
266             Provided with a L<CSS::Object::Selector> object and this adds it to the list of selectors contained in this rule.
267              
268             The object is added to the L</selectors> array object, which is an L<Module::Generic::Array> object.
269              
270             =head2 add_to
271              
272             Provided with a L<CSS::Object> object and this add our object to its list of elements by calling L<CSS::Object/add_rule>
273              
274             =head2 as_string
275              
276             This calls the L</format> and its method L<CSS::Object::Format/rule_as_string>
277              
278             It returns the css string produced or undef and sets an L<Module::Generic::Exception> upon error.
279              
280             =head2 elements
281              
282             Sets or gets the list of elements for this rule. This uses an array object from L<Module::Generic::Array>
283              
284             Typical elements for a rule are properties (L<CSS::Object::Property>) and comments (L<CSS::Object::Comment>).
285              
286             =head2 elements_as_string
287              
288             This takes our list of L</elements> and call L<CSS:Object::Format/elements_as_string> to stringify them and return a formatted string.
289              
290             =head2 format
291              
292             This is a L<CSS::Object::Format> object or one of its child modules.
293              
294             =head2 get_property_by_name
295              
296             Provided with a property name, and this returns its matching L<CSS::Object::Property> objects.
297              
298             It returns a list of objects in list context or an empty list if no match found.
299              
300             In object context, it returns the first match found or the L<Module::Generic::Null> special class object to allow chaining even when nothing was returned. in scalar context, it just returns the first entry found, if any, so this could very well be undefined.
301              
302             =head2 properties
303              
304             This sets or gets the L<Module::Generic::Array> object used to store all the L<CSS::Object::Property> objects.
305              
306             =head2 properties_as_string
307              
308             This returns the string value of all the properties objects currently held. It calls the method L<CSS::Object::Format/properties_as_string> to stringify those properties.
309              
310             =head2 remove_from
311              
312             This takes a L<CSS::Object> as argument and it will remove this current rule object from the css list of rules.
313              
314             It basically calls L<CSS::Object/remove_rule>.
315              
316             It returns the current rule object.
317              
318             =head2 remove_property
319              
320             Given a L<CSS::Object::Property>, this will remove it from its list of elements. It returns the current rule object.
321              
322             It basically does:
323              
324             $self->elements->remove( $rule );
325              
326             =head2 selectors
327              
328             This sets or gets the L<Module::Generic::Array> object used to store all the L<CSS::Object::Selector> objects.
329              
330             =head2 selectors_as_string
331              
332             This returns the string value of all the selector objects currently held. It calls the method L<CSS::Object::Format/selectors_as_string> to stringify those selectors.
333              
334             =head1 AUTHOR
335              
336             Jacques Deguest E<lt>F<jack@deguest.jp>E<gt>
337              
338             =head1 SEE ALSO
339              
340             L<CSS::Object>
341              
342             =head1 COPYRIGHT & LICENSE
343              
344             Copyright (c) 2020 DEGUEST Pte. Ltd.
345              
346             You can use, copy, modify and redistribute this package and associated
347             files under the same terms as Perl itself.
348              
349             =cut