lc_alchemy_cms 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (744) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +23 -0
  3. data/.gitignore +21 -0
  4. data/.hound.yml +2 -0
  5. data/.rspec +1 -0
  6. data/.rubocop.yml +861 -0
  7. data/.teatro.yml +7 -0
  8. data/.travis.yml +27 -0
  9. data/.yardopts +5 -0
  10. data/CODE_OF_CONDUCT.md +13 -0
  11. data/CONTRIBUTING.md +73 -0
  12. data/Gemfile +34 -0
  13. data/LICENSE +27 -0
  14. data/README.md +297 -0
  15. data/Rakefile +48 -0
  16. data/alchemy_cms.gemspec +81 -0
  17. data/app/assets/fonts/alchemy/icons.eot +0 -0
  18. data/app/assets/fonts/alchemy/icons.svg +71 -0
  19. data/app/assets/fonts/alchemy/icons.ttf +0 -0
  20. data/app/assets/fonts/alchemy/icons.woff +0 -0
  21. data/app/assets/images/alchemy/alchemy-logo.svg +70 -0
  22. data/app/assets/images/alchemy/favicon.ico +0 -0
  23. data/app/assets/images/alchemy/icon.svg +14 -0
  24. data/app/assets/images/alchemy/icons.png +0 -0
  25. data/app/assets/images/alchemy/lupe.cur +0 -0
  26. data/app/assets/images/alchemy/ui-icons_666666_256x240.png +0 -0
  27. data/app/assets/images/sassy-ie-overlay.png +0 -0
  28. data/app/assets/javascripts/alchemy/alchemy.autocomplete.js.coffee +30 -0
  29. data/app/assets/javascripts/alchemy/alchemy.base.js.coffee +142 -0
  30. data/app/assets/javascripts/alchemy/alchemy.browser.js.coffee +22 -0
  31. data/app/assets/javascripts/alchemy/alchemy.buttons.js.coffee +32 -0
  32. data/app/assets/javascripts/alchemy/alchemy.char_counter.js.coffee +19 -0
  33. data/app/assets/javascripts/alchemy/alchemy.confirm_dialog.js.coffee +85 -0
  34. data/app/assets/javascripts/alchemy/alchemy.custom.js +1 -0
  35. data/app/assets/javascripts/alchemy/alchemy.datepicker.js.coffee +31 -0
  36. data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +266 -0
  37. data/app/assets/javascripts/alchemy/alchemy.dirty.js.coffee +70 -0
  38. data/app/assets/javascripts/alchemy/alchemy.dragndrop.js.coffee +84 -0
  39. data/app/assets/javascripts/alchemy/alchemy.element_editors.js.coffee +138 -0
  40. data/app/assets/javascripts/alchemy/alchemy.elements_window.js.coffee +89 -0
  41. data/app/assets/javascripts/alchemy/alchemy.file_progress.js.coffee +63 -0
  42. data/app/assets/javascripts/alchemy/alchemy.growler.js.coffee +27 -0
  43. data/app/assets/javascripts/alchemy/alchemy.gui.js.coffee +22 -0
  44. data/app/assets/javascripts/alchemy/alchemy.hotkeys.js.coffee +49 -0
  45. data/app/assets/javascripts/alchemy/alchemy.html5.js +22 -0
  46. data/app/assets/javascripts/alchemy/alchemy.i18n.js.coffee +26 -0
  47. data/app/assets/javascripts/alchemy/alchemy.image_cropper.js.coffee +44 -0
  48. data/app/assets/javascripts/alchemy/alchemy.initializer.js.coffee +63 -0
  49. data/app/assets/javascripts/alchemy/alchemy.jquery_loader.js +42 -0
  50. data/app/assets/javascripts/alchemy/alchemy.js +52 -0
  51. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +250 -0
  52. data/app/assets/javascripts/alchemy/alchemy.list_filter.js.coffee +49 -0
  53. data/app/assets/javascripts/alchemy/alchemy.page_sorter.js +48 -0
  54. data/app/assets/javascripts/alchemy/alchemy.preview.js.coffee +106 -0
  55. data/app/assets/javascripts/alchemy/alchemy.preview_window.js.coffee +58 -0
  56. data/app/assets/javascripts/alchemy/alchemy.sitemap.js.coffee +50 -0
  57. data/app/assets/javascripts/alchemy/alchemy.spinner.js.coffee +49 -0
  58. data/app/assets/javascripts/alchemy/alchemy.string_extension.js.coffee +11 -0
  59. data/app/assets/javascripts/alchemy/alchemy.tinymce.js.coffee +66 -0
  60. data/app/assets/javascripts/alchemy/alchemy.translations.js.coffee +132 -0
  61. data/app/assets/javascripts/alchemy/alchemy.uploader.js.coffee +102 -0
  62. data/app/assets/javascripts/alchemy/alchemy.windows.js.coffee +42 -0
  63. data/app/assets/javascripts/alchemy/menubar.js.coffee +8 -0
  64. data/app/assets/javascripts/alchemy/preview.js +1 -0
  65. data/app/assets/javascripts/tinymce/plugins/alchemy_link/plugin.min.js +19 -0
  66. data/app/assets/stylesheets/alchemy/_defaults.scss +8 -0
  67. data/app/assets/stylesheets/alchemy/_extends.scss +93 -0
  68. data/app/assets/stylesheets/alchemy/_mixins.scss +112 -0
  69. data/app/assets/stylesheets/alchemy/_variables.scss +61 -0
  70. data/app/assets/stylesheets/alchemy/admin.scss +31 -0
  71. data/app/assets/stylesheets/alchemy/archive.scss +436 -0
  72. data/app/assets/stylesheets/alchemy/base.scss +609 -0
  73. data/app/assets/stylesheets/alchemy/buttons.scss +259 -0
  74. data/app/assets/stylesheets/alchemy/custom.scss +1 -0
  75. data/app/assets/stylesheets/alchemy/dashboard.scss +104 -0
  76. data/app/assets/stylesheets/alchemy/dialogs.scss +214 -0
  77. data/app/assets/stylesheets/alchemy/elements.scss +772 -0
  78. data/app/assets/stylesheets/alchemy/errors.scss +39 -0
  79. data/app/assets/stylesheets/alchemy/flash.scss +65 -0
  80. data/app/assets/stylesheets/alchemy/form_fields.scss +89 -0
  81. data/app/assets/stylesheets/alchemy/forms.scss +193 -0
  82. data/app/assets/stylesheets/alchemy/frame.scss +301 -0
  83. data/app/assets/stylesheets/alchemy/icon-font.scss +67 -0
  84. data/app/assets/stylesheets/alchemy/icons.scss +324 -0
  85. data/app/assets/stylesheets/alchemy/jquery-ui.scss +1511 -0
  86. data/app/assets/stylesheets/alchemy/menubar.scss +81 -0
  87. data/app/assets/stylesheets/alchemy/modules.scss +33 -0
  88. data/app/assets/stylesheets/alchemy/notices.scss +64 -0
  89. data/app/assets/stylesheets/alchemy/pagination.scss +65 -0
  90. data/app/assets/stylesheets/alchemy/print.scss +34 -0
  91. data/app/assets/stylesheets/alchemy/search.scss +73 -0
  92. data/app/assets/stylesheets/alchemy/selects.scss +235 -0
  93. data/app/assets/stylesheets/alchemy/sitemap.scss +385 -0
  94. data/app/assets/stylesheets/alchemy/tables.scss +218 -0
  95. data/app/assets/stylesheets/alchemy/toolbar.scss +146 -0
  96. data/app/assets/stylesheets/alchemy/upload.scss +121 -0
  97. data/app/assets/stylesheets/tinymce/skins/alchemy/content.min.css.scss +90 -0
  98. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/readme.md +1 -0
  99. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.eot +0 -0
  100. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.svg +175 -0
  101. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.ttf +0 -0
  102. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.woff +0 -0
  103. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.eot +0 -0
  104. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.svg +153 -0
  105. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.ttf +0 -0
  106. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.woff +0 -0
  107. data/app/assets/stylesheets/tinymce/skins/alchemy/img/anchor.gif +0 -0
  108. data/app/assets/stylesheets/tinymce/skins/alchemy/img/loader.gif +0 -0
  109. data/app/assets/stylesheets/tinymce/skins/alchemy/img/object.gif +0 -0
  110. data/app/assets/stylesheets/tinymce/skins/alchemy/img/trans.gif +0 -0
  111. data/app/assets/stylesheets/tinymce/skins/alchemy/img/wline.gif +0 -0
  112. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.ie7.min.css +1 -0
  113. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +1810 -0
  114. data/app/controllers/alchemy/admin/attachments_controller.rb +106 -0
  115. data/app/controllers/alchemy/admin/base_controller.rb +168 -0
  116. data/app/controllers/alchemy/admin/clipboard_controller.rb +51 -0
  117. data/app/controllers/alchemy/admin/contents_controller.rb +76 -0
  118. data/app/controllers/alchemy/admin/dashboard_controller.rb +89 -0
  119. data/app/controllers/alchemy/admin/elements_controller.rb +190 -0
  120. data/app/controllers/alchemy/admin/essence_files_controller.rb +47 -0
  121. data/app/controllers/alchemy/admin/essence_pictures_controller.rb +120 -0
  122. data/app/controllers/alchemy/admin/languages_controller.rb +17 -0
  123. data/app/controllers/alchemy/admin/layoutpages_controller.rb +19 -0
  124. data/app/controllers/alchemy/admin/legacy_page_urls_controller.rb +39 -0
  125. data/app/controllers/alchemy/admin/pages_controller.rb +359 -0
  126. data/app/controllers/alchemy/admin/pictures_controller.rb +168 -0
  127. data/app/controllers/alchemy/admin/resources_controller.rb +185 -0
  128. data/app/controllers/alchemy/admin/sites_controller.rb +6 -0
  129. data/app/controllers/alchemy/admin/tags_controller.rb +76 -0
  130. data/app/controllers/alchemy/admin/trash_controller.rb +27 -0
  131. data/app/controllers/alchemy/api/base_controller.rb +19 -0
  132. data/app/controllers/alchemy/api/contents_controller.rb +35 -0
  133. data/app/controllers/alchemy/api/elements_controller.rb +29 -0
  134. data/app/controllers/alchemy/api/pages_controller.rb +32 -0
  135. data/app/controllers/alchemy/attachments_controller.rb +35 -0
  136. data/app/controllers/alchemy/base_controller.rb +106 -0
  137. data/app/controllers/alchemy/elements_controller.rb +27 -0
  138. data/app/controllers/alchemy/messages_controller.rb +114 -0
  139. data/app/controllers/alchemy/pages_controller.rb +211 -0
  140. data/app/controllers/alchemy/pictures_controller.rb +82 -0
  141. data/app/helpers/alchemy/admin/attachments_helper.rb +12 -0
  142. data/app/helpers/alchemy/admin/base_helper.rb +471 -0
  143. data/app/helpers/alchemy/admin/contents_helper.rb +113 -0
  144. data/app/helpers/alchemy/admin/elements_helper.rb +134 -0
  145. data/app/helpers/alchemy/admin/essences_helper.rb +120 -0
  146. data/app/helpers/alchemy/admin/form_helper.rb +30 -0
  147. data/app/helpers/alchemy/admin/navigation_helper.rb +238 -0
  148. data/app/helpers/alchemy/admin/pages_helper.rb +70 -0
  149. data/app/helpers/alchemy/admin/pictures_helper.rb +30 -0
  150. data/app/helpers/alchemy/admin/tags_helper.rb +102 -0
  151. data/app/helpers/alchemy/base_helper.rb +81 -0
  152. data/app/helpers/alchemy/elements_block_helper.rb +162 -0
  153. data/app/helpers/alchemy/elements_helper.rb +291 -0
  154. data/app/helpers/alchemy/essences_helper.rb +138 -0
  155. data/app/helpers/alchemy/pages_helper.rb +417 -0
  156. data/app/helpers/alchemy/url_helper.rb +76 -0
  157. data/app/mailers/alchemy/messages.rb +15 -0
  158. data/app/models/alchemy.rb +7 -0
  159. data/app/models/alchemy/attachment.rb +129 -0
  160. data/app/models/alchemy/cell.rb +94 -0
  161. data/app/models/alchemy/content.rb +255 -0
  162. data/app/models/alchemy/content/factory.rb +190 -0
  163. data/app/models/alchemy/element.rb +513 -0
  164. data/app/models/alchemy/element/definitions.rb +52 -0
  165. data/app/models/alchemy/element/presenters.rb +87 -0
  166. data/app/models/alchemy/element_to_page.rb +7 -0
  167. data/app/models/alchemy/essence_boolean.rb +19 -0
  168. data/app/models/alchemy/essence_date.rb +24 -0
  169. data/app/models/alchemy/essence_file.rb +42 -0
  170. data/app/models/alchemy/essence_html.rb +23 -0
  171. data/app/models/alchemy/essence_link.rb +20 -0
  172. data/app/models/alchemy/essence_picture.rb +152 -0
  173. data/app/models/alchemy/essence_richtext.rb +47 -0
  174. data/app/models/alchemy/essence_select.rb +18 -0
  175. data/app/models/alchemy/essence_text.rb +22 -0
  176. data/app/models/alchemy/folded_page.rb +16 -0
  177. data/app/models/alchemy/language.rb +144 -0
  178. data/app/models/alchemy/language/code.rb +22 -0
  179. data/app/models/alchemy/legacy_page_url.rb +20 -0
  180. data/app/models/alchemy/message.rb +40 -0
  181. data/app/models/alchemy/page.rb +409 -0
  182. data/app/models/alchemy/page/page_cells.rb +71 -0
  183. data/app/models/alchemy/page/page_elements.rb +272 -0
  184. data/app/models/alchemy/page/page_naming.rb +122 -0
  185. data/app/models/alchemy/page/page_natures.rb +114 -0
  186. data/app/models/alchemy/page/page_scopes.rb +95 -0
  187. data/app/models/alchemy/page/page_users.rb +58 -0
  188. data/app/models/alchemy/picture.rb +220 -0
  189. data/app/models/alchemy/picture/sweeping.rb +17 -0
  190. data/app/models/alchemy/picture/transformations.rb +256 -0
  191. data/app/models/alchemy/site.rb +91 -0
  192. data/app/models/alchemy/site/layout.rb +38 -0
  193. data/app/models/alchemy/tag.rb +24 -0
  194. data/app/models/alchemy/translations.rb +7 -0
  195. data/app/models/alchemy/translations/essence_body_updater.rb +64 -0
  196. data/app/models/alchemy/translations/translation_pusher.rb +18 -0
  197. data/app/models/alchemy/tree_node.rb +4 -0
  198. data/app/serializers/alchemy/attachment_serializer.rb +15 -0
  199. data/app/serializers/alchemy/cell_serializer.rb +18 -0
  200. data/app/serializers/alchemy/content_serializer.rb +20 -0
  201. data/app/serializers/alchemy/element_serializer.rb +20 -0
  202. data/app/serializers/alchemy/essence_boolean_serializer.rb +11 -0
  203. data/app/serializers/alchemy/essence_date_serializer.rb +11 -0
  204. data/app/serializers/alchemy/essence_file_serializer.rb +12 -0
  205. data/app/serializers/alchemy/essence_html_serializer.rb +11 -0
  206. data/app/serializers/alchemy/essence_link_serializer.rb +14 -0
  207. data/app/serializers/alchemy/essence_picture_serializer.rb +28 -0
  208. data/app/serializers/alchemy/essence_richtext_serializer.rb +12 -0
  209. data/app/serializers/alchemy/essence_select_serializer.rb +11 -0
  210. data/app/serializers/alchemy/essence_text_serializer.rb +22 -0
  211. data/app/serializers/alchemy/legacy_element_serializer.rb +17 -0
  212. data/app/serializers/alchemy/page_serializer.rb +29 -0
  213. data/app/serializers/alchemy/picture_serializer.rb +16 -0
  214. data/app/views/alchemy/_menubar.html.erb +16 -0
  215. data/app/views/alchemy/admin/attachments/_archive_overlay.html.erb +32 -0
  216. data/app/views/alchemy/admin/attachments/_attachment.html.erb +63 -0
  217. data/app/views/alchemy/admin/attachments/_file_to_assign.html.erb +15 -0
  218. data/app/views/alchemy/admin/attachments/_files_list.html.erb +39 -0
  219. data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +11 -0
  220. data/app/views/alchemy/admin/attachments/_tag_list.html.erb +14 -0
  221. data/app/views/alchemy/admin/attachments/archive_overlay.js.erb +7 -0
  222. data/app/views/alchemy/admin/attachments/create.js.erb +11 -0
  223. data/app/views/alchemy/admin/attachments/destroy.js.erb +1 -0
  224. data/app/views/alchemy/admin/attachments/edit.html.erb +10 -0
  225. data/app/views/alchemy/admin/attachments/index.html.erb +29 -0
  226. data/app/views/alchemy/admin/attachments/new.html.erb +14 -0
  227. data/app/views/alchemy/admin/attachments/show.html.erb +3 -0
  228. data/app/views/alchemy/admin/clipboard/clear.js.erb +3 -0
  229. data/app/views/alchemy/admin/clipboard/index.html.erb +22 -0
  230. data/app/views/alchemy/admin/clipboard/insert.js.erb +19 -0
  231. data/app/views/alchemy/admin/clipboard/remove.js.erb +10 -0
  232. data/app/views/alchemy/admin/contents/_missing.html.erb +19 -0
  233. data/app/views/alchemy/admin/contents/create.js.erb +56 -0
  234. data/app/views/alchemy/admin/contents/destroy.js.erb +4 -0
  235. data/app/views/alchemy/admin/contents/new.html.erb +11 -0
  236. data/app/views/alchemy/admin/contents/order.js.erb +3 -0
  237. data/app/views/alchemy/admin/dashboard/_locked_pages.html.erb +38 -0
  238. data/app/views/alchemy/admin/dashboard/_recent_pages.html.erb +22 -0
  239. data/app/views/alchemy/admin/dashboard/_sites.html.erb +23 -0
  240. data/app/views/alchemy/admin/dashboard/_users.html.erb +19 -0
  241. data/app/views/alchemy/admin/dashboard/help.html.erb +21 -0
  242. data/app/views/alchemy/admin/dashboard/index.html.erb +44 -0
  243. data/app/views/alchemy/admin/dashboard/info.html.erb +64 -0
  244. data/app/views/alchemy/admin/elements/_add_picture.html.erb +14 -0
  245. data/app/views/alchemy/admin/elements/_element.html.erb +23 -0
  246. data/app/views/alchemy/admin/elements/_element_foot.html.erb +36 -0
  247. data/app/views/alchemy/admin/elements/_element_head.html.erb +23 -0
  248. data/app/views/alchemy/admin/elements/_new_element_form.html.erb +26 -0
  249. data/app/views/alchemy/admin/elements/_picture_gallery_editor.html.erb +24 -0
  250. data/app/views/alchemy/admin/elements/_refresh_editor.js.erb +8 -0
  251. data/app/views/alchemy/admin/elements/create.js.erb +46 -0
  252. data/app/views/alchemy/admin/elements/fold.js.erb +28 -0
  253. data/app/views/alchemy/admin/elements/index.html.erb +26 -0
  254. data/app/views/alchemy/admin/elements/list.html.erb +16 -0
  255. data/app/views/alchemy/admin/elements/new.html.erb +25 -0
  256. data/app/views/alchemy/admin/elements/order.js.erb +14 -0
  257. data/app/views/alchemy/admin/elements/trash.js.erb +12 -0
  258. data/app/views/alchemy/admin/elements/update.js.erb +28 -0
  259. data/app/views/alchemy/admin/essence_files/assign.js.erb +9 -0
  260. data/app/views/alchemy/admin/essence_files/edit.html.erb +18 -0
  261. data/app/views/alchemy/admin/essence_pictures/assign.js.erb +18 -0
  262. data/app/views/alchemy/admin/essence_pictures/crop.html.erb +50 -0
  263. data/app/views/alchemy/admin/essence_pictures/destroy.js.erb +24 -0
  264. data/app/views/alchemy/admin/essence_pictures/edit.html.erb +28 -0
  265. data/app/views/alchemy/admin/essence_pictures/save_link.js.erb +3 -0
  266. data/app/views/alchemy/admin/essence_pictures/update.js.erb +9 -0
  267. data/app/views/alchemy/admin/languages/_form.html.erb +14 -0
  268. data/app/views/alchemy/admin/languages/_language.html.erb +42 -0
  269. data/app/views/alchemy/admin/languages/_table.html.erb +37 -0
  270. data/app/views/alchemy/admin/languages/index.html.erb +23 -0
  271. data/app/views/alchemy/admin/layoutpages/_layoutpage.html.erb +63 -0
  272. data/app/views/alchemy/admin/layoutpages/edit.html.erb +15 -0
  273. data/app/views/alchemy/admin/layoutpages/index.html.erb +41 -0
  274. data/app/views/alchemy/admin/leave.html.erb +11 -0
  275. data/app/views/alchemy/admin/legacy_page_urls/_form.html.erb +5 -0
  276. data/app/views/alchemy/admin/legacy_page_urls/_label.html.erb +1 -0
  277. data/app/views/alchemy/admin/legacy_page_urls/_legacy_page_url.html.erb +13 -0
  278. data/app/views/alchemy/admin/legacy_page_urls/_new.html.erb +20 -0
  279. data/app/views/alchemy/admin/legacy_page_urls/create.js.erb +10 -0
  280. data/app/views/alchemy/admin/legacy_page_urls/destroy.js.erb +6 -0
  281. data/app/views/alchemy/admin/legacy_page_urls/update.js.erb +2 -0
  282. data/app/views/alchemy/admin/pages/_create_language_form.html.erb +54 -0
  283. data/app/views/alchemy/admin/pages/_external_link.html.erb +31 -0
  284. data/app/views/alchemy/admin/pages/_file_link.html.erb +31 -0
  285. data/app/views/alchemy/admin/pages/_form.html.erb +62 -0
  286. data/app/views/alchemy/admin/pages/_internal_link.html.erb +41 -0
  287. data/app/views/alchemy/admin/pages/_legacy_urls.html.erb +23 -0
  288. data/app/views/alchemy/admin/pages/_locked_page.html.erb +24 -0
  289. data/app/views/alchemy/admin/pages/_new_page_form.html.erb +11 -0
  290. data/app/views/alchemy/admin/pages/_page.html.erb +112 -0
  291. data/app/views/alchemy/admin/pages/_page_for_links.html.erb +45 -0
  292. data/app/views/alchemy/admin/pages/_page_status.html.erb +14 -0
  293. data/app/views/alchemy/admin/pages/_sitemap.html.erb +8 -0
  294. data/app/views/alchemy/admin/pages/_tinymce_custom_config.html.erb +13 -0
  295. data/app/views/alchemy/admin/pages/configure.html.erb +16 -0
  296. data/app/views/alchemy/admin/pages/configure_external.html.erb +33 -0
  297. data/app/views/alchemy/admin/pages/destroy.js.erb +19 -0
  298. data/app/views/alchemy/admin/pages/edit.html.erb +206 -0
  299. data/app/views/alchemy/admin/pages/flush.js.erb +2 -0
  300. data/app/views/alchemy/admin/pages/fold.js.erb +3 -0
  301. data/app/views/alchemy/admin/pages/index.html.erb +101 -0
  302. data/app/views/alchemy/admin/pages/info.html.erb +43 -0
  303. data/app/views/alchemy/admin/pages/link.html.erb +16 -0
  304. data/app/views/alchemy/admin/pages/locked.html.erb +3 -0
  305. data/app/views/alchemy/admin/pages/new.html.erb +26 -0
  306. data/app/views/alchemy/admin/pages/show.html.erb +1 -0
  307. data/app/views/alchemy/admin/pages/sort.js.erb +5 -0
  308. data/app/views/alchemy/admin/pages/unlock.js.erb +8 -0
  309. data/app/views/alchemy/admin/pages/update.js.erb +37 -0
  310. data/app/views/alchemy/admin/partials/_autocomplete_tag_list.html.erb +1 -0
  311. data/app/views/alchemy/admin/partials/_flash.html.erb +4 -0
  312. data/app/views/alchemy/admin/partials/_flash_notices.html.erb +5 -0
  313. data/app/views/alchemy/admin/partials/_language_tree_select.html.erb +11 -0
  314. data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +12 -0
  315. data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +33 -0
  316. data/app/views/alchemy/admin/partials/_routes.html.erb +25 -0
  317. data/app/views/alchemy/admin/partials/_search_form.html.erb +20 -0
  318. data/app/views/alchemy/admin/partials/_sub_navigation.html.erb +8 -0
  319. data/app/views/alchemy/admin/partials/_toolbar_button.html.erb +25 -0
  320. data/app/views/alchemy/admin/partials/_upload_form.html.erb +67 -0
  321. data/app/views/alchemy/admin/pictures/_archive.html.erb +53 -0
  322. data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +14 -0
  323. data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +78 -0
  324. data/app/views/alchemy/admin/pictures/_filter_bar.html.erb +33 -0
  325. data/app/views/alchemy/admin/pictures/_overlay_picture_list.html.erb +11 -0
  326. data/app/views/alchemy/admin/pictures/_picture.html.erb +87 -0
  327. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +28 -0
  328. data/app/views/alchemy/admin/pictures/_tag_list.html.erb +16 -0
  329. data/app/views/alchemy/admin/pictures/archive_overlay.js.erb +8 -0
  330. data/app/views/alchemy/admin/pictures/edit.html.erb +13 -0
  331. data/app/views/alchemy/admin/pictures/edit_multiple.html.erb +30 -0
  332. data/app/views/alchemy/admin/pictures/flush.js.erb +2 -0
  333. data/app/views/alchemy/admin/pictures/index.html.erb +109 -0
  334. data/app/views/alchemy/admin/pictures/index.js.erb +3 -0
  335. data/app/views/alchemy/admin/pictures/info.html.erb +38 -0
  336. data/app/views/alchemy/admin/pictures/new.html.erb +16 -0
  337. data/app/views/alchemy/admin/pictures/show.html.erb +11 -0
  338. data/app/views/alchemy/admin/resources/_form.html.erb +13 -0
  339. data/app/views/alchemy/admin/resources/_resource.html.erb +30 -0
  340. data/app/views/alchemy/admin/resources/_table.html.erb +25 -0
  341. data/app/views/alchemy/admin/resources/edit.html.erb +1 -0
  342. data/app/views/alchemy/admin/resources/index.csv.erb +13 -0
  343. data/app/views/alchemy/admin/resources/index.html.erb +32 -0
  344. data/app/views/alchemy/admin/resources/new.html.erb +1 -0
  345. data/app/views/alchemy/admin/sites/index.html.erb +23 -0
  346. data/app/views/alchemy/admin/tags/_radio_tag.html.erb +6 -0
  347. data/app/views/alchemy/admin/tags/_tag.html.erb +30 -0
  348. data/app/views/alchemy/admin/tags/edit.html.erb +24 -0
  349. data/app/views/alchemy/admin/tags/index.html.erb +52 -0
  350. data/app/views/alchemy/admin/tags/new.html.erb +7 -0
  351. data/app/views/alchemy/admin/trash/clear.js.erb +4 -0
  352. data/app/views/alchemy/admin/trash/index.html.erb +29 -0
  353. data/app/views/alchemy/attachments/show.html.erb +1 -0
  354. data/app/views/alchemy/base/500.html.erb +26 -0
  355. data/app/views/alchemy/base/error_notice.html.erb +1 -0
  356. data/app/views/alchemy/base/error_notice.js.erb +2 -0
  357. data/app/views/alchemy/base/permission_denied.js.erb +3 -0
  358. data/app/views/alchemy/base/redirect.js.erb +12 -0
  359. data/app/views/alchemy/base/update.js.erb +5 -0
  360. data/app/views/alchemy/breadcrumb/_page.html.erb +16 -0
  361. data/app/views/alchemy/breadcrumb/_separator.html.erb +1 -0
  362. data/app/views/alchemy/breadcrumb/_wrapper.html.erb +13 -0
  363. data/app/views/alchemy/elements/_editor_not_found.html.erb +5 -0
  364. data/app/views/alchemy/elements/_view_not_found.html.erb +1 -0
  365. data/app/views/alchemy/elements/show.html.erb +1 -0
  366. data/app/views/alchemy/elements/show.js.erb +1 -0
  367. data/app/views/alchemy/essences/_essence_boolean_editor.html.erb +16 -0
  368. data/app/views/alchemy/essences/_essence_boolean_view.html.erb +3 -0
  369. data/app/views/alchemy/essences/_essence_date_editor.html.erb +19 -0
  370. data/app/views/alchemy/essences/_essence_date_view.html.erb +11 -0
  371. data/app/views/alchemy/essences/_essence_file_editor.html.erb +57 -0
  372. data/app/views/alchemy/essences/_essence_file_view.html.erb +10 -0
  373. data/app/views/alchemy/essences/_essence_html_editor.html.erb +9 -0
  374. data/app/views/alchemy/essences/_essence_html_view.html.erb +3 -0
  375. data/app/views/alchemy/essences/_essence_link_editor.html.erb +25 -0
  376. data/app/views/alchemy/essences/_essence_link_view.html.erb +11 -0
  377. data/app/views/alchemy/essences/_essence_picture_editor.html.erb +59 -0
  378. data/app/views/alchemy/essences/_essence_picture_view.html.erb +5 -0
  379. data/app/views/alchemy/essences/_essence_richtext_editor.html.erb +13 -0
  380. data/app/views/alchemy/essences/_essence_richtext_view.html.erb +5 -0
  381. data/app/views/alchemy/essences/_essence_select_editor.html.erb +25 -0
  382. data/app/views/alchemy/essences/_essence_select_view.html.erb +3 -0
  383. data/app/views/alchemy/essences/_essence_text_editor.html.erb +18 -0
  384. data/app/views/alchemy/essences/_essence_text_view.html.erb +18 -0
  385. data/app/views/alchemy/essences/shared/_essence_picture_tools.html.erb +61 -0
  386. data/app/views/alchemy/essences/shared/_linkable_essence_tools.html.erb +19 -0
  387. data/app/views/alchemy/language_links/_language.html.erb +12 -0
  388. data/app/views/alchemy/language_links/_spacer.html.erb +1 -0
  389. data/app/views/alchemy/messages/contact_form_mail.de.text.erb +12 -0
  390. data/app/views/alchemy/messages/contact_form_mail.en.text.erb +12 -0
  391. data/app/views/alchemy/messages/contact_form_mail.es.text.erb +12 -0
  392. data/app/views/alchemy/messages/new.html.erb +1 -0
  393. data/app/views/alchemy/navigation/_image_link.html.erb +14 -0
  394. data/app/views/alchemy/navigation/_link.html.erb +20 -0
  395. data/app/views/alchemy/navigation/_renderer.html.erb +30 -0
  396. data/app/views/alchemy/pages/show.html.erb +1 -0
  397. data/app/views/alchemy/pages/show.rss.builder +20 -0
  398. data/app/views/alchemy/pages/sitemap.xml.erb +6 -0
  399. data/app/views/kaminari/alchemy/_first_page.html.erb +11 -0
  400. data/app/views/kaminari/alchemy/_gap.html.erb +8 -0
  401. data/app/views/kaminari/alchemy/_last_page.html.erb +11 -0
  402. data/app/views/kaminari/alchemy/_next_page.html.erb +13 -0
  403. data/app/views/kaminari/alchemy/_page.html.erb +14 -0
  404. data/app/views/kaminari/alchemy/_paginator.html.erb +23 -0
  405. data/app/views/kaminari/alchemy/_prev_page.html.erb +13 -0
  406. data/app/views/layouts/alchemy/admin.html.erb +109 -0
  407. data/app/views/layouts/alchemy/sitemap.xml.erb +4 -0
  408. data/bin/alchemy +267 -0
  409. data/bin/rails +8 -0
  410. data/config/alchemy/config.yml +189 -0
  411. data/config/alchemy/modules.yml +88 -0
  412. data/config/initializers/dragonfly.rb +25 -0
  413. data/config/initializers/simple_form.rb +144 -0
  414. data/config/locales/alchemy.de.yml +918 -0
  415. data/config/locales/alchemy.en.yml +920 -0
  416. data/config/locales/alchemy.es.yml +958 -0
  417. data/config/locales/alchemy.fr.yml +942 -0
  418. data/config/locales/alchemy.nl.yml +921 -0
  419. data/config/locales/alchemy.ru.yml +837 -0
  420. data/config/locales/simple_form.de.yml +26 -0
  421. data/config/locales/simple_form.en.yml +25 -0
  422. data/config/locales/simple_form.es.yml +6 -0
  423. data/config/locales/simple_form.fr.yml +26 -0
  424. data/config/locales/simple_form.nl.yml +25 -0
  425. data/config/locales/simple_form.ru.yml +25 -0
  426. data/config/routes.rb +164 -0
  427. data/db/migrate/20130827094554_alchemy_two_point_six.rb +380 -0
  428. data/db/migrate/20130828121054_remove_do_not_index_from_alchemy_essence_texts.rb +5 -0
  429. data/db/migrate/20130828121120_remove_do_not_index_from_alchemy_essence_richtexts.rb +5 -0
  430. data/db/migrate/20130918201742_add_published_at_to_alchemy_pages.rb +5 -0
  431. data/lib/alchemy/auth_accessors.rb +104 -0
  432. data/lib/alchemy/cache_digests/template_tracker.rb +65 -0
  433. data/lib/alchemy/config.rb +65 -0
  434. data/lib/alchemy/configuration_methods.rb +29 -0
  435. data/lib/alchemy/controller_actions.rb +138 -0
  436. data/lib/alchemy/engine.rb +104 -0
  437. data/lib/alchemy/errors.rb +82 -0
  438. data/lib/alchemy/essence.rb +232 -0
  439. data/lib/alchemy/filetypes.rb +33 -0
  440. data/lib/alchemy/forms/builder.rb +23 -0
  441. data/lib/alchemy/hints.rb +57 -0
  442. data/lib/alchemy/i18n.rb +70 -0
  443. data/lib/alchemy/kaminari/scoped_pagination_url_helper.rb +13 -0
  444. data/lib/alchemy/locale.rb +65 -0
  445. data/lib/alchemy/logger.rb +15 -0
  446. data/lib/alchemy/middleware/rescue_old_cookies.rb +27 -0
  447. data/lib/alchemy/modules.rb +75 -0
  448. data/lib/alchemy/mount_point.rb +47 -0
  449. data/lib/alchemy/name_conversions.rb +28 -0
  450. data/lib/alchemy/on_page_layout.rb +58 -0
  451. data/lib/alchemy/page_layout.rb +183 -0
  452. data/lib/alchemy/permissions.rb +221 -0
  453. data/lib/alchemy/picture_attributes.rb +29 -0
  454. data/lib/alchemy/resource.rb +238 -0
  455. data/lib/alchemy/resources_helper.rb +135 -0
  456. data/lib/alchemy/routing_constraints.rb +49 -0
  457. data/lib/alchemy/seeder.rb +53 -0
  458. data/lib/alchemy/shell.rb +102 -0
  459. data/lib/alchemy/ssl_protection.rb +30 -0
  460. data/lib/alchemy/tasks/helpers.rb +83 -0
  461. data/lib/alchemy/test_support/controller_requests.rb +73 -0
  462. data/lib/alchemy/test_support/essence_shared_examples.rb +286 -0
  463. data/lib/alchemy/test_support/factories.rb +147 -0
  464. data/lib/alchemy/test_support/integration_helpers.rb +33 -0
  465. data/lib/alchemy/tinymce.rb +68 -0
  466. data/lib/alchemy/touching.rb +41 -0
  467. data/lib/alchemy/upgrader.rb +80 -0
  468. data/lib/alchemy/upgrader/three_point_one.rb +54 -0
  469. data/lib/alchemy/upgrader/three_point_two.rb +69 -0
  470. data/lib/alchemy/upgrader/three_point_zero.rb +93 -0
  471. data/lib/alchemy/userstamp.rb +10 -0
  472. data/lib/alchemy/version.rb +7 -0
  473. data/lib/alchemy_cms.rb +5 -0
  474. data/lib/rails/generators/alchemy/base.rb +41 -0
  475. data/lib/rails/generators/alchemy/elements/elements_generator.rb +37 -0
  476. data/lib/rails/generators/alchemy/elements/templates/editor.html.erb +14 -0
  477. data/lib/rails/generators/alchemy/elements/templates/editor.html.haml +13 -0
  478. data/lib/rails/generators/alchemy/elements/templates/editor.html.slim +12 -0
  479. data/lib/rails/generators/alchemy/elements/templates/view.html.erb +27 -0
  480. data/lib/rails/generators/alchemy/elements/templates/view.html.haml +20 -0
  481. data/lib/rails/generators/alchemy/elements/templates/view.html.slim +20 -0
  482. data/lib/rails/generators/alchemy/essence/essence_generator.rb +52 -0
  483. data/lib/rails/generators/alchemy/essence/templates/editor.html.erb +17 -0
  484. data/lib/rails/generators/alchemy/essence/templates/view.html.erb +2 -0
  485. data/lib/rails/generators/alchemy/install/files/_article_editor.html.erb +5 -0
  486. data/lib/rails/generators/alchemy/install/files/_article_view.html.erb +7 -0
  487. data/lib/rails/generators/alchemy/install/files/_standard.html.erb +1 -0
  488. data/lib/rails/generators/alchemy/install/files/alchemy.de.yml +31 -0
  489. data/lib/rails/generators/alchemy/install/files/alchemy.elements.css.scss +30 -0
  490. data/lib/rails/generators/alchemy/install/files/alchemy.en.yml +31 -0
  491. data/lib/rails/generators/alchemy/install/files/alchemy.es.yml +31 -0
  492. data/lib/rails/generators/alchemy/install/files/application.html.erb +14 -0
  493. data/lib/rails/generators/alchemy/install/install_generator.rb +69 -0
  494. data/lib/rails/generators/alchemy/install/templates/elements.yml.tt +21 -0
  495. data/lib/rails/generators/alchemy/install/templates/page_layouts.yml.tt +10 -0
  496. data/lib/rails/generators/alchemy/module/module_generator.rb +30 -0
  497. data/lib/rails/generators/alchemy/module/templates/ability.rb.tt +11 -0
  498. data/lib/rails/generators/alchemy/module/templates/controller.rb.tt +2 -0
  499. data/lib/rails/generators/alchemy/module/templates/module_config.rb.tt +17 -0
  500. data/lib/rails/generators/alchemy/page_layouts/page_layouts_generator.rb +24 -0
  501. data/lib/rails/generators/alchemy/page_layouts/templates/layout.html.erb +1 -0
  502. data/lib/rails/generators/alchemy/page_layouts/templates/layout.html.haml +1 -0
  503. data/lib/rails/generators/alchemy/page_layouts/templates/layout.html.slim +1 -0
  504. data/lib/rails/generators/alchemy/site_layouts/site_layouts_generator.rb +23 -0
  505. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.erb +1 -0
  506. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.haml +1 -0
  507. data/lib/rails/generators/alchemy/site_layouts/templates/layout.html.slim +1 -0
  508. data/lib/rails/generators/alchemy/views/views_generator.rb +41 -0
  509. data/lib/rails/templates/alchemy.rb +7 -0
  510. data/lib/tasks/alchemy/convert.rake +39 -0
  511. data/lib/tasks/alchemy/db.rake +22 -0
  512. data/lib/tasks/alchemy/install.rake +61 -0
  513. data/lib/tasks/alchemy/tidy.rake +102 -0
  514. data/lib/tasks/alchemy/upgrade.rake +28 -0
  515. data/spec/controllers/admin/attachments_controller_spec.rb +211 -0
  516. data/spec/controllers/admin/base_controller_spec.rb +74 -0
  517. data/spec/controllers/admin/clipboard_controller_spec.rb +60 -0
  518. data/spec/controllers/admin/contents_controller_spec.rb +72 -0
  519. data/spec/controllers/admin/dashboard_controller_spec.rb +139 -0
  520. data/spec/controllers/admin/elements_controller_spec.rb +473 -0
  521. data/spec/controllers/admin/essence_files_controller_spec.rb +71 -0
  522. data/spec/controllers/admin/essence_pictures_controller_spec.rb +202 -0
  523. data/spec/controllers/admin/languages_controller_spec.rb +61 -0
  524. data/spec/controllers/admin/layoutpages_controller_spec.rb +27 -0
  525. data/spec/controllers/admin/pages_controller_spec.rb +553 -0
  526. data/spec/controllers/admin/pictures_controller_spec.rb +358 -0
  527. data/spec/controllers/admin/resources_controller_spec.rb +53 -0
  528. data/spec/controllers/admin/trash_controller_spec.rb +68 -0
  529. data/spec/controllers/alchemy/admin/tags_controller_spec.rb +63 -0
  530. data/spec/controllers/alchemy/api/contents_controller_spec.rb +126 -0
  531. data/spec/controllers/alchemy/api/elements_controller_spec.rb +125 -0
  532. data/spec/controllers/alchemy/api/pages_controller_spec.rb +134 -0
  533. data/spec/controllers/attachments_controller_spec.rb +64 -0
  534. data/spec/controllers/base_controller_spec.rb +51 -0
  535. data/spec/controllers/elements_controller_spec.rb +48 -0
  536. data/spec/controllers/messages_controller_spec.rb +199 -0
  537. data/spec/controllers/pages_controller_spec.rb +265 -0
  538. data/spec/controllers/pictures_controller_spec.rb +393 -0
  539. data/spec/dummy/Rakefile +6 -0
  540. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  541. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  542. data/spec/dummy/app/controllers/admin/events_controller.rb +3 -0
  543. data/spec/dummy/app/controllers/application_controller.rb +15 -0
  544. data/spec/dummy/app/controllers/login_controller.rb +5 -0
  545. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  546. data/spec/dummy/app/mailers/.gitkeep +0 -0
  547. data/spec/dummy/app/models/ability.rb +9 -0
  548. data/spec/dummy/app/models/dummy_model.rb +3 -0
  549. data/spec/dummy/app/models/dummy_user.rb +11 -0
  550. data/spec/dummy/app/models/event.rb +10 -0
  551. data/spec/dummy/app/models/location.rb +3 -0
  552. data/spec/dummy/app/views/alchemy/elements/_all_you_can_eat_editor.html.erb +11 -0
  553. data/spec/dummy/app/views/alchemy/elements/_article_editor.html.erb +10 -0
  554. data/spec/dummy/app/views/alchemy/elements/_article_view.html.erb +25 -0
  555. data/spec/dummy/app/views/alchemy/elements/_headline_editor.html.erb +1 -0
  556. data/spec/dummy/app/views/alchemy/elements/_headline_view.html.erb +1 -0
  557. data/spec/dummy/app/views/alchemy/elements/_news_view.html.erb +11 -0
  558. data/spec/dummy/app/views/alchemy/page_layouts/_standard.html.erb +14 -0
  559. data/spec/dummy/app/views/layouts/application.html.erb +17 -0
  560. data/spec/dummy/bin/bundle +3 -0
  561. data/spec/dummy/bin/rails +4 -0
  562. data/spec/dummy/bin/rake +4 -0
  563. data/spec/dummy/config.ru +4 -0
  564. data/spec/dummy/config/alchemy/cells.yml +5 -0
  565. data/spec/dummy/config/alchemy/elements.yml +112 -0
  566. data/spec/dummy/config/alchemy/page_layouts.yml +32 -0
  567. data/spec/dummy/config/application.rb +32 -0
  568. data/spec/dummy/config/boot.rb +5 -0
  569. data/spec/dummy/config/database.yml +32 -0
  570. data/spec/dummy/config/environment.rb +5 -0
  571. data/spec/dummy/config/environments/development.rb +41 -0
  572. data/spec/dummy/config/environments/production.rb +77 -0
  573. data/spec/dummy/config/environments/test.rb +43 -0
  574. data/spec/dummy/config/initializers/alchemy.rb +2 -0
  575. data/spec/dummy/config/initializers/assets.rb +11 -0
  576. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  577. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  578. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  579. data/spec/dummy/config/initializers/inflections.rb +16 -0
  580. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  581. data/spec/dummy/config/initializers/secret_token.rb +12 -0
  582. data/spec/dummy/config/initializers/session_store.rb +3 -0
  583. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  584. data/spec/dummy/config/routes.rb +12 -0
  585. data/spec/dummy/config/secrets.yml +22 -0
  586. data/spec/dummy/db/migrate/20121026104128_create_events.rb +20 -0
  587. data/spec/dummy/db/migrate/20130328101418_create_locations.rb +9 -0
  588. data/spec/dummy/db/migrate/20130827094554_alchemy_two_point_six.rb +380 -0
  589. data/spec/dummy/db/migrate/20130828121054_remove_do_not_index_from_alchemy_essence_texts.rb +5 -0
  590. data/spec/dummy/db/migrate/20130828121120_remove_do_not_index_from_alchemy_essence_richtexts.rb +5 -0
  591. data/spec/dummy/db/migrate/20130918201742_add_published_at_to_alchemy_pages.rb +5 -0
  592. data/spec/dummy/db/migrate/20131209225243_create_dummy_users.rb +9 -0
  593. data/spec/dummy/db/migrate/20150122213511_acts_as_taggable_on_migration.acts_as_taggable_on_engine.rb +31 -0
  594. data/spec/dummy/db/migrate/20150122213512_add_missing_unique_indices.acts_as_taggable_on_engine.rb +20 -0
  595. data/spec/dummy/db/migrate/20150122213513_add_taggings_counter_cache_to_tags.acts_as_taggable_on_engine.rb +15 -0
  596. data/spec/dummy/db/migrate/20150122213514_add_missing_taggable_index.acts_as_taggable_on_engine.rb +10 -0
  597. data/spec/dummy/db/migrate/20150412103152_create_dummy_model.rb +7 -0
  598. data/spec/dummy/db/schema.rb +322 -0
  599. data/spec/dummy/db/seeds.rb +1 -0
  600. data/spec/dummy/lib/assets/.gitkeep +0 -0
  601. data/spec/dummy/public/404.html +67 -0
  602. data/spec/dummy/public/422.html +67 -0
  603. data/spec/dummy/public/500.html +66 -0
  604. data/spec/dummy/public/favicon.ico +0 -0
  605. data/spec/features/admin/dashboard_spec.rb +82 -0
  606. data/spec/features/admin/language_tree_feature_spec.rb +33 -0
  607. data/spec/features/admin/legacy_page_url_management_spec.rb +62 -0
  608. data/spec/features/admin/link_overlay_spec.rb +54 -0
  609. data/spec/features/admin/locale_select_feature_spec.rb +25 -0
  610. data/spec/features/admin/modules_integration_spec.rb +24 -0
  611. data/spec/features/admin/navigation_feature_spec.rb +13 -0
  612. data/spec/features/admin/page_creation_feature_spec.rb +51 -0
  613. data/spec/features/admin/page_editing_feature_spec.rb +135 -0
  614. data/spec/features/admin/picture_library_integration_spec.rb +62 -0
  615. data/spec/features/admin/resources_integration_spec.rb +133 -0
  616. data/spec/features/admin/site_select_feature_spec.rb +32 -0
  617. data/spec/features/admin/tinymce_feature_spec.rb +34 -0
  618. data/spec/features/navigation_spec.rb +9 -0
  619. data/spec/features/page_feature_spec.rb +287 -0
  620. data/spec/features/picture_security_spec.rb +35 -0
  621. data/spec/features/security_spec.rb +24 -0
  622. data/spec/features/translation_integration_spec.rb +51 -0
  623. data/spec/fixtures/500x500.png +0 -0
  624. data/spec/fixtures/80x60.png +0 -0
  625. data/spec/fixtures/image with spaces.png +0 -0
  626. data/spec/fixtures/image.png +0 -0
  627. data/spec/fixtures/image2.PNG +0 -0
  628. data/spec/fixtures/image3.jpeg +0 -0
  629. data/spec/helpers/admin/attachments_helper_spec.rb +15 -0
  630. data/spec/helpers/admin/base_helper_spec.rb +270 -0
  631. data/spec/helpers/admin/contents_helper_spec.rb +65 -0
  632. data/spec/helpers/admin/elements_helper_spec.rb +178 -0
  633. data/spec/helpers/admin/essences_helper_spec.rb +140 -0
  634. data/spec/helpers/admin/navigation_helper_spec.rb +288 -0
  635. data/spec/helpers/admin/pages_helper_spec.rb +95 -0
  636. data/spec/helpers/admin/pictures_helper_spec.rb +29 -0
  637. data/spec/helpers/admin/tags_helper_spec.rb +113 -0
  638. data/spec/helpers/base_helper_spec.rb +45 -0
  639. data/spec/helpers/elements_block_helper_spec.rb +135 -0
  640. data/spec/helpers/elements_helper_spec.rb +311 -0
  641. data/spec/helpers/essences_helper_spec.rb +156 -0
  642. data/spec/helpers/pages_helper_spec.rb +413 -0
  643. data/spec/helpers/picture_url_helpers_spec.rb +35 -0
  644. data/spec/helpers/url_helper_spec.rb +174 -0
  645. data/spec/javascripts/alchemy/dialog_spec.coffee +82 -0
  646. data/spec/javascripts/alchemy/link_overlay_spec.coffee +25 -0
  647. data/spec/javascripts/alchemy_integration_spec.coffee +3 -0
  648. data/spec/javascripts/fixtures/select.html +3 -0
  649. data/spec/javascripts/helpers/mock-ajax.js +199 -0
  650. data/spec/javascripts/helpers/test_responses/test_responses.js +1 -0
  651. data/spec/javascripts/support/jasmine.yml +29 -0
  652. data/spec/libraries/auth_accessors_spec.rb +40 -0
  653. data/spec/libraries/config_spec.rb +112 -0
  654. data/spec/libraries/controller_actions_spec.rb +133 -0
  655. data/spec/libraries/i18n_spec.rb +30 -0
  656. data/spec/libraries/kaminari/scoped_pagination_url_helper_spec.rb +30 -0
  657. data/spec/libraries/modules_spec.rb +67 -0
  658. data/spec/libraries/mount_point_spec.rb +77 -0
  659. data/spec/libraries/on_page_layout_spec.rb +112 -0
  660. data/spec/libraries/page_layout_spec.rb +144 -0
  661. data/spec/libraries/permissions_spec.rb +261 -0
  662. data/spec/libraries/resource_spec.rb +371 -0
  663. data/spec/libraries/resources_helper_spec.rb +144 -0
  664. data/spec/libraries/shell_spec.rb +125 -0
  665. data/spec/libraries/template_tracker_spec.rb +94 -0
  666. data/spec/libraries/tinymce_spec.rb +67 -0
  667. data/spec/libraries/userstamp_spec.rb +10 -0
  668. data/spec/mailers/messages_spec.rb +23 -0
  669. data/spec/models/attachment_spec.rb +227 -0
  670. data/spec/models/cell_spec.rb +102 -0
  671. data/spec/models/content_spec.rb +404 -0
  672. data/spec/models/dummy_model_spec.rb +11 -0
  673. data/spec/models/element_spec.rb +617 -0
  674. data/spec/models/element_to_page_spec.rb +14 -0
  675. data/spec/models/essence_boolean_spec.rb +10 -0
  676. data/spec/models/essence_date_spec.rb +29 -0
  677. data/spec/models/essence_file_spec.rb +43 -0
  678. data/spec/models/essence_html_spec.rb +18 -0
  679. data/spec/models/essence_link_spec.rb +10 -0
  680. data/spec/models/essence_picture_spec.rb +183 -0
  681. data/spec/models/essence_richtext_spec.rb +18 -0
  682. data/spec/models/essence_select_spec.rb +10 -0
  683. data/spec/models/essence_text_spec.rb +114 -0
  684. data/spec/models/language_spec.rb +123 -0
  685. data/spec/models/legacy_page_url_spec.rb +21 -0
  686. data/spec/models/message_spec.rb +55 -0
  687. data/spec/models/page_spec.rb +1896 -0
  688. data/spec/models/picture_spec.rb +330 -0
  689. data/spec/models/site_spec.rb +233 -0
  690. data/spec/models/tag_spec.rb +31 -0
  691. data/spec/routing/api_routing_spec.rb +150 -0
  692. data/spec/routing/routing_spec.rb +234 -0
  693. data/spec/spec_helper.rb +89 -0
  694. data/spec/support/ci/install_phantomjs +7 -0
  695. data/spec/support/hint_examples.rb +30 -0
  696. data/spec/support/rspec-activemodel-mocks_patch.rb +8 -0
  697. data/spec/support/test_tweaks.rb +31 -0
  698. data/spec/support/transformation_examples.rb +180 -0
  699. data/spec/tasks/helpers_spec.rb +219 -0
  700. data/spec/views/essences/essence_boolean_editor_spec.rb +33 -0
  701. data/spec/views/essences/essence_boolean_view_spec.rb +25 -0
  702. data/spec/views/essences/essence_date_view_spec.rb +39 -0
  703. data/spec/views/essences/essence_file_editor_spec.rb +61 -0
  704. data/spec/views/essences/essence_file_view_spec.rb +24 -0
  705. data/spec/views/essences/essence_html_view_spec.rb +22 -0
  706. data/spec/views/essences/essence_link_view_spec.rb +41 -0
  707. data/spec/views/essences/essence_picture_view_spec.rb +129 -0
  708. data/spec/views/essences/essence_richtext_view_spec.rb +32 -0
  709. data/spec/views/essences/essence_select_view_spec.rb +12 -0
  710. data/spec/views/essences/essence_text_view_spec.rb +52 -0
  711. data/vendor/assets/images/Jcrop.gif +0 -0
  712. data/vendor/assets/javascripts/fileupload/jquery.fileupload-process.js +175 -0
  713. data/vendor/assets/javascripts/fileupload/jquery.fileupload-validate.js +122 -0
  714. data/vendor/assets/javascripts/fileupload/jquery.fileupload.js +1467 -0
  715. data/vendor/assets/javascripts/fileupload/jquery.iframe-transport.js +217 -0
  716. data/vendor/assets/javascripts/jquery_plugins/jquery.Jcrop.min.js +22 -0
  717. data/vendor/assets/javascripts/jquery_plugins/jquery.floatThead.min.js +3 -0
  718. data/vendor/assets/javascripts/jquery_plugins/jquery.scrollTo.min.js +7 -0
  719. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.nestedSortable.js +435 -0
  720. data/vendor/assets/javascripts/jquery_plugins/jquery.ui.tabspaging.js +296 -0
  721. data/vendor/assets/javascripts/keymaster.js +296 -0
  722. data/vendor/assets/javascripts/requestAnimationFrame.js +31 -0
  723. data/vendor/assets/javascripts/spin.min.js +1 -0
  724. data/vendor/assets/javascripts/tinymce/langs/de.js +200 -0
  725. data/vendor/assets/javascripts/tinymce/langs/es.js +200 -0
  726. data/vendor/assets/javascripts/tinymce/langs/fr.js +200 -0
  727. data/vendor/assets/javascripts/tinymce/langs/nl.js +200 -0
  728. data/vendor/assets/javascripts/tinymce/langs/ru.js +200 -0
  729. data/vendor/assets/javascripts/tinymce/license.txt +504 -0
  730. data/vendor/assets/javascripts/tinymce/plugins/anchor/plugin.min.js +1 -0
  731. data/vendor/assets/javascripts/tinymce/plugins/autoresize/plugin.min.js +1 -0
  732. data/vendor/assets/javascripts/tinymce/plugins/charmap/plugin.min.js +1 -0
  733. data/vendor/assets/javascripts/tinymce/plugins/code/plugin.min.js +1 -0
  734. data/vendor/assets/javascripts/tinymce/plugins/directionality/plugin.min.js +1 -0
  735. data/vendor/assets/javascripts/tinymce/plugins/fullscreen/plugin.min.js +1 -0
  736. data/vendor/assets/javascripts/tinymce/plugins/hr/plugin.min.js +1 -0
  737. data/vendor/assets/javascripts/tinymce/plugins/link/plugin.min.js +1 -0
  738. data/vendor/assets/javascripts/tinymce/plugins/paste/plugin.min.js +1 -0
  739. data/vendor/assets/javascripts/tinymce/plugins/tabfocus/plugin.min.js +1 -0
  740. data/vendor/assets/javascripts/tinymce/plugins/table/plugin.min.js +1 -0
  741. data/vendor/assets/javascripts/tinymce/themes/modern/theme.min.js +1 -0
  742. data/vendor/assets/javascripts/tinymce/tinymce.min.js +13 -0
  743. data/vendor/assets/stylesheets/jquery.Jcrop.min.css +28 -0
  744. metadata +1453 -0
@@ -0,0 +1,291 @@
1
+ module Alchemy
2
+ # This helpers are useful to render elements from pages.
3
+ #
4
+ # The most important helper for frontend developers is the {#render_elements} helper.
5
+ #
6
+ module ElementsHelper
7
+ include Alchemy::EssencesHelper
8
+ include Alchemy::UrlHelper
9
+ include Alchemy::ElementsBlockHelper
10
+
11
+ # Renders all elements from current page
12
+ #
13
+ # == Examples:
14
+ #
15
+ # === Render only certain elements:
16
+ #
17
+ # <header>
18
+ # <%= render_elements only: ['header', 'claim'] %>
19
+ # </header>
20
+ # <section id="content">
21
+ # <%= render_elements except: ['header', 'claim'] %>
22
+ # </section>
23
+ #
24
+ # === Render elements from global page:
25
+ #
26
+ # <footer>
27
+ # <%= render_elements from_page: 'footer' %>
28
+ # </footer>
29
+ #
30
+ # === Render elements from cell:
31
+ #
32
+ # <aside>
33
+ # <%= render_elements from_cell: 'sidebar' %>
34
+ # </aside>
35
+ #
36
+ # === Fallback to elements from global page:
37
+ #
38
+ # You can use the fallback option as an override for elements that are stored on another page.
39
+ # So you can take elements from a global page and only if the user adds an element on current page the
40
+ # local one gets rendered.
41
+ #
42
+ # 1. You have to pass the the name of the element the fallback is for as <tt>for</tt> key.
43
+ # 2. You have to pass a <tt>page_layout</tt> name or {Alchemy::Page} from where the fallback elements is taken from as <tt>from</tt> key.
44
+ # 3. You can pass the name of element to fallback with as <tt>with</tt> key. This is optional (the element name from the <tt>for</tt> key is taken as default).
45
+ #
46
+ # <%= render_elements(fallback: {
47
+ # for: 'contact_teaser',
48
+ # from: 'sidebar',
49
+ # with: 'contact_teaser'
50
+ # }) %>
51
+ #
52
+ # @param [Hash] options
53
+ # Additional options.
54
+ #
55
+ # @option options [Number] :count
56
+ # The amount of elements to be rendered (begins with first element found)
57
+ # @option options [Array or String] :except ([])
58
+ # A list of element names not to be rendered.
59
+ # @option options [Hash] :fallback
60
+ # Define elements that are rendered from another page.
61
+ # @option options [Alchemy::Cell or String] :from_cell
62
+ # The cell the elements are rendered from. You can pass a {Alchemy::Cell} name String or a {Alchemy::Cell} object.
63
+ # @option options [Alchemy::Page or String] :from_page (@page)
64
+ # The page the elements are rendered from. You can pass a page_layout String or a {Alchemy::Page} object.
65
+ # @option options [Array or String] :only ([])
66
+ # A list of element names only to be rendered.
67
+ # @option options [Boolean] :random
68
+ # Randomize the output of elements
69
+ # @option options [Boolean] :reverse
70
+ # Reverse the rendering order
71
+ # @option options [String] :sort_by
72
+ # The name of a {Alchemy::Content} to sort the elements by
73
+ # @option options [String] :separator
74
+ # A string that will be used to join the element partials. Default nil
75
+ #
76
+ def render_elements(options = {})
77
+ options = {
78
+ from_page: @page,
79
+ render_format: 'html'
80
+ }.update(options)
81
+
82
+ pages = pages_holding_elements(options.delete(:from_page))
83
+
84
+ if pages.blank?
85
+ warning('No page to get elements from was found')
86
+ return
87
+ end
88
+
89
+ elements = collect_elements_from_pages(pages, options)
90
+
91
+ if options[:sort_by].present?
92
+ elements = sort_elements_by_content(elements, options.delete(:sort_by))
93
+ end
94
+
95
+ render_element_view_partials(elements, options)
96
+ end
97
+
98
+ # This helper renders a {Alchemy::Element} partial.
99
+ #
100
+ # A element has always two partials:
101
+ #
102
+ # 1. A view partial (This is the view presented to the website visitor)
103
+ # 2. A editor partial (This is the form presented to the website editor while in page edit mode)
104
+ #
105
+ # The partials are located in <tt>app/views/alchemy/elements</tt>.
106
+ #
107
+ # == View partial naming
108
+ #
109
+ # The partials have to be named after the name of the element as defined in the <tt>elements.yml</tt> file and has to be suffixed with the partial part.
110
+ #
111
+ # === Example
112
+ #
113
+ # Given a headline element
114
+ #
115
+ # # elements.yml
116
+ # - name: headline
117
+ # contents:
118
+ # - name: text
119
+ # type: EssenceText
120
+ #
121
+ # Then your element view partials has to be named like:
122
+ #
123
+ # app/views/alchemy/elements/_headline_editor.html.erb
124
+ # app/views/alchemy/elements/_headline_view.html.erb
125
+ #
126
+ # === Element partials generator
127
+ #
128
+ # You can use this handy generator to let Alchemy generate the partials for you:
129
+ #
130
+ # $ rails generate alchemy:elements --skip
131
+ #
132
+ # == Usage
133
+ #
134
+ # <%= render_element(Alchemy::Element.published.named(:headline).first) %>
135
+ #
136
+ # @param [Alchemy::Element] element
137
+ # The element you want to render the view for
138
+ # @param [Symbol] part
139
+ # The type of element partial (<tt>:editor</tt> or <tt>:view</tt>) you want to render
140
+ # @param [Hash] options
141
+ # Additional options
142
+ # @param [Number] counter
143
+ # a counter
144
+ #
145
+ # @note If the view partial is not found <tt>alchemy/elements/_view_not_found.html.erb</tt>
146
+ # or <tt>alchemy/elements/_editor_not_found.html.erb</tt> gets rendered.
147
+ #
148
+ def render_element(element, part = :view, options = {}, counter = 1)
149
+ if element.nil?
150
+ warning('Element is nil')
151
+ render "alchemy/elements/#{part}_not_found", {name: 'nil'}
152
+ return
153
+ end
154
+
155
+ element.store_page(@page) if part.to_sym == :view
156
+
157
+ render "alchemy/elements/#{element.name}_#{part}", {
158
+ element: element,
159
+ counter: counter,
160
+ options: options
161
+ }.merge(options.delete(:locals) || {})
162
+
163
+ rescue ActionView::MissingTemplate => e
164
+ warning(%(
165
+ Element #{part} partial not found for #{element.name}.\n
166
+ #{e}
167
+ ))
168
+ render "alchemy/elements/#{part}_not_found", {
169
+ name: element.name,
170
+ error: "Element #{part} partial not found.<br>Use <code>rails generate alchemy:elements</code> to generate it."
171
+ }
172
+ end
173
+
174
+ # Returns a string for the id attribute of a html element for the given element
175
+ def element_dom_id(element)
176
+ return "" if element.nil?
177
+ "#{element.name}_#{element.id}".html_safe
178
+ end
179
+
180
+ # Renders the HTML tag attributes required for preview mode.
181
+ def element_preview_code(element)
182
+ tag_options(element_preview_code_attributes(element))
183
+ end
184
+
185
+ # Returns a hash containing the HTML tag attributes required for preview mode.
186
+ def element_preview_code_attributes(element)
187
+ return {} unless element.present? && @preview_mode && element.page == @page
188
+ { :'data-alchemy-element' => element.id }
189
+ end
190
+
191
+ # Returns the element's tags information as a string. Parameters and options
192
+ # are equivalent to {#element_tags_attributes}.
193
+ #
194
+ # @see #element_tags_attributes
195
+ #
196
+ # @return [String]
197
+ # HTML tag attributes containing the element's tag information.
198
+ #
199
+ def element_tags(element, options = {})
200
+ tag_options(element_tags_attributes(element, options))
201
+ end
202
+
203
+ # Returns the element's tags information as an attribute hash.
204
+ #
205
+ # @param [Alchemy::Element] element The {Alchemy::Element} you want to render the tags from.
206
+ #
207
+ # @option options [Proc] :formatter
208
+ # ('lambda { |tags| tags.join(' ') }')
209
+ # Lambda converting array of tags to a string.
210
+ #
211
+ # @return [Hash]
212
+ # HTML tag attributes containing the element's tag information.
213
+ #
214
+ def element_tags_attributes(element, options = {})
215
+ options = {
216
+ formatter: lambda { |tags| tags.join(' ') }
217
+ }.merge(options)
218
+
219
+ return {} if !element.taggable? || element.tag_list.blank?
220
+ { :'data-element-tags' => options[:formatter].call(element.tag_list) }
221
+ end
222
+
223
+ # Sort given elements by content.
224
+ #
225
+ # @param [Array] elements - The elements you want to sort
226
+ # @param [String] content_name - The name of the content you want to sort by
227
+ #
228
+ # @return [Array]
229
+ #
230
+ def sort_elements_by_content(elements, content_name)
231
+ elements.sort_by do |element|
232
+ content = element.content_by_name(content_name)
233
+ content ? content.ingredient.to_s : ''
234
+ end
235
+ end
236
+
237
+ private
238
+
239
+ def pages_holding_elements(page)
240
+ case page
241
+ when String
242
+ Language.current.pages.where(
243
+ page_layout: page,
244
+ restricted: false
245
+ ).to_a
246
+ when Page
247
+ page
248
+ end
249
+ end
250
+
251
+ def collect_elements_from_pages(page, options)
252
+ if page.is_a? Array
253
+ elements = page.collect { |p| p.find_elements(options) }.flatten
254
+ else
255
+ elements = page.find_elements(options)
256
+ end
257
+ if fallback_required?(elements, options)
258
+ elements += fallback_elements(options)
259
+ end
260
+ elements
261
+ end
262
+
263
+ def fallback_required?(elements, options)
264
+ options[:fallback] && elements.detect { |e| e.name == options[:fallback][:for] }.nil?
265
+ end
266
+
267
+ def fallback_elements(options)
268
+ fallback_options = options.delete(:fallback)
269
+ case fallback_options[:from]
270
+ when String
271
+ page = Language.current.pages.find_by(
272
+ page_layout: fallback_options[:from],
273
+ restricted: false
274
+ )
275
+ when Page
276
+ page = fallback_options[:from]
277
+ end
278
+ return [] if page.blank?
279
+ page.elements.named(fallback_options[:with].blank? ? fallback_options[:for] : fallback_options[:with])
280
+ end
281
+
282
+ def render_element_view_partials(elements, options = {})
283
+ buff = []
284
+ elements.each_with_index do |element, i|
285
+ buff << render_element(element, :view, options, i + 1)
286
+ end
287
+ buff.join(options[:separator]).html_safe
288
+ end
289
+
290
+ end
291
+ end
@@ -0,0 +1,138 @@
1
+ module Alchemy
2
+
3
+ # This helper contains methods to render the +essence+ from an +Element+ +Content+.
4
+ #
5
+ # Essences have two kinds of partials. An +editor+ and a +view+ partial.
6
+ #
7
+ # They both resist in +'app/views/alchemy/essences'+
8
+ #
9
+ # The partials are suffixed with the type of part.
10
+ #
11
+ # == Example:
12
+ #
13
+ # For an EssenceText
14
+ #
15
+ # The view partial is:
16
+ #
17
+ # +_essence_text_view.html.erb+
18
+ #
19
+ # The editor partial is:
20
+ #
21
+ # +_essence_text_editor.html.erb+
22
+ #
23
+ # == Usage:
24
+ #
25
+ # For front end web development you should mostly use the +render_essence_view_by_name+ helper.
26
+ #
27
+ # And the +render_essence_editor_by_name+ helper for Alchemy backend views.
28
+ #
29
+ module EssencesHelper
30
+
31
+ # Renders the +Essence+ view partial from +Element+ by name.
32
+ #
33
+ # Pass the name of the +Content+ from +Element+ as second argument.
34
+ #
35
+ # == Example:
36
+ #
37
+ # This renders the +Content+ named "intro" from element.
38
+ #
39
+ # <%= render_essence_view_by_name(element, "intro") %>
40
+ #
41
+ def render_essence_view_by_name(element, name, options = {}, html_options = {})
42
+ if element.blank?
43
+ warning('Element is nil')
44
+ return ""
45
+ end
46
+ content = element.content_by_name(name)
47
+ render_essence_view(content, options, html_options)
48
+ end
49
+
50
+ # Renders the +Esssence+ partial for given +Content+.
51
+ #
52
+ # The helper renders the view partial as default.
53
+ #
54
+ # Pass +:editor+ as second argument to render the editor partial
55
+ #
56
+ # == Options:
57
+ #
58
+ # You can pass a options Hash to each type of essence partial as third argument.
59
+ #
60
+ # This Hash is available as +options+ local variable.
61
+ #
62
+ # for_view: {}
63
+ # for_editor: {}
64
+ #
65
+ def render_essence(content, part = :view, options = {}, html_options = {})
66
+ options = {for_view: {}, for_editor: {}}.update(options)
67
+ if content.nil?
68
+ return part == :view ? "" : warning('Content is nil', _t(:content_not_found))
69
+ elsif content.essence.nil?
70
+ return part == :view ? "" : warning('Essence is nil', _t(:content_essence_not_found))
71
+ end
72
+ render partial: "alchemy/essences/#{content.essence_partial_name}_#{part}", locals: {
73
+ content: content,
74
+ options: options["for_#{part}".to_sym],
75
+ html_options: html_options
76
+ }
77
+ end
78
+
79
+ # Renders the +Esssence+ view partial for given +Content+.
80
+ #
81
+ # == Options:
82
+ #
83
+ # :image_size => "111x93" # Used by EssencePicture to render the image via RMagick to that size. [Default nil]
84
+ # :date_format => "Am %d. %m. %Y, um %H:%Mh" # Especially for EssenceDate. See Rubys Date.strftime for date formatting options. [Default nil]
85
+ # :show_caption => false # Pass Boolean to show/hide the caption of an EssencePicture. [Default true]
86
+ # :disable_link => true # You can surpress the link of an EssencePicture. Default false
87
+ #
88
+ def render_essence_view(content, options = {}, html_options = {})
89
+ render_essence(content, :view, {:for_view => options}, html_options)
90
+ end
91
+
92
+ # Renders a essence picture
93
+ #
94
+ def render_essence_picture_view(content, options, html_options)
95
+ options = {
96
+ show_caption: true,
97
+ disable_link: false
98
+ }.update(content.settings).update(options)
99
+ return if content.ingredient.blank?
100
+ if content.essence.caption.present? && options[:show_caption]
101
+ caption = content_tag(:figcaption, content.essence.caption, id: "#{dom_id(content.ingredient)}_caption", class: "image_caption")
102
+ end
103
+ img_tag = image_tag(
104
+ content.essence.picture_url(options), {
105
+ alt: (content.essence.alt_tag.blank? ? nil : content.essence.alt_tag),
106
+ title: (content.essence.title.blank? ? nil : content.essence.title),
107
+ class: (caption || content.essence.css_class.blank? ? nil : content.essence.css_class)
108
+ }.merge(caption ? {} : html_options)
109
+ )
110
+ output = caption ? img_tag + caption : img_tag
111
+ if content.essence.link.present? && !options[:disable_link]
112
+ output = link_to(url_for(content.essence.link), {
113
+ title: content.essence.link_title.blank? ? nil : content.essence.link_title,
114
+ target: (content.essence.link_target == "blank" ? "_blank" : nil),
115
+ 'data-link-target' => content.essence.link_target.blank? ? nil : content.essence.link_target
116
+ }) do
117
+ output
118
+ end
119
+ end
120
+ if caption
121
+ content_tag(:figure, output, {class: content.essence.css_class.blank? ? nil : content.essence.css_class}.merge(html_options))
122
+ else
123
+ output
124
+ end
125
+ end
126
+
127
+ # Fetches value from settings of given content
128
+ #
129
+ # @param content [Alchemy::Content] - The content that settings should be taken
130
+ # @param key [Symbol] - The hash key you want to fetch the value from
131
+ # @param options [Hash] - An optional Hash that can override the settings.
132
+ # Normally passed as options hash into the content editor view
133
+ def content_settings_value(content, key, options = {})
134
+ content.settings.update(options || {}).symbolize_keys[key.to_sym]
135
+ end
136
+
137
+ end
138
+ end
@@ -0,0 +1,417 @@
1
+ module Alchemy
2
+ module PagesHelper
3
+ include Alchemy::BaseHelper
4
+ include Alchemy::ElementsHelper
5
+
6
+ def picture_essence_caption(content)
7
+ content.try(:essence).try(:caption)
8
+ end
9
+
10
+ # Renders links to language root pages of all published languages.
11
+ #
12
+ # @option options linkname [String] ('name')
13
+ # Renders name/code of language, or I18n translation for code.
14
+ #
15
+ # @option options show_title [Boolean] (true)
16
+ # Renders title attributes for the links.
17
+ #
18
+ # @option options spacer [String] ('')
19
+ # Renders the passed spacer string. You can also overwrite the spacer partial: "alchemy/language_links/_spacer".
20
+ #
21
+ # @option options reverse [Boolean] (false)
22
+ # Reverses the ordering of the links.
23
+ #
24
+ def language_links(options={})
25
+ options = {
26
+ linkname: 'name',
27
+ show_title: true,
28
+ spacer: '',
29
+ reverse: false
30
+ }.merge(options)
31
+ languages = Language.published.with_root_page.order("name #{options[:reverse] ? 'DESC' : 'ASC'}")
32
+ return nil if languages.count < 2
33
+ render(
34
+ partial: "alchemy/language_links/language",
35
+ collection: languages,
36
+ spacer_template: "alchemy/language_links/spacer",
37
+ locals: {languages: languages, options: options}
38
+ )
39
+ end
40
+
41
+ # Renders the layout for current page.
42
+ #
43
+ # Page layout files belongs in +/app/views/alchemy/page_layouts/+
44
+ #
45
+ # Falls back to +/app/views/alchemy/page_layouts/standard+ if the page_layout partial is not found.
46
+ #
47
+ def render_page_layout
48
+ render @page, page: @page
49
+ rescue ActionView::MissingTemplate
50
+ warning("PageLayout: '#{@page.page_layout}' not found. Rendering standard page_layout.")
51
+ render 'alchemy/page_layouts/standard', page: @page
52
+ end
53
+
54
+ # Renders a partial for current site
55
+ #
56
+ # Place a rails partial into +app/views/alchemy/site_layouts+
57
+ #
58
+ # and name it like your site name.
59
+ #
60
+ # == Example:
61
+ #
62
+ # <%= render_site_layout %>
63
+ #
64
+ # renders +app/views/alchemy/site_layouts/_default_site.html.erb+ for the site named "Default Site".
65
+ #
66
+ def render_site_layout
67
+ render current_alchemy_site
68
+ rescue ActionView::MissingTemplate
69
+ warning("Site layout for #{current_alchemy_site.try(:name)} not found. Please run `rails g alchemy:site_layouts`")
70
+ return ""
71
+ end
72
+
73
+ # Renders the navigation.
74
+ #
75
+ # It produces a html <ul><li></li></ul> structure with all necessary classes so you can produce every navigation the web uses today.
76
+ # I.E. dropdown-navigations, simple mainnavigations or even complex nested ones.
77
+ #
78
+ # === HTML output:
79
+ #
80
+ # <ul class="navigation level_1">
81
+ # <li class="first home"><a href="/home" class="active" title="Homepage" lang="en" data-page-id="1">Homepage</a></li>
82
+ # <li class="contact"><a href="/contact" title="Contact" lang="en" data-page-id="2">Contact</a></li>
83
+ # <li class="last imprint"><a href="/imprint" title="Imprint" lang="en" data-page-id="3">Imprint</a></li>
84
+ # </ul>
85
+ #
86
+ # As you can see: Everything you need.
87
+ #
88
+ # Not pleased with the way Alchemy produces the navigation structure?
89
+ #
90
+ # Then feel free to overwrite the partials (_renderer.html.erb and _link.html.erb) found in +views/navigation/+ or pass different partials via the options +:navigation_partial+ and +:navigation_link_partial+.
91
+ #
92
+ # === Passing HTML classes and ids to the renderer
93
+ #
94
+ # A second hash can be passed as html_options to the navigation renderer partial.
95
+ #
96
+ # ==== Example:
97
+ #
98
+ # <%= render_navigation({from_page: 'subnavi'}, {class: 'navigation', id: 'subnavigation'}) %>
99
+ #
100
+ #
101
+ # @option options submenu [Boolean] (false)
102
+ # Do you want a nested <ul> <li> structure for the deeper levels of your navigation, or not?
103
+ # Used to display the subnavigation within the mainnaviagtion. I.e. for dropdown menues.
104
+ #
105
+ # @option options all_sub_menues [Boolean] (false)
106
+ # Renders the whole page tree.
107
+ #
108
+ # @option options from_page [Alchemy::Page] (@root_page)
109
+ # Do you want to render a navigation from a different page then the current page?
110
+ # Then pass an Page instance or a Alchemy::PageLayout name as string.
111
+ #
112
+ # @option options spacer [String] (nil)
113
+ # A spacer for the entries can be passed.
114
+ # Simple string, or even a complex html structure.
115
+ # I.e: "<span class='spacer'>|</spacer>".
116
+ #
117
+ # @option options navigation_partial [String] ("navigation/renderer")
118
+ # Pass a different partial to be taken for the navigation rendering.
119
+ # Alternatively you could override the +app/views/alchemy/navigation/renderer+ partial in your app.
120
+ #
121
+ # @option options navigation_link_partial [String] ("navigation/link")
122
+ # Alchemy places an <a> html link in <li> tags.
123
+ # The tag automatically has an active css class if necessary.
124
+ # So styling is everything. But maybe you don't want this.
125
+ # So feel free to make you own partial and pass the filename here.
126
+ # Alternatively you could override the +app/views/alchemy/navigation/link+ partial in your app.
127
+ #
128
+ # @option options show_nonactive [Boolean] (false)
129
+ # Commonly Alchemy only displays the submenu of the active page (if submenu: true).
130
+ # If you want to display all child pages then pass true (together with submenu: true of course).
131
+ # I.e. for css-driven drop down menues.
132
+ #
133
+ # @option options show_title [Boolean] (true)
134
+ # For our beloved SEOs :)
135
+ # Appends a title attribute to all links and places the +page.title+ content into it.
136
+ #
137
+ # @option options restricted_only [Boolean] (false)
138
+ # Render only restricted pages. I.E for members only navigations.
139
+ #
140
+ # @option options reverse [Boolean] (false)
141
+ # Reverse the output of the pages
142
+ #
143
+ # @option options reverse_children [Boolean] (false)
144
+ # Like reverse option, but only reverse the children of the first level
145
+ #
146
+ # @option options deepness [Fixnum] (nil)
147
+ # Show only pages up to this depth.
148
+ #
149
+ def render_navigation(options = {}, html_options = {})
150
+ options = {
151
+ submenu: false,
152
+ all_sub_menues: false,
153
+ from_page: @root_page || Language.current_root_page,
154
+ spacer: nil,
155
+ navigation_partial: 'alchemy/navigation/renderer',
156
+ navigation_link_partial: 'alchemy/navigation/link',
157
+ show_nonactive: false,
158
+ restricted_only: false,
159
+ show_title: true,
160
+ reverse: false,
161
+ reverse_children: false
162
+ }.merge(options)
163
+ page = page_or_find(options[:from_page])
164
+ return nil if page.blank?
165
+ pages = page.children.accessible_by(current_ability, :see)
166
+ pages = pages.restricted if options.delete(:restricted_only)
167
+ if depth = options[:deepness]
168
+ pages = pages.where("#{Page.table_name}.depth <= #{depth}")
169
+ end
170
+ if options[:reverse]
171
+ pages.reverse!
172
+ end
173
+ render options[:navigation_partial],
174
+ options: options,
175
+ pages: pages,
176
+ html_options: html_options
177
+ end
178
+
179
+ # Renders navigation the children and all siblings of the given page (standard is the current page).
180
+ #
181
+ # Use this helper if you want to render the subnavigation independent from the mainnavigation. I.E. to place it in a different area on your website.
182
+ #
183
+ # This helper passes all its options to the the render_navigation helper.
184
+ #
185
+ # === Options:
186
+ #
187
+ # from_page: @page # The page to render the navigation from
188
+ # submenu: true # Shows the nested children
189
+ # level: 2 # Normally there is no need to change the level parameter, just in a few special cases
190
+ #
191
+ def render_subnavigation(options = {}, html_options = {})
192
+ default_options = {
193
+ from_page: @page,
194
+ submenu: true,
195
+ level: 2
196
+ }
197
+ options = default_options.merge(options)
198
+ if !options[:from_page].nil?
199
+ while options[:from_page].level > options[:level] do
200
+ options[:from_page] = options[:from_page].parent
201
+ end
202
+ render_navigation(options, html_options)
203
+ else
204
+ return nil
205
+ end
206
+ end
207
+
208
+ # Returns true if page is in the active branch
209
+ def page_active?(page)
210
+ @_page_ancestors ||= Page.ancestors_for(@page)
211
+ @_page_ancestors.include?(page)
212
+ end
213
+
214
+ # Returns +'active'+ if the given external page is in the current url path or +nil+.
215
+ def external_page_css_class(page)
216
+ return nil if !page.redirects_to_external?
217
+ request.path.split('/').delete_if(&:blank?).first == page.urlname.gsub(/^\//, '') ? 'active' : nil
218
+ end
219
+
220
+ # Returns page links in a breadcrumb beginning from root to current page.
221
+ #
222
+ # === Options:
223
+ #
224
+ # separator: %(<span class="separator">></span>) # Maybe you don't want this separator. Pass another one.
225
+ # page: @page # Pass a different Page instead of the default (@page).
226
+ # without: nil # Pass Page object or array of Pages that must not be displayed.
227
+ # restricted_only: false # Pass boolean for displaying restricted pages only.
228
+ # reverse: false # Pass boolean for displaying breadcrumb in reversed reversed.
229
+ #
230
+ def render_breadcrumb(options={})
231
+ options = {
232
+ separator: ">",
233
+ page: @page,
234
+ restricted_only: false,
235
+ reverse: false,
236
+ link_active_page: false
237
+ }.merge(options)
238
+
239
+ pages = Page.
240
+ ancestors_for(options[:page]).
241
+ accessible_by(current_ability, :see)
242
+
243
+ if options.delete(:restricted_only)
244
+ pages = pages.restricted
245
+ end
246
+
247
+ if options.delete(:reverse)
248
+ pages.to_a.reverse!
249
+ end
250
+
251
+ if options[:without].present?
252
+ if options[:without].class == Array
253
+ pages = pages.to_a - options[:without]
254
+ else
255
+ pages.to_a.delete(options[:without])
256
+ end
257
+ end
258
+
259
+ render 'alchemy/breadcrumb/wrapper', pages: pages, options: options
260
+ end
261
+
262
+ # Returns current page title
263
+ #
264
+ # === Options:
265
+ #
266
+ # prefix: "" # Prefix
267
+ # separator: "" # Separating prefix and title
268
+ #
269
+ # === Webdevelopers
270
+ #
271
+ # Please use the render_meta_data() helper instead. There all important meta information gets rendered in one helper.
272
+ # So you dont have to worry about anything.
273
+ #
274
+ def render_page_title(options = {})
275
+ return "" if @page.title.blank?
276
+ options = {
277
+ prefix: "",
278
+ separator: ""
279
+ }.update(options)
280
+ title_parts = [options[:prefix]]
281
+ if response.status == 200
282
+ title_parts << @page.title
283
+ else
284
+ title_parts << response.status
285
+ end
286
+ title_parts.join(options[:separator])
287
+ end
288
+
289
+ # Returns a complete html <title> tag for the <head> part of the html document.
290
+ #
291
+ # === Webdevelopers:
292
+ #
293
+ # Please use the render_meta_data() helper. There all important meta information gets rendered in one helper.
294
+ # So you dont have to worry about anything.
295
+ #
296
+ def render_title_tag(options={})
297
+ default_options = {
298
+ prefix: "",
299
+ separator: ""
300
+ }
301
+ options = default_options.merge(options)
302
+ %(<title>#{render_page_title(options)}</title>).html_safe
303
+ end
304
+
305
+ # Renders a html <meta> tag for name: "" and content: ""
306
+ #
307
+ # === Webdevelopers:
308
+ #
309
+ # Please use the render_meta_data() helper. There all important meta information gets rendered in one helper.
310
+ # So you dont have to worry about anything.
311
+ #
312
+ def render_meta_tag(options={})
313
+ default_options = {
314
+ name: "",
315
+ default_language: "de",
316
+ content: ""
317
+ }
318
+ options = default_options.merge(options)
319
+ lang = (@page.language.blank? ? options[:default_language] : @page.language.code)
320
+ %(<meta name="#{options[:name]}" content="#{options[:content]}" lang="#{lang}">).html_safe
321
+ end
322
+
323
+ # This helper takes care of all important meta tags for your page.
324
+ #
325
+ # The meta data is been taken from the @page.title, @page.meta_description, @page.meta_keywords, @page.updated_at and @page.language database entries managed by the Alchemy user via the Alchemy cockpit.
326
+ #
327
+ # Assume that the user has entered following data into the Alchemy cockpit of the Page "home" and that the user wants that the searchengine (aka. google) robot should index the page and should follow all links on this page:
328
+ #
329
+ # Title = Homepage
330
+ # Description = Your page description
331
+ # Keywords: cms, ruby, rubyonrails, rails, software, development, html, javascript, ajax
332
+ #
333
+ # Then placing +render_meta_data(title_prefix: "Company", title_separator: "-")+ into the <head> part of the +pages.html.erb+ layout produces:
334
+ #
335
+ # <meta charset="UTF-8">
336
+ # <title>Company - #{@page.title}</title>
337
+ # <meta name="description" content="Your page description">
338
+ # <meta name="keywords" content="cms, ruby, rubyonrails, rails, software, development, html, javascript, ajax">
339
+ # <meta name="created" content="Tue Dec 16 10:21:26 +0100 2008">
340
+ # <meta name="robots" content="index, follow">
341
+ #
342
+ def render_meta_data options={}
343
+ if @page.blank?
344
+ warning("No Page found!")
345
+ return nil
346
+ end
347
+ default_options = {
348
+ title_prefix: "",
349
+ title_separator: "",
350
+ default_lang: "de"
351
+ }
352
+ options = default_options.merge(options)
353
+ # render meta description of the root page from language if the current meta description is empty
354
+ if @page.meta_description.blank?
355
+ description = Language.current.pages.published.language_roots.try(:meta_description)
356
+ else
357
+ description = @page.meta_description
358
+ end
359
+ # render meta keywords of the root page from language if the current meta keywords is empty
360
+ if @page.meta_keywords.blank?
361
+ keywords = Language.current.pages.published.language_roots.try(:meta_keywords)
362
+ else
363
+ keywords = @page.meta_keywords
364
+ end
365
+ robot = "#{@page.robot_index? ? "" : "no"}index, #{@page.robot_follow? ? "" : "no"}follow"
366
+ meta_string = %(
367
+ <meta charset="UTF-8">
368
+ #{render_title_tag(prefix: options[:title_prefix], separator: options[:title_separator])}
369
+ #{render_meta_tag(name: "description", content: description)}
370
+ #{render_meta_tag(name: "keywords", content: keywords)}
371
+ <meta name="created" content="#{@page.updated_at}">
372
+ <meta name="robots" content="#{robot}">
373
+ )
374
+ if @page.contains_feed?
375
+ meta_string += %(
376
+ <link rel="alternate" type="application/rss+xml" title="RSS" href="#{show_alchemy_page_url(@page, format: :rss)}">
377
+ )
378
+ end
379
+ return meta_string.html_safe
380
+ end
381
+
382
+ # Renders the partial for the cell with the given name of the current page.
383
+ # Cell partials are located in +app/views/cells/+ of your project.
384
+ #
385
+ # === Options are:
386
+ #
387
+ # from_page: Alchemy::Page # Alchemy::Page object from which the elements are rendered from.
388
+ # locals: Hash # Hash of variables that will be available in the partial. Example: {user: var1, product: var2}
389
+ #
390
+ def render_cell(name, options={})
391
+ default_options = {
392
+ from_page: @page,
393
+ locals: {}
394
+ }
395
+ options = default_options.merge(options)
396
+ cell = options[:from_page].cells.find_by_name(name)
397
+ return "" if cell.blank?
398
+ render partial: "alchemy/cells/#{name}", locals: {cell: cell}.merge(options[:locals])
399
+ end
400
+
401
+ # Returns true or false if no elements are in the cell found by name.
402
+ def cell_empty?(name)
403
+ cell = @page.cells.find_by_name(name)
404
+ return true if cell.blank?
405
+ cell.elements.blank?
406
+ end
407
+
408
+ # Include this in your layout file to have element selection magic in the page edit preview window.
409
+ def alchemy_preview_mode_code
410
+ if @preview_mode
411
+ output = javascript_tag("Alchemy = { locale: '#{session[:alchemy_locale]}' };")
412
+ output += javascript_include_tag("alchemy/preview")
413
+ end
414
+ end
415
+
416
+ end
417
+ end