UNPKG

17 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var tslib_1 = require("tslib");
4var fs_1 = require("mz/fs");
5var path_1 = require("path");
6var index_1 = require("./index");
7var PatchError_1 = require("./utils/PatchError");
8// eslint-disable-next-line @typescript-eslint/no-var-requires
9var pkg = require('../package');
10/**
11 * Run the script with the user-supplied arguments.
12 */
13function 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 /*break*/, 2];
21 return [4 /*yield*/, runWithPaths(options.paths, options)];
22 case 1:
23 _a.sent();
24 return [3 /*break*/, 4];
25 case 2: return [4 /*yield*/, runWithStdio(options)];
26 case 3:
27 _a.sent();
28 _a.label = 4;
29 case 4: return [2 /*return*/];
30 }
31 });
32 });
33}
34exports.default = run;
35function 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 // Legacy options that are now a no-op.
108 case '--prefer-const':
109 case '--keep-commonjs':
110 case '--enable-babel-constructor-workaround':
111 break;
112 // Legacy options that are now aliases for other options.
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 * Run decaffeinate on the given paths, changing them in place.
132 */
133function 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 /*yield*/, fs_1.stat(path)];
141 case 1:
142 info = _a.sent();
143 if (!info.isDirectory()) return [3 /*break*/, 3];
144 return [4 /*yield*/, processDirectory(path)];
145 case 2:
146 _a.sent();
147 return [3 /*break*/, 5];
148 case 3: return [4 /*yield*/, processFile(path)];
149 case 4:
150 _a.sent();
151 _a.label = 5;
152 case 5: return [2 /*return*/];
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 /*yield*/, 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 /*break*/, 12];
173 child = children_1_1.value;
174 childPath = path_1.join(path, child);
175 return [4 /*yield*/, fs_1.stat(childPath)];
176 case 4:
177 childStat = _b.sent();
178 if (!childStat.isDirectory()) return [3 /*break*/, 6];
179 return [4 /*yield*/, processDirectory(childPath)];
180 case 5:
181 _b.sent();
182 return [3 /*break*/, 11];
183 case 6:
184 if (!options.modernizeJS) return [3 /*break*/, 9];
185 if (!child.endsWith('.js')) return [3 /*break*/, 8];
186 return [4 /*yield*/, processPath(childPath)];
187 case 7:
188 _b.sent();
189 _b.label = 8;
190 case 8: return [3 /*break*/, 11];
191 case 9:
192 if (!(child.endsWith('.coffee') || child.endsWith('.litcoffee') || child.endsWith('.coffee.md'))) return [3 /*break*/, 11];
193 return [4 /*yield*/, 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 /*break*/, 3];
200 case 12: return [3 /*break*/, 15];
201 case 13:
202 e_2_1 = _b.sent();
203 e_2 = { error: e_2_1 };
204 return [3 /*break*/, 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 /*endfinally*/];
211 case 15: return [2 /*return*/];
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 /*yield*/, fs_1.readFile(path, 'utf8')];
226 case 1:
227 data = _a.sent();
228 resultCode = runWithCode(path, data, options);
229 return [4 /*yield*/, fs_1.writeFile(outputPath, resultCode)];
230 case 2:
231 _a.sent();
232 return [2 /*return*/];
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 /*break*/, 4];
247 path = paths_1_1.value;
248 return [4 /*yield*/, 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 /*break*/, 1];
255 case 4: return [3 /*break*/, 7];
256 case 5:
257 e_1_1 = _b.sent();
258 e_1 = { error: e_1_1 };
259 return [3 /*break*/, 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 /*endfinally*/];
266 case 7: return [2 /*return*/];
267 }
268 });
269 });
270}
271function runWithStdio(options) {
272 return tslib_1.__awaiter(this, void 0, void 0, function () {
273 return tslib_1.__generator(this, function (_a) {
274 return [2 /*return*/, 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 * Run decaffeinate on the given code string and return the resulting code.
288 */
289function 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 * Print version
309 */
310function version() {
311 console.log('%s v%s', pkg.name, pkg.version);
312}
313/**
314 * Print usage help.
315 */
316function 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}