card 1.19.6 → 1.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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