sveltejs / language-tools

The Svelte Language Server, and official extensions which use it
MIT License
1.21k stars 196 forks source link

Support for PostCSS validation #305

Closed gavinmcfarland closed 4 years ago

gavinmcfarland commented 4 years ago

Is your feature request related to a problem? Please describe. It would be great if when writing PostCSS style syntax the file was not marked as invalid, or show an error.

Describe the solution you'd like In particular when you nest CSS Rules Svelte shows an error saying it expects an identifier. The PostCSS Language Support plugin supports modern and experimental syntax highlighting. It would be great is the Svelte language plugin support the same features.

Describe alternatives you've considered I've considered and tries using the language attribute scss but this is technically incorrect as I am not using Sass.

Additional context Here is a screenshot of an example of where Svelte complains about the syntax. Notice the squiggly red lin under the &:hover rule. image.

jasonlyu123 commented 4 years ago

The extension you mention only supply syntax highlight. And it seems like it's injecting syntax rules to css. So As long as you have the extension installed, It 'll also enhance the css highlight on your svelte file.

As for the error, there are two sources for it. One is svelte compiler, we use it to provide svelte specific diagnostic, you would have to set up the necessary preprocessor. you can follow the instruction here

The second source is the vscode CSS language service we used. You can disable it by setting

svelte.plugin.css.diagnostics: false
jasonlyu123 commented 4 years ago

We are not planning on provide validation for postcss specific syntax now. So if you want to validate the postcss, you can install other extensions and setting it to treat svelte file as HTML.

Another thing about the extension you mentioned. If you want to use it to provide syntax highlight for your svelte file don't set lang=postcss attribute on style if not necessary because it inject the syntax to css.

gavinmcfarland commented 4 years ago

Hi, thanks for your comments. I referenced the PostCSS Language extension to show the features which it checks for and allows for as they are likely to be the same features you would check for error validation. The syntax highlighting is working fine with this plugin.

When you say I would have to setup the necessary preprocessor, do the instructions you linked to also apply to PostCSS? I'm assuming it's the svelete.config.js file that's important. I'm using sapper so do I have to create this file and set my preprocessor in this file and import it into rollup.config.js in order for the Svelte Language tools to understand PostCSS?

I'll try what you suggested. I know you don't plan on supporting PostCSS validation but obviously I would love support for it without having to disable all CSS validation. Thanks for helping and listening!

jasonlyu123 commented 4 years ago

Yes it also applies to postcss. Because the language server use the compiler to get the warning and errors so it also needs to know how to preprocess. Thesvelte.config.js is for the language server to know that.

gavinmcfarland commented 4 years ago

Hi @jasonlyu123 I just wanted to let you know that I created a svelte.config.js file and it didn't have any effect, also sharing this for other people so they are aware. It would be useful to know what the svelte language server looks for to determine what it needs to understand the language; I can't tell just from the example provided.

This is my preprocess configuration:

const sveltePreprocess = require('svelte-preprocess');
const phtmlUtilityClass = require('phtml-utility-class');

const preprocess = sveltePreprocess({
    postcss: true,
    pug({ content, filename }) {
        const code = pug.render(content)
        return { code, map: null }
    }
});

const myPreprocessor = {
    markup({ content, filename }) {
        content = content.replace(/(\<[^>]*=)(\{[^{}]*\})([^<]*\>)/gmi, (match, p1, p2, p3) => {
            return `${p1}"${p2}"${p3}`
        })
        return phtmlUtilityClass.process(content, { from: filename }).then(result => {
            return { code: result.html, map: null }
        });
    }
}

module.exports = {
    preprocess: [
        preprocess,
        myPreprocessor
    ],
};
dummdidumm commented 4 years ago

Arrays of preprocessors are not supported yet #279

gavinmcfarland commented 4 years ago

Thanks for that. I just checked to see if even when not using an array if it would make a difference and it doesn't. So just feeding back for yourself and others who might find this issue, that this has no effect on remedying the validation errors.

const sveltePreprocess = require('svelte-preprocess');
const phtmlUtilityClass = require('phtml-utility-class');

const preprocess = sveltePreprocess({
    postcss: true,
    pug({ content, filename }) {
        const code = pug.render(content)
        return { code, map: null }
    }
});

module.exports = {
    preprocess
};
jasonlyu123 commented 4 years ago

@limitlessloop Can you check the output window of vscode chose svelte and see if there are any errors? Also, can you provide your postcss config? I never manual setup postcss before.

gavinmcfarland commented 4 years ago

Hi @jasonlyu123. Thanks for your reply.

Below is the output:

Initialize language server at  /Users/limitlessloop/Sites/stancy/website
Trying to load config for /Users/limitlessloop/Sites/stancy/website/src/components/Button.svelte
Found config at  /Users/limitlessloop/Sites/stancy/website/svelte.config.js
Initialize new ts service at  
SnapshotManager File Statistics:
Project files: 0
Svelte files: 0
From node_modules: 0
Total: 0
Using Svelte v3.23.2 from /Users/limitlessloop/Sites/stancy/website/node_modules/svelte/compiler
Using Svelte v3.23.2 from /Users/limitlessloop/Sites/stancy/website/node_modules/svelte/compiler

And below is my PostCSS config

module.exports = {
    plugins: {
        'postcss-import': {},
        'postcss-logical': {},
        'postcss-preset-env': {
            autoprefixer: {
                flexbox: 'no-2009',
            },
            stage: 3,
            features: {
                'nesting-rules': true,
                'custom-properties': false,
            }
        },
    }
};

And this is the example code:

image

jasonlyu123 commented 4 years ago

What's the error message? I follow your config and the svelte error is gone only the error from vscod-css-language-service is left.

gavinmcfarland commented 4 years ago

Hmm. 🤔

These are the errors I get.

} Expected
at-rule or selector expected
CleanShot 2020-07-14 at 15 16 02@2x
jasonlyu123 commented 4 years ago

yup. that's the validation error by vscode-css-language-service. You can either add lang="postcss" attribute to the style to disable the css validation on this file or turn it off in the workspace by set svelte.plugin.css.diagnostics: false.

gavinmcfarland commented 4 years ago

I see, I wasn't clear on what you meant by svelte error.

Are we getting our wires crossed? I get you can turn it off, but then what was the point of adding the svelte.config.js file just to turn it off?

Also the thing with adding lang="postcss" to the style tag is that it then loses syntax highlighting, your advice earlier was not to add the lang attribute. Also PostCSS is not like other preprocessor in the respect that it's not a language itself, but merely a tool which can be used to support modern CSS so, in my opinion, it shouldn't need to have the lang attribute.

Anyway I'd like to understand how it works (the root of why the errors appear) then at least maybe I can talk to the PostCSS community or the maker of the PostCSS Language Support extension regarding support in Svelte files.

jasonlyu123 commented 4 years ago

The svelte compiler compiles the css. So when it encounters the syntax that it doesn't understand it would throw a parser error. That's what I meant about svelte error.

The svelte.config.js tell the language server to use this preprocess config to preprocess before compile. https://github.com/sveltejs/language-tools/blob/17bfd6e27fd8a6cbc6f417eb184bc7d0b1dac727/packages/language-server/src/plugins/svelte/SvelteDocument.ts#L79 So it adding svelte.config.js isn't suppressing the error.

The vscode-css-language-service error I mentioned is here https://github.com/sveltejs/language-tools/blob/17bfd6e27fd8a6cbc6f417eb184bc7d0b1dac727/packages/language-server/src/plugins/css/CSSPlugin.ts#L72 We use it to analyze the css only. But this module doesn't support the syntax you use so it throws a parser error as well. As you can see in the code. We'll skip the validation if the style's kind is postcss. That's why I said you can set the attribute. But the syntax highlight extension you mention before injecting to css, not postcss. So as long as you set the attribute the syntax highlight would be off. That's why I suggest avoid that if you want to use the extension to provide syntax highlight. Or you can find another alternative.

But as you said. A lot of postcss features are proposal syntax. It doesn't make sense to have to add a lang attribute. Maybe we could add another way to turn off the per file CSS validation.

gavinmcfarland commented 4 years ago

Thanks @jasonlyu123.

But this module doesn't support the syntax you use so it throws a parser error as well

By this module, are you referring to the PostCSS module? If so is it worth me talking with the author to see if anything could be done to support this? It seems to me if the Svelte Language Tools uses a config to preprocess before compile to analyze the CSS, then it would make sense that the PostCSS module it's using should support the syntax which it's throwing an error for?

jasonlyu123 commented 4 years ago

no, it's the vscode-css-language-service. They use their own parser and analysis. And they have no plan support css next.

gavinmcfarland commented 4 years ago

I see, thanks for confirming and your patience.

jasonlyu123 commented 4 years ago

Maybe you can use stylelint instead?

jaikme commented 4 years ago

Well, I just add the "svelte.plugin.css.diagnostics.enable": false to disable the error, but didn't work.

image image

I think my svelte.config.js is configured right

const SveltePreprocess = require('svelte-preprocess');
module.exports = {
  preprocess: SveltePreprocess({
    "defaults": {
      "script": "typescript",
      "style": "postcss" // Tried pcss too
    },
    "postcss": true
  }),
};

I'm using the PostCSS Language Support VSCode Extension. When I use lang="scss" or lang="less" (as it was suggested), the error mark gone. But with lang="pcss" ou lang="postcss" (even with the diagnosis disabled) does not work... Also, from Svelte output I got:

jasonlyu123 commented 4 years ago

@jaikme how do you config postcss? As far as I know, postcss require settings and your settings don't seems to be picked up by our instance of the preprocessor. So this is a separate issue, it's not related to the original post.

jaikme commented 4 years ago

@jasonlyu123 Ok. Here is my config. image image

dummdidumm commented 4 years ago

There are two parts to it - getting it to work for the build, and getting it to work for the VSCode extension. See the docs on how to setup PostCSS. I'm going to close this issue for now, but if anything is still unclear, let us know or - even better - create a PR with documentation enhancements.

We will very unlikely add support for advanced css features such as new CSS syntax or TailwindCSS because this will become a maintenance burden. There are many other good VSCode extension out there which do a great job at providing the advanced features and can be used together with the Svelte extension.