├── test ├── fixtures │ ├── single-import │ │ ├── actual.js │ │ └── expected.js │ ├── module-shadow │ │ ├── actual.js │ │ └── expected.js │ ├── import-default │ │ ├── actual.js │ │ └── expected.js │ ├── export-as-default │ │ ├── actual.js │ │ └── expected.js │ ├── export-default-anon-function │ │ ├── actual.js │ │ └── expected.js │ ├── import-mixing │ │ ├── actual.js │ │ └── expected.js │ ├── export-default-closure-func │ │ ├── actual.js │ │ └── expected.js │ ├── .babelrc │ ├── export-from │ │ ├── actual.js │ │ └── expected.js │ ├── export-from-default │ │ ├── actual.js │ │ └── expected.js │ ├── export-arrow │ │ ├── actual.js │ │ └── expected.js │ ├── commonjs-names │ │ ├── actual.js │ │ └── expected.js │ ├── functionexpression │ │ ├── actual.js │ │ └── expected.js │ ├── babel-runtime │ │ ├── actual.js │ │ └── expected.js │ ├── classexpression │ │ ├── actual.js │ │ └── expected.js │ ├── basic │ │ ├── actual.js │ │ └── expected.js │ ├── export-named │ │ ├── actual.js │ │ └── expected.js │ └── aux-comment │ │ ├── actual.js │ │ └── expected.js └── index.js ├── .gitignore ├── .babelrc ├── .npmignore ├── .editorconfig ├── LICENSE ├── package.json ├── README.md └── src └── index.js /test/fixtures/single-import/actual.js: -------------------------------------------------------------------------------- 1 | import 'a'; 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /dist 3 | *.log 4 | .directory 5 | -------------------------------------------------------------------------------- /test/fixtures/module-shadow/actual.js: -------------------------------------------------------------------------------- 1 | export function module() {}; 2 | -------------------------------------------------------------------------------- /test/fixtures/import-default/actual.js: -------------------------------------------------------------------------------- 1 | import { default as a } from './a'; 2 | -------------------------------------------------------------------------------- /test/fixtures/single-import/expected.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require('a'); 4 | -------------------------------------------------------------------------------- /test/fixtures/export-as-default/actual.js: -------------------------------------------------------------------------------- 1 | var a = 1; 2 | export { a as default } 3 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"], 3 | "plugins": ["transform-runtime"], 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/export-default-anon-function/actual.js: -------------------------------------------------------------------------------- 1 | export default function() { 2 | }; 3 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /src 3 | /test 4 | *.log 5 | .directory 6 | .editorconfig 7 | 8 | -------------------------------------------------------------------------------- /test/fixtures/import-mixing/actual.js: -------------------------------------------------------------------------------- 1 | import foo, {bar as a} from "foo"; 2 | 3 | foo; 4 | a; 5 | -------------------------------------------------------------------------------- /test/fixtures/export-as-default/expected.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var a = 1; 4 | module.exports = a; 5 | -------------------------------------------------------------------------------- /test/fixtures/export-default-closure-func/actual.js: -------------------------------------------------------------------------------- 1 | 2 | export default (function(){return "foo"})(); 3 | -------------------------------------------------------------------------------- /test/fixtures/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015-webpack"], 3 | "plugins": ["transform-runtime"], 4 | } 5 | -------------------------------------------------------------------------------- /test/fixtures/export-from/actual.js: -------------------------------------------------------------------------------- 1 | export { default as a, b, c as d } from 'e'; 2 | export * from 'f'; 3 | -------------------------------------------------------------------------------- /test/fixtures/export-from-default/actual.js: -------------------------------------------------------------------------------- 1 | export { a as default } from 'e'; 2 | export { default } from 'f'; 3 | -------------------------------------------------------------------------------- /test/fixtures/import-default/expected.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _a = require('./a'); 4 | 5 | var a = _a; 6 | -------------------------------------------------------------------------------- /test/fixtures/module-shadow/expected.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _module() {}exports.module = _module; 4 | ; 5 | -------------------------------------------------------------------------------- /test/fixtures/export-default-anon-function/expected.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function () {}; 4 | 5 | ; 6 | -------------------------------------------------------------------------------- /test/fixtures/export-default-closure-func/expected.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | module.exports = function () { 4 | return "foo"; 5 | }(); 6 | -------------------------------------------------------------------------------- /test/fixtures/export-arrow/actual.js: -------------------------------------------------------------------------------- 1 | export var foo = function(gen, ctx = null) { 2 | } 3 | 4 | export var bar = (gen, ctx = null) => { 5 | } 6 | -------------------------------------------------------------------------------- /test/fixtures/commonjs-names/actual.js: -------------------------------------------------------------------------------- 1 | import a from 'a'; 2 | 3 | var require = 1, 4 | module = 2, 5 | exports = 3; 6 | 7 | var b = 1; 8 | export default b; 9 | -------------------------------------------------------------------------------- /test/fixtures/functionexpression/actual.js: -------------------------------------------------------------------------------- 1 | import a from '/path/to/a'; 2 | doSomething(); 3 | export default function x() { 4 | hey(); 5 | }; 6 | doSomethingElse(); 7 | -------------------------------------------------------------------------------- /test/fixtures/import-mixing/expected.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _foo = require("foo"); 4 | 5 | var foo = _foo; 6 | var a = _foo.bar; 7 | 8 | 9 | foo; 10 | a; 11 | -------------------------------------------------------------------------------- /test/fixtures/export-from-default/expected.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _e = require('e'); 4 | 5 | var _f = require('f'); 6 | 7 | module.exports = _e.a; 8 | module.exports = _f; 9 | -------------------------------------------------------------------------------- /test/fixtures/babel-runtime/actual.js: -------------------------------------------------------------------------------- 1 | import classCallCheck from 'babel-runtime/class-call-check'; 2 | import { default as a, b} from 'babel-runtime/a'; 3 | import * as c from 'babel-runtime/b'; 4 | -------------------------------------------------------------------------------- /test/fixtures/commonjs-names/expected.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var a = require('a'); 4 | 5 | var _require = 1, 6 | _module = 2, 7 | _exports = 3; 8 | 9 | var b = 1; 10 | module.exports = b; 11 | -------------------------------------------------------------------------------- /test/fixtures/functionexpression/expected.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var a = require('/path/to/a'); 4 | 5 | doSomething(); 6 | module.exports = x; 7 | function x() { 8 | hey(); 9 | }; 10 | doSomethingElse(); 11 | -------------------------------------------------------------------------------- /test/fixtures/classexpression/actual.js: -------------------------------------------------------------------------------- 1 | import a from '/path/to/a'; 2 | doSomething(); 3 | export default class x { 4 | constructor() { 5 | 6 | } 7 | func() { 8 | 9 | } 10 | }; 11 | doSomethingElse(); 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | trim_trailing_whitespace = true 6 | indent_style = tab 7 | indent_size = 4 8 | insert_final_newline = true 9 | 10 | [*.{json,babelrc,eslintrc}] 11 | indent_style = space 12 | indent_size = 2 13 | -------------------------------------------------------------------------------- /test/fixtures/export-from/expected.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _e = require('e'); 4 | 5 | var _f = require('f'); 6 | 7 | exports.a = _e; 8 | exports.b = _e.b; 9 | exports.d = _e.c; 10 | 11 | for (var _f_key in _f) { 12 | if (_f_key !== "default") { 13 | exports[_f_key] = _f[_f_key]; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /test/fixtures/basic/actual.js: -------------------------------------------------------------------------------- 1 | import a from '/path/to/a'; 2 | import '/path/to/b'; 3 | import c from '/path/to/c'; 4 | import '/path/to/d'; 5 | import {e, f as g, h, i as j} from '/path/to/e'; 6 | import {k} from '/path/to/k'; 7 | import * as l from "/path/to/l"; 8 | doSomething(); 9 | export default x + y; 10 | doSomethingElse(); 11 | -------------------------------------------------------------------------------- /test/fixtures/export-arrow/expected.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var foo = exports.foo = function foo(gen) { 4 | var ctx = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; 5 | }; 6 | 7 | var bar = exports.bar = function bar(gen) { 8 | var ctx = arguments.length <= 1 || arguments[1] === undefined ? null : arguments[1]; 9 | }; 10 | -------------------------------------------------------------------------------- /test/fixtures/babel-runtime/expected.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var classCallCheck = require('babel-runtime/class-call-check').default; 4 | 5 | var _babelRuntimeA = require('babel-runtime/a'); 6 | 7 | var a = _babelRuntimeA.default; 8 | var b = _babelRuntimeA.b; 9 | 10 | var _babelRuntimeB = require('babel-runtime/b'); 11 | 12 | var c = _babelRuntimeB; 13 | -------------------------------------------------------------------------------- /test/fixtures/export-named/actual.js: -------------------------------------------------------------------------------- 1 | export var a = 1, aa = 2; 2 | export const b = 1, bb = 2; 3 | export let c = 1, cc = 3; 4 | export function d() { 5 | doSomething(); 6 | } 7 | export class e { 8 | doSomething() { 9 | doSomethingElse(); 10 | } 11 | } 12 | var f = 1; 13 | var h = 1; 14 | var i = 1; 15 | export { f }; 16 | export { f as g }; 17 | export { h, i }; 18 | -------------------------------------------------------------------------------- /test/fixtures/aux-comment/actual.js: -------------------------------------------------------------------------------- 1 | import "foo"; 2 | import "foo-bar"; 3 | import "./directory/foo-bar"; 4 | import foo from "foo2"; 5 | import * as foo2 from "foo3"; 6 | import {bar} from "foo4"; 7 | import {foo as bar2} from "foo5"; 8 | /* comment 1*/ 9 | export {test}; 10 | export var test = 5; 11 | 12 | bar(foo, bar2); 13 | 14 | /* my comment */ 15 | bar2; 16 | foo; 17 | -------------------------------------------------------------------------------- /test/fixtures/classexpression/expected.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var _classCallCheck = require('babel-runtime/helpers/classCallCheck').default; 4 | 5 | var _createClass = require('babel-runtime/helpers/createClass').default; 6 | 7 | var a = require('/path/to/a'); 8 | 9 | doSomething(); 10 | 11 | var x = function () { 12 | function x() { 13 | _classCallCheck(this, x); 14 | } 15 | 16 | _createClass(x, [{ 17 | key: 'func', 18 | value: function func() {} 19 | }]); 20 | 21 | return x; 22 | }(); 23 | 24 | module.exports = x; 25 | ; 26 | doSomethingElse(); 27 | -------------------------------------------------------------------------------- /test/fixtures/aux-comment/expected.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var foo = require("foo2"); 4 | 5 | var _foo = require("foo3"); 6 | 7 | var foo2 = _foo; 8 | 9 | var _foo2 = require("foo4"); 10 | 11 | var bar = _foo2.bar; 12 | 13 | var _foo3 = require("foo5"); 14 | 15 | var bar2 = _foo3.foo; 16 | 17 | require("foo"); 18 | 19 | require("foo-bar"); 20 | 21 | require("./directory/foo-bar"); 22 | 23 | /* comment 1*/ 24 | exports.test = test; 25 | var test = exports.test = 5; 26 | 27 | bar(foo, bar2); 28 | 29 | /* my comment */ 30 | bar2; 31 | foo; 32 | -------------------------------------------------------------------------------- /test/fixtures/basic/expected.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var a = require('/path/to/a'); 4 | 5 | var c = require('/path/to/c'); 6 | 7 | var _pathToE = require('/path/to/e'); 8 | 9 | var e = _pathToE.e; 10 | var g = _pathToE.f; 11 | var h = _pathToE.h; 12 | var j = _pathToE.i; 13 | 14 | var _pathToK = require('/path/to/k'); 15 | 16 | var k = _pathToK.k; 17 | 18 | var _pathToL = require("/path/to/l"); 19 | 20 | var l = _pathToL; 21 | 22 | require('/path/to/b'); 23 | 24 | require('/path/to/d'); 25 | 26 | doSomething(); 27 | module.exports = x + y; 28 | 29 | doSomethingElse(); 30 | -------------------------------------------------------------------------------- /test/fixtures/export-named/expected.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _classCallCheck = require("babel-runtime/helpers/classCallCheck").default; 4 | 5 | var _createClass = require("babel-runtime/helpers/createClass").default; 6 | 7 | var a = exports.a = 1, 8 | aa = exports.aa = 2; 9 | var b = exports.b = 1, 10 | bb = exports.bb = 2; 11 | var c = exports.c = 1, 12 | cc = exports.cc = 3; 13 | function d() { 14 | doSomething(); 15 | } 16 | exports.d = d; 17 | 18 | var e = exports.e = function () { 19 | function e() { 20 | _classCallCheck(this, e); 21 | } 22 | 23 | _createClass(e, [{ 24 | key: "doSomething", 25 | value: function doSomething() { 26 | doSomethingElse(); 27 | } 28 | }]); 29 | 30 | return e; 31 | }(); 32 | 33 | var f = 1; 34 | var h = 1; 35 | var i = 1; 36 | exports.f = f; 37 | exports.g = f; 38 | exports.h = h; 39 | exports.i = i; 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Andrey Gubanov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babel-plugin-transform-es2015-modules-simple-commonjs", 3 | "version": "0.3.0", 4 | "description": "Simplified imports and exports", 5 | "repository": "finom/babel-plugin-transform-es2015-modules-simple-commonjs", 6 | "license": "MIT", 7 | "main": "dist/index.js", 8 | "dependencies": { 9 | "babel-plugin-transform-strict-mode": "^6.8.0", 10 | "babel-runtime": "^6.3.19", 11 | "babel-template": "^6.3.13", 12 | "better-log": "^1.3.1" 13 | }, 14 | "devDependencies": { 15 | "babel-cli": "^6.3.17", 16 | "babel-core": "^6.3.21", 17 | "babel-plugin-transform-runtime": "^6.3.13", 18 | "babel-preset-es2015": "^6.5.0", 19 | "babel-preset-es2015-webpack": "^6.4.1", 20 | "babel-register": "^6.3.13", 21 | "chalk": "^1.1.0", 22 | "clear": "0.0.1", 23 | "diff": "^1.4.0", 24 | "watch": "^0.16.0" 25 | }, 26 | "scripts": { 27 | "release": "babel src --out-dir dist", 28 | "test": "node test", 29 | "watch": "node test --watch", 30 | "prepublish": "npm test && npm run release" 31 | }, 32 | "keywords": [ 33 | "babel-plugin", 34 | "commonjs" 35 | ] 36 | } 37 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var babel = require('babel-core'); 3 | var chalk = require('chalk'); 4 | var clear = require('clear'); 5 | var diff = require('diff'); 6 | var fs = require('fs'); 7 | var path = require('path'); 8 | 9 | require('babel-register'); 10 | 11 | var pluginPath = require.resolve('../src'); 12 | 13 | function runTests() { 14 | var testsPath = __dirname + '/fixtures/'; 15 | 16 | fs.readdirSync(testsPath).map(function(item) { 17 | return { 18 | path: path.join(testsPath, item), 19 | name: item, 20 | }; 21 | }).filter(function(item) { 22 | return fs.statSync(item.path).isDirectory(); 23 | }).forEach(runTest); 24 | } 25 | 26 | function runTest(dir) { 27 | var output = babel.transformFileSync(dir.path + '/actual.js', { 28 | plugins: [pluginPath] 29 | }); 30 | 31 | var expected = fs.readFileSync(dir.path + '/expected.js', 'utf-8'); 32 | 33 | function normalizeLines(str) { 34 | return str.replace(/\r\n/g, '\n').trimRight(); 35 | } 36 | 37 | var normalizedOutput = normalizeLines(output.code); 38 | var normalizedExpected = normalizeLines(expected); 39 | 40 | if (normalizedOutput === normalizedExpected) { 41 | process.stdout.write(chalk.bgWhite.black(dir.name) + ' ' + chalk.green('OK')); 42 | } else { 43 | process.stdout.write(chalk.bgWhite.black(dir.name) + ' ' + chalk.red('Different')); 44 | process.stdout.write('\n\n'); 45 | 46 | diff.diffLines(normalizedOutput, normalizedExpected) 47 | .forEach(function (part) { 48 | var value = part.value.replace(/\t/g, '» ').replace(/^\n$/, '↵\n'); 49 | if (part.added) { 50 | value = chalk.green(value); 51 | } else if (part.removed) { 52 | value = chalk.red(value); 53 | } 54 | 55 | 56 | process.stdout.write(value); 57 | }); 58 | } 59 | 60 | process.stdout.write('\n\n\n'); 61 | } 62 | 63 | if (process.argv.indexOf('--watch') >= 0) { 64 | require('watch').watchTree(__dirname + '/..', function () { 65 | delete require.cache[pluginPath]; 66 | clear(); 67 | console.log('Press Ctrl+C to stop watching...'); 68 | console.log('================================'); 69 | try { 70 | runTests(); 71 | } catch (e) { 72 | console.error(chalk.magenta(e.stack)); 73 | } 74 | }); 75 | } else { 76 | runTests(); 77 | } 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # babel-plugin-transform-es2015-modules-simple-commonjs [![npm version](https://badge.fury.io/js/babel-plugin-transform-es2015-modules-simple-commonjs.svg)](https://badge.fury.io/js/babel-plugin-transform-es2015-modules-simple-commonjs) 2 | 3 | Simple transformer for ECMAScript 2015 modules (CommonJS). 4 | 5 | Converts this code: 6 | ```js 7 | import x from '/path/to/x'; 8 | import y from '/path/to/y'; 9 | doSomething(); 10 | export default x + y; 11 | ``` 12 | 13 | Into this one: 14 | ```js 15 | var x = require('/path/to/x'); 16 | var y = require('/path/to/y'); 17 | doSomething(); 18 | module.exports = x + y; 19 | ``` 20 | 21 | Instead of this one (generated with ``babel-plugin-transform-es2015-modules-commonjs``): 22 | ```js 23 | Object.defineProperty(exports, "__esModule", { 24 | value: true 25 | }); 26 | 27 | var _x = require('/path/to/x'); 28 | 29 | var _x2 = _interopRequireDefault(_x); 30 | 31 | var _y = require('/path/to/y'); 32 | 33 | var _y2 = _interopRequireDefault(_y); 34 | 35 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 36 | 37 | doSomething(); 38 | exports.default = _x2.default + _y2.default; 39 | ``` 40 | 41 | This supports all standard es2015 import and export code with some caveats. 42 | 43 | ## Caveats 44 | 45 | 1. When exporting the final value is used, not the value when writing an export statement. It is not supported to mutate declarations that have been exported. You will not be warned, it will just not work. 46 | 47 | 2. You cannot export default and export a named item in the same file as `module.exports` assignment will conflict with the `exports` assignment. This transform will error if you attempt to do this. 48 | 49 | 3. If you mix default imports and importing `*`, it will work, but will not be valid in ES2015. E.g. with the following... 50 | 51 | ```js 52 | // file a 53 | export default 1; 54 | 55 | // file b 56 | import * as a from './a'; 57 | 58 | // file c 59 | export const c = 3; 60 | 61 | // file d 62 | import c from './c'; 63 | ``` 64 | 65 | In the official Babel module, `a` in `file b` will be undefined and `c` in `file d` will be undefined. Using this module, they will be `1` and `3` respectively. 66 | 67 | 4. Updating the exports on-the-fly will not work. This is not supported within commonjs normally anyway, but is supported with the official plugin. 68 | 69 | You may want to use a linter (such as eslint with eslint-plugin-import) in order to ensure that your code is standard whilst using this simplified transform. 70 | 71 | ## Installation 72 | 73 | ```sh 74 | $ npm install --save-dev babel-plugin-transform-es2015-modules-simple-commonjs 75 | ``` 76 | 77 | ## Usage 78 | 79 | ### Via `.babelrc` (Recommended) 80 | 81 | **.babelrc** 82 | 83 | ```json 84 | { 85 | "plugins": ["transform-es2015-modules-simple-commonjs"] 86 | } 87 | ``` 88 | 89 | ### Via Node API 90 | 91 | ```js 92 | require('babel').transform('code', { 93 | plugins: ['transform-es2015-modules-simple-commonjs'] 94 | }); 95 | ``` 96 | 97 | ### Usage with other ES2015 plugins 98 | 99 | This replaces the functionality in `transform-es2015-modules-commonjs`, but you may be better off using this with the `babel-preset-es2015-webpack` preset, which takes the es2015 preset and removes the commonjs transform. 100 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import 'better-log/install'; 2 | import template from "babel-template"; 3 | 4 | let buildRequire = template(` 5 | require($0); 6 | `); 7 | 8 | let buildRequireDefault = template(` 9 | require($0).default; 10 | `); 11 | 12 | let buildExportsAssignment = template(` 13 | module.exports = $0; 14 | `); 15 | 16 | let buildNamedExportsAssignment = template(` 17 | exports.$0 = $1; 18 | `); 19 | 20 | let buildExportAll = template(` 21 | for(var $1 in $0) { 22 | if ($1 !== "default") { 23 | exports[$1] = $0[$1]; 24 | } 25 | } 26 | `); 27 | 28 | module.exports = function({ 29 | types: t 30 | }) { 31 | return { 32 | inherits: require("babel-plugin-transform-strict-mode"), 33 | visitor: { 34 | Program: { 35 | exit(path, file) { 36 | let sources = [], 37 | anonymousSources = [], 38 | { scope } = path, 39 | hasDefaultExport = false, 40 | hasNamedExports = false, 41 | lastExportPath = null; 42 | 43 | // rename these commonjs variables if they're declared in the file 44 | scope.rename("module"); 45 | scope.rename("exports"); 46 | scope.rename("require"); 47 | 48 | let body = path.get("body"); 49 | 50 | function addSource(path) { 51 | let importedID = path.scope.generateUidIdentifier(path.node.source.value); 52 | 53 | sources.push(t.variableDeclaration("var", [ 54 | t.variableDeclarator(importedID, buildRequire( 55 | path.node.source 56 | ).expression) 57 | ])); 58 | 59 | return importedID; 60 | } 61 | 62 | for (let path of body) { 63 | if (path.isExportDefaultDeclaration()) { 64 | hasDefaultExport = true; 65 | lastExportPath = path; 66 | let declaration = path.get("declaration"); 67 | if(declaration.type == 'FunctionDeclaration') { 68 | if(declaration.node.id) { 69 | path.replaceWithMultiple ([ 70 | buildExportsAssignment(declaration.node.id), 71 | declaration.node 72 | ]); 73 | } else { 74 | path.replaceWith(buildExportsAssignment(t.toExpression(declaration.node))); 75 | } 76 | } else { 77 | path.replaceWith(buildExportsAssignment(declaration.node)); 78 | } 79 | continue; 80 | } 81 | 82 | if (path.isImportDeclaration()) { 83 | let specifiers = path.node.specifiers; 84 | let is2015Compatible = path.node.source.value.match(/babel-runtime[\\\/]/); 85 | if (specifiers.length == 0) { 86 | anonymousSources.push(buildRequire(path.node.source)); 87 | } else if (specifiers.length == 1 && specifiers[0].type == 'ImportDefaultSpecifier') { 88 | let template = is2015Compatible ? buildRequireDefault : buildRequire; 89 | sources.push(t.variableDeclaration("var", [ 90 | t.variableDeclarator(t.identifier(specifiers[0].local.name), template ( 91 | path.node.source 92 | ).expression) 93 | ])); 94 | } else { 95 | let importedID = addSource(path); 96 | 97 | specifiers.forEach(({imported, local}) => { 98 | if (!imported || (!is2015Compatible && imported.name === 'default')) { 99 | sources.push(t.variableDeclaration("var", [ 100 | t.variableDeclarator(t.identifier(local.name), t.identifier(importedID.name)) 101 | ])); 102 | } else { 103 | sources.push(t.variableDeclaration("var", [ 104 | t.variableDeclarator(t.identifier(local.name), t.identifier(importedID.name + '.' + imported.name)) 105 | ])); 106 | } 107 | }); 108 | } 109 | 110 | path.remove(); 111 | continue; 112 | } 113 | 114 | if (path.isExportNamedDeclaration()) { 115 | lastExportPath = path; 116 | let declaration = path.get("declaration"); 117 | 118 | // if we are exporting a class/function/variable 119 | if (declaration.node) { 120 | hasNamedExports = true; 121 | if (declaration.isFunctionDeclaration()) { 122 | let id = declaration.node.id; 123 | path.replaceWithMultiple([ 124 | declaration.node, 125 | buildNamedExportsAssignment(id, id) 126 | ]); 127 | } else if (declaration.isClassDeclaration()) { 128 | let id = declaration.node.id; 129 | path.replaceWithMultiple([ 130 | declaration.node, 131 | buildNamedExportsAssignment(id, id) 132 | ]); 133 | } else if (declaration.isVariableDeclaration()) { 134 | let declarators = declaration.get("declarations"); 135 | for (let decl of declarators) { 136 | let id = decl.get("id"); 137 | 138 | let init = decl.get("init"); 139 | if (!init.node) { 140 | init.replaceWith(t.identifier("undefined")); 141 | } 142 | 143 | if (id.isIdentifier()) { 144 | init.replaceWith(buildNamedExportsAssignment(id.node, init.node).expression); 145 | } 146 | } 147 | path.replaceWith(declaration.node); 148 | } 149 | continue; 150 | } 151 | 152 | // if we are exporting already instantiated variables 153 | let specifiers = path.get("specifiers"); 154 | if (specifiers.length) { 155 | let nodes = []; 156 | let source = path.node.source; 157 | let importedID; 158 | if (source) { 159 | // export a from 'b'; 160 | // 'b' is the source 161 | importedID = addSource(path); 162 | } 163 | 164 | for (let specifier of specifiers) { 165 | if (specifier.isExportSpecifier()) { 166 | let local = specifier.node.local; 167 | 168 | // if exporting from we need to modify the local lookup 169 | if (importedID) { 170 | if (local.name === 'default') { 171 | local = importedID; 172 | } else { 173 | local = t.memberExpression(importedID, local); 174 | } 175 | } 176 | 177 | // if exporting to default, its module.exports 178 | if (specifier.node.exported.name === 'default') { 179 | hasDefaultExport = true; 180 | nodes.push(buildExportsAssignment(local)); 181 | } else { 182 | hasNamedExports = true; 183 | nodes.push(buildNamedExportsAssignment(specifier.node.exported, local)); 184 | } 185 | } 186 | } 187 | 188 | path.replaceWithMultiple(nodes); 189 | } 190 | continue; 191 | } 192 | 193 | if (path.isExportAllDeclaration()) { 194 | // export * from 'a'; 195 | let importedID = addSource(path); 196 | let keyName = path.scope.generateUidIdentifier(importedID.name + "_key") 197 | 198 | path.replaceWithMultiple(buildExportAll(importedID, keyName)); 199 | } 200 | } 201 | 202 | if (hasNamedExports && hasDefaultExport) { 203 | throw lastExportPath.buildCodeFrameError('The simple-commonjs plugin does not support both a export default and a export named in the same file. This is because the module.exports would override any export'); 204 | } 205 | 206 | path.unshiftContainer("body", sources.concat(anonymousSources)); 207 | } 208 | } 209 | } 210 | }; 211 | }; 212 | --------------------------------------------------------------------------------