Skip to content

Commit

Permalink
refactor: config loading
Browse files Browse the repository at this point in the history
BREAKING CHANGE: the `config` option can be `boolean` or `string`, context is frozen
  • Loading branch information
evilebottnawi committed Sep 6, 2020
1 parent 108d871 commit d0ea725
Show file tree
Hide file tree
Showing 36 changed files with 1,111 additions and 1,361 deletions.
504 changes: 285 additions & 219 deletions README.md

Large diffs are not rendered by default.

32 changes: 2 additions & 30 deletions src/index.js
@@ -1,5 +1,3 @@
import path from 'path';

import { getOptions } from 'loader-utils';
import validateOptions from 'schema-utils';

Expand Down Expand Up @@ -38,6 +36,7 @@ export default async function loader(content, sourceMap) {
});

const callback = this.async();

const configOption =
typeof options.postcssOptions === 'undefined' ||
typeof options.postcssOptions.config === 'undefined'
Expand All @@ -46,35 +45,8 @@ export default async function loader(content, sourceMap) {
let loadedConfig = {};

if (configOption) {
const dataForLoadConfig = {
path: path.dirname(this.resourcePath),
ctx: {
file: {
extname: path.extname(this.resourcePath),
dirname: path.dirname(this.resourcePath),
basename: path.basename(this.resourcePath),
},
options: {},
},
};

if (typeof configOption.path !== 'undefined') {
dataForLoadConfig.path = path.resolve(configOption.path);
}

if (typeof configOption.ctx !== 'undefined') {
dataForLoadConfig.ctx.options = configOption.ctx;
}

dataForLoadConfig.ctx.webpack = this;

try {
loadedConfig = await loadConfig(
configOption,
dataForLoadConfig.ctx,
dataForLoadConfig.path,
this
);
loadedConfig = await loadConfig(this, configOption);
} catch (error) {
callback(error);

Expand Down
14 changes: 0 additions & 14 deletions src/options.json
Expand Up @@ -11,20 +11,6 @@
"config": {
"description": "Allows to specify PostCSS Config Path (https://github.com/postcss/postcss-loader#config)",
"anyOf": [
{
"type": "object",
"properties": {
"path": {
"description": "Allows to specify PostCSS Config Path (https://github.com/postcss/postcss-loader#path)",
"type": "string"
},
"ctx": {
"description": "Allows to specify PostCSS Config Context (https://github.com/postcss/postcss-loader#context-ctx)",
"type": "object"
}
},
"additionalProperties": false
},
{
"description": "Allows to specify the path to the configuration file",
"type": "string"
Expand Down
42 changes: 17 additions & 25 deletions src/utils.js
Expand Up @@ -15,20 +15,6 @@ const stat = (inputFileSystem, filePath) =>
});
});

const createContext = (context) => {
const result = {
cwd: process.cwd(),
env: process.env.NODE_ENV,
...context,
};

if (!result.env) {
process.env.NODE_ENV = 'development';
}

return result;
};

function exec(code, loaderContext) {
const { resource, context } = loaderContext;

Expand All @@ -44,12 +30,11 @@ function exec(code, loaderContext) {
return module.exports;
}

async function loadConfig(config, context, configPath, loaderContext) {
let searchPath = configPath ? path.resolve(configPath) : process.cwd();

if (typeof config === 'string') {
searchPath = path.resolve(config);
}
async function loadConfig(loaderContext, config) {
const searchPath =
typeof config === 'string'
? path.resolve(config)
: path.dirname(loaderContext.resourcePath);

let stats;

Expand Down Expand Up @@ -77,17 +62,23 @@ async function loadConfig(config, context, configPath, loaderContext) {
return {};
}

const patchedContext = createContext(context);

let resultConfig = result.config || {};

if (typeof resultConfig === 'function') {
resultConfig = resultConfig(patchedContext);
const api = {
env: process.env.NODE_ENV,
mode: loaderContext.mode,
file: loaderContext.resourcePath,
// For complex use
webpackLoaderContext: loaderContext,
};

resultConfig = resultConfig(api);
}

resultConfig.file = result.filepath;

loaderContext.addDependency(result.filepath);
loaderContext.addDependency(resultConfig.file);

return resultConfig;
}
Expand Down Expand Up @@ -126,7 +117,8 @@ function pluginFactory() {
} else if (
plugin &&
Object.keys(plugin).length === 1 &&
typeof plugin[Object.keys(plugin)[0]] === 'object' &&
(typeof plugin[Object.keys(plugin)[0]] === 'object' ||
typeof plugin[Object.keys(plugin)[0]] === 'boolean') &&
plugin[Object.keys(plugin)[0]] !== null
) {
const [name] = Object.keys(plugin);
Expand Down
153 changes: 153 additions & 0 deletions test/__snapshots__/config.test.js.snap
@@ -0,0 +1,153 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`"config" option should throw an error on the invalid config: errors 1`] = `
Array [
"ModuleBuildError: Module build failed (from \`replaced original path\`):
Error: invalid postcss config",
]
`;

exports[`"config" option should throw an error on the invalid config: warnings 1`] = `Array []`;

exports[`"config" option should throw an error on the unresolved config: errors 1`] = `
Array [
"ModuleBuildError: Module build failed (from \`replaced original path\`):
Error: No PostCSS Config found in: /test/fixtures/config-scope/css/unresolve.js",
]
`;

exports[`"config" option should throw an error on the unresolved config: warnings 1`] = `Array []`;

exports[`"config" option should work "String" value (relative path): css 1`] = `
"a { color: rgba(0, 0, 0, 1.0) }
.foo {
float: right;
}
"
`;

exports[`"config" option should work "String" value (relative path): errors 1`] = `Array []`;

exports[`"config" option should work "String" value (relative path): warnings 1`] = `Array []`;

exports[`"config" option should work with "String" value (absolute path): css 1`] = `
"a { color: rgba(0, 0, 0, 1.0) }
.foo {
float: right;
}
"
`;

exports[`"config" option should work with "String" value (absolute path): errors 1`] = `Array []`;

exports[`"config" option should work with "String" value (absolute path): warnings 1`] = `Array []`;

exports[`"config" option should work with "String" value (with path to the directory with the configuration): css 1`] = `
"a { color: rgba(0, 0, 0, 1.0) }
.foo {
float: right;
}
"
`;

exports[`"config" option should work with "String" value (with path to the directory with the configuration): errors 1`] = `Array []`;

exports[`"config" option should work with "String" value (with path to the directory with the configuration): warnings 1`] = `Array []`;

exports[`"config" option should work with "String" value and respect all options: css 1`] = `
"a {
color: black
}
/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0eWxlLnNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTtFQUNFO0FBREYiLCJmaWxlIjoic3R5bGUuY3NzIiwic291cmNlc0NvbnRlbnQiOlsiYVxuICBjb2xvcjogYmxhY2tcbiJdfQ== */"
`;

exports[`"config" option should work with "String" value and respect all options: errors 1`] = `Array []`;

exports[`"config" option should work with "String" value and respect all options: warnings 1`] = `Array []`;

exports[`"config" option should work with "false" value: css 1`] = `
"a { color: black }
.foo {
float: right;
}
"
`;

exports[`"config" option should work with "false" value: errors 1`] = `Array []`;

exports[`"config" option should work with "false" value: warnings 1`] = `Array []`;

exports[`"config" option should work with "package.json" configuration: css 1`] = `
".import {
color: red;
}
.test {
color: blue;
}
"
`;

exports[`"config" option should work with "package.json" configuration: errors 1`] = `Array []`;

exports[`"config" option should work with "package.json" configuration: warnings 1`] = `Array []`;

exports[`"config" option should work with "true" value: css 1`] = `
"a { color: rgba(0, 0, 0, 1.0) }
.foo {
float: right;
}
"
`;

exports[`"config" option should work with "true" value: errors 1`] = `Array []`;

exports[`"config" option should work with "true" value: warnings 1`] = `Array []`;

exports[`"config" option should work with the "postcssOptions" option: css 1`] = `
"a { color: rgba(0, 0, 0, 1.0) }
[dir=ltr] .foo { float: right;
}
[dir=rtl] .foo {
float: left;
}
"
`;

exports[`"config" option should work with the "postcssOptions" option: errors 1`] = `Array []`;

exports[`"config" option should work with the "postcssOptions" option: warnings 1`] = `Array []`;

exports[`"config" option should work without the specified value in the "postcssOptions" option: css 1`] = `
"a { color: rgba(0, 0, 0, 1.0) }
.foo {
float: right;
}
"
`;

exports[`"config" option should work without the specified value in the "postcssOptions" option: errors 1`] = `Array []`;

exports[`"config" option should work without the specified value in the "postcssOptions" option: warnings 1`] = `Array []`;

exports[`"config" option should work without the specified value: css 1`] = `
"a { color: rgba(0, 0, 0, 1.0) }
.foo {
float: right;
}
"
`;

exports[`"config" option should work without the specified value: errors 1`] = `Array []`;

exports[`"config" option should work without the specified value: warnings 1`] = `Array []`;
21 changes: 21 additions & 0 deletions test/__snapshots__/exec.test.js.snap
@@ -0,0 +1,21 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`"exec" option should work with "Boolean" value: css 1`] = `
"a {
color: green
}"
`;

exports[`"exec" option should work with "Boolean" value: errors 1`] = `Array []`;

exports[`"exec" option should work with "Boolean" value: warnings 1`] = `Array []`;

exports[`"exec" option should work with "JSS" parser: css 1`] = `
"a {
color: yellow
}"
`;

exports[`"exec" option should work with "JSS" parser: errors 1`] = `Array []`;

exports[`"exec" option should work with "JSS" parser: warnings 1`] = `Array []`;
44 changes: 22 additions & 22 deletions test/__snapshots__/loader.test.js.snap
@@ -1,27 +1,10 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`loader should emit Syntax Error: errors 1`] = `
Array [
"ModuleBuildError: Module build failed (from \`replaced original path\`):
SyntaxError
(1:3) Unnecessary curly bracket
> 1 | a {
| ^
2 | color: black;
3 | }
",
]
`;

exports[`loader should emit Syntax Error: warnings 1`] = `Array []`;

exports[`loader should emit asset: errors 1`] = `Array []`;
exports[`loader should emit asset using the "messages" API: errors 1`] = `Array []`;

exports[`loader should emit asset: warnings 1`] = `Array []`;
exports[`loader should emit asset using the "messages" API: warnings 1`] = `Array []`;

exports[`loader should emit warning: css 1`] = `
exports[`loader should emit warning using the "messages" API: css 1`] = `
"a {
color: black;
}
Expand Down Expand Up @@ -68,9 +51,9 @@ a {
"
`;

exports[`loader should emit warning: errors 1`] = `Array []`;
exports[`loader should emit warning using the "messages" API: errors 1`] = `Array []`;

exports[`loader should emit warning: warnings 1`] = `
exports[`loader should emit warning using the "messages" API: warnings 1`] = `
Array [
"ModuleWarning: Module Warning (from \`replaced original path\`):
Warning
Expand Down Expand Up @@ -123,6 +106,23 @@ Warning
]
`;
exports[`loader should throw an error on invalid syntax: errors 1`] = `
Array [
"ModuleBuildError: Module build failed (from \`replaced original path\`):
SyntaxError
(1:3) Unnecessary curly bracket
> 1 | a {
| ^
2 | color: black;
3 | }
",
]
`;
exports[`loader should throw an error on invalid syntax: warnings 1`] = `Array []`;
exports[`loader should work: css 1`] = `
"a {
color: black;
Expand Down

0 comments on commit d0ea725

Please sign in to comment.