jabs 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION +1 -1
- data/examples/config.ru +16 -6
- data/examples/jabs/drag_and_drop.js.jabs +23 -0
- data/examples/{src → jabs}/input_with_default.js.jabs +1 -1
- data/examples/views/drag_and_drop.haml +16 -0
- data/examples/views/input_with_default.haml +3 -0
- data/examples/views/layout.haml +8 -0
- data/lib/jabs.rb +10 -289
- data/lib/jabs/engine.rb +18 -0
- data/lib/jabs/middleware.rb +17 -3
- data/lib/jabs/precompiler.rb +252 -0
- data/lib/johnson/ext.rb +44 -0
- data/{vendor/jquery/jquery-1.3.1.js → lib/jquery/jquery-1.3.2.js} +316 -181
- data/lib/jquery/jquery.event.drag-1.5.js +137 -0
- data/lib/jquery/jquery.event.drop-1.2.js +157 -0
- data/lib/jquery/jquery.focus_and_blur.js +81 -0
- data/rspec/jabs/jabs_engine_spec.rb +78 -16
- metadata +13 -12
- data/examples/editor.html +0 -22
- data/examples/editor.js +0 -58
- data/examples/input_with_default.html +0 -13
- data/examples/input_with_default.js +0 -19
- data/examples/src/editor.html.haml +0 -19
- data/examples/src/editor.js.jabs +0 -50
- data/examples/src/input_with_default.html.haml +0 -10
- data/vendor/jquery/jquery-1.2.6.pack.js.gz +0 -11
- data/vendor/jquery/jquery.simulate.js +0 -152
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/examples/config.ru
CHANGED
@@ -1,10 +1,20 @@
|
|
1
1
|
require 'lib/jabs'
|
2
2
|
require 'pathname'
|
3
|
+
require 'sinatra'
|
4
|
+
require 'haml'
|
5
|
+
require 'sass'
|
3
6
|
|
4
|
-
|
5
|
-
|
7
|
+
class Example < Sinatra::Base
|
8
|
+
set :views, Jabs.root+'../examples/views'
|
9
|
+
|
10
|
+
%w{input_with_default drag_and_drop}.each do |part|
|
11
|
+
get "/#{part}" do
|
12
|
+
haml part.intern
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
use Jabs::Rack::Static, :urls => '/jabs', :root => Pathname.new(__FILE__).dirname.expand_path
|
18
|
+
Jabs::Rack.mount(self, '/jquery')
|
19
|
+
map("/examples") { run Example.new }
|
6
20
|
|
7
|
-
use Jabs::Rack::Static, :urls => '/src', :root => Pathname.new(__FILE__).dirname.expand_path
|
8
|
-
run lambda { |env|
|
9
|
-
[200, {'Content-Type'=>'text/html'}, "JABS"]
|
10
|
-
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
:ready
|
2
|
+
$#sortable
|
3
|
+
.sortable 'li'
|
4
|
+
|
5
|
+
def sortable parent_selector
|
6
|
+
:dragstart
|
7
|
+
event.target
|
8
|
+
.closest parent_selector
|
9
|
+
.clone
|
10
|
+
.css
|
11
|
+
position: 'absolute'
|
12
|
+
.appendTo document.body
|
13
|
+
|
14
|
+
:drag
|
15
|
+
event.dragProxy
|
16
|
+
.css
|
17
|
+
top: event.pageY
|
18
|
+
left: event.pageX
|
19
|
+
|
20
|
+
:dragend
|
21
|
+
event.dragProxy
|
22
|
+
.remove
|
23
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
%script{:src=> "/jabs/drag_and_drop.js.jabs"}
|
2
|
+
%style
|
3
|
+
:sass
|
4
|
+
ol, li
|
5
|
+
list-style: number
|
6
|
+
li
|
7
|
+
height: 20px
|
8
|
+
width: 300px
|
9
|
+
margin-bottom: 4px
|
10
|
+
background: black
|
11
|
+
color: white
|
12
|
+
%ol#sortable
|
13
|
+
%li One: Lorem ipsum dolor sit amet
|
14
|
+
%li Two: Lorem ipsum dolor sit amet.
|
15
|
+
%li Three: Lorem ipsum dolor sit amet.
|
16
|
+
%li Four: Lorem ipsum dolor sit amet.
|
data/lib/jabs.rb
CHANGED
@@ -2,56 +2,19 @@ require 'fold'
|
|
2
2
|
require 'rack'
|
3
3
|
require 'johnson'
|
4
4
|
require 'pathname'
|
5
|
-
puts require Pathname.new(__FILE__).dirname.expand_path+'jabs/middleware'
|
6
|
-
|
7
|
-
module Johnson
|
8
|
-
module Nodes
|
9
|
-
attr_accessor :value
|
10
|
-
class FallThrough < Node
|
11
|
-
def initialize(_row, _column, value)
|
12
|
-
@value = value
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
module Visitors
|
18
|
-
class EcmaVisitor
|
19
|
-
def visit_SourceElements(o)
|
20
|
-
newline = o.value.length > 0 ? "\n" : ' '
|
21
|
-
(@depth == 0 ? '' : "{#{newline}") +
|
22
|
-
indent {
|
23
|
-
o.value.map { |x|
|
24
|
-
code = x.accept(self)
|
25
|
-
semi = case x
|
26
|
-
when Nodes::FallThrough
|
27
|
-
""
|
28
|
-
when Nodes::Function, Nodes::While, Nodes::If, Nodes::Try, Nodes::Switch, Nodes::Case, Nodes::Default, Nodes::For, Nodes::ForIn
|
29
|
-
code =~ /\}\Z/ ? '' : ';'
|
30
|
-
else
|
31
|
-
';'
|
32
|
-
end
|
33
|
-
"#{indent}#{code}#{semi}"
|
34
|
-
}.join("\n")
|
35
|
-
} +
|
36
|
-
(@depth == 0 ? '' : "#{newline}}")
|
37
|
-
end
|
38
|
-
|
39
|
-
def visit_FallThrough(o)
|
40
|
-
o.value
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
class SexpVisitor
|
45
|
-
def visit_FallThrough(o)
|
46
|
-
[:fall_through, o.value]
|
47
|
-
end
|
48
|
-
end
|
49
|
-
end
|
50
|
-
end
|
51
5
|
|
52
6
|
module Jabs
|
53
|
-
|
7
|
+
def self.root
|
8
|
+
@root ||= Pathname.new(__FILE__).dirname.expand_path
|
9
|
+
end
|
10
|
+
|
11
|
+
require root+'jabs/precompiler'
|
12
|
+
require root+'jabs/engine'
|
13
|
+
require root+'jabs/middleware'
|
54
14
|
|
15
|
+
require root+'johnson/ext'
|
16
|
+
include Johnson::Nodes
|
17
|
+
|
55
18
|
def self.logger
|
56
19
|
@logger ||= begin
|
57
20
|
#TODO configurable logging
|
@@ -62,247 +25,5 @@ module Jabs
|
|
62
25
|
logger
|
63
26
|
end
|
64
27
|
end
|
65
|
-
|
66
|
-
class Precompiler < Fold::Precompiler
|
67
|
-
class << self
|
68
|
-
attr_accessor :spot_replacements
|
69
|
-
end
|
70
|
-
|
71
|
-
self.spot_replacements = []
|
72
|
-
|
73
|
-
def self.spot_replace key, &block
|
74
|
-
spot_replacements << block if block_given?
|
75
|
-
end
|
76
|
-
|
77
|
-
attr_reader :sexp, :current_sexp
|
78
|
-
|
79
|
-
def initialize
|
80
|
-
super
|
81
|
-
|
82
|
-
@ready = false
|
83
|
-
@current_sexp = []
|
84
|
-
@full_sexp = [:source_elements, @current_sexp]
|
85
|
-
end
|
86
|
-
|
87
|
-
folds :Line, // do
|
88
|
-
[:fall_through, (Precompiler.do_spot_replace(text, self) + children.map{|child| child.text}.join(""))]
|
89
|
-
end
|
90
|
-
|
91
|
-
folds :Selector, /^\$/ do
|
92
|
-
call(function(nil, ["$this"], [:source_elements, render_children]), jquery([:string, text]))
|
93
|
-
end
|
94
|
-
|
95
|
-
folds :SubSelector, /^&/ do
|
96
|
-
call(
|
97
|
-
function(nil, ["$this"], [:source_elements, render_children]),
|
98
|
-
call(access([:name, "$this"], [:name, "find"]), [:string, text])
|
99
|
-
)
|
100
|
-
end
|
101
|
-
|
102
|
-
folds :Event, /^:/ do
|
103
|
-
event_bind(text, [:name, "$this"], [:source_elements, [parse("var $this = jQuery(this)")] + render_children])
|
104
|
-
end
|
105
|
-
|
106
|
-
folds :Ready, /^:ready/ do
|
107
|
-
jquery(function(nil, [], [:source_elements, [call(function(nil, ["$this"], [:source_elements, render_children]), jquery([:name, "window"]))]]))
|
108
|
-
end
|
109
|
-
|
110
|
-
folds :Function, /^fun / do
|
111
|
-
parts = text.split(/ /)
|
112
|
-
name, arg_names = parts.shift, parts.join('').gsub(' ', '').split(',')
|
113
|
-
[:function, name, arg_names, [:source_elements, render_children]]
|
114
|
-
end
|
115
|
-
|
116
|
-
folds :Def, /^def / do
|
117
|
-
parts = text.split(/ /)
|
118
|
-
name, arg_names = parts.shift, parts.join('').gsub(' ', '').split(',')
|
119
|
-
[:assign_expr,
|
120
|
-
access(access([:name, "jQuery"], [:name, "fn"]), [:name, name]),
|
121
|
-
[:function, nil, arg_names, [:source_elements, [parse("var $this = this")] + render_children]]]
|
122
|
-
end
|
123
|
-
|
124
|
-
if_meta = %q{
|
125
|
-
index = parent.children.index(self)
|
126
|
-
_next = parent.children.slice index + 1
|
127
|
-
|
128
|
-
_else = if [Else, ElseIf].include? _next.class
|
129
|
-
_next.render
|
130
|
-
else
|
131
|
-
nil
|
132
|
-
end
|
133
|
-
[:if, parse(Precompiler.do_spot_replace(text)),[:source_elements, render_children], _else]
|
134
|
-
}
|
135
|
-
|
136
|
-
folds :If, /^if / do
|
137
|
-
eval if_meta
|
138
|
-
end
|
139
|
-
|
140
|
-
folds :Unless, /^unless / do
|
141
|
-
[:if, [:not, [:parenthesis, parse(Precompiler.do_spot_replace(text))]], [:source_elements, render_children], nil]
|
142
|
-
end
|
143
|
-
|
144
|
-
folds :Else, /^else/ do
|
145
|
-
[:source_elements, render_children]
|
146
|
-
end
|
147
|
-
|
148
|
-
folds :ElseIf, /^else if/ do
|
149
|
-
eval if_meta
|
150
|
-
end
|
151
|
-
|
152
|
-
folds :DotAccessor, /^\./ do
|
153
|
-
index = parent.children.index(self)
|
154
|
-
_next = parent.children.slice index + 1
|
155
|
-
_text = _next ? _next.text : ""
|
156
|
-
if children.any?
|
157
|
-
if (_text[/\}\)/])
|
158
|
-
[:fall_through, ("$this."+Precompiler.do_spot_replace(text, self) + children.map{|child| child.text}.join(""))]
|
159
|
-
else
|
160
|
-
call(
|
161
|
-
function(nil, ["$this"], [:source_elements, render_children]),
|
162
|
-
parse(Precompiler.do_spot_replace(".#{text}", self))
|
163
|
-
)
|
164
|
-
end
|
165
|
-
else
|
166
|
-
parse Precompiler.do_spot_replace(".#{text}", self)
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
spot_replace :DotAccessor do |expression, precompiler|
|
171
|
-
expression.gsub /(^\.([\w]+)|- \.(.+))(.*)/ do |match|
|
172
|
-
"$this#{Precompiler.compile_arguments expression, $1, match, $4}"
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
spot_replace :AccessUpAndCall do |expression, precompiler|
|
177
|
-
expression.gsub /\.\.(\..*)/ do |match|
|
178
|
-
"$this.prevObject#{Precompiler.do_spot_replace($1)}"
|
179
|
-
end
|
180
|
-
end
|
181
|
-
|
182
|
-
spot_replace :AccessUpUp do |expression, precompiler|
|
183
|
-
expression.
|
184
|
-
gsub(/ \.\.\/|^\.\.\//, "$this.prevObject/").
|
185
|
-
gsub(/\/\.\./, ".prevObject")
|
186
|
-
end
|
187
|
-
|
188
|
-
spot_replace :AccessUp do |expression, precompiler|
|
189
|
-
expression.gsub /\.\./ do
|
190
|
-
"$this.prevObject"
|
191
|
-
end
|
192
|
-
end
|
193
|
-
|
194
|
-
spot_replace :AttributeSetter do |expression, precompiler|
|
195
|
-
expression.gsub /@([\w]+)[ ]*=[ ]*(.*)/ do |match|
|
196
|
-
if $2[0] == ?=
|
197
|
-
match
|
198
|
-
else
|
199
|
-
"$this.attr('#{$1}', #{Precompiler.do_spot_replace $2, precompiler})"
|
200
|
-
end
|
201
|
-
end
|
202
|
-
end
|
203
28
|
|
204
|
-
spot_replace :AttributeAccessor do |expression, precompiler|
|
205
|
-
expression.gsub /@([\w]+)/ do
|
206
|
-
"$this.attr('#{$1}')"
|
207
|
-
end
|
208
|
-
end
|
209
|
-
|
210
|
-
spot_replace :DanglingThis do |expression, precompiler|
|
211
|
-
expression.gsub /prevObject\$this/ do
|
212
|
-
"prevObject"
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
def self.do_spot_replace expression, precompiler=nil
|
217
|
-
spot_replacements.each do |block|
|
218
|
-
expression = block.call(expression, precompiler)
|
219
|
-
end
|
220
|
-
expression
|
221
|
-
end
|
222
|
-
|
223
|
-
def self.compile_arguments expression, call, real, args
|
224
|
-
return real if expression[Regexp.new("^\\#{call}\\(")]
|
225
|
-
arguments = []
|
226
|
-
if args[/^\./]
|
227
|
-
"#{call}()#{do_spot_replace(args).gsub("$this", "")}"
|
228
|
-
else
|
229
|
-
args.split(/\s|,/).each do |arg|
|
230
|
-
arg.gsub!(/:(\w+)/) {%{"#{$1}"}}
|
231
|
-
next if arg[/\s/]
|
232
|
-
next if arg == ""
|
233
|
-
arguments << arg
|
234
|
-
end
|
235
|
-
"#{call}(#{arguments.join(', ')})"
|
236
|
-
end
|
237
|
-
end
|
238
|
-
|
239
|
-
def parse expression
|
240
|
-
self.class.do_spot_replace expression, self
|
241
|
-
Johnson::Parser.parse(expression).value.first
|
242
|
-
end
|
243
|
-
|
244
|
-
def source block=nil
|
245
|
-
source = [:source_elements]
|
246
|
-
source << [block] unless(block.nil? or block.empty?)
|
247
|
-
source
|
248
|
-
end
|
249
|
-
|
250
|
-
def event_bind event, binds_to, function_sexp=nil
|
251
|
-
call(access(binds_to, [:name, "live"]), [:string, event], function(nil, ["e"], function_sexp))
|
252
|
-
end
|
253
|
-
|
254
|
-
def call *args
|
255
|
-
[:function_call, args]
|
256
|
-
end
|
257
|
-
|
258
|
-
def onready function_sexp=nil
|
259
|
-
event_bind('ready', jquery([:name, "document"]), function_sexp)
|
260
|
-
end
|
261
|
-
|
262
|
-
def access left, right
|
263
|
-
[:dot_accessor, right, left]
|
264
|
-
end
|
265
|
-
|
266
|
-
def function name=nil, args=[], function_sexp=nil
|
267
|
-
[:function, name, args, function_sexp]
|
268
|
-
end
|
269
|
-
|
270
|
-
def jquery *jquery_arg
|
271
|
-
[:function_call, [
|
272
|
-
[:name, 'jQuery'],
|
273
|
-
*jquery_arg
|
274
|
-
]]
|
275
|
-
end
|
276
|
-
|
277
|
-
def johnsonize(sexp)
|
278
|
-
return sexp if sexp.is_a?(Johnson::Nodes::Node)
|
279
|
-
return sexp if sexp.class.to_s == "String"
|
280
|
-
return [] if sexp === []
|
281
|
-
return nil if sexp === nil
|
282
|
-
unless sexp.first.class.to_s == "Array"
|
283
|
-
if sexp.first.class.to_s == "Symbol"
|
284
|
-
klass = eval("Johnson::Nodes::#{sexp.shift.to_s.camelcase}")
|
285
|
-
klass.new 0,0, *sexp.map{|n|johnsonize(n)}
|
286
|
-
elsif sexp.is_a? Array
|
287
|
-
sexp.map{|n|johnsonize(n)}
|
288
|
-
else
|
289
|
-
sexp
|
290
|
-
end
|
291
|
-
else
|
292
|
-
sexp.map{|n|johnsonize(n)}
|
293
|
-
end
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
|
-
class Engine < Fold::Engine
|
298
|
-
|
299
|
-
def render context=nil
|
300
|
-
@p = precompiler_class.new
|
301
|
-
root = Johnson::Nodes::SourceElements.new 0, 0
|
302
|
-
@p.fold(lines).children.each{|c|root << @p.johnsonize(c.render)}
|
303
|
-
root.to_ecma
|
304
|
-
end
|
305
|
-
end
|
306
29
|
end
|
307
|
-
|
308
|
-
puts Jabs::Engine.new($stdin.read).render if $0 == __FILE__
|
data/lib/jabs/engine.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
module Jabs
|
2
|
+
class Engine < Fold::Engine
|
3
|
+
def render context=nil
|
4
|
+
@p = precompiler_class.new
|
5
|
+
root = Johnson::Nodes::SourceElements.new 0, 0
|
6
|
+
main = Johnson::Nodes::SourceElements.new 0, 0
|
7
|
+
root << @p.johnsonize(@p.call([:function, nil, [], main]))
|
8
|
+
|
9
|
+
@p.fold(lines).children.each{|c|main << @p.johnsonize(c.render)}
|
10
|
+
root.to_ecma
|
11
|
+
rescue Fold::FoldFactory::IndentationError => e
|
12
|
+
require 'pp'
|
13
|
+
pp lines
|
14
|
+
puts "______------UP"
|
15
|
+
raise e
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/jabs/middleware.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
module Jabs
|
2
|
-
|
3
2
|
module Rack
|
3
|
+
|
4
|
+
def self.mount(rack_builder, mount_pount)
|
5
|
+
rack_builder.map(mount_pount) do
|
6
|
+
run (lambda do |env|
|
7
|
+
source = %w{
|
8
|
+
jquery/jquery-1.3.2.js
|
9
|
+
jquery/jquery.event.drag-1.5.js
|
10
|
+
jquery/jquery.event.drop-1.2.js
|
11
|
+
jquery/jquery.focus_and_blur.js
|
12
|
+
}.map{|path| (Jabs.root+path).read }.join("\n")
|
13
|
+
|
14
|
+
[200, {'Content-Type'=> 'text/javascript'}, source]
|
15
|
+
end)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
4
19
|
class Static < ::Rack::Static
|
5
20
|
def initialize(app, options={})
|
6
21
|
super(app, options)
|
@@ -11,7 +26,6 @@ module Jabs
|
|
11
26
|
|
12
27
|
class File < ::Rack::File
|
13
28
|
def serving
|
14
|
-
@path += ".jabs" unless @path[/\.jabs$/]
|
15
29
|
status, headers, body = * super
|
16
30
|
return [status, headers, body] unless status == 200
|
17
31
|
|
@@ -19,7 +33,7 @@ module Jabs
|
|
19
33
|
|
20
34
|
headers['Content-Type'] = 'text/javascript'
|
21
35
|
headers['Content-Length'] = jabs.size.to_s
|
22
|
-
|
36
|
+
|
23
37
|
[status, headers, jabs]
|
24
38
|
end
|
25
39
|
end
|