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 CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.2.0
@@ -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
- puts Pathname.new(__FILE__).dirname.expand_path+'src'
5
- puts "OF"
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
+
@@ -3,7 +3,7 @@
3
3
  :blur
4
4
  if @value === ''
5
5
  @value = @default_value
6
-
6
+
7
7
  :focus
8
8
  if @value === @default_value
9
9
  @value = ''
@@ -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.
@@ -0,0 +1,3 @@
1
+ %script{:src=> "/jabs/input_with_default.js.jabs"}
2
+ %input{:type=>'text', :default_value => "hello!"}/
3
+ %input{:type=>'text', :default_value => "hello again!"}/
@@ -0,0 +1,8 @@
1
+ <DOCTYPE html>
2
+ %html
3
+ %head
4
+ %title Jabs Example
5
+ %meta{"http-equiv"=>"content-type", "content"=>"text/html; charset=utf-8"}
6
+ %script{:src=> "/jquery/jquery.js"}
7
+ %body= yield
8
+
@@ -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
- include Johnson::Nodes
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__
@@ -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
@@ -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