├── .babelrc ├── .flowconfig ├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── package.json ├── rollup.config.js ├── script └── bootstrap ├── src └── index.js └── test ├── mocha.opts └── test.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["es2015", { "modules": false }] 4 | ], 5 | "plugins": ["syntax-flow", "transform-flow-strip-types", "syntax-object-rest-spread", "transform-object-rest-spread"] 6 | } 7 | -------------------------------------------------------------------------------- /.flowconfig: -------------------------------------------------------------------------------- 1 | [ignore] 2 | /node_modules/semantic-release/.* 3 | /node_modules/config-chain/.* 4 | /node_modules/npmconf/.* 5 | 6 | [include] 7 | 8 | [libs] 9 | 10 | [options] 11 | munge_underscores=true 12 | esproposal.class_instance_fields=enable 13 | suppress_comment=\\(.\\|\n\\)*\\$FlowIssue 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: node_js 3 | cache: 4 | directories: 5 | - node_modules 6 | notifications: 7 | email: false 8 | node_js: 9 | - '6' 10 | - '4' 11 | before_install: 12 | - npm i -g npm@^2.0.0 13 | before_script: 14 | - npm prune 15 | after_success: 16 | - 'curl -Lo travis_after_all.py https://git.io/travis_after_all' 17 | - python travis_after_all.py 18 | - export $(cat .to_export_back) &> /dev/null 19 | - npm run semantic-release 20 | branches: 21 | except: 22 | - /^v\d+\.\d+\.\d+$/ 23 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Brian Donovan 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # babelrc-rollup 2 | 3 | Builds a babel configuration for rollup-plugin-babel by reading .babelrc. 4 | 5 | ## Install 6 | 7 | ``` 8 | $ npm install --save-dev babelrc-rollup 9 | ``` 10 | 11 | ## Usage 12 | 13 | Create a `.babelrc` file at the root of your project as normal: 14 | 15 | ```json 16 | { 17 | "presets": ["es2015"] 18 | } 19 | ``` 20 | 21 | Inside your `rollup.config.js`, do this: 22 | 23 | ```js 24 | import babelrc from 'babelrc-rollup'; 25 | import babel from 'rollup-plugin-babel'; 26 | 27 | export default { 28 | … 29 | plugins: [ 30 | babel(babelrc()) 31 | ] 32 | … 33 | }; 34 | ``` 35 | 36 | ### Options 37 | 38 | #### `path` (default: `'.babelrc'`) 39 | 40 | If you'd like to customize the path of your babelrc file, pass this option with 41 | a string path that can be read using `fs.readFile`. 42 | 43 | #### `config` 44 | 45 | Use this to avoid reading a babelrc file at all. You could use this to pull the 46 | config from `package.json` instead, for example. 47 | 48 | #### `addModuleOptions` (default: `true`) 49 | 50 | Disable this option if you do not want the `modules: false` option to be given 51 | to presets in your babel config. You probably don't want to change this unless 52 | you're using `findRollupPresets`. 53 | 54 | #### `findRollupPresets` (default: `false`) 55 | 56 | Enable this to replace presets with the equivalent rollup-compatible preset, if 57 | available. When this option is enabled, babelrc-rollup will try to resolve e.g. 58 | `es2015-rollup` instead of `es2015`. If no such preset can be found the original 59 | will be used. 60 | 61 | #### `addExternalHelpersPlugin` (default: `true`) 62 | 63 | By default, babelrc-rollup adds the [`external-helpers` plugin][external-helpers], 64 | which ensures that only one copy of each helper ends up in your bundle. Disable 65 | this option to prevent adding this plugin. 66 | 67 | 68 | ## A note on babel versions 69 | 70 | Since babel [v6.13.0][6-13-0], presets may be given options by using a tuple of 71 | `[name, opts]`. For example, instead of 72 | 73 | ```js 74 | { 75 | "presets": ["es2015"] 76 | } 77 | ``` 78 | 79 | You can do this: 80 | 81 | ```js 82 | { 83 | "presets": [ 84 | ["es2015", { "modules": false }] 85 | ] 86 | } 87 | ``` 88 | 89 | babelrc-rollup is meant to work with this version of babel or later, but earlier 90 | versions are supported by using the right options. The old way to configure the 91 | `es2015` preset for use with rollup was to use the `es2015-rollup` preset 92 | instead. To continue doing that, call `babelrc` like so: 93 | 94 | ```js 95 | babelrc({ 96 | addModuleOptions: false, 97 | findRollupPresets: true, 98 | addExternalHelpersPlugin: false 99 | }) 100 | ``` 101 | 102 | If you use the `es2015` preset, make sure you install `es2015-rollup` too. If 103 | you can use babel v6.13.0 or later, you should do so. 104 | 105 | [external-helpers]: https://babeljs.io/docs/plugins/external-helpers/ 106 | [6-13-0]: https://github.com/babel/babel/blob/master/CHANGELOG.md#v6130-2016-08-04 107 | [rollup-config]: https://github.com/eventualbuddha/babelrc-rollup/blob/master/rollup.config.js 108 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "babelrc-rollup", 3 | "description": "Builds a babel configuration for rollup-plugin-babel by reading .babelrc.", 4 | "main": "dist/babelrc-rollup.js", 5 | "jsnext:main": "dist/babelrc-rollup.mjs", 6 | "scripts": { 7 | "flow": "flow check", 8 | "build": "rollup -c", 9 | "pretest": "npm run flow && npm run bootstrap", 10 | "test": "mocha", 11 | "bootstrap": "./script/bootstrap", 12 | "prepublish": "npm test", 13 | "semantic-release": "semantic-release pre && npm publish && semantic-release post" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/eventualbuddha/babelrc-rollup.git" 18 | }, 19 | "keywords": [ 20 | "babel", 21 | "rollup" 22 | ], 23 | "files": [ 24 | "dist" 25 | ], 26 | "author": "Brian Donovan ", 27 | "license": "MIT", 28 | "bugs": { 29 | "url": "https://github.com/eventualbuddha/babelrc-rollup/issues" 30 | }, 31 | "homepage": "https://github.com/eventualbuddha/babelrc-rollup#readme", 32 | "devDependencies": { 33 | "babel-cli": "^6.11.4", 34 | "babel-plugin-external-helpers": "^6.8.0", 35 | "babel-plugin-syntax-flow": "^6.13.0", 36 | "babel-plugin-syntax-object-rest-spread": "^6.13.0", 37 | "babel-plugin-transform-es2015-parameters": "^6.11.4", 38 | "babel-plugin-transform-flow-strip-types": "^6.8.0", 39 | "babel-plugin-transform-object-rest-spread": "^6.8.0", 40 | "babel-preset-es2015": "^6.13.2", 41 | "flow-bin": "^0.30.0", 42 | "mocha": "^3.0.2", 43 | "reify": "^0.3.6", 44 | "rollup": "^0.34.7", 45 | "rollup-plugin-babel": "^2.6.1", 46 | "semantic-release": "^4.3.5" 47 | }, 48 | "publishConfig": { 49 | "registry": "https://registry.npmjs.org/" 50 | }, 51 | "dependencies": { 52 | "resolve": "^1.1.7" 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import babel from 'rollup-plugin-babel'; 2 | import babelrc from './dist/babelrc-rollup.mjs'; 3 | 4 | let pkg = require('./package.json'); 5 | 6 | export default { 7 | entry: 'src/index.js', 8 | plugins: [babel(babelrc())], 9 | external: Object.keys(pkg['dependencies']).concat(['fs']), 10 | targets: [ 11 | { 12 | dest: pkg['jsnext:main'], 13 | exports: 'named', 14 | format: 'es' 15 | }, 16 | { 17 | dest: pkg['main'], 18 | exports: 'named', 19 | format: 'cjs' 20 | } 21 | ] 22 | }; 23 | -------------------------------------------------------------------------------- /script/bootstrap: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | 5 | # reset dist 6 | rm -rf dist 7 | mkdir -p dist 8 | 9 | # use babel directly to create the ES module version 10 | babel \ 11 | src/index.js \ 12 | -o dist/babelrc-rollup.mjs 13 | 14 | # test our rollup build with the babel-built version 15 | npm run build 16 | 17 | # test our rollup build again with the rollup-built version 18 | npm run build 19 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /* @flow */ 2 | 3 | import { readFileSync } from 'fs'; 4 | import { sync as resolve } from 'resolve'; 5 | 6 | function startsWith(string: string, prefix: string): boolean { 7 | return string.lastIndexOf(prefix, 0) === 0; 8 | } 9 | 10 | type Preset = any; 11 | 12 | type BabelConfig = { 13 | filename?: string; 14 | filenameRelative?: string; 15 | presets?: Array; 16 | plugins?: Array; 17 | highlightCode?: boolean; 18 | only?: ?(RegExp | string | Array); 19 | ignore?: ?(RegExp | string | Array); 20 | auxiliaryCommentBefore?: ?string; 21 | auxiliaryCommentAfter?: ?string; 22 | sourceMaps?: boolean; 23 | inputSourceMap?: ?Object; 24 | sourceMapTarget?: string; 25 | sourceFileName?: string; 26 | sourceRoot?: string; 27 | moduleRoot?: string; 28 | moduleIds?: boolean; 29 | moduleId?: string; 30 | getModuleId?: (moduleName: string) => ?string; 31 | resolveModuleSource?: (source: string, filename: string) => ?string; 32 | code?: boolean; 33 | babelrc?: boolean; 34 | ast?: boolean; 35 | compact?: boolean | 'auto'; 36 | comments?: boolean; 37 | shouldPrintComment?: (commentContents: string) => boolean; 38 | env?: {[key: string]: BabelConfig}; 39 | retainLines?: boolean; 40 | extends?: ?string; 41 | }; 42 | 43 | type Options = { 44 | path?: string; 45 | config?: BabelConfig; 46 | findRollupPresets?: boolean; 47 | addModuleOptions?: boolean; 48 | addExternalHelpersPlugin?: boolean; 49 | resolve?: (path: string) => string; 50 | }; 51 | 52 | const DEFAULT_OPTIONS = { 53 | path: '.babelrc', 54 | findRollupPresets: false, 55 | addModuleOptions: true, 56 | addExternalHelpersPlugin: true, 57 | resolve 58 | }; 59 | 60 | export default function babelrc(options: Options|string={}): BabelConfig { 61 | if (typeof options === 'string') { 62 | options = { path: options }; 63 | } 64 | 65 | let resolvedOptions = { ...DEFAULT_OPTIONS, ...options }; 66 | 67 | if (!resolvedOptions.config && typeof resolvedOptions.path === 'string') { 68 | resolvedOptions.config = JSON.parse(readFileSync(resolvedOptions.path, { encoding: 'utf8' })); 69 | } 70 | 71 | return configWithoutModules(resolvedOptions.config, resolvedOptions); 72 | } 73 | 74 | export function configWithoutModules(config: BabelConfig, options: Options): BabelConfig { 75 | let result = {}; 76 | 77 | for (let key in config) { 78 | if (Object.prototype.hasOwnProperty.call(config, key)) { 79 | if (key === 'presets' && config.presets) { 80 | // Replace the es2015 preset with the es2015-rollup preset. 81 | result.presets = config.presets.map(preset => mapPreset(preset, options)); 82 | } else if (key === 'plugins' && config.plugins) { 83 | // Remove any explicit module plugins, e.g. es2015-modules-commonjs. 84 | result.plugins = config.plugins.filter( 85 | plugin => !startsWith(plugin, 'es2015-modules-') 86 | ); 87 | } else { 88 | result[key] = config[key]; 89 | } 90 | } 91 | } 92 | 93 | if (options.addExternalHelpersPlugin) { 94 | if (!result.plugins) { 95 | result.plugins = ['external-helpers']; 96 | } else { 97 | result.plugins = [...result.plugins, 'external-helpers']; 98 | } 99 | } 100 | 101 | // Make sure babel does not look for the babelrc file. 102 | result.babelrc = false; 103 | 104 | return result; 105 | } 106 | 107 | function mapPreset(preset: any, options: Options): any { 108 | let info = getPresetInfo(preset); 109 | 110 | if (!info) { 111 | return preset; 112 | } 113 | 114 | if (options.findRollupPresets && hasRollupVersionOfPreset(info.name, options.resolve || resolve)) { 115 | return [`${info.name}-rollup`, info.options]; 116 | } else if (options.addModuleOptions) { 117 | return [info.name, { ...info.options, modules: false }]; 118 | } else { 119 | return preset; 120 | } 121 | } 122 | 123 | function getPresetInfo(preset: any): ?{ name: string, options: Object } { 124 | if (typeof preset === 'string') { 125 | return { name: preset, options: {} }; 126 | } else if (Array.isArray(preset)) { 127 | let name = preset[0]; 128 | let options = preset[1] || {}; 129 | 130 | if (typeof name === 'string' && typeof options === 'object') { 131 | return { name, options }; 132 | } 133 | } 134 | 135 | return null; 136 | } 137 | 138 | function hasRollupVersionOfPreset(preset: string, resolve: (path: string) => string): boolean { 139 | try { 140 | // this will throw if it can't resolve it 141 | resolve(`babel-preset-${preset}-rollup`); 142 | return true; 143 | } catch (err) { 144 | return false; 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /test/mocha.opts: -------------------------------------------------------------------------------- 1 | --require reify 2 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | import babelrc from '..'; 2 | import { deepEqual, strictEqual } from 'assert'; 3 | 4 | describe('babelrc-rollup', () => { 5 | it('configures presets without config with modules: false', () => { 6 | deepEqual( 7 | babelrc({ 8 | config: { 9 | presets: [ 10 | 'es2015' 11 | ] 12 | } 13 | }).presets, 14 | [ 15 | ['es2015', { modules: false }] 16 | ] 17 | ); 18 | }); 19 | 20 | it('configures presets with config with modules: false', () => { 21 | deepEqual( 22 | babelrc({ 23 | config: { 24 | presets: [ 25 | ['es2015', { loose: true }] 26 | ] 27 | } 28 | }).presets, 29 | [ 30 | ['es2015', { loose: true, modules: false }] 31 | ] 32 | ); 33 | }); 34 | 35 | it('configures plugins to add external-helpers', () => { 36 | deepEqual( 37 | babelrc({ 38 | config: { 39 | plugins: [] 40 | } 41 | }).plugins, 42 | ['external-helpers'] 43 | ); 44 | }); 45 | 46 | it('prevents reading from a babelrc file', () => { 47 | strictEqual( 48 | babelrc({ 49 | config: {} 50 | }).babelrc, 51 | false 52 | ); 53 | }); 54 | 55 | it('allows searching for rollup-compatible alternatives for presets', () => { 56 | deepEqual( 57 | babelrc({ 58 | config: { 59 | presets: ['foo', 'bar'] 60 | }, 61 | findRollupPresets: true, 62 | // provide a mock version of the resolve method 63 | resolve(path) { 64 | if (path === 'babel-preset-foo-rollup') { 65 | return path; 66 | } else { 67 | throw new Error(`intentionally failing to resolve: ${path}`); 68 | } 69 | } 70 | }).presets, 71 | [ 72 | ['foo-rollup', {}], 73 | ['bar', { modules: false }] 74 | ] 75 | ) 76 | }); 77 | 78 | it('allows disabling setting the `modules` option', () => { 79 | deepEqual( 80 | babelrc({ 81 | config: { 82 | presets: ['foo', 'bar'] 83 | }, 84 | addModuleOptions: false 85 | }).presets, 86 | [ 'foo', 'bar' ] 87 | ) 88 | }); 89 | 90 | it('allows disabling adding the `external-helpers` plugin', () => { 91 | deepEqual( 92 | babelrc({ 93 | config: { 94 | plugins: [] 95 | }, 96 | addExternalHelpersPlugin: false 97 | }).plugins, 98 | [] 99 | ); 100 | }); 101 | }); 102 | --------------------------------------------------------------------------------