diff --git a/README.md b/README.md index 5b4237c..fdbc700 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,10 @@ This is not a trivial task. There are almost certainly a great many complex edge The example below is aspirational. It isn't yet implemented - it exists in the name of [README driven development](http://tom.preston-werner.com/2010/08/23/readme-driven-development.html). ```js -rollup.rollup( 'app.js', { +rollup.rollup({ + // The bundle's starting point + entry: 'app.js', + // Override the default path resolution resolvePath: function ( importee, importer ) { // return a string or a falsy value - if falsy, diff --git a/bin/runRollup.js b/bin/runRollup.js index e33ef4c..585c1fc 100644 --- a/bin/runRollup.js +++ b/bin/runRollup.js @@ -33,13 +33,16 @@ function bundle ( options, method ) { handleError({ code: 'MISSING_INPUT_OPTION' }); } - return rollup.rollup( options.input ).then( function ( bundle ) { + return rollup.rollup({ + entry: options.input + }).then( function ( bundle ) { var generateOptions = { + dest: options.output, format: options.format }; if ( options.output ) { - return bundle.write( options.output, generateOptions ); + return bundle.write( generateOptions ); } if ( options.sourcemap && options.sourcemap !== 'inline' ) { diff --git a/gobblefile.js b/gobblefile.js index cda2c18..fe4cde5 100644 --- a/gobblefile.js +++ b/gobblefile.js @@ -1,6 +1,6 @@ var gobble = require( 'gobble' ); -var selfhost = 1; +var selfhost = 0; module.exports = selfhost ? gobble( 'src' ) diff --git a/src/Bundle.js b/src/Bundle.js index 151f2a4..db13779 100644 --- a/src/Bundle.js +++ b/src/Bundle.js @@ -6,7 +6,9 @@ import Module from './Module'; import ExternalModule from './ExternalModule'; import finalisers from './finalisers/index'; import makeLegalIdentifier from './utils/makeLegalIdentifier'; +import ensureArray from './utils/ensureArray'; import { defaultResolver } from './utils/resolvePath'; +import { defaultLoader } from './utils/load'; function badExports ( option, keys ) { throw new Error( `'${option}' was specified for options.exports, but entry module has following exports: ${keys.join(', ')}` ); @@ -18,6 +20,15 @@ export default class Bundle { this.base = dirname( this.entryPath ); this.resolvePath = options.resolvePath || defaultResolver; + this.load = options.load || defaultLoader; + + this.resolvePathOptions = { + external: ensureArray( options.external ) + }; + + this.loadOptions = { + transform: ensureArray( options.transform ) + }; this.entryModule = null; this.modulePromises = {}; @@ -28,7 +39,7 @@ export default class Bundle { } fetchModule ( importee, importer ) { - return Promise.resolve( importer === null ? importee : this.resolvePath( importee, importer ) ) + return Promise.resolve( importer === null ? importee : this.resolvePath( importee, importer, this.resolvePathOptions ) ) .then( path => { if ( !path ) { // external module @@ -42,7 +53,7 @@ export default class Bundle { } if ( !has( this.modulePromises, path ) ) { - this.modulePromises[ path ] = readFile( path, { encoding: 'utf-8' }) + this.modulePromises[ path ] = Promise.resolve( this.load( path, this.loadOptions ) ) .then( source => { const module = new Module({ path, diff --git a/src/rollup.js b/src/rollup.js index d182df3..09baf6f 100644 --- a/src/rollup.js +++ b/src/rollup.js @@ -5,16 +5,21 @@ import Bundle from './Bundle'; let SOURCEMAPPING_URL = 'sourceMa'; SOURCEMAPPING_URL += 'ppingURL'; -export function rollup ( entry, options = {} ) { - const bundle = new Bundle({ - entry, - resolvePath: options.resolvePath - }); +export function rollup ( options ) { + if ( !options || !options.entry ) { + throw new Error( 'You must supply options.entry to rollup' ); + } + + const bundle = new Bundle( options ); return bundle.build().then( () => { return { generate: options => bundle.generate( options ), - write: ( dest, options = {} ) => { + write: options => { + if ( !options || !options.dest ) { + throw new Error( 'You must supply options.dest to bundle.write' ); + } + let { code, map } = bundle.generate({ dest, format: options.format, diff --git a/src/utils/ensureArray.js b/src/utils/ensureArray.js new file mode 100644 index 0000000..2669345 --- /dev/null +++ b/src/utils/ensureArray.js @@ -0,0 +1,5 @@ +export default function ensureArray ( thing ) { + if ( Array.isArray( thing ) ) return thing; + if ( thing == undefined ) return []; + return [ thing ]; +} diff --git a/src/utils/load.js b/src/utils/load.js new file mode 100644 index 0000000..1d8d826 --- /dev/null +++ b/src/utils/load.js @@ -0,0 +1,6 @@ +import { readFileSync } from 'sander'; + +export function defaultLoader ( path, options ) { + // TODO support plugins and transformers? + return readFileSync( path, { encoding: 'utf-8' }); +} diff --git a/src/utils/resolvePath.js b/src/utils/resolvePath.js index 4b07512..08de65d 100644 --- a/src/utils/resolvePath.js +++ b/src/utils/resolvePath.js @@ -1,11 +1,22 @@ import { dirname, isAbsolute, resolve } from 'path'; -export function defaultResolver ( importee, importer ) { +export function defaultResolver ( importee, importer, options ) { // absolute paths are left untouched if ( isAbsolute( importee ) ) return importee; - // external modules stay external - if ( importee[0] !== '.' ) return false; + // we try to resolve external modules + if ( importee[0] !== '.' ) { + // unless we want to keep it external, that is + if ( ~options.external.indexOf( importee ) ) return null; + + return resolveExternal( importee, importer, options ); + } return resolve( dirname( importer ), importee ).replace( /\.js$/, '' ) + '.js'; -} \ No newline at end of file +} + +function resolveExternal ( id, importer, options ) { + // for now, only node_modules is supported, and only jsnext:main + + throw new Error( "TODO" ); +} diff --git a/test/function/allows-external-modules-from-nested-module/_config.js b/test/function/allows-external-modules-from-nested-module/_config.js index 918a11a..d0c980e 100644 --- a/test/function/allows-external-modules-from-nested-module/_config.js +++ b/test/function/allows-external-modules-from-nested-module/_config.js @@ -1,3 +1,6 @@ module.exports = { - description: 'imports external modules from nested internal modules' + description: 'imports external modules from nested internal modules', + options: { + external: [ 'path' ] + } }; diff --git a/test/function/import-default-from-external/_config.js b/test/function/import-default-from-external/_config.js index d2d3885..98651b7 100644 --- a/test/function/import-default-from-external/_config.js +++ b/test/function/import-default-from-external/_config.js @@ -1,3 +1,6 @@ module.exports = { - description: 'imports default from external module' -}; \ No newline at end of file + description: 'imports default from external module', + options: { + external: [ 'path' ] + } +}; diff --git a/test/function/import-named-from-external/_config.js b/test/function/import-named-from-external/_config.js index 243412e..cab932b 100644 --- a/test/function/import-named-from-external/_config.js +++ b/test/function/import-named-from-external/_config.js @@ -1,3 +1,6 @@ module.exports = { - description: 'imports names from an external module' -}; \ No newline at end of file + description: 'imports names from an external module', + options: { + external: [ 'path' ] + } +}; diff --git a/test/function/import-namespace-from-external-module-renamed/_config.js b/test/function/import-namespace-from-external-module-renamed/_config.js index 86394b3..4cb00de 100644 --- a/test/function/import-namespace-from-external-module-renamed/_config.js +++ b/test/function/import-namespace-from-external-module-renamed/_config.js @@ -1,3 +1,6 @@ module.exports = { - description: 'imports a namespace from an external module and renames it' + description: 'imports a namespace from an external module and renames it', + options: { + external: [ 'path' ] + } }; diff --git a/test/function/import-namespace-from-external-module/_config.js b/test/function/import-namespace-from-external-module/_config.js index f107139..3704e5c 100644 --- a/test/function/import-namespace-from-external-module/_config.js +++ b/test/function/import-namespace-from-external-module/_config.js @@ -1,3 +1,6 @@ module.exports = { - description: 'imports a namespace from an external module' -}; \ No newline at end of file + description: 'imports a namespace from an external module', + options: { + external: [ 'path' ] + } +}; diff --git a/test/function/imports-are-deconflicted-b/_config.js b/test/function/imports-are-deconflicted-b/_config.js index a7c1041..eceba93 100644 --- a/test/function/imports-are-deconflicted-b/_config.js +++ b/test/function/imports-are-deconflicted-b/_config.js @@ -1,3 +1,6 @@ module.exports = { - description: 'deconflicts imports (redux)' + description: 'deconflicts imports (redux)', + options: { + external: [ 'path' ] + } }; diff --git a/test/function/imports-are-deconflicted/_config.js b/test/function/imports-are-deconflicted/_config.js index 49dbfd8..345f6b8 100644 --- a/test/function/imports-are-deconflicted/_config.js +++ b/test/function/imports-are-deconflicted/_config.js @@ -1,3 +1,6 @@ module.exports = { - description: 'deconflicts imports' + description: 'deconflicts imports', + options: { + external: [ 'path' ] + } }; diff --git a/test/function/shadowed-external-export/_config.js b/test/function/shadowed-external-export/_config.js index b39af37..2a744dc 100644 --- a/test/function/shadowed-external-export/_config.js +++ b/test/function/shadowed-external-export/_config.js @@ -1,3 +1,6 @@ module.exports = { - description: 'external modules are not shadowed' + description: 'external modules are not shadowed', + options: { + external: [ 'path' ] + } }; diff --git a/test/test.js b/test/test.js index 11ef072..5f71f6e 100644 --- a/test/test.js +++ b/test/test.js @@ -54,7 +54,11 @@ describe( 'rollup', function () { } ( config.skip ? it.skip : config.solo ? it.only : it )( dir, function () { - return rollup.rollup( FUNCTION + '/' + dir + '/main.js', extend( {}, config.options ) ) + var options = extend( {}, config.options, { + entry: FUNCTION + '/' + dir + '/main.js' + }) + + return rollup.rollup( options ) .then( function ( bundle ) { var unintendedError; @@ -142,7 +146,11 @@ describe( 'rollup', function () { config = { description: dir }; } - var bundlePromise = rollup.rollup( FORM + '/' + dir + '/main.js', extend( {}, config.options ) ); + var options = extend( {}, config.options, { + entry: FORM + '/' + dir + '/main.js' + }); + + var bundlePromise = rollup.rollup( options ); PROFILES.forEach( function ( profile ) { ( config.skip ? it.skip : config.solo ? it.only : it )( 'generates ' + profile.format, function () { @@ -172,7 +180,11 @@ describe( 'rollup', function () { describe( dir, function () { var config = require( SOURCEMAPS + '/' + dir + '/_config' ); - var bundlePromise = rollup.rollup( SOURCEMAPS + '/' + dir + '/main.js', extend( {}, config.options ) ); + var options = extend( {}, config.options, { + entry: SOURCEMAPS + '/' + dir + '/main.js' + }); + + var bundlePromise = rollup.rollup( options ); PROFILES.forEach( function ( profile ) { ( config.skip ? it.skip : config.solo ? it.only : it )( 'generates ' + profile.format, function () {