From b62aa070bf696405f79fe5da595bb26236e6b4d7 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 9 Jun 2016 16:04:01 -0400 Subject: [PATCH] build/bundle CLI --- bin/handleError.js | 57 --- bin/rollup | 873 +++++++++++++++++++++++++++++++++++- bin/showHelp.js | 13 - bin/src/handleError.js | 61 +++ bin/{ => src}/help.md | 2 +- bin/src/index.js | 38 ++ bin/{ => src}/runRollup.js | 95 ++-- bin/src/sourceMappingUrl.js | 4 + package.json | 8 +- rollup.config.cli.js | 29 ++ rollup.config.js | 4 +- test/mocha.opts | 1 + 12 files changed, 1053 insertions(+), 132 deletions(-) delete mode 100644 bin/handleError.js delete mode 100644 bin/showHelp.js create mode 100644 bin/src/handleError.js rename bin/{ => src}/help.md (98%) create mode 100644 bin/src/index.js rename bin/{ => src}/runRollup.js (61%) create mode 100644 bin/src/sourceMappingUrl.js create mode 100644 rollup.config.cli.js create mode 100644 test/mocha.opts diff --git a/bin/handleError.js b/bin/handleError.js deleted file mode 100644 index 21a100d..0000000 --- a/bin/handleError.js +++ /dev/null @@ -1,57 +0,0 @@ -var chalk = require( 'chalk' ); - -var handlers = { - MISSING_CONFIG: function () { - console.error( chalk.red( 'Config file must export an options object. See https://github.com/rollup/rollup/wiki/Command-Line-Interface#using-a-config-file' ) ); - }, - - MISSING_INPUT_OPTION: function () { - console.error( chalk.red( 'You must specify an --input (-i) option' ) ); - }, - - MISSING_OUTPUT_OPTION: function () { - console.error( chalk.red( 'You must specify an --output (-o) option when creating a file with a sourcemap' ) ); - }, - - MISSING_NAME: function ( err ) { - console.error( chalk.red( 'You must supply a name for UMD exports (e.g. `--name myModule`)' ) ); - }, - - PARSE_ERROR: function ( err ) { - console.error( chalk.red( 'Error parsing ' + err.file + ': ' + err.message ) ); - }, - - ONE_AT_A_TIME: function ( err ) { - console.error( chalk.red( 'rollup can only bundle one file at a time' ) ); - }, - - DUPLICATE_IMPORT_OPTIONS: function ( err ) { - console.error( chalk.red( 'use --input, or pass input path as argument' ) ); - }, - - ROLLUP_WATCH_NOT_INSTALLED: function ( err ) { - console.error( chalk.red( 'rollup --watch depends on the rollup-watch package, which could not be found. You can install it globally (recommended) with ' ) + chalk.cyan( 'npm install -g rollup-watch' ) ); - }, - - WATCHER_MISSING_INPUT_OR_OUTPUT: function ( err ) { - console.error( chalk.red( 'must specify --input and --output when using rollup --watch' ) ); - } -}; - -module.exports = function handleError ( err ) { - var handler; - - if ( handler = handlers[ err && err.code ] ) { - handler( err ); - } else { - console.error( chalk.red( err.message || err ) ); - - if ( err.stack ) { - console.error( chalk.grey( err.stack ) ); - } - } - - console.error( 'Type ' + chalk.cyan( 'rollup --help' ) + ' for help, or visit https://github.com/rollup/rollup/wiki' ); - - process.exit( 1 ); -}; diff --git a/bin/rollup b/bin/rollup index 123f388..2e1b2a6 100755 --- a/bin/rollup +++ b/bin/rollup @@ -1,9 +1,868 @@ #!/usr/bin/env node +'use strict'; -var minimist = require( 'minimist' ), - command; +function _interopDefault (ex) { return (ex && (typeof ex === 'object') && 'default' in ex) ? ex['default'] : ex; } -command = minimist( process.argv.slice( 2 ), { +var require$$1 = require('path'); +var require$$1__default = _interopDefault(require$$1); +var require$$0 = _interopDefault(require('module')); +var sourceMapSupport = require('source-map-support'); + +function createCommonjsModule(fn, module) { + return module = { exports: {} }, fn(module, module.exports), module.exports; +} + +var index = createCommonjsModule(function (module) { +module.exports = function (args, opts) { + if (!opts) opts = {}; + + var flags = { bools : {}, strings : {}, unknownFn: null }; + + if (typeof opts['unknown'] === 'function') { + flags.unknownFn = opts['unknown']; + } + + if (typeof opts['boolean'] === 'boolean' && opts['boolean']) { + flags.allBools = true; + } else { + [].concat(opts['boolean']).filter(Boolean).forEach(function (key) { + flags.bools[key] = true; + }); + } + + var aliases = {}; + Object.keys(opts.alias || {}).forEach(function (key) { + aliases[key] = [].concat(opts.alias[key]); + aliases[key].forEach(function (x) { + aliases[x] = [key].concat(aliases[key].filter(function (y) { + return x !== y; + })); + }); + }); + + [].concat(opts.string).filter(Boolean).forEach(function (key) { + flags.strings[key] = true; + if (aliases[key]) { + flags.strings[aliases[key]] = true; + } + }); + + var defaults = opts['default'] || {}; + + var argv = { _ : [] }; + Object.keys(flags.bools).forEach(function (key) { + setArg(key, defaults[key] === undefined ? false : defaults[key]); + }); + + var notFlags = []; + + if (args.indexOf('--') !== -1) { + notFlags = args.slice(args.indexOf('--')+1); + args = args.slice(0, args.indexOf('--')); + } + + function argDefined(key, arg) { + return (flags.allBools && /^--[^=]+$/.test(arg)) || + flags.strings[key] || flags.bools[key] || aliases[key]; + } + + function setArg (key, val, arg) { + if (arg && flags.unknownFn && !argDefined(key, arg)) { + if (flags.unknownFn(arg) === false) return; + } + + var value = !flags.strings[key] && isNumber(val) + ? Number(val) : val + ; + setKey(argv, key.split('.'), value); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), value); + }); + } + + function setKey (obj, keys, value) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + if (o[key] === undefined) o[key] = {}; + o = o[key]; + }); + + var key = keys[keys.length - 1]; + if (o[key] === undefined || flags.bools[key] || typeof o[key] === 'boolean') { + o[key] = value; + } + else if (Array.isArray(o[key])) { + o[key].push(value); + } + else { + o[key] = [ o[key], value ]; + } + } + + function aliasIsBoolean(key) { + return aliases[key].some(function (x) { + return flags.bools[x]; + }); + } + + for (var i = 0; i < args.length; i++) { + var arg = args[i]; + + if (/^--.+=/.test(arg)) { + // Using [\s\S] instead of . because js doesn't support the + // 'dotall' regex modifier. See: + // http://stackoverflow.com/a/1068308/13216 + var m = arg.match(/^--([^=]+)=([\s\S]*)$/); + var key = m[1]; + var value = m[2]; + if (flags.bools[key]) { + value = value !== 'false'; + } + setArg(key, value, arg); + } + else if (/^--no-.+/.test(arg)) { + var key = arg.match(/^--no-(.+)/)[1]; + setArg(key, false, arg); + } + else if (/^--.+/.test(arg)) { + var key = arg.match(/^--(.+)/)[1]; + var next = args[i + 1]; + if (next !== undefined && !/^-/.test(next) + && !flags.bools[key] + && !flags.allBools + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, next, arg); + i++; + } + else if (/^(true|false)$/.test(next)) { + setArg(key, next === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + else if (/^-[^-]+/.test(arg)) { + var letters = arg.slice(1,-1).split(''); + + var broken = false; + for (var j = 0; j < letters.length; j++) { + var next = arg.slice(j+2); + + if (next === '-') { + setArg(letters[j], next, arg) + continue; + } + + if (/[A-Za-z]/.test(letters[j]) && /=/.test(next)) { + setArg(letters[j], next.split('=')[1], arg); + broken = true; + break; + } + + if (/[A-Za-z]/.test(letters[j]) + && /-?\d+(\.\d*)?(e-?\d+)?$/.test(next)) { + setArg(letters[j], next, arg); + broken = true; + break; + } + + if (letters[j+1] && letters[j+1].match(/\W/)) { + setArg(letters[j], arg.slice(j+2), arg); + broken = true; + break; + } + else { + setArg(letters[j], flags.strings[letters[j]] ? '' : true, arg); + } + } + + var key = arg.slice(-1)[0]; + if (!broken && key !== '-') { + if (args[i+1] && !/^(-|--)[^-]/.test(args[i+1]) + && !flags.bools[key] + && (aliases[key] ? !aliasIsBoolean(key) : true)) { + setArg(key, args[i+1], arg); + i++; + } + else if (args[i+1] && /true|false/.test(args[i+1])) { + setArg(key, args[i+1] === 'true', arg); + i++; + } + else { + setArg(key, flags.strings[key] ? '' : true, arg); + } + } + } + else { + if (!flags.unknownFn || flags.unknownFn(arg) !== false) { + argv._.push( + flags.strings['_'] || !isNumber(arg) ? arg : Number(arg) + ); + } + if (opts.stopEarly) { + argv._.push.apply(argv._, args.slice(i + 1)); + break; + } + } + } + + Object.keys(defaults).forEach(function (key) { + if (!hasKey(argv, key.split('.'))) { + setKey(argv, key.split('.'), defaults[key]); + + (aliases[key] || []).forEach(function (x) { + setKey(argv, x.split('.'), defaults[key]); + }); + } + }); + + if (opts['--']) { + argv['--'] = new Array(); + notFlags.forEach(function(key) { + argv['--'].push(key); + }); + } + else { + notFlags.forEach(function(key) { + argv._.push(key); + }); + } + + return argv; +}; + +function hasKey (obj, keys) { + var o = obj; + keys.slice(0,-1).forEach(function (key) { + o = (o[key] || {}); + }); + + var key = keys[keys.length - 1]; + return key in o; +} + +function isNumber (x) { + if (typeof x === 'number') return true; + if (/^0x[0-9a-f]+$/i.test(x)) return true; + return /^[-+]?(?:\d+(?:\.\d*)?|\.\d+)(e[-+]?\d+)?$/.test(x); +} +}); + +var minimist = (index && typeof index === 'object' && 'default' in index ? index['default'] : index); + +var help = "rollup version __VERSION__\n=====================================\n\nUsage: rollup [options] \n\nBasic options:\n\n-v, --version Show version number\n-h, --help Show this help message\n-c, --config Use this config file (if argument is used but value\n is unspecified, defaults to rollup.config.js)\n-w, --watch Watch files in bundle and rebuild on changes\n-i, --input Input (alternative to )\n-o, --output Output (if absent, prints to stdout)\n-f, --format [es6] Type of output (amd, cjs, es6, iife, umd)\n-e, --external Comma-separate list of module IDs to exclude\n-g, --globals Comma-separate list of `module ID:Global` pairs\n Any module IDs defined here are added to external\n-n, --name Name for UMD export\n-u, --id ID for AMD module (default is anonymous)\n-m, --sourcemap Generate sourcemap (`-m inline` for inline map)\n--no-strict Don't emit a `\"use strict\";` in the generated modules.\n--no-indent Don't indent result\n--environment Settings passed to config file (see example)\n--no-conflict Generate a noConflict method for UMD globals\n--intro Content to insert at top of bundle (inside wrapper)\n--outro Content to insert at end of bundle (inside wrapper)\n--banner Content to insert at top of bundle (outside wrapper)\n--footer Content to insert at end of bundle (outside wrapper)\n\nExamples:\n\n# use settings in config file\nrollup -c\n\n# in config file, process.env.INCLUDE_DEPS === 'true'\n# and process.env.BUILD === 'production'\nrollup -c --environment INCLUDE_DEPS,BUILD:production\n\n# create CommonJS bundle.js from src/main.js\nrollup --format=cjs --output=bundle.js -- src/main.js\n\n# create self-executing IIFE using `window.jQuery`\n# and `window._` as external globals\nrollup -f iife --globals jquery:jQuery,lodash:_ \\\n -i src/app.js -o build/app.js -m build/app.js.map\n\nNotes:\n\n* When piping to stdout, only inline sourcemaps are permitted\n\nFor more information visit https://github.com/rollup/rollup/wiki\n"; + +var version = "0.29.1"; + +var index$1 = createCommonjsModule(function (module) { +/* +relative require +*/'use strict'; + +var path = require$$1__default; +var Module = require$$0; + +var modules = {}; + +var getModule = function(dir) { + var rootPath = dir ? path.resolve(dir) : process.cwd(); + var rootName = path.join(rootPath, '@root'); + var root = modules[rootName]; + if (!root) { + root = new Module(rootName); + root.filename = rootName; + root.paths = Module._nodeModulePaths(rootPath); + modules[rootName] = root; + } + return root; +}; + +var requireRelative = function(requested, relativeTo) { + var root = getModule(relativeTo); + return root.require(requested); +}; + +requireRelative.resolve = function(requested, relativeTo) { + var root = getModule(relativeTo); + return Module._resolveFilename(requested, root); +}; + +module.exports = requireRelative; +}); + +var relative = (index$1 && typeof index$1 === 'object' && 'default' in index$1 ? index$1['default'] : index$1); + +var index$4 = createCommonjsModule(function (module) { +'use strict'; +var argv = process.argv; + +var terminator = argv.indexOf('--'); +var hasFlag = function (flag) { + flag = '--' + flag; + var pos = argv.indexOf(flag); + return pos !== -1 && (terminator !== -1 ? pos < terminator : true); +}; + +module.exports = (function () { + if ('FORCE_COLOR' in process.env) { + return true; + } + + if (hasFlag('no-color') || + hasFlag('no-colors') || + hasFlag('color=false')) { + return false; + } + + if (hasFlag('color') || + hasFlag('colors') || + hasFlag('color=true') || + hasFlag('color=always')) { + return true; + } + + if (process.stdout && !process.stdout.isTTY) { + return false; + } + + if (process.platform === 'win32') { + return true; + } + + if ('COLORTERM' in process.env) { + return true; + } + + if (process.env.TERM === 'dumb') { + return false; + } + + if (/^screen|^xterm|^vt100|color|ansi|cygwin|linux/i.test(process.env.TERM)) { + return true; + } + + return false; +})(); +}); + +var require$$0$1 = (index$4 && typeof index$4 === 'object' && 'default' in index$4 ? index$4['default'] : index$4); + +var index$6 = createCommonjsModule(function (module) { +'use strict'; +module.exports = function () { + return /[\u001b\u009b][[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-ORZcf-nqry=><]/g; +}; +}); + +var require$$0$2 = (index$6 && typeof index$6 === 'object' && 'default' in index$6 ? index$6['default'] : index$6); + +var index$5 = createCommonjsModule(function (module) { +'use strict'; +var ansiRegex = require$$0$2; +var re = new RegExp(ansiRegex().source); // remove the `g` flag +module.exports = re.test.bind(re); +}); + +var require$$1$1 = (index$5 && typeof index$5 === 'object' && 'default' in index$5 ? index$5['default'] : index$5); + +var index$7 = createCommonjsModule(function (module) { +'use strict'; +var ansiRegex = require$$0$2(); + +module.exports = function (str) { + return typeof str === 'string' ? str.replace(ansiRegex, '') : str; +}; +}); + +var require$$2 = (index$7 && typeof index$7 === 'object' && 'default' in index$7 ? index$7['default'] : index$7); + +var index$8 = createCommonjsModule(function (module) { +'use strict'; + +function assembleStyles () { + var styles = { + modifiers: { + reset: [0, 0], + bold: [1, 22], // 21 isn't widely supported and 22 does the same thing + dim: [2, 22], + italic: [3, 23], + underline: [4, 24], + inverse: [7, 27], + hidden: [8, 28], + strikethrough: [9, 29] + }, + colors: { + black: [30, 39], + red: [31, 39], + green: [32, 39], + yellow: [33, 39], + blue: [34, 39], + magenta: [35, 39], + cyan: [36, 39], + white: [37, 39], + gray: [90, 39] + }, + bgColors: { + bgBlack: [40, 49], + bgRed: [41, 49], + bgGreen: [42, 49], + bgYellow: [43, 49], + bgBlue: [44, 49], + bgMagenta: [45, 49], + bgCyan: [46, 49], + bgWhite: [47, 49] + } + }; + + // fix humans + styles.colors.grey = styles.colors.gray; + + Object.keys(styles).forEach(function (groupName) { + var group = styles[groupName]; + + Object.keys(group).forEach(function (styleName) { + var style = group[styleName]; + + styles[styleName] = group[styleName] = { + open: '\u001b[' + style[0] + 'm', + close: '\u001b[' + style[1] + 'm' + }; + }); + + Object.defineProperty(styles, groupName, { + value: group, + enumerable: false + }); + }); + + return styles; +} + +Object.defineProperty(module, 'exports', { + enumerable: true, + get: assembleStyles +}); +}); + +var require$$3 = (index$8 && typeof index$8 === 'object' && 'default' in index$8 ? index$8['default'] : index$8); + +var index$9 = createCommonjsModule(function (module) { +'use strict'; + +var matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g; + +module.exports = function (str) { + if (typeof str !== 'string') { + throw new TypeError('Expected a string'); + } + + return str.replace(matchOperatorsRe, '\\$&'); +}; +}); + +var require$$4 = (index$9 && typeof index$9 === 'object' && 'default' in index$9 ? index$9['default'] : index$9); + +var index$2 = createCommonjsModule(function (module) { +'use strict'; +var escapeStringRegexp = require$$4; +var ansiStyles = require$$3; +var stripAnsi = require$$2; +var hasAnsi = require$$1$1; +var supportsColor = require$$0$1; +var defineProps = Object.defineProperties; +var isSimpleWindowsTerm = process.platform === 'win32' && !/^xterm/i.test(process.env.TERM); + +function Chalk(options) { + // detect mode if not set manually + this.enabled = !options || options.enabled === undefined ? supportsColor : options.enabled; +} + +// use bright blue on Windows as the normal blue color is illegible +if (isSimpleWindowsTerm) { + ansiStyles.blue.open = '\u001b[94m'; +} + +var styles = (function () { + var ret = {}; + + Object.keys(ansiStyles).forEach(function (key) { + ansiStyles[key].closeRe = new RegExp(escapeStringRegexp(ansiStyles[key].close), 'g'); + + ret[key] = { + get: function () { + return build.call(this, this._styles.concat(key)); + } + }; + }); + + return ret; +})(); + +var proto = defineProps(function chalk() {}, styles); + +function build(_styles) { + var builder = function () { + return applyStyle.apply(builder, arguments); + }; + + builder._styles = _styles; + builder.enabled = this.enabled; + // __proto__ is used because we must return a function, but there is + // no way to create a function with a different prototype. + /* eslint-disable no-proto */ + builder.__proto__ = proto; + + return builder; +} + +function applyStyle() { + // support varags, but simply cast to string in case there's only one arg + var args = arguments; + var argsLen = args.length; + var str = argsLen !== 0 && String(arguments[0]); + + if (argsLen > 1) { + // don't slice `arguments`, it prevents v8 optimizations + for (var a = 1; a < argsLen; a++) { + str += ' ' + args[a]; + } + } + + if (!this.enabled || !str) { + return str; + } + + var nestedStyles = this._styles; + var i = nestedStyles.length; + + // Turns out that on Windows dimmed gray text becomes invisible in cmd.exe, + // see https://github.com/chalk/chalk/issues/58 + // If we're on Windows and we're dealing with a gray color, temporarily make 'dim' a noop. + var originalDim = ansiStyles.dim.open; + if (isSimpleWindowsTerm && (nestedStyles.indexOf('gray') !== -1 || nestedStyles.indexOf('grey') !== -1)) { + ansiStyles.dim.open = ''; + } + + while (i--) { + var code = ansiStyles[nestedStyles[i]]; + + // Replace any instances already present with a re-opening code + // otherwise only the part of the string until said closing code + // will be colored, and the rest will simply be 'plain'. + str = code.open + str.replace(code.closeRe, code.open) + code.close; + } + + // Reset the original 'dim' if we changed it to work around the Windows dimmed gray issue. + ansiStyles.dim.open = originalDim; + + return str; +} + +function init() { + var ret = {}; + + Object.keys(styles).forEach(function (name) { + ret[name] = { + get: function () { + return build.call(this, [name]); + } + }; + }); + + return ret; +} + +defineProps(Chalk.prototype, init()); + +module.exports = new Chalk(); +module.exports.styles = ansiStyles; +module.exports.hasColor = hasAnsi; +module.exports.stripColor = stripAnsi; +module.exports.supportsColor = supportsColor; +}); + +var red = index$2.red; +var cyan = index$2.cyan; +var grey = index$2.grey; + +function stderr$1 ( msg ) { + console.error( msg ); // eslint-disable-line no-console +} + +var handlers = { + MISSING_CONFIG: function () { + stderr$1( red( 'Config file must export an options object. See https://github.com/rollup/rollup/wiki/Command-Line-Interface#using-a-config-file' ) ); + }, + + MISSING_INPUT_OPTION: function () { + stderr$1( red( 'You must specify an --input (-i) option' ) ); + }, + + MISSING_OUTPUT_OPTION: function () { + stderr$1( red( 'You must specify an --output (-o) option when creating a file with a sourcemap' ) ); + }, + + MISSING_NAME: function () { + stderr$1( red( 'You must supply a name for UMD exports (e.g. `--name myModule`)' ) ); + }, + + PARSE_ERROR: function ( err ) { + stderr$1( red( ("Error parsing " + (err.file) + ": " + (err.message)) ) ); + }, + + ONE_AT_A_TIME: function () { + stderr$1( red( 'rollup can only bundle one file at a time' ) ); + }, + + DUPLICATE_IMPORT_OPTIONS: function () { + stderr$1( red( 'use --input, or pass input path as argument' ) ); + }, + + ROLLUP_WATCH_NOT_INSTALLED: function () { + stderr$1( red( 'rollup --watch depends on the rollup-watch package, which could not be found. You can install it globally (recommended) with ' ) + cyan( 'npm install -g rollup-watch' ) ); + }, + + WATCHER_MISSING_INPUT_OR_OUTPUT: function () { + stderr$1( red( 'must specify --input and --output when using rollup --watch' ) ); + } +}; + +function handleError ( err ) { + var handler = handlers[ err && err.code ]; + + if ( handler ) { + handler( err ); + } else { + stderr$1( red( err.message || err ) ); + + if ( err.stack ) { + stderr$1( grey( err.stack ) ); + } + } + + stderr$1( ("Type " + (cyan( 'rollup --help' )) + " for help, or visit https://github.com/rollup/rollup/wiki") ); + + process.exit( 1 ); +} + +var SOURCEMAPPING_URL = 'sourceMa'; +SOURCEMAPPING_URL += 'ppingURL'; + +var SOURCEMAPPING_URL$1 = SOURCEMAPPING_URL; + +var rollup = require( '../dist/rollup.js' ); sourceMapSupport.install(); + +// stderr to stderr to keep `rollup main.js > bundle.js` from breaking +var stderr = console.error.bind( console ); // eslint-disable-line no-console + +function runRollup ( command ) { + if ( command._.length > 1 ) { + handleError({ code: 'ONE_AT_A_TIME' }); + } + + if ( command._.length === 1 ) { + if ( command.input ) { + handleError({ code: 'DUPLICATE_IMPORT_OPTIONS' }); + } + + command.input = command._[0]; + } + + if ( command.environment ) { + command.environment.split( ',' ).forEach( function ( pair ) { + var index = pair.indexOf( ':' ); + if ( ~index ) { + process.env[ pair.slice( 0, index ) ] = pair.slice( index + 1 ); + } else { + process.env[ pair ] = true; + } + }); + } + + var config = command.config === true ? 'rollup.config.js' : command.config; + + if ( config ) { + config = require$$1.resolve( config ); + + rollup.rollup({ + entry: config, + onwarn: function ( message ) { + if ( /Treating .+ as external dependency/.test( message ) ) return; + stderr( message ); + } + }).then( function ( bundle ) { + var ref = bundle.generate({ + format: 'cjs' + }), code = ref.code; + + // temporarily override require + var defaultLoader = require.extensions[ '.js' ]; + require.extensions[ '.js' ] = function ( m, filename ) { + if ( filename === config ) { + m._compile( code, filename ); + } else { + defaultLoader( m, filename ); + } + }; + + try { + var options = require( require$$1.resolve( config ) ); + if ( Object.keys( options ).length === 0 ) { + handleError({ code: 'MISSING_CONFIG' }); + } + execute( options, command ); + require.extensions[ '.js' ] = defaultLoader; + } catch ( err ) { + handleError( err ); + } + }) + .catch( stderr ); + } else { + execute( {}, command ); + } +} + +var equivalents = { + banner: 'banner', + footer: 'footer', + format: 'format', + globals: 'globals', + id: 'moduleId', + indent: 'indent', + input: 'entry', + intro: 'intro', + name: 'moduleName', + output: 'dest', + outro: 'outro', + sourcemap: 'sourceMap', + treeshake: 'treeshake' +}; + +function execute ( options, command ) { + var external = ( options.external || [] ) + .concat( command.external ? command.external.split( ',' ) : [] ); + + if ( command.globals ) { + var globals = Object.create( null ); + + command.globals.split( ',' ).forEach( function ( str ) { + var names = str.split( ':' ); + globals[ names[0] ] = names[1]; + + // Add missing Module IDs to external. + if ( external.indexOf( names[0] ) === -1 ) { + external.push( names[0] ); + } + }); + + command.globals = globals; + } + + options.onwarn = options.onwarn || stderr; + + options.external = external; + + options.noConflict = command.conflict === false; + delete command.conflict; + + // Use any options passed through the CLI as overrides. + Object.keys( equivalents ).forEach( function ( cliOption ) { + if ( command.hasOwnProperty( cliOption ) ) { + options[ equivalents[ cliOption ] ] = command[ cliOption ]; + } + }); + + try { + if ( command.watch ) { + if ( !options.entry || ( !options.dest && !options.targets ) ) { + handleError({ code: 'WATCHER_MISSING_INPUT_OR_OUTPUT' }); + } + + try { + var watch = relative( 'rollup-watch', process.cwd() ); + var watcher = watch( rollup, options ); + + watcher.on( 'event', function ( event ) { + switch ( event.code ) { + case 'STARTING': + stderr( 'checking rollup-watch version...' ); + break; + + case 'BUILD_START': + stderr( 'bundling...' ); + break; + + case 'BUILD_END': + stderr( 'bundled in ' + event.duration + 'ms. Watching for changes...' ); + break; + + default: + stderr( 'unknown event', event ); + } + }); + } catch ( err ) { + if ( err.code === 'MODULE_NOT_FOUND' ) { + err.code = 'ROLLUP_WATCH_NOT_INSTALLED'; + } + + handleError( err ); + } + } else { + bundle( options ).catch( handleError ); + } + } catch ( err ) { + handleError( err ); + } +} + +function clone ( object ) { + return assign( {}, object ); +} + +function assign ( target, source ) { + Object.keys( source ).forEach( function ( key ) { + target[ key ] = source[ key ]; + }); + return target; +} + +function bundle ( options ) { + if ( !options.entry ) { + handleError({ code: 'MISSING_INPUT_OPTION' }); + } + + return rollup.rollup( options ).then( function ( bundle ) { + if ( options.dest ) { + return bundle.write( options ); + } + + if ( options.targets ) { + var result = null; + + options.targets.forEach( function ( target ) { + result = bundle.write( assign( clone( options ), target ) ); + }); + + return result; + } + + if ( options.sourceMap && options.sourceMap !== 'inline' ) { + handleError({ code: 'MISSING_OUTPUT_OPTION' }); + } + + var ref = bundle.generate( options ), code = ref.code, map = ref.map; + + if ( options.sourceMap === 'inline' ) { + code += "\n//# " + SOURCEMAPPING_URL$1 + "=" + (map.toUrl()); + } + + process.stdout.write( code ); + }); +} + +var command = minimist( process.argv.slice( 2 ), { alias: { // Aliases strict: 'useStrict', @@ -26,13 +885,13 @@ command = minimist( process.argv.slice( 2 ), { }); if ( command.help || ( process.argv.length <= 2 && process.stdin.isTTY ) ) { - require( './showHelp' )(); + console.log( ("\n" + (help.replace('__VERSION__', version)) + "\n") ); // eslint-disable-line no-console } else if ( command.version ) { - console.log( 'rollup version ' + require( '../package.json' ).version ); + console.log( ("rollup version " + version) ); // eslint-disable-line no-console } else { - require( './runRollup' )( command ); -} + runRollup( command ); +} \ No newline at end of file diff --git a/bin/showHelp.js b/bin/showHelp.js deleted file mode 100644 index 1cc19b6..0000000 --- a/bin/showHelp.js +++ /dev/null @@ -1,13 +0,0 @@ -var fs = require( 'fs' ); -var path = require( 'path' ); - -module.exports = function () { - fs.readFile( path.join( __dirname, 'help.md' ), function ( err, result ) { - var help; - - if ( err ) throw err; - - help = result.toString().replace( '<%= version %>', require( '../package.json' ).version ); - console.log( '\n' + help + '\n' ); - }); -}; diff --git a/bin/src/handleError.js b/bin/src/handleError.js new file mode 100644 index 0000000..ba17d0c --- /dev/null +++ b/bin/src/handleError.js @@ -0,0 +1,61 @@ +import * as chalk from 'chalk'; + +function stderr ( msg ) { + console.error( msg ); // eslint-disable-line no-console +} + +const handlers = { + MISSING_CONFIG: () => { + stderr( chalk.red( 'Config file must export an options object. See https://github.com/rollup/rollup/wiki/Command-Line-Interface#using-a-config-file' ) ); + }, + + MISSING_INPUT_OPTION: () => { + stderr( chalk.red( 'You must specify an --input (-i) option' ) ); + }, + + MISSING_OUTPUT_OPTION: () => { + stderr( chalk.red( 'You must specify an --output (-o) option when creating a file with a sourcemap' ) ); + }, + + MISSING_NAME: () => { + stderr( chalk.red( 'You must supply a name for UMD exports (e.g. `--name myModule`)' ) ); + }, + + PARSE_ERROR: err => { + stderr( chalk.red( `Error parsing ${err.file}: ${err.message}` ) ); + }, + + ONE_AT_A_TIME: () => { + stderr( chalk.red( 'rollup can only bundle one file at a time' ) ); + }, + + DUPLICATE_IMPORT_OPTIONS: () => { + stderr( chalk.red( 'use --input, or pass input path as argument' ) ); + }, + + ROLLUP_WATCH_NOT_INSTALLED: () => { + stderr( chalk.red( 'rollup --watch depends on the rollup-watch package, which could not be found. You can install it globally (recommended) with ' ) + chalk.cyan( 'npm install -g rollup-watch' ) ); + }, + + WATCHER_MISSING_INPUT_OR_OUTPUT: () => { + stderr( chalk.red( 'must specify --input and --output when using rollup --watch' ) ); + } +}; + +export default function handleError ( err ) { + const handler = handlers[ err && err.code ]; + + if ( handler ) { + handler( err ); + } else { + stderr( chalk.red( err.message || err ) ); + + if ( err.stack ) { + stderr( chalk.grey( err.stack ) ); + } + } + + stderr( `Type ${chalk.cyan( 'rollup --help' )} for help, or visit https://github.com/rollup/rollup/wiki` ); + + process.exit( 1 ); +} diff --git a/bin/help.md b/bin/src/help.md similarity index 98% rename from bin/help.md rename to bin/src/help.md index 7b02ed1..cf2ef8b 100644 --- a/bin/help.md +++ b/bin/src/help.md @@ -1,4 +1,4 @@ -rollup version <%= version %> +rollup version __VERSION__ ===================================== Usage: rollup [options] diff --git a/bin/src/index.js b/bin/src/index.js new file mode 100644 index 0000000..1b8f1e6 --- /dev/null +++ b/bin/src/index.js @@ -0,0 +1,38 @@ +import minimist from 'minimist'; +import help from './help.md'; +import { version } from '../../package.json'; +import runRollup from './runRollup'; + +const command = minimist( process.argv.slice( 2 ), { + alias: { + // Aliases + strict: 'useStrict', + + // Short options + c: 'config', + d: 'indent', + e: 'external', + f: 'format', + g: 'globals', + h: 'help', + i: 'input', + m: 'sourcemap', + n: 'name', + o: 'output', + u: 'id', + v: 'version', + w: 'watch' + } +}); + +if ( command.help || ( process.argv.length <= 2 && process.stdin.isTTY ) ) { + console.log( `\n${help.replace('__VERSION__', version)}\n` ); // eslint-disable-line no-console +} + +else if ( command.version ) { + console.log( `rollup version ${version}` ); // eslint-disable-line no-console +} + +else { + runRollup( command ); +} diff --git a/bin/runRollup.js b/bin/src/runRollup.js similarity index 61% rename from bin/runRollup.js rename to bin/src/runRollup.js index 2009ff4..aeff331 100644 --- a/bin/runRollup.js +++ b/bin/src/runRollup.js @@ -1,15 +1,17 @@ -require( 'source-map-support' ).install(); +import { resolve } from 'path'; +import relative from 'require-relative'; +import handleError from './handleError'; +import SOURCEMAPPING_URL from './sourceMappingURL.js'; -var path = require( 'path' ); -var relative = require( 'require-relative' ); -var handleError = require( './handleError' ); -var chalk = require( 'chalk' ); -var rollup = require( '../' ); +const rollup = require( '../dist/rollup.js' ); // TODO make this an import, somehow -// log to stderr to keep `rollup main.js > bundle.js` from breaking -var log = console.error.bind(console); +import { install as installSourcemapSupport } from 'source-map-support'; +installSourcemapSupport(); -module.exports = function ( command ) { +// stderr to stderr to keep `rollup main.js > bundle.js` from breaking +const stderr = console.error.bind( console ); // eslint-disable-line no-console + +export default function runRollup ( command ) { if ( command._.length > 1 ) { handleError({ code: 'ONE_AT_A_TIME' }); } @@ -23,8 +25,8 @@ module.exports = function ( command ) { } if ( command.environment ) { - command.environment.split( ',' ).forEach( function ( pair ) { - var index = pair.indexOf( ':' ); + command.environment.split( ',' ).forEach( pair => { + const index = pair.indexOf( ':' ); if ( ~index ) { process.env[ pair.slice( 0, index ) ] = pair.slice( index + 1 ); } else { @@ -33,25 +35,25 @@ module.exports = function ( command ) { }); } - var config = command.config === true ? 'rollup.config.js' : command.config; + let config = command.config === true ? 'rollup.config.js' : command.config; if ( config ) { - config = path.resolve( config ); + config = resolve( config ); rollup.rollup({ entry: config, - onwarn: function ( message ) { + onwarn: message => { if ( /Treating .+ as external dependency/.test( message ) ) return; - log( message ); + stderr( message ); } - }).then( function ( bundle ) { - var code = bundle.generate({ + }).then( bundle => { + const { code } = bundle.generate({ format: 'cjs' - }).code; + }); // temporarily override require var defaultLoader = require.extensions[ '.js' ]; - require.extensions[ '.js' ] = function ( m, filename ) { + require.extensions[ '.js' ] = ( m, filename ) => { if ( filename === config ) { m._compile( code, filename ); } else { @@ -60,25 +62,23 @@ module.exports = function ( command ) { }; try { - var options = require( path.resolve( config ) ); + const options = require( resolve( config ) ); if ( Object.keys( options ).length === 0 ) { handleError({ code: 'MISSING_CONFIG' }); } + execute( options, command ); + require.extensions[ '.js' ] = defaultLoader; } catch ( err ) { handleError( err ); } - - execute( options, command ); - - require.extensions[ '.js' ] = defaultLoader; }) - .catch(log); + .catch( stderr ); } else { execute( {}, command ); } -}; +} -var equivalents = { +const equivalents = { banner: 'banner', footer: 'footer', format: 'format', @@ -95,14 +95,14 @@ var equivalents = { }; function execute ( options, command ) { - var external = ( options.external || [] ) + let external = ( options.external || [] ) .concat( command.external ? command.external.split( ',' ) : [] ); if ( command.globals ) { - var globals = Object.create( null ); + let globals = Object.create( null ); - command.globals.split( ',' ).forEach(function ( str ) { - var names = str.split( ':' ); + command.globals.split( ',' ).forEach( str => { + const names = str.split( ':' ); globals[ names[0] ] = names[1]; // Add missing Module IDs to external. @@ -114,7 +114,7 @@ function execute ( options, command ) { command.globals = globals; } - options.onwarn = options.onwarn || log; + options.onwarn = options.onwarn || stderr; options.external = external; @@ -122,7 +122,7 @@ function execute ( options, command ) { delete command.conflict; // Use any options passed through the CLI as overrides. - Object.keys( equivalents ).forEach( function ( cliOption ) { + Object.keys( equivalents ).forEach( cliOption => { if ( command.hasOwnProperty( cliOption ) ) { options[ equivalents[ cliOption ] ] = command[ cliOption ]; } @@ -135,25 +135,25 @@ function execute ( options, command ) { } try { - var watch = relative( 'rollup-watch', process.cwd() ); - var watcher = watch( rollup, options ); + const watch = relative( 'rollup-watch', process.cwd() ); + const watcher = watch( rollup, options ); - watcher.on( 'event', function ( event ) { + watcher.on( 'event', event => { switch ( event.code ) { case 'STARTING': - console.error( 'checking rollup-watch version...' ); + stderr( 'checking rollup-watch version...' ); break; case 'BUILD_START': - console.error( 'bundling...' ); + stderr( 'bundling...' ); break; case 'BUILD_END': - console.error( 'bundled in ' + event.duration + 'ms. Watching for changes...' ); + stderr( 'bundled in ' + event.duration + 'ms. Watching for changes...' ); break; default: - console.error( 'unknown event', event ); + stderr( 'unknown event', event ); } }); } catch ( err ) { @@ -176,7 +176,7 @@ function clone ( object ) { } function assign ( target, source ) { - Object.keys( source ).forEach( function ( key ) { + Object.keys( source ).forEach( key => { target[ key ] = source[ key ]; }); return target; @@ -187,15 +187,15 @@ function bundle ( options ) { handleError({ code: 'MISSING_INPUT_OPTION' }); } - return rollup.rollup( options ).then( function ( bundle ) { + return rollup.rollup( options ).then( bundle => { if ( options.dest ) { return bundle.write( options ); } if ( options.targets ) { - var result = null; + let result = null; - options.targets.forEach( function ( target ) { + options.targets.forEach( target => { result = bundle.write( assign( clone( options ), target ) ); }); @@ -206,13 +206,10 @@ function bundle ( options ) { handleError({ code: 'MISSING_OUTPUT_OPTION' }); } - var result = bundle.generate( options ); - - var code = result.code, - map = result.map; + let { code, map } = bundle.generate( options ); if ( options.sourceMap === 'inline' ) { - code += '\n//# sourceMappingURL=' + map.toUrl(); + code += `\n//# ${SOURCEMAPPING_URL}=${map.toUrl()}`; } process.stdout.write( code ); diff --git a/bin/src/sourceMappingUrl.js b/bin/src/sourceMappingUrl.js new file mode 100644 index 0000000..e7c4265 --- /dev/null +++ b/bin/src/sourceMappingUrl.js @@ -0,0 +1,4 @@ +let SOURCEMAPPING_URL = 'sourceMa'; +SOURCEMAPPING_URL += 'ppingURL'; + +export default SOURCEMAPPING_URL; diff --git a/package.json b/package.json index 67b23b4..6e2f61d 100644 --- a/package.json +++ b/package.json @@ -8,13 +8,14 @@ "rollup": "./bin/rollup" }, "scripts": { - "pretest": "npm run build", - "test": "mocha --compilers js:buble/register", + "pretest": "npm run build && npm run build:cli", + "test": "mocha", "pretest-coverage": "npm run build", "test-coverage": "rm -rf coverage/* && istanbul cover --report json node_modules/.bin/_mocha -- -u exports -R spec test/test.js", "posttest-coverage": "remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped.json -b dist && remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped.lcov -t lcovonly -b dist && remap-istanbul -i coverage/coverage-final.json -o coverage/coverage-remapped -t html -b dist", "ci": "npm run test-coverage && codecov < coverage/coverage-remapped.lcov", "build": "git rev-parse HEAD > .commithash && rollup -c -o dist/rollup.js", + "build:cli": "rollup -c rollup.config.cli.js", "build:browser": "git rev-parse HEAD > .commithash && rollup -c rollup.config.browser.js -o dist/rollup.browser.js", "prepublish": "npm run lint && npm test && npm run build:browser", "lint": "eslint src browser" @@ -51,8 +52,9 @@ "magic-string": "^0.15.1", "mocha": "^2.3.3", "remap-istanbul": "^0.5.1", - "rollup": "^0.26.2", + "rollup": "^0.29.1", "rollup-plugin-buble": "^0.6.0", + "rollup-plugin-commonjs": "^3.0.0", "rollup-plugin-node-resolve": "^1.5.0", "rollup-plugin-replace": "^1.0.1", "sander": "^0.5.0", diff --git a/rollup.config.cli.js b/rollup.config.cli.js new file mode 100644 index 0000000..4ae9f11 --- /dev/null +++ b/rollup.config.cli.js @@ -0,0 +1,29 @@ +import buble from 'rollup-plugin-buble'; +import json from 'rollup-plugin-json'; +import string from 'rollup-plugin-string'; +import nodeResolve from 'rollup-plugin-node-resolve'; +import commonjs from 'rollup-plugin-commonjs'; + +export default { + entry: 'bin/src/index.js', + dest: 'bin/rollup', + format: 'cjs', + banner: '#!/usr/bin/env node', + plugins: [ + string({ extensions: [ '.md' ] }), + json(), + buble(), + commonjs({ + include: 'node_modules/**', + namedExports: { 'chalk': [ 'red', 'cyan', 'grey' ] } + }), + nodeResolve({ + main: true + }) + ], + external: [ + 'path', + 'fs', + 'source-map-support' + ] +}; diff --git a/rollup.config.js b/rollup.config.js index 521d614..e7996f4 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,6 +1,6 @@ import { readFileSync } from 'fs'; import buble from 'rollup-plugin-buble'; -import npm from 'rollup-plugin-node-resolve'; +import nodeResolve from 'rollup-plugin-node-resolve'; import replace from 'rollup-plugin-replace'; var pkg = JSON.parse( readFileSync( 'package.json', 'utf-8' ) ); @@ -26,7 +26,7 @@ export default { include: [ 'src/**', 'node_modules/acorn/**' ] }), - npm({ + nodeResolve({ jsnext: true }), diff --git a/test/mocha.opts b/test/mocha.opts new file mode 100644 index 0000000..078771e --- /dev/null +++ b/test/mocha.opts @@ -0,0 +1 @@ +--compilers js:buble/register