Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: webpack-contrib/css-loader
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v3.6.0
Choose a base ref
...
head repository: webpack-contrib/css-loader
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v4.0.0
Choose a head ref

Commits on Jun 18, 2020

  1. docs: fix (#1095)

    evilebottnawi authored Jun 18, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    fcdc1ab View commit details

Commits on Jul 7, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    edf5347 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    f9b8ef9 View commit details

Commits on Jul 8, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    76f1480 View commit details

Commits on Jul 13, 2020

  1. refactor: enables icss only when css modules enabled (#1103)

    BREAKING CHANGE: `icss` plugin disable by default, you need to setup the `modules` option to enable it
    cap-Bernardito authored Jul 13, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3b47d0d View commit details
  2. refactor: respect the devtool option (#1105)

    BREAKING CHANGE: default value of the `sourceMap` option depends on the `devtool` option
    cap-Bernardito authored Jul 13, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    88e86ab View commit details

Commits on Jul 15, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    56c0427 View commit details
  2. refactor: move the localsConvention option to the modules option

    BREAKING CHANGE: the `localsConvention` option was moved to the `module` option (`modules.localsConvention`)
    alexander-akait committed Jul 15, 2020
    Copy the full SHA
    cfc1432 View commit details
  3. chore: minimum required Node.js version is 10.13.0 (#1109)

    BREAKING CHANGE: minimum required `Node.js` version is `10.13.0`
    evilebottnawi authored Jul 15, 2020
    4

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    cb80db0 View commit details

Commits on Jul 16, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d139ec1 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    bc19ddd View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    7cca035 View commit details

Commits on Jul 17, 2020

  1. refactor: esModule option is true by default (#1111)

    BREAKING CHANGE: the `esModule` option is `true` by default
    cap-Bernardito authored Jul 17, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    908ecee View commit details

Commits on Jul 20, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a5c1b5f View commit details

Commits on Jul 21, 2020

  1. refactor: code

    BREAKING CHANGE: inline syntax was changed
    evilebottnawi authored Jul 21, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ac5f413 View commit details
  2. refactor: rename the onlyLocals option (#1116)

    BREAKING CHANGE: the `onlyLocals` option was renamed to the `exportOnlyLocals` option and moved to the `module` option
    evilebottnawi authored Jul 21, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    e1c55e4 View commit details
  3. refactor: default values modules and module.auto are true (#1117)

    BREAKING CHANGE: the `modules` option is `true` by default for all files matching `/\.module\.\w+$/i.test(filename)` regular expression, `module.auto` is `true` by default
    evilebottnawi authored Jul 21, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    0080f88 View commit details
  4. refactor: the hashPrefix option was renamed to the `localIdentHashP…

    …refix` option (#1118)
    
    BREAKING CHANGE: the `hashPrefix` option was renamed to the `localIdentHashPrefix` option
    evilebottnawi authored Jul 21, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    3a96a3d View commit details
  5. refactor: the modules.context option was renamed to the `modules.lo…

    …calIdentContext` option (#1119)
    
    BREAKING CHANGE: the `modules.context` option was renamed to the `modules.localIdentContext` option, default `modules.localIdentContext` value is `compiler.context` for the `module.getLocalIdent` option
    evilebottnawi authored Jul 21, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    fc04401 View commit details
  6. refactor: the modules.localsConvention option was renamed to the `m…

    …odules.exportLocalsConvention` option (#1120)
    
    BREAKING CHANGE: the `modules.localsConvention` option was renamed to the `modules.exportLocalsConvention` option
    evilebottnawi authored Jul 21, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    069dbb0 View commit details

Commits on Jul 22, 2020

  1. refactor: getLocalIdent function (#1121)

    BREAKING CHANGE: the `getLocalIndent` option should be always `Function` and should always return `String` value
    evilebottnawi authored Jul 22, 2020
    7

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    d2f6bd2 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    58b4b98 View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    c153fe6 View commit details
  4. refactor: change function arguments of the import option (#1124)

    BREAKING CHANGE: function arguments of the `import` option were changed, it is now `funciton(url, media, resourcePath) {}`
    evilebottnawi authored Jul 22, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    01e8c76 View commit details
  5. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    791fff3 View commit details

Commits on Jul 23, 2020

  1. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    7f49a0a View commit details
  2. fix: parsing

    evilebottnawi authored Jul 23, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    1c20b1e View commit details

Commits on Jul 24, 2020

  1. refactor: code

    evilebottnawi authored Jul 24, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    83515fa View commit details
  2. Copy the full SHA
    5b45d87 View commit details
  3. test: imports

    evilebottnawi authored Jul 24, 2020

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    a54c955 View commit details

Commits on Jul 25, 2020

  1. chore(deps): update

    alexander-akait committed Jul 25, 2020
    Copy the full SHA
    9aa0549 View commit details
  2. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5303db2 View commit details
  3. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    5604205 View commit details
  4. chore(release): 4.0.0

    alexander-akait committed Jul 25, 2020
    Copy the full SHA
    7857d8f View commit details
Showing with 9,790 additions and 7,466 deletions.
  1. +1 −6 .github/workflows/nodejs.yml
  2. +35 −0 CHANGELOG.md
  3. +188 −103 README.md
  4. +1 −1 babel.config.js
  5. +2,466 −2,909 package-lock.json
  6. +23 −21 package.json
  7. +131 −87 src/index.js
  8. +40 −25 src/options.json
  9. +63 −55 src/plugins/postcss-icss-parser.js
  10. +110 −43 src/plugins/postcss-import-parser.js
  11. +190 −113 src/plugins/postcss-url-parser.js
  12. +303 −180 src/utils.js
  13. +136 −36 test/__snapshots__/esModule-option.test.js.snap
  14. +52 −52 test/__snapshots__/icss.test.js.snap
  15. +997 −250 test/__snapshots__/import-option.test.js.snap
  16. +40 −40 test/__snapshots__/importLoaders-option.test.js.snap
  17. +65 −47 test/__snapshots__/loader.test.js.snap
  18. +0 −320 test/__snapshots__/localsConvention-option.test.js.snap
  19. +3,299 −2,456 test/__snapshots__/modules-option.test.js.snap
  20. +0 −225 test/__snapshots__/onlyLocals-option.test.js.snap
  21. +149 −74 test/__snapshots__/sourceMap-option.test.js.snap
  22. +278 −134 test/__snapshots__/url-option.test.js.snap
  23. +62 −53 test/__snapshots__/validate-options.test.js.snap
  24. +138 −0 test/esModule-option.test.js
  25. +11 −0 test/fixtures/es-module/template/index.css
  26. +6 −0 test/fixtures/es-module/template/index.js
  27. +9 −0 test/fixtures/es-module/template/template.js
  28. +1 −0 test/fixtures/import/import-conditionNames.css
  29. +5 −0 test/fixtures/import/import-conditionNames.js
  30. +3 −0 test/fixtures/import/import-order.css
  31. +5 −0 test/fixtures/import/import-order.js
  32. +6 −0 test/fixtures/import/import-server-relative-url.css
  33. +5 −0 test/fixtures/import/import-server-relative-url.js
  34. +40 −5 test/fixtures/import/import.css
  35. +1 −0 test/fixtures/import/issue-683.css
  36. +5 −0 test/fixtures/import/issue-683.js
  37. +1 −0 test/fixtures/import/node_modules/issue-683/index.js
  38. +10 −0 test/fixtures/import/node_modules/issue-683/package.json
  39. +3 −0 test/fixtures/import/node_modules/issue-683/test.css
  40. 0 test/fixtures/import/node_modules/package-with-exports/index.cjs
  41. 0 test/fixtures/import/node_modules/package-with-exports/index.js
  42. +19 −0 test/fixtures/import/node_modules/package-with-exports/package.json
  43. +3 −0 test/fixtures/import/node_modules/package-with-exports/style.css
  44. +9 −0 test/fixtures/import/node_modules/test/package.json
  45. +3 −0 test/fixtures/import/node_modules/test/test.css
  46. +3 −0 test/fixtures/import/something.css
  47. +1 −0 test/fixtures/import/unresolved.css
  48. +5 −0 test/fixtures/import/unresolved.js
  49. +26 −0 test/fixtures/modules/composes/composes-preprocessors.css
  50. +5 −0 test/fixtures/modules/composes/composes-preprocessors.js
  51. +13 −1 test/fixtures/modules/composes/composes.css
  52. +8 −0 test/fixtures/modules/composes/less-file.less
  53. +11 −0 test/fixtures/modules/composes/scss-file.scss
  54. +8 −0 test/fixtures/modules/issue-914/source.css
  55. +5 −0 test/fixtures/modules/issue-914/source.js
  56. +7 −0 test/fixtures/modules/namedExport/base/index.css
  57. +5 −0 test/fixtures/modules/namedExport/base/index.js
  58. +3 −0 test/fixtures/modules/namedExport/broken/index.css
  59. +5 −0 test/fixtures/modules/namedExport/broken/index.js
  60. +20 −0 test/fixtures/modules/namedExport/nested/index.css
  61. +5 −0 test/fixtures/modules/namedExport/nested/index.js
  62. +11 −0 test/fixtures/modules/namedExport/template/index.css
  63. +8 −0 test/fixtures/modules/namedExport/template/index.js
  64. +11 −0 test/fixtures/modules/namedExport/template/template.js
  65. +2 −0 test/fixtures/modules/node_modules/test/index.css
  66. +9 −0 test/fixtures/modules/node_modules/test/package.json
  67. +1 −1 test/fixtures/modules/tests-cases/issue-589/source.css
  68. +6 −0 test/fixtures/modules/unresolved/source.css
  69. +5 −0 test/fixtures/modules/unresolved/source.js
  70. BIN test/fixtures/modules/url/img.png
  71. +1 −0 test/fixtures/modules/url/shared.css
  72. +10 −0 test/fixtures/modules/url/source.css
  73. +5 −0 test/fixtures/modules/url/source.js
  74. +2 −0 test/fixtures/simple-style.js
  75. +1 −1 test/fixtures/simple.css
  76. BIN test/fixtures/url/something.png
  77. +3 −0 test/fixtures/url/url-unresolved.css
  78. +5 −0 test/fixtures/url/url-unresolved.js
  79. +28 −2 test/fixtures/url/url.css
  80. +5 −0 test/helpers/getCompiler.js
  81. +2 −2 test/helpers/getErrors.js
  82. +1 −1 test/helpers/getModuleSource.js
  83. +21 −4 test/helpers/normalizeErrors.js
  84. +5 −0 test/helpers/preLoader.js
  85. +5 −0 test/helpers/string-loader.js
  86. +5 −0 test/helpers/url-loader.js
  87. +3 −1 test/icss.test.js
  88. +71 −3 test/import-option.test.js
  89. +38 −4 test/loader.test.js
  90. +0 −129 test/localsConvention-option.test.js
  91. +362 −23 test/modules-option.test.js
  92. +0 −45 test/onlyLocals-option.test.js
  93. +4 −0 test/runtime/__snapshots__/api.test.js.snap
  94. +26 −0 test/runtime/api.test.js
  95. +52 −0 test/sourceMap-option.test.js
  96. +8 −0 test/url-option.test.js
  97. +32 −14 test/validate-options.test.js
7 changes: 1 addition & 6 deletions .github/workflows/nodejs.yml
Original file line number Diff line number Diff line change
@@ -55,14 +55,9 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [8.x, 10.x, 12.x, 14.x]
node-version: [10.x, 12.x, 14.x]
webpack-version: [latest, next]

exclude:
# Webpack 5 does not support node 8
- node-version: 8.x
webpack-version: next

runs-on: ${{ matrix.os }}

steps:
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -2,6 +2,41 @@

All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.

## [4.0.0](https://github.com/webpack-contrib/css-loader/compare/v3.6.0...v4.0.0) (2020-07-25)


### ⚠ BREAKING CHANGES

* minimum required `Node.js` version is `10.13.0`
* minimum required `webpack` version is `4.27.0`
* the `esModule` option is `true` by default
* default value of the `sourceMap` option depends on the `devtool` option
* `icss` plugin disable by default, you need to setup the `modules` option to enable it
* the `modules` option is `true` by default for all files matching `/\.module\.\w+$/i.test(filename)` regular expression, `module.auto` is `true` by default
* the `modules.context` option was renamed to the `modules.localIdentContext` option
* default the `modules.localIdentContext` value is `compiler.context` for the `module.getLocalIdent` option
* the `modules.hashPrefix` option was renamed to the `modules.localIdentHashPrefix` option
* the `localsConvention` option was moved and renamed to the `modules.exportLocalsConvention` option
* the `getLocalIndent` option should be always `Function` and should always return `String` value
* the `onlyLocals` option was moved and renamed to the `modules.exportOnlyLocals` option
* function arguments of the `import` option were changed, it is now `funciton(url, media, resourcePath) {}`
* inline syntax was changed, please write `~` before the file request, i.e. rewrite `url(~!!loader!package/img.png)` to `url(!!loader!~package/img.png)`


### Features

* `@value` supports importing `url()` ([#1126](https://github.com/webpack-contrib/css-loader/issues/1126)) ([7f49a0a](https://github.com/webpack-contrib/css-loader/commit/7f49a0a6047846bb2e432558365e19d4a0dfb366))
* improve `url()` resolving algorithm ([bc19ddd](https://github.com/webpack-contrib/css-loader/commit/bc19ddd8779dafbc2a420870a3cb841041ce9c7c))
* named export for locals ([#1108](https://github.com/webpack-contrib/css-loader/issues/1108)) ([d139ec1](https://github.com/webpack-contrib/css-loader/commit/d139ec1d763f9944550b31f2a75183e488dd1224))
* respected the `style` field from package.json ([#1099](https://github.com/webpack-contrib/css-loader/issues/1099)) ([edf5347](https://github.com/webpack-contrib/css-loader/commit/edf5347e4203a62e50b87248a83da198afdc6eba))
* support `file:` protocol ([5604205](https://github.com/webpack-contrib/css-loader/commit/560420567eb0e1a635648b7f4ff0365db475384c))
* support server relative URLs

### Bug Fixes

* resolution algorithm, you don't need `~` inside packages in `node_modules` ([76f1480](https://github.com/webpack-contrib/css-loader/commit/76f1480b14265369ac5dc8dbbce467cfb8e814c5))


## [3.6.0](https://github.com/webpack-contrib/css-loader/compare/v3.5.3...v3.6.0) (2020-06-13)


291 changes: 188 additions & 103 deletions README.md

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion babel.config.js
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ module.exports = (api) => {
'@babel/preset-env',
{
targets: {
node: '8.9.0',
node: '10.13.0',
},
},
],
5,375 changes: 2,466 additions & 2,909 deletions package-lock.json

Large diffs are not rendered by default.

44 changes: 23 additions & 21 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "css-loader",
"version": "3.6.0",
"version": "4.0.0",
"description": "css loader module for webpack",
"license": "MIT",
"repository": "webpack-contrib/css-loader",
@@ -13,7 +13,7 @@
},
"main": "dist/cjs.js",
"engines": {
"node": ">= 8.9.0"
"node": ">= 10.13.0"
},
"scripts": {
"start": "npm run build -- -w",
@@ -40,54 +40,56 @@
"dist"
],
"peerDependencies": {
"webpack": "^4.0.0 || ^5.0.0"
"webpack": "^4.27.0 || ^5.0.0"
},
"dependencies": {
"camelcase": "^5.3.1",
"camelcase": "^6.0.0",
"cssesc": "^3.0.0",
"icss-utils": "^4.1.1",
"loader-utils": "^1.2.3",
"loader-utils": "^2.0.0",
"normalize-path": "^3.0.0",
"postcss": "^7.0.32",
"postcss-modules-extract-imports": "^2.0.0",
"postcss-modules-local-by-default": "^3.0.2",
"postcss-modules-local-by-default": "^3.0.3",
"postcss-modules-scope": "^2.2.0",
"postcss-modules-values": "^3.0.0",
"postcss-value-parser": "^4.1.0",
"schema-utils": "^2.7.0",
"semver": "^6.3.0"
"semver": "^7.3.2"
},
"devDependencies": {
"@babel/cli": "^7.10.1",
"@babel/core": "^7.10.2",
"@babel/preset-env": "^7.10.2",
"@commitlint/cli": "^8.3.5",
"@commitlint/config-conventional": "^8.3.4",
"@babel/cli": "^7.10.5",
"@babel/core": "^7.10.5",
"@babel/preset-env": "^7.10.4",
"@commitlint/cli": "^9.1.2",
"@commitlint/config-conventional": "^9.1.1",
"@webpack-contrib/defaults": "^6.3.0",
"@webpack-contrib/eslint-config-webpack": "^3.0.0",
"babel-jest": "^25.5.1",
"babel-jest": "^26.1.0",
"cross-env": "^7.0.2",
"del": "^5.1.0",
"del-cli": "^3.0.1",
"es-check": "^5.1.0",
"eslint": "^6.8.0",
"eslint": "^7.5.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-import": "^2.21.2",
"eslint-plugin-import": "^2.22.0",
"file-loader": "^6.0.0",
"husky": "^4.2.5",
"jest": "^25.5.4",
"lint-staged": "^10.2.10",
"jest": "^26.1.0",
"lint-staged": "^10.2.11",
"memfs": "^3.2.0",
"mini-css-extract-plugin": "^0.9.0",
"npm-run-all": "^4.1.5",
"postcss-loader": "^3.0.0",
"postcss-preset-env": "^6.7.0",
"prettier": "^2.0.5",
"sass": "^1.26.8",
"sass-loader": "^8.0.2",
"standard-version": "^8.0.0",
"sass": "^1.26.10",
"sass-loader": "^9.0.2",
"standard-version": "^8.0.2",
"strip-ansi": "^6.0.0",
"style-loader": "^1.2.1",
"url-loader": "^4.1.0",
"webpack": "^4.43.0"
"webpack": "^4.44.0"
},
"keywords": [
"webpack",
218 changes: 131 additions & 87 deletions src/index.js
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
import { getOptions, isUrlRequest, stringifyRequest } from 'loader-utils';
import { getOptions, stringifyRequest } from 'loader-utils';
import postcss from 'postcss';
import postcssPkg from 'postcss/package.json';
import validateOptions from 'schema-utils';
@@ -13,59 +13,130 @@ import Warning from './Warning';
import schema from './options.json';
import { icssParser, importParser, urlParser } from './plugins';
import {
normalizeOptions,
shouldUseModulesPlugins,
shouldUseImportPlugin,
shouldUseURLPlugin,
getPreRequester,
getExportCode,
getFilter,
getImportCode,
getModuleCode,
getModulesPlugins,
normalizeSourceMap,
shouldUseModulesPlugins,
sort,
} from './utils';

export default function loader(content, map, meta) {
const options = getOptions(this) || {};
export default async function loader(content, map, meta) {
const rawOptions = getOptions(this);

validateOptions(schema, options, {
validateOptions(schema, rawOptions, {
name: 'CSS Loader',
baseDataPath: 'options',
});

const callback = this.async();
const sourceMap = options.sourceMap || false;
const plugins = [];
const callback = this.async();

let options;

try {
options = normalizeOptions(rawOptions, this);
} catch (error) {
callback(error);

return;
}

const replacements = [];
const exports = [];

const needUseModulesPlugins = shouldUseModulesPlugins(options);

if (shouldUseModulesPlugins(options.modules, this.resourcePath)) {
if (needUseModulesPlugins) {
plugins.push(...getModulesPlugins(options, this));
}

const exportType = options.onlyLocals ? 'locals' : 'full';
const preRequester = getPreRequester(this);
const urlHandler = (url) =>
stringifyRequest(this, preRequester(options.importLoaders) + url);
const importPluginImports = [];
const importPluginApi = [];

plugins.push(icssParser({ urlHandler }));
if (shouldUseImportPlugin(options)) {
const resolver = this.getResolve({
mainFields: ['css', 'style', 'main', '...'],
mainFiles: ['index', '...'],
extensions: ['.css'],
restrictions: [/\.css$/i],
conditionNames: ['style'],
});

if (options.import !== false && exportType === 'full') {
plugins.push(
importParser({
imports: importPluginImports,
api: importPluginApi,
context: this.context,
rootContext: this.rootContext,
filter: getFilter(options.import, this.resourcePath),
urlHandler,
resolver,
urlHandler: (url) =>
stringifyRequest(
this,
getPreRequester(this)(options.importLoaders) + url
),
})
);
}

if (options.url !== false && exportType === 'full') {
const urlPluginImports = [];

if (shouldUseURLPlugin(options)) {
const urlResolver = this.getResolve({
mainFields: ['asset'],
conditionNames: ['asset'],
extensions: [],
});

plugins.push(
urlParser({
filter: getFilter(options.url, this.resourcePath, (value) =>
isUrlRequest(value)
),
imports: urlPluginImports,
replacements,
context: this.context,
rootContext: this.rootContext,
filter: getFilter(options.url, this.resourcePath),
resolver: urlResolver,
urlHandler: (url) => stringifyRequest(this, url),
})
);
}

const icssPluginImports = [];
const icssPluginApi = [];

if (needUseModulesPlugins) {
const icssResolver = this.getResolve({
mainFields: ['css', 'style', 'main', '...'],
mainFiles: ['index', '...'],
extensions: [],
conditionNames: ['style'],
});

plugins.push(
icssParser({
imports: icssPluginImports,
api: icssPluginApi,
replacements,
exports,
context: this.context,
rootContext: this.rootContext,
resolver: icssResolver,
urlHandler: (url) =>
stringifyRequest(
this,
getPreRequester(this)(options.importLoaders) + url
),
})
);
}

// Reuse CSS AST (PostCSS AST e.g 'postcss-loader') to avoid reparsing
if (meta) {
const { ast } = meta;
@@ -80,82 +151,55 @@ export default function loader(content, map, meta) {
}
}

postcss(plugins)
.process(content, {
let result;

try {
result = await postcss(plugins).process(content, {
from: this.resourcePath,
to: this.resourcePath,
map: options.sourceMap
? {
// Some loaders (example `"postcss-loader": "1.x.x"`) always generates source map, we should remove it
prev: sourceMap && map ? normalizeSourceMap(map) : null,
prev: map ? normalizeSourceMap(map) : null,
inline: false,
annotation: false,
}
: false,
})
.then((result) => {
for (const warning of result.warnings()) {
this.emitWarning(new Warning(warning));
}

const imports = [];
const apiImports = [];
const urlReplacements = [];
const icssReplacements = [];
const exports = [];

for (const message of result.messages) {
// eslint-disable-next-line default-case
switch (message.type) {
case 'import':
imports.push(message.value);
break;
case 'api-import':
apiImports.push(message.value);
break;
case 'url-replacement':
urlReplacements.push(message.value);
break;
case 'icss-replacement':
icssReplacements.push(message.value);
break;
case 'export':
exports.push(message.value);
break;
}
}

const { localsConvention } = options;
const esModule =
typeof options.esModule !== 'undefined' ? options.esModule : false;

const importCode = getImportCode(this, exportType, imports, esModule);
const moduleCode = getModuleCode(
result,
exportType,
sourceMap,
apiImports,
urlReplacements,
icssReplacements,
esModule
);
const exportCode = getExportCode(
exports,
exportType,
localsConvention,
icssReplacements,
esModule
);

return callback(null, `${importCode}${moduleCode}${exportCode}`);
})
.catch((error) => {
if (error.file) {
this.addDependency(error.file);
}

callback(
error.name === 'CssSyntaxError' ? new CssSyntaxError(error) : error
);
});
} catch (error) {
if (error.file) {
this.addDependency(error.file);
}

callback(
error.name === 'CssSyntaxError' ? new CssSyntaxError(error) : error
);

return;
}

for (const warning of result.warnings()) {
this.emitWarning(new Warning(warning));
}

const imports = []
.concat(icssPluginImports.sort(sort))
.concat(importPluginImports.sort(sort))
.concat(urlPluginImports.sort(sort));
const api = []
.concat(importPluginApi.sort(sort))
.concat(icssPluginApi.sort(sort));

if (options.modules.exportOnlyLocals !== true) {
imports.unshift({
importName: '___CSS_LOADER_API_IMPORT___',
url: stringifyRequest(this, require.resolve('./runtime/api')),
});
}

const importCode = getImportCode(imports, options);
const moduleCode = getModuleCode(result, api, replacements, options);
const exportCode = getExportCode(exports, replacements, options);

callback(null, `${importCode}${moduleCode}${exportCode}`);
}
65 changes: 40 additions & 25 deletions src/options.json
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@
"additionalProperties": false,
"properties": {
"auto": {
"description": "Allows auto enable CSS modules based on filename (https://github.com/webpack-contrib/css-loader#auto).",
"anyOf": [
{
"instanceof": "RegExp"
@@ -50,6 +51,7 @@
]
},
"mode": {
"description": "Setup `mode` option (https://github.com/webpack-contrib/css-loader#mode).",
"anyOf": [
{
"enum": ["local", "global", "pure"]
@@ -59,37 +61,58 @@
}
]
},
"exportGlobals": {
"type": "boolean"
},
"localIdentName": {
"type": "string"
"description": "Allows to configure the generated local ident name (https://github.com/webpack-contrib/css-loader#localidentname).",
"type": "string",
"minLength": 1
},
"localIdentContext": {
"description": "Allows to redefine basic loader context for local ident name (https://github.com/webpack-contrib/css-loader#localidentcontext).",
"type": "string",
"minLength": 1
},
"localIdentHashPrefix": {
"description": "Allows to add custom hash to generate more unique classes (https://github.com/webpack-contrib/css-loader#localidenthashprefix).",
"type": "string",
"minLength": 1
},
"localIdentRegExp": {
"description": "Allows to specify custom RegExp for local ident name (https://github.com/webpack-contrib/css-loader#localidentregexp).",
"anyOf": [
{
"type": "string"
"type": "string",
"minLength": 1
},
{
"instanceof": "RegExp"
}
]
},
"context": {
"type": "string"
"getLocalIdent": {
"description": "Allows to specify a function to generate the classname (https://github.com/webpack-contrib/css-loader#getlocalident).",
"instanceof": "Function"
},
"hashPrefix": {
"type": "string"
"namedExport": {
"description": "Enables/disables ES modules named export for locals (https://github.com/webpack-contrib/css-loader#namedexport).",
"type": "boolean"
},
"getLocalIdent": {
"anyOf": [
{
"type": "boolean"
},
{
"instanceof": "Function"
}
"exportGlobals": {
"description": "Allows to export names from global class or id, so you can use that as local name (https://github.com/webpack-contrib/css-loader#exportglobals).",
"type": "boolean"
},
"exportLocalsConvention": {
"description": "Style of exported classnames (https://github.com/webpack-contrib/css-loader#localsconvention).",
"enum": [
"asIs",
"camelCase",
"camelCaseOnly",
"dashes",
"dashesOnly"
]
},
"exportOnlyLocals": {
"description": "Export only locals (https://github.com/webpack-contrib/css-loader#exportonlylocals).",
"type": "boolean"
}
}
}
@@ -110,14 +133,6 @@
}
]
},
"localsConvention": {
"description": "Style of exported classnames (https://github.com/webpack-contrib/css-loader#localsconvention).",
"enum": ["asIs", "camelCase", "camelCaseOnly", "dashes", "dashesOnly"]
},
"onlyLocals": {
"description": "Export only locals (https://github.com/webpack-contrib/css-loader#onlylocals).",
"type": "boolean"
},
"esModule": {
"description": "Use the ES modules syntax (https://github.com/webpack-contrib/css-loader#esmodule).",
"type": "boolean"
118 changes: 63 additions & 55 deletions src/plugins/postcss-icss-parser.js
Original file line number Diff line number Diff line change
@@ -1,83 +1,91 @@
import postcss from 'postcss';
import { extractICSS, replaceValueSymbols, replaceSymbols } from 'icss-utils';
import { urlToRequest } from 'loader-utils';

function makeRequestableIcssImports(icssImports) {
return Object.keys(icssImports).reduce((accumulator, url) => {
const tokensMap = icssImports[url];
const tokens = Object.keys(tokensMap);
import { normalizeUrl, resolveRequests, requestify } from '../utils';

if (tokens.length === 0) {
return accumulator;
}
export default postcss.plugin(
'postcss-icss-parser',
(options) => async (css) => {
const importReplacements = Object.create(null);
const { icssImports, icssExports } = extractICSS(css);
const imports = new Map();
const tasks = [];

// eslint-disable-next-line guard-for-in
for (const url in icssImports) {
const tokens = icssImports[url];

if (Object.keys(tokens).length === 0) {
// eslint-disable-next-line no-continue
continue;
}

let normalizedUrl = url;
let prefix = '';

const queryParts = normalizedUrl.split('!');

const normalizedUrl = urlToRequest(url);
if (queryParts.length > 1) {
normalizedUrl = queryParts.pop();
prefix = queryParts.join('!');
}

const request = requestify(
normalizeUrl(normalizedUrl, true),
options.rootContext
);
const doResolve = async () => {
const { resolver, context } = options;
const resolvedUrl = await resolveRequests(resolver, context, [
...new Set([normalizedUrl, request]),
]);

if (!accumulator[normalizedUrl]) {
// eslint-disable-next-line no-param-reassign
accumulator[normalizedUrl] = tokensMap;
} else {
// eslint-disable-next-line no-param-reassign
accumulator[normalizedUrl] = {
...accumulator[normalizedUrl],
...tokensMap,
return { url: resolvedUrl, prefix, tokens };
};

tasks.push(doResolve());
}

return accumulator;
}, {});
}
const results = await Promise.all(tasks);

export default postcss.plugin(
'postcss-icss-parser',
(options) => (css, result) => {
const importReplacements = Object.create(null);
const extractedICSS = extractICSS(css);
const icssImports = makeRequestableIcssImports(extractedICSS.icssImports);

for (const [importIndex, url] of Object.keys(icssImports).entries()) {
const importName = `___CSS_LOADER_ICSS_IMPORT_${importIndex}___`;

result.messages.push(
{
type: 'import',
value: {
importName,
url: options.urlHandler ? options.urlHandler(url) : url,
},
},
{
type: 'api-import',
value: { type: 'internal', importName, dedupe: true },
}
);
for (let index = 0; index <= results.length - 1; index++) {
const { url, prefix, tokens } = results[index];
const newUrl = prefix ? `${prefix}!${url}` : url;
const importKey = newUrl;
let importName = imports.get(importKey);

const tokenMap = icssImports[url];
const tokens = Object.keys(tokenMap);
if (!importName) {
importName = `___CSS_LOADER_ICSS_IMPORT_${imports.size}___`;
imports.set(importKey, importName);

for (const [replacementIndex, token] of tokens.entries()) {
const replacementName = `___CSS_LOADER_ICSS_IMPORT_${importIndex}_REPLACEMENT_${replacementIndex}___`;
const localName = tokenMap[token];
options.imports.push({
importName,
url: options.urlHandler(newUrl),
icss: true,
index,
});

options.api.push({ importName, dedupe: true, index });
}

for (const [replacementIndex, token] of Object.keys(tokens).entries()) {
const replacementName = `___CSS_LOADER_ICSS_IMPORT_${index}_REPLACEMENT_${replacementIndex}___`;
const localName = tokens[token];

importReplacements[token] = replacementName;

result.messages.push({
type: 'icss-replacement',
value: { replacementName, importName, localName },
});
options.replacements.push({ replacementName, importName, localName });
}
}

if (Object.keys(importReplacements).length > 0) {
replaceSymbols(css, importReplacements);
}

const { icssExports } = extractedICSS;

for (const name of Object.keys(icssExports)) {
const value = replaceValueSymbols(icssExports[name], importReplacements);

result.messages.push({ type: 'export', value: { name, value } });
options.exports.push({ name, value });
}
}
);
153 changes: 110 additions & 43 deletions src/plugins/postcss-import-parser.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import { promisify } from 'util';

import postcss from 'postcss';
import valueParser from 'postcss-value-parser';
import { isUrlRequest } from 'loader-utils';

import { normalizeUrl } from '../utils';
import {
normalizeUrl,
resolveRequests,
isUrlRequestable,
requestify,
} from '../utils';

const pluginName = 'postcss-import-parser';

export default postcss.plugin(pluginName, (options) => (css, result) => {
const importsMap = new Map();
function walkAtRules(css, result, options, callback) {
const accumulator = [];

css.walkAtRules(/^import$/i, (atRule) => {
// Convert only top-level @import
@@ -25,13 +31,13 @@ export default postcss.plugin(pluginName, (options) => (css, result) => {
return;
}

const { nodes } = valueParser(atRule.params);
const { nodes: paramsNodes } = valueParser(atRule.params);

// No nodes - `@import ;`
// Invalid type - `@import foo-bar;`
if (
nodes.length === 0 ||
(nodes[0].type !== 'string' && nodes[0].type !== 'function')
paramsNodes.length === 0 ||
(paramsNodes[0].type !== 'string' && paramsNodes[0].type !== 'function')
) {
result.warn(`Unable to find uri in "${atRule.toString()}"`, {
node: atRule,
@@ -43,12 +49,12 @@ export default postcss.plugin(pluginName, (options) => (css, result) => {
let isStringValue;
let url;

if (nodes[0].type === 'string') {
if (paramsNodes[0].type === 'string') {
isStringValue = true;
url = nodes[0].value;
} else if (nodes[0].type === 'function') {
url = paramsNodes[0].value;
} else {
// Invalid function - `@import nourl(test.css);`
if (nodes[0].value.toLowerCase() !== 'url') {
if (paramsNodes[0].value.toLowerCase() !== 'url') {
result.warn(`Unable to find uri in "${atRule.toString()}"`, {
node: atRule,
});
@@ -57,10 +63,11 @@ export default postcss.plugin(pluginName, (options) => (css, result) => {
}

isStringValue =
nodes[0].nodes.length !== 0 && nodes[0].nodes[0].type === 'string';
paramsNodes[0].nodes.length !== 0 &&
paramsNodes[0].nodes[0].type === 'string';
url = isStringValue
? nodes[0].nodes[0].value
: valueParser.stringify(nodes[0].nodes);
? paramsNodes[0].nodes[0].value
: valueParser.stringify(paramsNodes[0].nodes);
}

// Empty url - `@import "";` or `@import url();`
@@ -72,61 +79,121 @@ export default postcss.plugin(pluginName, (options) => (css, result) => {
return;
}

const isRequestable = isUrlRequest(url);
accumulator.push({
atRule,
url,
isStringValue,
mediaNodes: paramsNodes.slice(1),
});
});

callback(null, accumulator);
}

const asyncWalkAtRules = promisify(walkAtRules);

export default postcss.plugin(pluginName, (options) => async (css, result) => {
const parsedResults = await asyncWalkAtRules(css, result, options);

if (parsedResults.length === 0) {
return Promise.resolve();
}

const imports = new Map();
const tasks = [];

for (const parsedResult of parsedResults) {
const { atRule, url, isStringValue, mediaNodes } = parsedResult;

let normalizedUrl = url;
let prefix = '';

const queryParts = normalizedUrl.split('!');

if (queryParts.length > 1) {
normalizedUrl = queryParts.pop();
prefix = queryParts.join('!');
}

const isRequestable = isUrlRequestable(normalizedUrl);

if (isRequestable) {
url = normalizeUrl(url, isStringValue);
normalizedUrl = normalizeUrl(normalizedUrl, isStringValue);

// Empty url after normalize - `@import '\
// \
// \
// ';
if (url.trim().length === 0) {
if (normalizedUrl.trim().length === 0) {
result.warn(`Unable to find uri in "${atRule.toString()}"`, {
node: atRule,
});

return;
// eslint-disable-next-line no-continue
continue;
}
}

const media = valueParser.stringify(nodes.slice(1)).trim().toLowerCase();
let media;

if (options.filter && !options.filter({ url, media })) {
return;
if (mediaNodes.length > 0) {
media = valueParser.stringify(mediaNodes).trim().toLowerCase();
}

if (options.filter && !options.filter(normalizedUrl, media)) {
// eslint-disable-next-line no-continue
continue;
}

atRule.remove();

if (isRequestable) {
const importKey = url;
let importName = importsMap.get(importKey);
const request = requestify(normalizedUrl, options.rootContext);
const doResolve = async () => {
const { resolver, context } = options;
const resolvedUrl = await resolveRequests(resolver, context, [
...new Set([request, normalizedUrl]),
]);

return { url: resolvedUrl, media, prefix, isRequestable };
};

tasks.push(doResolve());
} else {
tasks.push({ url, media, prefix, isRequestable });
}
}

const results = await Promise.all(tasks);

for (let index = 0; index <= results.length - 1; index++) {
const { url, isRequestable, media } = results[index];

if (isRequestable) {
const { prefix } = results[index];
const newUrl = prefix ? `${prefix}!${url}` : url;
const importKey = newUrl;
let importName = imports.get(importKey);

if (!importName) {
importName = `___CSS_LOADER_AT_RULE_IMPORT_${importsMap.size}___`;
importsMap.set(importKey, importName);

result.messages.push({
type: 'import',
value: {
importName,
url: options.urlHandler ? options.urlHandler(url) : url,
},
importName = `___CSS_LOADER_AT_RULE_IMPORT_${imports.size}___`;
imports.set(importKey, importName);

options.imports.push({
importName,
url: options.urlHandler(newUrl),
index,
});
}

result.messages.push({
type: 'api-import',
value: { type: 'internal', importName, media },
});
options.api.push({ importName, media, index });

return;
// eslint-disable-next-line no-continue
continue;
}

result.messages.push({
pluginName,
type: 'api-import',
value: { type: 'external', url, media },
});
});
options.api.push({ url, media, index });
}

return Promise.resolve();
});
303 changes: 190 additions & 113 deletions src/plugins/postcss-url-parser.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
import { promisify } from 'util';

import postcss from 'postcss';
import valueParser from 'postcss-value-parser';

import { normalizeUrl } from '../utils';
import {
normalizeUrl,
requestify,
resolveRequests,
isUrlRequestable,
} from '../utils';

const pluginName = 'postcss-url-parser';

@@ -13,146 +20,216 @@ function getNodeFromUrlFunc(node) {
return node.nodes && node.nodes[0];
}

function walkUrls(parsed, callback) {
parsed.walk((node) => {
if (node.type !== 'function') {
return;
}
function shouldHandleRule(rule, decl, result) {
// https://www.w3.org/TR/css-syntax-3/#typedef-url-token
if (rule.url.replace(/^[\s]+|[\s]+$/g, '').length === 0) {
result.warn(`Unable to find uri in '${decl.toString()}'`, { node: decl });

if (isUrlFunc.test(node.value)) {
const { nodes } = node;
const isStringValue = nodes.length !== 0 && nodes[0].type === 'string';
const url = isStringValue ? nodes[0].value : valueParser.stringify(nodes);
return false;
}

callback(getNodeFromUrlFunc(node), url, false, isStringValue);
return true;
}

// Do not traverse inside `url`
// eslint-disable-next-line consistent-return
return false;
}
function walkCss(css, result, options, callback) {
const accumulator = [];

if (isImageSetFunc.test(node.value)) {
for (const nNode of node.nodes) {
const { type, value } = nNode;
css.walkDecls((decl) => {
if (!needParseDecl.test(decl.value)) {
return;
}

if (type === 'function' && isUrlFunc.test(value)) {
const { nodes } = nNode;
const parsed = valueParser(decl.value);

const isStringValue =
nodes.length !== 0 && nodes[0].type === 'string';
const url = isStringValue
? nodes[0].value
: valueParser.stringify(nodes);
parsed.walk((node) => {
if (node.type !== 'function') {
return;
}

callback(getNodeFromUrlFunc(nNode), url, false, isStringValue);
if (isUrlFunc.test(node.value)) {
const { nodes } = node;
const isStringValue = nodes.length !== 0 && nodes[0].type === 'string';
const url = isStringValue
? nodes[0].value
: valueParser.stringify(nodes);

const rule = {
node: getNodeFromUrlFunc(node),
url,
needQuotes: false,
isStringValue,
};

if (shouldHandleRule(rule, decl, result)) {
accumulator.push({ decl, rule, parsed });
}

if (type === 'string') {
callback(nNode, value, true, true);
// Do not traverse inside `url`
// eslint-disable-next-line consistent-return
return false;
} else if (isImageSetFunc.test(node.value)) {
for (const nNode of node.nodes) {
const { type, value } = nNode;

if (type === 'function' && isUrlFunc.test(value)) {
const { nodes } = nNode;
const isStringValue =
nodes.length !== 0 && nodes[0].type === 'string';
const url = isStringValue
? nodes[0].value
: valueParser.stringify(nodes);

const rule = {
node: getNodeFromUrlFunc(nNode),
url,
needQuotes: false,
isStringValue,
};

if (shouldHandleRule(rule, decl, result)) {
accumulator.push({ decl, rule, parsed });
}
} else if (type === 'string') {
const rule = {
node: nNode,
url: value,
needQuotes: true,
isStringValue: true,
};

if (shouldHandleRule(rule, decl, result)) {
accumulator.push({ decl, rule, parsed });
}
}
}
}

// Do not traverse inside `image-set`
// eslint-disable-next-line consistent-return
return false;
}
// Do not traverse inside `image-set`
// eslint-disable-next-line consistent-return
return false;
}
});
});

callback(null, accumulator);
}

export default postcss.plugin(pluginName, (options) => (css, result) => {
const importsMap = new Map();
const replacementsMap = new Map();
const asyncWalkCss = promisify(walkCss);

let hasHelper = false;
export default postcss.plugin(pluginName, (options) => async (css, result) => {
const parsedResults = await asyncWalkCss(css, result, options);

css.walkDecls((decl) => {
if (!needParseDecl.test(decl.value)) {
return;
if (parsedResults.length === 0) {
return Promise.resolve();
}

const tasks = [];
const imports = new Map();
const replacements = new Map();

let hasUrlImportHelper = false;

for (const parsedResult of parsedResults) {
const { url, isStringValue } = parsedResult.rule;

let normalizedUrl = url;
let prefix = '';

const queryParts = normalizedUrl.split('!');

if (queryParts.length > 1) {
normalizedUrl = queryParts.pop();
prefix = queryParts.join('!');
}

const parsed = valueParser(decl.value);
normalizedUrl = normalizeUrl(normalizedUrl, isStringValue);

walkUrls(parsed, (node, url, needQuotes, isStringValue) => {
// https://www.w3.org/TR/css-syntax-3/#typedef-url-token
if (url.replace(/^[\s]+|[\s]+$/g, '').length === 0) {
result.warn(
`Unable to find uri in '${decl ? decl.toString() : decl.value}'`,
{ node: decl }
);
if (!isUrlRequestable(normalizedUrl)) {
// eslint-disable-next-line no-continue
continue;
}

return;
}
if (!options.filter(normalizedUrl)) {
// eslint-disable-next-line no-continue
continue;
}

if (options.filter && !options.filter(url)) {
return;
}
if (!hasUrlImportHelper) {
options.imports.push({
importName: '___CSS_LOADER_GET_URL_IMPORT___',
url: options.urlHandler(require.resolve('../runtime/getUrl.js')),
index: -1,
});

const splittedUrl = url.split(/(\?)?#/);
const [urlWithoutHash, singleQuery, hashValue] = splittedUrl;
const hash =
singleQuery || hashValue
? `${singleQuery ? '?' : ''}${hashValue ? `#${hashValue}` : ''}`
: '';

const normalizedUrl = normalizeUrl(urlWithoutHash, isStringValue);

const importKey = normalizedUrl;
let importName = importsMap.get(importKey);

if (!importName) {
importName = `___CSS_LOADER_URL_IMPORT_${importsMap.size}___`;
importsMap.set(importKey, importName);

if (!hasHelper) {
const urlToHelper = require.resolve('../runtime/getUrl.js');

result.messages.push({
pluginName,
type: 'import',
value: {
importName: '___CSS_LOADER_GET_URL_IMPORT___',
url: options.urlHandler
? options.urlHandler(urlToHelper)
: urlToHelper,
},
});

hasHelper = true;
}
hasUrlImportHelper = true;
}

result.messages.push({
pluginName,
type: 'import',
value: {
importName,
url: options.urlHandler
? options.urlHandler(normalizedUrl)
: normalizedUrl,
},
});
}
const splittedUrl = normalizedUrl.split(/(\?)?#/);
const [pathname, query, hashOrQuery] = splittedUrl;

let hash = query ? '?' : '';
hash += hashOrQuery ? `#${hashOrQuery}` : '';

const request = requestify(pathname, options.rootContext);
const doResolve = async () => {
const { resolver, context } = options;
const resolvedUrl = await resolveRequests(resolver, context, [
...new Set([request, normalizedUrl]),
]);

return { url: resolvedUrl, prefix, hash, parsedResult };
};

tasks.push(doResolve());
}

const results = await Promise.all(tasks);

for (let index = 0; index <= results.length - 1; index++) {
const {
url,
prefix,
hash,
parsedResult: { decl, rule, parsed },
} = results[index];
const newUrl = prefix ? `${prefix}!${url}` : url;
const importKey = newUrl;
let importName = imports.get(importKey);

if (!importName) {
importName = `___CSS_LOADER_URL_IMPORT_${imports.size}___`;
imports.set(importKey, importName);

options.imports.push({
importName,
url: options.urlHandler(newUrl),
index,
});
}

const replacementKey = JSON.stringify({ importKey, hash, needQuotes });
let replacementName = replacementsMap.get(replacementKey);
const { needQuotes } = rule;
const replacementKey = JSON.stringify({ newUrl, hash, needQuotes });
let replacementName = replacements.get(replacementKey);

if (!replacementName) {
replacementName = `___CSS_LOADER_URL_REPLACEMENT_${replacementsMap.size}___`;
replacementsMap.set(replacementKey, replacementName);
if (!replacementName) {
replacementName = `___CSS_LOADER_URL_REPLACEMENT_${replacements.size}___`;
replacements.set(replacementKey, replacementName);

result.messages.push({
pluginName,
type: 'url-replacement',
value: { replacementName, importName, hash, needQuotes },
});
}
options.replacements.push({
replacementName,
importName,
hash,
needQuotes,
});
}

// eslint-disable-next-line no-param-reassign
node.type = 'word';
// eslint-disable-next-line no-param-reassign
node.value = replacementName;
});
// eslint-disable-next-line no-param-reassign
rule.node.type = 'word';
// eslint-disable-next-line no-param-reassign
rule.node.value = replacementName;

// eslint-disable-next-line no-param-reassign
decl.value = parsed.toString();
});
}

return Promise.resolve();
});
483 changes: 303 additions & 180 deletions src/utils.js

Large diffs are not rendered by default.

172 changes: 136 additions & 36 deletions test/__snapshots__/esModule-option.test.js.snap
Original file line number Diff line number Diff line change
@@ -4,17 +4,17 @@ exports[`"esModule" option should work when not specified: errors 1`] = `Array [

exports[`"esModule" option should work when not specified: module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../src/runtime/api.js\\");
var ___CSS_LOADER_AT_RULE_IMPORT_0___ = require(\\"-!../../../src/index.js??[ident]!./imported.css\\");
var ___CSS_LOADER_GET_URL_IMPORT___ = require(\\"../../../src/runtime/getUrl.js\\");
var ___CSS_LOADER_URL_IMPORT_0___ = require(\\"./img.png\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident]!./imported.css\\";
import ___CSS_LOADER_GET_URL_IMPORT___ from \\"../../../src/runtime/getUrl.js\\";
import ___CSS_LOADER_URL_IMPORT_0___ from \\"./img.png\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);
// Module
exports.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.class {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.class {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
// Exports
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -54,13 +54,13 @@ var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../src/runtime/api.js\\");
var ___CSS_LOADER_AT_RULE_IMPORT_0___ = require(\\"-!../../../src/index.js??[ident]!./imported.css\\");
var ___CSS_LOADER_GET_URL_IMPORT___ = require(\\"../../../src/runtime/getUrl.js\\");
var ___CSS_LOADER_URL_IMPORT_0___ = require(\\"./img.png\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);
// Module
exports.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.class {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.class {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
// Exports
module.exports = exports;
module.exports = ___CSS_LOADER_EXPORT___;
"
`;

@@ -100,13 +100,13 @@ import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident]!./imported.css\\";
import ___CSS_LOADER_GET_URL_IMPORT___ from \\"../../../src/runtime/getUrl.js\\";
import ___CSS_LOADER_URL_IMPORT_0___ from \\"./img.png\\";
var exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);
// Module
exports.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.class {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.class {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
// Exports
export default exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -146,24 +146,24 @@ import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident]!./imported.css\\";
import ___CSS_LOADER_GET_URL_IMPORT___ from \\"../../../src/runtime/getUrl.js\\";
import ___CSS_LOADER_URL_IMPORT_0___ from \\"./img.png\\";
var exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);
// Module
exports.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n._3S58jeCkC6SOPhVLbU-Bwn {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.oFwPvuANP2XsfGir7HPVz {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
// Exports
exports.locals = {
\\"class\\": \\"_3S58jeCkC6SOPhVLbU-Bwn\\"
___CSS_LOADER_EXPORT___.locals = {
\\"class\\": \\"oFwPvuANP2XsfGir7HPVz\\"
};
export default exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

exports[`"esModule" option should work with a value equal to "true" and the "mode" value equal to "local": result 1`] = `
Array [
Array [
"../../src/index.js?[ident]!./es-module/imported.css",
"._3xfjtZ03Dx7Cld7Debi-wl {
"._2sn2s-Iv44Mnv3FmSmFVuI {
color: red;
}
",
@@ -175,7 +175,7 @@ Array [
/* Comment */
._3S58jeCkC6SOPhVLbU-Bwn {
.oFwPvuANP2XsfGir7HPVz {
color: red;
background: url(/webpack/public/path/img.png);
}
@@ -195,24 +195,24 @@ import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident]!./imported.css\\";
import ___CSS_LOADER_GET_URL_IMPORT___ from \\"../../../src/runtime/getUrl.js\\";
import ___CSS_LOADER_URL_IMPORT_0___ from \\"./img.png\\";
var exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);
// Module
exports.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n._3S58jeCkC6SOPhVLbU-Bwn {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.oFwPvuANP2XsfGir7HPVz {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
// Exports
exports.locals = {
\\"class\\": \\"_3S58jeCkC6SOPhVLbU-Bwn\\"
___CSS_LOADER_EXPORT___.locals = {
\\"class\\": \\"oFwPvuANP2XsfGir7HPVz\\"
};
export default exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

exports[`"esModule" option should work with a value equal to "true" and the "mode" value equal to "pure": result 1`] = `
Array [
Array [
"../../src/index.js?[ident]!./es-module/imported.css",
"._3xfjtZ03Dx7Cld7Debi-wl {
"._2sn2s-Iv44Mnv3FmSmFVuI {
color: red;
}
",
@@ -224,7 +224,7 @@ Array [
/* Comment */
._3S58jeCkC6SOPhVLbU-Bwn {
.oFwPvuANP2XsfGir7HPVz {
color: red;
background: url(/webpack/public/path/img.png);
}
@@ -244,13 +244,13 @@ import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident]!./imported.css\\";
import ___CSS_LOADER_GET_URL_IMPORT___ from \\"../../../src/runtime/getUrl.js\\";
import ___CSS_LOADER_URL_IMPORT_0___ from \\"./img.png\\";
var exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);
// Module
exports.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.class {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.class {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
// Exports
export default exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -281,3 +281,103 @@ Array [
`;

exports[`"esModule" option should work with a value equal to "true": warnings 1`] = `Array []`;

exports[`"esModule" option should work with commonjs css-loader + commonjs mini-css-extract-plugin: errors 1`] = `Array []`;

exports[`"esModule" option should work with commonjs css-loader + commonjs mini-css-extract-plugin: result 1`] = `undefined`;

exports[`"esModule" option should work with commonjs css-loader + commonjs mini-css-extract-plugin: warnings 1`] = `Array []`;

exports[`"esModule" option should work with commonjs css-loader + commonjs style-loader: errors 1`] = `Array []`;

exports[`"esModule" option should work with commonjs css-loader + commonjs style-loader: result 1`] = `
Object {
"css": Object {
"body": "BwpsNB5_0Pze7vq8KQOAN",
"footer": "_10gZ0Ke9A0uqq8u0Z2eRKA",
"header-baz": "_2n-RuEOd5cLXo65ILWgtue",
},
"html": "
<div class=\\"_2n-RuEOd5cLXo65ILWgtue\\">
<div class=\\"BwpsNB5_0Pze7vq8KQOAN\\">
<div class=\\"_10gZ0Ke9A0uqq8u0Z2eRKA\\">
",
}
`;
exports[`"esModule" option should work with commonjs css-loader + commonjs style-loader: warnings 1`] = `Array []`;
exports[`"esModule" option should work with commonjs css-loader + esModule mini-css-extract-plugin: errors 1`] = `Array []`;
exports[`"esModule" option should work with commonjs css-loader + esModule mini-css-extract-plugin: result 1`] = `undefined`;
exports[`"esModule" option should work with commonjs css-loader + esModule mini-css-extract-plugin: warnings 1`] = `Array []`;
exports[`"esModule" option should work with commonjs css-loader + esModule style-loader: errors 1`] = `Array []`;
exports[`"esModule" option should work with commonjs css-loader + esModule style-loader: result 1`] = `
Object {
"css": Object {
"body": "BwpsNB5_0Pze7vq8KQOAN",
"footer": "_10gZ0Ke9A0uqq8u0Z2eRKA",
"header-baz": "_2n-RuEOd5cLXo65ILWgtue",
},
"html": "
<div class=\\"_2n-RuEOd5cLXo65ILWgtue\\">
<div class=\\"BwpsNB5_0Pze7vq8KQOAN\\">
<div class=\\"_10gZ0Ke9A0uqq8u0Z2eRKA\\">
",
}
`;
exports[`"esModule" option should work with commonjs css-loader + esModule style-loader: warnings 1`] = `Array []`;
exports[`"esModule" option should work with esModule css-loader + commonjs mini-css-extract-plugin: errors 1`] = `Array []`;
exports[`"esModule" option should work with esModule css-loader + commonjs mini-css-extract-plugin: result 1`] = `undefined`;
exports[`"esModule" option should work with esModule css-loader + commonjs mini-css-extract-plugin: warnings 1`] = `Array []`;
exports[`"esModule" option should work with esModule css-loader + commonjs style-loader: errors 1`] = `Array []`;
exports[`"esModule" option should work with esModule css-loader + commonjs style-loader: result 1`] = `
Object {
"css": Object {
"body": "BwpsNB5_0Pze7vq8KQOAN",
"footer": "_10gZ0Ke9A0uqq8u0Z2eRKA",
"header-baz": "_2n-RuEOd5cLXo65ILWgtue",
},
"html": "
<div class=\\"_2n-RuEOd5cLXo65ILWgtue\\">
<div class=\\"BwpsNB5_0Pze7vq8KQOAN\\">
<div class=\\"_10gZ0Ke9A0uqq8u0Z2eRKA\\">
",
}
`;
exports[`"esModule" option should work with esModule css-loader + commonjs style-loader: warnings 1`] = `Array []`;
exports[`"esModule" option should work with esModule css-loader + esModule mini-css-extract-plugin: errors 1`] = `Array []`;
exports[`"esModule" option should work with esModule css-loader + esModule mini-css-extract-plugin: result 1`] = `undefined`;
exports[`"esModule" option should work with esModule css-loader + esModule mini-css-extract-plugin: warnings 1`] = `Array []`;
exports[`"esModule" option should work with esModule css-loader + esModule style-loader: errors 1`] = `Array []`;
exports[`"esModule" option should work with esModule css-loader + esModule style-loader: result 1`] = `
Object {
"css": Object {
"body": "BwpsNB5_0Pze7vq8KQOAN",
"footer": "_10gZ0Ke9A0uqq8u0Z2eRKA",
"header-baz": "_2n-RuEOd5cLXo65ILWgtue",
},
"html": "
<div class=\\"_2n-RuEOd5cLXo65ILWgtue\\">
<div class=\\"BwpsNB5_0Pze7vq8KQOAN\\">
<div class=\\"_10gZ0Ke9A0uqq8u0Z2eRKA\\">
",
}
`;
exports[`"esModule" option should work with esModule css-loader + esModule style-loader: warnings 1`] = `Array []`;
104 changes: 52 additions & 52 deletions test/__snapshots__/icss.test.js.snap
Original file line number Diff line number Diff line change
@@ -4,15 +4,15 @@ exports[`ICSS show work with the case "duplicate-export": errors 1`] = `Array []

exports[`ICSS show work with the case "duplicate-export": module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../../src/runtime/api.js\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../../src/runtime/api.js\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
// Module
exports.push([module.id, \\"\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"\\\\n\\", \\"\\"]);
// Exports
exports.locals = {
___CSS_LOADER_EXPORT___.locals = {
\\"_test\\": \\"_right_value\\"
};
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -33,15 +33,15 @@ exports[`ICSS show work with the case "duplicate-export-in-multiple-export": err

exports[`ICSS show work with the case "duplicate-export-in-multiple-export": module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../../src/runtime/api.js\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../../src/runtime/api.js\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
// Module
exports.push([module.id, \\"\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"\\\\n\\", \\"\\"]);
// Exports
exports.locals = {
___CSS_LOADER_EXPORT___.locals = {
\\"_test\\": \\"_right_value\\"
};
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -62,12 +62,12 @@ exports[`ICSS show work with the case "empty-export": errors 1`] = `Array []`;

exports[`ICSS show work with the case "empty-export": module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../../src/runtime/api.js\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../../src/runtime/api.js\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
// Module
exports.push([module.id, \\"\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"\\\\n\\", \\"\\"]);
// Exports
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -88,12 +88,12 @@ exports[`ICSS show work with the case "empty-import": errors 1`] = `Array []`;

exports[`ICSS show work with the case "empty-import": module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../../src/runtime/api.js\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../../src/runtime/api.js\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
// Module
exports.push([module.id, \\"\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"\\\\n\\", \\"\\"]);
// Exports
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -114,15 +114,15 @@ exports[`ICSS show work with the case "export": errors 1`] = `Array []`;

exports[`ICSS show work with the case "export": module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../../src/runtime/api.js\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../../src/runtime/api.js\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
// Module
exports.push([module.id, \\"\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"\\\\n\\", \\"\\"]);
// Exports
exports.locals = {
___CSS_LOADER_EXPORT___.locals = {
\\"_test\\": \\"_test\\"
};
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -143,16 +143,16 @@ exports[`ICSS show work with the case "export-reserved-keywords": errors 1`] = `

exports[`ICSS show work with the case "export-reserved-keywords": module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../../src/runtime/api.js\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../../src/runtime/api.js\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
// Module
exports.push([module.id, \\"\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"\\\\n\\", \\"\\"]);
// Exports
exports.locals = {
___CSS_LOADER_EXPORT___.locals = {
\\"constructor\\": \\"constructor\\",
\\"toString\\": \\"toString\\"
};
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -173,17 +173,17 @@ exports[`ICSS show work with the case "import": errors 1`] = `Array []`;

exports[`ICSS show work with the case "import": module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../../src/runtime/api.js\\");
var ___CSS_LOADER_ICSS_IMPORT_0___ = require(\\"-!../../../../../src/index.js??[ident]!./vars.css\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_ICSS_IMPORT_0___, \\"\\", true);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../../src/runtime/api.js\\";
import ___CSS_LOADER_ICSS_IMPORT_0___ from \\"-!../../../../../src/index.js??[ident]!./vars.css\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_ICSS_IMPORT_0___, \\"\\", true);
// Module
exports.push([module.id, \\".className {\\\\n color: \\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"primary-color\\"] + \\";\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\".className {\\\\n color: \\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"primary-color\\"] + \\";\\\\n}\\\\n\\", \\"\\"]);
// Exports
exports.locals = {
___CSS_LOADER_EXPORT___.locals = {
\\"primary-color\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"primary-color\\"] + \\"\\"
};
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -212,18 +212,18 @@ exports[`ICSS show work with the case "import-reserved-keywords": errors 1`] = `

exports[`ICSS show work with the case "import-reserved-keywords": module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../../src/runtime/api.js\\");
var ___CSS_LOADER_ICSS_IMPORT_0___ = require(\\"-!../../../../../src/index.js??[ident]!./vars.css\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_ICSS_IMPORT_0___, \\"\\", true);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../../src/runtime/api.js\\";
import ___CSS_LOADER_ICSS_IMPORT_0___ from \\"-!../../../../../src/index.js??[ident]!./vars.css\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_ICSS_IMPORT_0___, \\"\\", true);
// Module
exports.push([module.id, \\".className {\\\\n color: \\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"primary-color\\"] + \\";\\\\n display: \\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"secondary-color\\"] + \\";\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\".className {\\\\n color: \\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"primary-color\\"] + \\";\\\\n display: \\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"secondary-color\\"] + \\";\\\\n}\\\\n\\", \\"\\"]);
// Exports
exports.locals = {
___CSS_LOADER_EXPORT___.locals = {
\\"primary-color\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"primary-color\\"] + \\"\\",
\\"secondary-color\\": \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0___.locals[\\"secondary-color\\"] + \\"\\"
};
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -253,16 +253,16 @@ exports[`ICSS show work with the case "multiple-export": errors 1`] = `Array []`

exports[`ICSS show work with the case "multiple-export": module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../../src/runtime/api.js\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../../src/runtime/api.js\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
// Module
exports.push([module.id, \\"\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"\\\\n\\", \\"\\"]);
// Exports
exports.locals = {
___CSS_LOADER_EXPORT___.locals = {
\\"_test\\": \\"_test\\",
\\"_foo\\": \\"_bar\\"
};
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -283,19 +283,19 @@ exports[`ICSS show work with the case "multiple-keys-values-in-export": errors 1

exports[`ICSS show work with the case "multiple-keys-values-in-export": module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../../../src/runtime/api.js\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../../src/runtime/api.js\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
// Module
exports.push([module.id, \\"\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\"\\\\n\\", \\"\\"]);
// Exports
exports.locals = {
___CSS_LOADER_EXPORT___.locals = {
\\"_test\\": \\"_test\\",
\\"_test1\\": \\"1\\",
\\"_test2\\": \\"'string'\\",
\\"_test3\\": \\"1px 2px 3px\\",
\\"_test4\\": \\"1px 2px 3px, 1px 2px 3px\\"
};
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

1,247 changes: 997 additions & 250 deletions test/__snapshots__/import-option.test.js.snap

Large diffs are not rendered by default.

80 changes: 40 additions & 40 deletions test/__snapshots__/importLoaders-option.test.js.snap
Original file line number Diff line number Diff line change
@@ -4,16 +4,16 @@ exports[`"importLoaders" option should work when not specified: errors 1`] = `Ar

exports[`"importLoaders" option should work when not specified: module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../src/runtime/api.js\\");
var ___CSS_LOADER_AT_RULE_IMPORT_0___ = require(\\"-!../../../src/index.js!./imported.css\\");
var ___CSS_LOADER_AT_RULE_IMPORT_1___ = require(\\"-!../../../src/index.js!./other-imported.css\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_1___);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js!./imported.css\\";
import ___CSS_LOADER_AT_RULE_IMPORT_1___ from \\"-!../../../src/index.js!./other-imported.css\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_1___);
// Module
exports.push([module.id, \\".foo {\\\\n color: red;\\\\n color: rgba(0, 0, 255, 0.9);\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\".foo {\\\\n color: red;\\\\n color: rgba(0, 0, 255, 0.9);\\\\n}\\\\n\\", \\"\\"]);
// Exports
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -55,16 +55,16 @@ exports[`"importLoaders" option should work with a value equal to "0" (\`postcss

exports[`"importLoaders" option should work with a value equal to "0" (\`postcss-loader\` before): module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../src/runtime/api.js\\");
var ___CSS_LOADER_AT_RULE_IMPORT_0___ = require(\\"-!../../../src/index.js??[ident]!./imported.css\\");
var ___CSS_LOADER_AT_RULE_IMPORT_1___ = require(\\"-!../../../src/index.js??[ident]!./other-imported.css\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_1___);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident]!./imported.css\\";
import ___CSS_LOADER_AT_RULE_IMPORT_1___ from \\"-!../../../src/index.js??[ident]!./other-imported.css\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_1___);
// Module
exports.push([module.id, \\".foo {\\\\n color: red;\\\\n color: rgba(0, 0, 255, 0.9);\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\".foo {\\\\n color: red;\\\\n color: rgba(0, 0, 255, 0.9);\\\\n}\\\\n\\", \\"\\"]);
// Exports
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -106,16 +106,16 @@ exports[`"importLoaders" option should work with a value equal to "1" ("postcss-

exports[`"importLoaders" option should work with a value equal to "1" ("postcss-loader" before): module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../src/runtime/api.js\\");
var ___CSS_LOADER_AT_RULE_IMPORT_0___ = require(\\"-!../../../src/index.js??[ident]!./imported.css\\");
var ___CSS_LOADER_AT_RULE_IMPORT_1___ = require(\\"-!../../../src/index.js??[ident]!./other-imported.css\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_1___);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident]!./imported.css\\";
import ___CSS_LOADER_AT_RULE_IMPORT_1___ from \\"-!../../../src/index.js??[ident]!./other-imported.css\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_1___);
// Module
exports.push([module.id, \\".foo {\\\\n color: red;\\\\n color: rgba(0, 0, 255, 0.9);\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\".foo {\\\\n color: red;\\\\n color: rgba(0, 0, 255, 0.9);\\\\n}\\\\n\\", \\"\\"]);
// Exports
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -157,16 +157,16 @@ exports[`"importLoaders" option should work with a value equal to "1" (no loader

exports[`"importLoaders" option should work with a value equal to "1" (no loaders before): module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../src/runtime/api.js\\");
var ___CSS_LOADER_AT_RULE_IMPORT_0___ = require(\\"-!../../../src/index.js??[ident]!./imported.css\\");
var ___CSS_LOADER_AT_RULE_IMPORT_1___ = require(\\"-!../../../src/index.js??[ident]!./other-imported.css\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_1___);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident]!./imported.css\\";
import ___CSS_LOADER_AT_RULE_IMPORT_1___ from \\"-!../../../src/index.js??[ident]!./other-imported.css\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_1___);
// Module
exports.push([module.id, \\".foo {\\\\n color: red;\\\\n color: rgb(0 0 100% / 90%);\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\".foo {\\\\n color: red;\\\\n color: rgb(0 0 100% / 90%);\\\\n}\\\\n\\", \\"\\"]);
// Exports
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

@@ -208,16 +208,16 @@ exports[`"importLoaders" option should work with a value equal to "2" ("postcss-

exports[`"importLoaders" option should work with a value equal to "2" ("postcss-loader" before): module 1`] = `
"// Imports
var ___CSS_LOADER_API_IMPORT___ = require(\\"../../../src/runtime/api.js\\");
var ___CSS_LOADER_AT_RULE_IMPORT_0___ = require(\\"-!../../../src/index.js??[ident]!./imported.css\\");
var ___CSS_LOADER_AT_RULE_IMPORT_1___ = require(\\"-!../../../src/index.js??[ident]!./other-imported.css\\");
exports = ___CSS_LOADER_API_IMPORT___(false);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
exports.i(___CSS_LOADER_AT_RULE_IMPORT_1___);
import ___CSS_LOADER_API_IMPORT___ from \\"../../../src/runtime/api.js\\";
import ___CSS_LOADER_AT_RULE_IMPORT_0___ from \\"-!../../../src/index.js??[ident]!./imported.css\\";
import ___CSS_LOADER_AT_RULE_IMPORT_1___ from \\"-!../../../src/index.js??[ident]!./other-imported.css\\";
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_1___);
// Module
exports.push([module.id, \\".foo {\\\\n color: red;\\\\n color: rgba(0, 0, 255, 0.9);\\\\n}\\\\n\\", \\"\\"]);
___CSS_LOADER_EXPORT___.push([module.id, \\".foo {\\\\n color: red;\\\\n color: rgba(0, 0, 255, 0.9);\\\\n}\\\\n\\", \\"\\"]);
// Exports
module.exports = exports;
export default ___CSS_LOADER_EXPORT___;
"
`;

112 changes: 65 additions & 47 deletions test/__snapshots__/loader.test.js.snap

Large diffs are not rendered by default.

320 changes: 0 additions & 320 deletions test/__snapshots__/localsConvention-option.test.js.snap

This file was deleted.

5,755 changes: 3,299 additions & 2,456 deletions test/__snapshots__/modules-option.test.js.snap

Large diffs are not rendered by default.

225 changes: 0 additions & 225 deletions test/__snapshots__/onlyLocals-option.test.js.snap

This file was deleted.

Loading