build: add stylelint rule to ban concrete CSS rules inside theme files (#10003)

Adds a stylelint rule that will ensure that all of the CSS rules inside theme files are placed inside a mixin. This avoids style duplication whenever the file is imported.

Relates to #9999.
This commit is contained in:
Kristiyan Kostadinov
2018-02-26 16:05:53 +01:00
committed by Jeremy Elbourn
parent e3d7aeccc6
commit d078e5ee6a
4 changed files with 56 additions and 17 deletions
@@ -0,0 +1,39 @@
const stylelint = require('stylelint');
const path = require('path');
const ruleName = 'material/no-concrete-rules';
const messages = stylelint.utils.ruleMessages(ruleName, {
expected: pattern => `CSS rules must be placed inside a mixin for files matching '${pattern}'.`
});
/**
* Stylelint plugin that will log a warning for all top-level CSS rules.
* Can be used in theme files to ensure that everything is inside a mixin.
*/
const plugin = stylelint.createPlugin(ruleName, (isEnabled, options) => {
return (root, result) => {
if (!isEnabled) return;
const filePattern = new RegExp(options.filePattern);
const fileName = path.basename(root.source.input.file);
if (!filePattern.test(fileName)) return;
// Go through all the nodes and report a warning for every CSS rule or mixin inclusion.
// We use a regular `forEach`, instead of the PostCSS walker utils, because we only care
// about the top-level nodes.
root.nodes.forEach(node => {
if (node.type === 'rule' || (node.type === 'atrule' && node.name === 'include')) {
stylelint.utils.report({
result,
ruleName,
node,
message: messages.expected(filePattern)
});
}
});
};
});
plugin.ruleName = ruleName;
plugin.messages = messages;
module.exports = plugin;