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.

257 lines
7.0 KiB

2 years ago
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);
store(context, breakFor(context, Breaks.AfterComment) + context.indentWith);
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 breakFor(context, where) {
return context.format ? context.format.breaks[where] : emptyCharacter;
}
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
+ breakFor(context, where)
+ context.indentWith;
}
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 (
beforeBlockEnd
? breakFor(context, Breaks.BeforeBlockEnds)
: breakFor(context, Breaks.AfterProperty)
) + context.indentWith
+ Marker.CLOSE_CURLY_BRACKET
+ (isLast ? emptyCharacter : breakFor(context, where) + context.indentWith);
}
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 ? emptyCharacter : (breakFor(context, where) + context.indentWith))
: Marker.SEMICOLON;
}
function comma(context) {
return context.format
? Marker.COMMA + breakFor(context, Breaks.BetweenSelectors) + 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, breakFor(context, Breaks.AfterComment) + context.indentWith);
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
};