js2 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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