pax_global_header00006660000000000000000000000064130374264070014520gustar00rootroot0000000000000052 comment=bcdd07c2cc624f1cff30e5401b9c92b86c96a4e8 modify-babel-preset-3.2.1/000077500000000000000000000000001303742640700153555ustar00rootroot00000000000000modify-babel-preset-3.2.1/.gitignore000066400000000000000000000001161303742640700173430ustar00rootroot00000000000000/node_modules /npm-debug.log /test/fixtures/two/node_modules/one/node_modules modify-babel-preset-3.2.1/.travis.yml000066400000000000000000000000471303742640700174670ustar00rootroot00000000000000language: node_js node_js: - 5 - 6 modify-babel-preset-3.2.1/README.md000066400000000000000000000037211303742640700166370ustar00rootroot00000000000000 # modify-babel-preset [![npm](https://img.shields.io/npm/v/modify-babel-preset.svg)](http://npm.im/modify-babel-preset) [![npm](https://img.shields.io/npm/dm/modify-babel-preset.svg)](http://npm.im/modify-babel-preset) [![travis](https://travis-ci.org/developit/modify-babel-preset.svg?branch=master)](https://travis-ci.org/developit/modify-babel-preset) Create a modified babel preset based on an an existing preset. > Works best with `npm 3`. ```sh npm i -S modify-babel-preset ``` --- - [API](#api) - [Add/Update Plugins](#addupdate-plugins) - [Remove Plugins](#remove-plugins) - [Example](#example) --- ## API A single function that takes an existing preset name and a mapping of plugin modifications to apply to that preset. _Make sure you have the preset and any added plugins installed as dependencies._ ```js newPreset = modifyBabelPreset( 'existing-preset-name', { 'plugin-name': false, // remove 'other-plugin': true, // add 'foo': { loose:true } // add + config } ); ``` > Modification keys are babel plugin names _(you can exclude the `babel-plugin-` prefix)._ ### Add/Update Plugins To add a plugin, pass `true`, or a configuration object: ```js { // just add a plugin without config: 'plugin-name': true, // add a plugin and set its config 'other-plugin': { loose:true } } ``` > **Note:** adding a plugin that is already provided by the preset just overwrites its configuration. ### Remove Plugins To remove a plugin, pass `false`: ```js { 'plugin-name': false } ``` --- ## Example Here's a simple preset. Just this `index.js` and a package.json pointing to it with the preset and plugin installed as dependencies. ```js var modifyBabelPreset = require('modify-babel-preset'); // just export the cloned, modified preset config: module.exports = modifyBabelPreset('es2015', { // remove the typeof x==='symbol' transform: 'transform-es2015-typeof-symbol': false, // add the JSX transform: 'transform-react-jsx': true }); ``` modify-babel-preset-3.2.1/index.js000066400000000000000000000076651303742640700170400ustar00rootroot00000000000000var path = require('path'); var relative = require('require-relative'); var serialize = require('./lib/serialize'); var getFlattenedPlugins = require('./lib/flatten'); var normalizePreset = require('./lib/normalize-preset'); // strip a nested module path + filename down to just the innermost module's (file)name function getModuleName(path) { return path.replace(/(?:..[\\/])*(?:(?:.+[\\/])?node_modules[\\/]|[\\/]|\.\.[\\/])((@[^\\/]+[\\/])?[^\\/]+)([\\/].*)?$/g, '$1'); } function setHiddenProp(obj, prop, value) { if (Object.defineProperty) { Object.defineProperty(obj, prop, { enumerable: false, writable: true, value: value }); } else { obj[prop] = value; } } function extend(base, props) { for (var i in props) if (props.hasOwnProperty(i)) { base[i] = props[i]; } return base; } function requireBabelPlugin(name, relativeTo) { if (!name.match(/^babel-plugin-/)) { name = 'babel-plugin-' + name; } var relativeName; if (relativeTo) { try { relativeName = relative.resolve(name, relativeTo); } catch (err) {} } if (!relativeName) { try { relativeName = require.resolve(name); } catch(err) {} } name = relativeName || name; return { mod:require(name), name:name }; } module.exports = function(presetInput, modifications) { var options = {}; if (Array.isArray(presetInput)) { options = presetInput[1]; presetInput = presetInput[0]; } modifications = modifications || {}; var preset; if (typeof presetInput==='string') { if (!presetInput.match(/(^babel-preset-|[\\/])/)) { try { preset = relative.resolve('babel-preset-'+presetInput, __dirname); } catch(err) { console.log(err); } } if (!preset) { preset = require.resolve(presetInput); } } preset = path.resolve(preset); var presetModule = normalizePreset(require(preset), null, options); var orig = presetModule['modify-babel-preset']; if (orig) { console.log('Found nested modify-babel-preset configuration, flattening.'); return modify(orig.preset, extend(extend({}, orig.modifications), modifications)); } var cwd = path.dirname(preset) || process.cwd(); // console.log('cwd: ', cwd); var serialized = serialize(preset, { options: options, cwd: cwd }); var alias = serialized.alias; var plugins = getFlattenedPlugins(serialized); function isSameName(a, b) { if (typeof a!=='string' || typeof b!=='string') return false; return a.replace(/^babel-plugin-/i, '').toLowerCase() === b.replace(/^babel-plugin-/i, '').toLowerCase(); } function indexOf(plugins, key) { for (var i=plugins.length; i--; ) { var mod = Array.isArray(plugins[i]) ? plugins[i][0] : plugins[i]; var name = typeof mod==='string' && getModuleName(mod) || mod._original_name; name = alias[name] || name; if (isSameName(name, key)) { return i; } } return -1; } Object.keys(modifications).forEach(function(key) { if (key==='nameDrops' || key==='string') return; var value = modifications[key], index = indexOf(plugins, key); if (value===false) { if (index!==-1) { plugins.splice(index, 1); } else if (process.env.NODE_ENV==='development') { console.warn(key+' not found', __dirname); } } else { var imported = requireBabelPlugin(key, cwd), p = imported.mod; setHiddenProp(p, '_original_name', imported.name); if (value!==true) { p = [p].concat(value); } if (index<0) { plugins.push(p); } else { plugins[index] = p; } } }); if (modifications.string!==true) { plugins = plugins.map(function(plugin) { var mod = Array.isArray(plugin) ? plugin[0] : plugin; if (typeof mod==='string') { var p = path.resolve(cwd, mod); mod = require(p); setHiddenProp(mod, '_original_name', p); } return Array.isArray(plugin) ? [mod].concat(plugin.slice(1)) : mod; }); } var out = { plugins:plugins }; setHiddenProp(out, 'modify-babel-preset', { preset: path.dirname(path.resolve(preset)), modifications: modifications }); return out; }; modify-babel-preset-3.2.1/lib/000077500000000000000000000000001303742640700161235ustar00rootroot00000000000000modify-babel-preset-3.2.1/lib/flatten.js000066400000000000000000000003761303742640700201240ustar00rootroot00000000000000module.exports = function flatten(preset) { var plugins = [].concat(preset.plugins || []); (preset.presets || []).forEach(function(child) { var children = flatten(child); if (children) plugins = plugins.concat(children); }); return plugins; }; modify-babel-preset-3.2.1/lib/normalize-preset.js000066400000000000000000000005751303742640700217700ustar00rootroot00000000000000var babelCore; try { babelCore = require('babel-core'); } catch(err) {} module.exports = function normalizePreset(preset, context, options) { if (!context) context = babelCore; if (preset && typeof preset==='object' && preset.buildPreset) { preset = preset.buildPreset; } if (typeof preset==='function') { preset = preset(context, options || {}); } return preset; }; modify-babel-preset-3.2.1/lib/serialize.js000066400000000000000000000075751303742640700204660ustar00rootroot00000000000000var fs = require('fs'); var path = require('path'); var requireRelative = require('require-relative'); var normalizePreset = require('./normalize-preset'); var join = path.join; var dirname = path.dirname; var relative = path.relative; function getModulePath(filepath) { return filepath.replace(/(.*([\\/]node_modules|\.\.)[\\/](@[^\\/]+[\\/])?[^\\/]+)([\\/].*)?$/g, '$1') } // Attempt to require a module, returning false on error function req(name) { try { return require(name); } catch (err) { return false; } } // Attempt to resolve a module, returning `undefined` on error function resolve(name, relativeTo) { var path = false; try { path = requireRelative.resolve(name, relativeTo); } catch (err) { console.log('resolve failed for "'+name+'": '+err); } return path; } // fast npm always use symlink // and it resulted in module duplicated // or alias function fillAliasMap(path, list, map) { return list.reduce(function (symlinkedList, mod) { var realPath = relative(path, fs.realpathSync(join(path, mod))); if (realPath !== mod) { symlinkedList[realPath] = (mod); } return symlinkedList; }, map || {}); } // Get a list of child module names for the given module path function getChildren(path, type, alias) { var modules; try { modules = fs.readdirSync(join(path, 'node_modules')); } catch (err) { path = path.replace(/([\\/]node_modules)([\\/].*)?$/g, '$1'); modules = fs.readdirSync(path); } var children = (modules || []) .filter( realFile ) .sort( reverseSorter(type==='plugin' ? isPlugin : isPreset) ); fillAliasMap(path, children, alias); return children; } // is a filename an actual file function realFile(f) { return f && f.charAt(0)!=='.'; } // ascending sort based on the truthiness of a function function reverseSorter(comparison) { return function(a, b) { var ca = comparison(a), cb = comparison(b); return ca===cb ? 0 : (ca ? 1 : cb ? -1 : 0); } } function isPreset(name) { return name && name.match(/^babel\-preset\-/g); } function isPlugin(name) { return name && name.match(/^babel\-plugin\-/g); } // find the matching module *instance* in a list of module paths, remove and return it function findAndRemove(preset, path, list) { for (var i=list.length; i--; ) { var p = resolve(list[i], path), v = p && req(p); if (v && v===preset) { list.splice(i, 1); return p; } } } /** Resolve & serialize a Babel preset to a filename-based representation. * Nested filepaths are relative to `relativeTo` if specified. * Presets referenced as Strings (uncommon) are treated as dependencies of the preset that returned them. */ function loadPreset(name, opts, relativeTo) { var path = resolve(name, relativeTo), mod = normalizePreset(path && req(path), null, opts.options); if (!mod) throw new Error('Preset "'+name+'" not found.'); path = dirname(path); var out = { alias: {} }; if (mod.presets) { var availablePresets = getChildren(path, 'preset', out.alias); out.presets = mod.presets.map(function(preset) { if (typeof preset!=='string') { preset = findAndRemove(preset, path, availablePresets); } return loadPreset(preset, opts, path); }); } if (mod.plugins) { var availablePlugins = getChildren(path, 'plugin', out.alias); out.plugins = mod.plugins.map(function(plugin) { var name = Array.isArray(plugin) ? plugin[0] : plugin; if (typeof name!=='string') { if (name._original_name) { // console.log('using _original_name: ', name._original_name); name = name._original_name; } else { name = findAndRemove(name, path, availablePlugins); } } if (!name) return plugin; name = resolve(name, path); name = getModulePath(name); if (opts) { if (opts.cwd) name = relative(opts.cwd, name); if (opts.transform) name = opts.transform(name); } return Array.isArray(plugin) ? [name].concat(plugin.slice(1)) : name; }); } return out; } module.exports = loadPreset; modify-babel-preset-3.2.1/package.json000066400000000000000000000016531303742640700176500ustar00rootroot00000000000000{ "name": "modify-babel-preset", "version": "3.2.1", "description": "Create a modified babel preset based on an an existing preset.", "main": "index.js", "scripts": { "prepublish": "cross-env NODE_ENV=development npm test", "pretest": "cd test/fixtures/two/node_modules/one && npm i", "test": "mocha test/*.js", "release": "git commit -am $npm_package_version && git tag $npm_package_version && git push && git push --tags && npm publish" }, "keywords": [ "babel", "preset" ], "author": "Jason Miller ", "repository": { "type": "git", "url": "https://github.com/developit/modify-babel-preset.git" }, "license": "MIT", "dependencies": { "require-relative": "^0.8.7" }, "devDependencies": { "babel-plugin-transform-react-jsx": "^6.8.0", "babel-preset-es2015": "^6.9.0", "chai": "^3.5.0", "cross-env": "^2.0.0", "mocha": "^2.5.3" } } modify-babel-preset-3.2.1/test/000077500000000000000000000000001303742640700163345ustar00rootroot00000000000000modify-babel-preset-3.2.1/test/fixtures/000077500000000000000000000000001303742640700202055ustar00rootroot00000000000000modify-babel-preset-3.2.1/test/fixtures/two/000077500000000000000000000000001303742640700210165ustar00rootroot00000000000000modify-babel-preset-3.2.1/test/fixtures/two/index.js000066400000000000000000000004451303742640700224660ustar00rootroot00000000000000var path = require('path'), modify = require('../../../'); // module.exports = modify(path.resolve(__dirname+'/node_modules/one'), { module.exports = modify(require.resolve('one'), { // nameDrops: false, 'transform-es2015-typeof-symbol': false, 'transform-react-jsx': { pragma:'z' }, }); modify-babel-preset-3.2.1/test/fixtures/two/node_modules/000077500000000000000000000000001303742640700234735ustar00rootroot00000000000000modify-babel-preset-3.2.1/test/fixtures/two/node_modules/one/000077500000000000000000000000001303742640700242545ustar00rootroot00000000000000modify-babel-preset-3.2.1/test/fixtures/two/node_modules/one/index.js000066400000000000000000000003021303742640700257140ustar00rootroot00000000000000var modify = require('../../../../../'); module.exports = modify('es2015', { // nameDrops: false, 'transform-react-jsx': { pragma:'h' }, 'transform-es2015-typeof-symbol': { loose:true } }); modify-babel-preset-3.2.1/test/fixtures/two/node_modules/one/package.json000066400000000000000000000001711303742640700265410ustar00rootroot00000000000000{ "name": "one", "main": "./index.js", "devDependencies": { "babel-plugin-transform-react-jsx": "^6.6.5" } } modify-babel-preset-3.2.1/test/fixtures/two/package.json000066400000000000000000000002411303742640700233010ustar00rootroot00000000000000{ "name": "two", "main": "./index.js", "dependencies": { "one": "*" }, "devDependencies": { "babel-plugin-transform-react-jsx": "^6.6.5" } } modify-babel-preset-3.2.1/test/index.js000066400000000000000000000073021303742640700200030ustar00rootroot00000000000000var expect = require('chai').expect, requireRelative = require('require-relative'), modifyBabelPreset = require('..'), serializePreset = require('../lib/serialize'), es2015Preset = callFn(require('babel-preset-es2015')), transform = requireRelative('babel-preset-es2015', 'babel-plugin-transform-es2015-typeof-symbol'), jsxCore = require('babel-plugin-transform-react-jsx'), jsx = require('./fixtures/two/node_modules/one/node_modules/babel-plugin-transform-react-jsx'); function callFn(r) { if (typeof r==='function') r = r(); return r; } describe('modify-babel-preset', function() { it('should import string presets', function() { var out = modifyBabelPreset('babel-preset-es2015'); expect(out).to.deep.equal(es2015Preset); }); it('should import string presets without babel-preset- prefix', function() { var out = modifyBabelPreset('es2015'); expect(out).to.deep.equal(es2015Preset); }); it('should remove for false values', function() { var out = modifyBabelPreset('es2015', { 'transform-es2015-typeof-symbol': false }); expect(out.plugins).to.have.length(es2015Preset.plugins.length-1); expect(out.plugins).not.to.include(transform); }); it('should add for true values', function() { var out = modifyBabelPreset('es2015', { // nameDrops: false, 'transform-react-jsx': true }); expect(out.plugins).to.deep.equal( es2015Preset.plugins.concat(jsxCore) ); }); it('should add values with config', function() { var out = modifyBabelPreset('es2015', { nameDrops: false, 'transform-react-jsx': { pragma:'h' } }); expect(out.plugins).to.deep.equal( es2015Preset.plugins.concat([ [jsxCore, { pragma:'h' }] ]) ); }); xit('should work recursively', function() { var one = require('./fixtures/two/node_modules/one'); // var reference = serializePreset(require.resolve('babel-preset-es2015')).plugins.map( p => ( // Array.isArray(p) ? [getModuleName(p[0])].concat(p.slice(1)) : getModuleName(p) // )); // // var actual = one.plugins.map( p => ( // Array.isArray(p) ? [getModuleName(p[0]._original_name)].concat(p.slice(1)) : getModuleName(p._original_name) // )); // // // expect(reference).to.deep.equal(actual, 'Equal when serialized'); // // actual.forEach( (actual, i) => { // if (actual!==reference[i]) { // console.log(i+'\n actual: '+ JSON.stringify(actual)+'\n ref: '+ JSON.stringify(reference[i])); // console.log(' ===json? ', JSON.stringify(actual)===JSON.stringify(reference[i])); // //console.log(' ===func? ', one.plugins[i][0]===es2015Preset.plugins[i][0]); // } // }); // // function getModuleName(path) { // return path.replace(/^(.+\/)?node_modules\/([^\/]+)(\/.*)?$/g, '$2'); // } function stripNames(p) { if (Array.isArray(p)) delete p[0]._original_name; else delete p._original_name; return p; } var p = one.plugins.map(stripNames); expect(p).to.deep.equal( es2015Preset.plugins.concat([ [jsx, { pragma:'h' }] ]).map(function(p) { var fn = Array.isArray(p) ? p[0] : p; if (fn===transform || (fn._original_name && ~fn._original_name.indexOf('babel-plugin-transform-es2015-typeof-symbol'))) { return [fn, { loose:true }]; } return p; }).map(stripNames) ); console.log('one matched'); var two = require('./fixtures/two'); two.plugins.forEach(function(p) { var f = Array.isArray(p) ? p[0] : p; //delete p._original_name; }); // delete transform._original_name; // delete jsx._original_name; var target = es2015Preset.plugins.concat([ [jsx, { pragma:'z' }] ]); target.splice(17, 1); two.plugins = two.plugins.map(p => p+''); target = target.map(p => p+''); // console.log(two.plugins[17]===target[17]); expect(two.plugins).to.deep.equal(target); }); });