{"id":13518251,"url":"https://github.com/postcss/postcss-bem-linter","last_synced_at":"2025-12-18T01:21:56.876Z","repository":{"id":21423272,"uuid":"24741384","full_name":"postcss/postcss-bem-linter","owner":"postcss","description":"A BEM linter for postcss","archived":false,"fork":false,"pushed_at":"2023-10-07T16:41:13.000Z","size":555,"stargazers_count":576,"open_issues_count":21,"forks_count":35,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-05-03T23:26:57.173Z","etag":null,"topics":["bem","linter","postcss","suit-css"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/postcss.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2014-10-03T00:01:55.000Z","updated_at":"2025-03-28T20:52:45.000Z","dependencies_parsed_at":"2023-01-14T13:10:11.708Z","dependency_job_id":"82f4a7b7-a898-4514-a5c2-4d0bab025a13","html_url":"https://github.com/postcss/postcss-bem-linter","commit_stats":{"total_commits":195,"total_committers":26,"mean_commits":7.5,"dds":0.5641025641025641,"last_synced_commit":"a721dacce37a7306885c2c4dd3ebcece802f3075"},"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/postcss%2Fpostcss-bem-linter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/postcss%2Fpostcss-bem-linter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/postcss%2Fpostcss-bem-linter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/postcss%2Fpostcss-bem-linter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/postcss","download_url":"https://codeload.github.com/postcss/postcss-bem-linter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253806478,"owners_count":21967177,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bem","linter","postcss","suit-css"],"created_at":"2024-08-01T05:01:42.693Z","updated_at":"2025-12-18T01:21:56.807Z","avatar_url":"https://github.com/postcss.png","language":"JavaScript","readme":"# postcss-bem-linter\n\n[![Build Status](https://travis-ci.org/postcss/postcss-bem-linter.svg?branch=master)](https://travis-ci.org/postcss/postcss-bem-linter)\n\nA [PostCSS](https://github.com/postcss/postcss) plugin to lint *BEM-style* CSS.\n\n*BEM-style* describes CSS that follows a more-or-less strict set of conventions determining\nwhat selectors can be used. Typically, these conventions require that classes begin with\nthe name of the component (or \"block\") that contains them, and that all characters after the\ncomponent name follow a specified pattern. Original BEM methodology refers to \"blocks\", \"elements\",\nand \"modifiers\"; SUIT refers to \"components\", \"descendants\", and \"modifiers\". You might have your\nown terms for similar concepts.\n\n**With this plugin, you can check the validity of selectors against a set of BEM-style conventions.**\nYou can use preset patterns (SUIT and BEM, currently) or insert your own. The plugin will register\nwarnings if it finds CSS that does not follow the specified conventions.\n\n## Installation\n\n```\nnpm install postcss postcss-bem-linter --save-dev\n```\n\nVersion 1.0.0+ is compatible with PostCSS 5+. (Earlier versions are compatible with PostCSS 4.)\n\nThis plugin registers warnings via PostCSS. Therefore, you'll want to use it with a PostCSS runner that prints warnings (e.g. [`gulp-postcss`](https://github.com/postcss/gulp-postcss)) or another PostCSS plugin that prints warnings (e.g. [`postcss-reporter`](https://github.com/postcss/postcss-reporter)).\n\n**Throughout this document, terms like \"selector\", \"selector sequence\", and \"simple selector\" are used according to the definitions in the [Selectors Level 3 spec](http://www.w3.org/TR/css3-selectors/#selector-syntax).**\n\n### stylelint plugin\n\npostcss-bem-linter can also be used as a [stylelint](http://stylelint.io/) plugin: [stylelint-selector-bem-pattern](https://github.com/davidtheclark/stylelint-selector-bem-pattern).\n\nBy 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.\n\n## Conformance tests\n\n**Default mode**:\n\n* Only allow selector sequences that match the defined convention.\n* Only allow custom-property names that *begin* with the defined `ComponentName`.\n\n**Weak mode**:\n\n* While *initial* selector sequences (before combinators) must match the defined convention,\n  sequences *after combinators* are not held to any standard.\n\n*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](https://github.com/stylelint/stylelint). So from 0.5.0 onwards, this plugin leaves that business to stylelint to focus on its more unique task.*\n\n## Use\n\n```\nbemLinter([pattern[, options]])\n```\n\n### Defining your pattern\n\nPatterns consist of regular expressions, and functions that return regular expressions,\nor strings, which describe valid selector sequences.\n\nKeep in mind:\n- **Patterns describe sequences, not just simple selectors.** So if, for example,\nyou would like to be able to chain state classes to your component classes, as in\n`.Component.is-open`, your pattern needs to allow for this chaining.\n- **Pseudo-classes and pseudo-elements will be ignored if they occur at the end of the sequence.**\nInstead of `.Component:first-child.is-open`, you should use `.Component.is-open:first-child`.\nThe former will trigger a warning unless you've written a silly complicated pattern.\n\n#### Preset Patterns\n\nThe following preset patterns are available:\n\n- `'suit'` (default), as defined [here](https://github.com/suitcss/suit/blob/master/doc/naming-conventions.md).\n  Options:\n  - `namespace`: a namespace to prefix valid classes, as described\n    [in the SUIT docs](https://github.com/suitcss/suit/blob/master/doc/naming-conventions.md#namespace-optional)\n- `'bem'`, as defined [here](https://en.bem.info/methodology/naming-convention/).\n  - `namespace`: a namespace to prefix valid classes, to be separated from the block name with a hyphen,\n    e.g. with namespace `foo`, `.foo-dropdown__menu`.\n\nYou can use a preset pattern and its options in two ways:\n- Pass the preset's name as the first argument, and, if needed, an `options` object as the second,\n  e.g. `bemLinter('suit', { namespace: 'twt' })`.\n- Pass an object as the first and only argument, with the preset's name as the `preset` property and,\n  if needed, `presetOptions`, e.g. `bemLinter({ preset: 'suit', presetOptions: { namespace: 'twt' })`.\n\n**`'suit'` is the default pattern; so if you do not pass any `pattern` argument,\nSUIT conventions will be enforced.**\n\n#### Custom Patterns\n\nYou can define a custom pattern by passing as your first and only argument *an object with the following properties*:\n\n##### `componentName`\n\ndefault: `/^[-_a-zA-Z0-9]+$/`\n\nDescribes valid component names in one of the following forms:\n\n- A regular expression.\n- A string that provides a valid pattern for the `RegExp()` constructor.\n\n##### `componentSelectors`\n\nDescribes all valid selector sequences for the stylesheet in one of the following forms:\n\n- A *single function* that accepts a component name and returns a regular expression, e.g.\n\n```js\ncomponentSelectors(componentName) {\n  return new RegExp('^\\\\.ns-' + componentName + '(?:-[a-zA-Z]+)?$');\n}\n```\n\n- A *single string* that provides a valid pattern for the `RegExp()` constructor *when\n  `{componentName}` is interpolated with the defined component's name*, e.g.\n\n```js\ncomponentSelectors: '^\\\\.ns-{componentName}(?:-[a-zA-Z]+)?$'\n```\n\n- An *object consisting of two properties*, `initial` and `combined`. Both properties accept the\n  same two forms described above: a function accepting a component name and returning a regular\n  expression; or a string, interpolating the component name with `{componentName}`, that will\n  provide a valid pattern for the `RegExp()` constructor.\n\n  `initial` describes valid initial selector sequences — those occurring at the beginning of\n  a selector, before any combinators.\n\n  `combined` describes valid selector sequences allowed *after* combinators.\n  Two important notes about `combined`:\n    - If you do not specify a `combined` pattern, it is assumed that combined sequences must match the same pattern as initial sequences.\n    - In weak mode, *any* combined sequences are accepted, even if you have a `combined` pattern.\n\n##### `utilitySelectors`\n\nDescribes valid utility selector sequences. This will be used if the stylesheet defines a\ngroup of utilities, as explained below. Can take one of the following forms:\n\n- A regular expression.\n- A string that provides a valid pattern for the `RegExp()` constructor.\n\n##### `ignoreSelectors`\n\nDescribes selector sequences to ignore. You can use this to\nsystematically ignore selectors matching certain patterns, instead of having to add a\n`/* postcss-bem-linter: ignore */` comment above each one (see below).\nCan take one of the following forms:\n\n- A regular expression.\n- An array of regular expressions.\n- A string that provides a valid pattern for the `RegExp()` constructor.\n- An array of such string patterns.\n\n##### `ignoreCustomProperties`\n\nDescribes custom properties to ignore. Works the same as `ignoreSelectors`, above, so please read about that.\n\n### Overriding Presets\n\n*You can also choose a preset to start with and override specific parts of it, specific patterns.*\n\nFor example, if you want to use SUIT's preset generally but write your own `utilitySelectors` pattern,\nyou can do that with a config object like this:\n\n```js\n{\n  preset: 'suit',\n  utilitySelectors: /^\\.fancyUtilities-[a-z]+$/\n}\n```\n\n### Examples\n\nGiven all of the above, you might call the plugin in any of the following ways:\n\n```js\n// use 'suit' conventions\nbemLinter();\nbemLinter('suit');\nbemLinter('suit', { namespace: 'twt' });\nbemLinter({ preset: 'suit', presetOptions: { namespace: 'twt' }});\n\n// use 'bem' conventions\nbemLinter('bem');\nbemLinter('bem', { namespace: 'ydx' });\nbemLinter({ preset: 'bem', presetOptions: { namespace: 'ydx' }});\n\n// define a pattern for component names\nbemLinter({\n  componentName: /^[A-Z]+$/\n});\nbemLinter({\n  componentName: '^[A-Z]+$'\n});\n\n// define a single pattern for all selector sequences, initial or combined\nbemLinter({\n  componentSelectors(componentName) {\n    return new RegExp('^\\\\.' + componentName + '(?:-[a-z]+)?$');\n  }\n});\nbemLinter({\n  componentSelectors: '^\\\\.{componentName}(?:-[a-z]+)?$'\n});\n\n// define separate `componentName`, `initial`, `combined`, and `utilities` patterns\nbemLinter({\n  componentName: /^[A-Z]+$/,\n  componentSelectors: {\n    initial(componentName) {\n      return new RegExp('^\\\\.' + componentName + '(?:-[a-z]+)?$');\n    },\n    combined(componentName) {\n      return new RegExp('^\\\\.combined-' + componentName + '-[a-z]+$');\n    }\n  },\n  utilitySelectors: /^\\.util-[a-z]+$/\n});\nbemLinter({\n  componentName: '^[A-Z]+$',\n  componentSelectors: {\n    initial: '^\\\\.{componentName}(?:-[a-z]+)?$',\n    combined: '^\\\\.combined-{componentName}-[a-z]+$'\n  },\n  utilitySelectors: '^\\.util-[a-z]+$'\n});\n\n// start with the `bem` preset but include a special `componentName` pattern\n// and `ignoreSelectors` pattern to ignore Modernizr-injected `no-*` classes\nbemLinter({\n  preset: 'bem',\n  componentName: /^cmpnt_[a-zA-Z]+$/,\n  ignoreSelectors: /^\\.no-.+$/\n});\nbemLinter({\n  preset: 'bem',\n  componentName: '^cmpnt_[a-zA-Z]+$',\n  ignoreSelectors: '^\\.no-.+$'\n});\n\n// ... using an array for `ignoreSelectors`\nbemLinter({\n  preset: 'bem',\n  componentName: /^cmpnt_[a-zA-Z]+$/,\n  ignoreSelectors: [\n    /^\\.no-.+$/,\n    /^\\.isok-.+$/\n  ]\n});\nbemLinter({\n  preset: 'bem',\n  componentName: '^cmpnt_[a-zA-Z]+$',\n  ignoreSelectors: [\n    '^\\.no-.+$',\n    '^\\.isok-.+$'\n  ]\n});\n```\n\n### Defining a component and utilities\n\nThe plugin will only lint the CSS if it knows the context of the CSS: is it a utility or a\ncomponent. To define the context, use the configuration options to define it based on the filename\n(`css/components/*.css`) or use a special comment to define context for the CSS after it.\nWhen defining a component, the component name is needed.\n\n#### Define components and utilities implicitly based on their filename\n\nWhen defining a component base on the filename, the name of the file (minus the extension) will be\nused implicitly as the component name for linting.\nThe configuration option for implicit components take:\n\n- Enable it for all files: `implicitComponents: true`\n- Enable it for files that match a glob pattern: `implicitComponents: 'components/**/*.css'`\n- Enable it for files that match one of multiple glob patterns: `implicitComponents: ['components/**/*.css', 'others/**/*.css']`\n\nThe CSS will implicitly be linted as utilities in files marked as such by their filename.\nThe configuration option for implicit utilities take:\n\n- Enable it for files that match a glob pattern: `implicitUtilities: 'utils/*.css'`\n- Enable it for files that match one of multiple glob patterns: `implicitUtilities: ['util/*.css', 'bar/**/*.css']`\n\n#### Define components/utilities with a comment\n\nThese comment definitions can be provided in two syntaxes: concise and verbose.\n\n- Concise definition syntax: `/** @define ComponentName */` or `/** @define utilities */`\n- Verbose definition syntax: `/* postcss-bem-linter: define ComponentName */` or `/* postcss-bem-linter: define utilities */`.\n\nWeak mode is turned on by adding `; weak` to a definition,\ne.g. `/** @define ComponentName; weak */` or `/* postcss-bem-linter: define ComponentName; weak */`.\n\nConcise syntax:\n\n```css\n/** @define MyComponent */\n\n:root {\n  --MyComponent-property: value;\n}\n\n.MyComponent {}\n\n.MyComponent-other {}\n```\n\nVerbose syntax:\n\n```css\n/** postcss-bem-linter: define FancyComponent */\n\n:root {\n  --FancyComponent-property: value;\n}\n\n.FancyComponent {}\n\n.FancyComponent-other {}\n```\n\nWeak mode:\n\n```css\n/** @define MyComponent; weak */\n\n:root {\n  --MyComponent-property: value;\n}\n\n.MyComponent {}\n\n.MyComponent .other {}\n```\n\nImplicit:\n\n```javascript\nbemLinter({\n  preset: 'bem',\n  implicitComponents: 'components/**/*.css',\n  implicitUtilities: 'utils/*.css'\n});\n```\n\n\nUtilities:\n\n```css\n/** @define utilities */\n\n.u-sizeFill {}\n\n.u-sm-horse {}\n```\n\nIf a component is defined and the component name does not match your `componentName` pattern,\nthe plugin will throw an error.\n\n### Multiple definitions\n\nIt's recommended that you keep each defined group of rules in a distinct file,\nwith the definition at the top of the file. If, however, you have a good reason\nfor *multiple definitions within a single file*, you can do that.\n\nSuccessive definitions override each other. So the following works:\n\n```css\n/** @define Foo */\n.Foo {}\n\n/** @define Bar */\n.Bar {}\n\n/** @define utilities */\n.u-something {}\n```\n\nYou can also deliberately *end the enforcement of a definition* with the following special comments:\n`/** @end */` or `/* postcss-bem-linter: end */`.\n\n```css\n/** @define Foo */\n.Foo {}\n/** @end */\n\n.something-something-something {}\n```\n\nOne use-case for this functionality is when linting files *after* concatenation performed by a\nCSS processor like Less or Sass, whose syntax is not always compatible with PostCSS.\nSee [issue #57](https://github.com/postcss/postcss-bem-linter/issues/57).\n\n### Ignoring specific selectors\n\nIf you need to ignore a specific selector but do not want to ignore the entire stylesheet\nor end the enforcement of a definition, there are two ways to accomplish this:\n\nAs describe above, you can include an `ignoreSelectors` regular expression (or array of regular expressions) in your configuration.\nThis is the best approach if you want to systematically ignore all selectors matching a pattern (e.g. all Modernizr classes).\n\nIf you just want to ignore a single, isolated selector, though,\nyou can do so by *preceding the selector* with this comment: `/* postcss-bem-linter: ignore */`.\n\n```css\n/** @define MyComponent */\n\n.MyComponent {\n  display: flex;\n}\n\n/* postcss-bem-linter: ignore */\n.no-flexbox .Component {\n  display: block;\n}\n```\n\n*The comment will cause the linter to ignore **only** the very next selector.*\n\n### Testing CSS files\n\nPass your individual CSS files through the plugin. It will register warnings for\nconformance failures, which you can print to the console using\n[`postcss-reporter`](https://github.com/postcss/postcss-reporter) or relying\non a PostCSS runner (such as [`gulp-postcss`](https://github.com/postcss/gulp-postcss)).\n\n```js\nconst postcss = require('postcss');\nconst bemLinter = require('postcss-bem-linter');\nconst reporter = require('postcss-reporter');\n\nfiles.forEach(file =\u003e {\n  const css = fs.readFileSync(file, 'utf-8');\n  postcss()\n    .use(bemLinter())\n    .use(reporter())\n    .process(css)\n    .then(result =\u003e { .. });\n});\n```\n\n## Contributing\n\nPlease note that this project is released with a Contributor Code of Conduct. By participating in this project you agree to abide by its terms.\n\n### Development\n\nInstall dependencies. Requires [Yarn 1.x (Classic)](https://classic.yarnpkg.com/)\n\n```\nyarn\n```\n\nRun the tests.\n\n```\nyarn test\n```\n\nWatch and automatically re-run the unit tests.\n\n```\nyarn start\n```\n","funding_links":[],"categories":["JavaScript","With Pre-processors","Linters"],"sub_categories":["PostCSS","CSS"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpostcss%2Fpostcss-bem-linter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpostcss%2Fpostcss-bem-linter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpostcss%2Fpostcss-bem-linter/lists"}