|  | 
| 3 | 3 | 	Author Tobias Koppers @sokra | 
| 4 | 4 | */ | 
| 5 | 5 | var loaderUtils = require("loader-utils"); | 
| 6 |  | -var processCss = require("./processCss"); | 
|  | 6 | +var postcss = require("postcss"); | 
|  | 7 | +var plugin = require("./plugin"); | 
| 7 | 8 | var getImportPrefix = require("./getImportPrefix"); | 
| 8 | 9 | var compileExports = require("./compile-exports"); | 
| 9 |  | - | 
|  | 10 | +var CssLoaderError = require("./CssLoaderError"); | 
| 10 | 11 | 
 | 
| 11 | 12 | module.exports = function(content, map) { | 
| 12 |  | -	var callback = this.async(); | 
| 13 |  | -	var query = loaderUtils.getOptions(this) || {}; | 
| 14 |  | -	var camelCaseKeys = query.camelCase; | 
| 15 |  | -	var sourceMap = query.sourceMap || false; | 
| 16 |  | - | 
| 17 |  | -	if(sourceMap) { | 
| 18 |  | -		if (map) { | 
| 19 |  | -			if (typeof map === "string") { | 
| 20 |  | -				map = JSON.stringify(map); | 
| 21 |  | -			} | 
| 22 |  | - | 
| 23 |  | -			if (map.sources) { | 
| 24 |  | -				map.sources = map.sources.map(function (source) { | 
| 25 |  | -					return source.replace(/\\/g, '/'); | 
| 26 |  | -				}); | 
| 27 |  | -				map.sourceRoot = ''; | 
| 28 |  | -			} | 
| 29 |  | -		} | 
| 30 |  | -	} else { | 
| 31 |  | -		// Some loaders (example `"postcss-loader": "1.x.x"`) always generates source map, we should remove it | 
| 32 |  | -		map = null; | 
| 33 |  | -	} | 
| 34 |  | - | 
| 35 |  | -	processCss(content, map, { | 
| 36 |  | -		from: loaderUtils.getRemainingRequest(this).split("!").pop(), | 
| 37 |  | -		to: loaderUtils.getCurrentRequest(this).split("!").pop(), | 
| 38 |  | -		query: query, | 
| 39 |  | -		loaderContext: this, | 
| 40 |  | -		sourceMap: sourceMap | 
| 41 |  | -	}, function(err, result) { | 
| 42 |  | -		if(err) return callback(err); | 
| 43 |  | - | 
| 44 |  | -		var cssAsString = JSON.stringify(result.source); | 
| 45 |  | - | 
| 46 |  | -		// for importing CSS | 
| 47 |  | -		var importUrlPrefix = getImportPrefix(this, query); | 
| 48 |  | - | 
| 49 |  | -		var alreadyImported = {}; | 
| 50 |  | -		var importJs = result.importItems.filter(function(imp) { | 
| 51 |  | -			if(!imp.mediaQuery) { | 
| 52 |  | -				if(alreadyImported[imp.url]) | 
| 53 |  | -					return false; | 
| 54 |  | -				alreadyImported[imp.url] = true; | 
| 55 |  | -			} | 
| 56 |  | -			return true; | 
| 57 |  | -		}).map(function(imp) { | 
| 58 |  | -			if(!loaderUtils.isUrlRequest(imp.url)) { | 
| 59 |  | -				return "exports.push([module.id, " + | 
| 60 |  | -					JSON.stringify("@import url(" + imp.url + ");") + ", " + | 
| 61 |  | -					JSON.stringify(imp.mediaQuery) + "]);"; | 
| 62 |  | -			} else { | 
| 63 |  | -				var importUrl = importUrlPrefix + imp.url; | 
| 64 |  | -				return "exports.i(require(" + loaderUtils.stringifyRequest(this, importUrl) + "), " + JSON.stringify(imp.mediaQuery) + ");"; | 
| 65 |  | -			} | 
| 66 |  | -		}, this).join("\n"); | 
| 67 |  | - | 
| 68 |  | -		function importItemMatcher(item) { | 
| 69 |  | -			var match = result.importItemRegExp.exec(item); | 
| 70 |  | -			var idx = +match[1]; | 
| 71 |  | -			var importItem = result.importItems[idx]; | 
| 72 |  | -			var importUrl = importUrlPrefix + importItem.url; | 
| 73 |  | -			return "\" + require(" + loaderUtils.stringifyRequest(this, importUrl) + ").locals" + | 
| 74 |  | -				"[" + JSON.stringify(importItem.export) + "] + \""; | 
| 75 |  | -		} | 
| 76 |  | - | 
| 77 |  | -		cssAsString = cssAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this)); | 
| 78 |  | - | 
| 79 |  | -		// helper for ensuring valid CSS strings from requires | 
| 80 |  | -		var urlEscapeHelper = ""; | 
| 81 |  | - | 
| 82 |  | -		if(query.url !== false && result.urlItems.length > 0) { | 
| 83 |  | -			urlEscapeHelper = "var escape = require(" + loaderUtils.stringifyRequest(this, require.resolve("./url/escape.js")) + ");\n"; | 
| 84 |  | - | 
| 85 |  | -			cssAsString = cssAsString.replace(result.urlItemRegExpG, function(item) { | 
| 86 |  | -				var match = result.urlItemRegExp.exec(item); | 
| 87 |  | -				var idx = +match[1]; | 
| 88 |  | -				var urlItem = result.urlItems[idx]; | 
| 89 |  | -				var url = urlItem.url; | 
| 90 |  | -				idx = url.indexOf("?#"); | 
| 91 |  | -				if(idx < 0) idx = url.indexOf("#"); | 
| 92 |  | -				var urlRequest; | 
| 93 |  | -				if(idx > 0) { // idx === 0 is catched by isUrlRequest | 
| 94 |  | -					// in cases like url('webfont.eot?#iefix') | 
| 95 |  | -					urlRequest = url.substr(0, idx); | 
| 96 |  | -					return "\" + escape(require(" + loaderUtils.stringifyRequest(this, urlRequest) + ")) + \"" + | 
| 97 |  | -							url.substr(idx); | 
| 98 |  | -				} | 
| 99 |  | -				urlRequest = url; | 
| 100 |  | -				return "\" + escape(require(" + loaderUtils.stringifyRequest(this, urlRequest) + ")) + \""; | 
| 101 |  | -			}.bind(this)); | 
| 102 |  | -		} | 
| 103 |  | - | 
| 104 |  | -		var exportJs = compileExports(result, importItemMatcher.bind(this), camelCaseKeys); | 
| 105 |  | -		if (exportJs) { | 
| 106 |  | -			exportJs = "exports.locals = " + exportJs + ";"; | 
| 107 |  | -		} | 
| 108 |  | - | 
| 109 |  | -		var moduleJs; | 
| 110 |  | -		if(sourceMap && result.map) { | 
| 111 |  | -			// add a SourceMap | 
| 112 |  | -			map = result.map; | 
| 113 |  | -			if(map.sources) { | 
| 114 |  | -				map.sources = map.sources.map(function(source) { | 
| 115 |  | -					return source.split("!").pop().replace(/\\/g, '/'); | 
| 116 |  | -				}, this); | 
| 117 |  | -				map.sourceRoot = ""; | 
| 118 |  | -			} | 
| 119 |  | -			map.file = map.file.split("!").pop().replace(/\\/g, '/'); | 
| 120 |  | -			map = JSON.stringify(map); | 
| 121 |  | -			moduleJs = "exports.push([module.id, " + cssAsString + ", \"\", " + map + "]);"; | 
| 122 |  | -		} else { | 
| 123 |  | -			moduleJs = "exports.push([module.id, " + cssAsString + ", \"\"]);"; | 
| 124 |  | -		} | 
| 125 |  | - | 
| 126 |  | -		// embed runtime | 
| 127 |  | -		callback(null, urlEscapeHelper + | 
| 128 |  | -			"exports = module.exports = require(" + | 
| 129 |  | -			loaderUtils.stringifyRequest(this, require.resolve("./runtime.js")) + | 
| 130 |  | -			")(" + sourceMap + ");\n" + | 
| 131 |  | -			"// imports\n" + | 
| 132 |  | -			importJs + "\n\n" + | 
| 133 |  | -			"// module\n" + | 
| 134 |  | -			moduleJs + "\n\n" + | 
| 135 |  | -			"// exports\n" + | 
| 136 |  | -			exportJs); | 
| 137 |  | -	}.bind(this)); | 
|  | 13 | +  var callback = this.async(); | 
|  | 14 | +  var query = loaderUtils.getOptions(this) || {}; | 
|  | 15 | +  var camelCaseKeys = query.camelCase; | 
|  | 16 | +  var sourceMap = query.sourceMap || false; | 
|  | 17 | +  var loaderContext = this; | 
|  | 18 | + | 
|  | 19 | +  if (sourceMap) { | 
|  | 20 | +    if (map) { | 
|  | 21 | +      if (typeof map === "string") { | 
|  | 22 | +        map = JSON.stringify(map); | 
|  | 23 | +      } | 
|  | 24 | + | 
|  | 25 | +      if (map.sources) { | 
|  | 26 | +        map.sources = map.sources.map(function(source) { | 
|  | 27 | +          return source.replace(/\\/g, "/"); | 
|  | 28 | +        }); | 
|  | 29 | +        map.sourceRoot = ""; | 
|  | 30 | +      } | 
|  | 31 | +    } | 
|  | 32 | +  } else { | 
|  | 33 | +    // Some loaders (example `"postcss-loader": "1.x.x"`) always generates source map, we should remove it | 
|  | 34 | +    map = null; | 
|  | 35 | +  } | 
|  | 36 | + | 
|  | 37 | +  var parserOptions = { | 
|  | 38 | +    url: query.url !== false, | 
|  | 39 | +    import: query.import !== false, | 
|  | 40 | +    resolve: loaderContext.resolve | 
|  | 41 | +  }; | 
|  | 42 | + | 
|  | 43 | +  postcss([plugin(parserOptions)]) | 
|  | 44 | +    .process(content, { | 
|  | 45 | +      // we need a prefix to avoid path rewriting of PostCSS | 
|  | 46 | +      from: | 
|  | 47 | +        "/css-loader!" + | 
|  | 48 | +        loaderUtils | 
|  | 49 | +          .getRemainingRequest(loaderContext) | 
|  | 50 | +          .split("!") | 
|  | 51 | +          .pop(), | 
|  | 52 | +      to: loaderUtils | 
|  | 53 | +        .getCurrentRequest(loaderContext) | 
|  | 54 | +        .split("!") | 
|  | 55 | +        .pop(), | 
|  | 56 | +      map: sourceMap | 
|  | 57 | +        ? { | 
|  | 58 | +            prev: map, | 
|  | 59 | +            sourcesContent: true, | 
|  | 60 | +            inline: false, | 
|  | 61 | +            annotation: false | 
|  | 62 | +          } | 
|  | 63 | +        : null | 
|  | 64 | +    }) | 
|  | 65 | +    .then(function(result) { | 
|  | 66 | +      var cssAsString = JSON.stringify(result.css); | 
|  | 67 | +      // for importing CSS | 
|  | 68 | +      var importUrlPrefix = getImportPrefix(loaderContext, query); | 
|  | 69 | +      var alreadyImported = {}; | 
|  | 70 | +      var importItems = parserOptions.importItems; | 
|  | 71 | +      var importJs = importItems | 
|  | 72 | +        .filter(function(imp) { | 
|  | 73 | +          if (!imp.mediaQuery) { | 
|  | 74 | +            if (alreadyImported[imp.url]) { | 
|  | 75 | +              return false; | 
|  | 76 | +            } | 
|  | 77 | + | 
|  | 78 | +            alreadyImported[imp.url] = true; | 
|  | 79 | +          } | 
|  | 80 | + | 
|  | 81 | +          return true; | 
|  | 82 | +        }) | 
|  | 83 | +        .map(function(imp) { | 
|  | 84 | +          if (!loaderUtils.isUrlRequest(imp.url)) { | 
|  | 85 | +            return ( | 
|  | 86 | +              "exports.push([module.id, " + | 
|  | 87 | +              JSON.stringify("@import url(" + imp.url + ");") + | 
|  | 88 | +              ", " + | 
|  | 89 | +              JSON.stringify(imp.mediaQuery) + | 
|  | 90 | +              "]);" | 
|  | 91 | +            ); | 
|  | 92 | +          } else { | 
|  | 93 | +            var importUrl = importUrlPrefix + imp.url; | 
|  | 94 | + | 
|  | 95 | +            return ( | 
|  | 96 | +              "exports.i(require(" + | 
|  | 97 | +              loaderUtils.stringifyRequest(this, importUrl) + | 
|  | 98 | +              "), " + | 
|  | 99 | +              JSON.stringify(imp.mediaQuery) + | 
|  | 100 | +              ");" | 
|  | 101 | +            ); | 
|  | 102 | +          } | 
|  | 103 | +        }, loaderContext) | 
|  | 104 | +        .join("\n"); | 
|  | 105 | + | 
|  | 106 | +      function importItemMatcher(item) { | 
|  | 107 | +        var match = /___CSS_LOADER_IMPORT___([0-9]+)___/.exec(item); | 
|  | 108 | +        var idx = +match[1]; | 
|  | 109 | +        var importItem = parserOptions.importItems[idx]; | 
|  | 110 | +        var importUrl = importUrlPrefix + importItem.url; | 
|  | 111 | + | 
|  | 112 | +        return ( | 
|  | 113 | +          '" + require(' + | 
|  | 114 | +          loaderUtils.stringifyRequest(this, importUrl) + | 
|  | 115 | +          ").locals" + | 
|  | 116 | +          "[" + | 
|  | 117 | +          JSON.stringify(importItem.export) + | 
|  | 118 | +          '] + "' | 
|  | 119 | +        ); | 
|  | 120 | +      } | 
|  | 121 | + | 
|  | 122 | +      cssAsString = cssAsString.replace( | 
|  | 123 | +        /___CSS_LOADER_IMPORT___([0-9]+)___/g, | 
|  | 124 | +        importItemMatcher | 
|  | 125 | +      ); | 
|  | 126 | + | 
|  | 127 | +      // helper for ensuring valid CSS strings from requires | 
|  | 128 | +      var urlEscapeHelper = ""; | 
|  | 129 | +      var urlItems = parserOptions.urlItems; | 
|  | 130 | + | 
|  | 131 | +      if (query.url !== false && urlItems.length > 0) { | 
|  | 132 | +        urlEscapeHelper = | 
|  | 133 | +          "var escape = require(" + | 
|  | 134 | +          loaderUtils.stringifyRequest( | 
|  | 135 | +            loaderContext, | 
|  | 136 | +            require.resolve("./url/escape.js") | 
|  | 137 | +          ) + | 
|  | 138 | +          ");\n"; | 
|  | 139 | + | 
|  | 140 | +        cssAsString = cssAsString.replace( | 
|  | 141 | +          /___CSS_LOADER_URL___([0-9]+)___/g, | 
|  | 142 | +          function(item) { | 
|  | 143 | +            var match = /___CSS_LOADER_URL___([0-9]+)___/.exec(item); | 
|  | 144 | +            var idx = +match[1]; | 
|  | 145 | +            var urlItem = urlItems[idx]; | 
|  | 146 | +            var url = urlItem.url; | 
|  | 147 | + | 
|  | 148 | +            idx = url.indexOf("?#"); | 
|  | 149 | + | 
|  | 150 | +            if (idx < 0) { | 
|  | 151 | +              idx = url.indexOf("#"); | 
|  | 152 | +            } | 
|  | 153 | + | 
|  | 154 | +            var urlRequest; | 
|  | 155 | + | 
|  | 156 | +            if (idx > 0) { | 
|  | 157 | +              // idx === 0 is catched by isUrlRequest | 
|  | 158 | +              // in cases like url('webfont.eot?#iefix') | 
|  | 159 | +              urlRequest = url.substr(0, idx); | 
|  | 160 | + | 
|  | 161 | +              return ( | 
|  | 162 | +                '" + escape(require(' + | 
|  | 163 | +                loaderUtils.stringifyRequest(loaderContext, urlRequest) + | 
|  | 164 | +                ')) + "' + | 
|  | 165 | +                url.substr(idx) | 
|  | 166 | +              ); | 
|  | 167 | +            } | 
|  | 168 | + | 
|  | 169 | +            urlRequest = url; | 
|  | 170 | + | 
|  | 171 | +            return ( | 
|  | 172 | +              '" + escape(require(' + | 
|  | 173 | +              loaderUtils.stringifyRequest(loaderContext, urlRequest) + | 
|  | 174 | +              ')) + "' | 
|  | 175 | +            ); | 
|  | 176 | +          } | 
|  | 177 | +        ); | 
|  | 178 | +      } | 
|  | 179 | + | 
|  | 180 | +      var exportJs = compileExports( | 
|  | 181 | +        parserOptions, | 
|  | 182 | +        importItemMatcher, | 
|  | 183 | +        camelCaseKeys | 
|  | 184 | +      ); | 
|  | 185 | + | 
|  | 186 | +      if (exportJs) { | 
|  | 187 | +        exportJs = "exports.locals = " + exportJs + ";"; | 
|  | 188 | +      } | 
|  | 189 | + | 
|  | 190 | +      var moduleJs; | 
|  | 191 | + | 
|  | 192 | +      if (sourceMap && result.map) { | 
|  | 193 | +        // add a SourceMap | 
|  | 194 | +        map = result.map.toJSON(); | 
|  | 195 | + | 
|  | 196 | +        if (map.sources) { | 
|  | 197 | +          map.sources = map.sources.map(function(source) { | 
|  | 198 | +            return source | 
|  | 199 | +              .split("!") | 
|  | 200 | +              .pop() | 
|  | 201 | +              .replace(/\\/g, "/"); | 
|  | 202 | +          }, loaderContext); | 
|  | 203 | +          map.sourceRoot = ""; | 
|  | 204 | +        } | 
|  | 205 | + | 
|  | 206 | +        map.file = map.file | 
|  | 207 | +          .split("!") | 
|  | 208 | +          .pop() | 
|  | 209 | +          .replace(/\\/g, "/"); | 
|  | 210 | +        map = JSON.stringify(map); | 
|  | 211 | + | 
|  | 212 | +        moduleJs = | 
|  | 213 | +          "exports.push([module.id, " + cssAsString + ', "", ' + map + "]);"; | 
|  | 214 | +      } else { | 
|  | 215 | +        moduleJs = "exports.push([module.id, " + cssAsString + ', ""]);'; | 
|  | 216 | +      } | 
|  | 217 | + | 
|  | 218 | +      // embed runtime | 
|  | 219 | +      callback( | 
|  | 220 | +        null, | 
|  | 221 | +        urlEscapeHelper + | 
|  | 222 | +          "exports = module.exports = require(" + | 
|  | 223 | +          loaderUtils.stringifyRequest( | 
|  | 224 | +            loaderContext, | 
|  | 225 | +            require.resolve("./runtime.js") | 
|  | 226 | +          ) + | 
|  | 227 | +          ")(" + | 
|  | 228 | +          sourceMap + | 
|  | 229 | +          ");\n" + | 
|  | 230 | +          "// imports\n" + | 
|  | 231 | +          importJs + | 
|  | 232 | +          "\n\n" + | 
|  | 233 | +          "// module\n" + | 
|  | 234 | +          moduleJs + | 
|  | 235 | +          "\n\n" + | 
|  | 236 | +          "// exports\n" + | 
|  | 237 | +          exportJs | 
|  | 238 | +      ); | 
|  | 239 | +    }) | 
|  | 240 | +    .catch(function(error) { | 
|  | 241 | +      callback( | 
|  | 242 | +        error.name === "CssSyntaxError" | 
|  | 243 | +          ? new CssLoaderError( | 
|  | 244 | +              "Syntax Error", | 
|  | 245 | +              error.reason, | 
|  | 246 | +              error.line != null && error.column != null | 
|  | 247 | +                ? { line: error.line, column: error.column } | 
|  | 248 | +                : null, | 
|  | 249 | +              error.input.source | 
|  | 250 | +            ) | 
|  | 251 | +          : error | 
|  | 252 | +      ); | 
|  | 253 | +    }); | 
| 138 | 254 | }; | 
0 commit comments