rollup-plugin-inject
Advanced tools
@@ -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 { |
+6
-5
| { | ||
| "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": { |
+96
-96
@@ -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 { |
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
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
-40%18889
-8.66%6
50%466
-1.06%2
100%- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed