|
| 1 | +/* |
| 2 | + MIT License http://www.opensource.org/licenses/mit-license.php |
| 3 | + Author Tobias Koppers @sokra |
| 4 | +*/ |
| 5 | +var path = require("path"); |
| 6 | +var parseSource = require("./parseSource"); |
| 7 | +var ReplaceMany = require("./ReplaceMany"); |
| 8 | +var loaderUtils = require("loader-utils"); |
| 9 | +var SourceListMap = require("source-list-map").SourceListMap; |
| 10 | +var fromStringWithSourceMap = require("source-list-map").fromStringWithSourceMap; |
| 11 | +var CleanCSS = require("clean-css"); |
| 12 | + |
| 13 | +module.exports = function(content, map) { |
| 14 | + this.cacheable && this.cacheable(); |
| 15 | + var query = loaderUtils.parseQuery(this.query); |
| 16 | + var root = query.root; |
| 17 | + var forceMinimize = query.minimize; |
| 18 | + var importLoaders = parseInt(query.importLoaders, 10) || 0; |
| 19 | + var minimize = typeof forceMinimize !== "undefined" ? !!forceMinimize : (this && this.minimize); |
| 20 | + |
| 21 | + if(typeof map !== "string") { |
| 22 | + map = JSON.stringify(map); |
| 23 | + } |
| 24 | + |
| 25 | + var result = []; |
| 26 | + |
| 27 | + var stuff = parseSource(content); |
| 28 | + |
| 29 | + var replacer = new ReplaceMany(); |
| 30 | + stuff.imports.forEach(function(imp) { |
| 31 | + replacer.replace(imp.start, imp.length, ""); |
| 32 | + if(!loaderUtils.isUrlRequest(imp.url, root)) { |
| 33 | + result.push("exports.push([module.id, " + |
| 34 | + JSON.stringify("@import url(" + imp.url + ");") + ", " + |
| 35 | + JSON.stringify(imp.mediaQuery) + "]);"); |
| 36 | + } else { |
| 37 | + var loadersRequest = this.loaders.slice( |
| 38 | + this.loaderIndex, |
| 39 | + this.loaderIndex + 1 + importLoaders |
| 40 | + ).map(function(x) { return x.request; }).join("!"); |
| 41 | + var importUrl = "-!" + |
| 42 | + loadersRequest + "!" + |
| 43 | + loaderUtils.urlToRequest(imp.url); |
| 44 | + result.push("exports.i(require(" + loaderUtils.stringifyRequest(this, importUrl) + "), " + JSON.stringify(imp.mediaQuery) + ");"); |
| 45 | + } |
| 46 | + }, this); |
| 47 | + stuff.urls.forEach(function(url, idx) { |
| 48 | + replacer.replace(url.start, url.length, "__CSSLOADERURL_" + idx + "__"); |
| 49 | + }); |
| 50 | + var placeholders = {}; |
| 51 | + stuff.placeholders.forEach(function(placeholder) { |
| 52 | + var hash = require("crypto").createHash("md5"); |
| 53 | + hash.update(this.request); |
| 54 | + hash.update(placeholder.name); |
| 55 | + var ident = "z" + hash.digest("hex"); |
| 56 | + placeholders[placeholder.name] = ident; |
| 57 | + replacer.replace(placeholder.start, placeholder.length, ident); |
| 58 | + }, this); |
| 59 | + |
| 60 | + var cssContent = replacer.run(content); |
| 61 | + |
| 62 | + if(minimize) { |
| 63 | + var options = Object.create(query); |
| 64 | + if(query.sourceMap && map) { |
| 65 | + options.sourceMap = map; |
| 66 | + } |
| 67 | + var minimizeResult = new CleanCSS(options).minify(cssContent); |
| 68 | + map = minimizeResult.sourceMap; |
| 69 | + cssContent = minimizeResult.styles; |
| 70 | + if(typeof map !== "string") |
| 71 | + map = JSON.stringify(map); |
| 72 | + } |
| 73 | + |
| 74 | + var css = JSON.stringify(cssContent); |
| 75 | + |
| 76 | + var urlRegExp = /__CSSLOADERURL_[0-9]+__/g; |
| 77 | + css = css.replace(urlRegExp, function(str) { |
| 78 | + var match = /^__CSSLOADERURL_([0-9]+)__$/.exec(str); |
| 79 | + if(!match) return str; |
| 80 | + var idx = parseInt(match[1], 10); |
| 81 | + if(!stuff.urls[idx]) return str; |
| 82 | + var urlItem = stuff.urls[idx]; |
| 83 | + var url = urlItem.url; |
| 84 | + if(!loaderUtils.isUrlRequest(url, root)) |
| 85 | + return toEmbStr(urlItem.raw); |
| 86 | + var idx = url.indexOf("?#"); |
| 87 | + if(idx < 0) idx = url.indexOf("#"); |
| 88 | + if(idx > 0) { |
| 89 | + // in cases like url('webfont.eot?#iefix') |
| 90 | + var request = url.substr(0, idx); |
| 91 | + return "\"+require(" + loaderUtils.stringifyRequest(this, loaderUtils.urlToRequest(request, root)) + ")+\"" + url.substr(idx); |
| 92 | + } else if(idx === 0) { |
| 93 | + // only hash |
| 94 | + return toEmbStr(urlItem.raw); |
| 95 | + } |
| 96 | + return "\"+require(" + loaderUtils.stringifyRequest(this, loaderUtils.urlToRequest(url, root)) + ")+\""; |
| 97 | + }.bind(this)); |
| 98 | + |
| 99 | + function toEmbStr(str) { |
| 100 | + return JSON.stringify(str).replace(/^"|"$/g, ""); |
| 101 | + } |
| 102 | + |
| 103 | + if(query.sourceMap && !minimize) { |
| 104 | + var cssRequest = loaderUtils.getRemainingRequest(this); |
| 105 | + var request = loaderUtils.getCurrentRequest(this); |
| 106 | + if(!map) { |
| 107 | + var sourceMap = new SourceListMap(); |
| 108 | + sourceMap.add(content, cssRequest, content); |
| 109 | + map = sourceMap.toStringWithSourceMap({ |
| 110 | + file: request |
| 111 | + }).map; |
| 112 | + if(map.sources) { |
| 113 | + map.sources = map.sources.map(function(source) { |
| 114 | + var p = path.relative(query.context || this.options.context, source).replace(/\\/g, "/"); |
| 115 | + if(p.indexOf("../") !== 0) |
| 116 | + p = "./" + p; |
| 117 | + return "/" + p; |
| 118 | + }, this); |
| 119 | + map.sourceRoot = "webpack://"; |
| 120 | + } |
| 121 | + map = JSON.stringify(map); |
| 122 | + } |
| 123 | + result.push("exports.push([module.id, " + css + ", \"\", " + map + "]);"); |
| 124 | + } else { |
| 125 | + result.push("exports.push([module.id, " + css + ", \"\"]);"); |
| 126 | + } |
| 127 | + |
| 128 | + return "exports = module.exports = require(" + loaderUtils.stringifyRequest(this, require.resolve("./css-base.js")) + ")();\n" + |
| 129 | + result.join("\n"); |
| 130 | +} |
0 commit comments