[ Index ]

PHP Cross Reference of Unnamed Project

title

Body

[close]

/lib/lessphp/Visitor/ -> toCSS.php (source)

   1  <?php
   2  
   3  /**
   4   * toCSS Visitor
   5   *
   6   * @package Less
   7   * @subpackage visitor
   8   */
   9  class Less_Visitor_toCSS extends Less_VisitorReplacing{
  10  
  11      private $charset;
  12  
  13  	public function __construct(){
  14          parent::__construct();
  15      }
  16  
  17      /**
  18       * @param Less_Tree_Ruleset $root
  19       */
  20  	public function run( $root ){
  21          return $this->visitObj($root);
  22      }
  23  
  24  	public function visitRule( $ruleNode ){
  25          if( $ruleNode->variable ){
  26              return array();
  27          }
  28          return $ruleNode;
  29      }
  30  
  31  	public function visitMixinDefinition($mixinNode){
  32          // mixin definitions do not get eval'd - this means they keep state
  33          // so we have to clear that state here so it isn't used if toCSS is called twice
  34          $mixinNode->frames = array();
  35          return array();
  36      }
  37  
  38  	public function visitExtend(){
  39          return array();
  40      }
  41  
  42  	public function visitComment( $commentNode ){
  43          if( $commentNode->isSilent() ){
  44              return array();
  45          }
  46          return $commentNode;
  47      }
  48  
  49  	public function visitMedia( $mediaNode, &$visitDeeper ){
  50          $mediaNode->accept($this);
  51          $visitDeeper = false;
  52  
  53          if( !$mediaNode->rules ){
  54              return array();
  55          }
  56          return $mediaNode;
  57      }
  58  
  59  	public function visitDirective( $directiveNode ){
  60          if( isset($directiveNode->currentFileInfo['reference']) && (!property_exists($directiveNode,'isReferenced') || !$directiveNode->isReferenced) ){
  61              return array();
  62          }
  63          if( $directiveNode->name === '@charset' ){
  64              // Only output the debug info together with subsequent @charset definitions
  65              // a comment (or @media statement) before the actual @charset directive would
  66              // be considered illegal css as it has to be on the first line
  67              if( isset($this->charset) && $this->charset ){
  68  
  69                  //if( $directiveNode->debugInfo ){
  70                  //    $comment = new Less_Tree_Comment('/* ' . str_replace("\n",'',$directiveNode->toCSS())." */\n");
  71                  //    $comment->debugInfo = $directiveNode->debugInfo;
  72                  //    return $this->visit($comment);
  73                  //}
  74  
  75  
  76                  return array();
  77              }
  78              $this->charset = true;
  79          }
  80          return $directiveNode;
  81      }
  82  
  83  	public function checkPropertiesInRoot( $rulesetNode ){
  84  
  85          if( !$rulesetNode->firstRoot ){
  86              return;
  87          }
  88  
  89          foreach($rulesetNode->rules as $ruleNode){
  90              if( $ruleNode instanceof Less_Tree_Rule && !$ruleNode->variable ){
  91                  $msg = "properties must be inside selector blocks, they cannot be in the root. Index ".$ruleNode->index.($ruleNode->currentFileInfo ? (' Filename: '.$ruleNode->currentFileInfo['filename']) : null);
  92                  throw new Less_Exception_Compiler($msg);
  93              }
  94          }
  95      }
  96  
  97  
  98  	public function visitRuleset( $rulesetNode, &$visitDeeper ){
  99  
 100          $visitDeeper = false;
 101  
 102          $this->checkPropertiesInRoot( $rulesetNode );
 103  
 104          if( $rulesetNode->root ){
 105              return $this->visitRulesetRoot( $rulesetNode );
 106          }
 107  
 108          $rulesets = array();
 109          $rulesetNode->paths = $this->visitRulesetPaths($rulesetNode);
 110  
 111  
 112          // Compile rules and rulesets
 113          $nodeRuleCnt = count($rulesetNode->rules);
 114          for( $i = 0; $i < $nodeRuleCnt; ){
 115              $rule = $rulesetNode->rules[$i];
 116  
 117              if( property_exists($rule,'rules') ){
 118                  // visit because we are moving them out from being a child
 119                  $rulesets[] = $this->visitObj($rule);
 120                  array_splice($rulesetNode->rules,$i,1);
 121                  $nodeRuleCnt--;
 122                  continue;
 123              }
 124              $i++;
 125          }
 126  
 127  
 128          // accept the visitor to remove rules and refactor itself
 129          // then we can decide now whether we want it or not
 130          if( $nodeRuleCnt > 0 ){
 131              $rulesetNode->accept($this);
 132  
 133              if( $rulesetNode->rules ){
 134  
 135                  if( count($rulesetNode->rules) >  1 ){
 136                      $this->_mergeRules( $rulesetNode->rules );
 137                      $this->_removeDuplicateRules( $rulesetNode->rules );
 138                  }
 139  
 140                  // now decide whether we keep the ruleset
 141                  if( $rulesetNode->paths ){
 142                      //array_unshift($rulesets, $rulesetNode);
 143                      array_splice($rulesets,0,0,array($rulesetNode));
 144                  }
 145              }
 146  
 147          }
 148  
 149  
 150          if( count($rulesets) === 1 ){
 151              return $rulesets[0];
 152          }
 153          return $rulesets;
 154      }
 155  
 156  
 157      /**
 158       * Helper function for visitiRuleset
 159       *
 160       * return array|Less_Tree_Ruleset
 161       */
 162  	private function visitRulesetRoot( $rulesetNode ){
 163          $rulesetNode->accept( $this );
 164          if( $rulesetNode->firstRoot || $rulesetNode->rules ){
 165              return $rulesetNode;
 166          }
 167          return array();
 168      }
 169  
 170  
 171      /**
 172       * Helper function for visitRuleset()
 173       *
 174       * @return array
 175       */
 176  	private function visitRulesetPaths($rulesetNode){
 177  
 178          $paths = array();
 179          foreach($rulesetNode->paths as $p){
 180              if( $p[0]->elements[0]->combinator === ' ' ){
 181                  $p[0]->elements[0]->combinator = '';
 182              }
 183  
 184              foreach($p as $pi){
 185                  if( $pi->getIsReferenced() && $pi->getIsOutput() ){
 186                      $paths[] = $p;
 187                      break;
 188                  }
 189              }
 190          }
 191  
 192          return $paths;
 193      }
 194  
 195  	protected function _removeDuplicateRules( &$rules ){
 196          // remove duplicates
 197          $ruleCache = array();
 198          for( $i = count($rules)-1; $i >= 0 ; $i-- ){
 199              $rule = $rules[$i];
 200              if( $rule instanceof Less_Tree_Rule || $rule instanceof Less_Tree_NameValue ){
 201  
 202                  if( !isset($ruleCache[$rule->name]) ){
 203                      $ruleCache[$rule->name] = $rule;
 204                  }else{
 205                      $ruleList =& $ruleCache[$rule->name];
 206  
 207                      if( $ruleList instanceof Less_Tree_Rule || $ruleList instanceof Less_Tree_NameValue ){
 208                          $ruleList = $ruleCache[$rule->name] = array( $ruleCache[$rule->name]->toCSS() );
 209                      }
 210  
 211                      $ruleCSS = $rule->toCSS();
 212                      if( array_search($ruleCSS,$ruleList) !== false ){
 213                          array_splice($rules,$i,1);
 214                      }else{
 215                          $ruleList[] = $ruleCSS;
 216                      }
 217                  }
 218              }
 219          }
 220      }
 221  
 222  	protected function _mergeRules( &$rules ){
 223          $groups = array();
 224  
 225          //obj($rules);
 226  
 227          $rules_len = count($rules);
 228          for( $i = 0; $i < $rules_len; $i++ ){
 229              $rule = $rules[$i];
 230  
 231              if( ($rule instanceof Less_Tree_Rule) && $rule->merge ){
 232  
 233                  $key = $rule->name;
 234                  if( $rule->important ){
 235                      $key .= ',!';
 236                  }
 237  
 238                  if( !isset($groups[$key]) ){
 239                      $groups[$key] = array();
 240                  }else{
 241                      array_splice($rules, $i--, 1);
 242                      $rules_len--;
 243                  }
 244  
 245                  $groups[$key][] = $rule;
 246              }
 247          }
 248  
 249  
 250          foreach($groups as $parts){
 251  
 252              if( count($parts) > 1 ){
 253                  $rule = $parts[0];
 254                  $spacedGroups = array();
 255                  $lastSpacedGroup = array();
 256                  $parts_mapped = array();
 257                  foreach($parts as $p){
 258                      if( $p->merge === '+' ){
 259                          if( $lastSpacedGroup ){
 260                              $spacedGroups[] = self::toExpression($lastSpacedGroup);
 261                          }
 262                          $lastSpacedGroup = array();
 263                      }
 264                      $lastSpacedGroup[] = $p;
 265                  }
 266  
 267                  $spacedGroups[] = self::toExpression($lastSpacedGroup);
 268                  $rule->value = self::toValue($spacedGroups);
 269              }
 270          }
 271  
 272      }
 273  
 274  	public static function toExpression($values){
 275          $mapped = array();
 276          foreach($values as $p){
 277              $mapped[] = $p->value;
 278          }
 279          return new Less_Tree_Expression( $mapped );
 280      }
 281  
 282  	public static function toValue($values){
 283          //return new Less_Tree_Value($values); ??
 284  
 285          $mapped = array();
 286          foreach($values as $p){
 287              $mapped[] = $p;
 288          }
 289          return new Less_Tree_Value($mapped);
 290      }
 291  }
 292  


Generated: Thu Aug 11 10:00:09 2016 Cross-referenced by PHPXref 0.7.1