zafu 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|