cb
-PostCSS Loader
-
-> Loads && processes CSS with [PostCSS](https://github.com/postcss/postcss)
-
-**Kind**: global function
-**Returns**: cb - cb Result
-**Requires**: module:path, module:loader-utils, module:schema-utils, module:postcss, module:postcss-load-config, module:Error
-**Version**: 2.0.0
-**Author**: Andrey Sitnik (@ai) String | Source |
-| map | Object | Source Map |
-
-
-* [loader(css, map)](#loader) ⇒ cb
- * [.cb](#loader.cb) : function
- * [.cb](#loader.cb) : function
-
-
-
-### loader.cb : function
-**Kind**: static typedef of [loader](#loader)
-
-| Param | Type | Description |
-| --- | --- | --- |
-| null | Object | Error |
-| result | String | Result (JS Module) |
-| map | Object | Source Map |
-
-
-
-### loader.cb : function
-**Kind**: static typedef of [loader](#loader)
-
-| Param | Type | Description |
-| --- | --- | --- |
-| null | Object | Error |
-| css | String | Result (Raw Module) |
-| map | Object | Source Map |
-
diff --git a/README.md b/README.md
index f7546968..a27a5b95 100644
--- a/README.md
+++ b/README.md
@@ -1,53 +1,495 @@
-[![npm][npm]][npm-url]
-[![node][node]][node-url]
-[![deps][deps]][deps-url]
-[![tests][tests]][tests-url]
-[![coverage][cover]][cover-url]
-[![chat][chat]][chat-url]
-
-
-
-
-
- Michael Ciniawsky
-
- |
-
-
-
-
- Alexander Krasnoyarov
-
- |
-
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[`"postcssOptions" option should work with the "stringifier" option with "Function" value: errors 1`] = `[]`;
+
+exports[`"postcssOptions" option should work with the "stringifier" option with "Function" value: warnings 1`] = `[]`;
+
+exports[`"postcssOptions" option should work with the "stringifier" option with "Object" value: 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[`"postcssOptions" option should work with the "stringifier" option with "Object" value: errors 1`] = `[]`;
+
+exports[`"postcssOptions" option should work with the "stringifier" option with "Object" value: warnings 1`] = `[]`;
+
+exports[`"postcssOptions" option should work with the "stringifier" option with "String" value: 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[`"postcssOptions" option should work with the "stringifier" option with "String" value: errors 1`] = `[]`;
+
+exports[`"postcssOptions" option should work with the "stringifier" option with "String" value: warnings 1`] = `[]`;
+
+exports[`"postcssOptions" option should work with the "syntax" option with "Object" value: css 1`] = `
+"a
+ color: black
+"
+`;
+
+exports[`"postcssOptions" option should work with the "syntax" option with "Object" value: errors 1`] = `[]`;
+
+exports[`"postcssOptions" option should work with the "syntax" option with "Object" value: warnings 1`] = `[]`;
+
+exports[`"postcssOptions" option should work with the "syntax" option with "String" value: css 1`] = `
+"a
+ color: black
+"
+`;
+
+exports[`"postcssOptions" option should work with the "syntax" option with "String" value: errors 1`] = `[]`;
+
+exports[`"postcssOptions" option should work with the "syntax" option with "String" value: warnings 1`] = `[]`;
+
+exports[`"postcssOptions" option should work without the specified values in the "postcssOptions" option: css 1`] = `
+"a { color: rgba(0, 0, 0, 1.0) }
+
+.foo {
+ float: right;
+}
+"
+`;
+
+exports[`"postcssOptions" option should work without the specified values in the "postcssOptions" option: errors 1`] = `[]`;
+
+exports[`"postcssOptions" option should work without the specified values in the "postcssOptions" option: warnings 1`] = `[]`;
diff --git a/test/__snapshots__/sourceMap.test.js.snap b/test/__snapshots__/sourceMap.test.js.snap
new file mode 100644
index 00000000..9c7d7c21
--- /dev/null
+++ b/test/__snapshots__/sourceMap.test.js.snap
@@ -0,0 +1,810 @@
+// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
+
+exports[`"sourceMap" option should generate inline source maps when the "devtool" is "false": 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;
+ }
+}
+
+/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0eWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSIsImZpbGUiOiJzdHlsZS5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyJhIHtcbiAgY29sb3I6IGJsYWNrO1xufVxuXG5hIHtcbiAgY29sb3I6IHJlZDtcbn1cblxuYSB7XG4gIGNvbG9yOiBncmVlbjtcbn1cblxuYSB7XG4gIGNvbG9yOiBibHVlO1xufVxuXG4uY2xhc3Mge1xuICAteC1ib3JkZXItY29sb3I6IGJsdWUgYmx1ZSAqO1xuICAteC1jb2xvcjogKiAjZmFmYWZhO1xufVxuXG4uY2xhc3MtZm9vIHtcbiAgLXotYm9yZGVyLWNvbG9yOiBibHVlIGJsdWUgKjtcbiAgLXotY29sb3I6ICogI2ZhZmFmYTtcbn1cblxuLnBob25lIHtcbiAgJl90aXRsZSB7XG4gICAgd2lkdGg6IDUwMHB4O1xuXG4gICAgQG1lZGlhIChtYXgtd2lkdGg6IDUwMHB4KSB7XG4gICAgICB3aWR0aDogYXV0bztcbiAgICB9XG5cbiAgICBib2R5LmlzX2RhcmsgJiB7XG4gICAgICBjb2xvcjogd2hpdGU7XG4gICAgfVxuICB9XG5cbiAgaW1nIHtcbiAgICBkaXNwbGF5OiBibG9jaztcbiAgfVxufVxuIl19 */"
+`;
+
+exports[`"sourceMap" option should generate inline source maps when the "devtool" is "false": errors 1`] = `[]`;
+
+exports[`"sourceMap" option should generate inline source maps when the "devtool" is "false": warnings 1`] = `[]`;
+
+exports[`"sourceMap" option should generate inline source maps when the "devtool" is "true": 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;
+ }
+}
+
+/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0eWxlLmNzcyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSIsImZpbGUiOiJzdHlsZS5jc3MiLCJzb3VyY2VzQ29udGVudCI6WyJhIHtcbiAgY29sb3I6IGJsYWNrO1xufVxuXG5hIHtcbiAgY29sb3I6IHJlZDtcbn1cblxuYSB7XG4gIGNvbG9yOiBncmVlbjtcbn1cblxuYSB7XG4gIGNvbG9yOiBibHVlO1xufVxuXG4uY2xhc3Mge1xuICAteC1ib3JkZXItY29sb3I6IGJsdWUgYmx1ZSAqO1xuICAteC1jb2xvcjogKiAjZmFmYWZhO1xufVxuXG4uY2xhc3MtZm9vIHtcbiAgLXotYm9yZGVyLWNvbG9yOiBibHVlIGJsdWUgKjtcbiAgLXotY29sb3I6ICogI2ZhZmFmYTtcbn1cblxuLnBob25lIHtcbiAgJl90aXRsZSB7XG4gICAgd2lkdGg6IDUwMHB4O1xuXG4gICAgQG1lZGlhIChtYXgtd2lkdGg6IDUwMHB4KSB7XG4gICAgICB3aWR0aDogYXV0bztcbiAgICB9XG5cbiAgICBib2R5LmlzX2RhcmsgJiB7XG4gICAgICBjb2xvcjogd2hpdGU7XG4gICAgfVxuICB9XG5cbiAgaW1nIHtcbiAgICBkaXNwbGF5OiBibG9jaztcbiAgfVxufVxuIl19 */"
+`;
+
+exports[`"sourceMap" option should generate inline source maps when the "devtool" is "true": errors 1`] = `[]`;
+
+exports[`"sourceMap" option should generate inline source maps when the "devtool" is "true": warnings 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps using the "postcssOptions.map" option with "true" value and previous loader returns source maps ("sass-loader"): css 1`] = `
+"a {
+ color: coral;
+}
+/*# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInN0eWxlLnNjc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7RUFBSSIsImZpbGUiOiJzdHlsZS5zY3NzIiwic291cmNlc0NvbnRlbnQiOlsiYSB7XG4gIGNvbG9yOiBjb3JhbDtcbn0iXX0= */"
+`;
+
+exports[`"sourceMap" option should generate source maps using the "postcssOptions.map" option with "true" value and previous loader returns source maps ("sass-loader"): errors 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps using the "postcssOptions.map" option with "true" value and previous loader returns source maps ("sass-loader"): warnings 1`] = `
+[
+ "ModuleWarning: Module Warning (from \`replaced original path\`):
+Deprecation The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0.
+
+More info: https://sass-lang.com/d/legacy-js-api",
+]
+`;
+
+exports[`"sourceMap" option should generate source maps using the "postcssOptions.map" option with values and previous loader returns source maps ("sass-loader"): css 1`] = `
+"a {
+ color: coral;
+}
+/*# sourceMappingURL=style.scss.map */"
+`;
+
+exports[`"sourceMap" option should generate source maps using the "postcssOptions.map" option with values and previous loader returns source maps ("sass-loader"): errors 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps using the "postcssOptions.map" option with values and previous loader returns source maps ("sass-loader"): source map 1`] = `
+{
+ "file": "style.scss",
+ "mappings": "AAAA;EAAI",
+ "names": [],
+ "sourceRoot": "",
+ "sources": [
+ "style.scss",
+ ],
+ "sourcesContent": [
+ "a {
+ color: coral;
+}",
+ ],
+ "version": 3,
+}
+`;
+
+exports[`"sourceMap" option should generate source maps using the "postcssOptions.map" option with values and previous loader returns source maps ("sass-loader"): warnings 1`] = `
+[
+ "ModuleWarning: Module Warning (from \`replaced original path\`):
+Deprecation The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0.
+
+More info: https://sass-lang.com/d/legacy-js-api",
+]
+`;
+
+exports[`"sourceMap" option should generate source maps when previous loader returns source maps ("less-loader"): css 1`] = `
+"a {
+ color: coral;
+}
+/*# sourceMappingURL=style.css.map */"
+`;
+
+exports[`"sourceMap" option should generate source maps when previous loader returns source maps ("less-loader"): errors 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps when previous loader returns source maps ("less-loader"): source map 1`] = `
+{
+ "mappings": "AAAA;EAAI,YAAA",
+ "names": [],
+ "sourceRoot": "",
+ "sources": [
+ "../../style.less",
+ ],
+ "sourcesContent": [
+ "a { color: coral }
+",
+ ],
+ "version": 3,
+}
+`;
+
+exports[`"sourceMap" option should generate source maps when previous loader returns source maps ("less-loader"): warnings 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps when previous loader returns source maps ("sass-loader"): css 1`] = `
+"a {
+ color: coral;
+}"
+`;
+
+exports[`"sourceMap" option should generate source maps when previous loader returns source maps ("sass-loader"): errors 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps when previous loader returns source maps ("sass-loader"): source map 1`] = `
+{
+ "mappings": "AAAA;EAAI",
+ "names": [],
+ "sourceRoot": "",
+ "sources": [
+ "scss/style.scss",
+ ],
+ "sourcesContent": [
+ "a {
+ color: coral;
+}",
+ ],
+ "version": 3,
+}
+`;
+
+exports[`"sourceMap" option should generate source maps when previous loader returns source maps ("sass-loader"): warnings 1`] = `
+[
+ "ModuleWarning: Module Warning (from \`replaced original path\`):
+Deprecation The legacy JS API is deprecated and will be removed in Dart Sass 2.0.0.
+
+More info: https://sass-lang.com/d/legacy-js-api",
+]
+`;
+
+exports[`"sourceMap" option should generate source maps when value is not specified and the "devtool" with "source-map" value: 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[`"sourceMap" option should generate source maps when value is not specified and the "devtool" with "source-map" value: errors 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps when value is not specified and the "devtool" with "source-map" value: source map 1`] = `
+{
+ "mappings": "AAAA",
+ "names": [],
+ "sourceRoot": "",
+ "sources": [
+ "css/style.css",
+ ],
+ "sourcesContent": [
+ "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;
+ }
+}
+",
+ ],
+ "version": 3,
+}
+`;
+
+exports[`"sourceMap" option should generate source maps when value is not specified and the "devtool" with "source-map" value: warnings 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps with "false" value, but the "postcssOptions.map" has values: 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[`"sourceMap" option should generate source maps with "false" value, but the "postcssOptions.map" has values: errors 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps with "false" value, but the "postcssOptions.map" has values: source map 1`] = `
+{
+ "file": "style.css",
+ "mappings": "AAAA",
+ "names": [],
+ "sourceRoot": "",
+ "sources": [
+ "style.css",
+ ],
+ "sourcesContent": [
+ "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;
+ }
+}
+",
+ ],
+ "version": 3,
+}
+`;
+
+exports[`"sourceMap" option should generate source maps with "false" value, but the "postcssOptions.map" has values: warnings 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps with "true" value and the "devtool" option with "source-map" value: 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[`"sourceMap" option should generate source maps with "true" value and the "devtool" option with "source-map" value: errors 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps with "true" value and the "devtool" option with "source-map" value: source map 1`] = `
+{
+ "mappings": "AAAA",
+ "names": [],
+ "sourceRoot": "",
+ "sources": [
+ "css/style.css",
+ ],
+ "sourcesContent": [
+ "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;
+ }
+}
+",
+ ],
+ "version": 3,
+}
+`;
+
+exports[`"sourceMap" option should generate source maps with "true" value and the "devtool" option with "source-map" value: warnings 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps with "true" value and the "devtool" with "false" value: 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[`"sourceMap" option should generate source maps with "true" value and the "devtool" with "false" value: errors 1`] = `[]`;
+
+exports[`"sourceMap" option should generate source maps with "true" value and the "devtool" with "false" value: source map 1`] = `
+{
+ "mappings": "AAAA",
+ "names": [],
+ "sourceRoot": "",
+ "sources": [
+ "css/style.css",
+ ],
+ "sourcesContent": [
+ "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;
+ }
+}
+",
+ ],
+ "version": 3,
+}
+`;
+
+exports[`"sourceMap" option should generate source maps with "true" value and the "devtool" with "false" value: warnings 1`] = `[]`;
+
+exports[`"sourceMap" option should not generate source maps when value is not specified and the "devtool" option with "source-map" value: 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[`"sourceMap" option should not generate source maps when value is not specified and the "devtool" option with "source-map" value: errors 1`] = `[]`;
+
+exports[`"sourceMap" option should not generate source maps when value is not specified and the "devtool" option with "source-map" value: warnings 1`] = `[]`;
+
+exports[`"sourceMap" option should not generate source maps with "false" value and the "devtool" option with "false" value: 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[`"sourceMap" option should not generate source maps with "false" value and the "devtool" option with "false" value: errors 1`] = `[]`;
+
+exports[`"sourceMap" option should not generate source maps with "false" value and the "devtool" option with "false" value: warnings 1`] = `[]`;
+
+exports[`"sourceMap" option should not generate source maps with "false" value and the "devtool" option with "source-map" value: 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[`"sourceMap" option should not generate source maps with "false" value and the "devtool" option with "source-map" value: errors 1`] = `[]`;
+
+exports[`"sourceMap" option should not generate source maps with "false" value and the "devtool" option with "source-map" value: warnings 1`] = `[]`;
diff --git a/test/__snapshots__/validate-options.test.js.snap b/test/__snapshots__/validate-options.test.js.snap
new file mode 100644
index 00000000..f359e169
--- /dev/null
+++ b/test/__snapshots__/validate-options.test.js.snap
@@ -0,0 +1,158 @@
+// Jest Snapshot v1, https://jestjs.io/docs/snapshot-testing
+
+exports[`validate options should throw an error on the "execute" 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.execute should be a boolean.
+ -> Enables/Disables PostCSS parser support in 'CSS-in-JS'.
+ -> Read more at https://github.com/webpack/postcss-loader#execute"
+`;
+
+exports[`validate options should throw an error on the "execute" option with "[]" value 1`] = `
+"Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.
+ - options.execute should be a boolean.
+ -> Enables/Disables PostCSS parser support in 'CSS-in-JS'.
+ -> Read more at https://github.com/webpack/postcss-loader#execute"
+`;
+
+exports[`validate options should throw an error on the "execute" option with "{"foo":"bar"}" value 1`] = `
+"Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.
+ - options.execute should be a boolean.
+ -> Enables/Disables PostCSS parser support in 'CSS-in-JS'.
+ -> Read more at https://github.com/webpack/postcss-loader#execute"
+`;
+
+exports[`validate options should throw an error on the "execute" option with "{}" value 1`] = `
+"Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.
+ - options.execute should be a boolean.
+ -> Enables/Disables PostCSS parser support in 'CSS-in-JS'.
+ -> Read more at https://github.com/webpack/postcss-loader#execute"
+`;
+
+exports[`validate options should throw an error on the "execute" 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.execute should be a boolean.
+ -> Enables/Disables PostCSS parser support in 'CSS-in-JS'.
+ -> Read more at https://github.com/webpack/postcss-loader#execute"
+`;
+
+exports[`validate options should throw an error on the "execute" 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.execute should be a boolean.
+ -> Enables/Disables PostCSS parser support in 'CSS-in-JS'.
+ -> Read more at https://github.com/webpack/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 one of these:
+ string | function
+ -> The implementation of postcss to use, instead of the locally installed version
+ -> Read more at https://github.com/webpack/postcss-loader#implementation
+ Details:
+ * options.implementation should be a string.
+ * options.implementation should be an instance of function."
+`;
+
+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 one of these:
+ string | function
+ -> The implementation of postcss to use, instead of the locally installed version
+ -> Read more at https://github.com/webpack/postcss-loader#implementation
+ Details:
+ * options.implementation should be a string.
+ * options.implementation should be an instance of function."
+`;
+
+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 one of these:
+ string | function
+ -> The implementation of postcss to use, instead of the locally installed version
+ -> Read more at https://github.com/webpack/postcss-loader#implementation
+ Details:
+ * options.implementation should be a string.
+ * options.implementation should be an instance of function."
+`;
+
+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 one of these:
+ string | function
+ -> The implementation of postcss to use, instead of the locally installed version
+ -> Read more at https://github.com/webpack/postcss-loader#implementation
+ Details:
+ * options.implementation should be a string.
+ * options.implementation should be an instance of function."
+`;
+
+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:
+ object { config?, … } | function
+ -> Options to pass through to \`Postcss\`.
+ -> Read more at https://github.com/webpack/postcss-loader#postcssOptions
+ Details:
+ * options.postcssOptions.config should be one of these:
+ string | boolean
+ -> Allows to specify PostCSS config path.
+ -> Read more at https://github.com/webpack/postcss-loader#config
+ Details:
+ * options.postcssOptions.config should be a string.
+ -> Allows to specify the path to the configuration file
+ * options.postcssOptions.config should be a boolean.
+ -> Enables/Disables autoloading config"
+`;
+
+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:
+ object { config?, … } | function
+ -> Options to pass through to \`Postcss\`.
+ -> Read more at https://github.com/webpack/postcss-loader#postcssOptions
+ Details:
+ * options.postcssOptions.config should be one of these:
+ string | boolean
+ -> Allows to specify PostCSS config path.
+ -> Read more at https://github.com/webpack/postcss-loader#config
+ Details:
+ * options.postcssOptions.config should be a string.
+ -> Allows to specify the path to the configuration file
+ * options.postcssOptions.config should be a boolean.
+ -> Enables/Disables autoloading config"
+`;
+
+exports[`validate options should throw an error on the "sourceMap" 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.sourceMap should be a boolean.
+ -> Enables/Disables generation of source maps.
+ -> Read more at https://github.com/webpack/postcss-loader#sourcemap"
+`;
+
+exports[`validate options should throw an error on the "sourceMap" option with "[]" value 1`] = `
+"Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.
+ - options.sourceMap should be a boolean.
+ -> Enables/Disables generation of source maps.
+ -> Read more at https://github.com/webpack/postcss-loader#sourcemap"
+`;
+
+exports[`validate options should throw an error on the "sourceMap" option with "{}" value 1`] = `
+"Invalid options object. PostCSS Loader has been initialized using an options object that does not match the API schema.
+ - options.sourceMap should be a boolean.
+ -> Enables/Disables generation of source maps.
+ -> Read more at https://github.com/webpack/postcss-loader#sourcemap"
+`;
+
+exports[`validate options should throw an error on the "sourceMap" 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.sourceMap should be a boolean.
+ -> Enables/Disables generation of source maps.
+ -> Read more at https://github.com/webpack/postcss-loader#sourcemap"
+`;
+
+exports[`validate options should throw an error on the "sourceMap" 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.sourceMap should be a boolean.
+ -> Enables/Disables generation of source maps.
+ -> Read more at https://github.com/webpack/postcss-loader#sourcemap"
+`;
diff --git a/test/cjs.test.js b/test/cjs.test.js
new file mode 100644
index 00000000..dc8321a3
--- /dev/null
+++ b/test/cjs.test.js
@@ -0,0 +1,8 @@
+import src from "../src";
+import cjs from "../src/cjs";
+
+describe("cjs", () => {
+ it("should exported", () => {
+ expect(cjs).toEqual(src);
+ });
+});
diff --git a/test/config-autoload.test.js b/test/config-autoload.test.js
new file mode 100644
index 00000000..504bcfcc
--- /dev/null
+++ b/test/config-autoload.test.js
@@ -0,0 +1,216 @@
+import fs from "node:fs";
+import path from "node:path";
+
+import { loadConfig } from "../src/utils";
+
+const testDirectory = path.resolve(__dirname, "fixtures", "config-autoload");
+
+const loaderContext = {
+ fs,
+ addBuildDependency: () => true,
+ addDependency: () => true,
+};
+
+describe("autoload config", () => {
+ it('should load ".postcssrc"', async () => {
+ const loadedConfig = await loadConfig(
+ loaderContext,
+ path.resolve(testDirectory, "rc"),
+ );
+
+ expect(loadedConfig.config.map).toBe(false);
+ expect(loadedConfig.config.from).toBe("./test/rc/fixtures/index.css");
+ expect(loadedConfig.config.to).toBe("./test/rc/expect/index.css");
+ expect(Object.keys(loadedConfig.config.plugins)).toHaveLength(2);
+ expect(loadedConfig.filepath).toEqual(
+ path.resolve(testDirectory, "rc", ".postcssrc"),
+ );
+ });
+
+ it('should load ".postcssrc.js"', async () => {
+ const loadedConfig = await loadConfig(
+ loaderContext,
+ path.resolve(testDirectory, "rc-js"),
+ );
+
+ expect(loadedConfig.config.map).toBe(false);
+ expect(loadedConfig.config.from).toBe("./test/rc-js/fixtures/index.css");
+ expect(loadedConfig.config.to).toBe("./test/rc-js/expect/index.css");
+ expect(Object.keys(loadedConfig.config.plugins)).toHaveLength(2);
+ expect(loadedConfig.filepath).toEqual(
+ path.resolve(testDirectory, "rc-js", ".postcssrc.js"),
+ );
+ });
+
+ it('should load "package.json"', async () => {
+ const loadedConfig = await loadConfig(
+ loaderContext,
+ path.resolve(testDirectory, "pkg"),
+ );
+
+ expect(loadedConfig.config.parser).toBe(false);
+ expect(loadedConfig.config.syntax).toBe(false);
+ expect(loadedConfig.config.map).toBe(false);
+ expect(loadedConfig.config.from).toBe("./index.css");
+ expect(loadedConfig.config.to).toBe("./index.css");
+ expect(Object.keys(loadedConfig.config.plugins)).toHaveLength(2);
+ expect(loadedConfig.filepath).toEqual(
+ path.resolve(testDirectory, "pkg", "package.json"),
+ );
+ });
+
+ it('should load "postcss.config.js" with "Object" syntax of plugins', async () => {
+ const loadedConfig = await loadConfig(
+ loaderContext,
+ path.resolve(testDirectory, "js/object"),
+ );
+
+ expect(loadedConfig.config.map).toBe(false);
+ expect(loadedConfig.config.from).toBe(
+ "./test/fixtures/config-autoload/js/object/index.css",
+ );
+ expect(loadedConfig.config.to).toBe(
+ "./test/fixtures/config-autoload/js/object/expect/index.css",
+ );
+ expect(Object.keys(loadedConfig.config.plugins)).toHaveLength(2);
+ expect(loadedConfig.filepath).toEqual(
+ path.resolve(testDirectory, "js/object", "postcss.config.js"),
+ );
+ });
+
+ it('should load "postcss.config.cts" with "Object" syntax of plugins', async () => {
+ const loadedConfig = await loadConfig(
+ loaderContext,
+ path.resolve(testDirectory, "ts/object"),
+ );
+
+ expect(loadedConfig.config.map).toBe(false);
+ expect(loadedConfig.config.from).toBe(
+ "./test/fixtures/config-autoload/ts/object/index.css",
+ );
+ expect(loadedConfig.config.to).toBe(
+ "./test/fixtures/config-autoload/ts/object/expect/index.css",
+ );
+ expect(Object.keys(loadedConfig.config.plugins)).toHaveLength(2);
+ expect(loadedConfig.filepath).toEqual(
+ path.resolve(testDirectory, "ts/object", "postcss.config.ts"),
+ );
+ });
+
+ it('should load "postcss.config.js" with "Array" syntax of plugins', async () => {
+ const loadedConfig = await loadConfig(
+ loaderContext,
+ path.resolve(testDirectory, "js/array"),
+ );
+
+ expect(loadedConfig.config.map).toBe(false);
+ expect(loadedConfig.config.from).toBe(
+ "./test/fixtures/config-autoload/js/object/index.css",
+ );
+ expect(loadedConfig.config.to).toBe(
+ "./test/fixtures/config-autoload/js/object/expect/index.css",
+ );
+ expect(Object.keys(loadedConfig.config.plugins)).toHaveLength(4);
+ expect(loadedConfig.filepath).toEqual(
+ path.resolve(testDirectory, "js/array", "postcss.config.js"),
+ );
+ });
+
+ it('should load ESM version of "postcss.config.js" with "Array" syntax of plugins', async () => {
+ const loadedConfig = await loadConfig(
+ loaderContext,
+ path.resolve(testDirectory, "js/array-esm-js"),
+ );
+
+ expect(loadedConfig.config.map).toBe(false);
+ expect(loadedConfig.config.from).toBe(
+ "./test/fixtures/config-autoload/js/object/index.css",
+ );
+ expect(loadedConfig.config.to).toBe(
+ "./test/fixtures/config-autoload/js/object/expect/index.css",
+ );
+ expect(Object.keys(loadedConfig.config.plugins)).toHaveLength(4);
+ expect(loadedConfig.filepath).toEqual(
+ path.resolve(testDirectory, "js/array-esm-js", "postcss.config.js"),
+ );
+ });
+
+ // TODO Test manually with NODE_OPTIONS=--experimental-vm-modules to enable ESM support in jest
+ // eslint-disable-next-line jest/no-disabled-tests
+ it.skip('should load "postcss.config.mjs" with "Array" syntax of plugins', async () => {
+ const loadedConfig = await loadConfig(
+ loaderContext,
+ path.resolve(testDirectory, "js/array-mjs"),
+ );
+
+ expect(loadedConfig.config.map).toBe(false);
+ expect(loadedConfig.config.from).toBe(
+ "./test/fixtures/config-autoload/js/object/index.css",
+ );
+ expect(loadedConfig.config.to).toBe(
+ "./test/fixtures/config-autoload/js/object/expect/index.css",
+ );
+ expect(Object.keys(loadedConfig.config.plugins)).toHaveLength(4);
+ expect(loadedConfig.filepath).toEqual(
+ path.resolve(testDirectory, "js/array-mjs", "postcss.config.mjs"),
+ );
+ });
+
+ it('should load "postcss.config.ts" with "Array" syntax of plugins', async () => {
+ const loadedConfig = await loadConfig(
+ loaderContext,
+ path.resolve(testDirectory, "ts/array"),
+ );
+
+ expect(loadedConfig.config.map).toBe(false);
+ expect(loadedConfig.config.from).toBe(
+ "./test/fixtures/config-autoload/ts/object/index.css",
+ );
+ expect(loadedConfig.config.to).toBe(
+ "./test/fixtures/config-autoload/ts/object/expect/index.css",
+ );
+ expect(Object.keys(loadedConfig.config.plugins)).toHaveLength(4);
+ expect(loadedConfig.filepath).toEqual(
+ path.resolve(testDirectory, "ts/array", "postcss.config.ts"),
+ );
+ });
+
+ it('should load "postcss.config.mts" with "Array" syntax of plugins', async () => {
+ const loadedConfig = await loadConfig(
+ loaderContext,
+ path.resolve(testDirectory, "ts/array-mts"),
+ );
+
+ expect(loadedConfig.config.map).toBe(false);
+ expect(loadedConfig.config.from).toBe(
+ "./test/fixtures/config-autoload/ts/object/index.css",
+ );
+ expect(loadedConfig.config.to).toBe(
+ "./test/fixtures/config-autoload/ts/object/expect/index.css",
+ );
+ expect(Object.keys(loadedConfig.config.plugins)).toHaveLength(4);
+ expect(loadedConfig.filepath).toEqual(
+ path.resolve(testDirectory, "ts/array-mts", "postcss.config.mts"),
+ );
+ });
+
+ it('should load empty ".postcssrc"', async () => {
+ const loadedConfig = await loadConfig(
+ loaderContext,
+ path.resolve(testDirectory, "empty/.postcssrc"),
+ );
+
+ expect(loadedConfig.config).toBeUndefined();
+ expect(loadedConfig.filepath).toEqual(
+ path.resolve(testDirectory, "empty/.postcssrc"),
+ );
+ });
+
+ it('should throw an error on "unresolved" config', async () => {
+ try {
+ await loadConfig(loaderContext, path.resolve("unresolved"));
+ } catch (error) {
+ expect(error.message).toMatch(/^No PostCSS config found in: (.*)$/);
+ }
+ });
+});
diff --git a/test/execute.test.js b/test/execute.test.js
new file mode 100644
index 00000000..99c50a94
--- /dev/null
+++ b/test/execute.test.js
@@ -0,0 +1,122 @@
+import path from "node:path";
+
+import {
+ compile,
+ getCodeFromBundle,
+ getCompiler,
+ getErrors,
+ getWarnings,
+} from "./helpers";
+
+describe('"execute" option', () => {
+ it('should work with "Boolean" value', async () => {
+ const compiler = getCompiler(
+ "./jss/exec/index.js",
+ {},
+ {
+ module: {
+ rules: [
+ {
+ test: /style\.(exec\.js|js)$/i,
+ use: [
+ {
+ loader: require.resolve("./helpers/testLoader"),
+ options: {},
+ },
+ {
+ loader: path.resolve(__dirname, "../src"),
+ options: {
+ execute: true,
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ );
+ const stats = await compile(compiler);
+ const codeFromBundle = getCodeFromBundle("style.exec.js", stats);
+
+ expect(codeFromBundle.css).toMatchSnapshot("css");
+ expect(getWarnings(stats)).toMatchSnapshot("warnings");
+ expect(getErrors(stats)).toMatchSnapshot("errors");
+ });
+
+ it('should work with "postcss-js" parser', async () => {
+ const compiler = getCompiler(
+ "./jss/postcss-js/index.js",
+ {},
+ {
+ module: {
+ rules: [
+ {
+ test: /style\.js$/i,
+ use: [
+ {
+ loader: require.resolve("./helpers/testLoader"),
+ options: {},
+ },
+ {
+ loader: path.resolve(__dirname, "../src"),
+ options: {
+ postcssOptions: {
+ parser: "postcss-js",
+ },
+ execute: true,
+ },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ );
+ const stats = await compile(compiler);
+ const codeFromBundle = getCodeFromBundle("style.js", stats);
+
+ expect(codeFromBundle.css).toMatchSnapshot("css");
+ expect(getWarnings(stats)).toMatchSnapshot("warnings");
+ expect(getErrors(stats)).toMatchSnapshot("errors");
+ });
+
+ it("should reuse PostCSS AST with JS styles", async () => {
+ const spy = jest.fn();
+ const compiler = getCompiler(
+ "./jss/exec/index.js",
+ {},
+ {
+ module: {
+ rules: [
+ {
+ test: /style\.(exec\.js|js)$/i,
+ use: [
+ {
+ loader: require.resolve("./helpers/testLoader"),
+ options: {},
+ },
+ {
+ loader: path.resolve(__dirname, "../src"),
+ options: {
+ execute: true,
+ },
+ },
+ {
+ loader: require.resolve("./helpers/astLoader"),
+ options: { spy, execute: true },
+ },
+ ],
+ },
+ ],
+ },
+ },
+ );
+ const stats = await compile(compiler);
+ const codeFromBundle = getCodeFromBundle("style.exec.js", stats);
+
+ expect(spy).toHaveBeenCalledTimes(1);
+ expect(codeFromBundle.css).toMatchSnapshot("css");
+ expect(getWarnings(stats)).toMatchSnapshot("warnings");
+ expect(getErrors(stats)).toMatchSnapshot("errors");
+ });
+});
diff --git a/test/fixtures/config-autoload/empty/.postcssrc b/test/fixtures/config-autoload/empty/.postcssrc
new file mode 100644
index 00000000..8b137891
--- /dev/null
+++ b/test/fixtures/config-autoload/empty/.postcssrc
@@ -0,0 +1 @@
+
diff --git a/test/fixtures/config-autoload/empty/expect/index.css b/test/fixtures/config-autoload/empty/expect/index.css
new file mode 100644
index 00000000..500f931b
--- /dev/null
+++ b/test/fixtures/config-autoload/empty/expect/index.css
@@ -0,0 +1,7 @@
+.import {
+ color: red;
+}
+
+.test {
+ color: blue;
+}
diff --git a/test/fixtures/config-autoload/empty/expect/index.sss b/test/fixtures/config-autoload/empty/expect/index.sss
new file mode 100644
index 00000000..13f8e942
--- /dev/null
+++ b/test/fixtures/config-autoload/empty/expect/index.sss
@@ -0,0 +1,7 @@
+.import {
+ color: red
+}
+
+.test {
+ color: blue
+}
diff --git a/test/fixtures/config-autoload/empty/fixtures/imports/section.css b/test/fixtures/config-autoload/empty/fixtures/imports/section.css
new file mode 100644
index 00000000..626b1b56
--- /dev/null
+++ b/test/fixtures/config-autoload/empty/fixtures/imports/section.css
@@ -0,0 +1,3 @@
+.import {
+ color: red;
+}
diff --git a/test/fixtures/config-autoload/empty/fixtures/imports/section.sss b/test/fixtures/config-autoload/empty/fixtures/imports/section.sss
new file mode 100644
index 00000000..ecc74a7a
--- /dev/null
+++ b/test/fixtures/config-autoload/empty/fixtures/imports/section.sss
@@ -0,0 +1,2 @@
+.import
+ color: red
diff --git a/test/fixtures/config-autoload/empty/fixtures/index.css b/test/fixtures/config-autoload/empty/fixtures/index.css
new file mode 100644
index 00000000..48162650
--- /dev/null
+++ b/test/fixtures/config-autoload/empty/fixtures/index.css
@@ -0,0 +1,5 @@
+@import "imports/section.css";
+
+.test {
+ color: blue;
+}
diff --git a/test/fixtures/config-autoload/empty/fixtures/index.sss b/test/fixtures/config-autoload/empty/fixtures/index.sss
new file mode 100644
index 00000000..bedaed31
--- /dev/null
+++ b/test/fixtures/config-autoload/empty/fixtures/index.sss
@@ -0,0 +1,4 @@
+@import "imports/section.sss"
+
+.test
+ color: blue
diff --git a/test/fixtures/config-autoload/err/options/parser/.postcssrc.js b/test/fixtures/config-autoload/err/options/parser/.postcssrc.js
new file mode 100644
index 00000000..dba61ac0
--- /dev/null
+++ b/test/fixtures/config-autoload/err/options/parser/.postcssrc.js
@@ -0,0 +1,5 @@
+module.exports = function () {
+ return {
+ parser: 'postcss-parser'
+ }
+};
diff --git a/test/fixtures/config-autoload/err/options/stringifier/.postcssrc.js b/test/fixtures/config-autoload/err/options/stringifier/.postcssrc.js
new file mode 100644
index 00000000..390663f2
--- /dev/null
+++ b/test/fixtures/config-autoload/err/options/stringifier/.postcssrc.js
@@ -0,0 +1,5 @@
+module.exports = function () {
+ return {
+ stringifier: 'postcss-stringifier'
+ }
+};
diff --git a/test/fixtures/config-autoload/err/options/syntax/.postcssrc.js b/test/fixtures/config-autoload/err/options/syntax/.postcssrc.js
new file mode 100644
index 00000000..4804efcf
--- /dev/null
+++ b/test/fixtures/config-autoload/err/options/syntax/.postcssrc.js
@@ -0,0 +1,5 @@
+module.exports = function () {
+ return {
+ syntax: 'postcss-syntax'
+ }
+};
diff --git a/test/fixtures/config-autoload/err/plugins/.postcssrc.js b/test/fixtures/config-autoload/err/plugins/.postcssrc.js
new file mode 100644
index 00000000..c1f976e1
--- /dev/null
+++ b/test/fixtures/config-autoload/err/plugins/.postcssrc.js
@@ -0,0 +1,7 @@
+module.exports = function () {
+ return {
+ plugins: [
+ require('./plugin')
+ ]
+ }
+};
diff --git a/test/fixtures/config-autoload/err/plugins/array/.postcssrc.js b/test/fixtures/config-autoload/err/plugins/array/.postcssrc.js
new file mode 100644
index 00000000..96637a16
--- /dev/null
+++ b/test/fixtures/config-autoload/err/plugins/array/.postcssrc.js
@@ -0,0 +1,7 @@
+module.exports = function () {
+ return {
+ plugins: [
+ require('postcss-plugin')
+ ]
+ }
+};
diff --git a/test/fixtures/config-autoload/err/plugins/array/options/.postcssrc.js b/test/fixtures/config-autoload/err/plugins/array/options/.postcssrc.js
new file mode 100644
index 00000000..96637a16
--- /dev/null
+++ b/test/fixtures/config-autoload/err/plugins/array/options/.postcssrc.js
@@ -0,0 +1,7 @@
+module.exports = function () {
+ return {
+ plugins: [
+ require('postcss-plugin')
+ ]
+ }
+};
diff --git a/test/fixtures/config-autoload/err/plugins/object/.postcssrc.js b/test/fixtures/config-autoload/err/plugins/object/.postcssrc.js
new file mode 100644
index 00000000..a89a9768
--- /dev/null
+++ b/test/fixtures/config-autoload/err/plugins/object/.postcssrc.js
@@ -0,0 +1,7 @@
+module.exports = function () {
+ return {
+ plugins: {
+ 'postcss-plugin': {}
+ }
+ }
+};
diff --git a/test/fixtures/config-autoload/err/plugins/object/options/.postcssrc.js b/test/fixtures/config-autoload/err/plugins/object/options/.postcssrc.js
new file mode 100644
index 00000000..5985c978
--- /dev/null
+++ b/test/fixtures/config-autoload/err/plugins/object/options/.postcssrc.js
@@ -0,0 +1,7 @@
+module.exports = function () {
+ return {
+ plugins: {
+ 'postcss-plugin': { option: true }
+ }
+ }
+};
diff --git a/test/fixtures/config-autoload/err/plugins/plugin.js b/test/fixtures/config-autoload/err/plugins/plugin.js
new file mode 100644
index 00000000..8f7026e5
--- /dev/null
+++ b/test/fixtures/config-autoload/err/plugins/plugin.js
@@ -0,0 +1 @@
+module.exports = 'Invalid Plugin';
diff --git a/test/fixtures/config-autoload/js/array-esm-js/imports/section.css b/test/fixtures/config-autoload/js/array-esm-js/imports/section.css
new file mode 100644
index 00000000..4568aa99
--- /dev/null
+++ b/test/fixtures/config-autoload/js/array-esm-js/imports/section.css
@@ -0,0 +1,3 @@
+.import {
+ color: goldenrod;
+}
diff --git a/test/fixtures/config-autoload/js/array-esm-js/index.css b/test/fixtures/config-autoload/js/array-esm-js/index.css
new file mode 100644
index 00000000..3b228825
--- /dev/null
+++ b/test/fixtures/config-autoload/js/array-esm-js/index.css
@@ -0,0 +1,5 @@
+@import 'imports/section.css';
+
+.test {
+ color: cyan;
+}
diff --git a/test/fixtures/config-autoload/js/array-esm-js/index.js b/test/fixtures/config-autoload/js/array-esm-js/index.js
new file mode 100644
index 00000000..07bf0b31
--- /dev/null
+++ b/test/fixtures/config-autoload/js/array-esm-js/index.js
@@ -0,0 +1,3 @@
+import style from './index.css'
+
+export default style
diff --git a/test/fixtures/config-autoload/js/array-esm-js/postcss.config.js b/test/fixtures/config-autoload/js/array-esm-js/postcss.config.js
new file mode 100644
index 00000000..53cd49c0
--- /dev/null
+++ b/test/fixtures/config-autoload/js/array-esm-js/postcss.config.js
@@ -0,0 +1,21 @@
+import postcssNested from 'postcss-nested';
+export default function (api) {
+ return {
+ parser: 'sugarss',
+ syntax: 'sugarss',
+ map: api.mode === 'development' ? 'inline' : false,
+ from: './test/fixtures/config-autoload/js/object/index.css',
+ to: './test/fixtures/config-autoload/js/object/expect/index.css',
+ plugins: [
+ 'postcss-import',
+ [
+ 'postcss-nested',
+ {
+ // Options
+ }
+ ],
+ postcssNested,
+ postcssNested({ /* Options */ }),
+ ]
+ }
+};
diff --git a/test/fixtures/config-autoload/js/array-mjs/imports/section.css b/test/fixtures/config-autoload/js/array-mjs/imports/section.css
new file mode 100644
index 00000000..4568aa99
--- /dev/null
+++ b/test/fixtures/config-autoload/js/array-mjs/imports/section.css
@@ -0,0 +1,3 @@
+.import {
+ color: goldenrod;
+}
diff --git a/test/fixtures/config-autoload/js/array-mjs/index.css b/test/fixtures/config-autoload/js/array-mjs/index.css
new file mode 100644
index 00000000..3b228825
--- /dev/null
+++ b/test/fixtures/config-autoload/js/array-mjs/index.css
@@ -0,0 +1,5 @@
+@import 'imports/section.css';
+
+.test {
+ color: cyan;
+}
diff --git a/test/fixtures/config-autoload/js/array-mjs/index.js b/test/fixtures/config-autoload/js/array-mjs/index.js
new file mode 100644
index 00000000..07bf0b31
--- /dev/null
+++ b/test/fixtures/config-autoload/js/array-mjs/index.js
@@ -0,0 +1,3 @@
+import style from './index.css'
+
+export default style
diff --git a/test/fixtures/config-autoload/js/array-mjs/postcss.config.mjs b/test/fixtures/config-autoload/js/array-mjs/postcss.config.mjs
new file mode 100644
index 00000000..53cd49c0
--- /dev/null
+++ b/test/fixtures/config-autoload/js/array-mjs/postcss.config.mjs
@@ -0,0 +1,21 @@
+import postcssNested from 'postcss-nested';
+export default function (api) {
+ return {
+ parser: 'sugarss',
+ syntax: 'sugarss',
+ map: api.mode === 'development' ? 'inline' : false,
+ from: './test/fixtures/config-autoload/js/object/index.css',
+ to: './test/fixtures/config-autoload/js/object/expect/index.css',
+ plugins: [
+ 'postcss-import',
+ [
+ 'postcss-nested',
+ {
+ // Options
+ }
+ ],
+ postcssNested,
+ postcssNested({ /* Options */ }),
+ ]
+ }
+};
diff --git a/test/fixtures/config-autoload/js/array/imports/section.css b/test/fixtures/config-autoload/js/array/imports/section.css
new file mode 100644
index 00000000..4568aa99
--- /dev/null
+++ b/test/fixtures/config-autoload/js/array/imports/section.css
@@ -0,0 +1,3 @@
+.import {
+ color: goldenrod;
+}
diff --git a/test/fixtures/config-autoload/js/array/index.css b/test/fixtures/config-autoload/js/array/index.css
new file mode 100644
index 00000000..3b228825
--- /dev/null
+++ b/test/fixtures/config-autoload/js/array/index.css
@@ -0,0 +1,5 @@
+@import 'imports/section.css';
+
+.test {
+ color: cyan;
+}
diff --git a/test/fixtures/config-autoload/js/array/index.js b/test/fixtures/config-autoload/js/array/index.js
new file mode 100644
index 00000000..07bf0b31
--- /dev/null
+++ b/test/fixtures/config-autoload/js/array/index.js
@@ -0,0 +1,3 @@
+import style from './index.css'
+
+export default style
diff --git a/test/fixtures/config-autoload/js/array/postcss.config.js b/test/fixtures/config-autoload/js/array/postcss.config.js
new file mode 100644
index 00000000..33b130ba
--- /dev/null
+++ b/test/fixtures/config-autoload/js/array/postcss.config.js
@@ -0,0 +1,20 @@
+module.exports = function (api) {
+ return {
+ parser: 'sugarss',
+ syntax: 'sugarss',
+ map: api.mode === 'development' ? 'inline' : false,
+ from: './test/fixtures/config-autoload/js/object/index.css',
+ to: './test/fixtures/config-autoload/js/object/expect/index.css',
+ plugins: [
+ 'postcss-import',
+ [
+ 'postcss-nested',
+ {
+ // Options
+ }
+ ],
+ require('postcss-nested'),
+ require('postcss-nested')({ /* Options */ }),
+ ]
+ }
+};
diff --git a/test/fixtures/config-autoload/js/object/imports/section.css b/test/fixtures/config-autoload/js/object/imports/section.css
new file mode 100644
index 00000000..626b1b56
--- /dev/null
+++ b/test/fixtures/config-autoload/js/object/imports/section.css
@@ -0,0 +1,3 @@
+.import {
+ color: red;
+}
diff --git a/test/fixtures/config-autoload/js/object/index.css b/test/fixtures/config-autoload/js/object/index.css
new file mode 100644
index 00000000..48162650
--- /dev/null
+++ b/test/fixtures/config-autoload/js/object/index.css
@@ -0,0 +1,5 @@
+@import "imports/section.css";
+
+.test {
+ color: blue;
+}
diff --git a/test/fixtures/config-autoload/js/object/index.js b/test/fixtures/config-autoload/js/object/index.js
new file mode 100644
index 00000000..07bf0b31
--- /dev/null
+++ b/test/fixtures/config-autoload/js/object/index.js
@@ -0,0 +1,3 @@
+import style from './index.css'
+
+export default style
diff --git a/test/fixtures/config-autoload/js/object/postcss.config.js b/test/fixtures/config-autoload/js/object/postcss.config.js
new file mode 100644
index 00000000..b7e044db
--- /dev/null
+++ b/test/fixtures/config-autoload/js/object/postcss.config.js
@@ -0,0 +1,13 @@
+module.exports = function (api) {
+ return {
+ parser: 'sugarss',
+ syntax: 'sugarss',
+ map: api.mode === 'development' ? 'inline' : false,
+ from: './test/fixtures/config-autoload/js/object/index.css',
+ to: './test/fixtures/config-autoload/js/object/expect/index.css',
+ plugins: {
+ 'postcss-import': {},
+ 'postcss-nested': {},
+ }
+ }
+};
diff --git a/test/fixtures/config-autoload/pkg/imports/section.css b/test/fixtures/config-autoload/pkg/imports/section.css
new file mode 100644
index 00000000..626b1b56
--- /dev/null
+++ b/test/fixtures/config-autoload/pkg/imports/section.css
@@ -0,0 +1,3 @@
+.import {
+ color: red;
+}
diff --git a/test/fixtures/config-autoload/pkg/index.css b/test/fixtures/config-autoload/pkg/index.css
new file mode 100644
index 00000000..48162650
--- /dev/null
+++ b/test/fixtures/config-autoload/pkg/index.css
@@ -0,0 +1,5 @@
+@import "imports/section.css";
+
+.test {
+ color: blue;
+}
diff --git a/test/fixtures/config-autoload/pkg/index.js b/test/fixtures/config-autoload/pkg/index.js
new file mode 100644
index 00000000..07bf0b31
--- /dev/null
+++ b/test/fixtures/config-autoload/pkg/index.js
@@ -0,0 +1,3 @@
+import style from './index.css'
+
+export default style
diff --git a/test/fixtures/config-autoload/pkg/package.json b/test/fixtures/config-autoload/pkg/package.json
new file mode 100644
index 00000000..14995d0f
--- /dev/null
+++ b/test/fixtures/config-autoload/pkg/package.json
@@ -0,0 +1,15 @@
+{
+ "name": "postcss-config",
+ "version": "1.0.0",
+ "postcss": {
+ "parser": false,
+ "syntax": false,
+ "map": false,
+ "from": "./index.css",
+ "to": "./index.css",
+ "plugins": [
+ "postcss-import",
+ ["postcss-nested", {}]
+ ]
+ }
+}
diff --git a/test/fixtures/config-autoload/rc-js/.postcssrc.js b/test/fixtures/config-autoload/rc-js/.postcssrc.js
new file mode 100644
index 00000000..860983d6
--- /dev/null
+++ b/test/fixtures/config-autoload/rc-js/.postcssrc.js
@@ -0,0 +1,11 @@
+module.exports = {
+ "parser": "sugarss",
+ "syntax": "sugarss",
+ "map": false,
+ "from": "./test/rc-js/fixtures/index.css",
+ "to": "./test/rc-js/expect/index.css",
+ "plugins": [
+ "postcss-import",
+ ["postcss-nested", {}]
+ ]
+};
diff --git a/test/fixtures/config-autoload/rc-js/expect/index.css b/test/fixtures/config-autoload/rc-js/expect/index.css
new file mode 100644
index 00000000..500f931b
--- /dev/null
+++ b/test/fixtures/config-autoload/rc-js/expect/index.css
@@ -0,0 +1,7 @@
+.import {
+ color: red;
+}
+
+.test {
+ color: blue;
+}
diff --git a/test/fixtures/config-autoload/rc-js/expect/index.sss b/test/fixtures/config-autoload/rc-js/expect/index.sss
new file mode 100644
index 00000000..13f8e942
--- /dev/null
+++ b/test/fixtures/config-autoload/rc-js/expect/index.sss
@@ -0,0 +1,7 @@
+.import {
+ color: red
+}
+
+.test {
+ color: blue
+}
diff --git a/test/fixtures/config-autoload/rc-js/fixtures/imports/section.css b/test/fixtures/config-autoload/rc-js/fixtures/imports/section.css
new file mode 100644
index 00000000..626b1b56
--- /dev/null
+++ b/test/fixtures/config-autoload/rc-js/fixtures/imports/section.css
@@ -0,0 +1,3 @@
+.import {
+ color: red;
+}
diff --git a/test/fixtures/config-autoload/rc-js/fixtures/imports/section.sss b/test/fixtures/config-autoload/rc-js/fixtures/imports/section.sss
new file mode 100644
index 00000000..ecc74a7a
--- /dev/null
+++ b/test/fixtures/config-autoload/rc-js/fixtures/imports/section.sss
@@ -0,0 +1,2 @@
+.import
+ color: red
diff --git a/test/fixtures/config-autoload/rc-js/fixtures/index.css b/test/fixtures/config-autoload/rc-js/fixtures/index.css
new file mode 100644
index 00000000..48162650
--- /dev/null
+++ b/test/fixtures/config-autoload/rc-js/fixtures/index.css
@@ -0,0 +1,5 @@
+@import "imports/section.css";
+
+.test {
+ color: blue;
+}
diff --git a/test/fixtures/config-autoload/rc-js/fixtures/index.sss b/test/fixtures/config-autoload/rc-js/fixtures/index.sss
new file mode 100644
index 00000000..bedaed31
--- /dev/null
+++ b/test/fixtures/config-autoload/rc-js/fixtures/index.sss
@@ -0,0 +1,4 @@
+@import "imports/section.sss"
+
+.test
+ color: blue
diff --git a/test/fixtures/config-autoload/rc/.postcssrc b/test/fixtures/config-autoload/rc/.postcssrc
new file mode 100644
index 00000000..3c1b6b73
--- /dev/null
+++ b/test/fixtures/config-autoload/rc/.postcssrc
@@ -0,0 +1,11 @@
+{
+ "parser": "sugarss",
+ "syntax": "sugarss",
+ "map": false,
+ "from": "./test/rc/fixtures/index.css",
+ "to": "./test/rc/expect/index.css",
+ "plugins": [
+ "postcss-import",
+ ["postcss-nested", {}]
+ ]
+}
diff --git a/test/fixtures/config-autoload/rc/expect/index.css b/test/fixtures/config-autoload/rc/expect/index.css
new file mode 100644
index 00000000..500f931b
--- /dev/null
+++ b/test/fixtures/config-autoload/rc/expect/index.css
@@ -0,0 +1,7 @@
+.import {
+ color: red;
+}
+
+.test {
+ color: blue;
+}
diff --git a/test/fixtures/config-autoload/rc/expect/index.sss b/test/fixtures/config-autoload/rc/expect/index.sss
new file mode 100644
index 00000000..13f8e942
--- /dev/null
+++ b/test/fixtures/config-autoload/rc/expect/index.sss
@@ -0,0 +1,7 @@
+.import {
+ color: red
+}
+
+.test {
+ color: blue
+}
diff --git a/test/fixtures/config-autoload/rc/fixtures/imports/section.css b/test/fixtures/config-autoload/rc/fixtures/imports/section.css
new file mode 100644
index 00000000..626b1b56
--- /dev/null
+++ b/test/fixtures/config-autoload/rc/fixtures/imports/section.css
@@ -0,0 +1,3 @@
+.import {
+ color: red;
+}
diff --git a/test/fixtures/config-autoload/rc/fixtures/imports/section.sss b/test/fixtures/config-autoload/rc/fixtures/imports/section.sss
new file mode 100644
index 00000000..ecc74a7a
--- /dev/null
+++ b/test/fixtures/config-autoload/rc/fixtures/imports/section.sss
@@ -0,0 +1,2 @@
+.import
+ color: red
diff --git a/test/fixtures/config-autoload/rc/fixtures/index.css b/test/fixtures/config-autoload/rc/fixtures/index.css
new file mode 100644
index 00000000..48162650
--- /dev/null
+++ b/test/fixtures/config-autoload/rc/fixtures/index.css
@@ -0,0 +1,5 @@
+@import "imports/section.css";
+
+.test {
+ color: blue;
+}
diff --git a/test/fixtures/config-autoload/rc/fixtures/index.sss b/test/fixtures/config-autoload/rc/fixtures/index.sss
new file mode 100644
index 00000000..bedaed31
--- /dev/null
+++ b/test/fixtures/config-autoload/rc/fixtures/index.sss
@@ -0,0 +1,4 @@
+@import "imports/section.sss"
+
+.test
+ color: blue
diff --git a/test/fixtures/config-autoload/ts/array-mts/imports/section.css b/test/fixtures/config-autoload/ts/array-mts/imports/section.css
new file mode 100644
index 00000000..4568aa99
--- /dev/null
+++ b/test/fixtures/config-autoload/ts/array-mts/imports/section.css
@@ -0,0 +1,3 @@
+.import {
+ color: goldenrod;
+}
diff --git a/test/fixtures/config-autoload/ts/array-mts/index.css b/test/fixtures/config-autoload/ts/array-mts/index.css
new file mode 100644
index 00000000..3b228825
--- /dev/null
+++ b/test/fixtures/config-autoload/ts/array-mts/index.css
@@ -0,0 +1,5 @@
+@import 'imports/section.css';
+
+.test {
+ color: cyan;
+}
diff --git a/test/fixtures/config-autoload/ts/array-mts/index.js b/test/fixtures/config-autoload/ts/array-mts/index.js
new file mode 100644
index 00000000..07bf0b31
--- /dev/null
+++ b/test/fixtures/config-autoload/ts/array-mts/index.js
@@ -0,0 +1,3 @@
+import style from './index.css'
+
+export default style
diff --git a/test/fixtures/config-autoload/ts/array-mts/postcss.config.mts b/test/fixtures/config-autoload/ts/array-mts/postcss.config.mts
new file mode 100644
index 00000000..f556ec98
--- /dev/null
+++ b/test/fixtures/config-autoload/ts/array-mts/postcss.config.mts
@@ -0,0 +1,37 @@
+import type { Config as PostCSSConfig } from 'postcss-load-config';
+import type { LoaderContext } from 'webpack';
+
+type PostCSSLoaderContext = LoaderContext