UI for Zipcoin Blue

SourceMapDevToolPlugin.js 7.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const path = require("path");
  7. const crypto = require("crypto");
  8. const RequestShortener = require("./RequestShortener");
  9. const ConcatSource = require("webpack-sources").ConcatSource;
  10. const RawSource = require("webpack-sources").RawSource;
  11. const ModuleFilenameHelpers = require("./ModuleFilenameHelpers");
  12. const SourceMapDevToolModuleOptionsPlugin = require("./SourceMapDevToolModuleOptionsPlugin");
  13. const basename = (name) => {
  14. if(name.indexOf("/") < 0) return name;
  15. return name.substr(name.lastIndexOf("/") + 1);
  16. };
  17. function getTaskForFile(file, chunk, options, compilation) {
  18. const asset = compilation.assets[file];
  19. if(asset.__SourceMapDevToolFile === file && asset.__SourceMapDevToolData) {
  20. const data = asset.__SourceMapDevToolData;
  21. for(const cachedFile in data) {
  22. compilation.assets[cachedFile] = data[cachedFile];
  23. if(cachedFile !== file)
  24. chunk.files.push(cachedFile);
  25. }
  26. return;
  27. }
  28. let source, sourceMap;
  29. if(asset.sourceAndMap) {
  30. const sourceAndMap = asset.sourceAndMap(options);
  31. sourceMap = sourceAndMap.map;
  32. source = sourceAndMap.source;
  33. } else {
  34. sourceMap = asset.map(options);
  35. source = asset.source();
  36. }
  37. if(sourceMap) {
  38. return {
  39. chunk,
  40. file,
  41. asset,
  42. source,
  43. sourceMap,
  44. modules: undefined
  45. };
  46. }
  47. }
  48. class SourceMapDevToolPlugin {
  49. constructor(options) {
  50. if(arguments.length > 1)
  51. throw new Error("SourceMapDevToolPlugin only takes one argument (pass an options object)");
  52. // TODO: remove in webpack 3
  53. if(typeof options === "string") {
  54. options = {
  55. sourceMapFilename: options
  56. };
  57. }
  58. if(!options) options = {};
  59. this.sourceMapFilename = options.filename;
  60. this.sourceMappingURLComment = options.append === false ? false : options.append || "\n//# sourceMappingURL=[url]";
  61. this.moduleFilenameTemplate = options.moduleFilenameTemplate || "webpack:///[resourcePath]";
  62. this.fallbackModuleFilenameTemplate = options.fallbackModuleFilenameTemplate || "webpack:///[resourcePath]?[hash]";
  63. this.options = options;
  64. }
  65. apply(compiler) {
  66. const sourceMapFilename = this.sourceMapFilename;
  67. const sourceMappingURLComment = this.sourceMappingURLComment;
  68. const moduleFilenameTemplate = this.moduleFilenameTemplate;
  69. const fallbackModuleFilenameTemplate = this.fallbackModuleFilenameTemplate;
  70. const requestShortener = new RequestShortener(compiler.context);
  71. const options = this.options;
  72. options.test = options.test || /\.(js|css)($|\?)/i;
  73. const matchObject = ModuleFilenameHelpers.matchObject.bind(undefined, options);
  74. compiler.plugin("compilation", compilation => {
  75. new SourceMapDevToolModuleOptionsPlugin(options).apply(compilation);
  76. compilation.plugin("after-optimize-chunk-assets", function(chunks) {
  77. const moduleToSourceNameMapping = new Map();
  78. const tasks = [];
  79. chunks.forEach(function(chunk) {
  80. chunk.files.forEach(file => {
  81. if(matchObject(file)) {
  82. const task = getTaskForFile(file, chunk, options, compilation);
  83. if(task) {
  84. const modules = task.sourceMap.sources.map(source => {
  85. const module = compilation.findModule(source);
  86. return module || source;
  87. });
  88. for(let idx = 0; idx < modules.length; idx++) {
  89. const module = modules[idx];
  90. if(!moduleToSourceNameMapping.get(module)) {
  91. moduleToSourceNameMapping.set(module, ModuleFilenameHelpers.createFilename(module, moduleFilenameTemplate, requestShortener));
  92. }
  93. }
  94. task.modules = modules;
  95. tasks.push(task);
  96. }
  97. }
  98. });
  99. });
  100. const usedNamesSet = new Set(moduleToSourceNameMapping.values());
  101. const conflictDetectionSet = new Set();
  102. // all modules in defined order (longest identifier first)
  103. const allModules = Array.from(moduleToSourceNameMapping.keys()).sort((a, b) => {
  104. const ai = typeof a === "string" ? a : a.identifier();
  105. const bi = typeof b === "string" ? b : b.identifier();
  106. return ai.length - bi.length;
  107. });
  108. // find modules with conflicting source names
  109. for(let idx = 0; idx < allModules.length; idx++) {
  110. const module = allModules[idx];
  111. let sourceName = moduleToSourceNameMapping.get(module);
  112. let hasName = conflictDetectionSet.has(sourceName);
  113. if(!hasName) {
  114. conflictDetectionSet.add(sourceName);
  115. continue;
  116. }
  117. // try the fallback name first
  118. sourceName = ModuleFilenameHelpers.createFilename(module, fallbackModuleFilenameTemplate, requestShortener);
  119. hasName = usedNamesSet.has(sourceName);
  120. if(!hasName) {
  121. moduleToSourceNameMapping.set(module, sourceName);
  122. usedNamesSet.add(sourceName);
  123. continue;
  124. }
  125. // elsewise just append stars until we have a valid name
  126. while(hasName) {
  127. sourceName += "*";
  128. hasName = usedNamesSet.has(sourceName);
  129. }
  130. moduleToSourceNameMapping.set(module, sourceName);
  131. usedNamesSet.add(sourceName);
  132. }
  133. tasks.forEach(function(task) {
  134. const chunk = task.chunk;
  135. const file = task.file;
  136. const asset = task.asset;
  137. const sourceMap = task.sourceMap;
  138. const source = task.source;
  139. const modules = task.modules;
  140. const moduleFilenames = modules.map(m => moduleToSourceNameMapping.get(m));
  141. sourceMap.sources = moduleFilenames;
  142. if(sourceMap.sourcesContent && !options.noSources) {
  143. sourceMap.sourcesContent = sourceMap.sourcesContent.map((content, i) => `${content}\n\n\n${ModuleFilenameHelpers.createFooter(modules[i], requestShortener)}`);
  144. } else {
  145. sourceMap.sourcesContent = undefined;
  146. }
  147. sourceMap.sourceRoot = options.sourceRoot || "";
  148. sourceMap.file = file;
  149. asset.__SourceMapDevToolFile = file;
  150. asset.__SourceMapDevToolData = {};
  151. let currentSourceMappingURLComment = sourceMappingURLComment;
  152. if(currentSourceMappingURLComment !== false && /\.css($|\?)/i.test(file)) {
  153. currentSourceMappingURLComment = currentSourceMappingURLComment.replace(/^\n\/\/(.*)$/, "\n/*$1*/");
  154. }
  155. const sourceMapString = JSON.stringify(sourceMap);
  156. if(sourceMapFilename) {
  157. let filename = file;
  158. let query = "";
  159. const idx = filename.indexOf("?");
  160. if(idx >= 0) {
  161. query = filename.substr(idx);
  162. filename = filename.substr(0, idx);
  163. }
  164. let sourceMapFile = compilation.getPath(sourceMapFilename, {
  165. chunk,
  166. filename,
  167. query,
  168. basename: basename(filename)
  169. });
  170. if(sourceMapFile.indexOf("[contenthash]") !== -1) {
  171. sourceMapFile = sourceMapFile.replace(/\[contenthash\]/g, crypto.createHash("md5").update(sourceMapString).digest("hex"));
  172. }
  173. const sourceMapUrl = path.relative(path.dirname(file), sourceMapFile).replace(/\\/g, "/");
  174. if(currentSourceMappingURLComment !== false) {
  175. asset.__SourceMapDevToolData[file] = compilation.assets[file] = new ConcatSource(new RawSource(source), currentSourceMappingURLComment.replace(/\[url\]/g, sourceMapUrl));
  176. }
  177. asset.__SourceMapDevToolData[sourceMapFile] = compilation.assets[sourceMapFile] = new RawSource(sourceMapString);
  178. chunk.files.push(sourceMapFile);
  179. } else {
  180. asset.__SourceMapDevToolData[file] = compilation.assets[file] = new ConcatSource(new RawSource(source), currentSourceMappingURLComment
  181. .replace(/\[map\]/g, () => sourceMapString)
  182. .replace(/\[url\]/g, () => `data:application/json;charset=utf-8;base64,${new Buffer(sourceMapString, "utf-8").toString("base64")}`) // eslint-disable-line
  183. );
  184. }
  185. });
  186. });
  187. });
  188. }
  189. }
  190. module.exports = SourceMapDevToolPlugin;