nuxt-modules / stylelint

Stylelint module for Nuxt.js
MIT License
66 stars 9 forks source link

Doesn't work for imported .scss files by @import #89

Open selimdoyranli opened 1 year ago

selimdoyranli commented 1 year ago

I was using nuxt2 + @nuxtjs/style-resources + @nuxtjs/stylelint-module in my previous projects. It was working fine in my previous projects. I decided to switch to nuxt3, I'm using nuxt3 + @nuxtjs/stylelint-module in a project I've just tried, but as I mentioned in the title, the module does not lint on scss files imported with @import. By the way I don't use @nuxtjs/style-resources as I can provide global scss with vite in my nuxt3 project.

In all other files, namely in .vue files, lint works as SFC, in .scss files in the components folder, in my /scss/app.scss entry point. But the lint doesn't work for the scss files I imported with the @import method in my /scss/app.scss file.


nuxt config of my nuxt3 project;

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  srcDir: '',

  vite: {
    css: {
      preprocessorOptions: {
        /*
         ** Global Styles (Do not import actual styles)
         */
        scss: {
          additionalData: `
                @import "@/assets/style/scss/functions/_center.scss";
                @import "@/assets/style/scss/functions/_triangle.scss";
                @import "@/assets/style/scss/mixins/_font.scss";
                @import "@/assets/style/scss/mixins/_gradient.scss";
              `
        }
      }
    }
  },

  /*
   ** Global Styles (Actual styles)
   */
  css: [
    // Actual styles entry point (as import management)
    '~/assets/style/scss/app.scss'
  ],

  modules: [
    [
      '@nuxtjs/eslint-module',
      {
        // eslint module options
      }
    ],
    // https://github.com/nuxt-community/stylelint-module
    [
      '@nuxtjs/stylelint-module',
      {
        include: './src/{assets/style,components,layouts,pages}/**/*.{css,sass,scss,less,stylus,vue}'
      }
    ]
  ]
})

app.scss entry point file on my project;

// Variables
@import '../css/variables/color.css';
@import '../css/variables/font-size.css';
@import '../css/variables/border-radius.css';
@import '../css/variables/box-shadow.css';
@import '../css/variables/z-index.css';
@import '../css/variables/header.css';

/*
 * Overrides
 */
// Overrides put here (e.g. bootstrap grid override, lib ui overrides)

/*
 * Vendor
 */
// Vendor put here (e.g. animate.css, normalize.css)

// Base
@import 'base/general';

// Utils
@import 'utils/state';
@import 'utils/color';

// Shared (elements with common/shared style classes)
@import 'shared/page';
@import 'shared/layout';
@import 'shared/transition';

.stylelintrc.js

module.exports = {
  extends: [
    // https://github.com/constverum/stylelint-config-rational-order
    'stylelint-config-rational-order',
    // https://github.com/shannonmoeller/stylelint-config-prettier
    'stylelint-config-prettier'
  ],
  overrides: [
    {
      customSyntax: 'postcss-scss',
      files: ['./src/{assets/style,components,layouts,pages}/**/*.{css,sass,scss,less,stylus}']
    },
    {
      customSyntax: 'postcss-html',
      files: ['./src/*.vue', './src/**/*.vue']
    }
  ],
  plugins: [
    // https://github.com/kristerkari/stylelint-scss#list-of-rules
    'stylelint-scss',
    // https://github.com/hudochenkov/stylelint-order
    'stylelint-order',
    'stylelint-config-rational-order/plugin'
  ],
  rules: {
    indentation: [
      2,
      {
        baseIndentLevel: 0
      }
    ],
    'color-named': 'never',
    'color-function-notation': 'legacy',
    'at-rule-no-unknown': null,
    'declaration-empty-line-before': [
      'always',
      {
        except: ['after-declaration'],
        ignore: ['after-comment', 'first-nested', 'inside-single-line-block'],
        severity: 'warning'
      }
    ],
    'rule-empty-line-before': [
      'always',
      {
        ignore: ['after-comment', 'first-nested'],
        severity: 'warning'
      }
    ]
  }
}

package.json

{
  "private": true,
  "scripts": {
    "dev": "nuxt dev src",
    "build": "nuxt build src",
    "start": "nuxt start src",
    "generate": "nuxt generate src",
    "preview": "nuxt preview src",
    "postinstall": "nuxt prepare src",
    "lint:eslint": "eslint --ext .js,.ts,.vue,.pug --ignore-path .gitignore --ignore-path .eslintignore .",
    "lint:eslint:fix": "eslint --fix --ext .js,.ts,.vue,.pug --ignore-path .gitignore --ignore-path .eslintignore .",
    "lint:stylelint": "stylelint --ignore-path .stylelintignore \"src/{assets/style,components,layouts,pages}/**/*.{css,sass,scss,less,stylus,vue}\"",
    "lint:stylelint:fix": "stylelint --ignore-path .stylelintignore \"src/{assets/style,components,layouts,pages}/**/*.{css,sass,scss,less,stylus,vue}\" --fix",
    "prettier": "prettier --config ./.prettierrc.js --ignore-path ./.prettierignore --write \"**/*.{js,ts,json,css,scss,vue,html,pug}\" --end-of-line crlf",
    "commit": "cz"
  },
  "lint-staged": {
    "*.{ts,js,vue}": [
      "npm run lint:eslint",
      "npm run prettier"
    ],
    "*.json": [
      "npm run prettier"
    ],
    "src/{assets/style,components,layouts,pages}/**/*.{css,sass,scss,less,stylus,vue}": [
      "npm run lint:stylelint",
      "npm run prettier"
    ]
  },
  "devDependencies": {
    "@commitlint/cli": "^17.4.2",
    "@commitlint/config-conventional": "^17.4.2",
    "@nuxtjs/eslint-config-typescript": "^12.0.0",
    "@nuxtjs/eslint-module": "^4.1.0",
    "@nuxtjs/stylelint-module": "^5.1.0",
    "@prettier/plugin-pug": "^2.4.1",
    "@typescript-eslint/parser": "^5.59.11",
    "@volar-plugins/vetur": "^0.1.0",
    "@volar/vue-language-plugin-pug": "^1.0.24",
    "commitizen": "^4.3.0",
    "cz-conventional-changelog": "^3.3.0",
    "eslint": "^8.42.0",
    "eslint-config-prettier": "^8.8.0",
    "eslint-loader": "^4.0.2",
    "eslint-plugin-nuxt": "^4.0.0",
    "eslint-plugin-prettier": "^4.2.1",
    "eslint-plugin-vue": "^9.14.1",
    "husky": "4.2.5",
    "lint-staged": "^13.1.0",
    "nuxt": "^3.5.3",
    "postcss": "^8.4.21",
    "postcss-html": "^1.5.0",
    "postcss-scss": "^4.0.6",
    "prettier": "^2.8.4",
    "pug": "^3.0.2",
    "pug-plain-loader": "^1.1.0",
    "sass": "^1.58.0",
    "sass-loader": "^13.2.0",
    "stylelint": "^14.16.1",
    "stylelint-config-prettier": "^9.0.5",
    "stylelint-config-rational-order": "^0.1.2",
    "stylelint-order": "^6.0.2",
    "stylelint-scss": "^4.4.0",
    "vue-eslint-parser": "^9.3.1",
    "vue-eslint-parser-template-tokenizer-pug": "^0.4.10"
  },
  "config": {
    "commitizen": {
      "path": "cz-conventional-changelog"
    }
  }
}

My nuxt3 project and doesn't work on this, check link for the directory structure on my project:

https://stackblitz.com/github/selimdoyranli/nuxt3-boilerplate-issue

In addition my nuxt2 project and it works on this https://stackblitz.com/github/selimdoyranli/nuxt2-boilerplate

algora-pbc commented 1 year ago

💎 $20 bounty created by @selimdoyranli 👉 To claim this bounty, submit your pull request on Algora 📝 Before proceeding, please make sure you can receive payouts in your country 💵 Payment arrives in your account 2-5 days after the bounty is rewarded 💯 You keep 100% of the bounty award 🙏 Thank you for contributing to nuxt-modules/stylelint!

ricardogobbosouza commented 1 year ago

Hi @selimdoyranli Sorry for delay...

This module uses the vite-plugin-stylelint plugin under the hood.

Try enabling the chokidar option See https://github.com/ModyQyW/vite-plugin-stylelint#chokidar


// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  ...
  modules: [
    [
      '@nuxtjs/stylelint-module',
      {
        chokidar: true
      }
    ]
  ]
})
selimdoyranli commented 1 year ago

Hi @selimdoyranli Sorry for delay...

This module uses the vite-plugin-stylelint plugin under the hood.

Try enabling the chokidar option See https://github.com/ModyQyW/vite-plugin-stylelint#chokidar

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  ...
  modules: [
    [
      '@nuxtjs/stylelint-module',
      {
        chokidar: true
      }
    ]
  ]
})

It didn't work. Please try editing the _general.scss file (in this structure: https://stackblitz.com/github/selimdoyranli/nuxt3-boilerplate-issue) to debug the issue. For example, in this file body scope's color: red; (this banned rule) When I type, I should see an error message on the browser screen after HMR, but I don't. Only error message appears in terminal

browser terminal

selimdoyranli commented 1 year ago

Hi @selimdoyranli Sorry for delay... This module uses the plugin under the hood.vite-plugin-stylelint Try enabling the option See https://github.com/ModyQyW/vite-plugin-stylelint#chokidar`chokidar`

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  ...
  modules: [
    [
      '@nuxtjs/stylelint-module',
      {
        chokidar: true
      }
    ]
  ]
})

It didn't work. Please try editing the _general.scss file (in this structure: https://stackblitz.com/github/selimdoyranli/nuxt3-boilerplate-issue) to debug the issue. For example, in this file body scope's color: red; (this banned rule) When I type, I should see an error message on the browser screen after HMR, but I don't. Only error message appears in terminal

browser terminal

Actually, I can't use Nuxt3 due to this issue 🤣.If there is a bug I guess other developers may see this as a serious problem when migrating to nuxt3. (fyi @ricardogobbosouza @pi0 @manniL and I would appreciate your assistances) This problem doesn't occur when I'm using Nuxt2. Stylelint is important for me. Sorry for the spam.

ricardogobbosouza commented 1 year ago

Using the chokidar option, the vite plugin does not use transform and therefore the results only appear in the console

codernex commented 1 year ago

/attempt #89

raphlcx commented 1 year ago

/attempt #89

raphlcx commented 1 year ago

hi @selimdoyranli, the reason that vite build did not error out, was most likely because the underlying library vite-plugin-stylelint does not support failing builds on stylelint errors.

I've PR-ed to vite-plugin-stylelint to add the capability to failOnError. That should resolve the issue.

ModyQyW commented 1 year ago

vite-plugin-stylelint supports failing builds on Stylelint errors. However, there are some exceptions.

  1. only enable lintInWorker. Since the plugin is linting in worker, no plugin context that can be used. So we can't fail builds in this case.
  2. only enable chokidar. To be honest, I think we can use plugin context in this case. But I test and find it failed, see https://github.com/ModyQyW/vite-plugin-stylelint/blob/main/src/index.ts#L95. Appreciate it if someone sends me a PR and fixes this, or I will back to it later.
  3. enable both, follow 1.

@raphlcx Hey! Thanks for your PR! But I think it is going in the wrong direction. Correct me if I'm wrong. Thanks! 🙏

raphlcx commented 1 year ago

Actually, for Nuxt3 / Vite, would setting error on the plugin context prevent HMR from updating the browser? Should we utilise Vite's HMR API instead for handling or intercepting HMR updates?

Here's my experiment with nuxt-modules/eslint, which also sets error on plugin context.

First, I start the dev server using npm run dev.

Then, I intentionally modify Hello.vue to include non-compliant scripts:

// src/components/Hello.vue

<template lang="pug">
h1.hello hello 1
</template>

<script lang="ts">
console.log(1);
console.log(2);
</script>

<style lang="scss" src="./Hello.scss"></style>

And I noticed there's a number of ESLint errors on the terminal console:

..../src/components/Hello.vue
  6:15  error  Delete ;       prettier/prettier
  6:15  error  Extra semicolon  semi
  7:15  error  Delete ;       prettier/prettier
  7:15  error  Extra semicolon  semi

✖ 4 problems (4 errors, 0 warnings)
  4 errors and 0 warnings potentially fixable with the --fix option.

However, on my browser at localhost:3000, I'm still seeing successful console.log() calls on the browser console:

[vite] connecting... client.ts:18:8
[vite] connected. client.ts:133:14
1 Hello.vue:6:13
2 Hello.vue:7:8
<Suspense> is an experimental feature and its API will likely change. deps:1358:43

So, even by setting error on plugin context, the nuxt modules for ESLint also did not prevent HMR from delivering its updates to the browser, perhaps because it's not utilisng the HMR API? I might also be missing out something here.

ModyQyW commented 7 months ago

https://github.com/nuxt-modules/stylelint/issues/89 is trying to handle this issue.

rajanarahul93 commented 7 months ago

/attempt #89