checkNode.js 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. const stylelint = require('stylelint');
  2. const postcss = require('postcss');
  3. const postcssSorting = require('postcss-sorting');
  4. const checkOrder = require('./checkOrder');
  5. const getOrderData = require('./getOrderData');
  6. const ruleName = require('./ruleName');
  7. const messages = require('./messages');
  8. module.exports = function checkNode({
  9. node,
  10. originalNode,
  11. isFixEnabled,
  12. orderInfo,
  13. primaryOption,
  14. result,
  15. unspecified,
  16. }) {
  17. if (isFixEnabled) {
  18. let shouldFix = false;
  19. let allNodesData = [];
  20. node.each(function processEveryNode(child) {
  21. // return early if we know there is a violation and auto fix should be applied
  22. if (shouldFix) {
  23. return;
  24. }
  25. let { shouldSkip, isCorrectOrder } = handleCycle(child, allNodesData);
  26. if (shouldSkip) {
  27. return;
  28. }
  29. if (!isCorrectOrder) {
  30. shouldFix = true;
  31. }
  32. });
  33. if (shouldFix) {
  34. let sortingOptions = {
  35. order: primaryOption,
  36. };
  37. // creating PostCSS Root node with current node as a child,
  38. // so PostCSS Sorting can process it
  39. let tempRoot = postcss.root({ nodes: [originalNode] });
  40. postcssSorting(sortingOptions)(tempRoot);
  41. }
  42. }
  43. let allNodesData = [];
  44. node.each(function processEveryNode(child) {
  45. let { shouldSkip, isCorrectOrder, nodeData, previousNodeData } = handleCycle(
  46. child,
  47. allNodesData
  48. );
  49. if (shouldSkip) {
  50. return;
  51. }
  52. if (isCorrectOrder) {
  53. return;
  54. }
  55. stylelint.utils.report({
  56. message: messages.expected(nodeData.description, previousNodeData.description),
  57. node: child,
  58. result,
  59. ruleName,
  60. });
  61. });
  62. function handleCycle(child, allNodes) {
  63. // Skip comments
  64. if (child.type === 'comment') {
  65. return {
  66. shouldSkip: true,
  67. };
  68. }
  69. // Receive node description and expectedPosition
  70. let nodeOrderData = getOrderData(orderInfo, child);
  71. let nodeData = {
  72. node: child,
  73. description: nodeOrderData.description,
  74. expectedPosition: nodeOrderData.expectedPosition,
  75. };
  76. allNodes.push(nodeData);
  77. let previousNodeData = allNodes[allNodes.length - 2];
  78. // Skip first node
  79. if (!previousNodeData) {
  80. return {
  81. shouldSkip: true,
  82. };
  83. }
  84. return {
  85. isCorrectOrder: checkOrder({
  86. firstNodeData: previousNodeData,
  87. secondNodeData: nodeData,
  88. allNodesData: allNodes,
  89. isFixEnabled,
  90. result,
  91. unspecified,
  92. }),
  93. nodeData,
  94. previousNodeData,
  95. };
  96. }
  97. };