Skip to content
This repository has been archived by the owner on May 14, 2021. It is now read-only.

interpolate tagging for media queries? #202

Open
gex opened this issue Jul 2, 2018 · 6 comments
Open

interpolate tagging for media queries? #202

gex opened this issue Jul 2, 2018 · 6 comments

Comments

@gex
Copy link

gex commented Jul 2, 2018

hello,

i try to lint my styled components with stylelint order plugin and i don't know how to tag my tagged template literals i use for media queries.

my example component:

const Button = styled.button`
  width: 100%;

  ${desktop`
    width: auto;
  `};
`

for this i get an Expected -styled-mixin0 to come before width error. as far as i understand i need something like ${/* sc-block */ desktop``} but it didn't help.

i can solve this by something like ${/* sc-custom '@media screen{a{top:1}}' */ desktop``} ('@media screen {}' would be an empty block so i need a as a short selector and top as a short property) but it looks stupid and i'd like to avoid comments like this.

is it possible to declare my own tags somehow? or do you know a better solution?

@emilgoldsmith
Copy link
Member

Ahhh, okay, the thing is what sc-block does is replace your interpolation with styled-mixin (which is also what our processor guesses is the right thing to do, so it's the same with or without the tag for now). I'm afraid that we do not support making your own blocks as of right now, and the best we offer is exactly the custom tag. So I see two possible solutions for you:

  1. Use the custom tag, disable the order plugin, or order your interpolations at the place the linting rule wants you to even though it's not the intended place, basically make do with what you already have
  2. Add the feature you request, I don't actually think it should be way too hard, you could just add a config option that is an object with keys being the tag and values being what the tag should be replaced with. And then just a small refactor of this https://github.com/styled-components/stylelint-processor-styled-components/blob/master/src/utils/tagged-template-literal.js#L49-L111 so that it's a map with a special case for the custom tag maybe. Really shouldn't be too bad.

I'll tag this as an enhancement now, but if you can't be bothered implementing it feel free to close the issue.

@chinesedfan
Copy link
Member

@gex I think sc-custom has given you the ability to declare anything that need to be replaced with. For you example, how about simply disable the linting of interpolation by /* stylelint-disable */ and recover by /* stylelint-enable */?

const Button = styled.button`
  width: 100%;
  
  /* stylelint-disable */
  ${desktop`
    width: auto;
  `};
  /* stylelint-enable */
`

@gex
Copy link
Author

gex commented Jul 2, 2018

@chinesedfan i was under the impression that the css rules inside my desktop interpolations are linted by stylelint. i had some issues with syntax highlighting in atom and i fixed that with these steps. now i understand it wasn't about syntax highlighting only.

@emilgoldsmith i'm gonna try to add a pull request but it would be nice to solve this other issue at once. having this code

const Button = styled.button`
  width: 100%;

  ${props =>
    props.danger
      ? css`
          background: red;
          color: white;
        `
      : '' /* sc-custom 'zoom: 1' */};

  ${desktop`
    width: auto;
  ` /* sc-custom '@media (min-width: 75rem) { a { top: 1; } }' */};
`

stylelint understands what's inside css related to the danger prop but it doesn't know anything about what's inside the desktop interpolation. when i first read about interpolation tagging i assumed that's what sc-block does, instructing stylelint that it should check the template as well. is it possible to force the linting of a template content somehow? i think this sc-media we are talking about should also do that. what do you think?

@emilgoldsmith
Copy link
Member

Hmm I'm not sure I understand the details of what you're saying @gex but I'll clarify something I'm not sure whether you understand or not:

Our processor doesn't evaluate any Javascript whatsoever, it just reads your file as a static text file and parses the meaning of the Javascript without any evaluation and tries to extract the CSS to give to Stylelint so it can lint it. That means that we don't understand anything whatsoever inside any interpolation, as interpolations are javascript. Our processor just tries to replace interpolations with dummy CSS that won't make any stylelint errors but we will never be able to actually lint the contents of an interpolation. Then we'd need to follow imports and all kinds of crazy things, and it would suddenly possibly become very expensive in terms of RAM and CPU just for a linter,

@gex
Copy link
Author

gex commented Jul 2, 2018

@emilgoldsmith linting was always magical for me so thank you for making it more clear! :)

let me rephrase my questions. i'd like to solve two problems:

  1. i'm using the stylelint order plugin and i didn't know how to tell the processor that my interpolation is a media query. i can move my mixin into the properties to keep the alphabetical order but that's not readable in my opinion or i can use the sc-custom tag but it feels painful for me because i have to provide a valid, not empty media query to prevent linting errors. and because of the length of that tag i think it would be great to have an sc-media tag. i haven't run into other cases where it would be beneficial to know that the interpolation is a media query but since there are several other stylelint rules that are related to media queries i think i or other people maybe will :)
// instead of this
const A = styled.a`
  color: blue;

  ${desktop`
    color: lightblue;
  ` /* sc-custom '@media screen { a { top: 1; } }' */}
`

// i'd prefer this
const A = styled.a`
  color: blue;

  ${/* sc-media */ desktop`
    color: lightblue;
  `}
`
  1. i understand that the processor is just extracting the css code to give it to stylelint, that's how it understands what's inside a css interpolation but sometimes other interpolations also can contain a huge chunk of css and in these cases it would be great to be able to instruct the processor to extract that css as well. a proposed solution would be an sc-css tag:
// this doesn't have stylelint errors at the moment
const A = styled.a`
  color: blue;

  ${desktop`
    kolor: lightblue;
    text-align: centaur;
  `}
`

// this would have
const A = styled.a`
  color: blue;

  ${/* sc-css */ desktop`
    kolor: lightblue;
    text-align: centaur;
  `}
`

but since we know what could contain css, and i mean lintable css (sc-block and sc-media maybe sc-declaration?) and what not (sc-selector, sc-property and sc-value) an intelligent guessing would imply sc-css for the former.

edit: ...aaaand i just found #182 😇

@emilgoldsmith
Copy link
Member

I don't think we will ever support extracting anything from an interpolation to be honest, it'll be very hard to generalize it without evaluating CSS. I guess one could make a specific tag for breakpoints since it's a reocmmended SC pattern, and wraps it in a media query. It could then recurse on the TTL inside the interpolation. It would be a pretty custom case though, and not sure if enough users want it to support it? Maybe?

I'm completely okay with as I said above allowing a config option that can let you define your own tags as shortcuts, I think that could make some people's life quite a bit easier so you don't have to write the ugly custom tags.

Also beware though that processor support may be deprecated stylelint/stylelint#3408

and you might want to consider contributing to https://github.com/gucong3000/postcss-jsx instead

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

No branches or pull requests

3 participants