css-loader 0.27.1 → 0.28.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,45 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ <a name="0.28.1"></a>
6
+ ## [0.28.1](https://github.com/webpack/css-loader/compare/v0.28.0...v0.28.1) (2017-05-02)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * allow to specify a full hostname as a root URL ([#521](https://github.com/webpack/css-loader/issues/521)) ([06d27a1](https://github.com/webpack/css-loader/commit/06d27a1))
12
+ * case insensitivity of [@import](https://github.com/import) ([#514](https://github.com/webpack/css-loader/issues/514)) ([de4356b](https://github.com/webpack/css-loader/commit/de4356b))
13
+ * don't handle empty [@import](https://github.com/import) and url() ([#513](https://github.com/webpack/css-loader/issues/513)) ([868fc94](https://github.com/webpack/css-loader/commit/868fc94))
14
+ * imported variables are replaced in exports if followed by a comma ([#504](https://github.com/webpack/css-loader/issues/504)) ([956bad7](https://github.com/webpack/css-loader/commit/956bad7))
15
+ * loader now correctly handles `url` with space(s) ([#495](https://github.com/webpack/css-loader/issues/495)) ([534ea55](https://github.com/webpack/css-loader/commit/534ea55))
16
+ * url with a trailing space is now handled correctly ([#494](https://github.com/webpack/css-loader/issues/494)) ([e1ec4f2](https://github.com/webpack/css-loader/commit/e1ec4f2))
17
+ * use `btoa` instead `Buffer` ([#501](https://github.com/webpack/css-loader/issues/501)) ([fbb0714](https://github.com/webpack/css-loader/commit/fbb0714))
18
+
19
+
20
+ ### Performance Improvements
21
+
22
+ * generate source maps only when explicitly set ([#478](https://github.com/webpack/css-loader/issues/478)) ([b8f5c8f](https://github.com/webpack/css-loader/commit/b8f5c8f))
23
+
24
+
25
+
26
+ <a name="0.28.0"></a>
27
+ # [0.28.0](https://github.com/webpack/css-loader/compare/v0.27.3...v0.28.0) (2017-03-30)
28
+
29
+
30
+ ### Features
31
+
32
+ * add alias feature to rewrite URLs ([#274](https://github.com/webpack/css-loader/issues/274)) ([c8db489](https://github.com/webpack/css-loader/commit/c8db489))
33
+
34
+
35
+
36
+ <a name="0.27.3"></a>
37
+ ## [0.27.3](https://github.com/webpack/css-loader/compare/v0.27.2...v0.27.3) (2017-03-13)
38
+
39
+
40
+
41
+ <a name="0.27.2"></a>
42
+ # [0.27.2](https://github.com/webpack/css-loader/compare/v0.27.1...v0.27.2) (2017-03-12)
43
+
5
44
  <a name="0.27.1"></a>
6
45
  # [0.27.1](https://github.com/webpack/css-loader/compare/v0.27.0...v0.27.1) (2017-03-10)
7
46
 
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![chat][chat]][chat-url]
7
7
 
8
8
  <div align="center">
9
- <img width="200" height="200"
9
+ <img width="180" height="180" vspace="20"
10
10
  src="https://cdn.worldvectorlogo.com/logos/css-3.svg">
11
11
  <a href="https://github.com/webpack/webpack">
12
12
  <img width="200" height="200"
@@ -23,11 +23,16 @@ npm install --save-dev css-loader
23
23
 
24
24
  <h2 align="center">Usage</h2>
25
25
 
26
- The `css-loader` interprets `@import` and `url()` like `requires`.
26
+ The `css-loader` interprets `@import` and `url()` like `import/require()`
27
+ and will resolve them.
27
28
 
28
- Use the loader either via your webpack config, CLI or inline.
29
+ Good loaders for requiring your assets are the [file-loader](https://github.com/webpack/file-loader)
30
+ and the [url-loader](https://github.com/webpack/url-loader) which you should specify in your config (see [below](https://github.com/michael-ciniawsky/css-loader#assets)).
29
31
 
30
- ### Via webpack config (recommended)
32
+ **file.css**
33
+ ```js
34
+ import css from 'file.css';
35
+ ```
31
36
 
32
37
  **webpack.config.js**
33
38
  ```js
@@ -43,108 +48,155 @@ module.exports = {
43
48
  }
44
49
  ```
45
50
 
46
- **In your application**
47
- ```js
48
- import css from 'file.css';
49
- ```
51
+ ### `toString`
50
52
 
51
- ### CLI
53
+ You can also use the css-loader results directly as string, such as in Angular's component style.
52
54
 
53
- ```bash
54
- webpack --module-bind 'css=style-loader!css-loader'
55
+ **webpack.config.js**
56
+ ```js
57
+ {
58
+    test: /\.css$/,
59
+    use: [
60
+      'to-string-loader',
61
+ 'css-loader'
62
+    ]
63
+ }
55
64
  ```
56
65
 
57
- **In your application**
66
+ or
67
+
58
68
  ```js
59
- import css from 'file.css';
69
+ const css = require('./test.css').toString();
70
+
71
+ console.log(css); // {String}
60
72
  ```
61
73
 
62
- ### Inline
74
+ If there are SourceMaps, they will also be included in the result string.
75
+
76
+ If, for one reason or another, you need to extract CSS as a
77
+ plain string resource (i.e. not wrapped in a JS module) you
78
+ might want to check out the [extract-loader](https://github.com/peerigon/extract-loader).
79
+ It's useful when you, for instance, need to post process the CSS as a string.
63
80
 
64
- **In your application**
81
+ **webpack.config.js**
65
82
  ```js
66
- import css from 'style-loader!css-loader!./file.css';
83
+ {
84
+    test: /\.css$/,
85
+    use: [
86
+ 'handlebars-loader', // handlebars loader expects raw resource string
87
+      'extract-loader',
88
+ 'css-loader'
89
+    ]
90
+ }
67
91
  ```
68
92
 
69
93
  <h2 align="center">Options</h2>
70
94
 
71
- `@import` and `url()` are interpreted like `import` and will be resolved by the css-loader.
72
- Good loaders for requiring your assets are the [file-loader](https://github.com/webpack/file-loader)
73
- and the [url-loader](https://github.com/webpack/url-loader) which you should specify in your config (see below).
74
-
75
- To be compatible with existing css files (if not in CSS Module mode):
95
+ |Name|Type|Default|Description|
96
+ |:--:|:--:|:-----:|:----------|
97
+ |**`root`**|`{String}`|`/`|Path to resolve URLs, URLs starting with `/` will not be translated|
98
+ |**`url`**|`{Boolean}`|`true`| Enable/Disable `url()` handling|
99
+ |**`alias`**|`{Object}`|`{}`|Create aliases to import certain modules more easily|
100
+ |**`import`** |`{Boolean}`|`true`| Enable/Disable @import handling|
101
+ |**`modules`**|`{Boolean}`|`false`|Enable/Disable CSS Modules|
102
+ |**`minimize`**|`{Boolean\|Object}`|`false`|Enable/Disable minification|
103
+ |**`sourceMap`**|`{Boolean}`|`false`|Enable/Disable Sourcemaps|
104
+ |**`camelCase`**|`{Boolean\|String}`|`false`|Export Classnames in CamelCase|
105
+ |**`importLoaders`**|`{Number}`|`0`|Number of loaders applied before CSS loader|
76
106
 
77
- * `url(image.png)` => `require('./image.png')`
78
- * `url(~module/image.png)` => `require('module/image.png')`
107
+ ### `root`
79
108
 
80
- <h2 align="center">Options</h2>
109
+ For URLs that start with a `/`, the default behavior is to not translate them.
81
110
 
82
- |Name|Default|Description|
83
- |:--:|:-----:|:----------|
84
- |**`root`**|`/`|Path to resolve URLs, URLs starting with `/` will not be translated|
85
- |**`modules`**|`false`|Enable/Disable CSS Modules|
86
- |**`import`** |`true`| Enable/Disable @import handling|
87
- |**`url`**|`true`| Enable/Disable `url()` handling|
88
- |**`minimize`**|`false`|Enable/Disable minification|
89
- |**`sourceMap`**|`false`|Enable/Disable Sourcemaps|
90
- |**`camelCase`**|`false`|Export Classnames in CamelCase|
91
- |**`importLoaders`**|`0`|Number of loaders applied before CSS loader|
111
+ `url(/image.png) => url(/image.png)`
92
112
 
93
- The following webpack config can load CSS files, embed small PNG/JPG/GIF/SVG images as well as fonts as [Data URLs](https://tools.ietf.org/html/rfc2397) and copy larger files to the output directory.
113
+ If a `root` query parameter is set, however, it will be prepended to the URL
114
+ and then translated.
94
115
 
95
116
  **webpack.config.js**
96
117
  ```js
97
- module.exports = {
98
- module: {
99
- rules: [
100
- {
101
- test: /\.css$/,
102
- use: [ 'style-loader', 'css-loader' ]
103
- },
104
- {
105
- test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
106
- loader: 'url-loader',
107
- options: {
108
- limit: 10000
109
- }
110
- }
111
- ]
112
- }
113
- };
118
+ {
119
+ loader: 'css-loader',
120
+ options: { root: '.' }
121
+ }
114
122
  ```
115
123
 
116
- ### Root
124
+ `url(/image.png)` => `require('./image.png')`
117
125
 
118
- For URLs that start with a `/`, the default behavior is to not translate them:
126
+ Using 'Root-relative' urls is not recommended. You should only use it for legacy CSS files.
119
127
 
120
- * `url(/image.png)` => `url(/image.png)`
128
+ ### `url`
121
129
 
122
- If a `root` query parameter is set, however, it will be prepended to the URL
123
- and then translated:
130
+ To disable `url()` resolving by `css-loader` set the option to `false`.
131
+
132
+ To be compatible with existing css files (if not in CSS Module mode).
133
+
134
+ ```
135
+ url(image.png) => require('./image.png')
136
+ url(~module/image.png) => require('module/image.png')
137
+ ```
138
+
139
+ ### `alias`
140
+
141
+ Rewrite your urls with alias, this is useful when it's hard to change url paths of your input files, for example, when you're using some css / sass files in another package (bootstrap, ratchet, font-awesome, etc.).
142
+
143
+ `css-loader`'s `alias` follows the same syntax as webpack's `resolve.alias`, you can see the details at the [resolve docs] (https://webpack.js.org/configuration/resolve/#resolve-alias)
144
+
145
+ **file.scss**
146
+ ```css
147
+ @charset "UTF-8";
148
+ @import "bootstrap";
149
+ ```
124
150
 
125
151
  **webpack.config.js**
126
152
  ```js
127
- rules: [
128
- {
129
- test: /\.css$/,
130
- use: [
131
- 'style-loader',
132
- {
133
- loader: 'css-loader',
134
- options: { root: '.' }
153
+ {
154
+ test: /\.scss$/,
155
+ use: [
156
+ {
157
+ loader: "style-loader"
158
+ },
159
+ {
160
+ loader: "css-loader",
161
+ options: {
162
+ alias: {
163
+ "../fonts/bootstrap": "bootstrap-sass/assets/fonts/bootstrap"
164
+ }
135
165
  }
136
- ]
137
- }
138
- ]
166
+ },
167
+ {
168
+ loader: "sass-loader",
169
+ options: {
170
+ includePaths: [
171
+ path.resolve("./node_modules/bootstrap-sass/assets/stylesheets")
172
+ ]
173
+ }
174
+ }
175
+ ]
176
+ }
139
177
  ```
140
178
 
141
- * `url(/image.png)` => `require('./image.png')`
179
+ Check out this [working bootstrap example](https://github.com/bbtfr/webpack2-bootstrap-sass-sample).
142
180
 
143
- Using 'Root-relative' urls is not recommended. You should only use it for legacy CSS files.
181
+ ### `import`
144
182
 
145
- ### CSS Scope
183
+ To disable `@import` resolving by `css-loader` set the option to `false`
146
184
 
147
- By default CSS exports all class names into a global selector scope. Styles can be locally scoped to avoid globally scoping styles.
185
+ ```css
186
+ @import url('https://fonts.googleapis.com/css?family=Roboto');
187
+ ```
188
+
189
+ > _⚠️ Use with caution, since this disables resolving for **all** `@import`s, including css modules `composes: xxx from 'path/to/file.css'` feature._
190
+
191
+ ### [`modules`](https://github.com/css-modules/css-modules)
192
+
193
+ The query parameter `modules` enables the **CSS Modules** spec.
194
+
195
+ This enables local scoped CSS by default. (You can switch it off with `:global(...)` or `:global` for selectors and/or rules.).
196
+
197
+ #### `Scope`
198
+
199
+ By default CSS exports all classnames into a global selector scope. Styles can be locally scoped to avoid globally scoping styles.
148
200
 
149
201
  The syntax `:local(.className)` can be used to declare `className` in the local scope. The local identifiers are exported by the module.
150
202
 
@@ -152,7 +204,6 @@ With `:local` (without brackets) local mode can be switched on for this selector
152
204
 
153
205
  The loader replaces local selectors with unique identifiers. The choosen unique identifiers are exported by the module.
154
206
 
155
- **app.css**
156
207
  ```css
157
208
  :local(.className) { background: red; }
158
209
  :local .className { color: green; }
@@ -160,17 +211,16 @@ The loader replaces local selectors with unique identifiers. The choosen unique
160
211
  :local .className .subClass :global(.global-class-name) { color: blue; }
161
212
  ```
162
213
 
163
- **app.bundle.css**
164
- ``` css
214
+ ```css
165
215
  ._23_aKvs-b8bW2Vg3fwHozO { background: red; }
166
216
  ._23_aKvs-b8bW2Vg3fwHozO { color: green; }
167
217
  ._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 { color: green; }
168
218
  ._23_aKvs-b8bW2Vg3fwHozO ._13LGdX8RMStbBE9w-t0gZ1 .global-class-name { color: blue; }
169
219
  ```
170
220
 
171
- > Note: Identifiers are exported
221
+ > :information_source: Identifiers are exported
172
222
 
173
- ``` js
223
+ ```js
174
224
  exports.locals = {
175
225
  className: '_23_aKvs-b8bW2Vg3fwHozO',
176
226
  subClass: '_13LGdX8RMStbBE9w-t0gZ1'
@@ -179,13 +229,14 @@ exports.locals = {
179
229
 
180
230
  CamelCase is recommended for local selectors. They are easier to use in the within the imported JS module.
181
231
 
182
- `url()` URLs in block scoped (`:local .abc`) rules behave like requests in modules:
232
+ `url()` URLs in block scoped (`:local .abc`) rules behave like requests in modules.
183
233
 
184
- * `./file.png` instead of `file.png`
185
- * `module/file.png` instead of `~module/file.png`
234
+ ```
235
+ file.png => ./file.png
236
+ ~module/file.png => module/file.png
237
+ ```
186
238
 
187
239
  You can use `:local(#someId)`, but this is not recommended. Use classes instead of ids.
188
-
189
240
  You can configure the generated ident with the `localIdentName` query parameter (default `[hash:base64]`).
190
241
 
191
242
  **webpack.config.js**
@@ -204,39 +255,29 @@ You can configure the generated ident with the `localIdentName` query parameter
204
255
  }
205
256
  ```
206
257
 
207
- You can also specify the absolute path to your custom `getLocalIdent` function to generate classname based on a different schema. Note that this requires `webpack >= v2.x.` since to be able to pass function in. For example:
258
+ 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).
208
259
 
260
+ **webpack.config.js**
209
261
  ```js
210
262
  {
211
- test: /\.css$/,
212
- use: [
213
- {
214
- loader: 'css-loader',
215
- options: {
216
- modules: true,
217
- localIdentName: '[path][name]__[local]--[hash:base64:5]',
218
- getLocalIdent: (context, localIdentName, localName, options) => {
219
- return 'whatever_random_class_name'
220
- }
221
- }
263
+ loader: 'css-loader',
264
+ options: {
265
+ modules: true,
266
+ localIdentName: '[path][name]__[local]--[hash:base64:5]',
267
+ getLocalIdent: (context, localIdentName, localName, options) => {
268
+ return 'whatever_random_class_name'
222
269
  }
223
- ]
270
+ }
224
271
  }
225
272
  ```
226
273
 
227
- Note: 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.
274
+ > :information_source: 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.
228
275
 
229
- ### [CSS Modules](https://github.com/css-modules/css-modules)
276
+ #### `Composing`
230
277
 
231
- The query parameter `modules` enables the **CSS Modules** spec.
232
-
233
- This enables local scoped CSS by default. (You can switch it off with `:global(...)` or `:global` for selectors and/or rules.)
234
-
235
- ### CSS Composing
278
+ When declaring a local classname you can compose a local class from another local classname.
236
279
 
237
- When declaring a local class name you can compose a local class from another local class name.
238
-
239
- ``` css
280
+ ```css
240
281
  :local(.className) {
241
282
  background: red;
242
283
  color: yellow;
@@ -248,7 +289,7 @@ When declaring a local class name you can compose a local class from another loc
248
289
  }
249
290
  ```
250
291
 
251
- This doesn't result in any change to the CSS itself but exports multiple class names:
292
+ This doesn't result in any change to the CSS itself but exports multiple classnames.
252
293
 
253
294
  ```js
254
295
  exports.locals = {
@@ -268,18 +309,18 @@ exports.locals = {
268
309
  }
269
310
  ```
270
311
 
271
- ### Importing CSS Locals
312
+ #### `Importing`
272
313
 
273
- To import a local class name from another module:
314
+ To import a local classname from another module.
274
315
 
275
- ``` css
316
+ ```css
276
317
  :local(.continueButton) {
277
318
  composes: button from 'library/button.css';
278
319
  background: red;
279
320
  }
280
321
  ```
281
322
 
282
- ``` css
323
+ ```css
283
324
  :local(.nameEdit) {
284
325
  composes: edit highlight from './edit.css';
285
326
  background: red;
@@ -288,7 +329,7 @@ To import a local class name from another module:
288
329
 
289
330
  To import from multiple modules use multiple `composes:` rules.
290
331
 
291
- ``` css
332
+ ```css
292
333
  :local(.className) {
293
334
  composes: edit hightlight from './edit.css';
294
335
  composes: button from 'module/button.css';
@@ -297,137 +338,157 @@ To import from multiple modules use multiple `composes:` rules.
297
338
  }
298
339
  ```
299
340
 
300
- ### SourceMaps
341
+ ### `minimize`
301
342
 
302
- To include Sourcemaps set the `sourceMap` query param.
343
+ By default the css-loader minimizes the css if specified by the module system.
303
344
 
304
- I. e. the extract-text-webpack-plugin can handle them.
345
+ In some cases the minification is destructive to the css, so you can provide your own options to the minifier if needed. cssnano is used for minification and you find a [list of options here](http://cssnano.co/options/).
305
346
 
306
- They are not enabled by default because they expose a runtime overhead and increase in bundle size (JS SourceMap do not). In addition to that relative paths are buggy and you need to use an absolute public path which include the server URL.
347
+ You can also disable or enforce minification with the `minimize` query parameter.
307
348
 
308
349
  **webpack.config.js**
309
350
  ```js
310
351
  {
311
- test: /\.css$/,
312
- use: [
313
- {
314
- loader: 'css-loader',
315
- options: {
316
- sourceMap: true
317
- }
318
- }
319
- ]
352
+ loader: 'css-loader',
353
+ options: {
354
+ minimize: true || {/* CSSNano Options */}
355
+ }
320
356
  }
321
357
  ```
322
358
 
323
- ### toString
359
+ ### `sourceMap`
324
360
 
325
- You can also use the css-loader results directly as string, such as in Angular's component style.
361
+ To include source maps set the `sourceMap` option.
326
362
 
327
- **webpack.config.js**
363
+ I. e. the extract-text-webpack-plugin can handle them.
364
+
365
+ They are not enabled by default because they expose a runtime overhead and increase in bundle size (JS source maps do not). In addition to that relative paths are buggy and you need to use an absolute public path which include the server URL.
328
366
 
367
+ **webpack.config.js**
329
368
  ```js
330
369
  {
331
-    test: /\.css$/,
332
-    use: [
333
-      {
334
-        loaders: ['to-string-loader', 'css-loader']
335
-      }
336
-    ]
370
+ loader: 'css-loader',
371
+ options: {
372
+ sourceMap: true
373
+ }
337
374
  }
338
375
  ```
339
376
 
340
- or
377
+ ### `camelCase`
341
378
 
342
- ```js
343
- const cssText = require('./test.css').toString();
379
+ 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.
380
+
381
+ |Name|Type|Description|
382
+ |:--:|:--:|:----------|
383
+ |**`true`**|`{Boolean}`|Class names will be camelized|
384
+ |**`'dashes'`**|`{String}`|Only dashes in class names will be camelized|
385
+ |**`'only'`** |`{String}`|Introduced in `0.27.1`. Class names will be camelized, the original class name will be removed from the locals|
386
+ |**`'dashesOnly'`**|`{String}`|Introduced in `0.27.1`. Dashes in class names will be camelized, the original class name will be removed from the locals|
344
387
 
345
- console.log(cssText);
388
+ **file.css**
389
+ ```css
390
+ .class-name {}
346
391
  ```
347
392
 
348
- If there are SourceMaps, they will also be included in the result string.
393
+ **file.js**
394
+ ```js
395
+ import { className } from 'file.css';
396
+ ```
349
397
 
350
- ### ImportLoaders
398
+ **webpack.config.js**
399
+ ```js
400
+ {
401
+ loader: 'css-loader',
402
+ options: {
403
+ camelCase: true
404
+ }
405
+ }
406
+ ```
351
407
 
352
- The query parameter `importLoaders` allow to configure which loaders should be applied to `@import`ed resources.
408
+ ### `importLoaders`
353
409
 
354
- `importLoaders`: That many loaders after the css-loader are used to import resources.
410
+ The query parameter `importLoaders` allows to configure how many loaders before `css-loader` should be applied to `@import`ed resources.
355
411
 
356
412
  **webpack.config.js**
357
413
  ```js
358
414
  {
359
415
  test: /\.css$/,
360
416
  use: [
417
+ 'style-loader',
361
418
  {
362
419
  loader: 'css-loader',
363
420
  options: {
364
- importLoaders: 1
421
+ importLoaders: 1 // 0 => no loaders (default); 1 => postcss-loader; 2 => postcss-loader, sass-loader
365
422
  }
366
423
  },
367
- 'postcss-loader'
424
+ 'postcss-loader',
425
+ 'sass-loader'
368
426
  ]
369
427
  }
370
428
  ```
371
429
 
372
430
  This may change in the future, when the module system (i. e. webpack) supports loader matching by origin.
373
431
 
374
- ### Minification
432
+ <h2 align="center">Examples</h2>
375
433
 
376
- By default the css-loader minimizes the css if specified by the module system.
377
-
378
- In some cases the minification is destructive to the css, so you can provide some options to it. cssnano is used for minification and you find a [list of options here](http://cssnano.co/options/).
434
+ ### Assets
379
435
 
380
- You can also disable or enforce minification with the `minimize` query parameter.
436
+ The following `webpack.config.js` can load CSS files, embed small PNG/JPG/GIF/SVG images as well as fonts as [Data URLs](https://tools.ietf.org/html/rfc2397) and copy larger files to the output directory.
381
437
 
382
438
  **webpack.config.js**
383
439
  ```js
384
- {
385
- test: /\.css$/,
386
- use: [
387
- {
388
- loader: 'css-loader',
389
- options: {
390
- minimize: true || {/* CSSNano Options */}
440
+ module.exports = {
441
+ module: {
442
+ rules: [
443
+ {
444
+ test: /\.css$/,
445
+ use: [ 'style-loader', 'css-loader' ]
446
+ },
447
+ {
448
+ test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
449
+ loader: 'url-loader',
450
+ options: {
451
+ limit: 10000
452
+ }
391
453
  }
392
- }
393
- ]
454
+ ]
455
+ }
394
456
  }
395
457
  ```
396
458
 
397
- ### CamelCase
398
-
399
- 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.
400
-
401
- #### Possible Options
459
+ ### Extract
402
460
 
403
- |Option|Description|
404
- |:----:|:--------|
405
- |**`true`**|Class names will be camelized|
406
- |**`'dashes'`**|Only dashes in class names will be camelized|
407
- |**`'only'`** |Class names will be camelized, the original class name will be removed from the locals|
408
- |**`'dashesOnly'`**|Dashes in class names will be camelized, the original class name will be removed from the locals|
461
+ For production builds it's recommended to extract the CSS from your bundle being able to use parallel loading of CSS/JS resources later on. This can be achieved by using the [extract-text-webpack-plugin](https://github.com/webpack-contrib/extract-text-webpack-plugin) to extract the CSS when running in production mode.
409
462
 
410
463
  **webpack.config.js**
411
464
  ```js
412
- {
413
- test: /\.css$/,
414
- use: [
415
- {
416
- loader: 'css-loader',
417
- options: {
418
- camelCase: true
419
- }
420
- }
421
- ]
422
- }
423
- ```
465
+ const env = process.env.NODE_ENV
424
466
 
425
- ```css
426
- .class-name {}
427
- ```
467
+ const ExtractTextPlugin = require('extract-text-webpack-plugin')
428
468
 
429
- ```js
430
- import { className } from 'file.css';
469
+ module.exports = {
470
+ module: {
471
+ rules: [
472
+ {
473
+ test: /\.css$/,
474
+ use: env === 'production'
475
+ ? ExtractTextPlugin.extract({
476
+ fallback: 'style-loader'
477
+ use: [ 'css-loader' ]
478
+ })
479
+ : [ 'style-loader', 'css-loader' ]
480
+ },
481
+ ]
482
+ },
483
+ plugins: env === 'production'
484
+ ? [
485
+ new ExtractTextPlugin({
486
+ filename: '[name].css'
487
+ })
488
+ ]
489
+ : []
490
+ ]
491
+ }
431
492
  ```
432
493
 
433
494
  <h2 align="center">Maintainers</h2>
@@ -437,29 +498,49 @@ import { className } from 'file.css';
437
498
  <tr>
438
499
  <td align="center">
439
500
  <img width="150" height="150"
440
- src="https://avatars3.githubusercontent.com/u/166921?v=3&s=150">
501
+ src="https://github.com/bebraw.png?v=3&s=150">
441
502
  </br>
442
503
  <a href="https://github.com/bebraw">Juho Vepsäläinen</a>
443
504
  </td>
444
505
  <td align="center">
445
506
  <img width="150" height="150"
446
- src="https://avatars2.githubusercontent.com/u/8420490?v=3&s=150">
507
+ src="https://github.com/d3viant0ne.png?v=3&s=150">
447
508
  </br>
448
509
  <a href="https://github.com/d3viant0ne">Joshua Wiens</a>
449
510
  </td>
450
511
  <td align="center">
451
512
  <img width="150" height="150"
452
- src="https://avatars3.githubusercontent.com/u/533616?v=3&s=150">
513
+ src="https://github.com/SpaceK33z.png?v=3&s=150">
453
514
  </br>
454
515
  <a href="https://github.com/SpaceK33z">Kees Kluskens</a>
455
516
  </td>
456
517
  <td align="center">
457
518
  <img width="150" height="150"
458
- src="https://avatars3.githubusercontent.com/u/3408176?v=3&s=150">
519
+ src="https://github.com/TheLarkInn.png?v=3&s=150">
459
520
  </br>
460
521
  <a href="https://github.com/TheLarkInn">Sean Larkin</a>
461
522
  </td>
462
523
  </tr>
524
+ <tr>
525
+ <td align="center">
526
+ <img width="150" height="150"
527
+ src="https://github.com/michael-ciniawsky.png?v=3&s=150">
528
+ </br>
529
+ <a href="https://github.com/michael-ciniawsky">Michael Ciniawsky</a>
530
+ </td>
531
+ <td align="center">
532
+ <img width="150" height="150"
533
+ src="https://github.com/evilebottnawi.png?v=3&s=150">
534
+ </br>
535
+ <a href="https://github.com/evilebottnawi">Evilebot Tnawi</a>
536
+ </td>
537
+ <td align="center">
538
+ <img width="150" height="150"
539
+ src="https://github.com/joscha.png?v=3&s=150">
540
+ </br>
541
+ <a href="https://github.com/joscha">Joscha Feth</a>
542
+ </td>
543
+ </tr>
463
544
  <tbody>
464
545
  </table>
465
546
 
@@ -0,0 +1,36 @@
1
+ module.exports = function createResolver(alias) {
2
+ if(typeof alias !== "object" || Array.isArray(alias)) {
3
+ return function(url) {
4
+ return url
5
+ };
6
+ }
7
+
8
+ alias = Object.keys(alias).map(function(key) {
9
+ var onlyModule = false;
10
+ var obj = alias[key];
11
+ if(/\$$/.test(key)) {
12
+ onlyModule = true;
13
+ key = key.substr(0, key.length - 1);
14
+ }
15
+ if(typeof obj === "string") {
16
+ obj = {
17
+ alias: obj
18
+ };
19
+ }
20
+ obj = Object.assign({
21
+ name: key,
22
+ onlyModule: onlyModule
23
+ }, obj);
24
+ return obj;
25
+ });
26
+
27
+ return function(url) {
28
+ alias.forEach(function(obj) {
29
+ var name = obj.name;
30
+ if(url === name || (!obj.onlyModule && url.startsWith(name + "/"))) {
31
+ url = obj.alias + url.substr(name.length);
32
+ }
33
+ });
34
+ return url;
35
+ }
36
+ }
package/lib/css-base.js CHANGED
@@ -3,13 +3,13 @@
3
3
  Author Tobias Koppers @sokra
4
4
  */
5
5
  // css base code, injected by the css-loader
6
- module.exports = function() {
6
+ module.exports = function(useSourceMap) {
7
7
  var list = [];
8
8
 
9
9
  // return the list of modules as css string
10
10
  list.toString = function toString() {
11
11
  return this.map(function (item) {
12
- const content = cssWithMappingToString(item);
12
+ var content = cssWithMappingToString(item, useSourceMap);
13
13
  if(item[2]) {
14
14
  return "@media " + item[2] + "{" + content + "}";
15
15
  } else {
@@ -47,16 +47,30 @@ module.exports = function() {
47
47
  return list;
48
48
  };
49
49
 
50
- function cssWithMappingToString(item) {
50
+ function cssWithMappingToString(item, useSourceMap) {
51
51
  var content = item[1] || '';
52
52
  var cssMapping = item[3];
53
53
  if (!cssMapping) {
54
54
  return content;
55
55
  }
56
- var convertSourceMap = require('./convert-source-map');
57
- var sourceMapping = convertSourceMap.fromObject(cssMapping).toComment({multiline: true});
58
- var sourceURLs = cssMapping.sources.map(function (source) {
59
- return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'
60
- });
61
- return [content].concat(sourceURLs).concat([sourceMapping]).join('\n');
56
+
57
+ if (useSourceMap && typeof btoa === 'function') {
58
+ var sourceMapping = toComment(cssMapping);
59
+ var sourceURLs = cssMapping.sources.map(function (source) {
60
+ return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'
61
+ });
62
+
63
+ return [content].concat(sourceURLs).concat([sourceMapping]).join('\n');
64
+ }
65
+
66
+ return [content].join('\n');
67
+ }
68
+
69
+ // Adapted from convert-source-map (MIT)
70
+ function toComment(sourceMap) {
71
+ // eslint-disable-next-line no-undef
72
+ var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
73
+ var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;
74
+
75
+ return '/*# ' + data + ' */';
62
76
  }
package/lib/loader.js CHANGED
@@ -6,6 +6,7 @@ var loaderUtils = require("loader-utils");
6
6
  var processCss = require("./processCss");
7
7
  var getImportPrefix = require("./getImportPrefix");
8
8
  var compileExports = require("./compile-exports");
9
+ var createResolver = require("./createResolver");
9
10
 
10
11
 
11
12
  module.exports = function(content, map) {
@@ -15,9 +16,16 @@ module.exports = function(content, map) {
15
16
  var root = query.root;
16
17
  var moduleMode = query.modules || query.module;
17
18
  var camelCaseKeys = query.camelCase || query.camelcase;
19
+ var sourceMap = query.sourceMap || false;
20
+ var resolve = createResolver(query.alias);
18
21
 
19
- if(map !== null && typeof map !== "string") {
20
- map = JSON.stringify(map);
22
+ if(sourceMap) {
23
+ if (map && typeof map !== "string") {
24
+ map = JSON.stringify(map);
25
+ }
26
+ } else {
27
+ // Some loaders (example `"postcss-loader": "1.x.x"`) always generates source map, we should remove it
28
+ map = null;
21
29
  }
22
30
 
23
31
  processCss(content, map, {
@@ -26,7 +34,8 @@ module.exports = function(content, map) {
26
34
  to: loaderUtils.getCurrentRequest(this),
27
35
  query: query,
28
36
  minimize: this.minimize,
29
- loaderContext: this
37
+ loaderContext: this,
38
+ sourceMap: sourceMap
30
39
  }, function(err, result) {
31
40
  if(err) return callback(err);
32
41
 
@@ -69,7 +78,7 @@ module.exports = function(content, map) {
69
78
  var match = result.urlItemRegExp.exec(item);
70
79
  var idx = +match[1];
71
80
  var urlItem = result.urlItems[idx];
72
- var url = urlItem.url;
81
+ var url = resolve(urlItem.url);
73
82
  idx = url.indexOf("?#");
74
83
  if(idx < 0) idx = url.indexOf("#");
75
84
  var urlRequest;
@@ -108,7 +117,9 @@ module.exports = function(content, map) {
108
117
  }
109
118
 
110
119
  // embed runtime
111
- callback(null, "exports = module.exports = require(" + loaderUtils.stringifyRequest(this, require.resolve("./css-base.js")) + ")();\n" +
120
+ callback(null, "exports = module.exports = require(" +
121
+ loaderUtils.stringifyRequest(this, require.resolve("./css-base.js")) +
122
+ ")(" + query.sourceMap + ");\n" +
112
123
  "// imports\n" +
113
124
  importJs + "\n\n" +
114
125
  "// module\n" +
package/lib/processCss.js CHANGED
@@ -13,7 +13,7 @@ var localByDefault = require("postcss-modules-local-by-default");
13
13
  var extractImports = require("postcss-modules-extract-imports");
14
14
  var modulesScope = require("postcss-modules-scope");
15
15
  var modulesValues = require("postcss-modules-values");
16
- var cssnano = require("cssnano");
16
+ var valueParser = require('postcss-value-parser');
17
17
 
18
18
  var parserPlugin = postcss.plugin("css-loader-parser", function(options) {
19
19
  return function(css) {
@@ -24,21 +24,24 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) {
24
24
 
25
25
  function replaceImportsInString(str) {
26
26
  if(options.import) {
27
- var tokens = str.split(/(\S+)/);
28
- tokens = tokens.map(function (token) {
27
+ var tokens = valueParser(str);
28
+ tokens.walk(function (node) {
29
+ if (node.type !== 'word') {
30
+ return;
31
+ }
32
+ var token = node.value;
29
33
  var importIndex = imports["$" + token];
30
34
  if(typeof importIndex === "number") {
31
- return "___CSS_LOADER_IMPORT___" + importIndex + "___";
35
+ node.value = "___CSS_LOADER_IMPORT___" + importIndex + "___";
32
36
  }
33
- return token;
34
- });
35
- return tokens.join("");
37
+ })
38
+ return tokens.toString();
36
39
  }
37
40
  return str;
38
41
  }
39
42
 
40
43
  if(options.import) {
41
- css.walkAtRules("import", function(rule) {
44
+ css.walkAtRules(/import/i, function(rule) {
42
45
  var values = Tokenizer.parseValues(rule.params);
43
46
  var url = values.nodes[0].nodes[0];
44
47
  if(url.type === "url") {
@@ -46,6 +49,9 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) {
46
49
  } else if(url.type === "string") {
47
50
  url = url.value;
48
51
  } else throw rule.error("Unexpected format" + rule.params);
52
+ if (!url.replace(/\s/g, '').length) {
53
+ return;
54
+ }
49
55
  values.nodes[0].nodes.shift();
50
56
  var mediaQuery = Tokenizer.stringifyValues(values);
51
57
  if(loaderUtils.isUrlRequest(url, options.root) && options.mode === "global") {
@@ -98,8 +104,11 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) {
98
104
  }
99
105
  break;
100
106
  case "url":
101
- if (options.url && !/^#/.test(item.url) && loaderUtils.isUrlRequest(item.url, options.root)) {
102
- item.stringType = "";
107
+ if (options.url && item.url.replace(/\s/g, '').length && !/^#/.test(item.url) && loaderUtils.isUrlRequest(item.url, options.root)) {
108
+ // Don't remove quotes around url when contain space
109
+ if (item.url.indexOf(" ") === -1) {
110
+ item.stringType = "";
111
+ }
103
112
  delete item.innerSpacingBefore;
104
113
  delete item.innerSpacingAfter;
105
114
  var url = item.url;
@@ -133,7 +142,7 @@ var parserPlugin = postcss.plugin("css-loader-parser", function(options) {
133
142
 
134
143
  module.exports = function processCss(inputSource, inputMap, options, callback) {
135
144
  var query = options.query;
136
- var root = query.root;
145
+ var root = query.root && query.root.length > 0 ? query.root.replace(/\/$/, "") : query.root;
137
146
  var context = query.context;
138
147
  var localIdentName = query.localIdentName || "[hash:base64]";
139
148
  var localIdentRegExp = query.localIdentRegExp;
@@ -141,7 +150,7 @@ module.exports = function processCss(inputSource, inputMap, options, callback) {
141
150
  var minimize = typeof forceMinimize !== "undefined" ? !!forceMinimize : options.minimize;
142
151
 
143
152
  var customGetLocalIdent = query.getLocalIdent || getLocalIdent;
144
-
153
+
145
154
  var parserOptions = {
146
155
  root: root,
147
156
  mode: options.mode,
@@ -154,7 +163,9 @@ module.exports = function processCss(inputSource, inputMap, options, callback) {
154
163
  mode: options.mode,
155
164
  rewriteUrl: function(global, url) {
156
165
  if(parserOptions.url){
157
- if(!loaderUtils.isUrlRequest(url, root)) {
166
+ url = url.trim();
167
+
168
+ if(!url.replace(/\s/g, '').length || !loaderUtils.isUrlRequest(url, root)) {
158
169
  return url;
159
170
  }
160
171
  if(global) {
@@ -179,6 +190,7 @@ module.exports = function processCss(inputSource, inputMap, options, callback) {
179
190
  ]);
180
191
 
181
192
  if(minimize) {
193
+ var cssnano = require("cssnano");
182
194
  var minimizeOptions = assign({}, query.minimize);
183
195
  ["zindex", "normalizeUrl", "discardUnused", "mergeIdents", "reduceIdents", "autoprefixer"].forEach(function(name) {
184
196
  if(typeof minimizeOptions[name] === "undefined")
@@ -191,12 +203,12 @@ module.exports = function processCss(inputSource, inputMap, options, callback) {
191
203
  // we need a prefix to avoid path rewriting of PostCSS
192
204
  from: "/css-loader!" + options.from,
193
205
  to: options.to,
194
- map: {
206
+ map: options.sourceMap ? {
195
207
  prev: inputMap,
196
208
  sourcesContent: true,
197
209
  inline: false,
198
210
  annotation: false
199
- }
211
+ } : null
200
212
  }).then(function(result) {
201
213
  callback(null, {
202
214
  source: result.css,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "css-loader",
3
- "version": "0.27.1",
3
+ "version": "0.28.1",
4
4
  "author": "Tobias Koppers @sokra",
5
5
  "description": "css loader module for webpack",
6
6
  "engines": {
@@ -13,7 +13,6 @@
13
13
  ],
14
14
  "dependencies": {
15
15
  "babel-code-frame": "^6.11.0",
16
- "convert-source-map": "^1.3.0",
17
16
  "css-selector-tokenizer": "^0.7.0",
18
17
  "cssnano": ">=2.6.1 <4",
19
18
  "loader-utils": "^1.0.2",
@@ -24,6 +23,7 @@
24
23
  "postcss-modules-local-by-default": "^1.0.1",
25
24
  "postcss-modules-scope": "^1.0.0",
26
25
  "postcss-modules-values": "^1.1.0",
26
+ "postcss-value-parser": "^3.3.0",
27
27
  "source-list-map": "^0.1.7"
28
28
  },
29
29
  "devDependencies": {
@@ -1,143 +0,0 @@
1
- /* eslint-disable */
2
- 'use strict';
3
- // XXXXX: This file should not exist. Working around a core level bug
4
- // that prevents using fs at loaders.
5
- //var fs = require('fs'); // XXX
6
- var path = require('path');
7
-
8
- var commentRx = /^\s*\/(?:\/|\*)[@#]\s+sourceMappingURL=data:(?:application|text)\/json;(?:charset[:=]\S+?;)?base64,(?:.*)$/mg;
9
- var mapFileCommentRx =
10
- //Example (Extra space between slashes added to solve Safari bug. Exclude space in production):
11
- // / /# sourceMappingURL=foo.js.map /*# sourceMappingURL=foo.js.map */
12
- /(?:\/\/[@#][ \t]+sourceMappingURL=([^\s'"]+?)[ \t]*$)|(?:\/\*[@#][ \t]+sourceMappingURL=([^\*]+?)[ \t]*(?:\*\/){1}[ \t]*$)/mg
13
-
14
- function decodeBase64(base64) {
15
- return new Buffer(base64, 'base64').toString();
16
- }
17
-
18
- function stripComment(sm) {
19
- return sm.split(',').pop();
20
- }
21
-
22
- function readFromFileMap(sm, dir) {
23
- // NOTE: this will only work on the server since it attempts to read the map file
24
-
25
- mapFileCommentRx.lastIndex = 0;
26
- var r = mapFileCommentRx.exec(sm);
27
-
28
- // for some odd reason //# .. captures in 1 and /* .. */ in 2
29
- var filename = r[1] || r[2];
30
- var filepath = path.resolve(dir, filename);
31
-
32
- try {
33
- return fs.readFileSync(filepath, 'utf8');
34
- } catch (e) {
35
- throw new Error('An error occurred while trying to read the map file at ' + filepath + '\n' + e);
36
- }
37
- }
38
-
39
- function Converter (sm, opts) {
40
- opts = opts || {};
41
-
42
- if (opts.isFileComment) sm = readFromFileMap(sm, opts.commentFileDir);
43
- if (opts.hasComment) sm = stripComment(sm);
44
- if (opts.isEncoded) sm = decodeBase64(sm);
45
- if (opts.isJSON || opts.isEncoded) sm = JSON.parse(sm);
46
-
47
- this.sourcemap = sm;
48
- }
49
-
50
- Converter.prototype.toJSON = function (space) {
51
- return JSON.stringify(this.sourcemap, null, space);
52
- };
53
-
54
- Converter.prototype.toBase64 = function () {
55
- var json = this.toJSON();
56
- return new Buffer(json).toString('base64');
57
- };
58
-
59
- Converter.prototype.toComment = function (options) {
60
- var base64 = this.toBase64();
61
- var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;
62
- return options && options.multiline ? '/*# ' + data + ' */' : '//# ' + data;
63
- };
64
-
65
- // returns copy instead of original
66
- Converter.prototype.toObject = function () {
67
- return JSON.parse(this.toJSON());
68
- };
69
-
70
- Converter.prototype.addProperty = function (key, value) {
71
- if (this.sourcemap.hasOwnProperty(key)) throw new Error('property %s already exists on the sourcemap, use set property instead');
72
- return this.setProperty(key, value);
73
- };
74
-
75
- Converter.prototype.setProperty = function (key, value) {
76
- this.sourcemap[key] = value;
77
- return this;
78
- };
79
-
80
- Converter.prototype.getProperty = function (key) {
81
- return this.sourcemap[key];
82
- };
83
-
84
- exports.fromObject = function (obj) {
85
- return new Converter(obj);
86
- };
87
-
88
- exports.fromJSON = function (json) {
89
- return new Converter(json, { isJSON: true });
90
- };
91
-
92
- exports.fromBase64 = function (base64) {
93
- return new Converter(base64, { isEncoded: true });
94
- };
95
-
96
- exports.fromComment = function (comment) {
97
- comment = comment
98
- .replace(/^\/\*/g, '//')
99
- .replace(/\*\/$/g, '');
100
-
101
- return new Converter(comment, { isEncoded: true, hasComment: true });
102
- };
103
-
104
- exports.fromMapFileComment = function (comment, dir) {
105
- return new Converter(comment, { commentFileDir: dir, isFileComment: true, isJSON: true });
106
- };
107
-
108
- // Finds last sourcemap comment in file or returns null if none was found
109
- exports.fromSource = function (content) {
110
- var m = content.match(commentRx);
111
- return m ? exports.fromComment(m.pop()) : null;
112
- };
113
-
114
- // Finds last sourcemap comment in file or returns null if none was found
115
- exports.fromMapFileSource = function (content, dir) {
116
- var m = content.match(mapFileCommentRx);
117
- return m ? exports.fromMapFileComment(m.pop(), dir) : null;
118
- };
119
-
120
- exports.removeComments = function (src) {
121
- return src.replace(commentRx, '');
122
- };
123
-
124
- exports.removeMapFileComments = function (src) {
125
- return src.replace(mapFileCommentRx, '');
126
- };
127
-
128
- exports.generateMapFileComment = function (file, options) {
129
- var data = 'sourceMappingURL=' + file;
130
- return options && options.multiline ? '/*# ' + data + ' */' : '//# ' + data;
131
- };
132
-
133
- Object.defineProperty(exports, 'commentRegex', {
134
- get: function getCommentRegex () {
135
- return commentRx;
136
- }
137
- });
138
-
139
- Object.defineProperty(exports, 'mapFileCommentRegex', {
140
- get: function getMapFileCommentRegex () {
141
- return mapFileCommentRx;
142
- }
143
- });