loader.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. var loaderUtils = require("loader-utils");
  6. var processCss = require("./processCss");
  7. var getImportPrefix = require("./getImportPrefix");
  8. var compileExports = require("./compile-exports");
  9. var createResolver = require("./createResolver");
  10. module.exports = function(content, map) {
  11. if(this.cacheable) this.cacheable();
  12. var callback = this.async();
  13. var query = loaderUtils.getOptions(this) || {};
  14. var root = query.root;
  15. var moduleMode = query.modules || query.module;
  16. var camelCaseKeys = query.camelCase || query.camelcase;
  17. var sourceMap = query.sourceMap || false;
  18. var resolve = createResolver(query.alias);
  19. if(sourceMap) {
  20. if (map) {
  21. if (typeof map === "string") {
  22. map = JSON.stringify(map);
  23. }
  24. if (map.sources) {
  25. map.sources = map.sources.map(function (source) {
  26. return source.replace(/\\/g, '/');
  27. });
  28. map.sourceRoot = '';
  29. }
  30. }
  31. } else {
  32. // Some loaders (example `"postcss-loader": "1.x.x"`) always generates source map, we should remove it
  33. map = null;
  34. }
  35. processCss(content, map, {
  36. mode: moduleMode ? "local" : "global",
  37. from: loaderUtils.getRemainingRequest(this).split("!").pop(),
  38. to: loaderUtils.getCurrentRequest(this).split("!").pop(),
  39. query: query,
  40. minimize: this.minimize,
  41. loaderContext: this,
  42. sourceMap: sourceMap
  43. }, function(err, result) {
  44. if(err) return callback(err);
  45. var cssAsString = JSON.stringify(result.source);
  46. // for importing CSS
  47. var importUrlPrefix = getImportPrefix(this, query);
  48. var alreadyImported = {};
  49. var importJs = result.importItems.filter(function(imp) {
  50. if(!imp.mediaQuery) {
  51. if(alreadyImported[imp.url])
  52. return false;
  53. alreadyImported[imp.url] = true;
  54. }
  55. return true;
  56. }).map(function(imp) {
  57. if(!loaderUtils.isUrlRequest(imp.url, root)) {
  58. return "exports.push([module.id, " +
  59. JSON.stringify("@import url(" + imp.url + ");") + ", " +
  60. JSON.stringify(imp.mediaQuery) + "]);";
  61. } else {
  62. var importUrl = importUrlPrefix + imp.url;
  63. return "exports.i(require(" + loaderUtils.stringifyRequest(this, importUrl) + "), " + JSON.stringify(imp.mediaQuery) + ");";
  64. }
  65. }, this).join("\n");
  66. function importItemMatcher(item) {
  67. var match = result.importItemRegExp.exec(item);
  68. var idx = +match[1];
  69. var importItem = result.importItems[idx];
  70. var importUrl = importUrlPrefix + importItem.url;
  71. return "\" + require(" + loaderUtils.stringifyRequest(this, importUrl) + ").locals" +
  72. "[" + JSON.stringify(importItem.export) + "] + \"";
  73. }
  74. cssAsString = cssAsString.replace(result.importItemRegExpG, importItemMatcher.bind(this));
  75. if(query.url !== false) {
  76. cssAsString = cssAsString.replace(result.urlItemRegExpG, function(item) {
  77. var match = result.urlItemRegExp.exec(item);
  78. var idx = +match[1];
  79. var urlItem = result.urlItems[idx];
  80. var url = resolve(urlItem.url);
  81. idx = url.indexOf("?#");
  82. if(idx < 0) idx = url.indexOf("#");
  83. var urlRequest;
  84. if(idx > 0) { // idx === 0 is catched by isUrlRequest
  85. // in cases like url('webfont.eot?#iefix')
  86. urlRequest = url.substr(0, idx);
  87. return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \"" +
  88. url.substr(idx);
  89. }
  90. urlRequest = url;
  91. return "\" + require(" + loaderUtils.stringifyRequest(this, urlRequest) + ") + \"";
  92. }.bind(this));
  93. }
  94. var exportJs = compileExports(result, importItemMatcher.bind(this), camelCaseKeys);
  95. if (exportJs) {
  96. exportJs = "exports.locals = " + exportJs + ";";
  97. }
  98. var moduleJs;
  99. if(query.sourceMap && result.map) {
  100. // add a SourceMap
  101. map = result.map;
  102. if(map.sources) {
  103. map.sources = map.sources.map(function(source) {
  104. return source.split("!").pop().replace(/\\/g, '/');
  105. }, this);
  106. map.sourceRoot = "";
  107. }
  108. map.file = map.file.split("!").pop().replace(/\\/g, '/');
  109. map = JSON.stringify(map);
  110. moduleJs = "exports.push([module.id, " + cssAsString + ", \"\", " + map + "]);";
  111. } else {
  112. moduleJs = "exports.push([module.id, " + cssAsString + ", \"\"]);";
  113. }
  114. // embed runtime
  115. callback(null, "exports = module.exports = require(" +
  116. loaderUtils.stringifyRequest(this, require.resolve("./css-base.js")) +
  117. ")(" + query.sourceMap + ");\n" +
  118. "// imports\n" +
  119. importJs + "\n\n" +
  120. "// module\n" +
  121. moduleJs + "\n\n" +
  122. "// exports\n" +
  123. exportJs);
  124. }.bind(this));
  125. };