js2 0.0.10 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Manifest +42 -0
- data/README.md +65 -0
- data/Rakefile +19 -35
- data/bin/js2 +80 -66
- data/config/js2.yml +2 -0
- data/js2.gemspec +33 -0
- data/lib/js2/{haml_parser.rb → parser/haml.rb} +2 -2
- data/lib/js2/{haml_engine.rb → parser/haml_engine.rb} +1 -1
- data/lib/js2/parser/lexer.rb +37 -0
- data/lib/js2/{parser.rb → parser/tokenizer.rb} +157 -143
- data/lib/js2/{replace.rb → ragel/helper.rb} +16 -5
- data/lib/js2/ragel/tokenizer.rl +561 -0
- data/lib/js2/{tokenizer.rl.erb → ragel/tokenizer.rl.erb} +12 -19
- data/lib/js2/standard/factory.rb +289 -0
- data/lib/js2/standard/node.rb +75 -0
- data/lib/js2/util/compilation.rb +77 -0
- data/lib/js2/util/config.rb +84 -0
- data/lib/js2/util/exec.rb +34 -0
- data/lib/js2/util/file_handler.rb +73 -0
- data/lib/js2/{js2bootstrap.js2 → util/js2bootstrap.js2} +12 -68
- data/lib/js2/util/processor.rb +88 -0
- data/lib/js2/util/rdoc.rb +35 -0
- data/lib/js2/{sel_decorator.rb → util/sel_decorator.rb} +11 -1
- data/lib/js2.rb +22 -45
- data/test/compiled/bar.js +3 -0
- data/test/compiled/basic.comp.js +31 -0
- data/test/compiled/basic.js +27 -0
- data/test/compiled/foo.js +3 -0
- data/test/fixtures/bar.js2 +3 -0
- data/test/fixtures/basic.js2 +27 -0
- data/test/fixtures/basic.js2.haml +4 -0
- data/test/fixtures/basic.js2.yml +5 -0
- data/test/fixtures/curry.js2 +5 -0
- data/test/fixtures/foo.js2 +3 -0
- data/test/fixtures/member.js2 +14 -0
- data/test/fixtures/private.js2 +5 -0
- data/test/fixtures/property.js2 +4 -0
- data/test/test_helper.rb +25 -0
- data/test/test_js2.rb +43 -0
- data/wiki/features.md +106 -0
- data/wiki/installation.md +53 -0
- metadata +89 -83
- data/Changelog +0 -33
- data/History.txt +0 -4
- data/Manifest.txt +0 -35
- data/PostInstall.txt +0 -7
- data/README +0 -69
- data/README.rdoc +0 -69
- data/README.txt +0 -69
- data/examples/js2.yml +0 -8
- data/examples/test.yml +0 -5
- data/lib/javascript/sel_marker.js2 +0 -150
- data/lib/javascript/test.js2 +0 -73
- data/lib/js2/config.rb +0 -39
- data/lib/js2/daemon.rb +0 -35
- data/lib/js2/file_handler.rb +0 -91
- data/lib/js2/foo.js2.haml +0 -3
- data/lib/js2/js2.js +0 -110
- data/lib/js2/processor.rb +0 -112
- data/lib/js2/test/selenium.rb +0 -119
- data/lib/js2/test/selenium_element.rb +0 -234
- data/lib/js2/test/selenium_helper.rb +0 -27
- data/lib/js2/tree.rb +0 -351
- data/lib/js2/universe.rb +0 -123
- data/lib/tasks/js2.rake +0 -9
- data/website/index.txt +0 -86
- /data/{LICENSE → lib/js2/standard/class_node.rb} +0 -0
@@ -74,20 +74,21 @@
|
|
74
74
|
this[name] = member;
|
75
75
|
},
|
76
76
|
|
77
|
-
'
|
77
|
+
'setHTMLAssets': function (hash) {
|
78
78
|
// create temp class
|
79
79
|
var tempClass = function () {};
|
80
80
|
|
81
|
-
// look for super
|
81
|
+
// look for super htmlAssets
|
82
82
|
var par = this.parent;
|
83
83
|
if (par) {
|
84
|
-
var parCache = par.prototype.
|
84
|
+
var parCache = par.prototype.htmlAssets;
|
85
85
|
if (parCache) tempClass.prototype = parCache;
|
86
86
|
}
|
87
87
|
|
88
|
-
var
|
89
|
-
for (var k in hash)
|
90
|
-
this.oo('member', 'htmlCache',
|
88
|
+
var htmlAssets = new tempClass();
|
89
|
+
for (var k in hash) htmlAssets[k] = hash[k];
|
90
|
+
this.oo('member', 'htmlCache', htmlAssets);
|
91
|
+
this.oo('member', 'htmlAssets', htmlAssets);
|
91
92
|
},
|
92
93
|
|
93
94
|
'super': function (member) {
|
@@ -199,66 +200,6 @@
|
|
199
200
|
|
200
201
|
})(window);
|
201
202
|
|
202
|
-
class JS2.Observer {
|
203
|
-
function initialize (owner) {
|
204
|
-
this.lookupBefore = {};
|
205
|
-
this.lookupAfter = {};
|
206
|
-
|
207
|
-
this.replaced = {};
|
208
|
-
this.replacedValues = {};
|
209
|
-
}
|
210
|
-
|
211
|
-
function replaceFunction (owner, eventName) {
|
212
|
-
if (this.replaced[eventName]) return;
|
213
|
-
|
214
|
-
this.replacedValues[eventName] = owner[eventName];
|
215
|
-
this.replaced[eventName] = true;
|
216
|
-
owner[eventName] = this.getTrigger(eventName);
|
217
|
-
}
|
218
|
-
|
219
|
-
function trigger (owner, eventName, args) {
|
220
|
-
var beforeChain = this.lookupBefore[eventName];
|
221
|
-
if (beforeChain) this.executeChain(beforeChain, args);
|
222
|
-
|
223
|
-
var funct = this.replacedValues[eventName];
|
224
|
-
if (funct) funct.apply(owner, args);
|
225
|
-
|
226
|
-
var afterChain = this.lookupAfter[eventName];
|
227
|
-
if (afterChain) this.executeChain(afterChain, args);
|
228
|
-
}
|
229
|
-
|
230
|
-
function addListener (eventName, funct, before) {
|
231
|
-
var lookup = before ? this.lookupBefore : this.lookupAfter;
|
232
|
-
|
233
|
-
var chain = lookup[eventName] = lookup[eventName] || [];
|
234
|
-
chain.push(funct);
|
235
|
-
}
|
236
|
-
|
237
|
-
private
|
238
|
-
|
239
|
-
function getTrigger (eventName) {
|
240
|
-
return function () { this.__observer.trigger(this, eventName, arguments); };
|
241
|
-
}
|
242
|
-
|
243
|
-
function executeChain (chain, args) {
|
244
|
-
foreach (var f:i in chain) if (f) f.apply(this, args);
|
245
|
-
}
|
246
|
-
}
|
247
|
-
|
248
|
-
module JS2.Observable {
|
249
|
-
function addListener (eventName, funct, before) {
|
250
|
-
if (! this.__observer) this.__observer = new Factual.Core.Observer();
|
251
|
-
|
252
|
-
var id = this.__observer.addListener(eventName, funct, before);
|
253
|
-
this.__observer.replaceFunction(this, eventName);
|
254
|
-
return id;
|
255
|
-
}
|
256
|
-
|
257
|
-
function triggerEvent (eventName, args) {
|
258
|
-
if (this.__observer) this.__observer.trigger(this, eventName, args);
|
259
|
-
}
|
260
|
-
}
|
261
|
-
|
262
203
|
|
263
204
|
class JS2.App.Notifier {
|
264
205
|
var autoInc = 1;
|
@@ -340,7 +281,6 @@ class JS2.App.Notifier {
|
|
340
281
|
|
341
282
|
|
342
283
|
class JS2.App {
|
343
|
-
include JS2.Observer;
|
344
284
|
|
345
285
|
function start (options) {
|
346
286
|
// hack to get notifier
|
@@ -401,7 +341,11 @@ class JS2.App {
|
|
401
341
|
if (!config['class']) alert("Invalid class defined for " + name + ':' + config['class']);
|
402
342
|
var klass = JS2.OO.get(config['class']);
|
403
343
|
|
404
|
-
|
344
|
+
if (klass) {
|
345
|
+
components[config.name] = new klass();
|
346
|
+
} else if (console) {
|
347
|
+
console.log('class "' + config.name + '" was not found."');
|
348
|
+
}
|
405
349
|
this.register(components[config.name]);
|
406
350
|
}
|
407
351
|
|
@@ -0,0 +1,88 @@
|
|
1
|
+
class JS2::Util::Processor
|
2
|
+
attr_accessor :errors
|
3
|
+
|
4
|
+
def initialize (config)
|
5
|
+
@file_handler = config.file_handler
|
6
|
+
@lexer = config.lexer
|
7
|
+
@factory = config.node_factory
|
8
|
+
@haml_engine = config.haml_engine
|
9
|
+
@haml_parser = JS2::Parser::Haml.new(config.haml_engine, config.haml_vars)
|
10
|
+
|
11
|
+
@lookup = Hash.new
|
12
|
+
|
13
|
+
@config = config
|
14
|
+
end
|
15
|
+
|
16
|
+
def process!
|
17
|
+
@errors = []
|
18
|
+
|
19
|
+
ret = { :processed => [], :changed => [], :errors => @errors, :klasses => [], :pages => [] }
|
20
|
+
ret[:changed] = @file_handler.needs_update
|
21
|
+
return ret unless ret[:changed].any?
|
22
|
+
|
23
|
+
pages = ret[:pages]
|
24
|
+
klasses = Hash.new
|
25
|
+
|
26
|
+
@file_handler.get_files(:js2).each do |file|
|
27
|
+
begin
|
28
|
+
page = @lexer.parse_file(file, @factory)
|
29
|
+
page.klasses.each do |k|
|
30
|
+
(klasses[k.name] ||= []) << page.file
|
31
|
+
end
|
32
|
+
|
33
|
+
ret[:klasses] += page.klasses
|
34
|
+
|
35
|
+
pages << page
|
36
|
+
|
37
|
+
outfile = @file_handler.outfile(page.file)
|
38
|
+
outdir = File.dirname(outfile)
|
39
|
+
|
40
|
+
FileUtils.mkdir_p(outdir)
|
41
|
+
File.open(@file_handler.outfile(page.file), 'w') { |f| f << page.to_s() }
|
42
|
+
rescue Exception => e
|
43
|
+
@errors << [ "Can't compile #{file}", e ]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
js2_file = File.dirname(__FILE__) + '/js2bootstrap.js2'
|
48
|
+
js2_page = @lexer.parse_file(js2_file, @factory)
|
49
|
+
out_file = @file_handler.out_dir + '/js2bootstrap.js'
|
50
|
+
FileUtils.mkdir_p(@file_handler.out_dir)
|
51
|
+
File.open(out_file, 'w') { |f| f << js2_page.to_s() }
|
52
|
+
|
53
|
+
@file_handler.get_files(:haml).each do |file|
|
54
|
+
begin
|
55
|
+
result = @haml_parser.parse(file)
|
56
|
+
result.keys.each do |klass_name|
|
57
|
+
hash = result[klass_name]
|
58
|
+
|
59
|
+
out = []
|
60
|
+
hash.keys.sort.each do |key|
|
61
|
+
out << %{"#{key}":#{hash[key]}}
|
62
|
+
end
|
63
|
+
|
64
|
+
if files = klasses[klass_name]
|
65
|
+
outfile = @file_handler.outfile(files.first)
|
66
|
+
File.open(outfile, 'a') { |f| f << "#{klass_name}.oo('setHTMLAssets', {#{out.join(',')}});" }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
rescue Exception => e
|
70
|
+
@errors << [ "Can't compile #{file}", e ]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
@file_handler.get_files(:yml).each do |file|
|
75
|
+
begin
|
76
|
+
comps = JS2::Util::Compilation.parse(file, @file_handler)
|
77
|
+
comps.each do |c|
|
78
|
+
c.compile(klasses, errors)
|
79
|
+
end
|
80
|
+
rescue Exception => e
|
81
|
+
@errors << [ "Can't compile #{file}", e ]
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
return ret
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class JS2::Util::Rdoc
|
2
|
+
|
3
|
+
def self.build (pages, file_handler)
|
4
|
+
|
5
|
+
pages.each do |p|
|
6
|
+
str = ''
|
7
|
+
p.klasses.each do |k|
|
8
|
+
if k.comment
|
9
|
+
str << k.comment.clean.gsub(/^/, "# ") if k.comment
|
10
|
+
end
|
11
|
+
str << "class #{k.name.gsub(/\./, '::')}\n"
|
12
|
+
puts k.name
|
13
|
+
|
14
|
+
k.methods.each_with_index do |m,i|
|
15
|
+
puts ' - ' + m.name
|
16
|
+
str << m.comment.clean.gsub(/^/, " # ") if m.comment
|
17
|
+
str << " def #{m.name} (#{m.args})\n#{m.to_s.gsub(/^/, ' #')} end\n"
|
18
|
+
end
|
19
|
+
|
20
|
+
str << "end\n"
|
21
|
+
end
|
22
|
+
|
23
|
+
outfile = file_handler.docfile(p.file)
|
24
|
+
outdir = File.dirname(outfile)
|
25
|
+
FileUtils.mkdir_p(outdir)
|
26
|
+
File.open(outfile, 'w') { |f| f << str }
|
27
|
+
end
|
28
|
+
|
29
|
+
# TODO make this portable
|
30
|
+
jamis = File.dirname(__FILE__) + '/jamis.rb'
|
31
|
+
system("rdoc --template #{jamis} --extension js=rb #{file_handler.doc_dir}")
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'json'
|
2
2
|
|
3
|
-
class JS2::SelDecorator
|
3
|
+
class JS2::Util::SelDecorator
|
4
4
|
|
5
5
|
def initialize ()
|
6
6
|
@references = Hash.new
|
@@ -12,6 +12,16 @@ class JS2::SelDecorator
|
|
12
12
|
@in_class = false
|
13
13
|
end
|
14
14
|
|
15
|
+
def decorate (str, node)
|
16
|
+
if node.is_a?(JS2::Standard::ClassNode)
|
17
|
+
return translate(str, nil, true)
|
18
|
+
elsif node.is_a?(JS2::Standard::StuffNode)
|
19
|
+
return translate(str, nil, false)
|
20
|
+
else
|
21
|
+
return str
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
15
25
|
def translate (str, scope = nil, in_class = false)
|
16
26
|
@scope = scope
|
17
27
|
@in_class = in_class
|
data/lib/js2.rb
CHANGED
@@ -1,55 +1,32 @@
|
|
1
|
-
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
-
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
-
|
4
|
-
|
5
1
|
module JS2
|
6
|
-
VERSION = '0.0.10'
|
7
|
-
module Test
|
8
|
-
end
|
9
2
|
end
|
10
3
|
|
11
|
-
|
12
|
-
|
13
|
-
require 'js2/processor'
|
14
|
-
require 'js2/sel_decorator'
|
15
|
-
|
16
|
-
require 'js2/tree'
|
17
|
-
require 'js2/parser'
|
18
|
-
require 'js2/file_handler'
|
19
|
-
require 'js2/universe'
|
20
|
-
|
21
|
-
require 'js2/test/selenium'
|
22
|
-
require 'js2/test/selenium_element'
|
23
|
-
require 'js2/test/selenium_helper'
|
24
|
-
|
25
|
-
$:.unshift File.dirname(__FILE__)
|
4
|
+
module JS2::Parser
|
5
|
+
end
|
26
6
|
|
27
|
-
|
28
|
-
require 'rubygems'
|
29
|
-
require 'json'
|
30
|
-
rescue Exception => e
|
31
|
-
raise "JS2 Requires RubyGems and JSON gems"
|
7
|
+
module JS2::Standard
|
32
8
|
end
|
33
9
|
|
34
|
-
|
35
|
-
require 'haml'
|
36
|
-
require 'sass'
|
37
|
-
require 'js2/haml_parser'
|
38
|
-
require 'js2/haml_engine'
|
39
|
-
rescue Exception => e
|
40
|
-
puts "HAML is not installed deactivating support"
|
10
|
+
module JS2::Util
|
41
11
|
end
|
42
12
|
|
43
13
|
|
44
|
-
|
45
|
-
# for haml filter
|
46
|
-
module JS2
|
47
|
-
include Haml::Filters::Base
|
14
|
+
dir = File.dirname(__FILE__)
|
48
15
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
16
|
+
# compiling stuff
|
17
|
+
require "#{dir}/js2/parser/lexer"
|
18
|
+
require "#{dir}/js2/parser/tokenizer"
|
19
|
+
require "#{dir}/js2/parser/haml_engine"
|
20
|
+
require "#{dir}/js2/parser/haml"
|
21
|
+
|
22
|
+
# standard suite
|
23
|
+
require "#{dir}/js2/standard/node"
|
24
|
+
require "#{dir}/js2/standard/class_node"
|
25
|
+
require "#{dir}/js2/standard/factory"
|
26
|
+
|
27
|
+
# util stuff
|
28
|
+
require "#{dir}/js2/util/processor"
|
29
|
+
require "#{dir}/js2/util/file_handler"
|
30
|
+
require "#{dir}/js2/util/config"
|
31
|
+
require "#{dir}/js2/util/compilation"
|
32
|
+
require "#{dir}/js2/util/rdoc"
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
* Comments
|
4
|
+
* This is a comment
|
5
|
+
*/
|
6
|
+
JS2.OO.createClass("Test.Foo"); (function (K,Package) {var self=K; var _super=JS2.OO['super'];
|
7
|
+
K.oo('accessor', [ 'testAcc' ]);
|
8
|
+
K.oo('property', [ 'testProp' ]);
|
9
|
+
|
10
|
+
/*
|
11
|
+
* hello
|
12
|
+
*/
|
13
|
+
|
14
|
+
K.oo('method', "testFunct", function () {
|
15
|
+
|
16
|
+
});
|
17
|
+
|
18
|
+
K.oo('method', "testForeach", function () {
|
19
|
+
for (var i=0,ele,i__arr=elements,i__len=i__arr.length; (ele=i__arr[i]) || i<i__len; i++){
|
20
|
+
for (var i=0,yo,i__arr=yos,i__len=i__arr.length; (yo=i__arr[i]) || i<i__len; i++){
|
21
|
+
|
22
|
+
}
|
23
|
+
|
24
|
+
}
|
25
|
+
});
|
26
|
+
|
27
|
+
})(Test.Foo, Test);Test.Foo.oo('setHTMLCache', {"main":function(){return "<div class='hello'>world</div>"}});JS2.OO.createClass("Bar"); (function (K,Package) {var self=K; var _super=JS2.OO['super'];
|
28
|
+
|
29
|
+
})(Bar, null);JS2.OO.createClass("Foo"); (function (K,Package) {var self=K; var _super=JS2.OO['super'];
|
30
|
+
|
31
|
+
})(Foo, null);
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
* Comments
|
4
|
+
* This is a comment
|
5
|
+
*/
|
6
|
+
JS2.OO.createClass("Test.Foo"); (function (K,Package) {var self=K; var _super=JS2.OO['super'];
|
7
|
+
K.oo('accessor', [ 'testAcc' ]);
|
8
|
+
K.oo('property', [ 'testProp' ]);
|
9
|
+
|
10
|
+
/*
|
11
|
+
* hello
|
12
|
+
*/
|
13
|
+
|
14
|
+
K.oo('method', "testFunct", function () {
|
15
|
+
|
16
|
+
});
|
17
|
+
|
18
|
+
K.oo('method', "testForeach", function () {
|
19
|
+
for (var i=0,ele,i__arr=elements,i__len=i__arr.length; (ele=i__arr[i]) || i<i__len; i++){
|
20
|
+
for (var i=0,yo,i__arr=yos,i__len=i__arr.length; (yo=i__arr[i]) || i<i__len; i++){
|
21
|
+
|
22
|
+
}
|
23
|
+
|
24
|
+
}
|
25
|
+
});
|
26
|
+
|
27
|
+
})(Test.Foo, Test);Test.Foo.oo('setHTMLCache', {"main":function(){return "<div class='hello'>world</div>"}});
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
/*
|
3
|
+
* Comments
|
4
|
+
* This is a comment
|
5
|
+
*/
|
6
|
+
class Test.Foo {
|
7
|
+
accessor testAcc;
|
8
|
+
property testProp;
|
9
|
+
|
10
|
+
/*
|
11
|
+
* hello
|
12
|
+
*/
|
13
|
+
|
14
|
+
function testFunct () {
|
15
|
+
|
16
|
+
}
|
17
|
+
|
18
|
+
function testForeach () {
|
19
|
+
foreach (var ele:i in elements) {
|
20
|
+
foreach (var yo:i in yos) {
|
21
|
+
|
22
|
+
}
|
23
|
+
|
24
|
+
}
|
25
|
+
}
|
26
|
+
|
27
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class TestMember {
|
2
|
+
|
3
|
+
var WIDTH = 84;
|
4
|
+
var MENU_ACTIONS = [ 'sortData', 'sortData', 'hideColumn' ];
|
5
|
+
|
6
|
+
var arr = [ 'hello', 'world' ];
|
7
|
+
var one, two, three;
|
8
|
+
var foo = {};
|
9
|
+
var bar;
|
10
|
+
var foo1 = 'hello';
|
11
|
+
var bar1 = {
|
12
|
+
hello: "world"
|
13
|
+
};
|
14
|
+
}
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
require 'test/unit'
|
3
|
+
require File.dirname(__FILE__) + '/../lib/js2'
|
4
|
+
JS2_TEST_DIR = File.dirname(__FILE__)
|
5
|
+
|
6
|
+
class Test::Unit::TestCase
|
7
|
+
def js2_fixture (name)
|
8
|
+
return JS2_TEST_DIR + "/fixtures/#{name}.js2"
|
9
|
+
end
|
10
|
+
|
11
|
+
def js_read_fixture (name)
|
12
|
+
return File.read(JS2_TEST_DIR + "/fixtures/#{name}.js").chomp
|
13
|
+
end
|
14
|
+
|
15
|
+
def compare_dir (dir1, dir2)
|
16
|
+
files1 = Dir["#{dir1}/*.js"]
|
17
|
+
|
18
|
+
files1.each do |file|
|
19
|
+
content1 = File.read(file)
|
20
|
+
file2 = file.sub(/^#{dir1}/, dir2)
|
21
|
+
content2 = File.read(file2)
|
22
|
+
assert_equal(content1.chomp, content2.chomp, "Comparing #{file} and #{file2}")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/test/test_js2.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class TestJs2 < Test::Unit::TestCase
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@lexer = JS2::Parser::Lexer.new
|
7
|
+
@factory = JS2::Standard::Factory.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_processor
|
11
|
+
|
12
|
+
config = JS2::Util::Config.new
|
13
|
+
fh = config.file_handler
|
14
|
+
fh.js2_dir = './test/fixtures'
|
15
|
+
fh.out_dir = './test/out'
|
16
|
+
fh.haml_dir = './test/fixtures'
|
17
|
+
|
18
|
+
system("rm -rf #{fh.out_dir}")
|
19
|
+
|
20
|
+
processor = JS2::Util::Processor.new(config)
|
21
|
+
ret1 = processor.process!
|
22
|
+
ret2 = processor.process!
|
23
|
+
assert_equal(ret2[:changed].any?, false)
|
24
|
+
|
25
|
+
compare_dir(fh.out_dir, './test/compiled')
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_rdoc
|
29
|
+
|
30
|
+
config = JS2::Util::Config.new
|
31
|
+
fh = config.file_handler
|
32
|
+
fh.js2_dir = './test/fixtures'
|
33
|
+
fh.out_dir = './test/out'
|
34
|
+
fh.haml_dir = './test/fixtures'
|
35
|
+
fh.doc_dir = './test/doc'
|
36
|
+
system("rm -rf #{fh.out_dir}")
|
37
|
+
|
38
|
+
processor = JS2::Util::Processor.new(config)
|
39
|
+
ret = processor.process!
|
40
|
+
JS2::Util::Rdoc.build(ret[:pages], fh)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/wiki/features.md
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
## Object Oriented
|
2
|
+
|
3
|
+
### Class Definition
|
4
|
+
|
5
|
+
> class Foo {
|
6
|
+
> function method () {
|
7
|
+
> }
|
8
|
+
> }
|
9
|
+
|
10
|
+
### Inheritance
|
11
|
+
|
12
|
+
> class Vehicle {
|
13
|
+
> function drive () {
|
14
|
+
> alert('drive');
|
15
|
+
> }
|
16
|
+
> }
|
17
|
+
>
|
18
|
+
> class Car extends Vehicle {
|
19
|
+
> }
|
20
|
+
|
21
|
+
### Getters and Setters
|
22
|
+
|
23
|
+
> class Duck {
|
24
|
+
> property color; // adds getColor() and setColor()
|
25
|
+
> }
|
26
|
+
|
27
|
+
### Mixins (Ruby's multiple inheritance solution)
|
28
|
+
|
29
|
+
> module Flyable {
|
30
|
+
> function fly () {
|
31
|
+
> alert('Flying!');
|
32
|
+
> }
|
33
|
+
> }
|
34
|
+
>
|
35
|
+
> class Duck {
|
36
|
+
> include Flyable;
|
37
|
+
> }
|
38
|
+
|
39
|
+
### AOP (Aspect Oriented Programming)
|
40
|
+
|
41
|
+
> var me = new Human();
|
42
|
+
> me.addListener('walk', function () { alert('walking') });
|
43
|
+
|
44
|
+
### Static Methods
|
45
|
+
|
46
|
+
> class Human {
|
47
|
+
> static function getCount () {
|
48
|
+
> return this.count;
|
49
|
+
> }
|
50
|
+
> static function create () {
|
51
|
+
> if (this.count) {
|
52
|
+
> this.count++;
|
53
|
+
> } else {
|
54
|
+
> this.count = 1;
|
55
|
+
> }
|
56
|
+
> return new this();
|
57
|
+
> }
|
58
|
+
> }
|
59
|
+
|
60
|
+
## Syntactic Sugar
|
61
|
+
|
62
|
+
### Currying
|
63
|
+
|
64
|
+
> var nonScoped = [ ... lots of data .. ];
|
65
|
+
> var submitBtn = new Button();
|
66
|
+
> var ele = document.getElementById('submitBtn');
|
67
|
+
> ele.onClick = curry (evt) with (submitBtn) {
|
68
|
+
> submitBtn.click();
|
69
|
+
> };
|
70
|
+
|
71
|
+
### Foreach
|
72
|
+
|
73
|
+
> foreach (var item in array) alert(item);
|
74
|
+
> foreach (var item:i in array) alert(i + ' is ' + item);
|
75
|
+
> curry (arg1, arg2) with (scopeVar1, scopeVar2) { };
|
76
|
+
|
77
|
+
##Other Features
|
78
|
+
|
79
|
+
### Templating in HAML/SASS (useful for ajax applications)
|
80
|
+
|
81
|
+
> //--- in uiBuilder.js2.haml
|
82
|
+
> UIBuilder
|
83
|
+
> button(name)
|
84
|
+
> %div.button= "#name#"
|
85
|
+
>
|
86
|
+
> //--- in uiBuilder.js2
|
87
|
+
> class UIBuilder {
|
88
|
+
> function getButton (name) {
|
89
|
+
> this.htmlCache.button(name);
|
90
|
+
> }
|
91
|
+
> }
|
92
|
+
>
|
93
|
+
> //--- in page.html
|
94
|
+
> var ui = new UIBuilder();
|
95
|
+
> var ele = document.getElementById('buttonContainer');
|
96
|
+
> ele.innerHTML = ui.button('my button');
|
97
|
+
|
98
|
+
### Selenium Testing Integration
|
99
|
+
|
100
|
+
... Coming soon ...
|
101
|
+
|
102
|
+
This is a little bit harder to explain, and is only for Ruby Selenium RC developers. The idea is that complex javascript applications usually reference most important DOM elements in javascript for things such as altering html or adding event handlers. What selenium integration in js2 means is that one can use annotations in his/her code to "mark" DOM elements instead of using xpaths.
|
103
|
+
|
104
|
+
One of the pain points in Selenium testing is that the xpaths are always changing with each iteration of the view layer. In a complex javascript application, one has to maintain the references to DOM objects in javascript anyway, so this would be an easier way to maintain the Selenium references to the DOM.
|
105
|
+
|
106
|
+
While this is available, its not quite ready for public consumption.
|