beautify-css.js: 1.6.12

This commit is contained in:
tophf 2017-03-29 02:59:10 +03:00
parent 1cfd2752d5
commit 1fcac0ddf4

View File

@ -3,7 +3,7 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2007-2013 Einar Lielmanis and contributors. Copyright (c) 2007-2017 Einar Lielmanis, Liam Newman, and contributors.
Permission is hereby granted, free of charge, to any person Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation files obtaining a copy of this software and associated documentation files
@ -39,13 +39,15 @@
css_beautify(source_text, options); css_beautify(source_text, options);
The options are (default in brackets): The options are (default in brackets):
indent_size (4) indentation size, indent_size (4) indentation size,
indent_char (space) character to indent with, indent_char (space) character to indent with,
selector_separator_newline (true) - separate selectors with newline or preserve_newlines (default false) - whether existing line breaks should be preserved,
not (e.g. "a,\nbr" or "a, br") selector_separator_newline (true) - separate selectors with newline or
end_with_newline (false) - end with a newline not (e.g. "a,\nbr" or "a, br")
newline_between_rules (true) - add a new line after every css rule end_with_newline (false) - end with a newline
newline_between_rules (true) - add a new line after every css rule
space_around_selector_separator (false) - ensure space around selector separators:
'>', '+', '~' (e.g. "a>b" -> "a > b")
e.g e.g
css_beautify(css_source_text, { css_beautify(css_source_text, {
@ -53,7 +55,8 @@
'indent_char': '\t', 'indent_char': '\t',
'selector_separator': ' ', 'selector_separator': ' ',
'end_with_newline': false, 'end_with_newline': false,
'newline_between_rules': true 'newline_between_rules': true,
'space_around_selector_separator': true
}); });
*/ */
@ -61,23 +64,69 @@
// http://www.w3.org/TR/css3-syntax/ // http://www.w3.org/TR/css3-syntax/
(function() { (function() {
function css_beautify(source_text, options) {
options = options || {};
var indentSize = options.indent_size || 4;
var indentCharacter = options.indent_char || ' ';
var selectorSeparatorNewline = (options.selector_separator_newline === undefined) ? true : options.selector_separator_newline;
var end_with_newline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
var newline_between_rules = (options.newline_between_rules === undefined) ? true : options.newline_between_rules;
// compatibility function mergeOpts(allOptions, targetType) {
if (typeof indentSize === "string") { var finalOpts = {};
indentSize = parseInt(indentSize, 10); var name;
for (name in allOptions) {
if (name !== targetType) {
finalOpts[name] = allOptions[name];
}
} }
//merge in the per type settings for the targetType
if (targetType in allOptions) {
for (name in allOptions[targetType]) {
finalOpts[name] = allOptions[targetType][name];
}
}
return finalOpts;
}
var lineBreak = /\r\n|[\n\r\u2028\u2029]/;
var allLineBreaks = new RegExp(lineBreak.source, 'g');
function css_beautify(source_text, options) {
options = options || {};
// Allow the setting of language/file-type specific options
// with inheritance of overall settings
options = mergeOpts(options, 'css');
source_text = source_text || '';
var newlinesFromLastWSEat = 0;
var indentSize = options.indent_size ? parseInt(options.indent_size, 10) : 4;
var indentCharacter = options.indent_char || ' ';
var preserve_newlines = (options.preserve_newlines === undefined) ? false : options.preserve_newlines;
var selectorSeparatorNewline = (options.selector_separator_newline === undefined) ? true : options.selector_separator_newline;
var end_with_newline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
var newline_between_rules = (options.newline_between_rules === undefined) ? true : options.newline_between_rules;
var space_around_combinator = (options.space_around_combinator === undefined) ? false : options.space_around_combinator;
space_around_combinator = space_around_combinator || ((options.space_around_selector_separator === undefined) ? false : options.space_around_selector_separator);
var eol = options.eol ? options.eol : 'auto';
if (options.indent_with_tabs) {
indentCharacter = '\t';
indentSize = 1;
}
if (eol === 'auto') {
eol = '\n';
if (source_text && lineBreak.test(source_text || '')) {
eol = source_text.match(lineBreak)[0];
}
}
eol = eol.replace(/\\r/, '\r').replace(/\\n/, '\n');
// HACK: newline parsing inconsistent. This brute force normalizes the input.
source_text = source_text.replace(allLineBreaks, '\n');
// tokenizer // tokenizer
var whiteRe = /^\s+$/; var whiteRe = /^\s+$/;
var wordRe = /[\w$\-_]/;
var pos = -1, var pos = -1,
ch; ch;
@ -89,6 +138,7 @@
} }
function peek(skipWhitespace) { function peek(skipWhitespace) {
var result = '';
var prev_pos = pos; var prev_pos = pos;
if (skipWhitespace) { if (skipWhitespace) {
eatWhitespace(); eatWhitespace();
@ -121,12 +171,16 @@
return str; return str;
} }
function eatWhitespace() { function eatWhitespace(preserve_newlines_local) {
var result = ''; var result = 0;
while (whiteRe.test(peek())) { while (whiteRe.test(peek())) {
next(); next();
result += ch; if (ch === '\n' && preserve_newlines_local && preserve_newlines) {
print.newLine(true);
result++;
}
} }
newlinesFromLastWSEat = result;
return result; return result;
} }
@ -167,11 +221,20 @@
// and the next special character found opens // and the next special character found opens
// a new block // a new block
function foundNestedPseudoClass() { function foundNestedPseudoClass() {
var openParen = 0;
for (var i = pos + 1; i < source_text.length; i++) { for (var i = pos + 1; i < source_text.length; i++) {
var ch = source_text.charAt(i); var ch = source_text.charAt(i);
if (ch === "{") { if (ch === "{") {
return true; return true;
} else if (ch === ";" || ch === "}" || ch === ")") { } else if (ch === '(') {
// pseudoclasses can contain ()
openParen += 1;
} else if (ch === ')') {
if (openParen === 0) {
return false;
}
openParen -= 1;
} else if (ch === ";" || ch === "}") {
return false; return false;
} }
} }
@ -198,12 +261,18 @@
print["{"] = function(ch) { print["{"] = function(ch) {
print.singleSpace(); print.singleSpace();
output.push(ch); output.push(ch);
print.newLine(); if (!eatWhitespace(true)) {
print.newLine();
}
}; };
print["}"] = function(ch) { print["}"] = function(newline) {
print.newLine(); if (newline) {
output.push(ch); print.newLine();
print.newLine(); }
output.push('}');
if (!eatWhitespace(true)) {
print.newLine();
}
}; };
print._lastCharWhitespace = function() { print._lastCharWhitespace = function() {
@ -211,15 +280,17 @@
}; };
print.newLine = function(keepWhitespace) { print.newLine = function(keepWhitespace) {
if (!keepWhitespace) {
print.trim();
}
if (output.length) { if (output.length) {
if (!keepWhitespace && output[output.length - 1] !== '\n') {
print.trim();
} else if (output[output.length - 1] === basebaseIndentString) {
output.pop();
}
output.push('\n'); output.push('\n');
}
if (basebaseIndentString) { if (basebaseIndentString) {
output.push(basebaseIndentString); output.push(basebaseIndentString);
}
} }
}; };
print.singleSpace = function() { print.singleSpace = function() {
@ -228,6 +299,12 @@
} }
}; };
print.preserveSingleSpace = function() {
if (isAfterSpace) {
print.singleSpace();
}
};
print.trim = function() { print.trim = function() {
while (print._lastCharWhitespace()) { while (print._lastCharWhitespace()) {
output.pop(); output.pop();
@ -236,12 +313,10 @@
var output = []; var output = [];
if (basebaseIndentString) {
output.push(basebaseIndentString);
}
/*_____________________--------------------_____________________*/ /*_____________________--------------------_____________________*/
var insideRule = false; var insideRule = false;
var insidePropertyValue = false;
var enteringConditionalGroup = false; var enteringConditionalGroup = false;
var top_ch = ''; var top_ch = '';
var last_top_ch = ''; var last_top_ch = '';
@ -256,8 +331,12 @@
if (!ch) { if (!ch) {
break; break;
} else if (ch === '/' && peek() === '*') { /* css comment */ } else if (ch === '/' && peek() === '*') { /* css comment */
var header = lookBack(""); var header = indentLevel === 0;
print.newLine();
if (isAfterNewline || header) {
print.newLine();
}
output.push(eatComment()); output.push(eatComment());
print.newLine(); print.newLine();
if (header) { if (header) {
@ -271,40 +350,46 @@
output.push(eatComment()); output.push(eatComment());
print.newLine(); print.newLine();
} else if (ch === '@') { } else if (ch === '@') {
// pass along the space we found as a separate item print.preserveSingleSpace();
if (isAfterSpace) {
print.singleSpace();
}
output.push(ch);
// strip trailing space, if present, for hash property checks // deal with less propery mixins @{...}
var variableOrRule = peekString(": ,;{}()[]/='\""); if (peek() === '{') {
output.push(eatString('}'));
} else {
output.push(ch);
if (variableOrRule.match(/[ :]$/)) { // strip trailing space, if present, for hash property checks
// we have a variable or pseudo-class, add it and insert one space before continuing var variableOrRule = peekString(": ,;{}()[]/='\"");
next();
variableOrRule = eatString(": ").replace(/\s$/, '');
output.push(variableOrRule);
print.singleSpace();
}
variableOrRule = variableOrRule.replace(/\s$/, '') if (variableOrRule.match(/[ :]$/)) {
// we have a variable or pseudo-class, add it and insert one space before continuing
next();
variableOrRule = eatString(": ").replace(/\s$/, '');
output.push(variableOrRule);
print.singleSpace();
}
// might be a nesting at-rule variableOrRule = variableOrRule.replace(/\s$/, '');
if (variableOrRule in css_beautify.NESTED_AT_RULE) {
nestedLevel += 1; // might be a nesting at-rule
if (variableOrRule in css_beautify.CONDITIONAL_GROUP_RULE) { if (variableOrRule in css_beautify.NESTED_AT_RULE) {
enteringConditionalGroup = true; nestedLevel += 1;
if (variableOrRule in css_beautify.CONDITIONAL_GROUP_RULE) {
enteringConditionalGroup = true;
}
} }
} }
} else if (ch === '#' && peek() === '{') {
print.preserveSingleSpace();
output.push(eatString('}'));
} else if (ch === '{') { } else if (ch === '{') {
if (peek(true) === '}') { if (peek(true) === '}') {
eatWhitespace(); eatWhitespace();
next(); next();
print.singleSpace(); print.singleSpace();
output.push("{}"); output.push("{");
print.newLine(); print['}'](false);
if (newline_between_rules && indentLevel === 0) { if (newlinesFromLastWSEat < 2 && newline_between_rules && indentLevel === 0) {
print.newLine(true); print.newLine(true);
} }
} else { } else {
@ -321,25 +406,35 @@
} }
} else if (ch === '}') { } else if (ch === '}') {
outdent(); outdent();
print["}"](ch); print["}"](true);
insideRule = false; insideRule = false;
insidePropertyValue = false;
if (nestedLevel) { if (nestedLevel) {
nestedLevel--; nestedLevel--;
} }
if (newline_between_rules && indentLevel === 0) { if (newlinesFromLastWSEat < 2 && newline_between_rules && indentLevel === 0) {
print.newLine(true); print.newLine(true);
} }
} else if (ch === ":") { } else if (ch === ":") {
eatWhitespace(); eatWhitespace();
if ((insideRule || enteringConditionalGroup) && if ((insideRule || enteringConditionalGroup) &&
!(lookBack("&") || foundNestedPseudoClass())) { !(lookBack("&") || foundNestedPseudoClass()) &&
!lookBack("(")) {
// 'property: value' delimiter // 'property: value' delimiter
// which could be in a conditional group query // which could be in a conditional group query
output.push(':'); output.push(':');
print.singleSpace(); if (!insidePropertyValue) {
insidePropertyValue = true;
print.singleSpace();
}
} else { } else {
// sass/less parent reference don't use a space // sass/less parent reference don't use a space
// sass nested pseudo-class don't use a space // sass nested pseudo-class don't use a space
// preserve space before pseudoclasses/pseudoelements, as it means "in any child"
if (lookBack(" ") && output[output.length - 1] !== " ") {
output.push(" ");
}
if (peek() === ":") { if (peek() === ":") {
// pseudo-element // pseudo-element
next(); next();
@ -350,13 +445,14 @@
} }
} }
} else if (ch === '"' || ch === '\'') { } else if (ch === '"' || ch === '\'') {
if (isAfterSpace) { print.preserveSingleSpace();
print.singleSpace();
}
output.push(eatString(ch)); output.push(eatString(ch));
} else if (ch === ';') { } else if (ch === ';') {
insidePropertyValue = false;
output.push(ch); output.push(ch);
print.newLine(); if (!eatWhitespace(true)) {
print.newLine();
}
} else if (ch === '(') { // may be a url } else if (ch === '(') { // may be a url
if (lookBack("url")) { if (lookBack("url")) {
output.push(ch); output.push(ch);
@ -370,9 +466,7 @@
} }
} else { } else {
parenLevel++; parenLevel++;
if (isAfterSpace) { print.preserveSingleSpace();
print.singleSpace();
}
output.push(ch); output.push(ch);
eatWhitespace(); eatWhitespace();
} }
@ -381,38 +475,58 @@
parenLevel--; parenLevel--;
} else if (ch === ',') { } else if (ch === ',') {
output.push(ch); output.push(ch);
eatWhitespace(); if (!eatWhitespace(true) && selectorSeparatorNewline && !insidePropertyValue && parenLevel < 1) {
if (!insideRule && selectorSeparatorNewline && parenLevel < 1) {
print.newLine(); print.newLine();
} else { } else {
print.singleSpace(); print.singleSpace();
} }
} else if ((ch === '>' || ch === '+' || ch === '~') &&
!insidePropertyValue && parenLevel < 1) {
//handle combinator spacing
if (space_around_combinator) {
print.singleSpace();
output.push(ch);
print.singleSpace();
} else {
output.push(ch);
eatWhitespace();
// squash extra whitespace
if (ch && whiteRe.test(ch)) {
ch = '';
}
}
} else if (ch === ']') { } else if (ch === ']') {
output.push(ch); output.push(ch);
} else if (ch === '[') { } else if (ch === '[') {
if (isAfterSpace) { print.preserveSingleSpace();
print.singleSpace();
}
output.push(ch); output.push(ch);
} else if (ch === '=') { // no whitespace before or after } else if (ch === '=') { // no whitespace before or after
eatWhitespace() eatWhitespace();
ch = '='; output.push('=');
output.push(ch); if (whiteRe.test(ch)) {
} else { ch = '';
if (isAfterSpace) {
print.singleSpace();
} }
} else {
print.preserveSingleSpace();
output.push(ch); output.push(ch);
} }
} }
var sweetCode = output.join('').replace(/[\r\n\t ]+$/, ''); var sweetCode = '';
if (basebaseIndentString) {
sweetCode += basebaseIndentString;
}
sweetCode += output.join('').replace(/[\r\n\t ]+$/, '');
// establish end_with_newline // establish end_with_newline
if (end_with_newline) { if (end_with_newline) {
sweetCode += "\n"; sweetCode += '\n';
}
if (eol !== '\n') {
sweetCode = sweetCode.replace(/[\n]/g, eol);
} }
return sweetCode; return sweetCode;