js2 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Changelog ADDED
File without changes
data/History.txt ADDED
@@ -0,0 +1,4 @@
1
+ === 0.0.1 2009-11-20
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
data/LICENSE ADDED
File without changes
data/Manifest.txt ADDED
@@ -0,0 +1,43 @@
1
+ Changelog
2
+ History.txt
3
+ LICENSE
4
+ Manifest.txt
5
+ PostInstall.txt
6
+ README
7
+ README.rdoc
8
+ Rakefile
9
+ examples/js2.yml
10
+ examples/test.yml
11
+ lib/javascript/sel_marker.js2
12
+ lib/javascript/test.js2
13
+ lib/js2.rb
14
+ lib/js2/ast/class_node.rb
15
+ lib/js2/ast/comment_node.rb
16
+ lib/js2/ast/haml_node.rb
17
+ lib/js2/ast/include_node.rb
18
+ lib/js2/ast/inherited_node.rb
19
+ lib/js2/ast/member_node.rb
20
+ lib/js2/ast/method_node.rb
21
+ lib/js2/ast/module_node.rb
22
+ lib/js2/ast/node.rb
23
+ lib/js2/ast/nodes.rb
24
+ lib/js2/ast/stuff_node.rb
25
+ lib/js2/config.rb
26
+ lib/js2/daemon.rb
27
+ lib/js2/decorator/app.rb
28
+ lib/js2/decorator/cleanser.rb
29
+ lib/js2/decorator/standard.rb
30
+ lib/js2/decorator/test.rb
31
+ lib/js2/parser/fast.rb
32
+ lib/js2/parser/haml.rb
33
+ lib/js2/process/file_handler.rb
34
+ lib/js2/process/haml_engine.rb
35
+ lib/js2/process/universe.rb
36
+ lib/js2/processor.rb
37
+ lib/js2/test/selenium.rb
38
+ lib/js2/test/selenium_element.rb
39
+ lib/js2/test/selenium_helper.rb
40
+ lib/tasks/js2.rake
41
+ meta/c_tokenizer.rl.erb
42
+ meta/replace.rb
43
+ bin/js2
data/PostInstall.txt ADDED
@@ -0,0 +1,7 @@
1
+
2
+ For more information on js2, see http://js2.rubyforge.org
3
+
4
+ NOTE: Change this information in PostInstall.txt
5
+ You can also delete it if you don't want it.
6
+
7
+
data/README ADDED
File without changes
data/README.rdoc ADDED
@@ -0,0 +1,48 @@
1
+ = js2
2
+
3
+ * http://github.com/#{github_username}/#{project_name}
4
+
5
+ == DESCRIPTION:
6
+
7
+ FIX (describe your package)
8
+
9
+ == FEATURES/PROBLEMS:
10
+
11
+ * FIX (list of features or problems)
12
+
13
+ == SYNOPSIS:
14
+
15
+ FIX (code sample of usage)
16
+
17
+ == REQUIREMENTS:
18
+
19
+ * FIX (list of requirements)
20
+
21
+ == INSTALL:
22
+
23
+ * FIX (sudo gem install, anything else)
24
+
25
+ == LICENSE:
26
+
27
+ (The MIT License)
28
+
29
+ Copyright (c) 2009 FIXME full name
30
+
31
+ Permission is hereby granted, free of charge, to any person obtaining
32
+ a copy of this software and associated documentation files (the
33
+ 'Software'), to deal in the Software without restriction, including
34
+ without limitation the rights to use, copy, modify, merge, publish,
35
+ distribute, sublicense, and/or sell copies of the Software, and to
36
+ permit persons to whom the Software is furnished to do so, subject to
37
+ the following conditions:
38
+
39
+ The above copyright notice and this permission notice shall be
40
+ included in all copies or substantial portions of the Software.
41
+
42
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
43
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
44
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
45
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
46
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
47
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
48
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ require 'rubygems'
2
+ gem 'hoe', '>= 2.1.0'
3
+ require 'hoe'
4
+ require 'fileutils'
5
+ require './lib/js2'
6
+
7
+ Hoe.plugin :newgem
8
+ # Hoe.plugin :website
9
+ # Hoe.plugin :cucumberfeatures
10
+
11
+ # Generate all the Rake tasks
12
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
13
+ $hoe = Hoe.spec 'js2' do
14
+ self.developer 'Jeff Su', 'me@jeffsu.com'
15
+ self.rubyforge_name = self.name
16
+ # self.extra_deps = [['activesupport','>= 2.0.2']]
17
+
18
+ end
19
+
20
+ require 'newgem/tasks'
21
+ Dir['tasks/**/*.rake'].each { |t| load t }
22
+
23
+
24
+ task :default => [ :build_ragel, :test ] do
25
+ end
26
+
27
+ task :build_ragel do
28
+ puts "build_ragel"
29
+ system("cd meta/; ruby replace.rb; cd ../; ragel -C meta/final_tokenizer.rl; mv meta/final_tokenizer.c lib/js2/parser/fast.rb")
30
+ end
31
+
32
+ task :test do
33
+ puts "run test"
34
+ system("ruby test/test.rb")
35
+ end
36
+
37
+ namespace :js2 => :envionment do
38
+ task :build do
39
+ p = JS2::Processor.processor_from_file(RAILS_ROOT + '/config/js2.yml', RAILS_ENV)
40
+ p.write_files
41
+ end
42
+ end
data/bin/js2 ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+
5
+ require 'rubygems'
6
+ require 'js2'
7
+
8
+ options = Hash.new
9
+
10
+ usage = "Usage: js2 [options] <dir-with-js2>"
11
+ op = OptionParser.new do |opts|
12
+ opts.banner = usage
13
+
14
+ opts.on("--js2-haml-dir DIR", "Directory with js2.haml files") do |haml|
15
+ options[:js2_haml_dir] = haml
16
+ end
17
+
18
+ opts.on("--out-dir DIR", "Directory of js2 -> js output") do |out|
19
+ options[:write_dir] = out
20
+ end
21
+
22
+ opts.on("-d", "--daemonize") do |d|
23
+ options[:daemonize] = true
24
+ end
25
+
26
+ opts.on('-h', "--help", "Help Screen") do
27
+ puts opts
28
+ exit
29
+ end
30
+ end
31
+
32
+ begin
33
+ op.parse!(ARGV)
34
+ rescue OptionParser::ParseError => e
35
+ puts op
36
+ end
37
+
38
+ dir = ARGV.pop
39
+
40
+ unless dir
41
+ puts op
42
+ exit
43
+ end
44
+
45
+
46
+ config = JS2::Config.new
47
+
48
+ config.js2_dir = dir
49
+ config.js2_haml_dir = options[:js2_haml_dir] || dir
50
+ config.write_dir = options[:write_dir] || dir
51
+
52
+ p = JS2::Processor.get(config)
53
+ if options[:daemonize]
54
+ d = JS2::Daemon.new(p)
55
+ d.run do
56
+ "Recompiled at #{Time.now}"
57
+ sleep 0.5
58
+ end
59
+ else
60
+ p.write_files
61
+ end
data/examples/js2.yml ADDED
@@ -0,0 +1,8 @@
1
+ devlopment:
2
+ test_mode: true
3
+ js2_dir: './js2'
4
+ js2_haml_dir: './js2'
5
+ write_dir: './javascripts/public'
6
+ haml_dir: './app/views'
7
+ reference_dir: './spec/js2refs'
8
+ haml_engine_class: 'Sci::Javascript::HamlEngine'
data/examples/test.yml ADDED
@@ -0,0 +1,5 @@
1
+ test_mode: true
2
+ js2_dir: './test/js2'
3
+ js2_haml_dir: './test/js2'
4
+ write_dir: './test/js'
5
+ reference_dir: './test/refs'
@@ -0,0 +1,139 @@
1
+ class JS2.SelMarker {
2
+
3
+ function initialize () {
4
+ this.scopes = {};
5
+ this.children = {};
6
+ this.selectors = {};
7
+ this.normalized = false;
8
+
9
+ // keep track of all the handlers
10
+ JS2.SEL_TRACKER.idCount = JS2.SEL_TRACKER.idCount || 0;
11
+ JS2.SEL_TRACKER.idCount++;
12
+ JS2.SEL_TRACKER[JS2.SEL_TRACKER.idCount] = this;
13
+ }
14
+
15
+ function newChild (namespace) {
16
+ if (! this.children[namespace]) this.children[namespace] = new JS2.SelMarker();
17
+ return this.children[namespace];
18
+ }
19
+
20
+ function addVal (scope, key, val, selector) {
21
+ this.normalized = false;
22
+ if (! this.scopes[scope]) {
23
+ this.scopes[scope] = {};
24
+ this.selectors[scope] = {};
25
+ }
26
+ this.scopes[scope][key] = val;
27
+ this.selectors[scope][key] = selector;
28
+ }
29
+
30
+ function appendVal (scope, key, val, selector) {
31
+ this.normalized = false;
32
+ if (! this.scopes[scope]) {
33
+ this.scopes[scope] = {};
34
+ this.selectors[scope] = {};
35
+ }
36
+ if (! this.scopes[scope][key]) {
37
+ this.scopes[scope][key] = [];
38
+ this.selectors[scope][key] = [];
39
+ }
40
+ this.scopes[scope][key].push(val);
41
+ this.selectors[scope][key].push(selector);
42
+ }
43
+
44
+ function getRawVal (scope, key) {
45
+ this.normalize();
46
+ return this.scopes[scope][key];
47
+ }
48
+
49
+ function getVal (scope, key, idx) {
50
+ this.normalize();
51
+ if (idx === undefined) {
52
+ var val = this.scopes[scope][key];
53
+ var sel = this.selectors[scope][key];
54
+ if (val.find && sel) val = val.find(sel);
55
+ return (val.jquery && val.length == 1) ? val[0] : val;
56
+ } else {
57
+ var val = this.scopes[scope][key];
58
+ var sel = this.selectors[scope][key];
59
+ if (val.find && sel) val = val.find(sel);
60
+ return val[idx];
61
+ }
62
+ }
63
+
64
+ function getJQ (scope, key, idx) {
65
+ idx = idx || 0;
66
+ return $(this.getVal(scope, key, idx));
67
+ }
68
+
69
+ function toJson () {
70
+ return JSON.stringify(this.toHash());
71
+ }
72
+
73
+ function toHash () {
74
+ this.normalize();
75
+ var ret = {
76
+ 'children': {}
77
+ };
78
+
79
+ for (var name in this.scopes) {
80
+ var scope = this.scopes[name];
81
+ ret[name] = {};
82
+ for (var key in scope) {
83
+ var val = scope[key];
84
+ if (val.length == 1) {
85
+ ret[name][key] = 'Scalar';
86
+ } else {
87
+ ret[name][key] = 'Array';
88
+ }
89
+ }
90
+ }
91
+
92
+ for (var namespace in this.children) {
93
+ var childMarker = this.children[namespace];
94
+ ret.children[namespace] = childMarker.toHash();
95
+ }
96
+
97
+ return ret;
98
+ }
99
+
100
+ function normalize () {
101
+ // TODO
102
+ this.normalized = true;
103
+ }
104
+
105
+ private
106
+
107
+ function normalizeVal (val) {
108
+ var ret = [];
109
+ if (typeof val == 'object') {
110
+ if (val.jquery) {
111
+ foreach (var e in val) {
112
+ if (! e) continue;
113
+ ret.push(e);
114
+ }
115
+ } else if (val instanceof Array) {
116
+ foreach (var v in val) {
117
+ if (! v) continue;
118
+ var norms = this.normalizeVal(v);
119
+ foreach (var norm in norms) {
120
+ if (! norm) continue;
121
+ ret.push(norm);
122
+ }
123
+ }
124
+ }
125
+ }
126
+
127
+ return ret;
128
+ }
129
+
130
+ }
131
+
132
+ JS2.SEL_EVENTS = {};
133
+ JS2.SEL_EVENTS.LEFT_BUTTON = $.browser.msie ? 1 : 0;
134
+ JS2.SEL_EVENTS.LEFT_MOUSE_UP = $.Event('mouseup');
135
+ JS2.SEL_EVENTS.LEFT_MOUSE_UP.button = JS2.SEL_EVENTS.LEFT_BUTTON;
136
+ JS2.SEL_EVENTS.LEFT_MOUSE_DOWN = $.Event('mousedown');
137
+ JS2.SEL_EVENTS.LEFT_MOUSE_DOWN.button = JS2.SEL_EVENTS.LEFT_BUTTON;
138
+ JS2.SEL_TRACKER = {};
139
+ JS2.SEL_MARKER = new JS2.SelMarker();
@@ -0,0 +1,73 @@
1
+ class JS2.Test {
2
+ function initialize () {
3
+ this.store = {};
4
+ this.namespaces = {};
5
+ }
6
+
7
+ function setNamespace (name) {
8
+ this.namespaces[name] = this.namespaces[name] || {};
9
+ this.switchNamespace(name);
10
+ }
11
+
12
+ function switchNamespace (name) {
13
+ if (! this.namespaces[name]) this.setNamespace(name);
14
+ this.store = this.namespaces[name];
15
+ }
16
+
17
+ function addEle (klass, key, ele) {
18
+ if (! this.store[klass]) this.store[klass] = {};
19
+
20
+ var klassStore = this.store[klass];
21
+ if (! klassStore[key]) klassStore[key] = {};
22
+
23
+ klassStore[key] = ele;
24
+ }
25
+
26
+ function pushEle (klass, key, ele) {
27
+ if (! this.store[klass]) this.store[klass] = {};
28
+ if (! this.store[klass][key]) this.store[klass][key] = [];
29
+ if (ele.length && ele.length > 1) {
30
+ foreach (var e in ele) {
31
+ this.store[klass][key].push(ele);
32
+ }
33
+ } else {
34
+ this.store[klass][key].push(ele)
35
+ }
36
+ }
37
+
38
+ function getEle (klass, key, n) {
39
+ if (! this.store[klass]) return false;
40
+ var ele = this.store[klass][key];
41
+
42
+ if (! ele) return false;
43
+
44
+ n = n || 0;
45
+
46
+ if (ele.length > 0) {
47
+ return ele[n];
48
+ } else {
49
+ return ele;
50
+ }
51
+ }
52
+
53
+ function setEle (klass, key) {
54
+ var ele = this.currentEle;
55
+ if (ele) {
56
+ ele.setAttribute(this.currentID);
57
+ }
58
+
59
+ var newEle = this.store[klass][key];
60
+ if (! newEle) return false;
61
+
62
+ if (newEle.jquery) {
63
+ newEle = newEle[0];
64
+ }
65
+
66
+ this.currentID = newEle.getAttribute('id');
67
+ newEle.setAttribute('id', 'JS2_TEST_ELEMENT');
68
+
69
+ return newEle.nodeName;
70
+ }
71
+ }
72
+
73
+ JS2.TEST = new JS2.Test();
@@ -0,0 +1,105 @@
1
+ class JS2::AST::ClassNode < JS2::AST::Node
2
+ attr_accessor :name, :members, :extends, :filename, :parent, :mem_hash, :haml, :includes, :included_mods, :statics
3
+
4
+ def initialize (filename, n, text, mems, includes, statics)
5
+ @filename = filename
6
+ @line_number = n
7
+ @members = mems
8
+ @text = text
9
+ @mem_hash = Hash.new
10
+ @child_filenames = Array.new
11
+ @super_hash = Hash.new
12
+ @includes = includes
13
+ @included_mods = []
14
+ @statics = statics
15
+
16
+ self.close!
17
+
18
+ @finalized = false
19
+ end
20
+
21
+ def is_module?
22
+ return false
23
+ end
24
+
25
+ def members
26
+ if self.haml
27
+ return @members + [ self.haml ]
28
+ else
29
+ return @members
30
+ end
31
+ end
32
+
33
+ def close!
34
+ parse_text!()
35
+ @members.each do |m|
36
+ next if m.is_a? JS2::AST::CommentNode
37
+ @mem_hash[m.name] = m
38
+ end
39
+ end
40
+
41
+ def finalize!
42
+ # already done dude
43
+ return if @finalized
44
+ @finalized = true
45
+
46
+ # make the connection
47
+ if parent
48
+ parent.finalize!
49
+ end
50
+
51
+ haml.finalize!(parent) if haml
52
+
53
+
54
+ @super_hash = Hash.new
55
+
56
+ if parent
57
+ # if parent has haml but not child
58
+ if parent.haml && ! haml
59
+ inherited = JS2::AST::InheritedNode.new
60
+ inherited.name = 'htmlCache'
61
+ inherited.extends = self.extends
62
+ @mem_hash['htmlCache'] = inherited
63
+ @members.push(inherited)
64
+ end
65
+
66
+ parent.mem_hash.each_pair do |name, m|
67
+ if @mem_hash[m.name]
68
+ @super_hash[m.name] = parent.name
69
+ end
70
+ end
71
+ end
72
+
73
+ included_mods.reverse.each do |c|
74
+ merge(c)
75
+ end
76
+
77
+ merge(parent) if parent
78
+ end
79
+
80
+ def merge (c)
81
+ c.mem_hash.each_pair do |name, m|
82
+ unless @mem_hash[name]
83
+ inherited = JS2::AST::InheritedNode.new
84
+ inherited.name = m.name
85
+ inherited.extends = c.name
86
+ @mem_hash[m.name] = inherited
87
+ @members.push(inherited)
88
+ end
89
+ end
90
+ end
91
+
92
+ def super_hash
93
+ return @super_hash
94
+ end
95
+
96
+
97
+ def parse_text!
98
+ m = @text.match(/\s+([\w\.]+)\s+(extends ([\w\.]+))?/)
99
+ @name = m[1]
100
+ @extends = m[3]
101
+ end
102
+
103
+ end
104
+
105
+
@@ -0,0 +1,2 @@
1
+ class JS2::AST::CommentNode < JS2::AST::Node
2
+ end
@@ -0,0 +1,22 @@
1
+ class JS2::AST::HamlNode < Hash
2
+ attr_accessor :attrs
3
+
4
+ def initialize
5
+ @attrs = []
6
+ end
7
+
8
+ def finalize! (parent)
9
+ @attrs = []
10
+
11
+ if parent && parent.haml
12
+ parent.haml.keys.each do |k|
13
+ next if self[k]
14
+ @attrs << [ k, "#{parent.name}.prototype.htmlCache.#{k}" ]
15
+ end
16
+ end
17
+
18
+ self.keys.each do |k|
19
+ @attrs << [ k, self[k] ]
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,11 @@
1
+ class JS2::AST::IncludeNode < JS2::AST::Node
2
+ attr_accessor :name
3
+
4
+ def close!
5
+ if m = @text.match(/^(\s*)include\s*([\.\w]+)\s*;/)
6
+ @padding = m[1]
7
+ @name = m[2]
8
+ end
9
+ end
10
+
11
+ end
@@ -0,0 +1,7 @@
1
+ class JS2::AST::InheritedNode
2
+ attr_accessor :name, :extends
3
+
4
+ def to_js
5
+ return " #{name}: #{extends}.prototype.#{name}"
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ class JS2::AST::MemberNode < JS2::AST::Node
2
+ attr_accessor :name, :klass
3
+
4
+ def close!
5
+ if m = @text.match(/^(\s*)var\s*([\w\$]+)\s*=(.*);/)
6
+ @padding = m[1]
7
+ @name = m[2]
8
+ @text = m[3].sub(/;\s*$/m, '')
9
+ elsif m = @text.match(/^(\s*)accessor\s*([\w\$]+)\s*;/)
10
+ @padding = m[1]
11
+ @name = m[2]
12
+ @text = "function (val) { if (arguments.length>0) this._#{@name}=val; return this._#{@name}; }"
13
+ else
14
+ raise 'Invalid member'
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,29 @@
1
+ class JS2::AST::MethodNode < JS2::AST::Node
2
+ attr_accessor :name
3
+
4
+ def self.properties (filename, line, str)
5
+ ret = []
6
+
7
+ str.sub!(/property/, '')
8
+ str.split(/,/).collect { |s| s.strip.sub(/;$/, '') }.each do |prop|
9
+ name = String.new(prop)
10
+ name[0,1] = name[0,1].upcase
11
+ setter = "function set#{name} (val) { this.#{prop} = val; }"
12
+ getter = "function get#{name} () { return this.#{prop}; }"
13
+
14
+ ret << self.new(filename, line, setter)
15
+ ret << self.new(filename, line, getter)
16
+ end
17
+
18
+ return ret
19
+ end
20
+
21
+
22
+ def close!
23
+ m = @text.match(/^(\s*)function\s*(\w+)\s*(.*)\s*/m)
24
+ @padding = m[1]
25
+ @name = m[2]
26
+ @text = m[3].sub(/\s*$/m, '')
27
+ @annotations = []
28
+ end
29
+ end
@@ -0,0 +1,6 @@
1
+ class JS2::AST::ModuleNode < JS2::AST::ClassNode
2
+
3
+ def is_module?
4
+ return true
5
+ end
6
+ end
@@ -0,0 +1,14 @@
1
+ class JS2::AST::Node
2
+ attr_accessor :text, :filename, :line_number
3
+
4
+ def initialize (filename, n, text)
5
+ @line_number = n
6
+ @filename = filename
7
+ @text = text
8
+
9
+ self.close!
10
+ end
11
+
12
+ def close!
13
+ end
14
+ end