File Coverage

blib/lib/CSS/Object/Rule.pm
Criterion Covered Total %
statement 78 96 81.2
branch 16 36 44.4
condition 8 20 40.0
subroutine 23 29 79.3
pod 16 17 94.1
total 141 198 71.2


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