Browse Source

Merge pull request #95 from rollup/non-jsnextmain-resolver

allow imports of individual files from external modules
gh-109
Rich Harris 9 years ago
parent
commit
0f41108ace
  1. 4
      browser/sander.js
  2. 42
      src/utils/resolveId.js
  3. 4
      test/function/import-from-external-subdirectory/_config.js
  4. 5
      test/function/import-from-external-subdirectory/main.js

4
browser/sander.js

@ -1,3 +1,7 @@
export function readdirSync () {
throw new Error( 'Cannot use sander.readdirSync inside browser' );
}
export function readFile () {
throw new Error( 'Cannot use sander.readFile inside browser' );
}

42
src/utils/resolveId.js

@ -1,5 +1,14 @@
import { absolutePath, dirname, isAbsolute, resolve } from './path';
import { readFileSync } from 'sander';
import { readdirSync, readFileSync } from 'sander';
function dirExists ( dir ) {
try {
readdirSync( dir );
return true;
} catch ( err ) {
return false;
}
}
export function defaultResolver ( importee, importer, options ) {
// absolute paths are left untouched
@ -10,8 +19,10 @@ export function defaultResolver ( importee, importer, options ) {
// we try to resolve external modules
if ( importee[0] !== '.' ) {
const [ id ] = importee.split( /[\/\\]/ );
// unless we want to keep it external, that is
if ( ~options.external.indexOf( importee ) ) return null;
if ( ~options.external.indexOf( id ) ) return null;
return options.resolveExternal( importee, importer, options );
}
@ -24,29 +35,32 @@ export function defaultExternalResolver ( id, importer ) {
const root = absolutePath.exec( importer )[0];
let dir = dirname( importer );
while ( dir !== root && dir !== "." ) {
const pkgPath = resolve( dir, 'node_modules', id, 'package.json' );
let pkgJson;
// `foo` should use jsnext:main, but `foo/src/bar` shouldn't
const parts = id.split( /[\/\\]/ );
try {
pkgJson = readFileSync( pkgPath ).toString();
} catch ( err ) {
// noop
}
while ( dir !== root && dir !== '.' ) {
const modulePath = resolve( dir, 'node_modules', parts[0] );
if ( dirExists( modulePath ) ) {
// `foo/src/bar`
if ( parts.length > 1 ) {
return resolve( modulePath, ...parts.slice( 1 ) ).replace( /\.js$/, '' ) + '.js';
}
if ( pkgJson ) {
// `foo`
const pkgPath = resolve( modulePath, 'package.json' );
let pkg;
try {
pkg = JSON.parse( pkgJson );
pkg = JSON.parse( readFileSync( pkgPath ).toString() );
} catch ( err ) {
throw new Error( `Malformed JSON: ${pkgPath}` );
throw new Error( `Missing or malformed package.json: ${modulePath}` );
}
const main = pkg[ 'jsnext:main' ];
if ( !main ) {
throw new Error( `Package ${id} does not have a jsnext:main field, and so cannot be included in your rollup. Try adding it as an external module instead (e.g. options.external = ['${id}']). See https://github.com/rollup/rollup/wiki/jsnext:main for more info` );
throw new Error( `Package ${id} (imported by ${importer}) does not have a jsnext:main field, and so cannot be included in your rollup. Try adding it as an external module instead (e.g. options.external = ['${id}']). See https://github.com/rollup/rollup/wiki/jsnext:main for more info` );
}
return resolve( dirname( pkgPath ), main ).replace( /\.js$/, '' ) + '.js';

4
test/function/import-from-external-subdirectory/_config.js

@ -0,0 +1,4 @@
module.exports = {
description: 'default resolver imports from a subdirectory of an external module',
babel: true
};

5
test/function/import-from-external-subdirectory/main.js

@ -0,0 +1,5 @@
// this test is brittle, it relies on this dependency continuing
// to be structured in a certain way
import btoa from 'magic-string/src/utils/btoa';
assert.equal( btoa( 'it works' ), new Buffer( 'it works' ).toString( 'base64' ) );
Loading…
Cancel
Save