Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

first commit

  • Loading branch information...
commit e42c31e87316ba3f6cdbf2f3b6c8995ff771c8f5 0 parents
Rickey Visinski authored
2  .gitignore
@@ -0,0 +1,2 @@
+node_modules
+out
7 .npmignore
@@ -0,0 +1,7 @@
+*.html
+.git*
+src/
+test/
+out/
+node_modules/
+build.sh
24 LICENSE
@@ -0,0 +1,24 @@
+Copyright (c) 2009 - 2011, Einar Lielmanis
+
+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.
+
+
17 README.md
@@ -0,0 +1,17 @@
+# node-beautifier
+
+This is a nodejs module built upon Einars js-beautifier.
+It also incorporates the css and html beautifier based upon file extension.
+Easily use [js-beautify][https://github.com/einars/js-beautify] from the command line.
+
+ beautifier app.js style.css index.html
+
+## Install
+
+ npm install beautifier
+
+## License
+
+See LICENSE file.
+
+[js-beautify]: http://jsbeautifier.org/
3  bin/beautifier.js
@@ -0,0 +1,3 @@
+#!/usr/bin/node
+var beautify=require("../lib/beautify"),nopt=require("nopt"),fs=require("fs"),parsed=nopt();function die(b){console.warn(b);console.warn("Usage: "+process.argv[1]+" <scriptfile>{js,css,html}...");process.exit(1)}
+function lintFile(b){var d=b.split("."),c;fs.readFile(b,function(b,a){if(b)throw b;239===a[0]&&187===a[1]&&191===a[2]&&(a=a.slice(3));a=a.toString("utf8");switch(d[d.length-1]){case "js":c=beautify.js_beautify;break;case "css":c=beautify.css_beautify;break;case "html":c=beautify.html_beautify;break;default:die("invalid file format")}console.log(c(a))})}parsed.argv.remain.length||die("No files specified.");parsed.argv.remain.forEach(lintFile);
28 build.sh
@@ -0,0 +1,28 @@
+#!/bin/bash -
+#===============================================================================
+#
+# USAGE: ./build.sh
+#
+# DESCRIPTION: Compile source file into the actual node module
+#
+# AUTHOR: Rickey Visinski
+# REVISION: 0.0.1
+#===============================================================================
+
+set -o nounset # Treat unset variables as an error
+
+BIN=bin/beautifier.js
+LIB=lib/beautify.js
+
+echo '#!/usr/bin/node' > $BIN
+
+# I use the closure compiler, this is the quick and dirty check if you build from source
+if [[ $(which closure) ]] ; then
+ closure --compilation_level SIMPLE_OPTIMIZATIONS --js src/beautify*.js --js_output_file $LIB || exit 1
+ closure --compilation_level SIMPLE_OPTIMIZATIONS --js src/run-jsbeautifier.js >> $BIN || exit 1
+else
+ cat src/beautify*.js > $LIB
+ cat src/run-jsbeautify.js >> $BIN
+fi
+
+chmod +x $BIN
37 lib/beautify.js
@@ -0,0 +1,37 @@
+function css_beautify(v,f){function b(){return n=v.charAt(++d)}function t(a){for(var C=d;b();)if("\\"==n)b(),b();else if(n==a)break;else if("\n"==n)break;return v.substring(C,d+1)}function w(){for(var a=d;C.test(v.charAt(d+1));)d++;return d!=a}function g(){var a=d;do;while(C.test(b()));return d!=a+1}function h(){var a=d;for(b();b();)if("*"==n&&"/"==v.charAt(d+1)){d++;break}return v.substring(a,d+1)}var f=f||{},m=f.indent_size||4,a=f.indent_char||" ";"string"==typeof m&&(m=parseInt(m));var C=/^\s+$/,
+d=-1,n,x=v.match(/^[\r\n]*[\t ]*/)[0],a=Array(m+1).join(a),G=0;print={};print["{"]=function(a){print.singleSpace();r.push(a);print.newLine()};print["}"]=function(a){print.newLine();r.push(a);print.newLine()};print.newLine=function(a){if(!a)for(;C.test(r[r.length-1]);)r.pop();r.length&&r.push("\n");x&&r.push(x)};print.singleSpace=function(){r.length&&!C.test(r[r.length-1])&&r.push(" ")};var r=[];for(x&&r.push(x);;){var q=g();if(!n)break;"{"==n?(G++,x+=a,print["{"](n)):"}"==n?(G--,x=x.slice(0,-m),print["}"](n)):
+'"'==n||"'"==n?r.push(t(n)):";"==n?r.push(n,"\n",x):"/"==n&&"*"==v.charAt(d+1)?(print.newLine(),r.push(h(),"\n",x)):"("==n?(r.push(n),w(),"url"==r.slice(-4,-1).join("").toLowerCase()&&b()&&(")"!=n&&'"'!=n&&"'"!=n?r.push(t(")")):d--)):")"==n?r.push(n):","==n?(w(),r.push(n),print.singleSpace()):("]"!=n&&("["==n||"="==n?w():q&&print.singleSpace()),r.push(n))}return r.join("").replace(/[\n ]+$/,"")}"undefined"!==typeof exports&&(exports.css_beautify=css_beautify);function html_beautify(v,f){var b,t,w,g,h,f=f||{};t=f.indent_size||4;w=f.indent_char||" ";h=f.brace_style||"collapse";g=f.max_char||"120";unformatted=f.unformatted||["a"];b=new function(){this.pos=0;this.token="";this.current_mode="CONTENT";this.tags={parent:"parent1",parentcount:1,parent1:""};this.token_text=this.last_token=this.last_text=this.token_type=this.tag_type="";this.Utils={whitespace:["\n","\r","\t"," "],single_token:"br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed".split(","),
+extra_liners:["head","body","/html"],in_array:function(a,b){for(var d=0;d<b.length;d++)if(a===b[d])return!0;return!1}};this.get_content=function(){for(var a="",b=[],d=!1;"<"!==this.input.charAt(this.pos);){if(this.pos>=this.input.length)return b.length?b.join(""):["","TK_EOF"];a=this.input.charAt(this.pos);this.pos++;this.line_char_count++;if(this.Utils.in_array(a,this.Utils.whitespace))b.length&&(d=!0),this.line_char_count--;else{if(d){if(this.line_char_count>=this.max_char){b.push("\n");for(d=0;d<
+this.indent_level;d++)b.push(this.indent_string);this.line_char_count=0}else b.push(" "),this.line_char_count++;d=!1}b.push(a)}}return b.length?b.join(""):""};this.get_contents_to=function(a){if(this.pos==this.input.length)return["","TK_EOF"];var b="",a=RegExp("</"+a+"\\s*>","igm");a.lastIndex=this.pos;a=(a=a.exec(this.input))?a.index:this.input.length;this.pos<a&&(b=this.input.substring(this.pos,a),this.pos=a);return b};this.record_tag=function(a){this.tags[a+"count"]?this.tags[a+"count"]++:this.tags[a+
+"count"]=1;this.tags[a+this.tags[a+"count"]]=this.indent_level;this.tags[a+this.tags[a+"count"]+"parent"]=this.tags.parent;this.tags.parent=a+this.tags[a+"count"]};this.retrieve_tag=function(a){if(this.tags[a+"count"]){for(var b=this.tags.parent;b&&!(a+this.tags[a+"count"]===b);)b=this.tags[b+"parent"];b&&(this.indent_level=this.tags[a+this.tags[a+"count"]],this.tags.parent=this.tags[b+"parent"]);delete this.tags[a+this.tags[a+"count"]+"parent"];delete this.tags[a+this.tags[a+"count"]];1==this.tags[a+
+"count"]?delete this.tags[a+"count"]:this.tags[a+"count"]--}};this.get_tag=function(){var a="",b=[],d=!1;do{if(this.pos>=this.input.length)return b.length?b.join(""):["","TK_EOF"];a=this.input.charAt(this.pos);this.pos++;this.line_char_count++;if(this.Utils.in_array(a,this.Utils.whitespace))d=!0,this.line_char_count--;else{if("'"===a||'"'===a)if(!b[1]||"!"!==b[1])a+=this.get_unformatted(a),d=!0;"="===a&&(d=!1);b.length&&"="!==b[b.length-1]&&">"!==a&&d&&(this.line_char_count>=this.max_char?(this.print_newline(!1,
+b),this.line_char_count=0):(b.push(" "),this.line_char_count++),d=!1);b.push(a)}}while(">"!==a);a=b.join("");d=-1!=a.indexOf(" ")?a.indexOf(" "):a.indexOf(">");d=a.substring(1,d).toLowerCase();"/"===a.charAt(a.length-2)||this.Utils.in_array(d,this.Utils.single_token)?this.tag_type="SINGLE":"script"===d?(this.record_tag(d),this.tag_type="SCRIPT"):"style"===d?(this.record_tag(d),this.tag_type="STYLE"):this.Utils.in_array(d,unformatted)?(a=this.get_unformatted("</"+d+">",a),b.push(a),this.tag_type="SINGLE"):
+"!"===d.charAt(0)?-1!=d.indexOf("[if")?(-1!=a.indexOf("!IE")&&(a=this.get_unformatted("--\>",a),b.push(a)),this.tag_type="START"):-1!=d.indexOf("[endif")?(this.tag_type="END",this.unindent()):(a=-1!=d.indexOf("[cdata[")?this.get_unformatted("]]\>",a):this.get_unformatted("--\>",a),b.push(a),this.tag_type="SINGLE"):("/"===d.charAt(0)?(this.retrieve_tag(d.substring(1)),this.tag_type="END"):(this.record_tag(d),this.tag_type="START"),this.Utils.in_array(d,this.Utils.extra_liners)&&this.print_newline(!0,
+this.output));return b.join("")};this.get_unformatted=function(a,b){if(b&&-1!=b.indexOf(a))return"";var d="",g="",f=!0;do{if(this.pos>=this.input.length)break;d=this.input.charAt(this.pos);this.pos++;if(this.Utils.in_array(d,this.Utils.whitespace)){if(!f){this.line_char_count--;continue}if("\n"===d||"\r"===d){g+="\n";this.line_char_count=0;continue}}g+=d;this.line_char_count++;f=!0}while(-1==g.indexOf(a));return g};this.get_token=function(){var a;if("TK_TAG_SCRIPT"===this.last_token||"TK_TAG_STYLE"===
+this.last_token){var b=this.last_token.substr(7);a=this.get_contents_to(b);return"string"!==typeof a?a:[a,"TK_"+b]}if("CONTENT"===this.current_mode)return a=this.get_content(),"string"!==typeof a?a:[a,"TK_CONTENT"];if("TAG"===this.current_mode)return a=this.get_tag(),"string"!==typeof a?a:[a,"TK_TAG_"+this.tag_type]};this.get_full_indent=function(a){a=this.indent_level+a||0;return 1>a?"":Array(a+1).join(this.indent_string)};this.printer=function(a,b,d,g,f){this.input=a||"";this.output=[];this.indent_character=
+b;this.indent_string="";this.indent_size=d;this.brace_style=f;this.indent_level=0;this.max_char=g;for(a=this.line_char_count=0;a<this.indent_size;a++)this.indent_string+=this.indent_character;this.print_newline=function(a,b){this.line_char_count=0;if(b&&b.length){if(!a)for(;this.Utils.in_array(b[b.length-1],this.Utils.whitespace);)b.pop();b.push("\n");for(var d=0;d<this.indent_level;d++)b.push(this.indent_string)}};this.print_token=function(b){this.output.push(b)};this.indent=function(){this.indent_level++};
+this.unindent=function(){0<this.indent_level&&this.indent_level--}};return this};for(b.printer(v,w,t,g,h);;){t=b.get_token();b.token_text=t[0];b.token_type=t[1];if("TK_EOF"===b.token_type)break;switch(b.token_type){case "TK_TAG_START":b.print_newline(!1,b.output);b.print_token(b.token_text);b.indent();b.current_mode="CONTENT";break;case "TK_TAG_STYLE":case "TK_TAG_SCRIPT":b.print_newline(!1,b.output);b.print_token(b.token_text);b.current_mode="CONTENT";break;case "TK_TAG_END":"TK_CONTENT"===b.last_token&&
+""===b.last_text&&(t=b.token_text.match(/\w+/)[0],w=b.output[b.output.length-1].match(/<\s*(\w+)/),(null===w||w[1]!==t)&&b.print_newline(!0,b.output));b.print_token(b.token_text);b.current_mode="CONTENT";break;case "TK_TAG_SINGLE":b.print_newline(!1,b.output);b.print_token(b.token_text);b.current_mode="CONTENT";break;case "TK_CONTENT":""!==b.token_text&&b.print_token(b.token_text);b.current_mode="TAG";break;case "TK_STYLE":case "TK_SCRIPT":if(""!==b.token_text){b.output.push("\n");t=b.token_text;
+if("TK_SCRIPT"==b.token_type)var m="function"==typeof js_beautify&&js_beautify;else"TK_STYLE"==b.token_type&&(m="function"==typeof css_beautify&&css_beautify);g="keep"==f.indent_scripts?0:"separate"==f.indent_scripts?-b.indent_level:1;w=b.get_full_indent(g);m?t=m(t.replace(/^\s*/,w),f):(h=t.match(/^\s*/)[0].match(/[^\n\r]*$/)[0].split(b.indent_string).length-1,g=b.get_full_indent(g-h),t=t.replace(/^\s*/,w).replace(/\r\n|\r|\n/g,"\n"+g).replace(/\s*$/,""));t&&(b.print_token(t),b.print_newline(!0,b.output))}b.current_mode=
+"TAG"}b.last_token=b.token_type;b.last_text=b.token_text}return b.output.join("")}"undefined"!==typeof exports&&(exports.html_beautify=html_beautify);function js_beautify(v,f){function b(b){for(b="undefined"===typeof b?!1:b;l.length&&(" "===l[l.length-1]||l[l.length-1]===D||l[l.length-1]===K||b&&("\n"===l[l.length-1]||"\r"===l[l.length-1]));)l.pop()}function t(b){return b.replace(/^\s\s*|\s\s*$/,"")}function w(){var b=z;z=!1;g();z=b}function g(a){e.eat_next_space=!1;if(!z||!n(e.mode))if(a="undefined"===typeof a?!0:a,e.if_line=!1,b(),l.length){if("\n"!==l[l.length-1]||!a)E=!0,l.push("\n");K&&l.push(K);for(a=0;a<e.indentation_level;a+=1)l.push(D);
+e.var_line&&e.var_line_reindented&&l.push(D);e.case_body&&l.push(D)}}function h(){if("TK_COMMENT"===i)return g(!0);if(e.eat_next_space)e.eat_next_space=!1;else{var b=" ";l.length&&(b=l[l.length-1]);" "!==b&&"\n"!==b&&b!==D&&l.push(" ")}}function m(){E=!1;e.eat_next_space=!1;l.push(o)}function a(){e.indentation_level+=1}function C(){l.length&&l[l.length-1]===D&&l.pop()}function d(b){e&&L.push(e);e={previous_mode:e?e.mode:"BLOCK",mode:b,var_line:!1,var_line_tainted:!1,var_line_reindented:!1,in_html_comment:!1,
+if_line:!1,in_case:!1,case_body:!1,eat_next_space:!1,indentation_baseline:-1,indentation_level:e?e.indentation_level+(e.case_body?1:0)+(e.var_line&&e.var_line_reindented?1:0):0,ternary_depth:0}}function n(b){return"[EXPRESSION]"===b||"[INDENTED-EXPRESSION]"===b}function x(b){return q(b,["[EXPRESSION]","(EXPRESSION)","(FOR-EXPRESSION)","(COND-EXPRESSION)"])}function G(){M="DO_BLOCK"===e.mode;if(0<L.length){var b=e.mode;e=L.pop();e.previous_mode=b}}function r(b,a){for(var c=0;c<b.length;c++)if(t(b[c])[0]!=
+a)return!1;return!0}function q(b,a){for(var c=0;c<a.length;c+=1)if(a[c]===b)return!0;return!1}function P(b){for(var a=c,e=k.charAt(a);q(e,N)&&e!=b;){a++;if(a>=u)return 0;e=k.charAt(a)}return e}function Q(){A=0;if(c>=u)return["","TK_EOF"];H=!1;var a=k.charAt(c);c+=1;if(z&&n(e.mode)){for(var d=0;q(a,N);){"\n"===a?(b(),l.push("\n"),E=!0,d=0):"\t"===a?d+=4:"\r"!==a&&(d+=1);if(c>=u)return["","TK_EOF"];a=k.charAt(c);c+=1}-1===e.indentation_baseline&&(e.indentation_baseline=d);if(E){var f;for(f=0;f<e.indentation_level+
+1;f+=1)l.push(D);if(-1!==e.indentation_baseline)for(f=0;f<d-e.indentation_baseline;f++)l.push(" ")}}else{for(;q(a,N);){"\n"===a&&(A+=T?A<=T?1:0:1);if(c>=u)return["","TK_EOF"];a=k.charAt(c);c+=1}if(R&&1<A)for(f=0;f<A;f+=1)g(0===f),E=!0;H=0<A}if(q(a,O)){if(c<u)for(;q(k.charAt(c),O)&&!(a+=k.charAt(c),c+=1,c===u););if(c!==u&&a.match(/^[0-9]+[Ee]$/)&&("-"===k.charAt(c)||"+"===k.charAt(c)))return d=k.charAt(c),c+=1,f=Q(c),a+=d+f[0],[a,"TK_WORD"];if("in"===a)return[a,"TK_OPERATOR"];H&&"TK_OPERATOR"!==i&&
+"TK_EQUALS"!==i&&!e.if_line&&(R||"var"!==j)&&g();return[a,"TK_WORD"]}if("("===a||"["===a)return[a,"TK_START_EXPR"];if(")"===a||"]"===a)return[a,"TK_END_EXPR"];if("{"===a)return[a,"TK_START_BLOCK"];if("}"===a)return[a,"TK_END_BLOCK"];if(";"===a)return[a,"TK_SEMICOLON"];if("/"===a){d="";f=!0;if("*"===k.charAt(c)){c+=1;if(c<u)for(;!("*"===k.charAt(c)&&k.charAt(c+1)&&"/"===k.charAt(c+1))&&c<u;){a=k.charAt(c);d+=a;if("\r"===a||"\n"===a)f=!1;c+=1;if(c>=u)break}c+=2;return f&&0==A?["/*"+d+"*/","TK_INLINE_COMMENT"]:
+["/*"+d+"*/","TK_BLOCK_COMMENT"]}if("/"===k.charAt(c)){for(d=a;"\r"!==k.charAt(c)&&"\n"!==k.charAt(c)&&!(d+=k.charAt(c),c+=1,c>=u););c+=1;H&&g();return[d,"TK_COMMENT"]}}if("'"===a||'"'===a||"/"===a&&("TK_WORD"===i&&q(j,["return","do","else"])||")"===j&&q(e.previous_mode,["(COND-EXPRESSION)","(FOR-EXPRESSION)"])||"TK_COMMENT"===i||"TK_START_EXPR"===i||"TK_START_BLOCK"===i||"TK_END_BLOCK"===i||"TK_OPERATOR"===i||"TK_EQUALS"===i||"TK_EOF"===i||"TK_SEMICOLON"===i)){d=a;f=!1;var h=a;if(c<u)if("/"===d)for(a=
+!1;f||a||k.charAt(c)!==d;){if(h+=k.charAt(c),f?f=!1:(f="\\"===k.charAt(c),"["===k.charAt(c)?a=!0:"]"===k.charAt(c)&&(a=!1)),c+=1,c>=u)return[h,"TK_STRING"]}else for(;f||k.charAt(c)!==d;)if(h+=k.charAt(c),f=f?!1:"\\"===k.charAt(c),c+=1,c>=u)return[h,"TK_STRING"];c+=1;h+=d;if("/"===d)for(;c<u&&q(k.charAt(c),O);)h+=k.charAt(c),c+=1;return[h,"TK_STRING"]}if("#"===a){if(0===l.length&&"!"===k.charAt(c)){for(h=a;c<u&&"\n"!=a;)a=k.charAt(c),h+=a,c+=1;l.push(t(h)+"\n");g();return Q()}d="#";if(c<u&&q(k.charAt(c),
+U)){do a=k.charAt(c),d+=a,c+=1;while(c<u&&"#"!==a&&"="!==a);"#"!==a&&("["===k.charAt(c)&&"]"===k.charAt(c+1)?(d+="[]",c+=2):"{"===k.charAt(c)&&"}"===k.charAt(c+1)&&(d+="{}",c+=2));return[d,"TK_WORD"]}}if("<"===a&&"<\!--"===k.substring(c-1,c+3)){c+=3;for(a="<\!--";"\n"!=k[c]&&c<u;)a+=k[c],c++;e.in_html_comment=!0;return[a,"TK_COMMENT"]}if("-"===a&&e.in_html_comment&&"--\>"===k.substring(c-1,c+2))return e.in_html_comment=!1,c+=2,H&&g(),["--\>","TK_COMMENT"];if(q(a,I)){for(;c<u&&q(a+k.charAt(c),I)&&
+!(a+=k.charAt(c),c+=1,c>=u););return"="===a?[a,"TK_EQUALS"]:[a,"TK_OPERATOR"]}return[a,"TK_UNKNOWN"]}var k,l,o,i,j,s,B,e,L,D,N,O,I,c,F,U,p,J,M,H,E,A,K="",f=f?f:{},y;void 0!==f.space_after_anon_function&&void 0===f.jslint_happy&&(f.jslint_happy=f.space_after_anon_function);void 0!==f.braces_on_own_line&&(y=f.braces_on_own_line?"expand":"collapse");y=f.brace_style?f.brace_style:y?y:"collapse";B=f.indent_size?f.indent_size:4;F=f.indent_char?f.indent_char:" ";var R="undefined"===typeof f.preserve_newlines?
+!0:f.preserve_newlines,T="undefined"===typeof f.max_preserve_newlines?!1:f.max_preserve_newlines,z="undefined"===typeof f.keep_array_indentation?!1:f.keep_array_indentation,V="undefined"===typeof f.space_before_conditional?!0:f.space_before_conditional,S="undefined"===typeof f.indent_case?!1:f.indent_case;E=!1;var u=v.length;for(D="";0<B;)D+=F,B-=1;for(;v&&(" "===v[0]||"\t"===v[0]);)K+=v[0],v=v.substring(1);k=v;B="";i="TK_START_EXPR";s=j="";l=[];M=!1;N=["\n","\r","\t"," "];O="a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,0,1,2,3,4,5,6,7,8,9,_,$".split(",");
+U="0,1,2,3,4,5,6,7,8,9".split(",");I="+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::";I+=" <%= <% %> <?= <? ?>";I=I.split(" ");F="continue,try,throw,return,var,if,switch,case,default,for,while,break,function".split(",");L=[];d("BLOCK");for(c=0;;){J=Q(c);o=J[0];J=J[1];if("TK_EOF"===J)break;switch(J){case "TK_START_EXPR":if("["===o){if("TK_WORD"===i||")"===j){q(j,F)&&h();d("(EXPRESSION)");m();break}"[EXPRESSION]"===e.mode||"[INDENTED-EXPRESSION]"===
+e.mode?"]"===s&&","===j?("[EXPRESSION]"===e.mode&&(e.mode="[INDENTED-EXPRESSION]",z||a()),d("[EXPRESSION]"),z||g()):"["===j?("[EXPRESSION]"===e.mode&&(e.mode="[INDENTED-EXPRESSION]",z||a()),d("[EXPRESSION]"),z||g()):d("[EXPRESSION]"):d("[EXPRESSION]")}else"for"===B?d("(FOR-EXPRESSION)"):q(B,["if","while"])?d("(COND-EXPRESSION)"):d("(EXPRESSION)");";"===j||"TK_START_BLOCK"===i?g():"TK_END_EXPR"===i||"TK_START_EXPR"===i||"TK_END_BLOCK"===i||"."===j?H&&g():"TK_WORD"!==i&&"TK_OPERATOR"!==i?h():"function"===
+B||"typeof"===B?h():(q(j,F)||"catch"===j)&&V&&h();m();break;case "TK_END_EXPR":if("]"===o)if(z){if("}"===j){C();m();G();break}}else if("[INDENTED-EXPRESSION]"===e.mode&&"]"===j){G();g();m();break}G();m();break;case "TK_START_BLOCK":"do"===B?d("DO_BLOCK"):d("BLOCK");"expand"==y||"expand-strict"==y?(s=!1,"expand-strict"==y?(s="}"==P())||g(!0):"TK_OPERATOR"!==i&&("return"===j||"="===j||"throw"===j?h():g(!0)),m(),s||a()):("TK_OPERATOR"!==i&&"TK_START_EXPR"!==i?"TK_START_BLOCK"===i?g():h():n(e.previous_mode)&&
+","===j&&("}"===s?h():g()),a(),m());break;case "TK_END_BLOCK":G();"expand"==y||"expand-strict"==y?"{"!==j&&g():"TK_START_BLOCK"===i?E?C():b():n(e.mode)&&z?(z=!1,g(),z=!0):g();m();break;case "TK_WORD":if(M){h();m();h();M=!1;break}if("function"===o&&(e.var_line&&(e.var_line_reindented=!0),(E||";"===j)&&"{"!==j&&"TK_BLOCK_COMMENT"!=i&&"TK_COMMENT"!=i)){A=E?A:0;R||(A=1);for(p=0;p<2-A;p++)g(!1)}if("case"===o||"default"===o){":"===j||e.case_body?C():(S||e.indentation_level--,g(),S||e.indentation_level++);
+m();e.in_case=!0;e.case_body=!1;break}p="NONE";"TK_END_BLOCK"===i?q(o.toLowerCase(),["else","catch","finally"])?"expand"==y||"end-expand"==y||"expand-strict"==y?p="NEWLINE":(p="SPACE",h()):p="NEWLINE":"TK_SEMICOLON"===i&&("BLOCK"===e.mode||"DO_BLOCK"===e.mode)?p="NEWLINE":"TK_SEMICOLON"===i&&x(e.mode)?p="SPACE":"TK_STRING"===i?p="NEWLINE":"TK_WORD"===i?("else"===j&&b(!0),p="SPACE"):"TK_START_BLOCK"===i?p="NEWLINE":"TK_END_EXPR"===i&&(h(),p="NEWLINE");if(q(o,F)&&")"!==j&&(p="else"==j?"SPACE":"NEWLINE",
+"function"===o&&("get"===j||"set"===j)))p="SPACE";e.if_line&&"TK_END_EXPR"===i&&(e.if_line=!1);if(q(o.toLowerCase(),["else","catch","finally"]))"TK_END_BLOCK"!==i||"expand"==y||"end-expand"==y||"expand-strict"==y?g():(b(!0),h());else if("NEWLINE"===p){if(!(("TK_START_EXPR"===i||"="===j||","===j)&&"function"===o))if("function"===o&&"new"==j)h();else if("return"===j||"throw"===j)h();else if("TK_END_EXPR"!==i){if(("TK_START_EXPR"!==i||"var"!==o)&&":"!==j)"if"===o&&"else"===B&&"{"!==j?h():(e.var_line=
+!1,e.var_line_reindented=!1,g())}else q(o,F)&&")"!=j&&(e.var_line=!1,e.var_line_reindented=!1,g())}else n(e.mode)&&","===j&&"}"===s?g():"SPACE"===p&&h();m();B=o;"var"===o&&(e.var_line=!0,e.var_line_reindented=!1,e.var_line_tainted=!1);"if"===o&&(e.if_line=!0);"else"===o&&(e.if_line=!1);break;case "TK_SEMICOLON":m();e.var_line=!1;e.var_line_reindented=!1;"OBJECT"==e.mode&&(e.mode="BLOCK");break;case "TK_STRING":"TK_END_EXPR"===i&&q(e.previous_mode,["(COND-EXPRESSION)","(FOR-EXPRESSION)"])?h():"TK_STRING"==
+i||"TK_START_BLOCK"===i||"TK_END_BLOCK"===i||"TK_SEMICOLON"===i?g():"TK_WORD"===i&&h();m();break;case "TK_EQUALS":e.var_line&&(e.var_line_tainted=!0);h();m();h();break;case "TK_OPERATOR":p=s=!0;e.var_line&&","===o&&x(e.mode)&&(e.var_line_tainted=!1);if(e.var_line&&","===o)if(e.var_line_tainted){m();e.var_line_reindented=!0;e.var_line_tainted=!1;g();break}else e.var_line_tainted=!1;if("return"===j||"throw"===j){h();m();break}if(":"===o&&e.in_case){S&&(e.case_body=!0);m();g();e.in_case=!1;break}if("::"===
+o){m();break}if(","===o){e.var_line?e.var_line_tainted?(m(),g(),e.var_line_tainted=!1):(m(),h()):"TK_END_BLOCK"===i&&"(EXPRESSION)"!==e.mode?(m(),"OBJECT"===e.mode&&"}"===j?g():h()):"OBJECT"===e.mode?(m(),g()):(m(),h());break}else q(o,["--","++","!"])||q(o,["-","+"])&&(q(i,["TK_START_BLOCK","TK_START_EXPR","TK_EQUALS","TK_OPERATOR"])||q(j,F))?(p=s=!1,";"===j&&x(e.mode)&&(s=!0),"TK_WORD"===i&&q(j,F)&&(s=!0),"BLOCK"===e.mode&&("{"===j||";"===j)&&g()):"."===o?s=!1:":"===o?0==e.ternary_depth?(e.mode=
+"OBJECT",s=!1):e.ternary_depth-=1:"?"===o&&(e.ternary_depth+=1);s&&h();m();p&&h();break;case "TK_BLOCK_COMMENT":s=o.split(/\x0a|\x0d\x0a/);if(r(s.slice(1),"*")){g();l.push(s[0]);for(p=1;p<s.length;p++)g(),l.push(" "),l.push(t(s[p]))}else{1<s.length?g():"TK_END_BLOCK"===i?g():h();for(p=0;p<s.length;p++)l.push(s[p]),l.push("\n")}"\n"!=P("\n")&&g();break;case "TK_INLINE_COMMENT":h();m();x(e.mode)?h():w();break;case "TK_COMMENT":H?g():h();m();"\n"!=P("\n")&&w();break;case "TK_UNKNOWN":("return"===j||
+"throw"===j)&&h(),m()}s=j;i=J;j=o}return K+l.join("").replace(/[\n ]+$/,"")}"undefined"!==typeof exports&&(exports.js_beautify=js_beautify);
42 package.json
@@ -0,0 +1,42 @@
+{
+ "name": "beautifier",
+ "description": "The JavaScript, html, and css beautifier",
+ "homepage": "https://github.com/einars/js-beautify",
+ "keywords": [
+ "lint"
+ ],
+ "version": "0.1.1",
+ "author" : "Rickey Visinski",
+ "contributors": [
+ "Einar Lielmanis <einar@jsbeautifier.org>",
+ "Nochum Sossonko <nsossonko@hotmail.com>",
+ "Harutyun Amirjanyan <amirjanyan@gmail.com>",
+ "Anders Conbere <aconbere@gmail.com>"
+ ],
+ "bin": {
+ "beautifier": "./bin/beautifier.js"
+ },
+ "main": "./lib/beautify.js",
+ "dependencies": {
+ "nopt": "~1.0.0"
+ },
+ "engines": {
+ "node": ">=0.4.12"
+ },
+ "directories": {
+ "lib": "./lib"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git://github.com/rickeyski/node-beautifier.git"
+ },
+ "bugs": {
+ "url": "https://github.com/rickeyski/node-beautifier/issues"
+ },
+ "licenses": [
+ {
+ "type": "Modified MIT / BSD",
+ "url": "https://github.com/rickeyski/node-beautifier/blob/master/LICENSE"
+ }
+ ]
+}
199 src/beautify-css.js
@@ -0,0 +1,199 @@
+/*
+
+ CSS Beautifier
+---------------
+
+ Written by Harutyun Amirjanyan, (amirjanyan@gmail.com)
+
+ Based on code initially developed by: Einar Lielmanis, <elfz@laacz.lv>
+ http://jsbeautifier.org/
+
+
+ You are free to use this in any way you want, in case you find this useful or working for you.
+
+ Usage:
+ css_beautify(source_text);
+ css_beautify(source_text, options);
+
+ The options are:
+ indent_size (default 4) — indentation size,
+ indent_char (default space) — character to indent with,
+
+ e.g
+
+ css_beautify(css_source_text, {
+ 'indent_size': 1,
+ 'indent_char': '\t'
+ });
+*/
+
+// http://www.w3.org/TR/CSS21/syndata.html#tokenization
+// http://www.w3.org/TR/css3-syntax/
+//
+function css_beautify(source_text, options) {
+ options = options || {};
+ var indentSize = options.indent_size || 4;
+ var indentCharacter = options.indent_char || ' ';
+
+ // compatibility
+ if (typeof indentSize == "string")
+ indentSize = parseInt(indentSize);
+
+
+ // tokenizer
+ var whiteRe = /^\s+$/;
+ var wordRe = /[\w$\-_]/;
+
+ var pos = -1, ch;
+ function next() {
+ return ch = source_text.charAt(++pos)
+ }
+ function peek() {
+ return source_text.charAt(pos+1)
+ }
+ function eatString(comma) {
+ var start = pos;
+ while(next()){
+ if (ch=="\\"){
+ next();
+ next();
+ } else if (ch == comma) {
+ 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() {
+ var start = pos;
+ next();
+ while (next()) {
+ if (ch == "*" && peek() == "/") {
+ pos ++;
+ break;
+ }
+ }
+
+ return source_text.substring(start, pos + 1);
+ }
+
+
+ function lookBack(str, index) {
+ return output.slice(-str.length + (index||0), index).join("").toLowerCase() == str;
+ }
+
+ // printer
+ var indentString = source_text.match(/^[\r\n]*[\t ]*/)[0];
+ var singleIndent = Array(indentSize + 1).join(indentCharacter);
+ var indentLevel = 0;
+ function indent() {
+ indentLevel++;
+ indentString += singleIndent;
+ }
+ function outdent() {
+ indentLevel--;
+ indentString = indentString.slice(0, -indentSize);
+ }
+
+ print = {}
+ print["{"] = function(ch) {
+ print.singleSpace();
+ output.push(ch);
+ print.newLine();
+ }
+ print["}"] = function(ch) {
+ print.newLine();
+ output.push(ch);
+ print.newLine();
+ }
+
+ print.newLine = function(keepWhitespace) {
+ if (!keepWhitespace)
+ while (whiteRe.test(output[output.length - 1]))
+ output.pop();
+
+ if (output.length)
+ output.push('\n');
+ if (indentString)
+ output.push(indentString);
+ }
+ print.singleSpace = function() {
+ if (output.length && !whiteRe.test(output[output.length - 1]))
+ output.push(' ');
+ }
+ var output = [];
+ if (indentString)
+ output.push(indentString);
+ /*_____________________--------------------_____________________*/
+
+ while(true) {
+ var isAfterSpace = skipWhitespace();
+
+ if (!ch)
+ break;
+
+ if (ch == '{') {
+ indent();
+ print["{"](ch);
+ } else if (ch == '}') {
+ outdent();
+ print["}"](ch);
+ } else if (ch == '"' || ch == '\'') {
+ output.push(eatString(ch))
+ } else if (ch == ';') {
+ output.push(ch, '\n', indentString);
+ } else if (ch == '/' && peek() == '*') { // comment
+ print.newLine();
+ output.push(eatComment(), "\n", indentString);
+ } else if (ch == '(') { // may be a url
+ output.push(ch);
+ eatWhitespace();
+ if (lookBack("url", -1) && next()) {
+ if (ch != ')' && ch != '"' && ch != '\'')
+ output.push(eatString(')'));
+ else
+ pos--;
+ }
+ } else if (ch == ')') {
+ output.push(ch);
+ } else if (ch == ',') {
+ eatWhitespace();
+ output.push(ch);
+ print.singleSpace();
+ } else if (ch == ']') {
+ output.push(ch);
+ } else if (ch == '[' || ch == '=') { // no whitespace before or after
+ eatWhitespace();
+ output.push(ch);
+ } else {
+ if (isAfterSpace)
+ print.singleSpace();
+
+ output.push(ch);
+ }
+ }
+
+
+ var sweetCode = output.join('').replace(/[\n ]+$/, '');
+ return sweetCode;
+}
+
+
+if (typeof exports !== "undefined")
+ exports.css_beautify = css_beautify;
518 src/beautify-html.js
@@ -0,0 +1,518 @@
+/*
+
+ Style HTML
+---------------
+
+ Written by Nochum Sossonko, (nsossonko@hotmail.com)
+
+ Based on code initially developed by: Einar Lielmanis, <elfz@laacz.lv>
+ http://jsbeautifier.org/
+
+
+ You are free to use this in any way you want, in case you find this useful or working for you.
+
+ Usage:
+ style_html(html_source);
+
+ style_html(html_source, options);
+
+ The options are:
+ indent_size (default 4) — indentation size,
+ indent_char (default space) — character to indent with,
+ max_char (default 70) - maximum amount of characters per line,
+ brace_style (default "collapse") - "collapse" | "expand" | "end-expand"
+ put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line.
+ unformatted (default ['a']) - list of tags, that shouldn't be reformatted
+ indent_scripts (default normal) - "keep"|"separate"|"normal"
+
+ e.g.
+
+ style_html(html_source, {
+ 'indent_size': 2,
+ 'indent_char': ' ',
+ 'max_char': 78,
+ 'brace_style': 'expand',
+ 'unformatted': ['a', 'sub', 'sup', 'b', 'i', 'u']
+ });
+*/
+
+function html_beautify(html_source, options) {
+//Wrapper function to invoke all the necessary constructors and deal with the output.
+
+ var multi_parser,
+ indent_size,
+ indent_character,
+ max_char,
+ brace_style;
+
+ options = options || {};
+ indent_size = options.indent_size || 4;
+ indent_character = options.indent_char || ' ';
+ brace_style = options.brace_style || 'collapse';
+ max_char = options.max_char || '120';
+ unformatted = options.unformatted || ['a'];
+
+ function Parser() {
+
+ this.pos = 0; //Parser position
+ this.token = '';
+ this.current_mode = 'CONTENT'; //reflects the current Parser mode: TAG/CONTENT
+ this.tags = { //An object to hold tags, their position, and their parent-tags, initiated with default values
+ parent: 'parent1',
+ parentcount: 1,
+ parent1: ''
+ };
+ this.tag_type = '';
+ this.token_text = this.last_token = this.last_text = this.token_type = '';
+
+ this.Utils = { //Uilities made available to the various functions
+ whitespace: "\n\r\t ".split(''),
+ single_token: 'br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed'.split(','), //all the single tags for HTML
+ extra_liners: 'head,body,/html'.split(','), //for tags that need a line of whitespace before them
+ in_array: function (what, arr) {
+ for (var i=0; i<arr.length; i++) {
+ if (what === arr[i]) {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ this.get_content = function () { //function to capture regular content between tags
+
+ var input_char = '';
+ var content = [];
+ var space = false; //if a space is needed
+ while (this.input.charAt(this.pos) !== '<') {
+ if (this.pos >= this.input.length) {
+ return content.length?content.join(''):['', 'TK_EOF'];
+ }
+
+ input_char = this.input.charAt(this.pos);
+ this.pos++;
+ this.line_char_count++;
+
+ if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
+ if (content.length) {
+ space = true;
+ }
+ this.line_char_count--;
+ continue; //don't want to insert unnecessary space
+ }
+ else if (space) {
+ if (this.line_char_count >= this.max_char) { //insert a line when the max_char is reached
+ content.push('\n');
+ for (var i=0; i<this.indent_level; i++) {
+ content.push(this.indent_string);
+ }
+ this.line_char_count = 0;
+ }
+ else{
+ content.push(' ');
+ this.line_char_count++;
+ }
+ space = false;
+ }
+ content.push(input_char); //letter at-a-time (or string) inserted to an array
+ }
+ return content.length?content.join(''):'';
+ }
+
+ this.get_contents_to = function (name) { //get the full content of a script or style to pass to js_beautify
+ if (this.pos == this.input.length) {
+ return ['', 'TK_EOF'];
+ }
+ var input_char = '';
+ var content = '';
+ var reg_match = new RegExp('\<\/' + name + '\\s*\>', 'igm');
+ reg_match.lastIndex = this.pos;
+ var reg_array = reg_match.exec(this.input);
+ var end_script = reg_array?reg_array.index:this.input.length; //absolute end of script
+ if(this.pos < end_script) { //get everything in between the script tags
+ content = this.input.substring(this.pos, end_script);
+ this.pos = end_script;
+ }
+ return content;
+ }
+
+ this.record_tag = function (tag){ //function to record a tag and its parent in this.tags Object
+ if (this.tags[tag + 'count']) { //check for the existence of this tag type
+ this.tags[tag + 'count']++;
+ this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
+ }
+ else { //otherwise initialize this tag type
+ this.tags[tag + 'count'] = 1;
+ this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
+ }
+ this.tags[tag + this.tags[tag + 'count'] + 'parent'] = this.tags.parent; //set the parent (i.e. in the case of a div this.tags.div1parent)
+ this.tags.parent = tag + this.tags[tag + 'count']; //and make this the current parent (i.e. in the case of a div 'div1')
+ }
+
+ this.retrieve_tag = function (tag) { //function to retrieve the opening tag to the corresponding closer
+ if (this.tags[tag + 'count']) { //if the openener is not in the Object we ignore it
+ var temp_parent = this.tags.parent; //check to see if it's a closable tag.
+ while (temp_parent) { //till we reach '' (the initial value);
+ if (tag + this.tags[tag + 'count'] === temp_parent) { //if this is it use it
+ break;
+ }
+ temp_parent = this.tags[temp_parent + 'parent']; //otherwise keep on climbing up the DOM Tree
+ }
+ if (temp_parent) { //if we caught something
+ this.indent_level = this.tags[tag + this.tags[tag + 'count']]; //set the indent_level accordingly
+ this.tags.parent = this.tags[temp_parent + 'parent']; //and set the current parent
+ }
+ delete this.tags[tag + this.tags[tag + 'count'] + 'parent']; //delete the closed tags parent reference...
+ delete this.tags[tag + this.tags[tag + 'count']]; //...and the tag itself
+ if (this.tags[tag + 'count'] == 1) {
+ delete this.tags[tag + 'count'];
+ }
+ else {
+ this.tags[tag + 'count']--;
+ }
+ }
+ }
+
+ this.get_tag = function () { //function to get a full tag and parse its type
+ var input_char = '';
+ var content = [];
+ var space = false;
+
+ do {
+ if (this.pos >= this.input.length) {
+ return content.length?content.join(''):['', 'TK_EOF'];
+ }
+
+ input_char = this.input.charAt(this.pos);
+ this.pos++;
+ this.line_char_count++;
+
+ if (this.Utils.in_array(input_char, this.Utils.whitespace)) { //don't want to insert unnecessary space
+ space = true;
+ this.line_char_count--;
+ continue;
+ }
+
+ if (input_char === "'" || input_char === '"') {
+ if (!content[1] || content[1] !== '!') { //if we're in a comment strings don't get treated specially
+ input_char += this.get_unformatted(input_char);
+ space = true;
+ }
+ }
+
+ if (input_char === '=') { //no space before =
+ space = false;
+ }
+
+ if (content.length && content[content.length-1] !== '=' && input_char !== '>'
+ && space) { //no space after = or before >
+ if (this.line_char_count >= this.max_char) {
+ this.print_newline(false, content);
+ this.line_char_count = 0;
+ }
+ else {
+ content.push(' ');
+ this.line_char_count++;
+ }
+ space = false;
+ }
+ content.push(input_char); //inserts character at-a-time (or string)
+ } while (input_char !== '>');
+
+ var tag_complete = content.join('');
+ var tag_index;
+ if (tag_complete.indexOf(' ') != -1) { //if there's whitespace, thats where the tag name ends
+ tag_index = tag_complete.indexOf(' ');
+ }
+ else { //otherwise go with the tag ending
+ tag_index = tag_complete.indexOf('>');
+ }
+ var tag_check = tag_complete.substring(1, tag_index).toLowerCase();
+ if (tag_complete.charAt(tag_complete.length-2) === '/' ||
+ this.Utils.in_array(tag_check, this.Utils.single_token)) { //if this tag name is a single tag type (either in the list or has a closing /)
+ this.tag_type = 'SINGLE';
+ }
+ else if (tag_check === 'script') { //for later script handling
+ this.record_tag(tag_check);
+ this.tag_type = 'SCRIPT';
+ }
+ else if (tag_check === 'style') { //for future style handling (for now it justs uses get_content)
+ this.record_tag(tag_check);
+ this.tag_type = 'STYLE';
+ }
+ else if (this.Utils.in_array(tag_check, unformatted)) { // do not reformat the "unformatted" tags
+ var comment = this.get_unformatted('</'+tag_check+'>', tag_complete); //...delegate to get_unformatted function
+ content.push(comment);
+ this.tag_type = 'SINGLE';
+ }
+ else if (tag_check.charAt(0) === '!') { //peek for <!-- comment
+ if (tag_check.indexOf('[if') != -1) { //peek for <!--[if conditional comment
+ if (tag_complete.indexOf('!IE') != -1) { //this type needs a closing --> so...
+ var comment = this.get_unformatted('-->', tag_complete); //...delegate to get_unformatted
+ content.push(comment);
+ }
+ this.tag_type = 'START';
+ }
+ else if (tag_check.indexOf('[endif') != -1) {//peek for <!--[endif end conditional comment
+ this.tag_type = 'END';
+ this.unindent();
+ }
+ else if (tag_check.indexOf('[cdata[') != -1) { //if it's a <[cdata[ comment...
+ var comment = this.get_unformatted(']]>', tag_complete); //...delegate to get_unformatted function
+ content.push(comment);
+ this.tag_type = 'SINGLE'; //<![CDATA[ comments are treated like single tags
+ }
+ else {
+ var comment = this.get_unformatted('-->', tag_complete);
+ content.push(comment);
+ this.tag_type = 'SINGLE';
+ }
+ }
+ else {
+ if (tag_check.charAt(0) === '/') { //this tag is a double tag so check for tag-ending
+ this.retrieve_tag(tag_check.substring(1)); //remove it and all ancestors
+ this.tag_type = 'END';
+ }
+ else { //otherwise it's a start-tag
+ this.record_tag(tag_check); //push it on the tag stack
+ this.tag_type = 'START';
+ }
+ if (this.Utils.in_array(tag_check, this.Utils.extra_liners)) { //check if this double needs an extra line
+ this.print_newline(true, this.output);
+ }
+ }
+ return content.join(''); //returns fully formatted tag
+ }
+
+ this.get_unformatted = function (delimiter, orig_tag) { //function to return unformatted content in its entirety
+
+ if (orig_tag && orig_tag.indexOf(delimiter) != -1) {
+ return '';
+ }
+ var input_char = '';
+ var content = '';
+ var space = true;
+ do {
+
+ if (this.pos >= this.input.length) {
+ return content;
+ }
+
+ input_char = this.input.charAt(this.pos);
+ this.pos++
+
+ if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
+ if (!space) {
+ this.line_char_count--;
+ continue;
+ }
+ if (input_char === '\n' || input_char === '\r') {
+ content += '\n';
+ /* Don't change tab indention for unformatted blocks. If using code for html editing, this will greatly affect <pre> tags if they are specified in the 'unformatted array'
+ for (var i=0; i<this.indent_level; i++) {
+ content += this.indent_string;
+ }
+ space = false; //...and make sure other indentation is erased
+ */
+ this.line_char_count = 0;
+ continue;
+ }
+ }
+ content += input_char;
+ this.line_char_count++;
+ space = true;
+
+
+ } while (content.indexOf(delimiter) == -1);
+ return content;
+ }
+
+ this.get_token = function () { //initial handler for token-retrieval
+ var token;
+
+ if (this.last_token === 'TK_TAG_SCRIPT' || this.last_token === 'TK_TAG_STYLE') { //check if we need to format javascript
+ var type = this.last_token.substr(7)
+ token = this.get_contents_to(type);
+ if (typeof token !== 'string') {
+ return token;
+ }
+ return [token, 'TK_' + type];
+ }
+ if (this.current_mode === 'CONTENT') {
+ token = this.get_content();
+ if (typeof token !== 'string') {
+ return token;
+ }
+ else {
+ return [token, 'TK_CONTENT'];
+ }
+ }
+
+ if (this.current_mode === 'TAG') {
+ token = this.get_tag();
+ if (typeof token !== 'string') {
+ return token;
+ }
+ else {
+ var tag_name_type = 'TK_TAG_' + this.tag_type;
+ return [token, tag_name_type];
+ }
+ }
+ }
+
+ this.get_full_indent = function (level) {
+ level = this.indent_level + level || 0;
+ if (level < 1)
+ return '';
+
+ return Array(level + 1).join(this.indent_string);
+ }
+
+
+ this.printer = function (js_source, indent_character, indent_size, max_char, brace_style) { //handles input/output and some other printing functions
+
+ this.input = js_source || ''; //gets the input for the Parser
+ this.output = [];
+ this.indent_character = indent_character;
+ this.indent_string = '';
+ this.indent_size = indent_size;
+ this.brace_style = brace_style;
+ this.indent_level = 0;
+ this.max_char = max_char;
+ this.line_char_count = 0; //count to see if max_char was exceeded
+
+ for (var i=0; i<this.indent_size; i++) {
+ this.indent_string += this.indent_character;
+ }
+
+ this.print_newline = function (ignore, arr) {
+ this.line_char_count = 0;
+ if (!arr || !arr.length) {
+ return;
+ }
+ if (!ignore) { //we might want the extra line
+ while (this.Utils.in_array(arr[arr.length-1], this.Utils.whitespace)) {
+ arr.pop();
+ }
+ }
+ arr.push('\n');
+ for (var i=0; i<this.indent_level; i++) {
+ arr.push(this.indent_string);
+ }
+ }
+
+ this.print_token = function (text) {
+ this.output.push(text);
+ }
+
+ this.indent = function () {
+ this.indent_level++;
+ }
+
+ this.unindent = function () {
+ if (this.indent_level > 0) {
+ this.indent_level--;
+ }
+ }
+ }
+ return this;
+ }
+
+ /*_____________________--------------------_____________________*/
+
+ multi_parser = new Parser(); //wrapping functions Parser
+ multi_parser.printer(html_source, indent_character, indent_size, max_char, brace_style); //initialize starting values
+
+ while (true) {
+ var t = multi_parser.get_token();
+ multi_parser.token_text = t[0];
+ multi_parser.token_type = t[1];
+
+ if (multi_parser.token_type === 'TK_EOF') {
+ break;
+ }
+
+ switch (multi_parser.token_type) {
+ case 'TK_TAG_START':
+ multi_parser.print_newline(false, multi_parser.output);
+ multi_parser.print_token(multi_parser.token_text);
+ multi_parser.indent();
+ multi_parser.current_mode = 'CONTENT';
+ break;
+ case 'TK_TAG_STYLE':
+ case 'TK_TAG_SCRIPT':
+ multi_parser.print_newline(false, multi_parser.output);
+ multi_parser.print_token(multi_parser.token_text);
+ multi_parser.current_mode = 'CONTENT';
+ break;
+ case 'TK_TAG_END':
+ //Print new line only if the tag has no content and has child
+ if (multi_parser.last_token === 'TK_CONTENT' && multi_parser.last_text === '') {
+ var tag_name = multi_parser.token_text.match(/\w+/)[0];
+ var tag_extracted_from_last_output = multi_parser.output[multi_parser.output.length -1].match(/<\s*(\w+)/);
+ if (tag_extracted_from_last_output === null || tag_extracted_from_last_output[1] !== tag_name)
+ multi_parser.print_newline(true, multi_parser.output);
+ }
+ multi_parser.print_token(multi_parser.token_text);
+ multi_parser.current_mode = 'CONTENT';
+ break;
+ case 'TK_TAG_SINGLE':
+ multi_parser.print_newline(false, multi_parser.output);
+ multi_parser.print_token(multi_parser.token_text);
+ multi_parser.current_mode = 'CONTENT';
+ break;
+ case 'TK_CONTENT':
+ if (multi_parser.token_text !== '') {
+ multi_parser.print_token(multi_parser.token_text);
+ }
+ multi_parser.current_mode = 'TAG';
+ break;
+ case 'TK_STYLE':
+ case 'TK_SCRIPT':
+ if (multi_parser.token_text !== '') {
+ multi_parser.output.push('\n');
+ var text = multi_parser.token_text;
+ if (multi_parser.token_type == 'TK_SCRIPT') {
+ var _beautifier = typeof js_beautify == 'function' && js_beautify;
+ } else if (multi_parser.token_type == 'TK_STYLE') {
+ var _beautifier = typeof css_beautify == 'function' && css_beautify;
+ }
+
+ if (options.indent_scripts == "keep") {
+ var script_indent_level = 0;
+ } else if (options.indent_scripts == "separate") {
+ var script_indent_level = -multi_parser.indent_level;
+ } else {
+ var script_indent_level = 1;
+ }
+
+ var indentation = multi_parser.get_full_indent(script_indent_level);
+ if (_beautifier) {
+ // call the Beautifier if avaliable
+ text = _beautifier(text.replace(/^\s*/, indentation), options);
+ } else {
+ // simply indent the string otherwise
+ var white = text.match(/^\s*/)[0];
+ var _level = white.match(/[^\n\r]*$/)[0].split(multi_parser.indent_string).length - 1;
+ var reindent = multi_parser.get_full_indent(script_indent_level -_level);
+ text = text.replace(/^\s*/, indentation)
+ .replace(/\r\n|\r|\n/g, '\n' + reindent)
+ .replace(/\s*$/, '');
+ }
+ if (text) {
+ multi_parser.print_token(text);
+ multi_parser.print_newline(true, multi_parser.output);
+ }
+ }
+ multi_parser.current_mode = 'TAG';
+ break;
+ }
+ multi_parser.last_token = multi_parser.token_type;
+ multi_parser.last_text = multi_parser.token_text;
+ }
+ return multi_parser.output.join('');
+}
+
+if (typeof exports !== "undefined")
+ exports.html_beautify = html_beautify;
+
1,246 src/beautify.js
@@ -0,0 +1,1246 @@
+/*jslint onevar: false, plusplus: false */
+/*
+
+ JS Beautifier
+---------------
+
+
+ Written by Einar Lielmanis, <einar@jsbeautifier.org>
+ http://jsbeautifier.org/
+
+ Originally converted to javascript by Vital, <vital76@gmail.com>
+ "End braces on own line" added by Chris J. Shull, <chrisjshull@gmail.com>
+
+ You are free to use this in any way you want, in case you find this useful or working for you.
+
+ Usage:
+ js_beautify(js_source_text);
+ js_beautify(js_source_text, options);
+
+ The options are:
+ indent_size (default 4) — indentation size,
+ indent_char (default space) — character to indent with,
+ preserve_newlines (default true) — whether existing line breaks should be preserved,
+ preserve_max_newlines (default unlimited) - maximum number of line breaks to be preserved in one chunk,
+
+ jslint_happy (default false) — if true, then jslint-stricter mode is enforced.
+
+ jslint_happy !jslint_happy
+ ---------------------------------
+ function () function()
+
+ brace_style (default "collapse") - "collapse" | "expand" | "end-expand" | "expand-strict"
+ put braces on the same line as control statements (default), or put braces on own line (Allman / ANSI style), or just put end braces on own line.
+
+ expand-strict: put brace on own line even in such cases:
+
+ var a =
+ {
+ a: 5,
+ b: 6
+ }
+ This mode may break your scripts - e.g "return { a: 1 }" will be broken into two lines, so beware.
+
+ space_before_conditional: should the space before conditional statement be added, "if(true)" vs "if (true)"
+
+ e.g
+
+ js_beautify(js_source_text, {
+ 'indent_size': 1,
+ 'indent_char': '\t'
+ });
+
+
+*/
+
+
+
+function js_beautify(js_source_text, options) {
+
+ var input, output, token_text, last_type, last_text, last_last_text, last_word, flags, flag_store, indent_string;
+ var whitespace, wordchar, punct, parser_pos, line_starters, digits;
+ var prefix, token_type, do_block_just_closed;
+ var wanted_newline, just_added_newline, n_newlines;
+ var preindent_string = '';
+
+
+ // Some interpreters have unexpected results with foo = baz || bar;
+ options = options ? options : {};
+
+ var opt_brace_style;
+
+ // compatibility
+ if (options.space_after_anon_function !== undefined && options.jslint_happy === undefined) {
+ options.jslint_happy = options.space_after_anon_function;
+ }
+ if (options.braces_on_own_line !== undefined) { //graceful handling of deprecated option
+ opt_brace_style = options.braces_on_own_line ? "expand" : "collapse";
+ }
+ opt_brace_style = options.brace_style ? options.brace_style : (opt_brace_style ? opt_brace_style : "collapse");
+
+
+ var opt_indent_size = options.indent_size ? options.indent_size : 4;
+ var opt_indent_char = options.indent_char ? options.indent_char : ' ';
+ var opt_preserve_newlines = typeof options.preserve_newlines === 'undefined' ? true : options.preserve_newlines;
+ var opt_max_preserve_newlines = typeof options.max_preserve_newlines === 'undefined' ? false : options.max_preserve_newlines;
+ var opt_jslint_happy = true;
+ var opt_keep_array_indentation = typeof options.keep_array_indentation === 'undefined' ? false : options.keep_array_indentation;
+ var opt_space_before_conditional = typeof options.space_before_conditional === 'undefined' ? true : options.space_before_conditional;
+ var opt_indent_case = typeof options.indent_case === 'undefined' ? false : options.indent_case;
+
+ just_added_newline = false;
+
+ // cache the source's length.
+ var input_length = js_source_text.length;
+
+ function trim_output(eat_newlines) {
+ eat_newlines = typeof eat_newlines === 'undefined' ? false : eat_newlines;
+ while (output.length && (output[output.length - 1] === ' '
+ || output[output.length - 1] === indent_string
+ || output[output.length - 1] === preindent_string
+ || (eat_newlines && (output[output.length - 1] === '\n' || output[output.length - 1] === '\r')))) {
+ output.pop();
+ }
+ }
+
+ function trim(s) {
+ return s.replace(/^\s\s*|\s\s*$/, '');
+ }
+
+ function force_newline()
+ {
+ var old_keep_array_indentation = opt_keep_array_indentation;
+ opt_keep_array_indentation = false;
+ print_newline()
+ opt_keep_array_indentation = old_keep_array_indentation;
+ }
+
+ function print_newline(ignore_repeated) {
+
+ flags.eat_next_space = false;
+ if (opt_keep_array_indentation && is_array(flags.mode)) {
+ return;
+ }
+
+ ignore_repeated = typeof ignore_repeated === 'undefined' ? true : ignore_repeated;
+
+ flags.if_line = false;
+ trim_output();
+
+ if (!output.length) {
+ return; // no newline on start of file
+ }
+
+ if (output[output.length - 1] !== "\n" || !ignore_repeated) {
+ just_added_newline = true;
+ output.push("\n");
+ }
+ if (preindent_string) {
+ output.push(preindent_string);
+ }
+ for (var i = 0; i < flags.indentation_level; i += 1) {
+ output.push(indent_string);
+ }
+ if (flags.var_line && flags.var_line_reindented) {
+ output.push(indent_string); // skip space-stuffing, if indenting with a tab
+ }
+ if (flags.case_body) {
+ output.push(indent_string);
+ }
+ }
+
+
+
+ function print_single_space() {
+
+ if (last_type === 'TK_COMMENT') {
+ // no you will not print just a space after a comment
+ return print_newline(true);
+ }
+
+ if (flags.eat_next_space) {
+ flags.eat_next_space = false;
+ return;
+ }
+ var last_output = ' ';
+ if (output.length) {
+ last_output = output[output.length - 1];
+ }
+ if (last_output !== ' ' && last_output !== '\n' && last_output !== indent_string) { // prevent occassional duplicate space
+ output.push(' ');
+ }
+ }
+
+
+ function print_token() {
+ just_added_newline = false;
+ flags.eat_next_space = false;
+ output.push(token_text);
+ }
+
+ function indent() {
+ flags.indentation_level += 1;
+ }
+
+
+ function remove_indent() {
+ if (output.length && output[output.length - 1] === indent_string) {
+ output.pop();
+ }
+ }
+
+ function set_mode(mode) {
+ if (flags) {
+ flag_store.push(flags);
+ }
+ flags = {
+ previous_mode: flags ? flags.mode : 'BLOCK',
+ mode: mode,
+ var_line: false,
+ var_line_tainted: false,
+ var_line_reindented: false,
+ in_html_comment: false,
+ if_line: false,
+ in_case: false,
+ case_body: false,
+ eat_next_space: false,
+ indentation_baseline: -1,
+ indentation_level: (flags ? flags.indentation_level + (flags.case_body?1:0) + ((flags.var_line && flags.var_line_reindented) ? 1 : 0) : 0),
+ ternary_depth: 0
+ };
+ }
+
+ function is_array(mode) {
+ return mode === '[EXPRESSION]' || mode === '[INDENTED-EXPRESSION]';
+ }
+
+ function is_expression(mode) {
+ return in_array(mode, ['[EXPRESSION]', '(EXPRESSION)', '(FOR-EXPRESSION)', '(COND-EXPRESSION)']);
+ }
+
+ function restore_mode() {
+ do_block_just_closed = flags.mode === 'DO_BLOCK';
+ if (flag_store.length > 0) {
+ var mode = flags.mode;
+ flags = flag_store.pop();
+ flags.previous_mode = mode;
+ }
+ }
+
+ function all_lines_start_with(lines, c) {
+ for (var i = 0; i < lines.length; i++) {
+ if (trim(lines[i])[0] != c) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ function in_array(what, arr) {
+ for (var i = 0; i < arr.length; i += 1) {
+ if (arr[i] === what) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ function look_up(exclude) {
+ var local_pos = parser_pos;
+ var c = input.charAt(local_pos);
+ while (in_array(c, whitespace) && c != exclude) {
+ local_pos++;
+ if (local_pos >= input_length) return 0;
+ c = input.charAt(local_pos);
+ }
+ return c;
+ }
+
+ function get_next_token() {
+ n_newlines = 0;
+
+ if (parser_pos >= input_length) {
+ return ['', 'TK_EOF'];
+ }
+
+ wanted_newline = false;
+
+ var c = input.charAt(parser_pos);
+ parser_pos += 1;
+
+
+ var keep_whitespace = opt_keep_array_indentation && is_array(flags.mode);
+
+ if (keep_whitespace) {
+
+ //
+ // slight mess to allow nice preservation of array indentation and reindent that correctly
+ // first time when we get to the arrays:
+ // var a = [
+ // ....'something'
+ // we make note of whitespace_count = 4 into flags.indentation_baseline
+ // so we know that 4 whitespaces in original source match indent_level of reindented source
+ //
+ // and afterwards, when we get to
+ // 'something,
+ // .......'something else'
+ // we know that this should be indented to indent_level + (7 - indentation_baseline) spaces
+ //
+ var whitespace_count = 0;
+
+ while (in_array(c, whitespace)) {
+
+ if (c === "\n") {
+ trim_output();
+ output.push("\n");
+ just_added_newline = true;
+ whitespace_count = 0;
+ } else {
+ if (c === '\t') {
+ whitespace_count += 4;
+ } else if (c === '\r') {
+ // nothing
+ } else {
+ whitespace_count += 1;
+ }
+ }
+
+ if (parser_pos >= input_length) {
+ return ['', 'TK_EOF'];
+ }
+
+ c = input.charAt(parser_pos);
+ parser_pos += 1;
+
+ }
+ if (flags.indentation_baseline === -1) {
+ flags.indentation_baseline = whitespace_count;
+ }
+
+ if (just_added_newline) {
+ var i;
+ for (i = 0; i < flags.indentation_level + 1; i += 1) {
+ output.push(indent_string);
+ }
+ if (flags.indentation_baseline !== -1) {
+ for (i = 0; i < whitespace_count - flags.indentation_baseline; i++) {
+ output.push(' ');
+ }
+ }
+ }
+
+ } else {
+ while (in_array(c, whitespace)) {
+
+ if (c === "\n") {
+ n_newlines += ( (opt_max_preserve_newlines) ? (n_newlines <= opt_max_preserve_newlines) ? 1: 0: 1 );
+ }
+
+
+ if (parser_pos >= input_length) {
+ return ['', 'TK_EOF'];
+ }
+
+ c = input.charAt(parser_pos);
+ parser_pos += 1;
+
+ }
+
+ if (opt_preserve_newlines) {
+ if (n_newlines > 1) {
+ for (i = 0; i < n_newlines; i += 1) {
+ print_newline(i === 0);
+ just_added_newline = true;
+ }
+ }
+ }
+ wanted_newline = n_newlines > 0;
+ }
+
+
+ if (in_array(c, wordchar)) {
+ if (parser_pos < input_length) {
+ while (in_array(input.charAt(parser_pos), wordchar)) {
+ c += input.charAt(parser_pos);
+ parser_pos += 1;
+ if (parser_pos === input_length) {
+ break;
+ }
+ }
+ }
+
+ // small and surprisingly unugly hack for 1E-10 representation
+ if (parser_pos !== input_length && c.match(/^[0-9]+[Ee]$/) && (input.charAt(parser_pos) === '-' || input.charAt(parser_pos) === '+')) {
+
+ var sign = input.charAt(parser_pos);
+ parser_pos += 1;
+
+ var t = get_next_token(parser_pos);
+ c += sign + t[0];
+ return [c, 'TK_WORD'];
+ }
+
+ if (c === 'in') { // hack for 'in' operator
+ return [c, 'TK_OPERATOR'];
+ }
+ if (wanted_newline && last_type !== 'TK_OPERATOR'
+ && last_type !== 'TK_EQUALS'
+ && !flags.if_line && (opt_preserve_newlines || last_text !== 'var')) {
+ print_newline();
+ }
+ return [c, 'TK_WORD'];
+ }
+
+ if (c === '(' || c === '[') {
+ return [c, 'TK_START_EXPR'];
+ }
+
+ if (c === ')' || c === ']') {
+ return [c, 'TK_END_EXPR'];
+ }
+
+ if (c === '{') {
+ return [c, 'TK_START_BLOCK'];
+ }
+
+ if (c === '}') {
+ return [c, 'TK_END_BLOCK'];
+ }
+
+ if (c === ';') {
+ return [c, 'TK_SEMICOLON'];
+ }
+
+ if (c === '/') {
+ var comment = '';
+ // peek for comment /* ... */
+ var inline_comment = true;
+ if (input.charAt(parser_pos) === '*') {
+ parser_pos += 1;
+ if (parser_pos < input_length) {
+ while (! (input.charAt(parser_pos) === '*' && input.charAt(parser_pos + 1) && input.charAt(parser_pos + 1) === '/') && parser_pos < input_length) {
+ c = input.charAt(parser_pos);
+ comment += c;
+ if (c === '\x0d' || c === '\x0a') {
+ inline_comment = false;
+ }
+ parser_pos += 1;
+ if (parser_pos >= input_length) {
+ break;
+ }
+ }
+ }
+ parser_pos += 2;
+ if (inline_comment && n_newlines == 0) {
+ return ['/*' + comment + '*/', 'TK_INLINE_COMMENT'];
+ } else {
+ return ['/*' + comment + '*/', 'TK_BLOCK_COMMENT'];
+ }
+ }
+ // peek for comment // ...
+ if (input.charAt(parser_pos) === '/') {
+ comment = c;
+ while (input.charAt(parser_pos) !== '\r' && input.charAt(parser_pos) !== '\n') {
+ comment += input.charAt(parser_pos);
+ parser_pos += 1;
+ if (parser_pos >= input_length) {
+ break;
+ }
+ }
+ parser_pos += 1;
+ if (wanted_newline) {
+ print_newline();
+ }
+ return [comment, 'TK_COMMENT'];
+ }
+
+ }
+
+ if (c === "'" || // string
+ c === '"' || // string
+ (c === '/' &&
+ ((last_type === 'TK_WORD' && in_array(last_text, ['return', 'do', 'else'])) ||
+ (last_text === ')' && in_array(flags.previous_mode, ['(COND-EXPRESSION)', '(FOR-EXPRESSION)'])) ||
+ (last_type === 'TK_COMMENT' || last_type === 'TK_START_EXPR' || last_type === 'TK_START_BLOCK' || last_type === 'TK_END_BLOCK' || last_type === 'TK_OPERATOR' || last_type === 'TK_EQUALS' || last_type === 'TK_EOF' || last_type === 'TK_SEMICOLON')))) { // regexp
+ var sep = c;
+ var esc = false;
+ var resulting_string = c;
+
+ if (parser_pos < input_length) {
+ if (sep === '/') {
+ //
+ // handle regexp separately...
+ //
+ var in_char_class = false;
+ while (esc || in_char_class || input.charAt(parser_pos) !== sep) {
+ resulting_string += input.charAt(parser_pos);
+ if (!esc) {
+ esc = input.charAt(parser_pos) === '\\';
+ if (input.charAt(parser_pos) === '[') {
+ in_char_class = true;
+ } else if (input.charAt(parser_pos) === ']') {
+ in_char_class = false;
+ }
+ } else {
+ esc = false;
+ }
+ parser_pos += 1;
+ if (parser_pos >= input_length) {
+ // incomplete string/rexp when end-of-file reached.
+ // bail out with what had been received so far.
+ return [resulting_string, 'TK_STRING'];
+ }
+ }
+
+ } else {
+ //
+ // and handle string also separately
+ //
+ while (esc || input.charAt(parser_pos) !== sep) {
+ resulting_string += input.charAt(parser_pos);
+ if (!esc) {
+ esc = input.charAt(parser_pos) === '\\';
+ } else {
+ esc = false;
+ }
+ parser_pos += 1;
+ if (parser_pos >= input_length) {
+ // incomplete string/rexp when end-of-file reached.
+ // bail out with what had been received so far.
+ return [resulting_string, 'TK_STRING'];
+ }
+ }
+ }
+
+
+
+ }
+
+ parser_pos += 1;
+
+ resulting_string += sep;
+
+ if (sep === '/') {
+ // regexps may have modifiers /regexp/MOD , so fetch those, too
+ while (parser_pos < input_length && in_array(input.charAt(parser_pos), wordchar)) {
+ resulting_string += input.charAt(parser_pos);
+ parser_pos += 1;
+ }
+ }
+ return [resulting_string, 'TK_STRING'];
+ }
+
+ if (c === '#') {
+
+
+ if (output.length === 0 && input.charAt(parser_pos) === '!') {
+ // shebang
+ resulting_string = c;
+ while (parser_pos < input_length && c != '\n') {
+ c = input.charAt(parser_pos);
+ resulting_string += c;
+ parser_pos += 1;
+ }
+ output.push(trim(resulting_string) + '\n');
+ print_newline();
+ return get_next_token();
+ }
+
+
+
+ // Spidermonkey-specific sharp variables for circular references
+ // https://developer.mozilla.org/En/Sharp_variables_in_JavaScript
+ // http://mxr.mozilla.org/mozilla-central/source/js/src/jsscan.cpp around line 1935
+ var sharp = '#';
+ if (parser_pos < input_length && in_array(input.charAt(parser_pos), digits)) {
+ do {
+ c = input.charAt(parser_pos);
+ sharp += c;
+ parser_pos += 1;
+ } while (parser_pos < input_length && c !== '#' && c !== '=');
+ if (c === '#') {
+ //
+ } else if (input.charAt(parser_pos) === '[' && input.charAt(parser_pos + 1) === ']') {
+ sharp += '[]';
+ parser_pos += 2;
+ } else if (input.charAt(parser_pos) === '{' && input.charAt(parser_pos + 1) === '}') {
+ sharp += '{}';
+ parser_pos += 2;
+ }
+ return [sharp, 'TK_WORD'];
+ }
+ }
+
+ if (c === '<' && input.substring(parser_pos - 1, parser_pos + 3) === '<!--') {
+ parser_pos += 3;
+ c = '<!--';
+ while (input[parser_pos] != '\n' && parser_pos < input_length) {
+ c += input[parser_pos];
+ parser_pos++;
+ }
+ flags.in_html_comment = true;
+ return [c, 'TK_COMMENT'];
+ }
+
+ if (c === '-' && flags.in_html_comment && input.substring(parser_pos - 1, parser_pos + 2) === '-->') {
+ flags.in_html_comment = false;
+ parser_pos += 2;
+ if (wanted_newline) {
+ print_newline();
+ }
+ return ['-->', 'TK_COMMENT'];
+ }
+
+ if (in_array(c, punct)) {
+ while (parser_pos < input_length && in_array(c + input.charAt(parser_pos), punct)) {
+ c += input.charAt(parser_pos);
+ parser_pos += 1;
+ if (parser_pos >= input_length) {
+ break;
+ }
+ }
+
+ if (c === '=') {
+ return [c, 'TK_EQUALS'];
+ } else {
+ return [c, 'TK_OPERATOR'];
+ }
+ }
+
+ return [c, 'TK_UNKNOWN'];
+ }
+
+ //----------------------------------
+ indent_string = '';
+ while (opt_indent_size > 0) {
+ indent_string += opt_indent_char;
+ opt_indent_size -= 1;
+ }
+
+ while (js_source_text && (js_source_text[0] === ' ' || js_source_text[0] === '\t')) {
+ preindent_string += js_source_text[0];
+ js_source_text = js_source_text.substring(1);
+ }
+ input = js_source_text;
+
+ last_word = ''; // last 'TK_WORD' passed
+ last_type = 'TK_START_EXPR'; // last token type
+ last_text = ''; // last token text
+ last_last_text = ''; // pre-last token text
+ output = [];
+
+ do_block_just_closed = false;
+
+ whitespace = "\n\r\t ".split('');
+ wordchar = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$'.split('');
+ digits = '0123456789'.split('');
+
+ punct = '+ - * / % & ++ -- = += -= *= /= %= == === != !== > < >= <= >> << >>> >>>= >>= <<= && &= | || ! !! , : ? ^ ^= |= ::';
+ punct += ' <%= <% %> <?= <? ?>'; // try to be a good boy and try not to break the markup language identifiers
+ punct = punct.split(' ');
+
+ // words which should always start on new line.
+ line_starters = 'continue,try,throw,return,var,if,switch,case,default,for,while,break,function'.split(',');
+
+ // states showing if we are currently in expression (i.e. "if" case) - 'EXPRESSION', or in usual block (like, procedure), 'BLOCK'.
+ // some formatting depends on that.
+ flag_store = [];
+ set_mode('BLOCK');
+
+ parser_pos = 0;
+ while (true) {
+ var t = get_next_token(parser_pos);
+ token_text = t[0];
+ token_type = t[1];
+ if (token_type === 'TK_EOF') {
+ break;
+ }
+
+ switch (token_type) {
+
+ case 'TK_START_EXPR':
+
+ if (token_text === '[') {
+
+ if (last_type === 'TK_WORD' || last_text === ')') {
+ // this is array index specifier, break immediately
+ // a[x], fn()[x]
+ if (in_array(last_text, line_starters)) {
+ print_single_space();
+ }
+ set_mode('(EXPRESSION)');
+ print_token();
+ break;
+ }
+
+ if (flags.mode === '[EXPRESSION]' || flags.mode === '[INDENTED-EXPRESSION]') {
+ if (last_last_text === ']' && last_text === ',') {
+ // ], [ goes to new line
+ if (flags.mode === '[EXPRESSION]') {
+ flags.mode = '[INDENTED-EXPRESSION]';
+ if (!opt_keep_array_indentation) {
+ indent();
+ }
+ }
+ set_mode('[EXPRESSION]');
+ if (!opt_keep_array_indentation) {
+ print_newline();
+ }
+ } else if (last_text === '[') {
+ if (flags.mode === '[EXPRESSION]') {
+ flags.mode = '[INDENTED-EXPRESSION]';
+ if (!opt_keep_array_indentation) {
+ indent();
+ }
+ }
+ set_mode('[EXPRESSION]');
+
+ if (!opt_keep_array_indentation) {
+ print_newline();
+ }
+ } else {
+ set_mode('[EXPRESSION]');
+ }
+ } else {
+ set_mode('[EXPRESSION]');
+ }
+
+
+
+ } else {
+ if (last_word === 'for') {
+ set_mode('(FOR-EXPRESSION)');
+ } else if (in_array(last_word, ['if', 'while'])) {
+ set_mode('(COND-EXPRESSION)');
+ } else {
+ set_mode('(EXPRESSION)');
+ }
+ }
+
+ if (last_text === ';' || last_type === 'TK_START_BLOCK') {
+ print_newline();
+ } else if (last_type === 'TK_END_EXPR' || last_type === 'TK_START_EXPR' || last_type === 'TK_END_BLOCK' || last_text === '.') {
+ if (wanted_newline) {
+ print_newline();
+ }
+ // do nothing on (( and )( and ][ and ]( and .(
+ } else if (last_type !== 'TK_WORD' && last_type !== 'TK_OPERATOR') {
+ print_single_space();
+ } else if (last_word === 'function' || last_word === 'typeof') {
+ // function() vs function ()
+ if (opt_jslint_happy) {
+ print_single_space();
+ }
+ } else if (in_array(last_text, line_starters) || last_text === 'catch') {
+ if (opt_space_before_conditional) {
+ print_single_space();
+ }
+ }
+ print_token();
+
+ break;
+
+ case 'TK_END_EXPR':
+ if (token_text === ']') {
+ if (opt_keep_array_indentation) {
+ if (last_text === '}') {
+ // trim_output();
+ // print_newline(true);
+ remove_indent();
+ print_token();
+ restore_mode();
+ break;
+ }
+ } else {
+ if (flags.mode === '[INDENTED-EXPRESSION]') {
+ if (last_text === ']') {
+ restore_mode();
+ print_newline();
+ print_token();
+ break;
+ }
+ }
+ }
+ }
+ restore_mode();
+ print_token();
+ break;
+
+ case 'TK_START_BLOCK':
+
+ if (last_word === 'do') {
+ set_mode('DO_BLOCK');
+ } else {
+ set_mode('BLOCK');
+ }
+ if (opt_brace_style=="expand" || opt_brace_style=="expand-strict") {
+ var empty_braces = false;
+ if (opt_brace_style == "expand-strict")
+ {
+ empty_braces = (look_up() == '}');
+ if (!empty_braces) {
+ print_newline(true);
+ }
+ } else {
+ if (last_type !== 'TK_OPERATOR') {
+ if (last_text === 'return' || last_text === '=' || last_text === 'throw') {
+ print_single_space();
+ } else {
+ print_newline(true);
+ }
+ }
+ }
+ print_token();
+ if (!empty_braces) indent();
+ } else {
+ if (last_type !== 'TK_OPERATOR' && last_type !== 'TK_START_EXPR') {
+ if (last_type === 'TK_START_BLOCK') {
+ print_newline();
+ } else {
+ print_single_space();
+ }
+ } else {
+ // if TK_OPERATOR or TK_START_EXPR
+ if (is_array(flags.previous_mode) && last_text === ',') {
+ if (last_last_text === '}') {
+ // }, { in array context
+ print_single_space();
+ } else {
+ print_newline(); // [a, b, c, {
+ }
+ }
+ }
+ indent();
+ print_token();
+ }
+
+ break;
+
+ case 'TK_END_BLOCK':
+ restore_mode();
+ if (opt_brace_style=="expand" || opt_brace_style == "expand-strict") {
+ if (last_text !== '{') {
+ print_newline();
+ }
+ print_token();
+ } else {
+ if (last_type === 'TK_START_BLOCK') {
+ // nothing
+ if (just_added_newline) {
+ remove_indent();
+ } else {
+ // {}
+ trim_output();
+ }
+ } else {
+ if (is_array(flags.mode) && opt_keep_array_indentation) {
+ // we REALLY need a newline here, but newliner would skip that
+ opt_keep_array_indentation = false;
+ print_newline();
+ opt_keep_array_indentation = true;
+
+ } else {
+ print_newline();
+ }
+ }
+ print_token();
+ }
+ break;
+
+ case 'TK_WORD':
+
+ // no, it's not you. even I have problems understanding how this works
+ // and what does what.
+ if (do_block_just_closed) {
+ // do {} ## while ()
+ print_single_space();
+ print_token();
+ print_single_space();
+ do_block_just_closed = false;
+ break;
+ }
+
+ if (token_text === 'function') {
+ if (flags.var_line) {
+ flags.var_line_reindented = true;
+ }
+ if ((just_added_newline || last_text === ';') && last_text !== '{'
+ && last_type != 'TK_BLOCK_COMMENT' && last_type != 'TK_COMMENT') {
+ // make sure there is a nice clean space of at least one blank line
+ // before a new function definition
+ n_newlines = just_added_newline ? n_newlines : 0;
+ if ( ! opt_preserve_newlines) {
+ n_newlines = 1;
+ }
+
+ for (var i = 0; i < 2 - n_newlines; i++) {
+ print_newline(false);
+ }
+ }
+ }
+
+ if (token_text === 'case' || token_text === 'default') {
+ if (last_text === ':' || flags.case_body) {
+ // switch cases following one another
+ remove_indent();
+ } else {
+ // case statement starts in the same line where switch
+ if (!opt_indent_case)
+ flags.indentation_level--;
+ print_newline();
+ if (!opt_indent_case)
+ flags.indentation_level++;
+ }
+ print_token();
+ flags.in_case = true;
+ flags.case_body = false;
+ break;
+ }
+
+ prefix = 'NONE';
+
+ if (last_type === 'TK_END_BLOCK') {
+
+ if (!in_array(token_text.toLowerCase(), ['else', 'catch', 'finally'])) {
+ prefix = 'NEWLINE';
+ } else {
+ if (opt_brace_style=="expand" || opt_brace_style=="end-expand" || opt_brace_style == "expand-strict") {
+ prefix = 'NEWLINE';
+ } else {
+ prefix = 'SPACE';
+ print_single_space();
+ }
+ }
+ } else if (last_type === 'TK_SEMICOLON' && (flags.mode === 'BLOCK' || flags.mode === 'DO_BLOCK')) {
+ prefix = 'NEWLINE';
+ } else if (last_type === 'TK_SEMICOLON' && is_expression(flags.mode)) {
+ prefix = 'SPACE';
+ } else if (last_type === 'TK_STRING') {
+ prefix = 'NEWLINE';
+ } else if (last_type === 'TK_WORD') {
+ if (last_text === 'else') {
+ // eat newlines between ...else *** some_op...
+ // won't preserve extra newlines in this place (if any), but don't care that much
+ trim_output(true);
+ }
+ prefix = 'SPACE';
+ } else if (last_type === 'TK_START_BLOCK') {
+ prefix = 'NEWLINE';
+ } else if (last_type === 'TK_END_EXPR') {
+ print_single_space();
+ prefix = 'NEWLINE';
+ }
+
+ if (in_array(token_text, line_starters) && last_text !== ')') {
+ if (last_text == 'else') {
+ prefix = 'SPACE';
+ } else {
+ prefix = 'NEWLINE';
+ }
+
+ if (token_text === 'function' && (last_text === 'get' || last_text === 'set')) {
+ prefix = 'SPACE';
+ }
+ }
+
+ if (flags.if_line && last_type === 'TK_END_EXPR') {
+ flags.if_line = false;
+ }
+ if (in_array(token_text.toLowerCase(), ['else', 'catch', 'finally'])) {
+ if (last_type !== 'TK_END_BLOCK' || opt_brace_style=="expand" || opt_brace_style=="end-expand" || opt_brace_style == "expand-strict") {
+ print_newline();
+ } else {
+ trim_output(true);
+ print_single_space();
+ }
+ } else if (prefix === 'NEWLINE') {
+ if ((last_type === 'TK_START_EXPR' || last_text === '=' || last_text === ',') && token_text === 'function') {
+ // no need to force newline on 'function': (function
+ // DONOTHING
+ } else if (token_text === 'function' && last_text == 'new') {
+ print_single_space();
+ } else if (last_text === 'return' || last_text === 'throw') {
+ // no newline between 'return nnn'
+ print_single_space();
+ } else if (last_type !== 'TK_END_EXPR') {
+ if ((last_type !== 'TK_START_EXPR' || token_text !== 'var') && last_text !== ':') {
+ // no need to force newline on 'var': for (var x = 0...)
+ if (token_text === 'if' && last_word === 'else' && last_text !== '{') {
+ // no newline for } else if {
+ print_single_space();
+ } else {
+ flags.var_line = false;
+ flags.var_line_reindented = false;
+ print_newline();
+ }
+ }
+ } else if (in_array(token_text, line_starters) && last_text != ')') {
+ flags.var_line = false;
+ flags.var_line_reindented = false;
+ print_newline();
+ }
+ } else if (is_array(flags.mode) && last_text === ',' && last_last_text === '}') {
+ print_newline(); // }, in lists get a newline treatment
+ } else if (prefix === 'SPACE') {
+ print_single_space();
+ }
+ print_token();
+ last_word = token_text;
+
+ if (token_text === 'var') {
+ flags.var_line = true;
+ flags.var_line_reindented = false;
+ flags.var_line_tainted = false;
+ }
+
+ if (token_text === 'if') {
+ flags.if_line = true;
+ }
+ if (token_text === 'else') {
+ flags.if_line = false;
+ }
+
+ break;
+
+ case 'TK_SEMICOLON':
+
+ print_token();
+ flags.var_line = false;
+ flags.var_line_reindented = false;
+ if (flags.mode == 'OBJECT') {
+ // OBJECT mode is weird and doesn't get reset too well.
+ flags.mode = 'BLOCK';
+ }
+ break;
+
+ case 'TK_STRING':
+
+ if (last_type === 'TK_END_EXPR' && in_array(flags.previous_mode, ['(COND-EXPRESSION)', '(FOR-EXPRESSION)'])) {
+ print_single_space();
+ } else if (last_type == 'TK_STRING' || last_type === 'TK_START_BLOCK' || last_type === 'TK_END_BLOCK' || last_type === 'TK_SEMICOLON') {
+ print_newline();
+ } else if (last_type === 'TK_WORD') {
+ print_single_space();
+ }
+ print_token();
+ break;
+
+ case 'TK_EQUALS':
+ if (flags.var_line) {
+ // just got an '=' in a var-line, different formatting/line-breaking, etc will now be done
+ flags.var_line_tainted = true;
+ }
+ print_single_space();
+ print_token();
+ print_single_space();
+ break;
+
+ case 'TK_OPERATOR':
+
+ var space_before = true;
+ var space_after = true;
+
+ if (flags.var_line && token_text === ',' && (is_expression(flags.mode))) {
+ // do not break on comma, for(var a = 1, b = 2)
+ flags.var_line_tainted = false;
+ }
+
+ if (flags.var_line) {
+ if (token_text === ',') {
+ if (flags.var_line_tainted) {
+ print_token();
+ flags.var_line_reindented = true;
+ flags.var_line_tainted = false;
+ print_newline();
+ break;
+ } else {
+ flags.var_line_tainted = false;
+ }
+ // } else if (token_text === ':') {
+ // hmm, when does this happen? tests don't catch this
+ // flags.var_line = false;
+ }
+ }
+
+ if (last_text === 'return' || last_text === 'throw') {
+ // "return" had a special handling in TK_WORD. Now we need to return the favor
+ print_single_space();
+ print_token();
+ break;
+ }
+
+ if (token_text === ':' && flags.in_case) {
+ if (opt_indent_case)
+ flags.case_body = true;
+ print_token(); // colon really asks for separate treatment
+ print_newline();
+ flags.in_case = false;
+ break;
+ }
+
+ if (token_text === '::') {
+ // no spaces around exotic namespacing syntax operator
+ print_token();
+ break;
+ }
+
+ if (token_text === ',') {
+ if (flags.var_line) {
+ if (flags.var_line_tainted) {
+ print_token();
+ print_newline();
+ flags.var_line_tainted = false;
+ } else {
+ print_token();
+ print_single_space();
+ }
+ } else if (last_type === 'TK_END_BLOCK' && flags.mode !== "(EXPRESSION)") {
+ print_token();
+ if (flags.mode === 'OBJECT' && last_text === '}') {
+ print_newline();
+ } else {
+ print_single_space();
+ }
+ } else {
+ if (flags.mode === 'OBJECT') {
+ print_token();
+ print_newline();
+ } else {
+ // EXPR or DO_BLOCK
+ print_token();
+ print_single_space();
+ }
+ }
+ break;
+ // } else if (in_array(token_text, ['--', '++', '!']) || (in_array(token_text, ['-', '+']) && (in_array(last_type, ['TK_START_BLOCK', 'TK_START_EXPR', 'TK_EQUALS']) || in_array(last_text, line_starters) || in_array(last_text, ['==', '!=', '+=', '-=', '*=', '/=', '+', '-'])))) {
+ } else if (in_array(token_text, ['--', '++', '!']) || (in_array(token_text, ['-', '+']) && (in_array(last_type, ['TK_START_BLOCK', 'TK_START_EXPR', 'TK_EQUALS', 'TK_OPERATOR']) || in_array(last_text, line_starters)))) {
+ // unary operators (and binary +/- pretending to be unary) special cases
+
+ space_before = false;
+ space_after = false;
+
+ if (last_text === ';' && is_expression(flags.mode)) {
+ // for (;; ++i)
+ // ^^^
+ space_before = true;
+ }
+ if (last_type === 'TK_WORD' && in_array(last_text, line_starters)) {
+ space_before = true;
+ }
+
+ if (flags.mode === 'BLOCK' && (last_text === '{' || last_text === ';')) {
+ // { foo; --i }
+ // foo(); --bar;
+ print_newline();
+ }
+ } else if (token_text === '.') {
+ // decimal digits or object.property
+ space_before = false;
+
+ } else if (token_text === ':') {
+ if (flags.ternary_depth == 0) {
+ flags.mode = 'OBJECT';
+ space_before = false;
+ } else {
+ flags.ternary_depth -= 1;
+ }
+ } else if (token_text === '?') {
+ flags.ternary_depth += 1;
+ }
+ if (space_before) {
+ print_single_space();
+ }
+
+ print_token();
+
+ if (space_after) {
+ print_single_space();
+ }
+
+ break;
+
+ case 'TK_BLOCK_COMMENT':
+
+ var lines = token_text.split(/\x0a|\x0d\x0a/);
+
+ if (all_lines_start_with(lines.slice(1), '*')) {
+ // javadoc: reformat and reindent
+ print_newline();
+ output.push(lines[0]);
+ for (i = 1; i < lines.length; i++) {
+ print_newline();
+ output.push(' ');
+ output.push(trim(lines[i]));
+ }
+
+ } else {
+
+ // simple block comment: leave intact
+ if (lines.length > 1) {
+ // multiline comment block starts with a new line
+ print_newline();
+ } else {
+ // single-line /* comment */ stays where it is
+ if (last_type === 'TK_END_BLOCK') {
+ print_newline();
+ } else {
+ print_single_space();
+ }
+
+ }
+
+ for (i = 0; i < lines.length; i++) {
+ output.push(lines[i]);
+ output.push('\n');
+ }
+
+ }
+ if(look_up('\n') != '\n')
+ print_newline();
+ break;
+
+ case 'TK_INLINE_COMMENT':
+ print_single_space();
+ print_token();
+ if (is_expression(flags.mode)) {
+ print_single_space();
+ } else {
+ force_newline();
+ }
+ break;
+
+ case 'TK_COMMENT':
+
+ // print_newline();
+ if (wanted_newline) {
+ print_newline();
+ } else {
+ print_single_space();
+ }
+ print_token();
+ if(look_up('\n') != '\n')
+ force_newline();
+ break;
+
+ case 'TK_UNKNOWN':
+ if (last_text === 'return' || last_text === 'throw') {
+ print_single_space();
+ }
+ print_token();
+ break;
+ }
+
+ last_last_text = last_text;
+ last_type = token_type;
+ last_text = token_text;
+ }
+
+ var sweet_code = preindent_string + output.join('').replace(/[\n ]+$/, '');
+ return sweet_code;
+
+}
+
+// Add support for CommonJS. Just put this file somewhere on your require.paths
+// and you will be able to `var js_beautify = require("beautify").js_beautify`.
+if (typeof exports !== "undefined")
+ exports.js_beautify = js_beautify;
51 src/run-jsbeautifier.js
@@ -0,0 +1,51 @@
+var beautify = require("../lib/beautify");
+var nopt = require("nopt");
+var fs = require("fs");
+
+var parsed = nopt();
+
+function die(why) {
+ 'use strict';
+ console.warn(why);
+ console.warn("Usage: " + process.argv[1] + " <scriptfile>{js,css,html}...");
+ process.exit(1);
+}
+
+function lintFile(file) {
+ 'use strict';
+ var ft = file.split('.'), lint;
+
+ fs.readFile(file, function (err, data) {
+ if (err) {
+ throw err;
+ }
+
+ // Fix UTF8 with BOM
+ if (0xEF === data[0] && 0xBB === data[1] && 0xBF === data[2]) {
+ data = data.slice(3);
+ }
+
+ data = data.toString("utf8");
+
+ switch (ft[ft.length -1]) {
+ case "js":
+ lint = beautify.js_beautify;
+ break;
+ case "css":
+ lint = beautify.css_beautify;
+ break;
+ case "html":