index.js 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. 'use strict';
  2. const beforeBlockString = require('../../utils/beforeBlockString');
  3. const hasBlock = require('../../utils/hasBlock');
  4. const hasEmptyBlock = require('../../utils/hasEmptyBlock');
  5. const optionsMatches = require('../../utils/optionsMatches');
  6. const report = require('../../utils/report');
  7. const ruleMessages = require('../../utils/ruleMessages');
  8. const validateOptions = require('../../utils/validateOptions');
  9. const { isBoolean } = require('../../utils/validateTypes');
  10. const ruleName = 'block-no-empty';
  11. const messages = ruleMessages(ruleName, {
  12. rejected: 'Unexpected empty block',
  13. });
  14. const meta = {
  15. url: 'https://stylelint.io/user-guide/rules/list/block-no-empty',
  16. };
  17. /** @type {import('stylelint').Rule} */
  18. const rule = (primary, secondaryOptions) => {
  19. return (root, result) => {
  20. const validOptions = validateOptions(
  21. result,
  22. ruleName,
  23. {
  24. actual: primary,
  25. possible: isBoolean,
  26. },
  27. {
  28. actual: secondaryOptions,
  29. possible: {
  30. ignore: ['comments'],
  31. },
  32. optional: true,
  33. },
  34. );
  35. if (!validOptions) {
  36. return;
  37. }
  38. const ignoreComments = optionsMatches(secondaryOptions, 'ignore', 'comments');
  39. // Check both kinds of statements: rules and at-rules
  40. root.walkRules(check);
  41. root.walkAtRules(check);
  42. /**
  43. * @param {import('postcss').Rule | import('postcss').AtRule} statement
  44. */
  45. function check(statement) {
  46. if (!hasEmptyBlock(statement) && !ignoreComments) {
  47. return;
  48. }
  49. if (!hasBlock(statement)) {
  50. return;
  51. }
  52. const hasCommentsOnly = statement.nodes.every((node) => node.type === 'comment');
  53. if (!hasCommentsOnly) {
  54. return;
  55. }
  56. let index = beforeBlockString(statement, { noRawBefore: true }).length;
  57. // For empty blocks when using SugarSS parser
  58. if (statement.raws.between === undefined) {
  59. index--;
  60. }
  61. report({
  62. message: messages.rejected,
  63. node: statement,
  64. index,
  65. result,
  66. ruleName,
  67. });
  68. }
  69. };
  70. };
  71. rule.ruleName = ruleName;
  72. rule.messages = messages;
  73. rule.meta = meta;
  74. module.exports = rule;