|
|
/**
|
|
* 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 = 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 || ' ');
|
|
};
|