sveltejs / svelte

Cybernetically enhanced web apps
https://svelte.dev
MIT License
77.46k stars 4.04k forks source link

When processing Nested CSS the `ownSemicolon` flag in the PostCSS AST is set to true for rules with nodes. #9320

Open romainmenke opened 8 months ago

romainmenke commented 8 months ago

Describe the bug

re-post of : https://github.com/csstools/postcss-plugins/issues/1150

I am submitting this bug report after it was filed in postcss-nesting by @AlbertMarashi. I am a maintainer of postcss-nesting, I am not the author of the reproduction. I do not use Svelte, Vite, CSS modules, ... so I don't really know much about the repro or what the current best practices are in Svelte for CSS.

What I did :

This logs :

Rule
  selector   : div.svelte-15dw1hl.foo
  index      : 1
  nodes      : 1
  raw        : {"between":" ","semicolon":true,"after":"\n    ","ownSemicolon":";"}
  input.from : src/routes/+page.svelte?svelte&type=style&lang.css

For a regular rule "ownSemicolon":";" should not be present. This is not added by postcss-nesting.

Because I don't know anything about Svelte I am also unsure which parts might be responsible.

I know that currently there isn't really support for CSS Nesting in Svelte. So maybe good to test for this case when support is rolled out.

https://github.com/sveltejs/svelte/issues/8587

Bug description

Semicolons being added after } blocks using css nesting, leading to invalid CSS (semicolons not valid after } block)

Source CSS

button {
    display: flex;
    border: 1px solid var(--dark);
    width: 100%;
    justify-content: center;
    height: 100%;
    align-items: center;
    gap: 8px;
    padding: 4px 8px;
    font-size: 14px;
    font-weight: 500;
    &.selected {
        background: rgba(var(--brand-rgb), 0.1);
    }
    &:first-child {
        border-radius: 50px 0 0 50px;
    }
    &:last-child {
        border-radius: 0 50px 50px 0;
    }
}

Expected CSS

button.s-gwue9lYI_bHl{display:flex;border:1px solid var(--dark);width:100%;justify-content:center;height:100%;align-items:center;gap:8px;padding:4px 8px;font-size:14px;font-weight:500;}button.s-gwue9lYI_bHl.selected {
        background: rgba(var(--brand-rgb), 0.1);
    }button.s-gwue9lYI_bHl:first-child {
        border-radius: 50px 0 0 50px;
    }button.s-gwue9lYI_bHl:last-child {
        border-radius: 0 50px 50px 0;
    }.s-gwue9lYI_bHl{}

Actual CSS

button.s-gwue9lYI_bHl{display:flex;border:1px solid var(--dark);width:100%;justify-content:center;height:100%;align-items:center;gap:8px;padding:4px 8px;font-size:14px;font-weight:500;}button.s-gwue9lYI_bHl.selected {
        background: rgba(var(--brand-rgb), 0.1);
    };button.s-gwue9lYI_bHl:first-child {
        border-radius: 50px 0 0 50px;
    };button.s-gwue9lYI_bHl:last-child {
        border-radius: 0 50px 50px 0;
    }.s-gwue9lYI_bHl{}

Reproduction

https://github.com/AlbertMarashi/postcss-nesting-bug

Logs

N/A

System Info

N/A

Severity

not even an annoyance

AlbertMarashi commented 8 months ago

Thanks @romainmenke

ai commented 7 months ago

Small PostCSS plugin to fix the problem as a temporary solution:

module.exports = {
  postcssPlugin: 'svelte-nesting-css-fixer',
  Rule(rule) {
    delete rule.raws.ownSemicolon
  }
}
jangxyz commented 7 months ago

Small PostCSS plugin to fix the problem as a temporary solution:

What a perfect timing! I can live up with this until it gets merged. Thanks!

// postcss.config.cjs
const nested = require('postcss-nested');

const svelteNestingCssFixer = {
  postcssPlugin: 'svelte-nesting-css-fixer',
  Rule(rule) {
    delete rule.raws.ownSemicolon
  }
};

const config = {
  plugins: [
    nested, 
    svelteNestingCssFixer,
  ],
};

module.exports = config;