File Coverage

blib/lib/CSS/Object/Rule.pm
Criterion Covered Total %
statement 83 90 92.2
branch 16 32 50.0
condition 8 18 44.4
subroutine 24 27 88.8
pod 14 15 93.3
total 145 182 79.6


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