Skip to content

Commit 7ff086a

Browse files
crisbetojelbourn
authored andcommitted
build: add stylelint rule to avoid top-level ampersands in themes (#10280)
* Adds a stylelint rule that will log a warning for top-level ampersand selectors inside of mixins. This will help us avoid issues like #9991 in the future. * Makes the `mat-radio-color` internal.
1 parent 140c94e commit 7ff086a

File tree

3 files changed

+53
-5
lines changed

3 files changed

+53
-5
lines changed

src/lib/radio/_radio-theme.scss

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
@import '../core/theming/theming';
33
@import '../core/typography/typography-utils';
44

5-
@mixin mat-radio-color($palette) {
5+
@mixin _mat-radio-color($palette) {
66
&.mat-radio-checked .mat-radio-outer-circle {
77
border-color: mat-color($palette);
88
}
@@ -43,15 +43,15 @@
4343

4444
.mat-radio-button {
4545
&.mat-primary {
46-
@include mat-radio-color($primary);
46+
@include _mat-radio-color($primary);
4747
}
4848

4949
&.mat-accent {
50-
@include mat-radio-color($accent);
50+
@include _mat-radio-color($accent);
5151
}
5252

5353
&.mat-warn {
54-
@include mat-radio-color($warn);
54+
@include _mat-radio-color($warn);
5555
}
5656
}
5757
}

stylelint-config.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
"./tools/stylelint/selector-nested-pattern-scoped/index.js",
55
"./tools/stylelint/selector-no-deep/index.js",
66
"./tools/stylelint/no-nested-mixin/index.js",
7-
"./tools/stylelint/no-concrete-rules/index.js"
7+
"./tools/stylelint/no-concrete-rules/index.js",
8+
"./tools/stylelint/no-top-level-ampersand-in-mixin/index.js"
89
],
910
"rules": {
1011
"material/no-prefixes": [["last 2 versions", "not ie <= 10", "not ie_mob <= 10"]],
@@ -17,6 +18,9 @@
1718
"material/no-concrete-rules": [true, {
1819
"filePattern": "^_.*\\.scss$"
1920
}],
21+
"material/no-top-level-ampersand-in-mixin": [true, {
22+
"filePattern": "-theme\\.scss$"
23+
}],
2024

2125
"color-hex-case": "lower",
2226
"color-no-invalid-hex": true,
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
const stylelint = require('stylelint');
2+
const path = require('path');
3+
const ruleName = 'material/no-top-level-ampersand-in-mixin';
4+
const messages = stylelint.utils.ruleMessages(ruleName, {
5+
expected: () => `Selectors starting with an ampersand ` +
6+
`are not allowed inside top-level mixin rules`
7+
});
8+
9+
/**
10+
* Stylelint rule that doesn't allow for the top-level rules inside a
11+
* mixin to start with an ampersand. Does not apply to internal mixins.
12+
*/
13+
const plugin = stylelint.createPlugin(ruleName, (isEnabled, options) => {
14+
return (root, result) => {
15+
if (!isEnabled) return;
16+
17+
const filePattern = new RegExp(options.filePattern);
18+
const fileName = path.basename(root.source.input.file);
19+
20+
if (!filePattern.test(fileName)) return;
21+
22+
root.walkAtRules(node => {
23+
// Skip non-mixin atrules and internal mixins.
24+
if (node.name !== 'mixin' || node.params.indexOf('_') === 0) {
25+
return;
26+
}
27+
28+
node.nodes.forEach(childNode => {
29+
if (childNode.type === 'rule' && childNode.selector.indexOf('&') === 0) {
30+
stylelint.utils.report({
31+
result,
32+
ruleName,
33+
message: messages.expected(),
34+
node: childNode
35+
});
36+
}
37+
});
38+
});
39+
};
40+
});
41+
42+
plugin.ruleName = ruleName;
43+
plugin.messages = messages;
44+
module.exports = plugin;

0 commit comments

Comments
 (0)