diff --git a/README.md b/README.md index 66a041a..dba103a 100644 --- a/README.md +++ b/README.md @@ -23,9 +23,7 @@ npm install --save-dev babel-plugin-transform-react-jsx ### Via `.babelrc` (Recommended) -**.babelrc** - -Without options (no different from `transform-react-jsx`): +#### Without options (no different from `transform-react-jsx`): ```json { @@ -33,15 +31,15 @@ Without options (no different from `transform-react-jsx`): } ``` -With options: +#### With options: ```json { "plugins": [ ["transform-jsx-flexible", { "tags": { - "CustomTag1": "createElement_CustomTag1", - "CustomTag2": "createElement_CustomTag2" + "somelib.CustomTag1": "createElement_CustomTag1", + "somelib.CustomTag2": "createElement_CustomTag2" } }] ] @@ -56,9 +54,9 @@ var profile =

{[user.firstName, user.lastName].join(' ')}

; -var somethingElse = +var somethingElse =
-; +; ``` **Code Out** @@ -69,7 +67,7 @@ var profile = React.createElement("div", null, React.createElement("h3", null, [user.firstName, user.lastName].join(" ")) ); -var somethingElse = createElement_CustomTag1(CustomTag1, null, +var somethingElse = createElement_CustomTag1(somelib.CustomTag1, null, createElement_CustomTag1("div", null) ); ``` @@ -107,18 +105,22 @@ For example: "transform-jsx-flexible", { "tags": { - "CustomTag1": "createElement_CustomTag1", - "CustomTag2": "createElement_CustomTag2" + "somelib.CustomTag1": "createElement_CustomTag1", + "somelib.CustomTag2": "createElement_CustomTag2" } } ] ``` -Using this configuration, any `CustomTag1` element and any JSX elements +Using this configuration, any `somelib.CustomTag1` element and any JSX elements enclosed inside of it will be created using the function `createElement_CustomTag1()` in the transpiled JS code, instead of `React.createElement` (or the current default JSX function). -The same goes for `CustomTag2` and `createElement_CustomTag2`. Also, JSX -handlers can be changed within the same block by nesting these custom tags +The same goes for `somelib.CustomTag2` and `createElement_CustomTag2`. Also, +JSX handlers can be changed within the same block by nesting these custom tags together. + +For clarity and explicitness, it's recommended, but not required, to specify +any custom tags with a member expression (`somelib.CustomTag1` in the examples +above), rather than simply a tag name. diff --git a/index.js b/index.js index df484f7..4c36f82 100644 --- a/index.js +++ b/index.js @@ -8,6 +8,18 @@ module.exports = function( { types: t } ) { .reduce( ( object, property ) => t.memberExpression( object, property ) ); } + function getJSXMemberExpressionName( expr ) { + let namePieces = []; + if ( expr.object.object && expr.object.property ) { + namePieces = namePieces.concat( + getJSXMemberExpressionName( expr.object ) + ); + } else { + namePieces = namePieces.concat( expr.object.name ); + } + return namePieces.concat( expr.property.name ); + } + const JSX_ANNOTATION_REGEX = /\*?\s*@jsx\s+([^\s]+)/; const visitor = helper( { @@ -42,10 +54,20 @@ module.exports = function( { types: t } ) { do { const openingElement = currentPath.get( 'openingElement' ); if ( openingElement && openingElement.node ) { - const nodeName = openingElement.node.name.name; - if ( tagOptions[ nodeName ] ) { + const nodeNameExpr = openingElement.node.name; + let elementName; + if ( nodeNameExpr.type === 'JSXIdentifier' ) { + // A simple JSX expression like + elementName = nodeNameExpr.name; + } else if ( nodeNameExpr.type === 'JSXMemberExpression' ) { + // A JSX member expression like + elementName = getJSXMemberExpressionName( nodeNameExpr ) + .join( '.' ); + } + + if ( tagOptions[ elementName ] ) { jsxCurrentIdentifier = stringToCallExpression( - tagOptions[ nodeName ] + tagOptions[ elementName ] ); break; } diff --git a/test/fixtures/member-expression/member-expression/actual.js b/test/fixtures/member-expression/member-expression/actual.js new file mode 100644 index 0000000..f27d96e --- /dev/null +++ b/test/fixtures/member-expression/member-expression/actual.js @@ -0,0 +1,21 @@ +; + +; + +; + +; + + + +; + +; diff --git a/test/fixtures/member-expression/member-expression/expected.js b/test/fixtures/member-expression/member-expression/expected.js new file mode 100644 index 0000000..fc04c7c --- /dev/null +++ b/test/fixtures/member-expression/member-expression/expected.js @@ -0,0 +1,15 @@ +createElement_CustomTag1(CustomTag1, null); + +React.createElement(CustomTag2, null); + +createElement_CustomTag2(namespaced.CustomTag2, null); + +somelib.createElement_CustomTag3(namespaced.rather.deeply.CustomTag3, null); + +somelib.createElement_CustomTag3( + namespaced.rather.deeply.CustomTag3, + null, + somelib.createElement_CustomTag3(WithSomeWhitespace, { because: "why not" }) +); + +React.createElement(Component, { prop: "foo" }); diff --git a/test/fixtures/member-expression/options.json b/test/fixtures/member-expression/options.json new file mode 100644 index 0000000..a3ca7f0 --- /dev/null +++ b/test/fixtures/member-expression/options.json @@ -0,0 +1,14 @@ +{ + "plugins": [ + [ + "transform-jsx-flexible", { + "tags": { + "CustomTag1": "createElement_CustomTag1", + "namespaced.CustomTag2": "createElement_CustomTag2", + "namespaced.rather.deeply.CustomTag3": "somelib.createElement_CustomTag3" + } + } + ] + ] +} +