diff --git a/escodegen.js b/escodegen.js index a8d0170c..54735ba6 100644 --- a/escodegen.js +++ b/escodegen.js @@ -2434,8 +2434,90 @@ ModuleSpecifier: function (expr, precedence, flags) { return this.Literal(expr, precedence, flags); - } + }, + + JSXIdentifier: function (expr, precedence, flags) { + return expr.name; + }, + + JSXMemberExpression: function (expr, precedence, flags) { + var result = []; + result.push(this.generateExpression(expr.object, precedence, flags)); + result.push('.'); + result.push(this.generateExpression(expr.property, precedence, flags)); + return result; + }, + + JSXNamespacedName: function (expr, precedence, flags) { + var result = []; + result.push(this.generateExpression(expr.namespace, precedence, flags)); + result.push(':'); + result.push(this.generateExpression(expr.name, precedence, flags)); + return result; + }, + JSXEmptyExpression: function (expr, precedence, flags) { + return ''; + }, + + JSXExpressionContainer: function (expr, precedence, flags) { + return ['{', this.generateExpression(expr.expression, precedence, flags), '}']; + }, + + JSXOpeningElement: function (expr, precedence, flags) { + var result, i, iz; + result = ['<']; + result.push(this.generateExpression(expr.name, precedence, flags)); + if (expr.attributes) { + for(i = 0, iz = expr.attributes.length; i < iz; ++i) { + result.push(' '); + result.push(this.generateExpression(expr.attributes[i], precedence, flags)); + } + } + result.push(expr.selfClosing ? ' />' : '>'); + return result; + }, + + JSXClosingElement: function (expr, precedence, flags) { + return ['']; + }, + + JSXAttribute: function (expr, precedence, flags) { + var result = []; + result.push(this.generateExpression(expr.name, precedence, flags)); + result.push('='); + if (expr.value.type === 'Literal') { + result.push(this.generateExpression(expr.value, precedence, flags)); + return result; + } + if (expr.value.type === 'JSXExpressionContainer') { + result.push(this.generateExpression(expr.value.expression, precedence, flags)); + return result; + } + }, + + JSXSpreadAttribute: function (expr, precedence, flags) { + return ['{...', this.generateExpression(expr.argument, precedence, flags), '}']; + }, + + JSXText: function (expr, precedence, flags) { + return expr.value; + }, + + JSXElement: function (expr, precedence, flags) { + var result, i, iz; + result = []; + result.push(this.generateExpression(expr.openingElement, precedence, flags)); + if (expr.children) { + for(i = 0, iz = expr.children.length; i < iz; ++i) { + result.push(this.generateExpression(expr.children[i], precedence, flags)); + } + } + if (expr.closingElement) { + result.push(this.generateExpression(expr.closingElement, precedence, flags)); + } + return result; + } }; merge(CodeGenerator.prototype, CodeGenerator.Expression); diff --git a/package.json b/package.json index 30c90ddb..386df98c 100644 --- a/package.json +++ b/package.json @@ -30,9 +30,9 @@ "url": "http://github.com/estools/escodegen.git" }, "dependencies": { + "esprima": "^4.0.1", "estraverse": "^4.2.0", "esutils": "^2.0.2", - "esprima": "^3.1.3", "optionator": "^0.8.1" }, "optionalDependencies": { diff --git a/test/test.js b/test/test.js index a21cd487..0556ed37 100644 --- a/test/test.js +++ b/test/test.js @@ -30,7 +30,7 @@ 'use strict'; -var esprima = require('./3rdparty/esprima-1.0.0-dev'), +var esprima = require('esprima'), escodegen = require('./loader'), chai = require('chai'), expect = chai.expect, @@ -14871,6 +14871,357 @@ data = { }, tokens: [] } + }, + + 'JSX': { + + '': { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXIdentifier', + name: 'Tag' + }, + selfClosing: true, + attributes: [] + }, + children: [], + closingElement: null + }, + + '': { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXIdentifier', + name: 'TagWithSpace' + }, + selfClosing: true, + attributes: [] + }, + children: [], + closingElement: null + }, + + + '': { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXMemberExpression', + object: { + type: 'JSXMemberExpression', + object: { + type: 'JSXMemberExpression', + object: { + type: 'JSXIdentifier', + name: 'Member' + }, + property: { + type: 'JSXIdentifier', + name: 'Expression' + } + }, + property: { + type: 'JSXIdentifier', + name: 'Tag' + }, + }, + property: { + type: 'JSXIdentifier', + name: 'Name' + } + }, + selfClosing: true, + attributes: [] + }, + children: [], + closingElement: null + }, + + '': { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXIdentifier', + name: 'Tag' + }, + selfClosing: true, + attributes: [ + { + type: 'JSXAttribute', + name: { + type: 'JSXIdentifier', + name: 'attr' + }, + value: { + type: 'Literal', + value: 'string', + raw: '\"string\"' + } + } + ] + }, + children: [], + closingElement: null + }, + + ' {} }}/>': { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXIdentifier', + name: 'Spread' + }, + selfClosing: true, + attributes: [ + { + type: 'JSXSpreadAttribute', + argument: { + type: 'ObjectExpression', + properties: [ + { + type: 'Property', + key: { + type: 'Identifier', + name: 'attr' + }, + computed: false, + value: { + type: 'Literal', + value: 'string', + raw: 'string', + }, + kind: 'init', + method: false, + shorthand: false + }, + { + type: 'Property', + key: { + type: 'Identifier', + name: 'func' + }, + computed: false, + value: { + type: 'ArrowFunctionExpression', + id: null, + params: [], + body: { + type: 'BlockStatement', + body: [] + }, + generator: false, + expression: false, + 'async': false + }, + kind: 'init', + method: false, + shorthand: false + } + ] + } + } + ] + }, + children: [], + closingElement: null + }, + + '': { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXNamespacedName', + name: { + type: 'JSXIdentifier', + name: 'Name' + }, + namespace: { + type: 'JSXIdentifier', + name: 'Namespaced' + } + }, + selfClosing: true, + attributes: [] + }, + children: [], + closingElement: null + }, + + + ' { return true }}/>': { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXIdentifier', + name: 'Tag' + }, + selfClosing: true, + attributes: [ + { + "type": "JSXAttribute", + "name": { + "type": "JSXIdentifier", + "name": "attr" + }, + "value": { + "type": "Literal", + "value": "string", + "raw": "\"string\"" + } + }, + { + "type": "JSXAttribute", + "name": { + "type": "JSXIdentifier", + "name": "expression" + }, + "value": { + "type": "JSXExpressionContainer", + "expression": { + "type": "ArrowFunctionExpression", + "id": null, + "params": [], + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Literal", + "value": true, + "raw": "true" + } + } + ] + }, + generator: false, + expression: false + } + } + } + ] + }, + children: [], + closingElement: null + }, + + '': { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXIdentifier', + name: 'WithClosingTag' + }, + attributes: [] + }, + children: [], + closingElement: { + type: 'JSXClosingElement', + name: { + type: 'JSXIdentifier', + name: 'WithClosingTag' + } + } + }, + + 'text': { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXIdentifier', + name: 'WithTextChild' + }, + attributes: [] + }, + children: [ + { + type: 'JSXText', + value: 'text', + raw: 'text' + } + ], + closingElement: { + type: 'JSXClosingElement', + name: { + type: 'JSXIdentifier', + name: 'WithTextChild' + } + } + }, + + '{() => {}}': { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXIdentifier', + name: 'WithExpressionChild' + }, + attributes: [] + }, + children: [ + { + type: 'JSXExpressionContainer', + expression: { + type: 'ArrowFunctionExpression', + id: null, + params: [], + body: { + type: 'BlockStatement', + body: [] + }, + generator: false, + expression: false, + 'async': false + } + } + ], + closingElement: { + type: 'JSXClosingElement', + name: { + type: 'JSXIdentifier', + name: 'WithExpressionChild' + } + } + }, + + '{}': { + type: 'JSXElement', + openingElement: { + type: 'JSXOpeningElement', + name: { + type: 'JSXIdentifier', + name: 'EmptyExpression' + }, + selfClosing: false, + }, + children: [ + { + type: 'JSXExpressionContainer', + expression: { + type: 'JSXEmptyExpression' + } + } + ], + closingElement: { + type: 'JSXClosingElement', + name: { + type: 'JSXIdentifier', + name: 'EmptyExpression' + } + } + }, } }; @@ -14895,7 +15246,8 @@ function testIdentity(code, syntax) { range: false, loc: false, tokens: false, - raw: false + raw: false, + jsx: true }; expect(function () {