alchemy_cms 7.4.6 → 8.0.0.a
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.
Potentially problematic release.
This version of alchemy_cms might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +86 -0
- data/Gemfile +13 -6
- data/README.md +13 -5
- data/alchemy_cms.gemspec +14 -5
- data/app/assets/builds/alchemy/admin/page-select.css +1 -1
- data/app/assets/builds/alchemy/admin/print.css +1 -1
- data/app/assets/builds/alchemy/admin.css +2 -2
- data/app/assets/builds/alchemy/custom-properties.css +1 -1
- data/app/assets/builds/alchemy/welcome.css +1 -1
- data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css +1 -1
- data/app/assets/builds/tinymce/skins/ui/alchemy/content.min.css +1 -0
- data/app/assets/builds/tinymce/skins/ui/alchemy/skin.min.css +1 -1
- data/app/assets/config/alchemy_manifest.js +0 -2
- data/app/assets/images/alchemy/icons-sprite.svg +1 -0
- data/app/components/alchemy/admin/resource/applied_filter.rb +29 -0
- data/app/components/alchemy/admin/resource/checkbox_filter.rb +36 -0
- data/app/components/alchemy/admin/resource/datepicker_filter.rb +42 -0
- data/app/components/alchemy/admin/resource/select_filter.rb +43 -0
- data/app/components/alchemy/admin/toolbar_button.rb +5 -2
- data/app/components/alchemy/ingredients/number_view.rb +18 -0
- data/app/controllers/alchemy/admin/attachments_controller.rb +8 -15
- data/app/controllers/alchemy/admin/clipboard_controller.rb +2 -6
- data/app/controllers/alchemy/admin/elements_controller.rb +1 -1
- data/app/controllers/alchemy/admin/languages_controller.rb +1 -1
- data/app/controllers/alchemy/admin/pages_controller.rb +15 -15
- data/app/controllers/alchemy/admin/pictures_controller.rb +9 -5
- data/app/controllers/alchemy/admin/resources_controller.rb +16 -106
- data/app/controllers/alchemy/attachments_controller.rb +43 -14
- data/app/controllers/alchemy/messages_controller.rb +1 -1
- data/app/controllers/alchemy/pages_controller.rb +7 -2
- data/app/controllers/concerns/alchemy/admin/resource_filter.rb +92 -0
- data/app/decorators/alchemy/element_editor.rb +5 -48
- data/app/decorators/alchemy/ingredient_editor.rb +3 -53
- data/app/helpers/alchemy/admin/base_helper.rb +14 -84
- data/app/helpers/alchemy/admin/elements_helper.rb +4 -4
- data/app/helpers/alchemy/admin/pages_helper.rb +1 -1
- data/app/helpers/alchemy/base_helper.rb +0 -30
- data/app/helpers/alchemy/elements_block_helper.rb +0 -14
- data/app/helpers/alchemy/pages_helper.rb +1 -1
- data/{lib → app/helpers}/alchemy/resources_helper.rb +5 -45
- data/app/javascript/alchemy_admin/components/action.js +2 -0
- data/app/javascript/alchemy_admin/components/alchemy_html_element.js +3 -3
- data/app/javascript/alchemy_admin/components/datepicker.js +10 -2
- data/app/javascript/alchemy_admin/components/element_editor/delete_element_button.js +7 -7
- data/app/javascript/alchemy_admin/components/element_editor.js +1 -1
- data/app/javascript/alchemy_admin/components/index.js +1 -0
- data/app/javascript/alchemy_admin/components/remote_select.js +4 -1
- data/app/javascript/alchemy_admin/components/tags_autocomplete.js +5 -1
- data/app/javascript/alchemy_admin/components/tinymce.js +4 -2
- data/app/javascript/alchemy_admin/components/update_check.js +42 -0
- data/app/javascript/alchemy_admin/components/uploader/file_upload.js +15 -8
- data/app/javascript/alchemy_admin/components/uploader/progress.js +12 -6
- data/app/javascript/alchemy_admin/components/uploader.js +4 -2
- data/app/javascript/alchemy_admin/confirm_dialog.js +27 -57
- data/app/javascript/alchemy_admin/dirty.js +3 -2
- data/app/javascript/alchemy_admin/i18n.js +15 -16
- data/app/javascript/alchemy_admin/initializer.js +1 -49
- data/app/javascript/alchemy_admin/utils/ajax.js +51 -44
- data/app/javascript/alchemy_admin.js +3 -8
- data/app/models/alchemy/admin/filters/base.rb +38 -0
- data/app/models/alchemy/admin/filters/checkbox.rb +24 -0
- data/app/models/alchemy/admin/filters/datepicker.rb +53 -0
- data/app/models/alchemy/admin/filters/select.rb +70 -0
- data/app/models/alchemy/admin/resource_name.rb +27 -0
- data/app/models/alchemy/attachment.rb +51 -34
- data/app/models/alchemy/base_record.rb +2 -0
- data/app/models/alchemy/element/definitions.rb +1 -1
- data/app/models/alchemy/element/element_ingredients.rb +6 -6
- data/app/models/alchemy/element/presenters.rb +3 -12
- data/app/models/alchemy/element.rb +9 -27
- data/app/models/alchemy/element_definition.rb +160 -0
- data/app/models/alchemy/ingredient.rb +10 -43
- data/app/models/alchemy/ingredient_definition.rb +134 -0
- data/app/models/alchemy/ingredient_validator.rb +7 -3
- data/app/models/alchemy/ingredients/number.rb +19 -0
- data/app/models/alchemy/language.rb +0 -14
- data/app/models/alchemy/message.rb +3 -7
- data/app/models/alchemy/node.rb +1 -1
- data/app/models/alchemy/page/{page_layouts.rb → definitions.rb} +12 -19
- data/app/models/alchemy/page/fixed_attributes.rb +1 -1
- data/app/models/alchemy/page/page_elements.rb +13 -14
- data/app/models/alchemy/page/page_natures.rb +7 -7
- data/app/models/alchemy/page/page_scopes.rb +1 -1
- data/app/models/alchemy/page.rb +11 -33
- data/app/models/alchemy/page_definition.rb +115 -0
- data/app/models/alchemy/picture.rb +69 -79
- data/app/models/alchemy/picture_variant.rb +115 -5
- data/{lib → app/models}/alchemy/resource.rb +4 -18
- data/{lib → app/models}/alchemy/searchable_resource.rb +15 -0
- data/app/models/alchemy/site/layout.rb +5 -5
- data/app/models/alchemy/site.rb +0 -15
- data/app/models/alchemy/storage_adapter/active_storage/attachment_url.rb +41 -0
- data/app/models/alchemy/storage_adapter/active_storage/picture_url.rb +55 -0
- data/app/models/alchemy/storage_adapter/active_storage/preprocessor.rb +40 -0
- data/app/models/alchemy/storage_adapter/active_storage.rb +173 -0
- data/app/models/alchemy/{attachment/url.rb → storage_adapter/dragonfly/attachment_url.rb} +12 -12
- data/app/models/alchemy/{picture/url.rb → storage_adapter/dragonfly/picture_url.rb} +28 -12
- data/app/models/alchemy/{picture → storage_adapter/dragonfly}/preprocessor.rb +4 -4
- data/app/models/alchemy/storage_adapter/dragonfly.rb +183 -0
- data/app/models/alchemy/storage_adapter.rb +74 -0
- data/app/models/concerns/alchemy/picture_thumbnails.rb +19 -6
- data/app/serializers/alchemy/element_serializer.rb +0 -1
- data/app/services/alchemy/dragonfly_to_image_processing.rb +100 -0
- data/app/stylesheets/alchemy/_defaults.scss +3 -0
- data/app/stylesheets/alchemy/_extends.scss +69 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/_mixins.scss +36 -49
- data/app/stylesheets/alchemy/_variables.scss +5 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/archive.scss +20 -37
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/base.scss +16 -14
- data/app/stylesheets/alchemy/admin/buttons.scss +160 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/clipboard.scss +2 -2
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/dashboard.scss +13 -16
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/dialogs.scss +23 -16
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/elements.scss +150 -105
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/errors.scss +5 -5
- data/app/stylesheets/alchemy/admin/filters.scss +58 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/flatpickr.scss +53 -60
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/form_fields.scss +21 -7
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/forms.scss +31 -19
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/frame.scss +20 -16
- data/app/stylesheets/alchemy/admin/hints.scss +5 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/icons.scss +10 -1
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/image_library.scss +10 -8
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/images.scss +1 -1
- data/app/stylesheets/alchemy/admin/labels.scss +5 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/lists.scss +3 -3
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/navigation.scss +61 -55
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/nodes.scss +21 -18
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/notices.scss +18 -18
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/page-select.scss +2 -2
- data/app/stylesheets/alchemy/admin/pagination.scss +144 -0
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/preview_window.scss +8 -6
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/print.scss +1 -1
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/resource_info.scss +8 -5
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/search.scss +9 -6
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/selects.scss +49 -37
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/shoelace.scss +5 -6
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/sitemap.scss +38 -33
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/tables.scss +6 -4
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/tags.scss +6 -4
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/toolbar.scss +12 -6
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/typography.scss +2 -2
- data/app/{assets/stylesheets → stylesheets}/alchemy/admin/upload.scss +7 -5
- data/app/stylesheets/alchemy/admin.scss +44 -0
- data/app/stylesheets/alchemy/custom-properties.css +244 -0
- data/app/stylesheets/alchemy/welcome.scss +75 -0
- data/app/{assets/stylesheets → stylesheets}/tinymce/skins/content/alchemy/content.scss +8 -9
- data/app/stylesheets/tinymce/skins/ui/alchemy/content.scss +1 -0
- data/app/{assets/stylesheets → stylesheets}/tinymce/skins/ui/alchemy/skin.scss +133 -136
- data/app/views/alchemy/admin/attachments/_files_list.html.erb +2 -2
- data/app/views/alchemy/admin/attachments/_overlay_file_list.html.erb +1 -1
- data/app/views/alchemy/admin/{elements/_clipboard_button.html.erb → clipboard/_button.html.erb} +3 -5
- data/app/views/alchemy/admin/clipboard/_update_nested_element_button.turbo_stream.erb +11 -0
- data/app/views/alchemy/admin/clipboard/clear.turbo_stream.erb +4 -0
- data/app/views/alchemy/admin/clipboard/index.html.erb +15 -13
- data/app/views/alchemy/admin/clipboard/insert.turbo_stream.erb +18 -0
- data/app/views/alchemy/admin/clipboard/remove.turbo_stream.erb +9 -0
- data/app/views/alchemy/admin/dashboard/info.html.erb +17 -31
- data/app/views/alchemy/admin/elements/_element.html.erb +4 -8
- data/app/views/alchemy/admin/elements/_form.html.erb +1 -1
- data/app/views/alchemy/admin/elements/_header.html.erb +1 -0
- data/app/views/alchemy/admin/elements/_toolbar.html.erb +4 -6
- data/app/views/alchemy/admin/elements/create.turbo_stream.erb +2 -1
- data/app/views/alchemy/admin/elements/index.html.erb +2 -2
- data/app/views/alchemy/admin/ingredients/_file_fields.html.erb +3 -16
- data/app/views/alchemy/admin/ingredients/_picture_fields.html.erb +0 -9
- data/app/views/alchemy/admin/languages/_form.html.erb +1 -1
- data/app/views/alchemy/admin/languages/_table.html.erb +1 -1
- data/app/views/alchemy/admin/languages/index.html.erb +5 -2
- data/app/views/alchemy/admin/layoutpages/index.html.erb +1 -12
- data/app/views/alchemy/admin/pages/_form.html.erb +2 -2
- data/app/views/alchemy/admin/pages/_page.html.erb +2 -3
- data/app/views/alchemy/admin/pages/_toolbar.html.erb +1 -15
- data/app/views/alchemy/admin/pages/index.html.erb +1 -1
- data/app/views/alchemy/admin/partials/_remote_search_form.html.erb +9 -12
- data/app/views/alchemy/admin/partials/_search_form.html.erb +4 -9
- data/app/views/alchemy/admin/pictures/_archive.html.erb +4 -7
- data/app/views/alchemy/admin/pictures/_archive_overlay.html.erb +2 -1
- data/app/views/alchemy/admin/pictures/_filter_and_size_bar.html.erb +1 -1
- data/app/views/alchemy/admin/pictures/index.html.erb +2 -7
- data/app/views/alchemy/admin/resources/_applied_filters.html.erb +8 -0
- data/app/views/alchemy/admin/resources/_filter_bar.html.erb +11 -21
- data/app/views/alchemy/admin/resources/_pagination.html.erb +6 -0
- data/app/views/alchemy/admin/resources/_per_page_select.html.erb +4 -2
- data/app/views/alchemy/admin/resources/_resource_table.html.erb +1 -1
- data/app/views/alchemy/admin/resources/_table_header.html.erb +1 -15
- data/app/views/alchemy/admin/sites/index.html.erb +5 -1
- data/app/views/alchemy/admin/styleguide/index.html.erb +8 -0
- data/app/views/alchemy/admin/tags/index.html.erb +1 -1
- data/app/views/alchemy/admin/tinymce/_setup.html.erb +7 -7
- data/app/{javascript/alchemy_admin/locales/en.js → views/alchemy/admin/translations/_en.js} +5 -2
- data/app/views/alchemy/admin/uploader/_button.html.erb +1 -1
- data/app/views/alchemy/admin/uploader/_setup.html.erb +4 -4
- data/app/views/alchemy/base/redirect.js.erb +1 -1
- data/app/views/alchemy/ingredients/_number_editor.html.erb +24 -0
- data/app/views/alchemy/no_index.html.erb +31 -0
- data/app/views/alchemy/welcome.html.erb +12 -10
- data/app/views/kaminari/alchemy/_first_page.html.erb +5 -3
- data/app/views/kaminari/alchemy/_last_page.html.erb +5 -3
- data/app/views/kaminari/alchemy/_next_page.html.erb +5 -3
- data/app/views/kaminari/alchemy/_paginator.html.erb +18 -13
- data/app/views/kaminari/alchemy/_prev_page.html.erb +5 -3
- data/app/views/layouts/alchemy/admin.html.erb +5 -9
- data/bun.lockb +0 -0
- data/bundles/remixicon.mjs +153 -0
- data/config/alchemy/config.yml +3 -2
- data/config/initializers/dragonfly.rb +0 -1
- data/config/initializers/mime_types.rb +1 -0
- data/config/locales/alchemy.en.yml +32 -14
- data/config/routes.rb +0 -2
- data/eslint.config.js +2 -1
- data/lib/alchemy/admin/preview_url.rb +4 -5
- data/lib/alchemy/cache_digests/template_tracker.rb +6 -9
- data/lib/alchemy/config_missing.rb +14 -0
- data/lib/alchemy/configuration/base_option.rb +24 -0
- data/lib/alchemy/configuration/boolean_option.rb +16 -0
- data/lib/alchemy/configuration/class_option.rb +15 -0
- data/lib/alchemy/configuration/class_set_option.rb +46 -0
- data/lib/alchemy/configuration/integer_list_option.rb +13 -0
- data/lib/alchemy/configuration/integer_option.rb +12 -0
- data/lib/alchemy/configuration/list_option.rb +22 -0
- data/lib/alchemy/configuration/regexp_option.rb +11 -0
- data/lib/alchemy/configuration/string_list_option.rb +13 -0
- data/lib/alchemy/configuration/string_option.rb +11 -0
- data/lib/alchemy/configuration.rb +115 -0
- data/lib/alchemy/configuration_methods.rb +3 -1
- data/lib/alchemy/configurations/default_language.rb +12 -0
- data/lib/alchemy/configurations/default_site.rb +10 -0
- data/lib/alchemy/configurations/format_matchers.rb +11 -0
- data/lib/alchemy/configurations/mailer.rb +16 -0
- data/lib/alchemy/configurations/main.rb +216 -0
- data/lib/alchemy/configurations/preview.rb +32 -0
- data/lib/alchemy/configurations/sitemap.rb +10 -0
- data/lib/alchemy/configurations/uploader.rb +34 -0
- data/lib/alchemy/engine.rb +65 -17
- data/lib/alchemy/hints.rb +3 -7
- data/lib/alchemy/on_page_layout.rb +2 -2
- data/lib/alchemy/propshaft/tinymce_asset.rb +15 -0
- data/lib/alchemy/seeder.rb +2 -2
- data/lib/alchemy/tasks/usage.rb +4 -4
- data/lib/alchemy/test_support/config_stubbing.rb +1 -7
- data/lib/alchemy/test_support/factories/attachment_factory.rb +13 -2
- data/lib/alchemy/test_support/factories/language_factory.rb +1 -1
- data/lib/alchemy/test_support/factories/page_factory.rb +2 -3
- data/lib/alchemy/test_support/factories/picture_factory.rb +30 -2
- data/lib/alchemy/test_support/factories/site_factory.rb +2 -2
- data/lib/alchemy/test_support/having_crop_action_examples.rb +2 -2
- data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +80 -26
- data/lib/alchemy/test_support/shared_ingredient_examples.rb +5 -5
- data/lib/alchemy/upgrader/.keep +0 -0
- data/lib/alchemy/upgrader/eight_zero.rb +14 -0
- data/lib/alchemy/upgrader.rb +33 -20
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy.rb +192 -170
- data/lib/alchemy_cms.rb +1 -7
- data/lib/generators/alchemy/ingredient/ingredient_generator.rb +0 -3
- data/lib/generators/alchemy/install/files/_article.html.erb +6 -4
- data/lib/generators/alchemy/install/files/alchemy.en.yml +22 -3
- data/lib/generators/alchemy/install/files/application.html.erb +5 -0
- data/lib/generators/alchemy/install/install_generator.rb +5 -14
- data/lib/generators/alchemy/install/templates/alchemy.rb.tt +196 -0
- data/lib/generators/alchemy/install/templates/dragonfly.rb.tt +0 -1
- data/lib/generators/alchemy/install/templates/elements.yml.tt +3 -1
- data/lib/generators/alchemy/install/templates/menus.yml.tt +1 -1
- data/lib/generators/alchemy/install/templates/page_layouts.yml.tt +2 -2
- data/lib/generators/alchemy/page_layouts/page_layouts_generator.rb +2 -2
- data/lib/tasks/alchemy/assets.rake +14 -0
- data/lib/tasks/alchemy/upgrade.rake +12 -47
- data/vendor/javascript/tinymce.min.js +1 -1
- data/vitest.config.js +21 -0
- metadata +181 -180
- data/app/assets/builds/alchemy/admin/page-select.css.map +0 -1
- data/app/assets/builds/alchemy/admin/print.css.map +0 -1
- data/app/assets/builds/alchemy/admin.css.map +0 -1
- data/app/assets/builds/alchemy/custom-properties.css.map +0 -1
- data/app/assets/builds/alchemy/welcome.css.map +0 -1
- data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css.map +0 -1
- data/app/assets/builds/tinymce/skins/ui/alchemy/skin.min.css.map +0 -1
- data/app/assets/javascripts/alchemy/admin.js +0 -10
- data/app/assets/stylesheets/alchemy/_defaults.scss +0 -3
- data/app/assets/stylesheets/alchemy/_deprecated_variables.scss +0 -45
- data/app/assets/stylesheets/alchemy/_deprecation.scss +0 -17
- data/app/assets/stylesheets/alchemy/_extends.scss +0 -62
- data/app/assets/stylesheets/alchemy/_variables.scss +0 -201
- data/app/assets/stylesheets/alchemy/admin/buttons.scss +0 -124
- data/app/assets/stylesheets/alchemy/admin/hints.scss +0 -5
- data/app/assets/stylesheets/alchemy/admin/labels.scss +0 -3
- data/app/assets/stylesheets/alchemy/admin/pagination.scss +0 -92
- data/app/assets/stylesheets/alchemy/admin.scss +0 -42
- data/app/assets/stylesheets/alchemy/custom-properties.css +0 -98
- data/app/assets/stylesheets/alchemy/welcome.scss +0 -57
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.css +0 -711
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.inline.css +0 -705
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.inline.min.css +0 -7
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.min.css +0 -7
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.mobile.css +0 -29
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.mobile.min.css +0 -7
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/skin.mobile.css +0 -677
- data/app/assets/stylesheets/tinymce/skins/ui/alchemy/skin.mobile.min.css +0 -7
- data/app/controllers/alchemy/elements_controller.rb +0 -32
- data/app/models/alchemy/element/dom_id.rb +0 -31
- data/app/models/alchemy/picture/calculations.rb +0 -49
- data/app/models/alchemy/picture/transformations.rb +0 -115
- data/app/views/alchemy/admin/attachments/destroy.js.erb +0 -1
- data/app/views/alchemy/admin/clipboard/clear.js.erb +0 -3
- data/app/views/alchemy/admin/clipboard/insert.js.erb +0 -29
- data/app/views/alchemy/admin/clipboard/remove.js.erb +0 -10
- data/app/views/alchemy/admin/resources/_filter.html.erb +0 -12
- data/app/views/alchemy/admin/resources/_resource.html.erb +0 -34
- data/app/views/alchemy/admin/resources/_table.html.erb +0 -29
- data/app/views/alchemy/elements/show.html.erb +0 -1
- data/app/views/alchemy/elements/show.js.erb +0 -1
- data/app/views/alchemy/ingredients/_audio_view.html.erb +0 -1
- data/app/views/alchemy/ingredients/_boolean_view.html.erb +0 -1
- data/app/views/alchemy/ingredients/_datetime_view.html.erb +0 -3
- data/app/views/alchemy/ingredients/_file_view.html.erb +0 -4
- data/app/views/alchemy/ingredients/_headline_view.html.erb +0 -4
- data/app/views/alchemy/ingredients/_html_view.html.erb +0 -1
- data/app/views/alchemy/ingredients/_link_view.html.erb +0 -4
- data/app/views/alchemy/ingredients/_node_view.html.erb +0 -1
- data/app/views/alchemy/ingredients/_page_view.html.erb +0 -1
- data/app/views/alchemy/ingredients/_picture_view.html.erb +0 -4
- data/app/views/alchemy/ingredients/_richtext_view.html.erb +0 -3
- data/app/views/alchemy/ingredients/_select_view.html.erb +0 -1
- data/app/views/alchemy/ingredients/_text_view.html.erb +0 -4
- data/app/views/alchemy/ingredients/_video_view.html.erb +0 -3
- data/babel.config.js +0 -12
- data/config/initializers/assets.rb +0 -4
- data/lib/alchemy/config.rb +0 -114
- data/lib/alchemy/element_definition.rb +0 -73
- data/lib/alchemy/page_layout.rb +0 -73
- data/lib/alchemy/resource_filter.rb +0 -40
- data/lib/alchemy/upgrader/seven_point_four.rb +0 -26
- data/lib/alchemy/upgrader/seven_point_three.rb +0 -52
- data/lib/generators/alchemy/ingredient/templates/view.html.erb +0 -1
- data/lib/generators/alchemy/install/files/alchemy_admin.js +0 -1
- data/lib/generators/alchemy/install/files/all.js +0 -11
- data/lib/generators/alchemy/install/files/article.css +0 -25
- data/vendor/assets/images/remixicon.symbol.svg +0 -11
- /data/app/{assets/stylesheets → stylesheets}/alchemy/_fonts.scss +0 -0
- /data/app/{assets/stylesheets → stylesheets}/alchemy/admin/attachment-select.scss +0 -0
- /data/app/{assets/stylesheets → stylesheets}/alchemy/admin/attachments.scss +0 -0
- /data/app/{assets/stylesheets → stylesheets}/alchemy/admin/flash.scss +0 -0
- /data/app/{assets/stylesheets → stylesheets}/alchemy/admin/list_filter.scss +0 -0
- /data/app/{assets/stylesheets → stylesheets}/alchemy/admin/node-select.scss +0 -0
- /data/app/{assets/stylesheets → stylesheets}/alchemy/admin/spinner.scss +0 -0
- /data/app/{assets/stylesheets → stylesheets}/tinymce/skins/skintool.json +0 -0
- /data/app/{assets/stylesheets → stylesheets}/tinymce/skins/ui/alchemy/fonts/tinymce-mobile.woff +0 -0
@@ -0,0 +1,216 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "alchemy/configuration"
|
4
|
+
require "alchemy/configurations/default_language"
|
5
|
+
require "alchemy/configurations/default_site"
|
6
|
+
require "alchemy/configurations/format_matchers"
|
7
|
+
require "alchemy/configurations/mailer"
|
8
|
+
require "alchemy/configurations/preview"
|
9
|
+
require "alchemy/configurations/sitemap"
|
10
|
+
require "alchemy/configurations/uploader"
|
11
|
+
require "alchemy/deprecation"
|
12
|
+
|
13
|
+
module Alchemy
|
14
|
+
module Configurations
|
15
|
+
class Main < Alchemy::Configuration
|
16
|
+
# == This is the global Alchemy configuration class
|
17
|
+
|
18
|
+
# === Auto Log Out Time
|
19
|
+
#
|
20
|
+
# The amount of time of inactivity in minutes after which the user is kicked out of his current session.
|
21
|
+
#
|
22
|
+
# NOTE: This is only active in production environments
|
23
|
+
#
|
24
|
+
option :auto_logout_time, :integer, default: 30
|
25
|
+
|
26
|
+
# === Page caching
|
27
|
+
#
|
28
|
+
# Enable/Disable page caching globally.
|
29
|
+
#
|
30
|
+
# NOTE: You can enable/disable page caching for single Alchemy::Definitions in the page_layout.yml file.
|
31
|
+
#
|
32
|
+
option :cache_pages, :boolean, default: true
|
33
|
+
|
34
|
+
# === Sitemap
|
35
|
+
#
|
36
|
+
# Alchemy creates a XML, Google compatible, sitemap for you.
|
37
|
+
#
|
38
|
+
# The url is: http://your-domain.tld/sitemap.xml
|
39
|
+
#
|
40
|
+
# ==== Config Options:
|
41
|
+
#
|
42
|
+
# show_root [Boolean] # Show language root page in sitemap?
|
43
|
+
# show_flag [Boolean] # Enables the Checkbox in Page#update overlay. So your customer can set the visibility of pages in the sitemap.
|
44
|
+
configuration :sitemap, Sitemap
|
45
|
+
|
46
|
+
# === Default items per page in admin views
|
47
|
+
#
|
48
|
+
# In Alchemy's Admin, change how many items you would get shown per page by Kaminari
|
49
|
+
option :items_per_page, :integer, default: 15
|
50
|
+
|
51
|
+
# === Preview window URL configuration
|
52
|
+
#
|
53
|
+
# By default Alchemy uses its internal page preview renderer,
|
54
|
+
# but you can configure it to be any URL instead.
|
55
|
+
#
|
56
|
+
# Basic Auth is supported.
|
57
|
+
#
|
58
|
+
# preview:
|
59
|
+
# host: https://www.my-static-site.com
|
60
|
+
# auth:
|
61
|
+
# username: <%= ENV["BASIC_AUTH_USERNAME"] %>
|
62
|
+
# password: <%= ENV["BASIC_AUTH_PASSWORD"] %>
|
63
|
+
#
|
64
|
+
# Preview config per site is supported as well.
|
65
|
+
#
|
66
|
+
# preview:
|
67
|
+
# My site name:
|
68
|
+
# host: https://www.my-static-site.com
|
69
|
+
# auth:
|
70
|
+
# username: <%= ENV["BASIC_AUTH_USERNAME"] %>
|
71
|
+
# password: <%= ENV["BASIC_AUTH_PASSWORD"] %>
|
72
|
+
#
|
73
|
+
configuration :preview, Preview
|
74
|
+
|
75
|
+
# === Picture rendering settings
|
76
|
+
#
|
77
|
+
# Alchemy uses Dragonfly to render images. Settings for image rendering are specific to elements and are defined in elements.yml
|
78
|
+
#
|
79
|
+
# Example:
|
80
|
+
# - name: some_element
|
81
|
+
# ingredients:
|
82
|
+
# - role: some_picture
|
83
|
+
# type: Picture
|
84
|
+
# settings:
|
85
|
+
# hint: true
|
86
|
+
# crop: true # turns on image cropping
|
87
|
+
# size: '500x500' # image will be cropped to this size
|
88
|
+
#
|
89
|
+
# See http://markevans.github.com/dragonfly for further info.
|
90
|
+
#
|
91
|
+
# ==== Global Options:
|
92
|
+
#
|
93
|
+
# output_image_quality [Integer] # If image gets rendered as JPG or WebP this is the quality setting for it. (Default 85)
|
94
|
+
# preprocess_image_resize [String] # Use this option to resize images to the given size when they are uploaded to the image library. Downsizing example: '1000x1000>' (Default nil)
|
95
|
+
# image_output_format [String] # The global image output format setting. (Default +original+)
|
96
|
+
#
|
97
|
+
# NOTE: You can always override the output format in the settings of your ingredients in elements.yml, I.E. {format: 'gif'}
|
98
|
+
#
|
99
|
+
option :output_image_quality, :integer, default: 85
|
100
|
+
alias_method :output_image_jpg_quality, :output_image_quality
|
101
|
+
deprecate output_image_jpg_quality: :output_image_quality, deprecator: Alchemy::Deprecation
|
102
|
+
alias_method :output_image_jpg_quality=, :output_image_quality=
|
103
|
+
deprecate "output_image_jpg_quality=": :output_image_quality=, deprecator: Alchemy::Deprecation
|
104
|
+
option :preprocess_image_resize, :string
|
105
|
+
option :image_output_format, :string, default: "original"
|
106
|
+
option :sharpen_images, :boolean, default: false
|
107
|
+
|
108
|
+
# This is used by the seeder to create the default site.
|
109
|
+
configuration :default_site, DefaultSite
|
110
|
+
|
111
|
+
# This is the default language when seeding.
|
112
|
+
configuration :default_language, DefaultLanguage
|
113
|
+
|
114
|
+
# === Mailer Settings:
|
115
|
+
#
|
116
|
+
# To send emails via contact forms, you can create your form fields here and set which fields are to be validated.
|
117
|
+
#
|
118
|
+
# === Validating fields:
|
119
|
+
#
|
120
|
+
# Pass the field name as a symbol and a message_id (will be translated) to :validate_fields:
|
121
|
+
#
|
122
|
+
# ==== Options:
|
123
|
+
#
|
124
|
+
# page_layout_name: [String] # A +Alchemy::PageDefinition+ name. Used to render the contactform on a page with this layout.
|
125
|
+
# fields: [Array] # An Array of fieldnames.
|
126
|
+
# validate_fields: [Array] # An Array of fieldnames to be validated on presence.
|
127
|
+
#
|
128
|
+
# ==== Translating validation messages:
|
129
|
+
#
|
130
|
+
# The validation messages are passed through ::I18n.t so you can translate it in your language yml file.
|
131
|
+
#
|
132
|
+
# ==== Example:
|
133
|
+
#
|
134
|
+
# de:
|
135
|
+
# activemodel:
|
136
|
+
# attributes:
|
137
|
+
# alchemy/message:
|
138
|
+
# firstname: Vorname
|
139
|
+
#
|
140
|
+
configuration :mailer, Mailer
|
141
|
+
|
142
|
+
# === User roles
|
143
|
+
#
|
144
|
+
# You can add own user roles.
|
145
|
+
#
|
146
|
+
# Further documentation for the auth system used please visit:
|
147
|
+
#
|
148
|
+
# https://github.com/ryanb/cancan/wiki
|
149
|
+
#
|
150
|
+
# ==== Translating User roles
|
151
|
+
#
|
152
|
+
# Userroles can be translated inside your the language yml file under:
|
153
|
+
#
|
154
|
+
# alchemy:
|
155
|
+
# user_roles:
|
156
|
+
# rolename: Name of the role
|
157
|
+
#
|
158
|
+
option :user_roles, :string_list, default: %w[member author editor admin]
|
159
|
+
|
160
|
+
# === Uploader Settings
|
161
|
+
#
|
162
|
+
# upload_limit [Integer] # Set an amount of files upload limit of files which can be uploaded at once. Set 0 for unlimited.
|
163
|
+
# file_size_limit* [Integer] # Set a file size limit in mega bytes for a per file limit.
|
164
|
+
#
|
165
|
+
# *) Allow filetypes to upload. Pass * to allow all kind of files.
|
166
|
+
#
|
167
|
+
configuration :uploader, Uploader
|
168
|
+
|
169
|
+
# === Link Target Options
|
170
|
+
#
|
171
|
+
# Values for the link target selectbox inside the page link overlay.
|
172
|
+
# The value gets attached as a data-link-target attribute to the link.
|
173
|
+
#
|
174
|
+
# == Example:
|
175
|
+
#
|
176
|
+
# Open all links set to overlay inside an jQuery UI Dialog Window.
|
177
|
+
#
|
178
|
+
# jQuery(a[data-link-target="overlay"]).dialog();
|
179
|
+
#
|
180
|
+
option :link_target_options, :string_list, default: %w[blank]
|
181
|
+
|
182
|
+
# === Format matchers
|
183
|
+
#
|
184
|
+
# Named aliases for regular expressions that can be used in various places.
|
185
|
+
# The most common use case is the format validation of ingredients, or attribute validations of your individual models.
|
186
|
+
#
|
187
|
+
# == Example:
|
188
|
+
#
|
189
|
+
# validates_format_of :url, with: Alchemy.config.format_matchers.url
|
190
|
+
#
|
191
|
+
configuration :format_matchers, FormatMatchers
|
192
|
+
|
193
|
+
# The layout used for rendering the +alchemy/admin/pages#show+ action.
|
194
|
+
option :admin_page_preview_layout, :string, default: "application"
|
195
|
+
|
196
|
+
# The sizes for the preview size select in the page editor.
|
197
|
+
option :page_preview_sizes, :integer_list, default: [360, 640, 768, 1024, 1280, 1440]
|
198
|
+
|
199
|
+
# Enable full text search configuration
|
200
|
+
#
|
201
|
+
# It enables a searchable checkbox in the page form to toggle
|
202
|
+
# the searchable field. These information can used in a search
|
203
|
+
# plugin (e.g. https://github.com/AlchemyCMS/alchemy-pg_search).
|
204
|
+
#
|
205
|
+
# == Example
|
206
|
+
#
|
207
|
+
# # config/initializers/alchemy.rb
|
208
|
+
# Alchemy.config.page_searchable_checkbox = true
|
209
|
+
option :show_page_searchable_checkbox, :boolean, default: false
|
210
|
+
|
211
|
+
# The storage adapter for Pictures and Attachments
|
212
|
+
#
|
213
|
+
option :storage_adapter, :string, default: "dragonfly"
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
module Configurations
|
5
|
+
class Preview < Alchemy::Configuration
|
6
|
+
class PreviewAuth < Alchemy::Configuration
|
7
|
+
option :username, :string
|
8
|
+
option :password, :string
|
9
|
+
end
|
10
|
+
|
11
|
+
attr_reader :per_site_configs
|
12
|
+
|
13
|
+
def initialize(configuration = {})
|
14
|
+
@per_site_configs = []
|
15
|
+
configuration = configuration.with_indifferent_access
|
16
|
+
configuration.except(:host, :site_name, :auth).keys.each do |site_name|
|
17
|
+
@per_site_configs << Preview.new(configuration[site_name].merge(site_name: site_name))
|
18
|
+
end
|
19
|
+
super(configuration.slice(:host, :site_name, :auth))
|
20
|
+
end
|
21
|
+
|
22
|
+
option :site_name, :string, default: "*"
|
23
|
+
option :host, :string
|
24
|
+
|
25
|
+
configuration :auth, PreviewAuth
|
26
|
+
|
27
|
+
def for_site(site)
|
28
|
+
per_site_configs.detect { _1.site_name == site.name } || self
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
module Configurations
|
5
|
+
class Uploader < Alchemy::Configuration
|
6
|
+
class AllowedFileTypes < Alchemy::Configuration
|
7
|
+
option :alchemy_attachments, :string_list, default: ["*"]
|
8
|
+
option :alchemy_pictures, :string_list, default: %w[jpg jpeg gif png svg webp]
|
9
|
+
|
10
|
+
def set(configuration_hash)
|
11
|
+
super(configuration_hash.transform_keys { transform_key(_1) })
|
12
|
+
end
|
13
|
+
|
14
|
+
def get(key)
|
15
|
+
super(transform_key(key))
|
16
|
+
end
|
17
|
+
alias_method :[], :get
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def transform_key(key)
|
22
|
+
key.to_s.tr("/", "_")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Number of files that can be uploaded at once
|
27
|
+
option :upload_limit, :integer, default: 50
|
28
|
+
# Megabytes
|
29
|
+
option :file_size_limit, :integer, default: 100
|
30
|
+
|
31
|
+
configuration :allowed_filetypes, AllowedFileTypes
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
data/lib/alchemy/engine.rb
CHANGED
@@ -16,13 +16,29 @@ module Alchemy
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
initializer "alchemy.
|
20
|
-
|
19
|
+
initializer "alchemy.assets" do |app|
|
20
|
+
if defined?(Sprockets)
|
21
|
+
require_relative "../non_stupid_digest_assets"
|
22
|
+
NonStupidDigestAssets.whitelist += [/^tinymce\//]
|
23
|
+
app.config.assets.precompile << "alchemy_manifest.js"
|
24
|
+
end
|
21
25
|
end
|
22
26
|
|
23
27
|
initializer "alchemy.admin_stylesheets" do |app|
|
24
|
-
|
25
|
-
|
28
|
+
if defined?(Sprockets)
|
29
|
+
Alchemy.admin_stylesheets.each do |stylesheet|
|
30
|
+
app.config.assets.precompile << stylesheet
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
initializer "alchemy.propshaft" do |app|
|
36
|
+
if defined?(Propshaft)
|
37
|
+
if app.config.assets.server
|
38
|
+
# Monkey-patch Propshaft::Asset to enable access
|
39
|
+
# of TinyMCE assets without a hash digest.
|
40
|
+
require_relative "propshaft/tinymce_asset"
|
41
|
+
end
|
26
42
|
end
|
27
43
|
end
|
28
44
|
|
@@ -46,18 +62,18 @@ module Alchemy
|
|
46
62
|
end
|
47
63
|
end
|
48
64
|
|
49
|
-
|
50
|
-
elements_reloader =
|
65
|
+
config.to_prepare do
|
66
|
+
elements_reloader = Rails.application.config.file_watcher.new([ElementDefinition.definitions_file_path]) do
|
51
67
|
Rails.logger.info "[#{engine_name}] Reloading Element Definitions."
|
52
68
|
ElementDefinition.reset!
|
53
69
|
end
|
54
|
-
page_layouts_reloader =
|
70
|
+
page_layouts_reloader = Rails.application.config.file_watcher.new([PageDefinition.layouts_file_path]) do
|
55
71
|
Rails.logger.info "[#{engine_name}] Reloading Page Layouts."
|
56
|
-
|
72
|
+
PageDefinition.reset!
|
57
73
|
end
|
58
74
|
[elements_reloader, page_layouts_reloader].each do |reloader|
|
59
|
-
|
60
|
-
|
75
|
+
Rails.application.reloaders << reloader
|
76
|
+
Rails.application.reloader.to_run do
|
61
77
|
reloader.execute_if_updated
|
62
78
|
end
|
63
79
|
end
|
@@ -79,13 +95,36 @@ module Alchemy
|
|
79
95
|
down_arrow: '<alchemy-icon name="arrow-down" size="1x"></alchemy-icon>'
|
80
96
|
}
|
81
97
|
end
|
98
|
+
|
99
|
+
ActiveSupport.on_load(:active_storage_blob) do
|
100
|
+
ActiveStorage::Blob.define_singleton_method(:ransackable_attributes) do |_auth_object|
|
101
|
+
%w[filename]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Load Alchemy configuration from YAML files
|
107
|
+
# in config/alchemy/config.yml and config/alchemy/#{Rails.env}.config.yml
|
108
|
+
# if they exist.
|
109
|
+
# This has to be done before any app initializers are loaded, so that
|
110
|
+
# the configuration is available in all initializers.
|
111
|
+
initializer "alchemy.config_yml", before: :load_config_initializers do |app|
|
112
|
+
config_directory = Rails.root.join("config", "alchemy")
|
113
|
+
main_config = config_directory.join("config.yml")
|
114
|
+
env_specific_config = config_directory.join("#{Rails.env}.config.yml")
|
115
|
+
if File.exist?(main_config)
|
116
|
+
Alchemy.config.set_from_yaml(main_config)
|
117
|
+
end
|
118
|
+
if File.exist?(env_specific_config)
|
119
|
+
Alchemy.config.set_from_yaml(env_specific_config)
|
120
|
+
end
|
82
121
|
end
|
83
122
|
|
84
123
|
config.after_initialize do
|
85
124
|
if Alchemy.user_class
|
86
125
|
ActiveSupport.on_load(:active_record) do
|
87
126
|
Alchemy.user_class.model_stamper
|
88
|
-
Alchemy.user_class.stampable(stamper_class_name: Alchemy.
|
127
|
+
Alchemy.user_class.stampable(stamper_class_name: Alchemy.user_class_name)
|
89
128
|
end
|
90
129
|
end
|
91
130
|
|
@@ -96,14 +135,23 @@ module Alchemy
|
|
96
135
|
end
|
97
136
|
end
|
98
137
|
|
99
|
-
initializer "alchemy.webp-mime_type" do
|
100
|
-
|
101
|
-
|
102
|
-
Mime::Type.register("image/webp", :webp)
|
103
|
-
end
|
138
|
+
initializer "alchemy.webp-mime_type" do |app|
|
139
|
+
webp = "image/webp"
|
140
|
+
|
104
141
|
# Dragonfly uses Rack to read the mime type and guess what
|
142
|
+
# Rack 3.0 has this included, but Rails 8 still allows Rack 2.2
|
105
143
|
unless Rack::Mime::MIME_TYPES[".webp"]
|
106
|
-
Rack::Mime::MIME_TYPES[".webp"] =
|
144
|
+
Rack::Mime::MIME_TYPES[".webp"] = webp
|
145
|
+
end
|
146
|
+
|
147
|
+
# ActiveStorage 7.2 adds support for webp, but we still support Rails 7.1
|
148
|
+
if app.config.active_storage
|
149
|
+
unless app.config.active_storage.web_image_content_types.include? webp
|
150
|
+
app.config.active_storage.web_image_content_types += [webp]
|
151
|
+
end
|
152
|
+
unless app.config.active_storage.content_types_allowed_inline.include? webp
|
153
|
+
app.config.active_storage.content_types_allowed_inline += [webp]
|
154
|
+
end
|
107
155
|
end
|
108
156
|
end
|
109
157
|
end
|
data/lib/alchemy/hints.rb
CHANGED
@@ -35,7 +35,7 @@ module Alchemy
|
|
35
35
|
# @return String
|
36
36
|
#
|
37
37
|
def hint
|
38
|
-
hint =
|
38
|
+
hint = attributes[:hint]
|
39
39
|
if hint == true
|
40
40
|
Alchemy.t(hint_translation_attribute, scope: hint_translation_scope)
|
41
41
|
else
|
@@ -43,9 +43,9 @@ module Alchemy
|
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
46
|
-
# Returns true if the
|
46
|
+
# Returns true if the definition has a hint defined
|
47
47
|
def has_hint?
|
48
|
-
!!
|
48
|
+
!!attributes[:hint]
|
49
49
|
end
|
50
50
|
|
51
51
|
private
|
@@ -53,9 +53,5 @@ module Alchemy
|
|
53
53
|
def hint_translation_attribute
|
54
54
|
name
|
55
55
|
end
|
56
|
-
|
57
|
-
def hint_translation_scope
|
58
|
-
"#{self.class.model_name.to_s.demodulize.downcase}_hints"
|
59
|
-
end
|
60
56
|
end
|
61
57
|
end
|
@@ -9,7 +9,7 @@ module Alchemy
|
|
9
9
|
# Pass a block or method name in which you have the +@page+ object available and can do
|
10
10
|
# everything as if you were in a normal controller action.
|
11
11
|
#
|
12
|
-
# You can pass a +Alchemy::
|
12
|
+
# You can pass a +Alchemy::PageDefinition+ name, an array of names, or +:all+ to
|
13
13
|
# evaluate the callback on either some specific or all the pages.
|
14
14
|
#
|
15
15
|
# == Example:
|
@@ -56,7 +56,7 @@ module Alchemy
|
|
56
56
|
# Pass a block or method name in which you have the +@page+ object available and can do
|
57
57
|
# everything as if you were in a normal controller action.
|
58
58
|
#
|
59
|
-
# Pass a +Alchemy::
|
59
|
+
# Pass a +Alchemy::PageDefinition+ name, an array of names, or +:all+ to
|
60
60
|
# evaluate the callback on either some specific or all the pages.
|
61
61
|
#
|
62
62
|
def on_page_layout(page_layouts, callback = nil, &block)
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require "propshaft/asset"
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
module Propshaft
|
5
|
+
module TinymceAsset
|
6
|
+
# Allow TinyMCE assets to be accessed (in development mode) without a digest
|
7
|
+
def fresh?(digest)
|
8
|
+
super ||
|
9
|
+
(digest.blank? && logical_path.to_s.starts_with?("tinymce/"))
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Propshaft::Asset.prepend Alchemy::Propshaft::TinymceAsset
|
data/lib/alchemy/seeder.rb
CHANGED
@@ -116,7 +116,7 @@ module Alchemy
|
|
116
116
|
# If no languages are present, create a default language based
|
117
117
|
# on the host app's Alchemy configuration.
|
118
118
|
def create_default_language!
|
119
|
-
default_language = Alchemy
|
119
|
+
default_language = Alchemy.config.default_language
|
120
120
|
if default_language
|
121
121
|
Alchemy::Language.create!(
|
122
122
|
name: default_language["name"],
|
@@ -134,7 +134,7 @@ module Alchemy
|
|
134
134
|
end
|
135
135
|
|
136
136
|
def create_default_site!
|
137
|
-
default_site = Alchemy
|
137
|
+
default_site = Alchemy.config.default_site
|
138
138
|
if default_site
|
139
139
|
Alchemy::Site.create!(name: default_site["name"], host: default_site["host"])
|
140
140
|
else
|
data/lib/alchemy/tasks/usage.rb
CHANGED
@@ -11,8 +11,8 @@ module Alchemy
|
|
11
11
|
.group(:name)
|
12
12
|
.order("count DESC, name ASC")
|
13
13
|
.map { |e| {"name" => e.name, "count" => e.count} }
|
14
|
-
Alchemy::Element.definitions.reject { |definition| res.map { |e| e["name"] }.include?
|
15
|
-
res << {"name" => definition
|
14
|
+
Alchemy::Element.definitions.reject { |definition| res.map { |e| e["name"] }.include?(definition.name) }.sort_by(&:name).each do |definition|
|
15
|
+
res << {"name" => definition.name, "count" => 0}
|
16
16
|
end
|
17
17
|
res
|
18
18
|
end
|
@@ -23,8 +23,8 @@ module Alchemy
|
|
23
23
|
.group(:page_layout)
|
24
24
|
.order("count DESC, page_layout ASC")
|
25
25
|
.map { |p| {"page_layout" => p.page_layout, "count" => p.count} }
|
26
|
-
Alchemy::
|
27
|
-
res << {"page_layout" => page_layout
|
26
|
+
Alchemy::PageDefinition.all.reject { |page_layout| res.map { |p| p["page_layout"] }.include?(page_layout.name) }.sort_by(&:name).each do |page_layout|
|
27
|
+
res << {"page_layout" => page_layout.name, "count" => 0}
|
28
28
|
end
|
29
29
|
res
|
30
30
|
end
|
@@ -17,13 +17,7 @@ module Alchemy
|
|
17
17
|
# @param value [Object] The value you want to return instead of the original one
|
18
18
|
#
|
19
19
|
def stub_alchemy_config(key, value)
|
20
|
-
allow(Alchemy
|
21
|
-
if arg == key
|
22
|
-
value
|
23
|
-
else
|
24
|
-
Alchemy::Config.show[arg.to_s]
|
25
|
-
end
|
26
|
-
end
|
20
|
+
allow(Alchemy.config).to receive(key).and_return(value)
|
27
21
|
end
|
28
22
|
end
|
29
23
|
end
|
@@ -2,9 +2,20 @@
|
|
2
2
|
|
3
3
|
FactoryBot.define do
|
4
4
|
factory :alchemy_attachment, class: "Alchemy::Attachment" do
|
5
|
-
|
6
|
-
|
5
|
+
transient do
|
6
|
+
file do
|
7
|
+
Rack::Test::UploadedFile.new(
|
8
|
+
Alchemy::Engine.root.join("lib", "alchemy", "test_support", "fixtures", "image.png")
|
9
|
+
)
|
10
|
+
end
|
7
11
|
end
|
12
|
+
|
13
|
+
after(:build) do |attachment, acc|
|
14
|
+
if acc.file
|
15
|
+
attachment.file = acc.file
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
8
19
|
name { "image" }
|
9
20
|
file_name { "image.png" }
|
10
21
|
end
|
@@ -6,7 +6,7 @@ FactoryBot.define do
|
|
6
6
|
code { ::I18n.available_locales.first.to_s }
|
7
7
|
default { true }
|
8
8
|
frontpage_name { "Intro" }
|
9
|
-
page_layout { Alchemy
|
9
|
+
page_layout { Alchemy.config.default_language.page_layout }
|
10
10
|
|
11
11
|
public { true }
|
12
12
|
|
@@ -12,7 +12,7 @@ FactoryBot.define do
|
|
12
12
|
|
13
13
|
parent do
|
14
14
|
Alchemy::Page.find_by(language_root: true, language: language) ||
|
15
|
-
FactoryBot.create(:alchemy_page, :language_root, language: language)
|
15
|
+
FactoryBot.create(:alchemy_page, :public, :language_root, language: language)
|
16
16
|
end
|
17
17
|
|
18
18
|
# This speeds up creating of pages dramatically.
|
@@ -23,7 +23,6 @@ FactoryBot.define do
|
|
23
23
|
name { language&.frontpage_name || "Intro" }
|
24
24
|
page_layout { language&.page_layout || "index" }
|
25
25
|
language_root { true }
|
26
|
-
public_on { Time.current }
|
27
26
|
parent { nil }
|
28
27
|
end
|
29
28
|
|
@@ -41,7 +40,7 @@ FactoryBot.define do
|
|
41
40
|
end
|
42
41
|
after(:create) do |page|
|
43
42
|
if page.autogenerate_elements
|
44
|
-
page.definition
|
43
|
+
page.definition.autogenerate.each do |name|
|
45
44
|
create(
|
46
45
|
:alchemy_element,
|
47
46
|
name: name,
|
@@ -2,9 +2,37 @@
|
|
2
2
|
|
3
3
|
FactoryBot.define do
|
4
4
|
factory :alchemy_picture, class: "Alchemy::Picture" do
|
5
|
-
|
6
|
-
|
5
|
+
transient do
|
6
|
+
image_file do
|
7
|
+
Rack::Test::UploadedFile.new(
|
8
|
+
Alchemy::Engine.root.join("lib", "alchemy", "test_support", "fixtures", "image.png")
|
9
|
+
)
|
10
|
+
end
|
7
11
|
end
|
12
|
+
|
13
|
+
after(:build) do |picture, acc|
|
14
|
+
if acc.image_file
|
15
|
+
case Alchemy.storage_adapter.name
|
16
|
+
when :active_storage
|
17
|
+
filename = acc.image_file.original_filename
|
18
|
+
content_type = Marcel::MimeType.for(extension: File.extname(filename))
|
19
|
+
picture.image_file.attach(
|
20
|
+
io: acc.image_file.open,
|
21
|
+
filename:,
|
22
|
+
content_type:,
|
23
|
+
identify: false,
|
24
|
+
metadata: {
|
25
|
+
width: 1,
|
26
|
+
height: 1
|
27
|
+
}
|
28
|
+
)
|
29
|
+
when :dragonfly
|
30
|
+
picture.image_file = acc.image_file
|
31
|
+
picture.image_file_size = acc.image_file.size
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
8
36
|
name { "image" }
|
9
37
|
upload_hash { Time.current.hash }
|
10
38
|
end
|
@@ -8,8 +8,8 @@ FactoryBot.define do
|
|
8
8
|
trait :default do
|
9
9
|
public { true }
|
10
10
|
|
11
|
-
name { Alchemy
|
12
|
-
host { Alchemy
|
11
|
+
name { Alchemy.config.default_site.name }
|
12
|
+
host { Alchemy.config.default_site.host }
|
13
13
|
end
|
14
14
|
|
15
15
|
trait :public do
|
@@ -30,8 +30,8 @@ RSpec.shared_examples_for "having crop action" do |args|
|
|
30
30
|
let(:settings) { {} }
|
31
31
|
|
32
32
|
before do
|
33
|
-
picture.image_file_width
|
34
|
-
picture.image_file_height
|
33
|
+
allow(picture).to receive(:image_file_width) { 300 }
|
34
|
+
allow(picture).to receive(:image_file_height) { 250 }
|
35
35
|
allow(croppable_resource).to receive(:settings) { settings }
|
36
36
|
expect(Alchemy::Picture).to receive(:find_by) { picture }
|
37
37
|
end
|