buxlabs / amd-to-es6

convert amd to es
MIT License
35 stars 17 forks source link

support jsx #82

Open ryankshaw opened 6 years ago

ryankshaw commented 6 years ago

for example, I'd like it to handle code like:

define([
  'react',
  'enzyme',
  '../path/to/Component',
], (React, {mount}, Component) => {

    const wrapper = mount(
      <Component
        someProp={true}
        otherProp={someVar}
      />
    );
});

is that something you plan to support?

emilos commented 6 years ago

hey @ryankshaw I haven't planned it, but the lib depends on https://github.com/eslint/espree which does have jsx support out of the box, so it should be possible :)

It probably all boils down to passing a ecmaFeatures: { jsx: true } flag down conditionally to the parser here https://github.com/buxlabs/ast/blob/master/index.js#L17 and adding some specs (I'm not sure if anything else would be required)

Contribution is welcome! I can add it over the weekend if you're busy with other stuff

ryankshaw commented 6 years ago

that would be awesome @emilos! I'm not familiar enough with this code base to submit a pull request myself but it would be really cool of you to add it when you have time. thanks for taking the time to look at this!

emilos commented 6 years ago

I've investigated the issue a little bit, and it is possible but it requires more work than expected :) I have a tight schedule so this can take a while, sorry about that

ryankshaw commented 6 years ago

@emilos is there anything I could do to try to fix this myself? do you have any pointers on where to start? I'd still really benefit from this but don't want to bug you if you are too busy. And thank you for looking into it

emilos commented 6 years ago

hey @ryankshaw any help is appreciated :)

To give you a bigger picture - I can see two ways of making this happen

1) adjust all of the dependencies to handle jsx out of the box (this is a looot of work)

2) be able to parse the jsx, turn the jsx nodes into some temporary representation (like some unique identifiers), convert the code and replace the temporary identifiers with jsx code

a)

define(function () {
  return (<div>foo</div>)
})

b)

define(function () {
  return JSX_NODE_1
})

c)

export default JSX_NODE_1

d)

export default (<div>foo</div>)

Assuming we pick the 2nd option:

I.

You should probably start with letting jsx flag go through here (or even fix it to use Object assign and let any options come in to the parser)

https://github.com/buxlabs/ast/blob/master/index.js#L17

II.

In the next step we'd need to do the a) -> b) step, likely somewhere here:

https://github.com/buxlabs/amd-to-es6/blob/master/src/converter.js#L11

let transformed = []
if (options.jsx) {
  transformed = module.transformJsxNodes()
}

III.

in next step you'd need to add a transformJsxNodes method here:

https://github.com/buxlabs/amd-to-es6/blob/master/src/class/Module.js

the method should walk through the tree and replace the jsx nodes with the unique identifiers I mentioned above (not sure if you'll run into any issues here, but that might happen :) )

IV

Later we'd need to transform it back (probably on raw source, I think that escodegen generation library that's used does not support jsx out of the box)

https://github.com/buxlabs/amd-to-es6/blob/master/src/converter.js#L16

let source = module.toSource(options)
if (options.jsx && transformed.length > 0) {
   //  ... go through all transformations and bring back jsx code here
   return
}
return source

I think that would be it... let me know if you have any questions!