Skip to content

Commit

Permalink
Make css beautifier do base indent without new lines
Browse files Browse the repository at this point in the history
Fixes #523
  • Loading branch information
bitwiseman committed Sep 27, 2014
1 parent 809cf0f commit 6448f89
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 65 deletions.
29 changes: 13 additions & 16 deletions js/lib/beautify-css.js
Original file line number Diff line number Diff line change
Expand Up @@ -148,19 +148,19 @@
}

// printer
var indentString = source_text.match(/^[\r\n]*[\t ]*/)[0];
var basebaseIndentString = source_text.match(/^[\t ]*/)[0];
var singleIndent = new Array(indentSize + 1).join(indentCharacter);
var indentLevel = 0;
var nestedLevel = 0;

function indent() {
indentLevel++;
indentString += singleIndent;
basebaseIndentString += singleIndent;
}

function outdent() {
indentLevel--;
indentString = indentString.slice(0, -indentSize);
basebaseIndentString = basebaseIndentString.slice(0, -indentSize);
}

var print = {};
Expand Down Expand Up @@ -189,8 +189,8 @@
if (output.length) {
output.push('\n');
}
if (indentString) {
output.push(indentString);
if (basebaseIndentString) {
output.push(basebaseIndentString);
}
};
print.singleSpace = function () {
Expand All @@ -199,8 +199,8 @@
}
};
var output = [];
if (indentString) {
output.push(indentString);
if (basebaseIndentString) {
output.push(basebaseIndentString);
}
/*_____________________--------------------_____________________*/

Expand All @@ -214,13 +214,13 @@
break;
} else if (ch === '/' && peek() === '*') { /* css comment */
print.newLine();
output.push(eatComment(), "\n", indentString);
output.push(eatComment(), "\n", basebaseIndentString);
var header = lookBack("");
if (header) {
print.newLine();
}
} else if (ch === '/' && peek() === '/') { // single line comment
output.push(eatComment(true), indentString);
output.push(eatComment(true), basebaseIndentString);
} else if (ch === '@') {
// strip trailing space, if present, for hash property checks
var atRule = eatString(" ").replace(/ $/, '');
Expand Down Expand Up @@ -281,9 +281,9 @@
if (isCommentOnLine()) {
var beforeComment = eatString('/');
var comment = eatComment(true);
output.push(beforeComment, comment.substring(1, comment.length - 1), '\n', indentString);
output.push(beforeComment, comment.substring(1, comment.length - 1), '\n', basebaseIndentString);
} else {
output.push(ch, '\n', indentString);
output.push(ch, '\n', basebaseIndentString);
}
} else if (ch === '(') { // may be a url
if (lookBack("url")) {
Expand Down Expand Up @@ -333,15 +333,12 @@
}


var sweetCode = output.join('').replace(/[\n ]+$/, '');
var sweetCode = output.join('').replace(/[\r\n\t ]+$/, '');

// establish end_with_newline
var should = endWithNewline;
var actually = /\n$/.test(sweetCode);
if (should && !actually) {
if (should) {
sweetCode += "\n";
} else if (!should && actually) {
sweetCode = sweetCode.slice(0, -1);
}

return sweetCode;
Expand Down
30 changes: 15 additions & 15 deletions js/lib/beautify.js
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@
var prefix;

var handlers, MODE, opt;
var preindent_string = '';
var baseIndentString = '';


MODE = {
Expand Down Expand Up @@ -289,15 +289,15 @@
if(js_source_text && js_source_text.length) {
while ( (js_source_text.charAt(preindent_index) === ' ' ||
js_source_text.charAt(preindent_index) === '\t')) {
preindent_string += js_source_text.charAt(preindent_index);
baseIndentString += js_source_text.charAt(preindent_index);
preindent_index += 1;
}
js_source_text = js_source_text.substring(preindent_index);
}

last_type = 'TK_START_BLOCK'; // last token type
last_last_text = ''; // pre-last token text
output = new Output(indent_string, preindent_string);
output = new Output(indent_string, baseIndentString);


// Stack of parsing/formatting states, including MODE.
Expand Down Expand Up @@ -1215,7 +1215,7 @@
character_count += input.length;
}

this.remove_indent = function(indent_string, preindent_string) {
this.remove_indent = function(indent_string, baseIndentString) {
var splice_index = 0;

// skip empty lines
Expand All @@ -1224,7 +1224,7 @@
}

// skip the preindent string if present
if (preindent_string && line_items[0] === preindent_string) {
if (baseIndentString && line_items[0] === baseIndentString) {
splice_index = 1;
}

Expand All @@ -1235,20 +1235,20 @@
}
}

this.trim = function(indent_string, preindent_string) {
this.trim = function(indent_string, baseIndentString) {
while (this.get_item_count() &&
(this.last() === ' ' ||
this.last() === indent_string ||
this.last() === preindent_string)) {
this.last() === baseIndentString)) {
var item = line_items.pop();
character_count -= item.length;
}
}
}

function Output(indent_string, preindent_string) {
function Output(indent_string, baseIndentString) {
var lines =[];
this.preindent_string = preindent_string;
this.baseIndentString = baseIndentString;
this.current_line = null;
this.space_before_token = false;

Expand Down Expand Up @@ -1279,13 +1279,13 @@
for (var line_index = 1; line_index < lines.length; line_index++) {
sweet_code += '\n' + lines[line_index].get_output();
}
sweet_code = sweet_code.replace(/[\r\n ]+$/, '');
sweet_code = sweet_code.replace(/[\r\n\t ]+$/, '');
return sweet_code;
}

this.add_indent_string = function(indentation_level) {
if (preindent_string) {
this.current_line.push(preindent_string);
if (baseIndentString) {
this.current_line.push(baseIndentString);
}

// Never indent your first output indent at the start of the file
Expand Down Expand Up @@ -1328,21 +1328,21 @@

var output_length = lines.length;
while (index < output_length) {
lines[index].remove_indent(indent_string, preindent_string);
lines[index].remove_indent(indent_string, baseIndentString);
index++;
}
}

this.trim = function(eat_newlines) {
eat_newlines = (eat_newlines === undefined) ? false : eat_newlines;

this.current_line.trim(indent_string, preindent_string);
this.current_line.trim(indent_string, baseIndentString);

while (eat_newlines && lines.length > 1 &&
this.current_line.get_item_count() === 0) {
lines.pop();
this.current_line = lines[lines.length - 1]
this.current_line.trim(indent_string, preindent_string);
this.current_line.trim(indent_string, baseIndentString);
}
}

Expand Down
10 changes: 9 additions & 1 deletion js/test/beautify-tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -2089,6 +2089,13 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
btc("@media print {.tab{}}", "@media print {\n\t.tab {}\n}\n");
btc("@media print {.tab{background-image:url(foo@2x.png)}}", "@media print {\n\t.tab {\n\t\tbackground-image: url(foo@2x.png)\n\t}\n}\n");

//lead-in whitespace determines base-indent.
// lead-in newlines are stripped.
btc("\n\na, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}\n");
btc(" a, img {padding: 0.2px}", " a,\n img {\n \tpadding: 0.2px\n }\n");
btc(" \t \na, img {padding: 0.2px}", " \t a,\n \t img {\n \t \tpadding: 0.2px\n \t }\n");
btc("\n\n a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}\n");

// comments
btc("/* test */", "/* test */\n");
btc(".tabs{/* test */}", ".tabs {\n\t/* test */\n}\n");
Expand Down Expand Up @@ -2153,7 +2160,8 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify,
btc("a:not(\"foobar\\\";{}omg\"){\ncontent: 'example\\';{} text';\ncontent: \"example\\\";{} text\";}",
"a:not(\"foobar\\\";{}omg\") {\n content: 'example\\';{} text';\n content: \"example\\\";{} text\";\n}\n");

btc('html.js [data-custom="123"] {\n opacity: 1.00;\n}\n'); // may not eat the space before "["
// may not eat the space before "["
btc('html.js [data-custom="123"] {\n opacity: 1.00;\n}\n');
btc('html.js *[data-custom="123"] {\n opacity: 1.00;\n}\n');

return sanitytest;
Expand Down
29 changes: 14 additions & 15 deletions python/cssbeautifier/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,17 +86,19 @@ class Printer:
def __init__(self, indent_char, indent_size, default_indent=""):
self.indentSize = indent_size
self.singleIndent = (indent_size) * indent_char
self.indentString = default_indent
self.output = [default_indent]
self.baseIndentString = default_indent
self.output = []
if self.baseIndentString:
self.push(self.baseIndentString)

def __lastCharWhitespace(self):
return WHITE_RE.search(self.output[len(self.output) - 1]) is not None
return WHITE_RE.search(self.output[-1]) is not None

def indent(self):
self.indentString += self.singleIndent
self.baseIndentString += self.singleIndent

def outdent(self):
self.indentString = self.indentString[:-(self.indentSize + 1)]
self.baseIndentString = self.baseIndentString[:-(len(self.singleIndent))]

def push(self, string):
self.output.append(string)
Expand Down Expand Up @@ -130,8 +132,8 @@ def newLine(self, keepWhitespace=False):
if len(self.output) > 0:
self.output.append("\n")

if len(self.indentString) > 0:
self.output.append(self.indentString)
if len(self.baseIndentString) > 0:
self.output.append(self.baseIndentString)

def singleSpace(self):
if len(self.output) > 0 and not self.__lastCharWhitespace():
Expand Down Expand Up @@ -212,9 +214,9 @@ def isCommentOnLine(self):
return restOfLine.find('//') != -1

def beautify(self):
m = re.search("^[\r\n]*[\t ]*", self.source_text)
indentString = m.group(0)
printer = Printer(self.indentChar, self.indentSize, indentString)
m = re.search("^[\t ]*", self.source_text)
baseIndentString = m.group(0)
printer = Printer(self.indentChar, self.indentSize, baseIndentString)

insideRule = False
while True:
Expand Down Expand Up @@ -299,15 +301,12 @@ def beautify(self):

printer.push(self.ch)

sweet_code = printer.result()
sweet_code = re.sub('[\r\n\t ]+$', '', printer.result())

# establish end_with_newline
should = self.opts.end_with_newline
actually = sweet_code.endswith("\n")
if should and not actually:
if should:
sweet_code = sweet_code + "\n"
elif not should and actually:
sweet_code = sweet_code[:-1]

return sweet_code

11 changes: 8 additions & 3 deletions python/cssbeautifier/tests/test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,18 @@ def testBasics(self):
t('html.js [data-custom="123"] {\n\topacity: 1.00;\n}\n');
t('html.js *[data-custom="123"] {\n\topacity: 1.00;\n}\n');

# lead-in whitespace determines base-indent.
# lead-in newlines are stripped.
t("\n\na, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}\n")
t(" a, img {padding: 0.2px}", " a,\n img {\n \tpadding: 0.2px\n }\n")
t(" \t \na, img {padding: 0.2px}", " \t a,\n \t img {\n \t \tpadding: 0.2px\n \t }\n")
t("\n\n a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}\n")

def testComments(self):
self.resetOptions()
t = self.decodesto

t("/* test */", "/* test */\n\n")
t("/* test */", "/* test */\n")
t(".tabs{/* test */}", ".tabs {\n\t/* test */\n}\n")
t("/* header */.tabs {}", "/* header */\n\n.tabs {}\n")

Expand All @@ -53,7 +59,6 @@ def testSeperateSelectors(self):
t("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}\n")
t("a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}\n")


def testOptions(self):
self.resetOptions()
self.options.indent_size = 2
Expand All @@ -66,7 +71,7 @@ def testOptions(self):
t("#bla, #foo{color:black}", "#bla, #foo {\n color: black\n}\n")

def decodesto(self, input, expectation=None):
self.assertEqual(
self.assertMultiLineEqual(
cssbeautifier.beautify(input, self.options), expectation or input)

if __name__ == '__main__':
Expand Down
Loading

0 comments on commit 6448f89

Please sign in to comment.