UNPKG

js2coffee

Version:

JavaScript to CoffeeScript compiler

143 lines (123 loc) 4.04 kB
TransformerBase = require('./lib/transforms/base') BuilderBase = require('./lib/builder/base') Builder = require('./lib/builder') { buildError } = require('./lib/helpers') ###* # # Js2coffee API ### module.exports = js2coffee = (source, options) -> js2coffee.build(source, options).code ###* # js2coffee() : js2coffee(source, [options]) # Compiles JavaScript into CoffeeScript. # # output = js2coffee.build('a = 2', {}); # # output.code # output.ast # output.map # output.warnings # # All options are optional. Available options are: # # ~ filename (String): the filename, used in source maps and errors. # ~ comments (Boolean): set to `false` to disable comments. # # Here's what it does: # # 1. Parse code into a JS AST (`.parseJS()`) # 2. Mutate the JS AST into a CoffeeScript AST (`.transform()`) # 3. Render the AST into CoffeeScript (`.generate()`) ### js2coffee.build = (source, options = {}) -> options.filename ?= 'input.js' options.indent ?= 2 options.source = source ast = js2coffee.parseJS(source, options) {ast, warnings} = js2coffee.transform(ast, options) {code, map} = js2coffee.generate(ast, options) {code, ast, map, warnings} ###* # parseJS() : js2coffee.parseJS(source, [options]) # Parses JavaScript code into an AST via Esprima. # Returns a JavaScript AST. Throws an error if parsing can't continue. # # try # ast = js2coffee.parseJS('var a = 2;') # catch err # ... ### js2coffee.parseJS = (source, options = {}) -> try Esprima = require('esprima') Esprima.parse(source, loc: true, range: true, comment: true) catch err throw buildError(err, source, options.filename) ###* # transform() : js2coffee.transform(ast, [options]) # Mutates a given JavaScript syntax tree `ast` into a CoffeeScript AST. # # ast = js2coffee.parseJS('var a = 2;') # result = js2coffee.transform(ast) # # result.ast # result.warnings # # This performs a few traversals across the tree using traversal classes # (TransformerBase subclasses). # # These transformations will need to be done in multiple passes. The earlier # steps (function, comment, etc) will make drastic modifications to the tree # that the other transformations will need to pick up. ### js2coffee.transform = (ast, options = {}) -> ctx = {} run = (classes) -> TransformerBase.run(ast, options, classes, ctx) comments = not (options.comments is false) # Injects comments into the AST as BlockComment and LineComment nodes. run [ require('./lib/transforms/comments') ] if comments # Moves named functions to the top of the scope. run [ require('./lib/transforms/functions') ] # Everything else -- these can be done in one step without any side effects. run [ require('./lib/transforms/exponents') require('./lib/transforms/ifs') require('./lib/transforms/iife') require('./lib/transforms/literals') require('./lib/transforms/loops') require('./lib/transforms/members') require('./lib/transforms/objects') require('./lib/transforms/binary') require('./lib/transforms/empty_statements') require('./lib/transforms/others') require('./lib/transforms/precedence') require('./lib/transforms/returns') require('./lib/transforms/switches') require('./lib/transforms/unsupported') ] # Consolidate nested blocks -- block nesting can be a side effect of the # transformations above run [ require('./lib/transforms/blocks') ] { ast, warnings: ctx.warnings } ###* # generate() : js2coffee.generate(ast, [options]) # Generates CoffeeScript code from a given CoffeeScript AST. Returns an object # with `code` (CoffeeScript source code) and `map` (source mapping object). # # ast = js2coffee.parse('var a = 2;') # ast = js2coffee.transform(ast) # {code, map} = generate(ast) ### js2coffee.generate = (ast, options = {}) -> new Builder(ast, options).get() ###* # version : js2coffee.version # The version number ### js2coffee.version = require('./package.json').version