Permalink
Browse files

Work on --command improvements

  • Loading branch information...
1 parent 94ae19b commit ef44a01838a9365edcb2c010024d022fa4f3a449 @mixu committed Sep 4, 2013
View
@@ -2,3 +2,4 @@
test/tmp/
npm-debug.log
test/list-tasks/tmp/node_modules/
+test/node_modules/
@@ -6,6 +6,20 @@ var spawn = require('child_process').spawn;
// The output of the preceding task is piped into the writable/duplex stream,
// and the output of the readable/duplex stream is captured or piped forward
module.exports = function(options) {
+ if(typeof options.task === 'string') {
+ // parse quoted string variants:
+ // 1) not whitespace, not quote followed by not whitespace OR
+ // 2) double quote followed by not double quote or escaped double quote followed by double quote OR
+ // 3) single quote followed by not single quote or escaped single quote followed by single quote
+ options.task = options.task.match(/([^ \t\r\n"'][^ \t\r\n]*)|"(?:[\]["]|[^"])+"|'(?:[\][']|[^'])+'/g);
+ // since we're using uv_spawn which calls out to exec(3), we need to exclude the beginning quotes
+ options.task = options.task.map(function(i, index) {
+ if(index > 0 && i.charAt(0) == i.charAt(i.length-1) && (i.charAt(0) == '"' || i.charAt(0) == "'")) {
+ return i.substring(1, i.length-1);
+ }
+ return i;
+ });
+ }
var task = spawn.call(this, options.task[0], options.task.slice(1));
// The child_process API only emits errors when invoking the task fails.
@@ -0,0 +1,42 @@
+var Transform = require('readable-stream').Transform;
+
+function WrapCJS(options) {
+ Transform.call(this, options);
+ this.opts = options || {};
+ this.first = true;
+ this.buffer = '';
+}
+
+WrapCJS.prototype = Object.create(Transform.prototype, { constructor: { value: WrapCJS }});
+
+WrapCJS.prototype.writeFirst = function() {
+ this.push('var jade = require("jade").runtime; module.exports = ');
+ this.first = false;
+};
+
+WrapCJS.prototype._transform = function(chunk, encoding, done) {
+ if(this.first) {
+ this.writeFirst();
+ }
+ this.buffer += chunk;
+ done();
+};
+
+WrapCJS.prototype._flush = function(done) {
+ // for 0-length files, only _flush is called
+ if(this.first) {
+ this.writeFirst();
+ this.push('{};');
+ } else {
+ this.push(this.buffer.trim() + ';');
+ }
+ done();
+};
+
+module.exports = function(options) {
+ var instance = new WrapCJS(options);
+ return {
+ stdin: instance,
+ stdout: instance
+ };
+};
@@ -13,6 +13,7 @@ var fs = require('fs'),
filterPackages = require('../../list-tasks/filter-packages.js'),
wrapCommonJs = require('../../file-tasks/wrap-commonjs-web.js'),
wrapJson = require('../../file-tasks/wrap-json-web.js'),
+ wrapExports = require('../../file-tasks/wrap-exports-web.js')
log = require('minilog')('package-commonjs');
@@ -44,9 +45,7 @@ module.exports = function(list, options, out, onDone) {
// exclude files matching specific expressions
// - because .npmignores often do not cover all the files to exclude
var excludeList = [
-// new RegExp('\/test\/'),
new RegExp('\/dist\/'),
-// new RegExp('test\.js$'),
new RegExp('\/example\/'),
new RegExp('\/benchmark\/'),
new RegExp('[-.]min.js$')
@@ -85,7 +84,7 @@ module.exports = function(list, options, out, onDone) {
// if the main package is empty, use the next one
// TODO FIXME: this occurs when you are in a ./node_modules/ directory and run
// a regular build via the command line. Suddenly, the folder you are in is detected as a
- // separate package! Need a better test for this in the long run...c
+ // separate package! Need a better test for this in the long run...
if(list.packages[0].files.length === 0) {
list.packages.shift();
}
@@ -99,9 +98,20 @@ module.exports = function(list, options, out, onDone) {
// filter out non-JS files
var removed = [];
// find the ignore files (applying them in the correct order)
+ var whitelist = [
+ /(\.js|\.json)$/
+ ];
+ // if a command is applied to non-js files, then do not exclude them
+ if(Array.isArray(options.command)) {
+ options.command.forEach(function(command) {
+ whitelist.push(command.expr);
+ });
+ }
function traverse(packageObj) {
packageObj.files = packageObj.files.filter(function(item) {
- var result = (/(\.js|\.json)$/.test(item.name));
+ var result = (whitelist.some(function(expr) {
+ return expr.test(item.name);
+ }));
// also update list.files
if(!result) {
removed.push(item.name);
@@ -126,7 +136,11 @@ module.exports = function(list, options, out, onDone) {
// top level boundary
out.write('(function(){');
// the require() implementation
- out.write(fs.readFileSync(__dirname + '/resources/require.min.js'));
+ if(options.require !== false) {
+ out.write(fs.readFileSync(__dirname + '/resources/require.min.js'));
+ } else {
+ out.write(fs.readFileSync(__dirname + '/resources/require.fallthrough.js'));
+ }
// the registry definition
out.write('\nrequire.m = [];\n');
@@ -192,8 +206,45 @@ module.exports = function(list, options, out, onDone) {
tasks.push(function(done) {
out.write(JSON.stringify(relname) + ': ');
+ // task running
var last, tasks = [ ];
+ // 1st: any custom commands (in array order)
+ // 2nd: any wrapping
+ // 3rd: any reporting
+
+ // if a external command is applied, shift it onto the stack
+ if(options.command) {
+ if(Array.isArray(options.command)) {
+ // "advanced mode" where --command has extension-specific tasks
+ options.command.forEach(function(command) {
+ if(command.expr.test(item.name)) {
+ tasks.push(function() {
+ return spawn({
+ name: item.name, // full path
+ task: command.cmd
+ });
+ });
+ }
+ if(command.wrap == 'exports') {
+ // json wrapping and exports wrapping are the same thing
+ tasks.push(function() {
+ return wrapExports({ });
+ });
+ }
+ });
+ } else if(path.extname(item.name) == '.js') {
+ // "default mode" where --command applies only to .js files
+ tasks.push(function() {
+ return spawn({
+ name: item.name, // full path
+ task: options.command
+ });
+ });
+ }
+ }
+
switch(path.extname(item.name)) {
+ default:
case '.js':
tasks.push(function() {
return wrapCommonJs({
@@ -208,16 +259,7 @@ module.exports = function(list, options, out, onDone) {
});
break;
}
- // if a external command is applied, shift it onto the stack
if(options.command) {
- if(path.extname(item.name) == '.js') {
- tasks.unshift(function() {
- return spawn({
- name: item.name, // full path
- task: options.command
- });
- });
- }
// if we are reporting, add the stream size capture task at the end
// so we can report on results (e.g. of minification)
if(options.report) {
@@ -0,0 +1,82 @@
+/*!
+ * Require functions by TJ Holowaychuk <tj@learnboost.com>
+ * With enhancements by Mikito Takada for multi-package support.
+ */
+
+var globalRequire = require;
+/**
+ * Require the given path.
+ *
+ * @param {String} path
+ * @return {Object} exports
+ * @api public
+ */
+
+require = function(p, context, parent){
+ context || (context = 0);
+ var path = require.resolve(p, context),
+ mod = require.m[context][path];
+ if (!mod) {
+ mod = globalRequire(path);
+ if(!mod) {
+ throw new Error('failed to require "' + p + '" from ' + parent);
+ } else {
+ return mod;
+ }
+ }
+ if(mod.c) {
+ /* submodule - load the actual module */
+ context = mod.c;
+ path = mod.m;
+ mod = require.m[context][mod.m];
+ if (!mod) throw new Error('failed to require "' + path + '" from ' + context);
+ }
+ if (!mod.exports) {
+ mod.exports = {};
+ mod.call(mod.exports, mod, mod.exports, require.relative(path, context));
+ }
+ return mod.exports;
+}
+
+/**
+ * Resolve `path`.
+ *
+ * @param {String} path
+ * @return {Object} module
+ * @api public
+ */
+
+require.resolve = function(path, context){
+ var orig = path,
+ reg = path + '.js',
+ index = path + '/index.js';
+ return require.m[context][reg] && reg ||
+ require.m[context][index] && index ||
+ orig;
+};
+
+/**
+ * Return a require function relative to the `relativeTo` path.
+ *
+ * @param {String} relativeTo
+ * @return {Function}
+ * @api private
+ */
+
+require.relative = function(relativeTo, context) {
+ return function(p){
+ if ('.' != p.charAt(0)) return require(p, context, relativeTo);
+
+ var path = relativeTo.split('/')
+ , segs = p.split('/');
+ path.pop();
+
+ for (var i = 0; i < segs.length; i++) {
+ var seg = segs[i];
+ if ('..' == seg) path.pop();
+ else if ('.' != seg) path.push(seg);
+ }
+
+ return require(path.join('/'), context, relativeTo);
+ };
+};
@@ -0,0 +1,3 @@
+h1
+ | Hello
+ = ' ' + name
@@ -0,0 +1 @@
+module.exports = 'index.js';
@@ -6,8 +6,7 @@ var fs = require('fs'),
exports['integration tests'] = {
'can build a json file': function(done) {
- var Glue = require('gluejs'),
- file = fs.createWriteStream(__dirname + '/tmp/temp.js');
+ var file = fs.createWriteStream(__dirname + '/tmp/temp.js');
file.once('close', function() {
var result = require(__dirname + '/tmp/temp.js');
@@ -20,7 +19,52 @@ exports['integration tests'] = {
.include('./')
.export('module.exports')
.render(file);
+ },
+
+ '--command with unix pipe': function(done) {
+ new Glue()
+ .basepath(__dirname +'/fixtures/jade-file/')
+ .include('./')
+ .set('command', 'bash -c "echo \'module.exports = \"bar\";\'"')
+ .export('module.exports')
+ .render(function(err, txt) {
+ console.log(txt);
+ done();
+ });
+ },
+
+ '--command with specific extension': function(done) {
+ var file = fs.createWriteStream(__dirname + '/tmp/temp2.js');
+
+ file.once('close', function() {
+ var name = new Date().getTime();
+ // use standard require
+ var result = require(__dirname + '/tmp/temp2.js')({ name: name });
+ assert.deepEqual(result, '<h1>Hello '+name+'</h1>');
+ done();
+ });
+
+ new Glue()
+ .basepath(__dirname +'/fixtures/jade-file/')
+ .include('./')
+ .set('require', false)
+ .set('command', [
+ {
+ expr: new RegExp('^.+\.jade$'),
+ cmd: 'jade --client --no-debug',
+ wrap: 'exports'
+ // cmd: 'bash -c "echo \'module.exports = \"bar\";\'"'
+ },
+ {
+ expr: new RegExp('^.+\.jade$'),
+ cmd: 'uglifyjs --no-copyright'
+ }
+ ])
+ .main('foo.jade')
+ .export('module.exports')
+ .render(file);
}
+
};
// if this module is the script being run, then run the tests:
@@ -155,7 +155,7 @@ exports['filter-package'] = {
infer(list);
// now apply the filter
filter(list);
- console.log(util.inspect(list, null, 10, true));
+ // console.log(util.inspect(list, null, 10, true));
assert.deepEqual(list.files, [
{ name: '/a/index.js' },
{ name: '/a/node_modules/bar/index.js' },
View
@@ -0,0 +1,8 @@
+{
+ "name": "gluejs-tests",
+ "description": "Tests for gluejs",
+ "dependencies": {
+ "jade": "~2.0.0",
+ "coffee-script": "~1.6.3"
+ }
+}
Oops, something went wrong.

0 comments on commit ef44a01

Please sign in to comment.