From c9286a1de1f7ef8e88396414c23233918d2f868b Mon Sep 17 00:00:00 2001 From: Sebastian McKenzie Date: Wed, 10 Jun 2015 03:07:06 +0100 Subject: [PATCH] rewrite option handling - fixes #1636 --- packages/babel-cli/bin/babel/index.js | 9 ++- src/babel/api/node.js | 2 +- src/babel/api/register/node.js | 4 +- src/babel/tools/resolve-rc.js | 62 ++----------------- src/babel/transformation/file/index.js | 33 +++++----- .../transformation/file/option-parsers.js | 27 -------- .../{options.json => options/config.json} | 12 ++-- .../transformation/file/options/index.js | 32 ++++++++++ .../transformation/file/options/parsers.js | 29 +++++++++ .../transformation/file/options/resolve-rc.js | 62 +++++++++++++++++++ src/babel/util.js | 2 +- 11 files changed, 165 insertions(+), 109 deletions(-) delete mode 100644 src/babel/transformation/file/option-parsers.js rename src/babel/transformation/file/{options.json => options/config.json} (95%) create mode 100644 src/babel/transformation/file/options/index.js create mode 100644 src/babel/transformation/file/options/parsers.js create mode 100644 src/babel/transformation/file/options/resolve-rc.js diff --git a/packages/babel-cli/bin/babel/index.js b/packages/babel-cli/bin/babel/index.js index 3235ad51ef..4f27e33493 100755 --- a/packages/babel-cli/bin/babel/index.js +++ b/packages/babel-cli/bin/babel/index.js @@ -118,11 +118,16 @@ if (errors.length) { var opts = exports.opts = {}; each(options, function (opt, key) { - opts[key] = commander[key]; + if (commander[key] !== undefined) { + opts[key] = commander[key]; + } }); opts.ignore = util.arrayify(opts.ignore, util.regexify); -opts.only = util.arrayify(opts.only, util.regexify); + +if (opts.only) { + opts.only = util.arrayify(opts.only, util.regexify); +} var fn; diff --git a/src/babel/api/node.js b/src/babel/api/node.js index 1729910191..01a05a0f67 100644 --- a/src/babel/api/node.js +++ b/src/babel/api/node.js @@ -8,7 +8,7 @@ export { util, acorn, transform }; export { pipeline } from "../transformation"; export { canCompile } from "../util"; -export { default as options } from "../transformation/file/options"; +export { default as options } from "../transformation/file/options/config"; export { default as Transformer } from "../transformation/transformer"; export { default as TransformerPipeline } from "../transformation/transformer-pipeline"; export { default as traverse } from "../traversal"; diff --git a/src/babel/api/register/node.js b/src/babel/api/register/node.js index 8e45aaa64d..7e7a99fec4 100644 --- a/src/babel/api/register/node.js +++ b/src/babel/api/register/node.js @@ -1,6 +1,6 @@ import sourceMapSupport from "source-map-support"; import * as registerCache from "./cache"; -import resolveRc from "../../tools/resolve-rc"; +import resolveRc from "../../transformation/file/options/resolve-rc"; import extend from "lodash/object/extend"; import * as babel from "../node"; import each from "lodash/collection/each"; @@ -90,7 +90,7 @@ var shouldIgnore = function (filename) { if (!ignore && !only) { return getRelativePath(filename).split(path.sep).indexOf("node_modules") >= 0; } else { - return util.shouldIgnore(filename, ignore || [], only || []); + return util.shouldIgnore(filename, ignore || [], only); } }; diff --git a/src/babel/tools/resolve-rc.js b/src/babel/tools/resolve-rc.js index 7af26b57bc..7c9d30f80e 100644 --- a/src/babel/tools/resolve-rc.js +++ b/src/babel/tools/resolve-rc.js @@ -1,59 +1,5 @@ -import stripJsonComments from "strip-json-comments"; -import merge from "../helpers/merge"; -import path from "path"; -import fs from "fs"; +console.trace("I know someone out there is hotlinking straight to this file. This is a " + + "PRIVATE API. I hate you, but I wont break your code just because you're a " + + "programmer who practices bad habits."); -var cache = {}; -var jsons = {}; - -function exists(filename) { - if (!fs.existsSync) return false; - - var cached = cache[filename]; - if (cached != null) return cached; - return cache[filename] = fs.existsSync(filename); -} - -export default function (loc, opts = {}) { - var rel = ".babelrc"; - - if (!opts.babelrc) { - opts.babelrc = []; - } - - function find(start, rel) { - var file = path.join(start, rel); - - if (opts.babelrc.indexOf(file) >= 0) { - return; - } - - if (exists(file)) { - var content = fs.readFileSync(file, "utf8"); - var json; - - try { - json = jsons[content] = jsons[content] || JSON.parse(stripJsonComments(content)); - } catch (err) { - err.message = `${file}: ${err.message}`; - throw err; - } - - opts.babelrc.push(file); - - if (json.breakConfig) return; - merge(opts, json); - } - - var up = path.dirname(start); - if (up !== start) { // root - find(up, rel); - } - } - - if (opts.babelrc.indexOf(loc) < 0 && opts.breakConfig !== true) { - find(loc, rel); - } - - return opts; -} +export { default } from "../transformation/file/options/resolve-rc"; diff --git a/src/babel/transformation/file/index.js b/src/babel/transformation/file/index.js index 80c38d4f4f..ca3cef3490 100644 --- a/src/babel/transformation/file/index.js +++ b/src/babel/transformation/file/index.js @@ -1,5 +1,5 @@ +import { validateOption, normaliseOptions, config as optionsConfig } from "./options"; import convertSourceMap from "convert-source-map"; -import * as optionParsers from "./option-parsers"; import moduleFormatters from "../modules"; import PluginManager from "./plugin-manager"; import shebangRegex from "shebang-regex"; @@ -7,7 +7,7 @@ import NodePath from "../../traversal/path"; import Transformer from "../transformer"; import isFunction from "lodash/lang/isFunction"; import isAbsolute from "path-is-absolute"; -import resolveRc from "../../tools/resolve-rc"; +import resolveRc from "./options/resolve-rc"; import sourceMap from "source-map"; import generate from "../../generation"; import codeFrame from "../../helpers/code-frame"; @@ -52,7 +52,7 @@ export default class File { this.log = new Logger(this, opts.filename || "unknown"); this.ast = {}; - this.normalizeOptions(opts); + this.normaliseOptions(opts); this.buildTransformers(); @@ -98,10 +98,10 @@ export default class File { static soloHelpers = []; - static options = require("./options"); + static options = optionsConfig; - normalizeOptions(opts: Object) { - opts = this.opts = assign({}, opts); + normaliseOptions(opts: Object) { + opts = this.opts = normaliseOptions(assign({}, opts)); // resolve babelrc if (opts.filename) { @@ -120,26 +120,28 @@ export default class File { // merge in environment options var envKey = process.env.BABEL_ENV || process.env.NODE_ENV || "development"; - if (opts.env) merge(opts, opts.env[envKey]); + if (opts.env) merge(opts, normaliseOptions(opts.env[envKey])); // normalise options for (let key in File.options) { let option = File.options[key]; + var val = opts[key]; - var val = opts[key]; + // optional if (!val && option.optional) continue; + // deprecated if (val && option.deprecated) { this.log.deprecate("Deprecated option " + key + ": " + option.deprecated); } - if (val == null) { - val = clone(option.default); - } + // default + if (val == null) val = clone(option.default); - var optionParser = optionParsers[option.type]; - if (optionParser) val = optionParser(key, val, this.pipeline); + // validate + if (val) val = validateOption(key, val, this.pipeline); + // aaliases if (option.alias) { opts[option.alias] = opts[option.alias] || val; } else { @@ -164,7 +166,10 @@ export default class File { opts.basename = path.basename(opts.filename, path.extname(opts.filename)); opts.ignore = util.arrayify(opts.ignore, util.regexify); - opts.only = util.arrayify(opts.only, util.regexify); + + if (opts.only) { + opts.only = util.arrayify(opts.only, util.regexify); + } defaults(opts, { moduleRoot: opts.sourceRoot diff --git a/src/babel/transformation/file/option-parsers.js b/src/babel/transformation/file/option-parsers.js deleted file mode 100644 index c5ebdac1be..0000000000 --- a/src/babel/transformation/file/option-parsers.js +++ /dev/null @@ -1,27 +0,0 @@ -import * as util from "../../util"; - -export function transformerList(key, val, pipeline) { - val = util.arrayify(val); - - if (val.indexOf("all") >= 0 || val.indexOf(true) >= 0) { - val = Object.keys(pipeline.transformers); - } - - return pipeline._ensureTransformerNames(key, val); -} - -export function number(key, val) { - return +val; -} - -export function boolean(key, val) { - return !!val; -} - -export function booleanString(key, val) { - return util.booleanify(val); -} - -export function list(key, val) { - return util.list(val); -} diff --git a/src/babel/transformation/file/options.json b/src/babel/transformation/file/options/config.json similarity index 95% rename from src/babel/transformation/file/options.json rename to src/babel/transformation/file/options/config.json index 892baa0cfd..800592db7c 100644 --- a/src/babel/transformation/file/options.json +++ b/src/babel/transformation/file/options/config.json @@ -78,7 +78,8 @@ "blacklist": { "type": "transformerList", "description": "blacklist of transformers to NOT use", - "shorthand": "b" + "shorthand": "b", + "default": [] }, "whitelist": { @@ -90,7 +91,8 @@ "optional": { "type": "transformerList", - "description": "list of optional transformers to enable" + "description": "list of optional transformers to enable", + "default": [] }, "modules": { @@ -122,12 +124,14 @@ "plugins": { "type": "list", - "description": "" + "description": "", + "default": [] }, "ignore": { "type": "list", - "description": "list of glob paths to **not** compile" + "description": "list of glob paths to **not** compile", + "default": [] }, "only": { diff --git a/src/babel/transformation/file/options/index.js b/src/babel/transformation/file/options/index.js new file mode 100644 index 0000000000..79b796874f --- /dev/null +++ b/src/babel/transformation/file/options/index.js @@ -0,0 +1,32 @@ +import * as parsers from "./parsers"; +import config from "./config"; +import clone from "lodash/lang/clone"; + +export { config }; + +export function validateOption(key, val, pipeline) { + var opt = config[key]; + var parser = opt && parsers[opt.type]; + if (parser && parser.validate) { + return parser.validate(key, val, pipeline); + } else { + return val; + } +} + +export function normaliseOptions(options = {}) { + for (var key in options) { + var val = options[key]; + if (val == null) continue; + + var opt = config[key]; + if (!opt) continue; + + var parser = parsers[opt.type]; + if (parser) val = parser(val); + + options[key] = val; + } + + return options; +} diff --git a/src/babel/transformation/file/options/parsers.js b/src/babel/transformation/file/options/parsers.js new file mode 100644 index 0000000000..eda258c6c6 --- /dev/null +++ b/src/babel/transformation/file/options/parsers.js @@ -0,0 +1,29 @@ +import * as util from "../../../util"; + +export function transformerList(val) { + return util.arrayify(val); +} + +transformerList.validate = function (key, val, pipeline) { + if (val.indexOf("all") >= 0 || val.indexOf(true) >= 0) { + val = Object.keys(pipeline.transformers); + } + + return pipeline._ensureTransformerNames(key, val); +}; + +export function number(val) { + return +val; +} + +export function boolean(val) { + return !!val; +} + +export function booleanString(val) { + return util.booleanify(val); +} + +export function list(val) { + return util.list(val); +} diff --git a/src/babel/transformation/file/options/resolve-rc.js b/src/babel/transformation/file/options/resolve-rc.js new file mode 100644 index 0000000000..c502f0fe7f --- /dev/null +++ b/src/babel/transformation/file/options/resolve-rc.js @@ -0,0 +1,62 @@ +import stripJsonComments from "strip-json-comments"; +import { normaliseOptions } from "./index"; +import merge from "../../../helpers/merge"; +import path from "path"; +import fs from "fs"; + +var cache = {}; +var jsons = {}; + +function exists(filename) { + if (!fs.existsSync) return false; + + var cached = cache[filename]; + if (cached != null) return cached; + return cache[filename] = fs.existsSync(filename); +} + +export default function (loc, opts = {}) { + var rel = ".babelrc"; + + if (!opts.babelrc) { + opts.babelrc = []; + } + + function find(start, rel) { + var file = path.join(start, rel); + + if (opts.babelrc.indexOf(file) >= 0) { + return; + } + + if (exists(file)) { + var content = fs.readFileSync(file, "utf8"); + var json; + + try { + json = jsons[content] = jsons[content] || JSON.parse(stripJsonComments(content)); + normaliseOptions(json); + } catch (err) { + err.message = `${file}: ${err.message}`; + throw err; + } + + opts.babelrc.push(file); + + if (json.breakConfig) return; + + merge(opts, json); + } + + var up = path.dirname(start); + if (up !== start) { // root + find(up, rel); + } + } + + if (opts.babelrc.indexOf(loc) < 0 && opts.breakConfig !== true) { + find(loc, rel); + } + + return opts; +} diff --git a/src/babel/util.js b/src/babel/util.js index 379a6cc856..0d2a5549a2 100644 --- a/src/babel/util.js +++ b/src/babel/util.js @@ -111,7 +111,7 @@ export function booleanify(val: any): boolean { export function shouldIgnore(filename, ignore, only) { filename = slash(filename); - if (only.length) { + if (only) { for (let pattern of (only: Array)) { if (pattern.test(filename)) return false; }