js-beautify 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (74) hide show
  1. data/.document +5 -0
  2. data/.gitmodules +4 -0
  3. data/Gemfile +13 -0
  4. data/Gemfile.lock +27 -0
  5. data/LICENSE.txt +20 -0
  6. data/README.rdoc +13 -0
  7. data/Rakefile +29 -0
  8. data/VERSION +1 -0
  9. data/bin/js-beautify +5 -0
  10. data/init.sh +3 -0
  11. data/js-beautify-copy/.gitmodules +3 -0
  12. data/js-beautify-copy/Makefile +71 -0
  13. data/js-beautify-copy/README.md +39 -0
  14. data/js-beautify-copy/attic/beautify-cl/beautify-cl.js +142 -0
  15. data/js-beautify-copy/attic/bin/beautify_js +80 -0
  16. data/js-beautify-copy/attic/opera-userscript/beautifier.js +1087 -0
  17. data/js-beautify-copy/attic/opera-userscript/make_opera_userscript.sh +42 -0
  18. data/js-beautify-copy/attic/qtscript/jsbeautify.cpp +121 -0
  19. data/js-beautify-copy/attic/qtscript/jsbeautify.pro +5 -0
  20. data/js-beautify-copy/attic/qtscript/jsbeautify.qrc +6 -0
  21. data/js-beautify-copy/attic/qtscript/readme.txt +28 -0
  22. data/js-beautify-copy/attic/readme.txt +2 -0
  23. data/js-beautify-copy/attic/unmaintained/bbedit/jsBeautify_BBED.scpt +522 -0
  24. data/js-beautify-copy/attic/unmaintained/c-sharp/JSBeautify.cs +801 -0
  25. data/js-beautify-copy/attic/v8/README.txt +40 -0
  26. data/js-beautify-copy/attic/v8/beautify.h +2390 -0
  27. data/js-beautify-copy/attic/v8/jsbeautify.cpp +215 -0
  28. data/js-beautify-copy/beautify-css.js +198 -0
  29. data/js-beautify-copy/beautify-html.js +514 -0
  30. data/js-beautify-copy/beautify.js +1293 -0
  31. data/js-beautify-copy/favicon.png +0 -0
  32. data/js-beautify-copy/index.html +401 -0
  33. data/js-beautify-copy/jquery/jquery.cookie.js +96 -0
  34. data/js-beautify-copy/jquery/jquery.js +167 -0
  35. data/js-beautify-copy/license.txt +24 -0
  36. data/js-beautify-copy/php/jsbeautifier.php +1599 -0
  37. data/js-beautify-copy/php/test.php +476 -0
  38. data/js-beautify-copy/python/MANIFEST.in +2 -0
  39. data/js-beautify-copy/python/js-beautify +7 -0
  40. data/js-beautify-copy/python/js-beautify-profile +16 -0
  41. data/js-beautify-copy/python/js-beautify-test +10 -0
  42. data/js-beautify-copy/python/jsbeautifier/__init__.py +1166 -0
  43. data/js-beautify-copy/python/jsbeautifier/tests/__init__.py +1 -0
  44. data/js-beautify-copy/python/jsbeautifier/tests/testindentation.py +43 -0
  45. data/js-beautify-copy/python/jsbeautifier/tests/testjsbeautifier.py +464 -0
  46. data/js-beautify-copy/python/jsbeautifier/unpackers/README.specs.mkd +25 -0
  47. data/js-beautify-copy/python/jsbeautifier/unpackers/__init__.py +67 -0
  48. data/js-beautify-copy/python/jsbeautifier/unpackers/evalbased.py +39 -0
  49. data/js-beautify-copy/python/jsbeautifier/unpackers/javascriptobfuscator.py +58 -0
  50. data/js-beautify-copy/python/jsbeautifier/unpackers/myobfuscate.py +86 -0
  51. data/js-beautify-copy/python/jsbeautifier/unpackers/packer.py +104 -0
  52. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/__init__.py +2 -0
  53. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/test-myobfuscate-input.js +1 -0
  54. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/test-myobfuscate-output.js +65 -0
  55. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/test-packer-62-input.js +1 -0
  56. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/test-packer-non62-input.js +1 -0
  57. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/testjavascriptobfuscator.py +46 -0
  58. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/testmyobfuscate.py +40 -0
  59. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/testpacker.py +34 -0
  60. data/js-beautify-copy/python/jsbeautifier/unpackers/tests/testurlencode.py +36 -0
  61. data/js-beautify-copy/python/jsbeautifier/unpackers/urlencode.py +34 -0
  62. data/js-beautify-copy/python/setup.py +17 -0
  63. data/js-beautify-copy/tests/beautify-tests.js +489 -0
  64. data/js-beautify-copy/tests/run-tests +17 -0
  65. data/js-beautify-copy/tests/sanitytest.js +128 -0
  66. data/js-beautify-copy/unpackers/javascriptobfuscator_unpacker.js +103 -0
  67. data/js-beautify-copy/unpackers/myobfuscate_unpacker.js +81 -0
  68. data/js-beautify-copy/unpackers/p_a_c_k_e_r_unpacker.js +61 -0
  69. data/js-beautify-copy/unpackers/urlencode_unpacker.js +51 -0
  70. data/lib/js-beautify.rb +0 -0
  71. data/test/helper.rb +18 -0
  72. data/test/test_js-beautify.rb +7 -0
  73. data/update.sh +23 -0
  74. metadata +173 -0
@@ -0,0 +1,215 @@
1
+ /*
2
+ Copyright (c) 2010 Ariya Hidayat <ariya.hidayat@gmail.com>
3
+ Copyright (c) 2009 Einar Lielmanis
4
+ Copyright (c) 2010 Nicolas Ferrero <ferrero.nicolas@gmail.com>
5
+
6
+ Permission is hereby granted, free of charge, to any person
7
+ obtaining a copy of this software and associated documentation
8
+ files (the "Software"), to deal in the Software without
9
+ restriction, including without limitation the rights to use,
10
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ copies of the Software, and to permit persons to whom the
12
+ Software is furnished to do so, subject to the following
13
+ conditions:
14
+
15
+ The above copyright notice and this permission notice shall be
16
+ included in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <v8.h>
29
+ #include <string.h>
30
+ #include <stdlib.h>
31
+ #include "beautify.h"
32
+
33
+ #define BUF_SIZE 1024
34
+
35
+ using namespace v8;
36
+
37
+ Handle<String> readFile(const char* name)
38
+ {
39
+ FILE *file = stdin;
40
+ int len = 0;
41
+ char *buf;
42
+ Handle<String> result;
43
+
44
+ if (name)
45
+ {
46
+ file = fopen(name, "rb");
47
+
48
+ if (file == NULL)
49
+ {
50
+ return Handle<String>();
51
+ }
52
+
53
+ fseek(file, 0, SEEK_END);
54
+ len = ftell(file);
55
+ rewind(file);
56
+ buf = new char[len + 1];
57
+ buf[len] = '\0';
58
+ fread(buf, 1, len, file);
59
+ fclose(file);
60
+ result = String::New(buf);
61
+ delete[] buf;
62
+ }
63
+ else
64
+ {
65
+ char c;
66
+ buf = (char*)malloc(BUF_SIZE + 1);
67
+ int buf_size = BUF_SIZE + 1;
68
+
69
+ while ((c = getchar()) != EOF)
70
+ {
71
+ buf[len++] = c;
72
+
73
+ if (len == buf_size)
74
+ {
75
+ buf_size <<= 1;
76
+ buf = (char*)realloc(buf, buf_size);
77
+ }
78
+ }
79
+
80
+ buf[len] = '\0';
81
+ result = String::New(buf);
82
+ free(buf);
83
+ }
84
+
85
+ return result;
86
+ }
87
+
88
+ void writeFile(Handle<Value> result, const char* name)
89
+ {
90
+ if (result.IsEmpty() || result->IsUndefined())
91
+ {
92
+ return;
93
+ }
94
+
95
+ FILE* file = stdout;
96
+
97
+ if (name)
98
+ {
99
+ file = fopen(name, "wt");
100
+
101
+ if (file == NULL)
102
+ {
103
+ return;
104
+ }
105
+ }
106
+
107
+ String::Utf8Value str(result);
108
+ fprintf(file, "%s\n", *str);
109
+
110
+ if (name)
111
+ {
112
+ fclose(file);
113
+ }
114
+ }
115
+
116
+ static void usage(char* progname)
117
+ {
118
+ printf("Usage: %s [options] source-file\n", progname);
119
+ printf("[options]\n");
120
+ printf(" --overwrite : Overwrite source-file (use with care!)\n");
121
+ printf(" --indent-size or -s: Indentation size. (default 4)\n");
122
+ printf(" --indent-char or -c: Character to indent with. (default space)\n");
123
+ printf(" --disable-preserve-newlines or -d: Do not preserve existing line breaks.\n");
124
+ printf(" --indent-level or -l: Initial indentation level, you probably won't need this ever. (default 0)\n");
125
+ printf(" --space-after-anon-function or -f: Space is added between \"function ()\", otherwise the common \"function()\" output is used.\n");
126
+ printf(" --braces-on-own-line or -b: ANSI / Allman brace style, each opening/closing brace gets its own line.\n");
127
+ printf(" --keep-array-indentation or -k: Keep array indentation.\n");
128
+ printf(" --help or -h: Prints this help statement.\n");
129
+ }
130
+
131
+ int main(int argc, char* argv[])
132
+ {
133
+ Handle<String> source;
134
+ HandleScope handle_scope;
135
+ Handle<ObjectTemplate> global = ObjectTemplate::New();
136
+ Handle<ObjectTemplate> options = ObjectTemplate::New();
137
+ bool overwrite = false;
138
+ const char* output = 0;
139
+
140
+ for (int argpos = 1; argpos < argc; ++argpos)
141
+ {
142
+ if (argv[argpos][0] != '-')
143
+ {
144
+ source = readFile(argv[argpos]);
145
+ output = argv[argpos];
146
+ }
147
+ else if (strcmp(argv[argpos], "--stdin") == 0)
148
+ {
149
+ source = readFile(0);
150
+ }
151
+ else if (strcmp(argv[argpos], "--overwrite") == 0)
152
+ {
153
+ overwrite = true;
154
+ }
155
+ else if (strcmp(argv[argpos], "--indent-size") == 0 ||
156
+ strcmp(argv[argpos], "-s") == 0)
157
+ {
158
+ options->Set("indent_size", String::New(argv[argpos+1]));
159
+ }
160
+ else if (strcmp(argv[argpos], "--indent-char") == 0 ||
161
+ strcmp(argv[argpos], "-c") == 0)
162
+ {
163
+ options->Set("indent_char", String::New(argv[argpos+1]));
164
+ }
165
+ else if (strcmp(argv[argpos], "--disable-preserve-newlines") == 0 ||
166
+ strcmp(argv[argpos], "-d") == 0)
167
+ {
168
+ options->Set("preserve_newlines", Boolean::New(false));
169
+ }
170
+ else if (strcmp(argv[argpos], "--indent-level") == 0 ||
171
+ strcmp(argv[argpos], "-l") == 0)
172
+ {
173
+ options->Set("indent_level", String::New(argv[argpos+1]));
174
+ }
175
+ else if (strcmp(argv[argpos], "--space-after-anon-function") == 0 ||
176
+ strcmp(argv[argpos], "-f") == 0)
177
+ {
178
+ options->Set("space_after_anon_function", Boolean::New(true));
179
+ }
180
+ else if (strcmp(argv[argpos], "--braces-on-own-line") == 0 ||
181
+ strcmp(argv[argpos], "-b") == 0)
182
+ {
183
+ options->Set("braces_on_own_line", Boolean::New(true));
184
+ }
185
+ else if (strcmp(argv[argpos], "--keep-array-indentation") == 0 ||
186
+ strcmp(argv[argpos], "-k") == 0)
187
+ {
188
+ options->Set("keep_array_indentation", Boolean::New(true));
189
+ }
190
+ else if (strcmp(argv[argpos], "--help") == 0 ||
191
+ strcmp(argv[argpos], "-h") == 0)
192
+ {
193
+ usage(argv[0]);
194
+ return -1;
195
+ }
196
+ }
197
+
198
+ if (source.IsEmpty())
199
+ {
200
+ usage(argv[0]);
201
+ return -1;
202
+ }
203
+
204
+ global->Set("source", source);
205
+ global->Set("options", options);
206
+ Handle<Context> context = Context::New(NULL, global);
207
+ Context::Scope context_scope(context);
208
+ Handle<Script> beautifyScript = Script::Compile(String::New(beautify_code));
209
+ beautifyScript->Run();
210
+ Handle<Script> runnerScript = Script::Compile(String::New("js_beautify(source, options);"));
211
+ Handle<Value> result = runnerScript->Run();
212
+ writeFile(result, overwrite ? output : 0);
213
+ return 0;
214
+ }
215
+
@@ -0,0 +1,198 @@
1
+ /*
2
+
3
+ CSS Beautifier
4
+ ---------------
5
+
6
+ Written by Harutyun Amirjanyan, (amirjanyan@gmail.com)
7
+
8
+ Based on code initially developed by: Einar Lielmanis, <elfz@laacz.lv>
9
+ http://jsbeautifier.org/
10
+
11
+
12
+ You are free to use this in any way you want, in case you find this useful or working for you.
13
+
14
+ Usage:
15
+ css_beautify(source_text);
16
+ css_beautify(source_text, options);
17
+
18
+ The options are:
19
+ indent_size (default 4) — indentation size,
20
+ indent_char (default space) — character to indent with,
21
+
22
+ e.g
23
+
24
+ css_beautify(css_source_text, {
25
+ 'indent_size': 1,
26
+ 'indent_char': '\t'
27
+ });
28
+ */
29
+
30
+ // http://www.w3.org/TR/CSS21/syndata.html#tokenization
31
+ // http://www.w3.org/TR/css3-syntax/
32
+ function css_beautify(source_text, options) {
33
+ options = options || {};
34
+ var indentSize = options.indent_size || 4;
35
+ var indentCharacter = options.indent_char || ' ';
36
+
37
+ // compatibility
38
+ if (typeof indentSize == "string")
39
+ indentSize = parseInt(indentSize);
40
+
41
+
42
+ // tokenizer
43
+ var whiteRe = /^\s+$/;
44
+ var wordRe = /[\w$\-_]/;
45
+
46
+ var pos = -1, ch;
47
+ function next() {
48
+ return ch = source_text.charAt(++pos)
49
+ }
50
+ function peek() {
51
+ return source_text.charAt(pos+1)
52
+ }
53
+ function eatString(comma) {
54
+ var start = pos;
55
+ while(next()){
56
+ if (ch=="\\"){
57
+ next();
58
+ next();
59
+ } else if (ch == comma) {
60
+ break;
61
+ } else if (ch == "\n") {
62
+ break;
63
+ }
64
+ }
65
+ return source_text.substring(start, pos + 1);
66
+ }
67
+
68
+ function eatWhitespace() {
69
+ var start = pos;
70
+ while (whiteRe.test(peek()))
71
+ pos++;
72
+ return pos != start;
73
+ }
74
+
75
+ function skipWhitespace() {
76
+ var start = pos;
77
+ do{
78
+ }while (whiteRe.test(next()))
79
+ return pos != start + 1;
80
+ }
81
+
82
+ function eatComment() {
83
+ var start = pos;
84
+ next();
85
+ while (next()) {
86
+ if (ch == "*" && peek() == "/") {
87
+ pos ++;
88
+ break;
89
+ }
90
+ }
91
+
92
+ return source_text.substring(start, pos + 1);
93
+ }
94
+
95
+
96
+ function lookBack(str, index) {
97
+ return output.slice(-str.length + (index||0), index).join("").toLowerCase() == str;
98
+ }
99
+
100
+ // printer
101
+ var indentString = source_text.match(/^[\r\n]*[\t ]*/)[0];
102
+ var singleIndent = Array(indentSize + 1).join(indentCharacter);
103
+ var indentLevel = 0;
104
+ function indent() {
105
+ indentLevel++;
106
+ indentString += singleIndent;
107
+ }
108
+ function outdent() {
109
+ indentLevel--;
110
+ indentString = indentString.slice(0, -indentSize);
111
+ }
112
+
113
+ print = {}
114
+ print["{"] = function(ch) {
115
+ print.singleSpace();
116
+ output.push(ch);
117
+ print.newLine();
118
+ }
119
+ print["}"] = function(ch) {
120
+ print.newLine();
121
+ output.push(ch);
122
+ print.newLine();
123
+ }
124
+
125
+ print.newLine = function(keepWhitespace) {
126
+ if (!keepWhitespace)
127
+ while (whiteRe.test(output[output.length - 1]))
128
+ output.pop();
129
+
130
+ if (output.length)
131
+ output.push('\n');
132
+ if (indentString)
133
+ output.push(indentString);
134
+ }
135
+ print.singleSpace = function() {
136
+ if (output.length && !whiteRe.test(output[output.length - 1]))
137
+ output.push(' ');
138
+ }
139
+ var output = [];
140
+ if (indentString)
141
+ output.push(indentString);
142
+ /*_____________________--------------------_____________________*/
143
+
144
+ while(true) {
145
+ var isAfterSpace = skipWhitespace();
146
+
147
+ if (!ch)
148
+ break;
149
+
150
+ if (ch == '{') {
151
+ indent();
152
+ print["{"](ch);
153
+ } else if (ch == '}') {
154
+ outdent();
155
+ print["}"](ch);
156
+ } else if (ch == '"' || ch == '\'') {
157
+ output.push(eatString(ch))
158
+ } else if (ch == ';') {
159
+ output.push(ch, '\n', indentString);
160
+ } else if (ch == '/' && peek() == '*') { // comment
161
+ print.newLine();
162
+ output.push(eatComment(), "\n", indentString);
163
+ } else if (ch == '(') { // may be a url
164
+ output.push(ch);
165
+ eatWhitespace();
166
+ if (lookBack("url", -1) && next()) {
167
+ if (ch != ')' && ch != '"' && ch != '\'')
168
+ output.push(eatString(')'));
169
+ else
170
+ pos--;
171
+ }
172
+ } else if (ch == ')') {
173
+ output.push(ch);
174
+ } else if (ch == ',') {
175
+ eatWhitespace();
176
+ output.push(ch);
177
+ print.singleSpace();
178
+ } else if (ch == ']') {
179
+ output.push(ch);
180
+ } else if (ch == '[' || ch == '=') { // no whitespace before or after
181
+ eatWhitespace();
182
+ output.push(ch);
183
+ } else {
184
+ if (isAfterSpace)
185
+ print.singleSpace();
186
+
187
+ output.push(ch);
188
+ }
189
+ }
190
+
191
+
192
+ var sweetCode = output.join('').replace(/[\n ]+$/, '');
193
+ return sweetCode;
194
+ }
195
+
196
+
197
+ if (typeof exports !== "undefined")
198
+ exports.css_beautify = css_beautify;
@@ -0,0 +1,514 @@
1
+ /*
2
+
3
+ Style HTML
4
+ ---------------
5
+
6
+ Written by Nochum Sossonko, (nsossonko@hotmail.com)
7
+
8
+ Based on code initially developed by: Einar Lielmanis, <elfz@laacz.lv>
9
+ http://jsbeautifier.org/
10
+
11
+
12
+ You are free to use this in any way you want, in case you find this useful or working for you.
13
+
14
+ Usage:
15
+ style_html(html_source);
16
+
17
+ style_html(html_source, options);
18
+
19
+ The options are:
20
+ indent_size (default 4) — indentation size,
21
+ indent_char (default space) — character to indent with,
22
+ max_char (default 70) - maximum amount of characters per line,
23
+ brace_style (default "collapse") - "collapse" | "expand" | "end-expand"
24
+ 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.
25
+ unformatted (default ['a']) - list of tags, that shouldn't be reformatted
26
+ indent_scripts (default normal) - "keep"|"separate"|"normal"
27
+
28
+ e.g.
29
+
30
+ style_html(html_source, {
31
+ 'indent_size': 2,
32
+ 'indent_char': ' ',
33
+ 'max_char': 78,
34
+ 'brace_style': 'expand',
35
+ 'unformatted': ['a', 'sub', 'sup', 'b', 'i', 'u']
36
+ });
37
+ */
38
+
39
+ function style_html(html_source, options) {
40
+ //Wrapper function to invoke all the necessary constructors and deal with the output.
41
+
42
+ var multi_parser,
43
+ indent_size,
44
+ indent_character,
45
+ max_char,
46
+ brace_style;
47
+
48
+ options = options || {};
49
+ indent_size = options.indent_size || 4;
50
+ indent_character = options.indent_char || ' ';
51
+ brace_style = options.brace_style || 'collapse';
52
+ max_char = options.max_char == 0 ? Infinity : options.max_char || 70;
53
+ unformatted = options.unformatted || ['a'];
54
+
55
+ function Parser() {
56
+
57
+ this.pos = 0; //Parser position
58
+ this.token = '';
59
+ this.current_mode = 'CONTENT'; //reflects the current Parser mode: TAG/CONTENT
60
+ this.tags = { //An object to hold tags, their position, and their parent-tags, initiated with default values
61
+ parent: 'parent1',
62
+ parentcount: 1,
63
+ parent1: ''
64
+ };
65
+ this.tag_type = '';
66
+ this.token_text = this.last_token = this.last_text = this.token_type = '';
67
+
68
+ this.Utils = { //Uilities made available to the various functions
69
+ whitespace: "\n\r\t ".split(''),
70
+ single_token: 'br,input,link,meta,!doctype,basefont,base,area,hr,wbr,param,img,isindex,?xml,embed'.split(','), //all the single tags for HTML
71
+ extra_liners: 'head,body,/html'.split(','), //for tags that need a line of whitespace before them
72
+ in_array: function (what, arr) {
73
+ for (var i=0; i<arr.length; i++) {
74
+ if (what === arr[i]) {
75
+ return true;
76
+ }
77
+ }
78
+ return false;
79
+ }
80
+ }
81
+
82
+ this.get_content = function () { //function to capture regular content between tags
83
+
84
+ var input_char = '';
85
+ var content = [];
86
+ var space = false; //if a space is needed
87
+ while (this.input.charAt(this.pos) !== '<') {
88
+ if (this.pos >= this.input.length) {
89
+ return content.length?content.join(''):['', 'TK_EOF'];
90
+ }
91
+
92
+ input_char = this.input.charAt(this.pos);
93
+ this.pos++;
94
+ this.line_char_count++;
95
+
96
+ if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
97
+ if (content.length) {
98
+ space = true;
99
+ }
100
+ this.line_char_count--;
101
+ continue; //don't want to insert unnecessary space
102
+ }
103
+ else if (space) {
104
+ if (this.line_char_count >= this.max_char) { //insert a line when the max_char is reached
105
+ content.push('\n');
106
+ for (var i=0; i<this.indent_level; i++) {
107
+ content.push(this.indent_string);
108
+ }
109
+ this.line_char_count = 0;
110
+ }
111
+ else{
112
+ content.push(' ');
113
+ this.line_char_count++;
114
+ }
115
+ space = false;
116
+ }
117
+ content.push(input_char); //letter at-a-time (or string) inserted to an array
118
+ }
119
+ return content.length?content.join(''):'';
120
+ }
121
+
122
+ this.get_contents_to = function (name) { //get the full content of a script or style to pass to js_beautify
123
+ if (this.pos == this.input.length) {
124
+ return ['', 'TK_EOF'];
125
+ }
126
+ var input_char = '';
127
+ var content = '';
128
+ var reg_match = new RegExp('\<\/' + name + '\\s*\>', 'igm');
129
+ reg_match.lastIndex = this.pos;
130
+ var reg_array = reg_match.exec(this.input);
131
+ var end_script = reg_array?reg_array.index:this.input.length; //absolute end of script
132
+ if(this.pos < end_script) { //get everything in between the script tags
133
+ content = this.input.substring(this.pos, end_script);
134
+ this.pos = end_script;
135
+ }
136
+ return content;
137
+ }
138
+
139
+ this.record_tag = function (tag){ //function to record a tag and its parent in this.tags Object
140
+ if (this.tags[tag + 'count']) { //check for the existence of this tag type
141
+ this.tags[tag + 'count']++;
142
+ this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
143
+ }
144
+ else { //otherwise initialize this tag type
145
+ this.tags[tag + 'count'] = 1;
146
+ this.tags[tag + this.tags[tag + 'count']] = this.indent_level; //and record the present indent level
147
+ }
148
+ 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)
149
+ this.tags.parent = tag + this.tags[tag + 'count']; //and make this the current parent (i.e. in the case of a div 'div1')
150
+ }
151
+
152
+ this.retrieve_tag = function (tag) { //function to retrieve the opening tag to the corresponding closer
153
+ if (this.tags[tag + 'count']) { //if the openener is not in the Object we ignore it
154
+ var temp_parent = this.tags.parent; //check to see if it's a closable tag.
155
+ while (temp_parent) { //till we reach '' (the initial value);
156
+ if (tag + this.tags[tag + 'count'] === temp_parent) { //if this is it use it
157
+ break;
158
+ }
159
+ temp_parent = this.tags[temp_parent + 'parent']; //otherwise keep on climbing up the DOM Tree
160
+ }
161
+ if (temp_parent) { //if we caught something
162
+ this.indent_level = this.tags[tag + this.tags[tag + 'count']]; //set the indent_level accordingly
163
+ this.tags.parent = this.tags[temp_parent + 'parent']; //and set the current parent
164
+ }
165
+ delete this.tags[tag + this.tags[tag + 'count'] + 'parent']; //delete the closed tags parent reference...
166
+ delete this.tags[tag + this.tags[tag + 'count']]; //...and the tag itself
167
+ if (this.tags[tag + 'count'] == 1) {
168
+ delete this.tags[tag + 'count'];
169
+ }
170
+ else {
171
+ this.tags[tag + 'count']--;
172
+ }
173
+ }
174
+ }
175
+
176
+ this.get_tag = function () { //function to get a full tag and parse its type
177
+ var input_char = '';
178
+ var content = [];
179
+ var space = false;
180
+
181
+ do {
182
+ if (this.pos >= this.input.length) {
183
+ return content.length?content.join(''):['', 'TK_EOF'];
184
+ }
185
+
186
+ input_char = this.input.charAt(this.pos);
187
+ this.pos++;
188
+ this.line_char_count++;
189
+
190
+ if (this.Utils.in_array(input_char, this.Utils.whitespace)) { //don't want to insert unnecessary space
191
+ space = true;
192
+ this.line_char_count--;
193
+ continue;
194
+ }
195
+
196
+ if (input_char === "'" || input_char === '"') {
197
+ if (!content[1] || content[1] !== '!') { //if we're in a comment strings don't get treated specially
198
+ input_char += this.get_unformatted(input_char);
199
+ space = true;
200
+ }
201
+ }
202
+
203
+ if (input_char === '=') { //no space before =
204
+ space = false;
205
+ }
206
+
207
+ if (content.length && content[content.length-1] !== '=' && input_char !== '>'
208
+ && space) { //no space after = or before >
209
+ if (this.line_char_count >= this.max_char) {
210
+ this.print_newline(false, content);
211
+ this.line_char_count = 0;
212
+ }
213
+ else {
214
+ content.push(' ');
215
+ this.line_char_count++;
216
+ }
217
+ space = false;
218
+ }
219
+ content.push(input_char); //inserts character at-a-time (or string)
220
+ } while (input_char !== '>');
221
+
222
+ var tag_complete = content.join('');
223
+ var tag_index;
224
+ if (tag_complete.indexOf(' ') != -1) { //if there's whitespace, thats where the tag name ends
225
+ tag_index = tag_complete.indexOf(' ');
226
+ }
227
+ else { //otherwise go with the tag ending
228
+ tag_index = tag_complete.indexOf('>');
229
+ }
230
+ var tag_check = tag_complete.substring(1, tag_index).toLowerCase();
231
+ if (tag_complete.charAt(tag_complete.length-2) === '/' ||
232
+ 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 /)
233
+ this.tag_type = 'SINGLE';
234
+ }
235
+ else if (tag_check === 'script') { //for later script handling
236
+ this.record_tag(tag_check);
237
+ this.tag_type = 'SCRIPT';
238
+ }
239
+ else if (tag_check === 'style') { //for future style handling (for now it justs uses get_content)
240
+ this.record_tag(tag_check);
241
+ this.tag_type = 'STYLE';
242
+ }
243
+ else if (this.Utils.in_array(tag_check, unformatted)) { // do not reformat the "unformatted" tags
244
+ var comment = this.get_unformatted('</'+tag_check+'>', tag_complete); //...delegate to get_unformatted function
245
+ content.push(comment);
246
+ this.tag_type = 'SINGLE';
247
+ }
248
+ else if (tag_check.charAt(0) === '!') { //peek for <!-- comment
249
+ if (tag_check.indexOf('[if') != -1) { //peek for <!--[if conditional comment
250
+ if (tag_complete.indexOf('!IE') != -1) { //this type needs a closing --> so...
251
+ var comment = this.get_unformatted('-->', tag_complete); //...delegate to get_unformatted
252
+ content.push(comment);
253
+ }
254
+ this.tag_type = 'START';
255
+ }
256
+ else if (tag_check.indexOf('[endif') != -1) {//peek for <!--[endif end conditional comment
257
+ this.tag_type = 'END';
258
+ this.unindent();
259
+ }
260
+ else if (tag_check.indexOf('[cdata[') != -1) { //if it's a <[cdata[ comment...
261
+ var comment = this.get_unformatted(']]>', tag_complete); //...delegate to get_unformatted function
262
+ content.push(comment);
263
+ this.tag_type = 'SINGLE'; //<![CDATA[ comments are treated like single tags
264
+ }
265
+ else {
266
+ var comment = this.get_unformatted('-->', tag_complete);
267
+ content.push(comment);
268
+ this.tag_type = 'SINGLE';
269
+ }
270
+ }
271
+ else {
272
+ if (tag_check.charAt(0) === '/') { //this tag is a double tag so check for tag-ending
273
+ this.retrieve_tag(tag_check.substring(1)); //remove it and all ancestors
274
+ this.tag_type = 'END';
275
+ }
276
+ else { //otherwise it's a start-tag
277
+ this.record_tag(tag_check); //push it on the tag stack
278
+ this.tag_type = 'START';
279
+ }
280
+ if (this.Utils.in_array(tag_check, this.Utils.extra_liners)) { //check if this double needs an extra line
281
+ this.print_newline(true, this.output);
282
+ }
283
+ }
284
+ return content.join(''); //returns fully formatted tag
285
+ }
286
+
287
+ this.get_unformatted = function (delimiter, orig_tag) { //function to return unformatted content in its entirety
288
+
289
+ if (orig_tag && orig_tag.indexOf(delimiter) != -1) {
290
+ return '';
291
+ }
292
+ var input_char = '';
293
+ var content = '';
294
+ var space = true;
295
+ do {
296
+
297
+ if (this.pos >= this.input.length) {
298
+ return content;
299
+ }
300
+
301
+ input_char = this.input.charAt(this.pos);
302
+ this.pos++
303
+
304
+ if (this.Utils.in_array(input_char, this.Utils.whitespace)) {
305
+ if (!space) {
306
+ this.line_char_count--;
307
+ continue;
308
+ }
309
+ if (input_char === '\n' || input_char === '\r') {
310
+ content += '\n';
311
+ /* 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'
312
+ for (var i=0; i<this.indent_level; i++) {
313
+ content += this.indent_string;
314
+ }
315
+ space = false; //...and make sure other indentation is erased
316
+ */
317
+ this.line_char_count = 0;
318
+ continue;
319
+ }
320
+ }
321
+ content += input_char;
322
+ this.line_char_count++;
323
+ space = true;
324
+
325
+
326
+ } while (content.indexOf(delimiter) == -1);
327
+ return content;
328
+ }
329
+
330
+ this.get_token = function () { //initial handler for token-retrieval
331
+ var token;
332
+
333
+ if (this.last_token === 'TK_TAG_SCRIPT' || this.last_token === 'TK_TAG_STYLE') { //check if we need to format javascript
334
+ var type = this.last_token.substr(7)
335
+ token = this.get_contents_to(type);
336
+ if (typeof token !== 'string') {
337
+ return token;
338
+ }
339
+ return [token, 'TK_' + type];
340
+ }
341
+ if (this.current_mode === 'CONTENT') {
342
+ token = this.get_content();
343
+ if (typeof token !== 'string') {
344
+ return token;
345
+ }
346
+ else {
347
+ return [token, 'TK_CONTENT'];
348
+ }
349
+ }
350
+
351
+ if (this.current_mode === 'TAG') {
352
+ token = this.get_tag();
353
+ if (typeof token !== 'string') {
354
+ return token;
355
+ }
356
+ else {
357
+ var tag_name_type = 'TK_TAG_' + this.tag_type;
358
+ return [token, tag_name_type];
359
+ }
360
+ }
361
+ }
362
+
363
+ this.get_full_indent = function (level) {
364
+ level = this.indent_level + level || 0;
365
+ if (level < 1)
366
+ return '';
367
+
368
+ return Array(level + 1).join(this.indent_string);
369
+ }
370
+
371
+
372
+ this.printer = function (js_source, indent_character, indent_size, max_char, brace_style) { //handles input/output and some other printing functions
373
+
374
+ this.input = js_source || ''; //gets the input for the Parser
375
+ this.output = [];
376
+ this.indent_character = indent_character;
377
+ this.indent_string = '';
378
+ this.indent_size = indent_size;
379
+ this.brace_style = brace_style;
380
+ this.indent_level = 0;
381
+ this.max_char = max_char;
382
+ this.line_char_count = 0; //count to see if max_char was exceeded
383
+
384
+ for (var i=0; i<this.indent_size; i++) {
385
+ this.indent_string += this.indent_character;
386
+ }
387
+
388
+ this.print_newline = function (ignore, arr) {
389
+ this.line_char_count = 0;
390
+ if (!arr || !arr.length) {
391
+ return;
392
+ }
393
+ if (!ignore) { //we might want the extra line
394
+ while (this.Utils.in_array(arr[arr.length-1], this.Utils.whitespace)) {
395
+ arr.pop();
396
+ }
397
+ }
398
+ arr.push('\n');
399
+ for (var i=0; i<this.indent_level; i++) {
400
+ arr.push(this.indent_string);
401
+ }
402
+ }
403
+
404
+ this.print_token = function (text) {
405
+ this.output.push(text);
406
+ }
407
+
408
+ this.indent = function () {
409
+ this.indent_level++;
410
+ }
411
+
412
+ this.unindent = function () {
413
+ if (this.indent_level > 0) {
414
+ this.indent_level--;
415
+ }
416
+ }
417
+ }
418
+ return this;
419
+ }
420
+
421
+ /*_____________________--------------------_____________________*/
422
+
423
+ multi_parser = new Parser(); //wrapping functions Parser
424
+ multi_parser.printer(html_source, indent_character, indent_size, max_char, brace_style); //initialize starting values
425
+
426
+ while (true) {
427
+ var t = multi_parser.get_token();
428
+ multi_parser.token_text = t[0];
429
+ multi_parser.token_type = t[1];
430
+
431
+ if (multi_parser.token_type === 'TK_EOF') {
432
+ break;
433
+ }
434
+
435
+ switch (multi_parser.token_type) {
436
+ case 'TK_TAG_START':
437
+ multi_parser.print_newline(false, multi_parser.output);
438
+ multi_parser.print_token(multi_parser.token_text);
439
+ multi_parser.indent();
440
+ multi_parser.current_mode = 'CONTENT';
441
+ break;
442
+ case 'TK_TAG_STYLE':
443
+ case 'TK_TAG_SCRIPT':
444
+ multi_parser.print_newline(false, multi_parser.output);
445
+ multi_parser.print_token(multi_parser.token_text);
446
+ multi_parser.current_mode = 'CONTENT';
447
+ break;
448
+ case 'TK_TAG_END':
449
+ //Print new line only if the tag has no content and has child
450
+ if (multi_parser.last_token === 'TK_CONTENT' && multi_parser.last_text === '') {
451
+ var tag_name = multi_parser.token_text.match(/\w+/)[0];
452
+ var tag_extracted_from_last_output = multi_parser.output[multi_parser.output.length -1].match(/<\s*(\w+)/);
453
+ if (tag_extracted_from_last_output === null || tag_extracted_from_last_output[1] !== tag_name)
454
+ multi_parser.print_newline(true, multi_parser.output);
455
+ }
456
+ multi_parser.print_token(multi_parser.token_text);
457
+ multi_parser.current_mode = 'CONTENT';
458
+ break;
459
+ case 'TK_TAG_SINGLE':
460
+ multi_parser.print_newline(false, multi_parser.output);
461
+ multi_parser.print_token(multi_parser.token_text);
462
+ multi_parser.current_mode = 'CONTENT';
463
+ break;
464
+ case 'TK_CONTENT':
465
+ if (multi_parser.token_text !== '') {
466
+ multi_parser.print_token(multi_parser.token_text);
467
+ }
468
+ multi_parser.current_mode = 'TAG';
469
+ break;
470
+ case 'TK_STYLE':
471
+ case 'TK_SCRIPT':
472
+ if (multi_parser.token_text !== '') {
473
+ multi_parser.output.push('\n');
474
+ var text = multi_parser.token_text;
475
+ if (multi_parser.token_type == 'TK_SCRIPT') {
476
+ var _beautifier = typeof js_beautify == 'function' && js_beautify;
477
+ } else if (multi_parser.token_type == 'TK_STYLE') {
478
+ var _beautifier = typeof css_beautify == 'function' && css_beautify;
479
+ }
480
+
481
+ if (options.indent_scripts == "keep") {
482
+ var script_indent_level = 0;
483
+ } else if (options.indent_scripts == "separate") {
484
+ var script_indent_level = -multi_parser.indent_level;
485
+ } else {
486
+ var script_indent_level = 1;
487
+ }
488
+
489
+ var indentation = multi_parser.get_full_indent(script_indent_level);
490
+ if (_beautifier) {
491
+ // call the Beautifier if avaliable
492
+ text = _beautifier(text.replace(/^\s*/, indentation), options);
493
+ } else {
494
+ // simply indent the string otherwise
495
+ var white = text.match(/^\s*/)[0];
496
+ var _level = white.match(/[^\n\r]*$/)[0].split(multi_parser.indent_string).length - 1;
497
+ var reindent = multi_parser.get_full_indent(script_indent_level -_level);
498
+ text = text.replace(/^\s*/, indentation)
499
+ .replace(/\r\n|\r|\n/g, '\n' + reindent)
500
+ .replace(/\s*$/, '');
501
+ }
502
+ if (text) {
503
+ multi_parser.print_token(text);
504
+ multi_parser.print_newline(true, multi_parser.output);
505
+ }
506
+ }
507
+ multi_parser.current_mode = 'TAG';
508
+ break;
509
+ }
510
+ multi_parser.last_token = multi_parser.token_type;
511
+ multi_parser.last_text = multi_parser.token_text;
512
+ }
513
+ return multi_parser.output.join('');
514
+ }