Giter Site home page Giter Site logo

atfzl / eslint-plugin-css-modules Goto Github PK

View Code? Open in Web Editor NEW
153.0 153.0 34.0 631 KB

Project status: NOT MAINTAINED; Checks that you are using the existent css/scss classes, no more no less

JavaScript 95.71% SCSS 4.10% Less 0.19%
css css-modules eslint eslint-plugin scss

eslint-plugin-css-modules's People

Contributors

amannn avatar frenzzy avatar kangax avatar kristerkari avatar satazor avatar seek-showcase avatar yuhsianw avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

eslint-plugin-css-modules's Issues

Doesn't work anymore with new import * as style from './component.scss

Webpack css-loader introduced breaking change from version 7.0: https://github.com/webpack-contrib/css-loader/releases/tag/v7.0.0
Before:

import style from "./style.css";

console.log(style.myClass);

After:

import * as style from "./style.css";

console.log(style.myClass);

Expected: eslint-plugin-css-modules throws error if style.myClass isn't defined when we use new import style import * as style from "./style.css";

Actual: eslint-plugin-css-modules ignores such types of imports

False Positive with sass files

I'm running into an issue where we're dynamically creating class names to label our rows.

// styles.scss
$row-names: One Two Three

@each $row-name in $row-names {
  .row#{$row-name} {...}
}

and in the js file

// MyComponent.js
import styles from './styles.scss';

<div className={styles.rowOne}/>
<div className={styles.rowTwo}/>
<div className={styles.rowThree}/>

I end up getting the eslint: Class 'rowX' not found (css-modules/no-undef-class) error but class names properly assigned to the component.

I don't know if this is the correct place to post this issue or if work arounds exist for this.

It doesn't work with path-alias

The following code demonstrates the issue

/* ./src/styles/shared.scss */
.btn {
  font: inherit;
}
// ./src/elements/buttons/button.tsx
import shared from "@/styles/shared.scss";

export default function Button() {
  // css-modules plugin shows error here: `Class or exported property 'btn' not found`
  return (
    <button className={shared.btn}> 
      Test Buttton
    </button>
  );
}
// ./eslintrc.js
/** @type {import("eslint").Linter.Config} */
module.exports = {
  parser: "@typescript-eslint/parser",
  parserOptions: {
    sourceType: "module",
    ecmaFeatures: {
      jsx: true,
    },
  },
  extends: [
    "eslint:recommended",
    "plugin:@typescript-eslint/recommended",
    "plugin:css-modules/recommended", // shows unused classes: https://www.npmjs.com/package/eslint-plugin-css-modules
  ],
  env: {
    es6: true,
    node: true,
    browser: true,
  },
  plugins: ["json", "prettier", "import", "@typescript-eslint", "unused-imports", "css-modules"],
  rules: {
    "css-modules/no-unused-class": "warn",
    "css-modules/no-undef-class": ["error"],
    ],
    "import/extensions": [
      "error",
      "ignorePackages",
      {
        js: "never",
        jsx: "never",
        ts: "never",
        tsx: "never",
      },
    ],
  },
  settings: {
    "import/parsers": {
      "@typescript-eslint/parser": [".ts", ".tsx"],
    },
    "import/resolver": {
      typescript: {
        alwaysTryTypes: true, // always try to resolve types under `<root>@types` directory even it doesn't contain any source code, like `@types/unist`
        project: ["./tsconfig.json"],
      },
    },
  },
};
// ./tsconfig.json
{
  // jsconfig.json === tsconfig.json with allowJs: true
  "compilerOptions": {
    //intellisense config for VSCode
    "baseUrl": "./",
    "paths": {
      //none-js-ts files is not supported by intellisense. Use 'path-intellisense.mappings' in .vscode/settings.json instead
      //this is should be sync with aliases in webpack
      "@/*": ["src/*"],
      "images/*": ["src/assets/images/*"],
      "fonts/*": ["src/assets/fonts/*"]
    },
    "jsx": "react-jsx",
    "allowJs": true,
    "outDir": "",
    "noEmit": true, // exclude errors in console because it should be wrapped by webpack
    "esModuleInterop": true,
    "target": "ESNext",
    "module": "ESNext",
    "moduleResolution": "node",
    "strict": true,
    "noFallthroughCasesInSwitch": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true
  },
  "files": ["src/main.tsx"],
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist", "build", ".vscode"]
}

According to pointed config ESlint + TS understands path-alias @/ as root of the project.
But the css-modules don't understand it and the plugin shows error: Class or exported property 'btn' not found
The issue can be resolved by changing
import shared from "@/styles/shared.scss";
to
import shared from "./src/styles/shared.scss";

But how to tie the TS-path alias with the current plugin ?

Support dynamic object keys

Hi,

there's a quite common pattern which is not supported at the moment.
Accessing the styles object values with dynamic keys (variables).

import React, { PropTypes } from 'react';
import styles from './Button.css';

const Button = ({ theme }) => (
  <button className={styles[theme]} />
);

Button.propTypes = {
  theme: PropTypes.oneOf(['primary', 'secondary', 'danger']),
};

Button.defaultProps = {
  theme: 'primary',
};
.primary {
  color: green;
}

.secondary {
  color: blue;
}

.danger {
  color: red;
}

Results in:

css-modules/no-undef-class Class 'theme' not found at line ...
css-modules/no-unused-class Unused classes found: primary, secondary, danger at line ...

Only use class with composes

If you only use a class that is composing from another class within the same file it will say that the composed class is unused.

.round {
  border-radius: 50%;
}

.myThing {
  composes: round;
  background-color: red;
}

In this case if I only use .myThing in a component, the plugin will say that .round is never used.
Hope that makes sense.

no-undef-class in SASS with @import

I am trying to use Bootstrap 4 in my project. I've loaded it in my main component and all works.

Usage example: className={s.container}

But no-undef-class rule throws an error, because my bootstrap sass is just a list of imports and looks like this:

@import "../../node_modules/bootstrap/scss/functions";
@import "../../node_modules/bootstrap/scss/variables";
@import "../../node_modules/bootstrap/scss/mixins";
// ...

Add option for less files

This is a great plugin but it seems to be scoped to CSS/SCSS files even though it can support LESS as well.

Will follow up with a PR.

no-undef-class for "pseudo-nested" classes and classes from @import files

I'm using PostCSS, and if you have some kind of nesting, it throws a false no-undef-class. Take this example:

<div className={ styles['container-green'] }>
    This container is green
</div>

<div className={ `${styles.container} ${styles.isLoading}` }>
    This container is green
</div>
.container {
    &-green {
        background-color: green;
    }

    &.isLoading {
        background-color: grey;
    }
}

The linter does not recognise .container-green nor .container.isLoading, even though they exist.


Also, if I'm importing a file with a given class and use it in my component, it throws again no-undef-class. This might be an non issue, but I report it anyway. Take this example:

styles.css

.container-green {
     background-color: green;
}

component.css

@import 'styles.css';

...

component.js

<div className={ s['container-green'] }>
    This container is green
</div>

In this case container-green is not recognised as well.

Unused classes Found: Bracket notation

So I passed down class names as string props to be used in a reusable component. The styles are applied correctly in the bracket notation but the linter registers them as unused classes (even though they're being used)

props
bracket-notation
unused-classes

Is this intended or a bug?

no-unused-class for class names with variables in it

If I have a class like myClass-${myVar}, it throws a false no-unused-class.

Let's say I have this markup:

const myVar = 'container';

<div className={ `myClass-${myVar}` }>
    This container is blue
</div>

with these styles:

.myClass-container {
    color: blue;
}

The linter does not recognise myClass-${myVar} as myClass-container.

Multiple JS files for one CSS file

Hi, thanks for the plugin, it's awesome!!

I have been trying to implement it on a project and I have the issue of multiple JS files importing the same CSS file, which causes the plugin to give errors about unused classes, even when the classes are used by other files.

Would it be possible to implement such checking in this plugin or a stylelint plugin would suit better?

no-unused-class for scss mixins

_mixins.scss:

@mixin for-mobile-screen {
  @media screen and (max-width: 768px) {
    & {
      @content;
    }
  }
}

index.module.scss:

@use "mixins";

.xxx {
  @include mixins.for-mobile-screen {
    // ...
  }
}

index.tsx

import styles from "./index.module.scss";

Then, eslint says

error  Unused classes found in index.module.scss: for-mobile-screen  css-modules/no-unused-class

mixins.for-mobile-screen is not a selector, so this warning is false.
How can I fix this?

False positive alarm on unused class when using scss & parent selector

The ESLint warning is stating that the classes carouselListActive and carouselItemActive are detected as unused in the SubMenuCarousel.module.scss file. But they are not exist.

image

image

TSX

import cn from 'classnames';
import { FC } from 'react';
import { NavLink } from 'react-router-dom';
import s from './SubMenuCarousel.module.scss';

export interface ISubMenuCarouselProps {
  className?: string;
}

export const SubMenuCarousel: FC<ISubMenuCarouselProps> = ({ className = '' }) => {
  return (
    <nav className={cn(s.carousel, className)}>
      <ul className={cn(s.carouselList)}>
        <li className={s.carouselItem}>
          <NavLink
            to="/"
            className={({ isActive }) => cn(s.carouselLink, { [s.carouselLinkActive]: isActive })}
          />
        </li>
      </ul>
    </nav>
  );
};

SCSS

.carousel {
  margin: 0;

  &List {
    margin: 0;
  }

  &Item {
    margin: 0;
  }

  &Link {
    margin: 0;

    &Active {
      text-decoration: underline;
    }
  }
}

Add support for nested child selectors

<div className={ `${styles.container} ${styles.isLoading}` }>
    This container is green
</div>
.container {
    &-green {
        background-color: green;
    }

    &.isLoading {
        background-color: grey;
    }
}

The linter does not recognise .container.isLoading, even though they exist.

See #15

Class names can be hyphenated

styles.css:

.my-class {
/* ... */
}

app.jsx:

// ...
import styles from './styles.css';

const App = () => <div className={styles.myClass} />

creates a linting error as following:

css-modules/no-undef-class Class 'myClass not found

Isn't this undesired behavior? The class can be referenced using camelCase if one feels like hyphenating their classes.

P.S. Great plugin! Thank you :)

eslint-plugin-css-modules does not understand :local()

Hi all, I am having trouble getting the plugin to work. I have listed my setup below, everything that could maybe be relevant. As for the actual issue, it's almost like the plugin simply isn't doing anything.

I get the following types of errors:

In the jsx file it doesn't recognize any of the exported classNames:
........onlineUsersWidget.jsx

  15:25  error  Class or exported property 'onlineUsersWidget' not found  css-modules/no-undef-class
  16:29  error  Class or exported property 'onlineUsersHeader' not found  css-modules/no-undef-class
  19:25  error  Class or exported property 'onlineUsersList' not found    css-modules/no-undef-class
  26:24  error  Class or exported property 'onlineUser' not found         css-modules/no-undef-class
  27:32  error  Class or exported property 'selected' not found           css-modules/no-undef-class

In the sass file, it doesn't recognize ':local()'
........onlineUsersWidget.scss

  1:0  error  Parsing error: C:\Users\devbl\Documents\work_a24\projects\chat-inbox-ui\src\app\widgets\onlineUsers\onlineUsersWidget.scss: Unexpected token (1:0)

.eslintrc.json

  "extends": [
    "eslint:recommended",
    "plugin:react/recommended",
    "plugin:jest/recommended",
    "plugin:css-modules/recommended",
    "airbnb",
    "airbnb/hooks"
  ],
  "plugins": [
    "react",
    "css-modules"
  ],

package.json

{
  devDependencies: {
    "@babel/cli": "^7.5.5",
    "@babel/core": "^7.5.5",
    "@babel/plugin-proposal-class-properties": "^7.5.5",
    "@babel/plugin-proposal-decorators": "^7.4.4",
    "@babel/plugin-proposal-optional-chaining": "^7.2.0",
    "@babel/plugin-proposal-private-methods": "^7.4.4",
    "@babel/polyfill": "^7.4.4",
    "@babel/preset-env": "^7.5.5",
    "@babel/preset-react": "^7.0.0",
    "@testing-library/jest-dom": "^4.1.0",
    "@testing-library/react": "^9.1.3",
    "babel-eslint": "^11.0.0-beta.0",
    "babel-loader": "^8.0.6",
    "babel-plugin-transform-runtime": "^6.23.0",
    "babel-runtime": "^6.26.0",
    "css-loader": "^2.1.1",
    "eslint": "^6.1.0",
    "eslint-config-airbnb": "^18.0.1",
    "eslint-loader": "^3.0.0",
    "eslint-plugin-css-modules": "^2.11.0",
    "eslint-plugin-import": "^2.18.2",
    "eslint-plugin-jest": "^22.16.0",
    "eslint-plugin-jsx-a11y": "^6.2.3",
    "eslint-plugin-react": "^7.14.3",
    "eslint-plugin-react-hooks": "^1.7.0",
    "file-loader": "^4.2.0",
    "html-webpack-plugin": "^3.2.0",
    "jest": "^24.9.0",
    "jest-css-modules": "^2.1.0",
    "json-loader": "^0.5.7",
    "node-sass": "^4.12.0",
    "react-test-renderer": "^16.9.0",
    "sass-loader": "^7.3.1",
    "script-ext-html-webpack-plugin": "^2.1.4",
    "source-map-support": "^0.5.13",
    "style-loader": "^1.0.0",
    "url-loader": "^2.1.0",
.................
  }
}

onlineUsersWidget.jsx

import styles from './onlineUsersWidget.scss';

const OnlineUsersWidget = ({ onlineUsers, selectedUserId, onUserSelect }) => (
	<div className={styles.onlineUsersWidget}>
		<header className={styles.onlineUsersHeader}>
			<h3>Currently online ({onlineUsers.size})</h3>
..................

onlineUsersWidget.scss

:local(.onlineUsersWidget) {
  height: 100%;

  :local(.onlineUsersHeader) > h3 {
    line-height: 33px;
    color: #424242;
    font-size: 16px;
    padding: 0 10px;
......................

Pertainant Weback config bits:

...................
    entry: ['@babel/polyfill', path.join(baseDir, 'src', 'index.js')],
.....................
            {
                test: /\.s?css$/i,
                use: [
                    {
                        loader: 'style-loader'
                    },
                    {
                        loader: 'css-loader',
                        options: {
                            modules: true,
                            localIdentName: '[local]--[hash:base64:5]',
                            camelCase: true,
                            sourceMap: true
                        }
                    },
                    {
                        loader: 'sass-loader',
                        options: {
                            sourceMap: true
                        }
                    }
                ]
            }
.............................

.babelrc

{
  "presets": [
    ["@babel/preset-env", {
      "useBuiltIns": "entry",
      "corejs": "3.2.1"
    }],
    "@babel/preset-react"
  ],
  "plugins": [
    ["@babel/plugin-proposal-decorators", {"legacy": true}],
    ["@babel/plugin-proposal-class-properties", {"loose": true}],
    ["@babel/plugin-proposal-private-methods", { "loose": true }],
    "@babel/plugin-proposal-optional-chaining"
  ]
}

False negative with :not

SCSS:

.root {
  &:not(.selected) {
    opacity: 0.5;
  }
}

JS:

<div className={cx(styles.root, styles.selected)} />

Result:

Class 'selected' not found (css-modules/no-undef-class)

"Definition for rule was not found" for [email protected]

Hi,

I updated to CRA@2 with react 16.5.2 inside and after that I started getting eslint warnings
Definition for rule 'css-modules/no-unused-class' was not found for files that have such lines:
/* eslint css-modules/no-unused-class: [1, { markAsUsed: ['error'] }] */

As I understand it's an issue with different eslint versions for CRA ([email protected]) and for your plugin

Can you help with it somehow?

Parsing error: Unexpected keyword or identifier

Information:

  • ESLint version: latest
  • eslint-plugin-css version: latest

I'm trying to lint a simple .css file

a{
 color: red;
}

but I got the error Parsing error: Unexpected keyword or identifier

I use @typescript-eslint/parser

Does not play well with Node.12, Visual Code and possibly other Electron based editors

After digging deep into the code, I concluded that all the problems came from using deasync.

  • In Visual Code, I get the following error:

Screenshot 2019-11-01 at 17 49 45

This is because deasync is not compatible with Electon.

  • On Node.12, running eslint hangs whenever I use the plugin.

To solve these problems, we could instead use Node's ChildProcess#execSync or ChildProcess#spawnSync to run postcss-cli instead. The downside is that it would be a lot slower, specifically when linting large directories.

no-undef-class between version 2.3.0 -> 2.4.0

I've been using this plugin for a while (thanks!) and since upgrade to 2.4.0, I now have a ton of no-undef-class errors that were previously valid.

I will investigate more and follow up, but maybe you know?

no-undef-class with :global

If you have a global class that you only want something applied when it is a child of another class.

/* fails */
.holder :global .Select {}

If .holder doesn't have a class of it's own, it says that .holder is unused. To get it to pass we need to change .holder to have css applied otherwise it has an error of no-undef-class with .holder

/* passes */
.holder { display: block; }
.holder :global .Select {}

2.9.0 - Cannot read property 'content' of undefined

Caused by this new code (#42):

const filePath = filePathNode.content.replace(/^('|")/g, '').replace(/('|")$/, '');

TypeError: Cannot read property 'content' of undefined
    at /project/node_modules/eslint-plugin-css-modules/build/core/traversalUtils.js:143:35
    at Node.traverse (/project/node_modules/gonzales-pe/lib/gonzales.js:288:6)
    at Node.traverse (/project/node_modules/gonzales-pe/lib/gonzales.js:293:36)
    at getImportedFilePaths (/project/node_modules/eslint-plugin-css-modules/build/core/traversalUtils.js:138:7)
    at getStyleClasses (/project/node_modules/eslint-plugin-css-modules/build/core/index.js:156:69)
    at /project/node_modules/eslint-plugin-css-modules/build/core/index.js:157:30
    at Array.reduce (<anonymous>)
    at getStyleClasses (/project/node_modules/eslint-plugin-css-modules/build/core/index.js:156:85)
    at ImportDeclaration (/project/node_modules/eslint-plugin-css-modules/build/rules/no-undef-class.js:63:49)
    at /project/node_modules/eslint/lib/util/timing.js:122:13

Mark dynamically interpolated classes as used

Example:

import clsx from 'clsx';
import styles from './Button.module.scss';

function Button({children, className, variant = 'primary', ...rest}) {
  return (
    <button
      className={clsx(
        className,
        styles.root,
        styles[`root_variant-${variant}`]
      )}
      type="button"
      {...rest}
    >
      {children}
    </button>
  );
}
@import '~styles/theme';

.root {
  &_variant {
    &-primary {
      background-color: $colorPrimary;
    }

    &-secondary {
      background-color: $colorSecondary;
    }
  }
}

eslint-plugin-css-modules reports this error:

Unused classes found in Button.module.scss: root_variant, root_variant-primary, root_variant-secondary, root_variant-primary-secondary eslint(css-modules/no-unused-class)

This is the most common case I find in the code bases I'm working on where I have to disable the rule.

I'd propose that in this case all selectors should be marked as visited that match the dynamic pattern. So basically .root_variant-${variant} would create a regex like /\.root_variant-.*/ that is matched against all selectors.

For a limited amount of such variants you can of course create an explicit mapping, but I'm having this situation often, also with props like color which can contain a multitude of values and therefore I'd like to avoid the mapping.

@atfzl I know you don't maintain this repository anymore, but would you be open to a PR if I'd provide a fix?

no-unused-classes + descendant selectors

// Hero.css
.hero {
    ...
}

.hero .icon-add {
    ...
}

.hero.small .icon-add {
   ...
}

CSS modules exports an object with this shape:

{
  hero: '...',
  icon-add: '...',
  iconAdd: '...',
  small: '...'
}

And now some react component that uses it:

// Hero.css
import styles from './Hero';

export default ({ small }) => (
   <div className={ classNames(styles.hero, { [styles.small]: small }) }>
      <i className={ styles.iconAdd }></i>
   <div>
);

As you see, all the styles are being used but eslint-plugin-css-modules reports that icon-add isn't used.

New rule: no-implicit-access

This rule can process two cases:

  1. passing or assigning imported hash with classes anywhere
  2. accessing class dynamically like styles[var_with_any_name], but string is valid styles['className']

css-modules/no-undef-class error

I'm getting this error error Class 'container' not found css-modules/no-undef-class for the below scenario.

Home.js

import React from 'react';
import PropTypes from 'prop-types';
import s from './Home.scss';
class Home extends React.Component {
  render() {
    return (
      <div className={s.root}>
        <div className={s.container}>
          <h1>Soome Other Name</h1>
        </div>
      </div>
    );
  }
}

Home.scss

@import './commoncss.scss';

.root {
  padding-left: 20px;
  padding-right: 20px;
}

commoncss.scss

.container {
  margin: 0 auto;
  padding: 0 0 40px;
}

Usage with classNames

Thanks for creating this plugin! Super useful as I work on porting a project to CSS modules.

I'm running into an issue on components that make use of the classNames library. The following syntax will cause the css-modules/no-unused-class error to trigger:

const cx = classNames.bind(styles);
... 
<div className={cx('container', {
  'hidden': !this.state.isHidden
})} />

Is there a way around this? Thanks in advance.

False positive 'no-undef-class' when importing scss files using an alias path (aka using 'module-resolver')

Thanks for this nice plugin to eslint! It helps keeping the .scss files lean and clean! ๐ŸŽ‰

I'm facing an unexpected behaviour with a false positive css-modules/no-undef-class error. I think to have tracked it down to the case when the path of the imported .scss file uses an alias.

When importing the style file with the full relative path like this:

import cssGlobal from '../../../../assets/styles/global.scss';

I get the expected (long) list of classes that are defined but not used.

However, when I use the aliased version of the path (thanks to a combination of babel-plugin-module-resolver, eslint-plugin-import and eslint-import-resolver-babel-module) like this

import cssGlobal from 'styles/global.scss';

css-modules doesn't seem to find the class definitions and I get a bunch of css-modules/no-undef-class linting errors.

Is this a feature that is expected to work, or is something not standard in my project structure?

Any hints are greatly appreciated! Thanks! ๐Ÿ™‚

Environment

package.json

{
  "name": "my-project",
  "private": true,
  "dependencies": {
    "@rails/webpacker": "^3.0.1",
    "babel-preset-react": "^6.24.1",
    "prop-types": "^15.5.10",
    "react": "^15.6.1",
    "react-dom": "^15.6.1",
    "react-on-rails": "^9.0.2",
    "webpack-merge": "^4.1.0"
  },
  "devDependencies": {
    "babel-eslint": "^8.0.0",
    "babel-plugin-module-resolver": "^2.7.1",
    "eslint": "^3.19.0 || ^4.3.0",
    "eslint-config-airbnb": "^15.1.0",
    "eslint-import-resolver-babel-module": "^3.0.0",
    "eslint-plugin-css-modules": "^2.7.5",
    "eslint-plugin-import": "^2.7.0",
    "eslint-plugin-jsx-a11y": "^5.1.1",
    "eslint-plugin-react": "^7.1.0",
    "sass-lint": "^1.11.1",
    "webpack-dev-server": "^2.8.1"
  }
}

.babelrc

{
  "presets": [
    [
      "env",
      {
        "modules": false,
        "targets": {
          "browsers": "> 1%",
          "uglify": true
        },
        "useBuiltIns": true
      }
    ],
    "react"
  ],
  "plugins": [
    "syntax-dynamic-import",
    "transform-object-rest-spread",
    ["module-resolver", {
      "root": ["./client"],
      "alias": {
        "styles": "./client/app/assets/styles",
        "img": "./client/app/assets/img"
      },
      "extensions": [
        ".js",
        ".jsx",
        ".scss",
        ".css"
      ]
    }],
    [
      "transform-class-properties",
      {
        "spec": true
      }
    ]
  ]
}

.eslintrc.yml

plugins:
  - css-modules

extends:
  - airbnb
  - plugin:css-modules/recommended

# SOURCE: https://github.com/eslint/eslint/issues/4636#issuecomment-162910216
parser: babel-eslint

# SOURCE: https://github.com/tleunen/eslint-import-resolver-babel-module/issues/25#issuecomment-242980792
settings:
  import/resolver:
    babel-module:
      extensions:
        - ".js"
        - ".jsx"
        - ".scss"
        - ".css"

Unused classes found when classifier is used in composes

Example css:

.box{ ... }
.redBox {
 composes: box;
 background-color: red;
}

Example react code:

<div className={css.redBox}></div>

Now plugin in recommended configuration will say that .box is unused.

Error message: Unused classes found: box & rule css-modules/no-unused-class

Plugin should probably care if classifier is used in another compose and do not throw error when it's actually used by another used class.

Support for .vue files

The .vue file

<style lang="scss" scoped>
.unused-class {
  background: red;
}
</style>

My eslintrc.js config:

module.exports = {
  root: true,
  env: {
    browser: true,
    node: true
  },
  extends: [
    'plugin:vue/recommended',
    'plugin:css-modules/recommended'
  ],
  plugins: [
    'vue',
    'eslint-plugin-css-modules'
  ]
};

Expected: eslint should throws a warning/error for the unused class

Classes in global block should be ignored

classes defined in global block are being used for linting. These should be ignored.

.foo {
  /* this class should be used */
}

:global {
  /* all the classes in this block should be ignored */
  .bar {
   }

  .baz {
  }
}

Bug: Memory leak causing crash when linting many (3500+) files

As title describes - really simple as that to reproduce.

To be certain; I disabled all other eslint plugins - and confirmed this plugin as the cause of this issue.

This occurs on both latest stable's of eslint 3 & 4 with latest stable of css modules plugin.

The issue occurs at the very end of the linting process - presumably near the format phase. Memory jumps from 150mb to over 3gb.

Split in two different rules

First of all, thanks for this plugin! ๐Ÿ˜ƒ

What do you think about splitting css-modules/no-unused-or-extra-class in two different rules?So that it is possible, for example, to report an error when using an undeclared class but to report a warning when a class is unused.
e.g.

// .eslintrc.json
{
    ...
    "css-modules/no-undef-class": 2, // [1]
    "css-modules/no-unused-class": 1
}

PS It has been a little challenging to find the github repo of this package (since currently Google indexed just the npm page). Can you please add this repo's url to your package.json so that npm shows it?

Support css that is imported by multiple files

If I have multiple files that import the same css file, but use different classes from it, no-unused-class will warn me, even if it's not necessary.

Eg.

// a.js
import styles from "./styles.css"
console.log(styles.a)
// b.js
import styles from "./styles.css"
console.log(styles.b)
// styles.css
.a { color: red }
.b { color: blue }

Will yield these warnings:

a.js: Unused classes found: b   css-modules/no-unused-class
b.js: Unused classes found: a   css-modules/no-unused-class

Is there a way to prevent this, so this plugin can be reliably used as a css dead-code detection tool?

Issue with multiple classes in `composes`

Hi,

Per the spec:

It's possible to compose multiple classes with composes: classNameA classNameB;.

It seems the no-unused-class error incorrectly triggers when using this syntax, on a class that is only used for composition. Ex:

.foo {
  color: red;
}

.bar {
  color: blue;
}

.quux {
  composes: foo bar;
}

The error will be triggered on whatever classes aren't in the first part of composes, in this case that would be bar.

False "css-modules/no-undef-class" with keyframes

I have keyframe in my scss file like:

@keyframes blink1 {
  from {
    fill-opacity: 0.1;
  }

  50%{
    fill-opacity: 1;
  }

  100% {
    fill-opacity: 0.1;
  }
}

and It throws
60:23 error Class 'blink1' not found css-modules/no-undef-class
exception in jsx template.

I think that there are actually no blink1 class :)

no-undef-class dismisses classes within :global(.class) {

For "css-modules/no-undef-class" I'm facing an issue similar to others that have been fixed in the past.
Sometimes css module classes can be namespaced with globals as such:

:global(.some-class) {
    .accept {
        color: green;
    }

    .reject {
        color: red;
    }
}

Both accept and reject are valid classes, however the plugin drops them and they show up as errors in my repo:
46:65 error Class or exported property 'accept' not found css-modules/no-undef-class

I think it should be possible to disregard the global wrapper but still evaluate its contents to find valid classes within it.

Environment

I'm running:

  • eslint 7.32.0
  • eslint-plugin-css-modules 2.12.0
  • sass 1.75.0
  • node 18.16.1

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.