| var browserify = require('../'); |
| var path = require('path'); |
| var spawn = require('child_process').spawn; |
| var parseShell = require('shell-quote').parse; |
| var insertGlobals = require('insert-module-globals'); |
| var duplexer = require('duplexer2'); |
| var subarg = require('subarg'); |
| var glob = require('glob'); |
| var Readable = require('readable-stream').Readable; |
| var xtend = require('xtend'); |
| |
| module.exports = function (args, opts) { |
| var argv = subarg(args, { |
| 'boolean': [ |
| 'deps', 'pack', 'ig', 'dg', 'im', 'd', 'list', 'builtins', |
| 'commondir', 'bare', 'full-paths', 'bundle-external', 'bf', |
| 'node' |
| ], |
| string: [ 's', 'r', 'u', 'x', 't', 'i', 'o', 'e', 'c', 'it' ], |
| alias: { |
| ig: [ 'insert-globals', 'fast' ], |
| dg: [ 'detect-globals', 'detectGlobals', 'dg' ], |
| bf: [ 'browser-field', 'browserField' ], |
| im: 'ignore-missing', |
| it: 'ignore-transform', |
| igv: 'insert-global-vars', |
| d: 'debug', |
| s: 'standalone', |
| noParse: [ 'noparse' ], |
| 'full-paths': [ 'fullpaths', 'fullPaths' ], |
| r: 'require', |
| u: 'exclude', |
| x: 'external', |
| t: 'transform', |
| i: 'ignore', |
| o: 'outfile', |
| e: 'entry', |
| c: 'command', |
| bare: 'bear' |
| }, |
| 'default': { |
| ig: false, |
| im: false, |
| dg: true, |
| d: false, |
| builtins: true, |
| commondir: true, |
| 'bundle-external': true, |
| bf: true, |
| dedupe: true, |
| node: false |
| } |
| }); |
| |
| var entries = argv._.concat(argv.entry) |
| .filter(Boolean).map(function (entry) { |
| if (entry === '-') { |
| var s = process.stdin; |
| if (typeof s.read === 'function') return s; |
| // only needed for 0.8, remove at some point later: |
| var rs = Readable().wrap(s); |
| s.resume(); |
| return rs; |
| } |
| return entry; |
| }); |
| |
| if (argv.node) { |
| argv.bare = true; |
| argv.browserField = false; |
| } |
| if (argv.bare) { |
| argv.builtins = false; |
| argv.commondir = false; |
| if (argv.igv === undefined) { |
| argv.igv = '__filename,__dirname'; |
| } |
| } |
| |
| if (argv.igv) { |
| var insertGlobalVars = {}; |
| var wantedGlobalVars = argv.igv.split(','); |
| Object.keys(insertGlobals.vars).forEach(function (x) { |
| if (wantedGlobalVars.indexOf(x) === -1) { |
| insertGlobalVars[x] = undefined; |
| } |
| }); |
| } |
| |
| var ignoreTransform = argv['ignore-transform'] || argv.it; |
| var b = browserify(xtend({ |
| noParse: Array.isArray(argv.noParse) ? argv.noParse : [argv.noParse], |
| extensions: [].concat(argv.extension).filter(Boolean).map(function (extension) { |
| if (extension.charAt(0) != '.') { |
| return '.' + extension; |
| } else { |
| return extension |
| } |
| }), |
| ignoreTransform: [].concat(ignoreTransform).filter(Boolean), |
| entries: entries, |
| fullPaths: argv['full-paths'], |
| builtins: argv.builtins === false ? false : undefined, |
| commondir: argv.commondir === false ? false : undefined, |
| bundleExternal: argv['bundle-external'], |
| basedir: argv.basedir, |
| browserField: argv.browserField, |
| transformKey: argv['transform-key'] ? ['browserify', argv['transform-key']] : undefined, |
| dedupe: argv['dedupe'], |
| |
| detectGlobals: argv.detectGlobals, |
| insertGlobals: argv['insert-globals'] || argv.ig, |
| insertGlobalVars: insertGlobalVars, |
| ignoreMissing: argv['ignore-missing'] || argv.im, |
| debug: argv['debug'] || argv.d, |
| standalone: argv['standalone'] || argv.s |
| }, opts)); |
| function error (msg) { |
| var e = new Error(msg); |
| process.nextTick(function () { b.emit('error', e) }); |
| } |
| b.argv = argv; |
| [].concat(argv.p).concat(argv.plugin).filter(Boolean) |
| .forEach(function (p) { |
| var pf = p, pOpts = {}; |
| if (typeof p === 'object') { |
| pf = p._.shift(), pOpts = p; |
| } |
| b.plugin(pf, pOpts); |
| }) |
| ; |
| |
| [].concat(argv.ignore).filter(Boolean) |
| .forEach(function (i) { |
| b._pending ++; |
| glob(i, function (err, files) { |
| if (err) return b.emit('error', err); |
| if (files.length === 0) { |
| b.ignore(i); |
| } |
| else { |
| files.forEach(function (file) { b.ignore(file) }); |
| } |
| if (--b._pending === 0) b.emit('_ready'); |
| }); |
| }) |
| ; |
| |
| [].concat(argv.exclude).filter(Boolean) |
| .forEach(function (u) { |
| b.exclude(u); |
| |
| b._pending ++; |
| glob(u, function (err, files) { |
| if (err) return b.emit('error', err); |
| files.forEach(function (file) { b.exclude(file) }); |
| if (--b._pending === 0) b.emit('_ready'); |
| }); |
| }) |
| ; |
| |
| [].concat(argv.require).filter(Boolean) |
| .forEach(function (r) { |
| var xs = splitOnColon(r); |
| b.require(xs[0], { expose: xs.length === 1 ? xs[0] : xs[1] }) |
| }) |
| ; |
| |
| // resolve any external files and add them to the bundle as externals |
| [].concat(argv.external).filter(Boolean) |
| .forEach(function (x) { |
| var xs = splitOnColon(x); |
| if (xs.length === 2) { |
| add(xs[0], { expose: xs[1] }); |
| } |
| else if (/\*/.test(x)) { |
| b.external(x); |
| glob(x, function (err, files) { |
| files.forEach(function (file) { |
| add(file, {}); |
| }); |
| }); |
| } |
| else add(x, {}); |
| |
| function add (x, opts) { |
| if (/^[\/.]/.test(x)) b.external(path.resolve(x), opts) |
| else b.external(x, opts) |
| } |
| }) |
| ; |
| |
| [].concat(argv.transform) |
| .filter(Boolean) |
| .forEach(function (t) { addTransform(t) }) |
| ; |
| |
| [].concat(argv.g).concat(argv['global-transform']) |
| .filter(Boolean) |
| .forEach(function (t) { |
| addTransform(t, { global: true }); |
| }) |
| ; |
| |
| function addTransform (t, opts) { |
| if (typeof t === 'string' || typeof t === 'function') { |
| b.transform(opts, t); |
| } |
| else if (t && typeof t === 'object') { |
| if (!t._[0] || typeof t._[0] !== 'string') { |
| return error( |
| 'expected first parameter to be a transform string' |
| ); |
| } |
| if (opts) Object.keys(opts).forEach(function (key) { |
| t[key] = opts[key]; |
| }); |
| b.transform(t, t._.shift()); |
| } |
| else error('unexpected transform of type ' + typeof t); |
| } |
| |
| [].concat(argv.command).filter(Boolean) |
| .forEach(function (c) { |
| var cmd = parseShell(c); |
| b.transform(function (file) { |
| var env = Object.keys(process.env).reduce(function (acc, key) { |
| acc[key] = process.env[key]; |
| return acc; |
| }, {}); |
| env.FILENAME = file; |
| var ps = spawn(cmd[0], cmd.slice(1), { env: env }); |
| var error = ''; |
| ps.stderr.on('data', function (buf) { error += buf }); |
| |
| ps.on('exit', function (code) { |
| if (code === 0) return; |
| console.error([ |
| 'error running source transform command: ' + c, |
| error.split('\n').join('\n '), |
| '' |
| ].join('\n')); |
| process.exit(1); |
| }); |
| return duplexer(ps.stdin, ps.stdout); |
| }); |
| }) |
| ; |
| |
| if (argv.standalone === '') { |
| error('--standalone requires an export name argument'); |
| return b; |
| } |
| |
| return b; |
| }; |
| |
| function splitOnColon (f) { |
| var pos = f.lastIndexOf(':'); |
| if (pos == -1) { |
| return [f]; // No colon |
| } else { |
| if ((/[a-zA-Z]:[\\/]/.test(f)) && (pos == 1)){ |
| return [f]; // Windows path and colon is part of drive name |
| } else { |
| return [f.substr(0, pos), f.substr(pos + 1)]; |
| } |
| } |
| } |