Add beautify-css.js
This commit is contained in:
		
							parent
							
								
									997a0d432c
								
							
						
					
					
						commit
						901000101a
					
				
							
								
								
									
										457
									
								
								beautify/beautify-css.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										457
									
								
								beautify/beautify-css.js
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,457 @@ | |||
| /*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 | ||||
|         newline_between_rules (true)      - add a new line after every css rule | ||||
| 
 | ||||
|     e.g | ||||
| 
 | ||||
|     css_beautify(css_source_text, { | ||||
|       'indent_size': 1, | ||||
|       'indent_char': '\t', | ||||
|       'selector_separator': ' ', | ||||
|       'end_with_newline': false, | ||||
|       'newline_between_rules': true | ||||
|     }); | ||||
| */ | ||||
| 
 | ||||
| // 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 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
 | ||||
|         if (typeof indentSize === "string") { | ||||
|             indentSize = parseInt(indentSize, 10); | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         // tokenizer
 | ||||
|         var whiteRe = /^\s+$/; | ||||
|         var wordRe = /[\w$\-_]/; | ||||
| 
 | ||||
|         var pos = -1, | ||||
|             ch; | ||||
|         var parenLevel = 0; | ||||
| 
 | ||||
|         function next() { | ||||
|             ch = source_text.charAt(++pos); | ||||
|             return ch || ''; | ||||
|         } | ||||
| 
 | ||||
|         function peek(skipWhitespace) { | ||||
|             var prev_pos = pos; | ||||
|             if (skipWhitespace) { | ||||
|                 eatWhitespace(); | ||||
|             } | ||||
|             result = source_text.charAt(pos + 1) || ''; | ||||
|             pos = prev_pos - 1; | ||||
|             next(); | ||||
|             return result; | ||||
|         } | ||||
| 
 | ||||
|         function eatString(endChars) { | ||||
|             var start = pos; | ||||
|             while (next()) { | ||||
|                 if (ch === "\\") { | ||||
|                     next(); | ||||
|                 } else if (endChars.indexOf(ch) !== -1) { | ||||
|                     break; | ||||
|                 } else if (ch === "\n") { | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|             return source_text.substring(start, pos + 1); | ||||
|         } | ||||
| 
 | ||||
|         function peekString(endChar) { | ||||
|             var prev_pos = pos; | ||||
|             var str = eatString(endChar); | ||||
|             pos = prev_pos - 1; | ||||
|             next(); | ||||
|             return str; | ||||
|         } | ||||
| 
 | ||||
|         function eatWhitespace() { | ||||
|             var result = ''; | ||||
|             while (whiteRe.test(peek())) { | ||||
|                 next(); | ||||
|                 result += ch; | ||||
|             } | ||||
|             return result; | ||||
|         } | ||||
| 
 | ||||
|         function skipWhitespace() { | ||||
|             var result = ''; | ||||
|             if (ch && whiteRe.test(ch)) { | ||||
|                 result = ch; | ||||
|             } | ||||
|             while (whiteRe.test(next())) { | ||||
|                 result += ch; | ||||
|             } | ||||
|             return result; | ||||
|         } | ||||
| 
 | ||||
|         function eatComment(singleLine) { | ||||
|             var start = pos; | ||||
|             singleLine = peek() === "/"; | ||||
|             next(); | ||||
|             while (next()) { | ||||
|                 if (!singleLine && ch === "*" && peek() === "/") { | ||||
|                     next(); | ||||
|                     break; | ||||
|                 } else if (singleLine && ch === "\n") { | ||||
|                     return source_text.substring(start, pos); | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             return source_text.substring(start, pos) + ch; | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         function lookBack(str) { | ||||
|             return source_text.substring(pos - str.length, pos).toLowerCase() === | ||||
|                 str; | ||||
|         } | ||||
| 
 | ||||
|         // Nested pseudo-class if we are insideRule
 | ||||
|         // and the next special character found opens
 | ||||
|         // a new block
 | ||||
|         function foundNestedPseudoClass() { | ||||
|             for (var i = pos + 1; i < source_text.length; i++) { | ||||
|                 var ch = source_text.charAt(i); | ||||
|                 if (ch === "{") { | ||||
|                     return true; | ||||
|                 } else if (ch === ";" || ch === "}" || ch === ")") { | ||||
|                     return false; | ||||
|                 } | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         // printer
 | ||||
|         var basebaseIndentString = source_text.match(/^[\t ]*/)[0]; | ||||
|         var singleIndent = new Array(indentSize + 1).join(indentCharacter); | ||||
|         var indentLevel = 0; | ||||
|         var nestedLevel = 0; | ||||
| 
 | ||||
|         function indent() { | ||||
|             indentLevel++; | ||||
|             basebaseIndentString += singleIndent; | ||||
|         } | ||||
| 
 | ||||
|         function outdent() { | ||||
|             indentLevel--; | ||||
|             basebaseIndentString = basebaseIndentString.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) { | ||||
|                 print.trim(); | ||||
|             } | ||||
| 
 | ||||
|             if (output.length) { | ||||
|                 output.push('\n'); | ||||
|             } | ||||
|             if (basebaseIndentString) { | ||||
|                 output.push(basebaseIndentString); | ||||
|             } | ||||
|         }; | ||||
|         print.singleSpace = function() { | ||||
|             if (output.length && !print._lastCharWhitespace()) { | ||||
|                 output.push(' '); | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
|         print.trim = function() { | ||||
|             while (print._lastCharWhitespace()) { | ||||
|                 output.pop(); | ||||
|             } | ||||
|         }; | ||||
| 
 | ||||
| 
 | ||||
|         var output = []; | ||||
|         if (basebaseIndentString) { | ||||
|             output.push(basebaseIndentString); | ||||
|         } | ||||
|         /*_____________________--------------------_____________________*/ | ||||
| 
 | ||||
|         var insideRule = false; | ||||
|         var enteringConditionalGroup = false; | ||||
|         var top_ch = ''; | ||||
|         var last_top_ch = ''; | ||||
| 
 | ||||
|         while (true) { | ||||
|             var whitespace = skipWhitespace(); | ||||
|             var isAfterSpace = whitespace !== ''; | ||||
|             var isAfterNewline = whitespace.indexOf('\n') !== -1; | ||||
|             last_top_ch = top_ch; | ||||
|             top_ch = ch; | ||||
| 
 | ||||
|             if (!ch) { | ||||
|                 break; | ||||
|             } else if (ch === '/' && peek() === '*') { /* css comment */ | ||||
|                 var header = lookBack(""); | ||||
|                 print.newLine(); | ||||
|                 output.push(eatComment()); | ||||
|                 print.newLine(); | ||||
|                 if (header) { | ||||
|                     print.newLine(true); | ||||
|                 } | ||||
|             } else if (ch === '/' && peek() === '/') { // single line comment
 | ||||
|                 if (!isAfterNewline && last_top_ch !== '{') { | ||||
|                     print.trim(); | ||||
|                 } | ||||
|                 print.singleSpace(); | ||||
|                 output.push(eatComment()); | ||||
|                 print.newLine(); | ||||
|             } else if (ch === '@') { | ||||
|                 // pass along the space we found as a separate item
 | ||||
|                 if (isAfterSpace) { | ||||
|                     print.singleSpace(); | ||||
|                 } | ||||
|                 output.push(ch); | ||||
| 
 | ||||
|                 // strip trailing space, if present, for hash property checks
 | ||||
|                 var variableOrRule = peekString(": ,;{}()[]/='\""); | ||||
| 
 | ||||
|                 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(); | ||||
|                 } | ||||
| 
 | ||||
|                 variableOrRule = variableOrRule.replace(/\s$/, '') | ||||
| 
 | ||||
|                 // might be a nesting at-rule
 | ||||
|                 if (variableOrRule in css_beautify.NESTED_AT_RULE) { | ||||
|                     nestedLevel += 1; | ||||
|                     if (variableOrRule in css_beautify.CONDITIONAL_GROUP_RULE) { | ||||
|                         enteringConditionalGroup = true; | ||||
|                     } | ||||
|                 } | ||||
|             } else if (ch === '{') { | ||||
|                 if (peek(true) === '}') { | ||||
|                     eatWhitespace(); | ||||
|                     next(); | ||||
|                     print.singleSpace(); | ||||
|                     output.push("{}"); | ||||
|                     print.newLine(); | ||||
|                     if (newline_between_rules && indentLevel === 0) { | ||||
|                         print.newLine(true); | ||||
|                     } | ||||
|                 } 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--; | ||||
|                 } | ||||
|                 if (newline_between_rules && indentLevel === 0) { | ||||
|                     print.newLine(true); | ||||
|                 } | ||||
|             } else if (ch === ":") { | ||||
|                 eatWhitespace(); | ||||
|                 if ((insideRule || enteringConditionalGroup) && | ||||
|                     !(lookBack("&") || foundNestedPseudoClass())) { | ||||
|                     // 'property: value' delimiter
 | ||||
|                     // which could be in a conditional group query
 | ||||
|                     output.push(':'); | ||||
|                     print.singleSpace(); | ||||
|                 } else { | ||||
|                     // sass/less parent reference don't use a space
 | ||||
|                     // sass nested pseudo-class don't use a space
 | ||||
|                     if (peek() === ":") { | ||||
|                         // pseudo-element
 | ||||
|                         next(); | ||||
|                         output.push("::"); | ||||
|                     } else { | ||||
|                         // pseudo-class
 | ||||
|                         output.push(':'); | ||||
|                     } | ||||
|                 } | ||||
|             } else if (ch === '"' || ch === '\'') { | ||||
|                 if (isAfterSpace) { | ||||
|                     print.singleSpace(); | ||||
|                 } | ||||
|                 output.push(eatString(ch)); | ||||
|             } else if (ch === ';') { | ||||
|                 output.push(ch); | ||||
|                 print.newLine(); | ||||
|             } 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 { | ||||
|                     parenLevel++; | ||||
|                     if (isAfterSpace) { | ||||
|                         print.singleSpace(); | ||||
|                     } | ||||
|                     output.push(ch); | ||||
|                     eatWhitespace(); | ||||
|                 } | ||||
|             } else if (ch === ')') { | ||||
|                 output.push(ch); | ||||
|                 parenLevel--; | ||||
|             } else if (ch === ',') { | ||||
|                 output.push(ch); | ||||
|                 eatWhitespace(); | ||||
|                 if (!insideRule && selectorSeparatorNewline && parenLevel < 1) { | ||||
|                     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() | ||||
|                 ch = '='; | ||||
|                 output.push(ch); | ||||
|             } else { | ||||
|                 if (isAfterSpace) { | ||||
|                     print.singleSpace(); | ||||
|                 } | ||||
| 
 | ||||
|                 output.push(ch); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         var sweetCode = output.join('').replace(/[\r\n\t ]+$/, ''); | ||||
| 
 | ||||
|         // establish end_with_newline
 | ||||
|         if (end_with_newline) { | ||||
|             sweetCode += "\n"; | ||||
|         } | ||||
| 
 | ||||
|         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 | ||||
|     }; | ||||
| 
 | ||||
|     /*global define */ | ||||
|     if (typeof define === "function" && define.amd) { | ||||
|         // Add support for AMD ( https://github.com/amdjs/amdjs-api/wiki/AMD#defineamd-property- )
 | ||||
|         define([], function() { | ||||
|             return { | ||||
|                 css_beautify: css_beautify | ||||
|             }; | ||||
|         }); | ||||
|     } else if (typeof exports !== "undefined") { | ||||
|         // Add support for CommonJS. Just put this file somewhere on your require.paths
 | ||||
|         // and you will be able to `var html_beautify = require("beautify").html_beautify`.
 | ||||
|         exports.css_beautify = css_beautify; | ||||
|     } else if (typeof window !== "undefined") { | ||||
|         // If we're running a web page and don't have either of the above, add our one global
 | ||||
|         window.css_beautify = css_beautify; | ||||
|     } else if (typeof global !== "undefined") { | ||||
|         // If we don't even have window, try global.
 | ||||
|         global.css_beautify = css_beautify; | ||||
|     } | ||||
| 
 | ||||
| }()); | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user