/** * {@inheritdoc} */ public function compare(Node $other) { // we can compare only units if ($other instanceof self) { return $this->is($other->toString()) ? 0 : null; } }
/** * {@inheritdoc} */ public function toCSS(Context $context) { $value = $this->key instanceof GenerateCSSInterface ? $this->key->toCSS($context) : $this->key; if ($this->operator) { $value .= $this->operator; $value .= $this->value instanceof GenerateCSSInterface ? $this->value->toCSS($context) : $this->value; } return '[' . $value . ']'; }
/** * Constructor * * @param Node $value * @param int $index * @param FileInfo $currentFileInfo * @param bool $isCompiled */ public function __construct(Node $value, $index = 0, FileInfo $currentFileInfo = null, $isCompiled = false) { parent::__construct($value); $this->index = $index; $this->currentFileInfo = $currentFileInfo; $this->isCompiled = $isCompiled; }
/** * Constructor. * * @param string $value The comment value * @param bool $isLineComment */ public function __construct($value, $isLineComment = false, $index = 0, FileInfo $currentFileInfo = null) { parent::__construct($value); $this->isLineComment = (bool) $isLineComment; $this->index = $index; $this->currentFileInfo = $currentFileInfo; }
/** * Compiles the node * * @param Context $context The context * @param array|null $arguments Array of arguments * @param boolean|null $important Important flag * @return boolean */ public function compile(Context $context, $arguments = null, $important = null) { $a = $this->lvalue->compile($context); $b = $this->rvalue->compile($context); switch ($this->op) { case 'and': $result = $a && $b; break; case 'or': $result = $a || $b; break; default: $compared = Util::compareNodes($a, $b); // strict comparison, we cannot use switch here if ($compared === -1) { $result = $this->op === '<' || $this->op === '=<' || $this->op === '<='; } elseif ($compared === 0) { $result = $this->op === '=' || $this->op === '>=' || $this->op === '=<' || $this->op === '<='; } elseif ($compared === 1) { $result = $this->op === '>' || $this->op === '>=' || $this->op === '=>'; } else { $result = false; } break; } return $this->negate ? !$result : $result; }
/** * Constructor. * * @param string $name The name * @param array|string $value The value * @param RulesetNode|null|array $rules * @param int $index The index * @param FileInfo $currentFileInfo Current file info * @param DebugInfo $debugInfo The debug information * @param bool $isReferenced Is referenced? * @param bool $isRooted Is rooted? */ public function __construct($name, $value, $rules = null, $index = 0, FileInfo $currentFileInfo = null, DebugInfo $debugInfo = null, $isReferenced = false, $isRooted = false) { $this->name = $name; parent::__construct($value); if (null !== $rules) { if (is_array($rules)) { $this->rules = $rules; } else { $this->rules = [$rules]; $selectors = new SelectorNode([], [], null, $index, $currentFileInfo); $this->rules[0]->selectors = $selectors->createEmptySelectors(); } for ($i = 0; $i < count($this->rules); ++$i) { $this->rules[$i]->allowImports = true; } } else { // null $this->rules = $rules; } $this->index = $index; $this->currentFileInfo = $currentFileInfo; $this->debugInfo = $debugInfo; $this->isReferenced = $isReferenced; $this->isRooted = $isRooted; }
/** * Constructor * * @param string|array $rgb The rgb value * @param integer $alpha Alpha channel * @param string $originalForm Original form of the color * @throws InvalidArgumentException */ public function __construct($rgb, $alpha = 1, $originalForm = null) { if (!$rgb instanceof Color) { $value = new Color($rgb, $alpha, $originalForm); } else { $value = $rgb; } /* @var $value \ILess\Color */ parent::__construct($value); }
/** * Constructor * * @param string $value The string */ public function __construct($value = null) { if ($value === ' ') { $this->emptyOrWhitespace = true; } else { $value = trim($value); $this->emptyOrWhitespace = $value === ''; } parent::__construct($value); }
/** * Constructor. * * @param string|array $name The rule name * @param string|ValueNode $value The value * @param string $important Important keyword * @param string|null $merge Merge? * @param int $index Current index * @param FileInfo $currentFileInfo The current file info * @param bool $inline Inline flag * @param bool|null $variable */ public function __construct($name, $value, $important = null, $merge = null, $index = 0, FileInfo $currentFileInfo = null, $inline = false, $variable = null) { parent::__construct($value instanceof Node ? $value : new ValueNode([$value])); $this->name = $name; $this->important = $important ? ' ' . trim($important) : ''; $this->merge = $merge; $this->index = $index; $this->currentFileInfo = $currentFileInfo; $this->inline = (bool) $inline; $this->variable = null !== $variable ? $variable : is_string($name) && $name[0] === '@'; }
/** * Constructor * * @param CombinatorNode|string $combinator The combinator * @param string|Node $value The value * @param integer $index The current index * @param FileInfo $currentFileInfo Current file information */ public function __construct($combinator, $value, $index = 0, FileInfo $currentFileInfo = null) { $this->combinator = $combinator instanceof CombinatorNode ? $combinator : new CombinatorNode($combinator); if (is_string($value)) { $value = trim($value); } elseif (!$value) { $value = ''; } parent::__construct($value); $this->index = $index; $this->currentFileInfo = $currentFileInfo; }
/** * @inheritdoc */ public function generateCSS(Context $context, OutputInterface $output) { $isNotReference = !isset($this->path->currentFileInfo) || !$this->path->currentFileInfo->reference; if ($this->css && $isNotReference) { $output->add('@import '); $this->path->generateCSS($context, $output); if ($this->features) { $output->add(' '); $this->features->generateCSS($context, $output); } $output->add(';'); } return $output; }
/** * Updates the currentFileInfo object to the $value * * @param Node $node The node to update * @param FileInfo $newInfo The new file info */ protected function updateReferenceInCurrentFileInfo(Node $node, FileInfo $newInfo) { if (isset($node->currentFileInfo)) { $node->currentFileInfo->reference = $newInfo->reference; $node->currentFileInfo->rootPath = $newInfo->rootPath; } if (Node::propertyExists($node, 'rules') && is_array($node->rules) && $node->rules) { foreach ($node->rules as $rule) { $this->updateReferenceInCurrentFileInfo($rule, $newInfo); } } }
/** * @inheritdoc */ public function compare(Node $other) { // we need to provide The context for those $context = new Context(); if ($this->toCSS($context) === $other->toCSS($context)) { return 0; } }
/** * Creates a SVG gradient * * @param Node $direction * @param Node ...$stop1 * @return UrlNode * @throws CompilerException If the arguments are invalid */ public function svggradient(Node $direction) { $numArgs = func_num_args(); $arguments = func_get_args(); if ($numArgs === 2) { // a list of colors if (is_array($arguments[1]->value) && count($arguments[1]->value) < 2) { throw new CompilerException('svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]'); } $stops = $arguments[1]->value; } elseif ($numArgs < 3) { throw new CompilerException('svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position]'); } else { $stops = array_slice($arguments, 1); } $gradientType = 'linear'; $rectangleDimension = 'x="0" y="0" width="1" height="1"'; $renderEnv = new Context(['compress' => false]); $directionValue = $direction->toCSS($renderEnv); switch ($directionValue) { case 'to bottom': $gradientDirectionSvg = 'x1="0%" y1="0%" x2="0%" y2="100%"'; break; case 'to right': $gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="0%"'; break; case 'to bottom right': $gradientDirectionSvg = 'x1="0%" y1="0%" x2="100%" y2="100%"'; break; case 'to top right': $gradientDirectionSvg = 'x1="0%" y1="100%" x2="100%" y2="0%"'; break; case 'ellipse': case 'ellipse at center': $gradientType = 'radial'; $gradientDirectionSvg = 'cx="50%" cy="50%" r="75%"'; $rectangleDimension = 'x="-50" y="-50" width="101" height="101"'; break; default: throw new CompilerException("svg-gradient direction must be 'to bottom', 'to right', 'to bottom right', 'to top right' or 'ellipse at center'"); } $returner = '<?xml version="1.0" ?>' . '<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none">' . '<' . $gradientType . 'Gradient id="gradient" gradientUnits="userSpaceOnUse" ' . $gradientDirectionSvg . '>'; for ($i = 0; $i < count($stops); $i++) { if ($stops[$i] instanceof ExpressionNode) { $color = $stops[$i]->value[0]; $position = $stops[$i]->value[1]; } else { $color = $stops[$i]; $position = null; } if (!$color instanceof ColorNode || !(($i === 0 || $i + 1 === count($stops)) && $position === null) && !$position instanceof DimensionNode) { throw new CompilerException('svg-gradient expects direction, start_color [start_position], [color position,]..., end_color [end_position] or direction, color list'); } if ($position) { $positionValue = $position->toCSS($renderEnv); } elseif ($i === 0) { $positionValue = '0%'; } else { $positionValue = '100%'; } $colorValue = $color->getColor()->toRGB(); $alpha = $color->getAlpha(true); $returner .= '<stop offset="' . $positionValue . '" stop-color="' . $colorValue . '"' . ($alpha < 1 ? ' stop-opacity="' . $alpha . '"' : '') . '/>'; } $returner .= '</' . $gradientType . 'Gradient><rect ' . $rectangleDimension . ' fill="url(#gradient)" /></svg>'; $returner = Util::encodeURIComponent($returner); $returner = 'data:image/svg+xml,' . $returner; return new UrlNode(new QuotedNode("'" . $returner . "'", $returner, false)); }
/** * Constructor * * @param array $value * @throws Exception */ public function __construct(array $value) { parent::__construct($value); }
/** * Compares with another dimension * * @param Node $other * @return integer */ public function compare(Node $other) { if (!$other instanceof DimensionNode) { return null; } 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 null; } } return Util::numericCompare($a->value, $b->value); }
/** * Compares with another node * * @param Node $other * @return integer|null */ public function compare(Node $other) { if ($other instanceof QuotedNode && !$this->escaped && !$other->escaped) { return Util::numericCompare($this->value, $other->value); } else { $context = new Context(); return $other->toCSS($context) === $this->toCSS($context) ? 0 : null; } }
/** * Visits a ruleset node * * @param RulesetNode $node The node * @param VisitorArguments $arguments The arguments * @return array|RulesetNode */ public function visitRuleset(RulesetNode $node, VisitorArguments $arguments) { if ($node->firstRoot) { $this->checkPropertiesInRoot($node->rules); } $rulesets = []; if (!$node->root) { $paths = []; foreach ($node->paths as $p) { if ($p[0]->elements[0]->combinator->value === ' ') { $p[0]->elements[0]->combinator = new CombinatorNode(''); } foreach ($p as $pi) { /* @var $pi SelectorNode */ if ($pi->getIsReferenced() && $pi->getIsOutput()) { $paths[] = $p; break; } } } $node->paths = $paths; // Compile rules and rulesets for ($i = 0, $count = count($node->rules); $i < $count;) { $rule = $node->rules[$i]; //if ($rule instanceof ILess\ILess\Node\RuleNode || $rule instanceof ILess\ILess\Node\RulesetNode) { //if ($rule instanceof ILess\ILess\Node\RulesetNode) { if (Node::propertyExists($rule, 'rules')) { // visit because we are moving them out from being a child $rulesets[] = $this->visit($rule); array_splice($node->rules, $i, 1); $count--; continue; } $i++; } // accept the visitor to remove rules and refactor itself // then we can decide now whether we want it or not if ($count > 0) { $node->accept($this); } else { $node->rules = []; } $arguments->visitDeeper = false; // accept the visitor to remove rules and refactor itself // then we can decide now whether we want it or not if ($node->rules) { // passed by reference $this->mergeRules($node->rules); } if ($node->rules) { // passed by reference $this->removeDuplicateRules($node->rules); } // now decide whether we keep the ruleset if ($node->rules && $node->paths) { array_splice($rulesets, 0, 0, [$node]); } } else { $node->accept($this); $arguments->visitDeeper = false; if ($node->firstRoot || count($node->rules) > 0) { array_splice($rulesets, 0, 0, [$node]); } } if (count($rulesets) === 1) { return $rulesets[0]; } return $rulesets; }
/** * Constructor. * * @param string $key * @param string|Node $value */ public function __construct($key, $value) { parent::__construct($value); $this->key = $key; }