js2 0.0.1

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.
@@ -0,0 +1,123 @@
1
+ begin
2
+ require 'rubygems'
3
+ require 'haml'
4
+ require 'json'
5
+ rescue Exception
6
+ puts "HAML is not supported"
7
+ end
8
+
9
+ class JS2::Parser::Haml
10
+
11
+ def initialize (haml_engine)
12
+ @haml_engine = haml_engine
13
+ end
14
+
15
+ def parse_out_js (file)
16
+ padding = nil
17
+ js = []
18
+
19
+ File.read(file).split(/\r?\n/).each do |line|
20
+ if m = line.match(/^(\s*):js2/)
21
+ padding = m[1]
22
+ elsif padding
23
+ if m = line.match(/^#{padding}/)
24
+ js << line
25
+ elsif ! line.match(/^\s*$/)
26
+ padding = nil
27
+ end
28
+ end
29
+ end
30
+
31
+ return js.join("\n")
32
+ end
33
+
34
+ def parse (file)
35
+ lines = File.read(file).split(/\r?\n/)
36
+ result = Hash.new
37
+
38
+ klass = Hash.new
39
+ key = nil
40
+
41
+ until lines.empty?
42
+ line = lines.shift()
43
+
44
+ if m = line.match(/^\.?([\w\.]+)/)
45
+ klass = Hash.new
46
+ result[m[1]] = klass
47
+ elsif m = line.match(/^ sass/)
48
+ key = 'sass'
49
+ klass[key] = [ [ ], '' ]
50
+ elsif m = line.match(/^ \.?([\w]+)(\(([^)]+)\))?/)
51
+ key = m[1]
52
+ klass[key] = [ [], m[3] ]
53
+ elsif key
54
+ if key == 'sass'
55
+ klass[key][0] << line.sub(/^ /, '')
56
+ else
57
+ klass[key][0] << line.sub(/^ /, '')
58
+ end
59
+ end
60
+ end
61
+
62
+ result.keys.each do |class_name|
63
+ klass = result[class_name]
64
+ klass.each_pair do |key, array|
65
+ if key == 'sass'
66
+ array[0].unshift ".#{class_name.sub(/\.\w+$/, '').sub(/\./, '')}"
67
+ klass[key] = sassify(array[0].join("\n"))
68
+ else
69
+ klass[key] = functionize(array[0].join("\n"), array[1])
70
+ end
71
+ end
72
+ end
73
+
74
+ return result
75
+ end
76
+
77
+ private
78
+
79
+ def sassify (string)
80
+ begin
81
+ css = @haml_engine.sassify(string)
82
+ rescue
83
+ raise string
84
+ end
85
+ return css.gsub(/\n/, '').to_json
86
+ end
87
+
88
+ def functionize (string, params)
89
+ begin
90
+ html = @haml_engine.hamlize(string)
91
+ rescue
92
+ raise string
93
+ end
94
+
95
+ if params
96
+ return functionize_with_params(html, params)
97
+ end
98
+
99
+ counter = 0
100
+ segments = html.split(%r|#\w+#|).collect { |seg| seg.to_json }
101
+ ret = Array.new
102
+ segments.each_with_index do |seg, i|
103
+ ret.push(seg)
104
+ ret.push(%{arguments[#{i}]}) if (segments.length-1) > i
105
+ end
106
+ return %{function(){return #{ret.join('+')}}}
107
+ end
108
+
109
+
110
+ def functionize_with_params (string, params)
111
+ args = []
112
+ string.gsub!(/#([^#]+)#/) do |m|
113
+ args << m.gsub(/#/, '')
114
+ '###'
115
+ end
116
+
117
+ segments = string.split(%r|###|).collect { |seg| seg.to_json }
118
+ ret = segments.zip(args).flatten.reject { |a| a.nil? }.join('+');
119
+ return %{function(#{params}){return #{ret}}}
120
+ end
121
+
122
+
123
+ end
@@ -0,0 +1,84 @@
1
+ class JS2::Process::FileHandler
2
+ def initialize (params = {})
3
+ @read_dir = params[:read_dir]
4
+ @write_dir = params[:write_dir]
5
+ @haml_dir = params[:haml_dir]
6
+ @view_dir = params[:view_dir]
7
+
8
+ @mtimes = Hash.new
9
+ end
10
+
11
+ def class_file
12
+ return @write_dir + '/classes.js'
13
+ end
14
+
15
+ def get_view_files
16
+ return [] unless @view_dir
17
+ return Dir.glob(@view_dir + '/**/*.haml')
18
+ end
19
+
20
+ def get_haml_files
21
+ return [] unless @haml_dir
22
+ return Dir.glob(@haml_dir + '/**/*/*.js2.haml') + Dir.glob(@haml_dir + '/*.js2.haml')
23
+ end
24
+
25
+ def get_files
26
+ return Dir.glob(@read_dir + '/**/*/*.js2') + Dir.glob(@read_dir + '/*.js2')
27
+ end
28
+
29
+ def write_file (filename, str)
30
+ to_write = filename.sub(/^#{@read_dir}/, @write_dir).sub(/\.js2$/, '.js')
31
+ FileUtils.mkpath(File.dirname(to_write))
32
+ File.open(to_write, 'w') do |f|
33
+ f << str
34
+ end
35
+ end
36
+
37
+ def write_class_file (str)
38
+ FileUtils.mkpath(File.dirname(class_file))
39
+ File.open(class_file, 'w') do |f|
40
+ f << str
41
+ end
42
+ end
43
+
44
+ def need_update!
45
+ ret = false
46
+ did = Hash.new
47
+ self.get_files.each do |file|
48
+ mtime = File.mtime(file)
49
+ if @mtimes[file] != mtime
50
+ @mtimes[file] = mtime
51
+ ret = true
52
+ end
53
+ did[file] = mtime
54
+ end
55
+
56
+ self.get_haml_files.each do |file|
57
+ mtime = File.mtime(file)
58
+ if @mtimes[file] != mtime
59
+ @mtimes[file] = mtime
60
+ ret = true
61
+ end
62
+ did[file] = mtime
63
+ end
64
+
65
+ self.get_view_files.each do |file|
66
+ mtime = File.mtime(file)
67
+ if @mtimes[file] != mtime
68
+ @mtimes[file] = mtime
69
+ ret = true
70
+ end
71
+ did[file] = mtime
72
+ end
73
+
74
+ @mtimes.keys.each do |file|
75
+ ret = true unless did[file]
76
+ end
77
+
78
+ @mtimes = did
79
+ return ret
80
+ rescue
81
+ return true
82
+ end
83
+
84
+ end
@@ -0,0 +1,19 @@
1
+ begin
2
+ require 'rubygems'
3
+ require 'haml'
4
+ require 'sass'
5
+ require 'json'
6
+ rescue Exception
7
+ puts "HAML is not supported"
8
+ end
9
+
10
+
11
+ class JS2::Process::HamlEngine
12
+ def hamlize (string)
13
+ return Haml::Engine.new(string, { :ugly => true }).render(self).gsub(/\n/, '')
14
+ end
15
+
16
+ def sassify (string)
17
+ return Sass::Engine.new(string, { :ugly => true }).render
18
+ end
19
+ end
@@ -0,0 +1,57 @@
1
+ class JS2::Process::Universe
2
+ def initialize
3
+ @class_lookup = Hash.new
4
+ @haml_lookup = Hash.new
5
+ @node_containers = Array.new
6
+ @mod_lookup = Hash.new
7
+ end
8
+
9
+ def add_nodes (nodes)
10
+ nodes.select { |n| n.is_a? JS2::AST::ClassNode }.each do |k|
11
+ @class_lookup[k.name] = k
12
+ end
13
+
14
+ nodes.select { |n| n.is_a? JS2::AST::ModuleNode }.each do |k|
15
+ @class_lookup[k.name] = k
16
+ end
17
+
18
+ @node_containers << nodes
19
+ end
20
+
21
+ def node_containers
22
+ return @node_containers
23
+ end
24
+
25
+ def add_haml_hash (hash)
26
+ hash.each_pair do |name, haml_hash|
27
+ @haml_lookup[name] ||= JS2::AST::HamlNode.new
28
+ haml = @haml_lookup[name]
29
+
30
+ haml_hash.each_pair do |k,v|
31
+ haml[k] = v
32
+ end
33
+ end
34
+ end
35
+
36
+ def finalize! ()
37
+ @class_lookup.values.each do |k|
38
+ # set parents
39
+ k.parent = @class_lookup[k.extends] if k.extends
40
+ included_mods = []
41
+ k.includes.each do |mod_node|
42
+ m = @class_lookup[mod_node.name]
43
+ included_mods << m if m
44
+ end
45
+
46
+ k.included_mods = included_mods
47
+
48
+ # set haml
49
+ k.haml = @haml_lookup[k.name] if @haml_lookup[k.name]
50
+ end
51
+
52
+ @class_lookup.values.each do |k|
53
+ k.finalize!
54
+ end
55
+ end
56
+
57
+ end
@@ -0,0 +1,150 @@
1
+ require 'yaml'
2
+
3
+ class JS2::Processor
4
+ attr_accessor :fh, :haml_engine, :decorator
5
+
6
+ # ----------------------------------------------------------------------------
7
+ # Rails support
8
+ # ----------------------------------------------------------------------------
9
+ def self.from_rails
10
+ hash = YAML.load_file("#{RAILS_ROOT}/config/js2.yml")[RAILS_ENV]
11
+ config = JS2::Config.new(hash)
12
+ return self.get(config)
13
+ end
14
+
15
+ def self.daemon_from_rails
16
+ processor = self.from_rails
17
+ return JS2::Daemon.new(processor)
18
+ end
19
+
20
+ # ----------------------------------------------------------------------------
21
+ # yaml support
22
+ # ----------------------------------------------------------------------------
23
+ def self.from_yaml(file)
24
+ config = JS2::Config.new(YAML.load_file(file))
25
+ return self.get(config)
26
+ end
27
+
28
+ def self.daemon_from_yaml(file)
29
+ p = self.from_yaml(file)
30
+ return JS2::Daemon.new(p)
31
+ end
32
+
33
+ # ----------------------------------------------------------------------------
34
+ # legacy
35
+ # ----------------------------------------------------------------------------
36
+ def self.from_file (file, env = nil)
37
+ hash = YAML.load_file(file)
38
+ hash = hash[env] if env
39
+ config = JS2::Config.new(hash)
40
+ return self.get(config)
41
+ end
42
+
43
+ def self.processor_from_file (file, env = nil)
44
+ return self.from_file(file, env)
45
+ end
46
+
47
+ def self.daemon_from_file (file, env = nil)
48
+ p = self.from_file(file, env)
49
+ return JS2::Daemon.new(p)
50
+ end
51
+
52
+ def self.from_hash (hash)
53
+ config = JS2::Config.new(hash)
54
+ return self.get(config)
55
+ end
56
+
57
+ def self.daemon_from_hash (hash)
58
+ p = self.from_hash(hash)
59
+ return p
60
+ end
61
+
62
+
63
+ def self.get (config = nil)
64
+ # get config file
65
+ config ||= JS2::Config.new
66
+
67
+ # haml engine
68
+ haml_engine_class = config.haml_engine_class ?
69
+ config.haml_engine_class.constantize :
70
+ JS2::Process::HamlEngine
71
+
72
+ haml_engine = haml_engine_class.new
73
+
74
+ # file handler
75
+ js2_dir = config.js2_dir
76
+ write_dir = config.write_dir
77
+ js2_haml_dir = config.js2_haml_dir
78
+ haml_dir = config.haml_dir
79
+
80
+ file_handler = JS2::Process::FileHandler.new(
81
+ :read_dir => js2_dir,
82
+ :write_dir => write_dir,
83
+ :haml_dir => js2_haml_dir,
84
+ :view_dir => haml_dir
85
+ )
86
+
87
+ decorator_klass = config.test_mode ?
88
+ JS2::Decorator::Test :
89
+ JS2::Decorator::Standard
90
+
91
+ return self.new(
92
+ :test_mode => config.test_mode,
93
+ :reference_dir => config.reference_dir,
94
+ :haml_engine => haml_engine,
95
+ :file_handler => file_handler,
96
+ :decorator_klass => decorator_klass
97
+ )
98
+ end
99
+
100
+ def initialize (params)
101
+ @haml_engine = params[:haml_engine]
102
+ @fh = params[:file_handler]
103
+ @decorator_klass = params[:decorator_klass]
104
+ @reference_dir = params[:reference_dir]
105
+ @test_mode = params[:test_mode]
106
+ end
107
+
108
+ def write_files
109
+ universe = JS2::Process::Universe.new()
110
+
111
+ parser ||= JS2::Parser::Fast.new()
112
+ haml_parser ||= JS2::Parser::Haml.new(@haml_engine)
113
+ universe = JS2::Process::Universe.new
114
+
115
+ decorator = @decorator_klass.new
116
+
117
+ @fh.get_files.each do |filename|
118
+ nodes = parser.parse(filename)
119
+ universe.add_nodes(nodes)
120
+ end
121
+
122
+ @fh.get_haml_files.each do |filename|
123
+ hash = haml_parser.parse(filename)
124
+ universe.add_haml_hash(hash)
125
+ end
126
+
127
+ universe.finalize!
128
+
129
+ universe.node_containers.each do |nc|
130
+ str = decorator.draw_nodes(nc)
131
+ @fh.write_file(nc.filename, str)
132
+ end
133
+
134
+ str = decorator.draw_classes(universe.node_containers.flatten)
135
+ @fh.write_class_file(str)
136
+
137
+ if @test_mode
138
+ decorator.write_references(@reference_dir)
139
+ end
140
+
141
+ @fh.get_view_files.each do |filename|
142
+ js = haml_parser.parse_out_js(filename)
143
+ nodes = parser.parse_string(js)
144
+ decorator = @decorator_klass.new
145
+ decorator.draw_nodes(nodes)
146
+ decorator.write_references(@reference_dir)
147
+ end
148
+ end
149
+
150
+ end
@@ -0,0 +1,111 @@
1
+ begin
2
+ require 'rubygems'
3
+ gem "selenium-client", ">=1.2.16"
4
+ require "selenium/client"
5
+ require "yaml"
6
+ require "json"
7
+
8
+
9
+ class JS2::Test::Selenium < Selenium::Client::Driver
10
+ attr_accessor :reference_dir, :child_selector
11
+
12
+ RESET_SEL_MARKER = "if (window.JS2) { window.USE_SEL_MARKER = window.JS2.SEL_MARKER; }"
13
+
14
+ class << self
15
+
16
+ def logger
17
+ return @logger || nil
18
+ end
19
+
20
+ def logger= (a_logger)
21
+ @logger = a_logger
22
+ end
23
+
24
+ def connect (config_file, env = nil)
25
+ config = YAML.load_file(config_file)
26
+ config = config[env] if env
27
+
28
+ reference_dir = config['reference_dir'] || './spec/js2refs'
29
+ config = config['selenium']
30
+
31
+ ret = self.new( :host => config['host'] || 'localhost',
32
+ :port => config['port'] || 4444,
33
+ :browser => config['browser'] || '*firefox',
34
+ :url => config['url'] || 'http://google.com',
35
+
36
+ :timeout_in_second => config[:timeout] || 60,
37
+ :highlight_located_element => config['highlight'] || false,
38
+ :javascript_framework => config['framework'] || 'jquery' )
39
+
40
+ # hack to get an instance var in.
41
+ ret.reference_dir = reference_dir
42
+ ret.child_selector = nil
43
+
44
+ return ret
45
+ end
46
+ end
47
+
48
+ def get_sel_markers ()
49
+ json = self.execute("JS2.SEL_MARKER.toJson()")
50
+ struct = JSON.parse(json)
51
+ puts YAML::dump(struct)
52
+ end
53
+
54
+ def open!(uri)
55
+ ret = self.open(uri)
56
+ self.wait_for_page
57
+ self.set_sel_marker!
58
+ return ret
59
+ end
60
+
61
+ def execute (js)
62
+ puts js
63
+ return self.js_eval("window.eval(#{js.to_json});")
64
+ end
65
+
66
+ def uri
67
+ return self.location.sub(%r|^https?://(.*)?/|, '/')
68
+ end
69
+
70
+ def get_helper (klass_name)
71
+ klass = klass_name
72
+ ref_file = %|#{@reference_dir}/#{klass_name}.yml|
73
+ lookup = if File.exist? ref_file
74
+ YAML.load_file(ref_file)
75
+ else
76
+ Hash.new
77
+ end
78
+
79
+ return JS2::Test::SeleniumHelper.new(klass_name, lookup, self)
80
+ end
81
+
82
+ def child_scope (selector)
83
+ js = "if (window.JS2) { window.USE_SEL_MARKER = window.JS2.SEL_MARKER."
84
+ js << selector.split('>').collect { |s| "children.#{s}" }.join('.')
85
+ js << '};'
86
+ @keep_selector = js
87
+ self.set_sel_marker!
88
+ yield()
89
+ @keep_selector = nil
90
+ self.set_sel_marker!
91
+ end
92
+
93
+ def set_sel_marker!
94
+ self.execute(@keep_selector || RESET_SEL_MARKER)
95
+ end
96
+
97
+ def scope(klass_name)
98
+ self.set_sel_marker!
99
+ helper = get_helper(klass_name)
100
+ if block_given?
101
+ yield(helper)
102
+ else
103
+ return helper
104
+ end
105
+ end
106
+
107
+ end
108
+
109
+ rescue Exception => e
110
+ warn "No support for selenium"
111
+ end