index.js 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. 'use strict';
  2. const isStandardSyntaxRule = require('../../utils/isStandardSyntaxRule');
  3. const matchesStringOrRegExp = require('../../utils/matchesStringOrRegExp');
  4. const report = require('../../utils/report');
  5. const optionsMatches = require('../../utils/optionsMatches');
  6. const ruleMessages = require('../../utils/ruleMessages');
  7. const validateOptions = require('../../utils/validateOptions');
  8. const { isRegExp, isString, isBoolean } = require('../../utils/validateTypes');
  9. const ruleName = 'selector-disallowed-list';
  10. const messages = ruleMessages(ruleName, {
  11. rejected: (selector) => `Unexpected selector "${selector}"`,
  12. });
  13. const meta = {
  14. url: 'https://stylelint.io/user-guide/rules/list/selector-disallowed-list',
  15. };
  16. /** @type {import('stylelint').Rule<string | RegExp | Array<string | RegExp>, { splitList: boolean, ignore: string[] }>} */
  17. const rule = (primary, secondaryOptions) => {
  18. return (root, result) => {
  19. const validOptions = validateOptions(
  20. result,
  21. ruleName,
  22. {
  23. actual: primary,
  24. possible: [isString, isRegExp],
  25. },
  26. {
  27. actual: secondaryOptions,
  28. possible: {
  29. ignore: ['inside-block'],
  30. splitList: [isBoolean],
  31. },
  32. optional: true,
  33. },
  34. );
  35. if (!validOptions) {
  36. return;
  37. }
  38. const ignoreInsideBlock = optionsMatches(secondaryOptions, 'ignore', 'inside-block');
  39. const splitList = secondaryOptions && secondaryOptions.splitList;
  40. root.walkRules((ruleNode) => {
  41. if (!isStandardSyntaxRule(ruleNode)) {
  42. return;
  43. }
  44. if (ignoreInsideBlock) {
  45. const { parent } = ruleNode;
  46. const isInsideBlock = parent && parent.type !== 'root';
  47. if (isInsideBlock) {
  48. return;
  49. }
  50. }
  51. if (splitList) {
  52. ruleNode.selectors.forEach((selector) => {
  53. if (matchesStringOrRegExp(selector, primary)) {
  54. report({
  55. result,
  56. ruleName,
  57. message: messages.rejected(selector),
  58. node: ruleNode,
  59. word: selector,
  60. });
  61. }
  62. });
  63. } else {
  64. const { selector, raws } = ruleNode;
  65. if (matchesStringOrRegExp(selector, primary)) {
  66. const word = (raws.selector && raws.selector.raw) || selector;
  67. report({
  68. result,
  69. ruleName,
  70. message: messages.rejected(selector),
  71. node: ruleNode,
  72. word,
  73. });
  74. }
  75. }
  76. });
  77. };
  78. };
  79. rule.primaryOptionArray = true;
  80. rule.ruleName = ruleName;
  81. rule.messages = messages;
  82. rule.meta = meta;
  83. module.exports = rule;