alchemy_cms 7.4.5 → 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 +92 -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/picture_descriptions_controller.rb +5 -1
- data/app/controllers/alchemy/admin/pictures_controller.rb +10 -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/picture_descriptions_form_helper.rb +16 -0
- 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 +4 -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/growl.js +1 -0
- 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/picture_descriptions/_form.html.erb +5 -7
- data/app/views/alchemy/admin/picture_descriptions/edit.html.erb +2 -2
- 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/_form.html.erb +2 -2
- data/app/views/alchemy/admin/pictures/_picture_description_field.html.erb +21 -13
- 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/500.turbo_stream.erb +3 -0
- 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/db/migrate/20250626160259_add_unique_index_to_picture_descriptions.rb +7 -0
- 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 +184 -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,115 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support"
|
4
|
+
require "active_support/core_ext/string"
|
5
|
+
|
6
|
+
require "alchemy/configuration/boolean_option"
|
7
|
+
require "alchemy/configuration/class_option"
|
8
|
+
require "alchemy/configuration/class_set_option"
|
9
|
+
require "alchemy/configuration/integer_option"
|
10
|
+
require "alchemy/configuration/integer_list_option"
|
11
|
+
require "alchemy/configuration/regexp_option"
|
12
|
+
require "alchemy/configuration/string_list_option"
|
13
|
+
require "alchemy/configuration/string_option"
|
14
|
+
|
15
|
+
module Alchemy
|
16
|
+
class Configuration
|
17
|
+
def initialize(configuration_hash = {})
|
18
|
+
set(configuration_hash)
|
19
|
+
end
|
20
|
+
|
21
|
+
def set(configuration_hash)
|
22
|
+
configuration_hash.each do |key, value|
|
23
|
+
send(:"#{key}=", value)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
alias_method :get, :send
|
28
|
+
alias_method :[], :get
|
29
|
+
|
30
|
+
def show = self
|
31
|
+
|
32
|
+
def fetch(key, default = nil)
|
33
|
+
get(key) || default
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_from_yaml(file)
|
37
|
+
set(
|
38
|
+
YAML.safe_load(
|
39
|
+
ERB.new(File.read(file)).result,
|
40
|
+
permitted_classes: YAML_PERMITTED_CLASSES,
|
41
|
+
aliases: true
|
42
|
+
) || {}
|
43
|
+
)
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_h
|
47
|
+
self.class.defined_options.map do |option|
|
48
|
+
[option, send(option)]
|
49
|
+
end.concat(
|
50
|
+
self.class.defined_configurations.map do |configuration|
|
51
|
+
[configuration, send(configuration).to_h]
|
52
|
+
end
|
53
|
+
).to_h
|
54
|
+
end
|
55
|
+
|
56
|
+
class << self
|
57
|
+
def defined_configurations = []
|
58
|
+
|
59
|
+
def defined_options = []
|
60
|
+
|
61
|
+
def configuration(name, configuration_class)
|
62
|
+
# The defined configurations on a class are all those defined directly on
|
63
|
+
# that class as well as those defined on ancestors.
|
64
|
+
# We store these as a class instance variable on each class which has a
|
65
|
+
# configuration. super() collects configurations defined on ancestors.
|
66
|
+
singleton_configurations = (@defined_singleton_configurations ||= [])
|
67
|
+
singleton_configurations << name.to_sym
|
68
|
+
|
69
|
+
define_singleton_method :defined_configurations do
|
70
|
+
super() + singleton_configurations
|
71
|
+
end
|
72
|
+
|
73
|
+
define_method(name) do
|
74
|
+
unless instance_variable_get(:"@#{name}")
|
75
|
+
send(:"#{name}=", configuration_class.new)
|
76
|
+
end
|
77
|
+
instance_variable_get(:"@#{name}")
|
78
|
+
end
|
79
|
+
|
80
|
+
define_method(:"#{name}=") do |value|
|
81
|
+
if value.is_a?(configuration_class)
|
82
|
+
instance_variable_set(:"@#{name}", value)
|
83
|
+
else
|
84
|
+
send(name).set(value)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def option(name, type, default: nil, **args)
|
90
|
+
klass = "Alchemy::Configuration::#{type.to_s.camelize}Option".constantize
|
91
|
+
# The defined options on a class are all those defined directly on
|
92
|
+
# that class as well as those defined on ancestors.
|
93
|
+
# We store these as a class instance variable on each class which has a
|
94
|
+
# option. super() collects options defined on ancestors.
|
95
|
+
singleton_options = (@defined_singleton_options ||= [])
|
96
|
+
singleton_options << name.to_sym
|
97
|
+
|
98
|
+
define_singleton_method :defined_options do
|
99
|
+
super() + singleton_options
|
100
|
+
end
|
101
|
+
|
102
|
+
define_method(name) do
|
103
|
+
unless instance_variable_defined?(:"@#{name}")
|
104
|
+
send(:"#{name}=", default)
|
105
|
+
end
|
106
|
+
instance_variable_get(:"@#{name}").value
|
107
|
+
end
|
108
|
+
|
109
|
+
define_method(:"#{name}=") do |value|
|
110
|
+
instance_variable_set(:"@#{name}", klass.new(value:, name:, **args))
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -12,9 +12,11 @@ module Alchemy
|
|
12
12
|
#
|
13
13
|
# Config file is in +config/alchemy/config.yml+
|
14
14
|
#
|
15
|
+
# @deprecated - Use Alchemy.config.get instead
|
15
16
|
def configuration(name)
|
16
|
-
|
17
|
+
Alchemy.config.get(name)
|
17
18
|
end
|
19
|
+
deprecate configuration: "Alchemy.config.get", deprecator: Alchemy::Deprecation
|
18
20
|
|
19
21
|
# Returns true if more than one language is published on current site.
|
20
22
|
#
|
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
module Configurations
|
5
|
+
class DefaultLanguage < Alchemy::Configuration
|
6
|
+
option :name, :string, default: "English"
|
7
|
+
option :code, :string, default: "en"
|
8
|
+
option :page_layout, :string, default: "index"
|
9
|
+
option :frontpage_name, :string, default: "Index"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
module Configurations
|
5
|
+
class FormatMatchers < Alchemy::Configuration
|
6
|
+
option :email, :regexp, default: /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/
|
7
|
+
option :url, :regexp, default: /\A[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?\z/ix
|
8
|
+
option :link_url, :regexp, default: /^(tel:|mailto:|\/|[a-z]+:\/\/)/
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Alchemy
|
4
|
+
module Configurations
|
5
|
+
class Mailer < Alchemy::Configuration
|
6
|
+
option :page_layout_name, :string, default: "contact"
|
7
|
+
option :forward_to_page, :boolean, default: false
|
8
|
+
option :mail_success_page, :string, default: "thanks"
|
9
|
+
option :mail_from, :string, default: "your.mail@your-domain.com"
|
10
|
+
option :mail_to, :string, default: "your.mail@your-domain.com"
|
11
|
+
option :subject, :string, default: "A new contact form message"
|
12
|
+
option :fields, :string_list, default: %w[salutation firstname lastname address zip city phone email message]
|
13
|
+
option :validate_fields, :string_list, default: %w[lastname email]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -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
|