index = $index; $this->currentFileInfo = $currentFileInfo; $selectors = $this->emptySelectors(); $this->features = new Less_Tree_Value($features); $this->rules = array(new Less_Tree_Ruleset($selectors, $value)); $this->rules[0]->allowImports = true; } public function accept( $visitor ){ $this->features = $visitor->visitObj($this->features); $this->rules = $visitor->visitArray($this->rules); } /** * @see Less_Tree::genCSS */ public function genCSS( $output ){ $output->add( '@media ', $this->currentFileInfo, $this->index ); $this->features->genCSS( $output ); Less_Tree::outputRuleset( $output, $this->rules); } public function compile($env) { $media = new Less_Tree_Media(array(), array(), $this->index, $this->currentFileInfo ); $strictMathBypass = false; if( Less_Parser::$options['strictMath'] === false) { $strictMathBypass = true; Less_Parser::$options['strictMath'] = true; } $media->features = $this->features->compile($env); if( $strictMathBypass ){ Less_Parser::$options['strictMath'] = false; } $env->mediaPath[] = $media; $env->mediaBlocks[] = $media; array_unshift($env->frames, $this->rules[0]); $media->rules = array($this->rules[0]->compile($env)); array_shift($env->frames); array_pop($env->mediaPath); return !$env->mediaPath ? $media->compileTop($env) : $media->compileNested($env); } public function variable($name) { return $this->rules[0]->variable($name); } public function find($selector) { return $this->rules[0]->find($selector, $this); } public function emptySelectors(){ $el = new Less_Tree_Element('','&', $this->index, $this->currentFileInfo ); $sels = array( new Less_Tree_Selector(array($el), array(), null, $this->index, $this->currentFileInfo) ); $sels[0]->mediaEmpty = true; return $sels; } public function markReferenced(){ $this->rules[0]->markReferenced(); $this->isReferenced = true; Less_Tree::ReferencedArray($this->rules[0]->rules); } // evaltop public function compileTop($env) { $result = $this; if (count($env->mediaBlocks) > 1) { $selectors = $this->emptySelectors(); $result = new Less_Tree_Ruleset($selectors, $env->mediaBlocks); $result->multiMedia = true; } $env->mediaBlocks = array(); $env->mediaPath = array(); return $result; } public function compileNested($env) { $path = array_merge($env->mediaPath, array($this)); // Extract the media-query conditions separated with `,` (OR). foreach ($path as $key => $p) { $value = $p->features instanceof Less_Tree_Value ? $p->features->value : $p->features; $path[$key] = is_array($value) ? $value : array($value); } // Trace all permutations to generate the resulting media-query. // // (a, b and c) with nested (d, e) -> // a and d // a and e // b and c and d // b and c and e $permuted = $this->permute($path); $expressions = array(); foreach($permuted as $path){ for( $i=0, $len=count($path); $i < $len; $i++){ $path[$i] = Less_Parser::is_method($path[$i], 'toCSS') ? $path[$i] : new Less_Tree_Anonymous($path[$i]); } for( $i = count($path) - 1; $i > 0; $i-- ){ array_splice($path, $i, 0, array(new Less_Tree_Anonymous('and'))); } $expressions[] = new Less_Tree_Expression($path); } $this->features = new Less_Tree_Value($expressions); // Fake a tree-node that doesn't output anything. return new Less_Tree_Ruleset(array(), array()); } public function permute($arr) { if (!$arr) return array(); if (count($arr) == 1) return $arr[0]; $result = array(); $rest = $this->permute(array_slice($arr, 1)); foreach ($rest as $r) { foreach ($arr[0] as $a) { $result[] = array_merge( is_array($a) ? $a : array($a), is_array($r) ? $r : array($r) ); } } return $result; } public function bubbleSelectors($selectors) { if( !$selectors) return; $this->rules = array(new Less_Tree_Ruleset( $selectors, array($this->rules[0]))); } }