zena 1.2.1 → 1.2.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +38 -1
- data/app/controllers/documents_controller.rb +7 -5
- data/app/controllers/nodes_controller.rb +47 -6
- data/app/controllers/user_sessions_controller.rb +12 -3
- data/app/controllers/virtual_classes_controller.rb +8 -2
- data/app/models/acl.rb +5 -2
- data/app/models/cached_page.rb +5 -5
- data/app/models/column.rb +27 -4
- data/app/models/group.rb +1 -1
- data/app/models/node.rb +106 -24
- data/app/models/note.rb +2 -1
- data/app/models/relation.rb +9 -4
- data/app/models/relation_proxy.rb +2 -2
- data/app/models/role.rb +12 -5
- data/app/models/site.rb +10 -9
- data/app/models/skin.rb +8 -0
- data/app/models/string_hash.rb +65 -0
- data/app/models/text_document.rb +1 -1
- data/app/models/user.rb +2 -0
- data/app/models/virtual_class.rb +43 -10
- data/app/views/comments/create.rjs +1 -32
- data/app/views/comments/edit.rjs +1 -1
- data/app/views/comments/update.rjs +1 -1
- data/app/views/documents/show.rhtml +1 -1
- data/app/views/groups/_form.rhtml +7 -0
- data/app/views/groups/_li.rhtml +1 -1
- data/app/views/nodes/500.html +2 -1
- data/app/views/nodes/destroy.rjs +2 -0
- data/app/views/sites/jobs.erb +2 -3
- data/app/views/templates/document_create_tabs/_file.rhtml +1 -1
- data/app/views/templates/document_create_tabs/_import.rhtml +4 -1
- data/app/views/templates/document_create_tabs/_template.rhtml +3 -0
- data/app/views/templates/document_create_tabs/_text_document.rhtml +3 -0
- data/app/views/versions/custom_tab.rhtml +1 -1
- data/app/views/versions/edit.rhtml +1 -1
- data/bricks/acls/lib/bricks/acls.rb +3 -3
- data/bricks/acls/zena/test/unit/acl_test.rb +15 -0
- data/bricks/fs_skin/lib/bricks/fs_skin.rb +190 -0
- data/bricks/fs_skin/zena/init.rb +1 -0
- data/bricks/fs_skin/zena/migrate/20110702010330_add_fs_skin_to_idx_templates.rb +12 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Image-edit.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Image.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node-+index.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node-+notFound.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node-+search.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Node.zafu +1 -1
- data/bricks/{static → fs_skin}/zena/skins/blog/Post.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Project--kml.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/Project.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/comments.zafu +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/dict.yml +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/dateBg.jpg +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/header.png +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/mapPin.png +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/menu.gif +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/menuover.gif +0 -0
- data/bricks/{static → fs_skin}/zena/skins/blog/img/style.css +0 -0
- data/bricks/fs_skin/zena/tasks.rb +26 -0
- data/bricks/{static/zena/test/integration/static_integration_test.rb → fs_skin/zena/test/integration/fs_skin_integration_test.rb} +6 -6
- data/bricks/fs_skin/zena/test/unit/fs_skin_test.rb +33 -0
- data/bricks/grid/lib/bricks/grid.rb +4 -3
- data/bricks/tags/lib/bricks/tags.rb +1 -7
- data/bricks/zena/zena/migrate/20120605091558_add_ssl_login_to_site.rb +7 -0
- data/bricks/zena/zena/migrate/20120630123551_add_auto_publish_to_group.rb +9 -0
- data/config/bricks.yml +3 -3
- data/config/gems.yml +2 -3
- data/lib/tasks/zena.rake +7 -3
- data/lib/zafu.rb +7 -0
- data/lib/zafu/all.rb +21 -0
- data/lib/zafu/compiler.rb +7 -0
- data/lib/zafu/controller_methods.rb +58 -0
- data/lib/zafu/handler.rb +57 -0
- data/lib/zafu/info.rb +4 -0
- data/lib/zafu/markup.rb +309 -0
- data/lib/zafu/mock_helper.rb +42 -0
- data/lib/zafu/node_context.rb +203 -0
- data/lib/zafu/ordered_hash.rb +53 -0
- data/lib/zafu/parser.rb +676 -0
- data/lib/zafu/parsing_rules.rb +382 -0
- data/lib/zafu/process/ajax.rb +530 -0
- data/lib/zafu/process/conditional.rb +92 -0
- data/lib/zafu/process/context.rb +186 -0
- data/lib/zafu/process/forms.rb +143 -0
- data/lib/zafu/process/html.rb +186 -0
- data/lib/zafu/process/ruby_less_processing.rb +321 -0
- data/lib/zafu/security.rb +15 -0
- data/lib/zafu/template.rb +25 -0
- data/lib/zafu/test_helper.rb +19 -0
- data/lib/zafu/view_methods.rb +6 -0
- data/lib/zena.rb +1 -1
- data/lib/zena/acts/enrollable.rb +1 -1
- data/lib/zena/app.rb +4 -17
- data/lib/zena/console.rb +18 -1
- data/lib/zena/core_ext/file_utils.rb +13 -1
- data/lib/zena/core_ext/fixnum.rb +4 -0
- data/lib/zena/core_ext/float.rb +7 -0
- data/lib/zena/deploy.rb +4 -2
- data/lib/zena/deploy/app_init.rhtml +2 -1
- data/lib/zena/deploy/database.rhtml +1 -1
- data/lib/zena/info.rb +1 -1
- data/lib/zena/parser/zazen_rules.rb +4 -4
- data/lib/zena/routes.rb +1 -1
- data/lib/zena/test_controller.rb +1 -1
- data/lib/zena/use.rb +14 -1
- data/lib/zena/use/action.rb +4 -2
- data/lib/zena/use/ajax.rb +86 -38
- data/lib/zena/use/authlogic.rb +16 -1
- data/lib/zena/use/calendar.rb +37 -17
- data/lib/zena/use/conditional.rb +2 -2
- data/lib/zena/use/context.rb +30 -9
- data/lib/zena/use/dates.rb +39 -3
- data/lib/zena/use/display.rb +6 -19
- data/lib/zena/use/forms.rb +100 -79
- data/lib/zena/use/i18n.rb +40 -16
- data/lib/zena/use/query_builder.rb +0 -6
- data/lib/zena/use/query_node.rb +17 -4
- data/lib/zena/use/relations.rb +1 -3
- data/lib/zena/use/rendering.rb +10 -8
- data/lib/zena/use/scope_index.rb +5 -1
- data/lib/zena/use/search.rb +2 -1
- data/lib/zena/use/urls.rb +82 -77
- data/lib/zena/use/workflow.rb +12 -4
- data/lib/zena/use/zafu_safe_definitions.rb +37 -9
- data/lib/zena/use/zafu_templates.rb +49 -20
- data/lib/zena/use/zazen.rb +6 -2
- data/locale/it/LC_MESSAGES/zena.mo +0 -0
- data/locale/it/zena.mo +0 -0
- data/locale/it/zena.po +1982 -0
- data/public/images/arrow_back.png +0 -0
- data/public/images/remove_tag.png +0 -0
- data/public/javascripts/grid.js +800 -199
- data/public/javascripts/window.js +1 -1
- data/public/javascripts/zena.js +130 -21
- data/public/stylesheets/grid.css +11 -2
- data/public/stylesheets/zena.css +2 -1
- data/test/custom_queries/complex.host.yml +5 -0
- data/test/fixtures/files/TestNode.zafu +36 -0
- data/test/functional/nodes_controller_test.rb +18 -1
- data/test/integration/zafu_compiler/action.yml +2 -2
- data/test/integration/zafu_compiler/ajax.yml +44 -26
- data/test/integration/zafu_compiler/asset.yml +12 -2
- data/test/integration/zafu_compiler/basic.yml +0 -16
- data/test/integration/zafu_compiler/calendar.yml +6 -6
- data/test/integration/zafu_compiler/complex_ok.yml +23 -1
- data/test/integration/zafu_compiler/conditional.yml +5 -5
- data/test/integration/zafu_compiler/context.yml +6 -5
- data/test/integration/zafu_compiler/dates.yml +23 -2
- data/test/integration/zafu_compiler/display.yml +46 -2
- data/test/integration/zafu_compiler/errors.yml +2 -2
- data/test/integration/zafu_compiler/eval.yml +35 -7
- data/test/integration/zafu_compiler/forms.yml +47 -13
- data/test/integration/zafu_compiler/i18n.yml +2 -2
- data/test/integration/zafu_compiler/meta.yml +35 -1
- data/test/integration/zafu_compiler/query.yml +23 -4
- data/test/integration/zafu_compiler/relations.yml +10 -6
- data/test/integration/zafu_compiler/roles.yml +4 -4
- data/test/integration/zafu_compiler/rubyless.yml +11 -1
- data/test/integration/zafu_compiler/safe_definitions.yml +23 -5
- data/test/integration/zafu_compiler/security.yml +10 -6
- data/test/integration/zafu_compiler/urls.yml +23 -6
- data/test/integration/zafu_compiler/zafu_attributes.yml +1 -1
- data/test/integration/zafu_compiler/zazen.yml +14 -0
- data/test/selenium/Add/add3.rsel +8 -8
- data/test/selenium/Destroy/0setup.rsel +12 -0
- data/test/selenium/Destroy/destroy1.rsel +16 -0
- data/test/selenium/Edit/edit2.rsel +9 -9
- data/test/selenium/Edit/edit5.rsel +9 -9
- data/test/selenium/Edit/edit6.rsel +9 -9
- data/test/selenium/Form/form4.rsel +17 -0
- data/test/selenium/Toggle/toggle1.rsel +2 -0
- data/test/selenium/Toggle/toggle2.rsel +18 -0
- data/test/sites/zena/columns.yml +3 -0
- data/test/sites/zena/versions.yml +7 -0
- data/test/unit/cached_page_test.rb +13 -13
- data/test/unit/column_test.rb +26 -0
- data/test/unit/node_test.rb +16 -1
- data/test/unit/project_test.rb +6 -1
- data/test/unit/relation_test.rb +1 -1
- data/test/unit/role_test.rb +1 -1
- data/test/unit/string_hash_test.rb +30 -0
- data/test/unit/virtual_class_test.rb +31 -17
- data/test/unit/zafu_markup_test.rb +414 -0
- data/test/unit/zafu_node_context_test.rb +375 -0
- data/test/unit/zafu_ordered_hash_test.rb +69 -0
- data/test/unit/zena/acts/enrollable_test.rb +1 -1
- data/test/unit/zena/parser/zafu_asset.yml +0 -10
- data/test/unit/zena/parser/zazen.yml +1 -1
- data/test/unit/zena/parser_test.rb +1 -72
- data/test/unit/zena/use/dates_test.rb +1 -1
- data/test/unit/zena/use/rendering_test.rb +24 -7
- data/test/unit/zena/use/scope_index_test.rb +17 -0
- data/test/unit/zena/use/zazen_test.rb +2 -1
- data/zena.gemspec +71 -37
- metadata +104 -83
- data/app/views/nodes/destroy.erb +0 -0
- data/bricks/static/lib/bricks/static.rb +0 -151
- data/bricks/static/zena/init.rb +0 -1
- data/bricks/static/zena/migrate/20110702010330_add_static_to_idx_templates.rb +0 -12
- data/bricks/static/zena/test/unit/static_test.rb +0 -33
- data/lib/zena/parser/zafu_rules.rb +0 -244
- data/lib/zena/parser/zafu_tags.rb +0 -198
- data/lib/zena/parser/zena_rules.rb +0 -23
@@ -0,0 +1,321 @@
|
|
1
|
+
require 'rubyless'
|
2
|
+
|
3
|
+
module Zafu
|
4
|
+
module Process
|
5
|
+
module RubyLessProcessing
|
6
|
+
include RubyLess
|
7
|
+
|
8
|
+
def self.included(base)
|
9
|
+
base.process_unknown :rubyless_eval
|
10
|
+
|
11
|
+
base.class_eval do
|
12
|
+
def do_method(sym)
|
13
|
+
super
|
14
|
+
rescue RubyLess::Error => err
|
15
|
+
parser_error(err.message)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Actual method resolution. The lookup first starts in the current helper. If nothing is found there, it
|
21
|
+
# searches inside a 'helpers' module and finally looks into the current node_context.
|
22
|
+
# If nothing is found at this stage, we prepend the method with the current node and start over again.
|
23
|
+
def safe_method_type(signature, receiver = nil)
|
24
|
+
super || get_method_type(signature, false)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Resolve unknown methods by using RubyLess in the current compilation context (the
|
28
|
+
# translate method in RubyLess will call 'safe_method_type' in this module).
|
29
|
+
def rubyless_eval(params = @params)
|
30
|
+
if @method =~ /^([A-Z]\w+?)\?$/
|
31
|
+
return rubyless_class_scope($1)
|
32
|
+
end
|
33
|
+
|
34
|
+
rubyless_render(@method, params)
|
35
|
+
rescue RubyLess::NoMethodError => err
|
36
|
+
parser_continue("#{err.error_message} <span class='type'>#{err.method_with_arguments}</span> (#{node.klass} context)")
|
37
|
+
rescue RubyLess::Error => err
|
38
|
+
parser_continue(err.message)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Print documentation on the current node type.
|
42
|
+
def r_m
|
43
|
+
if @params[:helper] == 'true'
|
44
|
+
klass = helper.class
|
45
|
+
else
|
46
|
+
klass = node.klass
|
47
|
+
end
|
48
|
+
|
49
|
+
out "<div class='rubyless-m'><h3>Documentation for <b>#{klass}</b></h3>"
|
50
|
+
out "<ul>"
|
51
|
+
RubyLess::SafeClass.safe_methods_for(klass).each do |signature, opts|
|
52
|
+
opts = opts.dup
|
53
|
+
opts.delete(:method)
|
54
|
+
if opts.keys == [:class]
|
55
|
+
opts = opts[:class]
|
56
|
+
end
|
57
|
+
out "<li>#{signature.inspect} => #{opts.inspect}</li>"
|
58
|
+
end
|
59
|
+
out "</ul></div>"
|
60
|
+
end
|
61
|
+
|
62
|
+
# TEMPORARY METHOD DURING HACKING...
|
63
|
+
# def r_erb
|
64
|
+
# "<pre><%= @erb.gsub('<','<').gsub('>','>') %></pre>"
|
65
|
+
# end
|
66
|
+
|
67
|
+
def rubyless_render(method, params)
|
68
|
+
# We need to set this here because we cannot pass options to RubyLess or get them back
|
69
|
+
# when we evaluate the method to see if we can use blocks as arguments.
|
70
|
+
@rendering_block_owner = true
|
71
|
+
code = method_with_arguments(method, params)
|
72
|
+
# It is strange that we need to freeze code... But if we don't, we
|
73
|
+
# get double ##{} on some systems (Linux).
|
74
|
+
rubyless_expand RubyLess.translate(self, code.freeze)
|
75
|
+
ensure
|
76
|
+
@rendering_block_owner = false
|
77
|
+
end
|
78
|
+
|
79
|
+
def set_markup_attr(markup, key, value)
|
80
|
+
value = value.kind_of?(RubyLess::TypedString) ? value : RubyLess.translate_string(self, value)
|
81
|
+
if value.literal
|
82
|
+
markup.set_param(key, form_quote(value.literal))
|
83
|
+
else
|
84
|
+
markup.set_dyn_param(key, "<%= #{value} %>")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def append_markup_attr(markup, key, value)
|
89
|
+
value = RubyLess.translate_string(self, value)
|
90
|
+
if value.literal
|
91
|
+
markup.append_param(key, form_quote(value.literal))
|
92
|
+
else
|
93
|
+
markup.append_dyn_param(key, "<%= #{value} %>")
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
def get_attribute_or_eval(use_string_block = true)
|
98
|
+
if @params[:date] && method != 'link'
|
99
|
+
return parser_continue("'date' parameter is deprecated. Please use 'attr' or 'eval'.")
|
100
|
+
elsif attribute = @params[:attr]
|
101
|
+
code = "this.#{attribute}"
|
102
|
+
elsif code = @params[:eval] || @params[:test]
|
103
|
+
elsif code = @params[:param]
|
104
|
+
code = "params[:#{code}]"
|
105
|
+
elsif text = @params[:text]
|
106
|
+
code = "%Q{#{text}}"
|
107
|
+
elsif text = @params[:t]
|
108
|
+
code = "t(%Q{#{text}})"
|
109
|
+
# elsif var = @params[:var]
|
110
|
+
# if code = get_context_var('set_var', var)
|
111
|
+
# return code
|
112
|
+
# else
|
113
|
+
# return parser_continue("Var #{var.inspect} not declared.")
|
114
|
+
# end
|
115
|
+
elsif use_string_block && @blocks.size == 1 && @blocks.first.kind_of?(String)
|
116
|
+
return RubyLess::TypedString.new(@blocks.first.inspect, :class => String, :literal => @blocks.first)
|
117
|
+
else
|
118
|
+
return parser_continue("Missing attribute/eval parameter")
|
119
|
+
end
|
120
|
+
|
121
|
+
RubyLess.translate(self, code)
|
122
|
+
rescue RubyLess::Error => err
|
123
|
+
return parser_continue(err.message, code)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Pass default values as parameters in @context as :param_XXXX
|
127
|
+
def r_default
|
128
|
+
cont = {}
|
129
|
+
@params.each do |k, v|
|
130
|
+
cont[:"params_#{k}"] = v
|
131
|
+
end
|
132
|
+
expand_with cont
|
133
|
+
end
|
134
|
+
|
135
|
+
private
|
136
|
+
# Extract arguments from params (evaluates params as RubyLess strings).
|
137
|
+
def extract_from_params(*keys)
|
138
|
+
res = []
|
139
|
+
|
140
|
+
keys.each do |key|
|
141
|
+
next unless value = param(key.to_sym)
|
142
|
+
res << ":#{key} => #{RubyLess.translate_string(self, value)}"
|
143
|
+
end
|
144
|
+
|
145
|
+
res.empty? ? nil : res
|
146
|
+
end
|
147
|
+
|
148
|
+
def param(key, default = nil)
|
149
|
+
@params[key] || @context[:"params_#{key}"] || default
|
150
|
+
end
|
151
|
+
|
152
|
+
# Method resolution. The first matching method is returned. Order of evaluation is
|
153
|
+
# 1. find node_context (@page, @image, self)
|
154
|
+
# 2. set var (set_xxx = '...')
|
155
|
+
# 3. template helper methods
|
156
|
+
# 4. contextual node methods (var1.xxx)
|
157
|
+
# 5. contextual first node of list method ([...].first.xxx)
|
158
|
+
# 6. append block as argument (restart 1-5 with xxx(block_string))
|
159
|
+
def get_method_type(signature, added_options = false)
|
160
|
+
node = self.node
|
161
|
+
|
162
|
+
if type = node_context_from_signature(signature)
|
163
|
+
# Resolve this, @page, @node
|
164
|
+
type
|
165
|
+
elsif type = get_var_from_signature(signature)
|
166
|
+
# Resolved stored set_xxx='something' in context.
|
167
|
+
type
|
168
|
+
elsif type = safe_method_from(helper, signature)
|
169
|
+
# Resolve template helper methods
|
170
|
+
type
|
171
|
+
elsif helper.respond_to?(:helpers) && type = safe_method_from(helper.helpers, signature)
|
172
|
+
# Resolve by looking at the included helpers
|
173
|
+
type
|
174
|
+
elsif node && !node.list_context? && type = safe_method_from(node.klass, signature, node)
|
175
|
+
# not a list_contex
|
176
|
+
# Resolve node context methods: xxx.foo, xxx.bar
|
177
|
+
# All direct methods from nodes should be html escaped:
|
178
|
+
type = type[:class].call(self, node.klass, signature) if type[:class].kind_of?(Proc)
|
179
|
+
type.merge(:receiver => RubyLess::TypedString.new(node.name, :class => node.klass, :h => true))
|
180
|
+
elsif node && node.list_context? && type = safe_method_from(Array, signature, node)
|
181
|
+
# FIXME: why do we need this here ? Remove with related code in zafu_safe_definitions ?
|
182
|
+
type = type[:class].call(self, node.klass, signature) if type[:class].kind_of?(Proc)
|
183
|
+
type.merge(:receiver => RubyLess::TypedString.new(node.name, :class => Array, :elem => node.klass.first))
|
184
|
+
elsif node && node.list_context? && type = safe_method_from(node.klass.first, signature, node)
|
185
|
+
type = type[:class].call(self, node.klass, signature) if type[:class].kind_of?(Proc)
|
186
|
+
type.merge(:receiver => RubyLess::TypedString.new("#{node.name}.first", :class => node.klass.first, :h => true))
|
187
|
+
elsif @rendering_block_owner && @blocks.first.kind_of?(String) && !added_options
|
188
|
+
# Insert the block content into the method: <r:trans>blah</r:trans> becomes trans("blah")
|
189
|
+
signature_with_block = signature.dup
|
190
|
+
signature_with_block << String
|
191
|
+
if type = get_method_type(signature_with_block, true)
|
192
|
+
type.merge(:prepend_args => RubyLess::TypedString.new(@blocks.first.inspect, :class => String, :literal => @blocks.first))
|
193
|
+
else
|
194
|
+
nil
|
195
|
+
end
|
196
|
+
elsif node && !added_options
|
197
|
+
# Try prepending current node before arguments: link("foo") becomes link(var1, "foo")
|
198
|
+
signature_with_node = signature.dup
|
199
|
+
signature_with_node.insert(1, node.real_class) # node.klass ?
|
200
|
+
if type = get_method_type(signature_with_node, true)
|
201
|
+
type.merge(:prepend_args => RubyLess::TypedString.new(node.name, :class => node.klass))
|
202
|
+
else
|
203
|
+
nil
|
204
|
+
end
|
205
|
+
else
|
206
|
+
nil
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def method_with_arguments(method, params)
|
211
|
+
hash_arguments = []
|
212
|
+
arguments = []
|
213
|
+
params.keys.sort {|a,b| a.to_s <=> b.to_s}.each do |k|
|
214
|
+
if k =~ /\A_/
|
215
|
+
arguments << "%Q{#{params[k]}}"
|
216
|
+
else
|
217
|
+
hash_arguments << ":#{k} => %Q{#{params[k]}}"
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
if hash_arguments != []
|
222
|
+
arguments << hash_arguments.join(', ')
|
223
|
+
end
|
224
|
+
|
225
|
+
if arguments != []
|
226
|
+
if method =~ /^(.*)\((.*)\)$/
|
227
|
+
if $2 == ''
|
228
|
+
"#{$1}(#{arguments.join(', ')})"
|
229
|
+
else
|
230
|
+
"#{$1}(#{$2}, #{arguments.join(', ')})"
|
231
|
+
end
|
232
|
+
else
|
233
|
+
"#{method}(#{arguments.join(', ')})"
|
234
|
+
end
|
235
|
+
else
|
236
|
+
method
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def rubyless_expand(res)
|
241
|
+
if res.klass == String && !@blocks.detect {|b| !b.kind_of?(String)}
|
242
|
+
if lit = res.literal
|
243
|
+
out erb_escape(lit)
|
244
|
+
# TODO: Enable this when we have time to ensure tests/functionality work correctly.
|
245
|
+
#elsif res.opts[:h]
|
246
|
+
# show_string(res)
|
247
|
+
else
|
248
|
+
out "<%= #{res} %>"
|
249
|
+
end
|
250
|
+
elsif res.klass == Boolean
|
251
|
+
expand_if(res)
|
252
|
+
elsif @blocks.empty?
|
253
|
+
out "<%= #{res} %>"
|
254
|
+
else
|
255
|
+
expand_with_finder(:method => res, :class => res.klass, :query => res.opts[:query], :nil => res.could_be_nil?)
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def rubyless_class_scope(class_name)
|
260
|
+
return parser_error("Cannot scope class in list (use each before filtering).") if node.list_context?
|
261
|
+
|
262
|
+
# capital letter ==> class conditional
|
263
|
+
klass = Module.const_get(class_name)
|
264
|
+
if klass.ancestors.include?(node.klass)
|
265
|
+
expand_if("#{node}.kind_of?(#{klass})")
|
266
|
+
else
|
267
|
+
# render nothing: incompatible classes
|
268
|
+
''
|
269
|
+
end
|
270
|
+
rescue
|
271
|
+
parser_error("Invalid class name '#{class_name}'")
|
272
|
+
end
|
273
|
+
|
274
|
+
# Find a class or behavior based on a name. The returned class should implement
|
275
|
+
# 'safe_method_type'.
|
276
|
+
def get_class(class_name)
|
277
|
+
Module.const_get(class_name)
|
278
|
+
rescue
|
279
|
+
nil
|
280
|
+
end
|
281
|
+
|
282
|
+
# This is used to resolve 'this' (current NodeContext), '@node' as NodeContext with class Node,
|
283
|
+
# '@page' as first NodeContext of type Page, etc.
|
284
|
+
def node_context_from_signature(signature)
|
285
|
+
return nil unless signature.size == 1
|
286
|
+
ivar = signature.first
|
287
|
+
if ivar == 'this'
|
288
|
+
node.opts.merge(:class => node.klass, :method => node.name)
|
289
|
+
elsif ivar[0..0] == '@' && klass = get_class(ivar[1..-1].capitalize)
|
290
|
+
if node = self.node(klass)
|
291
|
+
node.opts.merge(:class => node.klass, :method => node.name)
|
292
|
+
else
|
293
|
+
nil
|
294
|
+
end
|
295
|
+
else
|
296
|
+
nil
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
# Find stored variables back. Stored elements are set with set_xxx='something to eval'.
|
301
|
+
def get_var_from_signature(signature)
|
302
|
+
return nil unless signature.size == 1
|
303
|
+
if var = get_context_var('set_var', signature.first)
|
304
|
+
{:method => var, :class => var.klass, :nil => var.could_be_nil?, :query => var.opts[:query]}
|
305
|
+
else
|
306
|
+
nil
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
310
|
+
def safe_method_from(solver, signature, receiver = nil)
|
311
|
+
|
312
|
+
if solver.respond_to?(:safe_method_type)
|
313
|
+
solver.safe_method_type(signature, receiver)
|
314
|
+
else
|
315
|
+
RubyLess::SafeClass.safe_method_type_for(solver, signature)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
end # RubyLessProcessing
|
320
|
+
end # Process
|
321
|
+
end # Zafu
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Zafu
|
2
|
+
module Security
|
3
|
+
SECURE_REGEXP = %r{<%|%>|<\Z}
|
4
|
+
SAFE_CODE = {'<%' => '<%', '%>' => '%>', '<' => '<'}
|
5
|
+
# Make sure translations and other literal values cannot be used to build erb.
|
6
|
+
def erb_escape(text)
|
7
|
+
# Do not only replace '<%' ! or <r:t>min</r:t>% ==> <% ...
|
8
|
+
text.gsub(SECURE_REGEXP) {|code| SAFE_CODE[code]}
|
9
|
+
end
|
10
|
+
|
11
|
+
def form_quote(text)
|
12
|
+
erb_escape(text).gsub("'", "'")
|
13
|
+
end
|
14
|
+
end # Security
|
15
|
+
end # Zafu
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'zafu/compiler'
|
2
|
+
|
3
|
+
module Zafu
|
4
|
+
class Template
|
5
|
+
def initialize(template, src_helper = nil, compiler = Zafu::Compiler)
|
6
|
+
if template.kind_of?(String)
|
7
|
+
@ast = compiler.new(template)
|
8
|
+
else
|
9
|
+
@ast = compiler.new_with_url(template.path, :helper => src_helper)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_erb(context = {})
|
14
|
+
@ast.to_erb(context)
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_ruby(context = {})
|
18
|
+
src = ::ERB.new("<% __in_erb_template=true %>#{to_erb(context)}", nil, '-').src
|
19
|
+
|
20
|
+
# Ruby 1.9 prepends an encoding to the source. However this is
|
21
|
+
# useless because you can only set an encoding on the first line
|
22
|
+
RUBY_VERSION >= '1.9' ? src.sub(/\A#coding:.*\n/, '') : src
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'zafu/template'
|
2
|
+
|
3
|
+
module Zafu
|
4
|
+
module TestHelper
|
5
|
+
include RubyLess::SafeClass
|
6
|
+
|
7
|
+
def zafu_erb(source, src_helper = self, compiler = Zafu::Compiler)
|
8
|
+
Zafu::Template.new(source, src_helper, compiler).to_erb(compilation_context)
|
9
|
+
end
|
10
|
+
|
11
|
+
def zafu_render(source, src_helper = self, compiler = Zafu::Compiler)
|
12
|
+
eval Zafu::Template.new(source, src_helper, compiler).to_ruby(compilation_context)
|
13
|
+
end
|
14
|
+
|
15
|
+
def compilation_context
|
16
|
+
{:node => @node_context, :helper => self}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/zena.rb
CHANGED
@@ -222,7 +222,7 @@ module Zena
|
|
222
222
|
def init
|
223
223
|
config = Rails.configuration
|
224
224
|
enable_tools
|
225
|
-
puts "** zena #{Zena::VERSION} starting (c) Gaspard Bucher
|
225
|
+
puts "** zena #{Zena::VERSION} starting (c) Gaspard Bucher 2012"
|
226
226
|
puts "** Bricks: #{Bricks::CONFIG.map{|k,v| k}.sort.join(', ')}"
|
227
227
|
|
228
228
|
add_load_paths(config)
|
data/lib/zena/acts/enrollable.rb
CHANGED
data/lib/zena/app.rb
CHANGED
@@ -55,24 +55,11 @@ module Zena
|
|
55
55
|
end
|
56
56
|
Bricks.apply_patches('application_controller.rb')
|
57
57
|
Bricks.apply_patches('application_helper.rb')
|
58
|
-
|
59
|
-
::User.class_eval do
|
60
|
-
Zena::Use.each_module_for('User') do |mod|
|
61
|
-
include mod
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
::Site.class_eval do
|
66
|
-
Zena::Use.each_module_for('Site') do |mod|
|
67
|
-
include mod
|
68
|
-
end
|
69
|
-
end
|
70
58
|
|
71
|
-
::
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
end
|
59
|
+
Zena::Use.upgrade_class('User')
|
60
|
+
Zena::Use.upgrade_class('Site')
|
61
|
+
Zena::Use.upgrade_class('Skin')
|
62
|
+
|
76
63
|
end
|
77
64
|
end
|
78
65
|
end
|
data/lib/zena/console.rb
CHANGED
@@ -195,7 +195,9 @@ module Zena
|
|
195
195
|
page_count = (count.to_f / limit).ceil
|
196
196
|
puts "#{count} nodes, #{page_count} chunk(s) (100 items)"
|
197
197
|
curr_page = 1
|
198
|
-
|
198
|
+
# We walk pages in reverse order in case objects are deleted
|
199
|
+
|
200
|
+
for curr_page in (1..page_count).to_a.reverse
|
199
201
|
query.offset = " OFFSET #{limit * (curr_page - 1)}"
|
200
202
|
if list = Node.do_find(:all, eval(query.to_s(:find)))
|
201
203
|
puts "Page #{curr_page}/#{page_count}"
|
@@ -206,5 +208,20 @@ module Zena
|
|
206
208
|
end
|
207
209
|
nil
|
208
210
|
end
|
211
|
+
|
212
|
+
def profile(node_id)
|
213
|
+
require 'ruby-prof'
|
214
|
+
ctrl = NodesController.new
|
215
|
+
ctrl.request = Struct.new(:format).new(Mime::HTML)
|
216
|
+
ctrl.instance_variable_set(:@node, nodes(node_id))
|
217
|
+
start = Time.now
|
218
|
+
result = RubyProf.profile do
|
219
|
+
yield(ctrl)
|
220
|
+
end
|
221
|
+
puts(Time.now - start)
|
222
|
+
File.open('grind.log', 'wb') do |f|
|
223
|
+
RubyProf::CallTreePrinter.new(result).print(f)
|
224
|
+
end
|
225
|
+
end
|
209
226
|
end # Console
|
210
227
|
end # Zena
|