zena 1.0.0.rc2 → 1.0.0.rc3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (274) hide show
  1. data/History.txt +23 -0
  2. data/README.rdoc +1 -1
  3. data/app/controllers/columns_controller.rb +3 -31
  4. data/app/controllers/comments_controller.rb +8 -3
  5. data/app/controllers/data_entries_controller.rb +1 -1
  6. data/app/controllers/documents_controller.rb +2 -2
  7. data/app/controllers/nodes_controller.rb +29 -12
  8. data/app/controllers/relations_controller.rb +2 -2
  9. data/app/controllers/sites_controller.rb +1 -1
  10. data/app/controllers/user_sessions_controller.rb +6 -3
  11. data/app/controllers/users_controller.rb +18 -16
  12. data/app/controllers/versions_controller.rb +20 -18
  13. data/app/controllers/virtual_classes_controller.rb +103 -17
  14. data/app/helpers/users_helper.rb +1 -1
  15. data/app/models/column.rb +19 -50
  16. data/app/models/comment.rb +2 -1
  17. data/app/models/node.rb +45 -22
  18. data/app/models/relation.rb +13 -0
  19. data/app/models/relation_proxy.rb +3 -2
  20. data/app/models/role.rb +213 -4
  21. data/app/models/site.rb +18 -11
  22. data/app/models/template.rb +37 -35
  23. data/app/models/version.rb +1 -1
  24. data/app/models/virtual_class.rb +154 -86
  25. data/app/views/columns/_li.html.erb +1 -1
  26. data/app/views/columns/index.html.erb +1 -9
  27. data/app/views/comments/index.rhtml +10 -8
  28. data/app/views/documents/_crop.rhtml +5 -6
  29. data/app/views/documents/crop_form.rjs +3 -2
  30. data/app/views/groups/index.rhtml +1 -1
  31. data/app/views/iformats/index.rhtml +1 -1
  32. data/app/views/nodes/_import_results.rhtml +1 -1
  33. data/app/views/nodes/_parent.rhtml +1 -2
  34. data/app/views/nodes/update.rjs +3 -4
  35. data/app/views/relations/index.erb +1 -1
  36. data/app/views/sites/index.erb +1 -1
  37. data/app/views/templates/drive_tabs/_drive.rhtml +0 -2
  38. data/app/views/templates/edit_tabs/_image.rhtml +1 -1
  39. data/app/views/templates/edit_tabs/_title.rhtml +0 -6
  40. data/app/views/users/index.rhtml +1 -1
  41. data/app/views/users/preferences.html.erb +2 -2
  42. data/app/views/versions/backup.rjs +1 -1
  43. data/app/views/versions/custom_tab.rhtml +9 -4
  44. data/app/views/versions/destroy.rjs +2 -2
  45. data/app/views/versions/update.rjs +2 -9
  46. data/app/views/virtual_classes/_form.erb +3 -2
  47. data/app/views/virtual_classes/import_prepare.html.erb +13 -0
  48. data/app/views/virtual_classes/index.erb +28 -8
  49. data/app/views/zafu/default/Node-+adminLayout.zafu +1 -13
  50. data/app/views/zafu/default/Node-+login.zafu +1 -0
  51. data/app/views/zafu/default/Node-+notFound.zafu +1 -1
  52. data/app/views/zafu/default/Node-+popupLayout.zafu +1 -2
  53. data/app/views/zafu/default/Node-+search.zafu +1 -1
  54. data/app/views/zafu/default/Node-admin.zafu +205 -0
  55. data/app/views/zafu/default/Node.zafu +11 -11
  56. data/bricks/captcha/lib/bricks/captcha.rb +3 -2
  57. data/bricks/mongrel/zena/init.rb +2 -1
  58. data/bricks/pdf/README +5 -5
  59. data/bricks/pdf/lib/bricks/pdf/engine/prince.rb +2 -2
  60. data/bricks/pdf/lib/bricks/pdf/engine/xhtml2pdf.rb +2 -2
  61. data/bricks/pdf/lib/bricks/pdf/install.rb +5 -5
  62. data/bricks/pdf/lib/bricks/pdf.rb +11 -11
  63. data/bricks/pdf/test/engines/test_prince.rb +4 -4
  64. data/bricks/pdf/test/engines/test_xhtml2pdf.rb +4 -4
  65. data/bricks/pdf/test/shoulda_macros/shoulda_pdf.rb +2 -2
  66. data/bricks/pdf/zena/init.rb +2 -2
  67. data/bricks/pdf/zena/tasks.rb +2 -2
  68. data/bricks/sphinx/lib/bricks/sphinx.rb +6 -2
  69. data/bricks/sphinx/zena/{sphinx.yml → sphinx.yml.erb} +2 -2
  70. data/bricks/sphinx/zena/tasks.rb +28 -2
  71. data/bricks/tags/lib/bricks/tags.rb +16 -1
  72. data/bricks/tags/zena/test/unit/tags_test.rb +15 -0
  73. data/bricks/tags/zena/test/zafu/tags.yml +5 -1
  74. data/bricks/worker/lib/bricks/worker.rb +39 -0
  75. data/bricks/worker/zena/deploy.rb +0 -2
  76. data/bricks/worker/zena/init.rb +1 -0
  77. data/bricks/worker/zena/test/sites/zena/delayed_jobs.yml +16 -0
  78. data/bricks/worker/zena/test/zafu/worker.yml +8 -0
  79. data/bricks/zena/zena/migrate/01_base.rb +36 -60
  80. data/bricks/zena/zena/migrate/02_zerox1_schema.rb +388 -0
  81. data/bricks/zena/zena/migrate/03_zerox1_data.rb +380 -0
  82. data/bricks/zena/zena/migrate/20110315161158_add_reverse_scope_to_roles.rb +9 -0
  83. data/config/database_example.yml +1 -1
  84. data/config/environment.rb +1 -1
  85. data/config/gems.yml +17 -14
  86. data/db/init/base/skins/default/Node-+index.zafu +8 -1
  87. data/db/init/base/skins/default/Node-+login.zafu +1 -0
  88. data/db/init/base/skins/default/Node-+popupLayout.zafu +1 -2
  89. data/db/init/base/skins/default/Node-+search.zafu +2 -2
  90. data/db/init/base/skins/default/Node.zafu +9 -9
  91. data/db/init/base/skins/default/{favicon.png → img/favicon.png} +0 -0
  92. data/db/init/base/skins/default/{style.css → img/style.css} +0 -0
  93. data/db/init/base/skins/default/img/translations.yml +11 -0
  94. data/db/init/base/skins/default/notes.zafu +7 -9
  95. data/doc/zafu_changes.yml +12 -0
  96. data/lib/bricks/loader.rb +38 -15
  97. data/lib/tasks/zena.rake +74 -24
  98. data/lib/zena/acts/enrollable.rb +4 -1
  99. data/lib/zena/acts/secure.rb +2 -48
  100. data/lib/zena/acts/serializable.rb +13 -1
  101. data/lib/zena/app.rb +9 -0
  102. data/lib/zena/code_syntax.rb +154 -151
  103. data/lib/zena/console.rb +141 -0
  104. data/lib/zena/controller/test_case.rb +1 -1
  105. data/lib/zena/db_helper/abstract_db.rb +17 -5
  106. data/lib/zena/db_helper/mysql.rb +14 -12
  107. data/lib/zena/db_helper/postgresql.rb +1 -2
  108. data/lib/zena/db_helper/sqlite3.rb +6 -6
  109. data/lib/zena/deploy/awstats.conf.rhtml +1 -1
  110. data/lib/zena/deploy/httpd.rhtml +6 -1
  111. data/lib/zena/deploy/vhost.rhtml +9 -1
  112. data/lib/zena/deploy.rb +12 -7
  113. data/lib/zena/foxy_parser.rb +3 -1
  114. data/lib/zena/info.rb +1 -1
  115. data/lib/zena/parser/zafu_tags.rb +1 -0
  116. data/lib/zena/parser/zazen_rules.rb +1 -1
  117. data/lib/zena/remote/node.rb +15 -3
  118. data/lib/zena/remote/serializable_array.rb +19 -0
  119. data/lib/zena/remote.rb +1 -0
  120. data/lib/zena/routes.rb +7 -2
  121. data/lib/zena/site_worker.rb +11 -1
  122. data/lib/zena/unit/test_case.rb +68 -0
  123. data/lib/zena/use/action.rb +6 -2
  124. data/lib/zena/use/ajax.rb +127 -53
  125. data/lib/zena/use/ancestry.rb +11 -8
  126. data/lib/zena/use/calendar.rb +265 -129
  127. data/lib/zena/use/conditional.rb +1 -1
  128. data/lib/zena/use/context.rb +5 -5
  129. data/lib/zena/use/dates.rb +172 -60
  130. data/lib/zena/use/display.rb +70 -39
  131. data/lib/zena/use/error_rendering.rb +1 -3
  132. data/lib/zena/use/field_index.rb +4 -1
  133. data/lib/zena/use/forms.rb +94 -72
  134. data/lib/zena/use/fulltext.rb +16 -24
  135. data/lib/zena/use/html_tags.rb +20 -12
  136. data/lib/zena/use/i18n.rb +37 -37
  137. data/lib/zena/use/image_builder.rb +8 -1
  138. data/lib/zena/use/ml_index.rb +16 -16
  139. data/lib/zena/use/prop_eval.rb +10 -5
  140. data/lib/zena/use/query_builder.rb +55 -23
  141. data/lib/zena/use/query_node.rb +51 -25
  142. data/lib/zena/use/refactor.rb +2 -28
  143. data/lib/zena/use/relations.rb +1 -1
  144. data/lib/zena/use/rendering.rb +29 -0
  145. data/lib/zena/use/scope_index.rb +75 -14
  146. data/lib/zena/use/search.rb +5 -10
  147. data/lib/zena/use/test_helper.rb +2 -2
  148. data/lib/zena/use/urls.rb +125 -104
  149. data/lib/zena/use/workflow.rb +2 -1
  150. data/lib/zena/use/zafu_attributes.rb +2 -2
  151. data/lib/zena/use/zafu_safe_definitions.rb +20 -0
  152. data/lib/zena/use/zafu_templates.rb +20 -6
  153. data/lib/zena/use/zazen.rb +31 -20
  154. data/lib/zena/view/test_case.rb +5 -0
  155. data/lib/zena/zafu_compiler.rb +24 -2
  156. data/lib/zena.rb +12 -6
  157. data/locale/de/LC_MESSAGES/zena.mo +0 -0
  158. data/locale/de/zena.po +1345 -1164
  159. data/locale/en/LC_MESSAGES/zena.mo +0 -0
  160. data/locale/en/zena.po +1275 -1129
  161. data/locale/fr/LC_MESSAGES/zena.mo +0 -0
  162. data/locale/fr/zena.mo +0 -0
  163. data/locale/fr/zena.po +1617 -1441
  164. data/locale/log.txt +9 -0
  165. data/locale/zena.pot +957 -748
  166. data/public/javascripts/prototype.js +1 -1
  167. data/public/javascripts/zena.js +99 -44
  168. data/public/stylesheets/admin.css +6 -4
  169. data/public/stylesheets/backend.css +71 -0
  170. data/public/stylesheets/calendar.css +24 -25
  171. data/public/stylesheets/code.css +11 -6
  172. data/public/stylesheets/comment.css +2 -1
  173. data/public/stylesheets/popup.css +7 -8
  174. data/test/custom_queries/complex.host.yml +15 -1
  175. data/test/fixtures/files/Node-test.zafu +29 -28
  176. data/test/fixtures/files/translations_de.yml +12 -1
  177. data/test/fixtures/files/translations_fr.yml +12 -1
  178. data/test/functional/comments_controller_test.rb +9 -0
  179. data/test/functional/iformats_controller_test.rb +1 -1
  180. data/test/functional/nodes_controller_test.rb +124 -35
  181. data/test/functional/users_controller_test.rb +132 -3
  182. data/test/functional/virtual_classes_controller_test.rb +75 -4
  183. data/test/integration/navigation_test.rb +51 -9
  184. data/test/integration/query_node/basic.yml +19 -7
  185. data/test/integration/query_node/complex.yml +1 -1
  186. data/test/integration/query_node/dates.yml +27 -1
  187. data/test/integration/query_node/filters.yml +1 -1
  188. data/test/integration/query_node/relations.yml +13 -4
  189. data/test/integration/query_node_test.rb +4 -0
  190. data/test/integration/xml_api_test.rb +6 -1
  191. data/test/integration/zafu_compiler/action.yml +3 -3
  192. data/test/integration/zafu_compiler/ajax.yml +103 -22
  193. data/test/integration/zafu_compiler/basic.yml +0 -52
  194. data/test/integration/zafu_compiler/calendar.yml +44 -20
  195. data/test/integration/zafu_compiler/comments.yml +53 -0
  196. data/test/integration/zafu_compiler/complex.yml +11 -11
  197. data/test/integration/zafu_compiler/complex_ok.yml +16 -3
  198. data/test/integration/zafu_compiler/conditional.yml +15 -5
  199. data/test/integration/zafu_compiler/context.yml +9 -0
  200. data/test/integration/zafu_compiler/dates.yml +43 -15
  201. data/test/integration/zafu_compiler/display.yml +60 -6
  202. data/test/integration/zafu_compiler/errors.yml +6 -2
  203. data/test/integration/zafu_compiler/forms.yml +45 -6
  204. data/test/integration/zafu_compiler/i18n.yml +8 -1
  205. data/test/integration/zafu_compiler/meta.yml +38 -0
  206. data/test/integration/zafu_compiler/query.yml +43 -4
  207. data/test/integration/zafu_compiler/relations.yml +26 -33
  208. data/test/integration/zafu_compiler/rubyless.yml +10 -0
  209. data/test/integration/zafu_compiler/safe_definitions.yml +21 -1
  210. data/test/integration/zafu_compiler/urls.yml +75 -5
  211. data/test/integration/zafu_compiler/version.yml +2 -2
  212. data/test/integration/zafu_compiler/zafu_attributes.yml +5 -1
  213. data/test/integration/zafu_compiler/zazen.yml +14 -6
  214. data/test/integration/zafu_compiler_test.rb +5 -1
  215. data/test/sites/complex/columns.yml +5 -0
  216. data/test/sites/complex/roles.yml +4 -0
  217. data/test/sites/zena/nodes.yml +13 -2
  218. data/test/sites/zena/roles.yml +13 -5
  219. data/test/sites/zena/versions.yml +27 -9
  220. data/test/unit/column_test.rb +51 -5
  221. data/test/unit/iformat_test.rb +2 -2
  222. data/test/unit/node_test.rb +29 -17
  223. data/test/unit/note_test.rb +1 -1
  224. data/test/unit/relation_proxy_test.rb +4 -5
  225. data/test/unit/relation_test.rb +16 -0
  226. data/test/unit/remote_test.rb +2 -2
  227. data/test/unit/role_test.rb +292 -4
  228. data/test/unit/site_test.rb +12 -0
  229. data/test/unit/template_test.rb +1 -1
  230. data/test/unit/text_document_test.rb +1 -1
  231. data/test/unit/virtual_class_test.rb +200 -83
  232. data/test/unit/zena/acts/enrollable_test.rb +26 -31
  233. data/test/unit/zena/use/calendar_test.rb +90 -37
  234. data/test/unit/zena/use/field_index_test.rb +28 -0
  235. data/test/unit/zena/use/html_tags_test.rb +7 -3
  236. data/test/unit/zena/use/ml_index_test.rb +2 -16
  237. data/test/unit/zena/use/nested_attributes_alias_view_test.rb +2 -2
  238. data/test/unit/zena/use/prop_eval_test.rb +50 -8
  239. data/test/unit/zena/use/query_node_test.rb +11 -0
  240. data/test/unit/zena/use/rendering_test.rb +72 -0
  241. data/test/unit/zena/use/scope_index_test.rb +37 -2
  242. data/test/unit/zena/use/urls_test.rb +10 -0
  243. data/test/unit/zena/use/zazen_test.rb +3 -3
  244. data/vendor/plugins/gettext_i18n_rails/Gemfile +11 -0
  245. data/vendor/plugins/gettext_i18n_rails/Gemfile.lock +92 -0
  246. data/vendor/plugins/gettext_i18n_rails/Rakefile +12 -17
  247. data/vendor/plugins/gettext_i18n_rails/Readme.md +215 -0
  248. data/vendor/plugins/gettext_i18n_rails/VERSION +1 -1
  249. data/vendor/plugins/gettext_i18n_rails/gettext_i18n_rails.gemspec +38 -34
  250. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/active_record.rb +1 -1
  251. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/backend.rb +30 -14
  252. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/haml_parser.rb +1 -1
  253. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/html_safe_translations.rb +29 -0
  254. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/i18n_hacks.rb +29 -1
  255. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/model_attributes_finder.rb +7 -1
  256. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/railtie.rb +10 -0
  257. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/ruby_gettext_extractor.rb +6 -2
  258. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/string_interpolate_fix.rb +20 -0
  259. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails/tasks.rb +120 -0
  260. data/vendor/plugins/gettext_i18n_rails/lib/gettext_i18n_rails.rb +10 -3
  261. data/vendor/plugins/gettext_i18n_rails/lib/tasks/gettext_rails_i18n.rake +1 -74
  262. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/active_record_spec.rb +51 -20
  263. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/backend_spec.rb +12 -7
  264. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails/string_interpolate_fix_spec.rb +32 -0
  265. data/vendor/plugins/gettext_i18n_rails/spec/gettext_i18n_rails_spec.rb +38 -1
  266. data/vendor/plugins/gettext_i18n_rails/spec/rails2/Gemfile +11 -0
  267. data/vendor/plugins/gettext_i18n_rails/spec/spec_helper.rb +1 -8
  268. data/zena.gemspec +2241 -2217
  269. metadata +123 -83
  270. data/.gitignore +0 -36
  271. data/app/views/nodes/_dates.rhtml +0 -13
  272. data/db/init/base/skins/default/Node-+adminLayout.zafu +0 -46
  273. data/db/init/base/skins/default/Node-tree.zafu +0 -19
  274. data/vendor/plugins/gettext_i18n_rails/README.markdown +0 -143
data/lib/zena/use/urls.rb CHANGED
@@ -1,7 +1,23 @@
1
1
  module Zena
2
2
  module Use
3
3
  module Urls
4
- ALLOWED_REGEXP = /\A(([a-zA-Z]+)([0-9]+)|([#{String::ALLOWED_CHARS_IN_FILENAME}]+))(_[a-zA-Z]+|)(\..+|)\Z/
4
+ NODE_ACTIONS = {
5
+ '' => {:url => '/nodes/#{node_zip}'},
6
+ 'drive' => {:url => '/nodes/#{node_zip}/edit'},
7
+ 'add_doc' => {:url => '/documents/new', :query => {:parent_id => 'node_zip'}},
8
+ 'destroy' => {:url => '/nodes/#{node_zip}', :method => 'delete'},
9
+ 'update' => {:url => '/nodes/#{node_zip}', :method => 'put'},
10
+ 'drop' => {:url => '/nodes/#{node_zip}/drop'},
11
+ 'unlink' => {:url => '/nodes/#{node_zip}/link/#{node.link_id}', :method => 'delete'},
12
+ 'zafu' => {:url => '/nodes/#{node_zip}/zafu'},
13
+ 'publish' => {:url => '/nodes/#{node_zip}/versions/0/publish', :method => 'put'},
14
+ 'propose' => {:url => '/nodes/#{node_zip}/versions/0/propose', :method => 'put'},
15
+ 'refuse' => {:url => '/nodes/#{node_zip}/versions/0/refuse', :method => 'put'},
16
+ 'edit' => {:url => '/nodes/#{node_zip}/versions/0/edit'},
17
+ }
18
+
19
+
20
+ ALLOWED_REGEXP = /\A(([a-zA-Z]+)([0-9]+)|([#{String::ALLOWED_CHARS_IN_FILENAME}%]+))(_[a-zA-Z]+|)(\..+|)\Z/
5
21
 
6
22
  module Common
7
23
  CACHESTAMP_FORMATS = ['jpg', 'png', 'gif', 'css', 'js']
@@ -15,22 +31,29 @@ module Zena
15
31
 
16
32
  # We overwrite some url writers that might use Node so that they use
17
33
  # zip instead of id.
18
- ['', 'edit_', 'delete_', 'drop_', 'zafu_'].each do |method|
19
- class_eval %Q{
20
- def #{method}node_path(node, options={}) # def edit_node_path(node, options={})
21
- if ep = options.delete(:encode_params)
22
- ep.split(',').map(&:strip).each do |key|
23
- value = params[key]
24
- options[key] = value unless value.blank?
25
- end
26
- end
27
- if node.kind_of?(Node) # if node.kind_of?(Node)
28
- super(node.zip, options) # super(node.zip, options)
29
- else # else
30
- super # super
31
- end # end
32
- end # end
33
- }
34
+ NODE_ACTIONS.each do |name, definition|
35
+ method = name.blank? ? 'node_path' : "#{name}_node_path"
36
+ hash_str = []
37
+ if query = definition[:query]
38
+ query.each do |k,v|
39
+ hash_str << ":#{k} => #{v}"
40
+ end
41
+ end
42
+
43
+ if hash_str.empty?
44
+ opts_merge = ''
45
+ else
46
+ opts_merge = "options = {#{hash_str.join(',')}}.merge(options)" # {:parent_id => node_zip}.merge(options)
47
+ end
48
+
49
+ class_eval(%Q{
50
+ def #{method}(node, options={}) # def zafu_node_path(node, options={})
51
+ return '#' unless node # return '#' unless node
52
+ node_zip = node.kind_of?(Node) ? node.zip : node # node_zip = node.kind_of?(Node) ? node.zip : node
53
+ #{opts_merge} # options = {:parent_id => node.zip}.merge(options)
54
+ append_query_params("#{definition[:url]}", options) # append_query_params("/nodes/\#{node.zip}/zafu", options)
55
+ end # end
56
+ }, __FILE__, __LINE__ - 5)
34
57
  end
35
58
 
36
59
  # Path to remove a node link.
@@ -159,6 +182,7 @@ module Zena
159
182
  # Url for a node. Options are 'mode' and 'format'
160
183
  # ex 'http://test.host/en/document34_print.html'
161
184
  def zen_url(node, opts={})
185
+ # FIXME: we *need* port number !
162
186
  zen_path(node,opts.merge(:host => visitor.site[:host]))
163
187
  end
164
188
 
@@ -224,27 +248,22 @@ module Zena
224
248
  module ViewMethods
225
249
  include Common
226
250
  include RubyLess
227
- safe_method [:url, Node] => {:class => String, :method => 'zen_url'}
228
- safe_method [:path, Node] => {:class => String, :method => 'zen_path'}
251
+ safe_method [:url, Node] => {:class => String, :method => 'zen_url'}
252
+ safe_method [:url, Node, Hash] => {:class => String, :method => 'zen_url'}
253
+ safe_method [:path, Node] => {:class => String, :method => 'zen_path'}
254
+ safe_method [:path, Node, Hash] => {:class => String, :method => 'zen_path'}
229
255
 
230
256
  safe_method [:zen_path, Node, Hash] => {:class => String, :accept_nil => true}
231
257
  safe_method [:zen_path, Node] => {:class => String, :accept_nil => true}
232
258
  safe_method [:zen_path, String, Hash] => {:class => String, :accept_nil => true, :method => 'dummy_zen_path'}
233
259
  safe_method [:zen_path, String] => {:class => String, :accept_nil => true, :method => 'dummy_zen_path'}
234
260
 
235
- safe_method [:zafu_node_path, Node, Hash] => {:class => String, :accept_nil => true}
236
- safe_method [:zafu_node_path, Node] => {:class => String, :accept_nil => true}
237
- safe_method [:update_node_path, Node, Hash] => {:class => String, :accept_nil => true, :method => 'node_path'}
238
- safe_method [:update_node_path, Node] => {:class => String, :accept_nil => true, :method => 'node_path'}
239
261
 
240
- safe_method [:edit_node_path, Node, Hash] => {:class => String, :accept_nil => true}
241
- safe_method [:edit_node_path, Node] => {:class => String, :accept_nil => true}
242
- safe_method [:delete_node_path, Node, Hash] => {:class => String, :accept_nil => true}
243
- safe_method [:delete_node_path, Node] => {:class => String, :accept_nil => true}
244
- safe_method [:drop_node_path, Node, Hash] => {:class => String, :accept_nil => true}
245
- safe_method [:drop_node_path, Node] => {:class => String, :accept_nil => true}
246
- safe_method [:unlink_node_path, Node, Hash] => {:class => String, :accept_nil => true}
247
- safe_method [:unlink_node_path, Node] => {:class => String, :accept_nil => true}
262
+ NODE_ACTIONS.keys.each do |action|
263
+ next if action.blank?
264
+ safe_method [:"#{action}_node_path", Node, Hash] => {:class => String, :accept_nil => true}
265
+ safe_method [:"#{action}_node_path", Node] => {:class => String, :accept_nil => true}
266
+ end
248
267
 
249
268
  safe_method :start_id => {:class => Number, :method => 'start_node_zip'}
250
269
 
@@ -304,6 +323,7 @@ module Zena
304
323
  def make_link(options = {})
305
324
  remote_target = (options[:update] || @params.delete(:update))
306
325
  options[:action] ||= @params.delete(:action)
326
+ confirm = @params.delete(:confirm)
307
327
 
308
328
  @markup.tag ||= 'a'
309
329
 
@@ -325,6 +345,22 @@ module Zena
325
345
  text = text_for_link(options[:default_text])
326
346
  end
327
347
 
348
+ http_method = http_method_from_action(options[:action])
349
+
350
+ if http_method == 'delete'
351
+ confirm ||= '#{t("Destroy ?")} "#{title}"'
352
+ end
353
+
354
+ if confirm
355
+ confirm = ::RubyLess.translate_string(self, confirm)
356
+
357
+ if confirm.literal
358
+ markup.set_param(:"data-confirm", confirm.literal)
359
+ else
360
+ markup.set_dyn_param(:"data-confirm", "<%= #{confirm} %>")
361
+ end
362
+ end
363
+
328
364
  if remote_target
329
365
  # ajax link (link_to_remote)
330
366
 
@@ -333,11 +369,17 @@ module Zena
333
369
 
334
370
 
335
371
  # Use onclick with Ajax.
336
- markup.set_dyn_param(:onclick, "new Ajax.Request(\"<%= #{href} %>\", {asynchronous:true, evalScripts:true, method:\"#{http_method_from_action(options[:action])}\"}); return false;")
372
+ markup.set_dyn_param(:onclick, "new Ajax.Request(\"<%= #{href} %>\", {asynchronous:true, evalScripts:true, method:\"#{http_method}\"}); return false;")
337
373
  else
338
374
  markup.set_dyn_param(:href, "<%= #{href} %>")
375
+
376
+ if http_method != 'get' || confirm
377
+ markup.set_dyn_param(:onclick, "return Zena.m(this,#{http_method.inspect})")
378
+ end
339
379
  end
340
380
 
381
+ # We wrap without callbacks (before_wrap, after_wrap) so that the link
382
+ # is used as raw text in these callbacks.
341
383
  markup.wrap(text)
342
384
  =begin
343
385
  query_params = options[:query_params] || {}
@@ -471,15 +513,6 @@ module Zena
471
513
  private
472
514
 
473
515
  # Build the 'href' part of a link.
474
- #
475
- # ==== Parameters
476
- #
477
- # * +:remote_target+ - a processing node to update
478
- # * +:action+ - action to use ('edit', 'show'). Default is 'show'.
479
- #
480
- # ==== Examples
481
- #
482
- # Product.count_by_sql "SELECT COUNT(*) FROM sales s, customers c WHERE s.customer_id = c.id"
483
516
  def make_href(remote_target = nil, opts = {})
484
517
  anchor = @params[:anchor]
485
518
  if anchor && !@params[:href]
@@ -487,13 +520,10 @@ module Zena
487
520
  return ::RubyLess.translate(self, "%Q{##{get_anchor_name(anchor)}}")
488
521
  end
489
522
 
490
- # if opts[:action] == 'edit' && !remote_target
491
- # method = 'edit_node_path'
492
- # els
493
- if %w{edit drop unlink}.include?(opts[:action])
523
+ if opts[:action] == 'edit' && remote_target
524
+ method = 'zafu_node_path'
525
+ elsif NODE_ACTIONS[opts[:action]]
494
526
  method = "#{opts[:action]}_node_path"
495
- elsif %w{update}.include?(opts[:action])
496
- method = 'update_node_path'
497
527
  elsif remote_target
498
528
  method = 'zafu_node_path'
499
529
  else
@@ -503,21 +533,11 @@ module Zena
503
533
  method_args = []
504
534
  hash_params = []
505
535
 
506
- # Select http verb.
507
- unless remote_target
508
- http_method = http_method_from_action(opts[:action])
509
- if http_method != 'get'
510
- hash_params << ":_method => '#{http_method}'"
511
- end
512
- end
513
-
514
536
  if href = @params[:href]
515
537
  method_args << href
516
538
  elsif node.will_be?(Version)
517
539
  method_args << "node"
518
540
  hash_params << ":lang => this.lang"
519
- elsif node.list_context?
520
- method_args << '@node'
521
541
  else
522
542
  method_args << 'this'
523
543
  end
@@ -525,12 +545,12 @@ module Zena
525
545
  insert_ajax_args(remote_target, hash_params, opts[:action]) if remote_target
526
546
 
527
547
  (opts[:query_params] || @params).each do |key, value|
528
- next if [:href, :eval, :text, :attr].include?(key)
548
+ next if [:href, :eval, :text, :attr, :t].include?(key)
529
549
  if key == :anchor
530
550
  value = get_anchor_name(value)
531
551
  end
532
552
 
533
- # FIXME: Do not force string interpolation.
553
+ # FIXME: how to not force string interpolation ?
534
554
  hash_params << "#{key.inspect} => %Q{#{value}}"
535
555
  end
536
556
 
@@ -552,13 +572,22 @@ module Zena
552
572
  return
553
573
  elsif target.kind_of?(String)
554
574
  # named target
555
- return nil unless target = find_target(target)
575
+ if target_block = find_target(target)
576
+ target = target_block
577
+ else
578
+ out parser_error("Could not find target name '#{target}'.")
579
+ return nil
580
+ end
556
581
  end
557
582
 
583
+
584
+ # FIXME: when we have proper markup.dyn_params[:id] support,
585
+ # we should not need this crap anymore.
558
586
  case action
559
587
  when 'edit'
560
- # 'each' target in parent hierarchy
561
- @insert_dom_id = %Q{"#{node.dom_id(:erb => false)}"}
588
+ # 'each' or 'block' target in parent hierarchy
589
+ is_list = ancestor(%w{each block}).method == 'each'
590
+ @insert_dom_id = %Q{"#{node.dom_id(:erb => false, :list => is_list)}"}
562
591
  hash_params << ":dom_id => insert_dom_id"
563
592
  hash_params << ":t_url => %Q{#{form_url(node.dom_prefix)}}"
564
593
  # To enable link edit fix the following line:
@@ -566,17 +595,11 @@ module Zena
566
595
  when 'unlink', 'delete'
567
596
  @insert_dom_id = %Q{"#{node.dom_id(:erb => false)}"}
568
597
  hash_params << ":dom_id => insert_dom_id"
569
- hash_params << ":t_url => %Q{#{template_url(target.name)}}"
570
- else # drop, swap
571
- if target.context && target.node
572
- # target loaded
573
- dom_name = target.node.dom_prefix
574
- else
575
- # hack until we find a way to prebuild the target....
576
- dom_name = target.name
577
- end
578
- hash_params << ":dom_id => %Q{#{dom_name}}"
579
- hash_params << ":t_url => %Q{#{template_url(dom_name)}}"
598
+ hash_params << ":t_url => %Q{#{template_url(node.dom_prefix)}}"
599
+ else #drop, #swap
600
+ @insert_dom_id, dom_prefix = get_dom_id(target)
601
+ hash_params << ":dom_id => insert_dom_id"
602
+ hash_params << ":t_url => %Q{#{template_url(dom_prefix)}}"
580
603
  end
581
604
 
582
605
  # method = opts[:method] || :get
@@ -632,7 +655,7 @@ module Zena
632
655
  def pagination_links
633
656
 
634
657
  return parser_error("not in pagination scope") unless pagination_key = get_context_var('paginate', 'key')
635
- page_direction = @params[:page]
658
+ page_direction = @params.delete(:page)
636
659
  case page_direction
637
660
  when 'previous', 'next'
638
661
  current = get_context_var('paginate', 'current')
@@ -640,21 +663,28 @@ module Zena
640
663
  prev_or_next = get_var_name('paginate', page_direction)
641
664
 
642
665
  if page_direction == 'previous'
643
- out "<% if #{prev_or_next} = (#{current} > 1 ? #{current} - 1 : nil) %>"
666
+ cond = "#{prev_or_next} = (#{current} > 1 ? #{current} - 1 : nil)"
644
667
  else
645
- out "<% if #{prev_or_next} = (#{count} - #{current} > 0 ? #{current} + 1 : nil) %>"
668
+ cond = "#{prev_or_next} = (#{count} - #{current} > 0 ? #{current} + 1 : nil)"
646
669
  end
647
670
 
648
671
  # previous_page // next_page
649
- set_context_var('set_var', "#{page_direction}_page", RubyLess::TypedString.new(prev_or_next, :class => Number, :nil => true))
650
-
651
- #, :params => @params.merge(:page => nil))
652
- out make_link(:default_text => "<%= #{prev_or_next} %>", :query_params => {pagination_key => "\#{#{page_direction}_page}"})
653
-
654
- if descendant('else')
655
- out expand_with(:in_if => true, :only => ['else', 'elsif'])
672
+ set_context_var('set_var', "#{page_direction}_page",
673
+ RubyLess::TypedString.new(prev_or_next, :class => Number, :nil => true)
674
+ )
675
+
676
+ unless descendant('link')
677
+ # Do not wrap twice
678
+ link = {
679
+ :href => '@node',
680
+ :eval => "#{page_direction}_page",
681
+ pagination_key => "\#{#{page_direction}_page}",
682
+ }.merge(@params)
683
+ # <r:link href='@node' p='next_page' eval='next_page'/>
684
+ wrap_in_block :method => 'link', :params => link
656
685
  end
657
- out "<% end %>"
686
+
687
+ out expand_if(cond)
658
688
  when 'list'
659
689
 
660
690
  node_count = get_context_var('paginate', 'nodes')
@@ -668,7 +698,7 @@ module Zena
668
698
  set_context_var('set_var', 'page_name', RubyLess::TypedString.new(page_name, String))
669
699
 
670
700
  if @blocks == [] || (@blocks.size == 1 && !@blocks.first.kind_of?(String) && @blocks.first.method == 'else')
671
- # We need to insert the default 'link' tag: <r:link href='@node' #{pagination_key}='#{this}' ... do='this'/>
701
+ # We need to insert the default 'link' tag: <r:link href='@node' #{pagination_key}='#{this}' ... do='page_name'/>
672
702
  link = {}
673
703
  @params.each do |k,v|
674
704
  next if [:tag, :page, :join, :page_count].include?(k)
@@ -682,19 +712,16 @@ module Zena
682
712
  link[:eval] = 'page_name'
683
713
  link[pagination_key.to_sym] = '#{this}'
684
714
 
685
- # <r:link href='@node' href='@node' p='#{this}' ... eval='this'/>
686
-
687
- @blocks = [make(:void, :method => 'link', :params => link)]
688
- # Clear cached descendants
689
- remove_instance_variable(:@all_descendants)
715
+ # <r:link href='@node' p='#{page_name}' ... eval='page_name'/>
716
+ add_block :method => 'link', :params => link
690
717
  end
691
718
 
692
719
  if !descendant('else')
693
720
  else_tag = {:method => 'else', :text => '<r:this/>'}
694
721
  else_tag[:tag] = tag if tag
695
- @blocks += [make(:void, else_tag)]
722
+ add_block else_tag
696
723
  # Clear cached descendants
697
- remove_instance_variable(:@all_descendants)
724
+ @all_descendants = nil
698
725
  end
699
726
 
700
727
  out "<% page_numbers(#{curr_page}, #{page_count}, #{(@params[:join] || ' ').inspect}, #{@params[:page_count] ? @params[:page_count].to_i : 'nil'}) do |#{page_number}, #{page_join}, #{page_name}| %>"
@@ -713,7 +740,8 @@ module Zena
713
740
  expand_with
714
741
  else
715
742
  method = get_attribute_or_eval(false)
716
- if !method && (@params.keys & [:attr, :eval, :text]) != []
743
+
744
+ if !method && (@params.keys & [:attr, :eval, :text, :t]) != []
717
745
  out @errors.last
718
746
  end
719
747
 
@@ -722,11 +750,11 @@ module Zena
722
750
  elsif default
723
751
  default
724
752
  elsif node.will_be?(Node)
725
- "<%= #{node}.prop['title'] %>"
753
+ "<%= #{node(Node)}.prop['title'] %>"
726
754
  elsif node.will_be?(Version)
727
- "<%= #{node}.node.prop['title'] %>"
755
+ "<%= #{node(Version)}.node.prop['title'] %>"
728
756
  elsif node.will_be?(Link)
729
- "<%= #{node}.name %>"
757
+ "<%= #{node(Link)}.name %>"
730
758
  else
731
759
  _('edit')
732
760
  end
@@ -735,14 +763,7 @@ module Zena
735
763
 
736
764
  # Return the HTTP verb to use for the given action.
737
765
  def http_method_from_action(action)
738
- case action
739
- when 'delete', 'unlink'
740
- 'delete'
741
- when 'drop', 'update'
742
- 'put'
743
- else
744
- 'get'
745
- end
766
+ (NODE_ACTIONS[action] || {})[:method] || 'get'
746
767
  end
747
768
  end # ZafuMethods
748
769
  end # Urls
@@ -17,7 +17,8 @@ module Zena
17
17
  # and it should be included *before* these two modules.
18
18
  module Workflow
19
19
  include RubyLess
20
- safe_method :can_edit? => Boolean, :can_write? => Boolean, :can_drive? => Boolean
20
+ safe_method :can_edit? => Boolean, :can_write? => Boolean, :can_drive? => Boolean,
21
+ :can_publish? => Boolean, :can_refuse? => Boolean, :can_unpublish? => Boolean
21
22
 
22
23
  WORKFLOW_ATTRIBUTES = %w{status publish_from}
23
24
  # The Workflow::VersionMethods module should be included in the model used as version.
@@ -57,7 +57,7 @@ module Zena
57
57
 
58
58
  # Remove 'live' param so that it does not alter RubyLess method building.
59
59
  def filter_live
60
- @live_param = @params.delete(:live)
60
+ @live_param = @params.delete(:live) unless %w{filter}.include?(@method)
61
61
  end
62
62
 
63
63
  # Evaluate 'set_xxx' param and store result in context with 'var' name. This name
@@ -89,7 +89,7 @@ module Zena
89
89
  @if_class_params.each do |class_name, code|
90
90
  begin
91
91
  typed_string = ::RubyLess.translate(self, code)
92
- @markup.append_dyn_param(:class, "<%= (#{typed_string}) ? ' #{class_name}' : '' %>", true)
92
+ @markup.append_dyn_param(:class, "<%= (#{typed_string}) ? ' #{class_name}' : '' %>", '')
93
93
  rescue RubyLess::NoMethodError => err
94
94
  text += parser_error(err.message, code)
95
95
  end
@@ -84,10 +84,20 @@ module Zena
84
84
  safe_method_for Number, :to_s => {:class => String, :pre_processor => true}
85
85
  safe_method_for Number, :to_f => {:class => Number, :pre_processor => true}
86
86
  safe_method_for Number, :to_i => {:class => Number, :pre_processor => true}
87
+ safe_method_for String, :to_f => {:class => Number, :pre_processor => true}
87
88
  safe_method_for NilClass, :to_f => {:class => Number, :pre_processor => true}
88
89
  safe_method_for NilClass, :to_i => {:class => Number, :pre_processor => true}
89
90
  safe_method_for Object, :blank? => Boolean
90
91
 
92
+ safe_method_for Time, [:advance, {
93
+ :years => Number,
94
+ :months => Number,
95
+ :weeks => Number,
96
+ :days => Number,
97
+ :hours => Number,
98
+ :minutes => Number,
99
+ :seconds => Number}] => Time
100
+
91
101
  safe_method_for Node, [:kind_of?, VirtualClass] =>
92
102
  {:method => 'nil', :nil => true, :pre_processor => kind_of_proc}
93
103
  safe_method_for Node, [:kind_of?, Role] =>
@@ -99,7 +109,17 @@ module Zena
99
109
  {:method => 'nil', :nil => true, :pre_processor => join_proc}
100
110
  safe_method_for Array, [:map, Symbol] => # supports map(:name)
101
111
  {:method => 'nil', :nil => true, :pre_processor => map_proc}
112
+ safe_method [:min, Number, Number] => {:method => 'zafu_min', :class => Number}
113
+ safe_method [:max, Number, Number] => {:method => 'zafu_max', :class => Number}
114
+ # Returns the smallest of two values.
115
+ def zafu_min(a, b)
116
+ [a, b].min
117
+ end
102
118
 
119
+ # Returns the largest of two values.
120
+ def zafu_max(a, b)
121
+ [a, b].max
122
+ end
103
123
  end # ViewMethods
104
124
 
105
125
 
@@ -155,6 +155,7 @@ module Zena
155
155
  # Return the template path without '.erb' extension in case we need to append '_form'
156
156
  # from a template's url. The expected url is of the form '/skin/Klass-mode/partial'
157
157
  def template_path_from_template_url(template_url=params[:t_url])
158
+ raise "Missing template_url (t_url parameter)" unless template_url
158
159
  if template_url =~ /\A\.|[^ #{String::ALLOWED_CHARS_IN_FILEPATH}]/
159
160
  raise Zena::AccessViolation.new("'template_url' contains illegal characters : #{template_url.inspect}")
160
161
  end
@@ -184,7 +185,7 @@ module Zena
184
185
  def default_template_url(opts = {})
185
186
  if opts[:format] && opts[:format] != 'html'
186
187
  raise ActiveRecord::RecordNotFound
187
- elsif %w{+login +index +adminLayout +popupLayout +notFound}.include?(opts[:mode])
188
+ elsif %w{+login +index +adminLayout +popupLayout +notFound admin}.include?(opts[:mode])
188
189
  zafu_url ="$default/Node-#{opts[:mode]}"
189
190
  elsif opts[:mode]
190
191
  raise ActiveRecord::RecordNotFound
@@ -237,7 +238,7 @@ module Zena
237
238
  document
238
239
  end
239
240
  end
240
-
241
+
241
242
  def zafu_node(name, klass)
242
243
  zafu_context[:node] = Zena::Use::NodeContext.new(name, klass)
243
244
  end
@@ -390,7 +391,7 @@ module Zena
390
391
  klass = [var.class]
391
392
  end
392
393
  end
393
-
394
+
394
395
  return Zena::Use::NodeContext.new(name, klass) if name
395
396
  end
396
397
 
@@ -433,7 +434,7 @@ module Zena
433
434
  if insert_dev
434
435
  # add template edit buttons
435
436
  if res =~ /<\/body>/
436
- res.sub!('</body>', "#{dev_box}<%= render_js %></body>")
437
+ res.sub!('</body>', "#{dev_box(template)}<%= render_js %></body>")
437
438
  else
438
439
  res << dev_box
439
440
  end
@@ -456,7 +457,7 @@ module Zena
456
457
  end
457
458
  end
458
459
 
459
- def dev_box
460
+ def dev_box(template = nil)
460
461
  used_nodes = self.asset_cache.used_assets
461
462
 
462
463
  res = "<div id='dev'><ul>\n"
@@ -464,6 +465,19 @@ module Zena
464
465
  next if nodes.empty?
465
466
  res << " <li><a class='group' onclick='$(\"dev_#{name}\").toggle();' href='#'>#{name}</a>\n"
466
467
  res << " <table class='dev_pop' id='dev_#{name}'#{name == 'images' ? " style='display:none;'" : ''}>\n"
468
+ if template && name == 'zafu'
469
+ # Create specialized template on the fly for current page
470
+ res << %Q{<tr><td colspan='2'><% if @node.kpath != #{template.tkpath.inspect} -%>
471
+ <% _znode_dev = ::Template.new(:title => @node.klass, :parent_id => #{@skin.zip}) %>
472
+ <% form_for(:node, _znode_dev, :url => nodes_path, :html => {:method => 'post', :id => 'zmake_template'}) do |f| %>
473
+ <%= f.hidden_field(:parent_id) %>
474
+ <%= f.hidden_field(:title) %>
475
+ <%= f.hidden_field(:klass) %>
476
+ <input type='hidden' name='redir' value='<%= request.path %>?rebuild=true'/>
477
+ <b><a href='javascript:' onclick='$("zmake_template").submit();return false;'><img src='/images/add.png' title='create template for <%= @node.klass %>'/> create <%= @node.klass %>.zafu</a></b>
478
+ <% end %>
479
+ <% end -%> #{node_action_link('add_doc', "#{@skin.zip}", :text => '')}</td></tr>}
480
+ end
467
481
  nodes.each do |path, node|
468
482
  res << " <tr><td class='actions'>#{zafu_helper.send(:node_actions, node)}</td><td>&nbsp;#{zafu_helper.send(:link_to, path.join('/'), zen_path(node))}</td></tr>\n"
469
483
  end
@@ -474,7 +488,7 @@ module Zena
474
488
  res << " <li><a class='group' onclick='$(\"dev_tools\").toggle();' href='#'>tools</a>\n"
475
489
  res << " <ul class='dev_pop' id='dev_tools'><li>\n"
476
490
  res << %Q{ <div style='float:right'><% form_for(:user, visitor, :url => user_path(visitor), :html => { :method => :put }) do |f| %>
477
- <%= f.select(:dev_skin_id, dev_skin_options, {}, {:onchange => 'this.form.submit()'}) %> <input style='display:none;' type='submit' value='<%= _('validate') %>'/>
491
+ <p><%= f.select(:dev_skin_id, dev_skin_options, {}, {:onchange => 'this.form.submit()'}) %> <input style='display:none;' type='submit' value='<%= _('validate') %>'/></p>
478
492
  <% end %></div>}
479
493
  res << " <a style='float:right; margin:0 8px;' href='?rebuild=true'>#{_('rebuild_btn')}</a>\n"
480
494
  res << "<% if @node.kind_of?(Skin) %><a href='<%= export_node_path(@node[:zip]) %>'>#{_('export')}</a>\n<% end %>"
@@ -1,6 +1,8 @@
1
+ require 'timeout'
1
2
  module Zena
2
3
  module Use
3
4
  module Zazen
5
+ ZAZEN_TIMEOUT = 5
4
6
  module ViewMethods
5
7
 
6
8
  include Zena::Use::Grid::ViewMethods
@@ -37,29 +39,38 @@ module Zena
37
39
  # * [!14!:37] you can use an image as the source for a link
38
40
  # * [!14!:www.example.com] use an image for an outgoing link
39
41
  def zazen(text, opt={})
40
- return '' unless text
41
- code_lang = opt[:code]
42
- if !code_lang.blank?
43
- return Zena::CodeSyntax.new(text, code_lang).to_html
44
- end
42
+ Timeout.timeout(ZAZEN_TIMEOUT) do
43
+ return '' unless text
44
+ code_lang = opt[:code]
45
+ if code_lang == '' && opt[:node].kind_of?(TextDocument)
46
+ # do not parse. This is to make sure we do not accidently parse
47
+ # TextDocument content as Zazen.
48
+ return text
49
+ end
50
+ if !code_lang.blank?
51
+ return Zena::CodeSyntax.new(text, code_lang).to_html
52
+ end
45
53
 
46
- opt = {:images=>true, :pretty_code=>true, :output=>'html'}.merge(opt)
47
- no_p = opt.delete(:no_p)
48
- img = opt[:images]
49
- if opt[:limit]
50
- opt[:limit] -= 1 unless opt[:limit] <= 0
51
- paragraphs = text.split(/\n\n|\r\n\r\n/)
52
- if paragraphs.size > (opt[:limit]+1) && opt[:limit] != -1
53
- text = paragraphs[0..opt[:limit]].join("\r\n\r\n") + " &#8230;"
54
+ opt = {:images=>true, :pretty_code=>true, :output=>'html'}.merge(opt)
55
+ no_p = opt.delete(:no_p)
56
+ img = opt[:images]
57
+ if opt[:limit]
58
+ opt[:limit] -= 1 unless opt[:limit] <= 0
59
+ paragraphs = text.split(/\n\n|\r\n\r\n/)
60
+ if paragraphs.size > (opt[:limit]+1) && opt[:limit] != -1
61
+ text = paragraphs[0..opt[:limit]].join("\r\n\r\n") + " &#8230;"
62
+ end
63
+ end
64
+ opt[:node] ||= @node
65
+ res = ZazenParser.new(text,:helper=>self).render(opt)
66
+ if no_p && !text.include?("\n")
67
+ res.gsub(%r{\A<p>|</p>\Z},'')
68
+ else
69
+ res
54
70
  end
55
71
  end
56
- opt[:node] ||= @node
57
- res = ZazenParser.new(text,:helper=>self).render(opt)
58
- if no_p && !text.include?("\n")
59
- res.gsub(%r{\A<p>|</p>\Z},'')
60
- else
61
- res
62
- end
72
+ rescue Timeout::Error
73
+ return %Q{<span class='parser_error'>#{_('Could not render text (Timeout error)')}</span>}
63
74
  end
64
75
 
65
76
  # TODO: test
@@ -68,6 +68,11 @@ module Zena
68
68
  end
69
69
 
70
70
  @flash = {}
71
+ class << @flash
72
+ def discard
73
+ clear
74
+ end
75
+ end
71
76
 
72
77
  @node
73
78
  end