UNPKG

3.58 kBJavaScriptView Raw
1/*
2 MIT License http://www.opensource.org/licenses/mit-license.php
3 Author Tobias Koppers @sokra
4*/
5var fs = require("fs");
6var path = require("path");
7var async = require("async");
8var loaderUtils = require("loader-utils");
9
10// Matches only the last occurrence of sourceMappingURL
11var baseRegex = "\\s*[@#]\\s*sourceMappingURL\\s*=\\s*([^\\s]*)(?![\\S\\s]*sourceMappingURL)",
12 // Matches /* ... */ comments
13 regex1 = new RegExp("/\\*"+baseRegex+"\\s*\\*/"),
14 // Matches // .... comments
15 regex2 = new RegExp("//"+baseRegex+"($|\n|\r\n?)"),
16 // Matches DataUrls
17 regexDataUrl = /data:[^;\n]+(?:;charset=[^;\n]+)?;base64,([a-zA-Z0-9+/]+={0,2})/;
18
19module.exports = function(input, inputMap) {
20 this.cacheable && this.cacheable();
21 var resolve = this.resolve;
22 var addDependency = this.addDependency;
23 var emitWarning = this.emitWarning || function() {};
24 var match = input.match(regex1) || input.match(regex2);
25 if(match) {
26 var url = match[1];
27 var dataUrlMatch = regexDataUrl.exec(url);
28 var callback = this.async();
29 if(dataUrlMatch) {
30 var mapBase64 = dataUrlMatch[1];
31 var mapStr = (new Buffer(mapBase64, "base64")).toString();
32 var map;
33 try {
34 map = JSON.parse(mapStr)
35 } catch (e) {
36 emitWarning("Cannot parse inline SourceMap '" + mapBase64.substr(0, 50) + "': " + e);
37 return untouched();
38 }
39 processMap(map, this.context, callback);
40 } else {
41 resolve(this.context, loaderUtils.urlToRequest(url, true), function(err, result) {
42 if(err) {
43 emitWarning("Cannot find SourceMap '" + url + "': " + err);
44 return untouched();
45 }
46 addDependency(result);
47 fs.readFile(result, "utf-8", function(err, content) {
48 if(err) {
49 emitWarning("Cannot open SourceMap '" + result + "': " + err);
50 return untouched();
51 }
52 var map;
53 try {
54 map = JSON.parse(content);
55 } catch (e) {
56 emitWarning("Cannot parse SourceMap '" + url + "': " + e);
57 return untouched();
58 }
59 processMap(map, path.dirname(result), callback);
60 });
61 }.bind(this));
62 return;
63 }
64 } else {
65 var callback = this.callback;
66 return untouched();
67 }
68 function untouched() {
69 callback(null, input, inputMap);
70 }
71 function processMap(map, context, callback) {
72 if(!map.sourcesContent || map.sourcesContent.length < map.sources.length) {
73 var sourcePrefix = map.sourceRoot ? map.sourceRoot + "/" : "";
74 map.sources = map.sources.map(function(s) { return sourcePrefix + s; });
75 delete map.sourceRoot;
76 var missingSources = map.sourcesContent ? map.sources.slice(map.sourcesContent.length) : map.sources;
77 async.map(missingSources, function(source, callback) {
78 resolve(context, loaderUtils.urlToRequest(source, true), function(err, result) {
79 if(err) {
80 emitWarning("Cannot find source file '" + source + "': " + err);
81 return callback(null, null);
82 }
83 addDependency(result);
84 fs.readFile(result, "utf-8", function(err, content) {
85 if(err) {
86 emitWarning("Cannot open source file '" + result + "': " + err);
87 return callback(null, null);
88 }
89 callback(null, {
90 source: result,
91 content: content
92 });
93 });
94 });
95 }, function(err, info) {
96 map.sourcesContent = map.sourcesContent || [];
97 info.forEach(function(res) {
98 if(res) {
99 map.sources[map.sourcesContent.length] = res.source;
100 map.sourcesContent.push(res.content);
101 } else {
102 map.sourcesContent.push(null);
103 }
104 });
105 processMap(map, context, callback);
106 });
107 return;
108 }
109 callback(null, input.replace(match[0], ''), map);
110 }
111}