Skip to content

Commit

Permalink
Add no-invalid-position-at-import-rule (#5202)
Browse files Browse the repository at this point in the history
  • Loading branch information
chuuddo committed Mar 26, 2021
1 parent 77269e3 commit 3dfa452
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 0 deletions.
1 change: 1 addition & 0 deletions docs/user-guide/rules/list.md
Expand Up @@ -79,6 +79,7 @@ Grouped first by the following categories and then by the [_thing_](http://apps.
- [`no-empty-source`](../../../lib/rules/no-empty-source/README.md): Disallow empty sources.
- [`no-extra-semicolons`](../../../lib/rules/no-extra-semicolons/README.md): Disallow extra semicolons (Autofixable).
- [`no-invalid-double-slash-comments`](../../../lib/rules/no-invalid-double-slash-comments/README.md): Disallow double-slash comments (`//...`) which are not supported by CSS.
- [`no-invalid-position-at-import-rule`](../../../lib/rules/no-invalid-position-at-import-rule/README.md): Disallow invalid position `@import` rules within a stylesheet.

## Limit language features

Expand Down
3 changes: 3 additions & 0 deletions lib/rules/index.js
Expand Up @@ -242,6 +242,9 @@ const rules = {
'no-invalid-double-slash-comments': importLazy(() =>
require('./no-invalid-double-slash-comments'),
)(),
'no-invalid-position-at-import-rule': importLazy(() =>
require('./no-invalid-position-at-import-rule'),
)(),
'no-missing-end-of-source-newline': importLazy(() =>
require('./no-missing-end-of-source-newline'),
)(),
Expand Down
51 changes: 51 additions & 0 deletions lib/rules/no-invalid-position-at-import-rule/README.md
@@ -0,0 +1,51 @@
# no-invalid-position-at-import-rule

Disallow invalid position `@import` rules within a stylesheet.

<!-- prettier-ignore -->
```css
a {}
@import 'foo.css';
/** ↑
* This @import */
```

Any `@import` rules must precede all other valid at-rules and style rules in a stylesheet (ignoring `@charset`), or else the `@import` rule is invalid.

## Options

### `true`

The following patterns are considered violations:

<!-- prettier-ignore -->
```css
a {}
@import 'foo.css';
```

<!-- prettier-ignore -->
```css
@media print {}
@import 'foo.css';
```

The following patterns are _not_ considered violations:

<!-- prettier-ignore -->
```css
@import 'foo.css';
a {}
```

<!-- prettier-ignore -->
```css
/* some comment */
@import 'foo.css';
```

<!-- prettier-ignore -->
```css
@charset 'utf-8';
@import 'foo.css';
```
113 changes: 113 additions & 0 deletions lib/rules/no-invalid-position-at-import-rule/__tests__/index.js
@@ -0,0 +1,113 @@
'use strict';

const stripIndent = require('common-tags').stripIndent;

const { messages, ruleName } = require('..');

testRule({
ruleName,
config: [true],

accept: [
{
code: stripIndent`
@import 'foo.css';
a {}
`,
description: '@import on first line',
},
{
code: stripIndent`
/* some comment */
@import 'foo.css';
`,
description: '@import after comment',
},
{
code: stripIndent`
@charset 'utf-8';
@import 'foo.css';
`,
description: '@import after @charset ',
},
{
code: stripIndent`
@import 'foo.css';
@import 'bar.css';
`,
description: '@import after another @import',
},
{
code: stripIndent`
@CHARSET 'utf-8';
@imPORT 'foo.css';
@import 'bar.css';
`,
description: 'case insensitive',
},
],

reject: [
{
code: stripIndent`
a {}
@import 'foo.css';
`,
message: messages.rejected,
description: '@import after selector',
line: 2,
column: 1,
},
{
code: stripIndent`
@media print {}
@import url('foo.css');
`,
message: messages.rejected,
description: '@import after another at-rule',
line: 2,
column: 1,
},
{
code: stripIndent`
@media print {}
@imPort URl('foo.css');
`,
message: messages.rejected,
description: 'case insensitive',
line: 2,
column: 1,
},
{
code: stripIndent`
@import 'foo.css';
a {}
@import 'bar.css';
`,
message: messages.rejected,
description: 'only second @import reported',
line: 3,
column: 1,
},
{
code: stripIndent`
a {}
@import 'foo.css';
@import 'bar.css';
`,
warnings: [
{
message: messages.rejected,
line: 2,
column: 1,
},
{
message: messages.rejected,
line: 3,
column: 1,
},
],
description: 'all @import reported',
},
],
});
52 changes: 52 additions & 0 deletions lib/rules/no-invalid-position-at-import-rule/index.js
@@ -0,0 +1,52 @@
// @ts-nocheck

'use strict';

const report = require('../../utils/report');
const ruleMessages = require('../../utils/ruleMessages');
const validateOptions = require('../../utils/validateOptions');

const ruleName = 'no-invalid-position-at-import-rule';

const messages = ruleMessages(ruleName, {
rejected: 'Unexpected invalid position @import rule',
});

function rule(actual) {
return (root, result) => {
const validOptions = validateOptions(result, ruleName, { actual });

if (!validOptions) {
return;
}

let invalidPosition = false;

root.walk((node) => {
const nodeName = node.name && node.name.toLowerCase();

if (node.type === 'comment' || (node.type === 'atrule' && nodeName === 'charset')) {
return;
}

if (node.type === 'atrule' && nodeName === 'import') {
if (invalidPosition) {
report({
message: messages.rejected,
node,
result,
ruleName,
});
}

return;
}

invalidPosition = true;
});
};
}

rule.ruleName = ruleName;
rule.messages = messages;
module.exports = rule;

0 comments on commit 3dfa452

Please sign in to comment.