-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathget-source-node.js
81 lines (68 loc) · 2.97 KB
/
get-source-node.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
/// FIXME: This is pretty much the same file used in the gobble-concat package. It should be refactored out somehow.
// Given a file name, reads it, checks it if has a sourcemap attached, then either:
// - Creates an identity sourcemap if it doesn't exist,
// - Reads the file with the sourcemap, or
// - Decodes an embedded base64 sourcemap
var SourceNode = require('source-map').SourceNode;
var SourceMapConsumer = require('source-map').SourceMapConsumer;
var sander = require('sander'),
readFile = sander.readFile,
readFileSync = sander.readFileSync,
realpathSync = sander.realpathSync,
path = require('path');
var sourceMapRegExp = new RegExp(/(?:\/\/#|\/\/@|\/\*#)\s*sourceMappingURL=(\S*)\s*(?:\*\/\s*)?$/);
var dataUriRegexp = new RegExp(/^(data:)([\w\/\+]+)(;charset[=:][\w-]+)?(;base64)?,(.*)/); // From https://github.com/ragingwind/data-uri-regex, modified
function getSourceNode(filepath, filename, forceIdentity) {
return readFile(filepath, filename).then( srcBuffer => {
var srcStr = srcBuffer.toString();
var match;
if (!forceIdentity) {
/// Run a regexp against the code to check for source mappings.
var match = sourceMapRegExp.exec(srcStr);
} else {
srcStr = srcStr.replace(sourceMapRegExp, '');
}
if (!match) {
// Create identity sourcemap
var realPath = realpathSync(filepath);
var realFilename = realpathSync(realPath, filename);
var lines = srcStr.split('\n');
var lineCount = lines.length;
var identNode = new SourceNode(null, null, null, '');
identNode.setSourceContent(realFilename, srcStr);
for (var i=0; i<lineCount; i++) {
var lineNode = new SourceNode(i+1, 0, realFilename, lines[i] + '\n');
identNode.add(lineNode);
}
// console.log('Created inline sourcemap for ', filename);
return identNode;
} else {
// Read sourcemap
srcStr = srcStr.replace(sourceMapRegExp, '');
var sourcemapFilename = match[1];
var dataUriMatch = dataUriRegexp.exec(match[1]);
if (dataUriMatch) {
// Read inline sourcemap
var data = dataUriMatch[5];
if (dataUriMatch[4] === ';base64') {
data = Buffer(data, 'base64').toString('utf8');
}
var parsedMap = new SourceMapConsumer( data.toString() );
// console.log('Loaded inline sourcemap for ', filename + ": (" + data.length + " bytes)");
return SourceNode.fromStringWithSourceMap( srcStr, parsedMap );
} else {
// Read external sourcemap
return readFile( path.join(filepath, path.dirname(filename)), sourcemapFilename )
.then( mapContents => {
// console.log('Loaded external sourcemap for ', filename + ": (" + sourcemapFilename + ")");
var parsedMap = new SourceMapConsumer( mapContents.toString() );
return SourceNode.fromStringWithSourceMap( srcStr, parsedMap );
}, err => {
console.error(filepath, sourcemapFilename);
throw new Error('File ' + filename + ' refers to a non-existing sourcemap at ' + filepath + ' / ' + sourcemapFilename + ' ' + err);
});
}
}
});
}
module.exports = getSourceNode;