1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | var tslib_1 = require("tslib");
|
4 | var fs_1 = require("mz/fs");
|
5 | var path_1 = require("path");
|
6 | var index_1 = require("./index");
|
7 | var PatchError_1 = require("./utils/PatchError");
|
8 |
|
9 | var pkg = require('../package');
|
10 |
|
11 |
|
12 |
|
13 | function run(args) {
|
14 | return tslib_1.__awaiter(this, void 0, void 0, function () {
|
15 | var options;
|
16 | return tslib_1.__generator(this, function (_a) {
|
17 | switch (_a.label) {
|
18 | case 0:
|
19 | options = parseArguments(args);
|
20 | if (!options.paths.length) return [3 , 2];
|
21 | return [4 , runWithPaths(options.paths, options)];
|
22 | case 1:
|
23 | _a.sent();
|
24 | return [3 , 4];
|
25 | case 2: return [4 , runWithStdio(options)];
|
26 | case 3:
|
27 | _a.sent();
|
28 | _a.label = 4;
|
29 | case 4: return [2 ];
|
30 | }
|
31 | });
|
32 | });
|
33 | }
|
34 | exports.default = run;
|
35 | function parseArguments(args) {
|
36 | var paths = [];
|
37 | var baseOptions = {};
|
38 | var modernizeJS = false;
|
39 | for (var i = 0; i < args.length; i++) {
|
40 | var arg = args[i];
|
41 | switch (arg) {
|
42 | case '-h':
|
43 | case '--help':
|
44 | usage();
|
45 | process.exit(0);
|
46 | break;
|
47 | case '-v':
|
48 | case '--version':
|
49 | version();
|
50 | process.exit(0);
|
51 | break;
|
52 | case '--use-cs2':
|
53 | baseOptions.useCS2 = true;
|
54 | break;
|
55 | case '--modernize-js':
|
56 | modernizeJS = true;
|
57 | break;
|
58 | case '--literate':
|
59 | baseOptions.literate = true;
|
60 | break;
|
61 | case '--disable-suggestion-comment':
|
62 | baseOptions.disableSuggestionComment = true;
|
63 | break;
|
64 | case '--no-array-includes':
|
65 | baseOptions.noArrayIncludes = true;
|
66 | break;
|
67 | case '--use-optional-chaining':
|
68 | console.warn("NOTE: " + arg + " is disabled and has no effect");
|
69 | break;
|
70 | case '--use-js-modules':
|
71 | baseOptions.useJSModules = true;
|
72 | break;
|
73 | case '--loose-js-modules':
|
74 | baseOptions.looseJSModules = true;
|
75 | break;
|
76 | case '--safe-import-function-identifiers':
|
77 | i++;
|
78 | baseOptions.safeImportFunctionIdentifiers = args[i].split(',');
|
79 | break;
|
80 | case '--prefer-let':
|
81 | baseOptions.preferLet = true;
|
82 | break;
|
83 | case '--disable-babel-constructor-workaround':
|
84 | baseOptions.disableBabelConstructorWorkaround = true;
|
85 | break;
|
86 | case '--disallow-invalid-constructors':
|
87 | baseOptions.disallowInvalidConstructors = true;
|
88 | break;
|
89 | case '--loose':
|
90 | baseOptions.loose = true;
|
91 | break;
|
92 | case '--loose-default-params':
|
93 | baseOptions.looseDefaultParams = true;
|
94 | break;
|
95 | case '--loose-for-expressions':
|
96 | baseOptions.looseForExpressions = true;
|
97 | break;
|
98 | case '--loose-for-of':
|
99 | baseOptions.looseForOf = true;
|
100 | break;
|
101 | case '--loose-includes':
|
102 | baseOptions.looseIncludes = true;
|
103 | break;
|
104 | case '--loose-comparison-negation':
|
105 | baseOptions.looseComparisonNegation = true;
|
106 | break;
|
107 |
|
108 | case '--prefer-const':
|
109 | case '--keep-commonjs':
|
110 | case '--enable-babel-constructor-workaround':
|
111 | break;
|
112 |
|
113 | case '--force-default-export':
|
114 | baseOptions.useJSModules = true;
|
115 | break;
|
116 | case '--allow-invalid-constructors':
|
117 | baseOptions.disableBabelConstructorWorkaround = true;
|
118 | break;
|
119 | default:
|
120 | if (arg.startsWith('-')) {
|
121 | console.error("Error: unrecognized option '" + arg + "'");
|
122 | process.exit(1);
|
123 | }
|
124 | paths.push(arg);
|
125 | break;
|
126 | }
|
127 | }
|
128 | return { paths: paths, baseOptions: baseOptions, modernizeJS: modernizeJS };
|
129 | }
|
130 |
|
131 |
|
132 |
|
133 | function runWithPaths(paths, options) {
|
134 | return tslib_1.__awaiter(this, void 0, void 0, function () {
|
135 | function processPath(path) {
|
136 | return tslib_1.__awaiter(this, void 0, void 0, function () {
|
137 | var info;
|
138 | return tslib_1.__generator(this, function (_a) {
|
139 | switch (_a.label) {
|
140 | case 0: return [4 , fs_1.stat(path)];
|
141 | case 1:
|
142 | info = _a.sent();
|
143 | if (!info.isDirectory()) return [3 , 3];
|
144 | return [4 , processDirectory(path)];
|
145 | case 2:
|
146 | _a.sent();
|
147 | return [3 , 5];
|
148 | case 3: return [4 , processFile(path)];
|
149 | case 4:
|
150 | _a.sent();
|
151 | _a.label = 5;
|
152 | case 5: return [2 ];
|
153 | }
|
154 | });
|
155 | });
|
156 | }
|
157 | function processDirectory(path) {
|
158 | return tslib_1.__awaiter(this, void 0, void 0, function () {
|
159 | var children, children_1, children_1_1, child, childPath, childStat, e_2_1;
|
160 | var e_2, _a;
|
161 | return tslib_1.__generator(this, function (_b) {
|
162 | switch (_b.label) {
|
163 | case 0: return [4 , fs_1.readdir(path)];
|
164 | case 1:
|
165 | children = _b.sent();
|
166 | _b.label = 2;
|
167 | case 2:
|
168 | _b.trys.push([2, 13, 14, 15]);
|
169 | children_1 = tslib_1.__values(children), children_1_1 = children_1.next();
|
170 | _b.label = 3;
|
171 | case 3:
|
172 | if (!!children_1_1.done) return [3 , 12];
|
173 | child = children_1_1.value;
|
174 | childPath = path_1.join(path, child);
|
175 | return [4 , fs_1.stat(childPath)];
|
176 | case 4:
|
177 | childStat = _b.sent();
|
178 | if (!childStat.isDirectory()) return [3 , 6];
|
179 | return [4 , processDirectory(childPath)];
|
180 | case 5:
|
181 | _b.sent();
|
182 | return [3 , 11];
|
183 | case 6:
|
184 | if (!options.modernizeJS) return [3 , 9];
|
185 | if (!child.endsWith('.js')) return [3 , 8];
|
186 | return [4 , processPath(childPath)];
|
187 | case 7:
|
188 | _b.sent();
|
189 | _b.label = 8;
|
190 | case 8: return [3 , 11];
|
191 | case 9:
|
192 | if (!(child.endsWith('.coffee') || child.endsWith('.litcoffee') || child.endsWith('.coffee.md'))) return [3 , 11];
|
193 | return [4 , processPath(childPath)];
|
194 | case 10:
|
195 | _b.sent();
|
196 | _b.label = 11;
|
197 | case 11:
|
198 | children_1_1 = children_1.next();
|
199 | return [3 , 3];
|
200 | case 12: return [3 , 15];
|
201 | case 13:
|
202 | e_2_1 = _b.sent();
|
203 | e_2 = { error: e_2_1 };
|
204 | return [3 , 15];
|
205 | case 14:
|
206 | try {
|
207 | if (children_1_1 && !children_1_1.done && (_a = children_1.return)) _a.call(children_1);
|
208 | }
|
209 | finally { if (e_2) throw e_2.error; }
|
210 | return [7 ];
|
211 | case 15: return [2 ];
|
212 | }
|
213 | });
|
214 | });
|
215 | }
|
216 | function processFile(path) {
|
217 | return tslib_1.__awaiter(this, void 0, void 0, function () {
|
218 | var extension, outputPath, data, resultCode;
|
219 | return tslib_1.__generator(this, function (_a) {
|
220 | switch (_a.label) {
|
221 | case 0:
|
222 | extension = path.endsWith('.coffee.md') ? '.coffee.md' : path_1.extname(path);
|
223 | outputPath = path_1.join(path_1.dirname(path), path_1.basename(path, extension)) + '.js';
|
224 | console.log(path + " \u2192 " + outputPath);
|
225 | return [4 , fs_1.readFile(path, 'utf8')];
|
226 | case 1:
|
227 | data = _a.sent();
|
228 | resultCode = runWithCode(path, data, options);
|
229 | return [4 , fs_1.writeFile(outputPath, resultCode)];
|
230 | case 2:
|
231 | _a.sent();
|
232 | return [2 ];
|
233 | }
|
234 | });
|
235 | });
|
236 | }
|
237 | var paths_1, paths_1_1, path, e_1_1;
|
238 | var e_1, _a;
|
239 | return tslib_1.__generator(this, function (_b) {
|
240 | switch (_b.label) {
|
241 | case 0:
|
242 | _b.trys.push([0, 5, 6, 7]);
|
243 | paths_1 = tslib_1.__values(paths), paths_1_1 = paths_1.next();
|
244 | _b.label = 1;
|
245 | case 1:
|
246 | if (!!paths_1_1.done) return [3 , 4];
|
247 | path = paths_1_1.value;
|
248 | return [4 , processPath(path)];
|
249 | case 2:
|
250 | _b.sent();
|
251 | _b.label = 3;
|
252 | case 3:
|
253 | paths_1_1 = paths_1.next();
|
254 | return [3 , 1];
|
255 | case 4: return [3 , 7];
|
256 | case 5:
|
257 | e_1_1 = _b.sent();
|
258 | e_1 = { error: e_1_1 };
|
259 | return [3 , 7];
|
260 | case 6:
|
261 | try {
|
262 | if (paths_1_1 && !paths_1_1.done && (_a = paths_1.return)) _a.call(paths_1);
|
263 | }
|
264 | finally { if (e_1) throw e_1.error; }
|
265 | return [7 ];
|
266 | case 7: return [2 ];
|
267 | }
|
268 | });
|
269 | });
|
270 | }
|
271 | function runWithStdio(options) {
|
272 | return tslib_1.__awaiter(this, void 0, void 0, function () {
|
273 | return tslib_1.__generator(this, function (_a) {
|
274 | return [2 , new Promise(function (resolve) {
|
275 | var data = '';
|
276 | process.stdin.on('data', function (chunk) { return (data += chunk); });
|
277 | process.stdin.on('end', function () {
|
278 | var resultCode = runWithCode('stdin', data, options);
|
279 | process.stdout.write(resultCode);
|
280 | resolve();
|
281 | });
|
282 | })];
|
283 | });
|
284 | });
|
285 | }
|
286 |
|
287 |
|
288 |
|
289 | function runWithCode(name, code, options) {
|
290 | var baseOptions = Object.assign({ filename: name }, options.baseOptions);
|
291 | try {
|
292 | if (options.modernizeJS) {
|
293 | return index_1.modernizeJS(code, baseOptions).code;
|
294 | }
|
295 | else {
|
296 | return index_1.convert(code, baseOptions).code;
|
297 | }
|
298 | }
|
299 | catch (err) {
|
300 | if (PatchError_1.default.detect(err)) {
|
301 | console.error(name + ": " + PatchError_1.default.prettyPrint(err));
|
302 | process.exit(1);
|
303 | }
|
304 | throw err;
|
305 | }
|
306 | }
|
307 |
|
308 |
|
309 |
|
310 | function version() {
|
311 | console.log('%s v%s', pkg.name, pkg.version);
|
312 | }
|
313 |
|
314 |
|
315 |
|
316 | function usage() {
|
317 | var exe = path_1.basename(process.argv[1]);
|
318 | console.log('%s [OPTIONS] PATH [PATH …]', exe);
|
319 | console.log('%s [OPTIONS] < INPUT', exe);
|
320 | console.log();
|
321 | console.log('Move your CoffeeScript source to JavaScript using modern syntax.');
|
322 | console.log();
|
323 | console.log('OPTIONS');
|
324 | console.log();
|
325 | console.log(' -h, --help Display this help message.');
|
326 | console.log(' --use-cs2 Treat the input as CoffeeScript 2 code. CoffeeScript 2 has');
|
327 | console.log(' some small breaking changes and differences in behavior');
|
328 | console.log(' compared with CS1, so decaffeinate assumes CS1 by default');
|
329 | console.log(' and allows CS2 via this flag.');
|
330 | console.log(' --modernize-js Treat the input as JavaScript and only run the');
|
331 | console.log(' JavaScript-to-JavaScript transforms, modifying the file(s)');
|
332 | console.log(' in-place.');
|
333 | console.log(' --literate Treat the input file as Literate CoffeeScript.');
|
334 | console.log(' --disable-suggestion-comment');
|
335 | console.log(' Do not include a comment with followup suggestions at the');
|
336 | console.log(' top of the output file.');
|
337 | console.log(' --no-array-includes Do not use Array.prototype.includes in generated code.');
|
338 | console.log(' --use-optional-chaining Use the upcoming optional chaining syntax for operators like `?.`.');
|
339 | console.log(' NOTE: this is disabled and has no effect.');
|
340 | console.log(' --use-js-modules Convert require and module.exports to import and export.');
|
341 | console.log(' --loose-js-modules Allow named exports when converting to JS modules.');
|
342 | console.log(' --safe-import-function-identifiers');
|
343 | console.log(' Comma-separated list of function names that may safely be in the ');
|
344 | console.log(' import/require section of the file. All other function calls ');
|
345 | console.log(' will disqualify later requires from being converted to imports.');
|
346 | console.log(' --prefer-let Use let instead of const for most variables in output code.');
|
347 | console.log(' --loose Enable all --loose... options.');
|
348 | console.log(' --loose-default-params Convert CS default params to JS default params.');
|
349 | console.log(' --loose-for-expressions Do not wrap expression loop targets in Array.from.');
|
350 | console.log(' --loose-for-of Do not wrap JS for...of loop targets in Array.from.');
|
351 | console.log(' --loose-includes Do not wrap in Array.from when converting in to includes.');
|
352 | console.log(' --loose-comparison-negation');
|
353 | console.log(' Allow unsafe simplifications like `!(a > b)` to `a <= b`.');
|
354 | console.log(' --disable-babel-constructor-workaround');
|
355 | console.log(' Never include the Babel/TypeScript workaround code to allow');
|
356 | console.log(' this before super in constructors.');
|
357 | console.log(' --disallow-invalid-constructors');
|
358 | console.log(' Give an error when constructors use this before super or');
|
359 | console.log(' omit the super call in a subclass.');
|
360 | console.log();
|
361 | console.log('EXAMPLES');
|
362 | console.log();
|
363 | console.log(' # Convert a .coffee file to a .js file.');
|
364 | console.log(' $ decaffeinate index.coffee');
|
365 | console.log();
|
366 | console.log(' # Pipe an example from the command-line.');
|
367 | console.log(' $ echo "a = 1" | decaffeinate');
|
368 | console.log();
|
369 | console.log(' # On macOS this may come in handy:');
|
370 | console.log(' $ pbpaste | decaffeinate | pbcopy');
|
371 | console.log();
|
372 | console.log(' # Process everything in a directory.');
|
373 | console.log(' $ decaffeinate src/');
|
374 | console.log();
|
375 | console.log(' # Redirect input from a file.');
|
376 | console.log(' $ decaffeinate < index.coffee');
|
377 | }
|