ezhlobo / babel-plugin-transform-jsx-classname-components

It allows you to specify inner components via class names
4 stars 0 forks source link

Allow down case objects #5

Open ezhlobo opened 5 years ago

ezhlobo commented 5 years ago

Some libraries like react-spring export objects start with down case.

Example: http://react-spring.surge.sh/perf

import { animated } from 'react-spring'

<animated.div />

It's not possible to allow down case for everything, but when you provide objects option, we can allow any case there.

mostrecent commented 5 years ago

I think this is a good idea. Did I get you right, it's not yet implemented, so even I'd give pass 'option': 'animated.div', it would be ignored because of the downcase, right?

And how would I pass the Babel options in a Webpack file anyway?

Assuming we had...

module.exports = {
   mode: 'development',
   module: {
     rules: [
       {
         test: /\.js$/,
         use: {
           loader: 'babel-loader',
           options: {
             plugins: [
               'transform-react-pug',                                                                                                                                                                            
               'transform-jsx-classname-components',                                                                                                                                                              
               'transform-react-jsx'
             ]
           }
         }
       }
     ]
   }
 }

...where would you put that option?

ezhlobo commented 5 years ago

@mostrecent you understood it correctly. It's not been implemented yet, however, I'm going to do that soon.

Not quite familiar with babel-loader, but I'm thinking of this way:

use: {
  loader: 'babel-loader',
  options: {
    plugins: [
      'transform-react-pug',
      ['transform-jsx-classname-components', {
        objects: ['animated'],
      }],
      'transform-react-jsx'
    ]
  }
}
ezhlobo commented 5 years ago

@mostrecent I made an attempt to make the fix, but it looks like the initial assumption is wrong. If you specify objects: ['animated'] it will work as expected:

pug`
  animated.Div
  animated.div
`
<animated.Div />
<animated className="div" />

There are several ways to make it work like we need:

  1. When objects option is specified, we will always treat the first classname as property name when these objects are tag names.

    - input -
    animated.div.test
    
    - output pugjs -
    <animated className="div test" />
    
    - output this plugin -
    <animated.div className="test" />

    We need to rely on the order of classNames.

  2. We can add new option to control what classNames should be transformed. For example we will ask to transform div as field name when it's for animated:

    - input -
    animated.first.div.test
    
    - output pugjs -
    <animated className="first div test" />
    
    - output this plugin -
    <animated.div className="first test" />

    The configuration is very hard in this case.

  3. We can add some logic, for example we can specify pairs what we want to treat as objects and property. For example pass animated.div to this option:

    - input -
    animated.first.div.test
    
    - output pugjs -
    <animated className="first div test" />
    
    - output this plugin -
    <animated.div className="first test" />

    The implementation is hard and the plugin will take more time to provide ready bundle.

I like the first option most, but I'd like to think about that a little. @mostrecent let me know if you have preferences as well ;).

mostrecent commented 5 years ago

@ezhlobo thanks for your ideas and sorry for my delayed reply. My gut feeling tends also to opt for the first solution. 2 and 3 would give us flexibility at the cost of a cumbersome config (2) and transpiling speed (3).

I need also to let it sink a bit. I don't know how often libs are going this way like react-spring did or if this is rather just an edge case...