1 | var _ = require('underscore'),
|
2 | async = require('async'),
|
3 | FileMap = require('./util/file-map'),
|
4 | fu = require('./fileUtil'),
|
5 | ChildPool = require('child-pool');
|
6 |
|
7 | var uglify = new ChildPool(__dirname + '/uglify-worker', {logId: 'uglify-worker'});
|
8 |
|
9 | exports.combine = function(context, files, output, minimize, noSeparator, callback) {
|
10 |
|
11 | function outputIfCompleted() {
|
12 | if (completed >= files.length) {
|
13 | var lastEl,
|
14 | map = new FileMap(output),
|
15 | warnings = [],
|
16 |
|
17 | tasks = [];
|
18 |
|
19 | _.each(content, function(el) {
|
20 | var content = el.content.toString();
|
21 |
|
22 | if (!noSeparator && (!lastEl || !lastEl.noSeparator) && map.content()) {
|
23 | map.add(undefined, '\n;;\n');
|
24 | }
|
25 |
|
26 | map.add(el.name, content, el, el.generated);
|
27 |
|
28 | lastEl = el;
|
29 | }, '');
|
30 |
|
31 | var inputs = [];
|
32 | content.forEach(function(el) {
|
33 | if (el.inputs) {
|
34 | inputs.push.apply(inputs, el.inputs);
|
35 | } else if (el.name) {
|
36 | inputs.push(el.name);
|
37 | }
|
38 | });
|
39 | inputs = _.unique(inputs);
|
40 |
|
41 |
|
42 | tasks.push(function(callback) {
|
43 | callback(undefined, map.content());
|
44 | });
|
45 |
|
46 |
|
47 | if (minimize) {
|
48 | var uglifyConfig = context.config.attributes.uglify || {};
|
49 |
|
50 | tasks.push(function(data, callback) {
|
51 | uglify.send({
|
52 | output: output,
|
53 | data: data,
|
54 | compressorOptions: uglifyConfig.compressor,
|
55 | manglerOptions: uglifyConfig.mangler,
|
56 | outputOptions: uglifyConfig.output,
|
57 | sourceMap: context.options.sourceMap ? map.sourceMap() : undefined
|
58 | },
|
59 | function(err, data) {
|
60 | if (err) {
|
61 | return callback(err);
|
62 | }
|
63 |
|
64 | _.each(data.warnings, function(msg) {
|
65 | var match = /(.*?)\s*\[.*:(\d+),(\d+)/.exec(msg);
|
66 | if (match) {
|
67 | var msg = match[1],
|
68 | line = parseInt(match[2], 10),
|
69 | column = match[3],
|
70 | context = map.context(line, column);
|
71 |
|
72 | if (context && (!context.fileContext || !context.fileContext.ignoreWarnings)) {
|
73 | context.msg = msg;
|
74 | warnings.push(context);
|
75 | }
|
76 | } else {
|
77 | warnings.push({msg: msg});
|
78 | }
|
79 | });
|
80 |
|
81 | if (data.sourceMap) {
|
82 |
|
83 |
|
84 |
|
85 | map.sourceMap = function() { return data.sourceMap; };
|
86 | }
|
87 |
|
88 | callback(err, data.data);
|
89 | });
|
90 | });
|
91 | }
|
92 |
|
93 |
|
94 | var sourceMap = context.options.sourceMap;
|
95 | if (sourceMap) {
|
96 | var inlineSourceMap = sourceMap === true;
|
97 |
|
98 | tasks.push(function(data, callback) {
|
99 | map.writeSourceMap({
|
100 | mapDestination: !inlineSourceMap && (sourceMap + '/' + context.buildPath),
|
101 | outputSource: inlineSourceMap,
|
102 | callback: function(err) {
|
103 | if (inlineSourceMap) {
|
104 | data += '\n' + map.sourceMapToken();
|
105 | }
|
106 | callback(err, data);
|
107 | }
|
108 | });
|
109 | });
|
110 | }
|
111 |
|
112 |
|
113 | tasks.push(function(data, callback) {
|
114 | fu.writeFile(output, data, callback);
|
115 | });
|
116 |
|
117 |
|
118 | async.waterfall(tasks, function(err) {
|
119 | if (err) {
|
120 | callback(new Error('Combined output "' + output + '" failed\n\t' + err));
|
121 | return;
|
122 | }
|
123 |
|
124 | callback(undefined, {
|
125 | fileName: output,
|
126 | inputs: inputs,
|
127 | warnings: warnings
|
128 | });
|
129 | });
|
130 | }
|
131 | }
|
132 | var completed = 0,
|
133 | content = [];
|
134 |
|
135 | files.forEach(function(resource) {
|
136 | var fileInfo = context.loadResource(resource, function(err) {
|
137 | if (err && callback) {
|
138 | callback(err);
|
139 | callback = undefined;
|
140 | return;
|
141 | }
|
142 |
|
143 | if (callback) {
|
144 | completed++;
|
145 | outputIfCompleted();
|
146 | }
|
147 | });
|
148 | content.push(fileInfo);
|
149 | });
|
150 | };
|