mirror of
https://github.com/beautifier/js-beautify.git
synced 2025-03-03 10:37:18 +00:00
Merge branch 'python-cssbeautifier'
This commit is contained in:
commit
42fbfe36e5
@ -38,26 +38,35 @@
|
|||||||
css_beautify(source_text);
|
css_beautify(source_text);
|
||||||
css_beautify(source_text, options);
|
css_beautify(source_text, options);
|
||||||
|
|
||||||
The options are:
|
The options are (default in brackets):
|
||||||
indent_size (default 4) — indentation size,
|
indent_size (4) — indentation size,
|
||||||
indent_char (default space) — character to indent with,
|
indent_char (space) — character to indent with,
|
||||||
|
selector_separator_newline (true) - separate selectors with newline or
|
||||||
|
not (e.g. "a,\nbr" or "a, br")
|
||||||
|
end_with_newline (false) - end with a newline
|
||||||
|
|
||||||
e.g
|
e.g
|
||||||
|
|
||||||
css_beautify(css_source_text, {
|
css_beautify(css_source_text, {
|
||||||
'indent_size': 1,
|
'indent_size': 1,
|
||||||
'indent_char': '\t'
|
'indent_char': '\t',
|
||||||
|
'selector_separator': ' ',
|
||||||
|
'end_with_newline': false,
|
||||||
});
|
});
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// http://www.w3.org/TR/CSS21/syndata.html#tokenization
|
// http://www.w3.org/TR/CSS21/syndata.html#tokenization
|
||||||
// http://www.w3.org/TR/css3-syntax/
|
// http://www.w3.org/TR/css3-syntax/
|
||||||
|
|
||||||
(function() {
|
(function () {
|
||||||
function css_beautify(source_text, options) {
|
function css_beautify(source_text, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
var indentSize = options.indent_size || 4;
|
var indentSize = options.indent_size || 4;
|
||||||
var indentCharacter = options.indent_char || ' ';
|
var indentCharacter = options.indent_char || ' ';
|
||||||
|
var selectorSeparatorNewline = true;
|
||||||
|
if (options.selector_separator_newline != undefined)
|
||||||
|
selectorSeparatorNewline = options.selector_separator_newline;
|
||||||
|
var endWithNewline = options.end_with_newline || false;
|
||||||
|
|
||||||
// compatibility
|
// compatibility
|
||||||
if (typeof indentSize === "string") {
|
if (typeof indentSize === "string") {
|
||||||
@ -81,13 +90,13 @@
|
|||||||
return source_text.charAt(pos + 1);
|
return source_text.charAt(pos + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
function eatString(comma) {
|
function eatString(endChar) {
|
||||||
var start = pos;
|
var start = pos;
|
||||||
while (next()) {
|
while (next()) {
|
||||||
if (ch === "\\") {
|
if (ch === "\\") {
|
||||||
next();
|
next();
|
||||||
next();
|
next();
|
||||||
} else if (ch === comma) {
|
} else if (ch === endChar) {
|
||||||
break;
|
break;
|
||||||
} else if (ch === "\n") {
|
} else if (ch === "\n") {
|
||||||
break;
|
break;
|
||||||
@ -125,7 +134,8 @@
|
|||||||
|
|
||||||
|
|
||||||
function lookBack(str) {
|
function lookBack(str) {
|
||||||
return source_text.substring(pos - str.length, pos).toLowerCase() === str;
|
return source_text.substring(pos - str.length, pos).toLowerCase() ===
|
||||||
|
str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// printer
|
// printer
|
||||||
@ -144,20 +154,24 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var print = {};
|
var print = {};
|
||||||
print["{"] = function(ch) {
|
print["{"] = function (ch) {
|
||||||
print.singleSpace();
|
print.singleSpace();
|
||||||
output.push(ch);
|
output.push(ch);
|
||||||
print.newLine();
|
print.newLine();
|
||||||
};
|
};
|
||||||
print["}"] = function(ch) {
|
print["}"] = function (ch) {
|
||||||
print.newLine();
|
print.newLine();
|
||||||
output.push(ch);
|
output.push(ch);
|
||||||
print.newLine();
|
print.newLine();
|
||||||
};
|
};
|
||||||
|
|
||||||
print.newLine = function(keepWhitespace) {
|
print._lastCharWhitespace = function () {
|
||||||
|
return whiteRe.test(output[output.length - 1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
print.newLine = function (keepWhitespace) {
|
||||||
if (!keepWhitespace) {
|
if (!keepWhitespace) {
|
||||||
while (whiteRe.test(output[output.length - 1])) {
|
while (print._lastCharWhitespace()) {
|
||||||
output.pop();
|
output.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -169,8 +183,8 @@
|
|||||||
output.push(indentString);
|
output.push(indentString);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
print.singleSpace = function() {
|
print.singleSpace = function () {
|
||||||
if (output.length && !whiteRe.test(output[output.length - 1])) {
|
if (output.length && !print._lastCharWhitespace()) {
|
||||||
output.push(' ');
|
output.push(' ');
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -180,27 +194,40 @@
|
|||||||
}
|
}
|
||||||
/*_____________________--------------------_____________________*/
|
/*_____________________--------------------_____________________*/
|
||||||
|
|
||||||
|
var insideRule = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
var isAfterSpace = skipWhitespace();
|
var isAfterSpace = skipWhitespace();
|
||||||
|
|
||||||
if (!ch) {
|
if (!ch) {
|
||||||
break;
|
break;
|
||||||
}
|
} else if (ch === '/' && peek() === '*') { // comment
|
||||||
|
print.newLine();
|
||||||
|
output.push(eatComment(), "\n", indentString);
|
||||||
if (ch === '{') {
|
var header = lookBack("")
|
||||||
indent();
|
if (header) {
|
||||||
print["{"](ch);
|
print.newLine();
|
||||||
|
}
|
||||||
|
} else if (ch === '{') {
|
||||||
|
eatWhitespace();
|
||||||
|
if (peek() == '}') {
|
||||||
|
next();
|
||||||
|
output.push(" {}");
|
||||||
|
} else {
|
||||||
|
indent();
|
||||||
|
print["{"](ch);
|
||||||
|
}
|
||||||
} else if (ch === '}') {
|
} else if (ch === '}') {
|
||||||
outdent();
|
outdent();
|
||||||
print["}"](ch);
|
print["}"](ch);
|
||||||
|
insideRule = false;
|
||||||
|
} else if (ch === ":") {
|
||||||
|
eatWhitespace();
|
||||||
|
output.push(ch, " ");
|
||||||
|
insideRule = true;
|
||||||
} else if (ch === '"' || ch === '\'') {
|
} else if (ch === '"' || ch === '\'') {
|
||||||
output.push(eatString(ch));
|
output.push(eatString(ch));
|
||||||
} else if (ch === ';') {
|
} else if (ch === ';') {
|
||||||
output.push(ch, '\n', indentString);
|
output.push(ch, '\n', indentString);
|
||||||
} else if (ch === '/' && peek() === '*') { // comment
|
|
||||||
print.newLine();
|
|
||||||
output.push(eatComment(), "\n", indentString);
|
|
||||||
} 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);
|
||||||
@ -224,7 +251,11 @@
|
|||||||
} else if (ch === ',') {
|
} else if (ch === ',') {
|
||||||
eatWhitespace();
|
eatWhitespace();
|
||||||
output.push(ch);
|
output.push(ch);
|
||||||
print.singleSpace();
|
if (!insideRule && selectorSeparatorNewline) {
|
||||||
|
print.newLine();
|
||||||
|
} else {
|
||||||
|
print.singleSpace();
|
||||||
|
}
|
||||||
} else if (ch === ']') {
|
} else if (ch === ']') {
|
||||||
output.push(ch);
|
output.push(ch);
|
||||||
} else if (ch === '[' || ch === '=') { // no whitespace before or after
|
} else if (ch === '[' || ch === '=') { // no whitespace before or after
|
||||||
@ -241,12 +272,21 @@
|
|||||||
|
|
||||||
|
|
||||||
var sweetCode = output.join('').replace(/[\n ]+$/, '');
|
var sweetCode = output.join('').replace(/[\n ]+$/, '');
|
||||||
|
|
||||||
|
// establish end_with_newline
|
||||||
|
var should = endWithNewline;
|
||||||
|
var actually = /\n$/.test(sweetCode)
|
||||||
|
if (should && !actually)
|
||||||
|
sweetCode += "\n";
|
||||||
|
else if (!should && actually)
|
||||||
|
sweetCode = sweetCode.slice(0, -1);
|
||||||
|
|
||||||
return sweetCode;
|
return sweetCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof define === "function") {
|
if (typeof define === "function") {
|
||||||
// Add support for require.js
|
// Add support for require.js
|
||||||
define(function(require, exports, module) {
|
define(function (require, exports, module) {
|
||||||
exports.css_beautify = css_beautify;
|
exports.css_beautify = css_beautify;
|
||||||
});
|
});
|
||||||
} else if (typeof exports !== "undefined") {
|
} else if (typeof exports !== "undefined") {
|
||||||
@ -261,4 +301,4 @@
|
|||||||
global.css_beautify = css_beautify;
|
global.css_beautify = css_beautify;
|
||||||
}
|
}
|
||||||
|
|
||||||
}());
|
}());
|
@ -1,7 +1,7 @@
|
|||||||
/*global js_beautify: true */
|
/*global js_beautify: true */
|
||||||
/*jshint */
|
/*jshint */
|
||||||
|
|
||||||
function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify)
|
function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify, css_beautify)
|
||||||
{
|
{
|
||||||
|
|
||||||
var opts = {
|
var opts = {
|
||||||
@ -12,7 +12,9 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify)
|
|||||||
keep_array_indentation: false,
|
keep_array_indentation: false,
|
||||||
brace_style: 'collapse',
|
brace_style: 'collapse',
|
||||||
space_before_conditional: true,
|
space_before_conditional: true,
|
||||||
break_chained_methods: false
|
break_chained_methods: false,
|
||||||
|
selector_separator: '\n',
|
||||||
|
end_with_newline: true
|
||||||
};
|
};
|
||||||
|
|
||||||
function test_js_beautifier(input)
|
function test_js_beautifier(input)
|
||||||
@ -25,6 +27,11 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify)
|
|||||||
return html_beautify(input, opts);
|
return html_beautify(input, opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function test_css_beautifier(input)
|
||||||
|
{
|
||||||
|
return css_beautify(input, opts);
|
||||||
|
}
|
||||||
|
|
||||||
var sanitytest;
|
var sanitytest;
|
||||||
|
|
||||||
// test the input on beautifier with the current flag settings
|
// test the input on beautifier with the current flag settings
|
||||||
@ -103,6 +110,16 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// test css
|
||||||
|
function btc(input, expectation)
|
||||||
|
{
|
||||||
|
var wrapped_input, wrapped_expectation;
|
||||||
|
|
||||||
|
expectation = expectation || input;
|
||||||
|
sanitytest.test_function(test_css_beautifier, 'css_beautify');
|
||||||
|
test_fragment(input, expectation);
|
||||||
|
}
|
||||||
|
|
||||||
// test the input on beautifier with the current flag settings,
|
// test the input on beautifier with the current flag settings,
|
||||||
// but dont't
|
// but dont't
|
||||||
function bt_braces(input, expectation)
|
function bt_braces(input, expectation)
|
||||||
@ -1703,7 +1720,38 @@ function run_beautifier_tests(test_obj, Urlencoded, js_beautify, html_beautify)
|
|||||||
'<div>Some test text that should wrap_inside_this\n' +
|
'<div>Some test text that should wrap_inside_this\n' +
|
||||||
' section here.</div>');
|
' section here.</div>');
|
||||||
|
|
||||||
|
// css beautifier
|
||||||
|
opts.indent_size = 1;
|
||||||
|
opts.indent_char = '\t';
|
||||||
|
opts.selector_separator_newline = true;
|
||||||
|
opts.end_with_newline = true;
|
||||||
|
|
||||||
|
// test basic css beautifier
|
||||||
|
btc('', '\n');
|
||||||
|
btc(".tabs{}", ".tabs {}\n");
|
||||||
|
btc(".tabs{color:red;}", ".tabs {\n\tcolor: red;\n}\n");
|
||||||
|
btc(".tabs{color:rgb(255, 255, 0)}", ".tabs {\n\tcolor: rgb(255, 255, 0)\n}\n");
|
||||||
|
btc(".tabs{background:url('back.jpg')}", ".tabs {\n\tbackground: url('back.jpg')\n}\n");
|
||||||
|
btc("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}\n");
|
||||||
|
btc("@media print {.tab{}}", "@media print {\n\t.tab {}\n}\n");
|
||||||
|
|
||||||
|
// comments
|
||||||
|
btc("/* test */", "/* test */\n");
|
||||||
|
btc(".tabs{/* test */}", ".tabs {\n\t/* test */\n}\n");
|
||||||
|
btc("/* header */.tabs {}", "/* header */\n\n.tabs {}\n");
|
||||||
|
|
||||||
|
// separate selectors
|
||||||
|
btc("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}\n");
|
||||||
|
btc("a, img {padding: 0.2px}", "a,\nimg {\n\tpadding: 0.2px\n}\n");
|
||||||
|
|
||||||
|
// test options
|
||||||
|
opts.indent_size = 2;
|
||||||
|
opts.indent_char = ' ';
|
||||||
|
opts.selector_separator_newline = false;
|
||||||
|
|
||||||
|
btc("#bla, #foo{color:green}", "#bla, #foo {\n color: green\n}\n");
|
||||||
|
btc("@media print {.tab{}}", "@media print {\n .tab {}\n}\n");
|
||||||
|
btc("#bla, #foo{color:black}", "#bla, #foo {\n color: black\n}\n");
|
||||||
|
|
||||||
return sanitytest;
|
return sanitytest;
|
||||||
}
|
}
|
||||||
|
@ -4,11 +4,12 @@
|
|||||||
var SanityTest = require('./sanitytest'),
|
var SanityTest = require('./sanitytest'),
|
||||||
Urlencoded = require('../lib/unpackers/urlencode_unpacker'),
|
Urlencoded = require('../lib/unpackers/urlencode_unpacker'),
|
||||||
js_beautify = require('../index').js_beautify,
|
js_beautify = require('../index').js_beautify,
|
||||||
|
css_beautify = require('../index').css_beautify,
|
||||||
html_beautify = require('../index').html_beautify,
|
html_beautify = require('../index').html_beautify,
|
||||||
run_beautifier_tests = require('./beautify-tests').run_beautifier_tests;
|
run_beautifier_tests = require('./beautify-tests').run_beautifier_tests;
|
||||||
|
|
||||||
function node_beautifier_tests() {
|
function node_beautifier_tests() {
|
||||||
var results = run_beautifier_tests(new SanityTest(), Urlencoded, js_beautify, html_beautify);
|
var results = run_beautifier_tests(new SanityTest(), Urlencoded, js_beautify, html_beautify, css_beautify);
|
||||||
console.log(results.results_raw());
|
console.log(results.results_raw());
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
290
python/cssbeautifier/__init__.py
Normal file
290
python/cssbeautifier/__init__.py
Normal file
@ -0,0 +1,290 @@
|
|||||||
|
from __future__ import print_function
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
from cssbeautifier.__version__ import __version__
|
||||||
|
|
||||||
|
#
|
||||||
|
# The MIT License (MIT)
|
||||||
|
|
||||||
|
# Copyright (c) 2013 Einar Lielmanis and contributors.
|
||||||
|
|
||||||
|
# Permission is hereby granted, free of charge, to any person
|
||||||
|
# obtaining a copy of this software and associated documentation files
|
||||||
|
# (the "Software"), to deal in the Software without restriction,
|
||||||
|
# including without limitation the rights to use, copy, modify, merge,
|
||||||
|
# publish, distribute, sublicense, and/or sell copies of the Software,
|
||||||
|
# and to permit persons to whom the Software is furnished to do so,
|
||||||
|
# subject to the following conditions:
|
||||||
|
|
||||||
|
# The above copyright notice and this permission notice shall be
|
||||||
|
# included in all copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||||
|
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||||
|
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
|
||||||
|
class BeautifierOptions:
|
||||||
|
def __init__(self):
|
||||||
|
self.indent_size = 4
|
||||||
|
self.indent_char = ' '
|
||||||
|
self.selector_separator_newline = True
|
||||||
|
self.end_with_newline = False
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return \
|
||||||
|
"""indent_size = %d
|
||||||
|
indent_char = [%s]
|
||||||
|
separate_selectors_newline = [%s]
|
||||||
|
end_with_newline = [%s]
|
||||||
|
""" % (self.indent_size, self.indent_char,
|
||||||
|
self.separate_selectors, self.end_with_newline)
|
||||||
|
|
||||||
|
|
||||||
|
def default_options():
|
||||||
|
return BeautifierOptions()
|
||||||
|
|
||||||
|
|
||||||
|
def beautify(string, opts=default_options()):
|
||||||
|
b = Beautifier(string, opts)
|
||||||
|
return b.beautify()
|
||||||
|
|
||||||
|
|
||||||
|
def beautify_file(file_name, opts=default_options()):
|
||||||
|
if file_name == '-': # stdin
|
||||||
|
stream = sys.stdin
|
||||||
|
else:
|
||||||
|
stream = open(file_name)
|
||||||
|
content = ''.join(stream.readlines())
|
||||||
|
b = Beautifier(content, opts)
|
||||||
|
return b.beautify()
|
||||||
|
|
||||||
|
|
||||||
|
def usage(stream=sys.stdout):
|
||||||
|
|
||||||
|
print("cssbeautifier.py@" + __version__ + """
|
||||||
|
|
||||||
|
CSS beautifier (http://jsbeautifier.org/)
|
||||||
|
|
||||||
|
""", file=stream)
|
||||||
|
if stream == sys.stderr:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 0
|
||||||
|
|
||||||
|
WHITE_RE = re.compile("^\s+$")
|
||||||
|
WORD_RE = re.compile("[\w$\-_]")
|
||||||
|
|
||||||
|
|
||||||
|
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]
|
||||||
|
|
||||||
|
def __lastCharWhitespace(self):
|
||||||
|
return WHITE_RE.search(self.output[len(self.output) - 1]) is not None
|
||||||
|
|
||||||
|
def indent(self):
|
||||||
|
self.indentString += self.singleIndent
|
||||||
|
|
||||||
|
def outdent(self):
|
||||||
|
self.indentString = self.indentString[:-(self.indentSize + 1)]
|
||||||
|
|
||||||
|
def push(self, string):
|
||||||
|
self.output.append(string)
|
||||||
|
|
||||||
|
def openBracket(self):
|
||||||
|
self.singleSpace()
|
||||||
|
self.output.append("{")
|
||||||
|
self.newLine()
|
||||||
|
|
||||||
|
def closeBracket(self):
|
||||||
|
self.newLine()
|
||||||
|
self.output.append("}")
|
||||||
|
self.newLine()
|
||||||
|
|
||||||
|
def colon(self):
|
||||||
|
self.output.append(":")
|
||||||
|
self.singleSpace()
|
||||||
|
|
||||||
|
def semicolon(self):
|
||||||
|
self.output.append(";")
|
||||||
|
self.newLine()
|
||||||
|
|
||||||
|
def comment(self, comment):
|
||||||
|
self.output.append(comment)
|
||||||
|
|
||||||
|
def newLine(self, keepWhitespace=False):
|
||||||
|
if not keepWhitespace:
|
||||||
|
while self.__lastCharWhitespace():
|
||||||
|
self.output.pop()
|
||||||
|
|
||||||
|
if len(self.output) > 0:
|
||||||
|
self.output.append("\n")
|
||||||
|
|
||||||
|
if len(self.indentString) > 0:
|
||||||
|
self.output.append(self.indentString)
|
||||||
|
|
||||||
|
def singleSpace(self):
|
||||||
|
if len(self.output) > 0 and not self.__lastCharWhitespace():
|
||||||
|
self.output.append(" ")
|
||||||
|
|
||||||
|
def result(self):
|
||||||
|
return "".join(self.output)
|
||||||
|
|
||||||
|
|
||||||
|
class Beautifier:
|
||||||
|
|
||||||
|
def __init__(self, source_text, opts=default_options()):
|
||||||
|
self.source_text = source_text
|
||||||
|
self.opts = opts
|
||||||
|
self.indentSize = opts.indent_size
|
||||||
|
self.indentChar = opts.indent_char
|
||||||
|
self.pos = -1
|
||||||
|
self.ch = None
|
||||||
|
|
||||||
|
def next(self):
|
||||||
|
self.pos = self.pos + 1
|
||||||
|
if self.pos < len(self.source_text):
|
||||||
|
self.ch = self.source_text[self.pos]
|
||||||
|
else:
|
||||||
|
self.ch = None
|
||||||
|
return self.ch
|
||||||
|
|
||||||
|
def peek(self):
|
||||||
|
if self.pos + 1 < len(self.source_text):
|
||||||
|
return self.source_text[self.pos + 1]
|
||||||
|
else:
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def eatString(self, endChar):
|
||||||
|
start = self.pos
|
||||||
|
while self.next():
|
||||||
|
if self.ch == "\\":
|
||||||
|
self.next()
|
||||||
|
self.next()
|
||||||
|
elif self.ch == endChar:
|
||||||
|
break
|
||||||
|
elif self.ch == "\n":
|
||||||
|
break
|
||||||
|
return self.source_text[start:self.pos] + endChar
|
||||||
|
|
||||||
|
def eatWhitespace(self):
|
||||||
|
start = self.pos
|
||||||
|
while WHITE_RE.search(self.peek()) is not None:
|
||||||
|
self.pos = self.pos + 1
|
||||||
|
return self.pos != start
|
||||||
|
|
||||||
|
def skipWhitespace(self):
|
||||||
|
start = self.pos
|
||||||
|
while self.next() and WHITE_RE.search(self.ch) is not None:
|
||||||
|
pass
|
||||||
|
return self.pos != start + 1
|
||||||
|
|
||||||
|
def eatComment(self):
|
||||||
|
start = self.pos
|
||||||
|
self.next()
|
||||||
|
while self.next():
|
||||||
|
if self.ch == "*" and self.peek() == "/":
|
||||||
|
self.pos = self.pos + 1
|
||||||
|
break
|
||||||
|
return self.source_text[start:self.pos + 1]
|
||||||
|
|
||||||
|
def lookBack(self, string):
|
||||||
|
past = self.source_text[self.pos - len(string):self.pos]
|
||||||
|
return past.lower() == string
|
||||||
|
|
||||||
|
def beautify(self):
|
||||||
|
m = re.search("^[\r\n]*[\t ]*", self.source_text)
|
||||||
|
indentString = m.group(0)
|
||||||
|
printer = Printer(self.indentChar, self.indentSize, indentString)
|
||||||
|
|
||||||
|
insideRule = False
|
||||||
|
while True:
|
||||||
|
isAfterSpace = self.skipWhitespace()
|
||||||
|
|
||||||
|
if not self.ch:
|
||||||
|
break
|
||||||
|
elif self.ch == '/' and self.peek() == '*':
|
||||||
|
comment = self.eatComment()
|
||||||
|
printer.comment(comment)
|
||||||
|
header = self.lookBack("")
|
||||||
|
if header:
|
||||||
|
printer.push("\n\n")
|
||||||
|
elif self.ch == '{':
|
||||||
|
self.eatWhitespace()
|
||||||
|
if self.peek() == '}':
|
||||||
|
self.next()
|
||||||
|
printer.push(" {}")
|
||||||
|
else:
|
||||||
|
printer.indent()
|
||||||
|
printer.openBracket()
|
||||||
|
elif self.ch == '}':
|
||||||
|
printer.outdent()
|
||||||
|
printer.closeBracket()
|
||||||
|
insideRule = False
|
||||||
|
elif self.ch == ":":
|
||||||
|
self.eatWhitespace()
|
||||||
|
printer.colon()
|
||||||
|
insideRule = True
|
||||||
|
elif self.ch == '"' or self.ch == '\'':
|
||||||
|
printer.push(self.eatString(self.ch))
|
||||||
|
elif self.ch == ';':
|
||||||
|
printer.semicolon()
|
||||||
|
elif self.ch == '(':
|
||||||
|
# may be a url
|
||||||
|
if self.lookBack("url"):
|
||||||
|
printer.push(self.ch)
|
||||||
|
self.eatWhitespace()
|
||||||
|
if self.next():
|
||||||
|
if self.ch is not ')' and self.ch is not '"' \
|
||||||
|
and self.ch is not '\'':
|
||||||
|
printer.push(self.eatString(')'))
|
||||||
|
else:
|
||||||
|
self.pos = self.pos - 1
|
||||||
|
else:
|
||||||
|
if isAfterSpace:
|
||||||
|
printer.singleSpace()
|
||||||
|
printer.push(self.ch)
|
||||||
|
self.eatWhitespace()
|
||||||
|
elif self.ch == ')':
|
||||||
|
printer.push(self.ch)
|
||||||
|
elif self.ch == ',':
|
||||||
|
self.eatWhitespace()
|
||||||
|
printer.push(self.ch)
|
||||||
|
if not insideRule and self.opts.selector_separator_newline:
|
||||||
|
printer.newLine()
|
||||||
|
else:
|
||||||
|
printer.singleSpace()
|
||||||
|
elif self.ch == ']':
|
||||||
|
printer.push(self.ch)
|
||||||
|
elif self.ch == '[' or self.ch == '=':
|
||||||
|
# no whitespace before or after
|
||||||
|
self.eatWhitespace()
|
||||||
|
printer.push(self.ch)
|
||||||
|
else:
|
||||||
|
if isAfterSpace:
|
||||||
|
printer.singleSpace()
|
||||||
|
|
||||||
|
printer.push(self.ch)
|
||||||
|
|
||||||
|
sweet_code = printer.result()
|
||||||
|
|
||||||
|
# establish end_with_newline
|
||||||
|
should = self.opts.end_with_newline
|
||||||
|
actually = sweet_code.endswith("\n")
|
||||||
|
if should and not actually:
|
||||||
|
sweet_code = sweet_code + "\n"
|
||||||
|
elif not should and actually:
|
||||||
|
sweet_code = sweet_code[:-1]
|
||||||
|
|
||||||
|
return sweet_code
|
||||||
|
|
1
python/cssbeautifier/__version__.py
Normal file
1
python/cssbeautifier/__version__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
__version__ = '1.0.0'
|
1
python/cssbeautifier/tests/__init__.py
Normal file
1
python/cssbeautifier/tests/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Empty file :)
|
60
python/cssbeautifier/tests/test.py
Normal file
60
python/cssbeautifier/tests/test.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import unittest
|
||||||
|
import cssbeautifier
|
||||||
|
|
||||||
|
|
||||||
|
class CSSBeautifierTest(unittest.TestCase):
|
||||||
|
|
||||||
|
def resetOptions(self):
|
||||||
|
self.options = cssbeautifier.default_options()
|
||||||
|
self.options.indent_size = 1
|
||||||
|
self.options.indent_char = '\t'
|
||||||
|
self.options.selector_separator_newline = True
|
||||||
|
self.options.end_with_newline = True
|
||||||
|
|
||||||
|
def testBasics(self):
|
||||||
|
self.resetOptions()
|
||||||
|
t = self.decodesto
|
||||||
|
|
||||||
|
t("", "\n")
|
||||||
|
t(".tabs{}", ".tabs {}\n")
|
||||||
|
t(".tabs{color:red}", ".tabs {\n\tcolor: red\n}\n")
|
||||||
|
t(".tabs{color:rgb(255, 255, 0)}", ".tabs {\n\tcolor: rgb(255, 255, 0)\n}\n")
|
||||||
|
t(".tabs{background:url('back.jpg')}", ".tabs {\n\tbackground: url('back.jpg')\n}\n")
|
||||||
|
t("#bla, #foo{color:red}", "#bla,\n#foo {\n\tcolor: red\n}\n")
|
||||||
|
t("@media print {.tab{}}", "@media print {\n\t.tab {}\n}\n")
|
||||||
|
|
||||||
|
|
||||||
|
def testComments(self):
|
||||||
|
self.resetOptions()
|
||||||
|
t = self.decodesto
|
||||||
|
|
||||||
|
t("/* test */", "/* test */\n\n")
|
||||||
|
t(".tabs{/* test */}", ".tabs {\n\t/* test */\n}\n")
|
||||||
|
t("/* header */.tabs {}", "/* header */\n\n.tabs {}\n")
|
||||||
|
|
||||||
|
|
||||||
|
def testSeperateSelectors(self):
|
||||||
|
self.resetOptions()
|
||||||
|
t = self.decodesto
|
||||||
|
|
||||||
|
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
|
||||||
|
self.options.indent_char = ' '
|
||||||
|
self.options.selector_separator_newline = False
|
||||||
|
t = self.decodesto
|
||||||
|
|
||||||
|
t("#bla, #foo{color:green}", "#bla, #foo {\n color: green\n}\n")
|
||||||
|
t("@media print {.tab{}}", "@media print {\n .tab {}\n}\n")
|
||||||
|
t("#bla, #foo{color:black}", "#bla, #foo {\n color: black\n}\n")
|
||||||
|
|
||||||
|
def decodesto(self, input, expectation=None):
|
||||||
|
self.assertEqual(
|
||||||
|
cssbeautifier.beautify(input, self.options), expectation or input)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
unittest.main()
|
Loading…
x
Reference in New Issue
Block a user