diff --git a/stylelint-config.json b/stylelint-config.json index 55e160bd08a1..10315a50cf70 100644 --- a/stylelint-config.json +++ b/stylelint-config.json @@ -1,10 +1,12 @@ { "plugins": [ "./tools/stylelint/no-prefixes/no-prefixes.js", - "./tools/stylelint/selector-nested-pattern-scoped/index.js" + "./tools/stylelint/selector-nested-pattern-scoped/index.js", + "./tools/stylelint/selector-no-deep/index.js" ], "rules": { "material/no-prefixes": [["last 2 versions", "not ie <= 10", "not ie_mob <= 10"]], + "material/selector-no-deep": true, "material/selector-nested-pattern-scoped": [".*[^&]$", { "message": "The & operator is not allowed at the end of theme selectors.", "filePattern": "-theme\\.scss$" diff --git a/tools/stylelint/selector-no-deep/index.js b/tools/stylelint/selector-no-deep/index.js new file mode 100644 index 000000000000..093e229e359f --- /dev/null +++ b/tools/stylelint/selector-no-deep/index.js @@ -0,0 +1,37 @@ +const stylelint = require('stylelint'); +const isStandardSyntaxRule = require('stylelint/lib/utils/isStandardSyntaxRule'); +const isStandardSyntaxSelector = require('stylelint/lib/utils/isStandardSyntaxSelector'); + +const ruleName = 'material/selector-no-deep'; +const messages = stylelint.utils.ruleMessages(ruleName, { + expected: selector => `Usage of the /deep/ in "${selector}" is not allowed`, +}); + + +/** + * Stylelint plugin that prevents uses of /deep/ in selectors. + */ +const plugin = stylelint.createPlugin(ruleName, isEnabled => { + return (root, result) => { + if (!isEnabled) return; + + root.walkRules(rule => { + if (rule.parent.type === 'rule' && + isStandardSyntaxRule(rule) && + isStandardSyntaxSelector(rule.selector) && + rule.selector.includes('/deep/')) { + + stylelint.utils.report({ + result, + ruleName, + message: messages.expected(rule.selector), + node: rule + }); + } + }); + }; +}); + +plugin.ruleName = ruleName; +plugin.messages = messages; +module.exports = plugin;