public function filterLoad(AssetInterface $asset) { $sourceUrl = $asset->getSourceUrl(); if (!$sourceUrl || false !== strpos($sourceUrl, '://')) { return; } $options = array($this->sprocketizePath); foreach ($this->includeDirs as $directory) { $options[] = '-I'; $options[] = $directory; } if (null !== $this->assetRoot) { $options[] = '-a'; $options[] = $this->assetRoot; } // hack in a temporary file sibling $options[] = $input = dirname($this->baseDir.'/'.$sourceUrl).'/.'.rand(11111, 99999).'-'.basename($sourceUrl); $tmp = tempnam(sys_get_temp_dir(), 'assetic_sprockets'); file_put_contents($tmp, $asset->getContent()); rename($tmp, $input); $proc = new Process(implode(' ', array_map('escapeshellarg', $options))); $code = $proc->run(); unlink($input); if (0 < $code) { throw new \RuntimeException($proc->getErrorOutput()); } $asset->setContent($proc->getOutput()); }
public function filterDump(AssetInterface $asset) { $sourceUrl = $asset->getSourceUrl(); $targetUrl = $asset->getTargetUrl(); if (null === $sourceUrl || null === $targetUrl || $sourceUrl == $targetUrl) { return; } // learn how to get from the target back to the source if (false !== strpos($sourceUrl, '://')) { // the source is absolute, this should be easy $parts = parse_url($sourceUrl); $host = $parts['scheme'] . '://' . $parts['host']; $path = dirname($parts['path']) . '/'; } else { // assume source and target are on the same host $host = ''; // pop entries off the target until it fits in the source if ('.' == dirname($sourceUrl)) { $path = str_repeat('../', substr_count($targetUrl, '/')); } elseif ('.' == ($targetDir = dirname($targetUrl))) { $path = dirname($sourceUrl) . '/'; } else { $path = ''; while (0 !== strpos($sourceUrl, $targetDir)) { if (false !== ($pos = strrpos($targetDir, '/'))) { $targetDir = substr($targetDir, 0, $pos); $path .= '../'; } else { $targetDir = ''; $path .= '../'; break; } } $path .= substr(dirname($sourceUrl) . '/', strlen($targetDir) + 1); } } $callback = function ($matches) use($host, $path) { if (false !== strpos($matches['url'], '://')) { // absolute return $matches[0]; } if ('/' == $matches['url'][0]) { // root relative return str_replace($matches['url'], $host . $matches['url'], $matches[0]); } // document relative $url = $matches['url']; while (0 === strpos($url, '../') && 2 <= substr_count($path, '/')) { $path = substr($path, 0, strrpos(rtrim($path, '/'), '/') + 1); $url = substr($url, 3); } return str_replace($matches['url'], $host . $path . $url, $matches[0]); }; $content = $asset->getContent(); $content = preg_replace_callback('/url\\((["\']?)(?<url>.*)(\\1)\\)/', $callback, $content); $content = preg_replace_callback('/import (["\'])(?<url>.*)(\\1)/', $callback, $content); $asset->setContent($content); }
public function filterLoad(AssetInterface $asset) { $sourceUrl = $asset->getSourceUrl(); if ($sourceUrl && false === strpos($sourceUrl, '://')) { $baseDir = self::isAbsolutePath($sourceUrl) ? '' : $this->baseDir . '/'; $sourceUrl = $baseDir . $sourceUrl; } $lc = new \lessc($sourceUrl); // the way lessc::parse is implemented, the content wins if both url and content are defined $asset->setContent($lc->parse($asset->getContent())); }
public function filterLoad(AssetInterface $asset) { static $format = <<<'EOF' var less = require('less'); var sys = require('sys'); new(less.Parser)(%s).parse(%s, function(e, tree) { if (e) { less.writeError(e); process.exit(2); } try { sys.print(tree.toCSS(%s)); process.exit(0); } catch (e) { less.writeError(e); process.exit(3); } }); EOF; $sourceUrl = $asset->getSourceUrl(); // parser options $parserOptions = array(); if ($sourceUrl && false === strpos($sourceUrl, '://')) { $baseDir = self::isAbsolutePath($sourceUrl) ? '' : $this->baseDir . '/'; $parserOptions['paths'] = array($baseDir . dirname($sourceUrl)); $parserOptions['filename'] = basename($sourceUrl); } // tree options $treeOptions = array(); if (null !== $this->compress) { $treeOptions['compress'] = $this->compress; } // node.js configuration $env = array(); if (0 < count($this->nodePaths)) { $env['NODE_PATH'] = implode(':', $this->nodePaths); } $options = array($this->nodeBin); $options[] = $input = tempnam(sys_get_temp_dir(), 'assetic_less'); file_put_contents($input, sprintf($format, json_encode($parserOptions), json_encode($asset->getContent()), json_encode($treeOptions))); $proc = new Process(implode(' ', array_map('escapeshellarg', $options)), null, $env); $code = $proc->run(); unlink($input); if (0 < $code) { throw new \RuntimeException($proc->getErrorOutput()); } $asset->setContent($proc->getOutput()); }
/** * {@inheritdoc} */ public function filterLoad(AssetInterface $asset) { static $format = <<<JAVASCRIPT var stylus = require('stylus'), sys = require('sys'); stylus(%s, %s).render(function(e, css){ if (e) { throw e; } sys.print(css); process.exit(0); }); JAVASCRIPT; // parser options $parserOptions = array(); if ($sourceUrl = $asset->getSourceUrl()) { $parserOptions['filename'] = basename($sourceUrl); $parserOptions['paths'] = array($this->baseDir . DIRECTORY_SEPARATOR . dirname($sourceUrl)); } if (null !== $this->compress) { $parserOptions['compress'] = $this->compress; } // node.js configuration $env = array(); if (0 < count($this->nodePaths)) { $env['NODE_PATH'] = implode(':', $this->nodePaths); } $options = array($this->nodeBin); $options[] = $input = tempnam(sys_get_temp_dir(), 'assetic_stylus'); file_put_contents($input, sprintf($format, json_encode($asset->getContent()), json_encode($parserOptions) )); $proc = new Process(implode(' ', array_map('escapeshellarg', $options)), null, $env); $code = $proc->run(); unlink($input); if (0 < $code) { throw new \RuntimeException($proc->getErrorOutput()); } $asset->setContent($proc->getOutput()); }
public function filterDump(AssetInterface $asset) { $filters = $this->filters; $plugins = $this->plugins; if (isset($filters['ImportImports']) && true === $filters['ImportImports']) { // find the base path $sourceUrl = $asset->getSourceUrl(); if (self::isAbsoluteUrl($sourceUrl) || self::isAbsolutePath($sourceUrl)) { $filters['ImportImports'] = array('BasePath' => dirname($sourceUrl)); } elseif ($this->baseDir) { $filters['ImportImports'] = array('BasePath' => $this->baseDir); if ('.' != ($dir = dirname($sourceUrl))) { $filters['ImportImports']['BasePath'] .= '/' . $dir; } } } $asset->setContent(\CssMin::minify($asset->getContent(), $filters, $plugins)); }
public function filterDump(AssetInterface $asset) { $sourceUrl = $asset->getSourceUrl(); $targetUrl = $asset->getTargetUrl(); if (null === $sourceUrl || null === $targetUrl || $sourceUrl == $targetUrl) { return; } // learn how to get from the target back to the source if (false !== strpos($sourceUrl, '://')) { // the source is absolute, this should be easy $parts = parse_url($sourceUrl); $host = $parts['scheme'].'://'.$parts['host']; $path = dirname($parts['path']).'/'; } else { // assume source and target are on the same host $host = ''; // pop entries off the target until it fits in the source $path = ''; $targetDir = dirname($targetUrl); while (0 !== strpos($sourceUrl, $targetDir)) { if (false !== $pos = strrpos($targetDir, '/')) { $targetDir = substr($targetDir, 0, $pos); $path .= '../'; } else { throw new \RuntimeException(sprintf('Unable to calculate relative path from "%s" to "%s"', $targetUrl, $sourceUrl)); } } $path .= substr(dirname($sourceUrl).'/', strlen($targetDir) + 1); } $filter = function($url) use($host, $path) { if (false !== strpos($url, '://')) { // absolute return $url; } elseif ('/' == $url[0]) { // root relative return $host.$url; } else { // document relative while (0 === strpos($url, '../') && 2 <= substr_count($path, '/')) { $path = substr($path, 0, strrpos(rtrim($path, '/'), '/') + 1); $url = substr($url, 3); } return $host.$path.$url; } }; // tokenize and filter the asset content $tokens = $this->tokenizer->tokenizeString($asset->getContent()); // cleanup the php tags codesniffer adds $tokens = array_slice($tokens, 1, -1); $token = array_pop($tokens); if (' ' != $token['content']) { $token['content'] = substr($token['content'], 0, -1); $tokens[] = $token; } $content = ''; $inUrl = $inImport = 0; for ($i = 0; $i < count($tokens); $i++) { $token = $tokens[$i]; if (T_URL == $token['code']) { $token['content'] = $filter($token['content']); } elseif (T_STRING == $token['code'] && 'url' == $token['content']) { $inUrl = 1; } elseif (T_STRING == $token['code'] && 'import' == $token['content'] && isset($tokens[$i - 1]) && T_ASPERAND == $tokens[$i - 1]['code']) { $inImport = 1; } elseif (T_OPEN_PARENTHESIS == $token['code'] && 1 == $inUrl) { $inUrl = 2; } elseif (T_CONSTANT_ENCAPSED_STRING == $token['code'] && (2 == $inUrl || 1 == $inImport)) { $quote = $token['content'][0]; $url = $filter(substr($token['content'], 1, -1)); $token['content'] = $quote.$url.$quote; } elseif (T_WHITESPACE != $token['code']) { $inUrl = $inImport = 0; } $content .= $token['content']; } $asset->setContent($content); }
/** * Hack around a bit, get the job done. */ public function filterLoad(AssetInterface $asset) { static $format = <<<'EOF' #!/usr/bin/env ruby require File.join(%s, 'sprockets') module Sprockets class Secretary def reset!(options = @options) @options = DEFAULT_OPTIONS.merge(options) @environment = Sprockets::Environment.new(@options[:root]) @preprocessor = Sprockets::Preprocessor.new(@environment, :strip_comments => @options[:strip_comments]) add_load_locations(@options[:load_path]) add_source_files(@options[:source_files]) end end class Preprocessor protected def pathname_for_relative_require_from(source_line) Sprockets::Pathname.new(@environment, File.join(%s, location_from(source_line))) end end end options = { :load_path => [], :source_files => [%s], :expand_paths => false } %ssecretary = Sprockets::Secretary.new(options) secretary.install_assets if options[:asset_root] print secretary.concatenation EOF; $sourceUrl = $asset->getSourceUrl(); if (!$sourceUrl || false !== strpos($sourceUrl, '://')) { return; } $more = ''; foreach ($this->includeDirs as $directory) { $more .= 'options[:load_path] << ' . var_export($directory, true) . "\n"; } if (null !== $this->assetRoot) { $more .= 'options[:asset_root] = ' . var_export($this->assetRoot, true) . "\n"; } if ($more) { $more .= "\n"; } $tmpAsset = tempnam(sys_get_temp_dir(), 'assetic_sprockets'); file_put_contents($tmpAsset, $asset->getContent()); $input = tempnam(sys_get_temp_dir(), 'assetic_sprockets'); file_put_contents($input, sprintf($format, var_export($this->sprocketsLib, true), var_export($this->baseDir, true), var_export($tmpAsset, true), $more)); $proc = new Process($cmd = implode(' ', array_map('escapeshellarg', array($this->rubyBin, $input)))); $code = $proc->run(); unlink($tmpAsset); unlink($input); if (0 < $code) { throw new \RuntimeException($proc->getErrorOutput()); } $asset->setContent($proc->getOutput()); }