grat 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}
|