alchemy_cms 4.6.7 → 5.0.0.beta1

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 (384) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +33 -1
  3. data/.github/workflows/stale.yml +1 -1
  4. data/.gitignore +20 -2
  5. data/.hound.yml +2 -1
  6. data/.prettierrc +6 -0
  7. data/.rubocop.yml +31 -10
  8. data/CHANGELOG.md +89 -32
  9. data/Gemfile +24 -22
  10. data/README.md +31 -19
  11. data/Rakefile +10 -8
  12. data/alchemy_cms.gemspec +6 -5
  13. data/app/assets/javascripts/alchemy/admin.js +1 -5
  14. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +2 -1
  15. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +0 -2
  16. data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +17 -17
  17. data/app/assets/javascripts/alchemy/node_select.js +39 -0
  18. data/app/assets/javascripts/alchemy/templates/index.js +1 -0
  19. data/app/assets/javascripts/alchemy/templates/node.hbs +16 -0
  20. data/app/assets/stylesheets/alchemy/admin.scss +3 -2
  21. data/app/assets/stylesheets/alchemy/base.scss +0 -1
  22. data/app/assets/stylesheets/alchemy/elements.scss +1 -1
  23. data/app/assets/stylesheets/alchemy/forms.scss +5 -0
  24. data/app/assets/stylesheets/alchemy/node-select.scss +43 -0
  25. data/app/assets/stylesheets/alchemy/nodes.scss +1 -1
  26. data/app/assets/stylesheets/alchemy/sitemap.scss +5 -1
  27. data/app/assets/stylesheets/alchemy/tables.scss +1 -24
  28. data/app/assets/stylesheets/tinymce/skins/alchemy/content.min.css.scss +3 -3
  29. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +7 -7
  30. data/app/controllers/alchemy/admin/attachments_controller.rb +8 -7
  31. data/app/controllers/alchemy/admin/base_controller.rb +16 -42
  32. data/app/controllers/alchemy/admin/clipboard_controller.rb +5 -4
  33. data/app/controllers/alchemy/admin/contents_controller.rb +1 -2
  34. data/app/controllers/alchemy/admin/dashboard_controller.rb +10 -9
  35. data/app/controllers/alchemy/admin/elements_controller.rb +20 -20
  36. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +12 -14
  37. data/app/controllers/alchemy/admin/languages_controller.rb +35 -2
  38. data/app/controllers/alchemy/admin/layoutpages_controller.rb +5 -2
  39. data/app/controllers/alchemy/admin/nodes_controller.rb +5 -4
  40. data/app/controllers/alchemy/admin/pages_controller.rb +50 -62
  41. data/app/controllers/alchemy/admin/pictures_controller.rb +16 -16
  42. data/app/controllers/alchemy/admin/resources_controller.rb +21 -13
  43. data/app/controllers/alchemy/admin/sites_controller.rb +18 -0
  44. data/app/controllers/alchemy/admin/styleguide_controller.rb +1 -0
  45. data/app/controllers/alchemy/admin/tags_controller.rb +5 -3
  46. data/app/controllers/alchemy/admin/trash_controller.rb +6 -6
  47. data/app/controllers/alchemy/api/base_controller.rb +2 -2
  48. data/app/controllers/alchemy/api/contents_controller.rb +4 -4
  49. data/app/controllers/alchemy/api/elements_controller.rb +8 -8
  50. data/app/controllers/alchemy/api/nodes_controller.rb +37 -1
  51. data/app/controllers/alchemy/api/pages_controller.rb +14 -23
  52. data/app/controllers/alchemy/attachments_controller.rb +5 -5
  53. data/app/controllers/alchemy/base_controller.rb +10 -9
  54. data/app/controllers/alchemy/messages_controller.rb +16 -23
  55. data/app/controllers/alchemy/pages_controller.rb +13 -11
  56. data/app/controllers/concerns/alchemy/admin/archive_overlay.rb +3 -2
  57. data/app/controllers/concerns/alchemy/admin/current_language.rb +23 -0
  58. data/app/controllers/concerns/alchemy/admin/uploader_responses.rb +5 -5
  59. data/app/controllers/concerns/alchemy/legacy_page_redirects.rb +4 -4
  60. data/app/controllers/concerns/alchemy/page_redirects.rb +2 -9
  61. data/app/controllers/concerns/alchemy/site_redirects.rb +2 -2
  62. data/app/decorators/alchemy/element_editor.rb +39 -0
  63. data/app/helpers/alchemy/admin/attachments_helper.rb +6 -6
  64. data/app/helpers/alchemy/admin/base_helper.rb +36 -35
  65. data/app/helpers/alchemy/admin/contents_helper.rb +3 -3
  66. data/app/helpers/alchemy/admin/elements_helper.rb +3 -88
  67. data/app/helpers/alchemy/admin/essences_helper.rb +8 -117
  68. data/app/helpers/alchemy/admin/form_helper.rb +1 -1
  69. data/app/helpers/alchemy/admin/navigation_helper.rb +24 -23
  70. data/app/helpers/alchemy/admin/pages_helper.rb +4 -4
  71. data/app/helpers/alchemy/admin/pictures_helper.rb +3 -3
  72. data/app/helpers/alchemy/admin/tags_helper.rb +8 -7
  73. data/app/helpers/alchemy/base_helper.rb +13 -8
  74. data/app/helpers/alchemy/elements_block_helper.rb +2 -31
  75. data/app/helpers/alchemy/elements_helper.rb +12 -58
  76. data/app/helpers/alchemy/pages_helper.rb +24 -174
  77. data/app/helpers/alchemy/url_helper.rb +2 -1
  78. data/app/mailers/alchemy/base_mailer.rb +1 -1
  79. data/app/mailers/alchemy/messages_mailer.rb +1 -1
  80. data/app/models/alchemy/attachment.rb +21 -19
  81. data/app/models/alchemy/base_record.rb +2 -5
  82. data/app/models/alchemy/content/factory.rb +24 -31
  83. data/app/models/alchemy/content.rb +33 -38
  84. data/app/models/alchemy/element/definitions.rb +4 -4
  85. data/app/models/alchemy/element/element_contents.rb +9 -6
  86. data/app/models/alchemy/element/element_essences.rb +4 -3
  87. data/app/models/alchemy/element/presenters.rb +3 -2
  88. data/app/models/alchemy/element.rb +46 -54
  89. data/app/models/alchemy/element_to_page.rb +1 -1
  90. data/app/models/alchemy/essence_boolean.rb +1 -3
  91. data/app/models/alchemy/essence_date.rb +2 -3
  92. data/app/models/alchemy/essence_file.rb +4 -4
  93. data/app/models/alchemy/essence_html.rb +1 -3
  94. data/app/models/alchemy/essence_link.rb +1 -3
  95. data/app/models/alchemy/essence_node.rb +18 -0
  96. data/app/models/alchemy/essence_page.rb +3 -16
  97. data/app/models/alchemy/essence_picture.rb +17 -16
  98. data/app/models/alchemy/essence_picture_view.rb +7 -6
  99. data/app/models/alchemy/essence_richtext.rb +1 -3
  100. data/app/models/alchemy/essence_select.rb +1 -3
  101. data/app/models/alchemy/essence_text.rb +0 -2
  102. data/app/models/alchemy/folded_page.rb +1 -0
  103. data/app/models/alchemy/language/code.rb +4 -4
  104. data/app/models/alchemy/language.rb +21 -35
  105. data/app/models/alchemy/legacy_page_url.rb +1 -1
  106. data/app/models/alchemy/message.rb +3 -3
  107. data/app/models/alchemy/node.rb +28 -5
  108. data/app/models/alchemy/page/fixed_attributes.rb +3 -2
  109. data/app/models/alchemy/page/page_elements.rb +35 -44
  110. data/app/models/alchemy/page/page_naming.rb +20 -70
  111. data/app/models/alchemy/page/page_natures.rb +7 -34
  112. data/app/models/alchemy/page/page_scopes.rb +23 -29
  113. data/app/models/alchemy/page/url_path.rb +0 -2
  114. data/app/models/alchemy/page.rb +47 -128
  115. data/app/models/alchemy/picture/transformations.rb +9 -7
  116. data/app/models/alchemy/picture/url.rb +5 -5
  117. data/app/models/alchemy/picture.rb +19 -28
  118. data/app/models/alchemy/site/layout.rb +2 -2
  119. data/app/models/alchemy/site.rb +6 -36
  120. data/app/models/concerns/alchemy/touch_elements.rb +24 -0
  121. data/app/serializers/alchemy/content_serializer.rb +0 -3
  122. data/app/serializers/alchemy/essence_boolean_serializer.rb +3 -3
  123. data/app/serializers/alchemy/essence_date_serializer.rb +3 -3
  124. data/app/serializers/alchemy/essence_file_serializer.rb +4 -2
  125. data/app/serializers/alchemy/essence_html_serializer.rb +3 -3
  126. data/app/serializers/alchemy/essence_link_serializer.rb +3 -3
  127. data/app/serializers/alchemy/essence_picture_serializer.rb +5 -4
  128. data/app/serializers/alchemy/essence_richtext_serializer.rb +3 -3
  129. data/app/serializers/alchemy/essence_select_serializer.rb +3 -3
  130. data/app/serializers/alchemy/essence_text_serializer.rb +5 -4
  131. data/app/serializers/alchemy/node_serializer.rb +2 -0
  132. data/app/serializers/alchemy/page_tree_serializer.rb +9 -13
  133. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +1 -2
  134. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +1 -2
  135. data/app/views/alchemy/admin/attachments/_files_list.html.erb +4 -4
  136. data/app/views/alchemy/admin/contents/create.js.erb +1 -3
  137. data/app/views/alchemy/admin/elements/_element.html.erb +9 -18
  138. data/app/views/alchemy/admin/elements/create.js.erb +1 -1
  139. data/app/views/alchemy/admin/elements/fold.js.erb +1 -1
  140. data/app/views/alchemy/admin/elements/index.html.erb +3 -3
  141. data/app/views/alchemy/admin/essence_files/assign.js.erb +1 -6
  142. data/app/views/alchemy/admin/essence_files/edit.html.erb +1 -1
  143. data/app/views/alchemy/admin/essence_pictures/assign.js.erb +1 -7
  144. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +1 -1
  145. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +7 -7
  146. data/app/views/alchemy/admin/essence_pictures/update.js.erb +1 -1
  147. data/app/views/alchemy/admin/languages/_form.html.erb +5 -5
  148. data/app/views/alchemy/admin/languages/_table.html.erb +3 -3
  149. data/app/views/alchemy/admin/languages/edit.html.erb +1 -0
  150. data/app/views/alchemy/admin/languages/index.html.erb +23 -4
  151. data/app/views/alchemy/admin/languages/new.html.erb +1 -0
  152. data/app/views/alchemy/admin/layoutpages/index.html.erb +3 -3
  153. data/app/views/alchemy/admin/nodes/_form.html.erb +18 -15
  154. data/app/views/alchemy/admin/nodes/_node.html.erb +1 -5
  155. data/app/views/alchemy/admin/nodes/index.html.erb +3 -4
  156. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +0 -8
  157. data/app/views/alchemy/admin/pages/_form.html.erb +0 -1
  158. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +1 -0
  159. data/app/views/alchemy/admin/pages/_page.html.erb +11 -19
  160. data/app/views/alchemy/admin/pages/_page_infos.html.erb +0 -4
  161. data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
  162. data/app/views/alchemy/admin/pages/info.html.erb +0 -9
  163. data/app/views/alchemy/admin/pages/unlock.js.erb +13 -6
  164. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +0 -2
  165. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -5
  166. data/app/views/alchemy/admin/pictures/_overlay_picture_list.html.erb +1 -1
  167. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +1 -2
  168. data/app/views/alchemy/admin/resources/_resource.html.erb +1 -1
  169. data/app/views/alchemy/admin/resources/_table.html.erb +2 -2
  170. data/app/views/alchemy/admin/sites/_form.html.erb +8 -0
  171. data/app/views/alchemy/admin/sites/edit.html.erb +1 -0
  172. data/app/views/alchemy/admin/sites/index.html.erb +21 -9
  173. data/app/views/alchemy/admin/sites/new.html.erb +1 -0
  174. data/app/views/alchemy/admin/tags/index.html.erb +2 -2
  175. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +10 -12
  176. data/app/views/alchemy/essences/_essence_date_editor.html.erb +11 -8
  177. data/app/views/alchemy/essences/_essence_file_editor.html.erb +16 -17
  178. data/app/views/alchemy/essences/_essence_html_editor.html.erb +8 -5
  179. data/app/views/alchemy/essences/_essence_link_editor.html.erb +18 -15
  180. data/app/views/alchemy/essences/_essence_node_editor.html.erb +27 -0
  181. data/app/views/alchemy/essences/_essence_node_view.html.erb +1 -0
  182. data/app/views/alchemy/essences/_essence_page_editor.html.erb +14 -11
  183. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +22 -20
  184. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +10 -7
  185. data/app/views/alchemy/essences/_essence_select_editor.html.erb +12 -16
  186. data/app/views/alchemy/essences/_essence_text_editor.html.erb +18 -17
  187. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +6 -11
  188. data/app/views/alchemy/pages/show.rss.builder +3 -2
  189. data/app/views/layouts/alchemy/admin.html.erb +1 -0
  190. data/babel.config.js +12 -0
  191. data/bin/rails +5 -4
  192. data/config/alchemy/config.yml +15 -18
  193. data/config/brakeman.ignore +1 -1
  194. data/config/initializers/assets.rb +2 -1
  195. data/config/initializers/dragonfly.rb +2 -1
  196. data/config/initializers/mime_types.rb +1 -0
  197. data/config/initializers/mini_profiler.rb +3 -2
  198. data/config/initializers/simple_form.rb +6 -6
  199. data/config/locales/alchemy.en.yml +23 -8
  200. data/config/routes.rb +25 -24
  201. data/config/spring.rb +3 -2
  202. data/db/migrate/20200226213334_alchemy_four_point_four.rb +313 -0
  203. data/db/migrate/20200423073425_create_alchemy_essence_nodes.rb +11 -0
  204. data/db/migrate/20200504210159_remove_site_id_from_nodes.rb +28 -0
  205. data/db/migrate/20200505215518_add_language_id_foreign_key_to_alchemy_pages.rb +8 -0
  206. data/db/migrate/20200511113603_add_menu_type_to_alchemy_nodes.rb +27 -0
  207. data/db/migrate/20200514091507_make_page_layoutpage_null_false.rb +6 -0
  208. data/db/migrate/20200519073500_remove_visible_from_alchemy_pages.rb +24 -0
  209. data/lib/alchemy/admin/locale.rb +3 -1
  210. data/lib/alchemy/admin/preview_url.rb +64 -0
  211. data/lib/alchemy/auth_accessors.rb +8 -7
  212. data/lib/alchemy/cache_digests/template_tracker.rb +5 -4
  213. data/lib/alchemy/config.rb +1 -5
  214. data/lib/alchemy/configuration_methods.rb +3 -1
  215. data/lib/alchemy/controller_actions.rb +6 -5
  216. data/lib/alchemy/deprecation.rb +2 -1
  217. data/lib/alchemy/elements_finder.rb +5 -5
  218. data/lib/alchemy/engine.rb +22 -14
  219. data/lib/alchemy/errors.rb +0 -7
  220. data/lib/alchemy/essence.rb +17 -16
  221. data/lib/alchemy/filetypes.rb +5 -5
  222. data/lib/alchemy/forms/builder.rb +4 -4
  223. data/lib/alchemy/hints.rb +1 -1
  224. data/lib/alchemy/i18n.rb +2 -1
  225. data/lib/alchemy/modules.rb +12 -12
  226. data/lib/alchemy/name_conversions.rb +5 -5
  227. data/lib/alchemy/on_page_layout/callbacks_runner.rb +1 -0
  228. data/lib/alchemy/page_layout.rb +15 -12
  229. data/lib/alchemy/paths.rb +1 -1
  230. data/lib/alchemy/permissions.rb +7 -6
  231. data/lib/alchemy/resource.rb +25 -17
  232. data/lib/alchemy/resources_helper.rb +12 -18
  233. data/lib/alchemy/routing_constraints.rb +1 -1
  234. data/lib/alchemy/seeder.rb +42 -14
  235. data/lib/alchemy/shell.rb +13 -10
  236. data/lib/alchemy/taggable.rb +1 -0
  237. data/lib/alchemy/tasks/tidy.rb +4 -3
  238. data/lib/alchemy/test_support/config_stubbing.rb +1 -0
  239. data/lib/alchemy/test_support/essence_shared_examples.rb +72 -72
  240. data/lib/alchemy/test_support/factories/attachment_factory.rb +5 -5
  241. data/lib/alchemy/test_support/factories/content_factory.rb +6 -6
  242. data/lib/alchemy/test_support/factories/dummy_user_factory.rb +7 -7
  243. data/lib/alchemy/test_support/factories/element_factory.rb +9 -9
  244. data/lib/alchemy/test_support/factories/essence_file_factory.rb +3 -3
  245. data/lib/alchemy/test_support/factories/essence_page_factory.rb +3 -3
  246. data/lib/alchemy/test_support/factories/essence_picture_factory.rb +4 -4
  247. data/lib/alchemy/test_support/factories/essence_text_factory.rb +3 -3
  248. data/lib/alchemy/test_support/factories/language_factory.rb +16 -14
  249. data/lib/alchemy/test_support/factories/node_factory.rb +8 -8
  250. data/lib/alchemy/test_support/factories/page_factory.rb +15 -27
  251. data/lib/alchemy/test_support/factories/picture_factory.rb +5 -5
  252. data/lib/alchemy/test_support/factories/site_factory.rb +7 -6
  253. data/lib/alchemy/test_support/factories.rb +1 -1
  254. data/lib/alchemy/test_support/integration_helpers.rb +1 -0
  255. data/lib/alchemy/test_support/shared_contexts.rb +5 -4
  256. data/lib/alchemy/test_support/shared_uploader_examples.rb +4 -3
  257. data/lib/alchemy/tinymce.rb +15 -13
  258. data/lib/alchemy/upgrader/five_point_zero.rb +41 -0
  259. data/lib/alchemy/upgrader/tasks/element_views_updater.rb +4 -4
  260. data/lib/alchemy/upgrader/tasks/harden_gutentag_migrations.rb +29 -0
  261. data/lib/alchemy/upgrader.rb +8 -7
  262. data/lib/alchemy/userstamp.rb +1 -1
  263. data/lib/alchemy/version.rb +1 -1
  264. data/lib/alchemy_cms.rb +52 -51
  265. data/lib/{rails/generators → generators}/alchemy/base.rb +5 -4
  266. data/lib/{rails/generators → generators}/alchemy/elements/elements_generator.rb +13 -9
  267. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.erb +0 -0
  268. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.haml +0 -0
  269. data/lib/{rails/generators → generators}/alchemy/elements/templates/view.html.slim +0 -0
  270. data/lib/{rails/generators → generators}/alchemy/essence/essence_generator.rb +15 -13
  271. data/lib/generators/alchemy/essence/templates/editor.html.erb +17 -0
  272. data/lib/{rails/generators → generators}/alchemy/essence/templates/view.html.erb +0 -0
  273. data/lib/{rails/generators → generators}/alchemy/install/files/_article.html.erb +0 -0
  274. data/lib/{rails/generators → generators}/alchemy/install/files/_standard.html.erb +0 -0
  275. data/lib/{rails/generators → generators}/alchemy/install/files/alchemy.en.yml +0 -0
  276. data/lib/generators/alchemy/install/files/alchemy_admin.js +1 -0
  277. data/lib/{rails/generators → generators}/alchemy/install/files/all.css +0 -0
  278. data/lib/{rails/generators → generators}/alchemy/install/files/all.js +0 -0
  279. data/lib/{rails/generators → generators}/alchemy/install/files/application.html.erb +0 -0
  280. data/lib/{rails/generators → generators}/alchemy/install/files/article.scss +0 -0
  281. data/lib/generators/alchemy/install/install_generator.rb +110 -0
  282. data/lib/{rails/generators → generators}/alchemy/install/templates/dragonfly.rb.tt +0 -0
  283. data/lib/{rails/generators → generators}/alchemy/install/templates/elements.yml.tt +0 -0
  284. data/lib/{rails/generators → generators}/alchemy/install/templates/menus.yml.tt +0 -0
  285. data/lib/{rails/generators → generators}/alchemy/install/templates/page_layouts.yml.tt +0 -0
  286. data/lib/{rails/generators → generators}/alchemy/menus/menus_generator.rb +2 -2
  287. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.erb +1 -4
  288. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.haml +1 -4
  289. data/lib/{rails/generators → generators}/alchemy/menus/templates/node.html.slim +1 -4
  290. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.erb +1 -1
  291. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.haml +1 -1
  292. data/lib/{rails/generators → generators}/alchemy/menus/templates/wrapper.html.slim +1 -1
  293. data/lib/{rails/generators → generators}/alchemy/module/module_generator.rb +3 -2
  294. data/lib/{rails/generators → generators}/alchemy/module/templates/ability.rb.tt +0 -0
  295. data/lib/{rails/generators → generators}/alchemy/module/templates/controller.rb.tt +0 -0
  296. data/lib/{rails/generators → generators}/alchemy/module/templates/module_config.rb.tt +0 -0
  297. data/lib/{rails/generators → generators}/alchemy/page_layouts/page_layouts_generator.rb +5 -4
  298. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.erb +0 -0
  299. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.haml +0 -0
  300. data/lib/{rails/generators → generators}/alchemy/page_layouts/templates/layout.html.slim +0 -0
  301. data/lib/{rails/generators → generators}/alchemy/site_layouts/site_layouts_generator.rb +4 -2
  302. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.erb +0 -0
  303. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.haml +0 -0
  304. data/lib/{rails/generators → generators}/alchemy/site_layouts/templates/layout.html.slim +0 -0
  305. data/lib/{rails/generators → generators}/alchemy/views/views_generator.rb +7 -6
  306. data/lib/kaminari/scoped_pagination_url_helper.rb +1 -0
  307. data/lib/tasks/alchemy/db.rake +3 -19
  308. data/lib/tasks/alchemy/install.rake +3 -2
  309. data/lib/tasks/alchemy/tidy.rake +9 -8
  310. data/lib/tasks/alchemy/upgrade.rake +18 -120
  311. data/package/admin.js +14 -0
  312. data/package/src/__tests__/i18n.spec.js +70 -0
  313. data/package/src/i18n.js +48 -0
  314. data/package/src/node_tree.js +72 -0
  315. data/package/src/translations.js +32 -0
  316. data/package/src/utils/__tests__/ajax.spec.js +124 -0
  317. data/package/src/utils/__tests__/events.spec.js +38 -0
  318. data/package/src/utils/ajax.js +48 -0
  319. data/package/src/utils/events.js +16 -0
  320. data/package.json +45 -0
  321. data/vendor/assets/fonts/fa-regular-400.eot +0 -0
  322. data/vendor/assets/fonts/fa-regular-400.svg +798 -358
  323. data/vendor/assets/fonts/fa-regular-400.ttf +0 -0
  324. data/vendor/assets/fonts/fa-regular-400.woff +0 -0
  325. data/vendor/assets/fonts/fa-regular-400.woff2 +0 -0
  326. data/vendor/assets/fonts/fa-solid-900.eot +0 -0
  327. data/vendor/assets/fonts/fa-solid-900.svg +4933 -1408
  328. data/vendor/assets/fonts/fa-solid-900.ttf +0 -0
  329. data/vendor/assets/fonts/fa-solid-900.woff +0 -0
  330. data/vendor/assets/fonts/fa-solid-900.woff2 +0 -0
  331. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +1 -2
  332. data/vendor/assets/stylesheets/fontawesome/_core.scss +5 -0
  333. data/vendor/assets/stylesheets/fontawesome/_fixed-width.scss +1 -1
  334. data/vendor/assets/stylesheets/fontawesome/_icons.scss +651 -2
  335. data/vendor/assets/stylesheets/fontawesome/_mixins.scss +0 -1
  336. data/vendor/assets/stylesheets/fontawesome/_rotated-flipped.scss +3 -2
  337. data/vendor/assets/stylesheets/fontawesome/_stacked.scss +1 -1
  338. data/vendor/assets/stylesheets/fontawesome/_variables.scss +662 -9
  339. data/vendor/assets/stylesheets/fontawesome/fontawesome.scss +2 -2
  340. data/vendor/assets/stylesheets/fontawesome/regular.scss +23 -0
  341. data/vendor/assets/stylesheets/fontawesome/solid.scss +24 -0
  342. metadata +117 -98
  343. data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +0 -32
  344. data/app/assets/javascripts/alchemy/alchemy.node_tree.js +0 -66
  345. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +0 -29
  346. data/app/assets/javascripts/alchemy/alchemy.utils.js +0 -45
  347. data/app/helpers/alchemy/essences_helper.rb +0 -119
  348. data/app/models/concerns/alchemy/content_touching.rb +0 -23
  349. data/app/serializers/alchemy/legacy_element_serializer.rb +0 -15
  350. data/app/views/alchemy/admin/contents/_missing.html.erb +0 -17
  351. data/app/views/alchemy/admin/pages/_menu_fields.html.erb +0 -37
  352. data/app/views/alchemy/admin/pages/configure_external.html.erb +0 -32
  353. data/app/views/alchemy/elements/_editor_not_found.html.erb +0 -4
  354. data/app/views/alchemy/navigation/_image_link.html.erb +0 -14
  355. data/app/views/alchemy/navigation/_link.html.erb +0 -19
  356. data/app/views/alchemy/navigation/_renderer.html.erb +0 -29
  357. data/db/migrate/20180226123013_alchemy_four_point_zero.rb +0 -363
  358. data/db/migrate/20180227224537_migrate_tags_to_gutentag.rb +0 -41
  359. data/db/migrate/20180519204655_add_fixed_to_alchemy_elements.rb +0 -6
  360. data/db/migrate/20191016073858_create_alchemy_essence_pages.rb +0 -8
  361. data/db/migrate/20191029212236_create_alchemy_nodes.rb +0 -24
  362. data/db/migrate/20200226081535_add_site_id_to_alchemy_nodes.rb +0 -15
  363. data/lib/alchemy/error_tracking/airbrake_handler.rb +0 -13
  364. data/lib/alchemy/error_tracking.rb +0 -14
  365. data/lib/alchemy/ssl_protection.rb +0 -34
  366. data/lib/alchemy/tasks/helpers.rb +0 -81
  367. data/lib/alchemy/test_support/controller_requests.rb +0 -93
  368. data/lib/alchemy/upgrader/four_point_four.rb +0 -52
  369. data/lib/alchemy/upgrader/four_point_one.rb +0 -42
  370. data/lib/alchemy/upgrader/four_point_six.rb +0 -50
  371. data/lib/alchemy/upgrader/four_point_two.rb +0 -86
  372. data/lib/alchemy/upgrader/tasks/cells_migration.rb +0 -45
  373. data/lib/alchemy/upgrader/tasks/cells_upgrader.rb +0 -166
  374. data/lib/alchemy/upgrader/tasks/element_partial_name_variable_updater.rb +0 -32
  375. data/lib/alchemy/upgrader/tasks/fixed_element_name_finder.rb +0 -31
  376. data/lib/alchemy/upgrader/tasks/harden_acts_as_taggable_on_migrations.rb +0 -27
  377. data/lib/alchemy/upgrader/tasks/picture_gallery_migration.rb +0 -65
  378. data/lib/alchemy/upgrader/tasks/picture_gallery_upgrader.rb +0 -210
  379. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +0 -15
  380. data/lib/rails/generators/alchemy/install/install_generator.rb +0 -60
  381. data/lib/tasks/alchemy/convert.rake +0 -98
  382. data/vendor/assets/javascripts/sortable/Sortable.min.js +0 -2
  383. data/vendor/assets/stylesheets/fontawesome/fa-regular.scss +0 -22
  384. data/vendor/assets/stylesheets/fontawesome/fa-solid.scss +0 -23
@@ -28,29 +28,25 @@ module Alchemy
28
28
  belongs_to :element, touch: true, inverse_of: :contents
29
29
  has_one :page, through: :element
30
30
 
31
- stampable stamper_class_name: Alchemy.user_class.name
32
-
33
- acts_as_list scope: [:element_id]
34
-
35
31
  # Essence scopes
36
- scope :essence_booleans, -> { where(essence_type: "Alchemy::EssenceBoolean") }
37
- scope :essence_dates, -> { where(essence_type: "Alchemy::EssenceDate") }
38
- scope :essence_files, -> { where(essence_type: "Alchemy::EssenceFile") }
39
- scope :essence_htmls, -> { where(essence_type: "Alchemy::EssenceHtml") }
40
- scope :essence_links, -> { where(essence_type: "Alchemy::EssenceLink") }
41
- scope :essence_pictures, -> { where(essence_type: "Alchemy::EssencePicture") }
32
+ scope :essence_booleans, -> { where(essence_type: "Alchemy::EssenceBoolean") }
33
+ scope :essence_dates, -> { where(essence_type: "Alchemy::EssenceDate") }
34
+ scope :essence_files, -> { where(essence_type: "Alchemy::EssenceFile") }
35
+ scope :essence_htmls, -> { where(essence_type: "Alchemy::EssenceHtml") }
36
+ scope :essence_links, -> { where(essence_type: "Alchemy::EssenceLink") }
37
+ scope :essence_pictures, -> { where(essence_type: "Alchemy::EssencePicture") }
42
38
  scope :essence_richtexts, -> { where(essence_type: "Alchemy::EssenceRichtext") }
43
- scope :essence_selects, -> { where(essence_type: "Alchemy::EssenceSelect") }
44
- scope :essence_texts, -> { where(essence_type: "Alchemy::EssenceText") }
45
- scope :named, ->(name) { where(name: name) }
46
- scope :available, -> { published.not_trashed }
47
- scope :published, -> { joins(:element).merge(Element.published) }
48
- scope :not_trashed, -> { joins(:element).merge(Element.not_trashed) }
49
- scope :not_restricted, -> { joins(:element).merge(Element.not_restricted) }
50
-
51
- delegate :restricted?, to: :page, allow_nil: true
52
- delegate :trashed?, to: :element, allow_nil: true
53
- delegate :public?, to: :element, allow_nil: true
39
+ scope :essence_selects, -> { where(essence_type: "Alchemy::EssenceSelect") }
40
+ scope :essence_texts, -> { where(essence_type: "Alchemy::EssenceText") }
41
+ scope :named, ->(name) { where(name: name) }
42
+ scope :available, -> { published.not_trashed }
43
+ scope :published, -> { joins(:element).merge(Element.published) }
44
+ scope :not_trashed, -> { joins(:element).merge(Element.not_trashed) }
45
+ scope :not_restricted, -> { joins(:element).merge(Element.not_restricted) }
46
+
47
+ delegate :restricted?, to: :page, allow_nil: true
48
+ delegate :trashed?, to: :element, allow_nil: true
49
+ delegate :public?, to: :element, allow_nil: true
54
50
 
55
51
  class << self
56
52
  # Returns the translated label for a content name.
@@ -72,7 +68,7 @@ module Alchemy
72
68
  Alchemy.t(
73
69
  content_name,
74
70
  scope: "content_names.#{element_name}",
75
- default: Alchemy.t("content_names.#{content_name}", default: content_name.humanize)
71
+ default: Alchemy.t("content_names.#{content_name}", default: content_name.humanize),
76
72
  )
77
73
  end
78
74
  end
@@ -99,6 +95,7 @@ module Alchemy
99
95
  # Settings from the elements.yml definition
100
96
  def settings
101
97
  return {} if definition.blank?
98
+
102
99
  @settings ||= definition.fetch(:settings, {})
103
100
  end
104
101
 
@@ -114,12 +111,14 @@ module Alchemy
114
111
 
115
112
  def siblings
116
113
  return [] if !element
114
+
117
115
  element.contents
118
116
  end
119
117
 
120
118
  # Gets the ingredient from essence
121
119
  def ingredient
122
120
  return nil if essence.nil?
121
+
123
122
  essence.ingredient
124
123
  end
125
124
 
@@ -129,7 +128,7 @@ module Alchemy
129
128
  {
130
129
  name: name,
131
130
  value: serialized_ingredient,
132
- link: essence.try(:link)
131
+ link: essence.try(:link),
133
132
  }.delete_if { |_k, v| v.blank? }
134
133
  end
135
134
 
@@ -145,6 +144,7 @@ module Alchemy
145
144
  # Sets the ingredient from essence
146
145
  def ingredient=(value)
147
146
  raise EssenceMissingError if essence.nil?
147
+
148
148
  essence.ingredient = value
149
149
  end
150
150
 
@@ -156,11 +156,12 @@ module Alchemy
156
156
  #
157
157
  def update_essence(params = {})
158
158
  raise EssenceMissingError if essence.nil?
159
+
159
160
  if essence.update(params)
160
- return true
161
+ true
161
162
  else
162
163
  errors.add(:essence, :validation_failed)
163
- return false
164
+ false
164
165
  end
165
166
  end
166
167
 
@@ -169,12 +170,13 @@ module Alchemy
169
170
  end
170
171
 
171
172
  def has_validations?
172
- definition['validate'].present?
173
+ definition["validate"].present?
173
174
  end
174
175
 
175
176
  # Returns a string used as dom id on html elements.
176
177
  def dom_id
177
- return '' if essence.nil?
178
+ return "" if essence.nil?
179
+
178
180
  "#{essence_partial_name}_#{id}"
179
181
  end
180
182
 
@@ -189,7 +191,7 @@ module Alchemy
189
191
 
190
192
  # Returns true if this content should be taken for element preview.
191
193
  def preview_content?
192
- !!definition['as_element_title']
194
+ !!definition["as_element_title"]
193
195
  end
194
196
 
195
197
  # Proxy method that returns the preview text from essence.
@@ -199,7 +201,8 @@ module Alchemy
199
201
  end
200
202
 
201
203
  def essence_partial_name
202
- return '' if essence.nil?
204
+ return "" if essence.nil?
205
+
203
206
  essence.partial_name
204
207
  end
205
208
 
@@ -223,19 +226,11 @@ module Alchemy
223
226
  "has_tinymce" + (has_custom_tinymce_config? ? " #{element.name}_#{name}" : "")
224
227
  end
225
228
 
226
- def editor
227
- @_editor ||= ContentEditor.new(self)
228
- end
229
- delegate :form_field_name, to: :editor
230
- deprecate form_field_name: "use Alchemy::ContentEditor#form_field_name instead", deprecator: Alchemy::Deprecation
231
- delegate :form_field_id, to: :editor
232
- deprecate form_field_id: "use Alchemy::ContentEditor#form_field_id instead", deprecator: Alchemy::Deprecation
233
-
234
229
  # Returns the default value from content definition
235
230
  #
236
231
  # If the value is a symbol it gets passed through i18n
237
232
  # inside the +alchemy.default_content_texts+ scope
238
- def default_text(default)
233
+ def default_value(default = definition[:default])
239
234
  case default
240
235
  when Symbol
241
236
  Alchemy.t(default, scope: :default_content_texts)
@@ -19,7 +19,7 @@ module Alchemy
19
19
  # Returns one element definition by given name.
20
20
  #
21
21
  def definition_by_name(name)
22
- definitions.detect { |d| d['name'] == name }
22
+ definitions.detect { |d| d["name"] == name }
23
23
  end
24
24
 
25
25
  private
@@ -30,21 +30,21 @@ module Alchemy
30
30
  if ::File.exist?(definitions_file_path)
31
31
  ::YAML.safe_load(ERB.new(File.read(definitions_file_path)).result, YAML_WHITELIST_CLASSES, [], true) || []
32
32
  else
33
- raise LoadError, "Could not find elements.yml file! Please run `rails generate alchemy:scaffold`"
33
+ raise LoadError, "Could not find elements.yml file! Please run `rails generate alchemy:install`"
34
34
  end
35
35
  end
36
36
 
37
37
  # Returns the +elements.yml+ file path
38
38
  #
39
39
  def definitions_file_path
40
- Rails.root.join 'config/alchemy/elements.yml'
40
+ Rails.root.join "config/alchemy/elements.yml"
41
41
  end
42
42
  end
43
43
 
44
44
  # The definition of this element.
45
45
  #
46
46
  def definition
47
- if definition = self.class.definitions.detect { |d| d['name'] == name }
47
+ if definition = self.class.definitions.detect { |d| d["name"] == name }
48
48
  definition
49
49
  else
50
50
  log_warning "Could not find element definition for #{name}. Please check your elements.yml file!"
@@ -47,6 +47,7 @@ module Alchemy
47
47
  #
48
48
  def update_contents(contents_attributes)
49
49
  return true if contents_attributes.nil?
50
+
50
51
  contents.each do |content|
51
52
  content_hash = contents_attributes[content.id.to_s] || next
52
53
  content.update_essence(content_hash) || errors.add(:base, :essence_validation_failed)
@@ -72,7 +73,7 @@ module Alchemy
72
73
  # rss_title: true
73
74
  #
74
75
  def content_for_rss_title
75
- content_for_rss_meta('title')
76
+ content_for_rss_meta("title")
76
77
  end
77
78
 
78
79
  # Returns the content that is marked as rss description.
@@ -86,13 +87,14 @@ module Alchemy
86
87
  # rss_description: true
87
88
  #
88
89
  def content_for_rss_description
89
- content_for_rss_meta('description')
90
+ content_for_rss_meta("description")
90
91
  end
91
92
 
92
93
  # Returns the array with the hashes for all element contents in the elements.yml file
93
94
  def content_definitions
94
95
  return nil if definition.blank?
95
- definition['contents']
96
+
97
+ definition["contents"]
96
98
  end
97
99
 
98
100
  # Returns the definition for given content_name
@@ -101,7 +103,7 @@ module Alchemy
101
103
  log_warning "Element #{name} is missing the content definition for #{content_name}"
102
104
  nil
103
105
  else
104
- content_definitions.detect { |d| d['name'] == content_name.to_s }
106
+ content_definitions.detect { |d| d["name"] == content_name.to_s }
105
107
  end
106
108
  end
107
109
 
@@ -136,12 +138,13 @@ module Alchemy
136
138
  def content_for_rss_meta(type)
137
139
  definition = content_definitions.detect { |c| c["rss_#{type}"] }
138
140
  return if definition.blank?
139
- contents.detect { |content| content.name == definition['name'] }
141
+
142
+ contents.detect { |content| content.name == definition["name"] }
140
143
  end
141
144
 
142
145
  # creates the contents for this element as described in the elements.yml
143
146
  def create_contents
144
- definition.fetch('contents', []).each do |attributes|
147
+ definition.fetch("contents", []).each do |attributes|
145
148
  Content.create(attributes.merge(element: self))
146
149
  end
147
150
  end
@@ -6,6 +6,7 @@ module Alchemy
6
6
  def ingredient(name)
7
7
  content = content_by_name(name)
8
8
  return nil if content.blank?
9
+
9
10
  content.ingredient
10
11
  end
11
12
 
@@ -96,12 +97,12 @@ module Alchemy
96
97
  errors.each do |error|
97
98
  messages << Alchemy.t(
98
99
  "#{name}.#{content_name}.#{error}",
99
- scope: 'content_validations',
100
+ scope: "content_validations",
100
101
  default: [
101
102
  "fields.#{content_name}.#{error}".to_sym,
102
- "errors.#{error}".to_sym
103
+ "errors.#{error}".to_sym,
103
104
  ],
104
- field: Content.translated_label_for(content_name, name)
105
+ field: Content.translated_label_for(content_name, name),
105
106
  )
106
107
  end
107
108
  end
@@ -23,7 +23,7 @@ module Alchemy
23
23
  # If no translation is found a humanized name is used.
24
24
  #
25
25
  def display_name_for(name)
26
- Alchemy.t(name, scope: 'element_names', default: name.to_s.humanize)
26
+ Alchemy.t(name, scope: "element_names", default: name.to_s.humanize)
27
27
  end
28
28
  end
29
29
 
@@ -32,7 +32,7 @@ module Alchemy
32
32
  # @see Alchemy::Element::Presenters#display_name_for
33
33
  #
34
34
  def display_name
35
- self.class.display_name_for(definition['name'] || name)
35
+ self.class.display_name_for(definition["name"] || name)
36
36
  end
37
37
 
38
38
  # Returns a preview text for element.
@@ -97,6 +97,7 @@ module Alchemy
97
97
 
98
98
  def preview_text_from_nested_elements(maxlength)
99
99
  return if all_nested_elements.empty?
100
+
100
101
  all_nested_elements.first.preview_text(maxlength)
101
102
  end
102
103
 
@@ -22,6 +22,8 @@
22
22
 
23
23
  module Alchemy
24
24
  class Element < BaseRecord
25
+ NAME_REGEXP = /\A[a-z0-9_-]+\z/
26
+
25
27
  include Alchemy::Logger
26
28
  include Alchemy::Taggable
27
29
  include Alchemy::Hints
@@ -34,7 +36,7 @@ module Alchemy
34
36
  "hint",
35
37
  "taggable",
36
38
  "compact",
37
- "message"
39
+ "message",
38
40
  ].freeze
39
41
 
40
42
  SKIPPED_ATTRIBUTES_ON_COPY = [
@@ -45,7 +47,7 @@ module Alchemy
45
47
  "folded",
46
48
  "position",
47
49
  "updated_at",
48
- "updater_id"
50
+ "updater_id",
49
51
  ].freeze
50
52
 
51
53
  # All Elements that share the same page id and parent element id and are fixed or not are considered a list.
@@ -58,19 +60,19 @@ module Alchemy
58
60
  #
59
61
  acts_as_list scope: [:page_id, :fixed, :parent_element_id]
60
62
 
61
- stampable stamper_class_name: Alchemy.user_class.name
63
+ stampable stamper_class_name: Alchemy.user_class_name
62
64
 
63
- has_many :contents, -> { order(:position) }, dependent: :destroy, inverse_of: :element
65
+ has_many :contents, dependent: :destroy, inverse_of: :element
64
66
 
65
67
  has_many :all_nested_elements,
66
68
  -> { order(:position).not_trashed },
67
- class_name: 'Alchemy::Element',
69
+ class_name: "Alchemy::Element",
68
70
  foreign_key: :parent_element_id,
69
71
  dependent: :destroy
70
72
 
71
73
  has_many :nested_elements,
72
74
  -> { order(:position).available },
73
- class_name: 'Alchemy::Element',
75
+ class_name: "Alchemy::Element",
74
76
  foreign_key: :parent_element_id,
75
77
  dependent: :destroy,
76
78
  inverse_of: :parent_element
@@ -79,17 +81,17 @@ module Alchemy
79
81
 
80
82
  # A nested element belongs to a parent element.
81
83
  belongs_to :parent_element,
82
- class_name: 'Alchemy::Element',
84
+ class_name: "Alchemy::Element",
83
85
  optional: true,
84
86
  touch: true,
85
87
  inverse_of: :nested_elements
86
88
 
87
89
  has_and_belongs_to_many :touchable_pages, -> { distinct },
88
- class_name: 'Alchemy::Page',
90
+ class_name: "Alchemy::Page",
89
91
  join_table: ElementToPage.table_name
90
92
 
91
93
  validates_presence_of :name, on: :create
92
- validates_format_of :name, on: :create, with: /\A[a-z0-9_-]+\z/
94
+ validates_format_of :name, on: :create, with: NAME_REGEXP
93
95
 
94
96
  attr_accessor :autogenerate_contents
95
97
  attr_accessor :autogenerate_nested_elements
@@ -98,19 +100,19 @@ module Alchemy
98
100
 
99
101
  after_update :touch_touchable_pages
100
102
 
101
- scope :trashed, -> { where(position: nil).order('updated_at DESC') }
102
- scope :not_trashed, -> { where.not(position: nil) }
103
- scope :published, -> { where(public: true) }
104
- scope :not_restricted, -> { joins(:page).merge(Page.not_restricted) }
105
- scope :available, -> { published.not_trashed }
106
- scope :named, ->(names) { where(name: names) }
107
- scope :excluded, ->(names) { where.not(name: names) }
108
- scope :fixed, -> { where(fixed: true) }
109
- scope :unfixed, -> { where(fixed: false) }
110
- scope :from_current_site, -> { where(Language.table_name => {site_id: Site.current || Site.default}).joins(page: 'language') }
111
- scope :folded, -> { where(folded: true) }
112
- scope :expanded, -> { where(folded: false) }
113
- scope :not_nested, -> { where(parent_element_id: nil) }
103
+ scope :trashed, -> { where(position: nil).order("updated_at DESC") }
104
+ scope :not_trashed, -> { where.not(position: nil) }
105
+ scope :published, -> { where(public: true) }
106
+ scope :not_restricted, -> { joins(:page).merge(Page.not_restricted) }
107
+ scope :available, -> { published.not_trashed }
108
+ scope :named, ->(names) { where(name: names) }
109
+ scope :excluded, ->(names) { where.not(name: names) }
110
+ scope :fixed, -> { where(fixed: true) }
111
+ scope :unfixed, -> { where(fixed: false) }
112
+ scope :from_current_site, -> { where(Language.table_name => { site_id: Site.current || Site.default }).joins(page: "language") }
113
+ scope :folded, -> { where(folded: true) }
114
+ scope :expanded, -> { where(folded: false) }
115
+ scope :not_nested, -> { where(parent_element_id: nil) }
114
116
 
115
117
  delegate :restricted?, to: :page, allow_nil: true
116
118
 
@@ -131,7 +133,8 @@ module Alchemy
131
133
  #
132
134
  def new(attributes = {})
133
135
  return super if attributes[:name].blank?
134
- element_attributes = attributes.to_h.merge(name: attributes[:name].split('#').first)
136
+
137
+ element_attributes = attributes.to_h.merge(name: attributes[:name].split("#").first)
135
138
  element_definition = Element.definition_by_name(element_attributes[:name])
136
139
  if element_definition.nil?
137
140
  raise(ElementDefinitionError, attributes)
@@ -139,11 +142,6 @@ module Alchemy
139
142
 
140
143
  super(element_definition.merge(element_attributes).except(*FORBIDDEN_DEFINITION_ATTRIBUTES))
141
144
  end
142
- alias_method :new_from_scratch, :new
143
- deprecate new_from_scratch: :new, deprecator: Alchemy::Deprecation
144
-
145
- alias_method :create_from_scratch, :create
146
- deprecate create_from_scratch: :create, deprecator: Alchemy::Deprecation
147
145
 
148
146
  # This methods does a copy of source and all depending contents and all of their depending essences.
149
147
  #
@@ -158,13 +156,13 @@ module Alchemy
158
156
  #
159
157
  def copy(source_element, differences = {})
160
158
  attributes = source_element.attributes.with_indifferent_access
161
- .except(*SKIPPED_ATTRIBUTES_ON_COPY)
162
- .merge(differences)
163
- .merge({
164
- autogenerate_contents: false,
165
- autogenerate_nested_elements: false,
166
- tag_list: source_element.tag_list
167
- })
159
+ .except(*SKIPPED_ATTRIBUTES_ON_COPY)
160
+ .merge(differences)
161
+ .merge({
162
+ autogenerate_contents: false,
163
+ autogenerate_nested_elements: false,
164
+ tag_list: source_element.tag_list,
165
+ })
168
166
 
169
167
  new_element = create!(attributes)
170
168
 
@@ -181,13 +179,15 @@ module Alchemy
181
179
 
182
180
  def all_from_clipboard(clipboard)
183
181
  return [] if clipboard.nil?
184
- where(id: clipboard.collect { |e| e['id'] })
182
+
183
+ where(id: clipboard.collect { |e| e["id"] })
185
184
  end
186
185
 
187
186
  # All elements in clipboard that could be placed on page
188
187
  #
189
188
  def all_from_clipboard_for_page(clipboard, page)
190
189
  return [] if clipboard.nil? || page.nil?
190
+
191
191
  all_from_clipboard(clipboard).select { |ce|
192
192
  page.available_element_names.include?(ce.name)
193
193
  }
@@ -199,7 +199,7 @@ module Alchemy
199
199
  # Pass an element name to get next of this kind.
200
200
  #
201
201
  def next(name = nil)
202
- elements = page.elements.published.where('position > ?', position)
202
+ elements = page.elements.published.where("position > ?", position)
203
203
  select_element(elements, name, :asc)
204
204
  end
205
205
 
@@ -208,13 +208,14 @@ module Alchemy
208
208
  # Pass an element name to get previous of this kind.
209
209
  #
210
210
  def prev(name = nil)
211
- elements = page.elements.published.where('position < ?', position)
211
+ elements = page.elements.published.where("position < ?", position)
212
212
  select_element(elements, name, :desc)
213
213
  end
214
214
 
215
215
  # Stores the page into +touchable_pages+ (Pages that have to be touched after updating the element).
216
216
  def store_page(page)
217
217
  return true if page.nil?
218
+
218
219
  unless touchable_pages.include? page
219
220
  touchable_pages << page
220
221
  end
@@ -233,7 +234,7 @@ module Alchemy
233
234
 
234
235
  # Returns true if the definition of this element has a taggable true value.
235
236
  def taggable?
236
- definition['taggable'] == true
237
+ definition["taggable"] == true
237
238
  end
238
239
 
239
240
  # The opposite of folded?
@@ -243,7 +244,7 @@ module Alchemy
243
244
 
244
245
  # Defined as compact element?
245
246
  def compact?
246
- definition['compact'] == true
247
+ definition["compact"] == true
247
248
  end
248
249
 
249
250
  # The element's view partial is dependent from its name
@@ -261,17 +262,7 @@ module Alchemy
261
262
  # Element partials live in +app/views/alchemy/elements+
262
263
  #
263
264
  def to_partial_path
264
- if Alchemy::LOOKUP_CONTEXT.exists?("#{name}_view", ["elements"], true)
265
- Alchemy::Deprecation.warn <<~WARN
266
- Having the `_view` suffix on your element view partials is deprecated
267
- and will not be supported in Alchemy 5.0 anymore. You can safely remove the suffix now.
268
-
269
- Please also rename the local `element` or `#{name}_view` variable into `#{name}`.
270
- WARN
271
- "alchemy/elements/#{name}_view"
272
- else
273
- "alchemy/elements/#{name}"
274
- end
265
+ "alchemy/elements/#{name}"
275
266
  end
276
267
 
277
268
  # Returns the key that's taken for cache path.
@@ -290,7 +281,7 @@ module Alchemy
290
281
 
291
282
  # A collection of element names that can be nested inside this element.
292
283
  def nestable_elements
293
- definition.fetch('nestable_elements', [])
284
+ definition.fetch("nestable_elements", [])
294
285
  end
295
286
 
296
287
  # Copy all nested elements from current element to given target element.
@@ -298,7 +289,7 @@ module Alchemy
298
289
  nested_elements.map do |nested_element|
299
290
  Element.copy(nested_element, {
300
291
  parent_element_id: target_element.id,
301
- page_id: target_element.page_id
292
+ page_id: target_element.page_id,
302
293
  })
303
294
  end
304
295
  end
@@ -306,7 +297,7 @@ module Alchemy
306
297
  private
307
298
 
308
299
  def generate_nested_elements
309
- definition.fetch('autogenerate', []).each do |nestable_element|
300
+ definition.fetch("autogenerate", []).each do |nestable_element|
310
301
  if nestable_elements.include?(nestable_element)
311
302
  Element.create(page: page, parent_element_id: id, name: nestable_element)
312
303
  else
@@ -326,6 +317,7 @@ module Alchemy
326
317
  #
327
318
  def touch_touchable_pages
328
319
  return unless respond_to?(:touchable_pages)
320
+
329
321
  touchable_pages.each(&:touch)
330
322
  end
331
323
  end
@@ -3,7 +3,7 @@
3
3
  module Alchemy
4
4
  class ElementToPage
5
5
  def self.table_name
6
- [Alchemy::Element.table_name, Alchemy::Page.table_name].join('_')
6
+ [Alchemy::Element.table_name, Alchemy::Page.table_name].join("_")
7
7
  end
8
8
  end
9
9
  end
@@ -8,14 +8,12 @@
8
8
  # value :boolean
9
9
  # created_at :datetime not null
10
10
  # updated_at :datetime not null
11
- # creator_id :integer
12
- # updater_id :integer
13
11
  #
14
12
 
15
13
  # Stores boolean values.
16
14
  # Provides a checkbox in the editor views.
17
15
  module Alchemy
18
16
  class EssenceBoolean < BaseRecord
19
- acts_as_essence ingredient_column: 'value'
17
+ acts_as_essence ingredient_column: "value"
20
18
  end
21
19
  end
@@ -6,19 +6,18 @@
6
6
  #
7
7
  # id :integer not null, primary key
8
8
  # date :datetime
9
- # creator_id :integer
10
- # updater_id :integer
11
9
  # created_at :datetime not null
12
10
  # updated_at :datetime not null
13
11
  #
14
12
 
15
13
  module Alchemy
16
14
  class EssenceDate < BaseRecord
17
- acts_as_essence ingredient_column: 'date'
15
+ acts_as_essence ingredient_column: "date"
18
16
 
19
17
  # Returns self.date for the Element#preview_text method.
20
18
  def preview_text(_maxlength = nil)
21
19
  return "" if date.blank?
20
+
22
21
  ::I18n.l(date, format: :'alchemy.essence_date')
23
22
  end
24
23
  end
@@ -8,8 +8,6 @@
8
8
  # attachment_id :integer
9
9
  # title :string
10
10
  # css_class :string
11
- # creator_id :integer
12
- # updater_id :integer
13
11
  # created_at :datetime not null
14
12
  # updated_at :datetime not null
15
13
  # link_text :string
@@ -18,19 +16,21 @@
18
16
  module Alchemy
19
17
  class EssenceFile < BaseRecord
20
18
  belongs_to :attachment, optional: true
21
- acts_as_essence ingredient_column: 'attachment'
19
+ acts_as_essence ingredient_column: "attachment"
22
20
 
23
21
  def attachment_url
24
22
  return if attachment.nil?
23
+
25
24
  routes.download_attachment_path(
26
25
  id: attachment.id,
27
26
  name: attachment.urlname,
28
- format: attachment.suffix
27
+ format: attachment.suffix,
29
28
  )
30
29
  end
31
30
 
32
31
  def preview_text(max = 30)
33
32
  return "" if attachment.blank?
33
+
34
34
  attachment.name.to_s[0..max - 1]
35
35
  end
36
36
 
@@ -6,15 +6,13 @@
6
6
  #
7
7
  # id :integer not null, primary key
8
8
  # source :text
9
- # creator_id :integer
10
- # updater_id :integer
11
9
  # created_at :datetime not null
12
10
  # updated_at :datetime not null
13
11
  #
14
12
 
15
13
  module Alchemy
16
14
  class EssenceHtml < BaseRecord
17
- acts_as_essence ingredient_column: 'source'
15
+ acts_as_essence ingredient_column: "source"
18
16
 
19
17
  # Returns the first x (default = 30) (HTML escaped) characters from self.source for the Element#preview_text method.
20
18
  def preview_text(maxlength = 30)
@@ -11,12 +11,10 @@
11
11
  # link_class_name :string
12
12
  # created_at :datetime not null
13
13
  # updated_at :datetime not null
14
- # creator_id :integer
15
- # updater_id :integer
16
14
  #
17
15
 
18
16
  module Alchemy
19
17
  class EssenceLink < BaseRecord
20
- acts_as_essence ingredient_column: 'link'
18
+ acts_as_essence ingredient_column: "link"
21
19
  end
22
20
  end