Skip to content

Commit

Permalink
JSX props values can be elements too (#268)
Browse files Browse the repository at this point in the history
Fixes #267

The value of a JSX attribute/prop can be a JSX element or a fragment.

Also fix a stray comma in JSX fragment output.
  • Loading branch information
arv authored and alangpierce committed Jun 21, 2018
1 parent 472cb8d commit 6c3e80f
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 7 deletions.
3 changes: 3 additions & 0 deletions src/parser/plugins/jsx/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,9 @@ function nextJSXTagToken(): void {
case charCodes.greaterThan:
finishToken(tt.jsxTagEnd);
break;
case charCodes.lessThan:
finishToken(tt.jsxTagStart);
break;
case charCodes.slash:
finishToken(tt.slash);
break;
Expand Down
6 changes: 3 additions & 3 deletions src/transformers/JSXTransformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ export default class JSXTransformer extends Transformer {
this.tokens.replaceToken("");
this.rootTransformer.processBalancedCode();
this.tokens.replaceToken("");
} else if (this.tokens.matches1(tt.jsxTagStart)) {
this.processJSXTag();
} else {
this.processStringPropValue();
}
Expand Down Expand Up @@ -214,9 +216,7 @@ export default class JSXTransformer extends Transformer {
? this.importProcessor.getIdentifierReplacement(jsxFragmentPragmaBase) ||
jsxFragmentPragmaBase
: jsxFragmentPragmaBase;
this.tokens.replaceToken(
`${resolvedFragmentPragmaBaseName}${jsxFragmentPragmaSuffix}, null, `,
);
this.tokens.replaceToken(`${resolvedFragmentPragmaBaseName}${jsxFragmentPragmaSuffix}, null`);
// Tag with children.
this.processChildren();
while (!this.tokens.matches1(tt.jsxTagEnd)) {
Expand Down
32 changes: 28 additions & 4 deletions test/jsx-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,30 @@ describe("transform JSX", () => {
);
});

it("handles element property values", () => {
assertResult(
`
<A foo=<B /> />
`,
`${JSX_PREFIX}
React.createElement(A, { foo: React.createElement(B, {${devProps(2)}} ), ${devProps(2)}} )
`,
);
});

it("handles fragment property values", () => {
assertResult(
`
<A foo=<>Hi</> />
`,
`${JSX_PREFIX}
React.createElement(A, { foo: React.createElement(React.Fragment, null, "Hi"), ${devProps(
2,
)}} )
`,
);
});

it("handles inline comments", () => {
assertResult(
`
Expand Down Expand Up @@ -311,7 +335,7 @@ describe("transform JSX", () => {
`,
`${JSX_PREFIX}
const f = (
React.createElement(React.Fragment, null,
React.createElement(React.Fragment, null
, React.createElement('div', {${devProps(4)}} )
, React.createElement('span', {${devProps(5)}} )
)
Expand All @@ -334,7 +358,7 @@ describe("transform JSX", () => {
`"use strict";${JSX_PREFIX}${IMPORT_DEFAULT_PREFIX}
var _react = require('react'); var _react2 = _interopRequireDefault(_react);
const f = (
_react2.default.createElement(_react2.default.Fragment, null,
_react2.default.createElement(_react2.default.Fragment, null
, _react2.default.createElement('div', {__self: this, __source: {fileName: _jsxFileName, lineNumber: 5}} )
, _react2.default.createElement('span', {__self: this, __source: {fileName: _jsxFileName, lineNumber: 6}} )
)
Expand All @@ -356,7 +380,7 @@ describe("transform JSX", () => {
`,
`${JSX_PREFIX}
const f = (
h(Fragment, null,
h(Fragment, null
, h('div', {__self: this, __source: {fileName: _jsxFileName, lineNumber: 4}} )
, h('span', {__self: this, __source: {fileName: _jsxFileName, lineNumber: 5}} )
)
Expand All @@ -380,7 +404,7 @@ describe("transform JSX", () => {
`"use strict";${JSX_PREFIX}
var _preact = require('preact');
const f = (
_preact.h(_preact.Fragment, null,
_preact.h(_preact.Fragment, null
, _preact.h('div', {__self: this, __source: {fileName: _jsxFileName, lineNumber: 5}} )
, _preact.h('span', {__self: this, __source: {fileName: _jsxFileName, lineNumber: 6}} )
)
Expand Down

0 comments on commit 6c3e80f

Please sign in to comment.