rollup-plugin-inject
Advanced tools
Comparing version 2.1.0 to 2.2.0
@@ -8,26 +8,26 @@ 'use strict'; | ||
var estreeWalker = require('estree-walker'); | ||
var acorn = require('acorn'); | ||
var MagicString = _interopDefault(require('magic-string')); | ||
function escape ( str ) { | ||
return str.replace( /[-[\]/{}()*+?.\\^$|]/g, '\\$&' ); | ||
function escape (str) { | ||
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'); | ||
} | ||
function isReference ( node, parent ) { | ||
if ( node.type === 'MemberExpression' ) { | ||
return !node.computed && isReference( node.object, node ); | ||
function isReference (node, parent) { | ||
if (node.type === 'MemberExpression') { | ||
return !node.computed && isReference(node.object, node); | ||
} | ||
if ( node.type === 'Identifier' ) { | ||
if (node.type === 'Identifier') { | ||
// TODO is this right? | ||
if ( parent.type === 'MemberExpression' ) { return parent.computed || node === parent.object; } | ||
if (parent.type === 'MemberExpression') | ||
{ return parent.computed || node === parent.object; } | ||
// disregard the `bar` in { bar: foo } | ||
if ( parent.type === 'Property' && node !== parent.value ) { return false; } | ||
if (parent.type === 'Property' && node !== parent.value) { return false; } | ||
// disregard the `bar` in `class Foo { bar () {...} }` | ||
if ( parent.type === 'MethodDefinition' ) { return false; } | ||
if (parent.type === 'MethodDefinition') { return false; } | ||
// disregard the `bar` in `export { foo as bar }` | ||
if ( parent.type === 'ExportSpecifier' && node !== parent.local ) { return; } | ||
if (parent.type === 'ExportSpecifier' && node !== parent.local) { return; } | ||
@@ -38,8 +38,8 @@ return true; | ||
function flatten ( node ) { | ||
function flatten (node) { | ||
var name; | ||
var parts = []; | ||
while ( node.type === 'MemberExpression' ) { | ||
parts.unshift( node.property.name ); | ||
while (node.type === 'MemberExpression') { | ||
parts.unshift(node.property.name); | ||
node = node.object; | ||
@@ -49,42 +49,18 @@ } | ||
name = node.name; | ||
parts.unshift( name ); | ||
parts.unshift(name); | ||
return { name: name, keypath: parts.join( '.' ) }; | ||
return { name: name, keypath: parts.join('.') }; | ||
} | ||
function assign ( target, source ) { | ||
Object.keys( source ).forEach( function (key) { | ||
target[ key ] = source[ key ]; | ||
}); | ||
return target; | ||
} | ||
function inject (options) { | ||
if (!options) { throw new Error('Missing options'); } | ||
function isArray ( thing ) { | ||
return Object.prototype.toString.call( thing ) === '[object Array]'; | ||
} | ||
var filter = rollupPluginutils.createFilter(options.include, options.exclude); | ||
function tryParse ( code, id ) { | ||
try { | ||
return acorn.parse( code, { | ||
ecmaVersion: 6, | ||
sourceType: 'module' | ||
}); | ||
} catch ( err ) { | ||
// TODO this should use rollup's official mechanism for plugin warnings (i.e. "this.warn" on the plugin context) | ||
// eslint-disable-next-line no-console | ||
console.warn( ("rollup-plugin-inject: failed to parse " + id + ". Consider restricting the plugin to particular files via options.include") ); | ||
} | ||
} | ||
function inject ( options ) { | ||
if ( !options ) { throw new Error( 'Missing options' ); } | ||
var filter = rollupPluginutils.createFilter( options.include, options.exclude ); | ||
var modules; | ||
if ( options.modules ) { | ||
if (options.modules) { | ||
modules = options.modules; | ||
} else { | ||
modules = assign( {}, options ); | ||
modules = Object.assign({}, options); | ||
delete modules.include; | ||
@@ -95,13 +71,18 @@ delete modules.exclude; | ||
// Fix paths on Windows | ||
if ( path.sep !== '/' ) { | ||
Object.keys( modules ).forEach( function (key) { | ||
var module = modules[ key ]; | ||
if (path.sep !== '/') { | ||
Object.keys(modules).forEach(function (key) { | ||
var module = modules[key]; | ||
modules[ key ] = isArray( module ) ? | ||
[ module[0].split( path.sep ).join( '/' ), module[1] ] : | ||
module.split( path.sep ).join( '/' ); | ||
modules[key] = Array.isArray(module) | ||
? [module[0].split(path.sep).join('/'), module[1]] | ||
: module.split(path.sep).join('/'); | ||
}); | ||
} | ||
var firstpass = new RegExp( ("(?:" + (Object.keys( modules ).map( escape ).join( '|' )) + ")"), 'g' ); | ||
var firstpass = new RegExp( | ||
("(?:" + (Object.keys(modules) | ||
.map(escape) | ||
.join('|')) + ")"), | ||
'g' | ||
); | ||
var sourceMap = options.sourceMap !== false; | ||
@@ -112,19 +93,28 @@ | ||
transform: function transform ( code, id ) { | ||
if ( !filter( id ) ) { return null; } | ||
if ( code.search( firstpass ) == -1 ) { return null; } | ||
transform: function transform (code, id) { | ||
if (!filter(id)) { return null; } | ||
if (code.search(firstpass) == -1) { return null; } | ||
if ( path.sep !== '/' ) { id = id.split( path.sep ).join( '/' ); } | ||
if (path.sep !== '/') { id = id.split(path.sep).join('/'); } | ||
var ast = tryParse( code, id ); | ||
if ( !ast ) { return null; } | ||
var ast = null; | ||
try { | ||
ast = this.parse(code); | ||
} catch (err) { | ||
this.warn({ | ||
code: 'PARSE_ERROR', | ||
message: | ||
("rollup-plugin-inject: failed to parse " + id + ". Consider restricting the plugin to particular files via options.include") | ||
}); | ||
} | ||
if (!ast) { return null; } | ||
// analyse scopes | ||
var scope = rollupPluginutils.attachScopes( ast, 'scope' ); | ||
var scope = rollupPluginutils.attachScopes(ast, 'scope'); | ||
var imports = {}; | ||
ast.body.forEach( function (node) { | ||
if ( node.type === 'ImportDeclaration' ) { | ||
node.specifiers.forEach( function (specifier) { | ||
imports[ specifier.local.name ] = true; | ||
ast.body.forEach(function (node) { | ||
if (node.type === 'ImportDeclaration') { | ||
node.specifiers.forEach(function (specifier) { | ||
imports[specifier.local.name] = true; | ||
}); | ||
@@ -134,28 +124,31 @@ } | ||
var magicString = new MagicString( code ); | ||
var magicString = new MagicString(code); | ||
var newImports = {}; | ||
function handleReference ( node, name, keypath ) { | ||
if ( keypath in modules && !scope.contains( name ) && !imports[ name ] ) { | ||
var module = modules[ keypath ]; | ||
if ( typeof module === 'string' ) { module = [ module, 'default' ]; } | ||
function handleReference (node, name, keypath) { | ||
if (keypath in modules && !scope.contains(name) && !imports[name]) { | ||
var module = modules[keypath]; | ||
if (typeof module === 'string') { module = [module, 'default']; } | ||
// prevent module from importing itself | ||
if ( module[0] === id ) { return; } | ||
if (module[0] === id) { return; } | ||
var hash = keypath + ":" + (module[0]) + ":" + (module[1]); | ||
var importLocalName = name === keypath ? name : rollupPluginutils.makeLegalIdentifier( ("$inject_" + keypath) ); | ||
var importLocalName = | ||
name === keypath ? name : rollupPluginutils.makeLegalIdentifier(("$inject_" + keypath)); | ||
if ( !newImports[ hash ] ) { | ||
if ( module[1] === '*' ) { | ||
newImports[ hash ] = "import * as " + importLocalName + " from '" + (module[0]) + "';"; | ||
if (!newImports[hash]) { | ||
if (module[1] === '*') { | ||
newImports[hash] = "import * as " + importLocalName + " from '" + (module[0]) + "';"; | ||
} else { | ||
newImports[ hash ] = "import { " + (module[1]) + " as " + importLocalName + " } from '" + (module[0]) + "';"; | ||
newImports[hash] = "import { " + (module[1]) + " as " + importLocalName + " } from '" + (module[0]) + "';"; | ||
} | ||
} | ||
if ( name !== keypath ) { | ||
magicString.overwrite( node.start, node.end, importLocalName, { storeName: true } ); | ||
if (name !== keypath) { | ||
magicString.overwrite(node.start, node.end, importLocalName, { | ||
storeName: true | ||
}); | ||
} | ||
@@ -167,37 +160,37 @@ | ||
estreeWalker.walk( ast, { | ||
enter: function enter ( node, parent ) { | ||
if ( sourceMap ) { | ||
magicString.addSourcemapLocation( node.start ); | ||
magicString.addSourcemapLocation( node.end ); | ||
estreeWalker.walk(ast, { | ||
enter: function enter (node, parent) { | ||
if (sourceMap) { | ||
magicString.addSourcemapLocation(node.start); | ||
magicString.addSourcemapLocation(node.end); | ||
} | ||
if ( node.scope ) { scope = node.scope; } | ||
if (node.scope) { scope = node.scope; } | ||
// special case – shorthand properties. because node.key === node.value, | ||
// we can't differentiate once we've descended into the node | ||
if ( node.type === 'Property' && node.shorthand ) { | ||
if (node.type === 'Property' && node.shorthand) { | ||
var name = node.key.name; | ||
handleReference( node, name, name ); | ||
handleReference(node, name, name); | ||
return this.skip(); | ||
} | ||
if ( isReference( node, parent ) ) { | ||
var ref = flatten( node ); | ||
if (isReference(node, parent)) { | ||
var ref = flatten(node); | ||
var name$1 = ref.name; | ||
var keypath = ref.keypath; | ||
var handled = handleReference( node, name$1, keypath ); | ||
if ( handled ) { return this.skip(); } | ||
var handled = handleReference(node, name$1, keypath); | ||
if (handled) { return this.skip(); } | ||
} | ||
}, | ||
leave: function leave ( node ) { | ||
if ( node.scope ) { scope = scope.parent; } | ||
leave: function leave (node) { | ||
if (node.scope) { scope = scope.parent; } | ||
} | ||
}); | ||
var keys = Object.keys( newImports ); | ||
if ( !keys.length ) { return null; } | ||
var keys = Object.keys(newImports); | ||
if (!keys.length) { return null; } | ||
var importBlock = keys.map( function (hash) { return newImports[ hash ]; } ).join( '\n\n' ); | ||
magicString.prepend( importBlock + '\n\n' ); | ||
var importBlock = keys.map(function (hash) { return newImports[hash]; }).join('\n\n'); | ||
magicString.prepend(importBlock + '\n\n'); | ||
@@ -204,0 +197,0 @@ return { |
import { attachScopes, createFilter, makeLegalIdentifier } from 'rollup-pluginutils'; | ||
import { sep } from 'path'; | ||
import { walk } from 'estree-walker'; | ||
import { parse } from 'acorn'; | ||
import MagicString from 'magic-string'; | ||
function escape ( str ) { | ||
return str.replace( /[-[\]/{}()*+?.\\^$|]/g, '\\$&' ); | ||
function escape (str) { | ||
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'); | ||
} | ||
function isReference ( node, parent ) { | ||
if ( node.type === 'MemberExpression' ) { | ||
return !node.computed && isReference( node.object, node ); | ||
function isReference (node, parent) { | ||
if (node.type === 'MemberExpression') { | ||
return !node.computed && isReference(node.object, node); | ||
} | ||
if ( node.type === 'Identifier' ) { | ||
if (node.type === 'Identifier') { | ||
// TODO is this right? | ||
if ( parent.type === 'MemberExpression' ) { return parent.computed || node === parent.object; } | ||
if (parent.type === 'MemberExpression') | ||
{ return parent.computed || node === parent.object; } | ||
// disregard the `bar` in { bar: foo } | ||
if ( parent.type === 'Property' && node !== parent.value ) { return false; } | ||
if (parent.type === 'Property' && node !== parent.value) { return false; } | ||
// disregard the `bar` in `class Foo { bar () {...} }` | ||
if ( parent.type === 'MethodDefinition' ) { return false; } | ||
if (parent.type === 'MethodDefinition') { return false; } | ||
// disregard the `bar` in `export { foo as bar }` | ||
if ( parent.type === 'ExportSpecifier' && node !== parent.local ) { return; } | ||
if (parent.type === 'ExportSpecifier' && node !== parent.local) { return; } | ||
@@ -33,8 +33,8 @@ return true; | ||
function flatten ( node ) { | ||
function flatten (node) { | ||
var name; | ||
var parts = []; | ||
while ( node.type === 'MemberExpression' ) { | ||
parts.unshift( node.property.name ); | ||
while (node.type === 'MemberExpression') { | ||
parts.unshift(node.property.name); | ||
node = node.object; | ||
@@ -44,42 +44,18 @@ } | ||
name = node.name; | ||
parts.unshift( name ); | ||
parts.unshift(name); | ||
return { name: name, keypath: parts.join( '.' ) }; | ||
return { name: name, keypath: parts.join('.') }; | ||
} | ||
function assign ( target, source ) { | ||
Object.keys( source ).forEach( function (key) { | ||
target[ key ] = source[ key ]; | ||
}); | ||
return target; | ||
} | ||
function inject (options) { | ||
if (!options) { throw new Error('Missing options'); } | ||
function isArray ( thing ) { | ||
return Object.prototype.toString.call( thing ) === '[object Array]'; | ||
} | ||
var filter = createFilter(options.include, options.exclude); | ||
function tryParse ( code, id ) { | ||
try { | ||
return parse( code, { | ||
ecmaVersion: 6, | ||
sourceType: 'module' | ||
}); | ||
} catch ( err ) { | ||
// TODO this should use rollup's official mechanism for plugin warnings (i.e. "this.warn" on the plugin context) | ||
// eslint-disable-next-line no-console | ||
console.warn( ("rollup-plugin-inject: failed to parse " + id + ". Consider restricting the plugin to particular files via options.include") ); | ||
} | ||
} | ||
function inject ( options ) { | ||
if ( !options ) { throw new Error( 'Missing options' ); } | ||
var filter = createFilter( options.include, options.exclude ); | ||
var modules; | ||
if ( options.modules ) { | ||
if (options.modules) { | ||
modules = options.modules; | ||
} else { | ||
modules = assign( {}, options ); | ||
modules = Object.assign({}, options); | ||
delete modules.include; | ||
@@ -90,13 +66,18 @@ delete modules.exclude; | ||
// Fix paths on Windows | ||
if ( sep !== '/' ) { | ||
Object.keys( modules ).forEach( function (key) { | ||
var module = modules[ key ]; | ||
if (sep !== '/') { | ||
Object.keys(modules).forEach(function (key) { | ||
var module = modules[key]; | ||
modules[ key ] = isArray( module ) ? | ||
[ module[0].split( sep ).join( '/' ), module[1] ] : | ||
module.split( sep ).join( '/' ); | ||
modules[key] = Array.isArray(module) | ||
? [module[0].split(sep).join('/'), module[1]] | ||
: module.split(sep).join('/'); | ||
}); | ||
} | ||
var firstpass = new RegExp( ("(?:" + (Object.keys( modules ).map( escape ).join( '|' )) + ")"), 'g' ); | ||
var firstpass = new RegExp( | ||
("(?:" + (Object.keys(modules) | ||
.map(escape) | ||
.join('|')) + ")"), | ||
'g' | ||
); | ||
var sourceMap = options.sourceMap !== false; | ||
@@ -107,19 +88,28 @@ | ||
transform: function transform ( code, id ) { | ||
if ( !filter( id ) ) { return null; } | ||
if ( code.search( firstpass ) == -1 ) { return null; } | ||
transform: function transform (code, id) { | ||
if (!filter(id)) { return null; } | ||
if (code.search(firstpass) == -1) { return null; } | ||
if ( sep !== '/' ) { id = id.split( sep ).join( '/' ); } | ||
if (sep !== '/') { id = id.split(sep).join('/'); } | ||
var ast = tryParse( code, id ); | ||
if ( !ast ) { return null; } | ||
var ast = null; | ||
try { | ||
ast = this.parse(code); | ||
} catch (err) { | ||
this.warn({ | ||
code: 'PARSE_ERROR', | ||
message: | ||
("rollup-plugin-inject: failed to parse " + id + ". Consider restricting the plugin to particular files via options.include") | ||
}); | ||
} | ||
if (!ast) { return null; } | ||
// analyse scopes | ||
var scope = attachScopes( ast, 'scope' ); | ||
var scope = attachScopes(ast, 'scope'); | ||
var imports = {}; | ||
ast.body.forEach( function (node) { | ||
if ( node.type === 'ImportDeclaration' ) { | ||
node.specifiers.forEach( function (specifier) { | ||
imports[ specifier.local.name ] = true; | ||
ast.body.forEach(function (node) { | ||
if (node.type === 'ImportDeclaration') { | ||
node.specifiers.forEach(function (specifier) { | ||
imports[specifier.local.name] = true; | ||
}); | ||
@@ -129,28 +119,31 @@ } | ||
var magicString = new MagicString( code ); | ||
var magicString = new MagicString(code); | ||
var newImports = {}; | ||
function handleReference ( node, name, keypath ) { | ||
if ( keypath in modules && !scope.contains( name ) && !imports[ name ] ) { | ||
var module = modules[ keypath ]; | ||
if ( typeof module === 'string' ) { module = [ module, 'default' ]; } | ||
function handleReference (node, name, keypath) { | ||
if (keypath in modules && !scope.contains(name) && !imports[name]) { | ||
var module = modules[keypath]; | ||
if (typeof module === 'string') { module = [module, 'default']; } | ||
// prevent module from importing itself | ||
if ( module[0] === id ) { return; } | ||
if (module[0] === id) { return; } | ||
var hash = keypath + ":" + (module[0]) + ":" + (module[1]); | ||
var importLocalName = name === keypath ? name : makeLegalIdentifier( ("$inject_" + keypath) ); | ||
var importLocalName = | ||
name === keypath ? name : makeLegalIdentifier(("$inject_" + keypath)); | ||
if ( !newImports[ hash ] ) { | ||
if ( module[1] === '*' ) { | ||
newImports[ hash ] = "import * as " + importLocalName + " from '" + (module[0]) + "';"; | ||
if (!newImports[hash]) { | ||
if (module[1] === '*') { | ||
newImports[hash] = "import * as " + importLocalName + " from '" + (module[0]) + "';"; | ||
} else { | ||
newImports[ hash ] = "import { " + (module[1]) + " as " + importLocalName + " } from '" + (module[0]) + "';"; | ||
newImports[hash] = "import { " + (module[1]) + " as " + importLocalName + " } from '" + (module[0]) + "';"; | ||
} | ||
} | ||
if ( name !== keypath ) { | ||
magicString.overwrite( node.start, node.end, importLocalName, { storeName: true } ); | ||
if (name !== keypath) { | ||
magicString.overwrite(node.start, node.end, importLocalName, { | ||
storeName: true | ||
}); | ||
} | ||
@@ -162,37 +155,37 @@ | ||
walk( ast, { | ||
enter: function enter ( node, parent ) { | ||
if ( sourceMap ) { | ||
magicString.addSourcemapLocation( node.start ); | ||
magicString.addSourcemapLocation( node.end ); | ||
walk(ast, { | ||
enter: function enter (node, parent) { | ||
if (sourceMap) { | ||
magicString.addSourcemapLocation(node.start); | ||
magicString.addSourcemapLocation(node.end); | ||
} | ||
if ( node.scope ) { scope = node.scope; } | ||
if (node.scope) { scope = node.scope; } | ||
// special case – shorthand properties. because node.key === node.value, | ||
// we can't differentiate once we've descended into the node | ||
if ( node.type === 'Property' && node.shorthand ) { | ||
if (node.type === 'Property' && node.shorthand) { | ||
var name = node.key.name; | ||
handleReference( node, name, name ); | ||
handleReference(node, name, name); | ||
return this.skip(); | ||
} | ||
if ( isReference( node, parent ) ) { | ||
var ref = flatten( node ); | ||
if (isReference(node, parent)) { | ||
var ref = flatten(node); | ||
var name$1 = ref.name; | ||
var keypath = ref.keypath; | ||
var handled = handleReference( node, name$1, keypath ); | ||
if ( handled ) { return this.skip(); } | ||
var handled = handleReference(node, name$1, keypath); | ||
if (handled) { return this.skip(); } | ||
} | ||
}, | ||
leave: function leave ( node ) { | ||
if ( node.scope ) { scope = scope.parent; } | ||
leave: function leave (node) { | ||
if (node.scope) { scope = scope.parent; } | ||
} | ||
}); | ||
var keys = Object.keys( newImports ); | ||
if ( !keys.length ) { return null; } | ||
var keys = Object.keys(newImports); | ||
if (!keys.length) { return null; } | ||
var importBlock = keys.map( function (hash) { return newImports[ hash ]; } ).join( '\n\n' ); | ||
magicString.prepend( importBlock + '\n\n' ); | ||
var importBlock = keys.map(function (hash) { return newImports[hash]; }).join('\n\n'); | ||
magicString.prepend(importBlock + '\n\n'); | ||
@@ -199,0 +192,0 @@ return { |
{ | ||
"name": "rollup-plugin-inject", | ||
"description": "Scan modules for global variables and inject `import` statements where necessary", | ||
"version": "2.1.0", | ||
"version": "2.2.0", | ||
"devDependencies": { | ||
"eslint": "^5.2.0", | ||
"mocha": "^5.2.0", | ||
"prettier": "^1.13.7", | ||
"rollup": "^0.63.4", | ||
"rollup-plugin-buble": "^0.19.2" | ||
"rollup-plugin-buble": "^0.19.2", | ||
"shx": "^0.3.2" | ||
}, | ||
"main": "dist/rollup-plugin-inject.cjs.js", | ||
"module": "dist/rollup-plugin-inject.es6.js", | ||
"jsnext:main": "dist/rollup-plugin-inject.es6.js", | ||
@@ -28,7 +31,5 @@ "scripts": { | ||
"dependencies": { | ||
"acorn": "^5.1.2", | ||
"estree-walker": "^0.5.0", | ||
"magic-string": "^0.25.0", | ||
"rollup-pluginutils": "^2.0.1", | ||
"shx": "^0.3.2" | ||
"rollup-pluginutils": "^2.0.1" | ||
}, | ||
@@ -35,0 +36,0 @@ "repository": { |
192
src/index.js
@@ -1,30 +0,33 @@ | ||
import { attachScopes, createFilter, makeLegalIdentifier } from 'rollup-pluginutils'; | ||
import { | ||
attachScopes, | ||
createFilter, | ||
makeLegalIdentifier | ||
} from 'rollup-pluginutils'; | ||
import { sep } from 'path'; | ||
import { walk } from 'estree-walker'; | ||
// TODO this should be using the "this.parse" function on rollup's plugin context instead | ||
import { parse } from 'acorn'; | ||
import MagicString from 'magic-string'; | ||
function escape ( str ) { | ||
return str.replace( /[-[\]/{}()*+?.\\^$|]/g, '\\$&' ); | ||
function escape (str) { | ||
return str.replace(/[-[\]/{}()*+?.\\^$|]/g, '\\$&'); | ||
} | ||
function isReference ( node, parent ) { | ||
if ( node.type === 'MemberExpression' ) { | ||
return !node.computed && isReference( node.object, node ); | ||
function isReference (node, parent) { | ||
if (node.type === 'MemberExpression') { | ||
return !node.computed && isReference(node.object, node); | ||
} | ||
if ( node.type === 'Identifier' ) { | ||
if (node.type === 'Identifier') { | ||
// TODO is this right? | ||
if ( parent.type === 'MemberExpression' ) return parent.computed || node === parent.object; | ||
if (parent.type === 'MemberExpression') | ||
return parent.computed || node === parent.object; | ||
// disregard the `bar` in { bar: foo } | ||
if ( parent.type === 'Property' && node !== parent.value ) return false; | ||
if (parent.type === 'Property' && node !== parent.value) return false; | ||
// disregard the `bar` in `class Foo { bar () {...} }` | ||
if ( parent.type === 'MethodDefinition' ) return false; | ||
if (parent.type === 'MethodDefinition') return false; | ||
// disregard the `bar` in `export { foo as bar }` | ||
if ( parent.type === 'ExportSpecifier' && node !== parent.local ) return; | ||
if (parent.type === 'ExportSpecifier' && node !== parent.local) return; | ||
@@ -35,8 +38,8 @@ return true; | ||
function flatten ( node ) { | ||
function flatten (node) { | ||
let name; | ||
let parts = []; | ||
while ( node.type === 'MemberExpression' ) { | ||
parts.unshift( node.property.name ); | ||
while (node.type === 'MemberExpression') { | ||
parts.unshift(node.property.name); | ||
node = node.object; | ||
@@ -46,42 +49,18 @@ } | ||
name = node.name; | ||
parts.unshift( name ); | ||
parts.unshift(name); | ||
return { name, keypath: parts.join( '.' ) }; | ||
return { name, keypath: parts.join('.') }; | ||
} | ||
function assign ( target, source ) { | ||
Object.keys( source ).forEach( key => { | ||
target[ key ] = source[ key ]; | ||
}); | ||
return target; | ||
} | ||
export default function inject (options) { | ||
if (!options) throw new Error('Missing options'); | ||
function isArray ( thing ) { | ||
return Object.prototype.toString.call( thing ) === '[object Array]'; | ||
} | ||
const filter = createFilter(options.include, options.exclude); | ||
function tryParse ( code, id ) { | ||
try { | ||
return parse( code, { | ||
ecmaVersion: 6, | ||
sourceType: 'module' | ||
}); | ||
} catch ( err ) { | ||
// TODO this should use rollup's official mechanism for plugin warnings (i.e. "this.warn" on the plugin context) | ||
// eslint-disable-next-line no-console | ||
console.warn( `rollup-plugin-inject: failed to parse ${id}. Consider restricting the plugin to particular files via options.include` ); | ||
} | ||
} | ||
export default function inject ( options ) { | ||
if ( !options ) throw new Error( 'Missing options' ); | ||
const filter = createFilter( options.include, options.exclude ); | ||
let modules; | ||
if ( options.modules ) { | ||
if (options.modules) { | ||
modules = options.modules; | ||
} else { | ||
modules = assign( {}, options ); | ||
modules = Object.assign({}, options); | ||
delete modules.include; | ||
@@ -92,13 +71,18 @@ delete modules.exclude; | ||
// Fix paths on Windows | ||
if ( sep !== '/' ) { | ||
Object.keys( modules ).forEach( key => { | ||
const module = modules[ key ]; | ||
if (sep !== '/') { | ||
Object.keys(modules).forEach(key => { | ||
const module = modules[key]; | ||
modules[ key ] = isArray( module ) ? | ||
[ module[0].split( sep ).join( '/' ), module[1] ] : | ||
module.split( sep ).join( '/' ); | ||
modules[key] = Array.isArray(module) | ||
? [module[0].split(sep).join('/'), module[1]] | ||
: module.split(sep).join('/'); | ||
}); | ||
} | ||
const firstpass = new RegExp( `(?:${Object.keys( modules ).map( escape ).join( '|' )})`, 'g' ); | ||
const firstpass = new RegExp( | ||
`(?:${Object.keys(modules) | ||
.map(escape) | ||
.join('|')})`, | ||
'g' | ||
); | ||
const sourceMap = options.sourceMap !== false; | ||
@@ -109,19 +93,28 @@ | ||
transform ( code, id ) { | ||
if ( !filter( id ) ) return null; | ||
if ( code.search( firstpass ) == -1 ) return null; | ||
transform (code, id) { | ||
if (!filter(id)) return null; | ||
if (code.search(firstpass) == -1) return null; | ||
if ( sep !== '/' ) id = id.split( sep ).join( '/' ); | ||
if (sep !== '/') id = id.split(sep).join('/'); | ||
const ast = tryParse( code, id ); | ||
if ( !ast ) return null; | ||
let ast = null; | ||
try { | ||
ast = this.parse(code); | ||
} catch (err) { | ||
this.warn({ | ||
code: 'PARSE_ERROR', | ||
message: | ||
`rollup-plugin-inject: failed to parse ${id}. Consider restricting the plugin to particular files via options.include` | ||
}); | ||
} | ||
if (!ast) return null; | ||
// analyse scopes | ||
let scope = attachScopes( ast, 'scope' ); | ||
let scope = attachScopes(ast, 'scope'); | ||
let imports = {}; | ||
ast.body.forEach( node => { | ||
if ( node.type === 'ImportDeclaration' ) { | ||
node.specifiers.forEach( specifier => { | ||
imports[ specifier.local.name ] = true; | ||
ast.body.forEach(node => { | ||
if (node.type === 'ImportDeclaration') { | ||
node.specifiers.forEach(specifier => { | ||
imports[specifier.local.name] = true; | ||
}); | ||
@@ -131,28 +124,35 @@ } | ||
const magicString = new MagicString( code ); | ||
const magicString = new MagicString(code); | ||
let newImports = {}; | ||
function handleReference ( node, name, keypath ) { | ||
if ( keypath in modules && !scope.contains( name ) && !imports[ name ] ) { | ||
let module = modules[ keypath ]; | ||
if ( typeof module === 'string' ) module = [ module, 'default' ]; | ||
function handleReference (node, name, keypath) { | ||
if (keypath in modules && !scope.contains(name) && !imports[name]) { | ||
let module = modules[keypath]; | ||
if (typeof module === 'string') module = [module, 'default']; | ||
// prevent module from importing itself | ||
if ( module[0] === id ) return; | ||
if (module[0] === id) return; | ||
const hash = `${keypath}:${module[0]}:${module[1]}`; | ||
const importLocalName = name === keypath ? name : makeLegalIdentifier( `$inject_${keypath}` ); | ||
const importLocalName = | ||
name === keypath ? name : makeLegalIdentifier(`$inject_${keypath}`); | ||
if ( !newImports[ hash ] ) { | ||
if ( module[1] === '*' ) { | ||
newImports[ hash ] = `import * as ${importLocalName} from '${module[0]}';`; | ||
if (!newImports[hash]) { | ||
if (module[1] === '*') { | ||
newImports[hash] = `import * as ${importLocalName} from '${ | ||
module[0] | ||
}';`; | ||
} else { | ||
newImports[ hash ] = `import { ${module[1]} as ${importLocalName} } from '${module[0]}';`; | ||
newImports[hash] = `import { ${ | ||
module[1] | ||
} as ${importLocalName} } from '${module[0]}';`; | ||
} | ||
} | ||
if ( name !== keypath ) { | ||
magicString.overwrite( node.start, node.end, importLocalName, { storeName: true } ); | ||
if (name !== keypath) { | ||
magicString.overwrite(node.start, node.end, importLocalName, { | ||
storeName: true | ||
}); | ||
} | ||
@@ -164,35 +164,35 @@ | ||
walk( ast, { | ||
enter ( node, parent ) { | ||
if ( sourceMap ) { | ||
magicString.addSourcemapLocation( node.start ); | ||
magicString.addSourcemapLocation( node.end ); | ||
walk(ast, { | ||
enter (node, parent) { | ||
if (sourceMap) { | ||
magicString.addSourcemapLocation(node.start); | ||
magicString.addSourcemapLocation(node.end); | ||
} | ||
if ( node.scope ) scope = node.scope; | ||
if (node.scope) scope = node.scope; | ||
// special case – shorthand properties. because node.key === node.value, | ||
// we can't differentiate once we've descended into the node | ||
if ( node.type === 'Property' && node.shorthand ) { | ||
if (node.type === 'Property' && node.shorthand) { | ||
const name = node.key.name; | ||
handleReference( node, name, name ); | ||
handleReference(node, name, name); | ||
return this.skip(); | ||
} | ||
if ( isReference( node, parent ) ) { | ||
const { name, keypath } = flatten( node ); | ||
const handled = handleReference( node, name, keypath ); | ||
if ( handled ) return this.skip(); | ||
if (isReference(node, parent)) { | ||
const { name, keypath } = flatten(node); | ||
const handled = handleReference(node, name, keypath); | ||
if (handled) return this.skip(); | ||
} | ||
}, | ||
leave ( node ) { | ||
if ( node.scope ) scope = scope.parent; | ||
leave (node) { | ||
if (node.scope) scope = scope.parent; | ||
} | ||
}); | ||
const keys = Object.keys( newImports ); | ||
if ( !keys.length ) return null; | ||
const keys = Object.keys(newImports); | ||
if (!keys.length) return null; | ||
const importBlock = keys.map( hash => newImports[ hash ] ).join( '\n\n' ); | ||
magicString.prepend( importBlock + '\n\n' ); | ||
const importBlock = keys.map(hash => newImports[hash]).join('\n\n'); | ||
magicString.prepend(importBlock + '\n\n'); | ||
@@ -199,0 +199,0 @@ return { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
3
18889
6
466
2
- Removedacorn@^5.1.2
- Removedshx@^0.3.2
- Removedacorn@5.7.4(transitive)
- Removedbalanced-match@1.0.2(transitive)
- Removedbrace-expansion@1.1.11(transitive)
- Removedconcat-map@0.0.1(transitive)
- Removedfs.realpath@1.0.0(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedglob@7.2.3(transitive)
- Removedhasown@2.0.2(transitive)
- Removedinflight@1.0.6(transitive)
- Removedinherits@2.0.4(transitive)
- Removedinterpret@1.4.0(transitive)
- Removedis-core-module@2.15.1(transitive)
- Removedminimatch@3.1.2(transitive)
- Removedminimist@1.2.8(transitive)
- Removedonce@1.4.0(transitive)
- Removedpath-is-absolute@1.0.1(transitive)
- Removedpath-parse@1.0.7(transitive)
- Removedrechoir@0.6.2(transitive)
- Removedresolve@1.22.8(transitive)
- Removedshelljs@0.8.5(transitive)
- Removedshx@0.3.4(transitive)
- Removedsupports-preserve-symlinks-flag@1.0.0(transitive)
- Removedwrappy@1.0.2(transitive)