helpers.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. var lineBreak = require('os').EOL;
  2. var AT_RULE = 'at-rule';
  3. var PROPERTY_SEPARATOR = ';';
  4. function hasMoreProperties(tokens, index) {
  5. for (var i = index, l = tokens.length; i < l; i++) {
  6. if (typeof tokens[i] != 'string')
  7. return true;
  8. }
  9. return false;
  10. }
  11. function supportsAfterClosingBrace(token) {
  12. return token[0][0] == 'background' || token[0][0] == 'transform' || token[0][0] == 'src';
  13. }
  14. function afterClosingBrace(token, valueIndex) {
  15. return token[valueIndex][0][token[valueIndex][0].length - 1] == ')' || token[valueIndex][0].indexOf('__ESCAPED_URL_CLEAN_CSS') === 0;
  16. }
  17. function afterComma(token, valueIndex) {
  18. return token[valueIndex][0] == ',';
  19. }
  20. function afterSlash(token, valueIndex) {
  21. return token[valueIndex][0] == '/';
  22. }
  23. function beforeComma(token, valueIndex) {
  24. return token[valueIndex + 1] && token[valueIndex + 1][0] == ',';
  25. }
  26. function beforeSlash(token, valueIndex) {
  27. return token[valueIndex + 1] && token[valueIndex + 1][0] == '/';
  28. }
  29. function inFilter(token) {
  30. return token[0][0] == 'filter' || token[0][0] == '-ms-filter';
  31. }
  32. function inSpecialContext(token, valueIndex, context) {
  33. return !context.spaceAfterClosingBrace && supportsAfterClosingBrace(token) && afterClosingBrace(token, valueIndex) ||
  34. beforeSlash(token, valueIndex) ||
  35. afterSlash(token, valueIndex) ||
  36. beforeComma(token, valueIndex) ||
  37. afterComma(token, valueIndex);
  38. }
  39. function selectors(tokens, context) {
  40. var store = context.store;
  41. for (var i = 0, l = tokens.length; i < l; i++) {
  42. store(tokens[i], context);
  43. if (i < l - 1)
  44. store(',', context);
  45. }
  46. }
  47. function body(tokens, context) {
  48. for (var i = 0, l = tokens.length; i < l; i++) {
  49. property(tokens, i, i == l - 1, context);
  50. }
  51. }
  52. function property(tokens, position, isLast, context) {
  53. var store = context.store;
  54. var token = tokens[position];
  55. if (typeof token == 'string') {
  56. store(token, context);
  57. } else if (token[0] == AT_RULE) {
  58. propertyAtRule(token[1], false, context);
  59. } else {
  60. store(token[0], context);
  61. store(':', context);
  62. value(tokens, position, isLast, context);
  63. }
  64. }
  65. function propertyAtRule(value, isLast, context) {
  66. var store = context.store;
  67. store(value, context);
  68. if (!isLast)
  69. store(PROPERTY_SEPARATOR, context);
  70. }
  71. function value(tokens, position, isLast, context) {
  72. var store = context.store;
  73. var token = tokens[position];
  74. var isVariableDeclaration = token[0][0].indexOf('--') === 0;
  75. var isBlockVariable = isVariableDeclaration && Array.isArray(token[1][0]);
  76. if (isVariableDeclaration && isBlockVariable && atRulesOrProperties(token[1])) {
  77. store('{', context);
  78. body(token[1], context);
  79. store('};', context);
  80. return;
  81. }
  82. for (var j = 1, m = token.length; j < m; j++) {
  83. store(token[j], context);
  84. if (j < m - 1 && (inFilter(token) || !inSpecialContext(token, j, context))) {
  85. store(' ', context);
  86. } else if (j == m - 1 && !isLast && hasMoreProperties(tokens, position + 1)) {
  87. store(PROPERTY_SEPARATOR, context);
  88. }
  89. }
  90. }
  91. function atRulesOrProperties(values) {
  92. for (var i = 0, l = values.length; i < l; i++) {
  93. if (values[i][0] == AT_RULE || Array.isArray(values[i][0]))
  94. return true;
  95. }
  96. return false;
  97. }
  98. function all(tokens, context) {
  99. var joinCharacter = context.keepBreaks ? lineBreak : '';
  100. var store = context.store;
  101. for (var i = 0, l = tokens.length; i < l; i++) {
  102. var token = tokens[i];
  103. switch (token[0]) {
  104. case 'at-rule':
  105. case 'text':
  106. store(token[1][0], context);
  107. store(joinCharacter, context);
  108. break;
  109. case 'block':
  110. selectors([token[1]], context);
  111. store('{', context);
  112. all(token[2], context);
  113. store('}', context);
  114. store(joinCharacter, context);
  115. break;
  116. case 'flat-block':
  117. selectors([token[1]], context);
  118. store('{', context);
  119. body(token[2], context);
  120. store('}', context);
  121. store(joinCharacter, context);
  122. break;
  123. default:
  124. selectors(token[1], context);
  125. store('{', context);
  126. body(token[2], context);
  127. store('}', context);
  128. store(joinCharacter, context);
  129. }
  130. }
  131. }
  132. module.exports = {
  133. all: all,
  134. body: body,
  135. property: property,
  136. selectors: selectors,
  137. value: value
  138. };