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; }
/** * @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); }
public function operate($env, $op, $other) { $value = Less_Environment::operate($env, $op, $this->value, $other->value); $unit = clone $this->unit; if ($op === '+' || $op === '-') { if (!count($unit->numerator) && !count($unit->denominator)) { $unit->numerator = $other->unit->numerator; $unit->denominator = $other->unit->denominator; } elseif (!count($other->unit->numerator) && !count($other->unit->denominator)) { // do nothing } else { $other = $other->convertTo($this->unit->usedUnits()); if ($env->strictUnits && $other->unit->toString() !== $unit->toCSS()) { throw new Less_CompilerException("Incompatible units. Change the units or use the unit function. Bad units: '" . $unit->toString() . "' and " . $other->unit->toString() + "'."); } $value = Less_Environment::operate($env, $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 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)); }
public function operate($env, $op, $other) { $result = array(); if (!$other instanceof Less_Tree_Color) { $other = $other->toColor(); } for ($c = 0; $c < 3; $c++) { $result[$c] = Less_Environment::operate($env, $op, $this->rgb[$c], $other->rgb[$c]); } return new Less_Tree_Color($result, $this->alpha + $other->alpha); }
public function Init() { self::$parensStack = 0; self::$tabLevel = 0; self::$lastRule = false; self::$mixin_stack = 0; if (Less_Parser::$options['compress']) { Less_Environment::$_outputMap = array(',' => ',', ': ' => ':', '' => '', ' ' => ' ', ':' => ' :', '+' => '+', '~' => '~', '>' => '>', '|' => '|', '^' => '^', '^^' => '^^'); } else { Less_Environment::$_outputMap = array(',' => ', ', ': ' => ': ', '' => '', ' ' => ' ', ':' => ' :', '+' => ' + ', '~' => ' ~ ', '>' => ' > ', '|' => '|', '^' => ' ^ ', '^^' => ' ^^ '); } }
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); }
public function datauri($mimetypeNode, $filePathNode = null) { $filePath = $filePathNode ? $filePathNode->value : null; $mimetype = $mimetypeNode->value; $args = 2; if (!$filePath) { $filePath = $mimetype; $args = 1; } $filePath = str_replace('\\', '/', $filePath); if (Less_Environment::isPathRelative($filePath)) { if (Less_Parser::$options['relativeUrls']) { $temp = $this->currentFileInfo['currentDirectory']; } else { $temp = $this->currentFileInfo['entryPath']; } if (!empty($temp)) { $filePath = Less_Environment::normalizePath(rtrim($temp, '/') . '/' . $filePath); } } // detect the mimetype if not given if ($args < 2) { /* incomplete $mime = require('mime'); mimetype = mime.lookup(path); // use base 64 unless it's an ASCII or UTF-8 format var charset = mime.charsets.lookup(mimetype); useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0; if (useBase64) mimetype += ';base64'; */ $mimetype = Less_Mime::lookup($filePath); $charset = Less_Mime::charsets_lookup($mimetype); $useBase64 = !in_array($charset, array('US-ASCII', 'UTF-8')); if ($useBase64) { $mimetype .= ';base64'; } } else { $useBase64 = preg_match('/;base64$/', $mimetype); } if (file_exists($filePath)) { $buf = @file_get_contents($filePath); } else { $buf = false; } // IE8 cannot handle a data-uri larger than 32KB. If this is exceeded // and the --ieCompat flag is enabled, return a normal url() instead. $DATA_URI_MAX_KB = 32; $fileSizeInKB = round(strlen($buf) / 1024); if ($fileSizeInKB >= $DATA_URI_MAX_KB) { $url = new Less_Tree_Url($filePathNode ? $filePathNode : $mimetypeNode, $this->currentFileInfo); return $url->compile($this); } if ($buf) { $buf = $useBase64 ? base64_encode($buf) : rawurlencode($buf); $filePath = '"data:' . $mimetype . ',' . $buf . '"'; } return new Less_Tree_Url(new Less_Tree_Anonymous($filePath)); }
/** * @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"); } }
/** * @param string $filename */ public function SetFileInfo($filename, $uri_root = '') { $filename = Less_Environment::normalizePath($filename); $dirname = preg_replace('/[^\\/\\\\]*$/', '', $filename); if (!empty($uri_root)) { $uri_root = rtrim($uri_root, '/') . '/'; } $currentFileInfo = array(); //entry info if (isset($this->env->currentFileInfo)) { $currentFileInfo['entryPath'] = $this->env->currentFileInfo['entryPath']; $currentFileInfo['entryUri'] = $this->env->currentFileInfo['entryUri']; $currentFileInfo['rootpath'] = $this->env->currentFileInfo['rootpath']; } else { $currentFileInfo['entryPath'] = $dirname; $currentFileInfo['entryUri'] = $uri_root; $currentFileInfo['rootpath'] = $dirname; } $currentFileInfo['currentDirectory'] = $dirname; $currentFileInfo['currentUri'] = $uri_root . basename($filename); $currentFileInfo['filename'] = $filename; $currentFileInfo['uri_root'] = $uri_root; //inherit reference if (isset($this->env->currentFileInfo['reference']) && $this->env->currentFileInfo['reference']) { $currentFileInfo['reference'] = true; } $this->env->currentFileInfo = $currentFileInfo; }
/** * 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 $import_dirs[$this->currentFileInfo['currentDirectory']] = $this->currentFileInfo['uri_root']; } else { //otherwise, the file should be relative to the server root $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); } } } } }
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; }
function compile($env) { $evald = $this->compileForImport($env); $uri = $full_path = false; //get path & uri $evald_path = $evald->getPath(); if ($evald_path && $env->isPathRelative($evald_path)) { foreach (Less_Parser::$import_dirs as $rootpath => $rooturi) { $temp = $rootpath . $evald_path; if (file_exists($temp)) { $full_path = Less_Environment::NormPath($temp); $uri = Less_Environment::NormPath(dirname($rooturi . $evald_path)); break; } } } if (!$full_path) { $uri = $evald_path; $full_path = $evald_path; } //import once $realpath = realpath($full_path); if (!isset($evald->options['multiple']) && $realpath && Less_Parser::FileParsed($realpath)) { $evald->skip = true; } $features = $evald->features ? $evald->features->compile($env) : null; if ($evald->skip) { return array(); } if ($evald->css) { $temp = $this->compilePath($env); return new Less_Tree_Import($this->compilePath($env), $features, $this->options, $this->index); } $parser = new Less_Parser($env); $evald->root = $parser->parseFile($full_path, $uri, true); $ruleset = new Less_Tree_Ruleset(array(), $evald->root->rules); $ruleset->evalImports($env); return $this->features ? new Less_Tree_Media($ruleset->rules, $this->features->value) : $ruleset->rules; }
/** * @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); } return new Less_Tree_URL($val, $this->currentFileInfo, true); }
public function compile($env, $args = NULL, $important = NULL) { $_arguments = array(); $mixinFrames = array_merge($this->frames, $env->frames); $mixinEnv = new Less_Environment(); $mixinEnv->addFrames($mixinFrames); $frame = $this->compileParams($env, $mixinEnv, $args, $_arguments); $ex = new Less_Tree_Expression($_arguments); array_unshift($frame->rules, new Less_Tree_Rule('@arguments', $ex->compile($env))); $rules = $important ? Less_Tree_Ruleset::makeImportant($this->selectors, $this->rules)->rules : array_slice($this->rules, 0); $ruleset = new Less_Tree_Ruleset(null, $rules); // duplicate the environment, adding new frames. $ruleSetEnv = new Less_Environment(); $ruleSetEnv->addFrame($this); $ruleSetEnv->addFrame($frame); $ruleSetEnv->addFrames($mixinFrames); $ruleSetEnv->compress = $env->compress; $ruleset = $ruleset->compile($ruleSetEnv); $ruleset->originalRuleset = $this; return $ruleset; }
public function SetFileInfo( $filename, $uri_root = ''){ $this->path = pathinfo($filename, PATHINFO_DIRNAME); $this->filename = Less_Environment::NormPath($filename); $dirname = preg_replace('/[^\/\\\\]*$/','',$this->filename); $currentFileInfo = array(); $currentFileInfo['currentDirectory'] = $dirname; $currentFileInfo['filename'] = $filename; $currentFileInfo['rootpath'] = $dirname; $currentFileInfo['entryPath'] = $dirname; if( empty($uri_root) ){ $currentFileInfo['uri_root'] = $uri_root; }else{ $currentFileInfo['uri_root'] = rtrim($uri_root,'/').'/'; } $this->env->currentFileInfo = $currentFileInfo; self::$import_dirs = array_merge( array( $dirname => $currentFileInfo['uri_root'] ), self::$import_dirs ); }