zafu 0.6.0 → 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +10 -0
- data/lib/zafu/info.rb +1 -1
- data/lib/zafu/markup.rb +20 -7
- data/lib/zafu/node_context.rb +23 -11
- data/lib/zafu/parser.rb +54 -22
- data/lib/zafu/process/ajax.rb +113 -42
- data/lib/zafu/process/conditional.rb +35 -10
- data/lib/zafu/process/context.rb +53 -18
- data/lib/zafu/process/forms.rb +11 -8
- data/lib/zafu/process/html.rb +2 -1
- data/lib/zafu/process/ruby_less_processing.rb +51 -14
- data/test/markup_test.rb +42 -5
- data/test/node_context_test.rb +30 -11
- data/test/zafu/meta.yml +5 -1
- data/zafu.gemspec +2 -2
- metadata +3 -3
data/History.txt
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
== 0.6.1 2010-07-22
|
2
|
+
|
3
|
+
* Minor enhancements
|
4
|
+
* Moved dependent method 'get_attribute_or_eval' from Zena.
|
5
|
+
* Fixed bugs in Markup#dup and NodeContext changing.
|
6
|
+
* Fixed error reporting on missing template.
|
7
|
+
* Added 'pre_wrap' method to Markup.
|
8
|
+
* Refactored wrapping to use a single method call.
|
9
|
+
* Fixed block in each dom scoping.
|
10
|
+
|
1
11
|
== 0.6.0 2010-05-27
|
2
12
|
|
3
13
|
* 3 major enhancements
|
data/lib/zafu/info.rb
CHANGED
data/lib/zafu/markup.rb
CHANGED
@@ -165,6 +165,10 @@ module Zafu
|
|
165
165
|
end
|
166
166
|
end
|
167
167
|
|
168
|
+
def append_attribute(text_to_append)
|
169
|
+
(@append ||= '') << text_to_append
|
170
|
+
end
|
171
|
+
|
168
172
|
def append_dyn_param(key, value, conditional = false)
|
169
173
|
spacer = conditional ? '' : ' '
|
170
174
|
if prev_value = @params.delete(key)
|
@@ -189,26 +193,35 @@ module Zafu
|
|
189
193
|
|
190
194
|
# Duplicate markup and make sure params and dyn_params are duplicated as well.
|
191
195
|
def dup
|
192
|
-
markup =
|
193
|
-
markup.params
|
194
|
-
markup.dyn_params
|
196
|
+
markup = super
|
197
|
+
markup.instance_variable_set(:@params, @params.dup)
|
198
|
+
markup.instance_variable_set(:@dyn_params, @dyn_params.dup)
|
199
|
+
markup.instance_variable_set(:@pre_wrap, @pre_wrap.dup) if @pre_wrap
|
195
200
|
markup
|
196
201
|
end
|
197
202
|
|
203
|
+
# Store some text to insert at the beggining of the tag content on wrap. Inserted
|
204
|
+
# elements are indexed in a hash but only values are shown.
|
205
|
+
def pre_wrap
|
206
|
+
@pre_wrap ||= {}
|
207
|
+
end
|
208
|
+
|
198
209
|
# Wrap the given text with our tag. If 'append' is not empty, append the text
|
199
210
|
# after the tag parameters: <li class='foo'[APPEND HERE]>text</li>.
|
200
|
-
def wrap(text
|
211
|
+
def wrap(text)
|
201
212
|
return text if @done
|
213
|
+
|
214
|
+
text = "#{@pre_wrap.values}#{text}" if @pre_wrap
|
215
|
+
|
202
216
|
if dyn_params[:id]
|
203
217
|
@tag ||= 'div'
|
204
218
|
end
|
205
219
|
|
206
|
-
append ||= []
|
207
220
|
if @tag
|
208
221
|
if text.blank? && EMPTY_TAGS.include?(@tag)
|
209
|
-
res = "<#{@tag}#{params_to_html}#{append
|
222
|
+
res = "#{@pre_wrap}<#{@tag}#{params_to_html}#{@append}/>"
|
210
223
|
else
|
211
|
-
res = "<#{@tag}#{params_to_html}#{append
|
224
|
+
res = "<#{@tag}#{params_to_html}#{@append}>#{text}</#{@tag}>"
|
212
225
|
end
|
213
226
|
else
|
214
227
|
res = text
|
data/lib/zafu/node_context.rb
CHANGED
@@ -36,10 +36,11 @@ module Zafu
|
|
36
36
|
# Return a new node context that corresponds to the current object when rendered alone (in an ajax response or
|
37
37
|
# from a direct 'show' in a controller). The returned node context has no parent (up is nil).
|
38
38
|
# The convention is to use the class of the current object to build this name.
|
39
|
-
# You can also use an 'after_class' parameter to move up in the current object's class hierarchy
|
39
|
+
# You can also use an 'after_class' parameter to move up in the current object's class hierarchy to get
|
40
|
+
# ivar name (see #master_class).
|
40
41
|
def as_main(after_class = nil)
|
41
|
-
klass = after_class ? master_class(after_class) : self.klass
|
42
|
-
NodeContext.new("@#{klass.to_s.underscore}", klass)
|
42
|
+
klass = after_class ? master_class(after_class) : Array(self.klass).first
|
43
|
+
NodeContext.new("@#{klass.to_s.underscore}", Array(self.klass).first)
|
43
44
|
end
|
44
45
|
|
45
46
|
# Find the class just afer 'after_class' in the class hierarchy.
|
@@ -56,12 +57,23 @@ module Zafu
|
|
56
57
|
end
|
57
58
|
|
58
59
|
# Generate a unique DOM id for this element based on dom_scopes defined in parent contexts.
|
59
|
-
def dom_id
|
60
|
-
|
60
|
+
def dom_id(opts = {})
|
61
|
+
options = {:list => true, :erb => true}.merge(opts)
|
62
|
+
|
63
|
+
if options[:erb]
|
64
|
+
dom = dom_id(options.merge(:erb => false))
|
65
|
+
if dom =~ /^#\{([^\{]+)\}$/
|
66
|
+
"<%= #{$1} %>"
|
67
|
+
elsif dom =~ /#\{/
|
68
|
+
"<%= %Q{#{dom}} %>"
|
69
|
+
else
|
70
|
+
dom
|
71
|
+
end
|
72
|
+
else
|
61
73
|
if @up
|
62
|
-
[dom_prefix] + @up.dom_scopes + [make_scope_id]
|
74
|
+
[dom_prefix] + @up.dom_scopes + (options[:list] ? [make_scope_id] : [])
|
63
75
|
else
|
64
|
-
[dom_prefix] + [make_scope_id]
|
76
|
+
[dom_prefix] + (options[:list] ? [make_scope_id] : [])
|
65
77
|
end.compact.uniq.join('_')
|
66
78
|
end
|
67
79
|
end
|
@@ -74,20 +86,20 @@ module Zafu
|
|
74
86
|
|
75
87
|
# Mark the current context as being a looping element (each) whose DOM id needs to be propagated to sub-nodes
|
76
88
|
# in order to ensure uniqueness of the dom_id (loops in loops problem).
|
77
|
-
def
|
89
|
+
def propagate_dom_scope!
|
78
90
|
@dom_scope = true
|
79
91
|
end
|
80
92
|
|
81
93
|
def get(klass)
|
82
94
|
if list_context?
|
83
|
-
if klass <=
|
95
|
+
if self.klass.first <= klass
|
84
96
|
NodeContext.new("#{self.name}.first", self.klass.first)
|
85
97
|
elsif @up
|
86
98
|
@up.get(klass)
|
87
99
|
else
|
88
100
|
nil
|
89
101
|
end
|
90
|
-
elsif self.klass
|
102
|
+
elsif self.klass <= klass
|
91
103
|
return self
|
92
104
|
elsif @up
|
93
105
|
@up.get(klass)
|
@@ -134,7 +146,7 @@ module Zafu
|
|
134
146
|
|
135
147
|
private
|
136
148
|
def make_scope_id
|
137
|
-
"
|
149
|
+
"\#{#{@name}.zip}"
|
138
150
|
end
|
139
151
|
end
|
140
152
|
end
|
data/lib/zafu/parser.rb
CHANGED
@@ -9,12 +9,23 @@ module Zafu
|
|
9
9
|
end
|
10
10
|
|
11
11
|
class Parser
|
12
|
-
|
13
|
-
|
12
|
+
# If you wonder what the difference is between 'after_wrap' and 'after_process' here it is:
|
13
|
+
# 'after_wrap' is called by the 'wrap' method from within the method handler, 'after_process' is called
|
14
|
+
# at the very end. Example:
|
15
|
+
#
|
16
|
+
# <% if var = Node.all -%> | <---
|
17
|
+
# <li>...</li> <--- content for after_wrap | <--- content for after_process
|
18
|
+
# <% end -%> | <---
|
19
|
+
#
|
20
|
+
|
21
|
+
|
22
|
+
TEXT_CALLBACKS = %w{before_parse after_parse before_wrap wrap after_wrap after_process}
|
23
|
+
PROCESS_CALLBACKS = %w{before_process expander process_unknown}
|
14
24
|
CALLBACKS = TEXT_CALLBACKS + PROCESS_CALLBACKS
|
15
25
|
|
16
26
|
@@callbacks = {}
|
17
|
-
attr_accessor :text, :method, :pass, :options, :blocks, :ids, :defined_ids, :parent, :errors
|
27
|
+
attr_accessor :text, :name, :method, :pass, :options, :blocks, :ids, :defined_ids, :parent, :errors
|
28
|
+
|
18
29
|
# Method parameters "<r:show attr='name'/>" (params contains {'attr' => 'name'}).
|
19
30
|
attr_accessor :params
|
20
31
|
|
@@ -22,6 +33,7 @@ module Zafu
|
|
22
33
|
def new_with_url(path, opts={})
|
23
34
|
helper = opts[:helper] || Zafu::MockHelper.new
|
24
35
|
text, fullpath, base_path = self.get_template_text(path, helper)
|
36
|
+
return parser_error("template '#{path}' not found", 'include') unless text
|
25
37
|
self.new(text, :helper => helper, :base_path => base_path, :included_history => [fullpath], :root => path)
|
26
38
|
end
|
27
39
|
|
@@ -34,7 +46,11 @@ module Zafu
|
|
34
46
|
end
|
35
47
|
|
36
48
|
def parser_error(message, method)
|
37
|
-
"<span class='parser_error'><span class='method'>#{method}
|
49
|
+
"<span class='parser_error'><span class='method'>#{erb_safe method}</span> <span class='message'>#{erb_safe message}</span></span>"
|
50
|
+
end
|
51
|
+
|
52
|
+
def erb_safe(text)
|
53
|
+
text.gsub('<%', '<%').gsub('%>', '%>')
|
38
54
|
end
|
39
55
|
|
40
56
|
CALLBACKS.each do |clbk|
|
@@ -85,6 +101,17 @@ module Zafu
|
|
85
101
|
}
|
86
102
|
end
|
87
103
|
|
104
|
+
alias wrap_callbacks wrap
|
105
|
+
|
106
|
+
def wrap(text)
|
107
|
+
after_wrap(
|
108
|
+
wrap_callbacks(
|
109
|
+
before_wrap(text) + @out_post
|
110
|
+
)
|
111
|
+
# @text contains unparsed data (white space)
|
112
|
+
) + @text
|
113
|
+
end
|
114
|
+
|
88
115
|
# This method is called at the very beginning of the processing chain and is
|
89
116
|
# used to store state to make 'process' reintrant...
|
90
117
|
def save_state
|
@@ -104,9 +131,17 @@ module Zafu
|
|
104
131
|
end
|
105
132
|
end
|
106
133
|
|
107
|
-
def parser_error(message, method = @method)
|
108
|
-
|
109
|
-
|
134
|
+
def parser_error(message, method = @method, halt = true)
|
135
|
+
if halt
|
136
|
+
self.class.parser_error(message, method)
|
137
|
+
else
|
138
|
+
@errors << self.class.parser_error(message, method)
|
139
|
+
nil
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def parser_continue(message, method = @method)
|
144
|
+
parser_error(message, method, false)
|
110
145
|
end
|
111
146
|
|
112
147
|
def process_unknown
|
@@ -194,7 +229,7 @@ module Zafu
|
|
194
229
|
def process(context={})
|
195
230
|
return '' if @method == 'ignore' || @method.blank?
|
196
231
|
|
197
|
-
|
232
|
+
saved = save_state
|
198
233
|
|
199
234
|
if @name
|
200
235
|
# we pass the name as 'context' in the children tags
|
@@ -209,18 +244,12 @@ module Zafu
|
|
209
244
|
|
210
245
|
@pass = {} # used to pass information to the parent (is this used ?)
|
211
246
|
|
212
|
-
res = expander || default_expander
|
213
|
-
|
214
|
-
res = before_wrap(res)
|
215
|
-
res = wrap(res + @out_post)
|
247
|
+
res = wrap(expander || default_expander)
|
216
248
|
|
217
|
-
|
218
|
-
res = after_wrap(res) + @text
|
219
|
-
|
220
|
-
after_process
|
249
|
+
res = after_process(res)
|
221
250
|
|
222
251
|
# restore state
|
223
|
-
restore_state(
|
252
|
+
restore_state(saved)
|
224
253
|
|
225
254
|
res
|
226
255
|
end
|
@@ -287,7 +316,7 @@ module Zafu
|
|
287
316
|
end
|
288
317
|
|
289
318
|
def include_template
|
290
|
-
return parser_error("missing 'template' attribute"
|
319
|
+
return parser_error("missing 'template' attribute") unless @params[:template]
|
291
320
|
if @options[:part] && @options[:part] == @params[:part]
|
292
321
|
# fetching only a part, do not open this element (same as original caller) as it is useless and will make us loop the loop.
|
293
322
|
@method = 'ignore'
|
@@ -301,7 +330,7 @@ module Zafu
|
|
301
330
|
|
302
331
|
included_text, absolute_url, base_path = self.class.get_template_text(@params[:template], @options[:helper], @options[:base_path])
|
303
332
|
|
304
|
-
if
|
333
|
+
if absolute_url
|
305
334
|
absolute_url += "::#{@params[:part].gsub('/','_')}" if @params[:part]
|
306
335
|
absolute_url += "??#{@options[:part].gsub('/','_')}" if @options[:part]
|
307
336
|
if @options[:included_history].include?(absolute_url)
|
@@ -310,7 +339,9 @@ module Zafu
|
|
310
339
|
included_history = @options[:included_history] + [absolute_url]
|
311
340
|
end
|
312
341
|
else
|
313
|
-
|
342
|
+
# Error: included_text contains the error meessage
|
343
|
+
@blocks = [included_text]
|
344
|
+
return
|
314
345
|
end
|
315
346
|
|
316
347
|
res = self.class.new(included_text, :helper => @options[:helper], :base_path => base_path, :included_history => included_history, :part => @params[:part], :parent => self) # we set :part to avoid loop failure when doing self inclusion
|
@@ -558,6 +589,7 @@ module Zafu
|
|
558
589
|
end
|
559
590
|
|
560
591
|
def expand_with(acontext={})
|
592
|
+
|
561
593
|
blocks = acontext.delete(:blocks) || @blocks
|
562
594
|
res = ""
|
563
595
|
|
@@ -580,10 +612,10 @@ module Zafu
|
|
580
612
|
|
581
613
|
blocks.each do |b|
|
582
614
|
if b.kind_of?(String)
|
583
|
-
if (!only || only.include?(:string)) && (!ignore || !ignore.include?(:string))
|
615
|
+
if (!only || (only.kind_of?(Array) && only.include?(:string))) && (!ignore || !ignore.include?(:string))
|
584
616
|
res << b
|
585
617
|
end
|
586
|
-
elsif (!only || only.include?(b.method)) && (!ignore || !ignore.include?(b.method))
|
618
|
+
elsif (!only || (only.kind_of?(Array) && only.include?(b.method)) || only =~ b.method) && (!ignore || !ignore.include?(b.method))
|
587
619
|
res << b.process(new_context.dup)
|
588
620
|
if pass = b.pass
|
589
621
|
if pass[:part]
|
data/lib/zafu/process/ajax.rb
CHANGED
@@ -10,6 +10,9 @@ module Zafu
|
|
10
10
|
def expand_with_finder(finder)
|
11
11
|
return super unless finder[:class].kind_of?(Array)
|
12
12
|
|
13
|
+
# reset scope
|
14
|
+
@context[:saved_template] = nil
|
15
|
+
|
13
16
|
# Get the block responsible for rendering each elements in the list
|
14
17
|
each_block = descendant('each')
|
15
18
|
add_block = descendant('add')
|
@@ -35,14 +38,14 @@ module Zafu
|
|
35
38
|
set_dom_prefix
|
36
39
|
|
37
40
|
# New node context.
|
38
|
-
open_node_context(finder, :node => self.node.move_to(var, finder[:class])) do
|
41
|
+
open_node_context(finder, :node => self.node.move_to(var, finder[:class])) do
|
39
42
|
# Pagination count and other contextual variables exist here.
|
40
43
|
|
41
44
|
# INLINE ==========
|
42
|
-
|
43
|
-
out @markup.wrap(
|
45
|
+
out wrap(
|
44
46
|
expand_with(
|
45
47
|
:in_if => false,
|
48
|
+
# 'r_add' needs the form when rendering. Send with :form.
|
46
49
|
:form => form_block,
|
47
50
|
:publish_after_save => publish_after_save,
|
48
51
|
# Do not render the form block directly: let [add] do this.
|
@@ -53,32 +56,32 @@ module Zafu
|
|
53
56
|
|
54
57
|
# Render 'else' clauses
|
55
58
|
@markup.done = false
|
56
|
-
out
|
59
|
+
out wrap(
|
57
60
|
expand_with(
|
58
61
|
:in_if => true,
|
59
62
|
:only => ['elsif', 'else']
|
60
63
|
)
|
61
64
|
)
|
62
|
-
end
|
63
|
-
out "<% end -%>"
|
64
65
|
|
65
|
-
|
66
|
-
|
66
|
+
# 2. Save 'each' template
|
67
|
+
store_block(each_block, :node => self.node.move_to(var, finder[:class])) #, :klass => klass) # do we need klass here ?
|
67
68
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
69
|
+
# 3. Save 'form' template
|
70
|
+
cont = {
|
71
|
+
:saved_template => form_url(node.dom_prefix),
|
72
|
+
:klass => klass,
|
73
|
+
:make_form => each_block == form_block,
|
74
|
+
:publish_after_save => publish_after_save,
|
75
|
+
}
|
75
76
|
|
76
|
-
|
77
|
+
store_block(form_block, cont)
|
78
|
+
end
|
79
|
+
out "<% end -%>"
|
77
80
|
else
|
78
81
|
super
|
79
82
|
end
|
80
83
|
|
81
|
-
# out
|
84
|
+
# out wrap(expand_with(:node => node.move_to(var, finder[:class]), :in_if => true))
|
82
85
|
|
83
86
|
|
84
87
|
#query = opts[:query]
|
@@ -114,13 +117,21 @@ module Zafu
|
|
114
117
|
|
115
118
|
# Store a context as a sub-template that can be used in ajax calls
|
116
119
|
def r_block
|
120
|
+
if parent.method == 'each' && @method == parent.single_child_method
|
121
|
+
# Block stored in 'each', do nothing
|
122
|
+
# What happens when this is used as remote target ?
|
123
|
+
return expand_with
|
124
|
+
end
|
125
|
+
|
117
126
|
# Since we are using ajax, we will need this object to have an ID set.
|
118
127
|
set_dom_prefix
|
119
128
|
|
129
|
+
@markup.done = false
|
130
|
+
|
120
131
|
if @context[:block] == self
|
121
132
|
# Storing template (called from within store_block)
|
122
|
-
# Set id with the template's node context (<%= @node.zip %>)
|
123
|
-
@markup.set_id(node.dom_id)
|
133
|
+
# Set id with the template's node context (<%= @node.zip %>).
|
134
|
+
@markup.set_id(node.dom_id(:list => false))
|
124
135
|
expand_with
|
125
136
|
else
|
126
137
|
# 1. store template
|
@@ -128,14 +139,43 @@ module Zafu
|
|
128
139
|
store_block(self)
|
129
140
|
|
130
141
|
# 2. render
|
131
|
-
# Set id with the current node context (<%= var1.zip %>)
|
132
|
-
@markup.set_id(node.dom_id)
|
142
|
+
# Set id with the current node context (<%= var1.zip %>).
|
143
|
+
@markup.set_id(node.dom_id(:list => false))
|
133
144
|
out expand_with
|
134
145
|
end
|
135
146
|
end
|
136
147
|
|
148
|
+
|
149
|
+
def r_edit
|
150
|
+
# ajax
|
151
|
+
if @context[:form_cancel]
|
152
|
+
# cancel button
|
153
|
+
@context[:form_cancel]
|
154
|
+
else
|
155
|
+
# edit button
|
156
|
+
|
157
|
+
# TODO: show 'reply' instead of 'edit' in comments if visitor != author
|
158
|
+
each_block = ancestor('each')
|
159
|
+
|
160
|
+
link = wrap(make_link(:default_text => _('edit'), :update => each_block, :action => 'edit'))
|
161
|
+
|
162
|
+
out "<% if #{node}.can_write? -%>#{link}<% end -%>"
|
163
|
+
end
|
164
|
+
|
165
|
+
#if @context[:template_url]
|
166
|
+
#else
|
167
|
+
# # FIXME: we could link to some html page to edit the item.
|
168
|
+
# ""
|
169
|
+
#end
|
170
|
+
end
|
171
|
+
|
172
|
+
def r_cancel
|
173
|
+
(@context[:form_options] || {})[:form_cancel]
|
174
|
+
end
|
175
|
+
|
137
176
|
def r_add
|
138
177
|
return parser_error("Should not be called from within 'each'") if parent.method == 'each'
|
178
|
+
return parser_error("Should not be called outside list context") unless node.list_context?
|
139
179
|
return '' if @context[:make_form]
|
140
180
|
|
141
181
|
if node.will_be?(Comment)
|
@@ -165,7 +205,7 @@ module Zafu
|
|
165
205
|
end
|
166
206
|
|
167
207
|
# Expand 'add' block
|
168
|
-
out
|
208
|
+
out wrap("#{expand_with(:onclick=>"[\"#{node.dom_prefix}_add\", \"#{node.dom_prefix}_form\"].each(Element.toggle);#{focus}return false;")}")
|
169
209
|
|
170
210
|
# New object to render form.
|
171
211
|
# FIXME: use 'klass' param in r_add or r_form instead of current list content.
|
@@ -185,10 +225,10 @@ module Zafu
|
|
185
225
|
# Expand (inline) 'form' block
|
186
226
|
out expand_block(form_block,
|
187
227
|
# Needed in form to be able to return the result
|
188
|
-
:template_url => template_url(node),
|
228
|
+
:template_url => template_url(node.dom_prefix),
|
189
229
|
# ??
|
190
230
|
:in_add => true,
|
191
|
-
#
|
231
|
+
# Used to get parameters like 'publish' or 'klass'
|
192
232
|
:add => self,
|
193
233
|
# Transform 'each' block into a form
|
194
234
|
:make_form => form_block.method == 'each',
|
@@ -199,7 +239,7 @@ module Zafu
|
|
199
239
|
else
|
200
240
|
# no ajax
|
201
241
|
@markup.append_param(:class, 'btn_add') if @markup.tag
|
202
|
-
out
|
242
|
+
out wrap(expand_with)
|
203
243
|
end
|
204
244
|
out "<% end -%>"
|
205
245
|
end
|
@@ -217,30 +257,49 @@ module Zafu
|
|
217
257
|
@markup.set_id(options[:id]) if options[:id]
|
218
258
|
@markup.set_param(:style, options[:style]) if options[:style]
|
219
259
|
|
220
|
-
out
|
260
|
+
out wrap(expand_with)
|
221
261
|
else
|
222
262
|
super
|
223
263
|
end
|
224
264
|
end
|
225
265
|
|
226
|
-
#
|
266
|
+
# Block visibility of descendance with 'do_list'.
|
267
|
+
def public_descendants
|
268
|
+
all = super
|
269
|
+
if ['context', 'each', 'block'].include?(self.method)
|
270
|
+
# do not propagate 'form',etc up
|
271
|
+
all.reject do |k,v|
|
272
|
+
['form','unlink'].include?(k)
|
273
|
+
end
|
274
|
+
elsif ['if', 'case'].include?(self.method)
|
275
|
+
all.reject do |k,v|
|
276
|
+
['else', 'elsif', 'when'].include?(k)
|
277
|
+
end
|
278
|
+
else
|
279
|
+
all
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# Return true if we need to insert the dom id for this element.
|
227
284
|
def need_dom_id?
|
228
|
-
@context[:form]
|
285
|
+
@context[:form] || descendant('unlink') || descendant('drop')
|
229
286
|
end
|
230
287
|
|
231
288
|
# Set a unique DOM prefix to build unique ids in the page.
|
232
|
-
def set_dom_prefix
|
289
|
+
def set_dom_prefix(node = self.node)
|
233
290
|
@name ||= unique_name
|
291
|
+
raise if @name == 'list3'
|
292
|
+
# TODO: should rebuild descendants list in parents...
|
234
293
|
node.dom_prefix = @name
|
235
294
|
end
|
236
295
|
|
237
296
|
# Unique template_url, ending with dom_id
|
238
|
-
def template_url(node)
|
239
|
-
"#{root.options[:root]}/#{
|
297
|
+
def template_url(dom_prefix = node.dom_prefix)
|
298
|
+
"#{root.options[:root]}/#{dom_prefix}"
|
240
299
|
end
|
241
300
|
|
242
|
-
def form_url(node)
|
243
|
-
template_url(
|
301
|
+
def form_url(dom_prefix = node.dom_prefix)
|
302
|
+
template_url(dom_prefix) + '_form'
|
244
303
|
end
|
245
304
|
|
246
305
|
# Return a different name on each call
|
@@ -263,27 +322,39 @@ module Zafu
|
|
263
322
|
end
|
264
323
|
end
|
265
324
|
|
325
|
+
private
|
266
326
|
|
327
|
+
# Find a block to update on the page
|
328
|
+
def find_target(name)
|
329
|
+
# Hack for drop until descendants is rebuilt on set_dom_prefix
|
330
|
+
return self if name == self.name
|
331
|
+
|
332
|
+
root.descendants('block').each do |block|
|
333
|
+
return block if block.name == name
|
334
|
+
end
|
335
|
+
|
336
|
+
out parser_error("could not find a block named '#{name}'")
|
337
|
+
return nil
|
338
|
+
end
|
267
339
|
|
268
|
-
private
|
269
340
|
def store_block(block, cont = {})
|
270
|
-
cont =
|
341
|
+
cont = context_without_vars.merge(cont)
|
271
342
|
|
272
343
|
# Create new node context
|
273
344
|
node = cont[:node].as_main(ActiveRecord::Base)
|
274
345
|
node.dom_prefix = @name
|
275
346
|
|
276
|
-
cont[:template_url] = template_url(node)
|
347
|
+
cont[:template_url] = template_url(node.dom_prefix)
|
277
348
|
cont[:node] = node
|
278
349
|
cont[:block] = block
|
279
350
|
cont[:saved_template] ||= cont[:template_url]
|
280
|
-
@context.each do |k, v|
|
281
|
-
if k.kind_of?(String)
|
282
|
-
cont[k] = nil
|
283
|
-
end
|
284
|
-
end
|
285
351
|
|
286
|
-
template =
|
352
|
+
template = nil
|
353
|
+
|
354
|
+
# We overwrite all context: no merge.
|
355
|
+
with_context(cont, false) do
|
356
|
+
template = expand_block(block)
|
357
|
+
end
|
287
358
|
|
288
359
|
out helper.save_erb_to_url(template, cont[:saved_template])
|
289
360
|
end
|
@@ -3,8 +3,8 @@ module Zafu
|
|
3
3
|
# This module manages conditional rendering (if, else, elsif, case, when).
|
4
4
|
module Conditional
|
5
5
|
def r_if(cond = nil)
|
6
|
-
cond ||=
|
7
|
-
return
|
6
|
+
cond ||= get_condition
|
7
|
+
return unless cond
|
8
8
|
expand_if(cond)
|
9
9
|
end
|
10
10
|
|
@@ -22,8 +22,8 @@ module Zafu
|
|
22
22
|
|
23
23
|
def r_elsif(cond = nil)
|
24
24
|
return '' unless @context[:in_if]
|
25
|
-
cond ||=
|
26
|
-
return
|
25
|
+
cond ||= get_condition
|
26
|
+
return unless cond
|
27
27
|
|
28
28
|
res = expand_with(:in_if => false, :markup => nil)
|
29
29
|
|
@@ -32,25 +32,50 @@ module Zafu
|
|
32
32
|
@markup.tag ||= markup.tag
|
33
33
|
@markup.steal_html_params_from(@params)
|
34
34
|
markup.params.each do |k, v|
|
35
|
-
next if @markup.
|
35
|
+
next if @markup.params[k]
|
36
36
|
@markup.set_param(k, v)
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
|
+
markup.dyn_params.each do |k, v|
|
40
|
+
next if @markup.params[k] || @markup.dyn_params[k]
|
41
|
+
@markup.set_dyn_param(k, v)
|
42
|
+
end
|
43
|
+
|
44
|
+
out "<% elsif #{cond} -%>#{wrap(res)}" # do not propagate
|
39
45
|
else
|
40
46
|
@markup.done = true # never wrap else/elsif clause
|
41
47
|
out "<% elsif #{cond} -%>#{res}" # do not propagate
|
42
48
|
end
|
43
49
|
end
|
44
50
|
|
45
|
-
# Expand blocks with conditional enabled (else, elsif, etc).
|
46
|
-
|
51
|
+
# Expand blocks with conditional processing enabled (else, elsif, etc).
|
52
|
+
#
|
53
|
+
# ==== Parameters
|
54
|
+
#
|
55
|
+
# * +condition+ - ruby condition for the conditional execution.
|
56
|
+
# * +new_node_context+ - (optional) new node context to enter if the clause succeeds.
|
57
|
+
# * +alt_markup+ - (optional) alternative markup to use for the 'else', 'elsif' clauses.
|
58
|
+
def expand_if(condition, new_node_context = self.node, alt_markup = @markup)
|
47
59
|
res = ""
|
48
60
|
res << "<% if #{condition} -%>"
|
49
|
-
|
50
|
-
|
61
|
+
|
62
|
+
with_context(:node => new_node_context) do
|
63
|
+
res << wrap(expand_with)
|
64
|
+
end
|
65
|
+
|
66
|
+
res << expand_with(:in_if => true, :only => /^[A-Z]|else|elsif|when/, :markup => alt_markup)
|
51
67
|
res << "<% end -%>"
|
52
68
|
res
|
53
69
|
end
|
70
|
+
|
71
|
+
private
|
72
|
+
def get_condition
|
73
|
+
if in_tag = @params[:in]
|
74
|
+
ancestor(in_tag) ? 'true' : 'false'
|
75
|
+
else
|
76
|
+
get_attribute_or_eval(false)
|
77
|
+
end
|
78
|
+
end
|
54
79
|
end # Context
|
55
80
|
end # Process
|
56
81
|
end # Zafu
|
data/lib/zafu/process/context.rb
CHANGED
@@ -5,7 +5,7 @@ module Zafu
|
|
5
5
|
# context, the "node" context holds information on the type of "this" (first responder).
|
6
6
|
module Context
|
7
7
|
def r_each
|
8
|
-
if node.
|
8
|
+
if node.list_context?
|
9
9
|
if @params[:alt_class] || @params[:join]
|
10
10
|
out "<% #{var}_max_index = #{node}.size - 1 -%>" if @params[:alt_reverse]
|
11
11
|
out "<% #{node}.each_with_index do |#{var},#{var}_index| -%>"
|
@@ -31,10 +31,19 @@ module Zafu
|
|
31
31
|
out "<% #{node}.each do |#{var}| -%>"
|
32
32
|
end
|
33
33
|
|
34
|
+
|
34
35
|
with_context(:node => node.move_to(var, node.klass.first)) do
|
36
|
+
# The id set here should be used as prefix for sub-nodes to ensure uniqueness of generated DOM ids
|
37
|
+
node.propagate_dom_scope!
|
38
|
+
|
35
39
|
steal_and_eval_html_params_for(@markup, @params)
|
36
|
-
|
37
|
-
|
40
|
+
|
41
|
+
if need_dom_id?
|
42
|
+
set_dom_prefix
|
43
|
+
@markup.set_id(node.dom_id)
|
44
|
+
end
|
45
|
+
|
46
|
+
out wrap(expand_with)
|
38
47
|
end
|
39
48
|
out "<% end -%>"
|
40
49
|
else
|
@@ -63,28 +72,37 @@ module Zafu
|
|
63
72
|
|
64
73
|
# Store some contextual value / variable inside a named group. This should be
|
65
74
|
# used to avoid key clashes between different types of elements to store.
|
66
|
-
def set_context_var(group, key, obj)
|
67
|
-
|
75
|
+
def set_context_var(group, key, obj, context = @context)
|
76
|
+
context["#{group}::#{key}"] = obj
|
68
77
|
end
|
69
78
|
|
70
79
|
# Retrieve a value from a given contextual group. The value must have been
|
71
80
|
# previously set with 'set_context_var' somewhere in the hierarchy.
|
72
|
-
def get_context_var(group, key)
|
73
|
-
|
81
|
+
def get_context_var(group, key, context = @context)
|
82
|
+
context["#{group}::#{key}"]
|
83
|
+
end
|
84
|
+
|
85
|
+
# Return a new context without contextual variables.
|
86
|
+
def context_without_vars
|
87
|
+
context = @context.dup
|
88
|
+
context.keys.each do |k|
|
89
|
+
context.delete(k) if k.kind_of?(String)
|
90
|
+
end
|
91
|
+
context
|
74
92
|
end
|
75
93
|
|
76
94
|
# Expand blocks in a new context.
|
77
95
|
# This method is partly overwriten in Ajax
|
78
96
|
def expand_with_finder(finder)
|
79
97
|
if finder[:nil]
|
80
|
-
open_node_context(finder) do
|
98
|
+
open_node_context(finder, :form => nil) do # do not propagate :form
|
81
99
|
expand_if("#{var} = #{finder[:method]}", node.move_to(var, finder[:class]))
|
82
100
|
end
|
83
101
|
else
|
84
102
|
res = ''
|
85
103
|
res << "<% #{var} = #{finder[:method]} -%>"
|
86
|
-
open_node_context(finder, :node => node.move_to(var, finder[:class])) do
|
87
|
-
res <<
|
104
|
+
open_node_context(finder, :node => node.move_to(var, finder[:class]), :form => nil) do
|
105
|
+
res << wrap(expand_with)
|
88
106
|
end
|
89
107
|
res
|
90
108
|
end
|
@@ -110,19 +128,36 @@ module Zafu
|
|
110
128
|
{}
|
111
129
|
end
|
112
130
|
|
113
|
-
#
|
114
|
-
#
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
131
|
+
# Get a variable name and store the name in context variables for the given group.
|
132
|
+
#
|
133
|
+
# ==== Parameters
|
134
|
+
#
|
135
|
+
# * +group_name+ - name of the variable context group
|
136
|
+
# * +wanted_name+ - wanted variable name (used as key to get real var back later with #get_context_var)
|
137
|
+
# * +context+ - (optional) can be used if we do not want to store the variable definition in the current context
|
138
|
+
#
|
139
|
+
def get_var_name(group_name, wanted_name, context = @context)
|
140
|
+
secure_name = wanted_name.gsub(/[^a-zA-Z0-9]/,'')
|
141
|
+
name = "_z#{secure_name}"
|
142
|
+
i = 0
|
143
|
+
while get_context_var('var', name, context)
|
144
|
+
i += 1
|
145
|
+
name = "_z#{secure_name}#{i}"
|
146
|
+
end
|
147
|
+
set_context_var('var', name, true)
|
148
|
+
set_context_var(group_name, wanted_name, name)
|
149
|
+
name
|
119
150
|
end
|
120
151
|
|
121
152
|
# Change context for a given scope.
|
122
|
-
def with_context(cont)
|
153
|
+
def with_context(cont, merge = true)
|
123
154
|
raise "Block missing" unless block_given?
|
124
155
|
cont_bak = @context.dup
|
125
|
-
|
156
|
+
if merge
|
157
|
+
@context.merge!(cont)
|
158
|
+
else
|
159
|
+
@context = cont
|
160
|
+
end
|
126
161
|
res = yield
|
127
162
|
@context = cont_bak
|
128
163
|
res
|
data/lib/zafu/process/forms.rb
CHANGED
@@ -13,7 +13,7 @@ module Zafu
|
|
13
13
|
|
14
14
|
if descendant('form_tag')
|
15
15
|
# We have a specific place to insert our form
|
16
|
-
out expand_with(:form_options => options)
|
16
|
+
out expand_with(:form_options => options, :form => self)
|
17
17
|
else
|
18
18
|
r_form_tag(options)
|
19
19
|
end
|
@@ -26,14 +26,16 @@ module Zafu
|
|
26
26
|
@params.each do |k, v|
|
27
27
|
markup.set_param(k, v)
|
28
28
|
end
|
29
|
-
out markup.wrap(expand_with)
|
30
29
|
else
|
31
30
|
# <form> inside <r:form>
|
32
31
|
form_tag(options) do |opts|
|
33
32
|
# Render error messages tag
|
34
33
|
form_error_messages(opts[:form_helper])
|
35
34
|
|
36
|
-
# Render
|
35
|
+
# Render form elements
|
36
|
+
out expand_with(opts)
|
37
|
+
|
38
|
+
# Render hidden fields (these must go after normal elements so that focusFirstElement works)
|
37
39
|
hidden_fields = form_hidden_fields(options)
|
38
40
|
out "<div class='hidden'>"
|
39
41
|
hidden_fields.each do |k,v|
|
@@ -47,9 +49,6 @@ module Zafu
|
|
47
49
|
end
|
48
50
|
out '</div>'
|
49
51
|
|
50
|
-
# Render form elements
|
51
|
-
out expand_with(opts)
|
52
|
-
|
53
52
|
# What is this ?
|
54
53
|
#@blocks = opts[:blocks_bak] if opts[:blocks_bak]
|
55
54
|
end
|
@@ -70,7 +69,10 @@ module Zafu
|
|
70
69
|
# Return id, style, form and cancel parts of the form.
|
71
70
|
def form_options
|
72
71
|
opts = {}
|
73
|
-
|
72
|
+
|
73
|
+
# Do we need this ?
|
74
|
+
# opts[:klass] = node.master_class(ActiveRecord::Base).to_s
|
75
|
+
|
74
76
|
if @context[:in_add]
|
75
77
|
opts[:id] = "#{node.dom_prefix}_form"
|
76
78
|
opts[:style] = 'display:none;'
|
@@ -99,8 +101,9 @@ module Zafu
|
|
99
101
|
# Render the 'form' tag and set expansion context.
|
100
102
|
def form_tag(options)
|
101
103
|
opts = options.dup
|
104
|
+
form = @context[:form]
|
102
105
|
|
103
|
-
if descendant('cancel') || descendant('edit')
|
106
|
+
if form && (form.descendant('cancel') || form.descendant('edit'))
|
104
107
|
# Pass 'form_cancel' content to expand_with (already in options).
|
105
108
|
else
|
106
109
|
# Insert cancel before form
|
data/lib/zafu/process/html.rb
CHANGED
@@ -107,7 +107,8 @@ module Zafu
|
|
107
107
|
|
108
108
|
src = @params.delete(key)
|
109
109
|
if src && src[0..6] != 'http://'
|
110
|
-
|
110
|
+
new_value = helper.send(:template_url_for_asset, :src => src, :base_path => @options[:base_path], :type => type)
|
111
|
+
@markup.params[key] = new_value.blank? ? src : new_value
|
111
112
|
end
|
112
113
|
|
113
114
|
@markup.steal_html_params_from(@params)
|
@@ -12,7 +12,7 @@ module Zafu
|
|
12
12
|
def do_method(sym)
|
13
13
|
super
|
14
14
|
rescue RubyLess::Error => err
|
15
|
-
|
15
|
+
parser_error(err.message)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -27,21 +27,21 @@ module Zafu
|
|
27
27
|
|
28
28
|
# Resolve unknown methods by using RubyLess in the current compilation context (the
|
29
29
|
# translate method in RubyLess will call 'safe_method_type' in this module).
|
30
|
-
def rubyless_eval
|
30
|
+
def rubyless_eval(params = @params)
|
31
31
|
if @method =~ /^[A-Z]\w+$/
|
32
32
|
return rubyless_class_scope(@method)
|
33
33
|
end
|
34
34
|
|
35
35
|
if code = @method[/^\#\{(.+)\}$/, 1]
|
36
|
-
|
36
|
+
params[:eval] = $1
|
37
37
|
r_show
|
38
38
|
else
|
39
|
-
rubyless_render(@method,
|
39
|
+
rubyless_render(@method, params)
|
40
40
|
end
|
41
41
|
rescue RubyLess::NoMethodError => err
|
42
|
-
|
42
|
+
parser_continue("#{err.error_message} <span class='type'>#{err.method_with_arguments}</span> for #{err.receiver_with_class}")
|
43
43
|
rescue RubyLess::Error => err
|
44
|
-
|
44
|
+
parser_continue(err.message)
|
45
45
|
end
|
46
46
|
|
47
47
|
# Print documentation on the current node type.
|
@@ -98,9 +98,40 @@ module Zafu
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
|
101
|
+
def get_attribute_or_eval(use_string_block = true)
|
102
|
+
if attribute = @params[:attr] || @params[:date]
|
103
|
+
code = "this.#{attribute}"
|
104
|
+
elsif code = @params[:eval] || @params[:test]
|
105
|
+
elsif text = @params[:text]
|
106
|
+
code = "%Q{#{text}}"
|
107
|
+
elsif use_string_block && @blocks.size == 1 && @blocks.first.kind_of?(String)
|
108
|
+
return RubyLess::TypedString.new(@blocks.first.inspect, :class => String, :literal => @blocks.first)
|
109
|
+
else
|
110
|
+
return parser_continue("Missing attribute/eval parameter")
|
111
|
+
end
|
112
|
+
|
113
|
+
RubyLess.translate(code, self)
|
114
|
+
rescue RubyLess::Error => err
|
115
|
+
return parser_continue(err.message, code)
|
116
|
+
end
|
117
|
+
|
101
118
|
private
|
119
|
+
# Extract arguments from params
|
120
|
+
def extract_from_params(*keys)
|
121
|
+
res = []
|
122
|
+
|
123
|
+
keys.each do |key|
|
124
|
+
next unless value = @params[key.to_sym]
|
125
|
+
res << ":#{key} => #{RubyLess.translate_string(value, self)}"
|
126
|
+
end
|
127
|
+
|
128
|
+
res.empty? ? nil : res
|
129
|
+
end
|
130
|
+
|
102
131
|
# block_owner should be set to true when we are resolving <r:xxx>...</r:xxx> or <div do='xxx'>...</div>
|
103
132
|
def get_method_type(signature, added_options = false)
|
133
|
+
raise "#{node.klass.class}" unless node.klass.kind_of?(Array) || node.klass.kind_of?(Class)
|
134
|
+
|
104
135
|
if type = node_context_from_signature(signature)
|
105
136
|
# Resolve self, @page, @node
|
106
137
|
type
|
@@ -213,15 +244,21 @@ module Zafu
|
|
213
244
|
def node_context_from_signature(signature)
|
214
245
|
return nil unless signature.size == 1
|
215
246
|
ivar = signature.first
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
247
|
+
if ivar == 'this'
|
248
|
+
if node.list_context?
|
249
|
+
raise RubyLess::Error.new("Cannot use 'this' in list_context.")
|
250
|
+
else
|
251
|
+
{:class => node.klass, :method => node.name}
|
252
|
+
end
|
253
|
+
elsif ivar[0..0] == '@' && klass = get_class(ivar[1..-1].capitalize)
|
254
|
+
if node = self.node(klass)
|
255
|
+
{:class => node.klass, :method => node.name}
|
256
|
+
else
|
257
|
+
nil
|
258
|
+
end
|
259
|
+
else
|
260
|
+
nil
|
223
261
|
end
|
224
|
-
{:class => context.klass, :method => context.name}
|
225
262
|
end
|
226
263
|
|
227
264
|
# Find stored variables back. Stored elements are set with set_xxx='something to eval'.
|
data/test/markup_test.rb
CHANGED
@@ -236,7 +236,7 @@ class MarkupTest < Test::Unit::TestCase
|
|
236
236
|
@markup.append_dyn_param(:class, '<%= @bar %>')
|
237
237
|
assert_equal '<%= @foo %> <%= @bar %>', @markup.dyn_params[:class]
|
238
238
|
end
|
239
|
-
|
239
|
+
|
240
240
|
should 'append param without spacer if conditional' do
|
241
241
|
@markup.append_dyn_param(:class, '<%= @bar %>', true)
|
242
242
|
assert_equal '<%= @foo %><%= @bar %>', @markup.dyn_params[:class]
|
@@ -278,7 +278,7 @@ class MarkupTest < Test::Unit::TestCase
|
|
278
278
|
@markup.prepend_dyn_param(:class, '<%= @to %>')
|
279
279
|
assert_equal '<%= @to %> <%= @fu %>', @markup.dyn_params[:class]
|
280
280
|
end
|
281
|
-
|
281
|
+
|
282
282
|
should 'prepend param without spacer if conditional' do
|
283
283
|
@markup.prepend_dyn_param(:class, '<%= @to %>', true)
|
284
284
|
assert_equal '<%= @to %><%= @fu %>', @markup.dyn_params[:class]
|
@@ -309,6 +309,11 @@ class MarkupTest < Test::Unit::TestCase
|
|
309
309
|
assert_equal "<p class='quote' style='padding:3px; border:1px solid red;'>#{@text}</p>", @markup.wrap(@text)
|
310
310
|
end
|
311
311
|
|
312
|
+
should 'add the appended params inside the tag' do
|
313
|
+
@markup.append_attribute("<%= anything %>")
|
314
|
+
assert_equal "<p class='quote' style='padding:3px; border:1px solid red;'<%= anything %>>#{@text}</p>", @markup.wrap(@text)
|
315
|
+
end
|
316
|
+
|
312
317
|
should 'not wrap twice if called twice' do
|
313
318
|
assert_equal "<p class='quote' style='padding:3px; border:1px solid red;'>#{@text}</p>", @markup.wrap(@markup.wrap(@text))
|
314
319
|
end
|
@@ -318,6 +323,11 @@ class MarkupTest < Test::Unit::TestCase
|
|
318
323
|
@markup.set_params(:baz => 'buzz')
|
319
324
|
assert_equal "<p class='quote' style='padding:3px; border:1px solid red;' baz='buzz' foo='<%= @bar %>'>foo</p>", @markup.wrap('foo')
|
320
325
|
end
|
326
|
+
|
327
|
+
should 'insert pre_wrap content' do
|
328
|
+
@markup.pre_wrap[:foo] = 'FOO'
|
329
|
+
assert_equal %q{<p class='quote' style='padding:3px; border:1px solid red;'>FOOcontent</p>}, @markup.wrap('content')
|
330
|
+
end
|
321
331
|
end
|
322
332
|
|
323
333
|
context 'Compiling params' do
|
@@ -345,14 +355,41 @@ class MarkupTest < Test::Unit::TestCase
|
|
345
355
|
context 'and changing params' do
|
346
356
|
setup do
|
347
357
|
@markup = Markup.new('p')
|
348
|
-
@markup.params[:class]
|
358
|
+
@markup.params[:class] = 'one'
|
349
359
|
@duplicate = @markup.dup
|
350
360
|
end
|
351
361
|
|
352
|
-
should 'not propagate changes to original' do
|
362
|
+
should 'not propagate params changes to original' do
|
353
363
|
@duplicate.params[:class] = 'two'
|
354
364
|
assert_equal "<p class='one'>one</p>", @markup.wrap('one')
|
355
365
|
end
|
366
|
+
|
367
|
+
should 'not propagate params changes to duplicate' do
|
368
|
+
@markup.params[:class] = 'two'
|
369
|
+
assert_equal "<p class='one'>one</p>", @duplicate.wrap('one')
|
370
|
+
end
|
371
|
+
|
372
|
+
should 'not propagate appended params to duplicate' do
|
373
|
+
@markup.append_param(:class, 'drop')
|
374
|
+
assert_equal "<p class='one'>one</p>", @duplicate.wrap('one')
|
375
|
+
end
|
376
|
+
|
377
|
+
should 'not propagate dyn_params changes to original' do
|
378
|
+
@markup.append_dyn_param(:class, 'two')
|
379
|
+
assert_equal "<p class='one'>one</p>", @duplicate.wrap('one')
|
380
|
+
end
|
381
|
+
|
382
|
+
should 'not propagate dyn_params changes to duplicate' do
|
383
|
+
@duplicate.append_dyn_param(:class, 'two')
|
384
|
+
assert_equal "<p class='one'>one</p>", @markup.wrap('one')
|
385
|
+
end
|
386
|
+
|
387
|
+
should 'not propagate pre_wrap changes to duplicate' do
|
388
|
+
@markup.pre_wrap[:drop] = 'no bombs'
|
389
|
+
@duplicate = @markup.dup
|
390
|
+
@duplicate.pre_wrap[:drop] = 'ego'
|
391
|
+
assert_equal "<p class='one'>no bombs</p>", @markup.wrap('')
|
392
|
+
end
|
356
393
|
end
|
357
394
|
|
358
395
|
context 'and wrapping' do
|
@@ -366,7 +403,7 @@ class MarkupTest < Test::Unit::TestCase
|
|
366
403
|
assert_equal '<p>one</p>', @duplicate.wrap('one')
|
367
404
|
end
|
368
405
|
end
|
369
|
-
end
|
406
|
+
end # Duplicating a markup
|
370
407
|
end
|
371
408
|
|
372
409
|
|
data/test/node_context_test.rb
CHANGED
@@ -90,15 +90,30 @@ class NodeContextTest < Test::Unit::TestCase
|
|
90
90
|
assert_equal subject.klass, subject.as_main.klass
|
91
91
|
end
|
92
92
|
|
93
|
-
should 'return
|
93
|
+
should 'return current class when using after_class argument' do
|
94
94
|
subject = NodeContext.new('@node', SubSubPage)
|
95
|
-
assert_equal
|
95
|
+
assert_equal SubSubPage, subject.as_main(Page).klass
|
96
96
|
end
|
97
97
|
|
98
98
|
should 'rebuild name from ancestor when using after_class argument' do
|
99
99
|
subject = NodeContext.new('@node', SubSubPage)
|
100
100
|
assert_equal '@sub_page', subject.as_main(Page).name
|
101
101
|
end
|
102
|
+
|
103
|
+
context 'in a list context' do
|
104
|
+
subject do
|
105
|
+
NodeContext.new('list', [SubSubPage])
|
106
|
+
end
|
107
|
+
|
108
|
+
should 'return current class when using after_class argument' do
|
109
|
+
assert_equal SubSubPage, subject.as_main(Page).klass
|
110
|
+
end
|
111
|
+
|
112
|
+
should 'rebuild name from ancestor when using after_class argument' do
|
113
|
+
assert_equal '@sub_page', subject.as_main(Page).name
|
114
|
+
end
|
115
|
+
end # in a list context
|
116
|
+
|
102
117
|
end
|
103
118
|
|
104
119
|
should 'return subclass on class_name' do
|
@@ -180,14 +195,14 @@ class NodeContextTest < Test::Unit::TestCase
|
|
180
195
|
NodeContext.new('super', SubPage)
|
181
196
|
end
|
182
197
|
|
183
|
-
should 'find the
|
198
|
+
should 'find the required class in ancestors' do
|
184
199
|
assert_equal subject.object_id, subject.get(Page).object_id
|
185
200
|
end
|
186
201
|
end
|
187
202
|
|
188
203
|
context 'In a list context' do
|
189
204
|
setup do
|
190
|
-
@grandma = NodeContext.new('@page',
|
205
|
+
@grandma = NodeContext.new('@page', SubPage)
|
191
206
|
@mother = @grandma.move_to('@comment', Comment)
|
192
207
|
end
|
193
208
|
|
@@ -223,6 +238,10 @@ class NodeContextTest < Test::Unit::TestCase
|
|
223
238
|
should 'return the node name in DOM id' do
|
224
239
|
assert_equal '<%= @foo.zip %>', subject.dom_id
|
225
240
|
end
|
241
|
+
|
242
|
+
should 'scope without erb on erb false' do
|
243
|
+
assert_equal '#{@foo.zip}', subject.dom_id(:erb => false)
|
244
|
+
end
|
226
245
|
end
|
227
246
|
|
228
247
|
context 'in a hierarchy of contexts' do
|
@@ -238,23 +257,23 @@ class NodeContextTest < Test::Unit::TestCase
|
|
238
257
|
|
239
258
|
context 'with parents as dom_scopes' do
|
240
259
|
setup do
|
241
|
-
@b.
|
242
|
-
@c.
|
260
|
+
@b.propagate_dom_scope!
|
261
|
+
@c.propagate_dom_scope!
|
243
262
|
end
|
244
263
|
|
245
264
|
should 'use dom_scopes' do
|
246
|
-
assert_equal '<%= var1.zip
|
265
|
+
assert_equal '<%= %Q{#{var1.zip}_#{var2.zip}_#{var3.zip}} %>', subject.dom_id
|
247
266
|
end
|
248
267
|
end
|
249
268
|
|
250
269
|
context 'with ancestors and self as dom_scopes' do
|
251
270
|
setup do
|
252
|
-
@a.
|
253
|
-
subject.
|
271
|
+
@a.propagate_dom_scope!
|
272
|
+
subject.propagate_dom_scope!
|
254
273
|
end
|
255
274
|
|
256
275
|
should 'not use self twice' do
|
257
|
-
assert_equal '<%= @node.zip
|
276
|
+
assert_equal '<%= %Q{#{@node.zip}_#{var3.zip}} %>', subject.dom_id
|
258
277
|
end
|
259
278
|
end
|
260
279
|
|
@@ -264,7 +283,7 @@ class NodeContextTest < Test::Unit::TestCase
|
|
264
283
|
end
|
265
284
|
|
266
285
|
should 'use dom_prefix' do
|
267
|
-
assert_equal '
|
286
|
+
assert_equal '<%= %Q{cart_#{var3.zip}} %>', subject.dom_id
|
268
287
|
end
|
269
288
|
end
|
270
289
|
|
data/test/zafu/meta.yml
CHANGED
@@ -5,4 +5,8 @@ some_template:
|
|
5
5
|
include_with_part:
|
6
6
|
# part 'a' is moved around
|
7
7
|
src: "<r:include template='/some/template'><r:with part='a'/><r:with part='b'>new b:<r:include template='/some/template' part='a'/></r:with></r:include>"
|
8
|
-
tem: "<div id='b'>new b:<div id='a'>a</div></div>"
|
8
|
+
tem: "<div id='b'>new b:<div id='a'>a</div></div>"
|
9
|
+
|
10
|
+
missing_template:
|
11
|
+
src: "<r:include template='Foo'/>"
|
12
|
+
tem: "/template 'Foo' not found/"
|
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.6.
|
8
|
+
s.version = "0.6.1"
|
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{2010-
|
12
|
+
s.date = %q{2010-07-22}
|
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
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 6
|
8
|
-
-
|
9
|
-
version: 0.6.
|
8
|
+
- 1
|
9
|
+
version: 0.6.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Gaspard Bucher
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-07-22 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|