Skip to content

Instantly share code, notes, and snippets.

@timwhitlock
Created August 19, 2014 20:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timwhitlock/95b0a3c326cebba68127 to your computer and use it in GitHub Desktop.
Save timwhitlock/95b0a3c326cebba68127 to your computer and use it in GitHub Desktop.
Exposes source maps to dynamic Assetic routes in debug mode
<?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