README
postcss-bem-linter
A PostCSS plugin to lint BEM-style CSS.
BEM-style describes CSS that follows a more-or-less strict set of conventions determining what selectors can be used. Typically, these conventions require that classes begin with the name of the component (or "block") that contains them, and that all characters after the component name follow a specified pattern. Original BEM methodology refers to "blocks", "elements", and "modifiers"; SUIT refers to "components", "descendants", and "modifiers". You might have your own terms for similar concepts.
With this plugin, you can check the validity of selectors against a set of BEM-style conventions. You can use preset patterns (SUIT and BEM, currently) or insert your own. The plugin will register warnings if it finds CSS that does not follow the specified conventions.
Installation
npm install postcss-bem-linter --save-dev
Version 1.0.0+ is compatible with PostCSS 5+. (Earlier versions are compatible with PostCSS 4.)
This plugin registers warnings via PostCSS. Therefore, you'll want to use it with a PostCSS runner that prints warnings (e.g. gulp-postcss
) or another PostCSS plugin that prints warnings (e.g. postcss-reporter
).
Throughout this document, terms like "selector", "selector sequence", and "simple selector" are used according to the definitions in the Selectors Level 3 spec.
stylelint plugin
postcss-bem-linter can also be used as a stylelint plugin: stylelint-selector-bem-pattern.
By using the stylelint plugin, all of your linting can happen in one step, seamlessly: postcss-bem-linter warnings will output alongside other stylelint warnings. Also, you can take advantage of all the other features that stylelint offers, such as a CLI and Node.js API, different formatters for output, etc.
Conformance tests
Default mode:
- Only allow selector sequences that match the defined convention.
- Only allow custom-property names that begin with the defined
ComponentName
.
Weak mode:
- While initial selector sequences (before combinators) must match the defined convention, sequences after combinators are not held to any standard.
Prior to 0.5.0, this plugin checked two other details: that :root
rules only contain custom-properties; and that the :root
selector is not grouped or combined with other selectors. These checks can now be performed by stylelint. So from 0.5.0 onwards, this plugin leaves that business to stylelint to focus on its more unique task.
Use
bemLinter([pattern[, options]])
Defining your pattern
Patterns consist of regular expressions, and functions that return regular expressions, or strings, which describe valid selector sequences.
Keep in mind:
- Patterns describe sequences, not just simple selectors. So if, for example,
you would like to be able to chain state classes to your component classes, as in
.Component.is-open
, your pattern needs to allow for this chaining. - Pseudo-classes and pseudo-elements will be ignored if they occur at the end of the sequence.
Instead of
.Component:first-child.is-open
, you should use.Component.is-open:first-child
. The former will trigger a warning unless you've written a silly complicated pattern.
Preset Patterns
The following preset patterns are available:
'suit'
(default), as defined here. Options:namespace
: a namespace to prefix valid classes, as described in the SUIT docs
'bem'
, as defined here.namespace
: a namespace to prefix valid classes, to be separated from the block name with a hyphen, e.g. with namespacefoo
,.foo-dropdown__menu
.
You can use a preset pattern and its options in two ways:
- Pass the preset's name as the first argument, and, if needed, an
options
object as the second, e.g.bemLinter('suit', { namespace: 'twt' })
. - Pass an object as the first and only argument, with the preset's name as the
preset
property and, if needed,presetOptions
, e.g.bemLinter({ preset: 'suit', presetOptions: { namespace: 'twt' })
.
'suit'
is the default pattern; so if you do not pass any pattern
argument,
SUIT conventions will be enforced.
Custom Patterns
You can define a custom pattern by passing as your first and only argument an object with the following properties:
componentName
default: /^[-_a-zA-Z0-9]+$/
Describes valid component names in one of the following forms:
- A regular expression.
- A string that provides a valid pattern for the
RegExp()
constructor.
componentSelectors
Describes all valid selector sequences for the stylesheet in one of the following forms:
- A single function that accepts a component name and returns a regular expression, e.g.
componentSelectors(componentName) {
return new RegExp('^\\.ns-' + componentName + '(?:-[a-zA-Z]+)?