index.js 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. const stylelint = require('stylelint');
  2. const _ = require('lodash');
  3. const { getContainingNode, isRuleWithNodes } = require('../../utils');
  4. const checkNodeForOrder = require('./checkNodeForOrder');
  5. const checkNodeForEmptyLines = require('./checkNodeForEmptyLines');
  6. const createOrderInfo = require('./createOrderInfo');
  7. const validatePrimaryOption = require('./validatePrimaryOption');
  8. const ruleName = require('./ruleName');
  9. const messages = require('./messages');
  10. function rule(primaryOption, options = {}, context = {}) {
  11. return function ruleBody(root, result) {
  12. let validOptions = stylelint.utils.validateOptions(
  13. result,
  14. ruleName,
  15. {
  16. actual: primaryOption,
  17. possible: validatePrimaryOption,
  18. },
  19. {
  20. actual: options,
  21. possible: {
  22. unspecified: ['top', 'bottom', 'ignore', 'bottomAlphabetical'],
  23. emptyLineBeforeUnspecified: ['always', 'never', 'threshold'],
  24. disableFix: _.isBoolean,
  25. emptyLineMinimumPropertyThreshold: _.isNumber,
  26. },
  27. optional: true,
  28. }
  29. );
  30. if (!validOptions) {
  31. return;
  32. }
  33. let isFixEnabled = context.fix && !options.disableFix;
  34. let expectedOrder = createOrderInfo(primaryOption);
  35. let processedParents = [];
  36. // Check all rules and at-rules recursively
  37. root.walk(function processRulesAndAtrules(input) {
  38. let node = getContainingNode(input);
  39. // Avoid warnings duplication, caused by interfering in `root.walk()` algorigthm with `getContainingNode()`
  40. if (processedParents.includes(node)) {
  41. return;
  42. }
  43. processedParents.push(node);
  44. if (isRuleWithNodes(node)) {
  45. checkNodeForOrder({
  46. node,
  47. originalNode: input,
  48. isFixEnabled,
  49. primaryOption,
  50. unspecified: options.unspecified || 'ignore',
  51. result,
  52. expectedOrder,
  53. });
  54. checkNodeForEmptyLines({
  55. node,
  56. context,
  57. emptyLineBeforeUnspecified: options.emptyLineBeforeUnspecified,
  58. emptyLineMinimumPropertyThreshold:
  59. options.emptyLineMinimumPropertyThreshold || 0,
  60. expectedOrder,
  61. isFixEnabled,
  62. primaryOption,
  63. result,
  64. });
  65. }
  66. });
  67. };
  68. }
  69. rule.primaryOptionArray = true;
  70. rule.ruleName = ruleName;
  71. rule.messages = messages;
  72. module.exports = rule;