Created
August 19, 2014 20:34
-
-
Save timwhitlock/95b0a3c326cebba68127 to your computer and use it in GitHub Desktop.
Exposes source maps to dynamic Assetic routes in debug mode
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace my\TestBundle\Assetic; | |
use Assetic\Factory\LazyAssetManager; | |
/** | |
* Overridden asset manager that exposes source maps referenced in CSS and JS | |
*/ | |
class AssetManager extends LazyAssetManager { | |
public function load(){ | |
parent::load(); | |
// skipping for production asset dump | |
// would be preferable to grab assetic.user_controller, but no container access. | |
if( ! $this->isDebug() ){ | |
return; | |
} | |
// add additional assets linked to those already found | |
$deps = array(); | |
// find each leaf asset that may have a sourcemapping url | |
foreach( $this->getNames() as $name ) { | |
$assets = $this->get($name); | |
$formula = $this->getFormula($name); | |
foreach( $assets as $pos => $asset ){ | |
$ext = pathinfo($asset->getSourcePath(),PATHINFO_EXTENSION); | |
if( 'js' !== $ext && 'css' !== $ext ){ | |
continue 2; | |
} | |
// have full path to original JS or CSS file | |
$path = $asset->getSourceRoot().'/'.$asset->getSourcePath(); | |
$text = file_get_contents( $path ); | |
if( ! preg_match('/#\s*sourceMappingURL\s*=\s*([^\s\*]+)/', $text, $r ) ){ | |
continue; | |
} | |
// sourcemap url is relative to source file location | |
$fdir = dirname($path); | |
$vdir = dirname($formula[2]['output']); | |
$deps[ static::mapPath( $vdir, $r[1] ) ] = $fpath = $fdir.'/'.$r[1]; | |
// handle sources that map depends upon | |
$json = file_get_contents( $fpath ); | |
$data = json_decode( $json, true ); | |
foreach( $data['sources'] as $sourcepath ){ | |
// source assumed to be relative to map location, but tollerate if not found | |
if( file_exists( $fpath = $fdir.'/'.$sourcepath ) ){ | |
$deps[ static::mapPath( $vdir, $sourcepath ) ] = $fpath; | |
} | |
} | |
} | |
} | |
// Add additional assets to lazy asset manager, will result in dynamic routes creating | |
foreach( $deps as $vpath => $fpath ){ | |
$key = md5( $vpath ); | |
$this->setFormula( $key, array ( | |
array( $fpath ), // <- single map file asset | |
array(), // <- no filters | |
array ( | |
'output' => $vpath, // <- controller pattern placeholder | |
'combine' => true, // <- prevents multiple routes for single asset | |
), | |
) ); | |
} | |
} | |
/** | |
* utility maps a relative path to an absolute one, based on a base path | |
* @param string base path e.g. "/some/location" | |
* @param string relatve path, e.g. "../thing" | |
* @return string absolute path, e.g. "/some/thing" | |
*/ | |
private static function mapPath( $base, $relative ){ | |
$absolute = explode('/', $base ); | |
$relative = explode('/', $relative); | |
while( $relative && $absolute ){ | |
$next = array_shift($relative); | |
if( '.' === $next ){ | |
// ignore | |
} | |
else if( '..' === $next ){ | |
array_pop( $absolute ); | |
} | |
else { | |
$absolute[] = $next; | |
} | |
} | |
return implode('/',$absolute); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment