/** * Module dependencies. */ var Base = require('./compiler'); var inherits = require('inherits'); /** * Expose compiler. */ module.exports = Compiler; /** * Initialize a new `Compiler`. */ function Compiler(options) { options = options || {}; Base.call(this, options); this.indentation = typeof options.indent === 'string' ? options.indent : ' '; } /** * Inherit from `Base.prototype`. */ inherits(Compiler, Base); /** * Compile `node`. */ Compiler.prototype.compile = function(node){ return this.stylesheet(node); }; /** * Visit stylesheet node. */ Compiler.prototype.stylesheet = function(node){ return this.mapVisit(node.stylesheet.rules, '\n\n'); }; /** * Visit comment node. */ Compiler.prototype.comment = function(node){ return this.emit(this.indent() + '/*' + node.comment + '*/', node.position); }; /** * Visit import node. */ Compiler.prototype.import = function(node){ return this.emit('@import ' + node.import + ';', node.position); }; /** * Visit media node. */ Compiler.prototype.media = function(node){ return this.emit('@media ' + node.media, node.position) + this.emit( ' {\n' + this.indent(1)) + this.mapVisit(node.rules, '\n\n') + this.emit( this.indent(-1) + '\n}'); }; /** * Visit document node. */ Compiler.prototype.document = function(node){ var doc = '@' + (node.vendor || '') + 'document ' + node.document; return this.emit(doc, node.position) + this.emit( ' ' + ' {\n' + this.indent(1)) + this.mapVisit(node.rules, '\n\n') + this.emit( this.indent(-1) + '\n}'); }; /** * Visit charset node. */ Compiler.prototype.charset = function(node){ return this.emit('@charset ' + node.charset + ';', node.position); }; /** * Visit namespace node. */ Compiler.prototype.namespace = function(node){ return this.emit('@namespace ' + node.namespace + ';', node.position); }; /** * Visit supports node. */ Compiler.prototype.supports = function(node){ return this.emit('@supports ' + node.supports, node.position) + this.emit( ' {\n' + this.indent(1)) + this.mapVisit(node.rules, '\n\n') + this.emit( this.indent(-1) + '\n}'); }; /** * Visit keyframes node. */ Compiler.prototype.keyframes = function(node){ return this.emit('@' + (node.vendor || '') + 'keyframes ' + node.name, node.position) + this.emit( ' {\n' + this.indent(1)) + this.mapVisit(node.keyframes, '\n') + this.emit( this.indent(-1) + '}'); }; /** * Visit keyframe node. */ Compiler.prototype.keyframe = function(node){ var decls = node.declarations; return this.emit(this.indent()) + this.emit(node.values.join(', '), node.position) + this.emit( ' {\n' + this.indent(1)) + this.mapVisit(decls, '\n') + this.emit( this.indent(-1) + '\n' + this.indent() + '}\n'); }; /** * Visit page node. */ Compiler.prototype.page = function(node){ var sel = node.selectors.length ? node.selectors.join(', ') + ' ' : ''; return this.emit('@page ' + sel, node.position) + this.emit('{\n') + this.emit(this.indent(1)) + this.mapVisit(node.declarations, '\n') + this.emit(this.indent(-1)) + this.emit('\n}'); }; /** * Visit font-face node. */ Compiler.prototype['font-face'] = function(node){ return this.emit('@font-face ', node.position) + this.emit('{\n') + this.emit(this.indent(1)) + this.mapVisit(node.declarations, '\n') + this.emit(this.indent(-1)) + this.emit('\n}'); }; /** * Visit host node. */ Compiler.prototype.host = function(node){ return this.emit('@host', node.position) + this.emit( ' {\n' + this.indent(1)) + this.mapVisit(node.rules, '\n\n') + this.emit( this.indent(-1) + '\n}'); }; /** * Visit custom-media node. */ Compiler.prototype['custom-media'] = function(node){ return this.emit('@custom-media ' + node.name + ' ' + node.media + ';', node.position); }; /** * Visit rule node. */ Compiler.prototype.rule = function(node){ var indent = this.indent(); var decls = node.declarations; if (!decls.length) return ''; return this.emit(node.selectors.map(function(s){ return indent + s }).join(',\n'), node.position) + this.emit(' {\n') + this.emit(this.indent(1)) + this.mapVisit(decls, '\n') + this.emit(this.indent(-1)) + this.emit('\n' + this.indent() + '}'); }; /** * Visit declaration node. */ Compiler.prototype.declaration = function(node){ return this.emit(this.indent()) + this.emit(node.property + ': ' + node.value, node.position) + this.emit(';'); }; /** * Increase, decrease or return current indentation. */ Compiler.prototype.indent = function(level) { this.level = this.level || 1; if (null != level) { this.level += level; return ''; } return Array(this.level).join(this.indentation); };