UNPKG

11.1 kBMarkdownView Raw
1[![Build Status](https://img.shields.io/travis/lebab/lebab.svg)](https://travis-ci.org/lebab/lebab)
2[![Coverage Status](https://img.shields.io/codecov/c/github/lebab/lebab/master.svg)](https://codecov.io/github/lebab/lebab)
3[![Dependencies](https://img.shields.io/librariesio/github/lebab/lebab.svg)](https://libraries.io/npm/lebab)
4[![License](https://img.shields.io/:license-mit-brightgreen.svg)](https://mohebifar.mit-license.org)
5[![Version](https://img.shields.io/npm/v/lebab.svg)](https://www.npmjs.com/package/lebab)
6
7# Lebab
8
9![Lebab](https://raw.githubusercontent.com/mohebifar/lebab-logo/master/logo.png)
10
11**Lebab** transpiles your ES5 code to ES6/ES7.
12It does exactly the opposite of what [Babel](https://babeljs.io/) does.
13If you want to understand what Lebab exactly does, **[try the live demo](https://lebab.github.io/).**
14
15
16## Install
17
18Install it using npm:
19
20```bash
21$ npm install -g lebab
22```
23
24Full build:
25
26- [latest Browserified version of Lebab](https://wzrd.in/standalone/lebab@latest)
27- [the same, using cdn.rawgit](https://umdfied.herokuapp.com/umdfied/lebab/latest)
28
29## Usage
30
31Convert your old-fashioned code using the `lebab` cli tool,
32enabling a specific transformation:
33
34```bash
35$ lebab es5.js -o es6.js --transform let
36```
37
38Or transform an entire directory of files in-place:
39
40```bash
41# .js files only
42$ lebab --replace src/js/ --transform arrow
43# For other file extensions, use explicit globbing
44$ lebab --replace 'src/js/**/*.jsx' --transform arrow
45```
46
47For all the possible values for `--transform` option
48see the detailed docs below or use `--help` from command line.
49
50
51## Features and known limitations
52
53The recommended way of using Lebab is to apply one transform at a time,
54read what exactly the transform does and what are its limitations,
55apply it for your code and inspect the diff carefully.
56
57### Safe transforms
58
59These transforms can be applied with relatively high confidence.
60They use pretty straight-forward and strict rules for changing the code.
61The resulting code should be almost 100% equivalent of the original code.
62
63- [x] **arrow** - callbacks to arrow functions
64 - [x] Converts bound functions like `function(){}.bind(this)`
65 - [x] not applied to unbound functions that use `this`
66 - [x] not applied to functions that use `arguments`
67 - [x] not applied to object properties (use `obj-method` transform)
68 - [ ] does not remove `that = this` assignments
69- [x] **arrow-return** - drop return statements in arrow functions
70 - [x] converts immediate return `{ return x; }` to `=> x`
71 - [x] applies to arrow functions and nested arrow functions
72 - [ ] LIMITATION only applies to arrow functions (run the `arrow` transform first)
73- [x] **for-of** - for loop to for-of loop
74 - [x] uses name `item` for loop variable when loop body begins with `var item = array[i];`
75 - [ ] [does not work when no such alias defined at the start of loop body][166]
76 - [ ] LIMITATION requires let/const variables (run the `let` transform first)
77- [x] **for-each** - for loop to `Array.forEach()`
78 - [x] uses name `item` for forEach parameter when loop body begins with `var item = array[i];`
79 - [ ] [does not work when no such alias defined at the start of loop body][166]
80 - [x] adds index parameter when loop body makes use of the index variable.
81 - [ ] LIMITATION requires let/const variables (run the `let` transform first)
82- [x] **arg-rest** - use of arguments to function(...args)
83 - [x] does not perform the transform when `args` variable already exists
84 - [ ] always names the rest-parameter to `args`
85 - [ ] LIMITATION [does not transform functions with formal parameters][191]
86 - [ ] LIMITATION [does not remove uses of `Array.slice.call(arguments)`][191]
87- [x] **arg-spread** - use of apply() to spread operator
88 - [x] recognizes `obj.method.apply(obj, args)`
89 - [x] recognizes `func.apply(undefined, args)`
90- [x] **obj-method** - function values in object to methods
91 - [ ] LIMITATION [does not convert named function expressions][127]
92 - [ ] does not convert arrow-functions
93- [x] **obj-shorthand** - `{foo: foo}` to `{foo}`
94 - [x] ignores numeric and `NaN` properties
95 - [ ] does not convert string properties
96- [x] **no-strict** - removal of `"use strict"` directives
97 - [x] does not touch stuff like `x = "use strict";`
98- [x] **exponent** - `Math.pow()` to `**` operator (**ES7**)
99 - [x] Full support for all new syntax from ES7
100- [x] **multi-var** - single `var x,y;` declaration to multiple `var x; var y;` (**refactor**)
101 - [x] Not related to any new syntax feature
102 - [x] EXPERIMENT [to see if Lebab could be a more generic refactoring helper][158]
103
104### Unsafe transforms
105
106These transforms should be applied with caution.
107They either use heuristics which can't guarantee that the resulting code is equivalent of the original code,
108or they have significant bugs which can result in breaking your code.
109
110- [x] **let** - `var` to `let`/`const`
111 - [x] never modified variables are converted to `const`
112 - [x] properly recognizes block-scoping
113 - [x] splits single var declaration to multiple `let`/`const` declarations if needed
114 - [x] recognizes vars defined/assigned using destructuring
115 - [x] vars that conflict with block-scoping are not converted
116 - [x] repeated declarations of the same var are not converted
117 - [x] existing `let`/`const` are not converted
118 - [ ] BUG [fails with repeated variable definitions that use destructuring][131]
119 - [ ] BUG [fails with closure over a loop variable][145]
120 - [ ] BUG [fails when function closes over variable declared after function is called][168]
121- [x] **class** - function/prototypes to classes
122 - [x] recognizes `Foo.prototype.method = function(){ ... };`
123 - [x] recognizes `Foo.prototype = { ...methods... };`
124 - [x] recognizes static methods like `Foo.method = function(){ ... };`
125 - [x] recognizes getters/setters defined with `Object.defineProperty()`
126 - [x] recognizes inheritance with `Child.prototype = new Parent()`
127 - [x] recognizes inheritance with `util.inherits(Child, Parent);`
128 - [x] converts superclass constructor calls to `super()`
129 - [x] converts superclass method calls to `super.method()`
130 - [ ] LIMITATION [does not require super() call in subclass constructor][186]
131 - [ ] LIMITATION [does not enforce super() call position in subclass constructor][186]
132 - [ ] LIMITATION [does not support namespaced classes][113]
133- [x] **commonjs** - CommonJS module definition to ES6 modules
134 - [x] converts `var foo = require("foo")` to `import foo from "foo"`
135 - [x] converts `var bar = require("foo").bar` to `import {bar} from "foo"`
136 - [x] converts `var {bar} = require("foo")` to `import {bar} from "foo"`
137 - [x] converts `module.exports = <anything>` to `export default <anything>`
138 - [x] converts `exports.foo = function(){}` to `export function foo(){}`
139 - [x] converts `exports.Foo = class {}` to `export class Foo {}`
140 - [x] converts `exports.foo = 123` to `export var foo = 123`
141 - [x] converts `exports.foo = bar` to `export {bar as foo}`
142 - [ ] LIMITATION does not check if named export conflicts with existing variable names
143 - [ ] LIMITATION Ignores imports/exports inside nested blocks/functions
144 - [ ] LIMITATION only handles `require()` calls in `var` declarations
145 - [ ] LIMITATION does not ensure that imported variable is treated as `const`
146 - [ ] LIMITATION [does not ensure named exports are imported with correct ES6 syntax][215]
147- [x] **template** - string concatenation to template strings
148 - [x] converts variables and arbitrary expressions to `${...}`
149 - [ ] BUG [removes indentation of multi-line strings][88]
150 - [ ] LIMITATION [ignores difference between `.toString()` and `.valueOf()`][107]
151- [x] **default-param** - default parameters instead of `a = a || 2`
152 - [x] recognizes `a = a || 2`
153 - [x] recognizes `a = a ? a : 2`
154 - [x] recognizes `a = a === undefined ? 2 : a`
155 - [x] recognizes `a = typeof a === 'undefined' ? 2 : a`
156 - [ ] LIMITATION [transforming `a = a || 2` does not produce strictly equivalent code][125]
157- [x] **destruct-param** - use destructuring for objects in function parameters
158 - [x] converts `(obj) => obj.a + obj.b` to `({a, b}) => a + b`
159 - [x] does not transform when conflicts with existing variables
160 - [x] does not transform when object properties are modified
161 - [ ] LIMITATION Only objects with maximum of 4 properties are transformed
162 - [ ] BUG [Can conflict with variables introduced by the transform itself][200]
163- [x] **includes** - `array.indexOf(foo) !== -1` to `array.includes(foo)` (**ES7**)
164 - [x] works for both strings and arrays
165 - [x] converts `!== -1` to `array.includes(foo)`
166 - [x] converts `=== -1` to `!array.includes(foo)`
167 - [x] recognizes all kinds of comparisons `>= 0`, `> -1`, etc
168 - [x] recognizes both `indexOf() != -1` and `-1 != indexOf()`
169 - [ ] LIMITATION does not detect that indexOf() is called on an actual Array or String.
170
171
172## Programming API
173
174Simply import and call the `transform()` function:
175
176```js
177import {transform} from 'lebab';
178const {code, warnings} = transform(
179 'var f = function(a) { return a; };', // code to transform
180 ['let', 'arrow', 'arrow-return'] // transforms to apply
181);
182console.log(code); // -> "const f = a => a;"
183```
184
185The warnings will be an array of objects like:
186
187```js
188[
189 {line: 12, msg: 'Unable to transform var', type: 'let'},
190 {line: 45, msg: 'Can not use arguments in arrow function', type: 'arrow'},
191]
192```
193
194Most of the time there won't be any warnings and the array will be empty.
195
196
197## Editor plugins
198
199Alternatively one can use Lebab through plugins in the following editors:
200
201- Atom: [atom-lebab](https://github.com/ga2mer/atom-lebab)
202- Sublime: [lebab-sublime](https://github.com/inkless/lebab-sublime) or [Lebab ES6 Transform](https://packagecontrol.io/packages/Lebab%20ES6%20Transform)
203- VSCode: [vscode-lebab](https://marketplace.visualstudio.com/items?itemName=mrmlnc.vscode-lebab)
204
205
206## What's next?
207
208Which feature should Lebab implement next?
209Let us know by [creating an issue](https://github.com/mohebifar/lebab/issues)
210or voicing your opinion in existing one.
211
212Want to contribute? [Read how Lebab looks for patterns in syntax trees.][pattern-matching]
213
214[pattern-matching]: http://nene.github.io/2016/04/02/matches-ast
215[88]: https://github.com/lebab/lebab/issues/88
216[107]: https://github.com/lebab/lebab/issues/107
217[113]: https://github.com/lebab/lebab/issues/113
218[125]: https://github.com/lebab/lebab/issues/125
219[127]: https://github.com/lebab/lebab/issues/127
220[131]: https://github.com/lebab/lebab/issues/131
221[145]: https://github.com/lebab/lebab/issues/145
222[158]: https://github.com/lebab/lebab/issues/158
223[166]: https://github.com/lebab/lebab/issues/166
224[168]: https://github.com/lebab/lebab/issues/168
225[186]: https://github.com/lebab/lebab/issues/186
226[191]: https://github.com/lebab/lebab/issues/191
227[200]: https://github.com/lebab/lebab/issues/200
228[215]: https://github.com/lebab/lebab/issues/215