zafu 0.7.9 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt CHANGED
@@ -1,3 +1,11 @@
1
+ == 0.8.0 2011-06-15
2
+
3
+ * Enhancements
4
+ * Include with 'part' can now replace method.
5
+ * Fixed 'merge' for OrderedHash.
6
+ * Fixed dom_scope from block in each (was not using propagated dom scope).
7
+ * Added support for comments (started with '//!').
8
+
1
9
  == 0.7.9 2011-05-26
2
10
 
3
11
  * Enhancements
data/lib/zafu/info.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Zafu
2
- VERSION = '0.7.9'
2
+ VERSION = '0.8.0'
3
3
  end
4
4
 
@@ -13,6 +13,9 @@ module Zafu
13
13
  # it has a name or dom id defined ('main', 'related', 'list', etc).
14
14
  attr_writer :dom_prefix
15
15
 
16
+ # This is used to force a given dom_id (in saved templates for example).
17
+ attr_accessor :saved_dom_id
18
+
16
19
  # Any kind of information that the compiler might need to use (QueryBuilder query used
17
20
  # to fetch the node for example).
18
21
  attr_reader :opts
@@ -48,7 +51,9 @@ module Zafu
48
51
  # ivar name (see #master_class).
49
52
  def as_main(after_class = nil)
50
53
  klass = after_class ? master_class(after_class) : single_class
51
- self.class.new("@#{klass.to_s.underscore}", single_class)
54
+ res = self.class.new("@#{klass.to_s.underscore}", single_class, nil, :new_record => @opts[:new_record])
55
+ res.dom_prefix = self.dom_prefix
56
+ res
52
57
  end
53
58
 
54
59
  # Find the class just afer 'after_class' in the class hierarchy.
@@ -64,25 +69,36 @@ module Zafu
64
69
  end
65
70
 
66
71
  # Generate a unique DOM id for this element based on dom_scopes defined in parent contexts.
72
+ # :code option returns ruby
73
+ # :erb option returns either string content or "<%= ... %>"
74
+ # default returns something to insert in interpolated string such as '#{xxx}'
67
75
  def dom_id(opts = {})
68
76
  dom_prefix = opts[:dom_prefix] || self.dom_prefix
69
77
  options = {:list => true, :erb => true}.merge(opts)
70
78
 
71
- if options[:erb]
72
- dom = dom_id(options.merge(:erb => false))
79
+ if options[:erb] || options[:code]
80
+ dom = dom_id(options.merge(:erb => false, :code => false))
81
+
73
82
  if dom =~ /^#\{([^\{]+)\}$/
74
- "<%= #{$1} %>"
83
+ code = $1
75
84
  elsif dom =~ /#\{/
76
- "<%= %Q{#{dom}} %>"
85
+ code = "%Q{#{dom}}"
77
86
  else
78
- dom
87
+ str = dom
88
+ code = dom.inspect
79
89
  end
80
- else
81
- if @up
82
- [dom_prefix] + @up.dom_scopes + (options[:list] ? [make_scope_id] : [])
90
+
91
+ if options[:code]
92
+ code
83
93
  else
84
- [dom_prefix] + (options[:list] ? [make_scope_id] : [])
85
- end.compact.uniq.join('_')
94
+ str || "<%= #{code} %>"
95
+ end
96
+ else
97
+ @saved_dom_id || (
98
+ [dom_prefix] +
99
+ dom_scopes +
100
+ (options[:list] ? [make_scope_id] : [])
101
+ ).compact.uniq.join('_')
86
102
  end
87
103
  end
88
104
 
@@ -17,6 +17,12 @@ module Zafu
17
17
  super
18
18
  end
19
19
 
20
+ def merge(hash)
21
+ res = dup
22
+ res.merge!(hash)
23
+ res
24
+ end
25
+
20
26
  alias o_keys keys
21
27
  def get_keys
22
28
  @keys ||= o_keys
@@ -93,9 +93,10 @@ module Zafu
93
93
  end
94
94
 
95
95
  def extract_name
96
- super ||
96
+ @options[:name] ||
97
97
  (%w{input select textarea}.include?(@method) ? nil : @params[:name]) ||
98
- @markup.params[:id]
98
+ @markup.params[:id] ||
99
+ @params[:id]
99
100
  end
100
101
 
101
102
  def remove_erb(text)
@@ -125,7 +126,12 @@ module Zafu
125
126
  # scan rules
126
127
  def scan
127
128
  # puts "SCAN(#{@method}): [#{@text}]"
128
- if @text =~ /\A([^<]*?)(^ *|)</m
129
+ if @text =~ %r{\A([^<]*?)(\s*)//!}m
130
+ # comment
131
+ flush $1
132
+ eat $2
133
+ scan_comment
134
+ elsif @text =~ /\A([^<]*?)(^ *|)</m
129
135
  flush $1
130
136
  eat $2
131
137
  if @text[1..1] == '/'
@@ -191,6 +197,16 @@ module Zafu
191
197
  end
192
198
  end
193
199
 
200
+ def scan_comment
201
+ if @text =~ %r{\A//!.*(\n|\Z)}
202
+ # zafu html escaped
203
+ eat $&
204
+ else
205
+ # error
206
+ flush
207
+ end
208
+ end
209
+
194
210
  def scan_tag(opts={})
195
211
  #puts "TAG(#{@method}): [#{@text}]"
196
212
  if @text =~ /\A<r:([\w_]+\??)([^>]*?)(\/?)>/
@@ -8,6 +8,7 @@ module Zafu
8
8
 
9
9
  # This method process a list and handles building the necessary templates for ajax 'add'.
10
10
  def expand_with_finder(finder)
11
+ @context.delete(:make_form) # Do not propagate.
11
12
  return super unless finder[:class].kind_of?(Array)
12
13
 
13
14
  # reset scope
@@ -25,8 +26,14 @@ module Zafu
25
26
  (edit_block && edit_block.params[:publish])
26
27
 
27
28
  # class name for create form
28
- klass = (add_block && add_block.params[:klass]) ||
29
- (form_block && form_block.params[:klass])
29
+ if class_name = (add_block && add_block.params[:klass]) ||
30
+ (form_block && form_block.params[:klass])
31
+ unless klass = get_class(class_name)
32
+ return parser_error("Invalid class '#{class_name}'")
33
+ end
34
+ else
35
+ klass = finder[:class].first
36
+ end
30
37
 
31
38
  if need_ajax?(each_block)
32
39
  # We need to build the templates for ajax rendering.
@@ -35,6 +42,7 @@ module Zafu
35
42
  # assign [] to var
36
43
  out "<% if (#{var} = #{finder[:method]}) || (#{node}.#{finder[:class].first <= Comment ? "can_comment?" : "can_write?"} && #{var}=[]) %>"
37
44
  # The list is not empty or we have enough rights to add new elements.
45
+
38
46
  node.dom_prefix = dom_name
39
47
 
40
48
  # New node context.
@@ -71,7 +79,10 @@ module Zafu
71
79
  :saved_template => form_url(node.dom_prefix),
72
80
  :klass => klass,
73
81
  :make_form => each_block == form_block,
82
+ # Used to get parameters like 'publish', 'done', 'after'
83
+ :add => add_block,
74
84
  :publish_after_save => publish_after_save,
85
+ :node => node.move_to("@node", klass, :new_record => true)
75
86
  }
76
87
 
77
88
  store_block(form_block, cont)
@@ -174,10 +185,11 @@ module Zafu
174
185
  # TODO: show 'reply' instead of 'edit' in comments if visitor != author
175
186
  block = ancestor(%w{each block})
176
187
 
177
- # 'publish' is detected by r_block and set in form.
178
- # removed so it does not polute link
179
- @params.delete('publish')
180
- @params.delete('cancel')
188
+ # These parameters are detected by r_block and set in form.
189
+ # removed so they do not polute link
190
+ @params.delete(:publish)
191
+ @params.delete(:cancel)
192
+ @params.delete(:tcancel)
181
193
 
182
194
  link = wrap(make_link(:default_text => _('edit'), :update => block, :action => 'edit'))
183
195
 
@@ -223,16 +235,7 @@ module Zafu
223
235
  # Expand 'add' block
224
236
  out wrap("#{expand_with(:onclick=>"[\"#{node.dom_prefix}_add\", \"#{node.dom_prefix}_form\"].each(Element.toggle);#{focus}return false;")}")
225
237
 
226
- if klass = @context[:klass]
227
- unless klass = get_class(klass)
228
- out parser_error("Invalid class '#{@context[:klass]}'")
229
- # Clean close ERB
230
- out "<% end -%>"
231
- return
232
- end
233
- else
234
- klass = Array(node.klass).first
235
- end
238
+ klass = @context[:klass] || node.single_class
236
239
 
237
240
  # New object to render form.
238
241
  new_node = node.move_to("#{var}_new", klass, :new_record => true)
@@ -252,7 +255,10 @@ module Zafu
252
255
  out expand_block(form_block,
253
256
  # Needed in form to be able to return the result
254
257
  :template_url => template_url(node.dom_prefix),
255
- # ??
258
+ # Used to avoid wrong dom_id in hidden form. Should not be
259
+ # necessary but it's hard to fix when node changes a lot (drop in add).
260
+ :dom_prefix => node.dom_prefix,
261
+ # Used to add needed hidden fields in form
256
262
  :in_add => true,
257
263
  # Used to get parameters like 'publish' or 'klass'
258
264
  :add => self,
@@ -279,9 +285,11 @@ module Zafu
279
285
  def r_each
280
286
  if @context[:saved_template]
281
287
  # render to start a saved template
288
+ node.saved_dom_id = "\#{ndom_id(#{node})}"
282
289
  node.propagate_dom_scope!
290
+ @markup.set_id(node.dom_id)
291
+
283
292
  options = form_options
284
- @markup.set_id(options[:id]) if options[:id]
285
293
  @markup.set_param(:style, options[:style]) if options[:style]
286
294
 
287
295
  out wrap(expand_with)
@@ -384,12 +392,12 @@ module Zafu
384
392
 
385
393
  def store_block(block, cont = {})
386
394
  cont, prefix = context_for_partial(cont)
387
- # Keep dom prefix
388
- dom_prefix = node.dom_prefix
389
395
 
390
396
  # Create new node context
391
397
  node = cont[:node].as_main(ActiveRecord::Base)
392
- node.dom_prefix = dom_prefix
398
+
399
+ # The dom_id will be calculated from the Ajax params in the view.
400
+ node.saved_dom_id = "\#{ndom_id(#{node})}"
393
401
 
394
402
  cont[:template_url] = template_url(node.dom_prefix)
395
403
  cont[:node] = node
@@ -29,22 +29,28 @@ module Zafu
29
29
 
30
30
  # We use 'elsif' just in case there are more then one 'else' clause
31
31
  if markup = @context[:markup]
32
- # Copy markup tag
33
- @markup.tag ||= markup.tag
34
- @markup.steal_html_params_from(@params)
35
- markup.params.each do |k, v|
36
- next if @markup.params[k]
37
- @markup.set_param(k, v)
38
- end
32
+ if @markup.tag.blank?
33
+ # Copy markup tag
34
+ @markup.tag = markup.tag
35
+ @markup.steal_html_params_from(@params)
36
+ markup.params.each do |k, v|
37
+ next if @markup.params[k]
38
+ @markup.set_param(k, v)
39
+ end
39
40
 
40
- markup.dyn_params.each do |k, v|
41
- next if @markup.params[k] || @markup.dyn_params[k]
42
- @markup.set_dyn_param(k, v)
41
+ markup.dyn_params.each do |k, v|
42
+ next if @markup.params[k] || @markup.dyn_params[k]
43
+ @markup.set_dyn_param(k, v)
44
+ end
45
+ inner = wrap(res)
46
+ else
47
+ markup.done = false
48
+ # Wrap with both markup (ours and the else/elsif clause).
49
+ inner = markup.wrap(wrap(res))
43
50
  end
44
-
45
- out "<% elsif #{cond} %>#{wrap(res)}" # do not propagate
51
+ out "<% elsif #{cond} %>#{inner}" # do not propagate
46
52
  else
47
- @markup.done = true # never wrap else/elsif clause
53
+ #@markup.done = true # never wrap else/elsif clause
48
54
  out "<% elsif #{cond} %>#{res}" # do not propagate
49
55
  end
50
56
  end
@@ -72,7 +78,11 @@ module Zafu
72
78
  private
73
79
  def get_condition
74
80
  if in_tag = @params[:in]
75
- ancestor(in_tag) ? 'true' : 'false'
81
+ if in_tag == 'form' && @context[:make_form]
82
+ 'true'
83
+ else
84
+ ancestor(in_tag) ? 'true' : 'false'
85
+ end
76
86
  else
77
87
  get_attribute_or_eval(false)
78
88
  end
@@ -10,6 +10,8 @@ module Zafu
10
10
  return ''
11
11
  end
12
12
 
13
+ return parser_error('Cannot render update form in list context.') if node.list_context?
14
+
13
15
  options = form_options
14
16
 
15
17
  @markup.set_id(options[:id]) if options[:id]
@@ -34,6 +34,13 @@ module Zafu
34
34
  obj.markup = @markup.dup
35
35
  end
36
36
  @markup.tag = nil
37
+
38
+ if sub_do
39
+ obj.method = @blocks.first.method
40
+ obj.params = @blocks.first.params
41
+ elsif params[:method]
42
+ obj.method = params[:method]
43
+ end
37
44
  super(obj)
38
45
  end
39
46
 
@@ -111,7 +118,7 @@ module Zafu
111
118
  end
112
119
 
113
120
  src = @params.delete(key)
114
- if src && src[0..6] != 'http://'
121
+ if src && src[0..7] != 'http://'
115
122
  new_value = helper.send(:template_url_for_asset, :src => src, :base_path => @options[:base_path], :type => type)
116
123
  @markup.params[key] = new_value.blank? ? src : new_value
117
124
  end
@@ -33,7 +33,7 @@ module Zafu
33
33
 
34
34
  rubyless_render(@method, params)
35
35
  rescue RubyLess::NoMethodError => err
36
- parser_continue("#{err.error_message} <span class='type'>#{err.method_with_arguments}</span> for #{err.receiver_with_class}")
36
+ parser_continue("#{err.error_message} <span class='type'>#{err.method_with_arguments}</span> (#{node.klass} context)")
37
37
  rescue RubyLess::Error => err
38
38
  parser_continue(err.message)
39
39
  end
@@ -133,7 +133,7 @@ module Zafu
133
133
  end
134
134
 
135
135
  private
136
- # Extract arguments from params
136
+ # Extract arguments from params (evaluates params as RubyLess strings).
137
137
  def extract_from_params(*keys)
138
138
  res = []
139
139
 
@@ -272,7 +272,6 @@ module Zafu
272
272
  # Find a class or behavior based on a name. The returned class should implement
273
273
  # 'safe_method_type'.
274
274
  def get_class(class_name)
275
- deb class_name
276
275
  Module.const_get(class_name)
277
276
  rescue
278
277
  nil
data/test/mock/params.rb CHANGED
@@ -9,5 +9,10 @@ module Mock
9
9
  out_post str
10
10
  end
11
11
  end
12
+
13
+
14
+ def r_inspect
15
+ out "#{@params.inspect}"
16
+ end
12
17
  end
13
18
  end
data/test/zafu/basic.yml CHANGED
@@ -13,3 +13,19 @@ empty_do:
13
13
  do_with_escaped_quote:
14
14
  src: "<li do='raw(\'blah\')'>blah</li>"
15
15
  tem: "<li><%= raw(\"blah\") %></li>"
16
+
17
+ quotes_in_quotes:
18
+ src: "<r:inspect line_numbers='true' text=\"<code lang='lua'&gt;function foo(a); print(a); end</code&gt;\"/>"
19
+ tem: "/:text=>\"<code lang='lua'>function foo\(a\); print\(a\); end</code>\"/"
20
+
21
+ comment:
22
+ src: "<r:raw>hello</r:raw> //! This is a comment that will be removed"
23
+ tem: "<%= raw(\"hello\") %>"
24
+
25
+ line_comment:
26
+ src: "<r:raw>hello</r:raw>\n//! This is a comment that will be removed\nabc"
27
+ tem: "<%= raw(\"hello\") %>\nabc"
28
+
29
+ do_not_touch_js_comment:
30
+ src: "<r:raw>hello</r:raw> // This is a comment that will not be removed"
31
+ tem: "<%= raw(\"hello\") %> // This is a comment that will not be removed"
data/zafu.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{zafu}
8
- s.version = "0.7.9"
8
+ s.version = "0.8.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Gaspard Bucher"]
12
- s.date = %q{2011-05-26}
12
+ s.date = %q{2011-06-15}
13
13
  s.description = %q{Provides a powerful templating language based on xhtml for rails}
14
14
  s.email = %q{gaspard@teti.ch}
15
15
  s.extra_rdoc_files = [
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zafu
3
3
  version: !ruby/object:Gem::Version
4
- hash: 17
4
+ hash: 63
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 7
9
- - 9
10
- version: 0.7.9
8
+ - 8
9
+ - 0
10
+ version: 0.8.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Gaspard Bucher
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-26 00:00:00 +02:00
18
+ date: 2011-06-15 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency