<repo_name>ericmasiello/stylelint-config-ericmasiello<file_sep>/index.js
module.exports = {
    bem: require('./bem'),
    cssModules: require('./cssModules'),
};
<file_sep>/.stylelintrcBem.js
const { bem } = require('./');

module.exports = bem;
<file_sep>/__tests__/bem.test.js
const { bem: config } = require('..');
const fs = require('fs');
const stylelint = require('stylelint');

const validSelectorsCss = fs.readFileSync('./__fixtures__/bem-css-valid.css', 'utf-8');
const invalidSelectorsCss = fs.readFileSync('./__fixtures__/bem-css-invalid.css', 'utf-8');
const invalidSpecificityCss = fs.readFileSync('./__fixtures__/specificity-css-invalid.css', 'utf-8');

describe('flags no warnings with valid selectors css', () => {
    let result;

    beforeEach(() => {
        result = stylelint.lint({
            code: validSelectorsCss,
            config,
        });
    });

    it('did not error', () => {
        return result.then(data => expect(data.errored).toBeFalsy());
    });

    it('flags no warnings', () => {
        return result.then(data => expect(data.results[0].warnings.length).toBe(0));
    });
});

describe('flags warnings with invalid specificty', () => {
    let result;

    beforeEach(() => {
        result = stylelint.lint({
            code: invalidSpecificityCss,
            config,
        });
    });

    it('violates selector-max-specificity', () => {
        return result.then(data => {
            const warnings = data.results[0].warnings.filter(warning => warning.rule === 'selector-max-specificity');
            expect(warnings).toHaveLength(3);
            expect(warnings[0].line).toBe(1);
            expect(warnings[1].line).toBe(5);
            expect(warnings[2].line).toBe(9);
        });
    });

    it('violates selector-max-compound-selectors', () => {
        return result.then(data => {
            const warnings = data.results[0].warnings.filter(
                warning => warning.rule === 'selector-max-compound-selectors'
            );
            expect(warnings).toHaveLength(1);
            expect(warnings[0].line).toBe(5);
        });
    });
});

describe('flags warnings with invalid css', () => {
    let result;

    beforeEach(() => {
        result = stylelint.lint({
            code: invalidSelectorsCss,
            config,
        });
    });

    it('violates selector-class-pattern', () => {
        const erroneousLineNumbers = [3, 7, 11, 15, 19, 23];
        return result.then(data => {
            const warnings = data.results[0].warnings.filter(warning => warning.rule === 'selector-class-pattern');
            expect(warnings).toHaveLength(erroneousLineNumbers.length);
            erroneousLineNumbers.forEach((lineNumber, i) => {
                expect(warnings[i].line).toBe(lineNumber);
            });
        });
    });
});
<file_sep>/bem.js
module.exports = {
  extends: 'stylelint-config-standard', 
  rules: {
    indentation: 4,
    'selector-class-pattern': '^([a-z][a-z0-9]*)((__|-{1,2})[a-z0-9]+)*$',
    'selector-max-compound-selectors': 3,
    'selector-max-specificity': '0,3,3',
    'declaration-colon-newline-after': null,
    'declaration-empty-line-before': null,
    'at-rule-empty-line-before': null,
    'at-rule-no-unknown': [true, {
      ignoreAtRules: [
        'mixin',
        'extend',
        'include',
        'function',
        'return',
        'if',
        'else',
        'for',
        'while',
        'each',
        'content',
        'at-root',
        'debug',
        'warn',
        'error',
      ],
    }],
  },
};
<file_sep>/cssModules.js
const cssmodules = require('stylelint-config-css-modules');
const bemConfig = require('./bem');

module.exports = {
    ...bemConfig,
    extends: [].concat(bemConfig.extends).concat('stylelint-config-css-modules'),
    rules: {
        ...bemConfig.rules,
        /*
            Enforces camelCase with support BEM style modifiers.

            Examples:
            .sample {}
            .mySample {}
            .mySample--error {}
            .mySample--specialState {}
        */
        'selector-class-pattern': '^([a-z][a-zA-Z0-9]*)((-{2})[a-z][a-zA-Z0-9]+)*$',
        'property-no-unknown': [
            true,
            {
                ignoreProperties: [...cssmodules.rules['property-no-unknown'][1].ignoreProperties],
            },
        ],
        'at-rule-no-unknown': [
            true,
            {
                ignoreAtRules: [
                    ...bemConfig.rules['at-rule-no-unknown'][1].ignoreAtRules,
                    ...cssmodules.rules['at-rule-no-unknown'][1].ignoreAtRules,
                ],
            },
        ],
    },
}<file_sep>/README.md
## stylelint-config-ericmasiello

`stylelint-config-ericmassielo` is a slightly more opinionated stylelint configuration than `stylelint-config-standard` that emphasizes minimal selector specificity as means toward improved CSS scalability.

The configuration comes in two variants:

1. A BEM (Block Element Modifier) variant that enforces kebab-case selector naming
2. A CSS Module variant that enforces camel case selector naming

For convenience, both configurations also white-list common SCSS directives.

### Install instructions

```shell
# npm
npm install --save-dev stylelint stylelint-config-ericmasiello

# yarn
yarn add -D stylelint stylelint-config-ericmasiello
```

Once installed, create a file in the root of your project named `.stylelintrc.js`.

If you prefer to use the BEM (Block Element Modifier) linting rules, set the contents to:

```js
// .stylelintrc.js
module.exports = {
    extends: 'stylelint-config-ericmasiello/bem',
};
```

Alternatively, if you prefer to use CSS Modules linting rules, set the contents to:

```js
// .stylelintrc.js
module.exports = {
    extends: 'stylelint-config-ericmasiello/cssModules',
};
```

If you need to ignore any files such as `normalize.css`, create a `.stylelintignore` file in the root of your project and list any files you need stylelint to ignore. For example:

```
normalize.css
normalize.min.css
```

To run the lint configuration, add a `script` to `package.json`.

```json
"scripts": {
  "lint:style": "stylelint \"src/**/*.{scss,css}\""
}
```

And then run the script like so:

```shell
# npm
npm run lint:style

# yarn
yarn lint:style
```
