summaryrefslogtreecommitdiffstats
path: root/devtools/shared/jsbeautify/src/beautify-css.js
diff options
context:
space:
mode:
Diffstat (limited to 'devtools/shared/jsbeautify/src/beautify-css.js')
-rw-r--r--devtools/shared/jsbeautify/src/beautify-css.js367
1 files changed, 367 insertions, 0 deletions
diff --git a/devtools/shared/jsbeautify/src/beautify-css.js b/devtools/shared/jsbeautify/src/beautify-css.js
new file mode 100644
index 000000000..faf9ac0f2
--- /dev/null
+++ b/devtools/shared/jsbeautify/src/beautify-css.js
@@ -0,0 +1,367 @@
+/*jshint curly:true, eqeqeq:true, laxbreak:true, noempty:false */
+/*
+
+ The MIT License (MIT)
+
+ Copyright (c) 2007-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.
+
+
+ CSS Beautifier
+---------------
+
+ Written by Harutyun Amirjanyan, (amirjanyan@gmail.com)
+
+ Based on code initially developed by: Einar Lielmanis, <einar@jsbeautifier.org>
+ http://jsbeautifier.org/
+
+ Usage:
+ css_beautify(source_text);
+ css_beautify(source_text, options);
+
+ The options are (default in brackets):
+ indent_size (4) — indentation size,
+ 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
+
+ css_beautify(css_source_text, {
+ 'indent_size': 1,
+ 'indent_char': '\t',
+ 'selector_separator': ' ',
+ 'end_with_newline': false,
+ });
+*/
+
+// http://www.w3.org/TR/CSS21/syndata.html#tokenization
+// http://www.w3.org/TR/css3-syntax/
+
+(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 endWithNewline = (options.end_with_newline === undefined) ? false : options.end_with_newline;
+
+ // compatibility
+ if (typeof indentSize === "string") {
+ indentSize = parseInt(indentSize, 10);
+ }
+
+
+ // tokenizer
+ var whiteRe = /^\s+$/;
+ var wordRe = /[\w$\-_]/;
+
+ var pos = -1,
+ ch;
+
+ function next() {
+ ch = source_text.charAt(++pos);
+ return ch;
+ }
+
+ function peek() {
+ return source_text.charAt(pos + 1);
+ }
+
+ function eatString(endChar) {
+ var start = pos;
+ while (next()) {
+ if (ch === "\\") {
+ next();
+ next();
+ } else if (ch === endChar) {
+ break;
+ } else if (ch === "\n") {
+ break;
+ }
+ }
+ return source_text.substring(start, pos + 1);
+ }
+
+ function eatWhitespace() {
+ var start = pos;
+ while (whiteRe.test(peek())) {
+ pos++;
+ }
+ return pos !== start;
+ }
+
+ function skipWhitespace() {
+ var start = pos;
+ do {} while (whiteRe.test(next()));
+ return pos !== start + 1;
+ }
+
+ function eatComment(singleLine) {
+ var start = pos;
+ next();
+ while (next()) {
+ if (ch === "*" && peek() === "/") {
+ pos++;
+ break;
+ } else if (singleLine && ch === "\n") {
+ break;
+ }
+ }
+
+ return source_text.substring(start, pos + 1);
+ }
+
+
+ function lookBack(str) {
+ return source_text.substring(pos - str.length, pos).toLowerCase() ===
+ str;
+ }
+
+ function isCommentOnLine() {
+ var endOfLine = source_text.indexOf('\n', pos);
+ if (endOfLine === -1) {
+ return false;
+ }
+ var restOfLine = source_text.substring(pos, endOfLine);
+ return restOfLine.indexOf('//') !== -1;
+ }
+
+ // printer
+ var indentString = source_text.match(/^[\r\n]*[\t ]*/)[0];
+ var singleIndent = new Array(indentSize + 1).join(indentCharacter);
+ var indentLevel = 0;
+ var nestedLevel = 0;
+
+ function indent() {
+ indentLevel++;
+ indentString += singleIndent;
+ }
+
+ function outdent() {
+ indentLevel--;
+ indentString = indentString.slice(0, -indentSize);
+ }
+
+ var print = {};
+ print["{"] = function (ch) {
+ print.singleSpace();
+ output.push(ch);
+ print.newLine();
+ };
+ print["}"] = function (ch) {
+ print.newLine();
+ output.push(ch);
+ print.newLine();
+ };
+
+ print._lastCharWhitespace = function () {
+ return whiteRe.test(output[output.length - 1]);
+ };
+
+ print.newLine = function (keepWhitespace) {
+ if (!keepWhitespace) {
+ while (print._lastCharWhitespace()) {
+ output.pop();
+ }
+ }
+
+ if (output.length) {
+ output.push('\n');
+ }
+ if (indentString) {
+ output.push(indentString);
+ }
+ };
+ print.singleSpace = function () {
+ if (output.length && !print._lastCharWhitespace()) {
+ output.push(' ');
+ }
+ };
+ var output = [];
+ if (indentString) {
+ output.push(indentString);
+ }
+ /*_____________________--------------------_____________________*/
+
+ var insideRule = false;
+ var enteringConditionalGroup = false;
+
+ while (true) {
+ var isAfterSpace = skipWhitespace();
+
+ if (!ch) {
+ break;
+ } else if (ch === '/' && peek() === '*') { /* css comment */
+ print.newLine();
+ output.push(eatComment(), "\n", indentString);
+ var header = lookBack("");
+ if (header) {
+ print.newLine();
+ }
+ } else if (ch === '/' && peek() === '/') { // single line comment
+ output.push(eatComment(true), indentString);
+ } else if (ch === '@') {
+ // strip trailing space, if present, for hash property checks
+ var atRule = eatString(" ").replace(/ $/, '');
+
+ // pass along the space we found as a separate item
+ output.push(atRule, ch);
+
+ // might be a nesting at-rule
+ if (atRule in css_beautify.NESTED_AT_RULE) {
+ nestedLevel += 1;
+ if (atRule in css_beautify.CONDITIONAL_GROUP_RULE) {
+ enteringConditionalGroup = true;
+ }
+ }
+ } else if (ch === '{') {
+ eatWhitespace();
+ if (peek() === '}') {
+ next();
+ output.push(" {}");
+ } else {
+ indent();
+ print["{"](ch);
+ // when entering conditional groups, only rulesets are allowed
+ if (enteringConditionalGroup) {
+ enteringConditionalGroup = false;
+ insideRule = (indentLevel > nestedLevel);
+ } else {
+ // otherwise, declarations are also allowed
+ insideRule = (indentLevel >= nestedLevel);
+ }
+ }
+ } else if (ch === '}') {
+ outdent();
+ print["}"](ch);
+ insideRule = false;
+ if (nestedLevel) {
+ nestedLevel--;
+ }
+ } else if (ch === ":") {
+ eatWhitespace();
+ if (insideRule || enteringConditionalGroup) {
+ // 'property: value' delimiter
+ // which could be in a conditional group query
+ output.push(ch, " ");
+ } else {
+ if (peek() === ":") {
+ // pseudo-element
+ next();
+ output.push("::");
+ } else {
+ // pseudo-class
+ output.push(ch);
+ }
+ }
+ } else if (ch === '"' || ch === '\'') {
+ output.push(eatString(ch));
+ } else if (ch === ';') {
+ if (isCommentOnLine()) {
+ var beforeComment = eatString('/');
+ var comment = eatComment(true);
+ output.push(beforeComment, comment.substring(1, comment.length - 1), '\n', indentString);
+ } else {
+ output.push(ch, '\n', indentString);
+ }
+ } else if (ch === '(') { // may be a url
+ if (lookBack("url")) {
+ output.push(ch);
+ eatWhitespace();
+ if (next()) {
+ if (ch !== ')' && ch !== '"' && ch !== '\'') {
+ output.push(eatString(')'));
+ } else {
+ pos--;
+ }
+ }
+ } else {
+ if (isAfterSpace) {
+ print.singleSpace();
+ }
+ output.push(ch);
+ eatWhitespace();
+ }
+ } else if (ch === ')') {
+ output.push(ch);
+ } else if (ch === ',') {
+ eatWhitespace();
+ output.push(ch);
+ if (!insideRule && selectorSeparatorNewline) {
+ print.newLine();
+ } else {
+ print.singleSpace();
+ }
+ } else if (ch === ']') {
+ output.push(ch);
+ } else if (ch === '[') {
+ if (isAfterSpace) {
+ print.singleSpace();
+ }
+ output.push(ch);
+ } else if (ch === '=') { // no whitespace before or after
+ eatWhitespace();
+ output.push(ch);
+ } else {
+ if (isAfterSpace) {
+ print.singleSpace();
+ }
+
+ output.push(ch);
+ }
+ }
+
+
+ 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;
+ }
+
+ // https://developer.mozilla.org/en-US/docs/Web/CSS/At-rule
+ css_beautify.NESTED_AT_RULE = {
+ "@page": true,
+ "@font-face": true,
+ "@keyframes": true,
+ // also in CONDITIONAL_GROUP_RULE below
+ "@media": true,
+ "@supports": true,
+ "@document": true
+ };
+ css_beautify.CONDITIONAL_GROUP_RULE = {
+ "@media": true,
+ "@supports": true,
+ "@document": true
+ };
+
+ exports.cssBeautify = css_beautify;
+}());