Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new option: attributeAlias #122

Open
wants to merge 5 commits into
base: master
Choose a base branch
from

Conversation

shirohana
Copy link
Contributor

I made a new option to solve #111, this option grant everyone can decide which syntax to use between:

pug`div( class="box" )`

and

pug`div( className="box" )`

But before that, I must implement expressional className so I can make attributeAlias works correctly.

This pull request brings two features in actual:

  • New plugin option attributeAlias
  • Implement expressional className

Usage

babel.config.js
{
  plugins: [
    // or shorthand:
    // ["transform-react-pug", {
    ["babel-plugin-transform-react-pug", {
      attributeAlias: {
        class: 'className'
      }
    }]
  ]
}

With attributeAlias: { class: 'className' } set, you can now write expressions inside class again just like the native syntax of Pug:

Changes

1. Allow expression and array

*Pug allows pass array as class attribute natively.

const darkMode = true

const A = pug`
  div.box( class=("is-large " + (darkMode ? "is-dark" : "")) )
`

const B = pug`
  div.box( class=${`is-large ${darkMode && "is-dark" : ""`} )
`

const C = pug`
  div.box( class=["is-large", darkMode && "is-dark"] )
`

All renders to: (ignore there's extra spaces in A and B)

<div className="box is-large is-dark" />

2. Correct syntax of className

*Also see: facebook/react#3138

Before:

pug`
  div( class=100 )
  div( class=["A", "B"] )
`
// => <div className={100} />
// => <div className={["A", "B"]} />

After:

pug`
  div( className=100 )`
  div( class=["A", "B"] )
`
// => <div className="100" />
// => <div className="A B" />

3. ClassName interpolation

import $ from './style.css'

const A = pug`div( class=$.Box )`
// => <div className={$.Box} />

const B = pug`div( class=[$.Box, $.isLarge ] )`
// => <div className={`${$.Box} ${$.isLarge}`} />

const C = pug`div( class=["class-1", "class-2"] )`
// => <div className="class-1 class-2" />

const D = pug`div( class=["class-1", $.InterpolateClass, "class-2"] )`
// => <div className={`class-1 ${$.InterpolateClass} class-2`} />

4. Default alias (❗Breaking Change)

Now we don't parse there attributes in initiative:

  • for => htmlFor
  • maxlength => maxLength

To make it works like before, create aliases in your babelrc:

babel.config.js
{
  plugins: [
    ["babel-plugin-transform-react-pug", {
      attributeAlias: {
        for: 'htmlFor',
        maxlength: 'maxLength'
      }
    }]
  ]
}

Question:

Is it a good idea that make class and for alias in default?

5. Limitation

Currently array spread operators are ignored, here's some sample:

const classes = ["class-1", "class-2"]

pug`
  div.box( classes=["class-1", "class-2"] )
`
// => <div className="box class-1 class-2" />

pug`
  div.box( classes=classes )
`
// => <div className={`box ${classes}`} />

pug`
  div( class=["box", ...classes] )
`
// => <div className="box" /> // ...ignored

More about attributeAlias

With this option, you can even do more than just classNames.

For example, you can create shorthands like that:

babel.config.js
{
  plugins: [
    ["babel-plugin-transform-react-pug", {
      attributeAlias: {
        "@click": 'onClick',
        "@change": 'onChange',
        "@value": 'defaultValue',
        "@html": 'dangerouslySetInnerHTML'
      }
    }]
  ]
}

And feel the power:

pug`
  button( @click=handleClick )
    | Button
`
// => <button onClick={handleClick}>Button</button>

pug`
  input( @change=setEmail, @value=email )
`
// => <input onChange={setEmail} defaultValue={email} />

pug`
  svg( @html={ __html: svgContentText } )
`
// => <svg dangerouslySetInnerHTML={{ __html: svgContentText }} />

@codecov-commenter
Copy link

Codecov Report

Merging #122 into master will increase coverage by 0.97%.
The diff coverage is 90.90%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #122      +/-   ##
==========================================
+ Coverage   87.14%   88.12%   +0.97%     
==========================================
  Files          21       21              
  Lines         459      480      +21     
  Branches      112      112              
==========================================
+ Hits          400      423      +23     
+ Misses         53       51       -2     
  Partials        6        6              
Impacted Files Coverage Δ
src/context.js 88.46% <ø> (ø)
src/index.js 100.00% <ø> (ø)
src/visitors/Tag.js 94.82% <90.00%> (+6.30%) ⬆️
src/utils/get-class-name-value.js 91.07% <91.07%> (+0.44%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0cb224b...d8ef7b9. Read the comment docs.

@shirohana
Copy link
Contributor Author

Any response (´・ω・`)?

@skotchpine
Copy link

This is brilliant. Good job!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants