/**
  * Apply a filter on file dump.
  *
  * @param  \Assetic\Asset\AssetInterface  $asset
  * @return void
  */
 public function filterDump(AssetInterface $asset)
 {
     // Using getSourceDirectory
     // instead of getSourceRoot
     // Since relative paths are based on the sourceDirectory...
     $this->assetDirectory = $this->realPath($asset->getSourceDirectory());
     $content = $asset->getContent();
     // Spin through the symlinks and normalize them. We'll first unset the original
     // symlink so that it doesn't clash with the new symlinks once they are added
     // back in.
     foreach ($this->symlinks as $link => $target) {
         unset($this->symlinks[$link]);
         if ($link == '//') {
             $link = $this->documentRoot;
         } else {
             $link = str_replace('//', $this->documentRoot . '/', $link);
         }
         $link = strtr($link, '/', DIRECTORY_SEPARATOR);
         $this->symlinks[$link] = $this->realPath($target);
     }
     $content = $this->trimUrls($content);
     $content = preg_replace_callback('/@import\\s+([\'"])(.*?)[\'"]/', array($this, 'processUriCallback'), $content);
     $content = preg_replace_callback('/url\\(\\s*([^\\)\\s]+)\\s*\\)/', array($this, 'processUriCallback'), $content);
     $asset->setContent($content);
 }
 public function filterLoad(AssetInterface $asset)
 {
     $sassProcessArgs = array();
     if (null !== $this->nodePath) {
         $sassProcessArgs[] = $this->nodePath;
     }
     $sassProcessArgs[] = $this->sassPath;
     $pb = $this->createProcessBuilder($sassProcessArgs);
     if ($dir = $asset->getSourceDirectory()) {
         $pb->add('--include-path')->add($dir);
     }
     if ($this->style) {
         $pb->add('--output-style')->add($this->style);
     }
     if ($this->sourceMap) {
         $pb->add('--source-map');
     }
     if ($this->debugInfo) {
         $pb->add('--source-comments');
     }
     foreach ($this->loadPaths as $loadPath) {
         $pb->add('--include-path')->add($loadPath);
     }
     // input
     $pb->add($input = tempnam(sys_get_temp_dir(), 'assetic_sass'));
     file_put_contents($input, $asset->getContent());
     $pb->add('--stdout');
     $proc = $pb->getProcess();
     $code = $proc->run();
     unlink($input);
     if (0 !== $code) {
         throw FilterException::fromProcess($proc)->setInput($asset->getContent());
     }
     $asset->setContent($proc->getOutput());
 }
Exemplo n.º 3
0
 /**
  * {@inheritdoc}
  */
 public function getSourceDirectory()
 {
     if (!$this->innerAsset) {
         $this->createInnerAsset();
     }
     return $this->innerAsset->getSourceDirectory();
 }
 public function filterLoad(AssetInterface $asset)
 {
     $pce = new CssEmbed();
     if ($dir = $asset->getSourceDirectory()) {
         $pce->setRootDir($dir);
     }
     $asset->setContent($pce->embedString($asset->getContent()));
 }
Exemplo n.º 5
0
 /**
  * Filters an asset just before it's dumped.
  *
  * @param AssetInterface $asset
  */
 public function filterDump(AssetInterface $asset)
 {
     $this->dispatch(new LoadThemeVariables($variables = new Collection()));
     $compiler = new Compiler();
     if ($dir = $asset->getSourceDirectory()) {
         $compiler->addImportPath($dir);
     }
     $compiler->setVariables($variables->all());
     $asset->setContent($this->parser->parse($compiler->compile($asset->getContent())));
 }
Exemplo n.º 6
0
 public function filterLoad(AssetInterface $asset)
 {
     $sass = new \Sass();
     $includePaths = array_merge(array($asset->getSourceDirectory()), $this->includePaths);
     $sass->setIncludePath(implode(':', $includePaths));
     if ($this->outputStyle) {
         $sass->setStyle($this->outputStyle);
     }
     $css = $sass->compile($asset->getContent());
     $asset->setContent($css);
 }
Exemplo n.º 7
0
 public function filterDump(AssetInterface $asset)
 {
     $filters = $this->filters;
     $plugins = $this->plugins;
     if (isset($filters['ImportImports']) && true === $filters['ImportImports']) {
         if ($dir = $asset->getSourceDirectory()) {
             $filters['ImportImports'] = array('BasePath' => $dir);
         } else {
             unset($filters['ImportImports']);
         }
     }
     $asset->setContent(\CssMin::minify($asset->getContent(), $filters, $plugins));
 }
Exemplo n.º 8
0
 /**
  * Filters an asset just before it's dumped.
  *
  * @param AssetInterface $asset
  */
 public function filterDump(AssetInterface $asset)
 {
     $compiler = new \lessc();
     $this->dispatch(new LoadThemeVariables($variables = new Collection()));
     $compiler->setVariables($variables->all());
     if ($dir = $asset->getSourceDirectory()) {
         $compiler->importDir = $dir;
     }
     foreach ($this->loadPaths as $loadPath) {
         $compiler->addImportDir($loadPath);
     }
     $asset->setContent($compiler->parse($this->parser->parse($asset->getContent())));
 }
Exemplo n.º 9
0
 public function filterLoad(AssetInterface $asset)
 {
     $lc = new \scssc();
     if ($this->compass) {
         new \scss_compass($lc);
     }
     if ($dir = $asset->getSourceDirectory()) {
         $lc->addImportPath($dir);
     }
     foreach ($this->importPaths as $path) {
         $lc->addImportPath($path);
     }
     $asset->setContent($lc->compile($asset->getContent()));
 }
Exemplo n.º 10
0
 public function filterLoad(AssetInterface $asset)
 {
     $source = $asset->getSourceDirectory() . path('ds') . $asset->getSourcePath();
     $sourceHash = sha1($source . filemtime($source));
     $input = path('tmp') . $sourceHash . '.less.tmp';
     if (!is_file($input)) {
         $content = $asset->getContent();
         /**
          * Fix ../ and similar urls.
          */
         $sourceDir = $asset->getSourceDirectory();
         $rootDir = path('root');
         /**
          * Source dir is always longer than root dir.
          * Dir diff will be prepended to urls.
          */
         $dirDiff = str_replace($rootDir, path('ds'), $sourceDir);
         /**
          * Make replacement.
          */
         $content = preg_replace_callback('/url\\(([\\s])?([\\"|\'])?(.*?)([\\"|\'])?([\\s])?\\)/i', function ($matches) use($sourceDir, $rootDir, $dirDiff) {
             $value = $matches[0];
             /**
              * We have to move $dots times towards root.
              */
             if ($dots = substr_count($value, '../')) {
                 /**
                  * We have to move $dots times towards root.
                  */
                 $resourcePath = realpath($sourceDir . path('ds') . str_repeat('..' . path('ds'), $dots));
                 $relativeDir = str_replace($rootDir, path('ds'), $resourcePath) . path('ds');
                 $urlPart = strpos($value, 'url("') !== false ? 'url("' : (strpos($value, 'url(\'') !== false ? 'url(\'' : 'url(');
                 $value = str_replace($urlPart, $urlPart . $relativeDir, str_replace('../', '', $value));
             }
             /**
              * We have to simply prepend path.
              */
             if (strpos($value, 'url("') !== false && strpos($value, 'url("/)') === false || strpos($value, 'url(\'') !== false && strpos($value, 'url(\'/') === false) {
                 $value = str_replace(['url("', 'url(\''], ['url("' . $dirDiff . '/', 'url(\'' . $dirDiff . '/'], $value);
             }
             return $value;
         }, $content);
     } else {
         $content = file_get_contents($input);
     }
     $asset->setContent($content);
 }
Exemplo n.º 11
0
 public function filterLoad(AssetInterface $asset)
 {
     $sc = new \scssc();
     if ($this->compass) {
         new \scss_compass($sc);
     }
     if ($dir = $asset->getSourceDirectory()) {
         $sc->addImportPath($dir);
     }
     foreach ($this->importPaths as $path) {
         $sc->addImportPath($path);
     }
     foreach ($this->customFunctions as $name => $callable) {
         $sc->registerFunction($name, $callable);
     }
     $asset->setContent($sc->compile($asset->getContent()));
 }
Exemplo n.º 12
0
 public function filterLoad(AssetInterface $asset)
 {
     $lc = new \lessc();
     if ($dir = $asset->getSourceDirectory()) {
         $lc->importDir = $dir;
     }
     foreach ($this->loadPaths as $loadPath) {
         $lc->addImportDir($loadPath);
     }
     if ($this->formatter) {
         $lc->setFormatter($this->formatter);
     }
     if (null !== $this->preserveComments) {
         $lc->setPreserveComments($this->preserveComments);
     }
     $asset->setContent($lc->parse($asset->getContent(), $this->presets));
 }
Exemplo n.º 13
0
 public function filterLoad(AssetInterface $asset)
 {
     $filePath = $asset->getSourceRoot() . DS . $asset->getSourcePath();
     Tlog::getInstance()->addDebug("Starting CSS processing: {$filePath}...");
     $importDirs = [];
     if ($dir = $asset->getSourceDirectory()) {
         $importDirs[$dir] = '';
     }
     foreach ($this->loadPaths as $loadPath) {
         $importDirs[$loadPath] = '';
     }
     $options = ['cache_dir' => $this->cacheDir, 'relativeUrls' => false, 'compress' => true, 'import_dirs' => $importDirs];
     $css_file_name = \Less_Cache::Get([$filePath => ''], $options);
     $content = @file_get_contents($this->cacheDir . DS . $css_file_name);
     if ($content === false) {
         $content = '';
         Tlog::getInstance()->warning("Compilation of {$filePath} did not generate an output file.");
     }
     $asset->setContent($content);
     Tlog::getInstance()->addDebug("CSS processing done.");
 }
Exemplo n.º 14
0
 public function filterLoad(AssetInterface $asset)
 {
     $lc = new \lessc();
     if ($dir = $asset->getSourceDirectory()) {
         $lc->importDir = $dir;
     }
     foreach ($this->loadPaths as $loadPath) {
         $lc->addImportDir($loadPath);
     }
     foreach ($this->customFunctions as $name => $callable) {
         $lc->registerFunction($name, $callable);
     }
     if ($this->formatter) {
         $lc->setFormatter($this->formatter);
     }
     if (null !== $this->preserveComments) {
         $lc->setPreserveComments($this->preserveComments);
     }
     if (method_exists($lc, 'setOptions') && count($this->options) > 0) {
         $lc->setOptions($this->options);
     }
     $asset->setContent($lc->parse($asset->getContent(), $this->presets));
 }
    /**
     * {@inheritdoc}
     */
    public function filterLoad(AssetInterface $asset)
    {
        static $format = <<<'EOF'
var stylus = require('stylus');
var sys    = require(process.binding('natives').util ? 'util' : 'sys');

stylus(%s, %s)%s.render(function(e, css){
    if (e) {
        throw e;
    }

    sys.print(css);
    process.exit(0);
});

EOF;
        // parser options
        $parserOptions = array();
        if ($dir = $asset->getSourceDirectory()) {
            $parserOptions['paths'] = array($dir);
            $parserOptions['filename'] = basename($asset->getSourcePath());
        }
        if (null !== $this->compress) {
            $parserOptions['compress'] = $this->compress;
        }
        $pb = $this->createProcessBuilder();
        $pb->add($this->nodeBin)->add($input = FilesystemUtils::createTemporaryFile('stylus'));
        file_put_contents($input, sprintf($format, json_encode($asset->getContent()), json_encode($parserOptions), $this->useNib ? '.use(require(\'nib\')())' : ''));
        $proc = $pb->getProcess();
        $code = $proc->run();
        unlink($input);
        if (0 !== $code) {
            throw FilterException::fromProcess($proc)->setInput($asset->getContent());
        }
        $asset->setContent($proc->getOutput());
    }
Exemplo n.º 16
0
    private function getHack(AssetInterface $asset)
    {
        static $format = <<<'EOF'

module Sprockets
  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

EOF;
        if ($dir = $asset->getSourceDirectory()) {
            return sprintf($format, var_export($dir, true));
        }
    }
Exemplo n.º 17
0
 /**
  * Returns the asset's source directory.
  *
  * @return string|null The asset's source directory
  */
 public function getSourceDirectory()
 {
     return $this->asset->getSourceDirectory();
 }
Exemplo n.º 18
0
 public function filterLoad(AssetInterface $asset)
 {
     $loadPaths = $this->loadPaths;
     if ($dir = $asset->getSourceDirectory()) {
         $loadPaths[] = $dir;
     }
     // compass does not seems to handle symlink, so we use realpath()
     $tempDir = realpath(sys_get_temp_dir());
     $compassProcessArgs = array($this->compassPath, 'compile', $tempDir);
     if (null !== $this->rubyPath) {
         $compassProcessArgs = array_merge(explode(' ', $this->rubyPath), $compassProcessArgs);
     }
     $pb = $this->createProcessBuilder($compassProcessArgs);
     if ($this->force) {
         $pb->add('--force');
     }
     if ($this->style) {
         $pb->add('--output-style')->add($this->style);
     }
     if ($this->quiet) {
         $pb->add('--quiet');
     }
     if ($this->boring) {
         $pb->add('--boring');
     }
     if ($this->noLineComments) {
         $pb->add('--no-line-comments');
     }
     // these two options are not passed into the config file
     // because like this, compass adapts this to be xxx_dir or xxx_path
     // whether it's an absolute path or not
     if ($this->imagesDir) {
         $pb->add('--images-dir')->add($this->imagesDir);
     }
     if ($this->javascriptsDir) {
         $pb->add('--javascripts-dir')->add($this->javascriptsDir);
     }
     // options in config file
     $optionsConfig = array();
     if (!empty($loadPaths)) {
         $optionsConfig['additional_import_paths'] = $loadPaths;
     }
     if ($this->unixNewlines) {
         $optionsConfig['sass_options']['unix_newlines'] = true;
     }
     if ($this->debugInfo) {
         $optionsConfig['sass_options']['debug_info'] = true;
     }
     if ($this->cacheLocation) {
         $optionsConfig['sass_options']['cache_location'] = $this->cacheLocation;
     }
     if ($this->noCache) {
         $optionsConfig['sass_options']['no_cache'] = true;
     }
     if ($this->httpPath) {
         $optionsConfig['http_path'] = $this->httpPath;
     }
     if ($this->httpImagesPath) {
         $optionsConfig['http_images_path'] = $this->httpImagesPath;
     }
     if ($this->httpFontsPath) {
         $optionsConfig['http_fonts_path'] = $this->httpFontsPath;
     }
     if ($this->httpGeneratedImagesPath) {
         $optionsConfig['http_generated_images_path'] = $this->httpGeneratedImagesPath;
     }
     if ($this->generatedImagesPath) {
         $optionsConfig['generated_images_path'] = $this->generatedImagesPath;
     }
     if ($this->httpJavascriptsPath) {
         $optionsConfig['http_javascripts_path'] = $this->httpJavascriptsPath;
     }
     if ($this->fontsDir) {
         $optionsConfig['fonts_dir'] = $this->fontsDir;
     }
     // options in configuration file
     if (count($optionsConfig)) {
         $config = array();
         foreach ($this->plugins as $plugin) {
             $config[] = sprintf("require '%s'", addcslashes($plugin, '\\'));
         }
         foreach ($optionsConfig as $name => $value) {
             if (!is_array($value)) {
                 $config[] = sprintf('%s = "%s"', $name, addcslashes($value, '\\'));
             } elseif (!empty($value)) {
                 $config[] = sprintf('%s = %s', $name, $this->formatArrayToRuby($value));
             }
         }
         $configFile = tempnam($tempDir, 'assetic_compass');
         file_put_contents($configFile, implode("\n", $config) . "\n");
         $pb->add('--config')->add($configFile);
     }
     $pb->add('--sass-dir')->add('')->add('--css-dir')->add('');
     // compass choose the type (sass or scss from the filename)
     if (null !== $this->scss) {
         $type = $this->scss ? 'scss' : 'sass';
     } elseif ($path = $asset->getSourcePath()) {
         // FIXME: what if the extension is something else?
         $type = pathinfo($path, PATHINFO_EXTENSION);
     } else {
         $type = 'scss';
     }
     $tempName = tempnam($tempDir, 'assetic_compass');
     unlink($tempName);
     // FIXME: don't use tempnam() here
     // input
     $input = $tempName . '.' . $type;
     // work-around for https://github.com/chriseppstein/compass/issues/748
     if (defined('PHP_WINDOWS_VERSION_MAJOR')) {
         $input = str_replace('\\', '/', $input);
     }
     $pb->add($input);
     file_put_contents($input, $asset->getContent());
     // output
     $output = $tempName . '.css';
     if ($this->homeEnv) {
         // it's not really usefull but... https://github.com/chriseppstein/compass/issues/376
         $pb->setEnv('HOME', sys_get_temp_dir());
         $this->mergeEnv($pb);
     }
     $proc = $pb->getProcess();
     $code = $proc->run();
     if (0 !== $code) {
         unlink($input);
         if (isset($configFile)) {
             unlink($configFile);
         }
         throw FilterException::fromProcess($proc)->setInput($asset->getContent());
     }
     $asset->setContent(file_get_contents($output));
     unlink($input);
     unlink($output);
     if (isset($configFile)) {
         unlink($configFile);
     }
 }
Exemplo n.º 19
0
 public function filterLoad(AssetInterface $asset)
 {
     $source = $asset->getSourceDirectory() . path('ds') . $asset->getSourcePath();
     $variablesPath = $this->getVarsPath();
     $sourceHash = sha1($source . filemtime($source) . $variablesPath);
     $output = path('tmp') . $sourceHash . '.less.tmp';
     $input = path('tmp') . $sourceHash . '.merged.less.tmp';
     if (!is_file($output)) {
         file_put_contents($input, file_get_contents($source) . ($variablesPath ? file_get_contents($variablesPath) : ''));
         $proc = new Process('lessc ' . $input . ' > ' . $output);
         $code = $proc->run();
         if (0 !== $code) {
             throw FilterException::fromProcess($proc)->setInput($asset->getContent());
         }
     }
     $content = file_get_contents($output);
     $asset->setContent($content);
 }
Exemplo n.º 20
0
 public function filterLoad(AssetInterface $asset)
 {
     $sassProcessArgs = array($this->sassPath);
     if (null !== $this->rubyPath) {
         $sassProcessArgs = array_merge(explode(' ', $this->rubyPath), $sassProcessArgs);
     }
     $pb = $this->createProcessBuilder($sassProcessArgs);
     if ($dir = $asset->getSourceDirectory()) {
         $pb->add('--load-path')->add($dir);
     }
     if ($this->unixNewlines) {
         $pb->add('--unix-newlines');
     }
     if (true === $this->scss || null === $this->scss && 'scss' == pathinfo($asset->getSourcePath(), PATHINFO_EXTENSION)) {
         $pb->add('--scss');
     }
     if ($this->style) {
         $pb->add('--style')->add($this->style);
     }
     if ($this->quiet) {
         $pb->add('--quiet');
     }
     if ($this->debugInfo) {
         $pb->add('--debug-info');
     }
     if ($this->lineNumbers) {
         $pb->add('--line-numbers');
     }
     foreach ($this->loadPaths as $loadPath) {
         $pb->add('--load-path')->add($loadPath);
     }
     if ($this->cacheLocation) {
         $pb->add('--cache-location')->add($this->cacheLocation);
     }
     if ($this->noCache) {
         $pb->add('--no-cache');
     }
     if ($this->compass) {
         $pb->add('--compass');
     }
     // input
     $pb->add($input = tempnam(sys_get_temp_dir(), 'assetic_sass'));
     file_put_contents($input, $asset->getContent());
     $proc = $pb->getProcess();
     $code = $proc->run();
     unlink($input);
     if (0 !== $code) {
         throw FilterException::fromProcess($proc)->setInput($asset->getContent());
     }
     $asset->setContent($proc->getOutput());
 }
Exemplo n.º 21
0
    public function filterLoad(AssetInterface $asset)
    {
        static $format = <<<'EOF'
var less = require('less');
var sys  = require(process.binding('natives').util ? 'util' : 'sys');

less.render(%s, %s, function(error, css) {
    if (error) {
        less.writeError(error);
        process.exit(2);
    }
    try {
        if (typeof css == 'string') {
            sys.print(css);
        } else {
            sys.print(css.css);
        }
    } catch (e) {
        less.writeError(error);
        process.exit(3);
    }
});

EOF;
        // parser options
        $parserOptions = $this->parserOptions;
        if ($dir = $asset->getSourceDirectory()) {
            $parserOptions['paths'] = array($dir);
            $parserOptions['filename'] = basename($asset->getSourcePath());
        }
        foreach ($this->loadPaths as $loadPath) {
            $parserOptions['paths'][] = $loadPath;
        }
        $pb = $this->createProcessBuilder();
        $pb->add($this->nodeBin)->add($input = FilesystemUtils::createTemporaryFile('less'));
        file_put_contents($input, sprintf($format, json_encode($asset->getContent()), json_encode(array_merge($parserOptions, $this->treeOptions))));
        $proc = $pb->getProcess();
        $code = $proc->run();
        unlink($input);
        if (0 !== $code) {
            throw FilterException::fromProcess($proc)->setInput($asset->getContent());
        }
        $asset->setContent($proc->getOutput());
    }
Exemplo n.º 22
0
 public function filterDump(AssetInterface $asset)
 {
     $pb = $this->createProcessBuilder(array($this->javaPath, '-jar', $this->jarPath));
     if (null !== $this->charset) {
         $pb->add('--charset')->add($this->charset);
     }
     if ($this->mhtml) {
         $pb->add('--mhtml');
     }
     if (null !== $this->mhtmlRoot) {
         $pb->add('--mhtmlroot')->add($this->mhtmlRoot);
     }
     // automatically define root if not already defined
     if (null === $this->root) {
         if ($dir = $asset->getSourceDirectory()) {
             $pb->add('--root')->add($dir);
         }
     } else {
         $pb->add('--root')->add($this->root);
     }
     if ($this->skipMissing) {
         $pb->add('--skip-missing');
     }
     if (null !== $this->maxUriLength) {
         $pb->add('--max-uri-length')->add($this->maxUriLength);
     }
     if (null !== $this->maxImageSize) {
         $pb->add('--max-image-size')->add($this->maxImageSize);
     }
     // input
     $pb->add($input = tempnam(sys_get_temp_dir(), 'assetic_cssembed'));
     file_put_contents($input, $asset->getContent());
     $proc = $pb->getProcess();
     $code = $proc->run();
     unlink($input);
     if (0 !== $code) {
         throw FilterException::fromProcess($proc)->setInput($asset->getContent());
     }
     $asset->setContent($proc->getOutput());
 }
Exemplo n.º 23
0
    public function filterLoad(AssetInterface $asset)
    {
        static $format = <<<'EOF'
var less = require('less');
var sys  = require(process.binding('natives').util ? 'util' : 'sys');

new(less.Parser)(%s).parse(%s, function(e, tree) {
    if (e) {
        less.writeError(e);
        process.exit(2);
    }

    try {
        sys.print(tree.toCSS(%s));
    } catch (e) {
        less.writeError(e);
        process.exit(3);
    }
});

EOF;
        // parser options
        $parserOptions = $this->parserOptions;
        if ($dir = $asset->getSourceDirectory()) {
            $parserOptions['paths'] = array($dir);
            $parserOptions['filename'] = basename($asset->getSourcePath());
        }
        foreach ($this->loadPaths as $loadPath) {
            $parserOptions['paths'][] = $loadPath;
        }
        $pb = $this->createProcessBuilder();
        $pb->add($this->nodeBin)->add($input = tempnam(sys_get_temp_dir(), 'assetic_less'));
        file_put_contents($input, sprintf($format, json_encode($parserOptions), json_encode($asset->getContent()), json_encode($this->treeOptions)));
        $proc = $pb->getProcess();
        $code = $proc->run();
        unlink($input);
        if (0 !== $code) {
            throw FilterException::fromProcess($proc)->setInput($asset->getContent());
        }
        $asset->setContent($proc->getOutput());
    }
Exemplo n.º 24
0
 public function filterDump(AssetInterface $asset)
 {
     $sourceBase = $asset->getSourceRoot();
     $sourcePath = $asset->getSourcePath();
     $targetPath = $asset->getTargetPath();
     $sourceDir = $asset->getSourceDirectory();
     if (null === $sourcePath || null === $targetPath || $sourcePath == $targetPath) {
         return;
     }
     // learn how to get from the target back to the source
     if (false !== strpos($sourceBase, '://')) {
         list($scheme, $url) = explode('://', $sourceBase . '/' . $sourcePath, 2);
         list($host, $path) = explode('/', $url, 2);
         $host = $scheme . '://' . $host . '/';
         $path = false === strpos($path, '/') ? '' : dirname($path);
         $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($sourcePath)) {
             $path = str_repeat('../', substr_count($targetPath, '/'));
         } elseif ('.' == ($targetDir = dirname($targetPath))) {
             $path = dirname($sourcePath) . '/';
         } else {
             $path = '';
             while (0 !== strpos($sourcePath, $targetDir)) {
                 if (false !== ($pos = strrpos($targetDir, '/'))) {
                     $targetDir = substr($targetDir, 0, $pos);
                     $path .= '../';
                 } else {
                     $targetDir = '';
                     $path .= '../';
                     break;
                 }
             }
             $path .= ltrim(substr(dirname($sourcePath) . '/', strlen($targetDir)), '/');
         }
     }
     $content = $this->filterReferences($asset->getContent(), function ($matches) use($sourceDir, $host) {
         $path = $sourceDir;
         if (false !== strpos($matches['url'], '://') || 0 === strpos($matches['url'], '//') || 0 === strpos($matches['url'], 'data:')) {
             // absolute or protocol-relative or data uri
             return $matches[0];
         }
         if (isset($matches['url'][0]) && '/' == $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);
         }
         $originalAsset = $path . $url;
         $originalAsset = reset(preg_split("/[#?]/", $originalAsset));
         $rootDir = $this->kernel->getRootDir();
         $rootDir = substr($rootDir, 0, -3);
         $relativeAsset = substr($originalAsset, strlen($rootDir));
         $assetName = $this->assetFactory->generateAssetName($relativeAsset);
         $targetAssetPath = $rootDir . 'web/' . $url;
         $targetParts = explode('/', $targetAssetPath);
         $fileName = $assetName . '_' . array_pop($targetParts);
         array_push($targetParts, $fileName);
         $targetAssetPath = implode('/', $targetParts);
         $targetAssetPath = reset(preg_split("/[#?]/", $targetAssetPath));
         $urlParts = explode('/', $matches['url']);
         array_pop($urlParts);
         array_push($urlParts, $fileName);
         $urlNew = implode('/', $urlParts);
         if (!is_dir($dir = dirname($targetAssetPath))) {
             if (false === @mkdir($dir, 0777, true)) {
                 throw new \RuntimeException('Unable to create directory ' . $dir);
             }
         }
         $asset = new FileAsset($originalAsset);
         try {
             $contents = $asset->dump();
         } catch (\Exception $e) {
             echo 'WARNING: ' . $e->getMessage();
         }
         if (false === @file_put_contents($targetAssetPath, $contents)) {
             throw new \RuntimeException('Unable to write file ' . $targetAssetPath);
         }
         $result = str_replace($matches['url'], $urlNew, $matches[0]);
         return $result;
     });
     $asset->setContent($content);
 }