asset-smasher
Advanced tools
Comparing version 0.2.12 to 0.3.0
# Asset Smasher Changelog | ||
## 0.3.0 (June 1, 2013) | ||
Functional Changes | ||
- The JSX transformer now can transform `.js` files (without the additional `.jsx` extension) as long as the `/** @jsx React.DOM */` comment is present in the file. | ||
- For `.jsx` files, the JSX transformer will add the `/** @jsx React.DOM */` comment to the file if it is missing. | ||
- CommonJS-style `.js` files can now be automatically wrapped with [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) `define` calls if a `/** @amd */` comment is present in the file. See the "AMD Support" section of the README for more info. | ||
API Changes (this should only affect you if you've written custom transformers) | ||
- The `shouldTransform` and `transformedFileName` methods in transformers now receive the asset object as a second parameter | ||
- The asset object now has a `transformInfo` property (that is an object) that transformers can use to put information in when they are processing. This can be used, for example, to prevent a file from being processed more than once (see `jsx_transform.js` for an example) | ||
- Post-transform operations now must be a constructor function rather than just a function(asset, cb). This is to allow options to be passed into the post-transformer (see `end_js_semicolon.js` or the new `amd_wrapper.js` for examples) | ||
## 0.2.12 (May 30, 2013) | ||
@@ -4,0 +18,0 @@ |
@@ -15,2 +15,3 @@ var path = require('path'); | ||
this.assetFilePath = options.assetFilePath; | ||
this.transformInfo = {}; | ||
this.contents = null; | ||
@@ -45,2 +46,3 @@ this.compiled = false; | ||
this._assetFileStat = null; | ||
this.transformInfo = {}; | ||
this.contents = null; | ||
@@ -47,0 +49,0 @@ this.compiled = false; |
@@ -95,5 +95,5 @@ var async = require('async'); | ||
}), | ||
postTransforms:_.map(postTransforms, function (transform) { | ||
return transform; | ||
}) | ||
postTransforms:_.sortBy(_.map(postTransforms, function (transform) { | ||
return new transform(options); | ||
}), 'priority') | ||
}); | ||
@@ -100,0 +100,0 @@ |
@@ -31,21 +31,4 @@ /** | ||
exports.postTransforms = { | ||
/** | ||
* Ensure that .js files end in a semicolon | ||
*/ | ||
EndJsSemicolon:function (asset, cb) { | ||
if (path.extname(asset.logicalName) === '.js') { | ||
var contents = asset.contents; | ||
if (Buffer.isBuffer(contents)) { | ||
contents = contents.toString('utf-8'); | ||
} | ||
if (!/\s*;[\s\n]*$/.test(contents)) { | ||
contents += ';\n'; | ||
} | ||
if (!/\n$/.test(contents)) { | ||
contents += '\n'; | ||
} | ||
asset.contents = contents; | ||
} | ||
cb(); | ||
} | ||
AmdWrapper:require('./post_transforms/amd_wrapper'), | ||
EndJsSemicolon:require('./post_transforms/end_js_semicolon') | ||
}; | ||
@@ -73,4 +56,5 @@ | ||
var currentTransform = null; | ||
// Reset the logical name | ||
// Reset the logical name and transform info | ||
asset.logicalName = path.basename(asset.assetFilePath); | ||
asset.transformInfo = {}; | ||
// Transform the asset | ||
@@ -91,3 +75,3 @@ async.waterfall([ | ||
for (var i = 0; i < transforms.length; ++i) { | ||
if (transforms[i].shouldTransform(asset.logicalName)) { | ||
if (transforms[i].shouldTransform(asset.logicalName, asset)) { | ||
currentTransform = transforms[i]; | ||
@@ -106,3 +90,3 @@ return true; | ||
setImmediateCompat(function() { | ||
postTransform(asset, eachCb); | ||
postTransform.transform(asset, eachCb); | ||
}); | ||
@@ -126,17 +110,32 @@ }, wfCb); | ||
var currentTransform = null; | ||
// Reset the logical name | ||
// Reset the logical name and transform info | ||
asset.logicalName = path.basename(asset.assetFilePath); | ||
// Just transform the name | ||
async.whilst(function () { | ||
for (var i = 0; i < transforms.length; ++i) { | ||
if (transforms[i].shouldTransform(asset.logicalName)) { | ||
currentTransform = transforms[i]; | ||
return true; | ||
asset.transformInfo = {}; | ||
// Perform "dry" - name only transformation | ||
async.waterfall([ | ||
function (wfCb) { | ||
// Load the asset (if it's not a manifest file/dir) | ||
if (!asset.isManifest() && !asset.contents) { | ||
asset.loadOriginalContents(wfCb); | ||
} | ||
else { | ||
wfCb(); | ||
} | ||
}, | ||
function (wfCb) { | ||
// Just transform the name | ||
async.whilst(function () { | ||
for (var i = 0; i < transforms.length; ++i) { | ||
if (transforms[i].shouldTransform(asset.logicalName, asset)) { | ||
currentTransform = transforms[i]; | ||
return true; | ||
} | ||
} | ||
return false; | ||
}, function (whilstCb) { | ||
asset.logicalName = currentTransform.transformedFileName(asset.logicalName, asset); | ||
whilstCb(); | ||
}, wfCb); | ||
} | ||
return false; | ||
}, function (whilstCb) { | ||
asset.logicalName = currentTransform.transformedFileName(asset.logicalName); | ||
whilstCb(); | ||
}, function (e) { | ||
], function (e) { | ||
cb(e, asset); | ||
@@ -146,7 +145,7 @@ }); | ||
getExtensions:function () { | ||
return _.flatten(_.map(this.transforms, function (transform) { | ||
return _.uniq(_.flatten(_.map(this.transforms, function (transform) { | ||
return transform.extensions(); | ||
})); | ||
}))); | ||
} | ||
}; | ||
@@ -17,7 +17,7 @@ /** | ||
}, | ||
shouldTransform:function (file) { | ||
return path.extname(file) === '.coffee'; | ||
shouldTransform:function (fileName, asset) { | ||
return path.extname(fileName) === '.coffee'; | ||
}, | ||
transformedFileName:function (file) { | ||
return path.basename(file, '.coffee'); | ||
transformedFileName:function (fileName, asset) { | ||
return path.basename(fileName, '.coffee'); | ||
}, | ||
@@ -34,3 +34,3 @@ transform:function (asset, cb) { | ||
// Transform the file name | ||
asset.logicalName = this.transformedFileName(asset.logicalName); | ||
asset.logicalName = this.transformedFileName(asset.logicalName, asset); | ||
// Get the contents | ||
@@ -37,0 +37,0 @@ var contents = asset.contents; |
@@ -20,7 +20,7 @@ /** | ||
}, | ||
shouldTransform:function (file) { | ||
return path.extname(file) === '.dust'; | ||
shouldTransform:function (fileName, asset) { | ||
return path.extname(fileName) === '.dust'; | ||
}, | ||
transformedFileName:function (file) { | ||
return path.basename(file, '.dust'); | ||
transformedFileName:function (fileName, asset) { | ||
return path.basename(fileName, '.dust'); | ||
}, | ||
@@ -41,3 +41,3 @@ transform:function (asset, cb) { | ||
// Transform the file name | ||
asset.logicalName = this.transformedFileName(asset.logicalName); | ||
asset.logicalName = this.transformedFileName(asset.logicalName, asset); | ||
// Compute the name for the template (logical name minus the .dust/.js) | ||
@@ -44,0 +44,0 @@ var logicalPath = asset.logicalPath; |
@@ -21,7 +21,7 @@ /** | ||
}, | ||
shouldTransform:function (file) { | ||
return path.extname(file) === '.ejs'; | ||
shouldTransform:function (fileName, asset) { | ||
return path.extname(fileName) === '.ejs'; | ||
}, | ||
transformedFileName:function (file) { | ||
return path.basename(file, '.ejs'); | ||
transformedFileName:function (fileName, asset) { | ||
return path.basename(fileName, '.ejs'); | ||
}, | ||
@@ -38,3 +38,3 @@ transform:function (asset, cb) { | ||
// Transform the file name | ||
asset.logicalName = this.transformedFileName(asset.logicalName); | ||
asset.logicalName = this.transformedFileName(asset.logicalName, asset); | ||
// Get the contents | ||
@@ -41,0 +41,0 @@ var contents = asset.contents; |
@@ -20,7 +20,7 @@ /** | ||
}, | ||
shouldTransform:function (file) { | ||
return path.extname(file) === '.hbs'; | ||
shouldTransform:function (fileName, asset) { | ||
return path.extname(fileName) === '.hbs'; | ||
}, | ||
transformedFileName:function (file) { | ||
return path.basename(file, '.hbs'); | ||
transformedFileName:function (fileName, asset) { | ||
return path.basename(fileName, '.hbs'); | ||
}, | ||
@@ -37,3 +37,3 @@ transform:function (asset, cb) { | ||
// Transform the file name | ||
asset.logicalName = this.transformedFileName(asset.logicalName); | ||
asset.logicalName = this.transformedFileName(asset.logicalName, asset); | ||
// Compute the name for the template (logical name minus the .hbs/.js) | ||
@@ -40,0 +40,0 @@ var logicalPath = asset.logicalPath; |
@@ -11,2 +11,4 @@ /** | ||
var JSX_PRAGMA = '/** @jsx React.DOM */'; | ||
var JSXTransform = module.exports = function JSXTransform(options) { | ||
@@ -17,9 +19,30 @@ this.options = options || {}; | ||
extensions:function () { | ||
return ['.jsx']; | ||
return ['.jsx', '.js']; | ||
}, | ||
shouldTransform:function (file) { | ||
return path.extname(file) === '.jsx'; | ||
shouldTransform:function (fileName, asset) { | ||
var ext = path.extname(fileName); | ||
// Don't transform files more than once | ||
if (asset.transformInfo.isJsxTransformed) { | ||
return false; | ||
// .jsx files are explicitly transformed | ||
} else if (ext === '.jsx') { | ||
return true; | ||
// a .js file that contains the @jsx pragma comment is implicitly transformed | ||
} else if (ext === '.js' && asset.contents) { | ||
var contents = asset.contents; | ||
if (Buffer.isBuffer(contents)) { | ||
contents = contents.toString('utf-8'); | ||
} | ||
return contents.indexOf(JSX_PRAGMA) >= 0; | ||
} else { | ||
return false; | ||
} | ||
}, | ||
transformedFileName:function (file) { | ||
return path.basename(file, '.jsx'); | ||
transformedFileName:function (fileName, asset) { | ||
asset.transformInfo.isJsxTransformed = true; | ||
if (path.extname(fileName) === '.jsx') { | ||
return path.basename(fileName, '.jsx'); | ||
} else { | ||
return fileName; // it's just a .js file - no transformation necessary | ||
} | ||
}, | ||
@@ -36,3 +59,3 @@ transform:function (asset, cb) { | ||
// Transform the file name | ||
asset.logicalName = this.transformedFileName(asset.logicalName); | ||
asset.logicalName = this.transformedFileName(asset.logicalName, asset); | ||
// Get the contents | ||
@@ -43,2 +66,6 @@ var contents = asset.contents; | ||
} | ||
// If the file is missing the @jsx pragma, add it | ||
if (contents.indexOf(JSX_PRAGMA) < 0) { | ||
contents = JSX_PRAGMA + '\n' + contents; | ||
} | ||
// Transform to js | ||
@@ -45,0 +72,0 @@ try { |
@@ -18,7 +18,7 @@ /** | ||
}, | ||
shouldTransform:function (file) { | ||
return path.extname(file) === '.less'; | ||
shouldTransform:function (fileName, asset) { | ||
return path.extname(fileName) === '.less'; | ||
}, | ||
transformedFileName:function (file) { | ||
return path.basename(file, '.less'); | ||
transformedFileName:function (fileName, asset) { | ||
return path.basename(fileName, '.less'); | ||
}, | ||
@@ -36,3 +36,3 @@ transform:function (asset, cb) { | ||
// Transform the file name | ||
asset.logicalName = this.transformedFileName(asset.logicalName); | ||
asset.logicalName = this.transformedFileName(asset.logicalName, asset); | ||
// Get the contents | ||
@@ -39,0 +39,0 @@ var contents = asset.contents; |
@@ -16,12 +16,12 @@ /** | ||
}, | ||
shouldTransform:function (file) { | ||
return path.extname(file) === '.mf'; | ||
shouldTransform:function (fileName, asset) { | ||
return path.extname(fileName) === '.mf'; | ||
}, | ||
transformedFileName:function (file) { | ||
return path.basename(file, '.mf'); | ||
transformedFileName:function (fileName, asset) { | ||
return path.basename(fileName, '.mf'); | ||
}, | ||
transform:function (asset, cb) { | ||
asset.logicalName = this.transformedFileName(asset.logicalName); | ||
asset.logicalName = this.transformedFileName(asset.logicalName, asset); | ||
cb(); | ||
} | ||
}; |
@@ -18,7 +18,7 @@ /** | ||
}, | ||
shouldTransform:function (file) { | ||
return path.extname(file) === '.styl'; | ||
shouldTransform:function (fileName, asset) { | ||
return path.extname(fileName) === '.styl'; | ||
}, | ||
transformedFileName:function (file) { | ||
return path.basename(file, '.styl'); | ||
transformedFileName:function (fileName, asset) { | ||
return path.basename(fileName, '.styl'); | ||
}, | ||
@@ -35,3 +35,3 @@ transform:function (asset, cb) { | ||
// Transform the file name | ||
asset.logicalName = this.transformedFileName(asset.logicalName); | ||
asset.logicalName = this.transformedFileName(asset.logicalName, asset); | ||
// Get the contents | ||
@@ -38,0 +38,0 @@ var contents = asset.contents; |
var path = require('path'); | ||
var url = require('url'); | ||
var async = require('async'); | ||
var underscore = require('underscore'); | ||
var _ = require('underscore'); | ||
var Smasher = require('./asset-smasher').Smasher; | ||
@@ -16,3 +16,3 @@ var send = require('send'); | ||
} | ||
this.serve = underscore.defaults(serve, { | ||
this.serve = _.defaults(serve, { | ||
individual: true | ||
@@ -19,0 +19,0 @@ }); |
{ | ||
"name": "asset-smasher", | ||
"description": "Asset pre-processor, merger, and compressor.", | ||
"version": "0.2.12", | ||
"version": "0.3.0", | ||
"author": "Jim Riecken <jriecken@gmail.com>", | ||
@@ -6,0 +6,0 @@ "keywords": [ |
@@ -14,2 +14,3 @@ # Asset Smasher | ||
- [Transformer Notes](#transformer-notes) | ||
- [AMD Support](#tn-amd) | ||
- [LESS/Stylus](#tn-less-styl) | ||
@@ -31,2 +32,3 @@ - [ejs](#tn-ejs) | ||
- `.jsx` - Transform JSX files (for use with [React](http://facebook.github.io/react/)) into JavaScript files. | ||
- Can wrap CommonJS-style JavaScript files with [AMD](https://github.com/amdjs/amdjs-api/wiki/AMD) `define` calls. | ||
- Processors can be chained together. E.g `test.js.hbs.ejs` (run Handlebars template through EJS, then compile it) | ||
@@ -441,2 +443,39 @@ - Additional processors can be plugged in. | ||
### <a name="tn-amd"></a> AMD Support | ||
Asset-smasher can wrap JavaScript files that follow the [CommonJS](http://wiki.commonjs.org/wiki/Modules) module format with [Asynchronous Module Definition](https://github.com/amdjs/amdjs-api/wiki/AMD) `define` calls. | ||
To enable the wrapping of a JavaScript file, put the following at the top of it: | ||
/** @amd */ | ||
This will cause asset smasher to: | ||
- Parse the contents of the file for any `require` calls | ||
- Wrap the contents of the file with a `define` call where the module id is the logical path of the file (minus `.js`) and the dependencies are anything that was `require`d. `require`, `exports`, and `module` are always dependencies. | ||
Example (say the file is in `scripts/foo.js`) | ||
/** @amd */ | ||
var x = require('x'); | ||
var y = require('../y'); | ||
exports.foo = function (bar) { | ||
return x(bar) + y(bar); | ||
}; | ||
This will be transformed into: | ||
define('scripts/foo', | ||
['require', 'exports', 'module', 'x', '../y'], | ||
function (require, exports, module, x, y) { | ||
var x = require('x'); | ||
var y = require('../y'); | ||
exports.foo = function (bar) { | ||
return x(bar) + y(bar); | ||
}; | ||
}); | ||
You can then use an AMD loader (like [require.js](http://requirejs.org/)) to load the modules. | ||
### <a name="tn-less-styl"></a> LESS/Stylus | ||
@@ -443,0 +482,0 @@ |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
94258
26
2056
492