index.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /**
  2. * Stringfy the given AST `node`.
  3. *
  4. * @param {Object} node
  5. * @param {Object} options
  6. * @return {String}
  7. * @api public
  8. */
  9. module.exports = function(node, options){
  10. return new Compiler(options).compile(node);
  11. };
  12. /**
  13. * Initialize a new `Compiler`.
  14. */
  15. function Compiler(options) {
  16. options = options || {};
  17. this.compress = options.compress;
  18. this.indentation = options.indent;
  19. }
  20. /**
  21. * Compile `node`.
  22. */
  23. Compiler.prototype.compile = function(node){
  24. return node.stylesheet.rules.map(this.visit, this)
  25. .join(this.compress ? '' : '\n\n');
  26. };
  27. /**
  28. * Visit `node`.
  29. */
  30. Compiler.prototype.visit = function(node){
  31. if (node.charset) return this.charset(node);
  32. if (node.keyframes) return this.keyframes(node);
  33. if (node.media) return this.media(node);
  34. if (node.import) return this.import(node);
  35. return this.rule(node);
  36. };
  37. /**
  38. * Visit import node.
  39. */
  40. Compiler.prototype.import = function(node){
  41. return '@import ' + node.import + ';';
  42. };
  43. /**
  44. * Visit media node.
  45. */
  46. Compiler.prototype.media = function(node){
  47. if (this.compress) {
  48. return '@media '
  49. + node.media
  50. + '{'
  51. + node.rules.map(this.visit, this).join('')
  52. + '}';
  53. }
  54. return '@media '
  55. + node.media
  56. + ' {\n'
  57. + this.indent(1)
  58. + node.rules.map(this.visit, this).join('\n\n')
  59. + this.indent(-1)
  60. + '\n}';
  61. };
  62. /**
  63. * Visit charset node.
  64. */
  65. Compiler.prototype.charset = function(node){
  66. if (this.compress) {
  67. return '@charset ' + node.charset + ';';
  68. }
  69. return '@charset ' + node.charset + ';\n';
  70. };
  71. /**
  72. * Visit keyframes node.
  73. */
  74. Compiler.prototype.keyframes = function(node){
  75. if (this.compress) {
  76. return '@'
  77. + (node.vendor || '')
  78. + 'keyframes '
  79. + node.name
  80. + '{'
  81. + node.keyframes.map(this.keyframe, this).join('')
  82. + '}';
  83. }
  84. return '@'
  85. + (node.vendor || '')
  86. + 'keyframes '
  87. + node.name
  88. + ' {\n'
  89. + this.indent(1)
  90. + node.keyframes.map(this.keyframe, this).join('\n')
  91. + this.indent(-1)
  92. + '}';
  93. };
  94. /**
  95. * Visit keyframe node.
  96. */
  97. Compiler.prototype.keyframe = function(node){
  98. if (this.compress) {
  99. return node.values.join(',')
  100. + '{'
  101. + node.declarations.map(this.declaration, this).join(';')
  102. + '}';
  103. }
  104. return this.indent()
  105. + node.values.join(', ')
  106. + ' {\n'
  107. + this.indent(1)
  108. + node.declarations.map(this.declaration, this).join(';\n')
  109. + this.indent(-1)
  110. + '\n' + this.indent() + '}\n';
  111. };
  112. /**
  113. * Visit rule node.
  114. */
  115. Compiler.prototype.rule = function(node){
  116. var indent = this.indent();
  117. if (this.compress) {
  118. return node.selectors.join(',')
  119. + '{'
  120. + node.declarations.map(this.declaration, this).join(';')
  121. + '}';
  122. }
  123. return node.selectors.map(function(s){ return indent + s }).join(',\n')
  124. + ' {\n'
  125. + this.indent(1)
  126. + node.declarations.map(this.declaration, this).join(';\n')
  127. + this.indent(-1)
  128. + '\n' + this.indent() + '}';
  129. };
  130. /**
  131. * Visit declaration node.
  132. */
  133. Compiler.prototype.declaration = function(node){
  134. if (this.compress) {
  135. return node.property + ':' + node.value;
  136. }
  137. return this.indent() + node.property + ': ' + node.value;
  138. };
  139. /**
  140. * Increase, decrease or return current indentation.
  141. */
  142. Compiler.prototype.indent = function(level) {
  143. this.level = this.level || 1;
  144. if (null != level) {
  145. this.level += level;
  146. return '';
  147. }
  148. return Array(this.level).join(this.indentation || ' ');
  149. };