Add support for .babelrc.js files

This commit is contained in:
Kai Cataldo
2016-11-24 00:04:10 -05:00
parent 0336cab757
commit d054cd0ea8
28 changed files with 375 additions and 19 deletions

View File

@@ -1,4 +1,3 @@
import type Logger from "../logger";
import resolve from "../../../helpers/resolve";
import json5 from "json5";
@@ -8,9 +7,10 @@ import fs from "fs";
const existsCache = {};
const jsonCache = {};
const BABELIGNORE_FILENAME = ".babelignore";
const BABELRC_FILENAME = ".babelrc";
const BABELRC_JS_FILENAME = ".babelrc.js";
const PACKAGE_FILENAME = "package.json";
const BABELIGNORE_FILENAME = ".babelignore";
function exists(filename) {
const cached = existsCache[filename];
@@ -46,7 +46,12 @@ class ConfigChainBuilder {
this.log = log;
}
findConfigs(loc) {
errorMultipleConfigs(loc1: string, loc2: string) {
throw new Error(`Multiple configuration files found. Please remove one:\n- ${
loc1}\n- ${loc2}`);
}
findConfigs(loc: string) {
if (!loc) return;
if (!path.isAbsolute(loc)) {
@@ -59,15 +64,26 @@ class ConfigChainBuilder {
while (loc !== (loc = path.dirname(loc))) {
if (!foundConfig) {
const configLoc = path.join(loc, BABELRC_FILENAME);
if (exists(configLoc)) {
this.addConfig(configLoc);
foundConfig = true;
}
const configJSLoc = path.join(loc, BABELRC_JS_FILENAME);
const pkgLoc = path.join(loc, PACKAGE_FILENAME);
if (!foundConfig && exists(pkgLoc)) {
foundConfig = this.addConfig(pkgLoc, "babel", JSON);
}
const configLocs = [configLoc, configJSLoc, pkgLoc];
const foundConfigs = configLocs.reduce((arr, config) => {
if (exists(config)) {
const configAdded = config === pkgLoc
? this.addConfig(config, "babel", JSON)
: this.addConfig(config);
if (configAdded && arr.length) {
this.errorMultipleConfigs(arr.pop(), config);
}
arr.push(config);
}
return arr;
}, []);
foundConfig = !!foundConfigs.length;
}
if (!foundIgnore) {
@@ -82,7 +98,7 @@ class ConfigChainBuilder {
}
}
addIgnoreConfig(loc) {
addIgnoreConfig(loc: string) {
const file = fs.readFileSync(loc, "utf8");
let lines = file.split("\n");
@@ -106,15 +122,35 @@ class ConfigChainBuilder {
this.resolvedConfigs.push(loc);
const content = fs.readFileSync(loc, "utf8");
let options;
if (path.extname(loc) === ".js") {
try {
const configModule = require(loc);
options = configModule && configModule.__esModule ? configModule.default : configModule;
} catch (err) {
err.message = `${loc}: Error while loading config - ${err.message}`;
throw err;
}
try {
options = jsonCache[content] = jsonCache[content] || json.parse(content);
if (key) options = options[key];
} catch (err) {
err.message = `${loc}: Error while parsing JSON - ${err.message}`;
throw err;
if (!options || typeof options !== "object") {
throw new Error("Configuration should be an exported JavaScript object.");
}
} else {
const content = fs.readFileSync(loc, "utf8");
try {
options = jsonCache[content] = jsonCache[content] || json.parse(content);
} catch (err) {
err.message = `${loc}: Error while parsing JSON - ${err.message}`;
throw err;
}
}
if (key) {
if (!options[key]) {
return false;
}
options = options[key];
}
this.mergeConfig({

View File

@@ -294,4 +294,253 @@ describe("buildConfigChain", function () {
assert.deepEqual(chain, expected);
});
it("js-config", function () {
const chain = buildConfigChain({
filename: fixture("js-config", "src.js"),
});
const expected = [
{
options: {
plugins: [
"foo",
"bar",
],
},
alias: fixture("js-config", ".babelrc.js"),
loc: fixture("js-config", ".babelrc.js"),
dirname: fixture("js-config"),
},
{
options: {
ignore: [
"root-ignore",
],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
dirname: fixture(),
},
{
options: {
filename: fixture("js-config", "src.js"),
},
alias: "base",
loc: "base",
dirname: fixture("js-config"),
},
];
assert.deepEqual(chain, expected);
});
it("js-config-default - should read transpiled export default", function () {
const chain = buildConfigChain({
filename: fixture("js-config-default", "src.js"),
});
const expected = [
{
options: {
plugins: [
"foo",
"bar",
],
},
alias: fixture("js-config-default", ".babelrc.js"),
loc: fixture("js-config-default", ".babelrc.js"),
dirname: fixture("js-config-default"),
},
{
options: {
ignore: [
"root-ignore",
],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
dirname: fixture(),
},
{
options: {
filename: fixture("js-config-default", "src.js"),
},
alias: "base",
loc: "base",
dirname: fixture("js-config-default"),
},
];
assert.deepEqual(chain, expected);
});
it("js-config-extended", function () {
const chain = buildConfigChain({
filename: fixture("js-config-extended", "src.js"),
});
const expected = [
{
options: {
plugins: [
"extended",
],
},
alias: fixture("extended.babelrc.json"),
loc: fixture("extended.babelrc.json"),
dirname: fixture(),
},
{
options: {
plugins: [
"foo",
"bar",
],
},
alias: fixture("js-config-extended", ".babelrc.js"),
loc: fixture("js-config-extended", ".babelrc.js"),
dirname: fixture("js-config-extended"),
},
{
options: {
ignore: [
"root-ignore",
],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
dirname: fixture(),
},
{
options: {
filename: fixture("js-config-extended", "src.js"),
},
alias: "base",
loc: "base",
dirname: fixture("js-config-extended"),
},
];
assert.deepEqual(chain, expected);
});
it("json-pkg-config-no-babel - should not throw if" +
" package.json doesn't contain a `babel` field", function () {
const chain = buildConfigChain({
filename: fixture("json-pkg-config-no-babel", "src.js"),
});
const expected = [
{
options: {
plugins: [
"json",
],
},
alias: fixture("json-pkg-config-no-babel", ".babelrc"),
loc: fixture("json-pkg-config-no-babel", ".babelrc"),
dirname: fixture("json-pkg-config-no-babel"),
},
{
options: {
ignore: [
"root-ignore",
],
},
alias: fixture(".babelignore"),
loc: fixture(".babelignore"),
dirname: fixture(),
},
{
options: {
filename: fixture("json-pkg-config-no-babel", "src.js"),
},
alias: "base",
loc: "base",
dirname: fixture("json-pkg-config-no-babel"),
},
];
assert.deepEqual(chain, expected);
});
it("js-json-config - should throw an error if both a .babelrc" +
" and a .babelrc.js are present", function () {
assert.throws(
function () {
buildConfigChain({
filename: fixture("js-json-config", "src.js"),
});
},
/Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*\.babelrc\.js/
);
});
it("js-pkg-config - should throw an error if both a .babelrc.js" +
" and a package.json with a babel field are present", function () {
assert.throws(
function () {
buildConfigChain({
filename: fixture("js-pkg-config", "src.js"),
});
},
/Multiple configuration files found\.(.|\n)*\.babelrc\.js(.|\n)*package\.json/
);
});
it("json-pkg-config - should throw an error if both a .babelrc" +
" and a package.json with a babel field are present", function () {
assert.throws(
function () {
buildConfigChain({
filename: fixture("json-pkg-config", "src.js"),
});
},
/Multiple configuration files found\.(.|\n)*\.babelrc(.|\n)*package\.json/
);
});
it("js-config-error", function () {
assert.throws(
function () {
buildConfigChain({
filename: fixture("js-config-error", "src.js"),
});
},
/Error while loading config/
);
});
it("js-config-error2", function () {
assert.throws(
function () {
buildConfigChain({
filename: fixture("js-config-error2", "src.js"),
});
},
/Configuration should be an exported JavaScript object/
);
});
it("js-config-error3", function () {
assert.throws(
function () {
buildConfigChain({
filename: fixture("js-config-error3", "src.js"),
});
},
/Configuration should be an exported JavaScript object/
);
});
it("json-config-error", function () {
assert.throws(
function () {
buildConfigChain({
filename: fixture("json-config-error", "src.js"),
});
},
/Error while parsing JSON/
);
});
});

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var plugins = ["foo", "bar"];
exports.default = {
plugins: plugins
};

View File

@@ -0,0 +1 @@
// empty

View File

@@ -0,0 +1,2 @@
throw new Error("Something bad happened!");
module.exports = {}

View File

@@ -0,0 +1 @@
// empty

View File

@@ -0,0 +1 @@
module.exports = '';

View File

@@ -0,0 +1 @@
// empty

View File

@@ -0,0 +1 @@
module.exports = null;

View File

@@ -0,0 +1 @@
// empty

View File

@@ -0,0 +1,6 @@
var plugins = ["foo", "bar"];
module.exports = {
extends: "../extended.babelrc.json",
plugins: plugins
}

View File

@@ -0,0 +1 @@
// empty

View File

@@ -0,0 +1,5 @@
var plugins = ["foo", "bar"];
module.exports = {
plugins: plugins
}

View File

@@ -0,0 +1 @@
// empty

View File

@@ -0,0 +1,5 @@
{
"plugins": [
"json"
]
}

View File

@@ -0,0 +1,5 @@
module.exports = {
plugins: [
"js"
]
}

View File

@@ -0,0 +1 @@
// empty

View File

@@ -0,0 +1,5 @@
module.exports = {
plugins: [
"js"
]
}

View File

@@ -0,0 +1,3 @@
{
"babel": {}
}

View File

@@ -0,0 +1 @@
// empty

View File

@@ -0,0 +1,3 @@
{
"bad: "json"
}

View File

@@ -0,0 +1 @@
// empty

View File

@@ -0,0 +1,5 @@
{
"plugins": [
"json"
]
}

View File

@@ -0,0 +1 @@
{}

View File

@@ -0,0 +1 @@
// empty

View File

@@ -0,0 +1,5 @@
{
"plugins": [
"json"
]
}

View File

@@ -0,0 +1,3 @@
{
"babel": {}
}

View File

@@ -0,0 +1 @@
// empty