ember-introjs
Version:
An Ember Component for intro.js
194 lines (151 loc) • 5.91 kB
JavaScript
import { statSync } from 'fs';
import { dirname, extname, resolve, sep } from 'path';
import { sync as nodeResolveSync } from 'resolve';
import { createFilter } from 'rollup-pluginutils';
import { EXTERNAL, PREFIX, HELPERS_ID, HELPERS } from './helpers.js';
import defaultResolver from './defaultResolver.js';
import { checkFirstpass, checkEsModule, transformCommonjs } from './transform.js';
import { getName } from './utils.js';
function getCandidatesForExtension ( resolved, extension ) {
return [
resolved + extension,
resolved + `${sep}index${extension}`
];
}
function getCandidates ( resolved, extensions ) {
return extensions.reduce(
( paths, extension ) => paths.concat( getCandidatesForExtension ( resolved, extension ) ),
[resolved]
);
}
// Return the first non-falsy result from an array of
// maybe-sync, maybe-promise-returning functions
function first ( candidates ) {
return function ( ...args ) {
return candidates.reduce( ( promise, candidate ) => {
return promise.then( result => result != null ?
result :
Promise.resolve( candidate( ...args ) ) );
}, Promise.resolve() );
};
}
function startsWith ( str, prefix ) {
return str.slice( 0, prefix.length ) === prefix;
}
export default function commonjs ( options = {} ) {
const extensions = options.extensions || ['.js'];
const filter = createFilter( options.include, options.exclude );
const ignoreGlobal = options.ignoreGlobal;
const customNamedExports = {};
if ( options.namedExports ) {
Object.keys( options.namedExports ).forEach( id => {
let resolvedId;
try {
resolvedId = nodeResolveSync( id, { basedir: process.cwd() });
} catch ( err ) {
resolvedId = resolve( id );
}
customNamedExports[ resolvedId ] = options.namedExports[ id ];
});
}
const esModulesWithoutDefaultExport = [];
const allowDynamicRequire = !!options.ignore; // TODO maybe this should be configurable?
const ignoreRequire = typeof options.ignore === 'function' ?
options.ignore :
Array.isArray( options.ignore ) ? id => ~options.ignore.indexOf( id ) :
() => false;
let entryModuleIdsPromise = null;
function resolveId ( importee, importer ) {
if ( importee === HELPERS_ID ) return importee;
if ( importer && startsWith( importer, PREFIX ) ) importer = importer.slice( PREFIX.length );
const isProxyModule = startsWith( importee, PREFIX );
if ( isProxyModule ) importee = importee.slice( PREFIX.length );
return resolveUsingOtherResolvers( importee, importer ).then( resolved => {
if ( resolved ) return isProxyModule ? PREFIX + resolved : resolved;
resolved = defaultResolver( importee, importer );
if ( isProxyModule ) {
if ( resolved ) return PREFIX + resolved;
return EXTERNAL + importee; // external
}
return resolved;
});
}
const sourceMap = options.sourceMap !== false;
const commonjsModules = new Map();
let resolveUsingOtherResolvers;
return {
name: 'commonjs',
options ( options ) {
const resolvers = ( options.plugins || [] )
.map( plugin => {
if ( plugin.resolveId === resolveId ) {
// substitute CommonJS resolution logic
return ( importee, importer ) => {
if ( importee[0] !== '.' || !importer ) return; // not our problem
const resolved = resolve( dirname( importer ), importee );
const candidates = getCandidates( resolved, extensions );
for ( let i = 0; i < candidates.length; i += 1 ) {
try {
const stats = statSync( candidates[i] );
if ( stats.isFile() ) return candidates[i];
} catch ( err ) { /* noop */ }
}
};
}
return plugin.resolveId;
})
.filter( Boolean );
const isExternal = id => options.external ?
Array.isArray( options.external ) ? ~options.external.indexOf( id ) :
options.external(id) :
false;
resolvers.unshift( id => isExternal( id ) ? false : null );
resolveUsingOtherResolvers = first( resolvers );
const entryModules = [].concat( options.input || options.entry );
entryModuleIdsPromise = Promise.all(
entryModules.map( entry => resolveId( entry ))
);
},
resolveId,
load ( id ) {
if ( id === HELPERS_ID ) return HELPERS;
// generate proxy modules
if ( startsWith( id, EXTERNAL ) ) {
const actualId = id.slice( EXTERNAL.length );
const name = getName( actualId );
return `import ${name} from ${JSON.stringify( actualId )}; export default ${name};`;
}
if ( startsWith( id, PREFIX ) ) {
const actualId = id.slice( PREFIX.length );
const name = getName( actualId );
if (commonjsModules.has( actualId ))
return `import { __moduleExports } from ${JSON.stringify( actualId )}; export default __moduleExports;`;
else if (esModulesWithoutDefaultExport.indexOf(actualId) !== -1)
return `import * as ${name} from ${JSON.stringify( actualId )}; export default ${name};`;
else
return `import * as ${name} from ${JSON.stringify( actualId )}; export default ( ${name} && ${name}['default'] ) || ${name};`;
}
},
transform ( code, id ) {
if ( !filter( id ) ) return null;
if ( extensions.indexOf( extname( id ) ) === -1 ) return null;
return entryModuleIdsPromise.then( (entryModuleIds) => {
const {isEsModule, hasDefaultExport, ast} = checkEsModule( code, id );
if ( isEsModule ) {
if ( !hasDefaultExport )
esModulesWithoutDefaultExport.push( id );
return;
}
// it is not an ES module but not a commonjs module, too.
if ( !checkFirstpass( code, ignoreGlobal ) ) {
esModulesWithoutDefaultExport.push( id );
return;
}
const transformed = transformCommonjs( code, id, entryModuleIds.indexOf(id) !== -1, ignoreGlobal, ignoreRequire, customNamedExports[ id ], sourceMap, allowDynamicRequire, ast );
if ( !transformed ) return;
commonjsModules.set( id, true );
return transformed;
});
}
};
}