hudochenkov / postcss-styled-syntax

PostCSS syntax for CSS-in-JS like styled-components
MIT License
69 stars 4 forks source link

Parsing Issue in 0.6.X #27

Closed eMerzh closed 6 months ago

eMerzh commented 6 months ago

Hello,

trying to upgrade to 0.6.2 (from 0.5)

We got a new issue on this code (via stylelint)

@media ${MQ.isMinTablet} {
        flex-direction: row;
        align-items: center;
        max-width: ${theme.variables.layout.classic.width.px};
        margin: 0 auto;
        padding-top: 0;
        padding-bottom: 0;
        width: 100%; /** IE11 hack to keep things as they need /o\ */
    }

63:57 βœ– Missed semicolon CssSyntaxError

(line 63 beeing max-width)

can you help us make it work?

Thanks :)

MattIPv4 commented 6 months ago

πŸ‘‹ Wasn't sure whether to create an issue or post here, but I suspect upgrading from 0.5 to 0.6.2 was also the cause of this issue we ran into:

  &:hover {
    ${props => !props.selected && `background: ${colors.blue};`}
    ${props => !props.selected && `box-shadow: 0 5px 20px -5px ${colors.blueShadow};`}

    p {
      ${props => !props.selected && `color: ${colors.white};`}
    }
  }
95:5: Unexpected empty line before rule (rule-empty-line-before) [error]

Line 95 is the empty line before the p {

hudochenkov commented 6 months ago

@eMerzh thank you for the report! Fixed in 0.6.3.

@MattIPv4 this works correctly. Previous versions were incorrectly parsing such case. Since v0.6.0 it is parsed correctly. So you need to update Stylelint configuration, and use except: ['first-nested'] or ignore: ['first-nested'] for rule-empty-line-before.

MattIPv4 commented 6 months ago

I'm not sure I follow how that rule would address this?

I would expect these two to both be treated the same:

  &:hover {
    background: ${colors.blue};

    p {
      color: ${colors.white};
    }
  }
  &:hover {
    ${props => !props.selected && `background: ${colors.blue};`}

    p {
      color: ${colors.white};
    }
  }

Yet, since v0.6 the second now throws an error?

eMerzh commented 6 months ago

awesome thanks for your work πŸ™Œ it works like a charms :)

hudochenkov commented 6 months ago

@MattIPv4 the second example in 0.5.0- incorrectly parsed as a rule with selector:

${props => !props.selected && `background: ${colors.blue};`}

    p

Instead of a rule with a selector p. Since 0.6.0 it is parsed correctly.

CSS-in-JS is a strange beast. We're using tools to work with it, which are built for completely different language β€” CSS. CSS does not have interpolations. This piece ${props => !props.selected &&background: ${colors.blue};} is not CSS. So with postcss-styled-syntax we try to adapt CSS-in-JS, which is not a true CSS, to work as much as possible with tools, which work only with CSS. Examples of such tools, are PostCSS and Stylelint, which is built on top of PostCSS.

Things like ${whatever} are not part of Abstract Syntax Tree, that PostCSS could generate. Because there is no equivalent in CSS language. The best we can do is to β€œhide” such pieces from CSS, so Stylelint has at least some changes to be helpful with CSS-in-JS.

So this examples:

&:hover {
    ${props => !props.selected && `background: ${colors.blue};`}

    p {
      color: ${colors.white};
    }
  }

PostCSS (and Stylelint) sees as:

&:hover {

    p {
      ...
    }
  }

Well, not exactly like this, but it shows close representation. Now you could see why rule-empty-line-before shows a warning now.

MattIPv4 commented 6 months ago

Ah okay, I didn't realise interpolations were completely removed from the tree, but with that context it does make sense why this is happening. Ty!