npm install postcss postcss-bem-linter --save-dev
-
Only allow selector sequences that match the defined convention. -
Only allow custom-property names that begin with the defined ComponentName .
-
While initial selector sequences (before combinators) must match the defined convention, sequences after combinators are not held to any standard.
bemLinter([pattern[, options]])
-
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.
'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 namespace foo , .foo-dropdown__menu .
-
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' }) .
-
A regular expression. -
A string that provides a valid pattern for the RegExp() constructor.
-
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]+)?$' ) ;
}
-
A single string that provides a valid pattern for the RegExp() constructor when {componentName} is interpolated with the defined component's name , e.g.
componentSelectors: '^\\.ns-{componentName}(?:-[a-zA-Z]+)?$'
-
An object consisting of two properties , initial and combined . Both properties accept the same two forms described above: a function accepting a component name and returning a regular expression; or a string, interpolating the component name with {componentName} , that will provide a valid pattern for the RegExp() constructor. initial describes valid initial selector sequences — those occurring at the beginning of a selector, before any combinators. combined describes valid selector sequences allowed after combinators. Two important notes about combined : -
If you do not specify a combined pattern, it is assumed that combined sequences must match the same pattern as initial sequences. -
In weak mode, any combined sequences are accepted, even if you have a combined pattern.
-
-
A regular expression. -
A string that provides a valid pattern for the RegExp() constructor.
-
A regular expression. -
An array of regular expressions. -
A string that provides a valid pattern for the RegExp() constructor. -
An array of such string patterns.
{
preset : 'suit' ,
utilitySelectors : / ^\.fancyUtilities-[a-z]+$ /
}
// use 'suit' conventions
bemLinter ( ) ;
bemLinter ( 'suit' ) ;
bemLinter ( 'suit' , { namespace : 'twt' } ) ;
bemLinter ( { preset : 'suit' , presetOptions : { namespace : 'twt' } } ) ;
// use 'bem' conventions
bemLinter ( 'bem' ) ;
bemLinter ( 'bem' , { namespace : 'ydx' } ) ;
bemLinter ( { preset : 'bem' , presetOptions : { namespace : 'ydx' } } ) ;
// define a pattern for component names
bemLinter ( {
componentName : / ^[A-Z]+$ /
} ) ;
bemLinter ( {
componentName : '^[A-Z]+$'
} ) ;
// define a single pattern for all selector sequences, initial or combined
bemLinter ( {
componentSelectors ( componentName ) {
return new RegExp ( '^\\.' + componentName + '(?:-[a-z]+)?$' ) ;
}
} ) ;
bemLinter ( {
componentSelectors : '^\\. {componentName}(?:-[a-z]+)?$'
} ) ;
// define separate `componentName`, `initial`, `combined`, and `utilities` patterns
bemLinter ( {
componentName : / ^[A-Z]+$ / ,
componentSelectors : {
initial ( componentName ) {
return new RegExp ( '^\\.' + componentName + '(?:-[a-z]+)?$' ) ;
} ,
combined ( componentName ) {
return new RegExp ( '^\\.combined-' + componentName + '-[a-z]+$' ) ;
}
} ,
utilitySelectors : / ^\.util-[a-z]+$ /
} ) ;
bemLinter ( {
componentName : '^[A-Z]+$' ,
componentSelectors : {
initial : '^\\. {componentName}(?:-[a-z]+)?$' ,
combined : '^\\.combined- {componentName}- [a-z]+$'
} ,
utilitySelectors : '^\.util-[a-z]+$'
} ) ;
// start with the `bem` preset but include a special `componentName` pattern
// and `ignoreSelectors` pattern to ignore Modernizr-injected `no-*` classes
bemLinter ( {
preset : 'bem' ,
componentName : / ^cmpnt_[a-zA-Z]+$ / ,
ignoreSelectors : / ^\.no-.+$ /
} ) ;
bemLinter ( {
preset : 'bem' ,
componentName : '^cmpnt_[a-zA-Z]+$' ,
ignoreSelectors : '^\.no-.+$'
} ) ;
// ... using an array for `ignoreSelectors`
bemLinter ( {
preset : 'bem' ,
componentName : / ^cmpnt_[a-zA-Z]+$ / ,
ignoreSelectors : [
/ ^\.no-.+$ / ,
/ ^\.isok-.+$ /
]
} ) ;
bemLinter ( {
preset : 'bem' ,
componentName : '^cmpnt_[a-zA-Z]+$' ,
ignoreSelectors : [
'^\.no-.+$' ,
'^\.isok-.+$'
]
} ) ;
-
Enable it for all files: implicitComponents: true -
Enable it for files that match a glob pattern: implicitComponents: 'components/**/*.css' -
Enable it for files that match one of multiple glob patterns: implicitComponents: ['components/**/*.css', 'others/**/*.css']
-
Enable it for files that match a glob pattern: implicitUtilities: 'utils/*.css' -
Enable it for files that match one of multiple glob patterns: implicitUtilities: ['util/*.css', 'bar/**/*.css']
-
Concise definition syntax: /** @define ComponentName */ or /** @define utilities */ -
Verbose definition syntax: /* postcss-bem-linter: define ComponentName */ or /* postcss-bem-linter: define utilities */ .
/** @define MyComponent */
: root { --MyComponent-property : value; } . MyComponent {} . MyComponent-other {}
/** postcss-bem-linter: define FancyComponent */
: root { --FancyComponent-property : value; } . FancyComponent {} . FancyComponent-other {}
/** @define MyComponent; weak */
: root { --MyComponent-property : value; } . MyComponent {} . MyComponent . other {}
bemLinter ( {
preset : 'bem' ,
implicitComponents : 'components/**/*.css' ,
implicitUtilities : 'utils/*.css'
} ) ;
/** @define utilities */ . u-sizeFill {} . u-sm-horse {}
/** @define Foo */ . Foo {} /** @define Bar */ . Bar {} /** @define utilities */ . u-something {}
/** @define Foo */ . Foo {} /** @end */ . something-something-something {}
/** @define MyComponent */ . MyComponent { display : flex; } /* postcss-bem-linter: ignore */ . no-flexbox . Component { display : block; }
const postcss = require ( 'postcss' ) ;
const bemLinter = require ( 'postcss-bem-linter' ) ;
const reporter = require ( 'postcss-reporter' ) ;
files . forEach ( file => {
const css = fs . readFileSync ( file , 'utf-8' ) ;
postcss ( )
. use ( bemLinter ( ) )
. use ( reporter ( ) )
. process ( css )
. then ( result => { . . } ) ;
} ) ;
yarn
yarn test
yarn start