From 04c3d1639e2b727b354982aa47343f976c481d53 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 9 Jul 2018 19:13:12 +0300 Subject: [PATCH 01/45] refactor: drop `css` modules BREAKING CHANGE: use `postcss-modules` plugin with `postcss-loader` --- README.md | 157 +---- lib/getLocalIdent.js | 23 - lib/loader.js | 2 - lib/localsLoader.js | 44 -- lib/processCss.js | 41 +- locals.js | 5 - package-lock.json | 564 ++++-------------- package.json | 10 +- test/camelCaseTest.js | 47 -- test/customGetLocalIdentTest.js | 19 - test/helpers.js | 13 - test/localTest.js | 212 ------- test/localsTest.js | 59 -- test/moduleTest.js | 17 - test/moduleTestCases/class-names/expected.css | 3 - test/moduleTestCases/class-names/source.css | 3 - test/moduleTestCases/comments/expected.css | 11 - test/moduleTestCases/comments/source.css | 11 - .../keyframes-and-animation/expected.css | 48 -- .../keyframes-and-animation/source.css | 48 -- test/moduleTestCases/leak-scope/expected.css | 37 -- test/moduleTestCases/leak-scope/source.css | 37 -- test/moduleTestCases/simple/expected.css | 11 - test/moduleTestCases/simple/source.css | 11 - test/moduleTestCases/urls/expected.css | 14 - test/moduleTestCases/urls/source.css | 14 - test/moduleTestCases/values/expected.css | 5 - test/moduleTestCases/values/source.css | 9 - test/urlTest.js | 8 +- test/valuesTest.js | 120 ---- 30 files changed, 129 insertions(+), 1474 deletions(-) delete mode 100644 lib/getLocalIdent.js delete mode 100644 lib/localsLoader.js delete mode 100644 locals.js delete mode 100644 test/camelCaseTest.js delete mode 100644 test/customGetLocalIdentTest.js delete mode 100644 test/localTest.js delete mode 100644 test/localsTest.js delete mode 100644 test/moduleTest.js delete mode 100644 test/moduleTestCases/class-names/expected.css delete mode 100644 test/moduleTestCases/class-names/source.css delete mode 100644 test/moduleTestCases/comments/expected.css delete mode 100644 test/moduleTestCases/comments/source.css delete mode 100644 test/moduleTestCases/keyframes-and-animation/expected.css delete mode 100644 test/moduleTestCases/keyframes-and-animation/source.css delete mode 100644 test/moduleTestCases/leak-scope/expected.css delete mode 100644 test/moduleTestCases/leak-scope/source.css delete mode 100644 test/moduleTestCases/simple/expected.css delete mode 100644 test/moduleTestCases/simple/source.css delete mode 100644 test/moduleTestCases/urls/expected.css delete mode 100644 test/moduleTestCases/urls/source.css delete mode 100644 test/moduleTestCases/values/expected.css delete mode 100644 test/moduleTestCases/values/source.css delete mode 100644 test/valuesTest.js diff --git a/README.md b/README.md index d0b8f631..dade6e33 100644 --- a/README.md +++ b/README.md @@ -96,10 +96,8 @@ It's useful when you, for instance, need to post process the CSS as a string. |:--:|:--:|:-----:|:----------| |**[`url`](#url)**|`{Boolean}`|`true`| Enable/Disable `url()` handling| |**[`import`](#import)** |`{Boolean}`|`true`| Enable/Disable @import handling| -|**[`modules`](#modules)**|`{Boolean}`|`false`|Enable/Disable CSS Modules| -|**[`localIdentName`](#localidentname)**|`{String}`|`[hash:base64]`|Configure the generated ident| |**[`sourceMap`](#sourcemap)**|`{Boolean}`|`false`|Enable/Disable Sourcemaps| -|**[`camelCase`](#camelcase)**|`{Boolean\|String}`|`false`|Export Classnames in CamelCase| +|**[`camelCase`](#camelcase)**|`{Boolean\|String}`|`false`|Export in CamelCase| |**[`importLoaders`](#importloaders)**|`{Number}`|`0`|Number of loaders applied before CSS loader| ### `url` @@ -123,159 +121,6 @@ To disable `@import` resolving by `css-loader` set the option to `false` > _⚠️ Use with caution, since this disables resolving for **all** `@import`s, including css modules `composes: xxx from 'path/to/file.css'` feature._ -### [`modules`](https://github.com/css-modules/css-modules) - -The query parameter `modules` enables the **CSS Modules** spec. - -This enables local scoped CSS by default. (You can switch it off with `:global(...)` or `:global` for selectors and/or rules.). - -#### `Scope` - -By default CSS exports all classnames into a global selector scope. Styles can be locally scoped to avoid globally scoping styles. - -The syntax `:local(.className)` can be used to declare `className` in the local scope. The local identifiers are exported by the module. - -With `:local` (without brackets) local mode can be switched on for this selector. `:global(.className)` can be used to declare an explicit global selector. With `:global` (without brackets) global mode can be switched on for this selector. - -The loader replaces local selectors with unique identifiers. The choosen unique identifiers are exported by the module. - -```css -:local(.className) { background: red; } -:local .className { color: green; } -:local(.className .subClass) { color: green; } -:local .className .subClass :global(.global-class-name) { color: blue; } -``` - -```css -._23_aKvs-b8bW2Vg3fwHozO { background: red; } -._23_aKvs-b8bW2Vg3fwHozO { color: green; } -._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 { color: green; } -._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 .global-class-name { color: blue; } -``` - -> ℹ️ Identifiers are exported - -```js -exports.locals = { - className: '_23_aKvs-b8bW2Vg3fwHozO', - subClass: '_13LGdX8RMStbBE9w-t0gZ1' -} -``` - -CamelCase is recommended for local selectors. They are easier to use in the within the imported JS module. - -`url()` URLs in block scoped (`:local .abc`) rules behave like requests in modules. - -``` -file.png => ./file.png -~module/file.png => module/file.png -``` - -You can use `:local(#someId)`, but this is not recommended. Use classes instead of ids. - -#### `Composing` - -When declaring a local classname you can compose a local class from another local classname. - -```css -:local(.className) { - background: red; - color: yellow; -} - -:local(.subClass) { - composes: className; - background: blue; -} -``` - -This doesn't result in any change to the CSS itself but exports multiple classnames. - -```js -exports.locals = { - className: '_23_aKvs-b8bW2Vg3fwHozO', - subClass: '_13LGdX8RMStbBE9w-t0gZ1 _23_aKvs-b8bW2Vg3fwHozO' -} -``` - -``` css -._23_aKvs-b8bW2Vg3fwHozO { - background: red; - color: yellow; -} - -._13LGdX8RMStbBE9w-t0gZ1 { - background: blue; -} -``` - -#### `Importing` - -To import a local classname from another module. - -```css -:local(.continueButton) { - composes: button from 'library/button.css'; - background: red; -} -``` - -```css -:local(.nameEdit) { - composes: edit highlight from './edit.css'; - background: red; -} -``` - -To import from multiple modules use multiple `composes:` rules. - -```css -:local(.className) { - composes: edit hightlight from './edit.css'; - composes: button from 'module/button.css'; - composes: classFromThisModule; - background: red; -} -``` - -### `localIdentName` - -You can configure the generated ident with the `localIdentName` query parameter. See [loader-utils's documentation](https://github.com/webpack/loader-utils#interpolatename) for more information on options. - - **webpack.config.js** -```js -{ - test: /\.css$/, - use: [ - { - loader: 'css-loader', - options: { - modules: true, - localIdentName: '[path][name]__[local]--[hash:base64:5]' - } - } - ] -} -``` - -You can also specify the absolute path to your custom `getLocalIdent` function to generate classname based on a different schema. This requires `webpack >= 2.2.1` (it supports functions in the `options` object). - -**webpack.config.js** -```js -{ - loader: 'css-loader', - options: { - modules: true, - localIdentName: '[path][name]__[local]--[hash:base64:5]', - getLocalIdent: (context, localIdentName, localName, options) => { - return 'whatever_random_class_name' - } - } -} -``` - -> ℹ️ For prerendering with extract-text-webpack-plugin you should use `css-loader/locals` instead of `style-loader!css-loader` **in the prerendering bundle**. It doesn't embed CSS but only exports the identifier mappings. - ### `sourceMap` To include source maps set the `sourceMap` option. diff --git a/lib/getLocalIdent.js b/lib/getLocalIdent.js deleted file mode 100644 index 79c7ab57..00000000 --- a/lib/getLocalIdent.js +++ /dev/null @@ -1,23 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -var loaderUtils = require("loader-utils"); -var path = require("path"); - -module.exports = function getLocalIdent(loaderContext, localIdentName, localName, options) { - if(!options.context) { - if (loaderContext.rootContext) { - options.context = loaderContext.rootContext; - } else if (loaderContext.options && typeof loaderContext.options.context === "string") { - options.context = loaderContext.options.context; - } else { - options.context = loaderContext.context; - } - } - var request = path.relative(options.context, loaderContext.resourcePath); - options.content = options.hashPrefix + request + "+" + localName; - localIdentName = localIdentName.replace(/\[local\]/gi, localName); - var hash = loaderUtils.interpolateName(loaderContext, localIdentName, options); - return hash.replace(new RegExp("[^a-zA-Z0-9\\-_\u00A0-\uFFFF]", "g"), "-").replace(/^((-?[0-9])|--)/, "_$1"); -}; diff --git a/lib/loader.js b/lib/loader.js index b76c86de..b5a1a681 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -11,7 +11,6 @@ var compileExports = require("./compile-exports"); module.exports = function(content, map) { var callback = this.async(); var query = loaderUtils.getOptions(this) || {}; - var moduleMode = query.modules; var camelCaseKeys = query.camelCase; var sourceMap = query.sourceMap || false; @@ -34,7 +33,6 @@ module.exports = function(content, map) { } processCss(content, map, { - mode: moduleMode ? "local" : "global", from: loaderUtils.getRemainingRequest(this).split("!").pop(), to: loaderUtils.getCurrentRequest(this).split("!").pop(), query: query, diff --git a/lib/localsLoader.js b/lib/localsLoader.js deleted file mode 100644 index e12546e8..00000000 --- a/lib/localsLoader.js +++ /dev/null @@ -1,44 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -var loaderUtils = require("loader-utils"); -var processCss = require("./processCss"); -var getImportPrefix = require("./getImportPrefix"); -var compileExports = require("./compile-exports"); - - -module.exports = function(content) { - var callback = this.async(); - var query = loaderUtils.getOptions(this) || {}; - var moduleMode = query.modules; - var camelCaseKeys = query.camelCase; - - processCss(content, null, { - mode: moduleMode ? "local" : "global", - query: query, - loaderContext: this, - }, function(err, result) { - if(err) return callback(err); - - // for importing CSS - var importUrlPrefix = getImportPrefix(this, query); - - function importItemMatcher(item) { - var match = result.importItemRegExp.exec(item); - var idx = +match[1]; - var importItem = result.importItems[idx]; - var importUrl = importUrlPrefix + importItem.url; - return "\" + require(" + loaderUtils.stringifyRequest(this, importUrl) + ")" + - "[" + JSON.stringify(importItem.export) + "] + \""; - } - - var exportJs = compileExports(result, importItemMatcher.bind(this), camelCaseKeys); - if (exportJs) { - exportJs = "module.exports = " + exportJs + ";"; - } - - - callback(null, exportJs); - }.bind(this)); -}; diff --git a/lib/processCss.js b/lib/processCss.js index 61eb7ce5..c7c946bc 100644 --- a/lib/processCss.js +++ b/lib/processCss.js @@ -6,13 +6,8 @@ var formatCodeFrame = require("babel-code-frame"); var Tokenizer = require("css-selector-tokenizer"); var postcss = require("postcss"); var loaderUtils = require("loader-utils"); -var getLocalIdent = require("./getLocalIdent"); var icssUtils = require('icss-utils'); -var localByDefault = require("postcss-modules-local-by-default"); -var extractImports = require("postcss-modules-extract-imports"); -var modulesScope = require("postcss-modules-scope"); -var modulesValues = require("postcss-modules-values"); var valueParser = require('postcss-value-parser'); var parserPlugin = postcss.plugin("css-loader-parser", function(options) { @@ -104,7 +99,8 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) { item.stringType = ""; delete item.innerSpacingBefore; delete item.innerSpacingAfter; - var url = item.url; + // For backward-compat after dropping css modules + var url = loaderUtils.urlToRequest(item.url.trim()); item.url = "___CSS_LOADER_URL___" + urlItems.length + "___"; urlItems.push({ url: url @@ -135,47 +131,14 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) { module.exports = function processCss(inputSource, inputMap, options, callback) { var query = options.query; - var context = query.context; - var localIdentName = query.localIdentName || "[hash:base64]"; - var localIdentRegExp = query.localIdentRegExp; - - var customGetLocalIdent = query.getLocalIdent || getLocalIdent; var parserOptions = { - mode: options.mode, url: query.url !== false, import: query.import !== false, resolve: options.resolve }; var pipeline = postcss([ - modulesValues, - localByDefault({ - mode: options.mode, - rewriteUrl: function(global, url) { - if(parserOptions.url){ - url = url.trim(); - - if(!url.replace(/\s/g, '').length || !loaderUtils.isUrlRequest(url)) { - return url; - } - if(global) { - return loaderUtils.urlToRequest(url); - } - } - return url; - } - }), - extractImports(), - modulesScope({ - generateScopedName: function generateScopedName (exportName) { - return customGetLocalIdent(options.loaderContext, localIdentName, exportName, { - regExp: localIdentRegExp, - hashPrefix: query.hashPrefix || "", - context: context - }); - } - }), parserPlugin(parserOptions) ]); diff --git a/locals.js b/locals.js deleted file mode 100644 index 2a85707e..00000000 --- a/locals.js +++ /dev/null @@ -1,5 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -module.exports = require("./lib/localsLoader"); diff --git a/package-lock.json b/package-lock.json index 41f1b6f7..25b7dec5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,9 +5,9 @@ "requires": true, "dependencies": { "JSONStream": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.2.tgz", - "integrity": "sha1-wQI3G27Dp887hHygDCC7D85Mbeo=", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.3.tgz", + "integrity": "sha512-3Sp6WZZ/lXl+nTDoGpGWHEpTnnC6X5fnkolYZR6nwIfzbxxvA8utPWe1gCt7i0m9uVGsSz2IS8K8mJ7HmlduMg==", "dev": true, "requires": { "jsonparse": "^1.2.0", @@ -21,9 +21,9 @@ "dev": true }, "acorn": { - "version": "5.5.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.5.3.tgz", - "integrity": "sha512-jd5MkIUlbbmb07nXH0DT3y7rDVtkzDi4XZOUVWAer8ajmF/DTSSbl5oNFyDOl/OXA33Bl79+ypHhl2pN20VeOQ==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.1.tgz", + "integrity": "sha512-d+nbxBUGKg7Arpsvbnlq61mc12ek3EY8EQldM3GPAhWJ1UVxC6TDGbIvUMNU6obBX3i1+ptCIzV4vq0gFPEGVQ==", "dev": true }, "acorn-jsx": { @@ -188,10 +188,16 @@ "js-tokens": "^3.0.2" } }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, "bcrypt-pbkdf": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.1.tgz", - "integrity": "sha1-Y7xdy2EzG5K8Bf1SiVPDNGKgb40=", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", "dev": true, "optional": true, "requires": { @@ -203,15 +209,6 @@ "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" }, - "boom": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/boom/-/boom-4.3.1.tgz", - "integrity": "sha1-T4owBctKfjiJ90kDD9JbluAdLjE=", - "dev": true, - "requires": { - "hoek": "4.x.x" - } - }, "brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", @@ -220,14 +217,6 @@ "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" - }, - "dependencies": { - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - } } }, "browser-stdout": { @@ -237,9 +226,9 @@ "dev": true }, "buffer-from": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.0.0.tgz", - "integrity": "sha512-83apNb8KK0Se60UE1+4Ukbe3HbfELJ6UlI4ldtOGs7So4KD26orJM8hIY9lxdzP+UpItH1Yh/Y8GUvNFWFFRxA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz", + "integrity": "sha512-c5mRlguI/Pe2dSZmpER62rSCu0ryKmWddzRYsuXc50U2/g8jMOulc31VZMa4mYx31U5xsmSOpDCgH88Vl9cDGQ==", "dev": true }, "builtin-modules": { @@ -385,17 +374,17 @@ } }, "color-convert": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.1.tgz", - "integrity": "sha512-mjGanIiwQJskCC18rPR6OmrZ6fm2Lc7PeGFYwCmy5J34wC6F1PzdGL6xeMfmgicfYcNLGuVFA3WzXtIDCQSZxQ==", + "version": "1.9.2", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.2.tgz", + "integrity": "sha512-3NUJZdhMhcdPn8vJ9v2UQJoH0qqoGUkYTgFEPZaPjEtwmmKUfNV46zZmgB2M5M4DCEQHMaCfWHCxiBflLm04Tg==", "requires": { - "color-name": "^1.1.1" + "color-name": "1.1.1" } }, "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha1-SxQVMEz1ACjqgWQ2Q72C6gWANok=" }, "combined-stream": { "version": "1.0.6", @@ -729,26 +718,6 @@ "which": "^1.2.9" } }, - "cryptiles": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-3.1.2.tgz", - "integrity": "sha1-qJ+7Ig9c4l7FboxKqKT9e1sNKf4=", - "dev": true, - "requires": { - "boom": "5.x.x" - }, - "dependencies": { - "boom": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/boom/-/boom-5.2.0.tgz", - "integrity": "sha512-Z5BTk6ZRe4tXXQlkqftmsAUANpXmuwlsF5Oov8ThoMbQRzdGTA1ngYRW160GexgOgjsFOKJz0LYhoNi+2AMBUw==", - "dev": true, - "requires": { - "hoek": "4.x.x" - } - } - } - }, "css-selector-tokenizer": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", @@ -928,18 +897,18 @@ "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" }, "error-ex": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", - "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "requires": { "is-arrayish": "^0.2.1" } }, "es5-ext": { - "version": "0.10.42", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.42.tgz", - "integrity": "sha512-AJxO1rmPe1bDEfSR6TJ/FgMFYuTBhR5R57KW58iCkYACMyFbrkqVyzXSurYoScDGvgyMpk7uRF/lPUPPTmsRSA==", + "version": "0.10.45", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", + "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", "dev": true, "requires": { "es6-iterator": "~2.0.3", @@ -1025,6 +994,12 @@ "source-map": "~0.2.0" }, "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, "estraverse": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-1.9.3.tgz", @@ -1108,9 +1083,9 @@ } }, "esprima": { - "version": "2.7.3", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", - "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", "dev": true }, "esrecurse": { @@ -1569,22 +1544,9 @@ } }, "has-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", - "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", - "dev": true - }, - "hawk": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/hawk/-/hawk-6.0.2.tgz", - "integrity": "sha512-miowhl2+U7Qle4vdLqDdPt9m09K6yZhkLDTWGoUiUzrQCn+mHHSmfJgAyGaLRZbPmTqfFFjRV1QWCW0VWUJBbQ==", - "dev": true, - "requires": { - "boom": "4.x.x", - "cryptiles": "3.x.x", - "hoek": "4.x.x", - "sntp": "2.x.x" - } + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, "he": { "version": "1.1.1", @@ -1592,16 +1554,10 @@ "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=", "dev": true }, - "hoek": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-4.2.1.tgz", - "integrity": "sha512-QLg82fGkfnJ/4iy1xZ81/9SIJiq1NGFUMGs6ParyjBZr6jW2Ufj/snDqTHixNlHdPNwN2RLVD0Pi3igeK9+JfA==", - "dev": true - }, "hosted-git-info": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.0.tgz", - "integrity": "sha512-lIbgIIQA3lz5XaB6vxakj6sDHADJiZadYEJB+FgA+C4nubM1NwcuvUr9EJPmnH1skZqpqUzWborWo8EIUi0Sdw==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, "http-signature": { @@ -1615,71 +1571,18 @@ "sshpk": "^1.7.0" } }, - "icss-replace-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", - "integrity": "sha1-Bupvg2ead0njhs/h/oEq5dsiPe0=" - }, "icss-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", "requires": { "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "postcss": { - "version": "6.0.22", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", - "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "requires": { - "has-flag": "^3.0.0" - } - } } }, "ignore": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.8.tgz", - "integrity": "sha512-pUh+xUQQhQzevjRHHFqqcTy0/dP/kS9I8HSrUydhihjuD09W6ldVWFtIrwhXdUJHis3i2rZNqEHpZH/cbinFbg==", + "version": "3.3.10", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", + "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==", "dev": true }, "imurmurhash": { @@ -1928,6 +1831,12 @@ "wordwrap": "^1.0.0" }, "dependencies": { + "esprima": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-2.7.3.tgz", + "integrity": "sha1-luO3DVd59q1JzQMmc9HDEnZ7pYE=", + "dev": true + }, "glob": { "version": "5.0.15", "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", @@ -1941,6 +1850,12 @@ "path-is-absolute": "^1.0.0" } }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", @@ -1964,13 +1879,13 @@ "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=" }, "js-yaml": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.7.0.tgz", - "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", "dev": true, "requires": { "argparse": "^1.0.7", - "esprima": "^2.6.0" + "esprima": "^4.0.0" } }, "jsbn": { @@ -2261,9 +2176,9 @@ } }, "lru-cache": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.2.tgz", - "integrity": "sha512-wgeVXhrDwAWnIF/yZARsFnMBtdFXOg1b8RIrhilp+0iDYN4mdQcNZElDZ0e4B64BhaxeQ5zN7PMyvu7we1kPeQ==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", "dev": true, "requires": { "pseudomap": "^1.0.2", @@ -2429,6 +2344,12 @@ "path-is-absolute": "^1.0.0" } }, + "has-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-1.0.0.tgz", + "integrity": "sha1-nZ55MWXOAXoA8AQYxD+UKnsdEfo=", + "dev": true + }, "supports-color": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-3.1.2.tgz", @@ -2595,9 +2516,9 @@ "dev": true }, "p-limit": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.2.0.tgz", - "integrity": "sha512-Y/OtIaXtUPr4/YpMv1pCL5L5ed0rumAaAeBSj12F+bSlMdys7i8oQF/GUJmfpTS/QoaRrS/k6pma29haJpsMng==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", "dev": true, "requires": { "p-try": "^1.0.0" @@ -2742,243 +2663,6 @@ "supports-color": "^5.3.0" } }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-modules-extract-imports": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.0.tgz", - "integrity": "sha1-ZhQOzs447wa/DT41XWm/WdFB6oU=", - "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "postcss": { - "version": "6.0.22", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", - "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", - "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "postcss": { - "version": "6.0.22", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", - "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", - "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "postcss": { - "version": "6.0.22", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", - "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "requires": { - "has-flag": "^3.0.0" - } - } - } - }, - "postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", - "requires": { - "icss-replace-symbols": "^1.1.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" - }, - "postcss": { - "version": "6.0.22", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.22.tgz", - "integrity": "sha512-Toc9lLoUASwGqxBSJGTVcOQiDqjK+Z2XlWBg+IgYwQMY9vA2f7iMpXVc1GpPcfTSyM5lkxNo0oDwDRO+wm7XHA==", - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" - }, "supports-color": { "version": "5.4.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", @@ -3031,9 +2715,9 @@ "dev": true }, "qs": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", - "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==", + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==", "dev": true }, "quick-lru": { @@ -3180,9 +2864,9 @@ } }, "regenerate": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.3.3.tgz", - "integrity": "sha512-jVpo1GadrDAK59t/0jRx5VxYWQEDkkEKi6+HjE3joFVLfDOh9Xrdh0dF1eSq+BI/SwvTQ44gSscJ8N5zYL61sg==" + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" }, "regexpu-core": { "version": "1.0.0", @@ -3223,9 +2907,9 @@ } }, "request": { - "version": "2.85.0", - "resolved": "https://registry.npmjs.org/request/-/request-2.85.0.tgz", - "integrity": "sha512-8H7Ehijd4js+s6wuVPLjwORxD4zeuyjYugprdOXlPSqaApmL/QOy+EB/beICHVCHkGMKNh5rvihb5ov+IDw4mg==", + "version": "2.87.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.87.0.tgz", + "integrity": "sha512-fcogkm7Az5bsS6Sl0sibkbhcKsnyon/jV1kF3ajGmF0c8HrttdKTPRT9hieOaQHA5HEq6r8OyWOo/o781C1tNw==", "dev": true, "requires": { "aws-sign2": "~0.7.0", @@ -3236,7 +2920,6 @@ "forever-agent": "~0.6.1", "form-data": "~2.3.1", "har-validator": "~5.0.3", - "hawk": "~6.0.2", "http-signature": "~1.2.0", "is-typedarray": "~1.0.0", "isstream": "~0.1.2", @@ -3246,7 +2929,6 @@ "performance-now": "^2.1.0", "qs": "~6.5.1", "safe-buffer": "^5.1.1", - "stringstream": "~0.0.5", "tough-cookie": "~2.3.3", "tunnel-agent": "^0.6.0", "uuid": "^3.1.0" @@ -3275,9 +2957,9 @@ } }, "resolve": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.7.1.tgz", - "integrity": "sha512-c7rwLofp8g1U+h1KNyHL/jicrKg1Ek4q+Lr33AL65uZTinUZHe30D5HlyN5V9NW0JX1D5dXQ4jqW5l7Sy/kGfw==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", "dev": true, "requires": { "path-parse": "^1.0.5" @@ -3339,6 +3021,12 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, "semver": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", @@ -3443,26 +3131,10 @@ "integrity": "sha1-7b+JA/ZvfOL46v1s7tZeJkyDGzU=", "dev": true }, - "sntp": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/sntp/-/sntp-2.1.0.tgz", - "integrity": "sha512-FL1b58BDrqS3A11lJ0zEdnJ3UOKqVxawAkF3k7F0CVN7VQ34aZrV+G8BZ1WC9ZL7NyrwsW0oviwsWDgRuVYtJg==", - "dev": true, - "requires": { - "hoek": "4.x.x" - } - }, - "source-list-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.0.tgz", - "integrity": "sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A==" - }, "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true, - "optional": true + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, "spdx-correct": { "version": "3.0.0", @@ -3521,9 +3193,9 @@ "dev": true }, "sshpk": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", - "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", + "version": "1.14.2", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.2.tgz", + "integrity": "sha1-xvxhZIo9nE52T9P8306hBeSSupg=", "dev": true, "requires": { "asn1": "~0.2.3", @@ -3533,13 +3205,14 @@ "ecc-jsbn": "~0.1.1", "getpass": "^0.1.1", "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", "tweetnacl": "~0.14.0" } }, "standard-version": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-4.3.0.tgz", - "integrity": "sha512-2UJ2BIUNa7+41PH4FvYicSQED2LCt2RXjmNFis+JZlxZtwzNnGn4uuL8WBUqHoC9b+bJ0AHIAX/bilzm+pGPeA==", + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-4.4.0.tgz", + "integrity": "sha512-jJ8FZhnmh9xJRQLnaXiGRLaAUNItIH29lOQZGpL5fd4+jUHto9Ij6SPCYN86h6ZNNXkYq2TYiIVVF7gVyC+pcQ==", "dev": true, "requires": { "chalk": "^1.1.3", @@ -3715,12 +3388,6 @@ "safe-buffer": "~5.1.0" } }, - "stringstream": { - "version": "0.0.5", - "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", - "integrity": "sha1-TkhM1N5aC7vuGORjB3EKioFiGHg=", - "dev": true - }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -3914,6 +3581,15 @@ "source-map": "~0.5.1", "uglify-to-browserify": "~1.0.0", "yargs": "~3.10.0" + }, + "dependencies": { + "source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", + "dev": true, + "optional": true + } } }, "uglify-to-browserify": { @@ -3945,9 +3621,9 @@ "dev": true }, "uuid": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.2.1.tgz", - "integrity": "sha512-jZnMwlb9Iku/O3smGWvZhauCf6cvvpKi4BKRiliS3cxnI+Gz9j5MEpTz2UFuXiKPJocb7gnsLHwiS05ige5BEA==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", "dev": true }, "validate-npm-package-license": { @@ -3972,9 +3648,9 @@ } }, "which": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, "requires": { "isexe": "^2.0.0" diff --git a/package.json b/package.json index 596a52ab..1ec6667d 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,7 @@ }, "files": [ "lib", - "index.js", - "locals.js" + "index.js" ], "dependencies": { "babel-code-frame": "^6.26.0", @@ -19,12 +18,7 @@ "loader-utils": "^1.0.2", "lodash.camelcase": "^4.3.0", "postcss": "^6.0.23", - "postcss-modules-extract-imports": "^1.2.0", - "postcss-modules-local-by-default": "^1.2.0", - "postcss-modules-scope": "^1.1.0", - "postcss-modules-values": "^1.3.0", - "postcss-value-parser": "^3.3.0", - "source-list-map": "^2.0.0" + "postcss-value-parser": "^3.3.0" }, "devDependencies": { "codecov": "^1.0.1", diff --git a/test/camelCaseTest.js b/test/camelCaseTest.js deleted file mode 100644 index cf4b0dfc..00000000 --- a/test/camelCaseTest.js +++ /dev/null @@ -1,47 +0,0 @@ -/*globals describe */ - -var test = require("./helpers").test; -var testRaw = require("./helpers").testRaw; - -describe("camelCase", function() { - var css = ".btn-info_is-disabled { color: blue; }"; - var cssMultipleDashes = ".btn--info_is-disabled { color: blue; }"; - var mixedCss = ".btn-info_is-disabled { color: blue; } .simple { color: red; }"; - var exports = { - with: [ - [1, "._1L-rnCOXCE_7H94L5XT4uB { color: blue; }", ""] - ], - without: [ - [1, "._1L-rnCOXCE_7H94L5XT4uB { color: blue; }", ""] - ], - dashes: [ - [1, "._1L-rnCOXCE_7H94L5XT4uB { color: blue; }", ""] - ], - multipleDashes: [ - [1, "._3JUlsKrl__OF70Fq391jEw { color: blue; }", ""] - ], - withoutOnly: [ - [1, "._1L-rnCOXCE_7H94L5XT4uB { color: blue; } .KKtodWG-IuEaequFjAsoJ { color: red; }", ""] - ], - dashesOnly: [ - [1, "._1L-rnCOXCE_7H94L5XT4uB { color: blue; } .KKtodWG-IuEaequFjAsoJ { color: red; }", ""] - ] - }; - exports.with.locals = {'btn-info_is-disabled': '_1L-rnCOXCE_7H94L5XT4uB'}; - exports.without.locals = {btnInfoIsDisabled: '_1L-rnCOXCE_7H94L5XT4uB', 'btn-info_is-disabled': '_1L-rnCOXCE_7H94L5XT4uB'}; - exports.dashes.locals = {btnInfo_isDisabled: '_1L-rnCOXCE_7H94L5XT4uB', 'btn-info_is-disabled': '_1L-rnCOXCE_7H94L5XT4uB'}; - exports.multipleDashes.locals = {btnInfo_isDisabled: '_3JUlsKrl__OF70Fq391jEw', 'btn--info_is-disabled': '_3JUlsKrl__OF70Fq391jEw'}; - exports.withoutOnly.locals = {btnInfoIsDisabled: '_1L-rnCOXCE_7H94L5XT4uB', simple: 'KKtodWG-IuEaequFjAsoJ'}; - exports.dashesOnly.locals = {btnInfo_isDisabled: '_1L-rnCOXCE_7H94L5XT4uB', simple: 'KKtodWG-IuEaequFjAsoJ'}; - test("with", css, exports.with, "?modules"); - test("without", css, exports.without, "?modules&camelCase"); - test("dashes", css, exports.dashes, "?modules&camelCase=dashes"); - test("multipleDashes", cssMultipleDashes, exports.multipleDashes, "?modules&camelCase=dashes"); - // Remove this option in v1.0.0 and make the removal of the original classname the default behaviour. See #440. - test("withoutOnly", mixedCss, exports.withoutOnly, "?modules&camelCase=only"); - // Remove this option in v1.0.0 and make the removal of the original classname the default behaviour. See #440. - test("dashesOnly", mixedCss, exports.dashesOnly, "?modules&camelCase=dashesOnly"); - - testRaw("withoutRaw", '.a {}', 'exports.locals = {\n\t"a": "_1buUQJccBRS2-2i27LCoDf"\n};', "?modules&camelCase"); - testRaw("dashesRaw", '.a {}', 'exports.locals = {\n\t"a": "_1buUQJccBRS2-2i27LCoDf"\n};', "?modules&camelCase=dashes"); -}); diff --git a/test/customGetLocalIdentTest.js b/test/customGetLocalIdentTest.js deleted file mode 100644 index ce581497..00000000 --- a/test/customGetLocalIdentTest.js +++ /dev/null @@ -1,19 +0,0 @@ -/*globals describe */ - -var testLocals = require("./helpers").testLocals; - -describe("customGetLocalIdent", function() { - testLocals("should return only locals", - ".abc :local(.def) { color: red; } :local .ghi .jkl { color: blue; }", - { - def: "foo", - ghi: "foo", - jkl: "foo" - }, - { - getLocalIdent: function () { - return 'foo' - } - } - ); -}); diff --git a/test/helpers.js b/test/helpers.js index 61d33d87..d3fa6c84 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -2,7 +2,6 @@ require("should"); var cssLoader = require("../index.js"); -var cssLoaderLocals = require("../locals.js"); var vm = require("vm"); function getEvaluated(output, modules) { @@ -126,18 +125,6 @@ exports.testMap = function test(name, input, map, addOptions, result, modules) { }); }; -exports.testLocals = function testLocals(name, input, result, query, modules) { - it(name, function(done) { - runLoader(cssLoaderLocals, input, undefined, { - query: query - }, function(err, output) { - if(err) return done(err); - assetEvaluated(output, result, modules); - done(); - }); - }); -}; - exports.testSingleItem = function testSingleItem(name, input, result, query, modules) { it(name, function(done) { runLoader(cssLoader, input, undefined, { diff --git a/test/localTest.js b/test/localTest.js deleted file mode 100644 index 34b16ce3..00000000 --- a/test/localTest.js +++ /dev/null @@ -1,212 +0,0 @@ -/*globals describe */ - -var test = require("./helpers").test; - -function testLocal(name, input, result, localsResult, query, modules) { - result.locals = localsResult; - test(name, input, result, query, modules); -} - -describe("local", function() { - testLocal("locals-format", ":local(.test) { background: red; }", [ - [1, ".test-2_pBx { background: red; }", ""] - ], { - test: "test-2_pBx" - }, "?localIdentName=[local]-[hash:base64:5]"); - testLocal("locals", ":local(.className) { background: red; }\n:local(#someId) { background: green; }\n" + - ":local(.className .subClass) { color: green; }\n:local(#someId .subClass) { color: blue; }", [ - [1, "._23J0282swY7bwvI2X4fHiV { background: red; }\n#_3vpqN0v_IxlO3TzQjbpB33 { background: green; }\n" + - "._23J0282swY7bwvI2X4fHiV ._1s1VsToXFz17cPAltMg7jz { color: green; }\n#_3vpqN0v_IxlO3TzQjbpB33 ._1s1VsToXFz17cPAltMg7jz { color: blue; }", ""] - ], { - className: "_23J0282swY7bwvI2X4fHiV", - someId: "_3vpqN0v_IxlO3TzQjbpB33", - subClass: "_1s1VsToXFz17cPAltMg7jz" - }); - testLocal("mode switching", ".c1 :local .c2 .c3 :global .c4 :local .c5, .c6 :local .c7 { background: red; }\n.c8 { background: red; }", [ - [1, ".c1 ._c2 ._c3 .c4 ._c5, .c6 ._c7 { background: red; }\n.c8 { background: red; }", ""] - ], { - c2: "_c2", - c3: "_c3", - c5: "_c5", - c7: "_c7" - }, "?localIdentName=_[local]"); - testLocal("comment in local", ":local(.c1/*.c2*/.c3) { background: red; }", [ - [1, "._c1/*.c2*/._c3 { background: red; }", ""] - ], { - c1: "_c1", - c3: "_c3" - }, "?localIdentName=_[local]"); - testLocal("comment in local", ":local(.c1/*.c2*/.c3) { background: red; }", [ - [1, "._c1/*.c2*/._c3 { background: red; }", ""] - ], { - c1: "_c1", - c3: "_c3" - }, "?localIdentName=_[local]"); - testLocal("strings in local", ":local(.c1[data-attr=\".c2)]'\"]:not(.c3):not(.c4)) { background: red; }", [ - [1, "._c1[data-attr=\".c2)]'\"]:not(._c3):not(._c4) { background: red; }", ""] - ], { - c1: "_c1", - c3: "_c3", - c4: "_c4" - }, "?localIdentName=_[local]"); - - testLocal("composes class simple", ":local(.c1) { a: 1; }\n:local(.c2) { composes: c1; b: 1; }", [ - [1, "._c1 { a: 1; }\n._c2 { b: 1; }", ""] - ], { - c1: "_c1", - c2: "_c2 _c1" - }, "?localIdentName=_[local]"); - testLocal("composes class from module", [ - ":local(.c1) { composes: c2 from \"./module\"; b: 1; }", - ":local(.c3) { composes: c1; b: 3; }", - ":local(.c5) { composes: c2 c4 from \"./module\"; b: 5; }" - ].join("\n"), [ - [2, ".test{c: d}", ""], - [1, [ - "._c1 { b: 1; }", - "._c3 { b: 3; }", - "._c5 { b: 5; }" - ].join("\n"), ""] - ], { - c1: "_c1 imported-c2", - c3: "_c3 _c1 imported-c2", - c5: "_c5 imported-c2 imported-c4" - }, "?localIdentName=_[local]", { - "./module": (function() { - var r = [ - [2, ".test{c: d}", ""] - ]; - r.locals = { - c2: "imported-c2", - c4: "imported-c4" - }; - return r; - }()) - }); - testLocal("composes class with hyphen from module", [ - ":local(.c1) { composes: c-2 from \"./module\"; b: 1; }", - ":local(.c3) { composes: c1; b: 3; }", - ":local(.c5) { composes: c-2 c4 from \"./module\"; b: 5; }" - ].join("\n"), [ - [2, ".test{c: d}", ""], - [1, [ - "._c1 { b: 1; }", - "._c3 { b: 3; }", - "._c5 { b: 5; }" - ].join("\n"), ""] - ], { - c1: "_c1 imported-c-2", - c3: "_c3 _c1 imported-c-2", - c5: "_c5 imported-c-2 imported-c4" - }, "?localIdentName=_[local]", { - "./module": (function() { - var r = [ - [2, ".test{c: d}", ""] - ]; - r.locals = { - "c-2": "imported-c-2", - c4: "imported-c4" - }; - return r; - }()) - }); - testLocal("composes class from module with import", [ - "@import url(\"module\");", - ":local(.c1) { composes: c2 c3 from \"./module\"; composes: c4 from \"./module\"; b: 1; }" - ].join("\n"), [ - [2, ".test{c: d}", ""], - [1, "._c1 { b: 1; }", ""] - ], { - c1: "_c1 imported-c2 imported-c3 imported-c4" - }, "?localIdentName=_[local]", { - "./module": (function() { - var r = [ - [2, ".test{c: d}", ""] - ]; - r.locals = { - c2: "imported-c2", - c3: "imported-c3", - c4: "imported-c4" - }; - return r; - }()) - }); - testLocal("module mode", ".className { background: url(./file.png); }\n#someId { background: url('module/file.jpg'); }\n" + - ".className .subClass { font-size: 5.5pt; }\n#someId .subClass { color: blue; }", [ - [1, "._23J0282swY7bwvI2X4fHiV { background: url({./file.png}); }\n#_3vpqN0v_IxlO3TzQjbpB33 { background: url({module/file.jpg}); }\n" + - "._23J0282swY7bwvI2X4fHiV ._1s1VsToXFz17cPAltMg7jz { font-size: 5.5pt; }\n#_3vpqN0v_IxlO3TzQjbpB33 ._1s1VsToXFz17cPAltMg7jz { color: blue; }", ""] - ], { - className: "_23J0282swY7bwvI2X4fHiV", - someId: "_3vpqN0v_IxlO3TzQjbpB33", - subClass: "_1s1VsToXFz17cPAltMg7jz" - }, "?modules"); - testLocal("class name parsing", ".-a0-34a___f { color: red; }", [ - [1, "._3ZMCqVa1XidxdqbX65hZ5D { color: red; }", ""] - ], { - "-a0-34a___f": "_3ZMCqVa1XidxdqbX65hZ5D" - }, "?modules"); - testLocal("imported values in decl", ".className { color: IMPORTED_NAME; }\n" + - ":import(\"./vars.css\") { IMPORTED_NAME: primary-color; }", [ - [1, "._className { color: red; }", ""] - ], { - "className": "_className" - }, "?modules&localIdentName=_[local]", { - "./vars.css": { - locals: { - "primary-color": "red" - } - } - }); - testLocal("issue-109", ".bar-1 { color: red; }", [ - [1, ".file--bar-1--2JvfJ { color: red; }", ""] - ], { - "bar-1": "file--bar-1--2JvfJ" - }, "?modules&importLoaders=1&localIdentName=[name]--[local]--[hash:base64:5]"); - testLocal("path naming", ".bar { color: red; }", [ - [1, ".path-to--file--bar { color: red; }", ""] - ], { - "bar": "path-to--file--bar" - }, { - query: "?modules&localIdentName=[path]-[name]--[local]", - resourcePath: "/root/path/to/file.css", - options: { - context: "/root/" - } - }); - testLocal("path naming with context", ".bar { color: red; }", [ - [1, ".to--file--bar { color: red; }", ""] - ], { - "bar": "to--file--bar" - }, { - query: "?modules&localIdentName=[path]-[name]--[local]&context=/root/path", - resourcePath: "/root/path/to/file.css", - options: { - context: "/root/" - } - }); - testLocal("hash prefix", ".bar { color: red; }", [ - [1, ".bar--58a3b08b9195a6af0de7431eaf3427c7 { color: red; }", ""] - ], { - "bar": "bar--58a3b08b9195a6af0de7431eaf3427c7" - }, "?modules&localIdentName=[local]--[hash]&hashPrefix=x"); - testLocal("prefixes leading digit with underscore", ":local(.test) { background: red; }", [ - [1, "._1test { background: red; }", ""] - ], { - test: "_1test" - }, "?localIdentName=1[local]"); - testLocal("prefixes leading hyphen + digit with underscore", ":local(.test) { background: red; }", [ - [1, "._-1test { background: red; }", ""] - ], { - test: "_-1test" - }, "?localIdentName=-1[local]"); - testLocal("prefixes two leading hyphens with underscore", ":local(.test) { background: red; }", [ - [1, "._--test { background: red; }", ""] - ], { - test: "_--test" - }, "?localIdentName=--[local]"); - testLocal("saves underscore prefix in exported class names", ":export { _test: _test }", [ - [1, "", ""] - ], { - _test: '_test' - }, "?localIdentName=[local]"); -}); diff --git a/test/localsTest.js b/test/localsTest.js deleted file mode 100644 index a706c2c8..00000000 --- a/test/localsTest.js +++ /dev/null @@ -1,59 +0,0 @@ -/*globals describe */ - -var testLocals = require("./helpers").testLocals; - -describe("locals", function() { - testLocals("should return only locals", - ".abc :local(.def) { color: red; } :local .ghi .jkl { color: blue; }", - { - def: "_def", - ghi: "_ghi", - jkl: "_jkl" - }, - "?localIdentName=_[local]" - ); - testLocals("should return only locals with composing", - ":local(.abc) { color: red; } :local(.def) { composes: abc; background: green; }", - { - abc: "_abc", - def: "_def _abc" - }, - "?localIdentName=_[local]" - ); - testLocals("should return only locals with importing", - ":local(.abc) { composes: def from \"./module.css\"; }", - { - abc: "_abc imported_def imported_ghi" - }, - "?localIdentName=_[local]", - { - "./module.css": { - def: "imported_def imported_ghi", - ghi: "imported_ghi" - } - } - ); - testLocals("should return only locals with importing", - ":local(.abc) { composes: def from \"./module1.css\"; composes: def from \"./module2.css\"; }", - { - abc: "_abc imported_def1 imported_ghi1 imported_def2" - }, - "?localIdentName=_[local]", - { - "./module1.css": { - def: "imported_def1 imported_ghi1", - ghi: "imported_ghi1" - }, - "./module2.css": { - def: "imported_def2" - } - } - ); - testLocals("should not fail on processing a url", - ":local(.abc) { background: url(http://example.com/image.jpg); }", - { - abc: "_abc" - }, - "?localIdentName=_[local]" - ); -}); diff --git a/test/moduleTest.js b/test/moduleTest.js deleted file mode 100644 index 956f543b..00000000 --- a/test/moduleTest.js +++ /dev/null @@ -1,17 +0,0 @@ -/*globals describe */ - -var test = require("./helpers").testSingleItem; - -var path = require("path"); -var fs = require("fs"); -var testCasesPath = path.join(__dirname, "moduleTestCases"); -var testCases = fs.readdirSync(testCasesPath); - -describe("module", function() { - testCases.forEach(function(name) { - var source = fs.readFileSync(path.join(testCasesPath, name, "source.css"), "utf-8"); - var expected = fs.readFileSync(path.join(testCasesPath, name, "expected.css"), "utf-8"); - - test(name, source, expected, "?modules&sourceMap&localIdentName=_[local]_"); - }); -}); diff --git a/test/moduleTestCases/class-names/expected.css b/test/moduleTestCases/class-names/expected.css deleted file mode 100644 index 695a9dc3..00000000 --- a/test/moduleTestCases/class-names/expected.css +++ /dev/null @@ -1,3 +0,0 @@ -._class-1_, ._class-10_ ._bar-1_ { - color: green; -} diff --git a/test/moduleTestCases/class-names/source.css b/test/moduleTestCases/class-names/source.css deleted file mode 100644 index b22e5c34..00000000 --- a/test/moduleTestCases/class-names/source.css +++ /dev/null @@ -1,3 +0,0 @@ -.class-1, .class-10 .bar-1 { - color: green; -} diff --git a/test/moduleTestCases/comments/expected.css b/test/moduleTestCases/comments/expected.css deleted file mode 100644 index 4c9a35f3..00000000 --- a/test/moduleTestCases/comments/expected.css +++ /dev/null @@ -1,11 +0,0 @@ -/* - * a ' above - */ - -._bg_ { - background-image: url({bg.jpg}); -} - -/* - * a ' below - */ \ No newline at end of file diff --git a/test/moduleTestCases/comments/source.css b/test/moduleTestCases/comments/source.css deleted file mode 100644 index 7a0b94f5..00000000 --- a/test/moduleTestCases/comments/source.css +++ /dev/null @@ -1,11 +0,0 @@ -/* - * a ' above - */ - -.bg { - background-image: url(bg.jpg); -} - -/* - * a ' below - */ \ No newline at end of file diff --git a/test/moduleTestCases/keyframes-and-animation/expected.css b/test/moduleTestCases/keyframes-and-animation/expected.css deleted file mode 100644 index fa04fb27..00000000 --- a/test/moduleTestCases/keyframes-and-animation/expected.css +++ /dev/null @@ -1,48 +0,0 @@ -._a_ { - color: green; -} - -@keyframes _bounce_ { - 0% { - transform: translateY(-100%); - opacity: 0; - } - 5% { - transform: translateY(-100%); - opacity: 0; - } -} - -@-webkit-keyframes _bounce2_ { - 0% { - transform: translateY(-100%); - opacity: 0; - } - 5% { - transform: translateY(-100%); - opacity: 0; - } -} - -._bounce_ { - animation-name: _bounce_; - animation: _bounce2_ 1s ease; -} - -._bounce2_ { - color: green; - animation: _bounce_ 1s ease; - animation-name: _bounce2_; -} - -._bounce3_ { - animation: _bounce_ 1s ease, _bounce2_ -} - -._bounce4_ { - animation: _bounce_ 1s ease, _bounce2_; -} - -._b_ { - color: green; -} diff --git a/test/moduleTestCases/keyframes-and-animation/source.css b/test/moduleTestCases/keyframes-and-animation/source.css deleted file mode 100644 index 5aa7d337..00000000 --- a/test/moduleTestCases/keyframes-and-animation/source.css +++ /dev/null @@ -1,48 +0,0 @@ -.a { - color: green; -} - -@keyframes bounce { - 0% { - transform: translateY(-100%); - opacity: 0; - } - 5% { - transform: translateY(-100%); - opacity: 0; - } -} - -@-webkit-keyframes bounce2 { - 0% { - transform: translateY(-100%); - opacity: 0; - } - 5% { - transform: translateY(-100%); - opacity: 0; - } -} - -.bounce { - animation-name: bounce; - animation: bounce2 1s ease; -} - -.bounce2 { - color: green; - animation: bounce 1s ease; - animation-name: bounce2; -} - -.bounce3 { - animation: bounce 1s ease, bounce2 -} - -.bounce4 { - animation: bounce 1s ease, bounce2; -} - -.b { - color: green; -} diff --git a/test/moduleTestCases/leak-scope/expected.css b/test/moduleTestCases/leak-scope/expected.css deleted file mode 100644 index 2d72df97..00000000 --- a/test/moduleTestCases/leak-scope/expected.css +++ /dev/null @@ -1,37 +0,0 @@ -._a_ { - color: green; - animation: _a_; -} - -@keyframes _b_ { - 0% { left: 10px; } - 100% { left: 20px; } -} - -._b_ { - animation: _b_; -} - -@keyframes c { - 0% { left: 10px; } - 100% { left: 20px; } -} - -._c_ { - animation: _c1_; - animation: _c2_, _c3_, _c4_; -} - -@keyframes d { - 0% { left: 10px; } - 100% { left: 20px; } -} - -.d1 { - animation: d1; - animation: d2, d3, d4; -} - -.d2 { - animation: _d2_; -} diff --git a/test/moduleTestCases/leak-scope/source.css b/test/moduleTestCases/leak-scope/source.css deleted file mode 100644 index 586ef5e7..00000000 --- a/test/moduleTestCases/leak-scope/source.css +++ /dev/null @@ -1,37 +0,0 @@ -.a { - color: green; - animation: a; -} - -@keyframes b { - 0% { left: 10px; } - 100% { left: 20px; } -} - -.b { - animation: b; -} - -@keyframes :global(c) { - 0% { left: 10px; } - 100% { left: 20px; } -} - -.c { - animation: c1; - animation: c2, c3, c4; -} - -@keyframes :global(d) { - 0% { left: 10px; } - 100% { left: 20px; } -} - -:global .d1 { - animation: d1; - animation: d2, d3, d4; -} - -:global(.d2) { - animation: d2; -} diff --git a/test/moduleTestCases/simple/expected.css b/test/moduleTestCases/simple/expected.css deleted file mode 100644 index 3f3a1c9d..00000000 --- a/test/moduleTestCases/simple/expected.css +++ /dev/null @@ -1,11 +0,0 @@ -._a_ ._b_, ._c_ ._d_, #_id_ { - color: green; - font-size: 1.5pt; -} -a[href="#b.c"]._x_._y_ { - color: green; - font-size: 1.5pt; -} -@keyframes _z_ { - 2.5% {color: green;} -} diff --git a/test/moduleTestCases/simple/source.css b/test/moduleTestCases/simple/source.css deleted file mode 100644 index e928aaf7..00000000 --- a/test/moduleTestCases/simple/source.css +++ /dev/null @@ -1,11 +0,0 @@ -.a .b, .c .d, #id { - color: green; - font-size: 1.5pt; -} -a[href="#b.c"].x.y { - color: green; - font-size: 1.5pt; -} -@keyframes z { - 2.5% {color: green;} -} diff --git a/test/moduleTestCases/urls/expected.css b/test/moduleTestCases/urls/expected.css deleted file mode 100644 index 9578f0ba..00000000 --- a/test/moduleTestCases/urls/expected.css +++ /dev/null @@ -1,14 +0,0 @@ -._a_ { - background: url({./module}); - background: url({./module}); - background: url("{./module module}"); - background: url("{./module module}"); - background: url({./module}); - background: url({./module}#?iefix); - background: url("#hash"); - background: url("#"); - background: url(data:image/png;base64,AAA); - background: url(http://example.com/image.jpg); - background: url(//example.com/image.png); - background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) url({./module}) xyz; -} diff --git a/test/moduleTestCases/urls/source.css b/test/moduleTestCases/urls/source.css deleted file mode 100644 index 1c58afe7..00000000 --- a/test/moduleTestCases/urls/source.css +++ /dev/null @@ -1,14 +0,0 @@ -.a { - background: url(./module); - background: url("./module"); - background: url("./module module"); - background: url('./module module'); - background: url('./module'); - background: url("./module#?iefix"); - background: url("#hash"); - background: url("#"); - background: url(data:image/png;base64,AAA); - background: url(http://example.com/image.jpg); - background: url(//example.com/image.png); - background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) url(./module) xyz; -} diff --git a/test/moduleTestCases/values/expected.css b/test/moduleTestCases/values/expected.css deleted file mode 100644 index ad85f81a..00000000 --- a/test/moduleTestCases/values/expected.css +++ /dev/null @@ -1,5 +0,0 @@ -._a_ { - background: red; - background: green; - background: red; -} diff --git a/test/moduleTestCases/values/source.css b/test/moduleTestCases/values/source.css deleted file mode 100644 index 27b0fcf6..00000000 --- a/test/moduleTestCases/values/source.css +++ /dev/null @@ -1,9 +0,0 @@ -@value aaa: red; -@value bbb: green; -@value ccc: aaa; - -.a { - background: aaa; - background: bbb; - background: ccc; -} diff --git a/test/urlTest.js b/test/urlTest.js index 7e7ac6c1..19a7ce67 100644 --- a/test/urlTest.js +++ b/test/urlTest.js @@ -74,16 +74,16 @@ describe("url", function() { [1, ".class { background: green url('') xyz }", ""] ]); test("empty url with spaces and quotes", ".class { background: green url(' ') xyz }", [ - [1, ".class { background: green url('') xyz }", ""] + [1, ".class { background: green url(' ') xyz }", ""] ]); test("empty url with newline and quotes", ".class { background: green url('\n') xyz }", [ - [1, ".class { background: green url('') xyz }", ""] + [1, ".class { background: green url('\n') xyz }", ""] ]); test("empty url with CRLF and quotes", ".class { background: green url('\r\n') xyz }", [ - [1, ".class { background: green url('') xyz }", ""] + [1, ".class { background: green url('\r\n') xyz }", ""] ]); test("empty url with tab and quotes", ".class { background: green url('\t') xyz }", [ - [1, ".class { background: green url('') xyz }", ""] + [1, ".class { background: green url('\t') xyz }", ""] ]); test("external absolute url", ".class { background: green url(https://raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", [ [1, ".class { background: green url(https://raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", ""] diff --git a/test/valuesTest.js b/test/valuesTest.js deleted file mode 100644 index 5b77aa54..00000000 --- a/test/valuesTest.js +++ /dev/null @@ -1,120 +0,0 @@ -/*globals describe */ - -var testLocals = require("./helpers").testLocals; -var test = require("./helpers").test; - -function testLocal(name, input, result, localsResult, query, modules) { - result.locals = localsResult; - test(name, input, result, query, modules); -} - -describe("values", function() { - testLocals("should export values", - "@value def: red; @value ghi: 1px solid black", - { - def: "red", - ghi: "1px solid black" - }, - "" - ); - testLocals("should export values and locals", - "@value def: red; .ghi { color: def; }", - { - def: "red", - ghi: "_ghi" - }, - "?modules&localIdentName=_[local]" - ); - testLocal("should import values from other module", - "@value def from './file'; .ghi { color: def; }", [ - [ 2, "", "" ], - [ 1, ".ghi { color: red; }", "" ] - ], { - def: "red" - }, "", { - "./file": (function() { - var a = [[2, "", ""]]; - a.locals = { - def: "red" - }; - return a; - })() - } - ); - testLocal("should import values with renaming", - "@value def as aaa from './file1'; @value def as bbb from './file2'; .ghi { background: aaa, bbb, def; }", [ - [ 2, "", "" ], - [ 3, "", "" ], - [ 1, ".ghi { background: red, green, def; }", "" ] - ], { - aaa: "red", - bbb: "green" - }, "", { - "./file1": (function() { - var a = [[2, "", ""]]; - a.locals = { - def: "red" - }; - return a; - })(), - "./file2": (function() { - var a = [[3, "", ""]]; - a.locals = { - def: "green" - }; - return a; - })() - } - ); - testLocal("should import values contain comma", - "@value color from './file1'; @value shadow: 0 0 color,0 0 color; .ghi { box-shadow: shadow; }", [ - [ 2, "", "" ], - [ 1, ".ghi { box-shadow: 0 0 red,0 0 red; }", "" ] - ], { - color: "red", - shadow: "0 0 red,0 0 red" - }, "", { - "./file1": (function() { - var a = [[2, "", ""]]; - a.locals = { - color: "red", - }; - return a; - })() - } - ); - testLocal("should import values contain comma and space before comma", - "@value color from './file1'; @value shadow: 0 0 color ,0 0 color; .ghi { box-shadow: shadow; }", [ - [ 2, "", "" ], - [ 1, ".ghi { box-shadow: 0 0 red ,0 0 red; }", "" ] - ], { - color: "red", - shadow: "0 0 red ,0 0 red" - }, "", { - "./file1": (function() { - var a = [[2, "", ""]]; - a.locals = { - color: "red", - }; - return a; - })() - } - ); - testLocal("should import values contain tralling comma and space after comma", - "@value color from './file1'; @value shadow: 0 0 color, 0 0 color; .ghi { box-shadow: shadow; }", [ - [ 2, "", "" ], - [ 1, ".ghi { box-shadow: 0 0 red, 0 0 red; }", "" ] - ], { - color: "red", - shadow: "0 0 red, 0 0 red" - }, "", { - "./file1": (function() { - var a = [[2, "", ""]]; - a.locals = { - color: "red", - }; - return a; - })() - } - ); -}); From 09e21c1bcddb6e9e66052d9e94e7c3a36f1c3c7d Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 9 Jul 2018 19:43:01 +0300 Subject: [PATCH 02/45] refactor: `runtime` code --- .eslintrc.yml | 2 +- lib/css-base.js | 76 ------------------------------------- lib/loader.js | 2 +- lib/runtime.js | 91 +++++++++++++++++++++++++++++++++++++++++++++ test/cssBaseTest.js | 16 ++++---- test/helpers.js | 4 +- 6 files changed, 103 insertions(+), 88 deletions(-) delete mode 100644 lib/css-base.js create mode 100644 lib/runtime.js diff --git a/.eslintrc.yml b/.eslintrc.yml index ff314c41..22f85ecd 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -41,7 +41,7 @@ rules: consistent-this: error curly: 'off' default-case: 'off' - dot-location: error + dot-location: 'off' dot-notation: - error - allowKeywords: true diff --git a/lib/css-base.js b/lib/css-base.js deleted file mode 100644 index 59af87df..00000000 --- a/lib/css-base.js +++ /dev/null @@ -1,76 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -// css base code, injected by the css-loader -module.exports = function(useSourceMap) { - var list = []; - - // return the list of modules as css string - list.toString = function toString() { - return this.map(function (item) { - var content = cssWithMappingToString(item, useSourceMap); - if(item[2]) { - return "@media " + item[2] + "{" + content + "}"; - } else { - return content; - } - }).join(""); - }; - - // import a list of modules into the list - list.i = function(modules, mediaQuery) { - if(typeof modules === "string") - modules = [[null, modules, ""]]; - var alreadyImportedModules = {}; - for(var i = 0; i < this.length; i++) { - var id = this[i][0]; - if(typeof id === "number") - alreadyImportedModules[id] = true; - } - for(i = 0; i < modules.length; i++) { - var item = modules[i]; - // skip already imported module - // this implementation is not 100% perfect for weird media query combinations - // when a module is imported multiple times with different media queries. - // I hope this will never occur (Hey this way we have smaller bundles) - if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) { - if(mediaQuery && !item[2]) { - item[2] = mediaQuery; - } else if(mediaQuery) { - item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"; - } - list.push(item); - } - } - }; - return list; -}; - -function cssWithMappingToString(item, useSourceMap) { - var content = item[1] || ''; - var cssMapping = item[3]; - if (!cssMapping) { - return content; - } - - if (useSourceMap && typeof btoa === 'function') { - var sourceMapping = toComment(cssMapping); - var sourceURLs = cssMapping.sources.map(function (source) { - return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */' - }); - - return [content].concat(sourceURLs).concat([sourceMapping]).join('\n'); - } - - return [content].join('\n'); -} - -// Adapted from convert-source-map (MIT) -function toComment(sourceMap) { - // eslint-disable-next-line no-undef - var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))); - var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64; - - return '/*# ' + data + ' */'; -} diff --git a/lib/loader.js b/lib/loader.js index b5a1a681..7f2127fb 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -126,7 +126,7 @@ module.exports = function(content, map) { // embed runtime callback(null, urlEscapeHelper + "exports = module.exports = require(" + - loaderUtils.stringifyRequest(this, require.resolve("./css-base.js")) + + loaderUtils.stringifyRequest(this, require.resolve("./runtime.js")) + ")(" + sourceMap + ");\n" + "// imports\n" + importJs + "\n\n" + diff --git a/lib/runtime.js b/lib/runtime.js new file mode 100644 index 00000000..caba0557 --- /dev/null +++ b/lib/runtime.js @@ -0,0 +1,91 @@ +/* + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra +*/ +// CSS (Loader) Runtime +module.exports = function(useSourceMap) { + const list = []; + + // return the list of modules as css string + list.toString = function toString() { + return this.map(function(item) { + const content = cssWithMappingToString(item, useSourceMap); + + if (item[2]) { + return "@media " + item[2] + "{" + content + "}"; + } + + return content; + }).join(""); + }; + + // import a list of modules into the list + list.i = function(modules, mediaQuery) { + if (typeof modules === "string") { + modules = [[null, modules, ""]]; + } + + const isImported = {}; + + for (let i = 0; i < this.length; i++) { + const id = this[i][0]; + + if (typeof id === "number") { + isImported[id] = true; + } + } + + for (let i = 0; i < modules.length; i++) { + const item = modules[i]; + + // skip already imported module + // this implementation is not 100% perfect for weird media query combinations + // when a module is imported multiple times with different media queries. + // I hope this will never occur (Hey this way we have smaller bundles) + if (typeof item[0] !== "number" || !isImported[item[0]]) { + if (mediaQuery && !item[2]) { + item[2] = mediaQuery; + } else if (mediaQuery) { + item[2] = "(" + item[2] + ") and (" + mediaQuery + ")"; + } + + list.push(item); + } + } + }; + + return list; +}; + +function cssWithMappingToString(item, useSourceMap) { + const content = item[1] || ""; + const sourceMap = item[3]; + + if (!sourceMap) { + return content; + } + + if (useSourceMap && typeof btoa === "function") { + const sourceMapping = toComment(sourceMap); + const sourceURLs = sourceMap.sources.map(function(source) { + return "/*# sourceURL=" + sourceMap.sourceRoot + source + " */"; + }); + + return [content] + .concat(sourceURLs) + .concat([sourceMapping]) + .join("\n"); + } + + return [content].join("\n"); +} + +// Adapted from convert-source-map (MIT) +function toComment(sourceMap) { + // eslint-disable-next-line no-undef + const base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap)))); + const data = + "sourceMappingURL=data:application/json;charset=utf-8;base64," + base64; + + return "/*# " + data + " */"; +} diff --git a/test/cssBaseTest.js b/test/cssBaseTest.js index 01b2a2ee..2dcce709 100644 --- a/test/cssBaseTest.js +++ b/test/cssBaseTest.js @@ -1,8 +1,8 @@ /*eslint-env mocha*/ -var base = require("../lib/css-base"); +var runtime = require("../lib/runtime"); -describe("css-base", function() { +describe("runtime", function() { before(function() { global.btoa = function btoa(str) { var buffer = null; @@ -22,23 +22,23 @@ describe("css-base", function() { }) it("should toString a single module", function() { - var m = base(); + var m = runtime(); m.push([1, "body { a: 1; }", ""]); m.toString().should.be.eql("body { a: 1; }"); }); it("should toString multiple modules", function() { - var m = base(); + var m = runtime(); m.push([2, "body { b: 2; }", ""]); m.push([1, "body { a: 1; }", ""]); m.toString().should.be.eql("body { b: 2; }body { a: 1; }"); }); it("should toString with media query", function() { - var m = base(); + var m = runtime(); m.push([1, "body { a: 1; }", "screen"]); m.toString().should.be.eql("@media screen{body { a: 1; }}"); }); it("should import modules", function() { - var m = base(); + var m = runtime(); var m1 = [1, "body { a: 1; }", "screen"]; var m2 = [2, "body { b: 2; }", ""]; var m3 = [3, "body { c: 3; }", ""]; @@ -53,7 +53,7 @@ describe("css-base", function() { "@media screen{body { a: 1; }}"); }); it("should toString with source mapping", function() { - var m = base(true); + var m = runtime(true); m.push([1, "body { a: 1; }", "", { file: "test.scss", sources: [ @@ -66,7 +66,7 @@ describe("css-base", function() { }); it("should toString without source mapping if btoa not avalibale", function() { global.btoa = null; - var m = base(true); + var m = runtime(true); m.push([1, "body { a: 1; }", "", { file: "test.scss", sources: [ diff --git a/test/helpers.js b/test/helpers.js index d3fa6c84..a5cf822c 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -9,8 +9,8 @@ function getEvaluated(output, modules) { var fn = vm.runInThisContext("(function(module, exports, require) {" + output + "})", "testcase.js"); var m = { exports: {}, id: 1 }; fn(m, m.exports, function(module) { - if(module.indexOf("css-base") >= 0) - return require("../lib/css-base"); + if(module.indexOf("runtime") >= 0) + return require("../lib/runtime"); if(module.indexOf("url/escape") >= 0) return require("../lib/url/escape"); if(module.indexOf("-!/path/css-loader!") === 0) From c012f9b2ff557c1b6beeffb362da4a7e28e84dc4 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 9 Jul 2018 20:10:35 +0300 Subject: [PATCH 03/45] refactor: move `postcss` plugin into own file --- lib/plugin.js | 129 +++++++++++++++++++++++ lib/processCss.js | 254 ++++++++++++---------------------------------- 2 files changed, 194 insertions(+), 189 deletions(-) create mode 100644 lib/plugin.js diff --git a/lib/plugin.js b/lib/plugin.js new file mode 100644 index 00000000..e5275cd7 --- /dev/null +++ b/lib/plugin.js @@ -0,0 +1,129 @@ +var postcss = require("postcss"); +var valueParser = require("postcss-value-parser"); +var Tokenizer = require("css-selector-tokenizer"); +var loaderUtils = require("loader-utils"); +var icssUtils = require("icss-utils"); + +module.exports = postcss.plugin("css-loader-parser", function(options) { + return function(css) { + var imports = {}; + var exports = {}; + var importItems = []; + var urlItems = []; + + function replaceImportsInString(str) { + if (options.import) { + var tokens = valueParser(str); + tokens.walk(function(node) { + if (node.type !== "word") { + return; + } + var token = node.value; + var importIndex = imports["$" + token]; + if (typeof importIndex === "number") { + node.value = "___CSS_LOADER_IMPORT___" + importIndex + "___"; + } + }); + return tokens.toString(); + } + return str; + } + + if (options.import) { + css.walkAtRules(/^import$/i, function(rule) { + var values = Tokenizer.parseValues(rule.params); + var url = values.nodes[0].nodes[0]; + if (url && url.type === "url") { + url = url.url; + } else if (url && url.type === "string") { + url = url.value; + } else throw rule.error("Unexpected format " + rule.params); + if (!url.replace(/\s/g, "").length) { + return; + } + values.nodes[0].nodes.shift(); + var mediaQuery = Tokenizer.stringifyValues(values); + + if (loaderUtils.isUrlRequest(url)) { + url = loaderUtils.urlToRequest(url); + } + + importItems.push({ + url: url, + mediaQuery: mediaQuery + }); + rule.remove(); + }); + } + + var icss = icssUtils.extractICSS(css); + exports = icss.icssExports; + Object.keys(icss.icssImports).forEach(function(key) { + var url = loaderUtils.parseString(key); + Object.keys(icss.icssImports[key]).forEach(function(prop) { + imports["$" + prop] = importItems.length; + importItems.push({ + url: url, + export: icss.icssImports[key][prop] + }); + }); + }); + + Object.keys(exports).forEach(function(exportName) { + exports[exportName] = replaceImportsInString(exports[exportName]); + }); + + function processNode(item) { + switch (item.type) { + case "value": + item.nodes.forEach(processNode); + break; + case "nested-item": + item.nodes.forEach(processNode); + break; + case "item": + var importIndex = imports["$" + item.name]; + if (typeof importIndex === "number") { + item.name = "___CSS_LOADER_IMPORT___" + importIndex + "___"; + } + break; + case "url": + if ( + options.url && + item.url.replace(/\s/g, "").length && + !/^#/.test(item.url) && + loaderUtils.isUrlRequest(item.url) + ) { + // Strip quotes, they will be re-added if the module needs them + item.stringType = ""; + delete item.innerSpacingBefore; + delete item.innerSpacingAfter; + // For backward-compat after dropping css modules + var url = loaderUtils.urlToRequest(item.url.trim()); + item.url = "___CSS_LOADER_URL___" + urlItems.length + "___"; + urlItems.push({ + url: url + }); + } + break; + } + } + + css.walkDecls(function(decl) { + var values = Tokenizer.parseValues(decl.value); + values.nodes.forEach(function(value) { + value.nodes.forEach(processNode); + }); + decl.value = Tokenizer.stringifyValues(values); + }); + css.walkAtRules(function(atrule) { + if (typeof atrule.params === "string") { + atrule.params = replaceImportsInString(atrule.params); + } + }); + + options.importItems = importItems; + options.urlItems = urlItems; + options.exports = exports; + }; +}); diff --git a/lib/processCss.js b/lib/processCss.js index c7c946bc..1ba0334f 100644 --- a/lib/processCss.js +++ b/lib/processCss.js @@ -3,204 +3,80 @@ Author Tobias Koppers @sokra */ var formatCodeFrame = require("babel-code-frame"); -var Tokenizer = require("css-selector-tokenizer"); var postcss = require("postcss"); -var loaderUtils = require("loader-utils"); - -var icssUtils = require('icss-utils'); -var valueParser = require('postcss-value-parser'); - -var parserPlugin = postcss.plugin("css-loader-parser", function(options) { - return function(css) { - var imports = {}; - var exports = {}; - var importItems = []; - var urlItems = []; - - function replaceImportsInString(str) { - if(options.import) { - var tokens = valueParser(str); - tokens.walk(function (node) { - if (node.type !== 'word') { - return; - } - var token = node.value; - var importIndex = imports["$" + token]; - if(typeof importIndex === "number") { - node.value = "___CSS_LOADER_IMPORT___" + importIndex + "___"; - } - }) - return tokens.toString(); - } - return str; - } - - if(options.import) { - css.walkAtRules(/^import$/i, function(rule) { - var values = Tokenizer.parseValues(rule.params); - var url = values.nodes[0].nodes[0]; - if(url && url.type === "url") { - url = url.url; - } else if(url && url.type === "string") { - url = url.value; - } else throw rule.error("Unexpected format " + rule.params); - if (!url.replace(/\s/g, '').length) { - return; - } - values.nodes[0].nodes.shift(); - var mediaQuery = Tokenizer.stringifyValues(values); - - if(loaderUtils.isUrlRequest(url)) { - url = loaderUtils.urlToRequest(url); - } - - importItems.push({ - url: url, - mediaQuery: mediaQuery - }); - rule.remove(); - }); - } - - var icss = icssUtils.extractICSS(css); - exports = icss.icssExports; - Object.keys(icss.icssImports).forEach(function(key) { - var url = loaderUtils.parseString(key); - Object.keys(icss.icssImports[key]).forEach(function(prop) { - imports["$" + prop] = importItems.length; - importItems.push({ - url: url, - export: icss.icssImports[key][prop] - }); - }) - }); - - Object.keys(exports).forEach(function(exportName) { - exports[exportName] = replaceImportsInString(exports[exportName]); - }); - - function processNode(item) { - switch (item.type) { - case "value": - item.nodes.forEach(processNode); - break; - case "nested-item": - item.nodes.forEach(processNode); - break; - case "item": - var importIndex = imports["$" + item.name]; - if (typeof importIndex === "number") { - item.name = "___CSS_LOADER_IMPORT___" + importIndex + "___"; - } - break; - case "url": - if (options.url && item.url.replace(/\s/g, '').length && !/^#/.test(item.url) && loaderUtils.isUrlRequest(item.url)) { - // Strip quotes, they will be re-added if the module needs them - item.stringType = ""; - delete item.innerSpacingBefore; - delete item.innerSpacingAfter; - // For backward-compat after dropping css modules - var url = loaderUtils.urlToRequest(item.url.trim()); - item.url = "___CSS_LOADER_URL___" + urlItems.length + "___"; - urlItems.push({ - url: url - }); - } - break; - } - } - - css.walkDecls(function(decl) { - var values = Tokenizer.parseValues(decl.value); - values.nodes.forEach(function(value) { - value.nodes.forEach(processNode); - }); - decl.value = Tokenizer.stringifyValues(values); - }); - css.walkAtRules(function(atrule) { - if(typeof atrule.params === "string") { - atrule.params = replaceImportsInString(atrule.params); - } - }); - - options.importItems = importItems; - options.urlItems = urlItems; - options.exports = exports; - }; -}); +var plugin = require("./plugin"); module.exports = function processCss(inputSource, inputMap, options, callback) { - var query = options.query; - - var parserOptions = { - url: query.url !== false, - import: query.import !== false, - resolve: options.resolve - }; - - var pipeline = postcss([ - parserPlugin(parserOptions) - ]); - - pipeline.process(inputSource, { - // we need a prefix to avoid path rewriting of PostCSS - from: "/css-loader!" + options.from, - to: options.to, - map: options.sourceMap ? { - prev: inputMap, - sourcesContent: true, - inline: false, - annotation: false - } : null - }).then(function(result) { - callback(null, { - source: result.css, - map: result.map && result.map.toJSON(), - exports: parserOptions.exports, - importItems: parserOptions.importItems, - importItemRegExpG: /___CSS_LOADER_IMPORT___([0-9]+)___/g, - importItemRegExp: /___CSS_LOADER_IMPORT___([0-9]+)___/, - urlItems: parserOptions.urlItems, - urlItemRegExpG: /___CSS_LOADER_URL___([0-9]+)___/g, - urlItemRegExp: /___CSS_LOADER_URL___([0-9]+)___/ - }); - }).catch(function(err) { - if (err.name === 'CssSyntaxError') { - var wrappedError = new CSSLoaderError( - 'Syntax Error', - err.reason, - err.line != null && err.column != null - ? {line: err.line, column: err.column} - : null, - err.input.source - ); - callback(wrappedError); - } else { - callback(err); - } - }); + var query = options.query; + var parserOptions = { + url: query.url !== false, + import: query.import !== false, + resolve: options.resolve + }; + + postcss([plugin(parserOptions)]) + .process(inputSource, { + // we need a prefix to avoid path rewriting of PostCSS + from: "/css-loader!" + options.from, + to: options.to, + map: options.sourceMap + ? { + prev: inputMap, + sourcesContent: true, + inline: false, + annotation: false + } + : null + }) + .then(function(result) { + callback(null, { + source: result.css, + map: result.map && result.map.toJSON(), + exports: parserOptions.exports, + importItems: parserOptions.importItems, + importItemRegExpG: /___CSS_LOADER_IMPORT___([0-9]+)___/g, + importItemRegExp: /___CSS_LOADER_IMPORT___([0-9]+)___/, + urlItems: parserOptions.urlItems, + urlItemRegExpG: /___CSS_LOADER_URL___([0-9]+)___/g, + urlItemRegExp: /___CSS_LOADER_URL___([0-9]+)___/ + }); + }) + .catch(function(err) { + if (err.name === "CssSyntaxError") { + var wrappedError = new CSSLoaderError( + "Syntax Error", + err.reason, + err.line != null && err.column != null + ? { line: err.line, column: err.column } + : null, + err.input.source + ); + callback(wrappedError); + } else { + callback(err); + } + }); }; function formatMessage(message, loc, source) { - var formatted = message; - if (loc) { - formatted = formatted - + ' (' + loc.line + ':' + loc.column + ')'; - } - if (loc && source) { - formatted = formatted - + '\n\n' + formatCodeFrame(source, loc.line, loc.column) + '\n'; - } - return formatted; + var formatted = message; + if (loc) { + formatted = formatted + " (" + loc.line + ":" + loc.column + ")"; + } + if (loc && source) { + formatted = + formatted + "\n\n" + formatCodeFrame(source, loc.line, loc.column) + "\n"; + } + return formatted; } function CSSLoaderError(name, message, loc, source, error) { - Error.call(this); - Error.captureStackTrace(this, CSSLoaderError); - this.name = name; - this.error = error; - this.message = formatMessage(message, loc, source); - this.hideStack = true; + Error.call(this); + Error.captureStackTrace(this, CSSLoaderError); + this.name = name; + this.error = error; + this.message = formatMessage(message, loc, source); + this.hideStack = true; } CSSLoaderError.prototype = Object.create(Error.prototype); From b130031190b290e736d67fd1bc1d051a8da21193 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 9 Jul 2018 20:23:17 +0300 Subject: [PATCH 04/45] refactor: move `CssLoaderError` into own file --- lib/CssLoaderError.js | 27 ++++++++++++++++++++++ lib/processCss.js | 54 ++++++++++++------------------------------- 2 files changed, 42 insertions(+), 39 deletions(-) create mode 100644 lib/CssLoaderError.js diff --git a/lib/CssLoaderError.js b/lib/CssLoaderError.js new file mode 100644 index 00000000..506f9f17 --- /dev/null +++ b/lib/CssLoaderError.js @@ -0,0 +1,27 @@ +var formatCodeFrame = require("babel-code-frame"); + +function formatMessage(message, loc, source) { + var formatted = message; + if (loc) { + formatted = formatted + " (" + loc.line + ":" + loc.column + ")"; + } + if (loc && source) { + formatted = + formatted + "\n\n" + formatCodeFrame(source, loc.line, loc.column) + "\n"; + } + return formatted; +} + +function CssLoaderError(name, message, loc, source, error) { + Error.call(this); + Error.captureStackTrace(this, CssLoaderError); + this.name = name; + this.error = error; + this.message = formatMessage(message, loc, source); + this.hideStack = true; +} + +CssLoaderError.prototype = Object.create(Error.prototype); +CssLoaderError.prototype.constructor = CssLoaderError; + +module.exports = CssLoaderError; diff --git a/lib/processCss.js b/lib/processCss.js index 1ba0334f..470d7e6d 100644 --- a/lib/processCss.js +++ b/lib/processCss.js @@ -2,9 +2,9 @@ MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ -var formatCodeFrame = require("babel-code-frame"); var postcss = require("postcss"); var plugin = require("./plugin"); +var CssLoaderError = require("./CssLoaderError"); module.exports = function processCss(inputSource, inputMap, options, callback) { var query = options.query; @@ -41,43 +41,19 @@ module.exports = function processCss(inputSource, inputMap, options, callback) { urlItemRegExp: /___CSS_LOADER_URL___([0-9]+)___/ }); }) - .catch(function(err) { - if (err.name === "CssSyntaxError") { - var wrappedError = new CSSLoaderError( - "Syntax Error", - err.reason, - err.line != null && err.column != null - ? { line: err.line, column: err.column } - : null, - err.input.source - ); - callback(wrappedError); - } else { - callback(err); - } + .catch(function(error) { + const preparedError = + error.name === "CssSyntaxError" + ? new CssLoaderError( + "Syntax Error", + error.reason, + error.line != null && error.column != null + ? { line: error.line, column: error.column } + : null, + error.input.source + ) + : error; + + callback(preparedError); }); }; - -function formatMessage(message, loc, source) { - var formatted = message; - if (loc) { - formatted = formatted + " (" + loc.line + ":" + loc.column + ")"; - } - if (loc && source) { - formatted = - formatted + "\n\n" + formatCodeFrame(source, loc.line, loc.column) + "\n"; - } - return formatted; -} - -function CSSLoaderError(name, message, loc, source, error) { - Error.call(this); - Error.captureStackTrace(this, CSSLoaderError); - this.name = name; - this.error = error; - this.message = formatMessage(message, loc, source); - this.hideStack = true; -} - -CSSLoaderError.prototype = Object.create(Error.prototype); -CSSLoaderError.prototype.constructor = CSSLoaderError; From d1f80eea8282d5ce4e588b7e4ecd8694bca0c374 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 9 Jul 2018 20:44:39 +0300 Subject: [PATCH 05/45] refactor: merge code from `processCss` with `loader` code --- .eslintrc.yml | 2 +- lib/loader.js | 372 ++++++++++++++++++++++++++++++---------------- lib/processCss.js | 59 -------- 3 files changed, 245 insertions(+), 188 deletions(-) delete mode 100644 lib/processCss.js diff --git a/.eslintrc.yml b/.eslintrc.yml index 22f85ecd..f70ca050 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -38,7 +38,7 @@ rules: - error - never consistent-return: 'off' - consistent-this: error + consistent-this: 'off' curly: 'off' default-case: 'off' dot-location: 'off' diff --git a/lib/loader.js b/lib/loader.js index 7f2127fb..87122c7b 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -3,136 +3,252 @@ Author Tobias Koppers @sokra */ var loaderUtils = require("loader-utils"); -var processCss = require("./processCss"); +var postcss = require("postcss"); +var plugin = require("./plugin"); var getImportPrefix = require("./getImportPrefix"); var compileExports = require("./compile-exports"); - +var CssLoaderError = require("./CssLoaderError"); module.exports = function(content, map) { - var callback = this.async(); - var query = loaderUtils.getOptions(this) || {}; - var camelCaseKeys = query.camelCase; - var sourceMap = query.sourceMap || false; - - if(sourceMap) { - if (map) { - if (typeof map === "string") { - map = JSON.stringify(map); - } - - if (map.sources) { - map.sources = map.sources.map(function (source) { - return source.replace(/\\/g, '/'); - }); - map.sourceRoot = ''; - } - } - } else { - // Some loaders (example `"postcss-loader": "1.x.x"`) always generates source map, we should remove it - map = null; - } - - processCss(content, map, { - from: loaderUtils.getRemainingRequest(this).split("!").pop(), - to: loaderUtils.getCurrentRequest(this).split("!").pop(), - query: query, - loaderContext: this, - sourceMap: sourceMap - }, function(err, result) { - if(err) return callback(err); - - var cssAsString = JSON.stringify(result.source); - - // for importing CSS - var importUrlPrefix = getImportPrefix(this, query); - - var alreadyImported = {}; - var importJs = result.importItems.filter(function(imp) { - if(!imp.mediaQuery) { - if(alreadyImported[imp.url]) - return false; - alreadyImported[imp.url] = true; - } - return true; - }).map(function(imp) { - if(!loaderUtils.isUrlRequest(imp.url)) { - return "exports.push([module.id, " + - JSON.stringify("@import url(" + imp.url + ");") + ", " + - JSON.stringify(imp.mediaQuery) + "]);"; - } else { - var importUrl = importUrlPrefix + imp.url; - return "exports.i(require(" + loaderUtils.stringifyRequest(this, importUrl) + "), " + JSON.stringify(imp.mediaQuery) + ");"; - } - }, this).join("\n"); - - function importItemMatcher(item) { - var match = result.importItemRegExp.exec(item); - var idx = +match[1]; - var importItem = result.importItems[idx]; - var importUrl = importUrlPrefix + importItem.url; - return "\" + require(" + loaderUtils.stringifyRequest(this, importUrl) + ").locals" + - "[" + JSON.stringify(importItem.export) + "] + \""; - } - - cssAsString = cssAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this)); - - // helper for ensuring valid CSS strings from requires - var urlEscapeHelper = ""; - - if(query.url !== false && result.urlItems.length > 0) { - urlEscapeHelper = "var escape = require(" + loaderUtils.stringifyRequest(this, require.resolve("./url/escape.js")) + ");\n"; - - cssAsString = cssAsString.replace(result.urlItemRegExpG, function(item) { - var match = result.urlItemRegExp.exec(item); - var idx = +match[1]; - var urlItem = result.urlItems[idx]; - var url = urlItem.url; - idx = url.indexOf("?#"); - if(idx < 0) idx = url.indexOf("#"); - var urlRequest; - if(idx > 0) { // idx === 0 is catched by isUrlRequest - // in cases like url('webfont.eot?#iefix') - urlRequest = url.substr(0, idx); - return "\" + escape(require(" + loaderUtils.stringifyRequest(this, urlRequest) + ")) + \"" + - url.substr(idx); - } - urlRequest = url; - return "\" + escape(require(" + loaderUtils.stringifyRequest(this, urlRequest) + ")) + \""; - }.bind(this)); - } - - var exportJs = compileExports(result, importItemMatcher.bind(this), camelCaseKeys); - if (exportJs) { - exportJs = "exports.locals = " + exportJs + ";"; - } - - var moduleJs; - if(sourceMap && result.map) { - // add a SourceMap - map = result.map; - if(map.sources) { - map.sources = map.sources.map(function(source) { - return source.split("!").pop().replace(/\\/g, '/'); - }, this); - map.sourceRoot = ""; - } - map.file = map.file.split("!").pop().replace(/\\/g, '/'); - map = JSON.stringify(map); - moduleJs = "exports.push([module.id, " + cssAsString + ", \"\", " + map + "]);"; - } else { - moduleJs = "exports.push([module.id, " + cssAsString + ", \"\"]);"; - } - - // embed runtime - callback(null, urlEscapeHelper + - "exports = module.exports = require(" + - loaderUtils.stringifyRequest(this, require.resolve("./runtime.js")) + - ")(" + sourceMap + ");\n" + - "// imports\n" + - importJs + "\n\n" + - "// module\n" + - moduleJs + "\n\n" + - "// exports\n" + - exportJs); - }.bind(this)); + var callback = this.async(); + var query = loaderUtils.getOptions(this) || {}; + var camelCaseKeys = query.camelCase; + var sourceMap = query.sourceMap || false; + var loaderContext = this; + + if (sourceMap) { + if (map) { + if (typeof map === "string") { + map = JSON.stringify(map); + } + + if (map.sources) { + map.sources = map.sources.map(function(source) { + return source.replace(/\\/g, "/"); + }); + map.sourceRoot = ""; + } + } + } else { + // Some loaders (example `"postcss-loader": "1.x.x"`) always generates source map, we should remove it + map = null; + } + + var parserOptions = { + url: query.url !== false, + import: query.import !== false, + resolve: loaderContext.resolve + }; + + postcss([plugin(parserOptions)]) + .process(content, { + // we need a prefix to avoid path rewriting of PostCSS + from: + "/css-loader!" + + loaderUtils + .getRemainingRequest(loaderContext) + .split("!") + .pop(), + to: loaderUtils + .getCurrentRequest(loaderContext) + .split("!") + .pop(), + map: sourceMap + ? { + prev: map, + sourcesContent: true, + inline: false, + annotation: false + } + : null + }) + .then(function(result) { + var cssAsString = JSON.stringify(result.css); + // for importing CSS + var importUrlPrefix = getImportPrefix(loaderContext, query); + var alreadyImported = {}; + var importItems = parserOptions.importItems; + var importJs = importItems + .filter(function(imp) { + if (!imp.mediaQuery) { + if (alreadyImported[imp.url]) { + return false; + } + + alreadyImported[imp.url] = true; + } + + return true; + }) + .map(function(imp) { + if (!loaderUtils.isUrlRequest(imp.url)) { + return ( + "exports.push([module.id, " + + JSON.stringify("@import url(" + imp.url + ");") + + ", " + + JSON.stringify(imp.mediaQuery) + + "]);" + ); + } + + var importUrl = importUrlPrefix + imp.url; + + return ( + "exports.i(require(" + + loaderUtils.stringifyRequest(this, importUrl) + + "), " + + JSON.stringify(imp.mediaQuery) + + ");" + ); + }) + .join("\n"); + + function importItemMatcher(item) { + var match = /___CSS_LOADER_IMPORT___([0-9]+)___/.exec(item); + var idx = +match[1]; + var importItem = parserOptions.importItems[idx]; + var importUrl = importUrlPrefix + importItem.url; + + return ( + '" + require(' + + loaderUtils.stringifyRequest(this, importUrl) + + ").locals" + + "[" + + JSON.stringify(importItem.export) + + '] + "' + ); + } + + cssAsString = cssAsString.replace( + /___CSS_LOADER_IMPORT___([0-9]+)___/g, + importItemMatcher + ); + + // helper for ensuring valid CSS strings from requires + var urlEscapeHelper = ""; + var urlItems = parserOptions.urlItems; + + if (query.url !== false && urlItems.length > 0) { + urlEscapeHelper = + "var escape = require(" + + loaderUtils.stringifyRequest( + loaderContext, + require.resolve("./url/escape.js") + ) + + ");\n"; + + cssAsString = cssAsString.replace( + /___CSS_LOADER_URL___([0-9]+)___/g, + function(item) { + var match = /___CSS_LOADER_URL___([0-9]+)___/.exec(item); + var idx = +match[1]; + var urlItem = urlItems[idx]; + var url = urlItem.url; + + idx = url.indexOf("?#"); + + if (idx < 0) { + idx = url.indexOf("#"); + } + + var urlRequest; + + if (idx > 0) { + // idx === 0 is catched by isUrlRequest + // in cases like url('webfont.eot?#iefix') + urlRequest = url.substr(0, idx); + + return ( + '" + escape(require(' + + loaderUtils.stringifyRequest(loaderContext, urlRequest) + + ')) + "' + + url.substr(idx) + ); + } + + urlRequest = url; + + return ( + '" + escape(require(' + + loaderUtils.stringifyRequest(loaderContext, urlRequest) + + ')) + "' + ); + } + ); + } + + var exportJs = compileExports( + parserOptions, + importItemMatcher, + camelCaseKeys + ); + + if (exportJs) { + exportJs = "exports.locals = " + exportJs + ";"; + } + + var moduleJs; + + if (sourceMap && result.map) { + // add a SourceMap + map = result.map.toJSON(); + + if (map.sources) { + map.sources = map.sources.map(function(source) { + return source + .split("!") + .pop() + .replace(/\\/g, "/"); + }, loaderContext); + map.sourceRoot = ""; + } + + map.file = map.file + .split("!") + .pop() + .replace(/\\/g, "/"); + map = JSON.stringify(map); + + moduleJs = + "exports.push([module.id, " + cssAsString + ', "", ' + map + "]);"; + } else { + moduleJs = "exports.push([module.id, " + cssAsString + ', ""]);'; + } + + // embed runtime + callback( + null, + urlEscapeHelper + + "exports = module.exports = require(" + + loaderUtils.stringifyRequest( + loaderContext, + require.resolve("./runtime.js") + ) + + ")(" + + sourceMap + + ");\n" + + "// imports\n" + + importJs + + "\n\n" + + "// module\n" + + moduleJs + + "\n\n" + + "// exports\n" + + exportJs + ); + }) + .catch(function(error) { + callback( + error.name === "CssSyntaxError" + ? new CssLoaderError( + "Syntax Error", + error.reason, + error.line != null && error.column != null + ? { line: error.line, column: error.column } + : null, + error.input.source + ) + : error + ); + }); }; diff --git a/lib/processCss.js b/lib/processCss.js deleted file mode 100644 index 470d7e6d..00000000 --- a/lib/processCss.js +++ /dev/null @@ -1,59 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -var postcss = require("postcss"); -var plugin = require("./plugin"); -var CssLoaderError = require("./CssLoaderError"); - -module.exports = function processCss(inputSource, inputMap, options, callback) { - var query = options.query; - var parserOptions = { - url: query.url !== false, - import: query.import !== false, - resolve: options.resolve - }; - - postcss([plugin(parserOptions)]) - .process(inputSource, { - // we need a prefix to avoid path rewriting of PostCSS - from: "/css-loader!" + options.from, - to: options.to, - map: options.sourceMap - ? { - prev: inputMap, - sourcesContent: true, - inline: false, - annotation: false - } - : null - }) - .then(function(result) { - callback(null, { - source: result.css, - map: result.map && result.map.toJSON(), - exports: parserOptions.exports, - importItems: parserOptions.importItems, - importItemRegExpG: /___CSS_LOADER_IMPORT___([0-9]+)___/g, - importItemRegExp: /___CSS_LOADER_IMPORT___([0-9]+)___/, - urlItems: parserOptions.urlItems, - urlItemRegExpG: /___CSS_LOADER_URL___([0-9]+)___/g, - urlItemRegExp: /___CSS_LOADER_URL___([0-9]+)___/ - }); - }) - .catch(function(error) { - const preparedError = - error.name === "CssSyntaxError" - ? new CssLoaderError( - "Syntax Error", - error.reason, - error.line != null && error.column != null - ? { line: error.line, column: error.column } - : null, - error.input.source - ) - : error; - - callback(preparedError); - }); -}; From ebdaf8452cb7dd40cc84251653a6d44b4c6e88c8 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 9 Jul 2018 21:40:36 +0300 Subject: [PATCH 06/45] refactor: drop export locals BREAKING CHANGE: `camelCase` option was removed --- README.md | 32 -------------------------- lib/compile-exports.js | 51 ------------------------------------------ lib/loader.js | 11 +++------ 3 files changed, 3 insertions(+), 91 deletions(-) delete mode 100644 lib/compile-exports.js diff --git a/README.md b/README.md index dade6e33..dcc585f2 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,6 @@ It's useful when you, for instance, need to post process the CSS as a string. |**[`url`](#url)**|`{Boolean}`|`true`| Enable/Disable `url()` handling| |**[`import`](#import)** |`{Boolean}`|`true`| Enable/Disable @import handling| |**[`sourceMap`](#sourcemap)**|`{Boolean}`|`false`|Enable/Disable Sourcemaps| -|**[`camelCase`](#camelcase)**|`{Boolean\|String}`|`false`|Export in CamelCase| |**[`importLoaders`](#importloaders)**|`{Number}`|`0`|Number of loaders applied before CSS loader| ### `url` @@ -139,37 +138,6 @@ They are not enabled by default because they expose a runtime overhead and incre } ``` -### `camelCase` - -By default, the exported JSON keys mirror the class names. If you want to camelize class names (useful in JS), pass the query parameter `camelCase` to css-loader. - -|Name|Type|Description| -|:--:|:--:|:----------| -|**`true`**|`{Boolean}`|Class names will be camelized| -|**`'dashes'`**|`{String}`|Only dashes in class names will be camelized| -|**`'only'`** |`{String}`|Introduced in `0.27.1`. Class names will be camelized, the original class name will be removed from the locals| -|**`'dashesOnly'`**|`{String}`|Introduced in `0.27.1`. Dashes in class names will be camelized, the original class name will be removed from the locals| - -**file.css** -```css -.class-name {} -``` - -**file.js** -```js -import { className } from 'file.css'; -``` - -**webpack.config.js** -```js -{ - loader: 'css-loader', - options: { - camelCase: true - } -} -``` - ### `importLoaders` The query parameter `importLoaders` allows to configure how many loaders before `css-loader` should be applied to `@import`ed resources. diff --git a/lib/compile-exports.js b/lib/compile-exports.js deleted file mode 100644 index 8e14087d..00000000 --- a/lib/compile-exports.js +++ /dev/null @@ -1,51 +0,0 @@ -var camelCase = require("lodash.camelcase"); - -function dashesCamelCase(str) { - return str.replace(/-+(\w)/g, function(match, firstLetter) { - return firstLetter.toUpperCase(); - }); -} - -module.exports = function compileExports(result, importItemMatcher, camelCaseKeys) { - if (!Object.keys(result.exports).length) { - return ""; - } - - var exportJs = Object.keys(result.exports).reduce(function(res, key) { - var valueAsString = JSON.stringify(result.exports[key]); - valueAsString = valueAsString.replace(result.importItemRegExpG, importItemMatcher); - function addEntry(k) { - res.push("\t" + JSON.stringify(k) + ": " + valueAsString); - } - - var targetKey; - switch(camelCaseKeys) { - case true: - addEntry(key); - targetKey = camelCase(key); - if (targetKey !== key) { - addEntry(targetKey); - } - break; - case 'dashes': - addEntry(key); - targetKey = dashesCamelCase(key); - if (targetKey !== key) { - addEntry(targetKey); - } - break; - case 'only': - addEntry(camelCase(key)); - break; - case 'dashesOnly': - addEntry(dashesCamelCase(key)); - break; - default: - addEntry(key); - break; - } - return res; - }, []).join(",\n"); - - return "{\n" + exportJs + "\n}"; -}; diff --git a/lib/loader.js b/lib/loader.js index 87122c7b..0f2994be 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -6,13 +6,11 @@ var loaderUtils = require("loader-utils"); var postcss = require("postcss"); var plugin = require("./plugin"); var getImportPrefix = require("./getImportPrefix"); -var compileExports = require("./compile-exports"); var CssLoaderError = require("./CssLoaderError"); module.exports = function(content, map) { var callback = this.async(); var query = loaderUtils.getOptions(this) || {}; - var camelCaseKeys = query.camelCase; var sourceMap = query.sourceMap || false; var loaderContext = this; @@ -100,7 +98,7 @@ module.exports = function(content, map) { JSON.stringify(imp.mediaQuery) + ");" ); - }) + }, loaderContext) .join("\n"); function importItemMatcher(item) { @@ -177,11 +175,8 @@ module.exports = function(content, map) { ); } - var exportJs = compileExports( - parserOptions, - importItemMatcher, - camelCaseKeys - ); + // Todo need save backward compatibility with old `style-loader` + var exportJs = ""; if (exportJs) { exportJs = "exports.locals = " + exportJs + ";"; From 8150d2be7b077a59b8024172d9267a4aff197da9 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 9 Jul 2018 21:49:29 +0300 Subject: [PATCH 07/45] refactor: drop `icss` utils --- lib/loader.js | 84 ++++++++++++++++++++------------------------------- lib/plugin.js | 50 ------------------------------ 2 files changed, 33 insertions(+), 101 deletions(-) diff --git a/lib/loader.js b/lib/loader.js index 0f2994be..bea62760 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -62,66 +62,48 @@ module.exports = function(content, map) { }) .then(function(result) { var cssAsString = JSON.stringify(result.css); - // for importing CSS - var importUrlPrefix = getImportPrefix(loaderContext, query); - var alreadyImported = {}; var importItems = parserOptions.importItems; - var importJs = importItems - .filter(function(imp) { - if (!imp.mediaQuery) { - if (alreadyImported[imp.url]) { - return false; + + if (query.import !== false && importItems.length > 0) { + var alreadyImported = {}; + var importJs = importItems + .filter(function(imp) { + if (!imp.mediaQuery) { + if (alreadyImported[imp.url]) { + return false; + } + + alreadyImported[imp.url] = true; } - alreadyImported[imp.url] = true; - } + return true; + }) + .map(function(imp) { + if (!loaderUtils.isUrlRequest(imp.url)) { + return ( + "exports.push([module.id, " + + JSON.stringify("@import url(" + imp.url + ");") + + ", " + + JSON.stringify(imp.mediaQuery) + + "]);" + ); + } + + // for importing CSS + var importUrlPrefix = getImportPrefix(loaderContext, query); + var importUrl = importUrlPrefix + imp.url; - return true; - }) - .map(function(imp) { - if (!loaderUtils.isUrlRequest(imp.url)) { return ( - "exports.push([module.id, " + - JSON.stringify("@import url(" + imp.url + ");") + - ", " + + "exports.i(require(" + + loaderUtils.stringifyRequest(this, importUrl) + + "), " + JSON.stringify(imp.mediaQuery) + - "]);" + ");" ); - } - - var importUrl = importUrlPrefix + imp.url; - - return ( - "exports.i(require(" + - loaderUtils.stringifyRequest(this, importUrl) + - "), " + - JSON.stringify(imp.mediaQuery) + - ");" - ); - }, loaderContext) - .join("\n"); - - function importItemMatcher(item) { - var match = /___CSS_LOADER_IMPORT___([0-9]+)___/.exec(item); - var idx = +match[1]; - var importItem = parserOptions.importItems[idx]; - var importUrl = importUrlPrefix + importItem.url; - - return ( - '" + require(' + - loaderUtils.stringifyRequest(this, importUrl) + - ").locals" + - "[" + - JSON.stringify(importItem.export) + - '] + "' - ); + }, loaderContext) + .join("\n"); } - cssAsString = cssAsString.replace( - /___CSS_LOADER_IMPORT___([0-9]+)___/g, - importItemMatcher - ); - // helper for ensuring valid CSS strings from requires var urlEscapeHelper = ""; var urlItems = parserOptions.urlItems; diff --git a/lib/plugin.js b/lib/plugin.js index e5275cd7..623e2900 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -2,33 +2,12 @@ var postcss = require("postcss"); var valueParser = require("postcss-value-parser"); var Tokenizer = require("css-selector-tokenizer"); var loaderUtils = require("loader-utils"); -var icssUtils = require("icss-utils"); module.exports = postcss.plugin("css-loader-parser", function(options) { return function(css) { - var imports = {}; - var exports = {}; var importItems = []; var urlItems = []; - function replaceImportsInString(str) { - if (options.import) { - var tokens = valueParser(str); - tokens.walk(function(node) { - if (node.type !== "word") { - return; - } - var token = node.value; - var importIndex = imports["$" + token]; - if (typeof importIndex === "number") { - node.value = "___CSS_LOADER_IMPORT___" + importIndex + "___"; - } - }); - return tokens.toString(); - } - return str; - } - if (options.import) { css.walkAtRules(/^import$/i, function(rule) { var values = Tokenizer.parseValues(rule.params); @@ -56,23 +35,6 @@ module.exports = postcss.plugin("css-loader-parser", function(options) { }); } - var icss = icssUtils.extractICSS(css); - exports = icss.icssExports; - Object.keys(icss.icssImports).forEach(function(key) { - var url = loaderUtils.parseString(key); - Object.keys(icss.icssImports[key]).forEach(function(prop) { - imports["$" + prop] = importItems.length; - importItems.push({ - url: url, - export: icss.icssImports[key][prop] - }); - }); - }); - - Object.keys(exports).forEach(function(exportName) { - exports[exportName] = replaceImportsInString(exports[exportName]); - }); - function processNode(item) { switch (item.type) { case "value": @@ -81,12 +43,6 @@ module.exports = postcss.plugin("css-loader-parser", function(options) { case "nested-item": item.nodes.forEach(processNode); break; - case "item": - var importIndex = imports["$" + item.name]; - if (typeof importIndex === "number") { - item.name = "___CSS_LOADER_IMPORT___" + importIndex + "___"; - } - break; case "url": if ( options.url && @@ -116,14 +72,8 @@ module.exports = postcss.plugin("css-loader-parser", function(options) { }); decl.value = Tokenizer.stringifyValues(values); }); - css.walkAtRules(function(atrule) { - if (typeof atrule.params === "string") { - atrule.params = replaceImportsInString(atrule.params); - } - }); options.importItems = importItems; options.urlItems = urlItems; - options.exports = exports; }; }); From f95be983155ac398553cb8018c0acdfdd3e570d2 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Mon, 9 Jul 2018 21:51:39 +0300 Subject: [PATCH 08/45] refactor: some stuff --- lib/getImportPrefix.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/getImportPrefix.js b/lib/getImportPrefix.js index 5d3be772..21ddd4f4 100644 --- a/lib/getImportPrefix.js +++ b/lib/getImportPrefix.js @@ -3,12 +3,18 @@ Author Tobias Koppers @sokra */ module.exports = function getImportPrefix(loaderContext, query) { - if(query.importLoaders === false) - return ""; - var importLoaders = parseInt(query.importLoaders, 10) || 0; - var loadersRequest = loaderContext.loaders.slice( - loaderContext.loaderIndex, - loaderContext.loaderIndex + 1 + importLoaders - ).map(function(x) { return x.request; }).join("!"); - return "-!" + loadersRequest + "!"; + if (query.importLoaders === false) { + return ""; + } + + const importLoaders = parseInt(query.importLoaders, 10) || 0; + const loadersRequest = loaderContext.loaders + .slice( + loaderContext.loaderIndex, + loaderContext.loaderIndex + 1 + importLoaders + ) + .map((x) => x.request) + .join("!"); + + return "-!" + loadersRequest + "!"; }; From c81edd4d69098539464168fdbac4af383fcce06b Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 10 Jul 2018 15:37:53 +0300 Subject: [PATCH 09/45] refactor: `url` part of plugin --- lib/plugin.js | 91 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 37 deletions(-) diff --git a/lib/plugin.js b/lib/plugin.js index 623e2900..f23d57be 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -5,23 +5,27 @@ var loaderUtils = require("loader-utils"); module.exports = postcss.plugin("css-loader-parser", function(options) { return function(css) { - var importItems = []; - var urlItems = []; + const importItems = []; + const urlItems = []; if (options.import) { css.walkAtRules(/^import$/i, function(rule) { - var values = Tokenizer.parseValues(rule.params); - var url = values.nodes[0].nodes[0]; + const values = Tokenizer.parseValues(rule.params); + let url = values.nodes[0].nodes[0]; + if (url && url.type === "url") { url = url.url; } else if (url && url.type === "string") { url = url.value; } else throw rule.error("Unexpected format " + rule.params); + if (!url.replace(/\s/g, "").length) { return; } + values.nodes[0].nodes.shift(); - var mediaQuery = Tokenizer.stringifyValues(values); + + const mediaQuery = Tokenizer.stringifyValues(values); if (loaderUtils.isUrlRequest(url)) { url = loaderUtils.urlToRequest(url); @@ -35,43 +39,56 @@ module.exports = postcss.plugin("css-loader-parser", function(options) { }); } - function processNode(item) { - switch (item.type) { - case "value": - item.nodes.forEach(processNode); - break; - case "nested-item": - item.nodes.forEach(processNode); - break; - case "url": - if ( - options.url && - item.url.replace(/\s/g, "").length && - !/^#/.test(item.url) && - loaderUtils.isUrlRequest(item.url) - ) { + if (options.url) { + css.walkDecls(decl => { + if (!decl.value.includes("url(")) { + return decl; + } + + const parsedValue = valueParser(decl.value); + + decl.value = parsedValue + .walk(node => { + if ( + node.type !== "function" || + node.value.toLowerCase() !== "url" || + node.nodes.length === 0 + ) { + return; + } + + const URLNode = node.nodes[0]; + const URLValue = URLNode.value.trim().replace(/\\[\r\n]/, ""); + + // Skip empty URLs + // Empty URL function equals request to current stylesheet where it is declared + if (URLValue.length === 0) { + return; + } + + if (!loaderUtils.isUrlRequest(URLValue)) { + return; + } + + // Remove spaces before and after + node.before = ""; + node.after = ""; + + const requestedURL = loaderUtils.urlToRequest(URLValue); + // Strip quotes, they will be re-added if the module needs them - item.stringType = ""; - delete item.innerSpacingBefore; - delete item.innerSpacingAfter; - // For backward-compat after dropping css modules - var url = loaderUtils.urlToRequest(item.url.trim()); - item.url = "___CSS_LOADER_URL___" + urlItems.length + "___"; + URLNode.quote = ""; + URLNode.value = "___CSS_LOADER_URL___" + urlItems.length + "___"; + urlItems.push({ - url: url + url: requestedURL }); - } - break; - } - } + }) + .toString(); - css.walkDecls(function(decl) { - var values = Tokenizer.parseValues(decl.value); - values.nodes.forEach(function(value) { - value.nodes.forEach(processNode); + return decl; }); - decl.value = Tokenizer.stringifyValues(values); - }); + } options.importItems = importItems; options.urlItems = urlItems; From c49b5da9df97012b36c3567d3d48383cd1970af5 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 10 Jul 2018 16:52:06 +0300 Subject: [PATCH 10/45] refactor: `import` part of plugin --- lib/plugin.js | 50 +++++++---- package-lock.json | 66 -------------- package.json | 3 - test/importTest.js | 215 +++++++++++++++++++++++++++++---------------- 4 files changed, 170 insertions(+), 164 deletions(-) diff --git a/lib/plugin.js b/lib/plugin.js index f23d57be..f2fd0cba 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -1,7 +1,6 @@ -var postcss = require("postcss"); -var valueParser = require("postcss-value-parser"); -var Tokenizer = require("css-selector-tokenizer"); -var loaderUtils = require("loader-utils"); +const postcss = require("postcss"); +const valueParser = require("postcss-value-parser"); +const loaderUtils = require("loader-utils"); module.exports = postcss.plugin("css-loader-parser", function(options) { return function(css) { @@ -10,38 +9,53 @@ module.exports = postcss.plugin("css-loader-parser", function(options) { if (options.import) { css.walkAtRules(/^import$/i, function(rule) { - const values = Tokenizer.parseValues(rule.params); - let url = values.nodes[0].nodes[0]; + const parsedValue = valueParser(rule.params); - if (url && url.type === "url") { - url = url.url; - } else if (url && url.type === "string") { - url = url.value; - } else throw rule.error("Unexpected format " + rule.params); - - if (!url.replace(/\s/g, "").length) { - return; + if (!parsedValue.nodes || !parsedValue.nodes[0]) { + throw rule.error("Unexpected format " + rule.params); } - values.nodes[0].nodes.shift(); + const firstNode = parsedValue.nodes[0]; + + let url = null; + + if ( + firstNode.type === "function" && + firstNode.value.toLowerCase() === "url" + ) { + if (firstNode.nodes[0]) { + firstNode.nodes[0].quote = ""; + } + + url = valueParser.stringify(firstNode.nodes); + } else if (firstNode.type === "string") { + url = firstNode.value; + } - const mediaQuery = Tokenizer.stringifyValues(values); + if (url.replace(/\s/g, "").length === 0) { + return; + } if (loaderUtils.isUrlRequest(url)) { url = loaderUtils.urlToRequest(url); } + const mediaQuery = valueParser + .stringify(parsedValue.nodes.slice(1)) + .trim(); + importItems.push({ url: url, mediaQuery: mediaQuery }); + rule.remove(); }); } if (options.url) { css.walkDecls(decl => { - if (!decl.value.includes("url(")) { + if (!/url\(/i.test(decl.value)) { return decl; } @@ -58,7 +72,7 @@ module.exports = postcss.plugin("css-loader-parser", function(options) { } const URLNode = node.nodes[0]; - const URLValue = URLNode.value.trim().replace(/\\[\r\n]/, ""); + const URLValue = URLNode.value.trim().replace(/\\[\r\n]/g, ""); // Skip empty URLs // Empty URL function equals request to current stylesheet where it is declared diff --git a/package-lock.json b/package-lock.json index 25b7dec5..94bf2809 100644 --- a/package-lock.json +++ b/package-lock.json @@ -718,21 +718,6 @@ "which": "^1.2.9" } }, - "css-selector-tokenizer": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.7.0.tgz", - "integrity": "sha1-5piEdK6MlTR3v15+/s/OzNnPTIY=", - "requires": { - "cssesc": "^0.1.0", - "fastparse": "^1.1.1", - "regexpu-core": "^1.0.0" - } - }, - "cssesc": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-0.1.0.tgz", - "integrity": "sha1-yBSQPkViM3GgR3tAEJqq++6t27Q=" - }, "currently-unhandled": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/currently-unhandled/-/currently-unhandled-0.4.1.tgz", @@ -1178,11 +1163,6 @@ "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", "dev": true }, - "fastparse": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.1.tgz", - "integrity": "sha1-0eJkOzipTXWDtHkGDmxK/8lAcfg=" - }, "figures": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", @@ -1571,14 +1551,6 @@ "sshpk": "^1.7.0" } }, - "icss-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", - "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", - "requires": { - "postcss": "^6.0.1" - } - }, "ignore": { "version": "3.3.10", "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz", @@ -1895,11 +1867,6 @@ "dev": true, "optional": true }, - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=" - }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -2101,11 +2068,6 @@ "integrity": "sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0=", "dev": true }, - "lodash.camelcase": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", - "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" - }, "lodash.create": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/lodash.create/-/lodash.create-3.1.1.tgz", @@ -2863,34 +2825,6 @@ "strip-indent": "^2.0.0" } }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==" - }, - "regexpu-core": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-1.0.0.tgz", - "integrity": "sha1-hqdj9Y7k18L2sQLkdkBQ3n7ZDGs=", - "requires": { - "regenerate": "^1.2.1", - "regjsgen": "^0.2.0", - "regjsparser": "^0.1.4" - } - }, - "regjsgen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", - "integrity": "sha1-bAFq3qxVT3WCP+N6wFuS1aTtsfc=" - }, - "regjsparser": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.1.5.tgz", - "integrity": "sha1-fuj4Tcb6eS0/0K4ijSS9lJ6tIFw=", - "requires": { - "jsesc": "~0.5.0" - } - }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", diff --git a/package.json b/package.json index 1ec6667d..9d0fa844 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,7 @@ ], "dependencies": { "babel-code-frame": "^6.26.0", - "css-selector-tokenizer": "^0.7.0", - "icss-utils": "^2.1.0", "loader-utils": "^1.0.2", - "lodash.camelcase": "^4.3.0", "postcss": "^6.0.23", "postcss-value-parser": "^3.3.0" }, diff --git a/test/importTest.js b/test/importTest.js index f3cdba58..7ce87773 100644 --- a/test/importTest.js +++ b/test/importTest.js @@ -1,85 +1,146 @@ /*globals describe */ -var assert = require('assert'); +var assert = require("assert"); var helpers = require("./helpers"); var test = helpers.test; var testError = helpers.testError; describe("import", function() { - test("import", "@import url(test.css);\n.class { a: b c d; }", [ - [2, ".test{a: b}", ""], - [1, ".class { a: b c d; }", ""] - ], "", { - "./test.css": [[2, ".test{a: b}", ""]] - }); - test("import camelcase", "@IMPORT url(test.css);\n.class { a: b c d; }", [ - [2, ".test{a: b}", ""], - [1, ".class { a: b c d; }", ""] - ], "", { - "./test.css": [[2, ".test{a: b}", ""]] - }); - test("import empty url", "@import url();\n.class { a: b c d; }", [ - [1, "@import url();\n.class { a: b c d; }", ""] - ], ""); - test("import empty url with quotes", "@import url('');\n.class { a: b c d; }", [ - [1, "@import url('');\n.class { a: b c d; }", ""] - ], ""); - test("import with string", "@import \"test.css\";\n.class { a: b c d; }", [ - [2, ".test{a: b}", ""], - [1, ".class { a: b c d; }", ""] - ], "", { - "./test.css": [[2, ".test{a: b}", ""]] - }); - test("import with empty string", "@import \"\";\n.class { a: b c d; }", [ - [1, "@import \"\";\n.class { a: b c d; }", ""] - ], ""); - test("import with string contain spaces", "@import \" \";\n.class { a: b c d; }", [ - [1, "@import \" \";\n.class { a: b c d; }", ""] - ], ""); - test("import with string contain newline", "@import \"\n\";\n.class { a: b c d; }", [ - [1, "@import \"\n\";\n.class { a: b c d; }", ""] - ], ""); - test("import with string contain CRLF", "@import \"\r\n\";\r\n.class { a: b c d; }", [ - [1, "@import \"\r\n\";\r\n.class { a: b c d; }", ""] - ], ""); - test("import with string contain tab", "@import \"\t\";\n.class { a: b c d; }", [ - [1, "@import \"\t\";\n.class { a: b c d; }", ""] - ], ""); - test("import 2", "@import url('test.css');\n.class { a: b c d; }", [ - [2, ".test{a: b}", "screen"], - [1, ".class { a: b c d; }", ""] - ], "", { - "./test.css": [[2, ".test{a: b}", "screen"]] - }); - test("import with media", "@import url('~test/css') screen and print;\n.class { a: b c d; }", [ - [3, ".test{a: b}", "((min-width: 100px)) and (screen and print)"], - [2, ".test{c: d}", "screen and print"], - [1, ".class { a: b c d; }", ""] - ], "", { - "test/css": [ - [3, ".test{a: b}", "(min-width: 100px)"], - [2, ".test{c: d}", ""] - ] - }); - test("import external", "@import url(http://example.com/style.css);\n@import url(\"//example.com/style.css\");", [ - [1, "@import url(http://example.com/style.css);", ""], - [1, "@import url(//example.com/style.css);", ""], - [1, "", ""] - ]); - test("import disabled", "@import url(test.css);\n.class { a: b c d; }", [ - [1, "@import url(test.css);\n.class { a: b c d; }", ""] - ], "?-import"); - test("@import-normalize left untouched", "@import-normalize;", [ - [1, "@import-normalize;", ""] - ]); - testError("@import without url", "@import;", function(err) { - assert.equal(err.message, [ - 'Unexpected format (1:1)', - '', - '> 1 | @import;', - ' | ^', - '', - ].join('\n')) - }) -}) + test( + "import", + "@import url(test.css);\n.class { a: b c d; }", + [[2, ".test{a: b}", ""], [1, ".class { a: b c d; }", ""]], + "", + { + "./test.css": [[2, ".test{a: b}", ""]] + } + ); + test( + "import camelcase", + "@IMPORT url(test.css);\n.class { a: b c d; }", + [[2, ".test{a: b}", ""], [1, ".class { a: b c d; }", ""]], + "", + { + "./test.css": [[2, ".test{a: b}", ""]] + } + ); + test( + "import empty url", + "@import url();\n.class { a: b c d; }", + [[1, "@import url();\n.class { a: b c d; }", ""]], + "" + ); + test( + "import empty url with quotes", + "@import url('');\n.class { a: b c d; }", + [[1, "@import url('');\n.class { a: b c d; }", ""]], + "" + ); + test( + "import with string", + '@import "test.css";\n.class { a: b c d; }', + [[2, ".test{a: b}", ""], [1, ".class { a: b c d; }", ""]], + "", + { + "./test.css": [[2, ".test{a: b}", ""]] + } + ); + test( + "import with empty string", + '@import "";\n.class { a: b c d; }', + [[1, '@import "";\n.class { a: b c d; }', ""]], + "" + ); + test( + "import with string contain spaces", + '@import " ";\n.class { a: b c d; }', + [[1, '@import " ";\n.class { a: b c d; }', ""]], + "" + ); + test( + "import with string contain newline", + '@import "\n";\n.class { a: b c d; }', + [[1, '@import "\n";\n.class { a: b c d; }', ""]], + "" + ); + test( + "import with string contain CRLF", + '@import "\r\n";\r\n.class { a: b c d; }', + [[1, '@import "\r\n";\r\n.class { a: b c d; }', ""]], + "" + ); + test( + "import with string contain tab", + '@import "\t";\n.class { a: b c d; }', + [[1, '@import "\t";\n.class { a: b c d; }', ""]], + "" + ); + test( + "import 2", + "@import url('test.css');\n.class { a: b c d; }", + [[2, ".test{a: b}", "screen"], [1, ".class { a: b c d; }", ""]], + "", + { + "./test.css": [[2, ".test{a: b}", "screen"]] + } + ); + test( + "import with media", + "@import url('~test/css') screen and print;\n.class { a: b c d; }", + [ + [3, ".test{a: b}", "((min-width: 100px)) and (screen and print)"], + [2, ".test{c: d}", "screen and print"], + [1, ".class { a: b c d; }", ""] + ], + "", + { + "test/css": [ + [3, ".test{a: b}", "(min-width: 100px)"], + [2, ".test{c: d}", ""] + ] + } + ); + test( + "import with media without space between url and media", + "@import url('~test/css')screen and print;\n.class { a: b c d; }", + [ + [3, ".test{a: b}", "((min-width: 100px)) and (screen and print)"], + [2, ".test{c: d}", "screen and print"], + [1, ".class { a: b c d; }", ""] + ], + "", + { + "test/css": [ + [3, ".test{a: b}", "(min-width: 100px)"], + [2, ".test{c: d}", ""] + ] + } + ); + test( + "import external", + '@import url(http://example.com/style.css);\n@import url("//example.com/style.css");', + [ + [1, "@import url(http://example.com/style.css);", ""], + [1, "@import url(//example.com/style.css);", ""], + [1, "", ""] + ] + ); + test( + "import disabled", + "@import url(test.css);\n.class { a: b c d; }", + [[1, "@import url(test.css);\n.class { a: b c d; }", ""]], + "?-import" + ); + test("@import-normalize left untouched", "@import-normalize;", [ + [1, "@import-normalize;", ""] + ]); + testError("@import without url", "@import;", function(err) { + assert.equal( + err.message, + ["Unexpected format (1:1)", "", "> 1 | @import;", " | ^", ""].join( + "\n" + ) + ); + }); +}); From 254be6b52622e11e0e107f501d0e9b58c0e62d6f Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 10 Jul 2018 16:59:23 +0300 Subject: [PATCH 11/45] refactor: stuff --- lib/loader.js | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/lib/loader.js b/lib/loader.js index bea62760..c811612e 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -38,19 +38,22 @@ module.exports = function(content, map) { resolve: loaderContext.resolve }; + const from = + "/css-loader!" + + loaderUtils + .getRemainingRequest(loaderContext) + .split("!") + .pop(); + const to = loaderUtils + .getCurrentRequest(loaderContext) + .split("!") + .pop(); + postcss([plugin(parserOptions)]) .process(content, { // we need a prefix to avoid path rewriting of PostCSS - from: - "/css-loader!" + - loaderUtils - .getRemainingRequest(loaderContext) - .split("!") - .pop(), - to: loaderUtils - .getCurrentRequest(loaderContext) - .split("!") - .pop(), + from, + to, map: sourceMap ? { prev: map, From d22c14f228cbf1a3907bc9db10f270bcf04bda9a Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 10 Jul 2018 17:09:51 +0300 Subject: [PATCH 12/45] refactor: escape --- lib/escape.js | 18 ++++++++++++++++++ lib/loader.js | 2 +- lib/url/escape.js | 16 ---------------- test/helpers.js | 4 ++-- 4 files changed, 21 insertions(+), 19 deletions(-) create mode 100644 lib/escape.js delete mode 100644 lib/url/escape.js diff --git a/lib/escape.js b/lib/escape.js new file mode 100644 index 00000000..bc7d0c90 --- /dev/null +++ b/lib/escape.js @@ -0,0 +1,18 @@ +module.exports = function escape(url) { + if (typeof url !== "string") { + return url; + } + + // If url is already wrapped in quotes, remove them + if (/^['"].*['"]$/.test(url)) { + url = url.slice(1, -1); + } + + // Should url be wrapped? + // See https://drafts.csswg.org/css-values-3/#urls + if (/["'() \t\n]/.test(url)) { + return '"' + url.replace(/"/g, '\\"').replace(/\n/g, "\\n") + '"'; + } + + return url; +}; diff --git a/lib/loader.js b/lib/loader.js index c811612e..86b54949 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -116,7 +116,7 @@ module.exports = function(content, map) { "var escape = require(" + loaderUtils.stringifyRequest( loaderContext, - require.resolve("./url/escape.js") + require.resolve("./escape.js") ) + ");\n"; diff --git a/lib/url/escape.js b/lib/url/escape.js deleted file mode 100644 index 25074a6e..00000000 --- a/lib/url/escape.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = function escape(url) { - if (typeof url !== 'string') { - return url - } - // If url is already wrapped in quotes, remove them - if (/^['"].*['"]$/.test(url)) { - url = url.slice(1, -1); - } - // Should url be wrapped? - // See https://drafts.csswg.org/css-values-3/#urls - if (/["'() \t\n]/.test(url)) { - return '"' + url.replace(/"/g, '\\"').replace(/\n/g, '\\n') + '"' - } - - return url -} diff --git a/test/helpers.js b/test/helpers.js index a5cf822c..7ac8e942 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -11,8 +11,8 @@ function getEvaluated(output, modules) { fn(m, m.exports, function(module) { if(module.indexOf("runtime") >= 0) return require("../lib/runtime"); - if(module.indexOf("url/escape") >= 0) - return require("../lib/url/escape"); + if(module.indexOf("escape") >= 0) + return require("../lib/escape"); if(module.indexOf("-!/path/css-loader!") === 0) module = module.substr(19); if(modules && module in modules) From cddbea562ac6349a55ea30368c257be4be0f2fec Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 10 Jul 2018 17:15:43 +0300 Subject: [PATCH 13/45] refactor: rename `escape` to `runtimeEscape` --- lib/loader.js | 8 ++++---- lib/{escape.js => runtimeEscape.js} | 0 test/helpers.js | 7 ++++--- 3 files changed, 8 insertions(+), 7 deletions(-) rename lib/{escape.js => runtimeEscape.js} (100%) diff --git a/lib/loader.js b/lib/loader.js index 86b54949..165b49d9 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -113,10 +113,10 @@ module.exports = function(content, map) { if (query.url !== false && urlItems.length > 0) { urlEscapeHelper = - "var escape = require(" + + "var runtimeEscape = require(" + loaderUtils.stringifyRequest( loaderContext, - require.resolve("./escape.js") + require.resolve("./runtimeEscape.js") ) + ");\n"; @@ -142,7 +142,7 @@ module.exports = function(content, map) { urlRequest = url.substr(0, idx); return ( - '" + escape(require(' + + '" + runtimeEscape(require(' + loaderUtils.stringifyRequest(loaderContext, urlRequest) + ')) + "' + url.substr(idx) @@ -152,7 +152,7 @@ module.exports = function(content, map) { urlRequest = url; return ( - '" + escape(require(' + + '" + runtimeEscape(require(' + loaderUtils.stringifyRequest(loaderContext, urlRequest) + ')) + "' ); diff --git a/lib/escape.js b/lib/runtimeEscape.js similarity index 100% rename from lib/escape.js rename to lib/runtimeEscape.js diff --git a/test/helpers.js b/test/helpers.js index 7ac8e942..137792e0 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -9,10 +9,11 @@ function getEvaluated(output, modules) { var fn = vm.runInThisContext("(function(module, exports, require) {" + output + "})", "testcase.js"); var m = { exports: {}, id: 1 }; fn(m, m.exports, function(module) { - if(module.indexOf("runtime") >= 0) + if(module.indexOf("runtime.js") >= 0) return require("../lib/runtime"); - if(module.indexOf("escape") >= 0) - return require("../lib/escape"); + if(module.indexOf("runtimeEscape.js") >= 0) { + return require("../lib/runtimeEscape"); + } if(module.indexOf("-!/path/css-loader!") === 0) module = module.substr(19); if(modules && module in modules) From 186f5b691a1caed5ca7e094840b977e8a85138f8 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 10 Jul 2018 17:17:39 +0300 Subject: [PATCH 14/45] refactor: `getImportPrefix` --- lib/getImportPrefix.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/getImportPrefix.js b/lib/getImportPrefix.js index 21ddd4f4..f1f01976 100644 --- a/lib/getImportPrefix.js +++ b/lib/getImportPrefix.js @@ -1,6 +1,6 @@ /* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra */ module.exports = function getImportPrefix(loaderContext, query) { if (query.importLoaders === false) { @@ -13,7 +13,7 @@ module.exports = function getImportPrefix(loaderContext, query) { loaderContext.loaderIndex, loaderContext.loaderIndex + 1 + importLoaders ) - .map((x) => x.request) + .map(x => x.request) .join("!"); return "-!" + loadersRequest + "!"; From aa3918a70c34f76031751db73cd5405970e48d30 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 10 Jul 2018 19:27:29 +0300 Subject: [PATCH 15/45] refactor: loader --- lib/loader.js | 170 ++++++++++++++++++++---------------------------- lib/plugin.js | 28 +++++--- test/urlTest.js | 9 +++ 3 files changed, 97 insertions(+), 110 deletions(-) diff --git a/lib/loader.js b/lib/loader.js index 165b49d9..5e4153b5 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -1,57 +1,54 @@ /* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra + MIT License http://www.opensource.org/licenses/mit-license.php + Author Tobias Koppers @sokra */ -var loaderUtils = require("loader-utils"); -var postcss = require("postcss"); -var plugin = require("./plugin"); -var getImportPrefix = require("./getImportPrefix"); -var CssLoaderError = require("./CssLoaderError"); +const loaderUtils = require("loader-utils"); +const postcss = require("postcss"); +const plugin = require("./plugin"); +const getImportPrefix = require("./getImportPrefix"); +const CssLoaderError = require("./CssLoaderError"); module.exports = function(content, map) { - var callback = this.async(); - var query = loaderUtils.getOptions(this) || {}; - var sourceMap = query.sourceMap || false; - var loaderContext = this; - - if (sourceMap) { - if (map) { - if (typeof map === "string") { - map = JSON.stringify(map); - } + const options = loaderUtils.getOptions(this) || {}; - if (map.sources) { - map.sources = map.sources.map(function(source) { - return source.replace(/\\/g, "/"); - }); - map.sourceRoot = ""; - } + // Todo validate options + + const cb = this.async(); + const sourceMap = options.sourceMap; + + var parserOptions = { + url: options.url !== false, + import: options.import !== false + }; + + if (sourceMap && map) { + if (typeof map === "string") { + map = JSON.parse(map); + } + + if (map.sources) { + map.sources = map.sources.map(source => source.replace(/\\/g, "/")); + map.sourceRoot = ""; } } else { // Some loaders (example `"postcss-loader": "1.x.x"`) always generates source map, we should remove it map = null; } - var parserOptions = { - url: query.url !== false, - import: query.import !== false, - resolve: loaderContext.resolve - }; - + // We need a prefix to avoid path rewriting of PostCSS const from = "/css-loader!" + loaderUtils - .getRemainingRequest(loaderContext) + .getRemainingRequest(this) .split("!") .pop(); const to = loaderUtils - .getCurrentRequest(loaderContext) + .getCurrentRequest(this) .split("!") .pop(); postcss([plugin(parserOptions)]) .process(content, { - // we need a prefix to avoid path rewriting of PostCSS from, to, map: sourceMap @@ -63,14 +60,14 @@ module.exports = function(content, map) { } : null }) - .then(function(result) { + .then(result => { var cssAsString = JSON.stringify(result.css); - var importItems = parserOptions.importItems; - if (query.import !== false && importItems.length > 0) { + if (options.import !== false) { var alreadyImported = {}; - var importJs = importItems - .filter(function(imp) { + var importJs = result.messages + .filter(message => message.type === "at-rule-import") + .filter(imp => { if (!imp.mediaQuery) { if (alreadyImported[imp.url]) { return false; @@ -81,7 +78,7 @@ module.exports = function(content, map) { return true; }) - .map(function(imp) { + .map(imp => { if (!loaderUtils.isUrlRequest(imp.url)) { return ( "exports.push([module.id, " + @@ -93,7 +90,7 @@ module.exports = function(content, map) { } // for importing CSS - var importUrlPrefix = getImportPrefix(loaderContext, query); + var importUrlPrefix = getImportPrefix(this, options); var importUrl = importUrlPrefix + imp.url; return ( @@ -103,61 +100,36 @@ module.exports = function(content, map) { JSON.stringify(imp.mediaQuery) + ");" ); - }, loaderContext) + }) .join("\n"); } - // helper for ensuring valid CSS strings from requires - var urlEscapeHelper = ""; - var urlItems = parserOptions.urlItems; + // Helper for ensuring valid CSS strings from requires + let urlEscapeHelper = ""; - if (query.url !== false && urlItems.length > 0) { + if (options.url !== false) { urlEscapeHelper = "var runtimeEscape = require(" + loaderUtils.stringifyRequest( - loaderContext, + this, require.resolve("./runtimeEscape.js") ) + ");\n"; - cssAsString = cssAsString.replace( - /___CSS_LOADER_URL___([0-9]+)___/g, - function(item) { - var match = /___CSS_LOADER_URL___([0-9]+)___/.exec(item); - var idx = +match[1]; - var urlItem = urlItems[idx]; - var url = urlItem.url; - - idx = url.indexOf("?#"); - - if (idx < 0) { - idx = url.indexOf("#"); - } - - var urlRequest; - - if (idx > 0) { - // idx === 0 is catched by isUrlRequest - // in cases like url('webfont.eot?#iefix') - urlRequest = url.substr(0, idx); - - return ( - '" + runtimeEscape(require(' + - loaderUtils.stringifyRequest(loaderContext, urlRequest) + - ')) + "' + - url.substr(idx) - ); - } - - urlRequest = url; - - return ( + result.messages + .filter(message => message.type === "css-loader-import-url") + .forEach(message => { + const { placeholder, url } = message; + const splittedURL = url.split(/(\?)?#/); + const importURLString = '" + runtimeEscape(require(' + - loaderUtils.stringifyRequest(loaderContext, urlRequest) + - ')) + "' - ); - } - ); + loaderUtils.stringifyRequest(this, splittedURL[0]) + + ')) + "' + + (splittedURL[1] ? splittedURL[1] : "") + + (splittedURL[2] ? `#${splittedURL[2]}` : ""); + + cssAsString = cssAsString.replace(placeholder, importURLString); + }); } // Todo need save backward compatibility with old `style-loader` @@ -170,16 +142,15 @@ module.exports = function(content, map) { var moduleJs; if (sourceMap && result.map) { - // add a SourceMap map = result.map.toJSON(); if (map.sources) { - map.sources = map.sources.map(function(source) { - return source + map.sources = map.sources.map(source => + source .split("!") .pop() - .replace(/\\/g, "/"); - }, loaderContext); + .replace(/\\/g, "/") + ); map.sourceRoot = ""; } @@ -196,14 +167,11 @@ module.exports = function(content, map) { } // embed runtime - callback( + cb( null, urlEscapeHelper + "exports = module.exports = require(" + - loaderUtils.stringifyRequest( - loaderContext, - require.resolve("./runtime.js") - ) + + loaderUtils.stringifyRequest(this, require.resolve("./runtime.js")) + ")(" + sourceMap + ");\n" + @@ -217,18 +185,20 @@ module.exports = function(content, map) { exportJs ); }) - .catch(function(error) { - callback( - error.name === "CssSyntaxError" + .catch(err => { + // Todo if (err.file) this.addDependency(err.file) + + cb( + err.name === "CssSyntaxError" ? new CssLoaderError( "Syntax Error", - error.reason, - error.line != null && error.column != null - ? { line: error.line, column: error.column } + err.reason, + err.line != null && err.column != null + ? { line: err.line, column: err.column } : null, - error.input.source + err.input.source ) - : error + : err ); }); }; diff --git a/lib/plugin.js b/lib/plugin.js index f2fd0cba..1632e88c 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -2,11 +2,10 @@ const postcss = require("postcss"); const valueParser = require("postcss-value-parser"); const loaderUtils = require("loader-utils"); -module.exports = postcss.plugin("css-loader-parser", function(options) { - return function(css) { - const importItems = []; - const urlItems = []; +const pluginName = "postcss-css-loader"; +module.exports = postcss.plugin(pluginName, function(options) { + return function(css, result) { if (options.import) { css.walkAtRules(/^import$/i, function(rule) { const parsedValue = valueParser(rule.params); @@ -44,7 +43,9 @@ module.exports = postcss.plugin("css-loader-parser", function(options) { .stringify(parsedValue.nodes.slice(1)) .trim(); - importItems.push({ + result.messages.push({ + pluginName, + type: "at-rule-import", url: url, mediaQuery: mediaQuery }); @@ -54,6 +55,8 @@ module.exports = postcss.plugin("css-loader-parser", function(options) { } if (options.url) { + let index = 0; + css.walkDecls(decl => { if (!/url\(/i.test(decl.value)) { return decl; @@ -89,22 +92,27 @@ module.exports = postcss.plugin("css-loader-parser", function(options) { node.after = ""; const requestedURL = loaderUtils.urlToRequest(URLValue); + const placeholder = "___CSS_LOADER_IMPORT_URL_PLACEHOLDER___" + index + "___"; + URLNode.value = placeholder; // Strip quotes, they will be re-added if the module needs them URLNode.quote = ""; - URLNode.value = "___CSS_LOADER_URL___" + urlItems.length + "___"; - urlItems.push({ + result.messages.push({ + pluginName, + type: "css-loader-import-url", + placeholder: placeholder, url: requestedURL }); + + index++; + + return false; }) .toString(); return decl; }); } - - options.importItems = importItems; - options.urlItems = urlItems; }; }); diff --git a/test/urlTest.js b/test/urlTest.js index 19a7ce67..7c6b5cfe 100644 --- a/test/urlTest.js +++ b/test/urlTest.js @@ -91,6 +91,15 @@ describe("url", function() { test("external schema-less url", ".class { background: green url(//raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", [ [1, ".class { background: green url(//raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", ""] ]); + test("font face with url", "@font-face { src: url('My-Font.woff2') format('woff2') }", [ + [1, "@font-face { src: url({./My-Font.woff2}) format('woff2') }", ""] + ], ""); + test("font face with url and query and fragment identifier", "@font-face { src: url('webfont.eot?#iefix') format('embedded-opentype') }", [ + [1, "@font-face { src: url({./webfont.eot}?#iefix) format('embedded-opentype') }", ""] + ], ""); + test("font face with url and fragment identifier", "@font-face { src: url('webfont.svg#svgFontName') format('svg') }", [ + [1, "@font-face { src: url({./webfont.svg}#svgFontName) format('svg') }", ""] + ], ""); test("module wrapped in spaces", ".class { background: green url(module) xyz }", [ [1, ".class { background: green url(module-wrapped) xyz }", ""] From 7570df9c181e340fd5783367572ef1e849ad9485 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 10 Jul 2018 20:07:47 +0300 Subject: [PATCH 16/45] refactor: tests --- lib/loader.js | 12 +- test/cssBaseTest.js | 150 +++++---- test/helpers.js | 238 +++++++------ test/simpleTest.js | 73 ++-- test/sourceMapTest.js | 467 +++++++++++++++----------- test/urlTest.js | 755 ++++++++++++++++++++++++++++++------------ 6 files changed, 1079 insertions(+), 616 deletions(-) diff --git a/lib/loader.js b/lib/loader.js index 5e4153b5..6810076b 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -16,11 +16,6 @@ module.exports = function(content, map) { const cb = this.async(); const sourceMap = options.sourceMap; - var parserOptions = { - url: options.url !== false, - import: options.import !== false - }; - if (sourceMap && map) { if (typeof map === "string") { map = JSON.parse(map); @@ -47,7 +42,12 @@ module.exports = function(content, map) { .split("!") .pop(); - postcss([plugin(parserOptions)]) + postcss([ + plugin({ + url: options.url !== false, + import: options.import !== false + }) + ]) .process(content, { from, to, diff --git a/test/cssBaseTest.js b/test/cssBaseTest.js index 2dcce709..cefea600 100644 --- a/test/cssBaseTest.js +++ b/test/cssBaseTest.js @@ -3,78 +3,88 @@ var runtime = require("../lib/runtime"); describe("runtime", function() { - before(function() { - global.btoa = function btoa(str) { - var buffer = null; + before(function() { + global.btoa = function btoa(str) { + var buffer = null; - if (str instanceof Buffer) { - buffer = str; - } else { - buffer = new Buffer(str.toString(), 'binary'); - } + if (str instanceof Buffer) { + buffer = str; + } else { + buffer = new Buffer(str.toString(), "binary"); + } - return buffer.toString('base64'); - } - }) + return buffer.toString("base64"); + }; + }); - after(function () { - global.btoa = null; - }) + after(function() { + global.btoa = null; + }); - it("should toString a single module", function() { - var m = runtime(); - m.push([1, "body { a: 1; }", ""]); - m.toString().should.be.eql("body { a: 1; }"); - }); - it("should toString multiple modules", function() { - var m = runtime(); - m.push([2, "body { b: 2; }", ""]); - m.push([1, "body { a: 1; }", ""]); - m.toString().should.be.eql("body { b: 2; }body { a: 1; }"); - }); - it("should toString with media query", function() { - var m = runtime(); - m.push([1, "body { a: 1; }", "screen"]); - m.toString().should.be.eql("@media screen{body { a: 1; }}"); - }); - it("should import modules", function() { - var m = runtime(); - var m1 = [1, "body { a: 1; }", "screen"]; - var m2 = [2, "body { b: 2; }", ""]; - var m3 = [3, "body { c: 3; }", ""]; - var m4 = [4, "body { d: 4; }", ""]; - m.i([m2, m3], ""); - m.i([m2], ""); - m.i([m2, m4], "print"); - m.push(m1); - m.toString().should.be.eql("body { b: 2; }" + - "body { c: 3; }" + - "@media print{body { d: 4; }}" + - "@media screen{body { a: 1; }}"); - }); - it("should toString with source mapping", function() { - var m = runtime(true); - m.push([1, "body { a: 1; }", "", { - file: "test.scss", - sources: [ - './path/to/test.scss' - ], - mappings: "AAAA;", - sourceRoot: "webpack://" - }]); - m.toString().should.be.eql("body { a: 1; }\n/*# sourceURL=webpack://./path/to/test.scss */\n/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC5zY3NzIiwic291cmNlcyI6WyIuL3BhdGgvdG8vdGVzdC5zY3NzIl0sIm1hcHBpbmdzIjoiQUFBQTsiLCJzb3VyY2VSb290Ijoid2VicGFjazovLyJ9 */"); - }); - it("should toString without source mapping if btoa not avalibale", function() { - global.btoa = null; - var m = runtime(true); - m.push([1, "body { a: 1; }", "", { - file: "test.scss", - sources: [ - './path/to/test.scss' - ], - mappings: "AAAA;", - sourceRoot: "webpack://" - }]); - m.toString().should.be.eql("body { a: 1; }"); - }); + it("should toString a single module", function() { + var m = runtime(); + m.push([1, "body { a: 1; }", ""]); + m.toString().should.be.eql("body { a: 1; }"); + }); + it("should toString multiple modules", function() { + var m = runtime(); + m.push([2, "body { b: 2; }", ""]); + m.push([1, "body { a: 1; }", ""]); + m.toString().should.be.eql("body { b: 2; }body { a: 1; }"); + }); + it("should toString with media query", function() { + var m = runtime(); + m.push([1, "body { a: 1; }", "screen"]); + m.toString().should.be.eql("@media screen{body { a: 1; }}"); + }); + it("should import modules", function() { + var m = runtime(); + var m1 = [1, "body { a: 1; }", "screen"]; + var m2 = [2, "body { b: 2; }", ""]; + var m3 = [3, "body { c: 3; }", ""]; + var m4 = [4, "body { d: 4; }", ""]; + m.i([m2, m3], ""); + m.i([m2], ""); + m.i([m2, m4], "print"); + m.push(m1); + m.toString().should.be.eql( + "body { b: 2; }" + + "body { c: 3; }" + + "@media print{body { d: 4; }}" + + "@media screen{body { a: 1; }}" + ); + }); + it("should toString with source mapping", function() { + var m = runtime(true); + m.push([ + 1, + "body { a: 1; }", + "", + { + file: "test.scss", + sources: ["./path/to/test.scss"], + mappings: "AAAA;", + sourceRoot: "webpack://" + } + ]); + m.toString().should.be.eql( + "body { a: 1; }\n/*# sourceURL=webpack://./path/to/test.scss */\n/*# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJmaWxlIjoidGVzdC5zY3NzIiwic291cmNlcyI6WyIuL3BhdGgvdG8vdGVzdC5zY3NzIl0sIm1hcHBpbmdzIjoiQUFBQTsiLCJzb3VyY2VSb290Ijoid2VicGFjazovLyJ9 */" + ); + }); + it("should toString without source mapping if btoa not avalibale", function() { + global.btoa = null; + var m = runtime(true); + m.push([ + 1, + "body { a: 1; }", + "", + { + file: "test.scss", + sources: ["./path/to/test.scss"], + mappings: "AAAA;", + sourceRoot: "webpack://" + } + ]); + m.toString().should.be.eql("body { a: 1; }"); + }); }); diff --git a/test/helpers.js b/test/helpers.js index 137792e0..1eb98364 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -5,93 +5,111 @@ var cssLoader = require("../index.js"); var vm = require("vm"); function getEvaluated(output, modules) { - try { - var fn = vm.runInThisContext("(function(module, exports, require) {" + output + "})", "testcase.js"); - var m = { exports: {}, id: 1 }; - fn(m, m.exports, function(module) { - if(module.indexOf("runtime.js") >= 0) - return require("../lib/runtime"); - if(module.indexOf("runtimeEscape.js") >= 0) { + try { + var fn = vm.runInThisContext( + "(function(module, exports, require) {" + output + "})", + "testcase.js" + ); + var m = { exports: {}, id: 1 }; + fn(m, m.exports, function(module) { + if (module.indexOf("runtime.js") >= 0) return require("../lib/runtime"); + if (module.indexOf("runtimeEscape.js") >= 0) { return require("../lib/runtimeEscape"); } - if(module.indexOf("-!/path/css-loader!") === 0) - module = module.substr(19); - if(modules && module in modules) - return modules[module]; - return "{" + module + "}"; - }); - } catch(e) { - console.error(output); // eslint-disable-line no-console - throw e; - } - delete m.exports.toString; - delete m.exports.i; - return m.exports; + if (module.indexOf("-!/path/css-loader!") === 0) + module = module.substr(19); + if (modules && module in modules) return modules[module]; + return "{" + module + "}"; + }); + } catch (e) { + console.error(output); // eslint-disable-line no-console + throw e; + } + delete m.exports.toString; + delete m.exports.i; + return m.exports; } function assetEvaluated(output, result, modules) { - var exports = getEvaluated(output, modules); - exports.should.be.eql(result); + var exports = getEvaluated(output, modules); + exports.should.be.eql(result); } function assertRaw(output, result) { - output.should.containEql(result); + output.should.containEql(result); } function runLoader(loader, input, map, addOptions, callback) { - var opt = { - options: { - context: "" - }, - callback: callback, - async: function() { - return callback; - }, - loaders: [{request: "/path/css-loader"}], - loaderIndex: 0, - context: "", - resource: "test.css", - resourcePath: "test.css", - request: "css-loader!test.css", - emitError: function(message) { - throw new Error(message); - } - }; - Object.keys(addOptions).forEach(function(key) { - opt[key] = addOptions[key]; - }); - loader.call(opt, input, map); + var opt = { + options: { + context: "" + }, + callback: callback, + async: function() { + return callback; + }, + loaders: [{ request: "/path/css-loader" }], + loaderIndex: 0, + context: "", + resource: "test.css", + resourcePath: "test.css", + request: "css-loader!test.css", + emitError: function(message) { + throw new Error(message); + } + }; + Object.keys(addOptions).forEach(function(key) { + opt[key] = addOptions[key]; + }); + loader.call(opt, input, map); } exports.test = function test(name, input, result, query, modules) { - it(name, function(done) { - runLoader(cssLoader, input, undefined, !query || typeof query === "string" ? { - query: query - } : query, function(err, output) { - if(err) return done(err); - assetEvaluated(output, result, modules); - done(); - }); - }); + it(name, function(done) { + runLoader( + cssLoader, + input, + undefined, + !query || typeof query === "string" + ? { + query: query + } + : query, + function(err, output) { + if (err) return done(err); + assetEvaluated(output, result, modules); + done(); + } + ); + }); }; exports.testRaw = function testRaw(name, input, result, query) { - it(name, function(done) { - runLoader(cssLoader, input, undefined, !query || typeof query === "string" ? { - query: query - } : query, function(err, output) { - if(err) return done(err); - assertRaw(output, result); - done(); - }); - }); -} + it(name, function(done) { + runLoader( + cssLoader, + input, + undefined, + !query || typeof query === "string" + ? { + query: query + } + : query, + function(err, output) { + if (err) return done(err); + assertRaw(output, result); + done(); + } + ); + }); +}; exports.testError = function test(name, input, onError) { - it(name, function(done) { - runLoader(cssLoader, input, undefined, {}, function(err, output) { // eslint-disable-line no-unused-vars + it(name, function(done) { + runLoader(cssLoader, input, undefined, {}, function(err, output) { + // eslint-disable-line no-unused-vars if (!err) { - done(new Error('Expected error to be thrown')); + done(new Error("Expected error to be thrown")); } else { try { onError(err); @@ -100,46 +118,64 @@ exports.testError = function test(name, input, onError) { } done(); } - }); - }); + }); + }); }; exports.testWithMap = function test(name, input, map, result, query, modules) { - it(name, function(done) { - runLoader(cssLoader, input, map, { - query: query - }, function(err, output) { - if(err) return done(err); - assetEvaluated(output, result, modules); - done(); - }); - }); + it(name, function(done) { + runLoader( + cssLoader, + input, + map, + { + query: query + }, + function(err, output) { + if (err) return done(err); + assetEvaluated(output, result, modules); + done(); + } + ); + }); }; exports.testMap = function test(name, input, map, addOptions, result, modules) { - it(name, function(done) { - runLoader(cssLoader, input, map, addOptions, function(err, output) { - if(err) return done(err); - assetEvaluated(output, result, modules); - done(); - }); - }); + it(name, function(done) { + runLoader(cssLoader, input, map, addOptions, function(err, output) { + if (err) return done(err); + assetEvaluated(output, result, modules); + done(); + }); + }); }; -exports.testSingleItem = function testSingleItem(name, input, result, query, modules) { - it(name, function(done) { - runLoader(cssLoader, input, undefined, { - query: query - }, function(err, output) { - if(err) return done(err); - var exports = getEvaluated(output, modules); - Array.isArray(exports).should.be.eql(true); - (exports.length).should.be.eql(1); - (exports[0].length >= 3).should.be.eql(true); - (exports[0][0]).should.be.eql(1); - (exports[0][2]).should.be.eql(""); - (exports[0][1]).should.be.eql(result); - done(); - }); - }); +exports.testSingleItem = function testSingleItem( + name, + input, + result, + query, + modules +) { + it(name, function(done) { + runLoader( + cssLoader, + input, + undefined, + { + query: query + }, + function(err, output) { + if (err) return done(err); + var exports = getEvaluated(output, modules); + Array.isArray(exports).should.be.eql(true); + exports.length.should.be.eql(1); + (exports[0].length >= 3).should.be.eql(true); + exports[0][0].should.be.eql(1); + exports[0][2].should.be.eql(""); + exports[0][1].should.be.eql(result); + done(); + } + ); + }); }; diff --git a/test/simpleTest.js b/test/simpleTest.js index a42ae808..696daf1c 100644 --- a/test/simpleTest.js +++ b/test/simpleTest.js @@ -1,48 +1,45 @@ /*globals describe */ -var assert = require('assert'); +var assert = require("assert"); var test = require("./helpers").test; var testError = require("./helpers").testError; describe("simple", function() { - test("empty", "", [ - [1, "", ""] - ]); - test("simple", ".class { a: b c d; }", [ - [1, ".class { a: b c d; }", ""] - ]); - test("simple2", ".class { a: b c d; }\n.two {}", [ - [1, ".class { a: b c d; }\n.two {}", ""] - ]); - test("escaped selector", ".u-m\\+ { a: b c d; }", [ - [1, ".u-m\\+ { a: b c d; }", ""] - ]); - test("escaped characters (uppercase)", ".class { content: \"\\F10C\" }", [ - [1, ".class { content: \"\\F10C\" }", ""] - ]); - // Need uncomment after resolve https://github.com/css-modules/postcss-modules-local-by-default/issues/108 - /*test("escape characters (lowercase)", ".class { content: \"\\f10C\" }", [ - [1, ".class { content: \"\\f10C\" }", ""] - ]);*/ - // Need uncomment after resolve https://github.com/mathiasbynens/cssesc/issues/10 - /*test("escape characters (two)", ".class { content: \"\\F10C \\F10D\" }", [ - [1, ".class { content: \"\\F10C \\F10D\" }", ""] - ]);*/ - test("charset directive", "@charset \"UTF-8\";\n .class { a: b c d; }", [ - [1, "@charset \"UTF-8\";\n .class { a: b c d; }", ""] - ]); + test("empty", "", [[1, "", ""]]); + test("simple", ".class { a: b c d; }", [[1, ".class { a: b c d; }", ""]]); + test("simple2", ".class { a: b c d; }\n.two {}", [ + [1, ".class { a: b c d; }\n.two {}", ""] + ]); + test("escaped selector", ".u-m\\+ { a: b c d; }", [ + [1, ".u-m\\+ { a: b c d; }", ""] + ]); + test("escaped characters (uppercase)", '.class { content: "\\F10C" }', [ + [1, '.class { content: "\\F10C" }', ""] + ]); + test("escape characters (lowercase)", '.class { content: "\\f10C" }', [ + [1, '.class { content: "\\f10C" }', ""] + ]); + test("escape characters (two)", '.class { content: "\\F10C \\F10D" }', [ + [1, '.class { content: "\\F10C \\F10D" }', ""] + ]); + test("charset directive", '@charset "UTF-8";\n .class { a: b c d; }', [ + [1, '@charset "UTF-8";\n .class { a: b c d; }', ""] + ]); test("custom variables", ":root {--foo: 1px;\n--bar: 2px;}", [ [1, ":root {--foo: 1px;\n--bar: 2px;}", ""] ]); - testError("error formatting", ".some {\n invalid css;\n}", function(err) { - assert.equal(err.message, [ - 'Unknown word (2:2)', - '', - ' 1 | .some {', - '> 2 | invalid css;', - ' | ^', - ' 3 | }', - '', - ].join('\n')); - }); + testError("error formatting", ".some {\n invalid css;\n}", function(err) { + assert.equal( + err.message, + [ + "Unknown word (2:2)", + "", + " 1 | .some {", + "> 2 | invalid css;", + " | ^", + " 3 | }", + "" + ].join("\n") + ); + }); }); diff --git a/test/sourceMapTest.js b/test/sourceMapTest.js index faf7578c..f5adb568 100644 --- a/test/sourceMapTest.js +++ b/test/sourceMapTest.js @@ -4,192 +4,289 @@ var testWithMap = require("./helpers").testWithMap; var testMap = require("./helpers").testMap; describe("source maps", function() { - testWithMap("falsy: null map doesn't cause an error", ".class { a: b c d; }", null, [ - [1, ".class { a: b c d; }", ""] - ]); - testWithMap("falsy: undefined map doesn't cause an error", ".class { a: b c d; }", undefined, [ - [1, ".class { a: b c d; }", ""] - ]); - testWithMap("should don't generate sourceMap when `sourceMap: false` and map exists", - ".class { a: b c d; }", - { - file: 'test.css', - mappings: 'AAAA,SAAS,SAAS,EAAE', - names: [], - sourceRoot: '', - sources: [ '/folder/test.css' ], - sourcesContent: [ '.class { a: b c d; }' ], - version: 3 - }, - [ - [1, ".class { a: b c d; }", ""] - ], - { - sourceMap: false - } - ); - testWithMap("should don't generate sourceMap when `sourceMap: true` and map exists", - ".class { a: b c d; }", - { - file: 'test.css', - mappings: 'AAAA,SAAS,SAAS,EAAE', - names: [], - sourceRoot: '', - sources: [ '/folder/test.css' ], - sourcesContent: [ '.class { a: b c d; }' ], - version: 3 - }, - [ - [1, ".class { a: b c d; }", "", { - file: 'test.css', - mappings: 'AAAA,SAAS,SAAS,EAAE', - names: [], - sourceRoot: '', - sources: [ '/folder/test.css' ], - sourcesContent: [ '.class { a: b c d; }' ], - version: 3 - }] - ], - { - sourceMap: true - } - ); - testWithMap("should don't generate sourceMap when `sourceMap: true` and map exists and string", + testWithMap( + "falsy: null map doesn't cause an error", + ".class { a: b c d; }", + null, + [[1, ".class { a: b c d; }", ""]] + ); + testWithMap( + "falsy: undefined map doesn't cause an error", + ".class { a: b c d; }", + undefined, + [[1, ".class { a: b c d; }", ""]] + ); + testWithMap( + "should don't generate sourceMap when `sourceMap: false` and map exists", + ".class { a: b c d; }", + { + file: "test.css", + mappings: "AAAA,SAAS,SAAS,EAAE", + names: [], + sourceRoot: "", + sources: ["/folder/test.css"], + sourcesContent: [".class { a: b c d; }"], + version: 3 + }, + [[1, ".class { a: b c d; }", ""]], + { + sourceMap: false + } + ); + testWithMap( + "should don't generate sourceMap when `sourceMap: true` and map exists", + ".class { a: b c d; }", + { + file: "test.css", + mappings: "AAAA,SAAS,SAAS,EAAE", + names: [], + sourceRoot: "", + sources: ["/folder/test.css"], + sourcesContent: [".class { a: b c d; }"], + version: 3 + }, + [ + [ + 1, ".class { a: b c d; }", - JSON.stringify({ - file: 'test.css', - mappings: 'AAAA,SAAS,SAAS,EAAE', - names: [], - sourceRoot: '', - sources: [ '/folder/test.css' ], - sourcesContent: [ '.class { a: b c d; }' ], - version: 3 - }), - [ - [1, ".class { a: b c d; }", "", { - file: 'test.css', - mappings: 'AAAA,SAAS,SAAS,EAAE', - names: [], - sourceRoot: '', - sources: [ '/folder/test.css' ], - sourcesContent: [ '.class { a: b c d; }' ], - version: 3 - }] - ], + "", { - sourceMap: true + file: "test.css", + mappings: "AAAA,SAAS,SAAS,EAAE", + names: [], + sourceRoot: "", + sources: ["/folder/test.css"], + sourcesContent: [".class { a: b c d; }"], + version: 3 } - ); - testMap("generate sourceMap (1 loader)", ".class { a: b c d; }", undefined, { - loaders: [{request: "/path/css-loader"}], - resource: "/folder/test.css", - request: "/path/css-loader!/folder/test.css", - query: "?sourceMap" - }, [ - [1, ".class { a: b c d; }", "", { - file: 'test.css', - mappings: 'AAAA,SAAS,SAAS,EAAE', - names: [], - sourceRoot: '', - sources: [ '/folder/test.css' ], - sourcesContent: [ '.class { a: b c d; }' ], - version: 3 - }] - ]); - testMap("generate sourceMap (1 loader, relative)", ".class { a: b c d; }", undefined, { - loaders: [{request: "/path/css-loader"}], - resource: "/folder/test.css", - request: "/path/css-loader!/folder/test.css", - query: "?sourceMap" - }, [ - [1, ".class { a: b c d; }", "", { - file: 'test.css', - mappings: 'AAAA,SAAS,SAAS,EAAE', - names: [], - sourceRoot: '', - sources: [ '/folder/test.css' ], - sourcesContent: [ '.class { a: b c d; }' ], - version: 3 - }] - ]); - testMap("generate sourceMap (1 loader, data url)", ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\"); }", undefined, { - loaders: [{request: "/path/css-loader"}], - resource: "/folder/test.css", - request: "/path/css-loader!/folder/test.css", - query: "?sourceMap" - }, [ - [1, ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\"); }", "", { - file: 'test.css', - mappings: 'AAAA,SAAS,6WAA6W,EAAE', - names: [], - sourceRoot: '', - sources: [ '/folder/test.css' ], - sourcesContent: [ '.class { background-image: url("data:image/svg+xml;charset=utf-8,"); }' ], - version: 3 - }] - ]); - testMap("generate sourceMap (1 loader, encoded data url)", ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%23007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E\"); }", undefined, { - loaders: [{request: "/path/css-loader"}], - resource: "/folder/test.css", - request: "/path/css-loader!/folder/test.css", - query: "?sourceMap" - }, [ - [1, ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%23007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E\"); }", "", { - file: 'test.css', - mappings: 'AAAA,SAAS,mmBAAmmB,EAAE', - names: [], - sourceRoot: '', - sources: [ '/folder/test.css' ], - sourcesContent: [ '.class { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%23007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E"); }' ], - version: 3 - }] - ]); - testMap("generate sourceMap (2 loaders)", ".class { a: b c d; }", undefined, { - loaders: [{request: "/path/css-loader"}, {request: "/path/sass-loader"}], - resource: "/folder/test.scss", - request: "/path/css-loader!/path/sass-loader!/folder/test.scss", - query: "?sourceMap" - }, [ - [1, ".class { a: b c d; }", "", { - file: 'test.scss', - mappings: 'AAAA,SAAS,SAAS,EAAE', - names: [], - sourceRoot: '', - sources: [ '/folder/test.scss' ], - sourcesContent: [ '.class { a: b c d; }' ], - version: 3 - }] - ]); - testMap("generate sourceMap (2 loaders) and map exist", ".class { a: b c d; }", { - file: 'test.scss', - mappings: 'AAAA,SAAS,SAAS,EAAE', - names: [], - sourceRoot: '', - sources: [ '/folder/test.scss' ], - sourcesContent: [ '.class { a: b c d; }' ], - version: 3 - }, { - loaders: [{request: "/path/css-loader"}, {request: "/path/sass-loader"}], - resource: "/folder/test.scss", - request: "/path/css-loader!/path/sass-loader!/folder/test.scss", - query: "?sourceMap" - }, [ - [1, ".class { a: b c d; }", "", { - file: 'test.scss', - mappings: 'AAAA,SAAS,SAAS,EAAE', - names: [], - sourceRoot: '', - sources: [ '/folder/test.scss' ], - sourcesContent: [ '.class { a: b c d; }' ], - version: 3 - }] - ]); - testMap("don't generate sourceMap (1 loader)", ".class { a: b c d; }", undefined, { - loaders: [{request: "/path/css-loader"}], - resource: "/folder/test.css", - request: "/path/css-loader!/folder/test.css", - query: "?sourceMap=false" - }, [ - [1, ".class { a: b c d; }", ""] - ]); + ] + ], + { + sourceMap: true + } + ); + testWithMap( + "should don't generate sourceMap when `sourceMap: true` and map exists and string", + ".class { a: b c d; }", + JSON.stringify({ + file: "test.css", + mappings: "AAAA,SAAS,SAAS,EAAE", + names: [], + sourceRoot: "", + sources: ["/folder/test.css"], + sourcesContent: [".class { a: b c d; }"], + version: 3 + }), + [ + [ + 1, + ".class { a: b c d; }", + "", + { + file: "test.css", + mappings: "AAAA,SAAS,SAAS,EAAE", + names: [], + sourceRoot: "", + sources: ["/folder/test.css"], + sourcesContent: [".class { a: b c d; }"], + version: 3 + } + ] + ], + { + sourceMap: true + } + ); + testMap( + "generate sourceMap (1 loader)", + ".class { a: b c d; }", + undefined, + { + loaders: [{ request: "/path/css-loader" }], + resource: "/folder/test.css", + request: "/path/css-loader!/folder/test.css", + query: "?sourceMap" + }, + [ + [ + 1, + ".class { a: b c d; }", + "", + { + file: "test.css", + mappings: "AAAA,SAAS,SAAS,EAAE", + names: [], + sourceRoot: "", + sources: ["/folder/test.css"], + sourcesContent: [".class { a: b c d; }"], + version: 3 + } + ] + ] + ); + testMap( + "generate sourceMap (1 loader, relative)", + ".class { a: b c d; }", + undefined, + { + loaders: [{ request: "/path/css-loader" }], + resource: "/folder/test.css", + request: "/path/css-loader!/folder/test.css", + query: "?sourceMap" + }, + [ + [ + 1, + ".class { a: b c d; }", + "", + { + file: "test.css", + mappings: "AAAA,SAAS,SAAS,EAAE", + names: [], + sourceRoot: "", + sources: ["/folder/test.css"], + sourcesContent: [".class { a: b c d; }"], + version: 3 + } + ] + ] + ); + testMap( + "generate sourceMap (1 loader, data url)", + ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\"); }", + undefined, + { + loaders: [{ request: "/path/css-loader" }], + resource: "/folder/test.css", + request: "/path/css-loader!/folder/test.css", + query: "?sourceMap" + }, + [ + [ + 1, + ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\"); }", + "", + { + file: "test.css", + mappings: "AAAA,SAAS,6WAA6W,EAAE", + names: [], + sourceRoot: "", + sources: ["/folder/test.css"], + sourcesContent: [ + ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\"); }" + ], + version: 3 + } + ] + ] + ); + testMap( + "generate sourceMap (1 loader, encoded data url)", + '.class { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%23007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E"); }', + undefined, + { + loaders: [{ request: "/path/css-loader" }], + resource: "/folder/test.css", + request: "/path/css-loader!/folder/test.css", + query: "?sourceMap" + }, + [ + [ + 1, + '.class { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%23007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E"); }', + "", + { + file: "test.css", + mappings: "AAAA,SAAS,mmBAAmmB,EAAE", + names: [], + sourceRoot: "", + sources: ["/folder/test.css"], + sourcesContent: [ + '.class { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%23007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E"); }' + ], + version: 3 + } + ] + ] + ); + testMap( + "generate sourceMap (2 loaders)", + ".class { a: b c d; }", + undefined, + { + loaders: [ + { request: "/path/css-loader" }, + { request: "/path/sass-loader" } + ], + resource: "/folder/test.scss", + request: "/path/css-loader!/path/sass-loader!/folder/test.scss", + query: "?sourceMap" + }, + [ + [ + 1, + ".class { a: b c d; }", + "", + { + file: "test.scss", + mappings: "AAAA,SAAS,SAAS,EAAE", + names: [], + sourceRoot: "", + sources: ["/folder/test.scss"], + sourcesContent: [".class { a: b c d; }"], + version: 3 + } + ] + ] + ); + testMap( + "generate sourceMap (2 loaders) and map exist", + ".class { a: b c d; }", + { + file: "test.scss", + mappings: "AAAA,SAAS,SAAS,EAAE", + names: [], + sourceRoot: "", + sources: ["/folder/test.scss"], + sourcesContent: [".class { a: b c d; }"], + version: 3 + }, + { + loaders: [ + { request: "/path/css-loader" }, + { request: "/path/sass-loader" } + ], + resource: "/folder/test.scss", + request: "/path/css-loader!/path/sass-loader!/folder/test.scss", + query: "?sourceMap" + }, + [ + [ + 1, + ".class { a: b c d; }", + "", + { + file: "test.scss", + mappings: "AAAA,SAAS,SAAS,EAAE", + names: [], + sourceRoot: "", + sources: ["/folder/test.scss"], + sourcesContent: [".class { a: b c d; }"], + version: 3 + } + ] + ] + ); + testMap( + "don't generate sourceMap (1 loader)", + ".class { a: b c d; }", + undefined, + { + loaders: [{ request: "/path/css-loader" }], + resource: "/folder/test.css", + request: "/path/css-loader!/folder/test.css", + query: "?sourceMap=false" + }, + [[1, ".class { a: b c d; }", ""]] + ); }); diff --git a/test/urlTest.js b/test/urlTest.js index 7c6b5cfe..1d51f720 100644 --- a/test/urlTest.js +++ b/test/urlTest.js @@ -3,221 +3,544 @@ var test = require("./helpers").test; describe("url", function() { - test("background img", ".class { background: green url( \"img.png\" ) xyz }", [ - [1, ".class { background: green url({./img.png}) xyz }", ""] - ]); - test("background img 2", ".class { background: green url(~img/png) url(aaa) xyz }", [ - [1, ".class { background: green url({img/png}) url({./aaa}) xyz }", ""] - ]); - test("background img 3", ".class { background: green url( 'img.png' ) xyz }", [ - [1, ".class { background: green url({./img.png}) xyz }", ""] - ]); - test("background img 4", ".class { background: green url( img.png ) xyz }", [ - [1, ".class { background: green url({./img.png}) xyz }", ""] - ]); - test("background img contain space in name", ".class { background: green url( \"img img.png\" ) xyz }", [ - [1, ".class { background: green url(\"{./img img.png}\") xyz }", ""] - ]); - test("background 2 img contain space in name", ".class { background: green url( 'img img.png' ) xyz }", [ - [1, ".class { background: green url(\"{./img img.png}\") xyz }", ""] - ]); - test("background img absolute", ".class { background: green url(/img.png) xyz }", [ - [1, ".class { background: green url(/img.png) xyz }", ""] - ]); - test("background img external", - ".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", [ - [1, ".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", ""] - ]); - test("background img external data", - ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\") }", [ - [1, ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\") }", ""] - ]); - test("background img external encoded data", - ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%2523007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E\") }", [ - [1, ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%2523007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E\") }", ""] - ]); - test("data url in filter", - ".class { filter: url('data:image/svg+xml;charset=utf-8,#filter'); }", [ - [1, ".class { filter: url('data:image/svg+xml;charset=utf-8,#filter'); }", ""] - ]); - test("encoded data url in filter", - ".class { filter: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%5C%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%5C%22%3E%3Cfilter%20id%3D%5C%22filter%5C%22%3E%3CfeGaussianBlur%20in%3D%5C%22SourceAlpha%5C%22%20stdDeviation%3D%5C%220%5C%22%20%2F%3E%3CfeOffset%20dx%3D%5C%221%5C%22%20dy%3D%5C%222%5C%22%20result%3D%5C%22offsetblur%5C%22%20%2F%3E%3CfeFlood%20flood-color%3D%5C%22rgba(255%2C255%2C255%2C1)%5C%22%20%2F%3E%3CfeComposite%20in2%3D%5C%22offsetblur%5C%22%20operator%3D%5C%22in%5C%22%20%2F%3E%3CfeMerge%3E%3CfeMergeNode%20%2F%3E%3CfeMergeNode%20in%3D%5C%22SourceGraphic%5C%22%20%2F%3E%3C%2FfeMerge%3E%3C%2Ffilter%3E%3C%2Fsvg%3E%23filter'); }", [ - [1, ".class { filter: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%5C%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%5C%22%3E%3Cfilter%20id%3D%5C%22filter%5C%22%3E%3CfeGaussianBlur%20in%3D%5C%22SourceAlpha%5C%22%20stdDeviation%3D%5C%220%5C%22%20%2F%3E%3CfeOffset%20dx%3D%5C%221%5C%22%20dy%3D%5C%222%5C%22%20result%3D%5C%22offsetblur%5C%22%20%2F%3E%3CfeFlood%20flood-color%3D%5C%22rgba(255%2C255%2C255%2C1)%5C%22%20%2F%3E%3CfeComposite%20in2%3D%5C%22offsetblur%5C%22%20operator%3D%5C%22in%5C%22%20%2F%3E%3CfeMerge%3E%3CfeMergeNode%20%2F%3E%3CfeMergeNode%20in%3D%5C%22SourceGraphic%5C%22%20%2F%3E%3C%2FfeMerge%3E%3C%2Ffilter%3E%3C%2Fsvg%3E%23filter'); }", ""] - ]); - test("filter hash", - ".highlight { filter: url(#highlight); }", [ - [1, ".highlight { filter: url(#highlight); }", ""] - ]); - test("filter hash quotation marks", - ".highlight { filter: url('#line-marker'); }", [ - [1, ".highlight { filter: url('#line-marker'); }", ""] - ]); - test("font face", "@font-face { src: url(regular.woff) format('woff'), url(~truetype/regular.ttf) format('truetype') }", [ - [1, "@font-face { src: url({./regular.woff}) format('woff'), url({truetype/regular.ttf}) format('truetype') }", ""] - ]); - test("media query", "@media (min-width: 500px) { body { background: url(image.png); } }", [ - [1, "@media (min-width: 500px) { body { background: url({./image.png}); } }", ""] - ]); - test("url in string", "a { content: \"do not use url(path)\"; } b { content: 'do not \"use\" url(path)'; }", [ - [1, "a { content: \"do not use url(path)\"; } b { content: 'do not \"use\" url(path)'; }", ""] - ]); - test("keyframe background img", "@keyframes anim { background: green url('img.png') xyz }", [ - [1, "@keyframes anim { background: green url({./img.png}) xyz }", ""] - ]); - test("-webkit-image-set", ".a { background-image: -webkit-image-set(url('url1x.png') 1x, url('url2x.png') 2x) }", [ - [1, ".a { background-image: -webkit-image-set(url({./url1x.png}) 1x, url({./url2x.png}) 2x) }", ""] - ]); - test("empty url", ".class { background: green url() xyz }", [ - [1, ".class { background: green url() xyz }", ""] - ]); - test("empty url with quotes", ".class { background: green url('') xyz }", [ - [1, ".class { background: green url('') xyz }", ""] - ]); - test("empty url with spaces and quotes", ".class { background: green url(' ') xyz }", [ - [1, ".class { background: green url(' ') xyz }", ""] - ]); - test("empty url with newline and quotes", ".class { background: green url('\n') xyz }", [ - [1, ".class { background: green url('\n') xyz }", ""] - ]); - test("empty url with CRLF and quotes", ".class { background: green url('\r\n') xyz }", [ - [1, ".class { background: green url('\r\n') xyz }", ""] - ]); - test("empty url with tab and quotes", ".class { background: green url('\t') xyz }", [ - [1, ".class { background: green url('\t') xyz }", ""] - ]); - test("external absolute url", ".class { background: green url(https://raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", [ - [1, ".class { background: green url(https://raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", ""] - ]); - test("external schema-less url", ".class { background: green url(//raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", [ - [1, ".class { background: green url(//raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", ""] - ]); - test("font face with url", "@font-face { src: url('My-Font.woff2') format('woff2') }", [ - [1, "@font-face { src: url({./My-Font.woff2}) format('woff2') }", ""] - ], ""); - test("font face with url and query and fragment identifier", "@font-face { src: url('webfont.eot?#iefix') format('embedded-opentype') }", [ - [1, "@font-face { src: url({./webfont.eot}?#iefix) format('embedded-opentype') }", ""] - ], ""); - test("font face with url and fragment identifier", "@font-face { src: url('webfont.svg#svgFontName') format('svg') }", [ - [1, "@font-face { src: url({./webfont.svg}#svgFontName) format('svg') }", ""] - ], ""); - - test("module wrapped in spaces", ".class { background: green url(module) xyz }", [ - [1, ".class { background: green url(module-wrapped) xyz }", ""] - ], "", { './module': "\"module-wrapped\"" }); - test("module with space", ".class { background: green url(module) xyz }", [ - [1, ".class { background: green url(\"module with space\") xyz }", ""] - ], "", { './module': "module with space" }); - test("module with quote", ".class { background: green url(module) xyz }", [ - [1, ".class { background: green url(\"module\\\"with\\\"quote\") xyz }", ""] - ], "", { './module': "module\"with\"quote" }); - test("module with quote wrapped", ".class { background: green url(module) xyz }", [ - [1, ".class { background: green url(\"module\\\"with\\\"quote\\\"wrapped\") xyz }", ""] - ], "", { './module': "\"module\"with\"quote\"wrapped\"" }); - test("module with parens", ".class { background: green url(module) xyz }", [ - [1, ".class { background: green url(\"module(with-parens)\") xyz }", ""] - ], "", { './module': 'module(with-parens)' }); - test("module with newline", ".class { background: green url(module) xyz }", [ - [1, ".class { background: green url(\"module\\nwith\\nnewline\") xyz }", ""] - ], "", { './module': "module\nwith\nnewline" }); - test("module from url-loader", ".class { background: green url(module) xyz }", [ - [1, ".class { background: green url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA) xyz }", ""] - ], "", { './module': "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA" }); - test("module from null-loader (empty object from webpack)", ".class { background: green url(module) xyz }", [ - [1, ".class { background: green url([object Object]) xyz }", ""] - ], "", { './module': {} }); - test("module is null", ".class { background: green url(module) xyz }", [ - [1, ".class { background: green url(null) xyz }", ""] - ], "", { './module': null }); + test("background img", '.class { background: green url( "img.png" ) xyz }', [ + [1, ".class { background: green url({./img.png}) xyz }", ""] + ]); + test( + "background img 2", + ".class { background: green url(~img/png) url(aaa) xyz }", + [[1, ".class { background: green url({img/png}) url({./aaa}) xyz }", ""]] + ); + test( + "background img 3", + ".class { background: green url( 'img.png' ) xyz }", + [[1, ".class { background: green url({./img.png}) xyz }", ""]] + ); + test("background img 4", ".class { background: green url( img.png ) xyz }", [ + [1, ".class { background: green url({./img.png}) xyz }", ""] + ]); + test( + "background img contain space in name", + '.class { background: green url( "img img.png" ) xyz }', + [[1, '.class { background: green url("{./img img.png}") xyz }', ""]] + ); + test( + "background 2 img contain space in name", + ".class { background: green url( 'img img.png' ) xyz }", + [[1, '.class { background: green url("{./img img.png}") xyz }', ""]] + ); + test( + "background img absolute", + ".class { background: green url(/img.png) xyz }", + [[1, ".class { background: green url(/img.png) xyz }", ""]] + ); + test( + "background img external", + ".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", + [ + [ + 1, + ".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", + "" + ] + ] + ); + test( + "background img external data", + ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\") }", + [ + [ + 1, + ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\") }", + "" + ] + ] + ); + test( + "background img external encoded data", + '.class { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%2523007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E") }', + [ + [ + 1, + '.class { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%2523007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E") }', + "" + ] + ] + ); + test( + "data url in filter", + '.class { filter: url(\'data:image/svg+xml;charset=utf-8,#filter\'); }', + [ + [ + 1, + '.class { filter: url(\'data:image/svg+xml;charset=utf-8,#filter\'); }', + "" + ] + ] + ); + test( + "encoded data url in filter", + ".class { filter: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%5C%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%5C%22%3E%3Cfilter%20id%3D%5C%22filter%5C%22%3E%3CfeGaussianBlur%20in%3D%5C%22SourceAlpha%5C%22%20stdDeviation%3D%5C%220%5C%22%20%2F%3E%3CfeOffset%20dx%3D%5C%221%5C%22%20dy%3D%5C%222%5C%22%20result%3D%5C%22offsetblur%5C%22%20%2F%3E%3CfeFlood%20flood-color%3D%5C%22rgba(255%2C255%2C255%2C1)%5C%22%20%2F%3E%3CfeComposite%20in2%3D%5C%22offsetblur%5C%22%20operator%3D%5C%22in%5C%22%20%2F%3E%3CfeMerge%3E%3CfeMergeNode%20%2F%3E%3CfeMergeNode%20in%3D%5C%22SourceGraphic%5C%22%20%2F%3E%3C%2FfeMerge%3E%3C%2Ffilter%3E%3C%2Fsvg%3E%23filter'); }", + [ + [ + 1, + ".class { filter: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%5C%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%5C%22%3E%3Cfilter%20id%3D%5C%22filter%5C%22%3E%3CfeGaussianBlur%20in%3D%5C%22SourceAlpha%5C%22%20stdDeviation%3D%5C%220%5C%22%20%2F%3E%3CfeOffset%20dx%3D%5C%221%5C%22%20dy%3D%5C%222%5C%22%20result%3D%5C%22offsetblur%5C%22%20%2F%3E%3CfeFlood%20flood-color%3D%5C%22rgba(255%2C255%2C255%2C1)%5C%22%20%2F%3E%3CfeComposite%20in2%3D%5C%22offsetblur%5C%22%20operator%3D%5C%22in%5C%22%20%2F%3E%3CfeMerge%3E%3CfeMergeNode%20%2F%3E%3CfeMergeNode%20in%3D%5C%22SourceGraphic%5C%22%20%2F%3E%3C%2FfeMerge%3E%3C%2Ffilter%3E%3C%2Fsvg%3E%23filter'); }", + "" + ] + ] + ); + test("filter hash", ".highlight { filter: url(#highlight); }", [ + [1, ".highlight { filter: url(#highlight); }", ""] + ]); + test( + "filter hash quotation marks", + ".highlight { filter: url('#line-marker'); }", + [[1, ".highlight { filter: url('#line-marker'); }", ""]] + ); + test( + "font face", + "@font-face { src: url(regular.woff) format('woff'), url(~truetype/regular.ttf) format('truetype') }", + [ + [ + 1, + "@font-face { src: url({./regular.woff}) format('woff'), url({truetype/regular.ttf}) format('truetype') }", + "" + ] + ] + ); + test( + "media query", + "@media (min-width: 500px) { body { background: url(image.png); } }", + [ + [ + 1, + "@media (min-width: 500px) { body { background: url({./image.png}); } }", + "" + ] + ] + ); + test( + "url in string", + 'a { content: "do not use url(path)"; } b { content: \'do not "use" url(path)\'; }', + [ + [ + 1, + 'a { content: "do not use url(path)"; } b { content: \'do not "use" url(path)\'; }', + "" + ] + ] + ); + test( + "keyframe background img", + "@keyframes anim { background: green url('img.png') xyz }", + [[1, "@keyframes anim { background: green url({./img.png}) xyz }", ""]] + ); + test( + "-webkit-image-set", + ".a { background-image: -webkit-image-set(url('url1x.png') 1x, url('url2x.png') 2x) }", + [ + [ + 1, + ".a { background-image: -webkit-image-set(url({./url1x.png}) 1x, url({./url2x.png}) 2x) }", + "" + ] + ] + ); + test("empty url", ".class { background: green url() xyz }", [ + [1, ".class { background: green url() xyz }", ""] + ]); + test("empty url with quotes", ".class { background: green url('') xyz }", [ + [1, ".class { background: green url('') xyz }", ""] + ]); + test( + "empty url with spaces and quotes", + ".class { background: green url(' ') xyz }", + [[1, ".class { background: green url(' ') xyz }", ""]] + ); + test( + "empty url with newline and quotes", + ".class { background: green url('\n') xyz }", + [[1, ".class { background: green url('\n') xyz }", ""]] + ); + test( + "empty url with CRLF and quotes", + ".class { background: green url('\r\n') xyz }", + [[1, ".class { background: green url('\r\n') xyz }", ""]] + ); + test( + "empty url with tab and quotes", + ".class { background: green url('\t') xyz }", + [[1, ".class { background: green url('\t') xyz }", ""]] + ); + test( + "external absolute url", + ".class { background: green url(https://raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", + [ + [ + 1, + ".class { background: green url(https://raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", + "" + ] + ] + ); + test( + "external schema-less url", + ".class { background: green url(//raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", + [ + [ + 1, + ".class { background: green url(//raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", + "" + ] + ] + ); + test( + "font face with url", + "@font-face { src: url('My-Font.woff2') format('woff2') }", + [[1, "@font-face { src: url({./My-Font.woff2}) format('woff2') }", ""]], + "" + ); + test( + "font face with url and query and fragment identifier", + "@font-face { src: url('webfont.eot?#iefix') format('embedded-opentype') }", + [ + [ + 1, + "@font-face { src: url({./webfont.eot}?#iefix) format('embedded-opentype') }", + "" + ] + ], + "" + ); + test( + "font face with url and fragment identifier", + "@font-face { src: url('webfont.svg#svgFontName') format('svg') }", + [ + [ + 1, + "@font-face { src: url({./webfont.svg}#svgFontName) format('svg') }", + "" + ] + ], + "" + ); - test("background img with url", ".class { background: green url( \"img.png\" ) xyz }", [ - [1, ".class { background: green url( \"img.png\" ) xyz }", ""] - ], "?-url"); - test("background img 2 with url", ".class { background: green url(~img/png) url(aaa) xyz }", [ - [1, ".class { background: green url(~img/png) url(aaa) xyz }", ""] - ], "?-url"); - test("background img 3 with url", ".class { background: green url( 'img.png' ) xyz }", [ - [1, ".class { background: green url( 'img.png' ) xyz }", ""] - ], "?-url"); - test("background img 4 with url", ".class { background: green url( img.png ) xyz }", [ - [1, ".class { background: green url( img.png ) xyz }", ""] - ], "?-url"); - test("background img with url contain space in name", ".class { background: green url( \"img img.png\" ) xyz }", [ - [1, ".class { background: green url( \"img img.png\" ) xyz }", ""] - ], "?-url"); - test("background 2 img with url contain space in name", ".class { background: green url( 'img img.png' ) xyz }", [ - [1, ".class { background: green url( 'img img.png' ) xyz }", ""] - ], "?-url"); - test("background img absolute with url", ".class { background: green url(/img.png) xyz }", [ - [1, ".class { background: green url(/img.png) xyz }", ""] - ], "?-url"); - test("background img external with url", - ".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", [ - [1, ".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", ""] - ], "?-url"); - test("background img external data with url", - ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\") }", [ - [1, ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\") }", ""] - ], "?-url"); - test("background img external encoded data with url", - ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%2523007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E\") }", [ - [1, ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%2523007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E\") }", ""] - ], "?-url"); - test("data url in filter with url", - ".class { filter: url('data:image/svg+xml;charset=utf-8,#filter'); }", [ - [1, ".class { filter: url('data:image/svg+xml;charset=utf-8,#filter'); }", ""] - ], "?-url"); - test("encoded data url in filter with url", - ".class { filter: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%5C%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%5C%22%3E%3Cfilter%20id%3D%5C%22filter%5C%22%3E%3CfeGaussianBlur%20in%3D%5C%22SourceAlpha%5C%22%20stdDeviation%3D%5C%220%5C%22%20%2F%3E%3CfeOffset%20dx%3D%5C%221%5C%22%20dy%3D%5C%222%5C%22%20result%3D%5C%22offsetblur%5C%22%20%2F%3E%3CfeFlood%20flood-color%3D%5C%22rgba(255%2C255%2C255%2C1)%5C%22%20%2F%3E%3CfeComposite%20in2%3D%5C%22offsetblur%5C%22%20operator%3D%5C%22in%5C%22%20%2F%3E%3CfeMerge%3E%3CfeMergeNode%20%2F%3E%3CfeMergeNode%20in%3D%5C%22SourceGraphic%5C%22%20%2F%3E%3C%2FfeMerge%3E%3C%2Ffilter%3E%3C%2Fsvg%3E%23filter'); }", [ - [1, ".class { filter: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%5C%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%5C%22%3E%3Cfilter%20id%3D%5C%22filter%5C%22%3E%3CfeGaussianBlur%20in%3D%5C%22SourceAlpha%5C%22%20stdDeviation%3D%5C%220%5C%22%20%2F%3E%3CfeOffset%20dx%3D%5C%221%5C%22%20dy%3D%5C%222%5C%22%20result%3D%5C%22offsetblur%5C%22%20%2F%3E%3CfeFlood%20flood-color%3D%5C%22rgba(255%2C255%2C255%2C1)%5C%22%20%2F%3E%3CfeComposite%20in2%3D%5C%22offsetblur%5C%22%20operator%3D%5C%22in%5C%22%20%2F%3E%3CfeMerge%3E%3CfeMergeNode%20%2F%3E%3CfeMergeNode%20in%3D%5C%22SourceGraphic%5C%22%20%2F%3E%3C%2FfeMerge%3E%3C%2Ffilter%3E%3C%2Fsvg%3E%23filter'); }", ""] - ], "?-url"); - test("filter hash with url", - ".highlight { filter: url(#highlight); }", [ - [1, ".highlight { filter: url(#highlight); }", ""] - ], "?-url"); - test("filter hash quotation marks with url", - ".highlight { filter: url('#line-marker'); }", [ - [1, ".highlight { filter: url('#line-marker'); }", ""] - ], "?-url"); - test("font face with url", "@font-face { src: url(regular.woff) format('woff'), url(~truetype/regular.ttf) format('truetype') }", [ - [1, "@font-face { src: url(regular.woff) format('woff'), url(~truetype/regular.ttf) format('truetype') }", ""] - ], "?-url"); - test("font face with url", "@font-face { src: url(Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix) format('embedded-opentype'), url(~opentype/Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix) format('embedded-opentype') }", [ - [1, "@font-face { src: url(Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix) format('embedded-opentype'), url(~opentype/Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix) format('embedded-opentype') }", ""] - ], "?-url"); - test("font face with url", "@font-face { src: url('Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix') format('embedded-opentype'), url(\"Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix\") format('embedded-opentype') }", [ - [1, "@font-face { src: url('Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix') format('embedded-opentype'), url(\"Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix\") format('embedded-opentype') }", ""] - ], "?-url"); - test("media query with url", "@media (min-width: 500px) { body { background: url(image.png); } }", [ - [1, "@media (min-width: 500px) { body { background: url(image.png); } }", ""] - ], "?-url"); - test("url in string with url", "a { content: \"do not use url(path)\"; } b { content: 'do not \"use\" url(path)'; }", [ - [1, "a { content: \"do not use url(path)\"; } b { content: 'do not \"use\" url(path)'; }", ""] - ], "?-url"); - test("keyframe background img with url", "@keyframes anim { background: green url('img.png') xyz }", [ - [1, "@keyframes anim { background: green url('img.png') xyz }", ""] - ], "?-url"); - test("empty url", ".class { background: green url() xyz }", [ - [1, ".class { background: green url() xyz }", ""] - ], "?-url"); - test("empty url with quotes", ".class { background: green url('') xyz }", [ - [1, ".class { background: green url('') xyz }", ""] - ], "?-url"); - test("empty url with spaces and quotes", ".class { background: green url(' ') xyz }", [ - [1, ".class { background: green url(' ') xyz }", ""] - ], "?-url"); - test("empty url with newline and quotes", ".class { background: green url('\n') xyz }", [ - [1, ".class { background: green url('\n') xyz }", ""] - ], "?-url"); - test("empty url with CRLF and quotes", ".class { background: green url('\r\n') xyz }", [ - [1, ".class { background: green url('\r\n') xyz }", ""] - ], "?-url"); - test("empty url with tab and quotes", ".class { background: green url('\t') xyz }", [ - [1, ".class { background: green url('\t') xyz }", ""] - ], "?-url"); - test("external absolute url", ".class { background: green url(https://raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", [ - [1, ".class { background: green url(https://raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", ""] - ], "?-url"); - test("external schema-less url", ".class { background: green url(//raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", [ - [1, ".class { background: green url(//raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", ""] - ], "?-url"); + test( + "module wrapped in spaces", + ".class { background: green url(module) xyz }", + [[1, ".class { background: green url(module-wrapped) xyz }", ""]], + "", + { "./module": '"module-wrapped"' } + ); + test( + "module with space", + ".class { background: green url(module) xyz }", + [[1, '.class { background: green url("module with space") xyz }', ""]], + "", + { "./module": "module with space" } + ); + test( + "module with quote", + ".class { background: green url(module) xyz }", + [[1, '.class { background: green url("module\\"with\\"quote") xyz }', ""]], + "", + { "./module": 'module"with"quote' } + ); + test( + "module with quote wrapped", + ".class { background: green url(module) xyz }", + [ + [ + 1, + '.class { background: green url("module\\"with\\"quote\\"wrapped") xyz }', + "" + ] + ], + "", + { "./module": '"module"with"quote"wrapped"' } + ); + test( + "module with parens", + ".class { background: green url(module) xyz }", + [[1, '.class { background: green url("module(with-parens)") xyz }', ""]], + "", + { "./module": "module(with-parens)" } + ); + test( + "module with newline", + ".class { background: green url(module) xyz }", + [ + [1, '.class { background: green url("module\\nwith\\nnewline") xyz }', ""] + ], + "", + { "./module": "module\nwith\nnewline" } + ); + test( + "module from url-loader", + ".class { background: green url(module) xyz }", + [ + [ + 1, + ".class { background: green url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA) xyz }", + "" + ] + ], + "", + { "./module": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAA" } + ); + test( + "module from null-loader (empty object from webpack)", + ".class { background: green url(module) xyz }", + [[1, ".class { background: green url([object Object]) xyz }", ""]], + "", + { "./module": {} } + ); + test( + "module is null", + ".class { background: green url(module) xyz }", + [[1, ".class { background: green url(null) xyz }", ""]], + "", + { "./module": null } + ); + + test( + "background img with url", + '.class { background: green url( "img.png" ) xyz }', + [[1, '.class { background: green url( "img.png" ) xyz }', ""]], + "?-url" + ); + test( + "background img 2 with url", + ".class { background: green url(~img/png) url(aaa) xyz }", + [[1, ".class { background: green url(~img/png) url(aaa) xyz }", ""]], + "?-url" + ); + test( + "background img 3 with url", + ".class { background: green url( 'img.png' ) xyz }", + [[1, ".class { background: green url( 'img.png' ) xyz }", ""]], + "?-url" + ); + test( + "background img 4 with url", + ".class { background: green url( img.png ) xyz }", + [[1, ".class { background: green url( img.png ) xyz }", ""]], + "?-url" + ); + test( + "background img with url contain space in name", + '.class { background: green url( "img img.png" ) xyz }', + [[1, '.class { background: green url( "img img.png" ) xyz }', ""]], + "?-url" + ); + test( + "background 2 img with url contain space in name", + ".class { background: green url( 'img img.png' ) xyz }", + [[1, ".class { background: green url( 'img img.png' ) xyz }", ""]], + "?-url" + ); + test( + "background img absolute with url", + ".class { background: green url(/img.png) xyz }", + [[1, ".class { background: green url(/img.png) xyz }", ""]], + "?-url" + ); + test( + "background img external with url", + ".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", + [ + [ + 1, + ".class { background: green url(data:image/png;base64,AAA) url(http://example.com/image.jpg) url(//example.com/image.png) xyz }", + "" + ] + ], + "?-url" + ); + test( + "background img external data with url", + ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\") }", + [ + [ + 1, + ".class { background-image: url(\"data:image/svg+xml;charset=utf-8,\") }", + "" + ] + ], + "?-url" + ); + test( + "background img external encoded data with url", + '.class { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%2523007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E") }', + [ + [ + 1, + '.class { background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%27http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%27%20viewBox%3D%270%200%2042%2026%27%20fill%3D%27%2523007aff%27%3E%3Crect%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%271%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2711%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2712%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3Crect%20y%3D%2722%27%20width%3D%274%27%20height%3D%274%27%2F%3E%3Crect%20x%3D%278%27%20y%3D%2723%27%20width%3D%2734%27%20height%3D%272%27%2F%3E%3C%2Fsvg%3E") }', + "" + ] + ], + "?-url" + ); + test( + "data url in filter with url", + '.class { filter: url(\'data:image/svg+xml;charset=utf-8,#filter\'); }', + [ + [ + 1, + '.class { filter: url(\'data:image/svg+xml;charset=utf-8,#filter\'); }', + "" + ] + ], + "?-url" + ); + test( + "encoded data url in filter with url", + ".class { filter: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%5C%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%5C%22%3E%3Cfilter%20id%3D%5C%22filter%5C%22%3E%3CfeGaussianBlur%20in%3D%5C%22SourceAlpha%5C%22%20stdDeviation%3D%5C%220%5C%22%20%2F%3E%3CfeOffset%20dx%3D%5C%221%5C%22%20dy%3D%5C%222%5C%22%20result%3D%5C%22offsetblur%5C%22%20%2F%3E%3CfeFlood%20flood-color%3D%5C%22rgba(255%2C255%2C255%2C1)%5C%22%20%2F%3E%3CfeComposite%20in2%3D%5C%22offsetblur%5C%22%20operator%3D%5C%22in%5C%22%20%2F%3E%3CfeMerge%3E%3CfeMergeNode%20%2F%3E%3CfeMergeNode%20in%3D%5C%22SourceGraphic%5C%22%20%2F%3E%3C%2FfeMerge%3E%3C%2Ffilter%3E%3C%2Fsvg%3E%23filter'); }", + [ + [ + 1, + ".class { filter: url('data:image/svg+xml;charset=utf-8,%3Csvg%20xmlns%3D%5C%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%5C%22%3E%3Cfilter%20id%3D%5C%22filter%5C%22%3E%3CfeGaussianBlur%20in%3D%5C%22SourceAlpha%5C%22%20stdDeviation%3D%5C%220%5C%22%20%2F%3E%3CfeOffset%20dx%3D%5C%221%5C%22%20dy%3D%5C%222%5C%22%20result%3D%5C%22offsetblur%5C%22%20%2F%3E%3CfeFlood%20flood-color%3D%5C%22rgba(255%2C255%2C255%2C1)%5C%22%20%2F%3E%3CfeComposite%20in2%3D%5C%22offsetblur%5C%22%20operator%3D%5C%22in%5C%22%20%2F%3E%3CfeMerge%3E%3CfeMergeNode%20%2F%3E%3CfeMergeNode%20in%3D%5C%22SourceGraphic%5C%22%20%2F%3E%3C%2FfeMerge%3E%3C%2Ffilter%3E%3C%2Fsvg%3E%23filter'); }", + "" + ] + ], + "?-url" + ); + test( + "filter hash with url", + ".highlight { filter: url(#highlight); }", + [[1, ".highlight { filter: url(#highlight); }", ""]], + "?-url" + ); + test( + "filter hash quotation marks with url", + ".highlight { filter: url('#line-marker'); }", + [[1, ".highlight { filter: url('#line-marker'); }", ""]], + "?-url" + ); + test( + "font face with url", + "@font-face { src: url(regular.woff) format('woff'), url(~truetype/regular.ttf) format('truetype') }", + [ + [ + 1, + "@font-face { src: url(regular.woff) format('woff'), url(~truetype/regular.ttf) format('truetype') }", + "" + ] + ], + "?-url" + ); + test( + "font face with url", + "@font-face { src: url(Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix) format('embedded-opentype'), url(~opentype/Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix) format('embedded-opentype') }", + [ + [ + 1, + "@font-face { src: url(Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix) format('embedded-opentype'), url(~opentype/Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix) format('embedded-opentype') }", + "" + ] + ], + "?-url" + ); + test( + "font face with url", + "@font-face { src: url('Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix') format('embedded-opentype'), url(\"Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix\") format('embedded-opentype') }", + [ + [ + 1, + "@font-face { src: url('Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix') format('embedded-opentype'), url(\"Mark Simonson - Proxima Nova Alt Regular-webfont.eot?#iefix\") format('embedded-opentype') }", + "" + ] + ], + "?-url" + ); + test( + "media query with url", + "@media (min-width: 500px) { body { background: url(image.png); } }", + [ + [ + 1, + "@media (min-width: 500px) { body { background: url(image.png); } }", + "" + ] + ], + "?-url" + ); + test( + "url in string with url", + 'a { content: "do not use url(path)"; } b { content: \'do not "use" url(path)\'; }', + [ + [ + 1, + 'a { content: "do not use url(path)"; } b { content: \'do not "use" url(path)\'; }', + "" + ] + ], + "?-url" + ); + test( + "keyframe background img with url", + "@keyframes anim { background: green url('img.png') xyz }", + [[1, "@keyframes anim { background: green url('img.png') xyz }", ""]], + "?-url" + ); + test( + "empty url", + ".class { background: green url() xyz }", + [[1, ".class { background: green url() xyz }", ""]], + "?-url" + ); + test( + "empty url with quotes", + ".class { background: green url('') xyz }", + [[1, ".class { background: green url('') xyz }", ""]], + "?-url" + ); + test( + "empty url with spaces and quotes", + ".class { background: green url(' ') xyz }", + [[1, ".class { background: green url(' ') xyz }", ""]], + "?-url" + ); + test( + "empty url with newline and quotes", + ".class { background: green url('\n') xyz }", + [[1, ".class { background: green url('\n') xyz }", ""]], + "?-url" + ); + test( + "empty url with CRLF and quotes", + ".class { background: green url('\r\n') xyz }", + [[1, ".class { background: green url('\r\n') xyz }", ""]], + "?-url" + ); + test( + "empty url with tab and quotes", + ".class { background: green url('\t') xyz }", + [[1, ".class { background: green url('\t') xyz }", ""]], + "?-url" + ); + test( + "external absolute url", + ".class { background: green url(https://raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", + [ + [ + 1, + ".class { background: green url(https://raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", + "" + ] + ], + "?-url" + ); + test( + "external schema-less url", + ".class { background: green url(//raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", + [ + [ + 1, + ".class { background: green url(//raw.githubusercontent.com/webpack/media/master/logo/icon.png) xyz }", + "" + ] + ], + "?-url" + ); }); From ff7a4c865345397f1ec64f5c04dc5ad2e8dc227e Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 10 Jul 2018 20:38:57 +0300 Subject: [PATCH 17/45] refactor: SyntaxError class --- lib/CssLoaderError.js | 27 --------------------------- lib/SyntaxError.js | 23 +++++++++++++++++++++++ lib/loader.js | 15 ++------------- 3 files changed, 25 insertions(+), 40 deletions(-) delete mode 100644 lib/CssLoaderError.js create mode 100644 lib/SyntaxError.js diff --git a/lib/CssLoaderError.js b/lib/CssLoaderError.js deleted file mode 100644 index 506f9f17..00000000 --- a/lib/CssLoaderError.js +++ /dev/null @@ -1,27 +0,0 @@ -var formatCodeFrame = require("babel-code-frame"); - -function formatMessage(message, loc, source) { - var formatted = message; - if (loc) { - formatted = formatted + " (" + loc.line + ":" + loc.column + ")"; - } - if (loc && source) { - formatted = - formatted + "\n\n" + formatCodeFrame(source, loc.line, loc.column) + "\n"; - } - return formatted; -} - -function CssLoaderError(name, message, loc, source, error) { - Error.call(this); - Error.captureStackTrace(this, CssLoaderError); - this.name = name; - this.error = error; - this.message = formatMessage(message, loc, source); - this.hideStack = true; -} - -CssLoaderError.prototype = Object.create(Error.prototype); -CssLoaderError.prototype.constructor = CssLoaderError; - -module.exports = CssLoaderError; diff --git a/lib/SyntaxError.js b/lib/SyntaxError.js new file mode 100644 index 00000000..c512c7ec --- /dev/null +++ b/lib/SyntaxError.js @@ -0,0 +1,23 @@ +const formatCodeFrame = require("babel-code-frame"); + +class SyntaxError extends Error { + constructor(err) { + super(err); + + this.name = this.constructor.name; + this.message = err.reason ? err.reason : err.message; + + if (err.line && err.column) { + this.message += " (" + err.line + ":" + err.column + ")"; + + if (err.source) { + this.message += + "\n\n" + formatCodeFrame(err.source, err.line, err.column) + "\n"; + } + } + + Error.captureStackTrace(this, this.constructor); + } +} + +module.exports = SyntaxError; diff --git a/lib/loader.js b/lib/loader.js index 6810076b..b92dcf80 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -6,7 +6,7 @@ const loaderUtils = require("loader-utils"); const postcss = require("postcss"); const plugin = require("./plugin"); const getImportPrefix = require("./getImportPrefix"); -const CssLoaderError = require("./CssLoaderError"); +const SyntaxError = require("./SyntaxError"); module.exports = function(content, map) { const options = loaderUtils.getOptions(this) || {}; @@ -188,17 +188,6 @@ module.exports = function(content, map) { .catch(err => { // Todo if (err.file) this.addDependency(err.file) - cb( - err.name === "CssSyntaxError" - ? new CssLoaderError( - "Syntax Error", - err.reason, - err.line != null && err.column != null - ? { line: err.line, column: err.column } - : null, - err.input.source - ) - : err - ); + cb(err.name === "CssSyntaxError" ? new SyntaxError(err) : err); }); }; From 2f769b3a76193a3934339e99f4a6a0cd5da3d55b Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Tue, 10 Jul 2018 21:21:32 +0300 Subject: [PATCH 18/45] refactor: loader --- lib/loader.js | 151 ++++++++++++++++++++++++------------------------ lib/plugin.js | 2 +- test/helpers.js | 3 + 3 files changed, 80 insertions(+), 76 deletions(-) diff --git a/lib/loader.js b/lib/loader.js index b92dcf80..bebb057c 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -8,13 +8,13 @@ const plugin = require("./plugin"); const getImportPrefix = require("./getImportPrefix"); const SyntaxError = require("./SyntaxError"); -module.exports = function(content, map) { +module.exports = function(content, map, meta) { const options = loaderUtils.getOptions(this) || {}; // Todo validate options const cb = this.async(); - const sourceMap = options.sourceMap; + const sourceMap = options.sourceMap || false; if (sourceMap && map) { if (typeof map === "string") { @@ -30,85 +30,95 @@ module.exports = function(content, map) { map = null; } - // We need a prefix to avoid path rewriting of PostCSS - const from = - "/css-loader!" + - loaderUtils - .getRemainingRequest(this) - .split("!") - .pop(); - const to = loaderUtils - .getCurrentRequest(this) - .split("!") - .pop(); + // Reuse CSS AST (PostCSS AST e.g 'postcss-loader') to avoid reparsing + if (meta) { + const { ast } = meta; + + if (ast && ast.type === "postcss") { + content = ast.root; + } + } - postcss([ + const plugins = [ plugin({ url: options.url !== false, import: options.import !== false }) - ]) - .process(content, { - from, - to, - map: sourceMap - ? { - prev: map, - sourcesContent: true, - inline: false, - annotation: false - } - : null - }) + ]; + + const postcssOptions = { + // We need a prefix to avoid path rewriting of PostCSS + from: + "/css-loader!" + + loaderUtils + .getRemainingRequest(this) + .split("!") + .pop(), + to: loaderUtils + .getCurrentRequest(this) + .split("!") + .pop(), + map: sourceMap + ? { + prev: map, + sourcesContent: true, + inline: false, + annotation: false + } + : null + }; + + postcss(plugins) + .process(content, postcssOptions) .then(result => { - var cssAsString = JSON.stringify(result.css); + let cssAsString = JSON.stringify(result.css); + let imports = ""; + let exports = ""; + let urlEscapeHelperCode = ""; if (options.import !== false) { - var alreadyImported = {}; - var importJs = result.messages + const alreadyImported = {}; + imports = result.messages .filter(message => message.type === "at-rule-import") - .filter(imp => { - if (!imp.mediaQuery) { - if (alreadyImported[imp.url]) { + .filter(message => { + if (!message.mediaQuery) { + if (alreadyImported[message.url]) { return false; } - alreadyImported[imp.url] = true; + alreadyImported[message.url] = true; } return true; }) - .map(imp => { - if (!loaderUtils.isUrlRequest(imp.url)) { + .map(message => { + if (!loaderUtils.isUrlRequest(message.url)) { return ( "exports.push([module.id, " + - JSON.stringify("@import url(" + imp.url + ");") + + JSON.stringify("@import url(" + message.url + ");") + ", " + - JSON.stringify(imp.mediaQuery) + + JSON.stringify(message.mediaQuery) + "]);" ); } // for importing CSS var importUrlPrefix = getImportPrefix(this, options); - var importUrl = importUrlPrefix + imp.url; + var importUrl = importUrlPrefix + message.url; return ( "exports.i(require(" + loaderUtils.stringifyRequest(this, importUrl) + "), " + - JSON.stringify(imp.mediaQuery) + + JSON.stringify(message.mediaQuery) + ");" ); }) .join("\n"); } - // Helper for ensuring valid CSS strings from requires - let urlEscapeHelper = ""; - if (options.url !== false) { - urlEscapeHelper = + urlEscapeHelperCode = "var runtimeEscape = require(" + loaderUtils.stringifyRequest( this, @@ -117,7 +127,7 @@ module.exports = function(content, map) { ");\n"; result.messages - .filter(message => message.type === "css-loader-import-url") + .filter(message => message.type === "function-url") .forEach(message => { const { placeholder, url } = message; const splittedURL = url.split(/(\?)?#/); @@ -132,15 +142,6 @@ module.exports = function(content, map) { }); } - // Todo need save backward compatibility with old `style-loader` - var exportJs = ""; - - if (exportJs) { - exportJs = "exports.locals = " + exportJs + ";"; - } - - var moduleJs; - if (sourceMap && result.map) { map = result.map.toJSON(); @@ -159,34 +160,34 @@ module.exports = function(content, map) { .pop() .replace(/\\/g, "/"); map = JSON.stringify(map); - - moduleJs = - "exports.push([module.id, " + cssAsString + ', "", ' + map + "]);"; - } else { - moduleJs = "exports.push([module.id, " + cssAsString + ', ""]);'; } - // embed runtime + const runtimeCode = `module.exports = exports = require(${loaderUtils.stringifyRequest( + this, + require.resolve("./runtime.js") + )})(${!!sourceMap});\n`; + const moduleCode = `// CSS Module\nexports.push([module.id, ${cssAsString}, ""${ + map ? `,${map}` : "" + }]);\n`; + const importsCode = imports ? `// CSS Imports\n${imports}\n` : ""; + // Todo need save backward compatibility with old `style-loader` and exports.locals + const exportsCode = exports ? `// CSS Exports\n${exports}\n` : false; + cb( null, - urlEscapeHelper + - "exports = module.exports = require(" + - loaderUtils.stringifyRequest(this, require.resolve("./runtime.js")) + - ")(" + - sourceMap + - ");\n" + - "// imports\n" + - importJs + - "\n\n" + - "// module\n" + - moduleJs + - "\n\n" + - "// exports\n" + - exportJs + [ + urlEscapeHelperCode, + runtimeCode, + importsCode, + moduleCode, + exportsCode + ].join("\n") ); }) .catch(err => { - // Todo if (err.file) this.addDependency(err.file) + if (err.file) { + this.addDependency(err.file); + } cb(err.name === "CssSyntaxError" ? new SyntaxError(err) : err); }); diff --git a/lib/plugin.js b/lib/plugin.js index 1632e88c..c7f62a82 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -100,7 +100,7 @@ module.exports = postcss.plugin(pluginName, function(options) { result.messages.push({ pluginName, - type: "css-loader-import-url", + type: "function-url", placeholder: placeholder, url: requestedURL }); diff --git a/test/helpers.js b/test/helpers.js index 1eb98364..089db8b7 100644 --- a/test/helpers.js +++ b/test/helpers.js @@ -56,6 +56,9 @@ function runLoader(loader, input, map, addOptions, callback) { request: "css-loader!test.css", emitError: function(message) { throw new Error(message); + }, + addDependency: function (dep) { + // Nothing } }; Object.keys(addOptions).forEach(function(key) { From fdfdc177b488069435cb0e1624208c4b9e5314e7 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Wed, 11 Jul 2018 15:56:02 +0300 Subject: [PATCH 19/45] refactor: use `runtime` message api --- .eslintrc.yml | 6 +- lib/getImportPrefix.js | 20 ------- lib/loader.js | 126 ++++++++++++++--------------------------- lib/plugin.js | 108 +++++++++++++++++++++++++++++------ test/importTest.js | 91 +++++++++++++++++++---------- 5 files changed, 194 insertions(+), 157 deletions(-) delete mode 100644 lib/getImportPrefix.js diff --git a/.eslintrc.yml b/.eslintrc.yml index f70ca050..7ea3f69a 100644 --- a/.eslintrc.yml +++ b/.eslintrc.yml @@ -9,7 +9,7 @@ rules: array-bracket-spacing: 'off' array-callback-return: error arrow-body-style: error - arrow-parens: error + arrow-parens: 'off' arrow-spacing: error block-scoped-var: 'off' block-spacing: @@ -90,7 +90,7 @@ rules: no-bitwise: error no-caller: error no-catch-shadow: error - no-confusing-arrow: error + no-confusing-arrow: 'off' no-continue: error no-div-regex: error no-duplicate-imports: error @@ -176,7 +176,7 @@ rules: no-useless-constructor: error no-useless-escape: error no-useless-rename: error - no-useless-return: error + no-useless-return: 'off' no-var: 'off' no-void: error no-warning-comments: error diff --git a/lib/getImportPrefix.js b/lib/getImportPrefix.js deleted file mode 100644 index f1f01976..00000000 --- a/lib/getImportPrefix.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - MIT License http://www.opensource.org/licenses/mit-license.php - Author Tobias Koppers @sokra -*/ -module.exports = function getImportPrefix(loaderContext, query) { - if (query.importLoaders === false) { - return ""; - } - - const importLoaders = parseInt(query.importLoaders, 10) || 0; - const loadersRequest = loaderContext.loaders - .slice( - loaderContext.loaderIndex, - loaderContext.loaderIndex + 1 + importLoaders - ) - .map(x => x.request) - .join("!"); - - return "-!" + loadersRequest + "!"; -}; diff --git a/lib/loader.js b/lib/loader.js index bebb057c..7ee6ce59 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -2,10 +2,10 @@ MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ + const loaderUtils = require("loader-utils"); const postcss = require("postcss"); const plugin = require("./plugin"); -const getImportPrefix = require("./getImportPrefix"); const SyntaxError = require("./SyntaxError"); module.exports = function(content, map, meta) { @@ -42,7 +42,9 @@ module.exports = function(content, map, meta) { const plugins = [ plugin({ url: options.url !== false, - import: options.import !== false + import: options.import !== false, + loaderContext: this, + importLoaders: options.importLoaders }) ]; @@ -71,75 +73,8 @@ module.exports = function(content, map, meta) { postcss(plugins) .process(content, postcssOptions) .then(result => { - let cssAsString = JSON.stringify(result.css); - let imports = ""; - let exports = ""; - let urlEscapeHelperCode = ""; - - if (options.import !== false) { - const alreadyImported = {}; - imports = result.messages - .filter(message => message.type === "at-rule-import") - .filter(message => { - if (!message.mediaQuery) { - if (alreadyImported[message.url]) { - return false; - } - - alreadyImported[message.url] = true; - } - - return true; - }) - .map(message => { - if (!loaderUtils.isUrlRequest(message.url)) { - return ( - "exports.push([module.id, " + - JSON.stringify("@import url(" + message.url + ");") + - ", " + - JSON.stringify(message.mediaQuery) + - "]);" - ); - } - - // for importing CSS - var importUrlPrefix = getImportPrefix(this, options); - var importUrl = importUrlPrefix + message.url; - - return ( - "exports.i(require(" + - loaderUtils.stringifyRequest(this, importUrl) + - "), " + - JSON.stringify(message.mediaQuery) + - ");" - ); - }) - .join("\n"); - } - - if (options.url !== false) { - urlEscapeHelperCode = - "var runtimeEscape = require(" + - loaderUtils.stringifyRequest( - this, - require.resolve("./runtimeEscape.js") - ) + - ");\n"; - - result.messages - .filter(message => message.type === "function-url") - .forEach(message => { - const { placeholder, url } = message; - const splittedURL = url.split(/(\?)?#/); - const importURLString = - '" + runtimeEscape(require(' + - loaderUtils.stringifyRequest(this, splittedURL[0]) + - ')) + "' + - (splittedURL[1] ? splittedURL[1] : "") + - (splittedURL[2] ? `#${splittedURL[2]}` : ""); - - cssAsString = cssAsString.replace(placeholder, importURLString); - }); + if (meta && meta.messages) { + result.messages = result.messages.concat(meta.messages); } if (sourceMap && result.map) { @@ -162,27 +97,46 @@ module.exports = function(content, map, meta) { map = JSON.stringify(map); } - const runtimeCode = `module.exports = exports = require(${loaderUtils.stringifyRequest( - this, - require.resolve("./runtime.js") - )})(${!!sourceMap});\n`; - const moduleCode = `// CSS Module\nexports.push([module.id, ${cssAsString}, ""${ - map ? `,${map}` : "" - }]);\n`; - const importsCode = imports ? `// CSS Imports\n${imports}\n` : ""; // Todo need save backward compatibility with old `style-loader` and exports.locals - const exportsCode = exports ? `// CSS Exports\n${exports}\n` : false; + let newContent = { + imports: "", + runtime: `module.exports = exports = require(${loaderUtils.stringifyRequest( + this, + require.resolve("./runtime.js") + )})(${!!sourceMap});\n`, + module: `exports.push([module.id, ${JSON.stringify(result.css)}, ""${ + map ? `,${map}` : "" + }]);\n`, + exports: "" + }; + + if (result.messages && result.messages.length > 0) { + newContent = result.messages + .filter(message => (message.type === "modify-runtime" ? message : false)) + .reduce((initialValue, message) => { + try { + initialValue = message.modifyRuntimeCode(this, initialValue); + } catch (err) { + this.emitError(err); + } + + return initialValue; + }, newContent); + } + + const {imports, runtime, module, exports} = newContent; cb( null, [ - urlEscapeHelperCode, - runtimeCode, - importsCode, - moduleCode, - exportsCode + imports ? `// CSS imports\n${imports}` : "", + runtime ? `// CSS runtime\n${runtime}` : "", + module ? `// CSS module\n${newContent.module}` : "", + exports ? `// CSS exports\n${newContent.exports}` : "" ].join("\n") ); + + return; }) .catch(err => { if (err.file) { @@ -190,5 +144,7 @@ module.exports = function(content, map, meta) { } cb(err.name === "CssSyntaxError" ? new SyntaxError(err) : err); + + return; }); }; diff --git a/lib/plugin.js b/lib/plugin.js index c7f62a82..df48ffea 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -4,9 +4,28 @@ const loaderUtils = require("loader-utils"); const pluginName = "postcss-css-loader"; +function getImportPrefix(loaderContext, importLoaders) { + if (importLoaders === false) { + return ""; + } + + const importLoadersValue = parseInt(importLoaders, 10) || 0; + const loadersRequest = loaderContext.loaders + .slice( + loaderContext.loaderIndex, + loaderContext.loaderIndex + 1 + importLoadersValue + ) + .map(x => x.request) + .join("!"); + + return "-!" + loadersRequest + "!"; +} + module.exports = postcss.plugin(pluginName, function(options) { return function(css, result) { if (options.import) { + const alreadyImported = {}; + css.walkAtRules(/^import$/i, function(rule) { const parsedValue = valueParser(rule.params); @@ -35,20 +54,43 @@ module.exports = postcss.plugin(pluginName, function(options) { return; } + const mediaQuery = valueParser + .stringify(parsedValue.nodes.slice(1)) + .trim(); + + let runtimeCode = ""; + if (loaderUtils.isUrlRequest(url)) { url = loaderUtils.urlToRequest(url); + + const importUrlPrefix = getImportPrefix( + options.loaderContext, + options.importLoaders + ); + + runtimeCode = `exports.i(require(${loaderUtils.stringifyRequest( + options.loaderContext, + importUrlPrefix + url + )}), ${JSON.stringify(mediaQuery)});\n`; + } else { + runtimeCode = `exports.push([module.id, ${JSON.stringify( + "@import url(" + url + ");" + )}, ${JSON.stringify(mediaQuery)}]);`; } - const mediaQuery = valueParser - .stringify(parsedValue.nodes.slice(1)) - .trim(); + if (!alreadyImported[url]) { + result.messages.push({ + pluginName, + type: "modify-runtime", + modifyRuntimeCode: (loaderContext, content) => { + content.runtime = `${content.runtime}${runtimeCode}\n`; + + return content; + } + }); - result.messages.push({ - pluginName, - type: "at-rule-import", - url: url, - mediaQuery: mediaQuery - }); + alreadyImported[url] = true; + } rule.remove(); }); @@ -75,15 +117,15 @@ module.exports = postcss.plugin(pluginName, function(options) { } const URLNode = node.nodes[0]; - const URLValue = URLNode.value.trim().replace(/\\[\r\n]/g, ""); + const URL = URLNode.value.trim().replace(/\\[\r\n]/g, ""); // Skip empty URLs // Empty URL function equals request to current stylesheet where it is declared - if (URLValue.length === 0) { + if (URL.length === 0) { return; } - if (!loaderUtils.isUrlRequest(URLValue)) { + if (!loaderUtils.isUrlRequest(URL)) { return; } @@ -91,21 +133,51 @@ module.exports = postcss.plugin(pluginName, function(options) { node.before = ""; node.after = ""; - const requestedURL = loaderUtils.urlToRequest(URLValue); - const placeholder = "___CSS_LOADER_IMPORT_URL_PLACEHOLDER___" + index + "___"; + const splittedURL = URL.split(/(\?)?#/); + const normalizedURL = splittedURL[0]; + + const requestedURL = loaderUtils.urlToRequest(normalizedURL); + const placeholder = + "___CSS_LOADER_IMPORT_URL_PLACEHOLDER___" + index + "___"; URLNode.value = placeholder; // Strip quotes, they will be re-added if the module needs them URLNode.quote = ""; + let hasURLEscapeRuntimeCode = false; + result.messages.push({ pluginName, - type: "function-url", - placeholder: placeholder, - url: requestedURL + type: "modify-runtime", + modifyRuntimeCode: (loaderContext, content) => { + if (!hasURLEscapeRuntimeCode) { + content.imports = `var runtimeEscape = require(${loaderUtils.stringifyRequest( + loaderContext, + require.resolve("./runtimeEscape.js") + )});\n${content.imports}`; + + hasURLEscapeRuntimeCode = true; + } + + content.imports = `${ + content.imports + }var ${placeholder} = require(${loaderUtils.stringifyRequest( + loaderContext, + requestedURL + )});\n`; + + content.module = content.module.replace( + placeholder, + `" + runtimeEscape(${placeholder}) + "${ + splittedURL[1] ? splittedURL[1] : "" + }${splittedURL[2] ? `#${splittedURL[2]}` : ""}` + ); + + return content; + } }); - index++; + index += 1; return false; }) diff --git a/test/importTest.js b/test/importTest.js index 7ce87773..0cedde4c 100644 --- a/test/importTest.js +++ b/test/importTest.js @@ -8,7 +8,7 @@ var testError = helpers.testError; describe("import", function() { test( - "import", + "url", "@import url(test.css);\n.class { a: b c d; }", [[2, ".test{a: b}", ""], [1, ".class { a: b c d; }", ""]], "", @@ -17,7 +17,16 @@ describe("import", function() { } ); test( - "import camelcase", + "url with quotes", + "@import url('test.css');\n.class { a: b c d; }", + [[2, ".test{a: b}", "screen"], [1, ".class { a: b c d; }", ""]], + "", + { + "./test.css": [[2, ".test{a: b}", "screen"]] + } + ); + test( + "at-rule in uppercase", "@IMPORT url(test.css);\n.class { a: b c d; }", [[2, ".test{a: b}", ""], [1, ".class { a: b c d; }", ""]], "", @@ -26,19 +35,28 @@ describe("import", function() { } ); test( - "import empty url", + "url in uppercase", + "@import URL(test.css);\n.class { a: b c d; }", + [[2, ".test{a: b}", ""], [1, ".class { a: b c d; }", ""]], + "", + { + "./test.css": [[2, ".test{a: b}", ""]] + } + ); + test( + "empty url", "@import url();\n.class { a: b c d; }", [[1, "@import url();\n.class { a: b c d; }", ""]], "" ); test( - "import empty url with quotes", + "empty url with quotes", "@import url('');\n.class { a: b c d; }", [[1, "@import url('');\n.class { a: b c d; }", ""]], "" ); test( - "import with string", + "string", '@import "test.css";\n.class { a: b c d; }', [[2, ".test{a: b}", ""], [1, ".class { a: b c d; }", ""]], "", @@ -47,63 +65,74 @@ describe("import", function() { } ); test( - "import with empty string", + "empty string", '@import "";\n.class { a: b c d; }', [[1, '@import "";\n.class { a: b c d; }', ""]], "" ); test( - "import with string contain spaces", + "string contain spaces", '@import " ";\n.class { a: b c d; }', [[1, '@import " ";\n.class { a: b c d; }', ""]], "" ); test( - "import with string contain newline", + "string contain newline", '@import "\n";\n.class { a: b c d; }', [[1, '@import "\n";\n.class { a: b c d; }', ""]], "" ); test( - "import with string contain CRLF", + "string contain CRLF", '@import "\r\n";\r\n.class { a: b c d; }', [[1, '@import "\r\n";\r\n.class { a: b c d; }', ""]], "" ); test( - "import with string contain tab", + "string contain tab", '@import "\t";\n.class { a: b c d; }', [[1, '@import "\t";\n.class { a: b c d; }', ""]], "" ); test( - "import 2", - "@import url('test.css');\n.class { a: b c d; }", - [[2, ".test{a: b}", "screen"], [1, ".class { a: b c d; }", ""]], + "duplicate", + "@import url(test.css);@import url(test.css);\n.class { a: b c d; }", + [[2, ".test{a: b}", ""], [1, ".class { a: b c d; }", ""]], "", { - "./test.css": [[2, ".test{a: b}", "screen"]] + "./test.css": [[2, ".test{a: b}", ""]] } ); test( - "import with media", - "@import url('~test/css') screen and print;\n.class { a: b c d; }", - [ - [3, ".test{a: b}", "((min-width: 100px)) and (screen and print)"], - [2, ".test{c: d}", "screen and print"], - [1, ".class { a: b c d; }", ""] - ], + "media", + "@import url(test.css) screen and print;\n.class { a: b c d; }", + [[2, ".test{a: b}", "screen and print"], [1, ".class { a: b c d; }", ""]], "", { - "test/css": [ - [3, ".test{a: b}", "(min-width: 100px)"], - [2, ".test{c: d}", ""] - ] + "./test.css": [[2, ".test{a: b}", ""]] + } + ); + test( + "media without space between url and media", + "@import url(test.css)screen and print;\n.class { a: b c d; }", + [[2, ".test{a: b}", "screen and print"], [1, ".class { a: b c d; }", ""]], + "", + { + "./test.css": [[2, ".test{a: b}", ""]] } ); test( - "import with media without space between url and media", - "@import url('~test/css')screen and print;\n.class { a: b c d; }", + "duplicate with same media", + "@import url(test.css) screen and print;@import url(test.css) screen and print;\n.class { a: b c d; }", + [[2, ".test{a: b}", "screen and print"], [1, ".class { a: b c d; }", ""]], + "", + { + "./test.css": [[2, ".test{a: b}", ""]] + } + ); + test( + "nested media", + "@import url('~test/css') screen and print;\n.class { a: b c d; }", [ [3, ".test{a: b}", "((min-width: 100px)) and (screen and print)"], [2, ".test{c: d}", "screen and print"], @@ -118,7 +147,7 @@ describe("import", function() { } ); test( - "import external", + "external", '@import url(http://example.com/style.css);\n@import url("//example.com/style.css");', [ [1, "@import url(http://example.com/style.css);", ""], @@ -127,15 +156,15 @@ describe("import", function() { ] ); test( - "import disabled", + "disabled", "@import url(test.css);\n.class { a: b c d; }", [[1, "@import url(test.css);\n.class { a: b c d; }", ""]], "?-import" ); - test("@import-normalize left untouched", "@import-normalize;", [ + test("non standard at-rule contain import word", "@import-normalize;", [ [1, "@import-normalize;", ""] ]); - testError("@import without url", "@import;", function(err) { + testError("without url", "@import;", function(err) { assert.equal( err.message, ["Unexpected format (1:1)", "", "> 1 | @import;", " | ^", ""].join( From f424b926e09e9bc0fc9971e83cf5c4cb406c454c Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Wed, 11 Jul 2018 20:36:05 +0300 Subject: [PATCH 20/45] refactor: `url` in lowercase --- lib/plugin.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/plugin.js b/lib/plugin.js index df48ffea..6b62d679 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -116,16 +116,16 @@ module.exports = postcss.plugin(pluginName, function(options) { return; } - const URLNode = node.nodes[0]; - const URL = URLNode.value.trim().replace(/\\[\r\n]/g, ""); + const urlNode = node.nodes[0]; + const url = urlNode.value.trim().replace(/\\[\r\n]/g, ""); // Skip empty URLs // Empty URL function equals request to current stylesheet where it is declared - if (URL.length === 0) { + if (url.length === 0) { return; } - if (!loaderUtils.isUrlRequest(URL)) { + if (!loaderUtils.isUrlRequest(url)) { return; } @@ -133,16 +133,16 @@ module.exports = postcss.plugin(pluginName, function(options) { node.before = ""; node.after = ""; - const splittedURL = URL.split(/(\?)?#/); + const splittedURL = url.split(/(\?)?#/); const normalizedURL = splittedURL[0]; const requestedURL = loaderUtils.urlToRequest(normalizedURL); const placeholder = "___CSS_LOADER_IMPORT_URL_PLACEHOLDER___" + index + "___"; - URLNode.value = placeholder; + urlNode.value = placeholder; // Strip quotes, they will be re-added if the module needs them - URLNode.quote = ""; + urlNode.quote = ""; let hasURLEscapeRuntimeCode = false; From 1aaecdda9ea2084d65430911dbf58f0569f9df45 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Wed, 11 Jul 2018 20:37:12 +0300 Subject: [PATCH 21/45] refactor: rename `modify-runtime` to `modify-runtime-code` --- lib/loader.js | 7 +++++-- lib/plugin.js | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/lib/loader.js b/lib/loader.js index 7ee6ce59..1162dd54 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -112,7 +112,10 @@ module.exports = function(content, map, meta) { if (result.messages && result.messages.length > 0) { newContent = result.messages - .filter(message => (message.type === "modify-runtime" ? message : false)) + .filter( + message => + message.type === "modify-runtime-code" ? message : false + ) .reduce((initialValue, message) => { try { initialValue = message.modifyRuntimeCode(this, initialValue); @@ -124,7 +127,7 @@ module.exports = function(content, map, meta) { }, newContent); } - const {imports, runtime, module, exports} = newContent; + const { imports, runtime, module, exports } = newContent; cb( null, diff --git a/lib/plugin.js b/lib/plugin.js index 6b62d679..6f5161e4 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -81,7 +81,7 @@ module.exports = postcss.plugin(pluginName, function(options) { if (!alreadyImported[url]) { result.messages.push({ pluginName, - type: "modify-runtime", + type: "modify-runtime-code", modifyRuntimeCode: (loaderContext, content) => { content.runtime = `${content.runtime}${runtimeCode}\n`; @@ -148,7 +148,7 @@ module.exports = postcss.plugin(pluginName, function(options) { result.messages.push({ pluginName, - type: "modify-runtime", + type: "modify-runtime-code", modifyRuntimeCode: (loaderContext, content) => { if (!hasURLEscapeRuntimeCode) { content.imports = `var runtimeEscape = require(${loaderUtils.stringifyRequest( From 45469b70989898b5cc7c977a87a99d7aa568508c Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Wed, 11 Jul 2018 20:57:02 +0300 Subject: [PATCH 22/45] refactor: `loader` and `plugin` --- lib/loader.js | 22 ++++++++++------------ lib/plugin.js | 24 ++++++++++++------------ 2 files changed, 22 insertions(+), 24 deletions(-) diff --git a/lib/loader.js b/lib/loader.js index 1162dd54..9e0de7cf 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -41,9 +41,9 @@ module.exports = function(content, map, meta) { const plugins = [ plugin({ + loaderContext: this, url: options.url !== false, import: options.import !== false, - loaderContext: this, importLoaders: options.importLoaders }) ]; @@ -98,7 +98,7 @@ module.exports = function(content, map, meta) { } // Todo need save backward compatibility with old `style-loader` and exports.locals - let newContent = { + let newContentObj = { imports: "", runtime: `module.exports = exports = require(${loaderUtils.stringifyRequest( this, @@ -111,31 +111,29 @@ module.exports = function(content, map, meta) { }; if (result.messages && result.messages.length > 0) { - newContent = result.messages + result.messages .filter( message => - message.type === "modify-runtime-code" ? message : false + message.type === "modify-generated-code" ? message : false ) - .reduce((initialValue, message) => { + .forEach((message) => { try { - initialValue = message.modifyRuntimeCode(this, initialValue); + newContentObj = message.modifyGeneratedCode(this, newContentObj); } catch (err) { this.emitError(err); } - - return initialValue; - }, newContent); + }); } - const { imports, runtime, module, exports } = newContent; + const { imports, runtime, module, exports } = newContentObj; cb( null, [ imports ? `// CSS imports\n${imports}` : "", runtime ? `// CSS runtime\n${runtime}` : "", - module ? `// CSS module\n${newContent.module}` : "", - exports ? `// CSS exports\n${newContent.exports}` : "" + module ? `// CSS module\n${module}` : "", + exports ? `// CSS exports\n${exports}` : "" ].join("\n") ); diff --git a/lib/plugin.js b/lib/plugin.js index 6f5161e4..55d8cafc 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -81,11 +81,11 @@ module.exports = postcss.plugin(pluginName, function(options) { if (!alreadyImported[url]) { result.messages.push({ pluginName, - type: "modify-runtime-code", - modifyRuntimeCode: (loaderContext, content) => { - content.runtime = `${content.runtime}${runtimeCode}\n`; + type: "modify-generated-code", + modifyGeneratedCode: (loaderContext, contentObj) => { + contentObj.runtime = `${contentObj.runtime}${runtimeCode}\n`; - return content; + return contentObj; } }); @@ -148,32 +148,32 @@ module.exports = postcss.plugin(pluginName, function(options) { result.messages.push({ pluginName, - type: "modify-runtime-code", - modifyRuntimeCode: (loaderContext, content) => { + type: "modify-generated-code", + modifyGeneratedCode: (loaderContext, contentObj) => { if (!hasURLEscapeRuntimeCode) { - content.imports = `var runtimeEscape = require(${loaderUtils.stringifyRequest( + contentObj.imports = `var runtimeEscape = require(${loaderUtils.stringifyRequest( loaderContext, require.resolve("./runtimeEscape.js") - )});\n${content.imports}`; + )});\n${contentObj.imports}`; hasURLEscapeRuntimeCode = true; } - content.imports = `${ - content.imports + contentObj.imports = `${ + contentObj.imports }var ${placeholder} = require(${loaderUtils.stringifyRequest( loaderContext, requestedURL )});\n`; - content.module = content.module.replace( + contentObj.module = contentObj.module.replace( placeholder, `" + runtimeEscape(${placeholder}) + "${ splittedURL[1] ? splittedURL[1] : "" }${splittedURL[2] ? `#${splittedURL[2]}` : ""}` ); - return content; + return contentObj; } }); From ede061dc57d864086ca82d7ea1b12b4040829d4b Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 12 Jul 2018 14:36:35 +0300 Subject: [PATCH 23/45] refactor: options --- lib/loader.js | 13 ++++++++----- lib/plugin.js | 15 +++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/lib/loader.js b/lib/loader.js index 9e0de7cf..6fbcad1b 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -15,6 +15,9 @@ module.exports = function(content, map, meta) { const cb = this.async(); const sourceMap = options.sourceMap || false; + const url = typeof options.url === "undefined" ? true : options.url; + const importOpt = typeof options.import === "undefined" ? true : options.import; + const importLoaders = options.importLoaders || 0; if (sourceMap && map) { if (typeof map === "string") { @@ -42,9 +45,9 @@ module.exports = function(content, map, meta) { const plugins = [ plugin({ loaderContext: this, - url: options.url !== false, - import: options.import !== false, - importLoaders: options.importLoaders + url, + import: importOpt, + importLoaders }) ]; @@ -114,11 +117,11 @@ module.exports = function(content, map, meta) { result.messages .filter( message => - message.type === "modify-generated-code" ? message : false + message.type === "modify-code" ? message : false ) .forEach((message) => { try { - newContentObj = message.modifyGeneratedCode(this, newContentObj); + newContentObj = message.modifyCode(this, newContentObj); } catch (err) { this.emitError(err); } diff --git a/lib/plugin.js b/lib/plugin.js index 55d8cafc..f9535edf 100644 --- a/lib/plugin.js +++ b/lib/plugin.js @@ -5,15 +5,10 @@ const loaderUtils = require("loader-utils"); const pluginName = "postcss-css-loader"; function getImportPrefix(loaderContext, importLoaders) { - if (importLoaders === false) { - return ""; - } - - const importLoadersValue = parseInt(importLoaders, 10) || 0; const loadersRequest = loaderContext.loaders .slice( loaderContext.loaderIndex, - loaderContext.loaderIndex + 1 + importLoadersValue + loaderContext.loaderIndex + 1 + importLoaders ) .map(x => x.request) .join("!"); @@ -81,8 +76,8 @@ module.exports = postcss.plugin(pluginName, function(options) { if (!alreadyImported[url]) { result.messages.push({ pluginName, - type: "modify-generated-code", - modifyGeneratedCode: (loaderContext, contentObj) => { + type: "modify-code", + modifyCode: (loaderContext, contentObj) => { contentObj.runtime = `${contentObj.runtime}${runtimeCode}\n`; return contentObj; @@ -148,8 +143,8 @@ module.exports = postcss.plugin(pluginName, function(options) { result.messages.push({ pluginName, - type: "modify-generated-code", - modifyGeneratedCode: (loaderContext, contentObj) => { + type: "modify-code", + modifyCode: (loaderContext, contentObj) => { if (!hasURLEscapeRuntimeCode) { contentObj.imports = `var runtimeEscape = require(${loaderUtils.stringifyRequest( loaderContext, From 9075cfc953b73b276e0ece6cf9bea5f120ca52d7 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 12 Jul 2018 15:03:01 +0300 Subject: [PATCH 24/45] feat: validate options --- lib/loader.js | 20 +- lib/options.json | 18 ++ package-lock.json | 530 +++++++++++++++++++++++++++++++++++++--------- package.json | 3 +- 4 files changed, 463 insertions(+), 108 deletions(-) create mode 100644 lib/options.json diff --git a/lib/loader.js b/lib/loader.js index 6fbcad1b..cbc03a63 100644 --- a/lib/loader.js +++ b/lib/loader.js @@ -3,6 +3,8 @@ Author Tobias Koppers @sokra */ +const schema = require("./options.json"); +const validate = require("@webpack-contrib/schema-utils"); const loaderUtils = require("loader-utils"); const postcss = require("postcss"); const plugin = require("./plugin"); @@ -11,13 +13,14 @@ const SyntaxError = require("./SyntaxError"); module.exports = function(content, map, meta) { const options = loaderUtils.getOptions(this) || {}; - // Todo validate options + validate({ name: "CSS Loader", schema, target: options }); const cb = this.async(); - const sourceMap = options.sourceMap || false; - const url = typeof options.url === "undefined" ? true : options.url; - const importOpt = typeof options.import === "undefined" ? true : options.import; - const importLoaders = options.importLoaders || 0; + const { url, import: importOpt, sourceMap, importLoaders } = Object.assign( + {}, + { url: true, import: true, sourceMap: false, importLoaders: 0 }, + loaderUtils.getOptions(this) || {} + ); if (sourceMap && map) { if (typeof map === "string") { @@ -115,11 +118,8 @@ module.exports = function(content, map, meta) { if (result.messages && result.messages.length > 0) { result.messages - .filter( - message => - message.type === "modify-code" ? message : false - ) - .forEach((message) => { + .filter(message => (message.type === "modify-code" ? message : false)) + .forEach(message => { try { newContentObj = message.modifyCode(this, newContentObj); } catch (err) { diff --git a/lib/options.json b/lib/options.json new file mode 100644 index 00000000..041673f3 --- /dev/null +++ b/lib/options.json @@ -0,0 +1,18 @@ +{ + "type": "object", + "properties": { + "url": { + "type": "boolean" + }, + "import": { + "type": "boolean" + }, + "sourceMap": { + "type": "boolean" + }, + "importLoaders": { + "type": "number" + } + }, + "additionalProperties": false +} diff --git a/package-lock.json b/package-lock.json index 94bf2809..7644202a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,19 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@webpack-contrib/schema-utils": { + "version": "1.0.0-beta.0", + "resolved": "https://registry.npmjs.org/@webpack-contrib/schema-utils/-/schema-utils-1.0.0-beta.0.tgz", + "integrity": "sha512-LonryJP+FxQQHsjGBi6W786TQB1Oym+agTpY0c+Kj8alnIw+DLUJb6SI8Y1GHGhLCH1yPRrucjObUmxNICQ1pg==", + "requires": { + "ajv": "^6.1.0", + "ajv-keywords": "^3.1.0", + "chalk": "^2.3.2", + "strip-ansi": "^4.0.0", + "text-table": "^0.2.0", + "webpack-log": "^1.1.2" + } + }, "JSONStream": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.3.tgz", @@ -44,22 +57,20 @@ } }, "ajv": { - "version": "5.5.2", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", - "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", - "dev": true, + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.2.tgz", + "integrity": "sha512-hOs7GfvI6tUI1LfZddH82ky6mOMyTuY0mk7kE2pWpmhhUSkumzaTO5vbVwij39MdwPQWCV4Zv57Eo06NtL/GVA==", "requires": { - "co": "^4.6.0", - "fast-deep-equal": "^1.0.0", + "fast-deep-equal": "^2.0.1", "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.3.0" + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.1" } }, "ajv-keywords": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", - "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", - "dev": true + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=" }, "align-text": { "version": "0.1.4", @@ -85,14 +96,17 @@ "dev": true }, "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" }, "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } }, "argparse": { "version": "1.0.10", @@ -186,6 +200,43 @@ "chalk": "^1.1.3", "esutils": "^2.0.2", "js-tokens": "^3.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=" + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + } } }, "balanced-match": { @@ -296,15 +347,13 @@ } }, "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" } }, "circular-json": { @@ -731,7 +780,6 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", - "dev": true, "requires": { "es5-ext": "^0.10.9" } @@ -799,6 +847,15 @@ "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", "dev": true }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "requires": { + "foreach": "^2.0.5", + "object-keys": "^1.0.8" + } + }, "del": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", @@ -894,7 +951,6 @@ "version": "0.10.45", "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.45.tgz", "integrity": "sha512-FkfM6Vxxfmztilbxxz5UKSD4ICMf5tSpRFtDNtkAhOxZ0EKtX6qwmXNyH/sFyIbX2P/nU5AMiA9jilWsUGJzCQ==", - "dev": true, "requires": { "es6-iterator": "~2.0.3", "es6-symbol": "~3.1.1", @@ -905,7 +961,6 @@ "version": "2.0.3", "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", - "dev": true, "requires": { "d": "1", "es5-ext": "^0.10.35", @@ -943,7 +998,6 @@ "version": "3.1.1", "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", - "dev": true, "requires": { "d": "1", "es5-ext": "~0.10.14" @@ -1055,6 +1109,48 @@ "table": "^3.7.8", "text-table": "~0.2.0", "user-home": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } } }, "espree": { @@ -1146,16 +1242,14 @@ "dev": true }, "fast-deep-equal": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", - "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", - "dev": true + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" }, "fast-json-stable-stringify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", - "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=", - "dev": true + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, "fast-levenshtein": { "version": "2.0.6", @@ -1212,6 +1306,11 @@ } } }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=" + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -1244,6 +1343,11 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, "generate-function": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.0.0.tgz", @@ -1260,9 +1364,9 @@ } }, "get-caller-file": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", - "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==", "dev": true }, "get-pkg-repo": { @@ -1513,6 +1617,32 @@ "requires": { "ajv": "^5.1.0", "har-schema": "^2.0.0" + }, + "dependencies": { + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "dev": true, + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", + "dev": true + } } }, "has-ansi": { @@ -1521,6 +1651,13 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "requires": { "ansi-regex": "^2.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + } } }, "has-flag": { @@ -1528,6 +1665,11 @@ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" }, + "has-symbols": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz", + "integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=" + }, "he": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz", @@ -1610,6 +1752,48 @@ "string-width": "^1.0.1", "strip-ansi": "^3.0.0", "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } } }, "interpret": { @@ -1880,10 +2064,9 @@ "dev": true }, "json-schema-traverse": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", - "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=", - "dev": true + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" }, "json-stable-stringify": { "version": "1.0.1", @@ -2121,6 +2304,23 @@ "lodash._reinterpolate": "~3.0.0" } }, + "log-symbols": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz", + "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==", + "requires": { + "chalk": "^2.0.1" + } + }, + "loglevelnext": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/loglevelnext/-/loglevelnext-1.0.5.tgz", + "integrity": "sha512-V/73qkPuJmx4BcBF19xPBr+0ZRVBhc4POxvZTZdMeXpJ4NItXSJ/MSwuFT0kQJlCbXvdlZoQQ/418bS1y9Jh6A==", + "requires": { + "es6-symbol": "^3.1.1", + "object.assign": "^4.1.0" + } + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -2350,8 +2550,7 @@ "next-tick": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", - "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=", - "dev": true + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" }, "nopt": { "version": "3.0.6", @@ -2407,6 +2606,22 @@ "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", "dev": true }, + "object-keys": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.12.tgz", + "integrity": "sha512-FTMyFUm2wBcGHnH2eXmz7tC6IwlqQZ6mVZ+6dm6vZ4IQIHjs6FdNsQBuKGPuUUUY6NfJw2PshC08Tn6LzLDOag==" + }, + "object.assign": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", + "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "requires": { + "define-properties": "^1.1.2", + "function-bind": "^1.1.1", + "has-symbols": "^1.0.0", + "object-keys": "^1.0.11" + } + }, "once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -2605,34 +2820,6 @@ "chalk": "^2.4.1", "source-map": "^0.6.1", "supports-color": "^5.4.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", - "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "supports-color": { - "version": "5.4.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", - "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", - "requires": { - "has-flag": "^3.0.0" - } - } } }, "postcss-value-parser": { @@ -2665,10 +2852,9 @@ "dev": true }, "punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", - "dev": true + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, "q": { "version": "1.5.1", @@ -3160,9 +3346,15 @@ }, "dependencies": { "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", "dev": true }, "camelcase": { @@ -3171,6 +3363,19 @@ "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=", "dev": true }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", @@ -3262,6 +3467,12 @@ "strip-ansi": "^4.0.0" }, "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -3279,6 +3490,21 @@ } } }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, "yargs": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", @@ -3311,6 +3537,23 @@ "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } } }, "string_decoder": { @@ -3323,11 +3566,11 @@ } }, "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "^3.0.0" } }, "strip-bom": { @@ -3355,9 +3598,12 @@ "dev": true }, "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=" + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "requires": { + "has-flag": "^3.0.0" + } }, "table": { "version": "3.8.3", @@ -3383,12 +3629,37 @@ "json-stable-stringify": "^1.0.1" } }, + "ajv-keywords": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-1.5.1.tgz", + "integrity": "sha1-MU3QpLM2j609/NxU7eYXG4htrzw=", + "dev": true + }, "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", "dev": true }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -3403,16 +3674,39 @@ "requires": { "is-fullwidth-code-point": "^2.0.0", "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } } }, "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "^3.0.0" + "ansi-regex": "^2.0.0" } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true } } }, @@ -3434,8 +3728,7 @@ "text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", - "dev": true + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=" }, "through": { "version": "2.3.8", @@ -3460,6 +3753,14 @@ "dev": true, "requires": { "punycode": "^1.4.1" + }, + "dependencies": { + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=", + "dev": true + } } }, "trim-newlines": { @@ -3533,6 +3834,14 @@ "dev": true, "optional": true }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "requires": { + "punycode": "^2.1.0" + } + }, "urlgrey": { "version": "0.4.4", "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz", @@ -3557,8 +3866,7 @@ "uuid": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", - "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==", - "dev": true + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" }, "validate-npm-package-license": { "version": "3.0.3", @@ -3581,6 +3889,17 @@ "extsprintf": "^1.2.0" } }, + "webpack-log": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-1.2.0.tgz", + "integrity": "sha512-U9AnICnu50HXtiqiDxuli5gLB5PGBo7VvcHx36jRZHwK4vzOYLbImqT4lwWwoMHdQWwEKw736fCHEekokTEKHA==", + "requires": { + "chalk": "^2.1.0", + "log-symbols": "^2.1.0", + "loglevelnext": "^1.0.1", + "uuid": "^3.1.0" + } + }, "which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", @@ -3617,6 +3936,23 @@ "requires": { "string-width": "^1.0.1", "strip-ansi": "^3.0.1" + }, + "dependencies": { + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + } } }, "wrappy": { diff --git a/package.json b/package.json index 9d0fa844..2d1b9abc 100644 --- a/package.json +++ b/package.json @@ -15,7 +15,8 @@ "babel-code-frame": "^6.26.0", "loader-utils": "^1.0.2", "postcss": "^6.0.23", - "postcss-value-parser": "^3.3.0" + "postcss-value-parser": "^3.3.0", + "@webpack-contrib/schema-utils": "^1.0.0-beta.0" }, "devDependencies": { "codecov": "^1.0.1", From 99ffe874578ecb10e2e20229830b2f4b3f35a1b4 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 12 Jul 2018 15:17:51 +0300 Subject: [PATCH 25/45] tests: escaped characters --- test/simpleTest.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/test/simpleTest.js b/test/simpleTest.js index 696daf1c..1ff9d441 100644 --- a/test/simpleTest.js +++ b/test/simpleTest.js @@ -13,6 +13,21 @@ describe("simple", function() { test("escaped selector", ".u-m\\+ { a: b c d; }", [ [1, ".u-m\\+ { a: b c d; }", ""] ]); + test("escaped selector (2)", ".grid.\\-top { a: b c d; }", [ + [1, ".grid.\\-top { a: b c d; }", ""] + ]); + test("escaped selector (3)", ".u-m\\00002b { a: b c d; }", [ + [1, ".u-m\\00002b { a: b c d; }", ""] + ]); + test("escaped characters", '.class { content: \'"\\\\f10c"\'; }', [ + [1, '.class { content: \'"\\\\f10c"\'; }', ""] + ]); + test("escaped characters (2)", '.class { font-family: \'微软雅黑\'; }', [ + [1, '.class { font-family: \'微软雅黑\'; }', ""] + ]); + test("escaped characters (3)", '.class { content: \'\\e901\'; }', [ + [1, '.class { content: \'\\e901\'; }', ""] + ]); test("escaped characters (uppercase)", '.class { content: "\\F10C" }', [ [1, '.class { content: "\\F10C" }', ""] ]); From 81d104a840339e800d34f6981be369526bd53875 Mon Sep 17 00:00:00 2001 From: evilebottnawi Date: Thu, 12 Jul 2018 17:11:07 +0300 Subject: [PATCH 26/45] refactor: webpack-defaults --- .babelrc | 35 + .circleci/config.yml | 156 + .editorconfig | 13 + .eslintignore | 2 + .eslintrc.js | 11 + .eslintrc.yml | 247 - .gitattributes | 1 + .github/CODEOWNERS | 6 + .github/CONTRIBUTING.md | 124 + .github/ISSUE_TEMPLATE.md | 25 +- .github/ISSUE_TEMPLATE/BUG.md | 51 + .github/ISSUE_TEMPLATE/DOCS.md | 30 + .github/ISSUE_TEMPLATE/FEATURE.md | 28 + .github/ISSUE_TEMPLATE/MODIFICATION.md | 33 + .github/ISSUE_TEMPLATE/SUPPORT.md | 9 + .github/PULL_REQUEST_TEMPLATE.md | 39 +- .gitignore | 17 + .prettierrc | 5 + .travis.yml | 29 - README.md | 280 +- appveyor.yml | 30 + codecov.yml | 10 + commitlint.config.js | 32 + index.js | 5 - lib/SyntaxError.js | 23 - lib/loader.js | 154 - lib/plugin.js | 185 - package-lock.json | 15874 +++++++++++++--- package.json | 104 +- src/SyntaxError.js | 24 + src/cjs.js | 4 + src/index.js | 171 + {lib => src}/options.json | 0 src/plugin.js | 202 + {lib => src}/runtime.js | 14 +- {lib => src}/runtimeEscape.js | 6 +- test/SyntaxError.test.js | 39 + test/__snapshots__/SyntaxError.test.js.snap | 21 + test/__snapshots__/import-option.test.js.snap | 584 + test/__snapshots__/loader.test.js.snap | 421 + .../source-map-option.test.js.snap | 138 + test/__snapshots__/url-option.test.js.snap | 365 + test/cjs.test.js | 10 + test/cssBaseTest.js | 90 - test/fixtures/basic.css | 47 + test/fixtures/basic.js | 4 + test/fixtures/broken.css | 3 + test/fixtures/broken.js | 4 + test/fixtures/empty.css | 0 test/fixtures/empty.js | 4 + .../import/at-rule-import-in-uppercase.css | 5 + .../import/duplicate-with-same-media.css | 6 + test/fixtures/import/duplicate.css | 6 + test/fixtures/import/empty-string.css | 5 + .../import/empty-url-with-double-quotes.css | 5 + .../import/empty-url-with-single-quotes.css | 5 + test/fixtures/import/empty-url.css | 5 + test/fixtures/import/external.css | 6 + test/fixtures/import/from-modules.css | 5 + test/fixtures/import/invalid.css | 5 + test/fixtures/import/media-nested.css | 5 + ...hout-space-between-url-and-media-query.css | 5 + test/fixtures/import/media.css | 5 + .../fixtures/import/multiple-with-media-2.css | 6 + test/fixtures/import/multiple-with-media.css | 6 + test/fixtures/import/multiple.css | 6 + .../import/node_modules/package/test.css | 3 + ...-standard-at-rule-contains-import-word.css | 5 + .../import/string-contains-spaces.css | 5 + test/fixtures/import/string.css | 5 + test/fixtures/import/test-media.css | 5 + test/fixtures/import/test-other.css | 3 + test/fixtures/import/test.css | 3 + .../import/url-function-in-uppercase.css | 5 + .../import/url-with-double-quotes.css | 5 + .../import/url-with-single-quotes.css | 5 + test/fixtures/import/url.css | 5 + test/fixtures/postcss-present-env.css | 39 + test/fixtures/source-map-loader.js | 5 + test/fixtures/source-map/basic.css | 3 + test/fixtures/url/font.eot | 0 test/fixtures/url/font.svg | 0 test/fixtures/url/font.woff | 0 test/fixtures/url/font.woff2 | 0 test/fixtures/url/img img.png | 0 test/fixtures/url/img.png | Bin 0 -> 78117 bytes test/fixtures/url/img2x.png | Bin 0 -> 78117 bytes .../url/node_modules/package/font.ttf | 0 .../fixtures/url/node_modules/package/img.png | Bin 0 -> 78117 bytes test/fixtures/url/other-img.png | Bin 0 -> 78117 bytes test/fixtures/url/url.css | 170 + test/helpers.js | 184 - test/helpers/compiler.js | 80 + test/helpers/evaluated.js | 78 + test/import-option.test.js | 278 + test/importTest.js | 175 - test/loader.test.js | 275 + test/runtime.test.js | 84 + test/runtimeEscape.test.js | 17 + test/simpleTest.js | 60 - test/source-map-option.test.js | 138 + test/sourceMapTest.js | 292 - test/url-option.test.js | 35 + test/urlTest.js | 546 - 104 files changed, 17284 insertions(+), 5019 deletions(-) create mode 100644 .babelrc create mode 100644 .circleci/config.yml create mode 100644 .editorconfig create mode 100644 .eslintignore create mode 100644 .eslintrc.js delete mode 100644 .eslintrc.yml create mode 100644 .github/CODEOWNERS create mode 100644 .github/CONTRIBUTING.md create mode 100644 .github/ISSUE_TEMPLATE/BUG.md create mode 100644 .github/ISSUE_TEMPLATE/DOCS.md create mode 100644 .github/ISSUE_TEMPLATE/FEATURE.md create mode 100644 .github/ISSUE_TEMPLATE/MODIFICATION.md create mode 100644 .github/ISSUE_TEMPLATE/SUPPORT.md create mode 100644 .prettierrc delete mode 100644 .travis.yml create mode 100644 appveyor.yml create mode 100644 codecov.yml create mode 100644 commitlint.config.js delete mode 100644 index.js delete mode 100644 lib/SyntaxError.js delete mode 100644 lib/loader.js delete mode 100644 lib/plugin.js create mode 100644 src/SyntaxError.js create mode 100644 src/cjs.js create mode 100644 src/index.js rename {lib => src}/options.json (100%) create mode 100644 src/plugin.js rename {lib => src}/runtime.js (86%) rename {lib => src}/runtimeEscape.js (73%) create mode 100644 test/SyntaxError.test.js create mode 100644 test/__snapshots__/SyntaxError.test.js.snap create mode 100644 test/__snapshots__/import-option.test.js.snap create mode 100644 test/__snapshots__/loader.test.js.snap create mode 100644 test/__snapshots__/source-map-option.test.js.snap create mode 100644 test/__snapshots__/url-option.test.js.snap create mode 100644 test/cjs.test.js delete mode 100644 test/cssBaseTest.js create mode 100644 test/fixtures/basic.css create mode 100644 test/fixtures/basic.js create mode 100644 test/fixtures/broken.css create mode 100644 test/fixtures/broken.js create mode 100644 test/fixtures/empty.css create mode 100644 test/fixtures/empty.js create mode 100644 test/fixtures/import/at-rule-import-in-uppercase.css create mode 100644 test/fixtures/import/duplicate-with-same-media.css create mode 100644 test/fixtures/import/duplicate.css create mode 100644 test/fixtures/import/empty-string.css create mode 100644 test/fixtures/import/empty-url-with-double-quotes.css create mode 100644 test/fixtures/import/empty-url-with-single-quotes.css create mode 100644 test/fixtures/import/empty-url.css create mode 100644 test/fixtures/import/external.css create mode 100644 test/fixtures/import/from-modules.css create mode 100644 test/fixtures/import/invalid.css create mode 100644 test/fixtures/import/media-nested.css create mode 100644 test/fixtures/import/media-without-space-between-url-and-media-query.css create mode 100644 test/fixtures/import/media.css create mode 100644 test/fixtures/import/multiple-with-media-2.css create mode 100644 test/fixtures/import/multiple-with-media.css create mode 100644 test/fixtures/import/multiple.css create mode 100644 test/fixtures/import/node_modules/package/test.css create mode 100644 test/fixtures/import/not-standard-at-rule-contains-import-word.css create mode 100644 test/fixtures/import/string-contains-spaces.css create mode 100644 test/fixtures/import/string.css create mode 100644 test/fixtures/import/test-media.css create mode 100644 test/fixtures/import/test-other.css create mode 100644 test/fixtures/import/test.css create mode 100644 test/fixtures/import/url-function-in-uppercase.css create mode 100644 test/fixtures/import/url-with-double-quotes.css create mode 100644 test/fixtures/import/url-with-single-quotes.css create mode 100644 test/fixtures/import/url.css create mode 100644 test/fixtures/postcss-present-env.css create mode 100644 test/fixtures/source-map-loader.js create mode 100644 test/fixtures/source-map/basic.css create mode 100644 test/fixtures/url/font.eot create mode 100644 test/fixtures/url/font.svg create mode 100644 test/fixtures/url/font.woff create mode 100644 test/fixtures/url/font.woff2 create mode 100644 test/fixtures/url/img img.png create mode 100644 test/fixtures/url/img.png create mode 100644 test/fixtures/url/img2x.png create mode 100644 test/fixtures/url/node_modules/package/font.ttf create mode 100644 test/fixtures/url/node_modules/package/img.png create mode 100644 test/fixtures/url/other-img.png create mode 100644 test/fixtures/url/url.css delete mode 100644 test/helpers.js create mode 100644 test/helpers/compiler.js create mode 100644 test/helpers/evaluated.js create mode 100644 test/import-option.test.js delete mode 100644 test/importTest.js create mode 100644 test/loader.test.js create mode 100644 test/runtime.test.js create mode 100644 test/runtimeEscape.test.js delete mode 100644 test/simpleTest.js create mode 100644 test/source-map-option.test.js delete mode 100644 test/sourceMapTest.js create mode 100644 test/url-option.test.js delete mode 100644 test/urlTest.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 00000000..e9675a27 --- /dev/null +++ b/.babelrc @@ -0,0 +1,35 @@ +{ + "presets": [ + [ + "env", + { + "useBuiltIns": true, + "targets": { + "node": "6.9.0" + }, + "exclude": [ + "transform-async-to-generator", + "transform-regenerator" + ] + } + ] + ], + "plugins": [ + [ + "transform-object-rest-spread", + { + "useBuiltIns": true + } + ] + ], + "env": { + "test": { + "presets": [ + "env" + ], + "plugins": [ + "transform-object-rest-spread" + ] + } + } +} \ No newline at end of file diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 00000000..d36940bd --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,156 @@ +unit_tests: &unit_tests + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package-lock.json" }} + - run: + name: NPM Rebuild + command: npm install + - run: + name: Run unit tests. + command: npm run ci:test +canary_tests: &canary_tests + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package-lock.json" }} + - run: + name: NPM Rebuild + command: npm install + - run: + name: Install Webpack Canary + command: npm i --no-save webpack@next + - run: + name: Run unit tests. + command: if [[ $(compver --name webpack --gte next --lt latest) < 1 ]] ; then printf "Next is older than Latest - Skipping Canary Suite"; else npm run ci:test ; fi + +version: 2 +jobs: + dependency_cache: + docker: + - image: webpackcontrib/circleci-node-base:latest + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package-lock.json" }} + - run: + name: Install Dependencies + command: npm install + - save_cache: + key: dependency-cache-{{ checksum "package-lock.json" }} + paths: + - ./node_modules + + node8-latest: + docker: + - image: webpackcontrib/circleci-node8:latest + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package-lock.json" }} + - run: + name: NPM Rebuild + command: npm install + - run: + name: Run unit tests. + command: npm run ci:coverage + - run: + name: Submit coverage data to codecov. + command: bash <(curl -s https://codecov.io/bash) + when: on_success + node6-latest: + docker: + - image: webpackcontrib/circleci-node6:latest + <<: *unit_tests + node9-latest: + docker: + - image: webpackcontrib/circleci-node9:latest + <<: *unit_tests + node8-canary: + docker: + - image: webpackcontrib/circleci-node8:latest + <<: *canary_tests + analysis: + docker: + - image: webpackcontrib/circleci-node-base:latest + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package-lock.json" }} + - run: + name: NPM Rebuild + command: npm install + - run: + name: Run linting. + command: npm run lint + - run: + name: Run NSP Security Check. + command: npm run security + - run: + name: Validate Commit Messages + command: npm run ci:lint:commits + publish: + docker: + - image: webpackcontrib/circleci-node-base:latest + steps: + - checkout + - restore_cache: + key: dependency-cache-{{ checksum "package-lock.json" }} + - run: + name: NPM Rebuild + command: npm install + # - run: + # name: Validate Commit Messages + # command: npm run release:validate + - run: + name: Publish to NPM + command: printf "noop running conventional-github-releaser" + +version: 2.0 +workflows: + version: 2 + validate-publish: + jobs: + - dependency_cache + - node6-latest: + requires: + - dependency_cache + filters: + tags: + only: /.*/ + - analysis: + requires: + - dependency_cache + filters: + tags: + only: /.*/ + - node8-latest: + requires: + - analysis + - node6-latest + filters: + tags: + only: /.*/ + - node9-latest: + requires: + - analysis + - node6-latest + filters: + tags: + only: /.*/ + - node8-canary: + requires: + - analysis + - node6-latest + filters: + tags: + only: /.*/ + - publish: + requires: + - node8-latest + - node8-canary + - node9-latest + filters: + branches: + only: + - master diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..45946eaa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,13 @@ +# editorconfig.org + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.md] +insert_final_newline = false +trim_trailing_whitespace = false diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 00000000..b2d59d1f --- /dev/null +++ b/.eslintignore @@ -0,0 +1,2 @@ +/node_modules +/dist \ No newline at end of file diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 00000000..f5064a31 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,11 @@ +module.exports = { + root: true, + plugins: ['prettier'], + extends: ['@webpack-contrib/eslint-config-webpack'], + rules: { + 'prettier/prettier': [ + 'error', + { singleQuote: true, trailingComma: 'es5', arrowParens: 'always' }, + ], + }, +}; diff --git a/.eslintrc.yml b/.eslintrc.yml deleted file mode 100644 index 7ea3f69a..00000000 --- a/.eslintrc.yml +++ /dev/null @@ -1,247 +0,0 @@ -env: - es6: true - node: true -extends: 'eslint:recommended' -parserOptions: - sourceType: module -rules: - accessor-pairs: error - array-bracket-spacing: 'off' - array-callback-return: error - arrow-body-style: error - arrow-parens: 'off' - arrow-spacing: error - block-scoped-var: 'off' - block-spacing: - - error - - always - brace-style: - - error - - 1tbs - - allowSingleLine: true - callback-return: 'off' - camelcase: - - error - - properties: never - capitalized-comments: 'off' - class-methods-use-this: error - comma-dangle: 'off' - comma-spacing: - - error - - after: true - before: false - comma-style: - - error - - last - complexity: error - computed-property-spacing: - - error - - never - consistent-return: 'off' - consistent-this: 'off' - curly: 'off' - default-case: 'off' - dot-location: 'off' - dot-notation: - - error - - allowKeywords: true - eol-last: error - eqeqeq: 'off' - func-call-spacing: error - func-name-matching: 'off' - func-names: 'off' - func-style: - - error - - declaration - generator-star-spacing: error - global-require: 'off' - guard-for-in: error - handle-callback-err: error - id-blacklist: error - id-length: 'off' - id-match: error - indent: 'off' - init-declarations: 'off' - jsx-quotes: error - key-spacing: error - keyword-spacing: 'off' - line-comment-position: 'off' - linebreak-style: - - error - - unix - lines-around-comment: error - lines-around-directive: error - max-depth: error - max-len: 'off' - max-lines: error - max-nested-callbacks: error - max-params: 'off' - max-statements: 'off' - max-statements-per-line: error - multiline-ternary: 'off' - new-cap: error - new-parens: error - newline-after-var: 'off' - newline-before-return: 'off' - newline-per-chained-call: 'off' - no-alert: error - no-array-constructor: error - no-await-in-loop: error - no-bitwise: error - no-caller: error - no-catch-shadow: error - no-confusing-arrow: 'off' - no-continue: error - no-div-regex: error - no-duplicate-imports: error - no-else-return: 'off' - no-empty-function: error - no-eq-null: 'off' - no-eval: error - no-extend-native: error - no-extra-bind: error - no-extra-label: error - no-extra-parens: 'off' - no-floating-decimal: error - no-implicit-globals: error - no-implied-eval: error - no-inline-comments: 'off' - no-inner-declarations: - - error - - functions - no-invalid-this: 'off' - no-iterator: error - no-label-var: error - no-labels: error - no-lone-blocks: error - no-lonely-if: error - no-loop-func: error - no-magic-numbers: 'off' - no-mixed-operators: error - no-mixed-requires: error - no-multi-assign: error - no-multi-spaces: 'off' - no-multi-str: error - no-multiple-empty-lines: error - no-native-reassign: error - no-negated-condition: 'off' - no-negated-in-lhs: error - no-nested-ternary: error - no-new: error - no-new-func: error - no-new-object: error - no-new-require: error - no-new-wrappers: error - no-octal-escape: error - no-param-reassign: 'off' - no-path-concat: error - no-plusplus: - - error - - allowForLoopAfterthoughts: true - no-process-env: error - no-process-exit: error - no-proto: error - no-prototype-builtins: error - no-restricted-globals: error - no-restricted-imports: error - no-restricted-modules: error - no-restricted-properties: error - no-restricted-syntax: error - no-return-assign: error - no-return-await: error - no-script-url: error - no-self-compare: error - no-sequences: error - no-shadow: error - no-shadow-restricted-names: error - no-spaced-func: error - no-sync: 'off' - no-tabs: 'off' - no-template-curly-in-string: error - no-ternary: 'off' - no-throw-literal: error - no-trailing-spaces: - - error - - skipBlankLines: true - no-undef-init: error - no-undefined: 'off' - no-underscore-dangle: error - no-unmodified-loop-condition: error - no-unneeded-ternary: error - no-unused-expressions: error - no-use-before-define: 'off' - no-useless-call: error - no-useless-computed-key: error - no-useless-concat: error - no-useless-constructor: error - no-useless-escape: error - no-useless-rename: error - no-useless-return: 'off' - no-var: 'off' - no-void: error - no-warning-comments: error - no-whitespace-before-property: error - no-with: error - object-curly-newline: 'off' - object-curly-spacing: 'off' - object-property-newline: - - error - - allowMultiplePropertiesPerLine: true - object-shorthand: 'off' - one-var: 'off' - one-var-declaration-per-line: error - operator-assignment: error - operator-linebreak: 'off' - padded-blocks: 'off' - prefer-arrow-callback: 'off' - prefer-const: error - prefer-destructuring: - - error - - array: false - object: false - prefer-numeric-literals: error - prefer-promise-reject-errors: error - prefer-reflect: 'off' - prefer-rest-params: error - prefer-spread: error - prefer-template: 'off' - quote-props: 'off' - quotes: 'off' - radix: - - error - - always - require-await: error - require-jsdoc: 'off' - rest-spread-spacing: error - semi: 'off' - semi-spacing: - - error - - after: true - before: false - sort-imports: error - sort-keys: 'off' - sort-vars: error - space-before-blocks: 'off' - space-before-function-paren: 'off' - space-in-parens: - - error - - never - space-infix-ops: error - space-unary-ops: error - spaced-comment: 'off' - strict: error - symbol-description: error - template-curly-spacing: error - unicode-bom: - - error - - never - valid-jsdoc: error - vars-on-top: 'off' - wrap-iife: - - error - - any - wrap-regex: 'off' - yield-star-spacing: error - yoda: - - error - - never diff --git a/.gitattributes b/.gitattributes index b1c30adb..543a250a 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,3 +1,4 @@ yarn.lock -diff * text=auto bin/* eol=lf +package-lock.json -diff diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..a3cedd77 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,6 @@ +# These are the default owners for everything in +# webpack-contrib +@webpack-contrib/org-maintainers + +# Add repository specific users / groups +# below here for libs that are not maintained by the org. \ No newline at end of file diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md new file mode 100644 index 00000000..e69279a5 --- /dev/null +++ b/.github/CONTRIBUTING.md @@ -0,0 +1,124 @@ +## Contributing in @webpack-contrib + +We'd always love contributions to further improve the webpack / webpack-contrib ecosystem! +Here are the guidelines we'd like you to follow: + +* [Questions and Problems](#question) +* [Issues and Bugs](#issue) +* [Feature Requests](#feature) +* [Pull Request Submission Guidelines](#submit-pr) +* [Commit Message Conventions](#commit) + +### Got a Question or Problem? + +Please submit support requests and questions to StackOverflow using the tag [[webpack]](http://stackoverflow.com/tags/webpack). +StackOverflow is better suited for this kind of support though you may also inquire in [Webpack Gitter](https://gitter.im/webpack/webpack). +The issue tracker is for bug reports and feature discussions. + +### Found an Issue or Bug? + +Before you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available. + +We want to fix all the issues as soon as possible, but before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs, we ask that you to provide a minimal reproduction scenario (github repo or failing test case). Having a live, reproducible scenario gives us a wealth of important information without going back & forth to you with additional questions like: + +- version of Webpack used +- version of the loader / plugin you are creating a bug report for +- the use-case that fails + +A minimal reproduce scenario allows us to quickly confirm a bug (or point out config problems) as well as confirm that we are fixing the right problem. + +We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it. + +Unfortunately, we are not able to investigate / fix bugs without a minimal reproduction, so if we don't hear back from you we are going to close an issue that doesn't have enough info to be reproduced. + +### Feature Requests? + +You can *request* a new feature by creating an issue on Github. + +If you would like to *implement* a new feature, please submit an issue with a proposal for your work `first`, to be sure that particular makes sense for the project. + +### Pull Request Submission Guidelines + +Before you submit your Pull Request (PR) consider the following guidelines: + +- Search Github for an open or closed PR that relates to your submission. You don't want to duplicate effort. +- Commit your changes using a descriptive commit message that follows our [commit message conventions](#commit). Adherence to these conventions is necessary because release notes are automatically generated from these messages. +- Fill out our `Pull Request Template`. Your pull request will not be considered if it is ignored. +- Please sign the `Contributor License Agreement (CLA)` when a pull request is opened. We cannot accept your pull request without this. Make sure you sign with the primary email address associated with your local / github account. + +### Webpack Contrib Commit Conventions + +Each commit message consists of a **header**, a **body** and a **footer**. The header has a special +format that includes a **type**, a **scope** and a **subject**: + +``` +(): + + + +