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.
248 lines
7.3 KiB
248 lines
7.3 KiB
var emptyCharacter = '';
|
|
|
|
var Breaks = require('../options/format').Breaks;
|
|
var Spaces = require('../options/format').Spaces;
|
|
|
|
var Marker = require('../tokenizer/marker');
|
|
var Token = require('../tokenizer/token');
|
|
|
|
function supportsAfterClosingBrace(token) {
|
|
return token[1][1] == 'background' || token[1][1] == 'transform' || token[1][1] == 'src';
|
|
}
|
|
|
|
function afterClosingBrace(token, valueIndex) {
|
|
return token[valueIndex][1][token[valueIndex][1].length - 1] == Marker.CLOSE_ROUND_BRACKET;
|
|
}
|
|
|
|
function afterComma(token, valueIndex) {
|
|
return token[valueIndex][1] == Marker.COMMA;
|
|
}
|
|
|
|
function afterSlash(token, valueIndex) {
|
|
return token[valueIndex][1] == Marker.FORWARD_SLASH;
|
|
}
|
|
|
|
function beforeComma(token, valueIndex) {
|
|
return token[valueIndex + 1] && token[valueIndex + 1][1] == Marker.COMMA;
|
|
}
|
|
|
|
function beforeSlash(token, valueIndex) {
|
|
return token[valueIndex + 1] && token[valueIndex + 1][1] == Marker.FORWARD_SLASH;
|
|
}
|
|
|
|
function inFilter(token) {
|
|
return token[1][1] == 'filter' || token[1][1] == '-ms-filter';
|
|
}
|
|
|
|
function disallowsSpace(context, token, valueIndex) {
|
|
return !context.spaceAfterClosingBrace && supportsAfterClosingBrace(token) && afterClosingBrace(token, valueIndex) ||
|
|
beforeSlash(token, valueIndex) ||
|
|
afterSlash(token, valueIndex) ||
|
|
beforeComma(token, valueIndex) ||
|
|
afterComma(token, valueIndex);
|
|
}
|
|
|
|
function rules(context, tokens) {
|
|
var store = context.store;
|
|
|
|
for (var i = 0, l = tokens.length; i < l; i++) {
|
|
store(context, tokens[i]);
|
|
|
|
if (i < l - 1) {
|
|
store(context, comma(context));
|
|
}
|
|
}
|
|
}
|
|
|
|
function body(context, tokens) {
|
|
var lastPropertyAt = lastPropertyIndex(tokens);
|
|
|
|
for (var i = 0, l = tokens.length; i < l; i++) {
|
|
property(context, tokens, i, lastPropertyAt);
|
|
}
|
|
}
|
|
|
|
function lastPropertyIndex(tokens) {
|
|
var index = tokens.length - 1;
|
|
|
|
for (; index >= 0; index--) {
|
|
if (tokens[index][0] != Token.COMMENT) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return index;
|
|
}
|
|
|
|
function property(context, tokens, position, lastPropertyAt) {
|
|
var store = context.store;
|
|
var token = tokens[position];
|
|
|
|
var propertyValue = token[2];
|
|
var isPropertyBlock = propertyValue && propertyValue[0] === Token.PROPERTY_BLOCK;
|
|
|
|
var needsSemicolon;
|
|
if ( context.format ) {
|
|
if ( context.format.semicolonAfterLastProperty || isPropertyBlock ) {
|
|
needsSemicolon = true;
|
|
} else if ( position < lastPropertyAt ) {
|
|
needsSemicolon = true;
|
|
} else {
|
|
needsSemicolon = false;
|
|
}
|
|
} else {
|
|
needsSemicolon = position < lastPropertyAt || isPropertyBlock;
|
|
}
|
|
|
|
var isLast = position === lastPropertyAt;
|
|
|
|
switch (token[0]) {
|
|
case Token.AT_RULE:
|
|
store(context, token);
|
|
store(context, semicolon(context, Breaks.AfterProperty, false));
|
|
break;
|
|
case Token.AT_RULE_BLOCK:
|
|
rules(context, token[1]);
|
|
store(context, openBrace(context, Breaks.AfterRuleBegins, true));
|
|
body(context, token[2]);
|
|
store(context, closeBrace(context, Breaks.AfterRuleEnds, false, isLast));
|
|
break;
|
|
case Token.COMMENT:
|
|
store(context, token);
|
|
break;
|
|
case Token.PROPERTY:
|
|
store(context, token[1]);
|
|
store(context, colon(context));
|
|
if (propertyValue) {
|
|
value(context, token);
|
|
}
|
|
store(context, needsSemicolon ? semicolon(context, Breaks.AfterProperty, isLast) : emptyCharacter);
|
|
break;
|
|
case Token.RAW:
|
|
store(context, token);
|
|
}
|
|
}
|
|
|
|
function value(context, token) {
|
|
var store = context.store;
|
|
var j, m;
|
|
|
|
if (token[2][0] == Token.PROPERTY_BLOCK) {
|
|
store(context, openBrace(context, Breaks.AfterBlockBegins, false));
|
|
body(context, token[2][1]);
|
|
store(context, closeBrace(context, Breaks.AfterBlockEnds, false, true));
|
|
} else {
|
|
for (j = 2, m = token.length; j < m; j++) {
|
|
store(context, token[j]);
|
|
|
|
if (j < m - 1 && (inFilter(token) || !disallowsSpace(context, token, j))) {
|
|
store(context, Marker.SPACE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function allowsBreak(context, where) {
|
|
return context.format && context.format.breaks[where];
|
|
}
|
|
|
|
function allowsSpace(context, where) {
|
|
return context.format && context.format.spaces[where];
|
|
}
|
|
|
|
function openBrace(context, where, needsPrefixSpace) {
|
|
if (context.format) {
|
|
context.indentBy += context.format.indentBy;
|
|
context.indentWith = context.format.indentWith.repeat(context.indentBy);
|
|
return (needsPrefixSpace && allowsSpace(context, Spaces.BeforeBlockBegins) ? Marker.SPACE : emptyCharacter) +
|
|
Marker.OPEN_CURLY_BRACKET +
|
|
(allowsBreak(context, where) ? context.format.breakWith : emptyCharacter) +
|
|
context.indentWith;
|
|
} else {
|
|
return Marker.OPEN_CURLY_BRACKET;
|
|
}
|
|
}
|
|
|
|
function closeBrace(context, where, beforeBlockEnd, isLast) {
|
|
if (context.format) {
|
|
context.indentBy -= context.format.indentBy;
|
|
context.indentWith = context.format.indentWith.repeat(context.indentBy);
|
|
return (allowsBreak(context, Breaks.AfterProperty) || beforeBlockEnd && allowsBreak(context, Breaks.BeforeBlockEnds) ? context.format.breakWith : emptyCharacter) +
|
|
context.indentWith +
|
|
Marker.CLOSE_CURLY_BRACKET +
|
|
(isLast ? emptyCharacter : (allowsBreak(context, where) ? context.format.breakWith : emptyCharacter) + context.indentWith);
|
|
} else {
|
|
return Marker.CLOSE_CURLY_BRACKET;
|
|
}
|
|
}
|
|
|
|
function colon(context) {
|
|
return context.format ?
|
|
Marker.COLON + (allowsSpace(context, Spaces.BeforeValue) ? Marker.SPACE : emptyCharacter) :
|
|
Marker.COLON;
|
|
}
|
|
|
|
function semicolon(context, where, isLast) {
|
|
return context.format ?
|
|
Marker.SEMICOLON + (isLast || !allowsBreak(context, where) ? emptyCharacter : context.format.breakWith + context.indentWith) :
|
|
Marker.SEMICOLON;
|
|
}
|
|
|
|
function comma(context) {
|
|
return context.format ?
|
|
Marker.COMMA + (allowsBreak(context, Breaks.BetweenSelectors) ? context.format.breakWith : emptyCharacter) + context.indentWith :
|
|
Marker.COMMA;
|
|
}
|
|
|
|
function all(context, tokens) {
|
|
var store = context.store;
|
|
var token;
|
|
var isLast;
|
|
var i, l;
|
|
|
|
for (i = 0, l = tokens.length; i < l; i++) {
|
|
token = tokens[i];
|
|
isLast = i == l - 1;
|
|
|
|
switch (token[0]) {
|
|
case Token.AT_RULE:
|
|
store(context, token);
|
|
store(context, semicolon(context, Breaks.AfterAtRule, isLast));
|
|
break;
|
|
case Token.AT_RULE_BLOCK:
|
|
rules(context, token[1]);
|
|
store(context, openBrace(context, Breaks.AfterRuleBegins, true));
|
|
body(context, token[2]);
|
|
store(context, closeBrace(context, Breaks.AfterRuleEnds, false, isLast));
|
|
break;
|
|
case Token.NESTED_BLOCK:
|
|
rules(context, token[1]);
|
|
store(context, openBrace(context, Breaks.AfterBlockBegins, true));
|
|
all(context, token[2]);
|
|
store(context, closeBrace(context, Breaks.AfterBlockEnds, true, isLast));
|
|
break;
|
|
case Token.COMMENT:
|
|
store(context, token);
|
|
store(context, allowsBreak(context, Breaks.AfterComment) ? context.format.breakWith : emptyCharacter);
|
|
break;
|
|
case Token.RAW:
|
|
store(context, token);
|
|
break;
|
|
case Token.RULE:
|
|
rules(context, token[1]);
|
|
store(context, openBrace(context, Breaks.AfterRuleBegins, true));
|
|
body(context, token[2]);
|
|
store(context, closeBrace(context, Breaks.AfterRuleEnds, false, isLast));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
all: all,
|
|
body: body,
|
|
property: property,
|
|
rules: rules,
|
|
value: value
|
|
};
|