From 6da7e90748364fe61231ba71e3d9057c41271f5f Mon Sep 17 00:00:00 2001 From: Zhicheng Wang Date: Sun, 5 Feb 2017 17:43:19 +0800 Subject: [PATCH] feat: Include the sourceMappingURL & sourceURL when toString() This feature is useful when you need to pass the result of css-loader to angular: call to require('to-string-loader!css-loader? sourceMap!sass-loader?sourceMap!./ test.scss') will include source mapping, And finally assigned to the component's styles metadata --- README.md | 27 +++++++++++++++++++++++++++ lib/css-base.js | 26 +++++++++++++++++++------- package.json | 1 + test/cssBaseTest.js | 12 ++++++++++++ 4 files changed, 59 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 659b7f68..9fd5ecc7 100644 --- a/README.md +++ b/README.md @@ -320,6 +320,33 @@ They are not enabled by default because they expose a runtime overhead and incre } ``` +### toString + +You can also use the css-loader results directly as string, such as in Angular's component style. + +**webpack.config.js** + +```js +{ +   test: /\.css$/, +   use: [ +     { +       loaders: ['to-string-loader', 'css-loader'] +     } +   ] +} +``` + +or + +```js +const cssText = require('./test.css').toString(); + +console.log(cssText); +``` + +If there are SourceMaps, they will also be included in the result string. + ### ImportLoaders The query parameter `importLoaders` allow to configure which loaders should be applied to `@import`ed resources. diff --git a/lib/css-base.js b/lib/css-base.js index 3f791979..1e240e59 100644 --- a/lib/css-base.js +++ b/lib/css-base.js @@ -8,16 +8,14 @@ module.exports = function() { // return the list of modules as css string list.toString = function toString() { - var result = []; - for(var i = 0; i < this.length; i++) { - var item = this[i]; + return this.map(function (item) { + const content = cssWithMappingToString(item); if(item[2]) { - result.push("@media " + item[2] + "{" + item[1] + "}"); + return "@media " + item[2] + "{" + content + "}"; } else { - result.push(item[1]); + return content; } - } - return result.join(""); + }).join(""); }; // import a list of modules into the list @@ -48,3 +46,17 @@ module.exports = function() { }; return list; }; + +function cssWithMappingToString(item) { + var content = item[1] || ''; + var cssMapping = item[3]; + if (!cssMapping) { + return content; + } + var convertSourceMap = require('convert-source-map'); + var sourceMapping = convertSourceMap.fromObject(cssMapping).toComment({multiline: true}); + var sourceURLs = cssMapping.sources.map(function (source) { + return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */' + }); + return [content].concat(sourceURLs).concat([sourceMapping]).join('\n'); +} diff --git a/package.json b/package.json index c3a60cca..58d38167 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ ], "dependencies": { "babel-code-frame": "^6.11.0", + "convert-source-map": "^1.3.0", "css-selector-tokenizer": "^0.7.0", "cssnano": ">=2.6.1 <4", "loader-utils": "^1.0.2", diff --git a/test/cssBaseTest.js b/test/cssBaseTest.js index 73b6f79d..4e659ac0 100644 --- a/test/cssBaseTest.js +++ b/test/cssBaseTest.js @@ -34,4 +34,16 @@ describe("css-base", function() { "@media print{body { d: 4; }}" + "@media screen{body { a: 1; }}"); }); + it("should toString with source mapping", function() { + var m = base(); + 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 */"); + }); });