zena 0.15.2 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (284) hide show
  1. data/.gitignore +20 -0
  2. data/CREDITS +27 -0
  3. data/Capfile +3 -0
  4. data/DEVELOPERS +46 -0
  5. data/History.txt +15 -0
  6. data/MIT-LICENSE +19 -0
  7. data/Rakefile +44 -0
  8. data/TODO +24 -0
  9. data/TODO_ZENA_1_0 +23 -0
  10. data/app/controllers/application_controller.rb +3 -0
  11. data/app/controllers/documents_controller.rb +22 -56
  12. data/app/controllers/nodes_controller.rb +42 -27
  13. data/app/controllers/pings_controller.rb +19 -0
  14. data/app/controllers/relations_controller.rb +5 -1
  15. data/app/controllers/sites_controller.rb +1 -46
  16. data/app/controllers/user_sessions_controller.rb +47 -0
  17. data/app/controllers/users_controller.rb +1 -0
  18. data/app/controllers/versions_controller.rb +25 -7
  19. data/app/controllers/virtual_classes_controller.rb +1 -1
  20. data/app/helpers/application_helper.rb +1 -1
  21. data/app/models/comment.rb +2 -1
  22. data/app/models/contact_content.rb +2 -2
  23. data/app/models/data_entry.rb +5 -6
  24. data/app/models/document.rb +14 -10
  25. data/app/models/document_content.rb +4 -6
  26. data/app/models/iformat.rb +2 -2
  27. data/app/models/image_content.rb +6 -9
  28. data/app/models/node.rb +106 -164
  29. data/app/models/page.rb +0 -20
  30. data/app/models/site.rb +42 -12
  31. data/app/models/template.rb +3 -8
  32. data/app/models/template_content.rb +2 -0
  33. data/app/models/text_document.rb +13 -8
  34. data/app/models/user.rb +47 -100
  35. data/app/models/user_session.rb +4 -0
  36. data/app/models/version.rb +1 -1
  37. data/app/views/comments/create.rjs +3 -3
  38. data/app/views/comments/edit.rjs +1 -1
  39. data/app/views/comments/update.rjs +1 -1
  40. data/app/views/nodes/_import_results.rhtml +1 -1
  41. data/app/views/nodes/create.rjs +3 -3
  42. data/app/views/templates/document_create_tabs/_file.rhtml +1 -2
  43. data/app/views/templates/document_create_tabs/_import.rhtml +7 -2
  44. data/app/views/templates/edit_tabs/_document.rhtml +1 -3
  45. data/app/views/templates/edit_tabs/_image.rhtml +1 -3
  46. data/app/views/versions/_tr.rhtml +1 -1
  47. data/app/views/versions/edit.rhtml +2 -26
  48. data/bin/zena +6 -1
  49. data/bricks/delayed_job/README +18 -0
  50. data/bricks/delayed_job/migrate/20091104191643_create_delayed_jobs_table.rb +19 -0
  51. data/bricks/delayed_job/misc/init.rb +8 -0
  52. data/bricks/delayed_job/misc/tasks.rb +2 -0
  53. data/bricks/math/patch/application_helper.rb +1 -1
  54. data/bricks/sphinx/MIT-LICENSE +19 -0
  55. data/bricks/sphinx/README +19 -0
  56. data/bricks/sphinx/lib/use_sphinx.rb +78 -0
  57. data/bricks/sphinx/migrate/20091102171258_add_delta_for_sphinx.rb +9 -0
  58. data/bricks/sphinx/misc/deploy.rb +20 -0
  59. data/bricks/sphinx/misc/sphinx.yml +12 -0
  60. data/bricks/sphinx/misc/tasks.rb +21 -0
  61. data/bricks/sphinx/patch/node.rb +8 -0
  62. data/bricks/tags/lib/has_tags.rb +5 -3
  63. data/bricks/tags/test/zafu/tags.yml +13 -1
  64. data/config/bricks.yml +35 -0
  65. data/config/deploy.rb +8 -1
  66. data/config/environment.rb +1 -1
  67. data/config/environments/production.rb +1 -1
  68. data/config/gems.yml +28 -5
  69. data/config/sphinx.yml +12 -0
  70. data/db/init/base/skins/default/Node-+popupLayout.zafu +1 -16
  71. data/db/migrate/20091026161708_add_persistence_token.rb +13 -0
  72. data/db/migrate/20091101184952_add_session_table.rb +16 -0
  73. data/db/migrate/20091123175137_add_single_access_token.rb +9 -0
  74. data/db/migrate/20091124161608_rebuild_fullpath.rb +11 -0
  75. data/db/schema.rb +21 -8
  76. data/doc/README_FOR_APP +24 -0
  77. data/doc/fixtures.graffle +19568 -0
  78. data/doc/fixtures.pdf +0 -0
  79. data/doc/template/LICENSE +184 -0
  80. data/doc/template/README +37 -0
  81. data/doc/template/allison.css +283 -0
  82. data/doc/template/allison.js +307 -0
  83. data/doc/template/allison.rb +260 -0
  84. data/doc/template/cache/BODY +588 -0
  85. data/doc/template/cache/CLASS_INDEX +4 -0
  86. data/doc/template/cache/CLASS_PAGE +1 -0
  87. data/doc/template/cache/FILE_INDEX +4 -0
  88. data/doc/template/cache/FILE_PAGE +1 -0
  89. data/doc/template/cache/FONTS +1 -0
  90. data/doc/template/cache/FR_INDEX_BODY +1 -0
  91. data/doc/template/cache/IMGPATH +1 -0
  92. data/doc/template/cache/INDEX +1 -0
  93. data/doc/template/cache/JAVASCRIPT +307 -0
  94. data/doc/template/cache/METHOD_INDEX +4 -0
  95. data/doc/template/cache/METHOD_LIST +1 -0
  96. data/doc/template/cache/SRC_PAGE +1 -0
  97. data/doc/template/cache/STYLE +283 -0
  98. data/doc/template/cache/URL +1 -0
  99. data/doc/zafu_changes.yml +29 -0
  100. data/lib/base_additions.rb +1 -1
  101. data/lib/bricks.rb +9 -0
  102. data/lib/bricks/loader.rb +86 -0
  103. data/lib/bricks/requirements_validation.rb +71 -0
  104. data/lib/tasks/zena.rake +42 -4
  105. data/lib/zafu/action.rb +285 -0
  106. data/lib/zafu/ajax.rb +93 -0
  107. data/lib/zafu/attributes.rb +117 -0
  108. data/lib/zafu/calendar.rb +159 -0
  109. data/lib/zafu/context.rb +330 -0
  110. data/lib/zafu/core/html.rb +102 -0
  111. data/lib/zafu/core/move_to_parser.rb +167 -0
  112. data/lib/zafu/dates.rb +58 -0
  113. data/lib/zafu/display.rb +502 -0
  114. data/lib/zafu/eval.rb +66 -0
  115. data/lib/zafu/experimental.rb +66 -0
  116. data/lib/zafu/i18n.rb +64 -0
  117. data/lib/zafu/meta.rb +25 -0
  118. data/lib/zafu/refactor.rb +73 -0
  119. data/lib/zafu/support/context.rb +265 -0
  120. data/lib/zafu/support/dom.rb +145 -0
  121. data/lib/zafu/support/erb.rb +62 -0
  122. data/lib/zafu/support/flow.rb +401 -0
  123. data/lib/zafu/support/forms.rb +461 -0
  124. data/lib/zafu/support/links.rb +306 -0
  125. data/lib/zafu_parser.rb +26 -2
  126. data/lib/zena.rb +34 -15
  127. data/lib/zena/acts/multiversion.rb +2 -2
  128. data/lib/zena/acts/secure.rb +41 -30
  129. data/lib/zena/app.rb +7 -10
  130. data/lib/zena/controller/test_case.rb +12 -7
  131. data/lib/zena/crypto_provider/initial.rb +15 -0
  132. data/lib/zena/db.rb +6 -1
  133. data/lib/zena/deploy.rb +34 -6
  134. data/lib/zena/deploy/logrotate_app.rhtml +9 -0
  135. data/lib/zena/deploy/logrotate_host.rhtml +34 -0
  136. data/lib/zena/deploy/template.rb +1 -9
  137. data/lib/zena/foxy_parser.rb +1 -1
  138. data/lib/zena/info.rb +3 -1
  139. data/lib/zena/migrator.rb +1 -1
  140. data/lib/zena/parser.rb +12 -4
  141. data/lib/zena/parser/zazen_rules.rb +6 -6
  142. data/lib/zena/parser/zena_rules.rb +1 -7
  143. data/lib/zena/routes.rb +5 -5
  144. data/lib/zena/test_controller.rb +7 -2
  145. data/lib/zena/unit/test_case.rb +6 -8
  146. data/lib/zena/use/ajax.rb +10 -10
  147. data/lib/zena/use/authlogic.rb +93 -0
  148. data/lib/zena/use/dyn_attributes.rb +5 -0
  149. data/lib/zena/use/html_tags.rb +16 -34
  150. data/lib/zena/use/i18n.rb +4 -1
  151. data/lib/zena/use/node_query_finders.rb +8 -4
  152. data/lib/zena/use/refactor.rb +8 -20
  153. data/lib/zena/use/relations.rb +1 -0
  154. data/lib/zena/use/rendering.rb +4 -2
  155. data/lib/zena/use/search.rb +52 -0
  156. data/lib/zena/use/test_helper.rb +27 -28
  157. data/lib/zena/use/upload.rb +188 -0
  158. data/lib/zena/use/urls.rb +16 -14
  159. data/lib/zena/use/zafu.rb +16 -63
  160. data/lib/zena/use/zazen.rb +8 -8
  161. data/lib/zena/view/test_case.rb +8 -4
  162. data/locale/en/LC_MESSAGES/zena.mo +0 -0
  163. data/locale/en/zena.po +3 -3
  164. data/public/.htaccess +40 -0
  165. data/public/javascripts/upload-progress.js +17 -8
  166. data/public/javascripts/zena.js +8 -2
  167. data/public/stylesheets/popup.css +1 -0
  168. data/script/about +3 -0
  169. data/script/apache_logging +25 -0
  170. data/script/breakpointer +3 -0
  171. data/script/console +3 -0
  172. data/script/dbconsole +3 -0
  173. data/script/destroy +3 -0
  174. data/script/generate +3 -0
  175. data/script/performance/benchmarker +3 -0
  176. data/script/performance/profiler +3 -0
  177. data/script/plugin +3 -0
  178. data/script/process/inspector +3 -0
  179. data/script/process/reaper +3 -0
  180. data/script/process/spawner +3 -0
  181. data/script/runner +3 -0
  182. data/script/server +3 -0
  183. data/script/set_revision +29 -0
  184. data/spec/controllers/versions_controller_spec.rb +11 -0
  185. data/test/fixtures/files/Node-test.zafu +1 -1
  186. data/test/functional/nodes_controller_test.rb +25 -0
  187. data/test/functional/pings_controller_test.rb +8 -0
  188. data/test/functional/user_sessions_controller_test.rb +59 -0
  189. data/test/functional/users_controller_test.rb +81 -19
  190. data/test/helpers/node_query/filters.yml +5 -0
  191. data/test/helpers/node_query_test.rb +3 -3
  192. data/test/integration/multiple_hosts_test.rb +1 -1
  193. data/test/integration/navigation_test.rb +1 -1
  194. data/test/sites/complex/users.yml +1 -1
  195. data/test/sites/ocean/users.yml +3 -3
  196. data/test/sites/zena/users.yml +5 -4
  197. data/test/test_zena.rb +38 -38
  198. data/test/unit/cached_page_test.rb +2 -2
  199. data/test/unit/comment_test.rb +0 -1
  200. data/test/unit/document_test.rb +23 -11
  201. data/test/unit/helpers/ping_helper_test.rb +4 -0
  202. data/test/unit/multiversion_test.rb +24 -16
  203. data/test/unit/node_test.rb +32 -93
  204. data/test/unit/note_test.rb +9 -0
  205. data/test/unit/page_test.rb +2 -2
  206. data/test/unit/secure_test.rb +2 -12
  207. data/test/unit/site_test.rb +43 -24
  208. data/test/unit/template_test.rb +45 -3
  209. data/test/unit/text_document_test.rb +4 -3
  210. data/test/unit/user_test.rb +13 -33
  211. data/test/unit/zena/db_test.rb +8 -0
  212. data/test/unit/zena/parser/zazen.yml +4 -4
  213. data/test/unit/zena/use/dates_view_methods_test.rb +2 -1
  214. data/test/unit/zena/use/html_tags_test.rb +12 -4
  215. data/test/unit/zena/use/refactor_test.rb +4 -3
  216. data/test/unit/zena/use/rendering_test.rb +1 -0
  217. data/test/unit/zena/use/upload_test.rb +76 -0
  218. data/test/unit/zena/use/urls_test.rb +4 -0
  219. data/test/unit/zena/use/zafu_test.rb +8 -0
  220. data/test/unit/zena/workflow/status_version_test.rb +6 -0
  221. data/test/unit/zena/zena_tags/ajax.yml +4 -4
  222. data/test/unit/zena/zena_tags/basic.yml +21 -10
  223. data/test/unit/zena/zena_tags/relations.yml +0 -6
  224. data/test/unit/zena/zena_tags/rubyless.yml +35 -0
  225. data/test/unit/zena/zena_tags/zazen.yml +4 -4
  226. data/test/unit/zena/zena_tags_test.rb +36 -4
  227. data/vendor/TextMate/Zena.tmbundle/Commands/Run all yaml tests.tmCommand +1 -1
  228. data/vendor/TextMate/Zena.tmbundle/Commands/Run focused yaml test.tmCommand +2 -3
  229. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/catch_exception.rb +39 -0
  230. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/run_script.rb +102 -58
  231. data/vendor/TextMate/Zena.tmbundle/Support/RubyMate/stdin_dialog.rb +14 -0
  232. data/vendor/TextMate/Zena.tmbundle/info.plist +2 -0
  233. data/zena.gemspec +2085 -0
  234. metadata +265 -90
  235. data/app/controllers/sessions_controller.rb +0 -41
  236. data/app/views/sites/zena_up.html.erb +0 -11
  237. data/config/database.yml +0 -40
  238. data/db/production.sqlite3 +0 -0
  239. data/lib/bricks/patcher.rb +0 -68
  240. data/lib/zena/parser/zena_tags.rb +0 -3562
  241. data/lib/zena/use/authentification.rb +0 -120
  242. data/public/images/ext/contact_pv.png +0 -0
  243. data/public/images/ext/other_pv.png +0 -0
  244. data/public/images/ext/page_pv.png +0 -0
  245. data/public/images/ext/page_tiny.png +0 -0
  246. data/public/images/ext/pdf_pv.png +0 -0
  247. data/public/images/ext/post_pv.png +0 -0
  248. data/public/images/ext/post_tiny.png +0 -0
  249. data/public/images/ext/project_pv.png +0 -0
  250. data/public/images/ext/project_tiny.png +0 -0
  251. data/public/images/ext/tag_pv.png +0 -0
  252. data/public/images/ext/zip_pv.png +0 -0
  253. data/tasks/ann.rake +0 -80
  254. data/tasks/bones.rake +0 -20
  255. data/tasks/gem.rake +0 -201
  256. data/tasks/git.rake +0 -40
  257. data/tasks/notes.rake +0 -27
  258. data/tasks/post_load.rake +0 -34
  259. data/tasks/rdoc.rake +0 -51
  260. data/tasks/rubyforge.rake +0 -55
  261. data/tasks/setup.rb +0 -292
  262. data/tasks/spec.rake +0 -54
  263. data/tasks/svn.rake +0 -47
  264. data/tasks/test.rake +0 -40
  265. data/tasks/zentest.rake +0 -36
  266. data/test/fixtures/comments.yml +0 -126
  267. data/test/fixtures/contact_contents.yml +0 -132
  268. data/test/fixtures/data_entries.yml +0 -65
  269. data/test/fixtures/discussions.yml +0 -48
  270. data/test/fixtures/document_contents.yml +0 -108
  271. data/test/fixtures/dyn_attributes.yml +0 -66
  272. data/test/fixtures/groups.yml +0 -86
  273. data/test/fixtures/groups_users.yml +0 -81
  274. data/test/fixtures/iformats.yml +0 -29
  275. data/test/fixtures/links.yml +0 -313
  276. data/test/fixtures/nodes.yml +0 -2592
  277. data/test/fixtures/relations.yml +0 -126
  278. data/test/fixtures/sites.yml +0 -58
  279. data/test/fixtures/template_contents.yml +0 -172
  280. data/test/fixtures/users.yml +0 -167
  281. data/test/fixtures/versions.yml +0 -1911
  282. data/test/fixtures/virtual_classes.yml +0 -87
  283. data/test/fixtures/zips.yml +0 -15
  284. data/test/functional/sessions_controller_test.rb +0 -73
@@ -0,0 +1,102 @@
1
+ module Zafu
2
+ module Core
3
+ module HTML
4
+ def get_html_params(params, tag_type)
5
+ res = {}
6
+ params.each do |k,v|
7
+ next unless v
8
+ if k.to_s =~ /\A(t?)set_(.+)$/
9
+ key = $2
10
+ trans = $1 == 't'
11
+ value, static = parse_attributes_in_value(v, :erb => !trans)
12
+
13
+ if trans
14
+ if static
15
+ value = ["'#{_(value)}'"] # array so it is not escaped on render
16
+ else
17
+ value = ["'<%= _(\"#{value}\") %>'"] # FIXME: use dict ! array so it is not escaped on render
18
+ end
19
+ end
20
+ res[key.to_sym] = value
21
+ elsif tag_type == :link && k == :_name
22
+ # :_name set by r_anchor
23
+ res[:name] ||= v
24
+ elsif tag_type == :link && ![:style, :class, :id, :title].include?(k)
25
+ # bad html parameter for links (some keys for link tags are used as query parameters)
26
+ # filter out
27
+ else
28
+ res[k] ||= v
29
+ end
30
+ end
31
+
32
+ #if params[:anchor]
33
+ # @anchor_param = nil
34
+ # res[:name] = anchor_name(params[:anchor], node)
35
+ #end
36
+
37
+ res
38
+ end
39
+
40
+ # Add a class name to the html_tag
41
+ def add_html_class(class_name)
42
+ if klass = @html_tag_params[:class]
43
+ @html_tag_params[:class] = "#{class_name} #{klass}"
44
+ else
45
+ @html_tag_params[:class] = class_name
46
+ end
47
+ end
48
+
49
+ def render_html_tag(text,*append)
50
+ append ||= []
51
+ return text if @html_tag_done
52
+ set_params = {}
53
+ if_params = {}
54
+ @params.each do |k,v|
55
+ if k.to_s =~ /^t?set_/
56
+ set_params[k] = v
57
+ end
58
+ end
59
+ tag_class = @html_tag_params[:class] || @params[:class]
60
+ if node_kind_of?(Node)
61
+
62
+ if @context[:make_form]
63
+ node_name = node
64
+ elsif (@method == 'each' || @method == 'each_group') && @context[:list]
65
+ node_name = var
66
+ elsif @method == 'context' || !respond_to?("r_#{@method}".to_sym)
67
+ node_name = @var || node
68
+ else
69
+ node_name = node
70
+ end
71
+
72
+ class_cond = nil
73
+ @params.each do |k,v|
74
+ if k.to_s =~ /^(.+)_if$/
75
+ klass = $1
76
+ cond = get_test_condition(node_name, :test => v)
77
+ elsif k.to_s =~ /^(.+)_if_(test|node|kind_of|klass|status|lang|can|in)$/
78
+ klass = $1
79
+ cond = get_test_condition(node_name, $2.to_sym => v)
80
+ end
81
+ if cond
82
+ class_cond = "#{cond} ? \" class='#{klass}'\" : #{class_cond}" # (x = 3) ? "class='foo'" :
83
+ end
84
+ end
85
+
86
+ if class_cond
87
+ append << "<%= #{class_cond}\"#{tag_class ? " class='#{tag_class}'" : ""}\" %>"
88
+ @html_tag_params.delete(:class)
89
+ end
90
+ end
91
+
92
+ @html_tag = 'div' if !@html_tag && (set_params != {} || @html_tag_params != {})
93
+
94
+ bak = @html_tag_params.dup
95
+ @html_tag_params = get_html_params(set_params.merge(@html_tag_params), @html_tag)
96
+ res = super(text,*append)
97
+ @html_tag_params = bak
98
+ res
99
+ end
100
+ end # HTML
101
+ end # Core
102
+ end # Zafu
@@ -0,0 +1,167 @@
1
+ # Elements here should be moved to the core zafu parser
2
+ module Zafu
3
+ module Core
4
+ module MoveToParser
5
+ def before_render
6
+ return unless super
7
+
8
+ @var = nil # reset var counter
9
+
10
+ if key = @params[:store]
11
+ set_stored(Node, key, node)
12
+ end
13
+
14
+ if key = @params[:store_date]
15
+ set_stored(Date, key, current_date)
16
+ end
17
+ if @method != 'link'
18
+ @anchor_param = @params[:anchor]
19
+ end
20
+
21
+ true
22
+ end
23
+
24
+
25
+ def after_render(text)
26
+ if @anchor_param
27
+ @params[:anchor] = @anchor_param # set back in case of double rendering so it is computed again
28
+ r_anchor + super
29
+ else
30
+ super
31
+ end
32
+ end
33
+
34
+ # Our special version of r_expand_with tag with "set_" parsing.
35
+ def r_expand_with
36
+ hash = {}
37
+ @params.each do |k,v|
38
+ if k.to_s =~ /^set_(.+)$/
39
+ # TODO: DRY with render_html_tag
40
+ k = $1
41
+ value, static = parse_attributes_in_value(v, :erb => false)
42
+ hash["exp_#{k}"] = static ? value.inspect : "\"#{value}\""
43
+ else
44
+ hash["exp_#{k}"] = v.inspect
45
+ end
46
+ end
47
+ @params = {}
48
+ expand_with(hash)
49
+ end
50
+
51
+ def expand_with(acontext={})
52
+ # set variables
53
+ context = nil
54
+ pre = ''
55
+ @blocks.each do |block|
56
+ next if block.kind_of?(String) || block.method != 'set'
57
+ @context[:vars] ||= []
58
+ context ||= @context.merge(acontext).merge(:set => true)
59
+ pre << expand_block(block, context)
60
+ @context[:vars] << block.params[:var]
61
+ end
62
+
63
+ pre + super
64
+ end
65
+
66
+ def do_method(sym)
67
+ method = sym
68
+ pre, post = '', ''
69
+
70
+ # do we need recursion ?
71
+ inc = descendant('include')
72
+ if inc && inc.params[:part] == @name
73
+ @context["#{@name}_method".to_sym] = method_name = template_url[1..-1].gsub(/[\/-]/,'_')
74
+ pre << "<% def #{method_name}(depth, node, list); return '' if depth > #{inc.params[:depth] ? [inc.params[:depth].to_i,30].min : 5}; _erbout = '' -%>"
75
+ post << "<% _erbout; end -%><%= #{method_name}(0,#{node},#{list || "[#{node}]"}) %>"
76
+ @context[:node] = 'node'
77
+ @context[:list] = 'list'
78
+ end
79
+
80
+ if @context[:make_form]
81
+ res = case method
82
+ when :r_title
83
+ make_input(:name => 'v_title')
84
+ when :r_link
85
+ make_input(:name => (@params[:attr] || 'v_title'))
86
+ when :r_show
87
+ make_input(:name => (@params[:attr] || @params[:tattr]), :date => @params[:date])
88
+ when :r_text
89
+ make_textarea(:name => 'v_text')
90
+ when :r_summary
91
+ make_textarea(:name => 'v_summary')
92
+ when :r_zazen
93
+ make_textarea(:name => @params[:attr])
94
+ else
95
+ if node_kind_of?(DataEntry) && @method.to_s =~ /node_/
96
+ # select node_id
97
+ "<%= select_id('#{base_class.to_s.underscore}', '#{@method}_id') %>"
98
+ end
99
+ end
100
+ res = "<#{@html_tag || 'div'} class='zazen'>#{res}</#{@html_tag || 'div'}>" if [:r_summary, :r_text].include?(sym)
101
+ end
102
+
103
+
104
+ res ||= super(method)
105
+ "#{pre}#{res}#{post}"
106
+ end
107
+
108
+ # recursion
109
+ def r_include
110
+ return '' if @context[:saved_template]
111
+ return super if @params[:template] || !@params[:part]
112
+ part = @params[:part].gsub(/[^a-zA-Z_]/,'')
113
+ method_name = @context["#{part}_method".to_sym]
114
+ return parser_error("no parent named '#{part}'") unless method_name
115
+ "<%= #{method_name}(depth+1,#{node},#{list}) %>"
116
+ end
117
+
118
+ # Find a block to update on the page
119
+ def find_target(name)
120
+ # find dom_id / template_url
121
+ target = nil
122
+ root.descendants('block').each do |b|
123
+ if b.name == name
124
+ target = b
125
+ break
126
+ end
127
+ end
128
+ out parser_error("could not find a block named '#{name}'") if target.nil?
129
+ target
130
+ end
131
+
132
+ def context
133
+ return @context if @context
134
+ # not rendered yet, find first parent with context
135
+ @context = parent ? parent.context : {}
136
+ end
137
+
138
+ # Block visibility of descendance with 'do_list'.
139
+ def public_descendants
140
+ all = super
141
+ if ['context', 'each', 'block'].include?(self.method)
142
+ # do not propagate 'form',etc up
143
+ all.reject do |k,v|
144
+ ['form','unlink'].include?(k)
145
+ end
146
+ elsif ['if', 'case'].include?(self.method)
147
+ all.reject do |k,v|
148
+ ['else', 'elsif', 'when'].include?(k)
149
+ end
150
+ else
151
+ all
152
+ end
153
+ end
154
+
155
+ def single_child_method
156
+ return @single_child_method if defined?(@single_child_method)
157
+ @single_child_method = if @blocks.size == 1
158
+ single_child = @blocks[0]
159
+ return nil if single_child.kind_of?(String)
160
+ single_child.html_tag ? nil : single_child.method
161
+ else
162
+ nil
163
+ end
164
+ end
165
+ end # MoveToParser
166
+ end # Core
167
+ end # Zafu
@@ -0,0 +1,58 @@
1
+ module Zafu
2
+ module Dates
3
+ def r_date
4
+ select = @params[:select]
5
+ case select
6
+ when 'main'
7
+ expand_with(:date=>'main_date')
8
+ when 'now'
9
+ expand_with(:date=>'Time.now')
10
+ else
11
+ if select =~ /^\d{4}-\d{1,2}-\d{1,2}$/
12
+ begin
13
+ d = Date.parse(select)
14
+ expand_with(:date=>select.inspect)
15
+ rescue
16
+ parser_error("invalid date '#{select}' should be 'YYYY-MM-DD'")
17
+ end
18
+ elsif date = find_stored(Date, select)
19
+ if date[0..0] == '"'
20
+ begin
21
+ d = Date.parse(date[1..-2])
22
+ expand_with(:date=>date)
23
+ rescue
24
+ parser_error("invalid date #{select} (#{date}) should be 'YYYY-MM-DD'")
25
+ end
26
+ else
27
+ expand_with(:date=>select)
28
+ end
29
+ elsif select =~ /\[(.*)\]/
30
+ date, static = parse_attributes_in_value(select, :erb => false)
31
+ expand_with(:date => "\"#{date}\"")
32
+ else
33
+ parser_error("bad parameter '#{select}'")
34
+ end
35
+ end
36
+ end
37
+
38
+ protected
39
+ def current_date
40
+ @context[:date] || 'main_date'
41
+ end
42
+
43
+ # This is used by zafu and it's a mess.
44
+ # ref_date can be a string ('2005-05-03') or ruby ('Time.now'). It should not come uncleaned from evil web.
45
+ def date_condition(date_cond, field, ref_date='today')
46
+ if date_cond == 'today' || ref_date == 'today'
47
+ ref_date = Zena::Db::NOW
48
+ elsif ref_date =~ /(\d{4}-\d{1,2}-\d{1,2}( \d{1,2}:\d{1,2}(:\d{1,2})?)?)/
49
+ ref_date = "'#{$1}'"
50
+ elsif ref_date =~ /\A"/
51
+ ref_date = "'\#{format_date(#{ref_date})}'"
52
+ else
53
+ ref_date = "'\#{#{ref_date}.strftime('%Y-%m-%d %H:%M:%S')}'"
54
+ end
55
+ Zena::Db.date_condition(date_cond, field, ref_date)
56
+ end
57
+ end # Dates
58
+ end # Zafu
@@ -0,0 +1,502 @@
1
+ module Zafu
2
+ module Display
3
+
4
+ # This should be done with rubyless... (methods on the compiler...)
5
+ class << self
6
+ def inline_methods(*args)
7
+ args.each do |name|
8
+ class_eval <<-END
9
+ def r_#{name}
10
+ "<%= #{name}(:node=>\#{node}\#{params_to_erb(@params)}) %>"
11
+ end
12
+ END
13
+ end
14
+ end
15
+
16
+ def direct_methods(*args)
17
+ args.each do |name|
18
+ class_eval <<-END
19
+ def r_#{name}
20
+ helper.#{name}
21
+ end
22
+ END
23
+ end
24
+ end
25
+ end
26
+
27
+ inline_methods :login_link, :visitor_link, :search_box, :show_menu, :show_path, :lang_links
28
+ direct_methods :uses_datebox
29
+
30
+ def r_javascripts
31
+ if @params[:list].nil?
32
+ list = %w{ prototype effects tablekit zena }
33
+ elsif @params[:list] == 'all'
34
+ list = %w{ prototype effects dragdrop tablekit zena }
35
+ else
36
+ list = @params[:list].split(',').map{|e| e.strip}
37
+ end
38
+ helper.javascript_include_tag(*list)
39
+ end
40
+
41
+ def r_stylesheets
42
+ if @params[:list] == 'all' || @params[:list].nil?
43
+ list = %w{ zena code }
44
+ else
45
+ list = @params[:list].split(',').map{|e| e.strip}
46
+ end
47
+ list << {:media => @params[:media]} if @params[:media]
48
+ helper.stylesheet_link_tag(*list)
49
+ end
50
+
51
+ def r_show
52
+ if attr_or_date = @params[:attr_or_date]
53
+ # using [var] shortcut. Can be either a date or an attribute/var
54
+ if attr_or_date == 'current_date' || attr_or_date =~ /_at$/
55
+ @params[:date] = attr_or_date
56
+ else
57
+ @params[:attr] = attr_or_date
58
+ end
59
+ end
60
+
61
+ if var_name = @params[:var]
62
+ return parser_error("var #{@params[:var].inspect} not set") unless @context[:vars] && @context[:vars].include?(var_name)
63
+ attribute_method = "set_#{var_name}"
64
+ elsif @params[:eval]
65
+ return unless attribute_method = parse_eval_parameter(@params[:eval])
66
+ elsif @params[:tattr]
67
+ attribute_method = "_(#{node_attribute(@params[:tattr], :else=>@params[:else], :default=>@params[:default])})"
68
+ elsif @params[:attr]
69
+ attribute_method = node_attribute(@params[:attr], :else=>@params[:else], :default=>@params[:default])
70
+ elsif p = @params[:param]
71
+ return "<%= params[#{p.to_sym.inspect}] %>"
72
+ elsif @params[:date]
73
+ # date can be any attribute v_created_at or updated_at etc.
74
+ # TODO format with @params[:format] and @params[:tformat] << translated format
75
+ # TODO: test
76
+ if @params[:tformat]
77
+ format = _(@params[:tformat])
78
+ elsif @params[:format]
79
+ format = @params[:format]
80
+ else
81
+ format = "%Y-%m-%d"
82
+ end
83
+
84
+ tz = ''
85
+ lang = ''
86
+ if tz_name = @params[:time_zone]
87
+ tz_list = @params.reject {|k,v| !(k.to_s =~ /^time_zone\d*$/)}.to_a.sort {|a,b| a[0].to_s <=> b[0].to_s }.map do |k,tz_name|
88
+ if tz_name =~ /^\[(\w+)\]$/
89
+ node_attribute($1)
90
+ else
91
+ begin
92
+ TZInfo::Timezone.get(tz_name)
93
+ rescue TZInfo::InvalidTimezoneIdentifier
94
+ return parser_error("invalid timezone #{tz_name.inspect}")
95
+ end
96
+ tz_name.inspect
97
+ end
98
+ end
99
+ tz = ", #{tz_list.join(' || ')}"
100
+ end
101
+ if lang = @params[:lang]
102
+ tz = ', nil' if tz == ''
103
+ lang = ", #{lang.inspect}"
104
+ end
105
+ attribute_method = "format_date(#{node_attribute(@params[:date])}, #{format.inspect}#{tz}#{lang})"
106
+ elsif @context[:trans]
107
+ # error
108
+ return "no attribute for 'show'".inspect
109
+ else
110
+ attribute_method = node_class.ancestors.include?(String) ? node : node_attribute('to_s')
111
+ end
112
+
113
+ if !@params[:date] && fmt = @params[:format]
114
+ begin
115
+ # test argument
116
+ sprintf(fmt, 123.45)
117
+ rescue ArgumentError
118
+ return parser_error("incorect format #{fmt.inspect}")
119
+ end
120
+ if fmt =~ /%[\d\.]*f/
121
+ modifier = ".to_f"
122
+ elsif fmt =~ /%[\d\.]*i/
123
+ modifier = ".to_i"
124
+ else
125
+ modifier = ''
126
+ end
127
+
128
+ if @params[:zero] == 'hide'
129
+ attribute_method = "sprintf_unless_zero(#{fmt.inspect}, #{attribute_method}#{modifier})"
130
+ else
131
+ attribute_method = "sprintf(#{fmt.inspect}, #{attribute_method}#{modifier})"
132
+ end
133
+ end
134
+
135
+
136
+ if @context[:trans]
137
+ # TODO: what do we do here with gsubs, url ?
138
+ return attribute_method
139
+ end
140
+
141
+ if gsub = @params[:gsub]
142
+ if gsub =~ /\A\/(.+)\/(.+)\/\Z/
143
+ value = $2
144
+ key = $1.gsub(/\#([\{\$\@])/,'# \1') # FIXME: SECURITY.
145
+ # Please note that .gsub(/#([\{\$\@])/,'\#\1') won't work, since '\#{blah}' will become '\\#{blah}' and 'blah' will be evaluated.
146
+ regexp_ok = begin
147
+ output = StringIO.open('','w')
148
+ $stderr = output
149
+ re = /#{key}/
150
+ output.string !~ /warning:/
151
+ rescue
152
+ false
153
+ ensure
154
+ $stderr = STDERR
155
+ false
156
+ end
157
+
158
+ if regexp_ok
159
+ attribute_method = "#{attribute_method}.to_s.gsub(/#{key}/,#{value.inspect})"
160
+ else
161
+ # invalid regexp
162
+ return parser_error("invalid gsub #{gsub.inspect}")
163
+ end
164
+ else
165
+ # error
166
+ return parser_error("invalid gsub #{gsub.inspect}")
167
+ end
168
+ end
169
+
170
+ if @params[:actions]
171
+ actions = "<%= node_actions(:node=>#{node}#{params_to_erb(:actions=>@params[:actions], :publish_after_save=>auto_publish_param)}) %>"
172
+ else
173
+ actions = ''
174
+ end
175
+
176
+ attribute = @params[:attr] || @params[:tattr] || @params[:date]
177
+
178
+ if (@params[:edit_preview] || @params[:ep]) == 'true'
179
+ @html_tag_params[:id] = "#{attribute}#{erb_node_id}"
180
+ @html_tag ||= 'span'
181
+ end
182
+
183
+ if @params[:edit] == 'true' && !['url','path'].include?(attribute)
184
+ "<% if #{node}.can_write? -%><span class='show_edit' id='#{erb_dom_id("_#{attribute}")}'>#{actions}<%= link_to_remote(#{attribute_method}, :url => edit_node_path(#{node_id}) + \"?attribute=#{attribute}&dom_id=#{dom_id("_#{attribute}")}#{auto_publish_param(true)}\", :method => :get) %></span><% else -%>#{actions}<%= #{attribute_method} %><% end -%>"
185
+ else
186
+ "#{actions}<%= #{attribute_method} %>"
187
+ end
188
+ end
189
+
190
+ def r_zazen
191
+ attribute = @params[:attr] || @params[:tattr]
192
+ limit = @params[:limit] ? ", :limit=>#{@params[:limit].to_i}" : ""
193
+ if @context[:trans]
194
+ # TODO: what do we do here with dates ?
195
+ return "#{node_attribute(attribute)}"
196
+ elsif @params[:tattr]
197
+ return "<%= zazen(_(#{node_attribute(attribute)})#{limit}, :node=>#{node(Node)}) %>"
198
+ elsif @params[:attr]
199
+ if output_format == 'html'
200
+ res = "<%= zazen(#{node_attribute(attribute)}#{limit}, :node=>#{node(Node)}) %>"
201
+ else
202
+ return "<%= zazen(#{node_attribute(attribute)}#{limit}, :node=>#{node(Node)}, :output=>#{output_format.inspect}) %>"
203
+ end
204
+ elsif @params[:date]
205
+ # date can be any attribute v_created_at or updated_at etc.
206
+ # TODO format with @params[:format] and @params[:tformat] << translated format
207
+ else
208
+ # error
209
+ end
210
+
211
+ @html_tag ||= 'div'
212
+
213
+ add_html_class('zazen')
214
+
215
+ if (@params[:edit_preview] || @params[:ep]) == 'true'
216
+ @html_tag_params[:id] = "#{attribute}#{erb_node_id}"
217
+ end
218
+
219
+ if @params[:edit] == 'true' && !['url','path'].include?(attribute)
220
+ edit_text = _('edit')
221
+ @html_tag_params[:id] = erb_dom_id("_#{attribute}")
222
+ res = "<% if #{node}.can_write? -%><span class='zazen_edit'><%= link_to_remote(#{edit_text.inspect}, :url => edit_node_path(#{node_id}) + \"?attribute=#{attribute}&dom_id=#{dom_id("_#{attribute}")}#{auto_publish_param(true)}&zazen=true\", :method => :get) %></span><% end -%>#{res}"
223
+ else
224
+ res
225
+ end
226
+ end
227
+
228
+ # TODO: test
229
+ def r_filter
230
+ if upd = @params[:update]
231
+ return unless block = find_target(upd)
232
+ else
233
+ return parser_error("missing 'block' in same parent") unless parent && block = parent.descendant('block')
234
+ end
235
+ return parser_error("cannot use 's' as key (used by start_node)") if @params[:key] == 's'
236
+ out "<%= form_remote_tag(:url => zafu_node_path(#{node_id}), :method => :get, :html => {:id => \"#{dom_id}_f\"}) %><div class='hidden'><input type='hidden' name='t_url' value='#{block.template_url}'/><input type='hidden' name='dom_id' value='#{block.erb_dom_id}'/>#{start_node_s_param(:input)}</div><div class='wrapper'>"
237
+ if @blocks == []
238
+ out "<input type='text' name='#{@params[:key] || 'f'}' value='<%= params[#{(@params[:key] || 'f').to_sym.inspect}] %>'/>"
239
+ else
240
+ out expand_with(:in_filter => true)
241
+ end
242
+ out "</div></form>"
243
+ if @params[:live] || @params[:update]
244
+ out "<%= observe_form( \"#{dom_id}_f\" , :method => :get, :frequency => 1, :submit =>\"#{dom_id}_f\", :url => zafu_node_path(#{node_id})) %>"
245
+ end
246
+ end
247
+
248
+ def r_title
249
+ if node_kind_of?(Version)
250
+ node = "#{self.node}.node"
251
+ elsif node_kind_of?(Node)
252
+ node = self.node
253
+ else
254
+ return parser_error('title','only works with nodes')
255
+ end
256
+ title_params = {}
257
+
258
+ title_params[:check_lang] = @params[:check_lang] if @params.include?(:check_lang)
259
+
260
+ if @params[:link]
261
+ value, static = parse_attributes_in_value(@params[:link], :erb => false)
262
+ link_param = ", :link=>\"#{value}\""
263
+ else
264
+ link_param = ''
265
+ end
266
+
267
+ res = "<%= show_title(:node=>#{node}#{link_param}#{params_to_erb(title_params)}"
268
+ if @params[:text]
269
+ res << ", :text=>#{@params[:text].inspect}"
270
+ elsif @params[:attr]
271
+ res << ", :text=>#{node_attribute(@params[:attr])}"
272
+ end
273
+
274
+ if @params.include?(:project)
275
+ res << ", :project=>#{@params[:project] == 'true'}"
276
+ end
277
+ res << ")"
278
+ if @params[:actions]
279
+ res << " + node_actions(:node=>#{node}#{params_to_erb(:actions=>@params[:actions], :publish_after_save=>auto_publish_param)})"
280
+ end
281
+ res << "%>"
282
+ if @params[:status] == 'true' || (@params[:status].nil? && @params[:actions])
283
+ @html_tag ||= 'span'
284
+ add_html_class("s<%= #{node}.version.status %>")
285
+ end
286
+ res
287
+ end
288
+
289
+ def r_content_for_layout
290
+ "<% if content_for_layout = yield -%><%= content_for_layout %><% else -%>" +
291
+ expand_with +
292
+ "<% end -%>"
293
+ end
294
+
295
+ def r_title_for_layout
296
+ "<% if @title_for_layout -%><%= @title_for_layout %><% elsif @node && !@node.new_record? -%><%= @node.rootpath %><% elsif @node.parent -%><%= @node.parent.rootpath %><% else -%>" +
297
+ expand_with +
298
+ "<% end -%>"
299
+ end
300
+
301
+ # TODO: replace with a more general 'zazen' or 'show' with id ?
302
+ def r_summary
303
+ limit = @params[:limit] ? ", :limit=>#{@params[:limit].to_i}" : ""
304
+ @html_tag ||= 'div'
305
+ if @html_tag_params[:id]
306
+ # add a sub-div
307
+ pre = "<div id='v_summary#{erb_node_id}'>"
308
+ post = "</div>"
309
+ else
310
+ pre = post = ''
311
+ @html_tag_params[:id] = "v_summary#{erb_node_id}"
312
+ end
313
+
314
+ add_html_class('zazen')
315
+
316
+ unless @params[:or]
317
+ text = @params[:text] ? @params[:text].inspect : node_attribute('v_summary')
318
+ out "#{pre}<%= zazen(#{text}#{limit}, :node=>#{node(Node)}) %>#{post}"
319
+ else
320
+ limit ||= ', :limit => 2'
321
+ first_name = 'v_summary'
322
+ first = node_attribute(first_name)
323
+
324
+ second_name = @params[:or].gsub(/[^a-z_]/,'') # FIXME: ist this still needed ? (ERB injection)
325
+ second = node_attribute(second_name)
326
+ out "#{pre}<% if #{first} != '' %>"
327
+ out "<%= zazen(#{first}, :node=>#{node(Node)}) %>"
328
+ out "<% else %>"
329
+ out "<%= zazen(#{second}#{limit}, :node=>#{node(Node)}) %>"
330
+ out "<% end %>#{post}"
331
+ end
332
+ end
333
+
334
+ def r_show_author
335
+ if @params[:size] == 'large'
336
+ out "#{_("posted by")} <b><%= #{node}.author.fullname %></b>"
337
+ out "<% if #{node}[:user_id] != #{node}.version[:user_id] -%>"
338
+ out "<% if #{node}[:ref_lang] != #{node}.version[:lang] -%>"
339
+ out "#{_("traduction by")} <b><%= #{node}.version.author.fullname %></b>"
340
+ out "<% else -%>"
341
+ out "#{_("modified by")} <b><%= #{node}.version.author.fullname %></b>"
342
+ out "<% end"
343
+ out " end -%>"
344
+ out " #{_("on")} <%= format_date(#{node}.version.updated_at, #{_('short_date').inspect}) %>."
345
+ if @params[:traductions] == 'true'
346
+ out " #{_("Traductions")} : <span class='traductions'><%= helper.traductions(:node=>#{node}).join(', ') %></span>"
347
+ end
348
+ else
349
+ out "<b><%= #{node}.version.author.initials %></b> - <%= format_date(#{node}.version.updated_at, #{_('short_date').inspect}) %>"
350
+ if @params[:traductions] == 'true'
351
+ out " <span class='traductions'>(<%= helper.traductions(:node=>#{node}).join(', ') %>)</span>"
352
+ end
353
+ end
354
+ end
355
+
356
+ # TODO: test
357
+ def r_actions
358
+ out expand_with
359
+ out "<%= node_actions(:node=>#{node}#{params_to_erb(:actions=>@params[:select], :publish_after_save=>auto_publish_param)}) %>"
360
+ end
361
+
362
+ # TODO: test
363
+ def r_admin_links
364
+ "<%= show_link(:admin_links).join('</#{@html_tag}><#{@html_tag}>') %>"
365
+ end
366
+
367
+ def r_text
368
+ text = @params[:text] ? @params[:text].inspect : "#{node_attribute('v_text')}"
369
+ limit = @params[:limit] ? ", :limit=>#{@params[:limit].to_i}" : ""
370
+
371
+ @html_tag ||= 'div'
372
+
373
+ if @html_tag_params[:id]
374
+ # add a sub-div
375
+ pre = "<div id='v_text#{erb_node_id}'>"
376
+ post = "</div>"
377
+ else
378
+ pre = post = ''
379
+ @html_tag_params[:id] = "v_text#{erb_node_id}"
380
+ end
381
+
382
+ add_html_class('zazen')
383
+
384
+ unless @params[:empty] == 'true'
385
+ out "#{pre}<% if #{node}.kind_of?(TextDocument); l = #{node}.content_lang -%>"
386
+ out "<%= zazen(\"<code\#{l ? \" lang='\#{l}'\" : ''} class=\\'full\\'>\#{#{text}}</code>\") %>"
387
+ out "<% else -%>"
388
+ out "<%= zazen(#{text}#{limit}, :node=>#{node(Node)}) %>"
389
+ out "<% end -%>#{post}"
390
+ else
391
+ out "#{pre}#{post}"
392
+ end
393
+ end
394
+
395
+ def r_img
396
+ return unless node_kind_of?(Node)
397
+ if @params[:src]
398
+ finder, klass = build_finder_for(:first, @params[:src])
399
+ return unless finder
400
+ return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
401
+ img = finder
402
+ else
403
+ img = node
404
+ end
405
+ mode = @params[:mode] || 'std'
406
+ # FIXME: replace this call by something that integrates better with html_tag_params and such.
407
+ res = "img_tag(#{img}, :mode=>#{mode.inspect}"
408
+ [:class, :alt_src, :id, :border, :style].each do |k|
409
+ res += ", :#{k}=>#{@params[k].inspect}" if @params[k]
410
+ end
411
+ res += ", :host => #{@context["exp_host"]}" if @context["exp_host"]
412
+ res += ")"
413
+ if @params[:link]
414
+ finder, klass = build_finder_for(:first, @params[:link])
415
+ return unless finder
416
+ return parser_error("invalid class (#{klass})") unless klass.ancestors.include?(Node)
417
+
418
+ opts_str = @context["exp_host"] ? ", :host => #{@context["exp_host"]}" : ""
419
+
420
+ "<a href='<%= zen_path(#{finder}#{opts_str}) %>'><%= #{res} %></a>"
421
+ else
422
+ "<%= #{res} %>"
423
+ end
424
+ end
425
+
426
+ # Compute statistics on elements in the current list context.
427
+ def r_stat
428
+ return parser_error("must be used inside a list context") unless list
429
+ find = @params[:find] || @params[:date] || 'count'
430
+ key = @params[:of] || @params[:from] || 'value'
431
+ case find
432
+ when 'sum'
433
+ value = "#{list}.flatten.inject(0) {|#{var}_sum,#{var}| #{var}_sum + #{node_attribute(key, :node => var)}.to_f}"
434
+ when 'min'
435
+ value = "#{node_attribute(key, :node => "min_array(#{list}) {|e| #{node_attribute(key, :node => 'e')}}")}"
436
+ when 'max'
437
+ value = "#{node_attribute(key, :node => "max_array(#{list}) {|e| #{node_attribute(key, :node => 'e')}}")}"
438
+ when 'count'
439
+ return "<%= #{list}.size %>"
440
+ end
441
+ if @params[:date]
442
+ # FIXME: DRY (r_show)
443
+ if @params[:tformat]
444
+ format = _(@params[:tformat])
445
+ elsif @params[:format]
446
+ format = @params[:format]
447
+ else
448
+ format = "%Y-%m-%d"
449
+ end
450
+ "<%= #{list}==[] ? '' : format_date(#{value}, #{format.inspect}) %>"
451
+ elsif format = @params[:format]
452
+
453
+ if @params[:zero] == 'hide'
454
+ "<%= #{list}==[] ? '' : sprintf_unless_zero(#{@params[:format].inspect}, #{value}) %>"
455
+ else
456
+ "<%= #{list}==[] ? '' : sprintf(#{@params[:format].inspect}, #{value}) %>"
457
+ end
458
+ else
459
+ "<%= #{list}==[] ? '' : #{value} %>"
460
+ end
461
+ end
462
+
463
+ def r_design
464
+ if @params[:by]
465
+ by = "<a href='#{@params[:href]}'>#{@params[:by]}</a>"
466
+ else
467
+ by = expand_with(:trans => true)
468
+ end
469
+ unless skin = @params[:skin]
470
+ skin = helper.instance_variable_get(:@controller).instance_variable_get(:@skin_name)
471
+ end
472
+ skin = "<i>#{skin}</i>" unless skin.blank?
473
+ _("%{skin}, design by %{name}") % {:name => by, :skin => skin}
474
+ end
475
+
476
+ # Shows a 'made with zena' link or logo. ;-) Thanks for using this !
477
+ # TODO: test and add translation.
478
+ # <r:zena show='logo'/> or <r:zena show='text'/> == <r:zena/>
479
+ def r_zena
480
+ if logo = @params[:logo]
481
+ # FIXME
482
+ case logo
483
+ when 'tiny'
484
+ else
485
+ end
486
+ else
487
+ text = case @params[:type]
488
+ when 'riding'
489
+ _("riding zena")
490
+ when 'peace'
491
+ _("in peace with zena")
492
+ when 'garden'
493
+ _("a zen garden")
494
+ else
495
+ _("made with zena")
496
+ end
497
+ "<a class='zena' href='http://zenadmin.org' title='zena <%= Zena::VERSION %>'>#{text}</a>"
498
+ end
499
+ end
500
+
501
+ end # Display
502
+ end # Zafu