diff --git a/lib/6to5/transformation/transform.js b/lib/6to5/transformation/transform.js
index 34f18bd114..6b3455b6ad 100644
--- a/lib/6to5/transformation/transform.js
+++ b/lib/6to5/transformation/transform.js
@@ -49,7 +49,6 @@ _.each({
numericLiterals: require("./transformers/numeric-literals"),
react: require("./transformers/react"),
- jsx: require("./transformers/jsx"),
_aliasFunctions: require("./transformers/_alias-functions"),
_blockHoist: require("./transformers/_block-hoist"),
diff --git a/lib/6to5/transformation/transformers/jsx.js b/lib/6to5/transformation/transformers/jsx.js
deleted file mode 100644
index 40bbc4911e..0000000000
--- a/lib/6to5/transformation/transformers/jsx.js
+++ /dev/null
@@ -1,101 +0,0 @@
-// Based upon the excellent jsx-transpiler by Ingvar Stepanyan (RReverser)
-// https://github.com/RReverser/jsx-transpiler
-
-var esutils = require("esutils");
-var t = require("../../types");
-var _ = require("lodash");
-
-var JSX_ANNOTATION_REGEX = /^\*\s*@jsx\s+([^\s]+)/;
-
-exports.Program = function (node, parent, file) {
- var jsx = "React.DOM";
-
- // looking for namespace annotation
- _.each(node.leadingComments, function (comment) {
- var matches = JSX_ANNOTATION_REGEX.exec(comment.value);
- if (matches) jsx = matches[1];
- });
-
- // prebuilding AST node
- file.jsx = jsx.split(".").map(t.identifier).reduce(function (object, property) {
- return t.memberExpression(object, property);
- });
-};
-
-exports.XJSIdentifier = function (node) {
- if (esutils.keyword.isIdentifierName(node.name)) {
- node.type = "Identifier";
- } else {
- return t.literal(node.name);
- }
-};
-
-exports.XJSNamespacedName = function () {
- throw new Error("Namespace tags are not supported. ReactJSX is not XML.");
-};
-
-exports.XJSMemberExpression = {
- exit: function (node) {
- node.computed = t.isLiteral(node.property);
- node.type = "MemberExpression";
- }
-};
-
-exports.XJSExpressionContainer = function (node) {
- return node.expression;
-};
-
-exports.XJSAttribute = {
- exit: function (node) {
- var value = node.value || t.literal(true);
- return t.property("init", node.name, value);
- }
-};
-
-exports.XJSOpeningElement = {
- exit: function (node, parent, file) {
- var tagExpr = node.name;
-
- if (t.isIdentifier(tagExpr)) {
- var tagName = tagExpr.name;
-
- if (/[a-z]/.exec(tagName[0]) || _.contains(tagName, "-")) {
- tagExpr = t.memberExpression(file.jsx, tagExpr);
- }
- }
-
- var props = node.attributes;
- if (props.length) {
- props = t.objectExpression(props);
- } else {
- props = t.literal(null);
- }
-
- return t.callExpression(tagExpr, [props]);
- }
-};
-
-exports.XJSElement = {
- exit: function (node) {
- var callExpr = node.openingElement;
- var children = node.children;
-
- _.each(children, function (child, i) {
- var val = child.value;
- if (t.isLiteral(child) && _.isString(val)) {
- val = val.replace(/\n(\s+)/g, " ");
-
- i = +i;
- if (i === 0) val = val.trimLeft();
- if (i === children.length - 1) val = val.trimRight();
-
- if (!val) return;
- child.value = val;
- }
-
- callExpr.arguments.push(child);
- });
-
- return t.inherits(callExpr, node);
- }
-};
diff --git a/lib/6to5/transformation/transformers/react.js b/lib/6to5/transformation/transformers/react.js
index 3a7f29cdeb..e43cd2ddfb 100644
--- a/lib/6to5/transformation/transformers/react.js
+++ b/lib/6to5/transformation/transformers/react.js
@@ -1,5 +1,101 @@
-var t = require("../../types");
-var _ = require("lodash");
+// Based upon the excellent jsx-transpiler by Ingvar Stepanyan (RReverser)
+// https://github.com/RReverser/jsx-transpiler
+
+// jsx
+
+var esutils = require("esutils");
+var t = require("../../types");
+var _ = require("lodash");
+
+exports.XJSIdentifier = function (node) {
+ if (esutils.keyword.isIdentifierName(node.name)) {
+ node.type = "Identifier";
+ } else {
+ return t.literal(node.name);
+ }
+};
+
+exports.XJSNamespacedName = function (node, parent, file) {
+ throw file.errorWithNode(node, "Namespace tags are not supported. ReactJSX is not XML.");
+};
+
+exports.XJSMemberExpression = {
+ exit: function (node) {
+ node.computed = t.isLiteral(node.property);
+ node.type = "MemberExpression";
+ }
+};
+
+exports.XJSExpressionContainer = function (node) {
+ return node.expression;
+};
+
+exports.XJSAttribute = {
+ exit: function (node) {
+ var value = node.value || t.literal(true);
+ return t.property("init", node.name, value);
+ }
+};
+
+exports.XJSOpeningElement = {
+ exit: function (node, parent, file) {
+ var tagExpr = node.name;
+ var args = [];
+
+ var tagName;
+ if (t.isIdentifier(tagExpr)) {
+ tagName = tagExpr.name;
+ } else if (t.isLiteral(tagExpr)) {
+ tagName = tagExpr.value;
+ }
+
+ if (tagName && (/[a-z]/.exec(tagName[0]) || _.contains(tagName, "-"))) {
+ args.push(t.literal(tagName));
+ } else {
+ args.push(tagExpr);
+ }
+
+ var props = node.attributes;
+ if (props.length) {
+ var first = props[0];
+ if (t.isXJSSpreadAttribute(first)) {
+ props.shift();
+ props = t.callExpression(
+ t.memberExpression(t.identifier("React"), t.identifier("__spread")),
+ [t.objectExpression([]), first.argument, t.objectExpression(props)]
+ );
+ } else {
+ props = t.objectExpression(props);
+ }
+ } else {
+ props = t.literal(null);
+ }
+
+ args.push(props);
+
+ tagExpr = t.memberExpression(t.identifier("React"), t.identifier("createElement"));
+ return t.callExpression(tagExpr, args);
+ }
+};
+
+exports.XJSElement = {
+ exit: function (node) {
+ var callExpr = node.openingElement;
+ var children = node.children;
+
+ var childrenToRender = node.children.filter(function(child) {
+ return !(t.isLiteral(child) && _.isString(child.value) && child.value.match(/^[ \t]*[\r\n][ \t\r\n]*$/));
+ });
+
+ _.each(childrenToRender, function (child, i) {
+ callExpr.arguments.push(child);
+ });
+
+ return t.inherits(callExpr, node);
+ }
+};
+
+// display names
var addDisplayName = function (id, call) {
if (!call || !t.isCallExpression(call)) return;
diff --git a/lib/6to5/types/visitor-keys.json b/lib/6to5/types/visitor-keys.json
index e577d2bbd8..af3cf76b1d 100644
--- a/lib/6to5/types/visitor-keys.json
+++ b/lib/6to5/types/visitor-keys.json
@@ -71,6 +71,6 @@
"XJSMemberExpression": ["object", "property"],
"XJSNamespacedName": ["namespace", "name"],
"XJSOpeningElement": ["name", "attributes"],
- "XJSSpreadAttribute": [],
+ "XJSSpreadAttribute": ["argument"],
"YieldExpression": ["argument"]
}
diff --git a/test/fixtures/transformation/jsx/annotation/actual.js b/test/fixtures/transformation/jsx/annotation/actual.js
deleted file mode 100644
index 2412fb7b42..0000000000
--- a/test/fixtures/transformation/jsx/annotation/actual.js
+++ /dev/null
@@ -1,3 +0,0 @@
-/** @jsx CUSTOM_DOM */
-
-
diff --git a/test/fixtures/transformation/jsx/annotation/expected.js b/test/fixtures/transformation/jsx/annotation/expected.js
deleted file mode 100644
index 2069c82ded..0000000000
--- a/test/fixtures/transformation/jsx/annotation/expected.js
+++ /dev/null
@@ -1,5 +0,0 @@
-/** @jsx CUSTOM_DOM */
-
-"use strict";
-
-CUSTOM_DOM.a(null);
diff --git a/test/fixtures/transformation/jsx/empty/actual.js b/test/fixtures/transformation/jsx/empty/actual.js
deleted file mode 100644
index 46a77a2ef3..0000000000
--- a/test/fixtures/transformation/jsx/empty/actual.js
+++ /dev/null
@@ -1 +0,0 @@
-{}
diff --git a/test/fixtures/transformation/jsx/empty/expected.js b/test/fixtures/transformation/jsx/empty/expected.js
deleted file mode 100644
index 6d37224243..0000000000
--- a/test/fixtures/transformation/jsx/empty/expected.js
+++ /dev/null
@@ -1,3 +0,0 @@
-"use strict";
-
-X(null, null);
\ No newline at end of file
diff --git a/test/fixtures/transformation/jsx/everything/actual.js b/test/fixtures/transformation/jsx/everything/actual.js
deleted file mode 100644
index 0c42b3a8af..0000000000
--- a/test/fixtures/transformation/jsx/everything/actual.js
+++ /dev/null
@@ -1,2 +0,0 @@
- :
-}>
diff --git a/test/fixtures/transformation/jsx/everything/expected.js b/test/fixtures/transformation/jsx/everything/expected.js
deleted file mode 100644
index 09090cb36e..0000000000
--- a/test/fixtures/transformation/jsx/everything/expected.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-X({
- "data-prop": x ? Y({
- prop: 2
- }) : Z(null)
-});
diff --git a/test/fixtures/transformation/jsx/expressions/actual.js b/test/fixtures/transformation/jsx/expressions/actual.js
deleted file mode 100644
index 8191b76c06..0000000000
--- a/test/fixtures/transformation/jsx/expressions/actual.js
+++ /dev/null
@@ -1,5 +0,0 @@
-({a});
-
-({a} {b});
-
-();
diff --git a/test/fixtures/transformation/jsx/expressions/expected.js b/test/fixtures/transformation/jsx/expressions/expected.js
deleted file mode 100644
index 9f944f9051..0000000000
--- a/test/fixtures/transformation/jsx/expressions/expected.js
+++ /dev/null
@@ -1,10 +0,0 @@
-"use strict";
-
-(X(null, a));
-
-(X(null, a, " ", b));
-
-(X({
- prop: a,
- yes: true
-}));
diff --git a/test/fixtures/transformation/jsx/known-tags/actual.js b/test/fixtures/transformation/jsx/known-tags/actual.js
deleted file mode 100644
index 41ab602321..0000000000
--- a/test/fixtures/transformation/jsx/known-tags/actual.js
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/test/fixtures/transformation/jsx/known-tags/expected.js b/test/fixtures/transformation/jsx/known-tags/expected.js
deleted file mode 100644
index 3a02eece90..0000000000
--- a/test/fixtures/transformation/jsx/known-tags/expected.js
+++ /dev/null
@@ -1,3 +0,0 @@
-"use strict";
-
-React.DOM.a(null);
\ No newline at end of file
diff --git a/test/fixtures/transformation/jsx/member-expression/actual.js b/test/fixtures/transformation/jsx/member-expression/actual.js
deleted file mode 100644
index 67707269e9..0000000000
--- a/test/fixtures/transformation/jsx/member-expression/actual.js
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/test/fixtures/transformation/jsx/member-expression/expected.js b/test/fixtures/transformation/jsx/member-expression/expected.js
deleted file mode 100644
index 2a43047839..0000000000
--- a/test/fixtures/transformation/jsx/member-expression/expected.js
+++ /dev/null
@@ -1,3 +0,0 @@
-"use strict";
-
-Test.X(null);
\ No newline at end of file
diff --git a/test/fixtures/transformation/jsx/no-xml-namespaces/actual.js b/test/fixtures/transformation/jsx/no-xml-namespaces/actual.js
deleted file mode 100644
index 80e9ac6925..0000000000
--- a/test/fixtures/transformation/jsx/no-xml-namespaces/actual.js
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/test/fixtures/transformation/jsx/self-closing-tags/actual.js b/test/fixtures/transformation/jsx/self-closing-tags/actual.js
deleted file mode 100644
index c74cd039aa..0000000000
--- a/test/fixtures/transformation/jsx/self-closing-tags/actual.js
+++ /dev/null
@@ -1,3 +0,0 @@
-();
-
-();
diff --git a/test/fixtures/transformation/jsx/self-closing-tags/expected.js b/test/fixtures/transformation/jsx/self-closing-tags/expected.js
deleted file mode 100644
index 9ba9c59036..0000000000
--- a/test/fixtures/transformation/jsx/self-closing-tags/expected.js
+++ /dev/null
@@ -1,7 +0,0 @@
-"use strict";
-
-(X(null));
-
-(X({
- prop: "1"
-}));
diff --git a/test/fixtures/transformation/jsx/simple-tags/actual.js b/test/fixtures/transformation/jsx/simple-tags/actual.js
deleted file mode 100644
index 87779ff5c6..0000000000
--- a/test/fixtures/transformation/jsx/simple-tags/actual.js
+++ /dev/null
@@ -1 +0,0 @@
-
diff --git a/test/fixtures/transformation/jsx/simple-tags/expected.js b/test/fixtures/transformation/jsx/simple-tags/expected.js
deleted file mode 100644
index b7bbfe9f22..0000000000
--- a/test/fixtures/transformation/jsx/simple-tags/expected.js
+++ /dev/null
@@ -1,3 +0,0 @@
-"use strict";
-
-X(null);
\ No newline at end of file
diff --git a/test/fixtures/transformation/jsx/tags-with-children/actual.js b/test/fixtures/transformation/jsx/tags-with-children/actual.js
deleted file mode 100644
index aa8ed7080b..0000000000
--- a/test/fixtures/transformation/jsx/tags-with-children/actual.js
+++ /dev/null
@@ -1,3 +0,0 @@
-();
-
-();
diff --git a/test/fixtures/transformation/jsx/tags-with-children/expected.js b/test/fixtures/transformation/jsx/tags-with-children/expected.js
deleted file mode 100644
index 13d7a21122..0000000000
--- a/test/fixtures/transformation/jsx/tags-with-children/expected.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-(X({
- prop: "2"
-}, Y(null)));
-
-(X({
- prop: "2"
-}, Y(null), Z(null)));
diff --git a/test/fixtures/transformation/jsx/tags-with-literals/actual.js b/test/fixtures/transformation/jsx/tags-with-literals/actual.js
deleted file mode 100644
index 5507ef2680..0000000000
--- a/test/fixtures/transformation/jsx/tags-with-literals/actual.js
+++ /dev/null
@@ -1,13 +0,0 @@
-( );
-
-(
-);
-
-(
- string
-);
-
-(
- string
- string
- );
diff --git a/test/fixtures/transformation/jsx/tags-with-literals/expected.js b/test/fixtures/transformation/jsx/tags-with-literals/expected.js
deleted file mode 100644
index 539d0d28d8..0000000000
--- a/test/fixtures/transformation/jsx/tags-with-literals/expected.js
+++ /dev/null
@@ -1,9 +0,0 @@
-"use strict";
-
-(X(null));
-
-(X(null));
-
-(X(null, "string"));
-
-(X(null, "string string"));
diff --git a/test/fixtures/transformation/react/.should-not-strip-nbsp-even-coupled-with-other-whitespace/actual.js b/test/fixtures/transformation/react/.should-not-strip-nbsp-even-coupled-with-other-whitespace/actual.js
new file mode 100644
index 0000000000..38d8acbab5
--- /dev/null
+++ b/test/fixtures/transformation/react/.should-not-strip-nbsp-even-coupled-with-other-whitespace/actual.js
@@ -0,0 +1 @@
+
;
diff --git a/test/fixtures/transformation/react/.should-not-strip-nbsp-even-coupled-with-other-whitespace/expected.js b/test/fixtures/transformation/react/.should-not-strip-nbsp-even-coupled-with-other-whitespace/expected.js
new file mode 100644
index 0000000000..796b172664
--- /dev/null
+++ b/test/fixtures/transformation/react/.should-not-strip-nbsp-even-coupled-with-other-whitespace/expected.js
@@ -0,0 +1 @@
+React.createElement("div", null, "\u00A0 ");
diff --git a/test/fixtures/transformation/react/.should-not-strip-tags-with-a-single-child-of-nbsp/actual.js b/test/fixtures/transformation/react/.should-not-strip-tags-with-a-single-child-of-nbsp/actual.js
new file mode 100644
index 0000000000..0e05a7be8d
--- /dev/null
+++ b/test/fixtures/transformation/react/.should-not-strip-tags-with-a-single-child-of-nbsp/actual.js
@@ -0,0 +1 @@
+
;
diff --git a/test/fixtures/transformation/react/.should-not-strip-tags-with-a-single-child-of-nbsp/expected.js b/test/fixtures/transformation/react/.should-not-strip-tags-with-a-single-child-of-nbsp/expected.js
new file mode 100644
index 0000000000..3c405fd729
--- /dev/null
+++ b/test/fixtures/transformation/react/.should-not-strip-tags-with-a-single-child-of-nbsp/expected.js
@@ -0,0 +1 @@
+React.createElement("div", null, "\u00A0");
diff --git a/test/fixtures/transformation/react/.should-properly-handle-comments-adjacent-to-children/actual.js b/test/fixtures/transformation/react/.should-properly-handle-comments-adjacent-to-children/actual.js
new file mode 100644
index 0000000000..412984681e
--- /dev/null
+++ b/test/fixtures/transformation/react/.should-properly-handle-comments-adjacent-to-children/actual.js
@@ -0,0 +1,13 @@
+var x = (
+
+ {/* A comment at the beginning */}
+ {/* A second comment at the beginning */}
+
+ {/* A nested comment */}
+
+ {/* A sandwiched comment */}
+
+ {/* A comment at the end */}
+ {/* A second comment at the end */}
+
+);
diff --git a/test/fixtures/transformation/react/.should-properly-handle-comments-adjacent-to-children/expected.js b/test/fixtures/transformation/react/.should-properly-handle-comments-adjacent-to-children/expected.js
new file mode 100644
index 0000000000..2d11293957
--- /dev/null
+++ b/test/fixtures/transformation/react/.should-properly-handle-comments-adjacent-to-children/expected.js
@@ -0,0 +1,11 @@
+var x = (React.createElement("div", null,
+ /* A comment at the beginning */
+ /* A second comment at the beginning */
+ React.createElement("span", null
+ /* A nested comment */
+ ),
+ /* A sandwiched comment */
+ React.createElement("br", null)
+ /* A comment at the end */
+ /* A second comment at the end */
+));
diff --git a/test/fixtures/transformation/react/.should-properly-handle-comments-between-props/actual.js b/test/fixtures/transformation/react/.should-properly-handle-comments-between-props/actual.js
new file mode 100644
index 0000000000..8b1943e8f6
--- /dev/null
+++ b/test/fixtures/transformation/react/.should-properly-handle-comments-between-props/actual.js
@@ -0,0 +1,10 @@
+var x = (
+
+
+
+);
diff --git a/test/fixtures/transformation/react/.should-properly-handle-comments-between-props/expected.js b/test/fixtures/transformation/react/.should-properly-handle-comments-between-props/expected.js
new file mode 100644
index 0000000000..ae95737591
--- /dev/null
+++ b/test/fixtures/transformation/react/.should-properly-handle-comments-between-props/expected.js
@@ -0,0 +1,8 @@
+var x = (React.createElement("div", {
+ /* a multi-line
+ comment */
+ attr1: "foo"},
+ React.createElement("span", {// a double-slash comment
+ attr2: "bar"}
+ )
+));
diff --git a/test/fixtures/transformation/react/adds-appropriate-newlines-when-using-spread-attribute/actual.js b/test/fixtures/transformation/react/adds-appropriate-newlines-when-using-spread-attribute/actual.js
new file mode 100644
index 0000000000..88ca6d7a77
--- /dev/null
+++ b/test/fixtures/transformation/react/adds-appropriate-newlines-when-using-spread-attribute/actual.js
@@ -0,0 +1,3 @@
+
diff --git a/test/fixtures/transformation/react/adds-appropriate-newlines-when-using-spread-attribute/expected.js b/test/fixtures/transformation/react/adds-appropriate-newlines-when-using-spread-attribute/expected.js
new file mode 100644
index 0000000000..31b010b451
--- /dev/null
+++ b/test/fixtures/transformation/react/adds-appropriate-newlines-when-using-spread-attribute/expected.js
@@ -0,0 +1,3 @@
+React.createElement(Component, React.__spread({}, this.props, {
+ sound: "moo"
+}));
diff --git a/test/fixtures/transformation/react/display-name-assignment-expression/expected.js b/test/fixtures/transformation/react/display-name-assignment-expression/expected.js
index f2159b2dfe..6d4c263e16 100644
--- a/test/fixtures/transformation/react/display-name-assignment-expression/expected.js
+++ b/test/fixtures/transformation/react/display-name-assignment-expression/expected.js
@@ -1,5 +1,3 @@
-"use strict";
-
var Component;
Component = React.createClass({
displayName: "Component",
diff --git a/test/fixtures/transformation/react/display-name-if-missing/expected.js b/test/fixtures/transformation/react/display-name-if-missing/expected.js
index 2ef17aa97c..64f8f0b30d 100644
--- a/test/fixtures/transformation/react/display-name-if-missing/expected.js
+++ b/test/fixtures/transformation/react/display-name-if-missing/expected.js
@@ -1,8 +1,6 @@
-"use strict";
-
var Whateva = React.createClass({
displayName: "Whatever",
render: function () {
return null;
}
-});
\ No newline at end of file
+});
diff --git a/test/fixtures/transformation/react/display-name-object-declaration/expected.js b/test/fixtures/transformation/react/display-name-object-declaration/expected.js
index ad5da2eed8..ab809e9330 100644
--- a/test/fixtures/transformation/react/display-name-object-declaration/expected.js
+++ b/test/fixtures/transformation/react/display-name-object-declaration/expected.js
@@ -1,5 +1,3 @@
-"use strict";
-
exports = {
Component: React.createClass({
displayName: "Component",
diff --git a/test/fixtures/transformation/react/display-name-property-assignment/expected.js b/test/fixtures/transformation/react/display-name-property-assignment/expected.js
index 661947e1c8..a4e1c4a382 100644
--- a/test/fixtures/transformation/react/display-name-property-assignment/expected.js
+++ b/test/fixtures/transformation/react/display-name-property-assignment/expected.js
@@ -1,5 +1,3 @@
-"use strict";
-
exports.Component = React.createClass({
displayName: "Component",
diff --git a/test/fixtures/transformation/react/display-name-variable-declaration/expected.js b/test/fixtures/transformation/react/display-name-variable-declaration/expected.js
index 7aedb82664..15d409759a 100644
--- a/test/fixtures/transformation/react/display-name-variable-declaration/expected.js
+++ b/test/fixtures/transformation/react/display-name-variable-declaration/expected.js
@@ -1,5 +1,3 @@
-"use strict";
-
var Component = React.createClass({
displayName: "Component",
diff --git a/test/fixtures/transformation/react/options.json b/test/fixtures/transformation/react/options.json
new file mode 100644
index 0000000000..a5a58b5836
--- /dev/null
+++ b/test/fixtures/transformation/react/options.json
@@ -0,0 +1,3 @@
+{
+ "blacklist": ["useStrict"]
+}
diff --git a/test/fixtures/transformation/react/should-allow-constructor-as-prop/actual.js b/test/fixtures/transformation/react/should-allow-constructor-as-prop/actual.js
new file mode 100644
index 0000000000..29c24a7630
--- /dev/null
+++ b/test/fixtures/transformation/react/should-allow-constructor-as-prop/actual.js
@@ -0,0 +1 @@
+;
diff --git a/test/fixtures/transformation/react/should-allow-constructor-as-prop/expected.js b/test/fixtures/transformation/react/should-allow-constructor-as-prop/expected.js
new file mode 100644
index 0000000000..5bda6d624f
--- /dev/null
+++ b/test/fixtures/transformation/react/should-allow-constructor-as-prop/expected.js
@@ -0,0 +1,3 @@
+React.createElement(Component, {
+ constructor: "foo"
+});
diff --git a/test/fixtures/transformation/react/should-allow-deeper-js-namespacing/actual.js b/test/fixtures/transformation/react/should-allow-deeper-js-namespacing/actual.js
new file mode 100644
index 0000000000..158b9a9dee
--- /dev/null
+++ b/test/fixtures/transformation/react/should-allow-deeper-js-namespacing/actual.js
@@ -0,0 +1 @@
+;
diff --git a/test/fixtures/transformation/react/should-allow-deeper-js-namespacing/expected.js b/test/fixtures/transformation/react/should-allow-deeper-js-namespacing/expected.js
new file mode 100644
index 0000000000..8dc54f904a
--- /dev/null
+++ b/test/fixtures/transformation/react/should-allow-deeper-js-namespacing/expected.js
@@ -0,0 +1 @@
+React.createElement(Namespace.DeepNamespace.Component, null);
diff --git a/test/fixtures/transformation/react/should-allow-js-namespacing/actual.js b/test/fixtures/transformation/react/should-allow-js-namespacing/actual.js
new file mode 100644
index 0000000000..6c104620cf
--- /dev/null
+++ b/test/fixtures/transformation/react/should-allow-js-namespacing/actual.js
@@ -0,0 +1 @@
+;
diff --git a/test/fixtures/transformation/react/should-allow-js-namespacing/blacklist.js b/test/fixtures/transformation/react/should-allow-js-namespacing/blacklist.js
new file mode 100644
index 0000000000..980df45724
--- /dev/null
+++ b/test/fixtures/transformation/react/should-allow-js-namespacing/blacklist.js
@@ -0,0 +1 @@
+React.createElement(Namespace.Component, null);
diff --git a/test/fixtures/transformation/react/should-allow-js-namespacing/expected.js b/test/fixtures/transformation/react/should-allow-js-namespacing/expected.js
new file mode 100644
index 0000000000..980df45724
--- /dev/null
+++ b/test/fixtures/transformation/react/should-allow-js-namespacing/expected.js
@@ -0,0 +1 @@
+React.createElement(Namespace.Component, null);
diff --git a/test/fixtures/transformation/react/should-avoid-wrapping-in-extra-parens-if-not-needed/actual.js b/test/fixtures/transformation/react/should-avoid-wrapping-in-extra-parens-if-not-needed/actual.js
new file mode 100644
index 0000000000..37ab4f48f1
--- /dev/null
+++ b/test/fixtures/transformation/react/should-avoid-wrapping-in-extra-parens-if-not-needed/actual.js
@@ -0,0 +1,15 @@
+var x =
+
+
;
+
+var x =
+ {this.props.children}
+
;
+
+var x =
+ {this.props.children}
+;
+
+var x =
+
+;
diff --git a/test/fixtures/transformation/react/should-avoid-wrapping-in-extra-parens-if-not-needed/expected.js b/test/fixtures/transformation/react/should-avoid-wrapping-in-extra-parens-if-not-needed/expected.js
new file mode 100644
index 0000000000..fc3c313d70
--- /dev/null
+++ b/test/fixtures/transformation/react/should-avoid-wrapping-in-extra-parens-if-not-needed/expected.js
@@ -0,0 +1,7 @@
+var x = React.createElement("div", null, React.createElement(Component, null));
+
+var x = React.createElement("div", null, this.props.children);
+
+var x = React.createElement(Composite, null, this.props.children);
+
+var x = React.createElement(Composite, null, React.createElement(Composite2, null));
diff --git a/test/fixtures/transformation/react/should-convert-simple-tags/actual.js b/test/fixtures/transformation/react/should-convert-simple-tags/actual.js
new file mode 100644
index 0000000000..b6d801a6bc
--- /dev/null
+++ b/test/fixtures/transformation/react/should-convert-simple-tags/actual.js
@@ -0,0 +1 @@
+var x = ;
diff --git a/test/fixtures/transformation/react/should-convert-simple-tags/expected.js b/test/fixtures/transformation/react/should-convert-simple-tags/expected.js
new file mode 100644
index 0000000000..73d0a3e9d5
--- /dev/null
+++ b/test/fixtures/transformation/react/should-convert-simple-tags/expected.js
@@ -0,0 +1 @@
+var x = React.createElement("div", null);
diff --git a/test/fixtures/transformation/react/should-convert-simple-text/actual.js b/test/fixtures/transformation/react/should-convert-simple-text/actual.js
new file mode 100644
index 0000000000..42c927f15a
--- /dev/null
+++ b/test/fixtures/transformation/react/should-convert-simple-text/actual.js
@@ -0,0 +1 @@
+var x = text
;
diff --git a/test/fixtures/transformation/react/should-convert-simple-text/expected.js b/test/fixtures/transformation/react/should-convert-simple-text/expected.js
new file mode 100644
index 0000000000..4a89144887
--- /dev/null
+++ b/test/fixtures/transformation/react/should-convert-simple-text/expected.js
@@ -0,0 +1 @@
+var x = React.createElement("div", null, "text");
diff --git a/test/fixtures/transformation/react/should-disallow-xml-namespacing/actual.js b/test/fixtures/transformation/react/should-disallow-xml-namespacing/actual.js
new file mode 100644
index 0000000000..50df717c12
--- /dev/null
+++ b/test/fixtures/transformation/react/should-disallow-xml-namespacing/actual.js
@@ -0,0 +1 @@
+;
diff --git a/test/fixtures/transformation/jsx/no-xml-namespaces/options.json b/test/fixtures/transformation/react/should-disallow-xml-namespacing/options.json
similarity index 100%
rename from test/fixtures/transformation/jsx/no-xml-namespaces/options.json
rename to test/fixtures/transformation/react/should-disallow-xml-namespacing/options.json
diff --git a/test/fixtures/transformation/react/should-handle-has-own-property-correctly/actual.js b/test/fixtures/transformation/react/should-handle-has-own-property-correctly/actual.js
new file mode 100644
index 0000000000..4d5e8fb63c
--- /dev/null
+++ b/test/fixtures/transformation/react/should-handle-has-own-property-correctly/actual.js
@@ -0,0 +1 @@
+testing;
diff --git a/test/fixtures/transformation/react/should-handle-has-own-property-correctly/expected.js b/test/fixtures/transformation/react/should-handle-has-own-property-correctly/expected.js
new file mode 100644
index 0000000000..55c8cea170
--- /dev/null
+++ b/test/fixtures/transformation/react/should-handle-has-own-property-correctly/expected.js
@@ -0,0 +1 @@
+React.createElement("hasOwnProperty", null, "testing");
diff --git a/test/fixtures/transformation/react/should-have-correct-comma-in-nested-children/actual.js b/test/fixtures/transformation/react/should-have-correct-comma-in-nested-children/actual.js
new file mode 100644
index 0000000000..fa82e1cd08
--- /dev/null
+++ b/test/fixtures/transformation/react/should-have-correct-comma-in-nested-children/actual.js
@@ -0,0 +1,5 @@
+var x = ;
diff --git a/test/fixtures/transformation/react/should-have-correct-comma-in-nested-children/expected.js b/test/fixtures/transformation/react/should-have-correct-comma-in-nested-children/expected.js
new file mode 100644
index 0000000000..f8a0851173
--- /dev/null
+++ b/test/fixtures/transformation/react/should-have-correct-comma-in-nested-children/expected.js
@@ -0,0 +1 @@
+var x = React.createElement("div", null, React.createElement("div", null, React.createElement("br", null)), React.createElement(Component, null, foo, React.createElement("br", null), bar), React.createElement("br", null));
diff --git a/test/fixtures/transformation/react/should-insert-commas-after-expressions-before-whitespace/actual.js b/test/fixtures/transformation/react/should-insert-commas-after-expressions-before-whitespace/actual.js
new file mode 100644
index 0000000000..92541bbb35
--- /dev/null
+++ b/test/fixtures/transformation/react/should-insert-commas-after-expressions-before-whitespace/actual.js
@@ -0,0 +1,16 @@
+var x =
+
+
diff --git a/test/fixtures/transformation/react/should-insert-commas-after-expressions-before-whitespace/expected.js b/test/fixtures/transformation/react/should-insert-commas-after-expressions-before-whitespace/expected.js
new file mode 100644
index 0000000000..f7a07f8b6c
--- /dev/null
+++ b/test/fixtures/transformation/react/should-insert-commas-after-expressions-before-whitespace/expected.js
@@ -0,0 +1,6 @@
+var x = React.createElement("div", {
+ attr1: "foo" + "bar",
+ attr2: "foo" + "bar" + "baz" + "bug",
+ attr3: "foo" + "bar" + "baz" + "bug",
+ attr4: "baz"
+});
diff --git a/test/fixtures/transformation/react/should-transform-known-hyphenated-tags/actual.js b/test/fixtures/transformation/react/should-transform-known-hyphenated-tags/actual.js
new file mode 100644
index 0000000000..1cb54dd688
--- /dev/null
+++ b/test/fixtures/transformation/react/should-transform-known-hyphenated-tags/actual.js
@@ -0,0 +1 @@
+;
diff --git a/test/fixtures/transformation/react/should-transform-known-hyphenated-tags/expected.js b/test/fixtures/transformation/react/should-transform-known-hyphenated-tags/expected.js
new file mode 100644
index 0000000000..140f5b1b8c
--- /dev/null
+++ b/test/fixtures/transformation/react/should-transform-known-hyphenated-tags/expected.js
@@ -0,0 +1 @@
+React.createElement("font-face", null);
diff --git a/test/fixtures/transformation/react/wraps-props-in-react-spread-for-spread-attributes/actual.js b/test/fixtures/transformation/react/wraps-props-in-react-spread-for-spread-attributes/actual.js
new file mode 100644
index 0000000000..4e9432dfa3
--- /dev/null
+++ b/test/fixtures/transformation/react/wraps-props-in-react-spread-for-spread-attributes/actual.js
@@ -0,0 +1,2 @@
+
diff --git a/test/fixtures/transformation/react/wraps-props-in-react-spread-for-spread-attributes/expected.js b/test/fixtures/transformation/react/wraps-props-in-react-spread-for-spread-attributes/expected.js
new file mode 100644
index 0000000000..5e5b8e74a0
--- /dev/null
+++ b/test/fixtures/transformation/react/wraps-props-in-react-spread-for-spread-attributes/expected.js
@@ -0,0 +1,4 @@
+React.createElement(Component, React.__spread({}, x, {
+ y: 2,
+ z: true
+}));