13

PostCSS BEM Linter plugin needs component definition for each block which is a time consuming thing to do in a legacy project.

Is there a way to use stylelint to check for the classes pattern and show error in all stylesheets (.scss in my case) of the project without needing component definition in each file/block?

https://csswizardry.com/2013/01/mindbemding-getting-your-head-round-bem-syntax/

.block {}
.block__element {}
.block--modifier {}
Jitendra Vyas
  • 148,487
  • 229
  • 573
  • 852

2 Answers2

3

I have a working example following on from @jeddy3 answer.
This is a copy of my stylelint.config.js

We override the bemSelector() function taken from https://github.com/postcss/postcss-bem-linter/blob/master/lib/preset-patterns.js

We use two dashes style instead of default BEM by changing the const modifier to match https://en.bem.info/methodology/naming-convention/#two-dashes-style

/**
 * @param {String} block
 * @param {Object} [presetOptions]
 * @param {String} [presetOptions.namespace]
 * @returns {RegExp}
 */
const bemSelector = (block, presetOptions) => {
  const ns = (presetOptions && presetOptions.namespace) ? `${presetOptions.namespace}-` : '';
  const WORD = '[a-zA-Z0-9]+(?:-[a-zA-Z0-9]+)*';
  const element = `(?:__${WORD})?`;
  const modifier = `(?:--${WORD}){0,2}`;
  const attribute = '(?:\\[.+\\])?';
  return new RegExp(`^\\.${ns}${block}${element}${modifier}${attribute}$`);
}

module.exports = {
  extends: 'stylelint-config-recommended-scss',
  plugins: [
    'stylelint-selector-bem-pattern'
  ],
  rules: {
    'plugin/selector-bem-pattern': {
      preset: 'bem',
      componentSelectors: bemSelector
    }
  }
}
minlare
  • 2,454
  • 25
  • 46
  • If anyone is reading this a few years down the line like I am, it looks like the `bemSelector()` function taken from https://github.com/postcss/postcss-bem-linter/blob/master/lib/preset-patterns.js now allows both "classic" BEM and "two-dashes" style BEM. Here: https://github.com/postcss/postcss-bem-linter/blob/master/lib/preset-patterns.js#L48 With `(?:_|--)` – golden_grahams Mar 26 '22 at 13:34
  • I'm trying to use a SCSS selector of `&.is-open {}`as a sort of state-like class. However I'm getting: "Stylelint: Invalid component selector ".c-stylelint.is-open" (plugin/selector-bem-pattern)" Do you get the same? Do you have any work arounds? – golden_grahams Jul 28 '22 at 12:41
1

You can use stylelint's selector-class-pattern rule to enforce a pattern for class selectors using a regular expression.

However, if you're writing BEM-like CSS then stylelint-selector-bem-pattern, which wraps PostCSS BEM Linter, is more powerful as it understands the concept of components, elements, modifiers and utility classes.

There is an option to implicitly define components based on their filename, removing the need for component definitions within each file.

jeddy3
  • 3,451
  • 1
  • 12
  • 21