zafu 0.5.0 → 0.6.0
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 +11 -0
- data/Rakefile +2 -1
- data/lib/zafu/all.rb +6 -4
- data/lib/zafu/controller_methods.rb +27 -18
- data/lib/zafu/info.rb +1 -1
- data/lib/zafu/markup.rb +87 -25
- data/lib/zafu/node_context.rb +48 -4
- data/lib/zafu/ordered_hash.rb +47 -0
- data/lib/zafu/parser.rb +140 -55
- data/lib/zafu/parsing_rules.rb +49 -17
- data/lib/zafu/process/ajax.rb +344 -66
- data/lib/zafu/process/conditional.rb +36 -25
- data/lib/zafu/process/context.rb +101 -4
- data/lib/zafu/process/forms.rb +124 -0
- data/lib/zafu/process/html.rb +78 -83
- data/lib/zafu/process/ruby_less_processing.rb +248 -0
- data/lib/zafu/test_helper.rb +1 -1
- data/lib/zafu/view_methods.rb +6 -0
- data/test/markup_test.rb +150 -8
- data/test/mock/classes.rb +24 -0
- data/test/mock/core_ext.rb +9 -0
- data/test/mock/params.rb +4 -10
- data/test/mock/process.rb +7 -0
- data/test/mock/test_compiler.rb +9 -0
- data/test/node_context_test.rb +135 -46
- data/test/ordered_hash_test.rb +69 -0
- data/test/ruby_less_test.rb +29 -19
- data/test/test_helper.rb +4 -3
- data/test/zafu/ajax.yml +7 -0
- data/test/zafu/asset.yml +3 -0
- data/test/zafu/basic.yml +3 -0
- data/test/zafu/markup.yml +4 -0
- data/test/zafu/meta.yml +8 -0
- data/test/zafu/security.yml +19 -0
- data/test/zafu_test.rb +29 -12
- data/zafu.gemspec +28 -6
- metadata +41 -8
- data/lib/zafu/process/ruby_less.rb +0 -145
data/lib/zafu/process/context.rb
CHANGED
@@ -6,16 +6,54 @@ module Zafu
|
|
6
6
|
module Context
|
7
7
|
def r_each
|
8
8
|
if node.klass.kind_of?(Array)
|
9
|
-
|
10
|
-
|
9
|
+
if @params[:alt_class] || @params[:join]
|
10
|
+
out "<% #{var}_max_index = #{node}.size - 1 -%>" if @params[:alt_reverse]
|
11
|
+
out "<% #{node}.each_with_index do |#{var},#{var}_index| -%>"
|
12
|
+
|
13
|
+
if join = @params[:join]
|
14
|
+
join = RubyLess.translate_string(join, self)
|
15
|
+
#if join_clause = @params[:join_if]
|
16
|
+
# set_stored(Node, 'prev', "#{var}_prev")
|
17
|
+
# cond = get_test_condition(var, :test=>join_clause)
|
18
|
+
# out "<%= #{var}_prev = #{node}[#{var}_index - 1]; (#{var}_index > 0 && #{cond}) ? #{join.inspect} : '' %>"
|
19
|
+
#else
|
20
|
+
out "<%= #{var}_index > 0 ? #{join} : '' %>"
|
21
|
+
#end
|
22
|
+
end
|
23
|
+
|
24
|
+
if alt_class = @params[:alt_class]
|
25
|
+
alt_class = RubyLess.translate_string(alt_class, self)
|
26
|
+
alt_test = @params[:alt_reverse] == 'true' ? "(#{var}_max_index - #{var}_index) % 2 != 0" : "#{var}_index % 2 != 0"
|
27
|
+
@markup.append_dyn_param(:class, "<%= #{alt_test} ? #{alt_class} : '' %>")
|
28
|
+
@markup.tag ||= 'div'
|
29
|
+
end
|
30
|
+
else
|
31
|
+
out "<% #{node}.each do |#{var}| -%>"
|
32
|
+
end
|
33
|
+
|
34
|
+
with_context(:node => node.move_to(var, node.klass.first)) do
|
35
|
+
steal_and_eval_html_params_for(@markup, @params)
|
36
|
+
@markup.set_id(node.dom_id) if need_dom_id?
|
37
|
+
out @markup.wrap(expand_with)
|
38
|
+
end
|
11
39
|
out "<% end -%>"
|
40
|
+
else
|
41
|
+
out expand_with
|
12
42
|
end
|
43
|
+
|
44
|
+
# We need to return true for Ajax 'make_form'
|
45
|
+
true
|
13
46
|
end
|
14
47
|
|
15
48
|
def helper
|
16
49
|
@context[:helper]
|
17
50
|
end
|
18
51
|
|
52
|
+
# Return true if we need to insert the dom id for this element. This method is overwritten in Ajax.
|
53
|
+
def need_dom_id?
|
54
|
+
false
|
55
|
+
end
|
56
|
+
|
19
57
|
# Return the node context for a given class (looks up into the hierarchy) or the
|
20
58
|
# current node context if klass is nil.
|
21
59
|
def node(klass = nil)
|
@@ -23,8 +61,33 @@ module Zafu
|
|
23
61
|
@context[:node].get(klass)
|
24
62
|
end
|
25
63
|
|
26
|
-
|
27
|
-
|
64
|
+
# Store some contextual value / variable inside a named group. This should be
|
65
|
+
# used to avoid key clashes between different types of elements to store.
|
66
|
+
def set_context_var(group, key, obj)
|
67
|
+
@context["#{group}::#{key}"] = obj
|
68
|
+
end
|
69
|
+
|
70
|
+
# Retrieve a value from a given contextual group. The value must have been
|
71
|
+
# previously set with 'set_context_var' somewhere in the hierarchy.
|
72
|
+
def get_context_var(group, key)
|
73
|
+
@context["#{group}::#{key}"]
|
74
|
+
end
|
75
|
+
|
76
|
+
# Expand blocks in a new context.
|
77
|
+
# This method is partly overwriten in Ajax
|
78
|
+
def expand_with_finder(finder)
|
79
|
+
if finder[:nil]
|
80
|
+
open_node_context(finder) do
|
81
|
+
expand_if("#{var} = #{finder[:method]}", node.move_to(var, finder[:class]))
|
82
|
+
end
|
83
|
+
else
|
84
|
+
res = ''
|
85
|
+
res << "<% #{var} = #{finder[:method]} -%>"
|
86
|
+
open_node_context(finder, :node => node.move_to(var, finder[:class])) do
|
87
|
+
res << @markup.wrap(expand_with)
|
88
|
+
end
|
89
|
+
res
|
90
|
+
end
|
28
91
|
end
|
29
92
|
|
30
93
|
# def context_with_node(name, klass)
|
@@ -40,6 +103,40 @@ module Zafu
|
|
40
103
|
@var = "var1"
|
41
104
|
end
|
42
105
|
end
|
106
|
+
|
107
|
+
# This method is called when we enter a new node context
|
108
|
+
def node_context_vars(finder)
|
109
|
+
# do nothing (this is a hook for other modules like QueryBuilder and RubyLess)
|
110
|
+
{}
|
111
|
+
end
|
112
|
+
|
113
|
+
# Declare a variable that can be used later in the compilation. This method
|
114
|
+
# returns the variable name to use.
|
115
|
+
def set_var(var_list, var_name)
|
116
|
+
var_name = var_name.to_sym
|
117
|
+
out parser_error("'#{var_name}' already defined.") if @context[var_name] || var_list[var_name]
|
118
|
+
var_list[var_name] = "_z#{var_name}"
|
119
|
+
end
|
120
|
+
|
121
|
+
# Change context for a given scope.
|
122
|
+
def with_context(cont)
|
123
|
+
raise "Block missing" unless block_given?
|
124
|
+
cont_bak = @context.dup
|
125
|
+
@context.merge!(cont)
|
126
|
+
res = yield
|
127
|
+
@context = cont_bak
|
128
|
+
res
|
129
|
+
end
|
130
|
+
|
131
|
+
# This should be called when we enter a new node context so that the proper hooks are
|
132
|
+
# triggered (insertion of contextual variables).
|
133
|
+
def open_node_context(finder, cont = {})
|
134
|
+
sub_context = node_context_vars(finder).merge(cont)
|
135
|
+
|
136
|
+
with_context(sub_context) do
|
137
|
+
yield
|
138
|
+
end
|
139
|
+
end
|
43
140
|
end # Context
|
44
141
|
end # Process
|
45
142
|
end # Zafu
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Zafu
|
2
|
+
module Process
|
3
|
+
module Forms
|
4
|
+
def self.included(base)
|
5
|
+
base.expander :make_form
|
6
|
+
end
|
7
|
+
|
8
|
+
def r_form
|
9
|
+
options = form_options
|
10
|
+
|
11
|
+
@markup.set_id(options[:id]) if options[:id]
|
12
|
+
@markup.set_param(:style, options[:style]) if options[:style]
|
13
|
+
|
14
|
+
if descendant('form_tag')
|
15
|
+
# We have a specific place to insert our form
|
16
|
+
out expand_with(:form_options => options)
|
17
|
+
else
|
18
|
+
r_form_tag(options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def r_form_tag(options = context[:form_options])
|
23
|
+
if options.blank?
|
24
|
+
# <form> not in <r:form>, just render all
|
25
|
+
markup = Zafu::Markup.new('form')
|
26
|
+
@params.each do |k, v|
|
27
|
+
markup.set_param(k, v)
|
28
|
+
end
|
29
|
+
out markup.wrap(expand_with)
|
30
|
+
else
|
31
|
+
# <form> inside <r:form>
|
32
|
+
form_tag(options) do |opts|
|
33
|
+
# Render error messages tag
|
34
|
+
form_error_messages(opts[:form_helper])
|
35
|
+
|
36
|
+
# Render hidden fields
|
37
|
+
hidden_fields = form_hidden_fields(options)
|
38
|
+
out "<div class='hidden'>"
|
39
|
+
hidden_fields.each do |k,v|
|
40
|
+
if v.kind_of?(String)
|
41
|
+
v = "'#{v}'" unless v.kind_of?(String) && ['"', "'"].include?(v[0..0])
|
42
|
+
out "<input type='hidden' name='#{k}' value=#{v}/>"
|
43
|
+
else
|
44
|
+
# We use ['ffff'] to indicate that the content is already escaped and ready for ERB.
|
45
|
+
out v.first
|
46
|
+
end
|
47
|
+
end
|
48
|
+
out '</div>'
|
49
|
+
|
50
|
+
# Render form elements
|
51
|
+
out expand_with(opts)
|
52
|
+
|
53
|
+
# What is this ?
|
54
|
+
#@blocks = opts[:blocks_bak] if opts[:blocks_bak]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def make_form
|
61
|
+
return nil unless @context[:make_form]
|
62
|
+
|
63
|
+
if method == 'each'
|
64
|
+
r_form
|
65
|
+
else
|
66
|
+
nil
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Return id, style, form and cancel parts of the form.
|
71
|
+
def form_options
|
72
|
+
opts = {}
|
73
|
+
opts[:klass] = node.master_class(ActiveRecord::Base)
|
74
|
+
if @context[:in_add]
|
75
|
+
opts[:id] = "#{node.dom_prefix}_form"
|
76
|
+
opts[:style] = 'display:none;'
|
77
|
+
end
|
78
|
+
|
79
|
+
if @context[:template_url]
|
80
|
+
opts[:form_tag] = "<% remote_form_for(:#{node.form_name}, #{node}, :html => {:id => \"#{node.dom_prefix}_form_t\"}) do |f| %>"
|
81
|
+
opts[:form_helper] = 'f'
|
82
|
+
else
|
83
|
+
opts[:form_tag] = "<% form_for(:#{node.form_name}, #{node}, :html => {:id => \"#{node.dom_prefix}_form_t\"}) do |f| %>"
|
84
|
+
opts[:form_helper] = 'f'
|
85
|
+
end
|
86
|
+
|
87
|
+
opts
|
88
|
+
end
|
89
|
+
|
90
|
+
# Return hidden fields that need to be inserted in the form.
|
91
|
+
def form_hidden_fields(opts)
|
92
|
+
if t_url = @context[:template_url]
|
93
|
+
{'t_url' => t_url}
|
94
|
+
else
|
95
|
+
{}
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Render the 'form' tag and set expansion context.
|
100
|
+
def form_tag(options)
|
101
|
+
opts = options.dup
|
102
|
+
|
103
|
+
if descendant('cancel') || descendant('edit')
|
104
|
+
# Pass 'form_cancel' content to expand_with (already in options).
|
105
|
+
else
|
106
|
+
# Insert cancel before form
|
107
|
+
out opts.delete(:form_cancel).to_s
|
108
|
+
end
|
109
|
+
|
110
|
+
# form_for ... do |f|
|
111
|
+
out opts.delete(:form_tag)
|
112
|
+
# f.xxx
|
113
|
+
yield(opts.merge(:in_form => true))
|
114
|
+
# close form
|
115
|
+
out opts[:form_helper] ? "<% end -%>" : '</form>'
|
116
|
+
end
|
117
|
+
|
118
|
+
def form_error_messages(f)
|
119
|
+
out "<%= #{f}.error_messages %>"
|
120
|
+
end
|
121
|
+
|
122
|
+
end # Forms
|
123
|
+
end # Process
|
124
|
+
end # Zafu
|
data/lib/zafu/process/html.rb
CHANGED
@@ -1,30 +1,36 @@
|
|
1
1
|
module Zafu
|
2
2
|
module Process
|
3
3
|
module HTML
|
4
|
-
|
4
|
+
def self.included(base)
|
5
|
+
base.wrap :wrap_html
|
6
|
+
end
|
5
7
|
|
6
8
|
# Replace the 'original' element in the included template with our new version.
|
7
9
|
def replace_with(new_obj)
|
8
10
|
super
|
9
|
-
|
10
|
-
|
11
|
-
|
11
|
+
# [self = original_element]. Replace @markup with content of the new_obj (<ul do='with'>...)
|
12
|
+
if new_obj.markup.tag
|
13
|
+
@markup.tag = new_obj.markup.tag
|
12
14
|
end
|
13
|
-
|
14
|
-
@markup.params.merge!(
|
15
|
+
|
16
|
+
@markup.params.merge!(new_obj.markup.params)
|
17
|
+
|
18
|
+
# We do not have to merge dyn_params since these are compiled before processing (and we are in
|
19
|
+
# the pre-processor)
|
20
|
+
|
15
21
|
if new_obj.params[:method]
|
16
|
-
@method = new_obj.params[:method]
|
22
|
+
@method = new_obj.params[:method]
|
17
23
|
elsif new_obj.sub_do
|
18
24
|
@method = 'void'
|
19
25
|
end
|
20
26
|
end
|
21
27
|
|
22
|
-
# Pass the caller's '
|
28
|
+
# Pass the caller's 'markup' to the included part.
|
23
29
|
def include_part(obj)
|
24
|
-
|
25
|
-
|
30
|
+
if @markup.tag
|
31
|
+
obj.markup = @markup.dup
|
32
|
+
end
|
26
33
|
@markup.tag = nil
|
27
|
-
@markup.params = {}
|
28
34
|
super(obj)
|
29
35
|
end
|
30
36
|
|
@@ -32,33 +38,29 @@ module Zafu
|
|
32
38
|
super && @markup.params == {} && @markup.tag.nil?
|
33
39
|
end
|
34
40
|
|
35
|
-
def
|
36
|
-
return
|
37
|
-
@markup.done = false
|
41
|
+
def compile_html_params
|
42
|
+
return if @markup.done
|
38
43
|
unless @markup.tag
|
39
44
|
if @markup.tag = @params.delete(:tag)
|
40
|
-
@markup.params
|
41
|
-
[:id, :class].each do |k|
|
42
|
-
next unless @params[k]
|
43
|
-
@markup.params[k] = @params.delete(k)
|
44
|
-
end
|
45
|
+
@markup.steal_html_params_from(@params)
|
45
46
|
end
|
46
47
|
end
|
48
|
+
|
47
49
|
# Translate dynamic params such as <tt>class='#{visitor.lang}'</tt> in the context
|
48
50
|
# of the current parser
|
49
51
|
@markup.compile_params(self)
|
50
|
-
|
51
|
-
# [each] is run many times with different roles. Some of these change html_tag_params.
|
52
|
-
@markup_bak = @markup.dup
|
53
|
-
true
|
54
52
|
end
|
55
53
|
|
56
|
-
def
|
57
|
-
|
58
|
-
@markup
|
59
|
-
res
|
54
|
+
def wrap_html(text)
|
55
|
+
compile_html_params
|
56
|
+
@markup.wrap(text)
|
60
57
|
end
|
61
58
|
|
59
|
+
#def restore_markup
|
60
|
+
# # restore @markup
|
61
|
+
# @markup = @markup_bak
|
62
|
+
#end
|
63
|
+
|
62
64
|
def inspect
|
63
65
|
@markup.done = false
|
64
66
|
res = super
|
@@ -66,7 +68,7 @@ module Zafu
|
|
66
68
|
if res =~ /\A\[(\w+)(.*)\/\]\Z/m
|
67
69
|
res = "[#{$1}#{$2}]<#{@markup.tag}/>[/#{$1}]"
|
68
70
|
elsif res =~ /\A\[([^\]]+)\](.*)\[\/(\w+)\]\Z/m
|
69
|
-
res = "[#{$1}]#{
|
71
|
+
res = "[#{$1}]#{@markup.wrap($2)}[/#{$3}]"
|
70
72
|
end
|
71
73
|
end
|
72
74
|
res
|
@@ -77,8 +79,6 @@ module Zafu
|
|
77
79
|
''
|
78
80
|
end
|
79
81
|
|
80
|
-
alias r_ r_ignore
|
81
|
-
|
82
82
|
def r_rename_asset
|
83
83
|
return expand_with unless @markup.tag
|
84
84
|
case @markup.tag
|
@@ -105,64 +105,59 @@ module Zafu
|
|
105
105
|
type = @markup.tag.to_sym
|
106
106
|
end
|
107
107
|
|
108
|
-
src = @params
|
109
|
-
if src && src[0..
|
110
|
-
@params[key] = helper.send(:template_url_for_asset, :src => src, :base_path => @options[:base_path], :type => type)
|
111
|
-
end
|
112
|
-
|
113
|
-
res = "<#{@markup.tag}#{params_to_html(@params)}"
|
114
|
-
@markup.done = true
|
115
|
-
inner = expand_with
|
116
|
-
if inner == ''
|
117
|
-
res + "/>"
|
118
|
-
else
|
119
|
-
res + ">#{inner}"
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
def r_form
|
124
|
-
res = "<#{@markup.tag}#{params_to_html(@params)}"
|
125
|
-
@markup.done = true
|
126
|
-
inner = expand_with
|
127
|
-
if inner == ''
|
128
|
-
res + "/>"
|
129
|
-
else
|
130
|
-
res + ">#{inner}"
|
108
|
+
src = @params.delete(key)
|
109
|
+
if src && src[0..6] != 'http://'
|
110
|
+
@markup.params[key] = helper.send(:template_url_for_asset, :src => src, :base_path => @options[:base_path], :type => type)
|
131
111
|
end
|
132
|
-
end
|
133
112
|
|
134
|
-
|
135
|
-
res = "<#{@markup.tag}#{params_to_html(@params)}"
|
136
|
-
@markup.done = true
|
137
|
-
inner = expand_with
|
138
|
-
if inner == ''
|
139
|
-
res + "></#{@markup.tag}>"
|
140
|
-
else
|
141
|
-
res + ">#{inner}"
|
142
|
-
end
|
143
|
-
end
|
113
|
+
@markup.steal_html_params_from(@params)
|
144
114
|
|
145
|
-
|
146
|
-
res = "<#{@markup.tag}#{params_to_html(@params)}"
|
147
|
-
@markup.done = true
|
148
|
-
inner = expand_with
|
149
|
-
if inner == ''
|
150
|
-
res + "/>"
|
151
|
-
else
|
152
|
-
res + ">#{inner}"
|
153
|
-
end
|
115
|
+
expand_with
|
154
116
|
end
|
155
117
|
|
156
|
-
def
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
end
|
118
|
+
#def r_form
|
119
|
+
# res = "<#{@markup.tag}#{params_to_html(@params)}"
|
120
|
+
# @markup.done = true
|
121
|
+
# inner = expand_with
|
122
|
+
# if inner == ''
|
123
|
+
# res + "/>"
|
124
|
+
# else
|
125
|
+
# res + ">#{inner}"
|
126
|
+
# end
|
127
|
+
#end
|
128
|
+
#
|
129
|
+
#def r_select
|
130
|
+
# res = "<#{@markup.tag}#{params_to_html(@params)}"
|
131
|
+
# @markup.done = true
|
132
|
+
# inner = expand_with
|
133
|
+
# if inner == ''
|
134
|
+
# res + "></#{@markup.tag}>"
|
135
|
+
# else
|
136
|
+
# res + ">#{inner}"
|
137
|
+
# end
|
138
|
+
#end
|
139
|
+
#
|
140
|
+
#def r_input
|
141
|
+
# res = "<#{@markup.tag}#{params_to_html(@params)}"
|
142
|
+
# @markup.done = true
|
143
|
+
# inner = expand_with
|
144
|
+
# if inner == ''
|
145
|
+
# res + "/>"
|
146
|
+
# else
|
147
|
+
# res + ">#{inner}"
|
148
|
+
# end
|
149
|
+
#end
|
150
|
+
#
|
151
|
+
#def r_textarea
|
152
|
+
# res = "<#{@markup.tag}#{params_to_html(@params)}"
|
153
|
+
# @markup.done = true
|
154
|
+
# inner = expand_with
|
155
|
+
# if inner == ''
|
156
|
+
# res + "/>"
|
157
|
+
# else
|
158
|
+
# res + ">#{inner}"
|
159
|
+
# end
|
160
|
+
#end
|
166
161
|
end # HTML
|
167
162
|
end # Process
|
168
163
|
end # Zafu
|