translate.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. function each(list) {
  2. if (list.head === null) {
  3. return '';
  4. }
  5. if (list.head === list.tail) {
  6. return translate(list.head.data);
  7. }
  8. return list.map(translate).join('');
  9. }
  10. function eachDelim(list, delimeter) {
  11. if (list.head === null) {
  12. return '';
  13. }
  14. if (list.head === list.tail) {
  15. return translate(list.head.data);
  16. }
  17. return list.map(translate).join(delimeter);
  18. }
  19. function translate(node) {
  20. switch (node.type) {
  21. case 'StyleSheet':
  22. return each(node.rules);
  23. case 'Atrule':
  24. var nodes = ['@', node.name];
  25. if (node.expression && !node.expression.sequence.isEmpty()) {
  26. nodes.push(' ', translate(node.expression));
  27. }
  28. if (node.block) {
  29. nodes.push('{', translate(node.block), '}');
  30. } else {
  31. nodes.push(';');
  32. }
  33. return nodes.join('');
  34. case 'Ruleset':
  35. return translate(node.selector) + '{' + translate(node.block) + '}';
  36. case 'Selector':
  37. return eachDelim(node.selectors, ',');
  38. case 'SimpleSelector':
  39. var nodes = node.sequence.map(function(node) {
  40. // add extra spaces around /deep/ combinator since comment beginning/ending may to be produced
  41. if (node.type === 'Combinator' && node.name === '/deep/') {
  42. return ' ' + translate(node) + ' ';
  43. }
  44. return translate(node);
  45. });
  46. return nodes.join('');
  47. case 'Block':
  48. return eachDelim(node.declarations, ';');
  49. case 'Declaration':
  50. return translate(node.property) + ':' + translate(node.value);
  51. case 'Property':
  52. return node.name;
  53. case 'Value':
  54. return node.important
  55. ? each(node.sequence) + '!important'
  56. : each(node.sequence);
  57. case 'Attribute':
  58. var result = translate(node.name);
  59. var flagsPrefix = ' ';
  60. if (node.operator !== null) {
  61. result += node.operator;
  62. if (node.value !== null) {
  63. result += translate(node.value);
  64. // space between string and flags is not required
  65. if (node.value.type === 'String') {
  66. flagsPrefix = '';
  67. }
  68. }
  69. }
  70. if (node.flags !== null) {
  71. result += flagsPrefix + node.flags;
  72. }
  73. return '[' + result + ']';
  74. case 'FunctionalPseudo':
  75. return ':' + node.name + '(' + eachDelim(node.arguments, ',') + ')';
  76. case 'Function':
  77. return node.name + '(' + eachDelim(node.arguments, ',') + ')';
  78. case 'Negation':
  79. return ':not(' + eachDelim(node.sequence, ',') + ')';
  80. case 'Braces':
  81. return node.open + each(node.sequence) + node.close;
  82. case 'Argument':
  83. case 'AtruleExpression':
  84. return each(node.sequence);
  85. case 'Url':
  86. return 'url(' + translate(node.value) + ')';
  87. case 'Progid':
  88. return translate(node.value);
  89. case 'Combinator':
  90. return node.name;
  91. case 'Identifier':
  92. return node.name;
  93. case 'PseudoClass':
  94. return ':' + node.name;
  95. case 'PseudoElement':
  96. return '::' + node.name;
  97. case 'Class':
  98. return '.' + node.name;
  99. case 'Id':
  100. return '#' + node.name;
  101. case 'Hash':
  102. return '#' + node.value;
  103. case 'Dimension':
  104. return node.value + node.unit;
  105. case 'Nth':
  106. return node.value;
  107. case 'Number':
  108. return node.value;
  109. case 'String':
  110. return node.value;
  111. case 'Operator':
  112. return node.value;
  113. case 'Raw':
  114. return node.value;
  115. case 'Unknown':
  116. return node.value;
  117. case 'Percentage':
  118. return node.value + '%';
  119. case 'Space':
  120. return ' ';
  121. case 'Comment':
  122. return '/*' + node.value + '*/';
  123. default:
  124. throw new Error('Unknown node type: ' + node.type);
  125. }
  126. }
  127. module.exports = translate;