ls-age / svelte-preprocess-sass

Svelte preprocessor for sass
91 stars 6 forks source link

Using the indented syntax option doesn't seem to work with Svelte's global selectors. #49

Closed elliotwaite closed 5 years ago

elliotwaite commented 5 years ago

When I try to use Sass's indented syntax option with one of Svelte's global selectors, I get an error.

rollup.config.js (using Sapper):

import { sass } from "svelte-preprocess-sass";

const sassOptions = {
  indentedSyntax: true
}

// Client:
svelte({
        dev,
        hydratable: true,
        emitCss: true,
        preprocess: {
          style: sass(sassOptions)
        }
}),

// Server
svelte({
        generate: "ssr",
        dev,
        preprocess: {
          style: sass(sassOptions)
        }
}),

component.svelte

<style type="text/sass">
:global(body)
  background: red
</style>

When I call npm run dev I get this error:

✗ server
Invalid CSS after "": expected 1 selector or at-rule, was "global(body): {"
✗ client
Invalid CSS after "": expected 1 selector or at-rule, was "global(body): {"

Any suggestions?

LukasHechenberger commented 5 years ago

Took some time to find this one 😄

The problem is, that it's invalid sass... There's nothing I can do about it, I'd advise you to write scss instead. You could also create an issue in the svelte repo.

elliotwaite commented 5 years ago

Yeah, was hoping there might be some way to make this plugin recognize the Svelte :global(...) selector and do something special to make it work, but perhaps there will be a better way to solve this issue. I've opened an issue on svelte: https://github.com/sveltejs/svelte/issues/2920

One idea I'm trying to get to work is just using scss for when I want to use global selectors, and sass otherwise. But for some reason this isn't working.

rollup.config.js

...
preprocess: [
  {
    style: sass({indentedSyntax: true}, {type: 'text/sass'}),
  },
  {
    style: sass({}, {type: 'text/scss'}),
  },
],
...

App.svelte:

<style type="text/sass">
h1
  color: purple
</style>

<style type="text/scss">
:global(h1) {
  background: red;
}
</style>

<h1>Hello world!</h1>

Error message:

1: <style type="text/sass">
2: h1
3:   color: purple
           ^
4: </style>
5:
ParseError: Identifier is expected

Any suggestions for where I'm going wrong with this idea?

LukasHechenberger commented 5 years ago

Well, only one <style> element is supported in svelte, so I guess you'll have to use scss anyway...

But you actually stumbled over an issue in rollup-preprocess-svelte, where multiple preprocessors are currently not supported. I fixed this one, and created a corresponding PR. Once this one is merged you'll get the right error message:

$ npx rollup -c
index.js → public/bundle.js...
[!] (svelte plugin) ParseError: You can only have one top-level <style> tag per component
App.svelte
3: </style>
4: 
5: <style type="text/scss">
   ^
6: :global(h1) {
7:   background: red;
ParseError: You can only have one top-level <style> tag per component
    at error$1 (/Users/lukas/Downloads/gi2el/node_modules/svelte/compiler.js:13494:20)
    at Parser$2.error (/Users/lukas/Downloads/gi2el/node_modules/svelte/compiler.js:13570:10)
    at parse$2 (/Users/lukas/Downloads/gi2el/node_modules/svelte/compiler.js:13664:17)
    at compile (/Users/lukas/Downloads/gi2el/node_modules/svelte/compiler.js:23813:12)
    at preprocessPromise.then.code (/Users/lukas/Downloads/gi2el/node_modules/rollup-plugin-svelte/index.js:259:22) 
elliotwaite commented 5 years ago

Ah, got it. Didn't know about the single <style> limitation. Thanks for pointing that out.

I was wondering why adding multiple preprocessors seemed to give strange results. But yeah, looks like that PR or the other one should fix it. 👍

Thanks for the help.

elliotwaite commented 5 years ago

Just found a solution! Adding the backslash escape character \:global(...) makes it valid indented sass syntax.

<style type="text/sass">
\:global(body)
  background: red
</style>

Thanks again for helping me with this.