card 1.19.6 → 1.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (298) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/card.gemspec +8 -7
  4. data/config/initializers/01_core_extensions/array.rb +4 -0
  5. data/config/initializers/01_core_extensions/persistent_identifiers.rb +12 -0
  6. data/config/initializers/02_patches/better_errors.rb +56 -0
  7. data/config/initializers/core_extensions.rb +13 -18
  8. data/config/initializers/patches.rb +8 -0
  9. data/config/locales/de.yml +0 -2
  10. data/db/migrate_core_cards/20150202143810_import_bootstrap_layout.rb +22 -12
  11. data/db/migrate_core_cards/20161102202156_tweak_recaptcha_setting_cards.rb +17 -0
  12. data/db/migrate_core_cards/20161103154836_update_keys.rb +46 -0
  13. data/lib/card.rb +1 -8
  14. data/lib/card/act_manager.rb +4 -0
  15. data/lib/card/auth/permissions.rb +5 -3
  16. data/lib/card/cache.rb +1 -20
  17. data/lib/card/cache/persistent.rb +6 -0
  18. data/lib/card/content/chunk.rb +4 -3
  19. data/lib/card/content/diff.rb +2 -2
  20. data/lib/card/content/diff/result.rb +11 -0
  21. data/lib/card/env/success.rb +4 -0
  22. data/lib/card/error.rb +2 -0
  23. data/lib/card/format.rb +14 -17
  24. data/lib/card/format/content.rb +16 -8
  25. data/lib/card/format/error.rb +3 -5
  26. data/lib/card/format/names.rb +22 -16
  27. data/lib/card/format/nest.rb +67 -61
  28. data/lib/card/format/nest/fetch.rb +40 -33
  29. data/lib/card/format/nest/main.rb +39 -19
  30. data/lib/card/format/nest/subformat.rb +3 -16
  31. data/lib/card/format/nest/view.rb +23 -32
  32. data/lib/card/format/permission.rb +49 -34
  33. data/lib/card/format/registration.rb +12 -6
  34. data/lib/card/format/render.rb +62 -73
  35. data/lib/card/migration.rb +14 -10
  36. data/lib/card/migration/import.rb +20 -19
  37. data/lib/card/migration/import/import_data.rb +50 -59
  38. data/lib/card/migration/import/import_data/card_attributes.rb +56 -0
  39. data/lib/card/migration/import/import_data/card_content.rb +33 -0
  40. data/lib/card/migration/import/merger.rb +47 -0
  41. data/lib/card/mod/loader.rb +4 -4
  42. data/lib/card/model/save_helper.rb +49 -10
  43. data/lib/card/name.rb +16 -52
  44. data/lib/card/name/fields_and_traits.rb +67 -0
  45. data/lib/card/name/variants.rb +17 -0
  46. data/lib/card/query.rb +6 -2
  47. data/lib/card/query/attributes.rb +1 -1
  48. data/lib/card/query/interpretation.rb +3 -3
  49. data/lib/card/set/event.rb +2 -1
  50. data/lib/card/set/format.rb +18 -7
  51. data/lib/card/set_pattern.rb +17 -13
  52. data/lib/card/tasks/card.rake +1 -1
  53. data/lib/card/view.rb +55 -0
  54. data/lib/card/view/cache.rb +90 -0
  55. data/lib/card/view/fetch.rb +109 -0
  56. data/lib/card/view/options.rb +164 -0
  57. data/lib/card/view/stub.rb +30 -0
  58. data/lib/card/view/visibility.rb +95 -0
  59. data/lib/cardio.rb +3 -2
  60. data/lib/cardio/schema.rb +21 -8
  61. data/lib/generators/card.rb +16 -2
  62. data/lib/generators/card/format/format_generator.rb +10 -9
  63. data/lib/generators/card/migration/migration_generator.rb +10 -5
  64. data/lib/generators/card/set/USAGE +1 -1
  65. data/lib/generators/card/set/set_generator.rb +11 -9
  66. data/mod/account/set/right/account.rb +38 -40
  67. data/mod/account/set/right/token.rb +2 -1
  68. data/mod/account/set/self/account_links.rb +34 -54
  69. data/mod/account/set/self/signin.rb +107 -93
  70. data/mod/account/set/type/signup.rb +33 -32
  71. data/mod/account/set/type/user.rb +28 -21
  72. data/mod/account/spec/set/all/account_spec.rb +9 -9
  73. data/mod/account/spec/set/right/account_spec.rb +23 -14
  74. data/mod/account/spec/set/right/email_spec.rb +6 -6
  75. data/mod/account/spec/set/right/password_spec.rb +4 -4
  76. data/mod/account/spec/set/right/token_spec.rb +3 -3
  77. data/mod/account/spec/set/self/account_links_spec.rb +3 -3
  78. data/mod/account/spec/set/self/signin_spec.rb +2 -2
  79. data/mod/account/spec/set/type/signup_spec.rb +7 -8
  80. data/mod/ace_editor/set/abstract/ace_editor.rb +1 -4
  81. data/mod/admin/set/self/admin.rb +2 -2
  82. data/mod/admin/set/self/admin_info.rb +1 -1
  83. data/mod/admin/set/self/recaptcha_private_key.rb +3 -0
  84. data/mod/admin/set/self/recaptcha_proxy.rb +3 -0
  85. data/mod/admin/set/self/recaptcha_public_key.rb +3 -0
  86. data/mod/admin/set/self/trash.rb +4 -4
  87. data/mod/admin/spec/set/self/admin_spec.rb +4 -4
  88. data/mod/admin/spec/set/self/version_spec.rb +1 -1
  89. data/mod/basic_formats/set/all/all_css.rb +3 -3
  90. data/mod/basic_formats/set/all/all_csv.rb +6 -6
  91. data/mod/basic_formats/set/all/all_js.rb +4 -0
  92. data/mod/basic_formats/set/all/base.rb +40 -62
  93. data/mod/basic_formats/set/all/json.rb +34 -39
  94. data/mod/basic_formats/set/all/rss.rb +6 -6
  95. data/mod/basic_formats/set/all/text.rb +3 -2
  96. data/mod/basic_formats/set/self/01_head/javascript.rb +2 -2
  97. data/mod/basic_formats/set/self/head.rb +6 -10
  98. data/mod/basic_formats/spec/set/all/all_css_spec.rb +1 -1
  99. data/mod/basic_formats/spec/set/all/all_csv_spec.rb +1 -1
  100. data/mod/basic_formats/spec/set/all/base_spec.rb +8 -5
  101. data/mod/basic_formats/spec/set/all/json_spec.rb +2 -2
  102. data/mod/basic_formats/spec/set/all/rss_spec.rb +4 -4
  103. data/mod/basic_types/set/type/plain_text.rb +3 -5
  104. data/mod/basic_types/spec/set/type/plain_text_spec.rb +2 -2
  105. data/mod/bootstrap/lib/bootstrap.rb +16 -0
  106. data/mod/bootstrap/lib/bootstrap/basic_tags.rb +26 -0
  107. data/mod/bootstrap/lib/bootstrap/component.rb +133 -0
  108. data/mod/bootstrap/lib/bootstrap/component/form.rb +31 -0
  109. data/mod/bootstrap/lib/bootstrap/component/horizontal_form.rb +38 -0
  110. data/mod/bootstrap/lib/bootstrap/component/layout.rb +83 -0
  111. data/mod/bootstrap/lib/bootstrap/component/panel.rb +9 -0
  112. data/mod/bootstrap/lib/bootstrap/component_loader.rb +30 -0
  113. data/mod/bootstrap/lib/bootstrap/delegate.rb +16 -0
  114. data/mod/bootstrap/lib/bootstrapper.rb +16 -0
  115. data/mod/bootstrap/lib/stylesheets/bootstrap/_tables.scss +55 -52
  116. data/mod/bootstrap/lib/stylesheets/bootstrap/mixins/_table-row.scss +12 -12
  117. data/mod/bootstrap/lib/stylesheets/bootstrap_cards.scss +12 -0
  118. data/mod/bootstrap/set/all/bootstrap/accordion.rb +63 -0
  119. data/mod/bootstrap/set/all/bootstrap/helper.rb +7 -140
  120. data/mod/bootstrap/set/all/bootstrap/navbar.rb +74 -0
  121. data/mod/bootstrap/set/all/bootstrap/table.rb +76 -46
  122. data/mod/bootstrap/set/all/bootstrap/tabs.rb +58 -23
  123. data/mod/bootstrap/set/all/bootstrap/wrapper.rb +14 -8
  124. data/mod/bootstrap/set/all/rich_bootstrap.rb +5 -3
  125. data/mod/bootstrap/spec/set/all/bootstrap/bootstrap_builder_spec.rb +31 -0
  126. data/mod/bootstrap/spec/set/all/bootstrap/bootstrap_spec.rb +20 -0
  127. data/mod/bootstrap/spec/set/all/bootstrap/form_spec.rb +59 -1
  128. data/mod/bootstrap/spec/set/all/bootstrap/layout_spec.rb +104 -15
  129. data/mod/carrierwave/set/abstract/attachment.rb +4 -3
  130. data/mod/carrierwave/set/abstract/attachment/paths.rb +1 -1
  131. data/mod/carrierwave/set/abstract/attachment/storage_type.rb +5 -11
  132. data/mod/carrierwave/set/type/file.rb +39 -32
  133. data/mod/carrierwave/set/type/image.rb +59 -34
  134. data/mod/carrierwave/spec/set/type/image_spec.rb +3 -3
  135. data/mod/core/chunk/link.rb +5 -0
  136. data/mod/core/chunk/{include.rb → nest.rb} +8 -29
  137. data/mod/core/chunk/reference.rb +5 -6
  138. data/mod/core/chunk/view_stub.rb +42 -0
  139. data/mod/core/format/html_format.rb +23 -26
  140. data/mod/core/set/abstract/code_file.rb +1 -1
  141. data/mod/core/set/all/actify.rb +1 -1
  142. data/mod/core/set/all/active_card.rb +0 -1
  143. data/mod/core/set/all/{tracked_attributes.rb → assign_attributes.rb} +55 -24
  144. data/mod/core/set/all/collection.rb +136 -122
  145. data/mod/core/set/all/content.rb +8 -0
  146. data/mod/core/set/all/event.rb +5 -2
  147. data/mod/core/set/all/export.rb +7 -7
  148. data/mod/core/set/all/fetch.rb +90 -26
  149. data/mod/core/set/all/initialize.rb +17 -6
  150. data/mod/core/set/all/name.rb +2 -3
  151. data/mod/core/set/all/permissions.rb +19 -11
  152. data/mod/core/set/all/states.rb +12 -2
  153. data/mod/core/set/all/trash.rb +1 -1
  154. data/mod/core/set/all/type.rb +2 -0
  155. data/mod/core/set/all/utils.rb +4 -3
  156. data/mod/core/spec/chunk/literal_spec.rb +2 -2
  157. data/mod/core/spec/chunk/uri_spec.rb +17 -17
  158. data/mod/core/spec/format/html_format_spec.rb +11 -13
  159. data/mod/core/spec/set/all/attribute_tracking_spec.rb +2 -2
  160. data/mod/core/spec/set/all/collection_spec.rb +21 -24
  161. data/mod/core/spec/set/all/content_spec.rb +1 -1
  162. data/mod/core/spec/set/all/export_spec.rb +3 -3
  163. data/mod/core/spec/set/all/fetch_spec.rb +5 -5
  164. data/mod/core/spec/set/all/initialize_spec.rb +4 -4
  165. data/mod/core/spec/set/all/name_spec.rb +6 -6
  166. data/mod/core/spec/set/all/permissions_spec.rb +10 -10
  167. data/mod/core/spec/set/all/references_spec.rb +1 -1
  168. data/mod/core/spec/set/all/rules2_spec.rb +24 -24
  169. data/mod/core/spec/set/all/rules_spec.rb +1 -1
  170. data/mod/core/spec/set/all/templating_spec.rb +8 -8
  171. data/mod/core/spec/set/all/tracked_attributes_spec.rb +6 -6
  172. data/mod/core/spec/set/all/type_spec.rb +5 -5
  173. data/mod/developer/spec/set/all/event_viz_spec.rb +1 -1
  174. data/mod/developer/spec/set/right/debug_spec.rb +1 -1
  175. data/mod/email/set/all/email_html.rb +2 -2
  176. data/mod/email/set/all/notify.rb +8 -3
  177. data/mod/email/set/right/bcc.rb +3 -3
  178. data/mod/email/set/right/follow.rb +5 -5
  179. data/mod/email/set/right/following.rb +1 -1
  180. data/mod/email/set/self/follow_defaults.rb +27 -16
  181. data/mod/email/set/type/email_template.rb +1 -1
  182. data/mod/email/set/type_plus_right/user/follow.rb +10 -9
  183. data/mod/history/lib/card/act.rb +4 -0
  184. data/mod/history/lib/card/act/act_renderer.rb +194 -0
  185. data/mod/history/lib/card/act/act_renderer/absolute_act_renderer.rb +25 -0
  186. data/mod/history/lib/card/act/act_renderer/relative_act_renderer.rb +41 -0
  187. data/mod/history/lib/card/action.rb +1 -0
  188. data/mod/history/lib/card/action/action_renderer.rb +92 -0
  189. data/mod/history/lib/card/action/differ.rb +6 -1
  190. data/mod/history/set/all/act_view.rb +64 -0
  191. data/mod/history/set/all/action_view.rb +65 -0
  192. data/mod/history/set/all/content_history.rb +44 -37
  193. data/mod/history/set/all/history.rb +49 -263
  194. data/mod/machines/lib/stylesheets/style_cards.scss +30 -115
  195. data/mod/machines/set/abstract/script.rb +42 -7
  196. data/mod/machines/set/right/machine_input.rb +4 -0
  197. data/mod/machines/set/type/coffee_script.rb +8 -22
  198. data/mod/machines/set/type/css.rb +2 -2
  199. data/mod/machines/set/type/java_script.rb +4 -24
  200. data/mod/machines/set/type/scss.rb +1 -1
  201. data/mod/machines/spec/set/type/css_spec.rb +1 -1
  202. data/mod/machines/spec/set/type/scss_spec.rb +3 -3
  203. data/mod/machines/spec/set/type/skin_spec.rb +7 -7
  204. data/mod/pointer/set/abstract/01_pointer.rb +44 -46
  205. data/mod/pointer/set/abstract/01_pointer/edit.rb +13 -13
  206. data/mod/pointer/set/right/options.rb +4 -0
  207. data/mod/pointer/spec/set/type/pointer_spec.rb +7 -7
  208. data/mod/prosemirror_editor/set/abstract/prosemirror_editor.rb +3 -3
  209. data/mod/settings/set/abstract/permission.rb +25 -18
  210. data/mod/settings/set/right/add_help.rb +3 -3
  211. data/mod/settings/set/right/structure.rb +10 -16
  212. data/mod/settings/spec/set/right/comment_spec.rb +3 -3
  213. data/mod/settings/spec/set/right/create_spec.rb +1 -1
  214. data/mod/settings/spec/set/right/style_spec.rb +1 -1
  215. data/mod/settings/spec/set/type/setting_spec.rb +1 -1
  216. data/mod/solid_cache/set/abstract/solid_cache.rb +4 -4
  217. data/mod/solid_cache/set/right/solid_cache.rb +9 -10
  218. data/mod/standard/set/abstract/01_search_params.rb +41 -0
  219. data/mod/standard/set/abstract/search.rb +132 -0
  220. data/mod/standard/set/abstract/search/paging.rb +81 -0
  221. data/mod/standard/set/abstract/search/paging/paging_links.rb +90 -0
  222. data/mod/standard/set/abstract/wql_search.rb +67 -0
  223. data/mod/standard/set/all/error.rb +89 -82
  224. data/mod/standard/set/all/links.rb +1 -1
  225. data/mod/standard/set/all/rich_html/content.rb +125 -141
  226. data/mod/standard/set/all/rich_html/editing.rb +115 -178
  227. data/mod/standard/set/all/rich_html/form.rb +111 -131
  228. data/mod/standard/set/all/rich_html/header.rb +57 -39
  229. data/mod/standard/set/all/rich_html/menu.rb +94 -94
  230. data/mod/standard/set/all/rich_html/modal.rb +5 -10
  231. data/mod/standard/set/all/rich_html/new.rb +103 -0
  232. data/mod/standard/set/all/rich_html/toolbar.rb +54 -74
  233. data/mod/standard/set/all/rich_html/wrapper.rb +111 -138
  234. data/mod/standard/set/rstar/rules.rb +27 -38
  235. data/mod/standard/set/rstar/rules_editor.rb +298 -277
  236. data/mod/standard/set/self/navbox.rb +20 -15
  237. data/mod/standard/set/self/recent.rb +25 -17
  238. data/mod/standard/set/self/search.rb +25 -4
  239. data/mod/standard/set/type/cardtype.rb +11 -9
  240. data/mod/standard/set/type/date.rb +1 -1
  241. data/mod/standard/set/type/number.rb +1 -1
  242. data/mod/standard/set/type/phrase.rb +1 -1
  243. data/mod/standard/set/type/search_type.rb +17 -282
  244. data/mod/standard/set/type/session.rb +1 -1
  245. data/mod/standard/set/type/set.rb +155 -131
  246. data/mod/standard/set/type/toggle.rb +1 -1
  247. data/mod/standard/set/type/uri.rb +4 -4
  248. data/mod/standard/spec/chunk/include_spec.rb +13 -31
  249. data/mod/standard/spec/chunk/link_spec.rb +1 -1
  250. data/mod/standard/spec/set/all/error_spec.rb +1 -1
  251. data/mod/standard/spec/set/all/history_spec.rb +2 -2
  252. data/mod/standard/spec/set/all/rich_html/form_spec.rb +4 -4
  253. data/mod/standard/spec/set/all/rich_html/toolbar_spec.rb +22 -0
  254. data/mod/standard/spec/set/all/rich_html/wrapper_spec.rb +3 -2
  255. data/mod/standard/spec/set/right/when_created_spec.rb +1 -1
  256. data/mod/standard/spec/set/right/when_last_edited_spec.rb +1 -1
  257. data/mod/standard/spec/set/rstar/rules_spec.rb +2 -3
  258. data/mod/standard/spec/set/self/head_spec.rb +2 -2
  259. data/mod/standard/spec/set/self/navbox_spec.rb +1 -1
  260. data/mod/standard/spec/set/self/now_spec.rb +1 -1
  261. data/mod/standard/spec/set/type/date_spec.rb +1 -1
  262. data/mod/standard/spec/set/type/email_template_spec.rb +1 -1
  263. data/mod/standard/spec/set/type/layout_type_spec.rb +1 -1
  264. data/mod/standard/spec/set/type/number_spec.rb +1 -1
  265. data/mod/standard/spec/set/type/phrase_spec.rb +1 -1
  266. data/mod/standard/spec/set/type/search_type_spec.rb +2 -2
  267. data/mod/standard/spec/set/type/set_spec.rb +2 -2
  268. data/mod/standard/spec/set/type/toggle_spec.rb +2 -2
  269. data/mod/standard/spec/set/type/uri_spec.rb +3 -1
  270. data/mod/tinymce_editor/set/abstract/tinymce_editor.rb +1 -1
  271. data/spec/config/initializers/core_extensions_spec.rb +40 -10
  272. data/spec/lib/card/auth_spec.rb +8 -8
  273. data/spec/lib/card/cache_spec.rb +3 -3
  274. data/spec/lib/card/chunk_spec.rb +4 -4
  275. data/spec/lib/card/codename_spec.rb +2 -2
  276. data/spec/lib/card/content_spec.rb +23 -23
  277. data/spec/lib/card/diff_spec.rb +1 -1
  278. data/spec/lib/card/format_spec.rb +19 -24
  279. data/spec/lib/card/loader_spec.rb +4 -4
  280. data/spec/lib/card/name_spec.rb +16 -16
  281. data/spec/lib/card/query_spec.rb +80 -80
  282. data/spec/lib/card/reference_spec.rb +5 -5
  283. data/spec/lib/card/set_spec.rb +6 -6
  284. data/spec/lib/card/subcards_spec.rb +14 -0
  285. data/spec/lib/card/view_cache_spec.rb +5 -5
  286. data/spec/models/card/cardtype_spec.rb +15 -15
  287. data/spec/models/card/create_spec.rb +2 -2
  288. data/spec/models/card/trash_spec.rb +24 -24
  289. data/spec/models/card/type_transition_spec.rb +8 -8
  290. data/spec/models/card/validation_spec.rb +5 -5
  291. data/spec/models/card_spec.rb +14 -14
  292. data/spec/spec_helper.rb +6 -2
  293. data/spec/support/card_spec_helper.rb +21 -11
  294. data/spec/support/helper/card_helper.rb +11 -4
  295. metadata +73 -15
  296. data/lib/card/cache/view_cache.rb +0 -103
  297. data/mod/bootstrap/set/all/bootstrap/layout.rb +0 -58
  298. data/mod/core/set/all/view_cache.rb +0 -9
@@ -1,4 +1,4 @@
1
-
1
+ # shared methods for card collections (Pointers, Searches, Sets, etc.)
2
2
  module ClassMethods
3
3
  def search spec, comment=nil
4
4
  results = ::Card::Query.run(spec, comment)
@@ -124,129 +124,137 @@ def contextual_content context_card, format_args={}, view_args={}
124
124
  )
125
125
  end
126
126
 
127
+ def each_chunk opts={}
128
+ content = opts[:content] || raw_content
129
+ chunk_type = opts[:chunk_type] || Card::Content::Chunk
130
+ Card::Content.new(content, self).find_chunks(chunk_type).each do |chunk|
131
+ next unless chunk.referee_name # filter commented nests
132
+ yield chunk
133
+ end
134
+ end
135
+
136
+ def each_reference_chunk content=nil
137
+ reference_chunk_type = Card::Content::Chunk::Reference
138
+ each_chunk content: content, chunk_type: reference_chunk_type do |chunk|
139
+ yield chunk
140
+ end
141
+ end
142
+
143
+ def each_nested_chunk content=nil
144
+ nest_chunk_type = Card::Content::Chunk::Nest
145
+ each_chunk content: content, chunk_type: nest_chunk_type do |chunk|
146
+ yield chunk
147
+ end
148
+ end
149
+
150
+ def each_item_name_with_options content=nil
151
+ each_reference_chunk content do |chunk|
152
+ options = chunk.respond_to?(:options) ? chunk.options : {}
153
+ yield chunk.referee_name, options
154
+ end
155
+ end
156
+
127
157
  format do
128
158
  def item_links _args={}
129
159
  raw(render_core).split(/[,\n]/)
130
160
  end
131
161
 
132
- def item_view args
133
- args[:item] ||
134
- (@nest_opts && @nest_opts[:view]) ||
135
- default_item_view
162
+ def nest_item cardish, options={}, &block
163
+ options = item_view_options options
164
+ options[:nest_name] = Card::Name.cardish(cardish).s
165
+ nest cardish, options, &block
136
166
  end
137
167
 
138
- def item_args args
139
- i_args = { view: item_view(args) }
140
- if (type = card.item_type)
141
- i_args[:type] = type
142
- end
143
- i_args
168
+ def implicit_item_view
169
+ view = voo_items_view || default_item_view
170
+ Card::View.canonicalize view
144
171
  end
145
172
 
146
- def search_params
147
- @search_params ||= begin
148
- p = default_search_params.clone
173
+ def voo_items_view
174
+ return unless (voo && items = voo.items)
175
+ items[:view]
176
+ end
149
177
 
150
- if focal?
151
- p[:offset] = params[:offset] if params[:offset]
152
- p[:limit] = params[:limit] if params[:limit]
153
- p.merge! params[:wql] if params[:wql]
154
- end
155
- p
156
- end
178
+ def default_item_view
179
+ :name
157
180
  end
158
181
 
159
- def default_search_params # wahh?
160
- set_default_search_params
182
+ def item_view_options new_options={}
183
+ options = (voo.items || {}).clone
184
+ options = options.merge new_options
185
+ options[:view] ||= implicit_item_view
186
+ determine_item_view_options_type options
187
+ options
161
188
  end
162
189
 
163
- def set_default_search_params overrides={}
164
- @default_search_params ||= begin
165
- p = { default_limit: 100 }.merge overrides
166
- set_search_params_variables! p
167
- p
168
- end
190
+ def determine_item_view_options_type options
191
+ return if options[:type]
192
+ type_from_rule = card.item_type
193
+ options[:type] = type_from_rule if type_from_rule
169
194
  end
170
195
 
171
- def set_search_params_variables! hash
172
- hash[:vars] = params[:vars] || {}
173
- params.each do |key, val|
174
- case key.to_s
175
- when "_wql" then hash.merge! val
176
- when /^\_(\w+)$/ then hash[:vars][Regexp.last_match(1).to_sym] = val
177
- end
196
+ def nested_fields content=nil
197
+ result = []
198
+ each_nested_field(content) do |chunk|
199
+ result << [chunk.referee_name, chunk.options]
178
200
  end
201
+ result
179
202
  end
180
203
 
181
- def each_reference_with_args args={}
182
- content_object = Card::Content.new _render_raw(args), card
183
- content_object.find_chunks(Card::Content::Chunk::Reference).each do |chunk|
184
- yield chunk.referee_name.to_s, nest_args(args, chunk)
204
+ def nested_fields_for_edit
205
+ return normalized_edit_fields if edit_fields.present?
206
+ result = []
207
+ each_nested_field do |chunk|
208
+ result << [chunk.options[:nest_name], chunk.options]
185
209
  end
210
+ result
186
211
  end
187
212
 
188
- def each_nested_chunk args={}
189
- content_object = Card::Content.new(_render_raw(args), card)
190
- content_object.find_chunks(Card::Content::Chunk::Include).each do |chunk|
191
- yield(chunk) if chunk.referee_name # filter commented nests
192
- end
213
+ def edit_fields
214
+ voo.edit_structure || []
193
215
  end
194
216
 
195
- def nested_fields args={}
196
- result = []
197
- each_nested_field(args) do |chunk|
198
- result << chunk
217
+ def normalized_edit_fields
218
+ edit_fields.map do |name, options|
219
+ options ||= Card.quick_fetch(name).name
220
+ options = { title: options } if options.is_a?(String)
221
+ [card.cardname.field(name), options]
199
222
  end
200
- result
201
223
  end
202
224
 
203
- def unique_chunks chunk, processed_set, &_block
204
- return if processed_set.include? chunk.referee_name.key
205
- processed_set << chunk.referee_name.key
206
- yield(chunk)
225
+ def process_field chunk, processed, &_block
226
+ return unless process_unique_field? chunk, processed
227
+ yield chunk
207
228
  end
208
229
 
209
- def each_nested_field args, &block
210
- processed_chunk_keys = ::Set.new([card.key])
211
-
212
- each_nested_chunk(args) do |chunk|
213
- # TODO: handle structures that are non-virtual
230
+ def each_nested_field content=nil, &block
231
+ processed = ::Set.new [card.key]
232
+ content ||= _render_raw
233
+ card.each_nested_chunk content do |chunk|
214
234
  next unless chunk.referee_name.to_name.field_of? card.name
215
- if chunk.referee_card &&
216
- chunk.referee_card.virtual? &&
217
- !processed_chunk_keys.include?(chunk.referee_name.key)
218
-
219
- processed_chunk_keys << chunk.referee_name.key
220
- subformat(chunk.referee_card).each_nested_field(args) do |sub_chunk|
221
- unique_chunks sub_chunk, processed_chunk_keys, &block
222
- end
223
- else
224
- unique_chunks chunk, processed_chunk_keys, &block
225
- end
235
+ process_nested_chunk chunk, processed, &block
226
236
  end
227
237
  end
228
238
 
229
- def map_references_with_args args={}, &_block
230
- result = []
231
- each_reference_with_args args do |name, n_args|
232
- result << yield(name, n_args)
233
- end
234
- result
239
+ def process_nested_chunk chunk, processed, &block
240
+ virtual = chunk.referee_card && chunk.referee_card.virtual?
241
+ # TODO: handle structures that are non-virtual
242
+ method = virtual ? :process_virtual_field : :process_field
243
+ send method, chunk, processed, &block
235
244
  end
236
245
 
237
- # process args for links and nests
238
- def nest_args args, chunk=nil
239
- r_args = item_args(args)
240
- r_args.merge! @nest_opts.clone if @nest_opts
241
-
242
- case chunk
243
- when Card::Content::Chunk::Include
244
- r_args.merge!(chunk.options)
245
- when Card::Content::Chunk::Link
246
- r_args.reverse_merge!(view: :link)
247
- r_args.reverse_merge!(title: chunk.link_text) if chunk.link_text
246
+ def process_virtual_field chunk, processed, &block
247
+ return unless process_unique_field? chunk, processed
248
+ subformat(chunk.referee_card).each_nested_field do |sub_chunk|
249
+ process_field sub_chunk, processed, &block
248
250
  end
249
- r_args
251
+ end
252
+
253
+ def process_unique_field? chunk, processed
254
+ key = chunk.referee_name.key
255
+ return false if processed.include? key
256
+ processed << key
257
+ true
250
258
  end
251
259
  end
252
260
 
@@ -255,52 +263,58 @@ format :html do
255
263
  card.item_names(args).size
256
264
  end
257
265
 
258
- view :tabs do |args|
259
- active_name = nil
260
- active_content = nil
261
- tabs = {}
262
- each_reference_with_args(item: :content) do |name, nest_args|
263
- tab_name = nest_args[:title] || name
264
- tabs[tab_name] = nest_path(name, nest_args).html_safe
266
+ view :tabs do
267
+ construct_tabs "tabs"
268
+ end
265
269
 
266
- active_name ||= tab_name
267
- # warning: nest changes nest_args
268
- active_content ||= nest(Card.fetch(name, new: {}), nest_args)
270
+ def construct_tabs tab_type
271
+ tabs = { active: {}, paths: {} }
272
+ voo.items[:view] ||= :content
273
+ card.each_item_name_with_options(_render_raw) do |name, options|
274
+ construct_tab tabs, name, options
269
275
  end
270
- lazy_loading_tabs tabs, active_name, active_content,
271
- type: args[:tab_type]
276
+ lazy_loading_tabs tabs[:paths], tabs[:active][:name],
277
+ tabs[:active][:content], type: tab_type
278
+ end
279
+
280
+ def construct_tab tabs, name, explicit_options
281
+ tab_options = item_view_options explicit_options
282
+ title = tab_title tab_options[:title], name
283
+ tabs[:paths][title] = { title: title,
284
+ path: nest_path(name, tab_options).html_safe }
285
+ return unless tabs[:active].empty?
286
+ tabs[:active] = { name: title, content: nest(name, tab_options) }
272
287
  end
273
- def default_tabs_args args
274
- args[:tab_type] ||= "tabs"
288
+
289
+ def tab_title title, name
290
+ return name unless title
291
+ name.to_name.title title, @context_names
275
292
  end
276
293
 
277
294
  # create a path for a nest with respect ot the nest options
278
- def nest_path name, nest_args
279
- path_args = {}
280
- path_args[:view] = nest_args[:view]
281
- path_args[:slot] = nest_args.clone
282
- path_args[:slot].delete(:view)
283
- page_path(name, path_args)
295
+ def nest_path name, nest_opts={}
296
+ path_opts = { slot: nest_opts.clone }
297
+ path_opts[:view] = path_opts[:slot].delete :view
298
+ page_path name, path_opts
284
299
  end
285
300
 
286
- view :pills, view: :tabs
287
- def default_pills_args args
288
- args[:tab_type] ||= "pills"
301
+ view :pills do
302
+ construct_tabs "pills"
289
303
  end
290
304
 
291
- view :tabs_static do |args|
292
- tabs = {}
293
- card.item_cards.each do |item|
294
- tabs[item.name] = nest item, item_args(args)
295
- end
296
- static_tabs tabs, args[:tab_type]
305
+ view :tabs_static do
306
+ construct_static_tabs "tabs"
297
307
  end
298
- def default_tabs_static_args args
299
- args[:tab_type] ||= "tabs"
308
+
309
+ view :pills_static do
310
+ construct_static_tabs "pills"
300
311
  end
301
312
 
302
- view :pills_static, view: :tabs_static
303
- def default_tabs_static_args args
304
- args[:tab_type] ||= "pills"
313
+ def construct_static_tabs tab_type
314
+ tabs = {}
315
+ card.item_cards.each do |item|
316
+ tabs[item.name] = nest item, item_view_options(args)
317
+ end
318
+ static_tabs tabs, tab_type
305
319
  end
306
320
  end
@@ -46,6 +46,14 @@ def last_draft_content
46
46
  drafts.last.card_changes.last.value
47
47
  end
48
48
 
49
+ event :set_content, :store, on: :save do
50
+ self.db_content = content || "" # necessary?
51
+ self.db_content = Card::Content.clean!(db_content) if clean_html?
52
+ @selected_action_id = @selected_content = nil
53
+ clear_drafts
54
+ reset_patterns_if_rule true
55
+ end
56
+
49
57
  event :save_draft, :store,
50
58
  on: :update, when: proc { Env.params["draft"] == "true" } do
51
59
  save_content_draft content
@@ -25,8 +25,11 @@ def changed_condition_applies? db_columns
25
25
  end
26
26
 
27
27
  def when_condition_applies? block
28
- return true unless block
29
- block.call(self)
28
+ case block
29
+ when Proc then block.call(self)
30
+ when Symbol then send block
31
+ else true
32
+ end
30
33
  end
31
34
 
32
35
  def single_changed_condition_applies? db_column
@@ -6,7 +6,7 @@ format :json do
6
6
  end
7
7
 
8
8
  # export the card itself and all nested content (up to 10 levels deep)
9
- view :export do |args|
9
+ view :export, cache: :never do |args|
10
10
  # avoid loops
11
11
  return [] if args[:count] > 10 || args[:processed_keys].include?(card.key)
12
12
  args[:processed_keys] << card.key
@@ -21,10 +21,10 @@ format :json do
21
21
  end
22
22
 
23
23
  # export all nested content (up to 10 levels deep)
24
- view :export_items do |args|
24
+ view :export_items, cache: :never do |args|
25
25
  result = []
26
- each_nested_chunk do |chunk|
27
- next if main_nest? chunk
26
+ card.each_nested_chunk do |chunk|
27
+ next if nest_name_main? chunk
28
28
  next unless (r_card = chunk.referee_card)
29
29
  next if r_card.new? || r_card == card
30
30
  next if args[:processed_keys].include?(r_card.key)
@@ -35,8 +35,8 @@ format :json do
35
35
  result.flatten.reject(&:blank?)
36
36
  end
37
37
 
38
- def main_nest? chunk
39
- chunk.respond_to?(:options) && chunk.options && chunk.options[:inc_name] &&
40
- chunk.options[:inc_name] == "_main"
38
+ def nest_name_main? chunk
39
+ chunk.respond_to?(:options) && chunk.options && chunk.options[:nest_name] &&
40
+ chunk.options[:nest_name] == "_main"
41
41
  end
42
42
  end
@@ -83,6 +83,14 @@ module ClassMethods
83
83
  end
84
84
  end
85
85
 
86
+ def fetch_name mark
87
+ if (card = quick_fetch(mark))
88
+ card.name
89
+ elsif block_given?
90
+ yield
91
+ end
92
+ end
93
+
86
94
  def quick_fetch mark
87
95
  fetch mark, skip_virtual: true, skip_modules: true
88
96
  end
@@ -183,6 +191,19 @@ module ClassMethods
183
191
  end
184
192
  end
185
193
 
194
+ def fetch_from_cast cast
195
+ fetch_args = cast[:id] ? [cast[:id].to_i] : [cast[:name], { new: cast }]
196
+ Card.fetch(*fetch_args)
197
+ end
198
+
199
+ def cardish cardish
200
+ if cardish.is_a? Card
201
+ cardish
202
+ else
203
+ fetch cardish, new: {}
204
+ end
205
+ end
206
+
186
207
  def deep_opts args
187
208
  opts = (args[:card] || {}).clone
188
209
  # clone so that original params remain unaltered. need deeper clone?
@@ -209,7 +230,8 @@ module ClassMethods
209
230
  opts[:skip_virtual] || opts[:new].present? || opts[:skip_type_lookup]
210
231
  end
211
232
 
212
- def compose_mark parts, opts
233
+ def compose_mark parts, opts={}
234
+ parts.flatten!
213
235
  return normalize_mark(parts.first, opts) if parts.size == 1
214
236
  parts.map do |p|
215
237
  normalized = normalize_mark p, {}
@@ -224,21 +246,33 @@ module ClassMethods
224
246
 
225
247
  def normalize_mark mark, opts
226
248
  case mark
227
- when Symbol then Card::Codename[mark]
228
- when Integer then mark.to_i
229
- when Card then mark.cardname
230
- when String, SmartName
249
+ when Symbol then require_id_for_codename mark
250
+ when Integer then mark.to_i
251
+ when Card then mark.cardname
252
+ when String, SmartName then normalize_stringy_mark mark, opts
231
253
  # there are some situations where this breaks if we use Card::Name
232
254
  # rather than SmartName, which would seem more correct.
233
255
  # very hard to reproduce, not captured in a spec :(
234
- case mark.to_s
235
- when /^\~(\d+)$/ then $1.to_i # id
236
- when /^\:(\w+)$/ then Card::Codename[$1.to_sym] # codename
237
- else fullname_from_mark mark, opts[:new] # name
238
- end
239
256
  end
240
257
  end
241
258
 
259
+ def normalize_stringy_mark mark, opts
260
+ case mark.to_s
261
+ when /^\~(\d+)$/ # id, eg "~75"
262
+ Regexp.last_match[1].to_i
263
+ when /^\:(\w+)$/ # codename, eg ":options"
264
+ require_id_for_codename(Regexp.last_match[1].to_sym)
265
+ else
266
+ fullname_from_mark mark, opts[:new]
267
+ end
268
+ end
269
+
270
+ def require_id_for_codename mark
271
+ id = Card::Codename[mark]
272
+ raise Card::Error::NotFound, "missing card with codename: #{mark}" unless id
273
+ id
274
+ end
275
+
242
276
  def fullname_from_mark name, new_opts={}
243
277
  if new_opts && (supercard = new_opts[:supercard])
244
278
  name.to_name.to_absolute_name supercard.name
@@ -283,30 +317,60 @@ def expire_pieces
283
317
  end
284
318
  end
285
319
 
286
- def expire_hard
320
+ def expire cache_type=nil
321
+ return unless (cache_class = cache_class_from_type cache_type)
322
+ expire_views
323
+ expire_names cache_class
324
+ expire_id cache_class
325
+ end
326
+
327
+ def cache_class_from_type cache_type
328
+ cache_type ? Card.cache.send(cache_type) : Card.cache
329
+ end
330
+
331
+ def register_view_cache_key cache_key
332
+ @view_cache_keys ||= []
333
+ @view_cache_keys << cache_key
334
+ @view_cache_keys.uniq!
335
+ hard_write_view_cache_keys
336
+ end
337
+
338
+ def hard_write_view_cache_keys
287
339
  return unless Card.cache.hard
288
- Card.cache.hard.delete key
289
- Card.cache.hard.delete "~#{id}" if id
340
+ Card.cache.hard.write_attribute key, :view_cache_keys, @view_cache_keys
290
341
  end
291
342
 
292
- def expire_soft
293
- Card.cache.soft.delete key
294
- Card.cache.soft.delete "~#{id}" if id
343
+ def expire_views
344
+ return unless @view_cache_keys
345
+ Array.wrap(@view_cache_keys).each do |view_cache_key|
346
+ Card::View.cache.delete view_cache_key
347
+ end
348
+ @view_cache_keys = nil
349
+ end
350
+
351
+ def expire_names cache
352
+ [name, name_was].each do |name_version|
353
+ expire_name name_version, cache
354
+ end
295
355
  end
296
356
 
297
- def expire
298
- expire_hard
299
- expire_soft
357
+ def expire_name name_version, cache
358
+ return unless name_version.present?
359
+ key_version = name_version.to_name.key
360
+ return unless key_version.present?
361
+ cache.delete key_version
362
+ end
363
+
364
+ def expire_id cache
365
+ return unless id.present?
366
+ cache.delete "~#{id}"
300
367
  end
301
368
 
302
369
  def refresh force=false
303
- if force || frozen? || readonly?
304
- fresh_card = self.class.find id
305
- fresh_card.include_set_modules
306
- fresh_card
307
- else
308
- self
309
- end
370
+ return self unless force || frozen? || readonly?
371
+ fresh_card = self.class.find id
372
+ fresh_card.include_set_modules
373
+ fresh_card
310
374
  end
311
375
 
312
376
  def eager_renew? opts