Skip to content

Commit

Permalink
Added variables-in-files rule (#3)
Browse files Browse the repository at this point in the history
* Added a test verifying exported name is correct

* Added variables-in-files rule

* Make sure current repo is linked so that tests pass

* Added linking of itself into the travis script
  • Loading branch information
DCzajkowski authored Jul 22, 2019
1 parent 395b821 commit dcb3ee5
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ node_js:

before_script:
- travis_retry yarn
- yarn link
- yarn link '@dczajkowski/stylelint-rules'

script:
- yarn lint
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ In your `.stylelintrc` config:
|| [declaration-property-unit-whitelist](./src/rules/declaration-property-unit-whitelist/README.md) | Require specific properties to have only given units |
|| [color-no-non-variables](./src/rules/color-no-non-variables/README.md) | Disallow usage of color literals (allows only variables) |
|| [no-floats-with-unit](./src/rules/no-floats-with-unit/README.md) | Disallow usage of floats with certain units |
|| [variables-in-files](./src/rules/variables-in-files/README.md) | Allow for variables to be declared only in specified files |
<!-- /rules-declaration -->

## License
Expand Down
40 changes: 40 additions & 0 deletions src/rules/variables-in-files/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# dczajkowski/variables-in-files
Requires variables to be declared in specified files.

## Usage
```json
{
"rules": {
"dczajkowski/variables-in-files": [["src/styles/variables.css"]]
}
}
```

For this config the following applies:

```css
/* This is allowed */

/* in src/styles/variables.css */

:root {
--color-blue: cornflowerblue;
}

.a {
--color-white: white;
}

/* This is not allowed */

/* in src/styles/partials/_navbar.css */

:root {
--color-blue: cornflowerblue;
}

.a {
--color-white: white;
}

```
51 changes: 51 additions & 0 deletions src/rules/variables-in-files/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import stylelint from 'stylelint';
import postcss from 'postcss';
import { namespace } from '../../constants';

export const ruleName = `${namespace}/variables-in-files`;
export const messages = stylelint.utils.ruleMessages(ruleName, {
illegalVariableDeclaration: (variable: string, file: string, allowedFiles: string[]) =>
`Illegal variable '${variable}' declaration in file '${file}'. Allowed files: ${allowedFiles
.map(file => `'${file}'`)
.join(', ')}.`,
});

const isVariableDeclaration = (prop: string) => prop.startsWith('--');

export default function(allowedFiles: string[] = []) {
return async function(postcssRoot: postcss.Root, postcssResult: postcss.Result) {
const validOptions = stylelint.utils.validateOptions(postcssResult, ruleName);

if (!validOptions || !Array.isArray(allowedFiles)) {
return;
}

const rootPath = `${process.cwd()}/`;

postcssRoot.walkDecls(node => {
const {
prop,
source: {
input: { file },
},
} = node;

if (!isVariableDeclaration(prop) || !file) {
return;
}

const relativePath = file.replace(rootPath, '');

if (allowedFiles.includes(relativePath)) {
return;
}

stylelint.utils.report({
message: messages.illegalVariableDeclaration(prop, relativePath, allowedFiles),
result: postcssResult,
ruleName,
node,
});
});
};
}
58 changes: 58 additions & 0 deletions tests/rules/variables-in-files.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { messages } from '../../src/rules/variables-in-files';
import test from 'tape';
import { lint } from 'stylelint';

const runStylelint = async (allowedFiles: string[], file: string) =>
lint({
code: `
:root {
--spacing: 1rem;
}
.a {
--color-blue: cornflowerblue;
}
`,
codeFilename: file,
config: {
plugins: ['@dczajkowski/stylelint-rules'],
rules: {
'dczajkowski/variables-in-files': [allowedFiles],
},
},
});

test('accepts variable declarations in allowed files', async t => {
t.plan(1);

const { errored } = await runStylelint(['vars/colors.css', 'vars/index.css'], 'vars/index.css');

t.false(errored);
});

interface Warning {
line: number;
column: number;
rule: string;
severity: 'error';
text: string;
}

test('disallows variable declarations in not-allowed files', async t => {
t.plan(4);

const allowedFiles = ['vars/colors.css', 'vars/index.css'];
const file = 'partials/_navbar.css';

const {
errored,
results: [{ warnings: unknownWarnings }],
} = await runStylelint(allowedFiles, file);

const warnings = <Warning[]>(<unknown[]>unknownWarnings);

t.true(errored);
t.equals(warnings.length, 2, 'There should be two warnings emitted.');
t.equals(warnings[0].text, messages.illegalVariableDeclaration('--spacing', file, allowedFiles));
t.equals(warnings[1].text, messages.illegalVariableDeclaration('--color-blue', file, allowedFiles));
});

0 comments on commit dcb3ee5

Please sign in to comment.