File: /var/www/vhosts/uyarreklam.com.tr/httpdocs/Tree.tar
Alpha.php 0000644 00000001500 15155315057 0006305 0 ustar 00 <?php
/**
* Alpha
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Alpha extends Less_Tree{
public $value;
public $type = 'Alpha';
public function __construct($val){
$this->value = $val;
}
//function accept( $visitor ){
// $this->value = $visitor->visit( $this->value );
//}
public function compile($env){
if( is_object($this->value) ){
$this->value = $this->value->compile($env);
}
return $this;
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$output->add( "alpha(opacity=" );
if( is_string($this->value) ){
$output->add( $this->value );
}else{
$this->value->genCSS( $output);
}
$output->add( ')' );
}
public function toCSS(){
return "alpha(opacity=" . (is_string($this->value) ? $this->value : $this->value->toCSS()) . ")";
}
} Anonymous.php 0000644 00000002114 15155315057 0007252 0 ustar 00 <?php
/**
* Anonymous
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Anonymous extends Less_Tree{
public $value;
public $quote;
public $index;
public $mapLines;
public $currentFileInfo;
public $type = 'Anonymous';
/**
* @param integer $index
* @param boolean $mapLines
*/
public function __construct($value, $index = null, $currentFileInfo = null, $mapLines = null ){
$this->value = $value;
$this->index = $index;
$this->mapLines = $mapLines;
$this->currentFileInfo = $currentFileInfo;
}
public function compile(){
return new Less_Tree_Anonymous($this->value, $this->index, $this->currentFileInfo, $this->mapLines);
}
public function compare($x){
if( !is_object($x) ){
return -1;
}
$left = $this->toCSS();
$right = $x->toCSS();
if( $left === $right ){
return 0;
}
return $left < $right ? -1 : 1;
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$output->add( $this->value, $this->currentFileInfo, $this->index, $this->mapLines );
}
public function toCSS(){
return $this->value;
}
}
Assignment.php 0000644 00000001321 15155315057 0007371 0 ustar 00 <?php
/**
* Assignment
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Assignment extends Less_Tree{
public $key;
public $value;
public $type = 'Assignment';
public function __construct($key, $val) {
$this->key = $key;
$this->value = $val;
}
public function accept( $visitor ){
$this->value = $visitor->visitObj( $this->value );
}
public function compile($env) {
return new Less_Tree_Assignment( $this->key, $this->value->compile($env));
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$output->add( $this->key . '=' );
$this->value->genCSS( $output );
}
public function toCss(){
return $this->key . '=' . $this->value->toCSS();
}
}
Attribute.php 0000644 00000001717 15155315057 0007235 0 ustar 00 <?php
/**
* Attribute
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Attribute extends Less_Tree{
public $key;
public $op;
public $value;
public $type = 'Attribute';
public function __construct($key, $op, $value){
$this->key = $key;
$this->op = $op;
$this->value = $value;
}
public function compile($env){
$key_obj = is_object($this->key);
$val_obj = is_object($this->value);
if( !$key_obj && !$val_obj ){
return $this;
}
return new Less_Tree_Attribute(
$key_obj ? $this->key->compile($env) : $this->key ,
$this->op,
$val_obj ? $this->value->compile($env) : $this->value);
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$output->add( $this->toCSS() );
}
public function toCSS(){
$value = $this->key;
if( $this->op ){
$value .= $this->op;
$value .= (is_object($this->value) ? $this->value->toCSS() : $this->value);
}
return '[' . $value . ']';
}
} Call.php 0000644 00000005515 15155315057 0006145 0 ustar 00 <?php
/**
* Call
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Call extends Less_Tree{
public $value;
public $name;
public $args;
public $index;
public $currentFileInfo;
public $type = 'Call';
public function __construct($name, $args, $index, $currentFileInfo = null ){
$this->name = $name;
$this->args = $args;
$this->index = $index;
$this->currentFileInfo = $currentFileInfo;
}
public function accept( $visitor ){
$this->args = $visitor->visitArray( $this->args );
}
//
// When evaluating a function call,
// we either find the function in `tree.functions` [1],
// in which case we call it, passing the evaluated arguments,
// or we simply print it out as it appeared originally [2].
//
// The *functions.js* file contains the built-in functions.
//
// The reason why we evaluate the arguments, is in the case where
// we try to pass a variable to a function, like: `saturate(@color)`.
// The function should receive the value, not the variable.
//
public function compile($env=null){
$args = array();
foreach($this->args as $a){
$args[] = $a->compile($env);
}
$nameLC = strtolower($this->name);
switch($nameLC){
case '%':
$nameLC = '_percent';
break;
case 'get-unit':
$nameLC = 'getunit';
break;
case 'data-uri':
$nameLC = 'datauri';
break;
case 'svg-gradient':
$nameLC = 'svggradient';
break;
}
$result = null;
if( $nameLC === 'default' ){
$result = Less_Tree_DefaultFunc::compile();
}else{
if( method_exists('Less_Functions',$nameLC) ){ // 1.
try {
$func = new Less_Functions($env, $this->currentFileInfo);
$result = call_user_func_array( array($func,$nameLC),$args);
} catch (Exception $e) {
throw new Less_Exception_Compiler('error evaluating function `' . $this->name . '` '.$e->getMessage().' index: '. $this->index);
}
} elseif( isset( $env->functions[$nameLC] ) && is_callable( $env->functions[$nameLC] ) ) {
try {
$result = call_user_func_array( $env->functions[$nameLC], $args );
} catch (Exception $e) {
throw new Less_Exception_Compiler('error evaluating function `' . $this->name . '` '.$e->getMessage().' index: '. $this->index);
}
}
}
if( $result !== null ){
return $result;
}
return new Less_Tree_Call( $this->name, $args, $this->index, $this->currentFileInfo );
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$output->add( $this->name . '(', $this->currentFileInfo, $this->index );
$args_len = count($this->args);
for($i = 0; $i < $args_len; $i++ ){
$this->args[$i]->genCSS( $output );
if( $i + 1 < $args_len ){
$output->add( ', ' );
}
}
$output->add( ')' );
}
//public function toCSS(){
// return $this->compile()->toCSS();
//}
}
Color.php 0000644 00000012170 15155315057 0006343 0 ustar 00 <?php
/**
* Color
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Color extends Less_Tree{
public $rgb;
public $alpha;
public $isTransparentKeyword;
public $type = 'Color';
public function __construct($rgb, $a = 1, $isTransparentKeyword = null ){
if( $isTransparentKeyword ){
$this->rgb = $rgb;
$this->alpha = $a;
$this->isTransparentKeyword = true;
return;
}
$this->rgb = array();
if( is_array($rgb) ){
$this->rgb = $rgb;
}else if( strlen($rgb) == 6 ){
foreach(str_split($rgb, 2) as $c){
$this->rgb[] = hexdec($c);
}
}else{
foreach(str_split($rgb, 1) as $c){
$this->rgb[] = hexdec($c.$c);
}
}
$this->alpha = is_numeric($a) ? $a : 1;
}
public function compile(){
return $this;
}
public function luma(){
$r = $this->rgb[0] / 255;
$g = $this->rgb[1] / 255;
$b = $this->rgb[2] / 255;
$r = ($r <= 0.03928) ? $r / 12.92 : pow((($r + 0.055) / 1.055), 2.4);
$g = ($g <= 0.03928) ? $g / 12.92 : pow((($g + 0.055) / 1.055), 2.4);
$b = ($b <= 0.03928) ? $b / 12.92 : pow((($b + 0.055) / 1.055), 2.4);
return 0.2126 * $r + 0.7152 * $g + 0.0722 * $b;
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$output->add( $this->toCSS() );
}
public function toCSS( $doNotCompress = false ){
$compress = Less_Parser::$options['compress'] && !$doNotCompress;
$alpha = Less_Functions::fround( $this->alpha );
//
// If we have some transparency, the only way to represent it
// is via `rgba`. Otherwise, we use the hex representation,
// which has better compatibility with older browsers.
// Values are capped between `0` and `255`, rounded and zero-padded.
//
if( $alpha < 1 ){
if( ( $alpha === 0 || $alpha === 0.0 ) && isset($this->isTransparentKeyword) && $this->isTransparentKeyword ){
return 'transparent';
}
$values = array();
foreach($this->rgb as $c){
$values[] = Less_Functions::clamp( round($c), 255);
}
$values[] = $alpha;
$glue = ($compress ? ',' : ', ');
return "rgba(" . implode($glue, $values) . ")";
}else{
$color = $this->toRGB();
if( $compress ){
// Convert color to short format
if( $color[1] === $color[2] && $color[3] === $color[4] && $color[5] === $color[6]) {
$color = '#'.$color[1] . $color[3] . $color[5];
}
}
return $color;
}
}
//
// Operations have to be done per-channel, if not,
// channels will spill onto each other. Once we have
// our result, in the form of an integer triplet,
// we create a new Color node to hold the result.
//
/**
* @param string $op
*/
public function operate( $op, $other) {
$rgb = array();
$alpha = $this->alpha * (1 - $other->alpha) + $other->alpha;
for ($c = 0; $c < 3; $c++) {
$rgb[$c] = Less_Functions::operate( $op, $this->rgb[$c], $other->rgb[$c]);
}
return new Less_Tree_Color($rgb, $alpha);
}
public function toRGB(){
return $this->toHex($this->rgb);
}
public function toHSL(){
$r = $this->rgb[0] / 255;
$g = $this->rgb[1] / 255;
$b = $this->rgb[2] / 255;
$a = $this->alpha;
$max = max($r, $g, $b);
$min = min($r, $g, $b);
$l = ($max + $min) / 2;
$d = $max - $min;
$h = $s = 0;
if( $max !== $min ){
$s = $l > 0.5 ? $d / (2 - $max - $min) : $d / ($max + $min);
switch ($max) {
case $r: $h = ($g - $b) / $d + ($g < $b ? 6 : 0); break;
case $g: $h = ($b - $r) / $d + 2; break;
case $b: $h = ($r - $g) / $d + 4; break;
}
$h /= 6;
}
return array('h' => $h * 360, 's' => $s, 'l' => $l, 'a' => $a );
}
//Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
public function toHSV() {
$r = $this->rgb[0] / 255;
$g = $this->rgb[1] / 255;
$b = $this->rgb[2] / 255;
$a = $this->alpha;
$max = max($r, $g, $b);
$min = min($r, $g, $b);
$v = $max;
$d = $max - $min;
if ($max === 0) {
$s = 0;
} else {
$s = $d / $max;
}
$h = 0;
if( $max !== $min ){
switch($max){
case $r: $h = ($g - $b) / $d + ($g < $b ? 6 : 0); break;
case $g: $h = ($b - $r) / $d + 2; break;
case $b: $h = ($r - $g) / $d + 4; break;
}
$h /= 6;
}
return array('h'=> $h * 360, 's'=> $s, 'v'=> $v, 'a' => $a );
}
public function toARGB(){
$argb = array_merge( (array) Less_Parser::round($this->alpha * 255), $this->rgb);
return $this->toHex( $argb );
}
public function compare($x){
if( !property_exists( $x, 'rgb' ) ){
return -1;
}
return ($x->rgb[0] === $this->rgb[0] &&
$x->rgb[1] === $this->rgb[1] &&
$x->rgb[2] === $this->rgb[2] &&
$x->alpha === $this->alpha) ? 0 : -1;
}
public function toHex( $v ){
$ret = '#';
foreach($v as $c){
$c = Less_Functions::clamp( Less_Parser::round($c), 255);
if( $c < 16 ){
$ret .= '0';
}
$ret .= dechex($c);
}
return $ret;
}
/**
* @param string $keyword
*/
public static function fromKeyword( $keyword ){
$keyword = strtolower($keyword);
if( Less_Colors::hasOwnProperty($keyword) ){
// detect named color
return new Less_Tree_Color(substr(Less_Colors::color($keyword), 1));
}
if( $keyword === 'transparent' ){
return new Less_Tree_Color( array(0, 0, 0), 0, true);
}
}
}
Comment.php 0000644 00000002350 15155315057 0006666 0 ustar 00 <?php
/**
* Comment
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Comment extends Less_Tree{
public $value;
public $silent;
public $isReferenced;
public $currentFileInfo;
public $type = 'Comment';
public function __construct($value, $silent, $index = null, $currentFileInfo = null ){
$this->value = $value;
$this->silent = !! $silent;
$this->currentFileInfo = $currentFileInfo;
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
//if( $this->debugInfo ){
//$output->add( tree.debugInfo($env, $this), $this->currentFileInfo, $this->index);
//}
$output->add( trim($this->value) );//TODO shouldn't need to trim, we shouldn't grab the \n
}
public function toCSS(){
return Less_Parser::$options['compress'] ? '' : $this->value;
}
public function isSilent(){
$isReference = ($this->currentFileInfo && isset($this->currentFileInfo['reference']) && (!isset($this->isReferenced) || !$this->isReferenced) );
$isCompressed = Less_Parser::$options['compress'] && !preg_match('/^\/\*!/', $this->value);
return $this->silent || $isReference || $isCompressed;
}
public function compile(){
return $this;
}
public function markReferenced(){
$this->isReferenced = true;
}
}
Condition.php 0000644 00000002731 15155315057 0007215 0 ustar 00 <?php
/**
* Condition
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Condition extends Less_Tree{
public $op;
public $lvalue;
public $rvalue;
public $index;
public $negate;
public $type = 'Condition';
public function __construct($op, $l, $r, $i = 0, $negate = false) {
$this->op = trim($op);
$this->lvalue = $l;
$this->rvalue = $r;
$this->index = $i;
$this->negate = $negate;
}
public function accept($visitor){
$this->lvalue = $visitor->visitObj( $this->lvalue );
$this->rvalue = $visitor->visitObj( $this->rvalue );
}
public function compile($env) {
$a = $this->lvalue->compile($env);
$b = $this->rvalue->compile($env);
switch( $this->op ){
case 'and':
$result = $a && $b;
break;
case 'or':
$result = $a || $b;
break;
default:
if( Less_Parser::is_method($a, 'compare') ){
$result = $a->compare($b);
}elseif( Less_Parser::is_method($b, 'compare') ){
$result = $b->compare($a);
}else{
throw new Less_Exception_Compiler('Unable to perform comparison', null, $this->index);
}
switch ($result) {
case -1:
$result = $this->op === '<' || $this->op === '=<' || $this->op === '<=';
break;
case 0:
$result = $this->op === '=' || $this->op === '>=' || $this->op === '=<' || $this->op === '<=';
break;
case 1:
$result = $this->op === '>' || $this->op === '>=';
break;
}
break;
}
return $this->negate ? !$result : $result;
}
}
DefaultFunc.php 0000644 00000001105 15155315057 0007461 0 ustar 00 <?php
/**
* DefaultFunc
*
* @package Less
* @subpackage tree
*/
class Less_Tree_DefaultFunc{
static $error_;
static $value_;
public static function compile(){
if( self::$error_ ){
throw new Exception(self::$error_);
}
if( self::$value_ !== null ){
return self::$value_ ? new Less_Tree_Keyword('true') : new Less_Tree_Keyword('false');
}
}
public static function value( $v ){
self::$value_ = $v;
}
public static function error( $e ){
self::$error_ = $e;
}
public static function reset(){
self::$value_ = self::$error_ = null;
}
} DetachedRuleset.php 0000644 00000001466 15155315057 0010340 0 ustar 00 <?php
/**
* DetachedRuleset
*
* @package Less
* @subpackage tree
*/
class Less_Tree_DetachedRuleset extends Less_Tree{
public $ruleset;
public $frames;
public $type = 'DetachedRuleset';
public function __construct( $ruleset, $frames = null ){
$this->ruleset = $ruleset;
$this->frames = $frames;
}
public function accept($visitor) {
$this->ruleset = $visitor->visitObj($this->ruleset);
}
public function compile($env){
if( $this->frames ){
$frames = $this->frames;
}else{
$frames = $env->frames;
}
return new Less_Tree_DetachedRuleset($this->ruleset, $frames);
}
public function callEval($env) {
if( $this->frames ){
return $this->ruleset->compile( $env->copyEvalEnv( array_merge($this->frames,$env->frames) ) );
}
return $this->ruleset->compile( $env );
}
}
Dimension.php 0000644 00000012212 15155315057 0007207 0 ustar 00 <?php
/**
* Dimension
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Dimension extends Less_Tree{
public $value;
public $unit;
public $type = 'Dimension';
public function __construct($value, $unit = null){
$this->value = floatval($value);
if( $unit && ($unit instanceof Less_Tree_Unit) ){
$this->unit = $unit;
}elseif( $unit ){
$this->unit = new Less_Tree_Unit( array($unit) );
}else{
$this->unit = new Less_Tree_Unit( );
}
}
public function accept( $visitor ){
$this->unit = $visitor->visitObj( $this->unit );
}
public function compile(){
return $this;
}
public function toColor() {
return new Less_Tree_Color(array($this->value, $this->value, $this->value));
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
if( Less_Parser::$options['strictUnits'] && !$this->unit->isSingular() ){
throw new Less_Exception_Compiler("Multiple units in dimension. Correct the units or use the unit function. Bad unit: ".$this->unit->toString());
}
$value = Less_Functions::fround( $this->value );
$strValue = (string)$value;
if( $value !== 0 && $value < 0.000001 && $value > -0.000001 ){
// would be output 1e-6 etc.
$strValue = number_format($strValue,10);
$strValue = preg_replace('/\.?0+$/','', $strValue);
}
if( Less_Parser::$options['compress'] ){
// Zero values doesn't need a unit
if( $value === 0 && $this->unit->isLength() ){
$output->add( $strValue );
return $strValue;
}
// Float values doesn't need a leading zero
if( $value > 0 && $value < 1 && $strValue[0] === '0' ){
$strValue = substr($strValue,1);
}
}
$output->add( $strValue );
$this->unit->genCSS( $output );
}
public function __toString(){
return $this->toCSS();
}
// In an operation between two Dimensions,
// we default to the first Dimension's unit,
// so `1px + 2em` will yield `3px`.
/**
* @param string $op
*/
public function operate( $op, $other){
$value = Less_Functions::operate( $op, $this->value, $other->value);
$unit = clone $this->unit;
if( $op === '+' || $op === '-' ){
if( !$unit->numerator && !$unit->denominator ){
$unit->numerator = $other->unit->numerator;
$unit->denominator = $other->unit->denominator;
}elseif( !$other->unit->numerator && !$other->unit->denominator ){
// do nothing
}else{
$other = $other->convertTo( $this->unit->usedUnits());
if( Less_Parser::$options['strictUnits'] && $other->unit->toString() !== $unit->toCSS() ){
throw new Less_Exception_Compiler("Incompatible units. Change the units or use the unit function. Bad units: '" . $unit->toString() . "' and " . $other->unit->toString() . "'.");
}
$value = Less_Functions::operate( $op, $this->value, $other->value);
}
}elseif( $op === '*' ){
$unit->numerator = array_merge($unit->numerator, $other->unit->numerator);
$unit->denominator = array_merge($unit->denominator, $other->unit->denominator);
sort($unit->numerator);
sort($unit->denominator);
$unit->cancel();
}elseif( $op === '/' ){
$unit->numerator = array_merge($unit->numerator, $other->unit->denominator);
$unit->denominator = array_merge($unit->denominator, $other->unit->numerator);
sort($unit->numerator);
sort($unit->denominator);
$unit->cancel();
}
return new Less_Tree_Dimension( $value, $unit);
}
public function compare($other) {
if ($other instanceof Less_Tree_Dimension) {
if( $this->unit->isEmpty() || $other->unit->isEmpty() ){
$a = $this;
$b = $other;
} else {
$a = $this->unify();
$b = $other->unify();
if( $a->unit->compare($b->unit) !== 0 ){
return -1;
}
}
$aValue = $a->value;
$bValue = $b->value;
if ($bValue > $aValue) {
return -1;
} elseif ($bValue < $aValue) {
return 1;
} else {
return 0;
}
} else {
return -1;
}
}
public function unify() {
return $this->convertTo(array('length'=> 'px', 'duration'=> 's', 'angle' => 'rad' ));
}
public function convertTo($conversions) {
$value = $this->value;
$unit = clone $this->unit;
if( is_string($conversions) ){
$derivedConversions = array();
foreach( Less_Tree_UnitConversions::$groups as $i ){
if( isset(Less_Tree_UnitConversions::${$i}[$conversions]) ){
$derivedConversions = array( $i => $conversions);
}
}
$conversions = $derivedConversions;
}
foreach($conversions as $groupName => $targetUnit){
$group = Less_Tree_UnitConversions::${$groupName};
//numerator
foreach($unit->numerator as $i => $atomicUnit){
$atomicUnit = $unit->numerator[$i];
if( !isset($group[$atomicUnit]) ){
continue;
}
$value = $value * ($group[$atomicUnit] / $group[$targetUnit]);
$unit->numerator[$i] = $targetUnit;
}
//denominator
foreach($unit->denominator as $i => $atomicUnit){
$atomicUnit = $unit->denominator[$i];
if( !isset($group[$atomicUnit]) ){
continue;
}
$value = $value / ($group[$atomicUnit] / $group[$targetUnit]);
$unit->denominator[$i] = $targetUnit;
}
}
$unit->cancel();
return new Less_Tree_Dimension( $value, $unit);
}
}
Directive.php 0000644 00000004032 15155315057 0007201 0 ustar 00 <?php
/**
* Directive
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Directive extends Less_Tree{
public $name;
public $value;
public $rules;
public $index;
public $isReferenced;
public $currentFileInfo;
public $debugInfo;
public $type = 'Directive';
public function __construct($name, $value = null, $rules = null, $index = null, $currentFileInfo = null, $debugInfo = null ){
$this->name = $name;
$this->value = $value;
if( $rules ){
$this->rules = $rules;
$this->rules->allowImports = true;
}
$this->index = $index;
$this->currentFileInfo = $currentFileInfo;
$this->debugInfo = $debugInfo;
}
public function accept( $visitor ){
if( $this->rules ){
$this->rules = $visitor->visitObj( $this->rules );
}
if( $this->value ){
$this->value = $visitor->visitObj( $this->value );
}
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$value = $this->value;
$rules = $this->rules;
$output->add( $this->name, $this->currentFileInfo, $this->index );
if( $this->value ){
$output->add(' ');
$this->value->genCSS($output);
}
if( $this->rules ){
Less_Tree::outputRuleset( $output, array($this->rules));
} else {
$output->add(';');
}
}
public function compile($env){
$value = $this->value;
$rules = $this->rules;
if( $value ){
$value = $value->compile($env);
}
if( $rules ){
$rules = $rules->compile($env);
$rules->root = true;
}
return new Less_Tree_Directive( $this->name, $value, $rules, $this->index, $this->currentFileInfo, $this->debugInfo );
}
public function variable($name){
if( $this->rules ){
return $this->rules->variable($name);
}
}
public function find($selector){
if( $this->rules ){
return $this->rules->find($selector, $this);
}
}
//rulesets: function () { if (this.rules) return tree.Ruleset.prototype.rulesets.apply(this.rules); },
public function markReferenced(){
$this->isReferenced = true;
if( $this->rules ){
Less_Tree::ReferencedArray($this->rules->rules);
}
}
}
Element.php 0000644 00000002760 15155315057 0006662 0 ustar 00 <?php
/**
* Element
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Element extends Less_Tree{
public $combinator = '';
public $value = '';
public $index;
public $currentFileInfo;
public $type = 'Element';
public $value_is_object = false;
public function __construct($combinator, $value, $index = null, $currentFileInfo = null ){
$this->value = $value;
$this->value_is_object = is_object($value);
if( $combinator ){
$this->combinator = $combinator;
}
$this->index = $index;
$this->currentFileInfo = $currentFileInfo;
}
public function accept( $visitor ){
if( $this->value_is_object ){ //object or string
$this->value = $visitor->visitObj( $this->value );
}
}
public function compile($env){
if( Less_Environment::$mixin_stack ){
return new Less_Tree_Element($this->combinator, ($this->value_is_object ? $this->value->compile($env) : $this->value), $this->index, $this->currentFileInfo );
}
if( $this->value_is_object ){
$this->value = $this->value->compile($env);
}
return $this;
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$output->add( $this->toCSS(), $this->currentFileInfo, $this->index );
}
public function toCSS(){
if( $this->value_is_object ){
$value = $this->value->toCSS();
}else{
$value = $this->value;
}
if( $value === '' && $this->combinator && $this->combinator === '&' ){
return '';
}
return Less_Environment::$_outputMap[$this->combinator] . $value;
}
}
Expression.php 0000644 00000003506 15155315057 0007427 0 ustar 00 <?php
/**
* Expression
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Expression extends Less_Tree{
public $value = array();
public $parens = false;
public $parensInOp = false;
public $type = 'Expression';
public function __construct( $value, $parens = null ){
$this->value = $value;
$this->parens = $parens;
}
public function accept( $visitor ){
$this->value = $visitor->visitArray( $this->value );
}
public function compile($env) {
$doubleParen = false;
if( $this->parens && !$this->parensInOp ){
Less_Environment::$parensStack++;
}
$returnValue = null;
if( $this->value ){
$count = count($this->value);
if( $count > 1 ){
$ret = array();
foreach($this->value as $e){
$ret[] = $e->compile($env);
}
$returnValue = new Less_Tree_Expression($ret);
}else{
if( ($this->value[0] instanceof Less_Tree_Expression) && $this->value[0]->parens && !$this->value[0]->parensInOp ){
$doubleParen = true;
}
$returnValue = $this->value[0]->compile($env);
}
} else {
$returnValue = $this;
}
if( $this->parens ){
if( !$this->parensInOp ){
Less_Environment::$parensStack--;
}elseif( !Less_Environment::isMathOn() && !$doubleParen ){
$returnValue = new Less_Tree_Paren($returnValue);
}
}
return $returnValue;
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$val_len = count($this->value);
for( $i = 0; $i < $val_len; $i++ ){
$this->value[$i]->genCSS( $output );
if( $i + 1 < $val_len ){
$output->add( ' ' );
}
}
}
public function throwAwayComments() {
if( is_array($this->value) ){
$new_value = array();
foreach($this->value as $v){
if( $v instanceof Less_Tree_Comment ){
continue;
}
$new_value[] = $v;
}
$this->value = $new_value;
}
}
}
Extend.php 0000644 00000003665 15155315057 0006525 0 ustar 00 <?php
/**
* Extend
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Extend extends Less_Tree{
public $selector;
public $option;
public $index;
public $selfSelectors = array();
public $allowBefore;
public $allowAfter;
public $firstExtendOnThisSelectorPath;
public $type = 'Extend';
public $ruleset;
public $object_id;
public $parent_ids = array();
/**
* @param integer $index
*/
public function __construct($selector, $option, $index){
static $i = 0;
$this->selector = $selector;
$this->option = $option;
$this->index = $index;
switch($option){
case "all":
$this->allowBefore = true;
$this->allowAfter = true;
break;
default:
$this->allowBefore = false;
$this->allowAfter = false;
break;
}
// This must use a string (instead of int) so that array_merge()
// preserves keys on arrays that use IDs in their keys.
$this->object_id = 'id_' . $i++;
$this->parent_ids = array(
$this->object_id => true
);
}
public function accept( $visitor ){
$this->selector = $visitor->visitObj( $this->selector );
}
public function compile( $env ){
Less_Parser::$has_extends = true;
$this->selector = $this->selector->compile($env);
return $this;
//return new Less_Tree_Extend( $this->selector->compile($env), $this->option, $this->index);
}
public function findSelfSelectors( $selectors ){
$selfElements = array();
for( $i = 0, $selectors_len = count($selectors); $i < $selectors_len; $i++ ){
$selectorElements = $selectors[$i]->elements;
// duplicate the logic in genCSS function inside the selector node.
// future TODO - move both logics into the selector joiner visitor
if( $i && $selectorElements && $selectorElements[0]->combinator === "") {
$selectorElements[0]->combinator = ' ';
}
$selfElements = array_merge( $selfElements, $selectors[$i]->elements );
}
$this->selfSelectors = array(new Less_Tree_Selector($selfElements));
}
}
Import.php 0000644 00000020333 15155315057 0006537 0 ustar 00 <?php
/**
* CSS @import node
*
* The general strategy here is that we don't want to wait
* for the parsing to be completed, before we start importing
* the file. That's because in the context of a browser,
* most of the time will be spent waiting for the server to respond.
*
* On creation, we push the import path to our import queue, though
* `import,push`, we also pass it a callback, which it'll call once
* the file has been fetched, and parsed.
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Import extends Less_Tree{
public $options;
public $index;
public $path;
public $features;
public $currentFileInfo;
public $css;
public $skip;
public $root;
public $type = 'Import';
public function __construct($path, $features, $options, $index, $currentFileInfo = null ){
$this->options = $options;
$this->index = $index;
$this->path = $path;
$this->features = $features;
$this->currentFileInfo = $currentFileInfo;
if( is_array($options) ){
$this->options += array('inline'=>false);
if( isset($this->options['less']) || $this->options['inline'] ){
$this->css = !isset($this->options['less']) || !$this->options['less'] || $this->options['inline'];
} else {
$pathValue = $this->getPath();
if( $pathValue && preg_match('/css([\?;].*)?$/',$pathValue) ){
$this->css = true;
}
}
}
}
//
// The actual import node doesn't return anything, when converted to CSS.
// The reason is that it's used at the evaluation stage, so that the rules
// it imports can be treated like any other rules.
//
// In `eval`, we make sure all Import nodes get evaluated, recursively, so
// we end up with a flat structure, which can easily be imported in the parent
// ruleset.
//
public function accept($visitor){
if( $this->features ){
$this->features = $visitor->visitObj($this->features);
}
$this->path = $visitor->visitObj($this->path);
if( !$this->options['inline'] && $this->root ){
$this->root = $visitor->visit($this->root);
}
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
if( $this->css ){
$output->add( '@import ', $this->currentFileInfo, $this->index );
$this->path->genCSS( $output );
if( $this->features ){
$output->add( ' ' );
$this->features->genCSS( $output );
}
$output->add( ';' );
}
}
public function toCSS(){
$features = $this->features ? ' ' . $this->features->toCSS() : '';
if ($this->css) {
return "@import " . $this->path->toCSS() . $features . ";\n";
} else {
return "";
}
}
/**
* @return string
*/
public function getPath(){
if ($this->path instanceof Less_Tree_Quoted) {
$path = $this->path->value;
$path = ( isset($this->css) || preg_match('/(\.[a-z]*$)|([\?;].*)$/',$path)) ? $path : $path . '.less';
} else if ($this->path instanceof Less_Tree_URL) {
$path = $this->path->value->value;
}else{
return null;
}
//remove query string and fragment
return preg_replace('/[\?#][^\?]*$/','',$path);
}
public function compileForImport( $env ){
return new Less_Tree_Import( $this->path->compile($env), $this->features, $this->options, $this->index, $this->currentFileInfo);
}
public function compilePath($env) {
$path = $this->path->compile($env);
$rootpath = '';
if( $this->currentFileInfo && $this->currentFileInfo['rootpath'] ){
$rootpath = $this->currentFileInfo['rootpath'];
}
if( !($path instanceof Less_Tree_URL) ){
if( $rootpath ){
$pathValue = $path->value;
// Add the base path if the import is relative
if( $pathValue && Less_Environment::isPathRelative($pathValue) ){
$path->value = $this->currentFileInfo['uri_root'].$pathValue;
}
}
$path->value = Less_Environment::normalizePath($path->value);
}
return $path;
}
public function compile( $env ){
$evald = $this->compileForImport($env);
//get path & uri
$path_and_uri = null;
if( is_callable(Less_Parser::$options['import_callback']) ){
$path_and_uri = call_user_func(Less_Parser::$options['import_callback'],$evald);
}
if( !$path_and_uri ){
$path_and_uri = $evald->PathAndUri();
}
if( $path_and_uri ){
list($full_path, $uri) = $path_and_uri;
}else{
$full_path = $uri = $evald->getPath();
}
//import once
if( $evald->skip( $full_path, $env) ){
return array();
}
if( $this->options['inline'] ){
//todo needs to reference css file not import
//$contents = new Less_Tree_Anonymous($this->root, 0, array('filename'=>$this->importedFilename), true );
Less_Parser::AddParsedFile($full_path);
$contents = new Less_Tree_Anonymous( file_get_contents($full_path), 0, array(), true );
if( $this->features ){
return new Less_Tree_Media( array($contents), $this->features->value );
}
return array( $contents );
}
// optional (need to be before "CSS" to support optional CSS imports. CSS should be checked only if empty($this->currentFileInfo))
if( isset($this->options['optional']) && $this->options['optional'] && !file_exists($full_path) && (!$evald->css || !empty($this->currentFileInfo))) {
return array();
}
// css ?
if( $evald->css ){
$features = ( $evald->features ? $evald->features->compile($env) : null );
return new Less_Tree_Import( $this->compilePath( $env), $features, $this->options, $this->index);
}
return $this->ParseImport( $full_path, $uri, $env );
}
/**
* Using the import directories, get the full absolute path and uri of the import
*
* @param Less_Tree_Import $evald
*/
public function PathAndUri(){
$evald_path = $this->getPath();
if( $evald_path ){
$import_dirs = array();
if( Less_Environment::isPathRelative($evald_path) ){
//if the path is relative, the file should be in the current directory
if ( $this->currentFileInfo ){
$import_dirs[ $this->currentFileInfo['currentDirectory'] ] = $this->currentFileInfo['uri_root'];
}
}else{
//otherwise, the file should be relative to the server root
if( $this->currentFileInfo ) {
$import_dirs[ $this->currentFileInfo['entryPath'] ] = $this->currentFileInfo['entryUri'];
}
//if the user supplied entryPath isn't the actual root
$import_dirs[ $_SERVER['DOCUMENT_ROOT'] ] = '';
}
// always look in user supplied import directories
$import_dirs = array_merge( $import_dirs, Less_Parser::$options['import_dirs'] );
foreach( $import_dirs as $rootpath => $rooturi){
if( is_callable($rooturi) ){
list($path, $uri) = call_user_func($rooturi, $evald_path);
if( is_string($path) ){
$full_path = $path;
return array( $full_path, $uri );
}
}elseif( !empty($rootpath) ){
$path = rtrim($rootpath,'/\\').'/'.ltrim($evald_path,'/\\');
if( file_exists($path) ){
$full_path = Less_Environment::normalizePath($path);
$uri = Less_Environment::normalizePath(dirname($rooturi.$evald_path));
return array( $full_path, $uri );
} elseif( file_exists($path.'.less') ){
$full_path = Less_Environment::normalizePath($path.'.less');
$uri = Less_Environment::normalizePath(dirname($rooturi.$evald_path.'.less'));
return array( $full_path, $uri );
}
}
}
}
}
/**
* Parse the import url and return the rules
*
* @return Less_Tree_Media|array
*/
public function ParseImport( $full_path, $uri, $env ){
$import_env = clone $env;
if( (isset($this->options['reference']) && $this->options['reference']) || isset($this->currentFileInfo['reference']) ){
$import_env->currentFileInfo['reference'] = true;
}
if( (isset($this->options['multiple']) && $this->options['multiple']) ){
$import_env->importMultiple = true;
}
$parser = new Less_Parser($import_env);
$root = $parser->parseFile($full_path, $uri, true);
$ruleset = new Less_Tree_Ruleset(array(), $root->rules );
$ruleset->evalImports($import_env);
return $this->features ? new Less_Tree_Media($ruleset->rules, $this->features->value) : $ruleset->rules;
}
/**
* Should the import be skipped?
*
* @return boolean|null
*/
private function Skip($path, $env){
$path = Less_Parser::AbsPath($path, true);
if( $path && Less_Parser::FileParsed($path) ){
if( isset($this->currentFileInfo['reference']) ){
return true;
}
return !isset($this->options['multiple']) && !$env->importMultiple;
}
}
}
Javascript.php 0000644 00000001036 15155315057 0007372 0 ustar 00 <?php
/**
* Javascript
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Javascript extends Less_Tree{
public $type = 'Javascript';
public $escaped;
public $expression;
public $index;
/**
* @param boolean $index
* @param boolean $escaped
*/
public function __construct($string, $index, $escaped){
$this->escaped = $escaped;
$this->expression = $string;
$this->index = $index;
}
public function compile(){
return new Less_Tree_Anonymous('/* Sorry, can not do JavaScript evaluation in PHP... :( */');
}
}
Keyword.php 0000644 00000001260 15155315057 0006707 0 ustar 00 <?php
/**
* Keyword
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Keyword extends Less_Tree{
public $value;
public $type = 'Keyword';
/**
* @param string $value
*/
public function __construct($value){
$this->value = $value;
}
public function compile(){
return $this;
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
if( $this->value === '%') {
throw new Less_Exception_Compiler("Invalid % without number");
}
$output->add( $this->value );
}
public function compare($other) {
if ($other instanceof Less_Tree_Keyword) {
return $other->value === $this->value ? 0 : 1;
} else {
return -1;
}
}
}
Media.php 0000644 00000010430 15155315057 0006301 0 ustar 00 <?php
/**
* Media
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Media extends Less_Tree{
public $features;
public $rules;
public $index;
public $currentFileInfo;
public $isReferenced;
public $type = 'Media';
public function __construct($value = array(), $features = array(), $index = null, $currentFileInfo = null ){
$this->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])));
}
}
Mixin/Call.php 0000644 00000011701 15155315057 0007223 0 ustar 00 <?php
class Less_Tree_Mixin_Call extends Less_Tree{
public $selector;
public $arguments;
public $index;
public $currentFileInfo;
public $important;
public $type = 'MixinCall';
/**
* less.js: tree.mixin.Call
*
*/
public function __construct($elements, $args, $index, $currentFileInfo, $important = false){
$this->selector = new Less_Tree_Selector($elements);
$this->arguments = $args;
$this->index = $index;
$this->currentFileInfo = $currentFileInfo;
$this->important = $important;
}
//function accept($visitor){
// $this->selector = $visitor->visit($this->selector);
// $this->arguments = $visitor->visit($this->arguments);
//}
public function compile($env){
$rules = array();
$match = false;
$isOneFound = false;
$candidates = array();
$defaultUsed = false;
$conditionResult = array();
$args = array();
foreach($this->arguments as $a){
$args[] = array('name'=> $a['name'], 'value' => $a['value']->compile($env) );
}
foreach($env->frames as $frame){
$mixins = $frame->find($this->selector);
if( !$mixins ){
continue;
}
$isOneFound = true;
$defNone = 0;
$defTrue = 1;
$defFalse = 2;
// To make `default()` function independent of definition order we have two "subpasses" here.
// At first we evaluate each guard *twice* (with `default() == true` and `default() == false`),
// and build candidate list with corresponding flags. Then, when we know all possible matches,
// we make a final decision.
$mixins_len = count($mixins);
for( $m = 0; $m < $mixins_len; $m++ ){
$mixin = $mixins[$m];
if( $this->IsRecursive( $env, $mixin ) ){
continue;
}
if( $mixin->matchArgs($args, $env) ){
$candidate = array('mixin' => $mixin, 'group' => $defNone);
if( $mixin instanceof Less_Tree_Ruleset ){
for( $f = 0; $f < 2; $f++ ){
Less_Tree_DefaultFunc::value($f);
$conditionResult[$f] = $mixin->matchCondition( $args, $env);
}
if( $conditionResult[0] || $conditionResult[1] ){
if( $conditionResult[0] != $conditionResult[1] ){
$candidate['group'] = $conditionResult[1] ? $defTrue : $defFalse;
}
$candidates[] = $candidate;
}
}else{
$candidates[] = $candidate;
}
$match = true;
}
}
Less_Tree_DefaultFunc::reset();
$count = array(0, 0, 0);
for( $m = 0; $m < count($candidates); $m++ ){
$count[ $candidates[$m]['group'] ]++;
}
if( $count[$defNone] > 0 ){
$defaultResult = $defFalse;
} else {
$defaultResult = $defTrue;
if( ($count[$defTrue] + $count[$defFalse]) > 1 ){
throw new Exception( 'Ambiguous use of `default()` found when matching for `' . $this->format($args) . '`' );
}
}
$candidates_length = count($candidates);
$length_1 = ($candidates_length == 1);
for( $m = 0; $m < $candidates_length; $m++){
$candidate = $candidates[$m]['group'];
if( ($candidate === $defNone) || ($candidate === $defaultResult) ){
try{
$mixin = $candidates[$m]['mixin'];
if( !($mixin instanceof Less_Tree_Mixin_Definition) ){
$mixin = new Less_Tree_Mixin_Definition('', array(), $mixin->rules, null, false);
$mixin->originalRuleset = $mixins[$m]->originalRuleset;
}
$rules = array_merge($rules, $mixin->evalCall($env, $args, $this->important)->rules);
} catch (Exception $e) {
//throw new Less_Exception_Compiler($e->getMessage(), $e->index, null, $this->currentFileInfo['filename']);
throw new Less_Exception_Compiler($e->getMessage(), null, null, $this->currentFileInfo);
}
}
}
if( $match ){
if( !$this->currentFileInfo || !isset($this->currentFileInfo['reference']) || !$this->currentFileInfo['reference'] ){
Less_Tree::ReferencedArray($rules);
}
return $rules;
}
}
if( $isOneFound ){
throw new Less_Exception_Compiler('No matching definition was found for `'.$this->Format( $args ).'`', null, $this->index, $this->currentFileInfo);
}else{
throw new Less_Exception_Compiler(trim($this->selector->toCSS()) . " is undefined in ".$this->currentFileInfo['filename'], null, $this->index);
}
}
/**
* Format the args for use in exception messages
*
*/
private function Format($args){
$message = array();
if( $args ){
foreach($args as $a){
$argValue = '';
if( $a['name'] ){
$argValue .= $a['name'] . ':';
}
if( is_object($a['value']) ){
$argValue .= $a['value']->toCSS();
}else{
$argValue .= '???';
}
$message[] = $argValue;
}
}
return implode(', ',$message);
}
/**
* Are we in a recursive mixin call?
*
* @return bool
*/
private function IsRecursive( $env, $mixin ){
foreach($env->frames as $recur_frame){
if( !($mixin instanceof Less_Tree_Mixin_Definition) ){
if( $mixin === $recur_frame ){
return true;
}
if( isset($recur_frame->originalRuleset) && $mixin->ruleset_id === $recur_frame->originalRuleset ){
return true;
}
}
}
return false;
}
}
Mixin/Definition.php 0000644 00000014253 15155315057 0010445 0 ustar 00 <?php
class Less_Tree_Mixin_Definition extends Less_Tree_Ruleset{
public $name;
public $selectors;
public $params;
public $arity = 0;
public $rules;
public $lookups = array();
public $required = 0;
public $frames = array();
public $condition;
public $variadic;
public $type = 'MixinDefinition';
// less.js : /lib/less/tree/mixin.js : tree.mixin.Definition
public function __construct($name, $params, $rules, $condition, $variadic = false, $frames = array() ){
$this->name = $name;
$this->selectors = array(new Less_Tree_Selector(array( new Less_Tree_Element(null, $name))));
$this->params = $params;
$this->condition = $condition;
$this->variadic = $variadic;
$this->rules = $rules;
if( $params ){
$this->arity = count($params);
foreach( $params as $p ){
if (! isset($p['name']) || ($p['name'] && !isset($p['value']))) {
$this->required++;
}
}
}
$this->frames = $frames;
$this->SetRulesetIndex();
}
//function accept( $visitor ){
// $this->params = $visitor->visit($this->params);
// $this->rules = $visitor->visit($this->rules);
// $this->condition = $visitor->visit($this->condition);
//}
public function toCSS(){
return '';
}
// less.js : /lib/less/tree/mixin.js : tree.mixin.Definition.evalParams
public function compileParams($env, $mixinFrames, $args = array() , &$evaldArguments = array() ){
$frame = new Less_Tree_Ruleset(null, array());
$params = $this->params;
$mixinEnv = null;
$argsLength = 0;
if( $args ){
$argsLength = count($args);
for($i = 0; $i < $argsLength; $i++ ){
$arg = $args[$i];
if( $arg && $arg['name'] ){
$isNamedFound = false;
foreach($params as $j => $param){
if( !isset($evaldArguments[$j]) && $arg['name'] === $params[$j]['name']) {
$evaldArguments[$j] = $arg['value']->compile($env);
array_unshift($frame->rules, new Less_Tree_Rule( $arg['name'], $arg['value']->compile($env) ) );
$isNamedFound = true;
break;
}
}
if ($isNamedFound) {
array_splice($args, $i, 1);
$i--;
$argsLength--;
continue;
} else {
throw new Less_Exception_Compiler("Named argument for " . $this->name .' '.$args[$i]['name'] . ' not found');
}
}
}
}
$argIndex = 0;
foreach($params as $i => $param){
if ( isset($evaldArguments[$i]) ){ continue; }
$arg = null;
if( isset($args[$argIndex]) ){
$arg = $args[$argIndex];
}
if (isset($param['name']) && $param['name']) {
if( isset($param['variadic']) ){
$varargs = array();
for ($j = $argIndex; $j < $argsLength; $j++) {
$varargs[] = $args[$j]['value']->compile($env);
}
$expression = new Less_Tree_Expression($varargs);
array_unshift($frame->rules, new Less_Tree_Rule($param['name'], $expression->compile($env)));
}else{
$val = ($arg && $arg['value']) ? $arg['value'] : false;
if ($val) {
$val = $val->compile($env);
} else if ( isset($param['value']) ) {
if( !$mixinEnv ){
$mixinEnv = new Less_Environment();
$mixinEnv->frames = array_merge( array($frame), $mixinFrames);
}
$val = $param['value']->compile($mixinEnv);
$frame->resetCache();
} else {
throw new Less_Exception_Compiler("Wrong number of arguments for " . $this->name . " (" . $argsLength . ' for ' . $this->arity . ")");
}
array_unshift($frame->rules, new Less_Tree_Rule($param['name'], $val));
$evaldArguments[$i] = $val;
}
}
if ( isset($param['variadic']) && $args) {
for ($j = $argIndex; $j < $argsLength; $j++) {
$evaldArguments[$j] = $args[$j]['value']->compile($env);
}
}
$argIndex++;
}
ksort($evaldArguments);
$evaldArguments = array_values($evaldArguments);
return $frame;
}
public function compile($env) {
if( $this->frames ){
return new Less_Tree_Mixin_Definition($this->name, $this->params, $this->rules, $this->condition, $this->variadic, $this->frames );
}
return new Less_Tree_Mixin_Definition($this->name, $this->params, $this->rules, $this->condition, $this->variadic, $env->frames );
}
public function evalCall($env, $args = NULL, $important = NULL) {
Less_Environment::$mixin_stack++;
$_arguments = array();
if( $this->frames ){
$mixinFrames = array_merge($this->frames, $env->frames);
}else{
$mixinFrames = $env->frames;
}
$frame = $this->compileParams($env, $mixinFrames, $args, $_arguments);
$ex = new Less_Tree_Expression($_arguments);
array_unshift($frame->rules, new Less_Tree_Rule('@arguments', $ex->compile($env)));
$ruleset = new Less_Tree_Ruleset(null, $this->rules);
$ruleset->originalRuleset = $this->ruleset_id;
$ruleSetEnv = new Less_Environment();
$ruleSetEnv->frames = array_merge( array($this, $frame), $mixinFrames );
$ruleset = $ruleset->compile( $ruleSetEnv );
if( $important ){
$ruleset = $ruleset->makeImportant();
}
Less_Environment::$mixin_stack--;
return $ruleset;
}
public function matchCondition($args, $env) {
if( !$this->condition ){
return true;
}
// set array to prevent error on array_merge
if(!is_array($this->frames)) {
$this->frames = array();
}
$frame = $this->compileParams($env, array_merge($this->frames,$env->frames), $args );
$compile_env = new Less_Environment();
$compile_env->frames = array_merge(
array($frame) // the parameter variables
, $this->frames // the parent namespace/mixin frames
, $env->frames // the current environment frames
);
$compile_env->functions = $env->functions;
return (bool)$this->condition->compile($compile_env);
}
public function matchArgs($args, $env = NULL){
$argsLength = count($args);
if( !$this->variadic ){
if( $argsLength < $this->required ){
return false;
}
if( $argsLength > count($this->params) ){
return false;
}
}else{
if( $argsLength < ($this->required - 1)){
return false;
}
}
$len = min($argsLength, $this->arity);
for( $i = 0; $i < $len; $i++ ){
if( !isset($this->params[$i]['name']) && !isset($this->params[$i]['variadic']) ){
if( $args[$i]['value']->compile($env)->toCSS() != $this->params[$i]['value']->compile($env)->toCSS() ){
return false;
}
}
}
return true;
}
}
NameValue.php 0000644 00000002460 15155315057 0007143 0 ustar 00 <?php
/**
* A simple css name-value pair
* ex: width:100px;
*
* In bootstrap, there are about 600-1,000 simple name-value pairs (depending on how forgiving the match is) -vs- 6,020 dynamic rules (Less_Tree_Rule)
* Using the name-value object can speed up bootstrap compilation slightly, but it breaks color keyword interpretation: color:red -> color:#FF0000;
*
* @package Less
* @subpackage tree
*/
class Less_Tree_NameValue extends Less_Tree{
public $name;
public $value;
public $index;
public $currentFileInfo;
public $type = 'NameValue';
public $important = '';
public function __construct($name, $value = null, $index = null, $currentFileInfo = null ){
$this->name = $name;
$this->value = $value;
$this->index = $index;
$this->currentFileInfo = $currentFileInfo;
}
public function genCSS( $output ){
$output->add(
$this->name
. Less_Environment::$_outputMap[': ']
. $this->value
. $this->important
. (((Less_Environment::$lastRule && Less_Parser::$options['compress'])) ? "" : ";")
, $this->currentFileInfo, $this->index);
}
public function compile ($env){
return $this;
}
public function makeImportant(){
$new = new Less_Tree_NameValue($this->name, $this->value, $this->index, $this->currentFileInfo);
$new->important = ' !important';
return $new;
}
}
Negative.php 0000644 00000001331 15155315057 0007024 0 ustar 00 <?php
/**
* Negative
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Negative extends Less_Tree{
public $value;
public $type = 'Negative';
public function __construct($node){
$this->value = $node;
}
//function accept($visitor) {
// $this->value = $visitor->visit($this->value);
//}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$output->add( '-' );
$this->value->genCSS( $output );
}
public function compile($env) {
if( Less_Environment::isMathOn() ){
$ret = new Less_Tree_Operation('*', array( new Less_Tree_Dimension(-1), $this->value ) );
return $ret->compile($env);
}
return new Less_Tree_Negative( $this->value->compile($env) );
}
} Operation.php 0000644 00000002600 15155315057 0007222 0 ustar 00 <?php
/**
* Operation
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Operation extends Less_Tree{
public $op;
public $operands;
public $isSpaced;
public $type = 'Operation';
/**
* @param string $op
*/
public function __construct($op, $operands, $isSpaced = false){
$this->op = trim($op);
$this->operands = $operands;
$this->isSpaced = $isSpaced;
}
public function accept($visitor) {
$this->operands = $visitor->visitArray($this->operands);
}
public function compile($env){
$a = $this->operands[0]->compile($env);
$b = $this->operands[1]->compile($env);
if( Less_Environment::isMathOn() ){
if( $a instanceof Less_Tree_Dimension && $b instanceof Less_Tree_Color ){
$a = $a->toColor();
}elseif( $b instanceof Less_Tree_Dimension && $a instanceof Less_Tree_Color ){
$b = $b->toColor();
}
if( !method_exists($a,'operate') ){
throw new Less_Exception_Compiler("Operation on an invalid type");
}
return $a->operate( $this->op, $b);
}
return new Less_Tree_Operation($this->op, array($a, $b), $this->isSpaced );
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$this->operands[0]->genCSS( $output );
if( $this->isSpaced ){
$output->add( " " );
}
$output->add( $this->op );
if( $this->isSpaced ){
$output->add( ' ' );
}
$this->operands[1]->genCSS( $output );
}
}
Paren.php 0000644 00000001101 15155315057 0006322 0 ustar 00 <?php
/**
* Paren
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Paren extends Less_Tree{
public $value;
public $type = 'Paren';
public function __construct($value) {
$this->value = $value;
}
public function accept($visitor){
$this->value = $visitor->visitObj($this->value);
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$output->add( '(' );
$this->value->genCSS( $output );
$output->add( ')' );
}
public function compile($env) {
return new Less_Tree_Paren($this->value->compile($env));
}
}
Quoted.php 0000644 00000003553 15155315057 0006533 0 ustar 00 <?php
/**
* Quoted
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Quoted extends Less_Tree{
public $escaped;
public $value;
public $quote;
public $index;
public $currentFileInfo;
public $type = 'Quoted';
/**
* @param string $str
*/
public function __construct($str, $content = '', $escaped = false, $index = false, $currentFileInfo = null ){
$this->escaped = $escaped;
$this->value = $content;
if( $str ){
$this->quote = $str[0];
}
$this->index = $index;
$this->currentFileInfo = $currentFileInfo;
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
if( !$this->escaped ){
$output->add( $this->quote, $this->currentFileInfo, $this->index );
}
$output->add( $this->value );
if( !$this->escaped ){
$output->add( $this->quote );
}
}
public function compile($env){
$value = $this->value;
if( preg_match_all('/`([^`]+)`/', $this->value, $matches) ){
foreach($matches as $i => $match){
$js = new Less_Tree_JavaScript($matches[1], $this->index, true);
$js = $js->compile()->value;
$value = str_replace($matches[0][$i], $js, $value);
}
}
if( preg_match_all('/@\{([\w-]+)\}/',$value,$matches) ){
foreach($matches[1] as $i => $match){
$v = new Less_Tree_Variable('@' . $match, $this->index, $this->currentFileInfo );
$v = $v->compile($env);
$v = ($v instanceof Less_Tree_Quoted) ? $v->value : $v->toCSS();
$value = str_replace($matches[0][$i], $v, $value);
}
}
return new Less_Tree_Quoted($this->quote . $value . $this->quote, $value, $this->escaped, $this->index, $this->currentFileInfo);
}
public function compare($x) {
if( !Less_Parser::is_method($x, 'toCSS') ){
return -1;
}
$left = $this->toCSS();
$right = $x->toCSS();
if ($left === $right) {
return 0;
}
return $left < $right ? -1 : 1;
}
}
Rule.php 0000644 00000006142 15155315057 0006176 0 ustar 00 <?php
/**
* Rule
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Rule extends Less_Tree{
public $name;
public $value;
public $important;
public $merge;
public $index;
public $inline;
public $variable;
public $currentFileInfo;
public $type = 'Rule';
/**
* @param string $important
*/
public function __construct($name, $value = null, $important = null, $merge = null, $index = null, $currentFileInfo = null, $inline = false){
$this->name = $name;
$this->value = ($value instanceof Less_Tree_Value || $value instanceof Less_Tree_Ruleset) ? $value : new Less_Tree_Value(array($value));
$this->important = $important ? ' ' . trim($important) : '';
$this->merge = $merge;
$this->index = $index;
$this->currentFileInfo = $currentFileInfo;
$this->inline = $inline;
$this->variable = ( is_string($name) && $name[0] === '@');
}
public function accept($visitor) {
$this->value = $visitor->visitObj( $this->value );
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$output->add( $this->name . Less_Environment::$_outputMap[': '], $this->currentFileInfo, $this->index);
try{
$this->value->genCSS( $output);
}catch( Less_Exception_Parser $e ){
$e->index = $this->index;
$e->currentFile = $this->currentFileInfo;
throw $e;
}
$output->add( $this->important . (($this->inline || (Less_Environment::$lastRule && Less_Parser::$options['compress'])) ? "" : ";"), $this->currentFileInfo, $this->index);
}
public function compile ($env){
$name = $this->name;
if( is_array($name) ){
// expand 'primitive' name directly to get
// things faster (~10% for benchmark.less):
if( count($name) === 1 && $name[0] instanceof Less_Tree_Keyword ){
$name = $name[0]->value;
}else{
$name = $this->CompileName($env,$name);
}
}
$strictMathBypass = Less_Parser::$options['strictMath'];
if( $name === "font" && !Less_Parser::$options['strictMath'] ){
Less_Parser::$options['strictMath'] = true;
}
try {
$evaldValue = $this->value->compile($env);
if( !$this->variable && $evaldValue->type === "DetachedRuleset") {
throw new Less_Exception_Compiler("Rulesets cannot be evaluated on a property.", null, $this->index, $this->currentFileInfo);
}
if( Less_Environment::$mixin_stack ){
$return = new Less_Tree_Rule($name, $evaldValue, $this->important, $this->merge, $this->index, $this->currentFileInfo, $this->inline);
}else{
$this->name = $name;
$this->value = $evaldValue;
$return = $this;
}
}catch( Less_Exception_Parser $e ){
if( !is_numeric($e->index) ){
$e->index = $this->index;
$e->currentFile = $this->currentFileInfo;
}
throw $e;
}
Less_Parser::$options['strictMath'] = $strictMathBypass;
return $return;
}
public function CompileName( $env, $name ){
$output = new Less_Output();
foreach($name as $n){
$n->compile($env)->genCSS($output);
}
return $output->toString();
}
public function makeImportant(){
return new Less_Tree_Rule($this->name, $this->value, '!important', $this->merge, $this->index, $this->currentFileInfo, $this->inline);
}
}
Ruleset.php 0000644 00000040236 15155315057 0006714 0 ustar 00 <?php
/**
* Ruleset
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Ruleset extends Less_Tree{
protected $lookups;
public $_variables;
public $_rulesets;
public $strictImports;
public $selectors;
public $rules;
public $root;
public $allowImports;
public $paths;
public $firstRoot;
public $type = 'Ruleset';
public $multiMedia;
public $allExtends;
public $ruleset_id;
public $originalRuleset;
public $first_oelements;
public function SetRulesetIndex(){
$this->ruleset_id = Less_Parser::$next_id++;
$this->originalRuleset = $this->ruleset_id;
if( $this->selectors ){
foreach($this->selectors as $sel){
if( $sel->_oelements ){
$this->first_oelements[$sel->_oelements[0]] = true;
}
}
}
}
public function __construct($selectors, $rules, $strictImports = null){
$this->selectors = $selectors;
$this->rules = $rules;
$this->lookups = array();
$this->strictImports = $strictImports;
$this->SetRulesetIndex();
}
public function accept( $visitor ){
if( $this->paths ){
$paths_len = count($this->paths);
for($i = 0,$paths_len; $i < $paths_len; $i++ ){
$this->paths[$i] = $visitor->visitArray($this->paths[$i]);
}
}elseif( $this->selectors ){
$this->selectors = $visitor->visitArray($this->selectors);
}
if( $this->rules ){
$this->rules = $visitor->visitArray($this->rules);
}
}
public function compile($env){
$ruleset = $this->PrepareRuleset($env);
// Store the frames around mixin definitions,
// so they can be evaluated like closures when the time comes.
$rsRuleCnt = count($ruleset->rules);
for( $i = 0; $i < $rsRuleCnt; $i++ ){
if( $ruleset->rules[$i] instanceof Less_Tree_Mixin_Definition || $ruleset->rules[$i] instanceof Less_Tree_DetachedRuleset ){
$ruleset->rules[$i] = $ruleset->rules[$i]->compile($env);
}
}
$mediaBlockCount = 0;
if( $env instanceof Less_Environment ){
$mediaBlockCount = count($env->mediaBlocks);
}
// Evaluate mixin calls.
$this->EvalMixinCalls( $ruleset, $env, $rsRuleCnt );
// Evaluate everything else
for( $i=0; $i<$rsRuleCnt; $i++ ){
if(! ($ruleset->rules[$i] instanceof Less_Tree_Mixin_Definition || $ruleset->rules[$i] instanceof Less_Tree_DetachedRuleset) ){
$ruleset->rules[$i] = $ruleset->rules[$i]->compile($env);
}
}
// Evaluate everything else
for( $i=0; $i<$rsRuleCnt; $i++ ){
$rule = $ruleset->rules[$i];
// for rulesets, check if it is a css guard and can be removed
if( $rule instanceof Less_Tree_Ruleset && $rule->selectors && count($rule->selectors) === 1 ){
// check if it can be folded in (e.g. & where)
if( $rule->selectors[0]->isJustParentSelector() ){
array_splice($ruleset->rules,$i--,1);
$rsRuleCnt--;
for($j = 0; $j < count($rule->rules); $j++ ){
$subRule = $rule->rules[$j];
if( !($subRule instanceof Less_Tree_Rule) || !$subRule->variable ){
array_splice($ruleset->rules, ++$i, 0, array($subRule));
$rsRuleCnt++;
}
}
}
}
}
// Pop the stack
$env->shiftFrame();
if ($mediaBlockCount) {
$len = count($env->mediaBlocks);
for($i = $mediaBlockCount; $i < $len; $i++ ){
$env->mediaBlocks[$i]->bubbleSelectors($ruleset->selectors);
}
}
return $ruleset;
}
/**
* Compile Less_Tree_Mixin_Call objects
*
* @param Less_Tree_Ruleset $ruleset
* @param integer $rsRuleCnt
*/
private function EvalMixinCalls( $ruleset, $env, &$rsRuleCnt ){
for($i=0; $i < $rsRuleCnt; $i++){
$rule = $ruleset->rules[$i];
if( $rule instanceof Less_Tree_Mixin_Call ){
$rule = $rule->compile($env);
$temp = array();
foreach($rule as $r){
if( ($r instanceof Less_Tree_Rule) && $r->variable ){
// do not pollute the scope if the variable is
// already there. consider returning false here
// but we need a way to "return" variable from mixins
if( !$ruleset->variable($r->name) ){
$temp[] = $r;
}
}else{
$temp[] = $r;
}
}
$temp_count = count($temp)-1;
array_splice($ruleset->rules, $i, 1, $temp);
$rsRuleCnt += $temp_count;
$i += $temp_count;
$ruleset->resetCache();
}elseif( $rule instanceof Less_Tree_RulesetCall ){
$rule = $rule->compile($env);
$rules = array();
foreach($rule->rules as $r){
if( ($r instanceof Less_Tree_Rule) && $r->variable ){
continue;
}
$rules[] = $r;
}
array_splice($ruleset->rules, $i, 1, $rules);
$temp_count = count($rules);
$rsRuleCnt += $temp_count - 1;
$i += $temp_count-1;
$ruleset->resetCache();
}
}
}
/**
* Compile the selectors and create a new ruleset object for the compile() method
*
*/
private function PrepareRuleset($env){
$hasOnePassingSelector = false;
$selectors = array();
if( $this->selectors ){
Less_Tree_DefaultFunc::error("it is currently only allowed in parametric mixin guards,");
foreach($this->selectors as $s){
$selector = $s->compile($env);
$selectors[] = $selector;
if( $selector->evaldCondition ){
$hasOnePassingSelector = true;
}
}
Less_Tree_DefaultFunc::reset();
} else {
$hasOnePassingSelector = true;
}
if( $this->rules && $hasOnePassingSelector ){
$rules = $this->rules;
}else{
$rules = array();
}
$ruleset = new Less_Tree_Ruleset($selectors, $rules, $this->strictImports);
$ruleset->originalRuleset = $this->ruleset_id;
$ruleset->root = $this->root;
$ruleset->firstRoot = $this->firstRoot;
$ruleset->allowImports = $this->allowImports;
// push the current ruleset to the frames stack
$env->unshiftFrame($ruleset);
// Evaluate imports
if( $ruleset->root || $ruleset->allowImports || !$ruleset->strictImports ){
$ruleset->evalImports($env);
}
return $ruleset;
}
function evalImports($env) {
$rules_len = count($this->rules);
for($i=0; $i < $rules_len; $i++){
$rule = $this->rules[$i];
if( $rule instanceof Less_Tree_Import ){
$rules = $rule->compile($env);
if( is_array($rules) ){
array_splice($this->rules, $i, 1, $rules);
$temp_count = count($rules)-1;
$i += $temp_count;
$rules_len += $temp_count;
}else{
array_splice($this->rules, $i, 1, array($rules));
}
$this->resetCache();
}
}
}
function makeImportant(){
$important_rules = array();
foreach($this->rules as $rule){
if( $rule instanceof Less_Tree_Rule || $rule instanceof Less_Tree_Ruleset || $rule instanceof Less_Tree_NameValue ){
$important_rules[] = $rule->makeImportant();
}else{
$important_rules[] = $rule;
}
}
return new Less_Tree_Ruleset($this->selectors, $important_rules, $this->strictImports );
}
public function matchArgs($args){
return !$args;
}
// lets you call a css selector with a guard
public function matchCondition( $args, $env ){
$lastSelector = end($this->selectors);
if( !$lastSelector->evaldCondition ){
return false;
}
if( $lastSelector->condition && !$lastSelector->condition->compile( $env->copyEvalEnv( $env->frames ) ) ){
return false;
}
return true;
}
function resetCache(){
$this->_rulesets = null;
$this->_variables = null;
$this->lookups = array();
}
public function variables(){
$this->_variables = array();
foreach( $this->rules as $r){
if ($r instanceof Less_Tree_Rule && $r->variable === true) {
$this->_variables[$r->name] = $r;
}
}
}
public function variable($name){
if( is_null($this->_variables) ){
$this->variables();
}
return isset($this->_variables[$name]) ? $this->_variables[$name] : null;
}
public function find( $selector, $self = null ){
$key = implode(' ',$selector->_oelements);
if( !isset($this->lookups[$key]) ){
if( !$self ){
$self = $this->ruleset_id;
}
$this->lookups[$key] = array();
$first_oelement = $selector->_oelements[0];
foreach($this->rules as $rule){
if( $rule instanceof Less_Tree_Ruleset && $rule->ruleset_id != $self ){
if( isset($rule->first_oelements[$first_oelement]) ){
foreach( $rule->selectors as $ruleSelector ){
$match = $selector->match($ruleSelector);
if( $match ){
if( $selector->elements_len > $match ){
$this->lookups[$key] = array_merge($this->lookups[$key], $rule->find( new Less_Tree_Selector(array_slice($selector->elements, $match)), $self));
} else {
$this->lookups[$key][] = $rule;
}
break;
}
}
}
}
}
}
return $this->lookups[$key];
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
if( !$this->root ){
Less_Environment::$tabLevel++;
}
$tabRuleStr = $tabSetStr = '';
if( !Less_Parser::$options['compress'] ){
if( Less_Environment::$tabLevel ){
$tabRuleStr = "\n".str_repeat( Less_Parser::$options['indentation'] , Less_Environment::$tabLevel );
$tabSetStr = "\n".str_repeat( Less_Parser::$options['indentation'] , Less_Environment::$tabLevel-1 );
}else{
$tabSetStr = $tabRuleStr = "\n";
}
}
$ruleNodes = array();
$rulesetNodes = array();
foreach($this->rules as $rule){
$class = get_class($rule);
if( ($class === 'Less_Tree_Media') || ($class === 'Less_Tree_Directive') || ($this->root && $class === 'Less_Tree_Comment') || ($class === 'Less_Tree_Ruleset' && $rule->rules) ){
$rulesetNodes[] = $rule;
}else{
$ruleNodes[] = $rule;
}
}
// If this is the root node, we don't render
// a selector, or {}.
if( !$this->root ){
/*
debugInfo = tree.debugInfo(env, this, tabSetStr);
if (debugInfo) {
output.add(debugInfo);
output.add(tabSetStr);
}
*/
$paths_len = count($this->paths);
for( $i = 0; $i < $paths_len; $i++ ){
$path = $this->paths[$i];
$firstSelector = true;
foreach($path as $p){
$p->genCSS( $output, $firstSelector );
$firstSelector = false;
}
if( $i + 1 < $paths_len ){
$output->add( ',' . $tabSetStr );
}
}
$output->add( (Less_Parser::$options['compress'] ? '{' : " {") . $tabRuleStr );
}
// Compile rules and rulesets
$ruleNodes_len = count($ruleNodes);
$rulesetNodes_len = count($rulesetNodes);
for( $i = 0; $i < $ruleNodes_len; $i++ ){
$rule = $ruleNodes[$i];
// @page{ directive ends up with root elements inside it, a mix of rules and rulesets
// In this instance we do not know whether it is the last property
if( $i + 1 === $ruleNodes_len && (!$this->root || $rulesetNodes_len === 0 || $this->firstRoot ) ){
Less_Environment::$lastRule = true;
}
$rule->genCSS( $output );
if( !Less_Environment::$lastRule ){
$output->add( $tabRuleStr );
}else{
Less_Environment::$lastRule = false;
}
}
if( !$this->root ){
$output->add( $tabSetStr . '}' );
Less_Environment::$tabLevel--;
}
$firstRuleset = true;
$space = ($this->root ? $tabRuleStr : $tabSetStr);
for( $i = 0; $i < $rulesetNodes_len; $i++ ){
if( $ruleNodes_len && $firstRuleset ){
$output->add( $space );
}elseif( !$firstRuleset ){
$output->add( $space );
}
$firstRuleset = false;
$rulesetNodes[$i]->genCSS( $output);
}
if( !Less_Parser::$options['compress'] && $this->firstRoot ){
$output->add( "\n" );
}
}
function markReferenced(){
if( !$this->selectors ){
return;
}
foreach($this->selectors as $selector){
$selector->markReferenced();
}
}
public function joinSelectors( $context, $selectors ){
$paths = array();
if( is_array($selectors) ){
foreach($selectors as $selector) {
$this->joinSelector( $paths, $context, $selector);
}
}
return $paths;
}
public function joinSelector( &$paths, $context, $selector){
$hasParentSelector = false;
foreach($selector->elements as $el) {
if( $el->value === '&') {
$hasParentSelector = true;
}
}
if( !$hasParentSelector ){
if( $context ){
foreach($context as $context_el){
$paths[] = array_merge($context_el, array($selector) );
}
}else {
$paths[] = array($selector);
}
return;
}
// The paths are [[Selector]]
// The first list is a list of comma separated selectors
// The inner list is a list of inheritance separated selectors
// e.g.
// .a, .b {
// .c {
// }
// }
// == [[.a] [.c]] [[.b] [.c]]
//
// the elements from the current selector so far
$currentElements = array();
// the current list of new selectors to add to the path.
// We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
// by the parents
$newSelectors = array(array());
foreach( $selector->elements as $el){
// non parent reference elements just get added
if( $el->value !== '&' ){
$currentElements[] = $el;
} else {
// the new list of selectors to add
$selectorsMultiplied = array();
// merge the current list of non parent selector elements
// on to the current list of selectors to add
if( $currentElements ){
$this->mergeElementsOnToSelectors( $currentElements, $newSelectors);
}
// loop through our current selectors
foreach($newSelectors as $sel){
// if we don't have any parent paths, the & might be in a mixin so that it can be used
// whether there are parents or not
if( !$context ){
// the combinator used on el should now be applied to the next element instead so that
// it is not lost
if( $sel ){
$sel[0]->elements = array_slice($sel[0]->elements,0);
$sel[0]->elements[] = new Less_Tree_Element($el->combinator, '', $el->index, $el->currentFileInfo );
}
$selectorsMultiplied[] = $sel;
}else {
// and the parent selectors
foreach($context as $parentSel){
// We need to put the current selectors
// then join the last selector's elements on to the parents selectors
// our new selector path
$newSelectorPath = array();
// selectors from the parent after the join
$afterParentJoin = array();
$newJoinedSelectorEmpty = true;
//construct the joined selector - if & is the first thing this will be empty,
// if not newJoinedSelector will be the last set of elements in the selector
if( $sel ){
$newSelectorPath = $sel;
$lastSelector = array_pop($newSelectorPath);
$newJoinedSelector = $selector->createDerived( array_slice($lastSelector->elements,0) );
$newJoinedSelectorEmpty = false;
}
else {
$newJoinedSelector = $selector->createDerived(array());
}
//put together the parent selectors after the join
if ( count($parentSel) > 1) {
$afterParentJoin = array_merge($afterParentJoin, array_slice($parentSel,1) );
}
if ( $parentSel ){
$newJoinedSelectorEmpty = false;
// join the elements so far with the first part of the parent
$newJoinedSelector->elements[] = new Less_Tree_Element( $el->combinator, $parentSel[0]->elements[0]->value, $el->index, $el->currentFileInfo);
$newJoinedSelector->elements = array_merge( $newJoinedSelector->elements, array_slice($parentSel[0]->elements, 1) );
}
if (!$newJoinedSelectorEmpty) {
// now add the joined selector
$newSelectorPath[] = $newJoinedSelector;
}
// and the rest of the parent
$newSelectorPath = array_merge($newSelectorPath, $afterParentJoin);
// add that to our new set of selectors
$selectorsMultiplied[] = $newSelectorPath;
}
}
}
// our new selectors has been multiplied, so reset the state
$newSelectors = $selectorsMultiplied;
$currentElements = array();
}
}
// if we have any elements left over (e.g. .a& .b == .b)
// add them on to all the current selectors
if( $currentElements ){
$this->mergeElementsOnToSelectors($currentElements, $newSelectors);
}
foreach( $newSelectors as $new_sel){
if( $new_sel ){
$paths[] = $new_sel;
}
}
}
function mergeElementsOnToSelectors( $elements, &$selectors){
if( !$selectors ){
$selectors[] = array( new Less_Tree_Selector($elements) );
return;
}
foreach( $selectors as &$sel){
// if the previous thing in sel is a parent this needs to join on to it
if( $sel ){
$last = count($sel)-1;
$sel[$last] = $sel[$last]->createDerived( array_merge($sel[$last]->elements, $elements) );
}else{
$sel[] = new Less_Tree_Selector( $elements );
}
}
}
}
RulesetCall.php 0000644 00000000735 15155315057 0007510 0 ustar 00 <?php
/**
* RulesetCall
*
* @package Less
* @subpackage tree
*/
class Less_Tree_RulesetCall extends Less_Tree{
public $variable;
public $type = "RulesetCall";
public function __construct($variable){
$this->variable = $variable;
}
public function accept($visitor) {}
public function compile( $env ){
$variable = new Less_Tree_Variable($this->variable);
$detachedRuleset = $variable->compile($env);
return $detachedRuleset->callEval($env);
}
}
Selector.php 0000644 00000010042 15155315057 0007041 0 ustar 00 <?php
/**
* Selector
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Selector extends Less_Tree{
public $elements;
public $condition;
public $extendList = array();
public $_css;
public $index;
public $evaldCondition = false;
public $type = 'Selector';
public $currentFileInfo = array();
public $isReferenced;
public $mediaEmpty;
public $elements_len = 0;
public $_oelements;
public $_oelements_assoc;
public $_oelements_len;
public $cacheable = true;
/**
* @param boolean $isReferenced
*/
public function __construct( $elements, $extendList = array() , $condition = null, $index=null, $currentFileInfo=null, $isReferenced=null ){
$this->elements = $elements;
$this->elements_len = count($elements);
$this->extendList = $extendList;
$this->condition = $condition;
if( $currentFileInfo ){
$this->currentFileInfo = $currentFileInfo;
}
$this->isReferenced = $isReferenced;
if( !$condition ){
$this->evaldCondition = true;
}
$this->CacheElements();
}
public function accept($visitor) {
$this->elements = $visitor->visitArray($this->elements);
$this->extendList = $visitor->visitArray($this->extendList);
if( $this->condition ){
$this->condition = $visitor->visitObj($this->condition);
}
if( $visitor instanceof Less_Visitor_extendFinder ){
$this->CacheElements();
}
}
public function createDerived( $elements, $extendList = null, $evaldCondition = null ){
$newSelector = new Less_Tree_Selector( $elements, ($extendList ? $extendList : $this->extendList), null, $this->index, $this->currentFileInfo, $this->isReferenced);
$newSelector->evaldCondition = $evaldCondition ? $evaldCondition : $this->evaldCondition;
return $newSelector;
}
public function match( $other ){
if( !$other->_oelements || ($this->elements_len < $other->_oelements_len) ){
return 0;
}
for( $i = 0; $i < $other->_oelements_len; $i++ ){
if( $this->elements[$i]->value !== $other->_oelements[$i]) {
return 0;
}
}
return $other->_oelements_len; // return number of matched elements
}
public function CacheElements(){
$this->_oelements = array();
$this->_oelements_assoc = array();
$css = '';
foreach($this->elements as $v){
$css .= $v->combinator;
if( !$v->value_is_object ){
$css .= $v->value;
continue;
}
if( !property_exists($v->value,'value') || !is_string($v->value->value) ){
$this->cacheable = false;
return;
}
$css .= $v->value->value;
}
$this->_oelements_len = preg_match_all('/[,&#\.\w-](?:[\w-]|(?:\\\\.))*/', $css, $matches);
if( $this->_oelements_len ){
$this->_oelements = $matches[0];
if( $this->_oelements[0] === '&' ){
array_shift($this->_oelements);
$this->_oelements_len--;
}
$this->_oelements_assoc = array_fill_keys($this->_oelements, true);
}
}
public function isJustParentSelector(){
return !$this->mediaEmpty &&
count($this->elements) === 1 &&
$this->elements[0]->value === '&' &&
($this->elements[0]->combinator === ' ' || $this->elements[0]->combinator === '');
}
public function compile($env) {
$elements = array();
foreach($this->elements as $el){
$elements[] = $el->compile($env);
}
$extendList = array();
foreach($this->extendList as $el){
$extendList[] = $el->compile($el);
}
$evaldCondition = false;
if( $this->condition ){
$evaldCondition = $this->condition->compile($env);
}
return $this->createDerived( $elements, $extendList, $evaldCondition );
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output, $firstSelector = true ){
if( !$firstSelector && $this->elements[0]->combinator === "" ){
$output->add(' ', $this->currentFileInfo, $this->index);
}
foreach($this->elements as $element){
$element->genCSS( $output );
}
}
public function markReferenced(){
$this->isReferenced = true;
}
public function getIsReferenced(){
return !isset($this->currentFileInfo['reference']) || !$this->currentFileInfo['reference'] || $this->isReferenced;
}
public function getIsOutput(){
return $this->evaldCondition;
}
}
UnicodeDescriptor.php 0000644 00000000643 15155315057 0010714 0 ustar 00 <?php
/**
* UnicodeDescriptor
*
* @package Less
* @subpackage tree
*/
class Less_Tree_UnicodeDescriptor extends Less_Tree{
public $value;
public $type = 'UnicodeDescriptor';
public function __construct($value){
$this->value = $value;
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$output->add( $this->value );
}
public function compile(){
return $this;
}
}
Unit.php 0000644 00000006131 15155315057 0006204 0 ustar 00 <?php
/**
* Unit
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Unit extends Less_Tree{
var $numerator = array();
var $denominator = array();
public $backupUnit;
public $type = 'Unit';
public function __construct($numerator = array(), $denominator = array(), $backupUnit = null ){
$this->numerator = $numerator;
$this->denominator = $denominator;
$this->backupUnit = $backupUnit;
}
public function __clone(){
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
if( $this->numerator ){
$output->add( $this->numerator[0] );
}elseif( $this->denominator ){
$output->add( $this->denominator[0] );
}elseif( !Less_Parser::$options['strictUnits'] && $this->backupUnit ){
$output->add( $this->backupUnit );
return ;
}
}
public function toString(){
$returnStr = implode('*',$this->numerator);
foreach($this->denominator as $d){
$returnStr .= '/'.$d;
}
return $returnStr;
}
public function __toString(){
return $this->toString();
}
/**
* @param Less_Tree_Unit $other
*/
public function compare($other) {
return $this->is( $other->toString() ) ? 0 : -1;
}
public function is($unitString){
return $this->toString() === $unitString;
}
public function isLength(){
$css = $this->toCSS();
return !!preg_match('/px|em|%|in|cm|mm|pc|pt|ex/',$css);
}
public function isAngle() {
return isset( Less_Tree_UnitConversions::$angle[$this->toCSS()] );
}
public function isEmpty(){
return !$this->numerator && !$this->denominator;
}
public function isSingular() {
return count($this->numerator) <= 1 && !$this->denominator;
}
public function usedUnits(){
$result = array();
foreach(Less_Tree_UnitConversions::$groups as $groupName){
$group = Less_Tree_UnitConversions::${$groupName};
foreach($this->numerator as $atomicUnit){
if( isset($group[$atomicUnit]) && !isset($result[$groupName]) ){
$result[$groupName] = $atomicUnit;
}
}
foreach($this->denominator as $atomicUnit){
if( isset($group[$atomicUnit]) && !isset($result[$groupName]) ){
$result[$groupName] = $atomicUnit;
}
}
}
return $result;
}
public function cancel(){
$counter = array();
$backup = null;
foreach($this->numerator as $atomicUnit){
if( !$backup ){
$backup = $atomicUnit;
}
$counter[$atomicUnit] = ( isset($counter[$atomicUnit]) ? $counter[$atomicUnit] : 0) + 1;
}
foreach($this->denominator as $atomicUnit){
if( !$backup ){
$backup = $atomicUnit;
}
$counter[$atomicUnit] = ( isset($counter[$atomicUnit]) ? $counter[$atomicUnit] : 0) - 1;
}
$this->numerator = array();
$this->denominator = array();
foreach($counter as $atomicUnit => $count){
if( $count > 0 ){
for( $i = 0; $i < $count; $i++ ){
$this->numerator[] = $atomicUnit;
}
}elseif( $count < 0 ){
for( $i = 0; $i < -$count; $i++ ){
$this->denominator[] = $atomicUnit;
}
}
}
if( !$this->numerator && !$this->denominator && $backup ){
$this->backupUnit = $backup;
}
sort($this->numerator);
sort($this->denominator);
}
}
UnitConversions.php 0000644 00000001144 15155315057 0010434 0 ustar 00 <?php
/**
* UnitConversions
*
* @package Less
* @subpackage tree
*/
class Less_Tree_UnitConversions{
public static $groups = array('length','duration','angle');
public static $length = array(
'm'=> 1,
'cm'=> 0.01,
'mm'=> 0.001,
'in'=> 0.0254,
'px'=> 0.000264583, // 0.0254 / 96,
'pt'=> 0.000352778, // 0.0254 / 72,
'pc'=> 0.004233333, // 0.0254 / 72 * 12
);
public static $duration = array(
's'=> 1,
'ms'=> 0.001
);
public static $angle = array(
'rad' => 0.1591549430919, // 1/(2*M_PI),
'deg' => 0.002777778, // 1/360,
'grad'=> 0.0025, // 1/400,
'turn'=> 1
);
} Url.php 0000644 00000003400 15155315057 0006023 0 ustar 00 <?php
/**
* Url
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Url extends Less_Tree{
public $attrs;
public $value;
public $currentFileInfo;
public $isEvald;
public $type = 'Url';
public function __construct($value, $currentFileInfo = null, $isEvald = null){
$this->value = $value;
$this->currentFileInfo = $currentFileInfo;
$this->isEvald = $isEvald;
}
public function accept( $visitor ){
$this->value = $visitor->visitObj($this->value);
}
/**
* @see Less_Tree::genCSS
*/
public function genCSS( $output ){
$output->add( 'url(' );
$this->value->genCSS( $output );
$output->add( ')' );
}
/**
* @param Less_Functions $ctx
*/
public function compile($ctx){
$val = $this->value->compile($ctx);
if( !$this->isEvald ){
// Add the base path if the URL is relative
if( Less_Parser::$options['relativeUrls']
&& $this->currentFileInfo
&& is_string($val->value)
&& Less_Environment::isPathRelative($val->value)
){
$rootpath = $this->currentFileInfo['uri_root'];
if ( !$val->quote ){
$rootpath = preg_replace('/[\(\)\'"\s]/', '\\$1', $rootpath );
}
$val->value = $rootpath . $val->value;
}
$val->value = Less_Environment::normalizePath( $val->value);
}
// Add cache buster if enabled
if( Less_Parser::$options['urlArgs'] ){
if( !preg_match('/^\s*data:/',$val->value) ){
$delimiter = strpos($val->value,'?') === false ? '?' : '&';
$urlArgs = $delimiter . Less_Parser::$options['urlArgs'];
$hash_pos = strpos($val->value,'#');
if( $hash_pos !== false ){
$val->value = substr_replace($val->value,$urlArgs, $hash_pos, 0);
} else {
$val->value .= $urlArgs;
}
}
}
return new Less_Tree_URL($val, $this->currentFileInfo, true);
}
}
Value.php 0000644 00000001432 15155315057 0006340 0 ustar 00 <?php
/**
* Value
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Value extends Less_Tree{
public $type = 'Value';
public $value;
public function __construct($value){
$this->value = $value;
}
public function accept($visitor) {
$this->value = $visitor->visitArray($this->value);
}
public function compile($env){
$ret = array();
$i = 0;
foreach($this->value as $i => $v){
$ret[] = $v->compile($env);
}
if( $i > 0 ){
return new Less_Tree_Value($ret);
}
return $ret[0];
}
/**
* @see Less_Tree::genCSS
*/
function genCSS( $output ){
$len = count($this->value);
for($i = 0; $i < $len; $i++ ){
$this->value[$i]->genCSS( $output );
if( $i+1 < $len ){
$output->add( Less_Environment::$_outputMap[','] );
}
}
}
}
Variable.php 0000644 00000002320 15155315057 0007006 0 ustar 00 <?php
/**
* Variable
*
* @package Less
* @subpackage tree
*/
class Less_Tree_Variable extends Less_Tree{
public $name;
public $index;
public $currentFileInfo;
public $evaluating = false;
public $type = 'Variable';
/**
* @param string $name
*/
public function __construct($name, $index = null, $currentFileInfo = null) {
$this->name = $name;
$this->index = $index;
$this->currentFileInfo = $currentFileInfo;
}
public function compile($env) {
if( $this->name[1] === '@' ){
$v = new Less_Tree_Variable(substr($this->name, 1), $this->index + 1, $this->currentFileInfo);
$name = '@' . $v->compile($env)->value;
}else{
$name = $this->name;
}
if ($this->evaluating) {
throw new Less_Exception_Compiler("Recursive variable definition for " . $name, null, $this->index, $this->currentFileInfo);
}
$this->evaluating = true;
foreach($env->frames as $frame){
if( $v = $frame->variable($name) ){
$r = $v->value->compile($env);
$this->evaluating = false;
return $r;
}
}
throw new Less_Exception_Compiler("variable " . $name . " is undefined in file ".$this->currentFileInfo["filename"], null, $this->index, $this->currentFileInfo);
}
}