forked from systemjs/builder
-
Notifications
You must be signed in to change notification settings - Fork 0
/
output.js
166 lines (134 loc) · 4.78 KB
/
output.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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
var path = require('path');
var mkdirp = require('mkdirp');
var fs = require('fs');
var Promise = require('bluebird');
var asp = require('bluebird').promisify;
var extend = require('./utils').extend;
var fromFileURL = require('./utils').fromFileURL;
var toFileURL = require('./utils').toFileURL;
function countLines(str) {
return str.split(/\r\n|\r|\n/).length;
}
// Process compiler outputs, gathering:
//
// concatOutputs: list of source strings to concatenate
// sourceMapsWithOffsets: list of [absolute offset,
// source map string] pairs
//
// Takes lists as empty references and populates via push.
function processOutputs(outputs) {
var removeSourceMaps = require('./sourcemaps').removeSourceMaps;
var offset = 0;
var outputObj = {};
var sources = outputObj.sources = [];
var sourceMapsWithOffsets = outputObj.sourceMapsWithOffsets = [];
outputs.forEach(function(output) {
var source;
if (typeof output == 'object') {
source = output.source || '';
var offset_ = output.sourceMapOffset || 0;
var map = output.sourceMap;
if (map) {
sourceMapsWithOffsets.push([offset + offset_, map]);
}
}
// NB perhaps we should enforce output is always an object down the chain?
else if (typeof output == 'string') {
source = output;
}
else {
throw "Unexpected output format: " + output.toString();
}
source = removeSourceMaps(source || '');
offset += countLines(source);
sources.push(source);
});
return outputObj;
}
function createOutput(outFile, outputs, basePath, sourceMaps, sourceMapContents) {
var concatenateSourceMaps = require('./sourcemaps').concatenateSourceMaps;
var outputObj = processOutputs(outputs);
if (sourceMaps)
var sourceMap = concatenateSourceMaps(outFile, outputObj.sourceMapsWithOffsets, basePath, sourceMapContents);
var output = outputObj.sources.join('\n');
return {
source: output,
sourceMap: sourceMap
};
}
function minify(output, fileName, mangle, uglifyOpts) {
var uglify = require('uglify-js');
var ast;
try{
ast = uglify.parse(output.source, { filename: fileName });
} catch(e){
throw new Error(e);
}
ast.figure_out_scope();
ast = ast.transform(uglify.Compressor(uglifyOpts.compress));
ast.figure_out_scope();
if (mangle !== false)
ast.mangle_names();
var sourceMap;
if (output.sourceMap) {
if (typeof output.sourceMap === 'string')
output.sourceMap = JSON.parse(output.sourceMap);
var sourceMapIn = output.sourceMap;
sourceMap = uglify.SourceMap({
file: fileName,
orig: sourceMapIn
});
if (uglifyOpts.sourceMapIncludeSources && sourceMapIn && Array.isArray(sourceMapIn.sourcesContent)) {
sourceMapIn.sourcesContent.forEach(function(content, idx) {
sourceMap.get().setSourceContent(sourceMapIn.sources[idx], content);
});
}
}
var outputOptions = uglifyOpts.beautify;
// keep first comment
outputOptions.comments = outputOptions.comments || function(node, comment) {
return comment.line === 1 && comment.col === 0;
};
outputOptions.source_map = sourceMap;
output.source = ast.print_to_string(outputOptions);
output.sourceMap = sourceMap;
return output;
}
function writeOutputFile(outFile, source, sourceMap) {
var outDir = path.dirname(outFile);
return asp(mkdirp)(path.dirname(outFile))
.then(function() {
if (!sourceMap)
return;
var sourceMapFileName = path.basename(outFile) + '.map';
source += '\n//# sourceMappingURL=' + sourceMapFileName;
return asp(fs.writeFile)(path.resolve(outDir, sourceMapFileName), sourceMap);
})
.then(function() {
return asp(fs.writeFile)(outFile, source);
});
}
exports.inlineSourceMap = inlineSourceMap;
function inlineSourceMap(source, sourceMap) {
if (!sourceMap)
throw new Error('NOTHING TO INLINE');
return source + '\n//# sourceMappingURL=data:application/json;base64,'
+ new Buffer(sourceMap.toString()).toString('base64');
}
exports.writeOutputs = function(outputs, baseURL, outputOpts) {
var outFile = outputOpts.outFile && path.resolve(outputOpts.outFile);
var basePath = fromFileURL(baseURL);
var fileName = outFile && path.basename(outFile) || 'output.js';
var output = createOutput(outFile || path.resolve(basePath, fileName), outputs, basePath, outputOpts.sourceMaps, outputOpts.sourceMapContents);
if (outputOpts.minify)
output = minify(output, fileName, outputOpts.mangle, outputOpts.uglify);
if (outputOpts.sourceMaps == 'inline') {
output.source = inlineSourceMap(output.source, output.sourceMap);
output.sourceMap = undefined;
}
if (!outputOpts.outFile)
return Promise.resolve(output);
return writeOutputFile(outFile, output.source, output.sourceMap).then(function() {
return output;
});
};