From c3236108034de9c751ae27583276570096756fc3 Mon Sep 17 00:00:00 2001 From: Alexander Akait <4567934+alexander-akait@users.noreply.github.com> Date: Sat, 18 Sep 2021 21:52:00 +0300 Subject: [PATCH] feat: added `string` value for the `exportType` option --- CHANGELOG.md | 2 +- README.md | 81 ++-- src/options.json | 4 +- src/utils.js | 36 +- test/__snapshots__/exportType.test.js.snap | 357 +++++++++++++++++- .../validate-options.test.js.snap | 8 +- test/exportType.test.js | 48 +++ test/fixtures/basic-string-css-modules.js | 5 + test/fixtures/basic-string.js | 5 + test/validate-options.test.js | 2 +- 10 files changed, 486 insertions(+), 62 deletions(-) create mode 100644 test/fixtures/basic-string-css-modules.js create mode 100644 test/fixtures/basic-string.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ac42bfe..1c7a245e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ All notable changes to this project will be documented in this file. See [standa ### Features -* allow the `exportLocalsConvention` option can be a function useful for named export ([#1351](https://github.com/webpack-contrib/css-loader/issues/1351)) ([3c4b357](https://github.com/webpack-contrib/css-loader/commit/3c4b35718273baaf9e0480db715b596fbe5d7453)) +* allow the `exportLocalsConvention` option can be a function, useful for named export ([#1351](https://github.com/webpack-contrib/css-loader/issues/1351)) ([3c4b357](https://github.com/webpack-contrib/css-loader/commit/3c4b35718273baaf9e0480db715b596fbe5d7453)) ## [6.1.0](https://github.com/webpack-contrib/css-loader/compare/v6.0.0...v6.1.0) (2021-07-17) diff --git a/README.md b/README.md index 34f893c1..8f784c70 100644 --- a/README.md +++ b/README.md @@ -54,48 +54,19 @@ module.exports = { And run `webpack` via your preferred method. -### `toString` - -You can also use the css-loader results directly as a string, such as in Angular's component style. - -**webpack.config.js** - -```js -module.exports = { - module: { - rules: [ - { - test: /\.css$/i, - use: ["to-string-loader", "css-loader"], - }, - ], - }, -}; -``` - -or - -```js -const css = require("./test.css").toString(); - -console.log(css); // {String} -``` - -If there are SourceMaps, they will also be included in the result string. - If, for one reason or another, you need to extract CSS as a file (i.e. do not store CSS in a JS module) you might want to check out the [recommend example](https://github.com/webpack-contrib/css-loader#recommend). ## Options -| Name | Type | Default | Description | -| :-----------------------------------: | :------------------------------: | :----------------: | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| **[`url`](#url)** | `{Boolean\|Object}` | `true` | Allows to enables/disables `url()`/`image-set()` functions handling | -| **[`import`](#import)** | `{Boolean\|Object}` | `true` | Allows to enables/disables `@import` at-rules handling | -| **[`modules`](#modules)** | `{Boolean\|String\|Object}` | `{auto: true}` | Allows to enables/disables or setup CSS Modules options | -| **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps | -| **[`importLoaders`](#importloaders)** | `{Number}` | `0` | Allows enables/disables or setups number of loaders applied before CSS loader for `@import`/CSS Modules and ICSS imports | -| **[`esModule`](#esmodule)** | `{Boolean}` | `true` | Use ES modules syntax | -| **[`exportType`](#exporttype)** | `{'array' \| 'css-style-sheet'}` | `array` | Allows exporting styles as array with modules or [constructable stylesheet](https://developers.google.com/web/updates/2019/02/constructable-stylesheets) (i.e. [`CSSStyleSheet`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet)) | +| Name | Type | Default | Description | +| :-----------------------------------: | :------------------------------------------: | :----------------: | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **[`url`](#url)** | `{Boolean\|Object}` | `true` | Allows to enables/disables `url()`/`image-set()` functions handling | +| **[`import`](#import)** | `{Boolean\|Object}` | `true` | Allows to enables/disables `@import` at-rules handling | +| **[`modules`](#modules)** | `{Boolean\|String\|Object}` | `{auto: true}` | Allows to enables/disables or setup CSS Modules options | +| **[`sourceMap`](#sourcemap)** | `{Boolean}` | `compiler.devtool` | Enables/Disables generation of source maps | +| **[`importLoaders`](#importloaders)** | `{Number}` | `0` | Allows enables/disables or setups number of loaders applied before CSS loader for `@import`/CSS Modules and ICSS imports | +| **[`esModule`](#esmodule)** | `{Boolean}` | `true` | Use ES modules syntax | +| **[`exportType`](#exporttype)** | `{'array' \| 'string' \| 'css-style-sheet'}` | `array` | Allows exporting styles as array with modules, string or [constructable stylesheet](https://developers.google.com/web/updates/2019/02/constructable-stylesheets) (i.e. [`CSSStyleSheet`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet)) | ### `url` @@ -1272,10 +1243,10 @@ module.exports = { ### `exportType` -Type: `'array' | 'css-style-sheet'` +Type: `'array' | 'string' | 'css-style-sheet'` Default: `'array'` -Allows exporting styles as array with modules or [constructable stylesheet](https://developers.google.com/web/updates/2019/02/constructable-stylesheets) (i.e. [`CSSStyleSheet`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet)). +Allows exporting styles as array with modules, string or [constructable stylesheet](https://developers.google.com/web/updates/2019/02/constructable-stylesheets) (i.e. [`CSSStyleSheet`](https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleSheet)). Default value is `'array'`, i.e. loader exports array of modules with specific API which is used in `style-loader` or other. **webpack.config.js** @@ -1331,6 +1302,36 @@ module.exports = { import "./styles.css"; ``` +#### `'string'` + +> ⚠ You don't need [`style-loader`](https://github.com/webpack-contrib/style-loader) anymore, please remove it. +> ⚠ The `esModules` option should be enabled if you want to use it with [`CSS modules`](https://github.com/webpack-contrib/css-loader#modules), by default for locals will be used [named export](https://github.com/webpack-contrib/css-loader#namedexport). + +The default export is `string`. + +**webpack.config.js** + +```js +module.exports = { + module: { + rules: [ + { + test: /\.(sa|sc|c)ss$/i, + use: ["css-loader", "postcss-loader", "sass-loader"], + }, + ], + }, +}; +``` + +**src/index.js** + +```js +import sheet from "./styles.css"; + +console.log(sheet); +``` + #### `'css-style-sheet'` > ⚠ `@import` rules not yet allowed, more [information](https://web.dev/css-module-scripts/#@import-rules-not-yet-allowed) diff --git a/src/options.json b/src/options.json index e57559f9..c9b25a14 100644 --- a/src/options.json +++ b/src/options.json @@ -195,9 +195,9 @@ "type": "boolean" }, "exportType": { - "description": "Allows exporting styles as array with modules or constructable stylesheet (i.e. `CSSStyleSheet`).", + "description": "Allows exporting styles as array with modules, string or constructable stylesheet (i.e. `CSSStyleSheet`).", "link": "https://github.com/webpack-contrib/css-loader#exporttype", - "enum": ["array", "css-style-sheet"] + "enum": ["array", "string", "css-style-sheet"] } }, "type": "object" diff --git a/src/utils.js b/src/utils.js index befe6399..81eb89dc 100644 --- a/src/utils.js +++ b/src/utils.js @@ -540,7 +540,8 @@ function getModulesOptions(rawOptions, exportType, loaderContext) { // eslint-disable-next-line no-underscore-dangle const { outputOptions } = loaderContext._compilation; - const isExportCSSStyleSheet = exportType === "css-style-sheet"; + const needNamedExport = + exportType === "css-style-sheet" || exportType === "string"; const modulesOptions = { auto, mode: "local", @@ -555,9 +556,9 @@ function getModulesOptions(rawOptions, exportType, loaderContext) { localIdentRegExp: undefined, // eslint-disable-next-line no-undefined getLocalIdent: undefined, - namedExport: isExportCSSStyleSheet || false, + namedExport: needNamedExport || false, exportLocalsConvention: - (rawModulesOptions.namedExport === true || isExportCSSStyleSheet) && + (rawModulesOptions.namedExport === true || needNamedExport) && typeof rawModulesOptions.exportLocalsConvention === "undefined" ? "camelCaseOnly" : "asIs", @@ -625,16 +626,16 @@ function getModulesOptions(rawOptions, exportType, loaderContext) { modulesOptions.mode = modulesOptions.mode(loaderContext.resourcePath); } - if (isExportCSSStyleSheet) { + if (needNamedExport) { if (rawOptions.esModule === false) { throw new Error( - "The 'exportType' option with the 'css-style-sheet' value requires the 'esModules' option to be enabled" + "The 'exportType' option with the 'css-style-sheet' or 'string' value requires the 'esModules' option to be enabled" ); } if (modulesOptions.namedExport === false) { throw new Error( - "The 'exportType' option with the 'css-style-sheet' value requires the 'modules.namedExport' option to be enabled" + "The 'exportType' option with the 'css-style-sheet' or 'string' value requires the 'modules.namedExport' option to be enabled" ); } } @@ -1142,11 +1143,24 @@ function getExportCode(exports, replacements, icssPluginUsed, options) { "___CSS_LOADER_STYLE_SHEET___.replaceSync(___CSS_LOADER_EXPORT___.toString());\n"; } - code += `${options.esModule ? "export default" : "module.exports ="} ${ - isCSSStyleSheetExport - ? "___CSS_LOADER_STYLE_SHEET___" - : "___CSS_LOADER_EXPORT___" - };\n`; + let finalExport; + + switch (options.exportType) { + case "string": + finalExport = "___CSS_LOADER_EXPORT___.toString()"; + break; + case "css-style-sheet": + finalExport = "___CSS_LOADER_STYLE_SHEET___"; + break; + default: + case "array": + finalExport = "___CSS_LOADER_EXPORT___"; + break; + } + + code += `${ + options.esModule ? "export default" : "module.exports =" + } ${finalExport};\n`; return code; } diff --git a/test/__snapshots__/exportType.test.js.snap b/test/__snapshots__/exportType.test.js.snap index 07fa8835..4125062b 100644 --- a/test/__snapshots__/exportType.test.js.snap +++ b/test/__snapshots__/exportType.test.js.snap @@ -3,7 +3,7 @@ exports[`'exportType' option should throw an error with 'css-style-sheet' value for CSS modules when \`esModule\` disabled, but 'modules.namedExport' enabled: errors 1`] = ` Array [ "ModuleBuildError: Module build failed (from \`replaced original path\`): -Error: The 'exportType' option with the 'css-style-sheet' value requires the 'esModules' option to be enabled", +Error: The 'exportType' option with the 'css-style-sheet' or 'string' value requires the 'esModules' option to be enabled", ] `; @@ -12,7 +12,7 @@ exports[`'exportType' option should throw an error with 'css-style-sheet' value exports[`'exportType' option should throw an error with 'css-style-sheet' value for CSS modules when \`esModule\` disabled: errors 1`] = ` Array [ "ModuleBuildError: Module build failed (from \`replaced original path\`): -Error: The 'exportType' option with the 'css-style-sheet' value requires the 'esModules' option to be enabled", +Error: The 'exportType' option with the 'css-style-sheet' or 'string' value requires the 'esModules' option to be enabled", ] `; @@ -21,7 +21,7 @@ exports[`'exportType' option should throw an error with 'css-style-sheet' value exports[`'exportType' option should throw an error with 'css-style-sheet' value for CSS modules when named export disabled: errors 1`] = ` Array [ "ModuleBuildError: Module build failed (from \`replaced original path\`): -Error: The 'exportType' option with the 'css-style-sheet' value requires the 'modules.namedExport' option to be enabled", +Error: The 'exportType' option with the 'css-style-sheet' or 'string' value requires the 'modules.namedExport' option to be enabled", ] `; @@ -2453,6 +2453,357 @@ a[href=\\"\\" i] { exports[`'exportType' option should work with 'css-style-sheet' value: warnings 1`] = `Array []`; +exports[`'exportType' option should work with 'string' value and CSS modules: errors 1`] = `Array []`; + +exports[`'exportType' option should work with 'string' value and CSS modules: module 1`] = ` +"// Imports +import ___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___ from \\"../../src/runtime/noSourceMaps.js\\"; +import ___CSS_LOADER_API_IMPORT___ from \\"../../src/runtime/api.js\\"; +var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___); +// Module +___CSS_LOADER_EXPORT___.push([module.id, \\"._LAQzblHTRmSe8Mk9eNB {\\\\n color: red;\\\\n}\\\\n\\", \\"\\"]); +// Exports +export var someClass = \\"_LAQzblHTRmSe8Mk9eNB\\"; +export default ___CSS_LOADER_EXPORT___.toString(); +" +`; + +exports[`'exportType' option should work with 'string' value and CSS modules: result 1`] = ` +Object { + "css": "._LAQzblHTRmSe8Mk9eNB { + color: red; +} +", + "locals": Object { + "someClass": "_LAQzblHTRmSe8Mk9eNB", + }, +} +`; + +exports[`'exportType' option should work with 'string' value and CSS modules: warnings 1`] = `Array []`; + +exports[`'exportType' option should work with 'string' value and generate source maps: errors 1`] = `Array []`; + +exports[`'exportType' option should work with 'string' value and generate source maps: module 1`] = ` +"// Imports +import ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \\"../../src/runtime/sourceMaps.js\\"; +import ___CSS_LOADER_API_IMPORT___ from \\"../../src/runtime/api.js\\"; +import ___CSS_LOADER_GET_URL_IMPORT___ from \\"../../src/runtime/getUrl.js\\"; +var ___CSS_LOADER_URL_IMPORT_0___ = new URL(\\"./url/img.png\\", import.meta.url); +var ___CSS_LOADER_URL_IMPORT_1___ = new URL(\\"data:img/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAhxJREFUSA3tk71rU1EYxnMTEoJUkowWwdJ2akEHBfGjCiIF6ZylVUKSm2TqZLGI+A/oIu2UXm8C4lAyF4SWji0tdFLo1Eo7VN0SaBEhH7e/Nz0nPTfGOjiaCyfPc5734zlfCQT6X/8E/vUErL81KBaL9y3LSnued5PcITjUOwR3gsFg2bbtjYt6/NGgXC4P1et1l2aPLmpAbD0SidjpdPqgV15PA9d17zQajU8UxHQRK/4G35Q5pveAK8LlI1ZjPMnlcltnyvnvbwaO41xvtVqy7YHztMACq5xnlb9EY3dRdvcGo1kj5wR+t1AofDG0gM+A875E8DNjRCexsrV8Pj9ZqVQitVrtqejxePxjMpmss5hVTB4buXvMb2DyU2tBTRS+BjvNlVYUpPl7iuVO3Gq1uoQx1FtSOW1gPgp5ZWrdBtNmUDgv5asgxQ8F1af5vhY0YjyjuWC3wTszKJz7GBOkcFlQfW2ONq4FjWi+Hj6DRCKxQOK2TlY4x92EuYd5dvMAbYIzfikau3pu5tJ8KxaLLfo0cyKci7tK4TZjUMcoXAmHwzle0Q/RaC5P1GFMyVx9R9Fo9HYqlTrSgqDvFelAqVQa5hmuMR/WGtjAaBdjwBoDQ0ZsnwVMZjKZ9n0Zem8DSeDPdrnZbL6F2l3NOvUYNZk4oVDoRTabPe4EDNJzB0ZcjAYxeoZ2i3FNxQ7BHYw/cB/fldaH//UETgHHO8S44KbfXgAAAABJRU5ErkJggg==\\", import.meta.url); +var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___); +var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___); +var ___CSS_LOADER_URL_REPLACEMENT_1___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_1___); +// Module +___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\\\\n.class-duplicate-url {\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\\\n:root {\\\\n --foo: 1px;\\\\n --bar: 2px;\\\\n}\\\\n\\\\n.class { a: b c d; }\\\\n\\\\n.two {}\\\\n\\\\n.u-m\\\\\\\\+ { a: b c d; }\\\\n\\\\n.class { content: \\\\\\"\\\\\\\\F10C\\\\\\" }\\\\n\\\\n@media only screen and (max-width: 600px) {\\\\n body {\\\\n background-color: lightblue;\\\\n }\\\\n}\\\\n\\\\n.class {\\\\n content: \\\\\\"\\\\\\\\2193\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2193\\\\\\\\2193\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2193 \\\\\\\\2193\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2193\\\\\\\\2193\\\\\\\\2193\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2193 \\\\\\\\2193 \\\\\\\\2193\\\\\\";\\\\n}\\\\n\\\\n.-top {}\\\\n.\\\\\\\\-top {}\\\\n\\\\n#\\\\\\\\#test {}\\\\n\\\\n.grid {\\\\n display: flex;\\\\n flex-wrap: wrap;\\\\n}\\\\n.grid.\\\\\\\\-top {\\\\n align-items: flex-start;\\\\n}\\\\n.grid.-top {\\\\n align-items: flex-start;\\\\n}\\\\n.grid.\\\\\\\\-middle {\\\\n align-items: center;\\\\n}\\\\n.grid.\\\\\\\\-bottom {\\\\n align-items: flex-end;\\\\n}\\\\n\\\\n.u-m\\\\\\\\00002b {}\\\\n\\\\n.u-m00002b {}\\\\n\\\\n#u-m\\\\\\\\+ {}\\\\n\\\\nbody {\\\\n font-family: '微软雅黑'; /* some chinese font name */\\\\n}\\\\n\\\\n.myStyle {\\\\n content: '\\\\\\\\e901';\\\\n}\\\\n\\\\n.myStyle {\\\\n content: '\\\\\\\\E901';\\\\n}\\\\n\\\\n.♫ {}\\\\n\\\\n.\\\\\\\\3A \\\\\\\\\`\\\\\\\\( {} /* matches elements with class=\\\\\\":\`(\\\\\\" */\\\\n.\\\\\\\\31 a2b3c {} /* matches elements with class=\\\\\\"1a2b3c\\\\\\" */\\\\n#\\\\\\\\#fake-id {} /* matches the element with id=\\\\\\"#fake-id\\\\\\" */\\\\n#-a-b-c- {} /* matches the element with id=\\\\\\"-a-b-c-\\\\\\" */\\\\n#© {} /* matches the element with id=\\\\\\"©\\\\\\" */\\\\n\\\\n:root {\\\\n --title-align: center;\\\\n --sr-only: {\\\\n position: absolute;\\\\n width: 1px;\\\\n height: 1px;\\\\n padding: 0;\\\\n overflow: hidden;\\\\n clip: rect(0,0,0,0);\\\\n white-space: nowrap;\\\\n clip-path: inset(50%);\\\\n border: 0;\\\\n };\\\\n}\\\\n\\\\n.test {\\\\n content: \\\\\\"\\\\\\\\2014\\\\\\\\A0\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2014 \\\\\\\\A0\\\\\\";\\\\n content: \\\\\\"\\\\\\\\A0 \\\\\\\\2014\\\\\\";\\\\n content: \\\\\\"\\\\\\\\A0\\\\\\\\2014\\\\\\";\\\\n margin-top: 1px\\\\\\\\9;\\\\n background-color: #000\\\\\\\\9;\\\\n}\\\\n\\\\n.light.on .bulb:before{\\\\n content: '💡';\\\\n}\\\\n\\\\n.base64 {\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_1___ + \\");\\\\n}\\\\n\\\\na[href=''] {\\\\n color: red;\\\\n}\\\\n\\\\na[href='' i] {\\\\n color: red;\\\\n}\\\\n\\\\na[href=\\\\\\"\\\\\\"] {\\\\n color: blue;\\\\n}\\\\n\\\\na[href=\\\\\\"\\\\\\" i] {\\\\n color: blue;\\\\n}\\\\n\\", \\"\\",{\\"version\\":3,\\"sources\\":[\\"webpack://./basic-css-style-sheet.css\\"],\\"names\\":[],\\"mappings\\":\\"AAAA,gBAAgB;;AAEhB,YAAY;;AAEZ;EACE,UAAU;EACV,mDAAgC;AAClC;;AAEA;EACE,mDAAgC;AAClC;;AAEA;EACE,UAAU;EACV,UAAU;AACZ;;AAEA,SAAS,QAAQ,EAAE;;AAEnB,MAAM;;AAEN,SAAS,QAAQ,EAAE;;AAEnB,SAAS,iBAAiB;;AAE1B;EACE;IACE,2BAA2B;EAC7B;AACF;;AAEA;EACE,gBAAgB;EAChB,qBAAqB;EACrB,sBAAsB;EACtB,0BAA0B;EAC1B,4BAA4B;AAC9B;;AAEA,OAAO;AACP,QAAQ;;AAER,SAAS;;AAET;EACE,aAAa;EACb,eAAe;AACjB;AACA;EACE,uBAAuB;AACzB;AACA;EACE,uBAAuB;AACzB;AACA;EACE,mBAAmB;AACrB;AACA;EACE,qBAAqB;AACvB;;AAEA,aAAa;;AAEb,YAAY;;AAEZ,QAAQ;;AAER;EACE,mBAAmB,EAAE,2BAA2B;AAClD;;AAEA;EACE,gBAAgB;AAClB;;AAEA;EACE,gBAAgB;AAClB;;AAEA,IAAI;;AAEJ,WAAW,EAAE,sCAAsC;AACnD,YAAY,EAAE,yCAAyC;AACvD,YAAY,EAAE,2CAA2C;AACzD,UAAU,EAAE,0CAA0C;AACtD,IAAI,EAAE,oCAAoC;;AAE1C;EACE,qBAAqB;EACrB;;;;;;;;;;GAUC;AACH;;AAEA;EACE,mBAAmB;EACnB,oBAAoB;EACpB,oBAAoB;EACpB,mBAAmB;EACnB,iBAAiB;EACjB,wBAAwB;AAC1B;;AAEA;EACE,aAAa;AACf;;AAEA;EACE,mDAAq1B;AACv1B;;AAEA;EACE,UAAU;AACZ;;AAEA;EACE,UAAU;AACZ;;AAEA;EACE,WAAW;AACb;;AAEA;EACE,WAAW;AACb\\",\\"sourcesContent\\":[\\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.class {\\\\n color: red;\\\\n background: url(\\\\\\"./url/img.png\\\\\\");\\\\n}\\\\n\\\\n.class-duplicate-url {\\\\n background: url(\\\\\\"./url/img.png\\\\\\");\\\\n}\\\\n\\\\n:root {\\\\n --foo: 1px;\\\\n --bar: 2px;\\\\n}\\\\n\\\\n.class { a: b c d; }\\\\n\\\\n.two {}\\\\n\\\\n.u-m\\\\\\\\+ { a: b c d; }\\\\n\\\\n.class { content: \\\\\\"\\\\\\\\F10C\\\\\\" }\\\\n\\\\n@media only screen and (max-width: 600px) {\\\\n body {\\\\n background-color: lightblue;\\\\n }\\\\n}\\\\n\\\\n.class {\\\\n content: \\\\\\"\\\\\\\\2193\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2193\\\\\\\\2193\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2193 \\\\\\\\2193\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2193\\\\\\\\2193\\\\\\\\2193\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2193 \\\\\\\\2193 \\\\\\\\2193\\\\\\";\\\\n}\\\\n\\\\n.-top {}\\\\n.\\\\\\\\-top {}\\\\n\\\\n#\\\\\\\\#test {}\\\\n\\\\n.grid {\\\\n display: flex;\\\\n flex-wrap: wrap;\\\\n}\\\\n.grid.\\\\\\\\-top {\\\\n align-items: flex-start;\\\\n}\\\\n.grid.-top {\\\\n align-items: flex-start;\\\\n}\\\\n.grid.\\\\\\\\-middle {\\\\n align-items: center;\\\\n}\\\\n.grid.\\\\\\\\-bottom {\\\\n align-items: flex-end;\\\\n}\\\\n\\\\n.u-m\\\\\\\\00002b {}\\\\n\\\\n.u-m00002b {}\\\\n\\\\n#u-m\\\\\\\\+ {}\\\\n\\\\nbody {\\\\n font-family: '微软雅黑'; /* some chinese font name */\\\\n}\\\\n\\\\n.myStyle {\\\\n content: '\\\\\\\\e901';\\\\n}\\\\n\\\\n.myStyle {\\\\n content: '\\\\\\\\E901';\\\\n}\\\\n\\\\n.♫ {}\\\\n\\\\n.\\\\\\\\3A \\\\\\\\\`\\\\\\\\( {} /* matches elements with class=\\\\\\":\`(\\\\\\" */\\\\n.\\\\\\\\31 a2b3c {} /* matches elements with class=\\\\\\"1a2b3c\\\\\\" */\\\\n#\\\\\\\\#fake-id {} /* matches the element with id=\\\\\\"#fake-id\\\\\\" */\\\\n#-a-b-c- {} /* matches the element with id=\\\\\\"-a-b-c-\\\\\\" */\\\\n#© {} /* matches the element with id=\\\\\\"©\\\\\\" */\\\\n\\\\n:root {\\\\n --title-align: center;\\\\n --sr-only: {\\\\n position: absolute;\\\\n width: 1px;\\\\n height: 1px;\\\\n padding: 0;\\\\n overflow: hidden;\\\\n clip: rect(0,0,0,0);\\\\n white-space: nowrap;\\\\n clip-path: inset(50%);\\\\n border: 0;\\\\n };\\\\n}\\\\n\\\\n.test {\\\\n content: \\\\\\"\\\\\\\\2014\\\\\\\\A0\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2014 \\\\\\\\A0\\\\\\";\\\\n content: \\\\\\"\\\\\\\\A0 \\\\\\\\2014\\\\\\";\\\\n content: \\\\\\"\\\\\\\\A0\\\\\\\\2014\\\\\\";\\\\n margin-top: 1px\\\\\\\\9;\\\\n background-color: #000\\\\\\\\9;\\\\n}\\\\n\\\\n.light.on .bulb:before{\\\\n content: '💡';\\\\n}\\\\n\\\\n.base64 {\\\\n background: url(data:img/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAhxJREFUSA3tk71rU1EYxnMTEoJUkowWwdJ2akEHBfGjCiIF6ZylVUKSm2TqZLGI+A/oIu2UXm8C4lAyF4SWji0tdFLo1Eo7VN0SaBEhH7e/Nz0nPTfGOjiaCyfPc5734zlfCQT6X/8E/vUErL81KBaL9y3LSnued5PcITjUOwR3gsFg2bbtjYt6/NGgXC4P1et1l2aPLmpAbD0SidjpdPqgV15PA9d17zQajU8UxHQRK/4G35Q5pveAK8LlI1ZjPMnlcltnyvnvbwaO41xvtVqy7YHztMACq5xnlb9EY3dRdvcGo1kj5wR+t1AofDG0gM+A875E8DNjRCexsrV8Pj9ZqVQitVrtqejxePxjMpmss5hVTB4buXvMb2DyU2tBTRS+BjvNlVYUpPl7iuVO3Gq1uoQx1FtSOW1gPgp5ZWrdBtNmUDgv5asgxQ8F1af5vhY0YjyjuWC3wTszKJz7GBOkcFlQfW2ONq4FjWi+Hj6DRCKxQOK2TlY4x92EuYd5dvMAbYIzfikau3pu5tJ8KxaLLfo0cyKci7tK4TZjUMcoXAmHwzle0Q/RaC5P1GFMyVx9R9Fo9HYqlTrSgqDvFelAqVQa5hmuMR/WGtjAaBdjwBoDQ0ZsnwVMZjKZ9n0Zem8DSeDPdrnZbL6F2l3NOvUYNZk4oVDoRTabPe4EDNJzB0ZcjAYxeoZ2i3FNxQ7BHYw/cB/fldaH//UETgHHO8S44KbfXgAAAABJRU5ErkJggg==);\\\\n}\\\\n\\\\na[href=''] {\\\\n color: red;\\\\n}\\\\n\\\\na[href='' i] {\\\\n color: red;\\\\n}\\\\n\\\\na[href=\\\\\\"\\\\\\"] {\\\\n color: blue;\\\\n}\\\\n\\\\na[href=\\\\\\"\\\\\\" i] {\\\\n color: blue;\\\\n}\\\\n\\"],\\"sourceRoot\\":\\"\\"}]); +// Exports +export default ___CSS_LOADER_EXPORT___.toString(); +" +`; + +exports[`'exportType' option should work with 'string' value and generate source maps: result 1`] = ` +"@charset \\"UTF-8\\"; + +/* Comment */ + +.class { + color: red; + background: url(replaced_file_protocol_/webpack/public/path/img.png); +} + +.class-duplicate-url { + background: url(replaced_file_protocol_/webpack/public/path/img.png); +} + +:root { + --foo: 1px; + --bar: 2px; +} + +.class { a: b c d; } + +.two {} + +.u-m\\\\+ { a: b c d; } + +.class { content: \\"\\\\F10C\\" } + +@media only screen and (max-width: 600px) { + body { + background-color: lightblue; + } +} + +.class { + content: \\"\\\\2193\\"; + content: \\"\\\\2193\\\\2193\\"; + content: \\"\\\\2193 \\\\2193\\"; + content: \\"\\\\2193\\\\2193\\\\2193\\"; + content: \\"\\\\2193 \\\\2193 \\\\2193\\"; +} + +.-top {} +.\\\\-top {} + +#\\\\#test {} + +.grid { + display: flex; + flex-wrap: wrap; +} +.grid.\\\\-top { + align-items: flex-start; +} +.grid.-top { + align-items: flex-start; +} +.grid.\\\\-middle { + align-items: center; +} +.grid.\\\\-bottom { + align-items: flex-end; +} + +.u-m\\\\00002b {} + +.u-m00002b {} + +#u-m\\\\+ {} + +body { + font-family: '微软雅黑'; /* some chinese font name */ +} + +.myStyle { + content: '\\\\e901'; +} + +.myStyle { + content: '\\\\E901'; +} + +.♫ {} + +.\\\\3A \\\\\`\\\\( {} /* matches elements with class=\\":\`(\\" */ +.\\\\31 a2b3c {} /* matches elements with class=\\"1a2b3c\\" */ +#\\\\#fake-id {} /* matches the element with id=\\"#fake-id\\" */ +#-a-b-c- {} /* matches the element with id=\\"-a-b-c-\\" */ +#© {} /* matches the element with id=\\"©\\" */ + +:root { + --title-align: center; + --sr-only: { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip: rect(0,0,0,0); + white-space: nowrap; + clip-path: inset(50%); + border: 0; + }; +} + +.test { + content: \\"\\\\2014\\\\A0\\"; + content: \\"\\\\2014 \\\\A0\\"; + content: \\"\\\\A0 \\\\2014\\"; + content: \\"\\\\A0\\\\2014\\"; + margin-top: 1px\\\\9; + background-color: #000\\\\9; +} + +.light.on .bulb:before{ + content: '💡'; +} + +.base64 { + background: url(data:img/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAhxJREFUSA3tk71rU1EYxnMTEoJUkowWwdJ2akEHBfGjCiIF6ZylVUKSm2TqZLGI+A/oIu2UXm8C4lAyF4SWji0tdFLo1Eo7VN0SaBEhH7e/Nz0nPTfGOjiaCyfPc5734zlfCQT6X/8E/vUErL81KBaL9y3LSnued5PcITjUOwR3gsFg2bbtjYt6/NGgXC4P1et1l2aPLmpAbD0SidjpdPqgV15PA9d17zQajU8UxHQRK/4G35Q5pveAK8LlI1ZjPMnlcltnyvnvbwaO41xvtVqy7YHztMACq5xnlb9EY3dRdvcGo1kj5wR+t1AofDG0gM+A875E8DNjRCexsrV8Pj9ZqVQitVrtqejxePxjMpmss5hVTB4buXvMb2DyU2tBTRS+BjvNlVYUpPl7iuVO3Gq1uoQx1FtSOW1gPgp5ZWrdBtNmUDgv5asgxQ8F1af5vhY0YjyjuWC3wTszKJz7GBOkcFlQfW2ONq4FjWi+Hj6DRCKxQOK2TlY4x92EuYd5dvMAbYIzfikau3pu5tJ8KxaLLfo0cyKci7tK4TZjUMcoXAmHwzle0Q/RaC5P1GFMyVx9R9Fo9HYqlTrSgqDvFelAqVQa5hmuMR/WGtjAaBdjwBoDQ0ZsnwVMZjKZ9n0Zem8DSeDPdrnZbL6F2l3NOvUYNZk4oVDoRTabPe4EDNJzB0ZcjAYxeoZ2i3FNxQ7BHYw/cB/fldaH//UETgHHO8S44KbfXgAAAABJRU5ErkJggg==); +} + +a[href=''] { + color: red; +} + +a[href='' i] { + color: red; +} + +a[href=\\"\\"] { + color: blue; +} + +a[href=\\"\\" i] { + color: blue; +} + +/*# sourceURL=webpack://./basic-css-style-sheet.css */ +/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8uL2Jhc2ljLWNzcy1zdHlsZS1zaGVldC5jc3MiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsZ0JBQWdCOztBQUVoQixZQUFZOztBQUVaO0VBQ0UsVUFBVTtFQUNWLG1EQUFnQztBQUNsQzs7QUFFQTtFQUNFLG1EQUFnQztBQUNsQzs7QUFFQTtFQUNFLFVBQVU7RUFDVixVQUFVO0FBQ1o7O0FBRUEsU0FBUyxRQUFRLEVBQUU7O0FBRW5CLE1BQU07O0FBRU4sU0FBUyxRQUFRLEVBQUU7O0FBRW5CLFNBQVMsaUJBQWlCOztBQUUxQjtFQUNFO0lBQ0UsMkJBQTJCO0VBQzdCO0FBQ0Y7O0FBRUE7RUFDRSxnQkFBZ0I7RUFDaEIscUJBQXFCO0VBQ3JCLHNCQUFzQjtFQUN0QiwwQkFBMEI7RUFDMUIsNEJBQTRCO0FBQzlCOztBQUVBLE9BQU87QUFDUCxRQUFROztBQUVSLFNBQVM7O0FBRVQ7RUFDRSxhQUFhO0VBQ2IsZUFBZTtBQUNqQjtBQUNBO0VBQ0UsdUJBQXVCO0FBQ3pCO0FBQ0E7RUFDRSx1QkFBdUI7QUFDekI7QUFDQTtFQUNFLG1CQUFtQjtBQUNyQjtBQUNBO0VBQ0UscUJBQXFCO0FBQ3ZCOztBQUVBLGFBQWE7O0FBRWIsWUFBWTs7QUFFWixRQUFROztBQUVSO0VBQ0UsbUJBQW1CLEVBQUUsMkJBQTJCO0FBQ2xEOztBQUVBO0VBQ0UsZ0JBQWdCO0FBQ2xCOztBQUVBO0VBQ0UsZ0JBQWdCO0FBQ2xCOztBQUVBLElBQUk7O0FBRUosV0FBVyxFQUFFLHNDQUFzQztBQUNuRCxZQUFZLEVBQUUseUNBQXlDO0FBQ3ZELFlBQVksRUFBRSwyQ0FBMkM7QUFDekQsVUFBVSxFQUFFLDBDQUEwQztBQUN0RCxJQUFJLEVBQUUsb0NBQW9DOztBQUUxQztFQUNFLHFCQUFxQjtFQUNyQjs7Ozs7Ozs7OztHQVVDO0FBQ0g7O0FBRUE7RUFDRSxtQkFBbUI7RUFDbkIsb0JBQW9CO0VBQ3BCLG9CQUFvQjtFQUNwQixtQkFBbUI7RUFDbkIsaUJBQWlCO0VBQ2pCLHdCQUF3QjtBQUMxQjs7QUFFQTtFQUNFLGFBQWE7QUFDZjs7QUFFQTtFQUNFLG1EQUFxMUI7QUFDdjFCOztBQUVBO0VBQ0UsVUFBVTtBQUNaOztBQUVBO0VBQ0UsVUFBVTtBQUNaOztBQUVBO0VBQ0UsV0FBVztBQUNiOztBQUVBO0VBQ0UsV0FBVztBQUNiIiwic291cmNlc0NvbnRlbnQiOlsiQGNoYXJzZXQgXCJVVEYtOFwiO1xuXG4vKiBDb21tZW50ICovXG5cbi5jbGFzcyB7XG4gIGNvbG9yOiByZWQ7XG4gIGJhY2tncm91bmQ6IHVybChcIi4vdXJsL2ltZy5wbmdcIik7XG59XG5cbi5jbGFzcy1kdXBsaWNhdGUtdXJsIHtcbiAgYmFja2dyb3VuZDogdXJsKFwiLi91cmwvaW1nLnBuZ1wiKTtcbn1cblxuOnJvb3Qge1xuICAtLWZvbzogMXB4O1xuICAtLWJhcjogMnB4O1xufVxuXG4uY2xhc3MgeyBhOiBiIGMgZDsgfVxuXG4udHdvIHt9XG5cbi51LW1cXCsgeyBhOiBiIGMgZDsgfVxuXG4uY2xhc3MgeyBjb250ZW50OiBcIlxcRjEwQ1wiIH1cblxuQG1lZGlhIG9ubHkgc2NyZWVuIGFuZCAobWF4LXdpZHRoOiA2MDBweCkge1xuICBib2R5IHtcbiAgICBiYWNrZ3JvdW5kLWNvbG9yOiBsaWdodGJsdWU7XG4gIH1cbn1cblxuLmNsYXNzIHtcbiAgY29udGVudDogXCJcXDIxOTNcIjtcbiAgY29udGVudDogXCJcXDIxOTNcXDIxOTNcIjtcbiAgY29udGVudDogXCJcXDIxOTMgXFwyMTkzXCI7XG4gIGNvbnRlbnQ6IFwiXFwyMTkzXFwyMTkzXFwyMTkzXCI7XG4gIGNvbnRlbnQ6IFwiXFwyMTkzIFxcMjE5MyBcXDIxOTNcIjtcbn1cblxuLi10b3Age31cbi5cXC10b3Age31cblxuI1xcI3Rlc3Qge31cblxuLmdyaWQge1xuICBkaXNwbGF5OiBmbGV4O1xuICBmbGV4LXdyYXA6IHdyYXA7XG59XG4uZ3JpZC5cXC10b3Age1xuICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcbn1cbi5ncmlkLi10b3Age1xuICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcbn1cbi5ncmlkLlxcLW1pZGRsZSB7XG4gIGFsaWduLWl0ZW1zOiBjZW50ZXI7XG59XG4uZ3JpZC5cXC1ib3R0b20ge1xuICBhbGlnbi1pdGVtczogZmxleC1lbmQ7XG59XG5cbi51LW1cXDAwMDAyYiB7fVxuXG4udS1tMDAwMDJiIHt9XG5cbiN1LW1cXCsge31cblxuYm9keSB7XG4gIGZvbnQtZmFtaWx5OiAnw6XCvsKuw6jCvcKvw6nCm8KFw6nCu8KRJzsgLyogc29tZSBjaGluZXNlIGZvbnQgbmFtZSAqL1xufVxuXG4ubXlTdHlsZSB7XG4gIGNvbnRlbnQ6ICdcXGU5MDEnO1xufVxuXG4ubXlTdHlsZSB7XG4gIGNvbnRlbnQ6ICdcXEU5MDEnO1xufVxuXG4uw6LCmcKrIHt9XG5cbi5cXDNBIFxcYFxcKCB7fSAvKiBtYXRjaGVzIGVsZW1lbnRzIHdpdGggY2xhc3M9XCI6YChcIiAqL1xuLlxcMzEgYTJiM2Mge30gLyogbWF0Y2hlcyBlbGVtZW50cyB3aXRoIGNsYXNzPVwiMWEyYjNjXCIgKi9cbiNcXCNmYWtlLWlkIHt9IC8qIG1hdGNoZXMgdGhlIGVsZW1lbnQgd2l0aCBpZD1cIiNmYWtlLWlkXCIgKi9cbiMtYS1iLWMtIHt9IC8qIG1hdGNoZXMgdGhlIGVsZW1lbnQgd2l0aCBpZD1cIi1hLWItYy1cIiAqL1xuI8OCwqkge30gLyogbWF0Y2hlcyB0aGUgZWxlbWVudCB3aXRoIGlkPVwiw4LCqVwiICovXG5cbjpyb290IHtcbiAgLS10aXRsZS1hbGlnbjogY2VudGVyO1xuICAtLXNyLW9ubHk6IHtcbiAgICBwb3NpdGlvbjogYWJzb2x1dGU7XG4gICAgd2lkdGg6IDFweDtcbiAgICBoZWlnaHQ6IDFweDtcbiAgICBwYWRkaW5nOiAwO1xuICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgY2xpcDogcmVjdCgwLDAsMCwwKTtcbiAgICB3aGl0ZS1zcGFjZTogbm93cmFwO1xuICAgIGNsaXAtcGF0aDogaW5zZXQoNTAlKTtcbiAgICBib3JkZXI6IDA7XG4gIH07XG59XG5cbi50ZXN0IHtcbiAgY29udGVudDogXCJcXDIwMTRcXEEwXCI7XG4gIGNvbnRlbnQ6IFwiXFwyMDE0IFxcQTBcIjtcbiAgY29udGVudDogXCJcXEEwIFxcMjAxNFwiO1xuICBjb250ZW50OiBcIlxcQTBcXDIwMTRcIjtcbiAgbWFyZ2luLXRvcDogMXB4XFw5O1xuICBiYWNrZ3JvdW5kLWNvbG9yOiAjMDAwXFw5O1xufVxuXG4ubGlnaHQub24gLmJ1bGI6YmVmb3Jle1xuICBjb250ZW50OiAnw7DCn8KSwqEnO1xufVxuXG4uYmFzZTY0IHtcbiAgYmFja2dyb3VuZDogdXJsKGRhdGE6aW1nL2pwZztiYXNlNjQsaVZCT1J3MEtHZ29BQUFBTlNVaEVVZ0FBQUJnQUFBQVlDQVlBQUFEZ2R6MzRBQUFBQVhOU1IwSUFyczRjNlFBQUFoeEpSRUZVU0EzdGs3MXJVMUVZeG5NVEVvSlVrb3dXd2RKMmFrRUhCZkdqQ2lJRjZaeWxWVUtTbTJUcVpMR0krQS9vSXUyVVhtOEM0bEF5RjRTV2ppMHRkRkxvMUVvN1ZOMFNhQkVoSDdlL056MG5QVGZHT2ppYUN5ZlBjNTczNHpsZkNRVDZYLzhFL3ZVRXJMODFLQmFMOXkzTFNudWVkNVBjSVRqVU93UjNnc0ZnMmJidGpZdDYvTkdnWEM0UDFldDFsMmFQTG1wQWJEMFNpZGpwZFBxZ1YxNVBBOWQxN3pRYWpVOFV4SFFSSy80RzM1UTVwdmVBSzhMbEkxWmpQTW5sY2x0bnl2bnZid2FPNDF4dnRWcXk3WUh6dE1BQ3E1eG5sYjlFWTNkUmR2Y0dvMWtqNXdSK3QxQW9mREcwZ00rQTg3NUU4RE5qUkNleHNyVjhQajlacVZRaXRWcnRxZWp4ZVB4ak1wbXNzNWhWVEI0YnVYdk1iMkR5VTJ0QlRSUytCanZObFZZVXBQbDdpdVZPM0dxMXVvUXgxRnRTT1cxZ1BncDVaV3JkQnRObVVEZ3Y1YXNneFE4RjFhZjV2aFkwWWp5anVXQzN3VHN6S0p6N0dCT2tjRmxRZlcyT05xNEZqV2krSGo2RFJDS3hRT0syVGxZNHg5MkV1WWQ1ZHZNQWJZSXpmaWthdTNwdTV0SjhLeGFMTGZvMGN5S2NpN3RLNFRaalVNY29YQW1Id3psZTBRL1JhQzVQMUdGTXlWeDlSOUZvOUhZcWxUclNncUR2RmVsQXFWUWE1aG11TVIvV0d0akFhQmRqd0JvRFEwWnNud1ZNWmpLWjluMFplbThEU2VEUGRyblpiTDZGMmwzTk92VVlOWms0b1ZEb1JUYWJQZTRFRE5KekIwWmNqQVl4ZW9aMmkzRk54UTdCSFl3L2NCL2ZsZGFILy9VRVRnSEhPOFM0NEtiZlhnQUFBQUJKUlU1RXJrSmdnZz09KTtcbn1cblxuYVtocmVmPScnXSB7XG4gIGNvbG9yOiByZWQ7XG59XG5cbmFbaHJlZj0nJyBpXSB7XG4gIGNvbG9yOiByZWQ7XG59XG5cbmFbaHJlZj1cIlwiXSB7XG4gIGNvbG9yOiBibHVlO1xufVxuXG5hW2hyZWY9XCJcIiBpXSB7XG4gIGNvbG9yOiBibHVlO1xufVxuIl0sInNvdXJjZVJvb3QiOiIifQ== */" +`; + +exports[`'exportType' option should work with 'string' value and generate source maps: warnings 1`] = `Array []`; + +exports[`'exportType' option should work with 'string' value: errors 1`] = `Array []`; + +exports[`'exportType' option should work with 'string' value: module 1`] = ` +"// Imports +import ___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___ from \\"../../src/runtime/noSourceMaps.js\\"; +import ___CSS_LOADER_API_IMPORT___ from \\"../../src/runtime/api.js\\"; +import ___CSS_LOADER_GET_URL_IMPORT___ from \\"../../src/runtime/getUrl.js\\"; +var ___CSS_LOADER_URL_IMPORT_0___ = new URL(\\"./url/img.png\\", import.meta.url); +var ___CSS_LOADER_URL_IMPORT_1___ = new URL(\\"data:img/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAhxJREFUSA3tk71rU1EYxnMTEoJUkowWwdJ2akEHBfGjCiIF6ZylVUKSm2TqZLGI+A/oIu2UXm8C4lAyF4SWji0tdFLo1Eo7VN0SaBEhH7e/Nz0nPTfGOjiaCyfPc5734zlfCQT6X/8E/vUErL81KBaL9y3LSnued5PcITjUOwR3gsFg2bbtjYt6/NGgXC4P1et1l2aPLmpAbD0SidjpdPqgV15PA9d17zQajU8UxHQRK/4G35Q5pveAK8LlI1ZjPMnlcltnyvnvbwaO41xvtVqy7YHztMACq5xnlb9EY3dRdvcGo1kj5wR+t1AofDG0gM+A875E8DNjRCexsrV8Pj9ZqVQitVrtqejxePxjMpmss5hVTB4buXvMb2DyU2tBTRS+BjvNlVYUpPl7iuVO3Gq1uoQx1FtSOW1gPgp5ZWrdBtNmUDgv5asgxQ8F1af5vhY0YjyjuWC3wTszKJz7GBOkcFlQfW2ONq4FjWi+Hj6DRCKxQOK2TlY4x92EuYd5dvMAbYIzfikau3pu5tJ8KxaLLfo0cyKci7tK4TZjUMcoXAmHwzle0Q/RaC5P1GFMyVx9R9Fo9HYqlTrSgqDvFelAqVQa5hmuMR/WGtjAaBdjwBoDQ0ZsnwVMZjKZ9n0Zem8DSeDPdrnZbL6F2l3NOvUYNZk4oVDoRTabPe4EDNJzB0ZcjAYxeoZ2i3FNxQ7BHYw/cB/fldaH//UETgHHO8S44KbfXgAAAABJRU5ErkJggg==\\", import.meta.url); +var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___); +var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___); +var ___CSS_LOADER_URL_REPLACEMENT_1___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_1___); +// Module +___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\\\\n.class-duplicate-url {\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\\\n:root {\\\\n --foo: 1px;\\\\n --bar: 2px;\\\\n}\\\\n\\\\n.class { a: b c d; }\\\\n\\\\n.two {}\\\\n\\\\n.u-m\\\\\\\\+ { a: b c d; }\\\\n\\\\n.class { content: \\\\\\"\\\\\\\\F10C\\\\\\" }\\\\n\\\\n@media only screen and (max-width: 600px) {\\\\n body {\\\\n background-color: lightblue;\\\\n }\\\\n}\\\\n\\\\n.class {\\\\n content: \\\\\\"\\\\\\\\2193\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2193\\\\\\\\2193\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2193 \\\\\\\\2193\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2193\\\\\\\\2193\\\\\\\\2193\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2193 \\\\\\\\2193 \\\\\\\\2193\\\\\\";\\\\n}\\\\n\\\\n.-top {}\\\\n.\\\\\\\\-top {}\\\\n\\\\n#\\\\\\\\#test {}\\\\n\\\\n.grid {\\\\n display: flex;\\\\n flex-wrap: wrap;\\\\n}\\\\n.grid.\\\\\\\\-top {\\\\n align-items: flex-start;\\\\n}\\\\n.grid.-top {\\\\n align-items: flex-start;\\\\n}\\\\n.grid.\\\\\\\\-middle {\\\\n align-items: center;\\\\n}\\\\n.grid.\\\\\\\\-bottom {\\\\n align-items: flex-end;\\\\n}\\\\n\\\\n.u-m\\\\\\\\00002b {}\\\\n\\\\n.u-m00002b {}\\\\n\\\\n#u-m\\\\\\\\+ {}\\\\n\\\\nbody {\\\\n font-family: '微软雅黑'; /* some chinese font name */\\\\n}\\\\n\\\\n.myStyle {\\\\n content: '\\\\\\\\e901';\\\\n}\\\\n\\\\n.myStyle {\\\\n content: '\\\\\\\\E901';\\\\n}\\\\n\\\\n.♫ {}\\\\n\\\\n.\\\\\\\\3A \\\\\\\\\`\\\\\\\\( {} /* matches elements with class=\\\\\\":\`(\\\\\\" */\\\\n.\\\\\\\\31 a2b3c {} /* matches elements with class=\\\\\\"1a2b3c\\\\\\" */\\\\n#\\\\\\\\#fake-id {} /* matches the element with id=\\\\\\"#fake-id\\\\\\" */\\\\n#-a-b-c- {} /* matches the element with id=\\\\\\"-a-b-c-\\\\\\" */\\\\n#© {} /* matches the element with id=\\\\\\"©\\\\\\" */\\\\n\\\\n:root {\\\\n --title-align: center;\\\\n --sr-only: {\\\\n position: absolute;\\\\n width: 1px;\\\\n height: 1px;\\\\n padding: 0;\\\\n overflow: hidden;\\\\n clip: rect(0,0,0,0);\\\\n white-space: nowrap;\\\\n clip-path: inset(50%);\\\\n border: 0;\\\\n };\\\\n}\\\\n\\\\n.test {\\\\n content: \\\\\\"\\\\\\\\2014\\\\\\\\A0\\\\\\";\\\\n content: \\\\\\"\\\\\\\\2014 \\\\\\\\A0\\\\\\";\\\\n content: \\\\\\"\\\\\\\\A0 \\\\\\\\2014\\\\\\";\\\\n content: \\\\\\"\\\\\\\\A0\\\\\\\\2014\\\\\\";\\\\n margin-top: 1px\\\\\\\\9;\\\\n background-color: #000\\\\\\\\9;\\\\n}\\\\n\\\\n.light.on .bulb:before{\\\\n content: '💡';\\\\n}\\\\n\\\\n.base64 {\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_1___ + \\");\\\\n}\\\\n\\\\na[href=''] {\\\\n color: red;\\\\n}\\\\n\\\\na[href='' i] {\\\\n color: red;\\\\n}\\\\n\\\\na[href=\\\\\\"\\\\\\"] {\\\\n color: blue;\\\\n}\\\\n\\\\na[href=\\\\\\"\\\\\\" i] {\\\\n color: blue;\\\\n}\\\\n\\", \\"\\"]); +// Exports +export default ___CSS_LOADER_EXPORT___.toString(); +" +`; + +exports[`'exportType' option should work with 'string' value: result 1`] = ` +"@charset \\"UTF-8\\"; + +/* Comment */ + +.class { + color: red; + background: url(replaced_file_protocol_/webpack/public/path/img.png); +} + +.class-duplicate-url { + background: url(replaced_file_protocol_/webpack/public/path/img.png); +} + +:root { + --foo: 1px; + --bar: 2px; +} + +.class { a: b c d; } + +.two {} + +.u-m\\\\+ { a: b c d; } + +.class { content: \\"\\\\F10C\\" } + +@media only screen and (max-width: 600px) { + body { + background-color: lightblue; + } +} + +.class { + content: \\"\\\\2193\\"; + content: \\"\\\\2193\\\\2193\\"; + content: \\"\\\\2193 \\\\2193\\"; + content: \\"\\\\2193\\\\2193\\\\2193\\"; + content: \\"\\\\2193 \\\\2193 \\\\2193\\"; +} + +.-top {} +.\\\\-top {} + +#\\\\#test {} + +.grid { + display: flex; + flex-wrap: wrap; +} +.grid.\\\\-top { + align-items: flex-start; +} +.grid.-top { + align-items: flex-start; +} +.grid.\\\\-middle { + align-items: center; +} +.grid.\\\\-bottom { + align-items: flex-end; +} + +.u-m\\\\00002b {} + +.u-m00002b {} + +#u-m\\\\+ {} + +body { + font-family: '微软雅黑'; /* some chinese font name */ +} + +.myStyle { + content: '\\\\e901'; +} + +.myStyle { + content: '\\\\E901'; +} + +.♫ {} + +.\\\\3A \\\\\`\\\\( {} /* matches elements with class=\\":\`(\\" */ +.\\\\31 a2b3c {} /* matches elements with class=\\"1a2b3c\\" */ +#\\\\#fake-id {} /* matches the element with id=\\"#fake-id\\" */ +#-a-b-c- {} /* matches the element with id=\\"-a-b-c-\\" */ +#© {} /* matches the element with id=\\"©\\" */ + +:root { + --title-align: center; + --sr-only: { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + overflow: hidden; + clip: rect(0,0,0,0); + white-space: nowrap; + clip-path: inset(50%); + border: 0; + }; +} + +.test { + content: \\"\\\\2014\\\\A0\\"; + content: \\"\\\\2014 \\\\A0\\"; + content: \\"\\\\A0 \\\\2014\\"; + content: \\"\\\\A0\\\\2014\\"; + margin-top: 1px\\\\9; + background-color: #000\\\\9; +} + +.light.on .bulb:before{ + content: '💡'; +} + +.base64 { + background: url(data:img/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAhxJREFUSA3tk71rU1EYxnMTEoJUkowWwdJ2akEHBfGjCiIF6ZylVUKSm2TqZLGI+A/oIu2UXm8C4lAyF4SWji0tdFLo1Eo7VN0SaBEhH7e/Nz0nPTfGOjiaCyfPc5734zlfCQT6X/8E/vUErL81KBaL9y3LSnued5PcITjUOwR3gsFg2bbtjYt6/NGgXC4P1et1l2aPLmpAbD0SidjpdPqgV15PA9d17zQajU8UxHQRK/4G35Q5pveAK8LlI1ZjPMnlcltnyvnvbwaO41xvtVqy7YHztMACq5xnlb9EY3dRdvcGo1kj5wR+t1AofDG0gM+A875E8DNjRCexsrV8Pj9ZqVQitVrtqejxePxjMpmss5hVTB4buXvMb2DyU2tBTRS+BjvNlVYUpPl7iuVO3Gq1uoQx1FtSOW1gPgp5ZWrdBtNmUDgv5asgxQ8F1af5vhY0YjyjuWC3wTszKJz7GBOkcFlQfW2ONq4FjWi+Hj6DRCKxQOK2TlY4x92EuYd5dvMAbYIzfikau3pu5tJ8KxaLLfo0cyKci7tK4TZjUMcoXAmHwzle0Q/RaC5P1GFMyVx9R9Fo9HYqlTrSgqDvFelAqVQa5hmuMR/WGtjAaBdjwBoDQ0ZsnwVMZjKZ9n0Zem8DSeDPdrnZbL6F2l3NOvUYNZk4oVDoRTabPe4EDNJzB0ZcjAYxeoZ2i3FNxQ7BHYw/cB/fldaH//UETgHHO8S44KbfXgAAAABJRU5ErkJggg==); +} + +a[href=''] { + color: red; +} + +a[href='' i] { + color: red; +} + +a[href=\\"\\"] { + color: blue; +} + +a[href=\\"\\" i] { + color: blue; +} +" +`; + +exports[`'exportType' option should work with 'string' value: warnings 1`] = `Array []`; + exports[`'exportType' option should work with CSS modules and the 'exportOnlyLocals' option: errors 1`] = `Array []`; exports[`'exportType' option should work with CSS modules and the 'exportOnlyLocals' option: module 1`] = ` diff --git a/test/__snapshots__/validate-options.test.js.snap b/test/__snapshots__/validate-options.test.js.snap index 3cf63714..07e4a828 100644 --- a/test/__snapshots__/validate-options.test.js.snap +++ b/test/__snapshots__/validate-options.test.js.snap @@ -10,16 +10,16 @@ exports[`validate options should throw an error on the "esModule" option with "t exports[`validate options should throw an error on the "exportType" option with "false" value 1`] = ` "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema. - options.exportType should be one of these: - \\"array\\" | \\"css-style-sheet\\" - -> Allows exporting styles as array with modules or constructable stylesheet (i.e. \`CSSStyleSheet\`). + \\"array\\" | \\"string\\" | \\"css-style-sheet\\" + -> Allows exporting styles as array with modules, string or constructable stylesheet (i.e. \`CSSStyleSheet\`). -> Read more at https://github.com/webpack-contrib/css-loader#exporttype" `; exports[`validate options should throw an error on the "exportType" option with "true" value 1`] = ` "Invalid options object. CSS Loader has been initialized using an options object that does not match the API schema. - options.exportType should be one of these: - \\"array\\" | \\"css-style-sheet\\" - -> Allows exporting styles as array with modules or constructable stylesheet (i.e. \`CSSStyleSheet\`). + \\"array\\" | \\"string\\" | \\"css-style-sheet\\" + -> Allows exporting styles as array with modules, string or constructable stylesheet (i.e. \`CSSStyleSheet\`). -> Read more at https://github.com/webpack-contrib/css-loader#exporttype" `; diff --git a/test/exportType.test.js b/test/exportType.test.js index 29b2c031..cd726b8f 100644 --- a/test/exportType.test.js +++ b/test/exportType.test.js @@ -36,6 +36,54 @@ describe("'exportType' option", () => { expect(getErrors(stats)).toMatchSnapshot("errors"); }); + it("should work with 'string' value", async () => { + const compiler = getCompiler("./basic-string.js", { + exportType: "string", + }); + const stats = await compile(compiler); + + expect( + getModuleSource("./basic-css-style-sheet.css", stats) + ).toMatchSnapshot("module"); + expect(getExecutedCode("main.bundle.js", compiler, stats)).toMatchSnapshot( + "result" + ); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); + + it("should work with 'string' value and generate source maps", async () => { + const compiler = getCompiler("./basic-string.js", { + exportType: "string", + sourceMap: true, + }); + const stats = await compile(compiler); + + expect( + getModuleSource("./basic-css-style-sheet.css", stats) + ).toMatchSnapshot("module"); + expect(getExecutedCode("main.bundle.js", compiler, stats)).toMatchSnapshot( + "result" + ); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); + + it("should work with 'string' value and CSS modules", async () => { + const compiler = getCompiler("./basic-string-css-modules.js", { + exportType: "string", + modules: true, + }); + const stats = await compile(compiler); + + expect(getModuleSource("./simple.css", stats)).toMatchSnapshot("module"); + expect(getExecutedCode("main.bundle.js", compiler, stats)).toMatchSnapshot( + "result" + ); + expect(getWarnings(stats)).toMatchSnapshot("warnings"); + expect(getErrors(stats)).toMatchSnapshot("errors"); + }); + it("should work with 'css-style-sheet' value", async () => { const compiler = getCompiler("./basic-css-style-sheet.js", { exportType: "css-style-sheet", diff --git a/test/fixtures/basic-string-css-modules.js b/test/fixtures/basic-string-css-modules.js new file mode 100644 index 00000000..971cba11 --- /dev/null +++ b/test/fixtures/basic-string-css-modules.js @@ -0,0 +1,5 @@ +import css, { someClass } from './simple.css'; + +__export__ = { css, locals: { someClass } }; + +export default css; diff --git a/test/fixtures/basic-string.js b/test/fixtures/basic-string.js new file mode 100644 index 00000000..05c2f754 --- /dev/null +++ b/test/fixtures/basic-string.js @@ -0,0 +1,5 @@ +import css from './basic-css-style-sheet.css'; + +__export__ = css; + +export default css; diff --git a/test/validate-options.test.js b/test/validate-options.test.js index 3376905e..f9a85414 100644 --- a/test/validate-options.test.js +++ b/test/validate-options.test.js @@ -88,7 +88,7 @@ describe("validate options", () => { failure: ["true"], }, exportType: { - success: ["array", "css-style-sheet"], + success: ["array", "string", "css-style-sheet"], failure: ["true", false], }, unknown: {