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

usage with styled-jsx and styles #103

Open
conarwelsh opened this issue Jun 20, 2019 · 11 comments
Open

usage with styled-jsx and styles #103

conarwelsh opened this issue Jun 20, 2019 · 11 comments

Comments

@conarwelsh
Copy link

I am using Next.js, and would like to use Pug instead of JSX, and Stylus instead of normal CSS. However I am running into some headaches. Maybe you can spot a simple mistake I am missing? I am guessing it is just ordering of the plugins somehow but not sure how to change that. It is an empty repo so it is simple to reproduce, its just as follows:

pages/index.js

import React from "react"

export default ({ children }) => {
  // WORKS AS EXPECTED
  return <section className="wrapper">
    <button>test</button>
    <style jsx>{`
      .wrapper
        background: blue
    `}</style>
  </section>
  
  // "WORKS" but applies all styles globally without scope
  // return pug`
  //   section.wrapper
  //     button test

  //     style(jsx).
  //       .wrapper {
  //         background: blue
  //       }
  // `

  // DOES NOT WORK AT ALL
  // return pug`
  //   section.wrapper
  //     button test

  //     style(jsx).
  //       .wrapper
  //         background: blue
  // `
}

package.json

{
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start"
  },
  "dependencies": {
    "next": "^8.1.0",
    "react": "^16.8.6",
    "react-dom": "^16.8.6"
  },
  "devDependencies": {
    "babel-plugin-transform-react-pug": "^7.0.1",
    "styled-jsx-plugin-stylus": "^0.0.4",
    "stylus": "^0.54.5"
  }
}

babel.config.js

module.exports = {
  "presets": [
    [
      "next/babel",
      {
        "styled-jsx": {
          "plugins": ["styled-jsx-plugin-stylus"]
        }
      }
    ]
  ],
  "plugins": [
    "transform-react-pug",
  ]
}
@ezhlobo
Copy link
Member

ezhlobo commented Jun 21, 2019

@conarwelsh thank you for reporting this. I guess the issue is in our generator, we should combine the content of piped text into TemplateLiteral.

Will check out deeper and let you know the results ;)

@ezhlobo
Copy link
Member

ezhlobo commented Jun 21, 2019

Proposed Solution

Combine tokens between start-pipeless-text and end-pipeless-text to one text token.

Then transform text token with multiline values into Template Literal inside JSXExpressionContainer.

Problem

So, when we give input like this

style.
  .wrapper {
    color: red;
  }

It generates these tokens for pug text:

{ type: 'start-pipeless-text', ... }

{ type: 'text', ... ,
  val: '.wrapper {' }

{ type: 'newline', ... }

{ type: 'text', ... ,
  val: '  color: red;' }

{ type: 'newline', ... }

{ type: 'text', ... ,
  val: '}' }

{ type: 'newline', ... }

{ type: 'text', ... ,
  val: '' }

{ type: 'end-pipeless-text', ... }

When we map these tokens to JSX we get something like this:

{ type: 'JSXText',
  value: '.wrapper {' }

{ type: 'JSXExpressionContainer',
  expression: { 
    type: 'StringLiteral',
    value: '\n' } }

{ type: 'JSXExpressionContainer',
  expression: { 
    type: 'StringLiteral',
    value: '  color: red;' } }

{ type: 'JSXExpressionContainer',
  expression: { 
    type: 'StringLiteral',
    value: '\n' } }

{ type: 'JSXText',
  value: '}'}

{ type: 'JSXExpressionContainer',
  expression: { 
    type: 'StringLiteral',
    value: '\n' } }

{ type: 'JSXText',
  value: ''}

To make it work it should return something like this:

{ type: 'JSXExpressionContainer',
  expression: {
    type: 'TemplateLiteral',
    quasis: [{
      type: 'TemplateElement',
      value: '\n .wrapper {\n background: blue\n }\n '
    }] } }

Might be a bit different, picked that from astexplorer: https://astexplorer.net/#/gist/3fc6bec2eea654d23e0d4e7683cce74e/dc5a0bc575151295e7cbe5c5341172dc0d78cf89

@ezhlobo
Copy link
Member

ezhlobo commented Jun 21, 2019

@conarwelsh I'm gonna take care about this soon, but it will take some time. I assume to deliver this by Tuesday (I hope earlier though).

@ezhlobo
Copy link
Member

ezhlobo commented Jun 22, 2019

@conarwelsh well, it might take more time than I expected due to personal circumstances. In the meantime you can apply a workaround:

styled(jsx) ${`
  .wrapper {
    background: blue
  }
`}

styled(jsx) ${`
  .wrapper
    background: blue
`}

See how it will be transformed

@stefan-contiero
Copy link

Hello! Similar situation here: I tried to use Pug and integrate external CSS and styles outside of the component, without luck in both cases. I believe the problem is related/smiliar to this issue.
I also gave a try the workaround proposed by @ezhlobo without any success.

@ezhlobo
Copy link
Member

ezhlobo commented Jul 30, 2019

@2mittens hm, external styles should not be affected this plugin. Will it be possible for you to provide a repository or example on any sandbox where I can see the reproduced issue?

@stefan-contiero
Copy link

stefan-contiero commented Jul 30, 2019

@2mittens hm, external styles should not be affected this plugin. Will it be possible for you to provide a repository or example on any sandbox where I can see the reproduced issue?

Sure, you can find a simple example here: https://github.com/2mittens/pug-external-styled-jsx
There are two pages: / and /working, the first one in pug, and the other one is the same page but with JSX.

Let me know if you need anything else, thank you!

@stefan-contiero
Copy link

Quick update, I found an obvious workaround to make external styles work with pug while also taking advantage of styled-jsx scoping:

import React from 'react';

import styles from './example.css';

const ExampleComponent = () => {
  // wrap pug in JSX
  return (
    <> {
      pug`
        .your-pug-template
      `
    }
    <style jsx>{styles}</style>
    </>
  )
};

export default ExampleComponent;

@davidtai
Copy link

davidtai commented Aug 26, 2019

The style(jsx) inside of a pug template isn't executed by the styled-jsx reader. You should get a jsx-1234 class on the root tag (sibling tags in case of a fragment) and all child tags and the contents of the style tag should be moved to an aggregate style tag.

It seems like whatever is happening is due to the style-jsx logic executing after the pug transform. This seems to be a much larger issue than that the original author is reporting. Quite simply, these two plugins don't seem to work with each other at all.

You can test with @stefan-contiero's example.

@teetlaja
Copy link

Any news about this issue?

@ezhlobo
Copy link
Member

ezhlobo commented Sep 21, 2020

@teetl6 unfortunately there is no updates.

I'd like to discuss others' possible implementations or any code contribution regarding this problem...

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

No branches or pull requests

5 participants