1
0
mirror of https://github.com/bobwen-dev/react-templates synced 2025-04-12 00:56:39 +02:00

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. * Easy syntax that's similar to HTML, supported by most IDEs.
* Clear separation of presentation and logic - almost zero HTML in component files. * 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. * 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 ## 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. 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)); 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 ## License
Copyright (c) 2014 Wix. Licensed under the MIT license. Copyright (c) 2014 Wix. Licensed under the MIT license.

View File

@ -25,7 +25,7 @@ $ rt <filename>[,<filename>] [<args>]
Options: Options:
-h, --help Show help. -h, --help Show help.
-c, --color Use colors in output. - default: true -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 -r, --force Force creation of output. skip file check. - default: false
-f, --format String Use a specific output format. (stylish|json) - default: stylish -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 -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>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>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>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> </ul>
</section> </section>
<section id="home-section" class="home-section"> <section id="home-section" class="home-section">

View File

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

View File

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

View File

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