utils.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. var hasOwnProperty = Object.prototype.hasOwnProperty;
  2. function isEqualLists(a, b) {
  3. var cursor1 = a.head;
  4. var cursor2 = b.head;
  5. while (cursor1 !== null && cursor2 !== null && cursor1.data.id === cursor2.data.id) {
  6. cursor1 = cursor1.next;
  7. cursor2 = cursor2.next;
  8. }
  9. return cursor1 === null && cursor2 === null;
  10. }
  11. function isEqualDeclarations(a, b) {
  12. var cursor1 = a.head;
  13. var cursor2 = b.head;
  14. while (cursor1 !== null && cursor2 !== null && cursor1.data.id === cursor2.data.id) {
  15. cursor1 = cursor1.next;
  16. cursor2 = cursor2.next;
  17. }
  18. return cursor1 === null && cursor2 === null;
  19. }
  20. function compareDeclarations(declarations1, declarations2) {
  21. var result = {
  22. eq: [],
  23. ne1: [],
  24. ne2: [],
  25. ne2overrided: []
  26. };
  27. var fingerprints = Object.create(null);
  28. var declarations2hash = Object.create(null);
  29. for (var cursor = declarations2.head; cursor; cursor = cursor.next) {
  30. declarations2hash[cursor.data.id] = true;
  31. }
  32. for (var cursor = declarations1.head; cursor; cursor = cursor.next) {
  33. var data = cursor.data;
  34. if (data.fingerprint) {
  35. fingerprints[data.fingerprint] = data.value.important;
  36. }
  37. if (declarations2hash[data.id]) {
  38. declarations2hash[data.id] = false;
  39. result.eq.push(data);
  40. } else {
  41. result.ne1.push(data);
  42. }
  43. }
  44. for (var cursor = declarations2.head; cursor; cursor = cursor.next) {
  45. var data = cursor.data;
  46. if (declarations2hash[data.id]) {
  47. // if declarations1 has overriding declaration, this is not a difference
  48. // but take in account !important - prev should be equal or greater than follow
  49. if (hasOwnProperty.call(fingerprints, data.fingerprint) &&
  50. Number(fingerprints[data.fingerprint]) >= Number(data.value.important)) {
  51. result.ne2overrided.push(data);
  52. } else {
  53. result.ne2.push(data);
  54. }
  55. }
  56. }
  57. return result;
  58. }
  59. function addSelectors(dest, source) {
  60. source.each(function(sourceData) {
  61. var newStr = sourceData.id;
  62. var cursor = dest.head;
  63. while (cursor) {
  64. var nextStr = cursor.data.id;
  65. if (nextStr === newStr) {
  66. return;
  67. }
  68. if (nextStr > newStr) {
  69. break;
  70. }
  71. cursor = cursor.next;
  72. }
  73. dest.insert(dest.createItem(sourceData), cursor);
  74. });
  75. return dest;
  76. }
  77. // check if simpleselectors has no equal specificity and element selector
  78. function hasSimilarSelectors(selectors1, selectors2) {
  79. return selectors1.some(function(a) {
  80. return selectors2.some(function(b) {
  81. return a.compareMarker === b.compareMarker;
  82. });
  83. });
  84. }
  85. // test node can't to be skipped
  86. function unsafeToSkipNode(node) {
  87. switch (node.type) {
  88. case 'Ruleset':
  89. // unsafe skip ruleset with selector similarities
  90. return hasSimilarSelectors(node.selector.selectors, this);
  91. case 'Atrule':
  92. // can skip at-rules with blocks
  93. if (node.block) {
  94. // non-stylesheet blocks are safe to skip since have no selectors
  95. if (node.block.type !== 'StyleSheet') {
  96. return false;
  97. }
  98. // unsafe skip at-rule if block contains something unsafe to skip
  99. return node.block.rules.some(unsafeToSkipNode, this);
  100. }
  101. break;
  102. }
  103. // unsafe by default
  104. return true;
  105. }
  106. module.exports = {
  107. isEqualLists: isEqualLists,
  108. isEqualDeclarations: isEqualDeclarations,
  109. compareDeclarations: compareDeclarations,
  110. addSelectors: addSelectors,
  111. hasSimilarSelectors: hasSimilarSelectors,
  112. unsafeToSkipNode: unsafeToSkipNode
  113. };