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.
256 lines
7.0 KiB
256 lines
7.0 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); |
|
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 |
|
};
|
|
|