New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

esperanto

Package Overview
Dependencies
Maintainers
1
Versions
75
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

esperanto - npm Package Compare versions

Comparing version 0.1.1 to 0.3.0

lib/esperanto.js

11

index.js

@@ -1,3 +0,2 @@

var recast = require( 'recast' ),
parse = require( './lib/parse' ),
var transform = require( './lib/transform' ),
generators = require( './lib/generators' );

@@ -9,4 +8,4 @@

var parsed = parse( source, options );
return generators.amd( parsed, options );
var transformed = transform( source, options, true );
return generators.amd( transformed, options );
},

@@ -17,5 +16,5 @@

var parsed = parse( source, options );
return generators.cjs( parsed, options );
var transformed = transform( source, options );
return generators.cjs( transformed, options );
}
};

@@ -1,29 +0,53 @@

var recast = require( 'recast' );
var __export;
module.exports = function ( parsed, options ) {
__export = function amd ( parsed, options ) {
var generated = '', imports = parsed.imports, exports = parsed.exports;
var guessIndent = require( '../utils/guessIndent' ),
applyIndent = require( '../utils/applyIndent' ),
intro,
outro,
code = '',
imports = parsed.imports,
hasExports = parsed.hasExports,
importPaths = '',
importNames = '',
indent;
generated += 'define([' +
( options.defaultOnly ? imports : imports.concat( 'exports' ) ).map( quote ).join( ',' ) +
'], function (' +
( options.defaultOnly ? imports.map( getImportName ) : imports.map( getImportName ).concat( 'exports' ) ).join( ',' ) +
') {\n\n';
if ( imports.length ) {
importPaths = '[' +
( options.defaultOnly ?
imports.map( getPath ) :
imports.map( getPath ).concat( 'exports' )
).map( quote ).join( ',' ) +
'],';
if ( options.defaultOnly ) {
generated += 'var __export;\n\n';
importNames = (
options.defaultOnly ?
imports.map( getImportName ) :
imports.map( getImportName ).concat( 'exports' )
).join( ', ' );
}
generated += recast.print( parsed.ast ).code;
intro = 'define(' + importPaths + 'function (' + importNames + ') {';
if ( options.defaultOnly ) {
generated += '\nreturn __export;';
if ( options.addUseStrict !== false ) {
code = "'use strict';\n\n";
}
generated += '\n\n});';
if ( options.defaultOnly && !parsed.alreadyReturned && hasExports ) {
code += 'var __export;\n\n';
}
return generated.trim();
code += parsed.body;
if ( options.defaultOnly && !parsed.alreadyReturned && hasExports ) {
code += '\nreturn __export;';
}
outro = '});';
indent = options.indent || guessIndent( parsed.body );
return [ intro, applyIndent( code.trim(), indent ), outro ].join( '\n\n' );
};
function quote ( str ) {

@@ -33,4 +57,9 @@ return "'" + str + "'";

function getImportName ( x, i ) {
return '__imports_' + i;
function getPath ( x ) {
return x.path;
}
function getImportName ( x ) {
return x.name;
}
module.exports = __export;

@@ -1,22 +0,25 @@

var recast = require( 'recast' );
module.exports = function ( parsed, options ) {
var generated = '', imports = parsed.imports, exports = parsed.exports;
var result = [],
code = parsed.body.trim(),
imports = parsed.imports,
hasExports = parsed.hasExports;
generated += imports.map( function ( source, i ) {
return 'var __imports_' + i + ' = require(\'' + source + '\');'
}).join( '\n' ) + '\n';
if ( imports.length ) {
result[0] = imports.map( function ( x ) {
return 'var ' + x.name + ' = require(\'' + x.path + '\');';
}).join( '\n' );
}
if ( options.defaultOnly ) {
generated += 'var __export;\n\n';
if ( options.defaultOnly && !parsed.alreadyReturned && hasExports ) {
code = 'var __export;\n\n' + code;
}
generated += recast.print( parsed.ast ).code;
result.push( code );
if ( options.defaultOnly ) {
generated += '\nmodule.exports = __export;';
if ( options.defaultOnly && !parsed.alreadyReturned && hasExports ) {
result.push( 'module.exports = __export;' );
}
return generated.trim();
};
return result.join( '\n' );
};
{
"name": "esperanto",
"description": "An easier way to convert ES6 modules to AMD and CommonJS",
"version": "0.1.1",
"version": "0.3.0",
"author": "Rich Harris",
"dependencies": {
"recast": "~0.7.0"
"acorn": "~0.7.0"
},
"main": "lib/esperanto.js",
"devDependencies": {

@@ -13,3 +14,5 @@ "promo": "~0.1.1",

"rimraf": "~2.2.8",
"mkdirp": "~0.5.0"
"mkdirp": "~0.5.0",
"gobble": "~0.1.2",
"gobble-requirejs": "~0.1.0"
},

@@ -16,0 +19,0 @@ "files": [

# esperanto
coming soon...
A better way to transpile ES6 modules to AMD and CommonJS:
* Easier - no laborious configuration
* Simpler - doesn't make dangerous assumptions about your project setup
* Smarter - non-destructive source code transformation, no runtime Traceur dependency, and no ES5-only features
* Faster - roughly 10x quicker than the alternatives
## Installation
```bash
npm install esperanto
```
## Usage
```js
var fs = require( 'fs' );
var esperanto = require( 'esperanto' );
fs.readFile( 'path/to/es6/modules/foo.js', function ( err, result ) {
if ( err ) throw err;
fs.writeFile( 'path/to/amd/output/foo.js', esperanto.toAmd( result.toString() ) );
fs.writeFile( 'path/to/cjs/output/foo.js', esperanto.toCjs( result.toString() ) );
});
```
Esperanto exposes two methods - `esperanto.toAmd()` and `esperanto.toCjs()`. Both methods take a `source` argument, which is the source code of an ES6 module, and an optional second argument, `options`.
The `options` argument can have a `defaultOnly` property, which defaults to `false`. See the next section for an explanation.
If you're using `esperanto.toAmd()`, you have two additional options:
* `indent` (string) specifies how to indent the contents of the module. By default, esperanto will guess the correct indentation from the code, and default to a single tab character if it's not sure.
* `addUseStrict` (boolean) determines whether the 'use strict' pragma should be added to the top of the module. Defaults to `true`.
## When to use `defaultOnly`
ES6 modules support both *default* and *named* imports and exports:
```js
// default
import foo from 'foo';
var bar = foo.toUpperCase();
export default bar;
// named
import { foo, bar } from 'baz';
var bar = foo.toUpperCase();
export { qux };
```
See [jsmodules.io](http://jsmodules.io/) for an explanation of the difference.
This is a good design, but [it poses problems](https://gist.github.com/domenic/4748675) for developers who want to use ES6 modules with existing codebases. An AMD representation of the first example above might look like this:
```js
define(['foo','exports'], function (__import_1,exports) {
var foo = __import_1.default;
var bar = foo.toUpperCase();
exports.default = bar;
});
```
As long as `foo` is also a transpiled ES6 module with a `default` property (or an AMD module that had a `default` property added by design), that's fine - as far as *this* module is concerned. But if `foo` is an external library, that almost certainly won't be the case.
On the other side of the fence, if someone were to require this ES6 module from within an AMD module, they'd have the same problem in reverse.
Esperanto's `defaultOnly` option solves this problem. As long as you're not using named imports or exports, it will cause modules to behave as you (as a seasoned user of AMD or CommonJS modules) would naturally expect:
```js
define(['foo'],function (foo) {
'use strict';
var bar = foo.toUpperCase();
return bar;
});
```
## Why not use existing module transpilers?
There are already a couple of ES6 module transpilers. Let's consider our example from above...
```js
import foo from 'foo';
var bar = foo.toUpperCase();
export default bar;
```
...and see how those transpilers fare.
### [bitovi/transpile](https://github.com/bitovi/transpile)
```js
var transpile = require( 'transpile' );
var transpiled = transpile.to({
name: 'test',
source: test, // the contents of the module
metadata: { format: 'es6' }
}, 'amd' );
```
Pretty easy - we just tell it what input and output formats to use, and off it goes. It's a bit of a shame that you have to specify a `name` property, since AMD best practice is to use anonymous modules, but never mind. What does the result look like?
```js
define('sample', ['foo'], function ($__0) {
'use strict';
if (!$__0 || !$__0.__esModule)
$__0 = { 'default': $__0 };
var foo = $traceurRuntime.assertObject($__0).default;
var bar = foo.toUpperCase();
var $__default = bar;
return {
get default() {
return $__default;
},
__esModule: true
};
});
```
Wait, I'm supposed to use Traceur in production? No thanks! Oh, and I still need to support IE8, so that `get default()` is a no-go.
### [esnext/es6-module-transpiler](https://github.com/esnext/es6-module-transpiler)
```js
var transpiler = require( 'es6-module-transpiler' );
var Container = transpiler.Container;
var FileResolver = transpiler.FileResolver;
var BundleFormatter = transpiler.formatters.bundle;
var AmdFormatter = require( 'es6-module-transpiler-amd-formatter' );
var container = new Container({
resolvers: [new FileResolver(['./'])],
formatter: new AmdFormatter()
});
container.getModule('test');
container.write('output/test.js');
```
This time, rather than passing in a string, we have to point the transpiler to the files on disk. That's because it actually follows the dependency graph of your modules, so that it can (if you're not using the [AMD formatter](https://github.com/caridy/es6-module-transpiler-amd-formatter)) bundle up your source code into a single file. If it can't find a module, it errors out - so as far as I can tell, it's impossible to use es6-module-transpiler if you have external dependencies (e.g. in a `bower_components` folder) that aren't packaged as ES6 modules.
Leaving aside that minor problem, what does the result look like?
```js
define("test", ["foo", "exports"], function(foo$$, __exports__) {
"use strict";
function __es6_export__(name, value) {
__exports__[name] = value;
}
var foo;
foo = foo$$["default"];
var bar = foo.toUpperCase();
__es6_export__("default", bar);
});
//# sourceMappingURL=es6-module-transpiler.js.map
```
Better, certainly, and you get source maps. Though as with [transpile](https://github.com/bitovi/transpile), you're stuck with named (as opposed to anonymous) AMD modules. Frankly, though, the external dependencies thing is a dealbreaker for me.
### esperanto
Here's the code to generate AMD output:
```js
var transpiled = esperanto.toAmd( test );
```
And here's the output:
```js
define(['foo','exports'], function (__imports_0,exports) {
var foo = __imports_0.default;
var bar = foo.toUpperCase();
exports.default = bar;
});
```
If we run it in `defaultOnly` mode...
```js
var transpiled = esperanto.toAmd( test, { defaultOnly: true });
```
```js
define(['foo'],function (foo) {
'use strict';
var bar = foo.toUpperCase();
return bar;
});
```
No muss, no fuss. Oh, and did I mention that it's an order of magnitude faster than the alternatives?
## Still to-do
* A proper test suite (if you want to test esperanto, clone this module, `cd` into this folder, `npm install` dependencies, and run `node test.js`. The generated code will be written to the `output` folder)
* Renaming imports (e.g. `import { unlink as rm } from 'fs'`)
* Source maps?
* Allow named modules, if you're into that
## Credits
Many thanks to [Marijn Haverbeke](http://marijnhaverbeke.nl/) for [Acorn](https://github.com/marijnh/acorn), which does all the heavy lifting.
## License
Copyright 2014 Rich Harris. MIT Licensed.
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc