index.js 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. const stylelint = require('stylelint');
  2. const { getContainingNode, isRuleWithNodes } = require('../../utils');
  3. const { isNumber } = require('../../utils/validateType');
  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. emptyLineMinimumPropertyThreshold: isNumber,
  25. },
  26. optional: true,
  27. }
  28. );
  29. if (!validOptions) {
  30. return;
  31. }
  32. let isFixEnabled = context.fix;
  33. let expectedOrder = createOrderInfo(primaryOption);
  34. let processedParents = [];
  35. // Check all rules and at-rules recursively
  36. root.walk(function processRulesAndAtrules(input) {
  37. let node = getContainingNode(input);
  38. // Avoid warnings duplication, caused by interfering in `root.walk()` algorigthm with `getContainingNode()`
  39. if (processedParents.includes(node)) {
  40. return;
  41. }
  42. processedParents.push(node);
  43. if (isRuleWithNodes(node)) {
  44. checkNodeForOrder({
  45. node,
  46. isFixEnabled,
  47. primaryOption,
  48. unspecified: options.unspecified || 'ignore',
  49. result,
  50. expectedOrder,
  51. });
  52. checkNodeForEmptyLines({
  53. node,
  54. context,
  55. emptyLineBeforeUnspecified: options.emptyLineBeforeUnspecified,
  56. emptyLineMinimumPropertyThreshold:
  57. options.emptyLineMinimumPropertyThreshold || 0,
  58. expectedOrder,
  59. isFixEnabled,
  60. primaryOption,
  61. result,
  62. });
  63. }
  64. });
  65. };
  66. }
  67. rule.primaryOptionArray = true;
  68. rule.ruleName = ruleName;
  69. rule.messages = messages;
  70. module.exports = rule;