2
2
MIT License http://www.opensource.org/licenses/mit-license.php
3
3
Author Tobias Koppers @sokra
4
4
*/
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 ;
7
8
var loaderUtils = require ( "loader-utils" ) ;
8
9
9
10
module . exports = function ( content , map ) {
10
11
this . cacheable && this . cacheable ( ) ;
11
12
var result = [ ] ;
12
- var queryString = this . query || "" ;
13
+ var cssRequest = loaderUtils . getRemainingRequest ( this ) ;
13
14
var query = loaderUtils . parseQuery ( this . query ) ;
14
15
var root = query . root ;
15
16
var forceMinimize = query . minimize ;
16
17
var importLoaders = parseInt ( query . importLoaders , 10 ) || 0 ;
17
18
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 ;
23
20
24
- if ( tree ) {
25
- var imports = extractImports ( tree ) ;
26
- annotateUrls ( tree ) ;
21
+ var tree = css . parse ( content , {
22
+ source : cssRequest
23
+ } ) ;
27
24
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 ) ;
42
27
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 ) ;
44
48
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 ) {
46
50
var match = / ^ % C S S U R L \[ % ( [ " ' ] ? ( .* ?) [ " ' ] ? ) % \] C S S U R L % $ / . exec ( JSON . parse ( '"' + str + '"' ) ) ;
47
51
var url = loaderUtils . parseString ( match [ 2 ] ) ;
48
52
if ( ! loaderUtils . isUrlRequest ( match [ 2 ] , root ) ) return JSON . stringify ( match [ 1 ] ) . replace ( / ^ " | " $ / g, "" ) ;
@@ -58,107 +62,72 @@ module.exports = function(content, map) {
58
62
}
59
63
return "\"+require(" + JSON . stringify ( loaderUtils . urlToRequest ( url , root ) ) + ")+\"" ;
60
64
} ) ;
61
- if ( query . sourceMap && ! minimize ) {
62
- var cssRequest = loaderUtils . getRemainingRequest ( this ) ;
65
+ if ( genSourceMap ) {
63
66
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 ( {
66
72
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 ) ;
86
76
}
87
- result . push ( "exports.push([module.id, " + css + ", \"\", " + map + "]);" ) ;
77
+ result . push ( "exports.push([module.id, " + cssString + ", \"\", " + map + "]);" ) ;
88
78
} else {
89
- result . push ( "exports.push([module.id, " + css + ", \"\"]);" ) ;
79
+ result . push ( "exports.push([module.id, " + cssString + ", \"\"]);" ) ;
90
80
}
91
81
return "exports = module.exports = require(" + JSON . stringify ( require . resolve ( "./cssToString" ) ) + ")();\n" +
92
82
result . join ( "\n" ) ;
93
83
}
94
84
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
+
95
94
function extractImports ( tree ) {
96
95
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 -- ;
127
104
}
128
105
}
129
- removes . reverse ( ) . forEach ( function ( i ) {
130
- tree . splice ( i , 1 ) ;
131
- } ) ;
132
106
return results ;
133
107
}
108
+
134
109
function 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 ] ) ;
138
113
}
139
114
}
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
+ } ) ;
162
131
}
163
132
}
164
133
0 commit comments