index.js 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. const postcss = require('postcss');
  2. const createExpectedPropertiesOrder = require('../createExpectedPropertiesOrder');
  3. const getComments = require('../getComments');
  4. const getPropertiesOrderData = require('../getPropertiesOrderData');
  5. const getContainingNode = require('../getContainingNode');
  6. const isCustomProperty = require('../isCustomProperty');
  7. const isRuleWithNodes = require('../isRuleWithNodes');
  8. const isStandardSyntaxProperty = require('../isStandardSyntaxProperty');
  9. const sorting = require('../sorting');
  10. module.exports = function(css, opts) {
  11. const isAlphabetical = opts['properties-order'] === 'alphabetical';
  12. const expectedOrder = isAlphabetical
  13. ? null
  14. : createExpectedPropertiesOrder(opts['properties-order']);
  15. let unspecifiedPropertiesPosition = opts['unspecified-properties-position'];
  16. if (!unspecifiedPropertiesPosition) {
  17. unspecifiedPropertiesPosition = 'bottom';
  18. }
  19. css.walk(function(input) {
  20. const node = getContainingNode(input);
  21. if (isRuleWithNodes(node)) {
  22. const allRuleNodes = [];
  23. let declarations = [];
  24. node.each(function(childNode, index) {
  25. if (
  26. childNode.type === 'decl' &&
  27. isStandardSyntaxProperty(childNode.prop) &&
  28. !isCustomProperty(childNode.prop)
  29. ) {
  30. let unprefixedPropName = postcss.vendor.unprefixed(childNode.prop);
  31. // Hack to allow -moz-osx-font-smoothing to be understood
  32. // just like -webkit-font-smoothing
  33. if (unprefixedPropName.indexOf('osx-') === 0) {
  34. unprefixedPropName = unprefixedPropName.slice(4);
  35. }
  36. const propData = {
  37. name: childNode.prop,
  38. unprefixedName: unprefixedPropName,
  39. orderData: isAlphabetical
  40. ? null
  41. : getPropertiesOrderData(expectedOrder, unprefixedPropName),
  42. node: childNode,
  43. initialIndex: index,
  44. unspecifiedPropertiesPosition,
  45. };
  46. // add a marker
  47. childNode.sortProperty = true;
  48. // If comment on separate line before node, use node's indexes for comment
  49. const commentsBefore = getComments.beforeDeclaration([], childNode.prev(), propData);
  50. // If comment on same line with the node and node, use node's indexes for comment
  51. const commentsAfter = getComments.afterDeclaration([], childNode.next(), propData);
  52. declarations = declarations.concat(commentsBefore, propData, commentsAfter);
  53. }
  54. });
  55. if (isAlphabetical) {
  56. declarations.sort(sorting.sortDeclarationsAlphabetically);
  57. } else {
  58. declarations.sort(sorting.sortDeclarations);
  59. }
  60. let foundDeclarations = false;
  61. node.each(function(childNode) {
  62. if (childNode.sortProperty) {
  63. if (!foundDeclarations) {
  64. foundDeclarations = true;
  65. declarations.forEach(item => {
  66. allRuleNodes.push(item.node);
  67. });
  68. }
  69. } else {
  70. allRuleNodes.push(childNode);
  71. }
  72. });
  73. node.removeAll();
  74. node.append(allRuleNodes);
  75. }
  76. });
  77. };