alchemy_cms 7.3.5 → 7.4.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +60 -0
- data/Gemfile +3 -3
- data/README.md +2 -2
- data/alchemy_cms.gemspec +1 -4
- data/app/assets/builds/alchemy/admin.css +9 -1
- data/app/assets/builds/alchemy/admin.css.map +1 -1
- data/app/assets/builds/alchemy/custom-properties.css +1 -1
- data/app/assets/builds/alchemy/custom-properties.css.map +1 -1
- data/app/assets/builds/alchemy/preview.min.js +1 -0
- data/app/assets/builds/alchemy/welcome.css +1 -1
- data/app/assets/builds/alchemy/welcome.css.map +1 -1
- data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css +1 -1
- data/app/assets/builds/tinymce/skins/content/alchemy/content.min.css.map +1 -1
- data/app/assets/config/alchemy_manifest.js +0 -4
- data/app/assets/javascripts/alchemy/admin.js +8 -6
- data/app/assets/stylesheets/alchemy/admin/elements.scss +43 -7
- data/app/assets/stylesheets/alchemy/admin/forms.scss +4 -0
- data/app/assets/stylesheets/alchemy/admin/navigation.scss +9 -1
- data/app/assets/stylesheets/alchemy/admin/preview_window.scss +22 -17
- data/app/assets/stylesheets/alchemy/admin.scss +1 -1
- data/app/assets/stylesheets/alchemy/custom-properties.css +2 -1
- data/app/components/alchemy/ingredients/link_view.rb +7 -1
- data/app/components/alchemy/ingredients/picture_view.rb +5 -2
- data/app/components/alchemy/ingredients/text_view.rb +4 -1
- data/app/components/concerns/alchemy/ingredients/link_target.rb +18 -0
- data/app/controllers/alchemy/admin/base_controller.rb +8 -3
- data/app/controllers/alchemy/admin/elements_controller.rb +2 -2
- data/app/controllers/alchemy/admin/layoutpages_controller.rb +1 -0
- data/app/controllers/alchemy/admin/pages_controller.rb +5 -1
- data/app/controllers/alchemy/elements_controller.rb +3 -0
- data/app/helpers/alchemy/admin/form_helper.rb +1 -1
- data/app/helpers/alchemy/admin/navigation_helper.rb +22 -1
- data/app/javascript/alchemy_admin/components/action.js +2 -1
- data/app/javascript/alchemy_admin/components/dialog_link.js +3 -18
- data/app/javascript/alchemy_admin/components/element_editor.js +9 -0
- data/app/javascript/alchemy_admin/components/elements_window.js +34 -0
- data/app/javascript/alchemy_admin/components/elements_window_handle.js +65 -0
- data/app/javascript/alchemy_admin/components/icon.js +2 -2
- data/app/javascript/alchemy_admin/components/index.js +1 -0
- data/app/javascript/alchemy_admin/components/preview_window.js +5 -5
- data/app/javascript/alchemy_admin/components/uploader/file_upload.js +1 -1
- data/app/javascript/alchemy_admin/confirm_dialog.js +9 -11
- data/app/javascript/alchemy_admin/dialog.js +329 -0
- data/app/javascript/alchemy_admin/hotkeys.js +3 -2
- data/app/javascript/alchemy_admin/image_cropper.js +56 -48
- data/app/javascript/alchemy_admin/image_overlay.js +73 -0
- data/app/javascript/alchemy_admin/initializer.js +51 -2
- data/app/javascript/alchemy_admin/link_dialog.js +2 -1
- data/app/javascript/alchemy_admin/node_tree.js +3 -1
- data/app/javascript/alchemy_admin/page_sorter.js +1 -1
- data/app/javascript/alchemy_admin/picture_selector.js +2 -1
- data/app/javascript/alchemy_admin/shoelace_theme.js +2 -2
- data/app/javascript/alchemy_admin/templates/compiled.js +1 -0
- data/app/javascript/alchemy_admin.js +10 -6
- data/app/javascript/preview.js +117 -0
- data/app/models/alchemy/image_cropper_settings.rb +3 -4
- data/app/views/alchemy/_preview_mode_code.html.erb +1 -1
- data/app/views/alchemy/admin/crop.html.erb +18 -16
- data/app/views/alchemy/admin/dashboard/info.html.erb +1 -1
- data/app/views/alchemy/admin/elements/_add_nested_element_form.html.erb +9 -8
- data/app/views/alchemy/admin/elements/_clipboard_button.html.erb +14 -0
- data/app/views/alchemy/admin/elements/_element.html.erb +2 -0
- data/app/views/alchemy/admin/elements/_form.html.erb +15 -13
- data/app/views/alchemy/admin/elements/create.turbo_stream.erb +34 -0
- data/app/views/alchemy/admin/elements/index.html.erb +3 -15
- data/app/views/alchemy/admin/ingredients/_picture_fields.html.erb +1 -1
- data/app/views/alchemy/admin/layoutpages/edit.html.erb +7 -5
- data/app/views/alchemy/admin/nodes/_form.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_current_page.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_form.html.erb +43 -40
- data/app/views/alchemy/admin/pages/_locked_page.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_page_layout_filter.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_sitemap.html.erb +1 -1
- data/app/views/alchemy/admin/pages/_table.html.erb +2 -2
- data/app/views/alchemy/admin/pages/edit.html.erb +1 -1
- data/app/views/alchemy/admin/pages/update.turbo_stream.erb +39 -0
- data/app/views/alchemy/admin/partials/_main_navigation_entry.html.erb +3 -4
- data/app/views/alchemy/admin/pictures/_picture_description_field.html.erb +7 -5
- data/app/views/alchemy/admin/pictures/index.html.erb +13 -9
- data/app/views/alchemy/admin/resources/_filter_bar.html.erb +1 -1
- data/app/views/layouts/alchemy/admin.html.erb +8 -4
- data/bun.lockb +0 -0
- data/bundles/tinymce.js +2 -0
- data/config/alchemy/config.yml +3 -3
- data/config/alchemy/modules.yml +7 -6
- data/config/importmap.rb +4 -0
- data/config/routes.rb +1 -1
- data/lib/alchemy/engine.rb +6 -0
- data/lib/alchemy/modules.rb +0 -27
- data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +10 -10
- data/lib/alchemy/tinymce.rb +2 -1
- data/lib/alchemy/upgrader/seven_point_four.rb +26 -0
- data/lib/alchemy/version.rb +1 -1
- data/lib/alchemy.rb +14 -0
- data/lib/alchemy_cms.rb +0 -2
- data/lib/generators/alchemy/ingredient/ingredient_generator.rb +5 -0
- data/lib/generators/alchemy/ingredient/templates/view.html.erb +1 -1
- data/lib/generators/alchemy/ingredient/templates/view_component.rb.tt +10 -0
- data/lib/generators/alchemy/install/install_generator.rb +0 -1
- data/lib/generators/alchemy/install/templates/elements.yml.tt +1 -1
- data/lib/tasks/alchemy/upgrade.rake +19 -20
- data/rollup.config.mjs +44 -1
- data/vendor/javascript/cropperjs.min.js +10 -0
- data/vendor/javascript/handlebars.min.js +29 -0
- data/vendor/javascript/jquery.min.js +2 -0
- data/vendor/javascript/select2.min.js +23 -0
- data/vendor/javascript/tinymce.min.js +1 -1
- metadata +40 -92
- data/app/assets/javascripts/alchemy/alchemy.dialog.js.coffee +0 -271
- data/app/assets/javascripts/alchemy/alchemy.image_overlay.coffee +0 -54
- data/app/assets/javascripts/alchemy/alchemy.preview.js.coffee +0 -97
- data/app/assets/javascripts/alchemy/preview.js +0 -1
- data/app/assets/javascripts/alchemy/templates/index.js +0 -2
- data/app/javascript/alchemy_admin/gui.js +0 -12
- data/app/views/alchemy/admin/elements/create.js.erb +0 -35
- data/app/views/alchemy/admin/pages/update.js.erb +0 -43
- data/lib/alchemy/upgrader/seven_point_zero.rb +0 -36
- data/vendor/assets/images/Jcrop.gif +0 -0
- data/vendor/assets/javascripts/jquery_plugins/jquery.Jcrop.min.js +0 -7
- data/vendor/assets/javascripts/jquery_plugins/select2.js +0 -3729
- data/vendor/assets/stylesheets/jquery.Jcrop.min.css +0 -2
- data/vendor/assets/stylesheets/tinymce/skins/content/default/content.min.css +0 -1
- /data/app/{assets/javascripts/alchemy → javascript/alchemy_admin}/templates/node_folder.hbs +0 -0
- /data/app/{assets/javascripts/alchemy → javascript/alchemy_admin}/templates/page_folder.hbs +0 -0
- /data/app/{assets/javascripts/tinymce/icons/remixicons/icons.js → javascript/tinymce/icons/remixicons/index.js} +0 -0
- /data/app/{assets/javascripts/tinymce/plugins/alchemy_link/plugin.min.js → javascript/tinymce/plugins/alchemy_link/index.js} +0 -0
- /data/vendor/assets/{fonts → images}/remixicon.symbol.svg +0 -0
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="page_status_and_name" id="
|
1
|
+
<div class="page_status_and_name" id="locked_page_<%= current_page.id %>">
|
2
2
|
<%= render 'alchemy/admin/pages/page_infos', page: current_page %>
|
3
3
|
<%= render 'alchemy/admin/pages/page_status', page: current_page %>
|
4
4
|
</div>
|
@@ -1,55 +1,58 @@
|
|
1
|
-
<%=
|
2
|
-
|
3
|
-
|
4
|
-
<%=
|
1
|
+
<%= turbo_frame_tag @page do %>
|
2
|
+
<%= alchemy_form_for [:admin, @page], class: 'edit_page', remote: false do |f| %>
|
3
|
+
<% unless @page.language_root? || @page.layoutpage %>
|
4
|
+
<%= render Alchemy::Admin::PageSelect.new(@page.parent) do %>
|
5
|
+
<%= f.input :parent_id, required: true %>
|
6
|
+
<% end %>
|
5
7
|
<% end %>
|
6
|
-
<% end %>
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
<div class="input check_boxes">
|
10
|
+
<label class="control-label"><%= Alchemy.t(:page_status) %></label>
|
11
|
+
<div class="control_group">
|
12
|
+
<%= render 'alchemy/admin/pages/publication_fields' %>
|
13
|
+
<%= page_status_checkbox(@page, :restricted) %>
|
14
|
+
<% if configuration(:sitemap)['show_flag'] %>
|
15
|
+
<%= page_status_checkbox(@page, :sitemap) %>
|
16
|
+
<% end %>
|
17
|
+
</div>
|
16
18
|
</div>
|
17
|
-
</div>
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
<%= f.input :name, autofocus: true %>
|
21
|
+
<%= f.input :urlname, as: 'string', input_html: {value: @page.slug}, label: Alchemy::Page.human_attribute_name(:slug) %>
|
22
|
+
<alchemy-char-counter max-chars="60">
|
23
|
+
<%= f.input :title %>
|
24
|
+
</alchemy-char-counter>
|
25
|
+
|
26
|
+
<% if Alchemy.enable_searchable %>
|
27
|
+
<div class="input check_boxes">
|
28
|
+
<label class="control-label"><%= Alchemy.t(:fulltext_search) %></label>
|
29
|
+
<div class="control_group">
|
30
|
+
<%= page_status_checkbox(@page, :searchable) %>
|
31
|
+
</div>
|
32
|
+
</div>
|
33
|
+
<% end %>
|
24
34
|
|
25
|
-
<% if Alchemy.enable_searchable %>
|
26
35
|
<div class="input check_boxes">
|
27
|
-
<label class="control-label"><%= Alchemy.t(:
|
36
|
+
<label class="control-label"><%= Alchemy.t(:search_engines) %></label>
|
28
37
|
<div class="control_group">
|
29
|
-
<%= page_status_checkbox(@page, :
|
38
|
+
<%= page_status_checkbox(@page, :robot_index) %>
|
39
|
+
<%= page_status_checkbox(@page, :robot_follow) %>
|
30
40
|
</div>
|
31
41
|
</div>
|
32
|
-
<% end %>
|
33
42
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
<%= page_status_checkbox(@page, :robot_index) %>
|
38
|
-
<%= page_status_checkbox(@page, :robot_follow) %>
|
39
|
-
</div>
|
40
|
-
</div>
|
43
|
+
<alchemy-char-counter max-chars="160">
|
44
|
+
<%= f.input :meta_description, as: 'text' %>
|
45
|
+
</alchemy-char-counter>
|
41
46
|
|
42
|
-
|
43
|
-
|
44
|
-
|
47
|
+
<%= f.input :meta_keywords,
|
48
|
+
as: 'text',
|
49
|
+
hint: Alchemy.t('pages.update.comma_seperated') %>
|
45
50
|
|
46
|
-
|
47
|
-
|
48
|
-
|
51
|
+
<%= render Alchemy::Admin::TagsAutocomplete.new do %>
|
52
|
+
<%= f.input :tag_list, input_html: { value: f.object.tag_list.join(",") } %>
|
53
|
+
<% end %>
|
49
54
|
|
50
|
-
|
51
|
-
<%= f.
|
55
|
+
<%= hidden_field_tag :view, params[:view] %>
|
56
|
+
<%= f.submit Alchemy.t(:save) %>
|
52
57
|
<% end %>
|
53
|
-
|
54
|
-
<%= f.submit Alchemy.t(:save) %>
|
55
58
|
<% end %>
|
@@ -19,7 +19,7 @@
|
|
19
19
|
</label>
|
20
20
|
</div>
|
21
21
|
|
22
|
-
<script type="
|
22
|
+
<script type="module">
|
23
23
|
$(function() {
|
24
24
|
$("#page_layout").on("change", function(e) {
|
25
25
|
var url = "<%= alchemy.admin_pages_path(search_filter_params.except(:page_layout, :page).merge(view: "list")) %>";
|
@@ -67,7 +67,7 @@
|
|
67
67
|
<% table.with_action :configure, Alchemy.t(:edit_page_properties) do |page| %>
|
68
68
|
<%= link_to_dialog(
|
69
69
|
render_icon(:cog),
|
70
|
-
alchemy.configure_admin_page_path(page),
|
70
|
+
alchemy.configure_admin_page_path(page, view: "list"),
|
71
71
|
{
|
72
72
|
title: Alchemy.t(:edit_page_properties),
|
73
73
|
size: '450x680'
|
@@ -91,7 +91,7 @@
|
|
91
91
|
<% end %>
|
92
92
|
|
93
93
|
|
94
|
-
<script type="
|
94
|
+
<script type="module">
|
95
95
|
$(function() {
|
96
96
|
Alchemy.PagePublicationFields();
|
97
97
|
});
|
@@ -144,7 +144,7 @@
|
|
144
144
|
<% end %>
|
145
145
|
|
146
146
|
<% content_for :javascripts do %>
|
147
|
-
<script type="
|
147
|
+
<script type="module">
|
148
148
|
$(document).one('turbo:load', function() {
|
149
149
|
$('#unlock_page_form, #publish_page_form').on('submit', function(event) {
|
150
150
|
var not_dirty = Alchemy.checkPageDirtyness(this);
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<alchemy-growl><%= @notice %></alchemy-action>
|
2
|
+
<alchemy-action name="closeCurrentDialog"></alchemy-action>
|
3
|
+
|
4
|
+
<% if @while_page_edit -%>
|
5
|
+
<%= turbo_stream.replace "locked_page_#{@page.id}" do %>
|
6
|
+
<%= render("alchemy/admin/pages/current_page", current_page: @page) %>
|
7
|
+
<% end %>
|
8
|
+
<alchemy-action name="reloadPreview"></alchemy-action>
|
9
|
+
<% else %>
|
10
|
+
<%= turbo_stream.replace "locked_page_#{@page.id}" do %>
|
11
|
+
<%= render("alchemy/admin/pages/locked_page", locked_page: @page) %>
|
12
|
+
<% end %>
|
13
|
+
|
14
|
+
<% if @view == "list" %>
|
15
|
+
<turbo-stream action="refresh"></turbo-stream>
|
16
|
+
<% elsif @page.parent_id != @old_parent_id -%>
|
17
|
+
<%= turbo_stream.append "sitemap" do %>
|
18
|
+
<script type="module">
|
19
|
+
Alchemy.currentSitemap.load(<%= @page.get_language_root.id %>);
|
20
|
+
</script>
|
21
|
+
<% end %>
|
22
|
+
<% else -%>
|
23
|
+
<% if @page.layoutpage %>
|
24
|
+
<%= turbo_stream.replace "page_#{@page.id}" do %>
|
25
|
+
<%= render("alchemy/admin/layoutpages/layoutpage", layoutpage: @page) %>
|
26
|
+
<% end %>
|
27
|
+
<% else %>
|
28
|
+
<%= turbo_stream.append "sitemap" do %>
|
29
|
+
<script type="module">
|
30
|
+
const page = document.getElementById('page_<%= @page.id %>');
|
31
|
+
const page_html = "<%= j render('page', page: @page) %>".replace(/__ID__/g, "<%= @page.id %>");
|
32
|
+
const compiler = Handlebars.compile(page_html);
|
33
|
+
const tree = <%== @tree.to_json %>;
|
34
|
+
page.outerHTML = compiler(tree.pages[0]);
|
35
|
+
</script>
|
36
|
+
<% end %>
|
37
|
+
<% end %>
|
38
|
+
<% end -%>
|
39
|
+
<% end %>
|
@@ -6,10 +6,9 @@
|
|
6
6
|
<% elsif navigation["inline_image"] %>
|
7
7
|
<%== navigation["inline_image"] %>
|
8
8
|
<% elsif navigation["icon"] %>
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
</svg>
|
9
|
+
<%= content_tag :"alchemy-icon", nil,
|
10
|
+
name: navigation["icon"],
|
11
|
+
"icon-style": navigation["icon-style"] %>
|
13
12
|
<% else %>
|
14
13
|
<%= render_icon :table %>
|
15
14
|
<% end %>
|
@@ -21,9 +21,11 @@
|
|
21
21
|
<script type="module">
|
22
22
|
const select = document.querySelector("#language_id")
|
23
23
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
if (select) {
|
25
|
+
select.addEventListener("change", () => {
|
26
|
+
const url = new URL(select.dataset.url)
|
27
|
+
url.searchParams.set("language_id", select.value)
|
28
|
+
Turbo.visit(url, { frame: "picture_descriptions" })
|
29
|
+
})
|
30
|
+
}
|
29
31
|
</script>
|
@@ -86,16 +86,20 @@
|
|
86
86
|
</div>
|
87
87
|
|
88
88
|
<% content_for :javascripts do %>
|
89
|
-
<script type="
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
89
|
+
<script type="module">
|
90
|
+
import ImageOverlay from "alchemy_admin/image_overlay";
|
91
|
+
import pictureSelector from "alchemy_admin/picture_selector";
|
92
|
+
import { on } from "alchemy_admin/utils/events";
|
93
|
+
|
94
|
+
pictureSelector();
|
95
|
+
on("click", "#picture_archive", ".thumbnail_background", (event) => {
|
96
|
+
const url = event.target.closest("a")?.href;
|
97
|
+
const overlay = new ImageOverlay(url, {
|
98
|
+
size: `${window.innerWidth}x${window.innerHeight}`,
|
99
|
+
padding: false
|
98
100
|
});
|
101
|
+
overlay.open();
|
102
|
+
event.preventDefault();
|
99
103
|
});
|
100
104
|
</script>
|
101
105
|
<% end %>
|
@@ -5,15 +5,17 @@
|
|
5
5
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
6
6
|
<title><%= render_alchemy_title %></title>
|
7
7
|
<link rel="shortcut icon" href="<%= asset_path('alchemy/favicon.ico') %>">
|
8
|
+
<link rel="preload" href="<%= asset_path("remixicon.symbol.svg") %>" as="image" type="<%= Mime::Type.lookup_by_extension(:svg) %>" crossorigin>
|
8
9
|
<%= csrf_meta_tag %>
|
9
10
|
<meta name="robots" content="noindex">
|
10
|
-
<meta name="alchemy-icon-sprite" content="<%= asset_path("remixicon.symbol.svg") %>">
|
11
11
|
<meta name="turbo-prefetch" content="false">
|
12
12
|
<meta name="turbo-cache-control" content="no-cache">
|
13
13
|
<%= stylesheet_link_tag('alchemy/custom-properties', media: 'screen', 'data-turbo-track' => true) %>
|
14
14
|
<%= stylesheet_link_tag('alchemy/admin', media: 'screen', 'data-turbo-track' => true) %>
|
15
15
|
<%= stylesheet_link_tag('alchemy/admin/print', media: 'print', 'data-turbo-track' => true) %>
|
16
|
-
|
16
|
+
<% Alchemy.admin_stylesheets.each do |stylesheet| %>
|
17
|
+
<%= stylesheet_link_tag(stylesheet, 'data-turbo-track' => true) %>
|
18
|
+
<% end %>
|
17
19
|
<%= yield :stylesheets %>
|
18
20
|
<script>
|
19
21
|
// Global Alchemy JavaScript object.
|
@@ -32,7 +34,9 @@
|
|
32
34
|
<% end %>
|
33
35
|
<%= yield :javascript_includes %>
|
34
36
|
</head>
|
35
|
-
<%= content_tag :body, id: 'alchemy',
|
37
|
+
<%= content_tag :body, id: 'alchemy',
|
38
|
+
class: alchemy_body_class + ["alchemy-light"],
|
39
|
+
style: cookies["alchemy-elements-window-width"] && "--elements-window-width: #{cookies["alchemy-elements-window-width"]}px" do %>
|
36
40
|
<noscript>
|
37
41
|
<h1><%= Alchemy.t(:javascript_disabled_headline) %></h1>
|
38
42
|
<p><%= Alchemy.t(:javascript_disabled_text) %></p>
|
@@ -89,7 +93,7 @@
|
|
89
93
|
<div id="main_content">
|
90
94
|
<%= yield %>
|
91
95
|
</div>
|
92
|
-
<script>
|
96
|
+
<script type="module">
|
93
97
|
// Setting the correct locale for select2 dropdown replacement.
|
94
98
|
$.extend($.fn.select2.defaults, $.fn.select2.locales['<%= ::I18n.locale %>']);
|
95
99
|
</script>
|
data/bun.lockb
CHANGED
Binary file
|
data/bundles/tinymce.js
CHANGED
@@ -3,6 +3,7 @@ import tinymce from "tinymce"
|
|
3
3
|
|
4
4
|
/* Default icons are required. After that, import custom icons if applicable */
|
5
5
|
import "tinymce/icons/default"
|
6
|
+
import "tinymce/icons/remixicons"
|
6
7
|
|
7
8
|
/* Required TinyMCE components */
|
8
9
|
import "tinymce/themes/silver"
|
@@ -16,5 +17,6 @@ import "tinymce/plugins/directionality"
|
|
16
17
|
import "tinymce/plugins/fullscreen"
|
17
18
|
import "tinymce/plugins/link"
|
18
19
|
import "tinymce/plugins/lists"
|
20
|
+
import "tinymce/plugins/alchemy_link"
|
19
21
|
|
20
22
|
export default tinymce
|
data/config/alchemy/config.yml
CHANGED
@@ -199,9 +199,9 @@ link_target_options: [blank]
|
|
199
199
|
# validates_format_of :url, with: Alchemy::Config.get('format_matchers')['url']
|
200
200
|
#
|
201
201
|
format_matchers:
|
202
|
-
email: !ruby/regexp
|
203
|
-
url: !ruby/regexp
|
204
|
-
link_url: !ruby/regexp
|
202
|
+
email: !ruby/regexp /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/
|
203
|
+
url: !ruby/regexp /\A[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?\z/ix
|
204
|
+
link_url: !ruby/regexp /^(tel:|mailto:|\/|[a-z]+:\/\/)/
|
205
205
|
|
206
206
|
# The layout used for rendering the +alchemy/admin/pages#show+ action.
|
207
207
|
admin_page_preview_layout: application
|
data/config/alchemy/modules.yml
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
name: Home
|
8
8
|
controller: "/alchemy/admin/dashboard"
|
9
9
|
action: index
|
10
|
-
icon: home-2
|
10
|
+
icon: home-2
|
11
11
|
|
12
12
|
- name: pages
|
13
13
|
engine_name: alchemy
|
@@ -16,7 +16,7 @@
|
|
16
16
|
name: "modules.pages"
|
17
17
|
controller: "/alchemy/admin/pages"
|
18
18
|
action: index
|
19
|
-
icon: pages
|
19
|
+
icon: pages
|
20
20
|
sub_navigation:
|
21
21
|
- name: "modules.pages"
|
22
22
|
controller: "/alchemy/admin/pages"
|
@@ -35,7 +35,7 @@
|
|
35
35
|
name: "modules.menus"
|
36
36
|
controller: "/alchemy/admin/nodes"
|
37
37
|
action: index
|
38
|
-
icon: menu-2
|
38
|
+
icon: menu-2
|
39
39
|
|
40
40
|
- name: languages
|
41
41
|
engine_name: alchemy
|
@@ -45,6 +45,7 @@
|
|
45
45
|
controller: "/alchemy/admin/languages"
|
46
46
|
action: index
|
47
47
|
icon: translate-2
|
48
|
+
icon-style: none
|
48
49
|
|
49
50
|
- name: sites
|
50
51
|
engine_name: alchemy
|
@@ -53,7 +54,7 @@
|
|
53
54
|
name: "modules.sites"
|
54
55
|
controller: "/alchemy/admin/sites"
|
55
56
|
action: index
|
56
|
-
icon: global
|
57
|
+
icon: global
|
57
58
|
|
58
59
|
- name: tags
|
59
60
|
engine_name: alchemy
|
@@ -62,7 +63,7 @@
|
|
62
63
|
name: "modules.tags"
|
63
64
|
controller: "/alchemy/admin/tags"
|
64
65
|
action: index
|
65
|
-
icon: price-tag-3
|
66
|
+
icon: price-tag-3
|
66
67
|
|
67
68
|
- name: archive
|
68
69
|
engine_name: alchemy
|
@@ -71,7 +72,7 @@
|
|
71
72
|
controller: "/alchemy/admin/pictures"
|
72
73
|
action: index
|
73
74
|
name: "modules.library"
|
74
|
-
icon: archive-drawer
|
75
|
+
icon: archive-drawer
|
75
76
|
sub_navigation:
|
76
77
|
- name: "modules.pictures"
|
77
78
|
controller: "/alchemy/admin/pictures"
|
data/config/importmap.rb
CHANGED
@@ -1,7 +1,11 @@
|
|
1
1
|
pin "@ungap/custom-elements", to: "ungap-custom-elements.min.js", preload: true # @1.3.0
|
2
2
|
pin "clipboard", to: "clipboard.min.js", preload: true
|
3
|
+
pin "cropperjs", to: "cropperjs.min.js", preload: true
|
3
4
|
pin "flatpickr", to: "flatpickr.min.js", preload: true # @4.6.13
|
5
|
+
pin "handlebars", to: "handlebars.min.js", preload: true # @4.7.8
|
6
|
+
pin "jquery", to: "jquery.min.js", preload: true
|
4
7
|
pin "keymaster", to: "keymaster.min.js", preload: true
|
8
|
+
pin "select2", to: "select2.min.js", preload: true
|
5
9
|
pin "sortablejs", to: "sortable.min.js", preload: true # @1.15.1
|
6
10
|
pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
|
7
11
|
pin "shoelace", to: "shoelace.min.js", preload: true
|
data/config/routes.rb
CHANGED
data/lib/alchemy/engine.rb
CHANGED
@@ -20,6 +20,12 @@ module Alchemy
|
|
20
20
|
NonStupidDigestAssets.whitelist += [/^tinymce\//]
|
21
21
|
end
|
22
22
|
|
23
|
+
initializer "alchemy.admin_stylesheets" do |app|
|
24
|
+
Alchemy.admin_stylesheets.each do |stylesheet|
|
25
|
+
app.config.assets.precompile << stylesheet
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
23
29
|
initializer "alchemy.importmap" do |app|
|
24
30
|
watch_paths = []
|
25
31
|
|
data/lib/alchemy/modules.rb
CHANGED
@@ -27,35 +27,8 @@ module Alchemy
|
|
27
27
|
def register_module(module_definition)
|
28
28
|
definition_hash = module_definition.deep_stringify_keys
|
29
29
|
|
30
|
-
### Validate controller(s) existence
|
31
|
-
if definition_hash["navigation"].is_a?(Hash)
|
32
|
-
defined_controllers = [definition_hash["navigation"]["controller"]]
|
33
|
-
|
34
|
-
if definition_hash["navigation"]["sub_navigation"].is_a?(Array)
|
35
|
-
defined_controllers.concat(definition_hash["navigation"]["sub_navigation"].map { |x| x["controller"] })
|
36
|
-
end
|
37
|
-
|
38
|
-
validate_controllers_existence(defined_controllers, definition_hash)
|
39
|
-
end
|
40
|
-
|
41
30
|
@@alchemy_modules |= [definition_hash]
|
42
31
|
end
|
43
|
-
|
44
|
-
private
|
45
|
-
|
46
|
-
def validate_controllers_existence(controllers, definition_hash)
|
47
|
-
controllers.each do |controller_val|
|
48
|
-
next if controller_val.blank?
|
49
|
-
|
50
|
-
controller_name = "#{controller_val.camelize}Controller"
|
51
|
-
|
52
|
-
begin
|
53
|
-
controller_name.constantize
|
54
|
-
rescue NameError
|
55
|
-
raise "Error in AlchemyCMS module definition: '#{definition_hash["name"]}'. Could not find the matching controller class #{controller_name.sub(/^::/, "")} for the specified controller: '#{controller_val}'"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
59
32
|
end
|
60
33
|
|
61
34
|
# Get the module definition for given module name
|
@@ -562,8 +562,8 @@ RSpec.shared_examples_for "having picture thumbnails" do
|
|
562
562
|
context "size 200x50" do
|
563
563
|
let(:size) { "200x50" }
|
564
564
|
|
565
|
-
it "default box should be [0, 25, 200,
|
566
|
-
expect(subject[:default_box]).to eq([0, 25, 200,
|
565
|
+
it "default box should be [0, 25, 200, 50]" do
|
566
|
+
expect(subject[:default_box]).to eq([0, 25, 200, 50])
|
567
567
|
end
|
568
568
|
end
|
569
569
|
|
@@ -578,16 +578,16 @@ RSpec.shared_examples_for "having picture thumbnails" do
|
|
578
578
|
context "size 50x100" do
|
579
579
|
let(:size) { "50x100" }
|
580
580
|
|
581
|
-
it "the hash should be {x1: 75, y1: 0, x2:
|
582
|
-
expect(subject[:default_box]).to eq([75, 0,
|
581
|
+
it "the hash should be {x1: 75, y1: 0, x2: 50, y2: 100}" do
|
582
|
+
expect(subject[:default_box]).to eq([75, 0, 50, 100])
|
583
583
|
end
|
584
584
|
end
|
585
585
|
|
586
586
|
context "size 50x50" do
|
587
587
|
let(:size) { "50x50" }
|
588
588
|
|
589
|
-
it "the hash should be {x1: 50, y1: 0, x2:
|
590
|
-
expect(subject[:default_box]).to eq([50, 0,
|
589
|
+
it "the hash should be {x1: 50, y1: 0, x2: 100, y2: 100}" do
|
590
|
+
expect(subject[:default_box]).to eq([50, 0, 100, 100])
|
591
591
|
end
|
592
592
|
end
|
593
593
|
|
@@ -602,16 +602,16 @@ RSpec.shared_examples_for "having picture thumbnails" do
|
|
602
602
|
context "size 400x100" do
|
603
603
|
let(:size) { "400x100" }
|
604
604
|
|
605
|
-
it "the hash should be {x1: 0, y1: 25, x2: 200, y2:
|
606
|
-
expect(subject[:default_box]).to eq([0, 25, 200,
|
605
|
+
it "the hash should be {x1: 0, y1: 25, x2: 200, y2: 50}" do
|
606
|
+
expect(subject[:default_box]).to eq([0, 25, 200, 50])
|
607
607
|
end
|
608
608
|
end
|
609
609
|
|
610
610
|
context "size 200x200" do
|
611
611
|
let(:size) { "200x200" }
|
612
612
|
|
613
|
-
it "the hash should be {x1: 50, y1: 0, x2:
|
614
|
-
expect(subject[:default_box]).to eq([50, 0,
|
613
|
+
it "the hash should be {x1: 50, y1: 0, x2: 100, y2: 100}" do
|
614
|
+
expect(subject[:default_box]).to eq([50, 0, 100, 100])
|
615
615
|
end
|
616
616
|
end
|
617
617
|
end
|
data/lib/alchemy/tinymce.rb
CHANGED
@@ -5,6 +5,7 @@ module Alchemy
|
|
5
5
|
mattr_accessor :languages, :plugins
|
6
6
|
|
7
7
|
DEFAULT_PLUGINS = %w[
|
8
|
+
alchemy_link
|
8
9
|
anchor
|
9
10
|
charmap
|
10
11
|
code
|
@@ -14,7 +15,7 @@ module Alchemy
|
|
14
15
|
lists
|
15
16
|
]
|
16
17
|
|
17
|
-
@@plugins = DEFAULT_PLUGINS
|
18
|
+
@@plugins = DEFAULT_PLUGINS
|
18
19
|
@@init = {
|
19
20
|
skin: "alchemy",
|
20
21
|
content_css: "/assets/tinymce/skins/content/alchemy/content.min.css",
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "fileutils"
|
4
|
+
require "thor"
|
5
|
+
|
6
|
+
module Alchemy
|
7
|
+
class Upgrader::SevenPointFour < Upgrader
|
8
|
+
include Thor::Base
|
9
|
+
include Thor::Actions
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def update_custom_css_config
|
13
|
+
if File.exist? "app/assets/config/manifest.js"
|
14
|
+
log "Removing alchemy/admin/custom.css from assets config file."
|
15
|
+
task.gsub_file "app/assets/config/manifest.js", %r{//= link alchemy/admin/custom.css\n}, ""
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def task
|
22
|
+
@_task || new
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
data/lib/alchemy/version.rb
CHANGED
data/lib/alchemy.rb
CHANGED
@@ -98,6 +98,20 @@ module Alchemy
|
|
98
98
|
}])
|
99
99
|
end
|
100
100
|
|
101
|
+
# Additional stylesheets to be included in the Alchemy admin UI
|
102
|
+
#
|
103
|
+
# == Example
|
104
|
+
#
|
105
|
+
# # lib/alchemy/devise/engine.rb
|
106
|
+
# initializer "alchemy.devise.stylesheets", before: "alchemy.admin_stylesheets" do
|
107
|
+
# Alchemy.admin_stylesheets << "alchemy/devise/admin.css"
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# @return [Set<String>]
|
111
|
+
def self.admin_stylesheets
|
112
|
+
@_admin_stylesheets ||= Set.new(["alchemy/admin/custom.css"])
|
113
|
+
end
|
114
|
+
|
101
115
|
# Define page publish targets
|
102
116
|
#
|
103
117
|
# A publish target is a ActiveJob that gets performed
|
data/lib/alchemy_cms.rb
CHANGED
@@ -11,9 +11,7 @@ require "awesome_nested_set"
|
|
11
11
|
require "cancan"
|
12
12
|
require "dragonfly"
|
13
13
|
require "gutentag"
|
14
|
-
require "handlebars_assets"
|
15
14
|
require "importmap-rails"
|
16
|
-
require "jquery-rails"
|
17
15
|
require "kaminari"
|
18
16
|
require "non_stupid_digest_assets"
|
19
17
|
require "ransack"
|