/*jshint node:true*/ /// /// import parse from './parse/index'; import { emit, EmitterOptions } from './emit/emitter'; import fs = require('fs-extra'); import path = require('path'); import parseArgs = require('minimist'); import readlineSync = require('readline-sync'); import { CustomVisitor } from "./custom-visitors"; import { getLockTimestamp, updateLockTimestamp } from "./tool/lock"; function readdir(dir: string, prefix = '', result: string[] = []): string[] { fs.readdirSync(dir).forEach(file => { let fileName = path.join(prefix, file); let filePath = path.join(dir, file); if (!fs.statSync(filePath).isDirectory()) { result.push(fileName); } else { readdir(filePath, fileName, result); } }); return result; } function displayHelp(): void { console.log('usage: as3-to-typescript [options]'); console.log(''); console.log(' Available options:'); console.log(' --commonjs: ignore AS3 packages on TypeScript output.'); console.log(' --visitors: use custom a output visitor. (--visitors dictionary,createjs)'); console.log(' --interactive: ask to write the output in case it was manually modified'); console.log(' --overwrite: overwrite output files'); console.log(''); } export function run(): void { let args = parseArgs(process.argv, { '--': true }); if (args._.length === 2) { displayHelp(); process.exit(0); } if (args._.length !== 4) { throw new Error('source dir and output dir are mandatory'); } let sourceDir = path.resolve(process.cwd(), args._[2]); if (!fs.existsSync(sourceDir) || !fs.statSync(sourceDir).isDirectory()) { throw new Error('invalid source dir'); } let outputDir = path.resolve(process.cwd(), args._[3]); if (fs.existsSync(outputDir)) { if (!fs.statSync(outputDir).isDirectory()) { throw new Error('invalid ouput dir'); } } else { fs.mkdirSync(outputDir); } let visitors = (args['visitors']) ? args['visitors'].split(",").map((name: string) => require(`./custom-visitors/${name}`).default) : [] let overwrite = !!args['overwrite']; let commonjs = args['commonjs']; let interactive = args['interactive']; if (overwrite && interactive) { console.error("You can't have '--overwrite' and '--interactive' at the same time."); process.exit(); } // get last conversion timestamp let previousLockTimestamp = getLockTimestamp(outputDir); let nextLockTimestamp = Math.floor((new Date()).getTime() / 1000); let files = readdir(sourceDir).filter(file => /.as$/.test(file)); let number = 0; let length = files.length; // get class definitions by namespace let definitionsByNamespace: {[ns: string]: string[]} = {}; files.forEach(file => { let segments = file.match(/([a-zA-Z]+)/g); segments.pop(); let identifier = segments.pop(); let ns = segments.join("."); if (!definitionsByNamespace[ ns ]) { definitionsByNamespace[ ns ] = [ ]; } definitionsByNamespace[ ns ].push( identifier ); }); let emitterOptions: EmitterOptions = { lineSeparator: '\n', useNamespaces: !commonjs, customVisitors: visitors, definitionsByNamespace: definitionsByNamespace }; files.forEach(file => { console.log('(' + ( number + 1 ) + '/' + length + ') \'' + file + '\''); let fileTs = file.replace(/.as$/, '.ts'); let inputFile = path.resolve(sourceDir, file); let outputFile = path.resolve(outputDir, fileTs); if (!overwrite && fs.existsSync(outputFile)) { let stat = fs.statSync(outputFile) if (previousLockTimestamp.getTime() !== stat.mtime.getTime()) { if (interactive && !readlineSync.keyInYN(`"${ fileTs }" has been modified. Overwrite it?`)) { return; } } } let content = fs.readFileSync(inputFile, 'UTF-8'); let ast = parse(path.basename(file), content); let contents = emit(ast, content, emitterOptions); visitors.forEach((visitor: CustomVisitor) => { if (visitor.postProcessing) { contents = visitor.postProcessing(emitterOptions, contents); } }) fs.outputFileSync(outputFile, contents.replace(/\r\n/g, "\n")); fs.utimesSync(outputFile, nextLockTimestamp, nextLockTimestamp); number ++; }); updateLockTimestamp(outputDir, nextLockTimestamp); }