22 MIT License http://www.opensource.org/licenses/mit-license.php
33 Author Tobias Koppers @sokra
44*/
5- var csso = require ( "csso" ) ;
6- var SourceMapGenerator = require ( "source-map" ) . SourceMapGenerator ;
5+ var css = require ( "css" ) ;
6+ var SourceNode = require ( "source-map" ) . SourceNode ;
7+ var SourceMapConsumer = require ( "source-map" ) . SourceMapConsumer ;
78var loaderUtils = require ( "loader-utils" ) ;
89
910module . exports = function ( content , map ) {
1011 this . cacheable && this . cacheable ( ) ;
1112 var result = [ ] ;
12- var queryString = this . query || "" ;
13+ var cssRequest = loaderUtils . getRemainingRequest ( this ) ;
1314 var query = loaderUtils . parseQuery ( this . query ) ;
1415 var root = query . root ;
1516 var forceMinimize = query . minimize ;
1617 var importLoaders = parseInt ( query . importLoaders , 10 ) || 0 ;
1718 var minimize = typeof forceMinimize !== "undefined" ? ! ! forceMinimize : ( this && this . minimize ) ;
18- var tree = csso . parse ( content , "stylesheet" ) ;
19- if ( tree && minimize ) {
20- tree = csso . compress ( tree , query . disableStructuralMinification ) ;
21- tree = csso . cleanInfo ( tree ) ;
22- }
19+ var genSourceMap = query . sourceMap ;
2320
24- if ( tree ) {
25- var imports = extractImports ( tree ) ;
26- annotateUrls ( tree ) ;
21+ var tree = css . parse ( content , {
22+ source : cssRequest
23+ } ) ;
2724
28- imports . forEach ( function ( imp ) {
29- if ( ! loaderUtils . isUrlRequest ( imp . url ) ) {
30- result . push ( "exports.push([module.id, " + JSON . stringify ( "@import url(" + imp . url + ");" ) + ", " + JSON . stringify ( imp . media . join ( "" ) ) + "]);" ) ;
31- } else {
32- var importUrl = "-!" +
33- this . loaders . slice (
34- this . loaderIndex ,
35- this . loaderIndex + 1 + importLoaders
36- ) . map ( function ( x ) { return x . request ; } ) . join ( "!" ) + "!" +
37- loaderUtils . urlToRequest ( imp . url ) ;
38- result . push ( "require(" + JSON . stringify ( require . resolve ( "./mergeImport" ) ) + ")(exports, require(" + JSON . stringify ( importUrl ) + "), " + JSON . stringify ( imp . media . join ( "" ) ) + ");" ) ;
39- }
40- } , this ) ;
41- }
25+ var imports = extractImports ( tree . stylesheet ) ;
26+ annotateUrls ( tree ) ;
4227
43- var css = JSON . stringify ( tree ? csso . translate ( tree ) : "" ) ;
28+ imports . forEach ( function ( imp ) {
29+ if ( ! loaderUtils . isUrlRequest ( imp . url ) ) {
30+ result . push ( "exports.push([module.id, " + JSON . stringify ( "@import url(" + imp . url + ");" ) + ", " + JSON . stringify ( imp . media . join ( "" ) ) + "]);" ) ;
31+ } else {
32+ var importUrl = "-!" +
33+ this . loaders . slice (
34+ this . loaderIndex ,
35+ this . loaderIndex + 1 + importLoaders
36+ ) . map ( function ( x ) { return x . request ; } ) . join ( "!" ) + "!" +
37+ loaderUtils . urlToRequest ( imp . url ) ;
38+ result . push ( "require(" + JSON . stringify ( require . resolve ( "./mergeImport" ) ) + ")(exports, require(" + JSON . stringify ( importUrl ) + "), " + JSON . stringify ( imp . media . join ( " " ) ) + ");" ) ;
39+ }
40+ } , this ) ;
41+
42+
43+ var cssResult = css . stringify ( tree , {
44+ compress : ! ! minimize ,
45+ sourcemap : genSourceMap
46+ } ) ;
47+ var cssString = JSON . stringify ( genSourceMap ? cssResult . code : cssResult ) ;
4448 var uriRegExp = / % C S S U R L \[ % ( .* ?) % \] C S S U R L % / g;
45- css = css . replace ( uriRegExp , function ( str ) {
49+ cssString = cssString . replace ( uriRegExp , function ( str ) {
4650 var match = / ^ % C S S U R L \[ % ( [ " ' ] ? ( .* ?) [ " ' ] ? ) % \] C S S U R L % $ / . exec ( JSON . parse ( '"' + str + '"' ) ) ;
4751 var url = loaderUtils . parseString ( match [ 2 ] ) ;
4852 if ( ! loaderUtils . isUrlRequest ( match [ 2 ] , root ) ) return JSON . stringify ( match [ 1 ] ) . replace ( / ^ " | " $ / g, "" ) ;
@@ -58,107 +62,72 @@ module.exports = function(content, map) {
5862 }
5963 return "\"+require(" + JSON . stringify ( loaderUtils . urlToRequest ( url , root ) ) + ")+\"" ;
6064 } ) ;
61- if ( query . sourceMap && ! minimize ) {
62- var cssRequest = loaderUtils . getRemainingRequest ( this ) ;
65+ if ( genSourceMap ) {
6366 var request = loaderUtils . getCurrentRequest ( this ) ;
64- if ( ! map ) {
65- var sourceMap = new SourceMapGenerator ( {
67+
68+ if ( map ) {
69+ var node = SourceNode . fromStringWithSourceMap ( cssResult . code , new SourceMapConsumer ( cssResult . map ) ) ;
70+ node . applySourceMap ( map ) ;
71+ map = node . toStringWithSourceMap ( {
6672 file : request
67- } ) ;
68- var lines = content . split ( "\n" ) . length ;
69- for ( var i = 0 ; i < lines ; i ++ ) {
70- sourceMap . addMapping ( {
71- generated : {
72- line : i + 1 ,
73- column : 0
74- } ,
75- source : cssRequest ,
76- original : {
77- line : i + 1 ,
78- column : 0
79- } ,
80- } ) ;
81- }
82- sourceMap . setSourceContent ( cssRequest , content ) ;
83- map = JSON . stringify ( sourceMap . toJSON ( ) ) ;
84- } else if ( typeof map !== "string" ) {
85- map = JSON . stringify ( map ) ;
73+ } ) . map . toString ( ) ;
74+ } else {
75+ map = JSON . stringify ( cssResult . map ) ;
8676 }
87- result . push ( "exports.push([module.id, " + css + ", \"\", " + map + "]);" ) ;
77+ result . push ( "exports.push([module.id, " + cssString + ", \"\", " + map + "]);" ) ;
8878 } else {
89- result . push ( "exports.push([module.id, " + css + ", \"\"]);" ) ;
79+ result . push ( "exports.push([module.id, " + cssString + ", \"\"]);" ) ;
9080 }
9181 return "exports = module.exports = require(" + JSON . stringify ( require . resolve ( "./cssToString" ) ) + ")();\n" +
9282 result . join ( "\n" ) ;
9383}
9484
85+ function parseImport ( str ) {
86+ var m = / ^ \s * u r l \s * \( ( [ ^ \) ] + | \s * " [ ^ " ] " \s * | \s * ' [ ^ ' ] ' \s * ) \) \s * ( .* ) $ / i. exec ( str ) ;
87+ if ( ! m ) return ;
88+ return {
89+ url : loaderUtils . parseString ( m [ 1 ] . trim ( ) ) ,
90+ media : m [ 2 ] . split ( / \s + / )
91+ } ;
92+ }
93+
9594function extractImports ( tree ) {
9695 var results = [ ] ;
97- var removes = [ ] ;
98- for ( var i = 1 ; i < tree . length ; i ++ ) {
99- var rule = tree [ i ] ;
100- if ( rule [ 0 ] === "atrules" &&
101- rule [ 1 ] [ 0 ] === "atkeyword" &&
102- rule [ 1 ] [ 1 ] [ 0 ] === "ident" &&
103- rule [ 1 ] [ 1 ] [ 1 ] === "import" ) {
104- var imp = {
105- url : null ,
106- media : [ ]
107- } ;
108- for ( var j = 2 ; j < rule . length ; j ++ ) {
109- var item = rule [ j ] ;
110- if ( item [ 0 ] === "string" ) {
111- imp . url = loaderUtils . parseString ( item [ 1 ] ) ;
112- } else if ( item [ 0 ] === "uri" ) {
113- imp . url = item [ 1 ] [ 0 ] === "string" ? loaderUtils . parseString ( item [ 1 ] [ 1 ] ) : item [ 1 ] [ 1 ] ;
114- } else if ( item [ 0 ] === "ident" && item [ 1 ] !== "url" ) {
115- imp . media . push ( csso . translate ( item ) ) ;
116- } else if ( item [ 0 ] !== "s" || imp . media . length > 0 ) {
117- imp . media . push ( csso . translate ( item ) ) ;
118- }
119- }
120- while ( imp . media . length > 0 &&
121- / ^ \s * $ / . test ( imp . media [ imp . media . length - 1 ] ) )
122- imp . media . pop ( ) ;
123- if ( imp . url !== null ) {
124- results . push ( imp ) ;
125- removes . push ( i ) ;
126- }
96+ for ( var i = 0 ; i < tree . rules . length ; i ++ ) {
97+ var rule = tree . rules [ i ] ;
98+ if ( rule . type === "import" ) {
99+ var imp = parseImport ( rule . import ) ;
100+ if ( ! imp ) continue ;
101+ results . push ( imp ) ;
102+ tree . rules . splice ( i , 1 ) ;
103+ i -- ;
127104 }
128105 }
129- removes . reverse ( ) . forEach ( function ( i ) {
130- tree . splice ( i , 1 ) ;
131- } ) ;
132106 return results ;
133107}
108+
134109function annotateUrls ( tree ) {
135- function iterateChildren ( ) {
136- for ( var i = 1 ; i < tree . length ; i ++ ) {
137- annotateUrls ( tree [ i ] ) ;
110+ function iterateChildren ( children ) {
111+ for ( var i = 0 ; i < children . length ; i ++ ) {
112+ annotateUrls ( children [ i ] ) ;
138113 }
139114 }
140- switch ( tree [ 0 ] ) {
141- case "stylesheet" : return iterateChildren ( ) ;
142- case "ruleset" : return iterateChildren ( ) ;
143- case "block" : return iterateChildren ( ) ;
144- case "atruleb" : return iterateChildren ( ) ;
145- case "atruler" : return iterateChildren ( ) ;
146- case "atrulers" : return iterateChildren ( ) ;
147- case "declaration" : return iterateChildren ( ) ;
148- case "value" : return iterateChildren ( ) ;
149- case "uri" :
150- for ( var i = 1 ; i < tree . length ; i ++ ) {
151- var item = tree [ i ] ;
152- switch ( item [ 0 ] ) {
153- case "ident" :
154- case "raw" :
155- item [ 1 ] = "%CSSURL[%" + item [ 1 ] + "%]CSSURL%" ;
156- return ;
157- case "string" :
158- item [ 1 ] = "%CSSURL[%" + item [ 1 ] + "%]CSSURL%" ;
159- return ;
160- }
161- }
115+ switch ( tree . type ) {
116+ case "stylesheet" : return iterateChildren ( tree . stylesheet . rules ) ;
117+ case "rule" : return iterateChildren ( tree . declarations ) ;
118+ case "document" : return iterateChildren ( tree . rules ) ;
119+ case "font-face" : return iterateChildren ( tree . declarations ) ;
120+ case "host" : return iterateChildren ( tree . rules ) ;
121+ case "keyframes" : return iterateChildren ( tree . keyframes ) ;
122+ case "keyframe" : return iterateChildren ( tree . declarations ) ;
123+ case "media" : return iterateChildren ( tree . rules ) ;
124+ case "page" : return iterateChildren ( tree . declarations ) ;
125+ case "supports" : return iterateChildren ( tree . rules ) ;
126+ case "declaration" :
127+ tree . value = tree . value . replace ( / u r l \s * \( ( [ ^ \) ] + | \s * " [ ^ " ] " \s * | \s * ' [ ^ ' ] ' \s * ) \) / ig, function ( match ) {
128+ var m = / ^ u r l \s * \( ( [ ^ \) ] + | \s * " [ ^ " ] " \s * | \s * ' [ ^ ' ] ' \s * ) \) $ / i. exec ( match ) ;
129+ return "url(%CSSURL[%" + m [ 1 ] . trim ( ) + "%]CSSURL%)" ;
130+ } ) ;
162131 }
163132}
164133
0 commit comments