Merge pull request #7091 from loganfsmyth/config-overrides
Allow configs to have an 'overrides' array
This commit is contained in:
commit
a19349a22a
@ -7,6 +7,7 @@ import {
|
|||||||
validate,
|
validate,
|
||||||
type ValidatedOptions,
|
type ValidatedOptions,
|
||||||
type IgnoreList,
|
type IgnoreList,
|
||||||
|
type ConfigApplicableTest,
|
||||||
} from "./validation/options";
|
} from "./validation/options";
|
||||||
|
|
||||||
const debug = buildDebug("babel:config:config-chain");
|
const debug = buildDebug("babel:config:config-chain");
|
||||||
@ -40,7 +41,7 @@ export type PresetInstance = {
|
|||||||
dirname: string,
|
dirname: string,
|
||||||
};
|
};
|
||||||
|
|
||||||
type ConfigContext = {
|
export type ConfigContext = {
|
||||||
filename: string | null,
|
filename: string | null,
|
||||||
cwd: string,
|
cwd: string,
|
||||||
envName: string,
|
envName: string,
|
||||||
@ -54,16 +55,53 @@ type ConfigContextNamed = {
|
|||||||
/**
|
/**
|
||||||
* Build a config chain for a given preset.
|
* Build a config chain for a given preset.
|
||||||
*/
|
*/
|
||||||
export const buildPresetChain = makeWeakCache(
|
export const buildPresetChain: (
|
||||||
({ dirname, options, alias }: PresetInstance): ConfigChain => {
|
arg: PresetInstance,
|
||||||
const result = createUncachedDescriptors(dirname, options, alias);
|
context: *,
|
||||||
const { plugins, presets } = result;
|
) => * = makeChainWalker({
|
||||||
return {
|
init: arg => arg,
|
||||||
plugins: plugins(),
|
root: preset => loadPresetDescriptors(preset),
|
||||||
presets: presets(),
|
env: (preset, envName) => loadPresetEnvDescriptors(preset)(envName),
|
||||||
options: [normalizeOptions(result.options)],
|
overrides: (preset, index) => loadPresetOverridesDescriptors(preset)(index),
|
||||||
};
|
overridesEnv: (preset, index, envName) =>
|
||||||
},
|
loadPresetOverridesEnvDescriptors(preset)(index)(envName),
|
||||||
|
});
|
||||||
|
const loadPresetDescriptors = makeWeakCache((preset: PresetInstance) =>
|
||||||
|
buildRootDescriptors(preset, preset.alias, createUncachedDescriptors),
|
||||||
|
);
|
||||||
|
const loadPresetEnvDescriptors = makeWeakCache((preset: PresetInstance) =>
|
||||||
|
makeStrongCache((envName: string) =>
|
||||||
|
buildEnvDescriptors(
|
||||||
|
preset,
|
||||||
|
preset.alias,
|
||||||
|
createUncachedDescriptors,
|
||||||
|
envName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const loadPresetOverridesDescriptors = makeWeakCache((preset: PresetInstance) =>
|
||||||
|
makeStrongCache((index: number) =>
|
||||||
|
buildOverrideDescriptors(
|
||||||
|
preset,
|
||||||
|
preset.alias,
|
||||||
|
createUncachedDescriptors,
|
||||||
|
index,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const loadPresetOverridesEnvDescriptors = makeWeakCache(
|
||||||
|
(preset: PresetInstance) =>
|
||||||
|
makeStrongCache((index: number) =>
|
||||||
|
makeStrongCache((envName: string) =>
|
||||||
|
buildOverrideEnvDescriptors(
|
||||||
|
preset,
|
||||||
|
preset.alias,
|
||||||
|
createUncachedDescriptors,
|
||||||
|
index,
|
||||||
|
envName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -72,14 +110,8 @@ export const buildPresetChain = makeWeakCache(
|
|||||||
export function buildRootChain(
|
export function buildRootChain(
|
||||||
cwd: string,
|
cwd: string,
|
||||||
opts: ValidatedOptions,
|
opts: ValidatedOptions,
|
||||||
envName: string,
|
context: ConfigContext,
|
||||||
): ConfigChain | null {
|
): ConfigChain | null {
|
||||||
const context = {
|
|
||||||
filename: opts.filename ? path.resolve(cwd, opts.filename) : null,
|
|
||||||
cwd,
|
|
||||||
envName,
|
|
||||||
};
|
|
||||||
|
|
||||||
const programmaticChain = loadProgrammaticChain(
|
const programmaticChain = loadProgrammaticChain(
|
||||||
{
|
{
|
||||||
options: opts,
|
options: opts,
|
||||||
@ -137,6 +169,16 @@ const loadProgrammaticChain = makeChainWalker({
|
|||||||
root: input => buildRootDescriptors(input, "base", createCachedDescriptors),
|
root: input => buildRootDescriptors(input, "base", createCachedDescriptors),
|
||||||
env: (input, envName) =>
|
env: (input, envName) =>
|
||||||
buildEnvDescriptors(input, "base", createCachedDescriptors, envName),
|
buildEnvDescriptors(input, "base", createCachedDescriptors, envName),
|
||||||
|
overrides: (input, index) =>
|
||||||
|
buildOverrideDescriptors(input, "base", createCachedDescriptors, index),
|
||||||
|
overridesEnv: (input, index, envName) =>
|
||||||
|
buildOverrideEnvDescriptors(
|
||||||
|
input,
|
||||||
|
"base",
|
||||||
|
createCachedDescriptors,
|
||||||
|
index,
|
||||||
|
envName,
|
||||||
|
),
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -146,6 +188,9 @@ const loadFileChain = makeChainWalker({
|
|||||||
init: input => validateFile(input),
|
init: input => validateFile(input),
|
||||||
root: file => loadFileDescriptors(file),
|
root: file => loadFileDescriptors(file),
|
||||||
env: (file, envName) => loadFileEnvDescriptors(file)(envName),
|
env: (file, envName) => loadFileEnvDescriptors(file)(envName),
|
||||||
|
overrides: (file, index) => loadFileOverridesDescriptors(file)(index),
|
||||||
|
overridesEnv: (file, index, envName) =>
|
||||||
|
loadFileOverridesEnvDescriptors(file)(index)(envName),
|
||||||
});
|
});
|
||||||
const validateFile = makeWeakCache((file: ConfigFile): ValidatedFile => ({
|
const validateFile = makeWeakCache((file: ConfigFile): ValidatedFile => ({
|
||||||
filepath: file.filepath,
|
filepath: file.filepath,
|
||||||
@ -165,6 +210,29 @@ const loadFileEnvDescriptors = makeWeakCache((file: ValidatedFile) =>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
const loadFileOverridesDescriptors = makeWeakCache((file: ValidatedFile) =>
|
||||||
|
makeStrongCache((index: number) =>
|
||||||
|
buildOverrideDescriptors(
|
||||||
|
file,
|
||||||
|
file.filepath,
|
||||||
|
createUncachedDescriptors,
|
||||||
|
index,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const loadFileOverridesEnvDescriptors = makeWeakCache((file: ValidatedFile) =>
|
||||||
|
makeStrongCache((index: number) =>
|
||||||
|
makeStrongCache((envName: string) =>
|
||||||
|
buildOverrideEnvDescriptors(
|
||||||
|
file,
|
||||||
|
file.filepath,
|
||||||
|
createUncachedDescriptors,
|
||||||
|
index,
|
||||||
|
envName,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
function buildRootDescriptors({ dirname, options }, alias, descriptors) {
|
function buildRootDescriptors({ dirname, options }, alias, descriptors) {
|
||||||
return descriptors(dirname, options, alias);
|
return descriptors(dirname, options, alias);
|
||||||
@ -180,6 +248,38 @@ function buildEnvDescriptors(
|
|||||||
return opts ? descriptors(dirname, opts, `${alias}.env["${envName}"]`) : null;
|
return opts ? descriptors(dirname, opts, `${alias}.env["${envName}"]`) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function buildOverrideDescriptors(
|
||||||
|
{ dirname, options },
|
||||||
|
alias,
|
||||||
|
descriptors,
|
||||||
|
index,
|
||||||
|
) {
|
||||||
|
const opts = options.overrides && options.overrides[index];
|
||||||
|
if (!opts) throw new Error("Assertion failure - missing override");
|
||||||
|
|
||||||
|
return descriptors(dirname, opts, `${alias}.overrides[${index}]`);
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildOverrideEnvDescriptors(
|
||||||
|
{ dirname, options },
|
||||||
|
alias,
|
||||||
|
descriptors,
|
||||||
|
index,
|
||||||
|
envName,
|
||||||
|
) {
|
||||||
|
const override = options.overrides && options.overrides[index];
|
||||||
|
if (!override) throw new Error("Assertion failure - missing override");
|
||||||
|
|
||||||
|
const opts = override.env && override.env[envName];
|
||||||
|
return opts
|
||||||
|
? descriptors(
|
||||||
|
dirname,
|
||||||
|
opts,
|
||||||
|
`${alias}.overrides[${index}].env["${envName}"]`,
|
||||||
|
)
|
||||||
|
: null;
|
||||||
|
}
|
||||||
|
|
||||||
function makeChainWalker<
|
function makeChainWalker<
|
||||||
ArgT,
|
ArgT,
|
||||||
InnerT: { options: ValidatedOptions, dirname: string },
|
InnerT: { options: ValidatedOptions, dirname: string },
|
||||||
@ -187,10 +287,14 @@ function makeChainWalker<
|
|||||||
init,
|
init,
|
||||||
root,
|
root,
|
||||||
env,
|
env,
|
||||||
|
overrides,
|
||||||
|
overridesEnv,
|
||||||
}: {
|
}: {
|
||||||
init: ArgT => InnerT,
|
init: ArgT => InnerT,
|
||||||
root: InnerT => OptionsAndDescriptors,
|
root: InnerT => OptionsAndDescriptors,
|
||||||
env: (InnerT, string) => OptionsAndDescriptors | null,
|
env: (InnerT, string) => OptionsAndDescriptors | null,
|
||||||
|
overrides: (InnerT, number) => OptionsAndDescriptors,
|
||||||
|
overridesEnv: (InnerT, number, string) => OptionsAndDescriptors | null,
|
||||||
}): (ArgT, ConfigContext, Set<ConfigFile> | void) => ConfigChain | null {
|
}): (ArgT, ConfigContext, Set<ConfigFile> | void) => ConfigChain | null {
|
||||||
return (arg, context, files = new Set()) => {
|
return (arg, context, files = new Set()) => {
|
||||||
const input = init(arg);
|
const input = init(arg);
|
||||||
@ -200,13 +304,30 @@ function makeChainWalker<
|
|||||||
const flattenedConfigs = [];
|
const flattenedConfigs = [];
|
||||||
|
|
||||||
const rootOpts = root(input);
|
const rootOpts = root(input);
|
||||||
|
if (configIsApplicable(rootOpts, dirname, context)) {
|
||||||
flattenedConfigs.push(rootOpts);
|
flattenedConfigs.push(rootOpts);
|
||||||
|
|
||||||
const envOpts = env(input, context.envName);
|
const envOpts = env(input, context.envName);
|
||||||
if (envOpts) {
|
if (envOpts && configIsApplicable(envOpts, dirname, context)) {
|
||||||
flattenedConfigs.push(envOpts);
|
flattenedConfigs.push(envOpts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(rootOpts.options.overrides || []).forEach((_, index) => {
|
||||||
|
const overrideOps = overrides(input, index);
|
||||||
|
if (configIsApplicable(overrideOps, dirname, context)) {
|
||||||
|
flattenedConfigs.push(overrideOps);
|
||||||
|
|
||||||
|
const overrideEnvOpts = overridesEnv(input, index, context.envName);
|
||||||
|
if (
|
||||||
|
overrideEnvOpts &&
|
||||||
|
configIsApplicable(overrideEnvOpts, dirname, context)
|
||||||
|
) {
|
||||||
|
flattenedConfigs.push(overrideEnvOpts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Process 'ignore' and 'only' before 'extends' items are processed so
|
// Process 'ignore' and 'only' before 'extends' items are processed so
|
||||||
// that we don't do extra work loading extended configs if a file is
|
// that we don't do extra work loading extended configs if a file is
|
||||||
// ignored.
|
// ignored.
|
||||||
@ -351,6 +472,42 @@ function dedupDescriptors(
|
|||||||
}, []);
|
}, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function configIsApplicable(
|
||||||
|
{ options }: OptionsAndDescriptors,
|
||||||
|
dirname: string,
|
||||||
|
context: ConfigContext,
|
||||||
|
): boolean {
|
||||||
|
return (
|
||||||
|
(options.test === undefined ||
|
||||||
|
configFieldIsApplicable(context, options.test, dirname)) &&
|
||||||
|
(options.include === undefined ||
|
||||||
|
configFieldIsApplicable(context, options.include, dirname)) &&
|
||||||
|
(options.exclude === undefined ||
|
||||||
|
!configFieldIsApplicable(context, options.exclude, dirname))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function configFieldIsApplicable(
|
||||||
|
context: ConfigContext,
|
||||||
|
test: ConfigApplicableTest,
|
||||||
|
dirname: string,
|
||||||
|
): boolean {
|
||||||
|
if (context.filename === null) {
|
||||||
|
throw new Error(
|
||||||
|
`Configuration contains explicit test/include/exclude checks, but no filename was passed to Babel`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// $FlowIgnore - Flow refinements aren't quite smart enough for this :(
|
||||||
|
const ctx: ConfigContextNamed = context;
|
||||||
|
|
||||||
|
const patterns = Array.isArray(test) ? test : [test];
|
||||||
|
|
||||||
|
// Disabling negation here because it's a bit buggy from
|
||||||
|
// https://github.com/babel/babel/issues/6907 and it's not clear that it is
|
||||||
|
// needed since users can use 'exclude' alongside 'test'/'include'.
|
||||||
|
return matchesPatterns(ctx, patterns, dirname, false /* allowNegation */);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests if a filename should be ignored based on "ignore" and "only" options.
|
* Tests if a filename should be ignored based on "ignore" and "only" options.
|
||||||
*/
|
*/
|
||||||
@ -360,11 +517,14 @@ function shouldIgnore(
|
|||||||
only: ?IgnoreList,
|
only: ?IgnoreList,
|
||||||
dirname: string,
|
dirname: string,
|
||||||
): boolean {
|
): boolean {
|
||||||
if (context.filename === null) return false;
|
if (ignore) {
|
||||||
|
if (context.filename === null) {
|
||||||
|
throw new Error(
|
||||||
|
`Configuration contains ignore checks, but no filename was passed to Babel`,
|
||||||
|
);
|
||||||
|
}
|
||||||
// $FlowIgnore - Flow refinements aren't quite smart enough for this :(
|
// $FlowIgnore - Flow refinements aren't quite smart enough for this :(
|
||||||
const ctx: ConfigContextNamed = context;
|
const ctx: ConfigContextNamed = context;
|
||||||
|
|
||||||
if (ignore) {
|
|
||||||
if (matchesPatterns(ctx, ignore, dirname)) {
|
if (matchesPatterns(ctx, ignore, dirname)) {
|
||||||
debug(
|
debug(
|
||||||
"Ignored %o because it matched one of %O from %o",
|
"Ignored %o because it matched one of %O from %o",
|
||||||
@ -377,6 +537,14 @@ function shouldIgnore(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (only) {
|
if (only) {
|
||||||
|
if (context.filename === null) {
|
||||||
|
throw new Error(
|
||||||
|
`Configuration contains ignore checks, but no filename was passed to Babel`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// $FlowIgnore - Flow refinements aren't quite smart enough for this :(
|
||||||
|
const ctx: ConfigContextNamed = context;
|
||||||
|
|
||||||
if (!matchesPatterns(ctx, only, dirname)) {
|
if (!matchesPatterns(ctx, only, dirname)) {
|
||||||
debug(
|
debug(
|
||||||
"Ignored %o because it failed to match one of %O from %o",
|
"Ignored %o because it failed to match one of %O from %o",
|
||||||
@ -399,6 +567,7 @@ function matchesPatterns(
|
|||||||
context: ConfigContextNamed,
|
context: ConfigContextNamed,
|
||||||
patterns: IgnoreList,
|
patterns: IgnoreList,
|
||||||
dirname: string,
|
dirname: string,
|
||||||
|
allowNegation?: boolean = true,
|
||||||
): boolean {
|
): boolean {
|
||||||
const res = [];
|
const res = [];
|
||||||
const strings = [];
|
const strings = [];
|
||||||
@ -420,13 +589,19 @@ function matchesPatterns(
|
|||||||
const absolutePatterns = strings.map(pattern => {
|
const absolutePatterns = strings.map(pattern => {
|
||||||
// Preserve the "!" prefix so that micromatch can use it for negation.
|
// Preserve the "!" prefix so that micromatch can use it for negation.
|
||||||
const negate = pattern[0] === "!";
|
const negate = pattern[0] === "!";
|
||||||
|
if (negate && !allowNegation) {
|
||||||
|
throw new Error(`Negation of file paths is not supported.`);
|
||||||
|
}
|
||||||
if (negate) pattern = pattern.slice(1);
|
if (negate) pattern = pattern.slice(1);
|
||||||
|
|
||||||
return (negate ? "!" : "") + path.resolve(dirname, pattern);
|
return (negate ? "!" : "") + path.resolve(dirname, pattern);
|
||||||
});
|
});
|
||||||
|
|
||||||
if (
|
if (
|
||||||
micromatch(possibleDirs, absolutePatterns, { nocase: true }).length > 0
|
micromatch(possibleDirs, absolutePatterns, {
|
||||||
|
nocase: true,
|
||||||
|
nonegate: !allowNegation,
|
||||||
|
}).length > 0
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import merge from "lodash/merge";
|
|||||||
import {
|
import {
|
||||||
buildRootChain,
|
buildRootChain,
|
||||||
buildPresetChain,
|
buildPresetChain,
|
||||||
|
type ConfigContext,
|
||||||
type ConfigChain,
|
type ConfigChain,
|
||||||
type PresetInstance,
|
type PresetInstance,
|
||||||
} from "./config-chain";
|
} from "./config-chain";
|
||||||
@ -36,6 +37,12 @@ export type { Plugin };
|
|||||||
export type PluginPassList = Array<Plugin>;
|
export type PluginPassList = Array<Plugin>;
|
||||||
export type PluginPasses = Array<PluginPassList>;
|
export type PluginPasses = Array<PluginPassList>;
|
||||||
|
|
||||||
|
// Context not including filename since it is used in places that cannot
|
||||||
|
// process 'ignore'/'only' and other filename-based logic.
|
||||||
|
type SimpleContext = {
|
||||||
|
envName: string,
|
||||||
|
};
|
||||||
|
|
||||||
export default function loadConfig(inputOpts: mixed): ResolvedConfig | null {
|
export default function loadConfig(inputOpts: mixed): ResolvedConfig | null {
|
||||||
if (
|
if (
|
||||||
inputOpts != null &&
|
inputOpts != null &&
|
||||||
@ -49,27 +56,32 @@ export default function loadConfig(inputOpts: mixed): ResolvedConfig | null {
|
|||||||
const { envName = getEnv(), cwd = "." } = args;
|
const { envName = getEnv(), cwd = "." } = args;
|
||||||
const absoluteCwd = path.resolve(cwd);
|
const absoluteCwd = path.resolve(cwd);
|
||||||
|
|
||||||
const configChain = buildRootChain(absoluteCwd, args, envName);
|
const context: ConfigContext = {
|
||||||
|
filename: args.filename ? path.resolve(cwd, args.filename) : null,
|
||||||
|
cwd: absoluteCwd,
|
||||||
|
envName,
|
||||||
|
};
|
||||||
|
|
||||||
|
const configChain = buildRootChain(absoluteCwd, args, context);
|
||||||
if (!configChain) return null;
|
if (!configChain) return null;
|
||||||
|
|
||||||
const optionDefaults = {};
|
const optionDefaults = {};
|
||||||
const options = {};
|
const options = {};
|
||||||
const passes = [[]];
|
const passes = [[]];
|
||||||
try {
|
try {
|
||||||
(function recurseDescriptors(
|
const ignored = (function recurseDescriptors(
|
||||||
config: {
|
config: {
|
||||||
plugins: Array<UnloadedDescriptor>,
|
plugins: Array<UnloadedDescriptor>,
|
||||||
presets: Array<UnloadedDescriptor>,
|
presets: Array<UnloadedDescriptor>,
|
||||||
},
|
},
|
||||||
pass: Array<Plugin>,
|
pass: Array<Plugin>,
|
||||||
envName: string,
|
|
||||||
) {
|
) {
|
||||||
const plugins = config.plugins.map(descriptor =>
|
const plugins = config.plugins.map(descriptor =>
|
||||||
loadPluginDescriptor(descriptor, envName),
|
loadPluginDescriptor(descriptor, context),
|
||||||
);
|
);
|
||||||
const presets = config.presets.map(descriptor => {
|
const presets = config.presets.map(descriptor => {
|
||||||
return {
|
return {
|
||||||
preset: loadPresetDescriptor(descriptor, envName),
|
preset: loadPresetDescriptor(descriptor, context),
|
||||||
pass: descriptor.ownPass ? [] : pass,
|
pass: descriptor.ownPass ? [] : pass,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
@ -85,14 +97,16 @@ export default function loadConfig(inputOpts: mixed): ResolvedConfig | null {
|
|||||||
);
|
);
|
||||||
|
|
||||||
for (const { preset, pass } of presets) {
|
for (const { preset, pass } of presets) {
|
||||||
recurseDescriptors(
|
if (!preset) return true;
|
||||||
|
|
||||||
|
const ignored = recurseDescriptors(
|
||||||
{
|
{
|
||||||
plugins: preset.plugins,
|
plugins: preset.plugins,
|
||||||
presets: preset.presets,
|
presets: preset.presets,
|
||||||
},
|
},
|
||||||
pass,
|
pass,
|
||||||
envName,
|
|
||||||
);
|
);
|
||||||
|
if (ignored) return true;
|
||||||
|
|
||||||
preset.options.forEach(opts => {
|
preset.options.forEach(opts => {
|
||||||
merge(optionDefaults, opts);
|
merge(optionDefaults, opts);
|
||||||
@ -110,9 +124,10 @@ export default function loadConfig(inputOpts: mixed): ResolvedConfig | null {
|
|||||||
presets: configChain.presets,
|
presets: configChain.presets,
|
||||||
},
|
},
|
||||||
passes[0],
|
passes[0],
|
||||||
envName,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (ignored) return null;
|
||||||
|
|
||||||
configChain.options.forEach(opts => {
|
configChain.options.forEach(opts => {
|
||||||
merge(options, opts);
|
merge(options, opts);
|
||||||
});
|
});
|
||||||
@ -152,7 +167,7 @@ export default function loadConfig(inputOpts: mixed): ResolvedConfig | null {
|
|||||||
const loadDescriptor = makeWeakCache(
|
const loadDescriptor = makeWeakCache(
|
||||||
(
|
(
|
||||||
{ value, options, dirname, alias }: UnloadedDescriptor,
|
{ value, options, dirname, alias }: UnloadedDescriptor,
|
||||||
cache: CacheConfigurator<{ envName: string }>,
|
cache: CacheConfigurator<SimpleContext>,
|
||||||
): LoadedDescriptor => {
|
): LoadedDescriptor => {
|
||||||
// Disabled presets should already have been filtered out
|
// Disabled presets should already have been filtered out
|
||||||
if (options === false) throw new Error("Assertion failure");
|
if (options === false) throw new Error("Assertion failure");
|
||||||
@ -199,7 +214,7 @@ const loadDescriptor = makeWeakCache(
|
|||||||
*/
|
*/
|
||||||
function loadPluginDescriptor(
|
function loadPluginDescriptor(
|
||||||
descriptor: UnloadedDescriptor,
|
descriptor: UnloadedDescriptor,
|
||||||
envName: string,
|
context: SimpleContext,
|
||||||
): Plugin {
|
): Plugin {
|
||||||
if (descriptor.value instanceof Plugin) {
|
if (descriptor.value instanceof Plugin) {
|
||||||
if (descriptor.options) {
|
if (descriptor.options) {
|
||||||
@ -211,15 +226,13 @@ function loadPluginDescriptor(
|
|||||||
return descriptor.value;
|
return descriptor.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return instantiatePlugin(loadDescriptor(descriptor, { envName }), {
|
return instantiatePlugin(loadDescriptor(descriptor, context), context);
|
||||||
envName,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const instantiatePlugin = makeWeakCache(
|
const instantiatePlugin = makeWeakCache(
|
||||||
(
|
(
|
||||||
{ value, options, dirname, alias }: LoadedDescriptor,
|
{ value, options, dirname, alias }: LoadedDescriptor,
|
||||||
cache: CacheConfigurator<{ envName: string }>,
|
cache: CacheConfigurator<SimpleContext>,
|
||||||
): Plugin => {
|
): Plugin => {
|
||||||
const pluginObj = validatePluginObject(value);
|
const pluginObj = validatePluginObject(value);
|
||||||
|
|
||||||
@ -239,7 +252,7 @@ const instantiatePlugin = makeWeakCache(
|
|||||||
|
|
||||||
// If the inherited plugin changes, reinstantiate this plugin.
|
// If the inherited plugin changes, reinstantiate this plugin.
|
||||||
const inherits = cache.invalidate(data =>
|
const inherits = cache.invalidate(data =>
|
||||||
loadPluginDescriptor(inheritsDescriptor, data.envName),
|
loadPluginDescriptor(inheritsDescriptor, data),
|
||||||
);
|
);
|
||||||
|
|
||||||
plugin.pre = chain(inherits.pre, plugin.pre);
|
plugin.pre = chain(inherits.pre, plugin.pre);
|
||||||
@ -263,10 +276,11 @@ const instantiatePlugin = makeWeakCache(
|
|||||||
*/
|
*/
|
||||||
const loadPresetDescriptor = (
|
const loadPresetDescriptor = (
|
||||||
descriptor: UnloadedDescriptor,
|
descriptor: UnloadedDescriptor,
|
||||||
envName: string,
|
context: ConfigContext,
|
||||||
): ConfigChain => {
|
): ConfigChain | null => {
|
||||||
return buildPresetChain(
|
return buildPresetChain(
|
||||||
instantiatePreset(loadDescriptor(descriptor, { envName })),
|
instantiatePreset(loadDescriptor(descriptor, context)),
|
||||||
|
context,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -6,6 +6,7 @@ import type {
|
|||||||
PluginList,
|
PluginList,
|
||||||
PluginItem,
|
PluginItem,
|
||||||
PluginTarget,
|
PluginTarget,
|
||||||
|
ConfigApplicableTest,
|
||||||
SourceMapsOption,
|
SourceMapsOption,
|
||||||
SourceTypeOption,
|
SourceTypeOption,
|
||||||
CompactOption,
|
CompactOption,
|
||||||
@ -104,6 +105,13 @@ export function assertObject(key: string, value: mixed): {} | void {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function assertArray(key: string, value: mixed): ?$ReadOnlyArray<mixed> {
|
||||||
|
if (value != null && !Array.isArray(value)) {
|
||||||
|
throw new Error(`.${key} must be an array, or undefined`);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
export function assertIgnoreList(key: string, value: mixed): IgnoreList | void {
|
export function assertIgnoreList(key: string, value: mixed): IgnoreList | void {
|
||||||
const arr = assertArray(key, value);
|
const arr = assertArray(key, value);
|
||||||
if (arr) {
|
if (arr) {
|
||||||
@ -122,12 +130,38 @@ function assertIgnoreItem(
|
|||||||
!(value instanceof RegExp)
|
!(value instanceof RegExp)
|
||||||
) {
|
) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`.${key}[${index}] must be an array of string/Funtion/RegExp values, or or undefined`,
|
`.${key}[${index}] must be an array of string/Funtion/RegExp values, or undefined`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function assertConfigApplicableTest(
|
||||||
|
key: string,
|
||||||
|
value: mixed,
|
||||||
|
): ConfigApplicableTest | void {
|
||||||
|
if (Array.isArray(value)) {
|
||||||
|
value.forEach((item, i) => {
|
||||||
|
if (!checkValidTest(item)) {
|
||||||
|
throw new Error(`.${key}[${i}] must be a string/Function/RegExp.`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else if (!checkValidTest(value)) {
|
||||||
|
throw new Error(
|
||||||
|
`.${key} must be a string/Function/RegExp, or an array of those`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return (value: any);
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkValidTest(value: mixed): boolean {
|
||||||
|
return (
|
||||||
|
typeof value === "string" ||
|
||||||
|
typeof value === "function" ||
|
||||||
|
value instanceof RegExp
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function assertPluginList(key: string, value: mixed): PluginList | void {
|
export function assertPluginList(key: string, value: mixed): PluginList | void {
|
||||||
const arr = assertArray(key, value);
|
const arr = assertArray(key, value);
|
||||||
if (arr) {
|
if (arr) {
|
||||||
@ -198,10 +232,3 @@ function assertPluginTarget(
|
|||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function assertArray(key: string, value: mixed): ?$ReadOnlyArray<mixed> {
|
|
||||||
if (value != null && !Array.isArray(value)) {
|
|
||||||
throw new Error(`.${key} must be an array, or undefined`);
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -5,9 +5,11 @@ import {
|
|||||||
assertString,
|
assertString,
|
||||||
assertBoolean,
|
assertBoolean,
|
||||||
assertObject,
|
assertObject,
|
||||||
|
assertArray,
|
||||||
assertInputSourceMap,
|
assertInputSourceMap,
|
||||||
assertIgnoreList,
|
assertIgnoreList,
|
||||||
assertPluginList,
|
assertPluginList,
|
||||||
|
assertConfigApplicableTest,
|
||||||
assertFunction,
|
assertFunction,
|
||||||
assertSourceMaps,
|
assertSourceMaps,
|
||||||
assertCompact,
|
assertCompact,
|
||||||
@ -44,6 +46,22 @@ const NONPRESET_VALIDATORS: ValidatorSet = {
|
|||||||
$PropertyType<ValidatedOptions, "ignore">,
|
$PropertyType<ValidatedOptions, "ignore">,
|
||||||
>),
|
>),
|
||||||
only: (assertIgnoreList: Validator<$PropertyType<ValidatedOptions, "only">>),
|
only: (assertIgnoreList: Validator<$PropertyType<ValidatedOptions, "only">>),
|
||||||
|
overrides: (assertOverridesList: Validator<
|
||||||
|
$PropertyType<ValidatedOptions, "overrides">,
|
||||||
|
>),
|
||||||
|
|
||||||
|
// We could limit these to 'overrides' blocks, but it's not clear why we'd
|
||||||
|
// bother, when the ability to limit a config to a specific set of files
|
||||||
|
// is a fairly general useful feature.
|
||||||
|
test: (assertConfigApplicableTest: Validator<
|
||||||
|
$PropertyType<ValidatedOptions, "test">,
|
||||||
|
>),
|
||||||
|
include: (assertConfigApplicableTest: Validator<
|
||||||
|
$PropertyType<ValidatedOptions, "include">,
|
||||||
|
>),
|
||||||
|
exclude: (assertConfigApplicableTest: Validator<
|
||||||
|
$PropertyType<ValidatedOptions, "exclude">,
|
||||||
|
>),
|
||||||
};
|
};
|
||||||
|
|
||||||
const COMMON_VALIDATORS: ValidatorSet = {
|
const COMMON_VALIDATORS: ValidatorSet = {
|
||||||
@ -142,6 +160,12 @@ export type ValidatedOptions = {
|
|||||||
env?: EnvSet<ValidatedOptions>,
|
env?: EnvSet<ValidatedOptions>,
|
||||||
ignore?: IgnoreList,
|
ignore?: IgnoreList,
|
||||||
only?: IgnoreList,
|
only?: IgnoreList,
|
||||||
|
overrides?: OverridesList,
|
||||||
|
|
||||||
|
// Generally verify if a given config object should be applied to the given file.
|
||||||
|
test?: ConfigApplicableTest,
|
||||||
|
include?: ConfigApplicableTest,
|
||||||
|
exclude?: ConfigApplicableTest,
|
||||||
|
|
||||||
presets?: PluginList,
|
presets?: PluginList,
|
||||||
plugins?: PluginList,
|
plugins?: PluginList,
|
||||||
@ -196,12 +220,15 @@ export type PluginItem =
|
|||||||
| [PluginTarget, PluginOptions, string];
|
| [PluginTarget, PluginOptions, string];
|
||||||
export type PluginList = $ReadOnlyArray<PluginItem>;
|
export type PluginList = $ReadOnlyArray<PluginItem>;
|
||||||
|
|
||||||
|
export type OverridesList = Array<ValidatedOptions>;
|
||||||
|
export type ConfigApplicableTest = IgnoreItem | Array<IgnoreItem>;
|
||||||
|
|
||||||
export type SourceMapsOption = boolean | "inline" | "both";
|
export type SourceMapsOption = boolean | "inline" | "both";
|
||||||
export type SourceTypeOption = "module" | "script" | "unambiguous";
|
export type SourceTypeOption = "module" | "script" | "unambiguous";
|
||||||
export type CompactOption = boolean | "auto";
|
export type CompactOption = boolean | "auto";
|
||||||
export type RootInputSourceMapOption = {} | boolean;
|
export type RootInputSourceMapOption = {} | boolean;
|
||||||
|
|
||||||
export type OptionsType = "arguments" | "file" | "env" | "preset";
|
export type OptionsType = "arguments" | "file" | "env" | "preset" | "override";
|
||||||
|
|
||||||
export function validate(type: OptionsType, opts: {}): ValidatedOptions {
|
export function validate(type: OptionsType, opts: {}): ValidatedOptions {
|
||||||
assertNoDuplicateSourcemap(opts);
|
assertNoDuplicateSourcemap(opts);
|
||||||
@ -216,6 +243,12 @@ export function validate(type: OptionsType, opts: {}): ValidatedOptions {
|
|||||||
if (type === "env" && key === "env") {
|
if (type === "env" && key === "env") {
|
||||||
throw new Error(`.${key} is not allowed inside another env block`);
|
throw new Error(`.${key} is not allowed inside another env block`);
|
||||||
}
|
}
|
||||||
|
if (type === "env" && key === "overrides") {
|
||||||
|
throw new Error(`.${key} is not allowed inside an env block`);
|
||||||
|
}
|
||||||
|
if (type === "override" && key === "overrides") {
|
||||||
|
throw new Error(`.${key} is not allowed inside an overrides block`);
|
||||||
|
}
|
||||||
|
|
||||||
const validator =
|
const validator =
|
||||||
COMMON_VALIDATORS[key] ||
|
COMMON_VALIDATORS[key] ||
|
||||||
@ -266,3 +299,16 @@ function assertEnvSet(key: string, value: mixed): EnvSet<ValidatedOptions> {
|
|||||||
}
|
}
|
||||||
return (obj: any);
|
return (obj: any);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function assertOverridesList(key: string, value: mixed): OverridesList {
|
||||||
|
const arr = assertArray(key, value);
|
||||||
|
if (arr) {
|
||||||
|
for (const [index, item] of arr.entries()) {
|
||||||
|
const env = assertObject(`${index}`, item);
|
||||||
|
if (!env) throw new Error(`.${key}[${index}] must be an object`);
|
||||||
|
|
||||||
|
validate("override", env);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (arr: any);
|
||||||
|
}
|
||||||
|
|||||||
@ -8,6 +8,420 @@ function fixture(...args) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
describe("buildConfigChain", function() {
|
describe("buildConfigChain", function() {
|
||||||
|
describe("test", () => {
|
||||||
|
describe("single", () => {
|
||||||
|
it("should process matching string values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
test: fixture("nonexistant-fake"),
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process matching RegExp values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
test: new RegExp(fixture("nonexistant-fake")),
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process matching function values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
test: p => p.indexOf(fixture("nonexistant-fake")) === 0,
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching string values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
test: fixture("nonexistant-fake-unknown"),
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching RegExp values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
test: new RegExp(fixture("nonexistant-unknown")),
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching function values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
test: p => p.indexOf(fixture("nonexistant-unknown")) === 0,
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("array", () => {
|
||||||
|
it("should process matching string values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
test: [fixture("nonexistant-fake")],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process matching RegExp values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
test: [new RegExp(fixture("nonexistant-fake"))],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process matching function values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
test: [p => p.indexOf(fixture("nonexistant-fake")) === 0],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching string values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
test: [fixture("nonexistant-fake-unknown")],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching RegExp values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
test: [new RegExp(fixture("nonexistant-unknown"))],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching function values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
test: [p => p.indexOf(fixture("nonexistant-unknown")) === 0],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("include", () => {
|
||||||
|
describe("single", () => {
|
||||||
|
it("should process matching string values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
include: fixture("nonexistant-fake"),
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process matching RegExp values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
include: new RegExp(fixture("nonexistant-fake")),
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process matching function values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
include: p => p.indexOf(fixture("nonexistant-fake")) === 0,
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching string values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
include: fixture("nonexistant-fake-unknown"),
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching RegExp values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
include: new RegExp(fixture("nonexistant-unknown")),
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching function values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
include: p => p.indexOf(fixture("nonexistant-unknown")) === 0,
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("array", () => {
|
||||||
|
it("should process matching string values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
include: [fixture("nonexistant-fake")],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process matching RegExp values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
include: [new RegExp(fixture("nonexistant-fake"))],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process matching function values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
include: [p => p.indexOf(fixture("nonexistant-fake")) === 0],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching string values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
include: [fixture("nonexistant-fake-unknown")],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching RegExp values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
include: [new RegExp(fixture("nonexistant-unknown"))],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching function values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
include: [p => p.indexOf(fixture("nonexistant-unknown")) === 0],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("exclude", () => {
|
||||||
|
describe("single", () => {
|
||||||
|
it("should process matching string values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
exclude: fixture("nonexistant-fake"),
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process matching RegExp values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
exclude: new RegExp(fixture("nonexistant-fake")),
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process matching function values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
exclude: p => p.indexOf(fixture("nonexistant-fake")) === 0,
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching string values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
exclude: fixture("nonexistant-fake-unknown"),
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching RegExp values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
exclude: new RegExp(fixture("nonexistant-unknown")),
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching function values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
exclude: p => p.indexOf(fixture("nonexistant-unknown")) === 0,
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("array", () => {
|
||||||
|
it("should process matching string values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
exclude: [fixture("nonexistant-fake")],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process matching RegExp values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
exclude: [new RegExp(fixture("nonexistant-fake"))],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process matching function values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
exclude: [p => p.indexOf(fixture("nonexistant-fake")) === 0],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, undefined);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching string values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
exclude: [fixture("nonexistant-fake-unknown")],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching RegExp values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
exclude: [new RegExp(fixture("nonexistant-unknown"))],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should process non-matching function values", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
exclude: [p => p.indexOf(fixture("nonexistant-unknown")) === 0],
|
||||||
|
comments: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("ignore", () => {
|
describe("ignore", () => {
|
||||||
it("should ignore files that match", () => {
|
it("should ignore files that match", () => {
|
||||||
const opts = loadOptions({
|
const opts = loadOptions({
|
||||||
@ -387,6 +801,40 @@ describe("buildConfigChain", function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe("overrides merging", () => {
|
||||||
|
it("should apply matching overrides over base configs", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
comments: true,
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
test: fixture("nonexistant-fake"),
|
||||||
|
comments: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, false);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should not apply non-matching overrides over base configs", () => {
|
||||||
|
const opts = loadOptions({
|
||||||
|
filename: fixture("nonexistant-fake", "src.js"),
|
||||||
|
babelrc: false,
|
||||||
|
comments: true,
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
test: fixture("nonexistant-unknown"),
|
||||||
|
comments: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
assert.equal(opts.comments, true);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("config files", () => {
|
describe("config files", () => {
|
||||||
const getDefaults = () => ({
|
const getDefaults = () => ({
|
||||||
babelrc: false,
|
babelrc: false,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user