You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

254 lines
4.8 KiB

4 years ago
  1. /**
  2. * Module dependencies.
  3. */
  4. var Base = require('./compiler');
  5. var inherits = require('inherits');
  6. /**
  7. * Expose compiler.
  8. */
  9. module.exports = Compiler;
  10. /**
  11. * Initialize a new `Compiler`.
  12. */
  13. function Compiler(options) {
  14. options = options || {};
  15. Base.call(this, options);
  16. this.indentation = options.indent;
  17. }
  18. /**
  19. * Inherit from `Base.prototype`.
  20. */
  21. inherits(Compiler, Base);
  22. /**
  23. * Compile `node`.
  24. */
  25. Compiler.prototype.compile = function(node){
  26. return this.stylesheet(node);
  27. };
  28. /**
  29. * Visit stylesheet node.
  30. */
  31. Compiler.prototype.stylesheet = function(node){
  32. return this.mapVisit(node.stylesheet.rules, '\n\n');
  33. };
  34. /**
  35. * Visit comment node.
  36. */
  37. Compiler.prototype.comment = function(node){
  38. return this.emit(this.indent() + '/*' + node.comment + '*/', node.position);
  39. };
  40. /**
  41. * Visit import node.
  42. */
  43. Compiler.prototype.import = function(node){
  44. return this.emit('@import ' + node.import + ';', node.position);
  45. };
  46. /**
  47. * Visit media node.
  48. */
  49. Compiler.prototype.media = function(node){
  50. return this.emit('@media ' + node.media, node.position)
  51. + this.emit(
  52. ' {\n'
  53. + this.indent(1))
  54. + this.mapVisit(node.rules, '\n\n')
  55. + this.emit(
  56. this.indent(-1)
  57. + '\n}');
  58. };
  59. /**
  60. * Visit document node.
  61. */
  62. Compiler.prototype.document = function(node){
  63. var doc = '@' + (node.vendor || '') + 'document ' + node.document;
  64. return this.emit(doc, node.position)
  65. + this.emit(
  66. ' '
  67. + ' {\n'
  68. + this.indent(1))
  69. + this.mapVisit(node.rules, '\n\n')
  70. + this.emit(
  71. this.indent(-1)
  72. + '\n}');
  73. };
  74. /**
  75. * Visit charset node.
  76. */
  77. Compiler.prototype.charset = function(node){
  78. return this.emit('@charset ' + node.charset + ';', node.position);
  79. };
  80. /**
  81. * Visit namespace node.
  82. */
  83. Compiler.prototype.namespace = function(node){
  84. return this.emit('@namespace ' + node.namespace + ';', node.position);
  85. };
  86. /**
  87. * Visit supports node.
  88. */
  89. Compiler.prototype.supports = function(node){
  90. return this.emit('@supports ' + node.supports, node.position)
  91. + this.emit(
  92. ' {\n'
  93. + this.indent(1))
  94. + this.mapVisit(node.rules, '\n\n')
  95. + this.emit(
  96. this.indent(-1)
  97. + '\n}');
  98. };
  99. /**
  100. * Visit keyframes node.
  101. */
  102. Compiler.prototype.keyframes = function(node){
  103. return this.emit('@' + (node.vendor || '') + 'keyframes ' + node.name, node.position)
  104. + this.emit(
  105. ' {\n'
  106. + this.indent(1))
  107. + this.mapVisit(node.keyframes, '\n')
  108. + this.emit(
  109. this.indent(-1)
  110. + '}');
  111. };
  112. /**
  113. * Visit keyframe node.
  114. */
  115. Compiler.prototype.keyframe = function(node){
  116. var decls = node.declarations;
  117. return this.emit(this.indent())
  118. + this.emit(node.values.join(', '), node.position)
  119. + this.emit(
  120. ' {\n'
  121. + this.indent(1))
  122. + this.mapVisit(decls, '\n')
  123. + this.emit(
  124. this.indent(-1)
  125. + '\n'
  126. + this.indent() + '}\n');
  127. };
  128. /**
  129. * Visit page node.
  130. */
  131. Compiler.prototype.page = function(node){
  132. var sel = node.selectors.length
  133. ? node.selectors.join(', ') + ' '
  134. : '';
  135. return this.emit('@page ' + sel, node.position)
  136. + this.emit('{\n')
  137. + this.emit(this.indent(1))
  138. + this.mapVisit(node.declarations, '\n')
  139. + this.emit(this.indent(-1))
  140. + this.emit('\n}');
  141. };
  142. /**
  143. * Visit font-face node.
  144. */
  145. Compiler.prototype['font-face'] = function(node){
  146. return this.emit('@font-face ', node.position)
  147. + this.emit('{\n')
  148. + this.emit(this.indent(1))
  149. + this.mapVisit(node.declarations, '\n')
  150. + this.emit(this.indent(-1))
  151. + this.emit('\n}');
  152. };
  153. /**
  154. * Visit host node.
  155. */
  156. Compiler.prototype.host = function(node){
  157. return this.emit('@host', node.position)
  158. + this.emit(
  159. ' {\n'
  160. + this.indent(1))
  161. + this.mapVisit(node.rules, '\n\n')
  162. + this.emit(
  163. this.indent(-1)
  164. + '\n}');
  165. };
  166. /**
  167. * Visit custom-media node.
  168. */
  169. Compiler.prototype['custom-media'] = function(node){
  170. return this.emit('@custom-media ' + node.name + ' ' + node.media + ';', node.position);
  171. };
  172. /**
  173. * Visit rule node.
  174. */
  175. Compiler.prototype.rule = function(node){
  176. var indent = this.indent();
  177. var decls = node.declarations;
  178. if (!decls.length) return '';
  179. return this.emit(node.selectors.map(function(s){ return indent + s }).join(',\n'), node.position)
  180. + this.emit(' {\n')
  181. + this.emit(this.indent(1))
  182. + this.mapVisit(decls, '\n')
  183. + this.emit(this.indent(-1))
  184. + this.emit('\n' + this.indent() + '}');
  185. };
  186. /**
  187. * Visit declaration node.
  188. */
  189. Compiler.prototype.declaration = function(node){
  190. return this.emit(this.indent())
  191. + this.emit(node.property + ': ' + node.value, node.position)
  192. + this.emit(';');
  193. };
  194. /**
  195. * Increase, decrease or return current indentation.
  196. */
  197. Compiler.prototype.indent = function(level) {
  198. this.level = this.level || 1;
  199. if (null != level) {
  200. this.level += level;
  201. return '';
  202. }
  203. return Array(this.level).join(this.indentation || ' ');
  204. };