/** * Tries to find a file. * * @param string $path The path to a file * @param FileInfo $currentFileInfo * * @return string|false */ protected function find($path, FileInfo $currentFileInfo) { if (Util::isPathAbsolute($path) && is_readable($path)) { return realpath($path); } elseif (is_readable($currentFileInfo->currentDirectory . $path)) { return realpath($currentFileInfo->currentDirectory . $path); } // try import dirs foreach ($this->importDirs as $importDir) { if (is_readable($importDir . '/' . $path)) { return realpath($importDir . '/' . $path); } } return false; }
/** * Does the import * * @param ImportedFile $file The imported file * @param string $path The original path * @param FileInfo $currentFileInfo Current file info * @param array $importOptions Import options * @param boolean $fromCache Is the imported file coming from cache? * @throws ParserException * @throws Exception * @return array */ protected function doImport(ImportedFile $file, $path, FileInfo $currentFileInfo, array $importOptions = [], $fromCache = false) { $newEnv = Context::createCopyForCompilation($this->context, $this->context->frames); $newFileInfo = clone $currentFileInfo; if ($this->context->relativeUrls) { // Pass on an updated rootPath if path of imported file is relative and file // is in a (sub|sup) directory // // Examples: // - If path of imported file is 'module/nav/nav.less' and rootPath is 'less/', // then rootPath should become 'less/module/nav/' // - If path of imported file is '../mixins.less' and rootPath is 'less/', // then rootPath should become 'less/../' if (!Util::isPathAbsolute($path) && ($lastSlash = strrpos($path, '/')) !== false) { $relativeSubDirectory = substr($path, 0, $lastSlash + 1); $newFileInfo->rootPath = $newFileInfo->rootPath . $relativeSubDirectory; } } // we need to clone here, to prevent modification of node current info object $newEnv->currentFileInfo = $newFileInfo; $newEnv->processImports = false; if ($currentFileInfo->reference || isset($importOptions['reference']) && $importOptions['reference']) { $newEnv->currentFileInfo->reference = true; } $key = $file->getPath(); $root = null; $alreadyImported = false; // check for already imported file if (isset($this->importedFiles[$key])) { $alreadyImported = true; } elseif (!$file->getRuleset()) { try { // we do not parse the root but load the file as is if (isset($importOptions['inline']) && $importOptions['inline']) { $root = $file->getContent(); } else { $parser = new Core($newEnv, $this, $this->pluginManager); $root = $parser->parseFile($file, true); $root->root = false; $root->firstRoot = false; } $file->setRuleset($root); // we need to catch parse exceptions } catch (Exception $e) { // rethrow throw $e; } catch (\Exception $error) { $file->setError($error); } $this->setImportedFile($key, $file, $path, $currentFileInfo); } else { $this->setImportedFile($key, $file, $path, $currentFileInfo); } if ($fromCache) { $ruleset = $this->importedFiles[$key][0]->getRuleset(); if ($ruleset instanceof Node) { // this is a workaround for reference and import one issues when taken cache $this->updateReferenceInCurrentFileInfo($ruleset, $newEnv->currentFileInfo); } } return [$alreadyImported, $this->importedFiles[$key][0]]; }
/** * Runs the task based on the arguments * * @return integer 0 on success, error code on failure */ public function run() { if (!$this->isValid()) { echo $this->getUsage(); // return error return 1; } elseif ($this->getOption('version')) { echo Parser\Core::VERSION . ' [compatible with less.js ' . Parser\Core::LESS_JS_VERSION . ']' . PHP_EOL; return 0; } elseif ($this->getOption('help')) { echo $this->getUsage(); return 0; } try { $toBeParsed = $this->cliArguments['arguments'][0]; $parser = new Parser($this->prepareOptionsForTheParser()); $method = null; // read from stdin if (in_array($toBeParsed, $this->stdAliases)) { $toBeParsed = file_get_contents('php://stdin'); $method = 'parseString'; } else { if (!Util::isPathAbsolute($toBeParsed)) { $toBeParsed = sprintf('%s/%s', $this->currentDir, $toBeParsed); } $method = 'parseFile'; } // setup file $setupFile = $this->getOption('setup_file'); if ($setupFile === null) { $setupFilePath = getcwd() . '/.iless'; if (file_exists($setupFilePath)) { if (!is_readable($setupFilePath)) { throw new \RuntimeException(sprintf('Setup file "%s" could not be loaded. File does not exist or is not readable.', $setupFile)); } self::loadSetupFile($setupFilePath, $parser); } } else { $setupFilePath = $setupFile; if (!Util::isPathAbsolute($setupFilePath)) { $setupFilePath = getcwd() . '/' . $setupFile; } if (!is_readable($setupFilePath)) { throw new \RuntimeException(sprintf('Setup file "%s" could not be loaded. File does not exist or is not readable.', $setupFilePath)); } self::loadSetupFile($setupFilePath, $parser); } $parser->{$method}($toBeParsed); $toBeSavedTo = null; if (isset($this->cliArguments['arguments'][1])) { $toBeSavedTo = $this->cliArguments['arguments'][1]; if (!Util::isPathAbsolute($toBeSavedTo)) { $toBeSavedTo = sprintf('%s/%s', $this->currentDir, $toBeSavedTo); } } $css = $parser->getCSS(); // where to put the css? if ($toBeSavedTo) { // write the result $this->saveCSS($toBeSavedTo, $css, $this->getOption('append')); } else { echo $css; } } catch (Exception $e) { if (!$this->getOption('silent')) { $this->renderException($e); } return $e->getCode() ?: 1; } return 0; }
/** * Returns file editor link. The link format can be customized. * * @param FileInfo|string $file The current file * @param int $line * * @return string|void * * @see setFileEditorUrlFormat */ protected function getFileEditorLink($file, $line = null) { if ($file instanceof FileInfo) { $path = $file->filename; if ($file->importedFile) { $path = $file->importedFile->getPath(); } if (strpos($path, '__string_to_parse__') === 0) { $path = '[input string]'; } } else { $path = $file; } // when in cli or not accessible via filesystem, don't generate links if (PHP_SAPI == 'cli' || !Util::isPathAbsolute($path)) { return $path; } return sprintf('<a href="%s" class="file-edit">%s</a>', htmlspecialchars(strtr(self::$fileEditUrlFormat, ['%f' => $path, '%file' => $path, '%line' => $line, '%l' => $line])), $path); }