optimize.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. var mergeAdjacent = require('./merge-adjacent');
  2. var mergeMediaQueries = require('./merge-media-queries');
  3. var mergeNonAdjacentByBody = require('./merge-non-adjacent-by-body');
  4. var mergeNonAdjacentBySelector = require('./merge-non-adjacent-by-selector');
  5. var reduceNonAdjacent = require('./reduce-non-adjacent');
  6. var removeDuplicateFontAtRules = require('./remove-duplicate-font-at-rules');
  7. var removeDuplicateMediaQueries = require('./remove-duplicate-media-queries');
  8. var removeDuplicates = require('./remove-duplicates');
  9. var removeUnusedAtRules = require('./remove-unused-at-rules');
  10. var restructure = require('./restructure');
  11. var optimizeProperties = require('./properties/optimize');
  12. var OptimizationLevel = require('../../options/optimization-level').OptimizationLevel;
  13. var Token = require('../../tokenizer/token');
  14. function removeEmpty(tokens) {
  15. for (var i = 0, l = tokens.length; i < l; i++) {
  16. var token = tokens[i];
  17. var isEmpty = false;
  18. switch (token[0]) {
  19. case Token.RULE:
  20. isEmpty = token[1].length === 0 || token[2].length === 0;
  21. break;
  22. case Token.NESTED_BLOCK:
  23. removeEmpty(token[2]);
  24. isEmpty = token[2].length === 0;
  25. break;
  26. case Token.AT_RULE:
  27. isEmpty = token[1].length === 0;
  28. break;
  29. case Token.AT_RULE_BLOCK:
  30. isEmpty = token[2].length === 0;
  31. }
  32. if (isEmpty) {
  33. tokens.splice(i, 1);
  34. i--;
  35. l--;
  36. }
  37. }
  38. }
  39. function recursivelyOptimizeBlocks(tokens, context) {
  40. for (var i = 0, l = tokens.length; i < l; i++) {
  41. var token = tokens[i];
  42. if (token[0] == Token.NESTED_BLOCK) {
  43. var isKeyframes = /@(-moz-|-o-|-webkit-)?keyframes/.test(token[1][0][1]);
  44. level2Optimize(token[2], context, !isKeyframes);
  45. }
  46. }
  47. }
  48. function recursivelyOptimizeProperties(tokens, context) {
  49. for (var i = 0, l = tokens.length; i < l; i++) {
  50. var token = tokens[i];
  51. switch (token[0]) {
  52. case Token.RULE:
  53. optimizeProperties(token[2], true, true, context);
  54. break;
  55. case Token.NESTED_BLOCK:
  56. recursivelyOptimizeProperties(token[2], context);
  57. }
  58. }
  59. }
  60. function level2Optimize(tokens, context, withRestructuring) {
  61. var levelOptions = context.options.level[OptimizationLevel.Two];
  62. var reduced;
  63. var i;
  64. recursivelyOptimizeBlocks(tokens, context);
  65. recursivelyOptimizeProperties(tokens, context);
  66. if (levelOptions.removeDuplicateRules) {
  67. removeDuplicates(tokens, context);
  68. }
  69. if (levelOptions.mergeAdjacentRules) {
  70. mergeAdjacent(tokens, context);
  71. }
  72. if (levelOptions.reduceNonAdjacentRules) {
  73. reduceNonAdjacent(tokens, context);
  74. }
  75. if (levelOptions.mergeNonAdjacentRules && levelOptions.mergeNonAdjacentRules != 'body') {
  76. mergeNonAdjacentBySelector(tokens, context);
  77. }
  78. if (levelOptions.mergeNonAdjacentRules && levelOptions.mergeNonAdjacentRules != 'selector') {
  79. mergeNonAdjacentByBody(tokens, context);
  80. }
  81. if (levelOptions.restructureRules && levelOptions.mergeAdjacentRules && withRestructuring) {
  82. restructure(tokens, context);
  83. mergeAdjacent(tokens, context);
  84. }
  85. if (levelOptions.restructureRules && !levelOptions.mergeAdjacentRules && withRestructuring) {
  86. restructure(tokens, context);
  87. }
  88. if (levelOptions.removeDuplicateFontRules) {
  89. removeDuplicateFontAtRules(tokens, context);
  90. }
  91. if (levelOptions.removeDuplicateMediaBlocks) {
  92. removeDuplicateMediaQueries(tokens, context);
  93. }
  94. if (levelOptions.removeUnusedAtRules) {
  95. removeUnusedAtRules(tokens, context);
  96. }
  97. if (levelOptions.mergeMedia) {
  98. reduced = mergeMediaQueries(tokens, context);
  99. for (i = reduced.length - 1; i >= 0; i--) {
  100. level2Optimize(reduced[i][2], context, false);
  101. }
  102. }
  103. if (levelOptions.removeEmpty) {
  104. removeEmpty(tokens);
  105. }
  106. return tokens;
  107. }
  108. module.exports = level2Optimize;