Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow tooling authors to provide custom postcss factory through options #511

Merged
merged 1 commit into from
Jan 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -593,6 +593,37 @@ module.exports = {
};
```

### `implementation`

Type: `Function`

The special `implementation` option determines which implementation of PostCSS to use. Overrides the locally installed `peerDependency` version of `postcss`.

**This option is only really useful for downstream tooling authors to ease the PostCSS 7-to-8 transition.**

**webpack.config.js**

```js
module.exports = {
module: {
rules: [
{
test: /\.css$/i,
use: [
{ loader: "style-loader" },
{ loader: "css-loader" },
{
loader: "postcss-loader",
options: { implementation: require("postcss") },
},
{ loader: "sass-loader" },
],
},
],
},
};
```

## Examples

### SugarSS
Expand Down
7 changes: 6 additions & 1 deletion src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ export default async function loader(content, sourceMap, meta) {
? true
: options.postcssOptions.config;

const postcssFactory = options.implementation || postcss;

let loadedConfig;

if (configOption) {
Expand Down Expand Up @@ -105,7 +107,10 @@ export default async function loader(content, sourceMap, meta) {
let result;

try {
result = await postcss(plugins).process(root || content, processOptions);
result = await postcssFactory(plugins).process(
root || content,
processOptions
);
} catch (error) {
if (error.file) {
this.addDependency(error.file);
Expand Down
4 changes: 4 additions & 0 deletions src/options.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
"sourceMap": {
"description": "Enables/Disables generation of source maps (https://github.com/postcss/postcss-loader#sourcemap)",
"type": "boolean"
},
"implementation": {
"description": "The implementation of postcss to use, instead of the locally installed version (https://github.com/postcss/postcss-loader#implementation)",
"instanceof": "Function"
}
},
"additionalProperties": false
Expand Down
52 changes: 52 additions & 0 deletions test/__snapshots__/implementation.test.js.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`"implementation" option should work with a custom instance of PostCSS: css 1`] = `
"a {
color: black;
}

a {
color: red;
}

a {
color: green;
}

a {
color: blue;
}

.class {
-x-border-color: blue blue *;
-x-color: * #fafafa;
}

.class-foo {
-z-border-color: blue blue *;
-z-color: * #fafafa;
}

.phone {
&_title {
width: 500px;

@media (max-width: 500px) {
width: auto;
}

body.is_dark & {
color: white;
}
}

img {
display: block;
}
}
"
`;

exports[`"implementation" option should work with a custom instance of PostCSS: errors 1`] = `Array []`;

exports[`"implementation" option should work with a custom instance of PostCSS: warnings 1`] = `Array []`;
30 changes: 30 additions & 0 deletions test/__snapshots__/validate-options.test.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,36 @@ exports[`validate options should throw an error on the "execute" option with "te
-> Enables/Disables PostCSS parser support in 'CSS-in-JS' (https://github.com/postcss/postcss-loader#execute)"
`;

exports[`validate options should throw an error on the "implementation" option with "/test/" value 1`] = `
"Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.
- options.implementation should be an instance of function.
-> The implementation of postcss to use, instead of the locally installed version (https://github.com/postcss/postcss-loader#implementation)"
`;

exports[`validate options should throw an error on the "implementation" option with "[]" value 1`] = `
"Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.
- options.implementation should be an instance of function.
-> The implementation of postcss to use, instead of the locally installed version (https://github.com/postcss/postcss-loader#implementation)"
`;

exports[`validate options should throw an error on the "implementation" option with "{}" value 1`] = `
"Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.
- options.implementation should be an instance of function.
-> The implementation of postcss to use, instead of the locally installed version (https://github.com/postcss/postcss-loader#implementation)"
`;

exports[`validate options should throw an error on the "implementation" option with "1" value 1`] = `
"Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.
- options.implementation should be an instance of function.
-> The implementation of postcss to use, instead of the locally installed version (https://github.com/postcss/postcss-loader#implementation)"
`;

exports[`validate options should throw an error on the "implementation" option with "something" value 1`] = `
"Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.
- options.implementation should be an instance of function.
-> The implementation of postcss to use, instead of the locally installed version (https://github.com/postcss/postcss-loader#implementation)"
`;

exports[`validate options should throw an error on the "postcssOptions" option with "{"config":[]}" value 1`] = `
"Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.
- options.postcssOptions should be one of these:
Expand Down
26 changes: 26 additions & 0 deletions test/implementation.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import postcss from "postcss";

import {
compile,
getCompiler,
getErrors,
getCodeFromBundle,
getWarnings,
} from "./helpers";

describe('"implementation" option', () => {
it("should work with a custom instance of PostCSS", async () => {
const spy = jest.fn(postcss);
const compiler = getCompiler("./css/index.js", {
// Wrap the spy so it is an instanceof Function
implementation: (...args) => spy(...args),
});
const stats = await compile(compiler);
const codeFromBundle = getCodeFromBundle("style.css", stats);

expect(spy).toHaveBeenCalledTimes(1);
expect(codeFromBundle.css).toMatchSnapshot("css");
expect(getWarnings(stats)).toMatchSnapshot("warnings");
expect(getErrors(stats)).toMatchSnapshot("errors");
});
});
4 changes: 4 additions & 0 deletions test/validate-options.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ describe("validate options", () => {
success: [true, false],
failure: [1, /test/, [], {}, "something"],
},
implementation: {
success: [require("postcss")],
failure: [1, /test/, [], {}, "something"],
},
};

function stringifyValue(value) {
Expand Down