Exemple #1
0
 /**
  * @param Context $context
  *
  * @return Node|RulesetNode
  */
 public function callCompile(Context $context)
 {
     if ($this->frames) {
         return $this->ruleset->compile(Context::createCopyForCompilation($context, array_merge($this->frames, $context->frames)));
     }
     return $this->ruleset->compile($context);
 }
Exemple #2
0
 /**
  * Visits a ruleset node.
  *
  * @param RulesetNode $node The node
  * @param VisitorArguments $arguments The arguments
  */
 public function visitRuleset(RulesetNode $node, VisitorArguments $arguments)
 {
     $paths = [];
     if (!$node->root) {
         $selectors = [];
         foreach ($node->selectors as $selector) {
             /* @var $selector SelectorNode */
             if ($selector->getIsOutput()) {
                 $selectors[] = $selector;
             }
         }
         $node->selectors = $selectors;
         if (count($selectors)) {
             $context = $this->contexts[count($this->contexts) - 1];
             $paths = $node->joinSelectors($context, $selectors);
         } else {
             $node->rules = [];
         }
         $node->paths = $paths;
     }
     $this->contexts[] = $paths;
 }
Exemple #3
0
 /**
  * Generates the CSS.
  *
  * @param Context $context
  *
  * @return string
  */
 public function generateCSS(Context $context)
 {
     $output = new MappedOutput($this->contentsMap, $this);
     // catch the output
     $this->root->generateCSS($context, $output);
     // prepare sources
     foreach ($this->contentsMap as $filename => $contents) {
         // match md5 hash in square brackets _[#HASH#]_
         // see ILess\Parser\Core::parseString()
         if (preg_match('/(\\[__[0-9a-f]{32}__\\])+$/', $filename)) {
             $filename = substr($filename, 0, -38);
         }
         $this->sources[$this->normalizeFilename($filename)] = $contents;
     }
     $sourceMapUrl = null;
     if ($url = $this->getOption('url')) {
         $sourceMapUrl = $url;
     } elseif ($path = $this->getOption('filename')) {
         $sourceMapUrl = $this->normalizeFilename($path);
         // naming conventions, make it foobar.css.map
         if (!preg_match('/\\.map$/', $sourceMapUrl)) {
             $sourceMapUrl = sprintf('%s.map', $sourceMapUrl);
         }
     }
     $sourceMapContent = $this->generateJson();
     // write map to a file
     if ($file = $this->getOption('write_to')) {
         $this->saveMap($file, $sourceMapContent);
     } else {
         $sourceMap = 'data:application/json;';
         if ($this->getOption('inline_encode_base64')) {
             $sourceMap .= 'base64,';
             $sourceMapContent = base64_encode($sourceMapContent);
         } else {
             $sourceMapContent = Util::encodeURIComponent($sourceMapContent);
         }
         $sourceMapUrl = $sourceMap . $sourceMapContent;
     }
     if ($sourceMapUrl) {
         $output->add(sprintf('/*# sourceMappingURL=%s */', $sourceMapUrl));
     }
     return $output->toString();
 }
Exemple #4
0
 /**
  * Compile parameters.
  *
  * @param Context $context The context
  * @param Context $mixinEnv The mixin environment
  * @param array $arguments Array of arguments
  * @param array $compiledArguments The compiled arguments
  *
  * @throws
  *
  * @return mixed
  */
 public function compileParams(Context $context, Context $mixinEnv, $arguments = [], array &$compiledArguments = [])
 {
     $frame = new RulesetNode([], []);
     $params = $this->params;
     $argsCount = 0;
     if (isset($mixinEnv->frames[0]) && $mixinEnv->frames[0]->functionRegistry) {
         $frame->functionRegistry = $mixinEnv->frames[0]->functionRegistry->inherit();
     }
     // create a copy of mixin environment
     $mixinEnv = Context::createCopyForCompilation($mixinEnv, array_merge([$frame], $mixinEnv->frames));
     if ($arguments) {
         $argsCount = count($arguments);
         for ($i = 0; $i < $argsCount; ++$i) {
             if (!isset($arguments[$i])) {
                 continue;
             }
             $arg = $arguments[$i];
             if (isset($arg['name']) && ($name = $arg['name'])) {
                 $isNamedFound = false;
                 foreach ($params as $j => $param) {
                     if (!isset($compiledArguments[$j]) && $name === $params[$j]['name']) {
                         $compiledArguments[$j] = $arg['value']->compile($context);
                         array_unshift($frame->rules, new RuleNode($name, $arg['value']->compile($context)));
                         $isNamedFound = true;
                         break;
                     }
                 }
                 if ($isNamedFound) {
                     array_splice($arguments, $i, 1);
                     --$i;
                     continue;
                 } else {
                     throw new CompilerException(sprintf('The named argument for `%s` %s was not found.', $this->name, $arguments[$i]['name']));
                 }
             }
         }
     }
     $argIndex = 0;
     foreach ($params as $i => $param) {
         if (array_key_exists($i, $compiledArguments)) {
             continue;
         }
         $arg = null;
         if (array_key_exists($argIndex, $arguments)) {
             $arg = $arguments[$argIndex];
         }
         if (isset($param['name']) && ($name = $param['name'])) {
             if (isset($param['variadic']) && $param['variadic']) {
                 $varArgs = [];
                 for ($j = $argIndex; $j < $argsCount; ++$j) {
                     $varArgs[] = $arguments[$j]['value']->compile($context);
                 }
                 $expression = new ExpressionNode($varArgs);
                 array_unshift($frame->rules, new RuleNode($name, $expression->compile($context)));
             } else {
                 $val = $arg && $arg['value'] ? $arg['value'] : false;
                 if ($val) {
                     $val = $val->compile($context);
                 } elseif (isset($param['value'])) {
                     $val = $param['value']->compile($mixinEnv);
                     $frame->resetCache();
                 } else {
                     throw new CompilerException(sprintf('Wrong number of arguments for `%s` (%s for %s)', $this->name, count($arguments), $this->arity));
                 }
                 array_unshift($frame->rules, new RuleNode($name, $val));
                 $compiledArguments[$i] = $val;
             }
         }
         if (isset($param['variadic']) && $param['variadic'] && $arguments) {
             for ($j = $argIndex; $j < $argsCount; ++$j) {
                 $compiledArguments[$j] = $arguments[$j]['value']->compile($context);
             }
         }
         ++$argIndex;
     }
     ksort($compiledArguments);
     return $frame;
 }
Exemple #5
0
 /**
  * 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;
 }
Exemple #6
0
 /**
  * Compiles the node
  *
  * @param Context $context The context
  * @param array|null $arguments Array of arguments
  * @param boolean|null $important Important flag
  * @return array|ImportNode|MediaNode
  * @throws Exception
  * @throws LogicException
  */
 public function compile(Context $context, $arguments = null, $important = null)
 {
     if ($this->getOption('plugin')) {
         $registry = isset($context->frames[0]) && $context->frames[0]->functionRegistry ? $context->frames[0]->functionRegistry : null;
         if ($registry && $this->root && $this->root->functions) {
             /* @var $registry FunctionRegistry */
             foreach ($this->root->functions as $funcFile) {
                 $registry->loadPlugin($funcFile);
             }
         }
         return [];
     }
     if ($this->skip) {
         return [];
     }
     if ($this->getOption('inline')) {
         $contents = new AnonymousNode($this->root, 0, new FileInfo(['filename' => $this->importedFilename, 'reference' => $this->path->currentFileInfo->reference]), true, true, false);
         return $this->features ? new MediaNode([$contents], $this->features->value) : [$contents];
     } elseif ($this->css) {
         $features = $this->features ? $this->features->compile($context) : null;
         $import = new ImportNode($this->compilePath($context), $features, $this->options, $this->index);
         if (!$import->css && $this->hasError()) {
             throw $this->getError();
         }
         return $import;
     } else {
         $ruleset = new RulesetNode([], $this->root ? $this->root->rules : []);
         $ruleset->compileImports($context);
         return $this->features ? new MediaNode($ruleset->rules, $this->features->value) : $ruleset->rules;
     }
 }
Exemple #7
0
 /**
  * @covers getType
  */
 public function testGetType()
 {
     $r = new RulesetNode([new ElementNode(' ', 'foobar')], []);
     $this->assertEquals('Ruleset', $r->getType());
 }