grat 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +14 -0
- data/Rakefile +1 -1
- data/grat.gemspec +3 -3
- data/lib/environment.rb +1 -1
- data/lib/grat.rb +3 -3
- data/lib/grat/content.rb +95 -1
- data/lib/grat/page.rb +1 -9
- data/lib/grat/template.rb +2 -38
- data/public/gratfiles/application.js +8 -1
- data/public/gratfiles/einars-js-beautify/HTML-Beautify.js +427 -0
- data/public/gratfiles/einars-js-beautify/beautify-cl.js +112 -0
- data/public/gratfiles/einars-js-beautify/beautify-tests.js +273 -0
- data/public/gratfiles/einars-js-beautify/beautify.js +891 -0
- data/public/gratfiles/einars-js-beautify/bin/beautify_js +53 -0
- data/public/gratfiles/einars-js-beautify/index.html +243 -0
- data/public/gratfiles/einars-js-beautify/javascriptobfuscator_unpacker.js +91 -0
- data/public/gratfiles/einars-js-beautify/license.txt +23 -0
- data/public/gratfiles/einars-js-beautify/sanitytest.js +128 -0
- data/public/gratfiles/einars-js-beautify/unmaintained/bbedit/jsBeautify_BBED.scpt +522 -0
- data/public/gratfiles/einars-js-beautify/unmaintained/c-sharp/JSBeautify.cs +801 -0
- data/public/gratfiles/einars-js-beautify/unmaintained/opera-userscript/make_opera_userscript.sh +35 -0
- data/public/gratfiles/einars-js-beautify/unmaintained/opera-userscript/opera_userscript.js +711 -0
- data/public/gratfiles/js-beautifier.min.js +1 -0
- data/views/content_form.haml +9 -17
- data/views/layout.haml +2 -0
- metadata +16 -2
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
|
3
|
+
def print_usage
|
4
|
+
puts <<End
|
5
|
+
Usage: #{File.basename($0)} file
|
6
|
+
Usage: echo 'JavaScript input' | #{File.basename($0)}
|
7
|
+
|
8
|
+
Using this is a vim filter command
|
9
|
+
----------------------------------
|
10
|
+
|
11
|
+
This can also be used as a vim filter command (see help filter).
|
12
|
+
|
13
|
+
Simply select the lines to be beautified in visual mode and type .!beautify_js.
|
14
|
+
|
15
|
+
Better yet, create a vim command to execute it for you, and put that in your .vimrc:
|
16
|
+
command! -range=% -nargs=0 BeautifyJavascript <line1>,<line2>!#{$0}
|
17
|
+
|
18
|
+
Then you can simply type BeautifyJavascript to process the entire buffer or select a range of lines to only pass those lines through the filter.
|
19
|
+
End
|
20
|
+
exit
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
if STDIN.tty?
|
25
|
+
if ARGV.size >= 1
|
26
|
+
# Get the absolute path of the filename given
|
27
|
+
require 'pathname'
|
28
|
+
path = Pathname.new(ARGV[0]).realpath.to_s
|
29
|
+
else
|
30
|
+
print_usage
|
31
|
+
end
|
32
|
+
else
|
33
|
+
# Assume they are piping the input in. Save that input in a temporary file and pass that file to beautify-cl.js
|
34
|
+
require 'tempfile'
|
35
|
+
file = Tempfile.new('beautify_js')
|
36
|
+
file.puts STDIN.read
|
37
|
+
file.close
|
38
|
+
path = file.path
|
39
|
+
end
|
40
|
+
#system "cat #{path}"
|
41
|
+
|
42
|
+
|
43
|
+
# Change directory so that the load() calls in beautify-cl.js are able to find the files they need
|
44
|
+
Dir.chdir File.dirname(__FILE__)
|
45
|
+
Dir.chdir '..'
|
46
|
+
#puts Dir.getwd
|
47
|
+
|
48
|
+
|
49
|
+
command = "rhino beautify-cl.js '#{path}' 2>&1"
|
50
|
+
#puts command
|
51
|
+
#output = `#{command}`
|
52
|
+
system command
|
53
|
+
|
@@ -0,0 +1,243 @@
|
|
1
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
3
|
+
<!--
|
4
|
+
|
5
|
+
(c) 2006-2009: Einar Lielmanis, einars@gmail.com
|
6
|
+
|
7
|
+
-->
|
8
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
9
|
+
<head>
|
10
|
+
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
11
|
+
<title>Online javascript beautifier</title>
|
12
|
+
<script type="text/javascript">
|
13
|
+
function add_onload_function(fn)
|
14
|
+
{
|
15
|
+
var oe=window.onload;
|
16
|
+
window.onload = function() { if (oe) oe(); fn(); }
|
17
|
+
}
|
18
|
+
add_onload_function(function() {
|
19
|
+
|
20
|
+
var tabsize = get_var('tabsize');
|
21
|
+
if (tabsize) {
|
22
|
+
document.getElementById('tabsize').value = tabsize;
|
23
|
+
}
|
24
|
+
|
25
|
+
|
26
|
+
var c = document.forms[0].content;
|
27
|
+
c && c.setSelectionRange && c.setSelectionRange(0, 0);
|
28
|
+
c && c.focus && c.focus();
|
29
|
+
});
|
30
|
+
|
31
|
+
function starts_with(str, what)
|
32
|
+
{
|
33
|
+
return str.substr(0, what.length) === what;
|
34
|
+
}
|
35
|
+
|
36
|
+
function trim_leading_comments(str)
|
37
|
+
{
|
38
|
+
// very basic. doesn't support /* ... */
|
39
|
+
str = str.replace(/^(\s*\/\/[^\n]*\n)+/, '');
|
40
|
+
str = str.replace(/^\s+/, '');
|
41
|
+
return str;
|
42
|
+
}
|
43
|
+
|
44
|
+
function unpacker_filter(source)
|
45
|
+
{
|
46
|
+
|
47
|
+
if (document.getElementById('detect-packers').checked) {
|
48
|
+
|
49
|
+
var stripped_source = trim_leading_comments(source);
|
50
|
+
|
51
|
+
//try {
|
52
|
+
if (starts_with(stripped_source.toLowerCase().replace(/ +/g, ''), 'eval(function(p,a,c,k')) {
|
53
|
+
eval('var unpacked_source = ' + stripped_source.substring(4) + ';')
|
54
|
+
return unpacker_filter(unpacked_source);
|
55
|
+
} else if (JavascriptObfuscator.detect(stripped_source)) {
|
56
|
+
var unpacked = JavascriptObfuscator.unpack(stripped_source);
|
57
|
+
if (unpacked !== stripped_source) { // avoid infinite loop if nothing done
|
58
|
+
return unpacker_filter(unpacked);
|
59
|
+
}
|
60
|
+
}
|
61
|
+
//} catch (error) {
|
62
|
+
//source = '// jsbeautifier: unpacking failed\n'
|
63
|
+
//+ '// You may wish to send me a report to einar@jsbeautifier.org\n'
|
64
|
+
//+ source;
|
65
|
+
//}
|
66
|
+
}
|
67
|
+
return source;
|
68
|
+
|
69
|
+
}
|
70
|
+
|
71
|
+
|
72
|
+
function do_js_beautify()
|
73
|
+
{
|
74
|
+
document.getElementById('beautify').disabled = true;
|
75
|
+
var js_source = document.getElementById('content').value.replace(/^\s+/, '');
|
76
|
+
var indent_size = document.getElementById('tabsize').value;
|
77
|
+
var indent_char = ' ';
|
78
|
+
var preserve_newlines = document.getElementById('preserve-newlines').checked;
|
79
|
+
|
80
|
+
if (indent_size == 1) {
|
81
|
+
indent_char = '\t';
|
82
|
+
}
|
83
|
+
|
84
|
+
|
85
|
+
if (js_source && js_source[0] === '<' && js_source.substring(0, 4) !== '<!--') {
|
86
|
+
document.getElementById('content').value = style_html(js_source, indent_size, indent_char, 80);
|
87
|
+
} else {
|
88
|
+
document.getElementById('content').value =
|
89
|
+
js_beautify(unpacker_filter(js_source), {indent_size: indent_size, indent_char: indent_char, preserve_newlines:preserve_newlines, space_after_anon_function:true});
|
90
|
+
}
|
91
|
+
|
92
|
+
document.getElementById('beautify').disabled = false;
|
93
|
+
return false;
|
94
|
+
}
|
95
|
+
|
96
|
+
|
97
|
+
function get_var( name )
|
98
|
+
{
|
99
|
+
var res = new RegExp( "[\\?&]" + name + "=([^&#]*)" ).exec( window.location.href );
|
100
|
+
return res ? res[1] : "";
|
101
|
+
}
|
102
|
+
|
103
|
+
function run_tests()
|
104
|
+
{
|
105
|
+
var st = new SanityTest();
|
106
|
+
run_beautifier_tests(st);
|
107
|
+
JavascriptObfuscator.run_tests(st);
|
108
|
+
return st.results();
|
109
|
+
}
|
110
|
+
|
111
|
+
</script>
|
112
|
+
<script type="text/javascript" src="sanitytest.js" ></script>
|
113
|
+
<script type="text/javascript" src="beautify.js" ></script>
|
114
|
+
<script type="text/javascript" src="beautify-tests.js" ></script>
|
115
|
+
<script type="text/javascript" src="javascriptobfuscator_unpacker.js" ></script>
|
116
|
+
<script type="text/javascript" src="HTML-Beautify.js" ></script>
|
117
|
+
|
118
|
+
<style type="text/css">
|
119
|
+
/* I guess I need a CSS beautifer as well */
|
120
|
+
form {
|
121
|
+
margin: 0 10px 0 10px;
|
122
|
+
}
|
123
|
+
textarea {
|
124
|
+
width: 100%;
|
125
|
+
height: 420px;
|
126
|
+
border: 1px solid #ccc; padding: 3px;
|
127
|
+
}
|
128
|
+
h1 {
|
129
|
+
font-family: "trebuchet ms", arial, sans-serif;
|
130
|
+
font-weight: normal;
|
131
|
+
font-size: 28px;
|
132
|
+
color: #666;
|
133
|
+
margin-bottom: 15px;
|
134
|
+
border-bottom: 1px solid #666;
|
135
|
+
}
|
136
|
+
a {
|
137
|
+
color: #36d;
|
138
|
+
}
|
139
|
+
select {
|
140
|
+
width: 19%;
|
141
|
+
}
|
142
|
+
button {
|
143
|
+
width: 40%;
|
144
|
+
cursor: pointer;
|
145
|
+
}
|
146
|
+
body, label, button, select {
|
147
|
+
font-family: "myriad web", verdana, arial, helvetica, sans-serif;
|
148
|
+
font-size: 14px;
|
149
|
+
}
|
150
|
+
textarea, pre, span.code {
|
151
|
+
font-family: terminus, consolas, "lucida console", "courier new", courier, monospace;
|
152
|
+
font-size: 12px;
|
153
|
+
}
|
154
|
+
div#bottom {
|
155
|
+
color: #333;
|
156
|
+
margin: 20px;
|
157
|
+
}
|
158
|
+
a#signature {
|
159
|
+
background: url(http://spicausis.lv/spic-sign-blog.png) no-repeat bottom right;
|
160
|
+
display:block;
|
161
|
+
width: 15px;
|
162
|
+
height: 21px;
|
163
|
+
position: fixed;
|
164
|
+
bottom: 0px;
|
165
|
+
right: 0px;
|
166
|
+
}
|
167
|
+
h2 {
|
168
|
+
color: #555;
|
169
|
+
font-size: 14px;
|
170
|
+
text-decoration: underline;
|
171
|
+
margin-top: 14px;
|
172
|
+
}
|
173
|
+
p {
|
174
|
+
line-height: 150%;
|
175
|
+
font-size: 14px;
|
176
|
+
margin: 0;
|
177
|
+
}
|
178
|
+
div#footer {
|
179
|
+
margin: 20px 0 0 0;
|
180
|
+
font-size: 12px;
|
181
|
+
border-top: 1px solid #ddd;
|
182
|
+
padding-top: 16px;
|
183
|
+
|
184
|
+
}
|
185
|
+
|
186
|
+
</style>
|
187
|
+
</head>
|
188
|
+
<body>
|
189
|
+
<h1>Javascript beautifier</h1>
|
190
|
+
<form method="post" action="?">
|
191
|
+
<textarea rows="30" cols="30" name="content" id="content">
|
192
|
+
/* paste in your code and press Beautify button */
|
193
|
+
if('this_is'==/an_example/){do_something();}else{var a=b?(c%d):e[f];}
|
194
|
+
</textarea><br />
|
195
|
+
<button onclick="return do_js_beautify()" id="beautify">Beautify</button>
|
196
|
+
<select name="tabsize" id="tabsize">
|
197
|
+
<option value="1">indent with a tab character</option>
|
198
|
+
<option value="2">indent with 2 spaces</option>
|
199
|
+
<option value="3">indent with 3 spaces</option>
|
200
|
+
<option value="4" selected="selected">indent with 4 spaces</option>
|
201
|
+
<option value="8">indent with 8 spaces</option>
|
202
|
+
</select>
|
203
|
+
<input type="checkbox" id="preserve-newlines" checked="checked" /><label for="preserve-newlines"> Preserve empty lines?</label>
|
204
|
+
<input type="checkbox" id="detect-packers" checked="checked" /><label for="detect-packers"> Detect packers?</label>
|
205
|
+
</form>
|
206
|
+
<div id="bottom">
|
207
|
+
<p>This beautifier can process your messy or compacted javascript, making it all neatly and consistently formatted and
|
208
|
+
readable.</p>
|
209
|
+
<p>You can always see the latest version of the code in <a
|
210
|
+
href="http://github.com/einars/js-beautify">github</a>, and you can download the beautifier for
|
211
|
+
local use (<a href="http://github.com/einars/js-beautify/zipball/master">zip</a>, <a href="http://github.com/einars/js-beautify/tarball/master">tar.gz</a>) as well.</p>
|
212
|
+
<h2>Packers and obfuscators</h2>
|
213
|
+
<p>The beautifier contains automatic unpacker for <a href="http://dean.edwards.name/packer/">Dean Edward's p.a.c.k.e.r</a> and scripts obfuscated by javascriptobfuscator.com.</p>
|
214
|
+
<h2>Formatting from command-line</h2>
|
215
|
+
<p>To beautify from the command-line you can use provided beautify-cl.js script, using <a href="http://www.mozilla.org/rhino/">Rhino javascript engine</a>. See the file contents for the details.</p>
|
216
|
+
<h2><a href="http://fiddler2.com/">Fiddler</a></h2>
|
217
|
+
<p>This popular web debugging proxy for Windows has a <a href="http://fiddler2.com/Fiddler2/extensions.asp">Javascript Formatter addon</a> (based on this beautifier) which can reformat javascript on the fly.</p>
|
218
|
+
<h2>Vim</h2>
|
219
|
+
<p>Aj3423 converted the script to vimscript — and so now there is a <a href="http://www.vim.org/scripts/script.php?script_id=2727">vim plugin</a> for the quality javascript beautifying.</p>
|
220
|
+
<h2>Other nice things</h2>
|
221
|
+
<p>If you're writing javascript code, <a href="http://jslint.com/">JSLint</a> is a really fine piece of software, too. You don't have to follow its recommendations blindly, but understanding what it says about your code can greatly improve your skills.</p>
|
222
|
+
<h2>Contacts</h2>
|
223
|
+
<p>If you find some problems with the generated javascript, adapt the script for your favorite editor, or something, my email is einar@jsbeautifier.org.</p>
|
224
|
+
<div id="footer">
|
225
|
+
<pre id="testresults"></pre>
|
226
|
+
Written by <a href="mailto:einar@jsbeautifier.org">Einar Lielmanis</a>, with the help of <a href="http://jason.diamond.name/weblog/">Jason Diamond</a>, Patrick Hof, Nochum, Andreas Schneider, Dave Vasilevsky, <a href="http://my.opera.com/Vital/blog/">Vital,</a> Ron Baldwin and others.
|
227
|
+
<a href="#" onclick="document.getElementById('testresults').style.display='block'; document.getElementById('testresults').innerHTML=run_tests(); return false;">Run tests?</a>
|
228
|
+
|
229
|
+
</div>
|
230
|
+
</div>
|
231
|
+
<a id="signature" href="http://spicausis.lv/"></a>
|
232
|
+
|
233
|
+
<script src="http://www.google-analytics.com/ga.js" type="text/javascript"></script>
|
234
|
+
<script type="text/javascript">
|
235
|
+
if (window._gat) {
|
236
|
+
var tracker = _gat._getTracker("UA-7409939-1");
|
237
|
+
if (tracker && tracker._trackPageview) {
|
238
|
+
tracker._trackPageview();
|
239
|
+
}
|
240
|
+
}
|
241
|
+
</script>
|
242
|
+
</body>
|
243
|
+
</html>
|
@@ -0,0 +1,91 @@
|
|
1
|
+
//
|
2
|
+
// simple unpacker/deobfuscator for scripts messed up with javascriptobfuscator.com
|
3
|
+
// written by Einar Lielmanis <einar@jsbeautifier.org>
|
4
|
+
//
|
5
|
+
// usage:
|
6
|
+
//
|
7
|
+
// if (JavascriptObfuscator.detect(some_string)) {
|
8
|
+
// var unpacked = JavascriptObfuscator.unpack(some_string);
|
9
|
+
// }
|
10
|
+
//
|
11
|
+
//
|
12
|
+
|
13
|
+
var JavascriptObfuscator = {
|
14
|
+
detect: function (str) {
|
15
|
+
return /^var _0x[a-f0-9]+ ?\= ?\[/.test(str);
|
16
|
+
},
|
17
|
+
|
18
|
+
unpack: function (str) {
|
19
|
+
if (JavascriptObfuscator.detect(str)) {
|
20
|
+
var matches = /var (_0x[a-f\d]+) ?\= ?\[(.*?)\];/.exec(str);
|
21
|
+
if (matches) {
|
22
|
+
var var_name = matches[1];
|
23
|
+
var strings = JavascriptObfuscator._smart_split(JavascriptObfuscator._unescape(matches[2]));
|
24
|
+
var str = str.substring(matches[0].length);
|
25
|
+
for (var k in strings) {
|
26
|
+
str = str.replace(new RegExp(var_name + '\\[' + k + '\\]', 'g'), strings[k]);
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}
|
30
|
+
return str;
|
31
|
+
},
|
32
|
+
|
33
|
+
_smart_split: function(str) {
|
34
|
+
var strings = [];
|
35
|
+
var pos = 0;
|
36
|
+
while (pos < str.length) {
|
37
|
+
if (str.charAt(pos) == '"') {
|
38
|
+
// new word
|
39
|
+
var word = '';
|
40
|
+
pos += 1;
|
41
|
+
while (pos < str.length) {
|
42
|
+
if (str.charAt(pos) == '"') {
|
43
|
+
break;
|
44
|
+
}
|
45
|
+
if (str.charAt(pos) == '\\') {
|
46
|
+
word += '\\';
|
47
|
+
pos++;
|
48
|
+
}
|
49
|
+
word += str.charAt(pos);
|
50
|
+
pos++;
|
51
|
+
}
|
52
|
+
strings.push('"' + word + '"');
|
53
|
+
}
|
54
|
+
pos += 1;
|
55
|
+
}
|
56
|
+
return strings;
|
57
|
+
},
|
58
|
+
|
59
|
+
|
60
|
+
_unescape: function (str) {
|
61
|
+
// inefficient if used repeatedly or on small strings, but wonderful on single large chunk of text
|
62
|
+
for (var i = 32; i < 128; i++) {
|
63
|
+
str = str.replace(new RegExp('\\\\x' + i.toString(16), 'ig'), String.fromCharCode(i));
|
64
|
+
}
|
65
|
+
return str;
|
66
|
+
},
|
67
|
+
|
68
|
+
|
69
|
+
run_tests: function (sanity_test) {
|
70
|
+
var t = sanity_test || new SanityTest();
|
71
|
+
t.test_function(JavascriptObfuscator._smart_split, "JavascriptObfuscator._smart_split");
|
72
|
+
t.expect('', []);
|
73
|
+
t.expect('"a", "b"', ['"a"', '"b"']);
|
74
|
+
t.expect('"aaa","bbbb"', ['"aaa"', '"bbbb"']);
|
75
|
+
t.expect('"a", "b\\\""', ['"a"', '"b\\\""']);
|
76
|
+
t.test_function(JavascriptObfuscator._unescape, 'JavascriptObfuscator._unescape');
|
77
|
+
t.expect('\\x40', '@');
|
78
|
+
t.expect('\\x10', '\\x10');
|
79
|
+
t.expect('\\x1', '\\x1');
|
80
|
+
t.test_function(JavascriptObfuscator.detect, 'JavascriptObfuscator.detect');
|
81
|
+
t.expect('', false);
|
82
|
+
t.expect('abcd', false);
|
83
|
+
t.expect('var _0xaaaa', false);
|
84
|
+
t.expect('var _0xaaaa = ["a", "b"]', true);
|
85
|
+
t.expect('var _0xaaaa=["a", "b"]', true);
|
86
|
+
t.expect('var _0x1234=["a","b"]', true);
|
87
|
+
return t;
|
88
|
+
}
|
89
|
+
|
90
|
+
|
91
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2009 Einar Lielmanis
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person
|
4
|
+
obtaining a copy of this software and associated documentation
|
5
|
+
files (the "Software"), to deal in the Software without
|
6
|
+
restriction, including without limitation the rights to use,
|
7
|
+
copy, modify, merge, publish, distribute, sublicense, and/or sell
|
8
|
+
copies of the Software, and to permit persons to whom the
|
9
|
+
Software is furnished to do so, subject to the following
|
10
|
+
conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
17
|
+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
19
|
+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
20
|
+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
22
|
+
OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
|
@@ -0,0 +1,128 @@
|
|
1
|
+
//
|
2
|
+
// simple testing interface
|
3
|
+
// written by Einar Lielmanis, einar@jsbeautifier.org
|
4
|
+
//
|
5
|
+
// usage:
|
6
|
+
//
|
7
|
+
// var t = new SanityTest(function (x) { return x; }, 'my function');
|
8
|
+
// t.expect('input', 'output');
|
9
|
+
// t.expect('a', 'a');
|
10
|
+
// output_somewhere(t.results()); // good for <pre>, html safe-ish
|
11
|
+
// alert(t.results_raw()); // html unescaped
|
12
|
+
|
13
|
+
|
14
|
+
function SanityTest (func, test_name) {
|
15
|
+
|
16
|
+
var test_func = func || function (x) {
|
17
|
+
return x;
|
18
|
+
}
|
19
|
+
|
20
|
+
var test_name = test_name || '';
|
21
|
+
|
22
|
+
var n_failed = 0;
|
23
|
+
var n_succeeded = 0;
|
24
|
+
|
25
|
+
var failures = [];
|
26
|
+
|
27
|
+
this.test_function = function(func, name) {
|
28
|
+
test_func = func;
|
29
|
+
test_name = name || '';
|
30
|
+
}
|
31
|
+
|
32
|
+
|
33
|
+
this.expect = function(parameters, expected_value) {
|
34
|
+
// multi-parameter calls not supported (I don't need them now).
|
35
|
+
var result = test_func(parameters);
|
36
|
+
// proper array checking is a pain. i'll do it later, compare strings representations instead
|
37
|
+
if ((result === expected_value) || (expected_value instanceof Array && result.join(', ') == expected_value.join(', '))) {
|
38
|
+
n_succeeded += 1;
|
39
|
+
} else {
|
40
|
+
n_failed += 1;
|
41
|
+
failures.push([test_name, parameters, expected_value, result]);
|
42
|
+
}
|
43
|
+
}
|
44
|
+
|
45
|
+
|
46
|
+
this.results_raw = function() {
|
47
|
+
var results = '';
|
48
|
+
if (n_failed === 0) {
|
49
|
+
if (n_succeeded === 0) {
|
50
|
+
results = 'No tests run.';
|
51
|
+
} else {
|
52
|
+
results = 'All ' + n_succeeded + ' tests passed.';
|
53
|
+
}
|
54
|
+
} else {
|
55
|
+
for (var i = 0 ; i < failures.length; i++) {
|
56
|
+
var f = failures[i];
|
57
|
+
if (f[0]) {
|
58
|
+
f[0] = f[0] + ' ';
|
59
|
+
}
|
60
|
+
results += '---- ' + f[0] + 'input -------\n' + this.prettyprint(f[1]) + '\n';
|
61
|
+
results += '---- ' + f[0] + 'expected ----\n' + this.prettyprint(f[2]) + '\n';
|
62
|
+
results += '---- ' + f[0] + 'output ------\n' + this.prettyprint(f[3]) + '\n\n';
|
63
|
+
|
64
|
+
}
|
65
|
+
results += n_failed + ' tests failed.\n';
|
66
|
+
}
|
67
|
+
return results;
|
68
|
+
}
|
69
|
+
|
70
|
+
|
71
|
+
this.results = function() {
|
72
|
+
return this.lazy_escape(this.results_raw());
|
73
|
+
}
|
74
|
+
|
75
|
+
|
76
|
+
this.prettyprint = function(something, quote_strings) {
|
77
|
+
var type = typeof something;
|
78
|
+
switch(type.toLowerCase()) {
|
79
|
+
case 'string':
|
80
|
+
if (quote_strings) {
|
81
|
+
return "'" + something.replace("'", "\\'") + "'";
|
82
|
+
} else {
|
83
|
+
return something;
|
84
|
+
}
|
85
|
+
case 'number':
|
86
|
+
return '' + something;
|
87
|
+
case 'boolean':
|
88
|
+
return something ? 'true' : 'false';
|
89
|
+
case 'undefined':
|
90
|
+
return 'undefined';
|
91
|
+
case 'object':
|
92
|
+
if (something instanceof Array) {
|
93
|
+
var x = [];
|
94
|
+
var expected_index = 0;
|
95
|
+
for (k in something) {
|
96
|
+
if (k == expected_index) {
|
97
|
+
x.push(this.prettyprint(something[k], true));
|
98
|
+
expected_index += 1;
|
99
|
+
} else {
|
100
|
+
x.push('\n' + k + ': ' + this.prettyprint(something[k], true));
|
101
|
+
}
|
102
|
+
}
|
103
|
+
return '[' + x.join(', ') + ']';
|
104
|
+
} else {
|
105
|
+
return 'object: ' + something;
|
106
|
+
}
|
107
|
+
default:
|
108
|
+
return type + ': ' + something;
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
|
113
|
+
this.lazy_escape = function (str) {
|
114
|
+
return str.replace(/</g, '<').replace(/\>/g, '>').replace(/\n/g, '<br />');
|
115
|
+
}
|
116
|
+
|
117
|
+
|
118
|
+
this.log = function () {
|
119
|
+
if (window.console) {
|
120
|
+
if (console.firebug) {
|
121
|
+
console.log.apply(console, Array.prototype.slice.call(arguments));
|
122
|
+
} else {
|
123
|
+
console.log.call(console, Array.prototype.slice.call(arguments));
|
124
|
+
}
|
125
|
+
}
|
126
|
+
};
|
127
|
+
|
128
|
+
}
|