close #pr-14 es6 modules support

This commit is contained in:
ido 2015-02-19 14:45:41 +02:00
parent b1e17e6bd9
commit 4d00e92772
8 changed files with 43 additions and 18 deletions

View File

@ -10,7 +10,7 @@ Lightweight templates for [React](http://facebook.github.io/react/index.html).
* Easy syntax that's similar to HTML, supported by most IDEs.
* Clear separation of presentation and logic - almost zero HTML in component files.
* Declarative coding ensures that the HTML that you write and the HTML you inspect look nearly identical.
* Supports AMD, CommonJS, and globals.
* Supports AMD, CommonJS, ES6, Typescript and globals.
## How does it work
React Templates compiles an *.rt file (react template file - an extended HTML format) into a JavaScript file. This file, which uses AMD syntax, returns a function. When invoked, this function returns a virtual React DOM based on React.DOM elements and custom user components.
@ -343,6 +343,20 @@ module.exports = function () {
return _.map(items, repeatItem1.bind(this));
};
```
###### Compiled (with ES6 flag):
```javascript
import { React } from 'react/addons';
import { _ } from 'lodash';
import { MyComp } from 'comps/myComp';
import { utils } from 'utils/utils';
function repeatItem1(item, itemIndex) {
return React.createElement(MyComp, {}, React.createElement('div', {}, utils.toLower(item.name)));
}
export default function () {
return _.map(items, repeatItem1.bind(this));
};
```
## License
Copyright (c) 2014 Wix. Licensed under the MIT license.

View File

@ -25,7 +25,7 @@ $ rt <filename>[,<filename>] [<args>]
Options:
-h, --help Show help.
-c, --color Use colors in output. - default: true
-m, --modules String Use output modules. (amd|commonjs|none) - default: none
-m, --modules String Use output modules. (amd|commonjs|es6|none) - default: none
-r, --force Force creation of output. skip file check. - default: false
-f, --format String Use a specific output format. (stylish|json) - default: stylish
-t, --target-version String React version to generate code for (0.12.1, 0.12.0, 0.11.2, 0.11.1, 0.11.0, 0.10.0) - default: 0.12.1

View File

@ -65,7 +65,7 @@
<li>Easy syntax that's similar to HTML, supported by most IDEs.</li>
<li>Clear separation of presentation and logic - almost zero HTML in component files.</li>
<li>Declarative coding ensures that the HTML that you write and the HTML you inspect look nearly identical.</li>
<li>Supports <a href="#amd">AMD</a>, <a href="#commonjs">CommonJS</a>, and globals.</li>
<li>Supports <a href="#amd">AMD</a>, <a href="#commonjs">CommonJS</a>, <a href="#es6">ES6</a>, Typescript and globals.</li>
</ul>
</section>
<section id="home-section" class="home-section">

View File

@ -24,7 +24,7 @@
"chalk": "^0.5.1",
"cheerio": "^0.18.0",
"escodegen": "^1.6.1",
"esprima": "^2.0.0",
"esprima-harmony": "^7001.1.0-dev-harmony-fb",
"lodash": "^3.2.0",
"optionator": "^0.5.0",
"text-table": "^0.2.0"

View File

@ -45,7 +45,7 @@ module.exports = optionator({
alias: 'm',
default: 'none',
type: 'String',
description: 'Use output modules. (amd|commonjs|none|typescript)'
description: 'Use output modules. (amd|commonjs|none|es6|typescript)'
}, {
option: 'name',
alias: 'n',

View File

@ -4,7 +4,7 @@
'use strict';
var cheerio = require('cheerio');
var _ = require('lodash');
var esprima = require('esprima');
var esprima = require('esprima-harmony');
var escodegen = require('escodegen');
var reactDOMSupport = require('./reactDOMSupport');
var stringUtils = require('./stringUtils');
@ -20,13 +20,24 @@ var tagTemplate = _.template('<%= name %>.apply(this,_.flatten([<%= props %><%=
var simpleTagTemplateCreateElement = _.template('React.createElement(<%= name %>,<%= props %><%= children %>)');
var tagTemplateCreateElement = _.template('React.createElement.apply(this,_.flatten([<%= name %>,<%= props %><%= children %>]))');
var commentTemplate = _.template(' /* <%= data %> */ ');
var templateAMDTemplate = _.template("define(<%= name ? '\"'+name + '\", ' : '' %>[<%= requirePaths %>], function (<%= requireNames %>) {\n'use strict';\n <%= injectedFunctions %>\nreturn function(){ return <%= body %>};\n});");
var templateCommonJSTemplate = _.template("'use strict';\n<%= vars %>\n\n<%= injectedFunctions %>\nmodule.exports = function(){ return <%= body %>};\n");
var templateES6Template = _.template('<%= vars %>\n\n<%= injectedFunctions %>\nexport default function(){ return <%= body %>}\n');
var templatePJSTemplate = _.template('var <%= name %> = function () {\n' +
'<%= injectedFunctions %>\n' +
'return <%= body %>\n' +
'};\n');
var templateTypescriptTemplate = _.template('<%= vars %>\n\n<%= injectedFunctions %>\nvar fn = function() { return <%= body %> };\nexport = fn\n');
var templates = {
amd: templateAMDTemplate,
commonjs: templateCommonJSTemplate,
typescript: templateTypescriptTemplate,
es6: templateES6Template,
none: templatePJSTemplate
};
var htmlSelfClosingTags = ['area', 'base', 'br', 'col', 'command', 'embed', 'hr', 'img', 'input', 'keygen', 'link', 'meta', 'param', 'source', 'track', 'wbr'];
var templateProp = 'rt-repeat';
@ -338,7 +349,7 @@ function handleSelfClosingHtmlTags(nodes) {
function convertTemplateToReact(html, options) {
var rootNode = cheerio.load(html, {lowerCaseTags: false, lowerCaseAttributeNames: false, xmlMode: true, withStartIndices: true});
options = _.defaults({}, options, defaultOptions);
var defines = {'react/addons': 'React', lodash: '_'};
var defines = options.defines ? options.defines : {'react/addons': 'React', lodash: '_'};
var context = defaultContext(html, options);
var rootTags = _.filter(rootNode.root()[0].children, {type: 'tag'});
rootTags = handleSelfClosingHtmlTags(rootTags);
@ -373,6 +384,8 @@ function convertTemplateToReact(html, options) {
var vars;
if (options.modules === 'typescript') {
vars = _(defines).map(function (reqVar, reqPath) { return 'import ' + reqVar + " = require('" + reqPath + "');"; }).join('\n');
} else if (options.modules === 'es6') {
vars = _(defines).map(function (reqVar, reqPath) { return 'import {' + reqVar + "} from '" + reqPath + "';"; }).join('\n');
} else {
vars = _(defines).map(function (reqVar, reqPath) { return 'var ' + reqVar + " = require('" + reqPath + "');"; }).join('\n');
}
@ -392,16 +405,8 @@ function convertTemplateToReact(html, options) {
}
function generate(data, options) {
if (options.modules === 'amd') {
return templateAMDTemplate(data);
}
if (options.modules === 'commonjs') {
return templateCommonJSTemplate(data);
}
if (options.modules === 'typescript') {
return templateTypescriptTemplate(data);
}
return templatePJSTemplate(data);
var template = templates[options.modules];
return template(data);
}
/**

5
test/data/div.rt.es6.js Normal file
View File

@ -0,0 +1,5 @@
import { React } from 'react/addons';
import { _ } from 'lodash';
export default function () {
return React.createElement('div', {});
};

View File

@ -127,11 +127,12 @@ function compareAndWrite(t, actual, expected, filename) {
}
}
test('conversion test commonjs', function (t) {
test('convert div with all module types', function (t) {
var files = [
{source: 'div.rt', expected: 'div.rt.commonjs.js', options: {modules: 'commonjs'}},
{source: 'div.rt', expected: 'div.rt.amd.js', options: {modules: 'amd', name: 'div'}},
{source: 'div.rt', expected: 'div.rt.globals.js', options: {modules: 'none', name: 'div'}},
{source: 'div.rt', expected: 'div.rt.es6.js', options: {modules: 'es6', name: 'div'}},
{source: 'div.rt', expected: 'div.rt.typescript.ts', options: {modules: 'typescript'}}
];
t.plan(files.length);