Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
97.24% |
141 / 145 |
|
89.47% |
17 / 19 |
CRAP | |
0.00% |
0 / 1 |
Less_Visitor_toCSS | |
97.24% |
141 / 145 |
|
89.47% |
17 / 19 |
80 | |
0.00% |
0 / 1 |
__construct | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
run | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
visitDeclaration | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
visitMixinDefinition | |
100.00% |
2 / 2 |
|
100.00% |
1 / 1 |
1 | |||
visitExtend | |
100.00% |
1 / 1 |
|
100.00% |
1 / 1 |
1 | |||
visitComment | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
visitMedia | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
2 | |||
visitAtRule | |
95.24% |
20 / 21 |
|
0.00% |
0 / 1 |
10 | |||
checkPropertiesInRoot | |
57.14% |
4 / 7 |
|
0.00% |
0 / 1 |
8.83 | |||
visitRuleset | |
100.00% |
26 / 26 |
|
100.00% |
1 / 1 |
10 | |||
visitAnonymous | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
visitImport | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
3 | |||
visitRulesetRoot | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
3 | |||
visitRulesetPaths | |
100.00% |
9 / 9 |
|
100.00% |
1 / 1 |
6 | |||
_removeDuplicateRules | |
100.00% |
13 / 13 |
|
100.00% |
1 / 1 |
8 | |||
_mergeRules | |
100.00% |
27 / 27 |
|
100.00% |
1 / 1 |
11 | |||
toExpression | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
toValue | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
hasVisibleChild | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
7 |
1 | <?php |
2 | /** |
3 | * @private |
4 | */ |
5 | class Less_Visitor_toCSS extends Less_VisitorReplacing { |
6 | |
7 | private $charset; |
8 | |
9 | public function __construct() { |
10 | parent::__construct(); |
11 | } |
12 | |
13 | /** |
14 | * @param Less_Tree_Ruleset $root |
15 | */ |
16 | public function run( $root ) { |
17 | return $this->visitObj( $root ); |
18 | } |
19 | |
20 | public function visitDeclaration( $declNode ) { |
21 | if ( $declNode->variable ) { |
22 | return []; |
23 | } |
24 | return $declNode; |
25 | } |
26 | |
27 | public function visitMixinDefinition( $mixinNode ) { |
28 | // mixin definitions do not get eval'd - this means they keep state |
29 | // so we have to clear that state here so it isn't used if toCSS is called twice |
30 | $mixinNode->frames = []; |
31 | return []; |
32 | } |
33 | |
34 | public function visitExtend() { |
35 | return []; |
36 | } |
37 | |
38 | public function visitComment( $commentNode ) { |
39 | if ( $commentNode->isSilent() ) { |
40 | return []; |
41 | } |
42 | return $commentNode; |
43 | } |
44 | |
45 | public function visitMedia( $mediaNode, &$visitDeeper ) { |
46 | $mediaNode->accept( $this ); |
47 | $visitDeeper = false; |
48 | |
49 | if ( !$mediaNode->rules ) { |
50 | return []; |
51 | } |
52 | return $mediaNode; |
53 | } |
54 | |
55 | public function visitAtRule( $atRuleNode, &$visitDeeper ) { |
56 | if ( $atRuleNode->name === '@charset' ) { |
57 | if ( !$atRuleNode->getIsReferenced() ) { |
58 | return; |
59 | } |
60 | if ( isset( $this->charset ) && $this->charset ) { |
61 | // NOTE: Skip debugInfo handling (not implemented) |
62 | return; |
63 | } |
64 | $this->charset = true; |
65 | } |
66 | |
67 | if ( $atRuleNode->rules ) { |
68 | self::_mergeRules( $atRuleNode->rules[0]->rules ); |
69 | // process childs |
70 | $atRuleNode->accept( $this ); |
71 | $visitDeeper = false; |
72 | |
73 | // the directive was directly referenced and therefore needs to be shown in the output |
74 | if ( $atRuleNode->getIsReferenced() ) { |
75 | return $atRuleNode; |
76 | } |
77 | |
78 | if ( !$atRuleNode->rules ) { |
79 | return; |
80 | } |
81 | if ( $this->hasVisibleChild( $atRuleNode ) ) { |
82 | // marking as referenced in case the directive is stored inside another directive |
83 | $atRuleNode->markReferenced(); |
84 | return $atRuleNode; |
85 | } |
86 | // The directive was not directly referenced and does not contain anything that |
87 | //was referenced. Therefore it must not be shown in output. |
88 | return; |
89 | } else { |
90 | if ( !$atRuleNode->getIsReferenced() ) { |
91 | return; |
92 | } |
93 | } |
94 | |
95 | return $atRuleNode; |
96 | } |
97 | |
98 | public function checkPropertiesInRoot( $rulesetNode ) { |
99 | if ( !$rulesetNode->firstRoot ) { |
100 | return; |
101 | } |
102 | |
103 | foreach ( $rulesetNode->rules as $ruleNode ) { |
104 | if ( $ruleNode instanceof Less_Tree_Declaration && !$ruleNode->variable ) { |
105 | $msg = "properties must be inside selector blocks, they cannot be in the root. Index " . $ruleNode->index . |
106 | ( $ruleNode->currentFileInfo ? ' Filename: ' . $ruleNode->currentFileInfo['filename'] : null ); |
107 | throw new Less_Exception_Compiler( $msg ); |
108 | } |
109 | } |
110 | } |
111 | |
112 | public function visitRuleset( $rulesetNode, &$visitDeeper ) { |
113 | $visitDeeper = false; |
114 | |
115 | $this->checkPropertiesInRoot( $rulesetNode ); |
116 | |
117 | if ( $rulesetNode->root ) { |
118 | return $this->visitRulesetRoot( $rulesetNode ); |
119 | } |
120 | |
121 | $rulesets = []; |
122 | $rulesetNode->paths = $this->visitRulesetPaths( $rulesetNode ); |
123 | |
124 | // Compile rules and rulesets |
125 | $nodeRuleCnt = $rulesetNode->rules ? count( $rulesetNode->rules ) : 0; |
126 | for ( $i = 0; $i < $nodeRuleCnt; ) { |
127 | $rule = $rulesetNode->rules[$i]; |
128 | |
129 | if ( property_exists( $rule, 'rules' ) ) { |
130 | // visit because we are moving them out from being a child |
131 | $rulesets[] = $this->visitObj( $rule ); |
132 | array_splice( $rulesetNode->rules, $i, 1 ); |
133 | $nodeRuleCnt--; |
134 | continue; |
135 | } |
136 | $i++; |
137 | } |
138 | |
139 | // accept the visitor to remove rules and refactor itself |
140 | // then we can decide now whether we want it or not |
141 | if ( $nodeRuleCnt > 0 ) { |
142 | $rulesetNode->accept( $this ); |
143 | |
144 | if ( $rulesetNode->rules ) { |
145 | |
146 | if ( count( $rulesetNode->rules ) > 1 ) { |
147 | self::_mergeRules( $rulesetNode->rules ); |
148 | $this->_removeDuplicateRules( $rulesetNode->rules ); |
149 | } |
150 | |
151 | // now decide whether we keep the ruleset |
152 | if ( $rulesetNode->paths ) { |
153 | // array_unshift($rulesets, $rulesetNode); |
154 | array_splice( $rulesets, 0, 0, [ $rulesetNode ] ); |
155 | } |
156 | } |
157 | |
158 | } |
159 | |
160 | if ( count( $rulesets ) === 1 ) { |
161 | return $rulesets[0]; |
162 | } |
163 | return $rulesets; |
164 | } |
165 | |
166 | public function visitAnonymous( $anonymousNode ) { |
167 | if ( !$anonymousNode->getIsReferenced() ) { |
168 | return; |
169 | } |
170 | |
171 | $anonymousNode->accept( $this ); |