File Coverage

blib/lib/CSS/Moonfall.pm
Criterion Covered Total %
statement 93 98 94.9
branch 30 36 83.3
condition 2 3 66.6
subroutine 25 25 100.0
pod 2 2 100.0
total 152 164 92.6


line stmt bran cond sub pod time code
1             package CSS::Moonfall;
2 14     14   264109 use strict;
  14         36  
  14         543  
3 14     14   80 use warnings;
  14         23  
  14         418  
4 14     14   91 use base 'Exporter';
  14         22  
  14         2080  
5 14     14   17640 use Text::Balanced 'extract_bracketed';
  14         709379  
  14         13187  
6              
7             our @EXPORT = qw/filter fill/;
8             our $VERSION = '0.04';
9              
10             sub filter {
11 12     12 1 169 my $package = shift;
12 12         29 my $in = shift;
13 12         44 my $out = '';
14              
15 12         60 while (length $in) {
16 66         247 ((my $extracted), $in, my $prefix)
17             = extract_bracketed($in, '[q]', '[^\[]+');
18 66 100       20584 return $out . $in if !defined($extracted);
19 55         126 $out .= $prefix;
20              
21             # get rid of the []
22 55         110 substr($extracted, -1, 1, '');
23 55         101 substr($extracted, 0, 1, '');
24              
25             # get the rest of the line around the extracted text so we can check
26             # how much we should indent, and whether to compress the output into
27             # one line
28 55         869 my ($preline) = $prefix =~ /(.*)$/;
29 55         166 my ($postline) = $in =~ /^(.*)/;
30              
31 55         148 $out .= _process($package, $extracted, 1, $preline, $postline);
32             }
33              
34 1         37 return $out;
35             }
36              
37             sub fill {
38 8     8 1 5267 my $values = shift;
39 8 50       70 my $total = delete $values->{total} or do {
40 1         5 require Carp;
41 1         2 Carp::croak "You must define a total size in a call to fill.";
42             };
43              
44 8         27 my $unfilled = 0;
45              
46 8         31 for my $k (keys %$values) {
47 30 100       65 if (defined(my $w = $values->{$k})) {
48 13         39 $total -= $w;
49             }
50             else {
51 18         34 ++$unfilled;
52             }
53             }
54              
55 8         26 $total = int($total / $unfilled);
56              
57 8         36 for (values %$values) {
58 30 100       78 defined or $_ = $total;
59             }
60              
61 8         3713 return $values;
62             }
63              
64             # this is where all the logic of expanding [foo] into some arbitrary string is
65             sub _process {
66 139     139   255 my $package = shift;
67 139         170 my $in = shift;
68 139         134 my $top = shift;
69 139         190 my $pre = shift;
70 139         170 my $post = shift;
71              
72 139         254 $in =~ s/^\s+//;
73 139         229 $in =~ s/\s+$//;
74              
75 139 100       413 if ($in =~ /^[a-zA-Z_]\w*/) {
76 79 100       217 return $in if !$top;
77 39         124 $in = '$' . $in;
78             }
79              
80 99 100   11   4323 my $out = $top ? eval "package $package; no strict 'vars'; $in" : $in;
  10     9   89  
  10     8   23  
  10     5   332  
  8     1   42  
  8     1   34  
  8     1   161  
  7     1   37  
  7     1   12  
  7     1   193  
  4     1   22  
  4     1   5  
  4     1   108  
        1      
        1      
        1      
        1      
81              
82 99         198 my @kv = _expand($out);
83              
84 99 100       467 if (@kv > 1) {
    100          
85 21         37 my $joiner = ' ';
86 21         37 my $indent = '';
87 21 100 66     143 if ($pre =~ /^\s*$/ && $post =~ /^\s*$/) {
88 11         21 $joiner = "\n";
89 11         13 $indent = $pre;
90             }
91              
92 21         93 my $first = 0;
93 85         179 $out = join $joiner, map {
94 103         187 my ($k, $v) = @$_;
95 85         169 $k =~ s/_/-/g;
96 85         181 $v = _process($package, $v, 0, $pre, $post);
97 85 100       319 ($first++ ? $indent : '') . "$k: $v;";
98             }
99 21         79 sort {$a->[0] cmp $b->[0]} @kv;
100             }
101             elsif ($kv[0] =~ /^\d+$/) {
102 60         103 $out .= 'px';
103             }
104              
105 99         398 return $out;
106             }
107              
108             # try to expand an array/hash ref, recursively, into a list of pairs
109             # if a value is a reference, then the key is dropped and the value is expanded
110             # in place
111             sub _expand {
112 101     101   150 my $in = shift;
113 101 100       350 return $in if !ref($in);
114              
115 24         31 my @kv;
116              
117 24 100       91 if (ref($in) eq 'HASH') {
    50          
118 19         100 while (my ($k, $v) = each %$in) {
119 67 100       92 if (ref($v)) {
120 3         29 push @kv, _expand($v);
121             }
122             else {
123 65         244 push @kv, [$k => $v];
124             }
125             }
126             }
127             elsif (ref($in) eq 'ARRAY') {
128 6 50       53 if (ref($in->[0]) eq 'ARRAY') {
129 1         22 for (@$in) {
130 0         0 my ($k, $v) = @$_;
131 0 0       0 if (ref($v)) {
132 0         0 push @kv, _expand($v);
133             }
134             else {
135 0         0 push @kv, [$k => $v];
136             }
137             }
138             }
139             else {
140 5         10 my $i;
141 5         15 for ($i = 0; $i < @$in; $i += 2) {
142 21         41 my ($k, $v) = ($in->[$i], $in->[$i+1]);
143 21 50       33 if (ref($v)) {
144 0         0 push @kv, _expand($v);
145             }
146             else {
147 21         77 push @kv, [$k => $v];
148             }
149             }
150             }
151             }
152              
153 23         113 return @kv;
154             }
155              
156             1;
157              
158             __END__