args.js 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. var browserify = require('../');
  2. var path = require('path');
  3. var spawn = require('child_process').spawn;
  4. var parseShell = require('shell-quote').parse;
  5. var insertGlobals = require('insert-module-globals');
  6. var duplexer = require('duplexer2');
  7. var subarg = require('subarg');
  8. var glob = require('glob');
  9. var Readable = require('readable-stream').Readable;
  10. var xtend = require('xtend');
  11. module.exports = function (args, opts) {
  12. var argv = subarg(args, {
  13. 'boolean': [
  14. 'deps', 'pack', 'ig', 'dg', 'im', 'd', 'list', 'builtins',
  15. 'commondir', 'bare', 'full-paths', 'bundle-external', 'bf',
  16. 'node', 'preserve-symlinks'
  17. ],
  18. string: [ 's', 'r', 'u', 'x', 't', 'i', 'o', 'e', 'c', 'it' ],
  19. alias: {
  20. ig: [ 'insert-globals', 'fast' ],
  21. dg: [ 'detect-globals', 'detectGlobals', 'dg' ],
  22. bf: [ 'browser-field', 'browserField' ],
  23. im: 'ignore-missing',
  24. it: 'ignore-transform',
  25. igv: 'insert-global-vars',
  26. d: 'debug',
  27. s: 'standalone',
  28. noParse: [ 'noparse' ],
  29. 'full-paths': [ 'fullpaths', 'fullPaths' ],
  30. r: 'require',
  31. u: 'exclude',
  32. x: 'external',
  33. t: 'transform',
  34. i: 'ignore',
  35. o: 'outfile',
  36. e: 'entry',
  37. c: 'command',
  38. bare: 'bear'
  39. },
  40. 'default': {
  41. ig: false,
  42. im: false,
  43. dg: true,
  44. d: false,
  45. builtins: true,
  46. commondir: true,
  47. 'bundle-external': true,
  48. bf: true,
  49. dedupe: true,
  50. node: false
  51. }
  52. });
  53. var entries = argv._.concat(argv.entry)
  54. .filter(Boolean).map(function (entry) {
  55. if (entry === '-') {
  56. var s = process.stdin;
  57. if (typeof s.read === 'function') return s;
  58. // only needed for 0.8, remove at some point later:
  59. var rs = Readable().wrap(s);
  60. s.resume();
  61. return rs;
  62. }
  63. return entry;
  64. });
  65. if (argv.igv) {
  66. var insertGlobalVars = {};
  67. var wantedGlobalVars = argv.igv.split(',');
  68. Object.keys(insertGlobals.vars).forEach(function (x) {
  69. if (wantedGlobalVars.indexOf(x) === -1) {
  70. insertGlobalVars[x] = undefined;
  71. }
  72. });
  73. }
  74. var ignoreTransform = argv['ignore-transform'] || argv.it;
  75. var b = browserify(xtend({
  76. node: argv.node,
  77. bare: argv.bare,
  78. noParse: Array.isArray(argv.noParse) ? argv.noParse : [argv.noParse],
  79. extensions: [].concat(argv.extension).filter(Boolean).map(function (extension) {
  80. if (extension.charAt(0) != '.') {
  81. return '.' + extension;
  82. } else {
  83. return extension
  84. }
  85. }),
  86. ignoreTransform: [].concat(ignoreTransform).filter(Boolean),
  87. entries: entries,
  88. fullPaths: argv['full-paths'],
  89. builtins: argv.builtins === false ? false : undefined,
  90. commondir: argv.commondir === false ? false : undefined,
  91. bundleExternal: argv['bundle-external'],
  92. basedir: argv.basedir,
  93. browserField: argv.browserField,
  94. transformKey: argv['transform-key'] ? ['browserify', argv['transform-key']] : undefined,
  95. dedupe: argv['dedupe'],
  96. preserveSymlinks: argv['preserve-symlinks'],
  97. detectGlobals: argv.detectGlobals,
  98. insertGlobals: argv['insert-globals'] || argv.ig,
  99. insertGlobalVars: insertGlobalVars,
  100. ignoreMissing: argv['ignore-missing'] || argv.im,
  101. debug: argv['debug'] || argv.d,
  102. standalone: argv['standalone'] || argv.s
  103. }, opts));
  104. function error (msg) {
  105. var e = new Error(msg);
  106. process.nextTick(function () { b.emit('error', e) });
  107. }
  108. b.argv = argv;
  109. [].concat(argv.p).concat(argv.plugin).filter(Boolean)
  110. .forEach(function (p) {
  111. var pf = p, pOpts = {};
  112. if (typeof p === 'object') {
  113. pf = p._.shift(), pOpts = p;
  114. }
  115. b.plugin(pf, pOpts);
  116. })
  117. ;
  118. [].concat(argv.ignore).filter(Boolean)
  119. .forEach(function (i) {
  120. b._pending ++;
  121. glob(i, function (err, files) {
  122. if (err) return b.emit('error', err);
  123. if (files.length === 0) {
  124. b.ignore(i);
  125. }
  126. else {
  127. files.forEach(function (file) { b.ignore(file) });
  128. }
  129. if (--b._pending === 0) b.emit('_ready');
  130. });
  131. })
  132. ;
  133. [].concat(argv.exclude).filter(Boolean)
  134. .forEach(function (u) {
  135. b.exclude(u);
  136. b._pending ++;
  137. glob(u, function (err, files) {
  138. if (err) return b.emit('error', err);
  139. files.forEach(function (file) { b.exclude(file) });
  140. if (--b._pending === 0) b.emit('_ready');
  141. });
  142. })
  143. ;
  144. [].concat(argv.require).filter(Boolean)
  145. .forEach(function (r) {
  146. var xs = splitOnColon(r);
  147. b.require(xs[0], { expose: xs.length === 1 ? xs[0] : xs[1] })
  148. })
  149. ;
  150. // resolve any external files and add them to the bundle as externals
  151. [].concat(argv.external).filter(Boolean)
  152. .forEach(function (x) {
  153. var xs = splitOnColon(x);
  154. if (xs.length === 2) {
  155. add(xs[0], { expose: xs[1] });
  156. }
  157. else if (/\*/.test(x)) {
  158. b.external(x);
  159. glob(x, function (err, files) {
  160. files.forEach(function (file) {
  161. add(file, {});
  162. });
  163. });
  164. }
  165. else add(x, {});
  166. function add (x, opts) {
  167. if (/^[\/.]/.test(x)) b.external(path.resolve(x), opts)
  168. else b.external(x, opts)
  169. }
  170. })
  171. ;
  172. [].concat(argv.transform)
  173. .filter(Boolean)
  174. .forEach(function (t) { addTransform(t) })
  175. ;
  176. [].concat(argv.g).concat(argv['global-transform'])
  177. .filter(Boolean)
  178. .forEach(function (t) {
  179. addTransform(t, { global: true });
  180. })
  181. ;
  182. function addTransform (t, opts) {
  183. if (typeof t === 'string' || typeof t === 'function') {
  184. b.transform(opts, t);
  185. }
  186. else if (t && typeof t === 'object') {
  187. if (!t._[0] || typeof t._[0] !== 'string') {
  188. return error(
  189. 'expected first parameter to be a transform string'
  190. );
  191. }
  192. if (opts) Object.keys(opts).forEach(function (key) {
  193. t[key] = opts[key];
  194. });
  195. b.transform(t, t._.shift());
  196. }
  197. else error('unexpected transform of type ' + typeof t);
  198. }
  199. [].concat(argv.command).filter(Boolean)
  200. .forEach(function (c) {
  201. var cmd = parseShell(c);
  202. b.transform(function (file) {
  203. var env = Object.keys(process.env).reduce(function (acc, key) {
  204. acc[key] = process.env[key];
  205. return acc;
  206. }, {});
  207. env.FILENAME = file;
  208. var ps = spawn(cmd[0], cmd.slice(1), { env: env });
  209. var error = '';
  210. ps.stderr.on('data', function (buf) { error += buf });
  211. ps.on('exit', function (code) {
  212. if (code === 0) return;
  213. console.error([
  214. 'error running source transform command: ' + c,
  215. error.split('\n').join('\n '),
  216. ''
  217. ].join('\n'));
  218. process.exit(1);
  219. });
  220. return duplexer(ps.stdin, ps.stdout);
  221. });
  222. })
  223. ;
  224. if (argv.standalone === '') {
  225. error('--standalone requires an export name argument');
  226. return b;
  227. }
  228. return b;
  229. };
  230. function splitOnColon (f) {
  231. var pos = f.lastIndexOf(':');
  232. if (pos == -1) {
  233. return [f]; // No colon
  234. } else {
  235. if ((/[a-zA-Z]:[\\/]/.test(f)) && (pos == 1)){
  236. return [f]; // Windows path and colon is part of drive name
  237. } else {
  238. return [f.substr(0, pos), f.substr(pos + 1)];
  239. }
  240. }
  241. }