alchemy_cms 7.1.0.pre.b1 → 7.1.0.pre.b2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/Gemfile +1 -1
  4. data/README.md +2 -2
  5. data/alchemy_cms.gemspec +1 -1
  6. data/app/assets/config/alchemy_manifest.js +3 -4
  7. data/app/assets/images/alchemy/missing-image.svg +1 -1
  8. data/app/assets/javascripts/alchemy/admin.js +0 -4
  9. data/app/assets/javascripts/alchemy/alchemy.link_dialog.js.coffee +4 -4
  10. data/app/assets/javascripts/tinymce/icons/remixicons/icons.js +93 -0
  11. data/app/assets/javascripts/tinymce/plugins/alchemy_link/plugin.min.js +37 -18
  12. data/app/assets/stylesheets/alchemy/_variables.scss +11 -3
  13. data/app/assets/stylesheets/alchemy/archive.scss +5 -2
  14. data/app/assets/stylesheets/alchemy/buttons.scss +5 -4
  15. data/app/assets/stylesheets/alchemy/dialogs.scss +1 -1
  16. data/app/assets/stylesheets/alchemy/elements.scss +4 -5
  17. data/app/assets/stylesheets/tinymce/skins/content/alchemy/content.min.scss +69 -0
  18. data/app/assets/stylesheets/tinymce/skins/skintool.json +38 -0
  19. data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.css +711 -0
  20. data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.inline.css +705 -0
  21. data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.inline.min.css +7 -0
  22. data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.min.css +7 -0
  23. data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.mobile.css +29 -0
  24. data/app/assets/stylesheets/tinymce/skins/ui/alchemy/content.mobile.min.css +7 -0
  25. data/app/assets/stylesheets/tinymce/skins/ui/alchemy/fonts/tinymce-mobile.woff +0 -0
  26. data/app/assets/stylesheets/tinymce/skins/ui/alchemy/skin.min.scss +3798 -0
  27. data/app/assets/stylesheets/tinymce/skins/ui/alchemy/skin.mobile.css +677 -0
  28. data/app/assets/stylesheets/tinymce/skins/ui/alchemy/skin.mobile.min.css +7 -0
  29. data/app/controllers/alchemy/admin/pages_controller.rb +9 -4
  30. data/app/javascript/alchemy_admin/clipboard.js +16 -0
  31. data/app/javascript/alchemy_admin/components/tinymce.js +8 -20
  32. data/app/javascript/alchemy_admin/picture_editors.js +4 -2
  33. data/app/javascript/alchemy_admin/utils/debounce.js +10 -0
  34. data/app/javascript/alchemy_admin/utils/max.js +3 -0
  35. data/app/javascript/alchemy_admin.js +4 -10
  36. data/app/models/alchemy/page/page_naming.rb +7 -0
  37. data/app/models/alchemy/page.rb +2 -2
  38. data/app/models/alchemy/picture_variant.rb +11 -2
  39. data/app/models/concerns/alchemy/picture_thumbnails.rb +1 -1
  40. data/app/views/alchemy/admin/attachments/show.html.erb +2 -15
  41. data/app/views/alchemy/admin/pictures/_picture.html.erb +3 -5
  42. data/app/views/alchemy/admin/pictures/_picture_to_assign.html.erb +1 -1
  43. data/app/views/alchemy/admin/resources/_filter.html.erb +1 -1
  44. data/app/views/alchemy/admin/resources/_per_page_select.html.erb +1 -1
  45. data/app/views/alchemy/admin/tinymce/_setup.html.erb +1 -2
  46. data/app/views/alchemy/ingredients/shared/_picture_tools.html.erb +2 -2
  47. data/bundles/shoelace.js +10 -0
  48. data/bundles/tinymce.js +20 -0
  49. data/config/alchemy/config.yml +11 -10
  50. data/config/brakeman.ignore +0 -34
  51. data/config/importmap.rb +9 -14
  52. data/config/initializers/dragonfly.rb +1 -0
  53. data/config/locales/alchemy.en.yml +2 -0
  54. data/lib/alchemy/config.rb +24 -2
  55. data/lib/alchemy/engine.rb +2 -1
  56. data/lib/alchemy/test_support/having_picture_thumbnails_examples.rb +6 -6
  57. data/lib/alchemy/tinymce.rb +13 -2
  58. data/lib/alchemy/version.rb +1 -1
  59. data/package.json +18 -6
  60. data/rollup.config.mjs +65 -0
  61. data/vendor/assets/stylesheets/tinymce/skins/content/default/content.min.css +1 -0
  62. data/vendor/javascript/clipboard.min.js +7 -0
  63. data/vendor/javascript/flatpickr.min.js +1 -0
  64. data/vendor/javascript/keymaster.min.js +1 -0
  65. data/vendor/javascript/rails-ujs.min.js +1 -0
  66. data/vendor/javascript/shoelace.min.js +995 -0
  67. data/vendor/javascript/sortable.min.js +7 -0
  68. data/vendor/javascript/tinymce.min.js +1 -0
  69. data/vendor/javascript/ungap-custom-elements.min.js +3 -0
  70. metadata +30 -38
  71. data/.codeclimate.yml +0 -35
  72. data/.editorconfig +0 -23
  73. data/.github/FUNDING.yml +0 -4
  74. data/.github/ISSUE_TEMPLATE/Bug_report.md +0 -22
  75. data/.github/ISSUE_TEMPLATE/Feature_request.md +0 -17
  76. data/.github/PULL_REQUEST_TEMPLATE.md +0 -18
  77. data/.github/workflows/backport.yml +0 -36
  78. data/.github/workflows/brakeman-analysis.yml +0 -46
  79. data/.github/workflows/lint.yml +0 -37
  80. data/.github/workflows/stale.yml +0 -33
  81. data/.github/workflows/test.yml +0 -125
  82. data/.gitignore +0 -32
  83. data/.hound.yml +0 -9
  84. data/.localeapp/config.rb +0 -8
  85. data/.prettierrc +0 -6
  86. data/.rspec +0 -1
  87. data/.rubocop.yml +0 -7
  88. data/.standard.yml +0 -4
  89. data/.yardopts +0 -5
  90. data/app/assets/stylesheets/tinymce/skins/alchemy/content.min.css.scss +0 -94
  91. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.svg +0 -63
  92. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.ttf +0 -0
  93. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce-small.woff +0 -0
  94. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.svg +0 -129
  95. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.ttf +0 -0
  96. data/app/assets/stylesheets/tinymce/skins/alchemy/fonts/tinymce.woff +0 -0
  97. data/app/assets/stylesheets/tinymce/skins/alchemy/img/anchor.gif +0 -0
  98. data/app/assets/stylesheets/tinymce/skins/alchemy/img/loader.gif +0 -0
  99. data/app/assets/stylesheets/tinymce/skins/alchemy/img/object.gif +0 -0
  100. data/app/assets/stylesheets/tinymce/skins/alchemy/img/trans.gif +0 -0
  101. data/app/assets/stylesheets/tinymce/skins/alchemy/skin.min.css.scss +0 -2077
  102. data/vendor/assets/javascripts/clipboard.min.js +0 -7
  103. data/vendor/assets/javascripts/keymaster.js +0 -296
  104. data/vendor/assets/javascripts/requestAnimationFrame.js +0 -31
  105. data/vendor/assets/javascripts/tinymce/license.txt +0 -504
  106. data/vendor/assets/javascripts/tinymce/tinymce.min.js +0 -2
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Copyright (c) Tiny Technologies, Inc. All rights reserved.
3
+ * Licensed under the LGPL or a commercial license.
4
+ * For LGPL see License.txt in the project root for license information.
5
+ * For commercial licenses see https://www.tiny.cloud/
6
+ */
7
+ .tinymce-mobile-outer-container{all:initial;display:block}.tinymce-mobile-outer-container *{border:0;box-sizing:initial;cursor:inherit;float:none;line-height:1;margin:0;outline:0;padding:0;-webkit-tap-highlight-color:transparent;text-shadow:none;white-space:nowrap}.tinymce-mobile-icon-arrow-back::before{content:"\e5cd"}.tinymce-mobile-icon-image::before{content:"\e412"}.tinymce-mobile-icon-cancel-circle::before{content:"\e5c9"}.tinymce-mobile-icon-full-dot::before{content:"\e061"}.tinymce-mobile-icon-align-center::before{content:"\e234"}.tinymce-mobile-icon-align-left::before{content:"\e236"}.tinymce-mobile-icon-align-right::before{content:"\e237"}.tinymce-mobile-icon-bold::before{content:"\e238"}.tinymce-mobile-icon-italic::before{content:"\e23f"}.tinymce-mobile-icon-unordered-list::before{content:"\e241"}.tinymce-mobile-icon-ordered-list::before{content:"\e242"}.tinymce-mobile-icon-font-size::before{content:"\e245"}.tinymce-mobile-icon-underline::before{content:"\e249"}.tinymce-mobile-icon-link::before{content:"\e157"}.tinymce-mobile-icon-unlink::before{content:"\eca2"}.tinymce-mobile-icon-color::before{content:"\e891"}.tinymce-mobile-icon-previous::before{content:"\e314"}.tinymce-mobile-icon-next::before{content:"\e315"}.tinymce-mobile-icon-large-font::before,.tinymce-mobile-icon-style-formats::before{content:"\e264"}.tinymce-mobile-icon-undo::before{content:"\e166"}.tinymce-mobile-icon-redo::before{content:"\e15a"}.tinymce-mobile-icon-removeformat::before{content:"\e239"}.tinymce-mobile-icon-small-font::before{content:"\e906"}.tinymce-mobile-format-matches::after,.tinymce-mobile-icon-readonly-back::before{content:"\e5ca"}.tinymce-mobile-icon-small-heading::before{content:"small"}.tinymce-mobile-icon-large-heading::before{content:"large"}.tinymce-mobile-icon-large-heading::before,.tinymce-mobile-icon-small-heading::before{font-family:sans-serif;font-size:80%}.tinymce-mobile-mask-edit-icon::before{content:"\e254"}.tinymce-mobile-icon-back::before{content:"\e5c4"}.tinymce-mobile-icon-heading::before{content:"Headings";font-family:sans-serif;font-size:80%;font-weight:700}.tinymce-mobile-icon-h1::before{content:"H1";font-weight:700}.tinymce-mobile-icon-h2::before{content:"H2";font-weight:700}.tinymce-mobile-icon-h3::before{content:"H3";font-weight:700}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask{align-items:center;display:flex;justify-content:center;background:rgba(51,51,51,.5);height:100%;position:absolute;top:0;width:100%}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container{align-items:center;border-radius:50%;display:flex;flex-direction:column;font-family:sans-serif;font-size:1em;justify-content:space-between}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .mixin-menu-item{align-items:center;display:flex;justify-content:center;border-radius:50%;height:2.1em;width:2.1em}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{align-items:center;display:flex;justify-content:center;flex-direction:column;font-size:1em}@media only screen and (min-device-width:700px){.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section{font-size:1.2em}}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon{align-items:center;display:flex;justify-content:center;border-radius:50%;height:2.1em;width:2.1em;background-color:#fff;color:#207ab7}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section .tinymce-mobile-mask-tap-icon::before{content:"\e900";font-family:tinymce-mobile,sans-serif}.tinymce-mobile-outer-container .tinymce-mobile-disabled-mask .tinymce-mobile-content-container .tinymce-mobile-content-tap-section:not(.tinymce-mobile-mask-tap-icon-selected) .tinymce-mobile-mask-tap-icon{z-index:2}.tinymce-mobile-android-container.tinymce-mobile-android-maximized{background:#fff;border:none;bottom:0;display:flex;flex-direction:column;left:0;position:fixed;right:0;top:0}.tinymce-mobile-android-container:not(.tinymce-mobile-android-maximized){position:relative}.tinymce-mobile-android-container .tinymce-mobile-editor-socket{display:flex;flex-grow:1}.tinymce-mobile-android-container .tinymce-mobile-editor-socket iframe{display:flex!important;flex-grow:1;height:auto!important}.tinymce-mobile-android-scroll-reload{overflow:hidden}:not(.tinymce-mobile-readonly-mode)>.tinymce-mobile-android-selection-context-toolbar{margin-top:23px}.tinymce-mobile-toolstrip{background:#fff;display:flex;flex:0 0 auto;z-index:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar{align-items:center;background-color:#fff;border-bottom:1px solid #ccc;display:flex;flex:1;height:2.5em;width:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group{align-items:center;display:flex;height:100%;flex-shrink:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group>div{align-items:center;display:flex;height:100%;flex:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-exit-container{background:#f44336}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group.tinymce-mobile-toolbar-scrollable-group{flex-grow:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{padding-left:.5em;padding-right:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button{align-items:center;display:flex;height:80%;margin-left:2px;margin-right:2px}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item.tinymce-mobile-toolbar-button.tinymce-mobile-toolbar-button-selected{background:#bfbfbf;color:#ccc}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:first-of-type,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar:not(.tinymce-mobile-context-toolbar) .tinymce-mobile-toolbar-group:last-of-type{background:#207ab7;color:#eceff1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group{align-items:center;display:flex;height:100%;flex:1;padding-bottom:.4em;padding-top:.4em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog{display:flex;min-height:1.5em;overflow:hidden;padding-left:0;padding-right:0;position:relative;width:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain{display:flex;height:100%;transition:left cubic-bezier(.4,0,1,1) .15s;width:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen{display:flex;flex:0 0 auto;justify-content:space-between;width:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen input{font-family:Sans-serif}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container{display:flex;flex-grow:1;position:relative}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container .tinymce-mobile-input-container-x{-ms-grid-row-align:center;align-self:center;background:inherit;border:none;border-radius:50%;color:#888;font-size:.6em;font-weight:700;height:100%;padding-right:2px;position:absolute;right:0}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-input-container.tinymce-mobile-input-container-empty .tinymce-mobile-input-container-x{display:none}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous{align-items:center;display:flex}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous::before{align-items:center;display:flex;font-weight:700;height:100%;padding-left:.5em;padding-right:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-next.tinymce-mobile-toolbar-navigation-disabled::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serialised-dialog .tinymce-mobile-serialised-dialog-chain .tinymce-mobile-serialised-dialog-screen .tinymce-mobile-icon-previous.tinymce-mobile-toolbar-navigation-disabled::before{visibility:hidden}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item{color:#ccc;font-size:10px;line-height:10px;margin:0 2px;padding-top:3px}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-item.tinymce-mobile-dot-active{color:#bfbfbf}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-large-heading::before{margin-left:.5em;margin-right:.9em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-font::before,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-icon-small-heading::before{margin-left:.9em;margin-right:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider{display:flex;flex:1;margin-left:0;margin-right:0;padding:.28em 0;position:relative}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container{align-items:center;display:flex;flex-grow:1;height:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-size-container .tinymce-mobile-slider-size-line{background:#ccc;display:flex;flex:1;height:.2em;margin-bottom:.3em;margin-top:.3em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container{padding-left:2em;padding-right:2em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container{align-items:center;display:flex;flex-grow:1;height:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-slider-gradient-container .tinymce-mobile-slider-gradient{background:linear-gradient(to right,red 0,#feff00 17%,#0f0 33%,#00feff 50%,#00f 67%,#ff00fe 83%,red 100%);display:flex;flex:1;height:.2em;margin-bottom:.3em;margin-top:.3em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-black{background:#000;height:.2em;margin-bottom:.3em;margin-top:.3em;width:1.2em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider.tinymce-mobile-hue-slider-container .tinymce-mobile-hue-slider-white{background:#fff;height:.2em;margin-bottom:.3em;margin-top:.3em;width:1.2em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb{align-items:center;background-clip:padding-box;background-color:#455a64;border:.5em solid rgba(136,136,136,0);border-radius:3em;bottom:0;color:#fff;display:flex;height:.5em;justify-content:center;left:-10px;margin:auto;position:absolute;top:0;transition:border 120ms cubic-bezier(.39,.58,.57,1);width:.5em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-slider .tinymce-mobile-slider-thumb.tinymce-mobile-thumb-active{border:.5em solid rgba(136,136,136,.39)}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper,.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group>div{align-items:center;display:flex;height:100%;flex:1}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-serializer-wrapper{flex-direction:column;justify-content:center}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item{align-items:center;display:flex}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-toolbar-group-item:not(.tinymce-mobile-serialised-dialog){height:100%}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group .tinymce-mobile-dot-container{display:flex}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input{background:#fff;border:none;border-radius:0;color:#455a64;flex-grow:1;font-size:.85em;padding-bottom:.1em;padding-left:5px;padding-top:.1em}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::-webkit-input-placeholder{color:#888}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input:-ms-input-placeholder{color:#888}.tinymce-mobile-toolstrip .tinymce-mobile-toolbar.tinymce-mobile-context-toolbar .tinymce-mobile-toolbar-group input::placeholder{color:#888}.tinymce-mobile-dropup{background:#fff;display:flex;overflow:hidden;width:100%}.tinymce-mobile-dropup.tinymce-mobile-dropup-shrinking{transition:height .3s ease-out}.tinymce-mobile-dropup.tinymce-mobile-dropup-growing{transition:height .3s ease-in}.tinymce-mobile-dropup.tinymce-mobile-dropup-closed{flex-grow:0}.tinymce-mobile-dropup.tinymce-mobile-dropup-open:not(.tinymce-mobile-dropup-growing){flex-grow:1}.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height:200px}@media only screen and (orientation:landscape){.tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height:200px}}@media only screen and (min-device-width :320px) and (max-device-width :568px) and (orientation :landscape){.tinymce-mobile-ios-container .tinymce-mobile-dropup:not(.tinymce-mobile-dropup-closed){min-height:150px}}.tinymce-mobile-styles-menu{font-family:sans-serif;outline:4px solid #000;overflow:hidden;position:relative;width:100%}.tinymce-mobile-styles-menu [role=menu]{display:flex;flex-direction:column;height:100%;position:absolute;width:100%}.tinymce-mobile-styles-menu [role=menu].transitioning{transition:transform .5s ease-in-out}.tinymce-mobile-styles-menu .tinymce-mobile-styles-item{border-bottom:1px solid #ddd;color:#455a64;cursor:pointer;display:flex;padding:1em 1em;position:relative}.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser .tinymce-mobile-styles-collapse-icon::before{color:#455a64;content:"\e314";font-family:tinymce-mobile,sans-serif}.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-styles-item-is-menu::after{color:#455a64;content:"\e315";font-family:tinymce-mobile,sans-serif;padding-left:1em;padding-right:1em;position:absolute;right:0}.tinymce-mobile-styles-menu .tinymce-mobile-styles-item.tinymce-mobile-format-matches::after{font-family:tinymce-mobile,sans-serif;padding-left:1em;padding-right:1em;position:absolute;right:0}.tinymce-mobile-styles-menu .tinymce-mobile-styles-collapser,.tinymce-mobile-styles-menu .tinymce-mobile-styles-separator{align-items:center;background:#fff;border-top:#455a64;color:#455a64;display:flex;min-height:2.5em;padding-left:1em;padding-right:1em}.tinymce-mobile-styles-menu [data-transitioning-destination=before][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=before]{transform:translate(-100%)}.tinymce-mobile-styles-menu [data-transitioning-destination=current][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=current]{transform:translate(0)}.tinymce-mobile-styles-menu [data-transitioning-destination=after][data-transitioning-state],.tinymce-mobile-styles-menu [data-transitioning-state=after]{transform:translate(100%)}@font-face{font-family:tinymce-mobile;font-style:normal;font-weight:400;src:url(fonts/tinymce-mobile.woff?8x92w3) format('woff')}@media (min-device-width:700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size:25px}}@media (max-device-width:700px){.tinymce-mobile-outer-container,.tinymce-mobile-outer-container input{font-size:18px}}.tinymce-mobile-icon{font-family:tinymce-mobile,sans-serif}.mixin-flex-and-centre{align-items:center;display:flex;justify-content:center}.mixin-flex-bar{align-items:center;display:flex;height:100%}.tinymce-mobile-outer-container .tinymce-mobile-editor-socket iframe{background-color:#fff;width:100%}.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{background-color:#207ab7;border-radius:50%;bottom:1em;color:#fff;font-size:1em;height:2.1em;position:fixed;right:2em;width:2.1em;align-items:center;display:flex;justify-content:center}@media only screen and (min-device-width:700px){.tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{font-size:1.2em}}.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket{height:300px;overflow:hidden}.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-editor-socket iframe{height:100%}.tinymce-mobile-outer-container:not(.tinymce-mobile-fullscreen-maximized) .tinymce-mobile-toolstrip{display:none}input[type=file]::-webkit-file-upload-button{display:none}@media only screen and (min-device-width :320px) and (max-device-width :568px) and (orientation :landscape){.tinymce-mobile-ios-container .tinymce-mobile-editor-socket .tinymce-mobile-mask-edit-icon{bottom:50%}}
@@ -183,14 +183,19 @@ module Alchemy
183
183
  respond_to do |format|
184
184
  format.js
185
185
  format.html do
186
- redirect_to(
187
- params[:redirect_to].presence || admin_pages_path,
188
- allow_other_host: true
189
- )
186
+ redirect_to(unlock_redirect_path, allow_other_host: true)
190
187
  end
191
188
  end
192
189
  end
193
190
 
191
+ def unlock_redirect_path
192
+ if params[:redirect_to].to_s.match?(/\A\/admin\/(layout_)?pages/)
193
+ params[:redirect_to]
194
+ else
195
+ admin_pages_path
196
+ end
197
+ end
198
+
194
199
  # Sets the page public and updates the published_at attribute that is used as cache_key
195
200
  #
196
201
  def publish
@@ -0,0 +1,16 @@
1
+ import "clipboard"
2
+
3
+ const clipboard = new ClipboardJS("[data-clipboard-text]")
4
+
5
+ clipboard.on("success", (e) => {
6
+ Alchemy.growl(e.trigger.dataset.clipboardSuccessText)
7
+ e.clearSelection()
8
+ })
9
+
10
+ const currentDialog = Alchemy.currentDialog()
11
+
12
+ if (currentDialog) {
13
+ currentDialog.dialog.on("DialogClose.Alchemy", () => {
14
+ clipboard.destroy()
15
+ })
16
+ }
@@ -1,12 +1,10 @@
1
+ import "tinymce"
1
2
  import { AlchemyHTMLElement } from "alchemy_admin/components/alchemy_html_element"
2
3
  import { currentLocale } from "alchemy_admin/i18n"
3
4
 
4
- const TOOLBAR_ROW_HEIGHT = 30
5
- const TOOLBAR_BORDER_WIDTH = 1
6
- const STATUSBAR_HEIGHT = 29.5
7
- const EDITOR_BORDER_WIDTH = 2
8
-
9
5
  class Tinymce extends AlchemyHTMLElement {
6
+ #min_height = null
7
+
10
8
  /**
11
9
  * the observer will initialize Tinymce if the textarea becomes visible
12
10
  */
@@ -89,7 +87,7 @@ class Tinymce extends AlchemyHTMLElement {
89
87
 
90
88
  // read the attributes on the component and add them as custom configuration
91
89
  this.getAttributeNames().forEach((attributeName) => {
92
- if (!["class", "id", "is", "name"].includes(attributeName)) {
90
+ if (!["class", "id", "is", "name", "style"].includes(attributeName)) {
93
91
  const config = this.getAttribute(attributeName)
94
92
  const key = attributeName.replaceAll("-", "_")
95
93
 
@@ -125,21 +123,11 @@ class Tinymce extends AlchemyHTMLElement {
125
123
  }
126
124
 
127
125
  get minHeight() {
128
- let minHeight = this.configuration.min_height || 0
129
-
130
- if (Array.isArray(this.configuration.toolbar)) {
131
- minHeight += this.configuration.toolbar.length * TOOLBAR_ROW_HEIGHT
132
- minHeight += TOOLBAR_BORDER_WIDTH
133
- } else if (this.configuration.toolbar) {
134
- minHeight += TOOLBAR_ROW_HEIGHT
135
- minHeight += TOOLBAR_BORDER_WIDTH
136
- }
137
- if (this.configuration.statusbar) {
138
- minHeight += STATUSBAR_HEIGHT
139
- }
140
- minHeight += EDITOR_BORDER_WIDTH
126
+ return this.#min_height || this.configuration.min_height
127
+ }
141
128
 
142
- return minHeight
129
+ set minHeight(value) {
130
+ this.#min_height = value
143
131
  }
144
132
  }
145
133
 
@@ -1,5 +1,5 @@
1
- import debounce from "lodash-es/debounce"
2
- import max from "lodash-es/max"
1
+ import debounce from "alchemy_admin/utils/debounce"
2
+ import max from "alchemy_admin/utils/max"
3
3
  import { get } from "alchemy_admin/utils/ajax"
4
4
  import ImageLoader from "alchemy_admin/image_loader"
5
5
 
@@ -27,6 +27,8 @@ class PictureEditor {
27
27
  this.imageLoader = new ImageLoader(this.image)
28
28
  }
29
29
 
30
+ // The mutation observer is observing multiple fields that all get updated
31
+ // simultaneously. We only want to update the image once, so we debounce.
30
32
  this.update = debounce(() => {
31
33
  this.updateImage()
32
34
  this.updateCropLink()
@@ -0,0 +1,10 @@
1
+ export default function (func, delay) {
2
+ let timeout
3
+
4
+ return function (...args) {
5
+ const that = this
6
+
7
+ clearTimeout(timeout)
8
+ timeout = setTimeout(() => func.apply(that, args), delay)
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ export default function (a, b) {
2
+ return a >= b ? a : b
3
+ }
@@ -1,5 +1,7 @@
1
1
  import "@ungap/custom-elements"
2
2
  import "@hotwired/turbo-rails"
3
+ import "keymaster"
4
+
3
5
  import Rails from "@rails/ujs"
4
6
 
5
7
  import GUI from "alchemy_admin/gui"
@@ -16,9 +18,6 @@ import SortableElements from "alchemy_admin/sortable_elements"
16
18
  import Spinner from "alchemy_admin/spinner"
17
19
  import PagePublicationFields from "alchemy_admin/page_publication_fields"
18
20
 
19
- // Setting jQueryUIs global animation duration to something more snappy
20
- $.fx.speeds._default = 400
21
-
22
21
  // Web Components
23
22
  import "alchemy_admin/components/button"
24
23
  import "alchemy_admin/components/char_counter"
@@ -34,14 +33,9 @@ import "alchemy_admin/components/page_select"
34
33
  import "alchemy_admin/components/select"
35
34
  import "alchemy_admin/components/spinner"
36
35
  import "alchemy_admin/components/tinymce"
37
- import "@shoelace/progress-bar"
38
- import "@shoelace/switch"
39
- import "@shoelace/tab"
40
- import "@shoelace/tab-group"
41
- import "@shoelace/tab-panel"
42
- import "@shoelace/tooltip"
36
+ import "alchemy_admin/clipboard"
43
37
 
44
- import { setDefaultAnimation } from "@shoelace/animation-registry"
38
+ import { setDefaultAnimation } from "shoelace"
45
39
 
46
40
  // Change the default animation for all dialogs
47
41
  setDefaultAnimation("tooltip.show", {
@@ -25,6 +25,8 @@ module Alchemy
25
25
  after_update :update_descendants_urlnames,
26
26
  if: :saved_change_to_urlname?
27
27
 
28
+ before_save :destroy_obsolete_legacy_urls, if: :renamed?
29
+
28
30
  after_move :update_urlname!
29
31
  end
30
32
 
@@ -55,6 +57,11 @@ module Alchemy
55
57
  descendants.each(&:update_urlname!)
56
58
  end
57
59
 
60
+ def destroy_obsolete_legacy_urls
61
+ obsolete_legacy_urls = legacy_urls.select { |legacy_url| legacy_url.urlname == urlname }
62
+ legacy_urls.destroy(obsolete_legacy_urls)
63
+ end
64
+
58
65
  # Sets the urlname to a url friendly slug.
59
66
  # Either from name, or if present, from urlname.
60
67
  # The urlname contains the whole path including parent urlnames.
@@ -114,8 +114,8 @@ module Alchemy
114
114
 
115
115
  has_one :site, through: :language
116
116
  has_many :site_languages, through: :site, source: :languages
117
- has_many :folded_pages
118
- has_many :legacy_urls, class_name: "Alchemy::LegacyPageUrl"
117
+ has_many :folded_pages, dependent: :destroy
118
+ has_many :legacy_urls, class_name: "Alchemy::LegacyPageUrl", dependent: :destroy
119
119
  has_many :nodes, class_name: "Alchemy::Node", inverse_of: :page
120
120
  has_many :versions, class_name: "Alchemy::PageVersion", inverse_of: :page, dependent: :destroy
121
121
  has_one :draft_version, -> { drafts }, class_name: "Alchemy::PageVersion"
@@ -14,6 +14,8 @@ module Alchemy
14
14
  include Alchemy::Picture::Transformations
15
15
 
16
16
  ANIMATED_IMAGE_FORMATS = %w[gif webp]
17
+ TRANSPARENT_IMAGE_FORMATS = %w[gif webp png]
18
+ ENCODABLE_IMAGE_FORMATS = %w[jpg jpeg webp]
17
19
 
18
20
  attr_reader :picture, :render_format
19
21
 
@@ -94,12 +96,15 @@ module Alchemy
94
96
 
95
97
  convert_format = render_format.sub("jpeg", "jpg") != picture.image_file_format.sub("jpeg", "jpg")
96
98
 
97
- if render_format =~ /jpe?g/ && (convert_format || options[:quality])
98
- quality = options[:quality] || Config.get(:output_image_jpg_quality)
99
+ if encodable_image? && (convert_format || options[:quality])
100
+ quality = options[:quality] || Config.get(:output_image_quality)
99
101
  encoding_options << "-quality #{quality}"
100
102
  end
101
103
 
102
104
  if options[:flatten]
105
+ if render_format.in?(TRANSPARENT_IMAGE_FORMATS) && picture.image_file_format.in?(TRANSPARENT_IMAGE_FORMATS)
106
+ encoding_options << "-background transparent"
107
+ end
103
108
  encoding_options << "-flatten"
104
109
  end
105
110
 
@@ -111,5 +116,9 @@ module Alchemy
111
116
 
112
117
  image
113
118
  end
119
+
120
+ def encodable_image?
121
+ render_format.in?(ENCODABLE_IMAGE_FORMATS)
122
+ end
114
123
  end
115
124
  end
@@ -84,7 +84,7 @@ module Alchemy
84
84
  crop_from: crop && crop_from.presence || default_crop_from&.join("x"),
85
85
  crop_size: crop && crop_size.presence || default_crop_size&.join("x"),
86
86
  flatten: true,
87
- format: picture&.image_file_format || "jpg"
87
+ format: "webp"
88
88
  }
89
89
  end
90
90
 
@@ -8,14 +8,14 @@
8
8
  <div class="value with-icon">
9
9
  <label><%= Alchemy::Attachment.human_attribute_name(:url) %></label>
10
10
  <p><%= @attachment.url %></p>
11
- <a data-clipboard-text="<%= @attachment.url %>" class="icon_button--right">
11
+ <a data-clipboard-text="<%= @attachment.url %>" data-clipboard-success-text="<%= Alchemy.t("Copied to clipboard") %>" class="icon_button--right">
12
12
  <%= render_icon(:clipboard) %>
13
13
  </a>
14
14
  </div>
15
15
  <div class="value with-icon">
16
16
  <label><%= Alchemy::Attachment.human_attribute_name(:download_url) %></label>
17
17
  <p><%= @attachment.url(download: true) %></p>
18
- <a data-clipboard-text="<%= @attachment.url(download: true) %>" class="icon_button--right">
18
+ <a data-clipboard-text="<%= @attachment.url(download: true) %>" data-clipboard-success-text="<%= Alchemy.t("Copied to clipboard") %>" class="icon_button--right">
19
19
  <%= render_icon(:clipboard) %>
20
20
  </a>
21
21
  </div>
@@ -39,16 +39,3 @@
39
39
  Your browser does not support frames.
40
40
  </iframe>
41
41
  <% end %>
42
-
43
- <script type="text/javascript">
44
- $(function() {
45
- var clipboard = new Clipboard('.icon_button--right');
46
- clipboard.on('success', function(e) {
47
- Alchemy.growl('<%= Alchemy.t("Copied to clipboard") %>');
48
- e.clearSelection();
49
- });
50
- Alchemy.currentDialog().dialog.on('DialogClose.Alchemy', function() {
51
- clipboard.destroy();
52
- });
53
- });
54
- </script>
@@ -20,11 +20,9 @@
20
20
  </sl-tooltip>
21
21
  </span>
22
22
  <% end %>
23
- <% image = image_tag(
24
- picture.url(size: preview_size(@size), flatten: true) || "alchemy/missing-image.svg",
25
- alt: picture.name
26
- ) %>
27
- <% if can?(:edit, picture) %>
23
+ <% picture_url = picture.url(size: preview_size(@size), flatten: true, format: "webp") %>
24
+ <% image = image_tag(picture_url || "alchemy/missing-image.svg", alt: picture.name) %>
25
+ <% if can?(:edit, picture) && picture_url %>
28
26
  <%= link_to(
29
27
  image,
30
28
  alchemy.admin_picture_path(
@@ -2,7 +2,7 @@
2
2
  <sl-tooltip content="<%= Alchemy.t(:assign_image) %>">
3
3
  <%= link_to(
4
4
  image_tag(
5
- picture_to_assign.url(size: preview_size(size), flatten: true) || "alchemy/missing-image.svg",
5
+ picture_to_assign.url(size: preview_size(size), flatten: true, format: "webp") || "alchemy/missing-image.svg",
6
6
  alt: picture_to_assign.name
7
7
  ),
8
8
  alchemy.assign_admin_picture_path(
@@ -3,7 +3,7 @@
3
3
  <%= select_tag(
4
4
  filter.name,
5
5
  options_for_select(
6
- filter.options_for_select, params[:filter].try(:[], filter.name)
6
+ filter.options_for_select, search_filter_params.dig(:filter, filter.name)
7
7
  ),
8
8
  include_blank: Alchemy.t(:all, scope: ['resources', resource_name, 'filters']),
9
9
  data: { remote: !!request.xhr? },
@@ -1,6 +1,6 @@
1
1
  <%= form_tag url_for, method: :get, class: 'per-page-select-form' do |f| %>
2
2
  <% search_filter_params.reject { |k, _| k == 'page' || k == 'per_page' }.each do |key, value| %>
3
- <% if value.is_a? Hash %>
3
+ <% if value.is_a? ActionController::Parameters %>
4
4
  <% value.each do |k, v| %>
5
5
  <%= hidden_field_tag "#{key}[#{k}]", v, id: nil %>
6
6
  <% end %>
@@ -1,7 +1,6 @@
1
1
  <% asset_host = ActionController::Base.config.asset_host %>
2
2
 
3
- <link rel="preload" href="<%= asset_host %><%= assets_prefix %>/tinymce/skins/alchemy/skin.min.css" as="style" />
4
- <link rel="preload" href="<%= asset_host %><%= assets_prefix %>/tinymce/skins/alchemy/content.min.css" as="style" />
3
+ <link rel="preload" href="<%= asset_host %><%= assets_prefix %>/tinymce/skins/ui/alchemy/skin.min.css" as="style" />
5
4
  <% if Alchemy::Tinymce.init[:content_css] %>
6
5
  <link rel="preload" href="<%= asset_host %><%= Alchemy::Tinymce.init[:content_css] %>" as="style" />
7
6
  <% end %>
@@ -35,8 +35,8 @@
35
35
  <% if linkable %>
36
36
  <%= render "alchemy/ingredients/shared/link_tools", ingredient_editor: picture_editor %>
37
37
  <% else %>
38
- <span class="disabled"><%= render_icon("link", style: "m") %></span>
39
- <span class="disabled"><%= render_icon("link-unlink", style: "m") %></span>
38
+ <span class="icon_button disabled"><%= render_icon("link", style: "m") %></span>
39
+ <span class="icon_button disabled"><%= render_icon("link-unlink", style: "m") %></span>
40
40
  <% end %>
41
41
 
42
42
  <%= content_tag "sl-tooltip", content: Alchemy.t(:edit_image_properties), placement: "top-end" do %>
@@ -0,0 +1,10 @@
1
+ // Used to bundle our own Shoelace build with Rollup
2
+ import "@shoelace-style/shoelace/dist/utilities/animation-registry.js"
3
+ import "@shoelace-style/shoelace/dist/components/switch/switch.js"
4
+ import "@shoelace-style/shoelace/dist/components/tab/tab.js"
5
+ import "@shoelace-style/shoelace/dist/components/tab-group/tab-group.js"
6
+ import "@shoelace-style/shoelace/dist/components/tab-panel/tab-panel.js"
7
+ import "@shoelace-style/shoelace/dist/components/tooltip/tooltip.js"
8
+ import "@shoelace-style/shoelace/dist/components/progress-bar/progress-bar.js"
9
+ import { setDefaultAnimation } from "@shoelace-style/shoelace/dist/utilities/animation-registry.js"
10
+ export { setDefaultAnimation }
@@ -0,0 +1,20 @@
1
+ /* Import TinyMCE */
2
+ import tinymce from "tinymce"
3
+
4
+ /* Default icons are required. After that, import custom icons if applicable */
5
+ import "tinymce/icons/default"
6
+
7
+ /* Required TinyMCE components */
8
+ import "tinymce/themes/silver"
9
+ import "tinymce/models/dom"
10
+
11
+ /* Import plugins */
12
+ import "tinymce/plugins/anchor"
13
+ import "tinymce/plugins/charmap"
14
+ import "tinymce/plugins/code"
15
+ import "tinymce/plugins/directionality"
16
+ import "tinymce/plugins/fullscreen"
17
+ import "tinymce/plugins/link"
18
+ import "tinymce/plugins/lists"
19
+
20
+ export default tinymce
@@ -78,13 +78,13 @@ items_per_page: 15
78
78
  #
79
79
  # ==== Global Options:
80
80
  #
81
- # output_image_jpg_quality [Integer] # If image gets rendered as JPG this is the quality setting for it. (Default 85)
81
+ # output_image_quality [Integer] # If image gets rendered as JPG or WebP this is the quality setting for it. (Default 85)
82
82
  # 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)
83
83
  # image_output_format [String] # The global image output format setting. (Default +original+)
84
84
  #
85
85
  # NOTE: You can always override the output format in the settings of your ingredients in elements.yml, I.E. {format: 'gif'}
86
86
  #
87
- output_image_jpg_quality: 85
87
+ output_image_quality: 85
88
88
  preprocess_image_resize:
89
89
  image_output_format: original
90
90
 
@@ -133,7 +133,8 @@ mailer:
133
133
  mail_from: your.mail@your-domain.com
134
134
  mail_to: your.mail@your-domain.com
135
135
  subject: A new contact form message
136
- fields: [salutation, firstname, lastname, address, zip, city, phone, email, message]
136
+ fields:
137
+ [salutation, firstname, lastname, address, zip, city, phone, email, message]
137
138
  validate_fields: [lastname, email]
138
139
 
139
140
  # === User roles
@@ -166,14 +167,14 @@ uploader:
166
167
  file_size_limit: 100
167
168
  allowed_filetypes:
168
169
  alchemy/attachments:
169
- - '*'
170
+ - "*"
170
171
  alchemy/pictures:
171
- - jpg
172
- - jpeg
173
- - gif
174
- - png
175
- - svg
176
- - webp
172
+ - jpg
173
+ - jpeg
174
+ - gif
175
+ - png
176
+ - svg
177
+ - webp
177
178
 
178
179
  # === Link Target Options
179
180
  #
@@ -46,40 +46,6 @@
46
46
  ],
47
47
  "note": "Because we actually can't know all attributes each inheriting controller supports, we permit all resource model params. It is adviced that all inheriting controllers implement this method and provide its own set of permitted attributes. As this all happens inside the password protected /admin namespace this can be considered a false positive."
48
48
  },
49
- {
50
- "warning_type": "Dynamic Render Path",
51
- "warning_code": 15,
52
- "fingerprint": "384ec61125c6390d59fb7ebcf52792ba284bfd463d70d4ef552ab6c328e776f6",
53
- "check_name": "Render",
54
- "message": "Render path contains parameter value",
55
- "file": "app/views/alchemy/admin/elements/fold.js.erb",
56
- "line": 11,
57
- "link": "https://brakemanscanner.org/docs/warning_types/dynamic_render_path/",
58
- "code": "render(action => Alchemy::ElementEditor.new(Element.find(params[:id])), {})",
59
- "render_path": [
60
- {
61
- "type": "controller",
62
- "class": "Alchemy::Admin::ElementsController",
63
- "method": "fold",
64
- "line": 98,
65
- "file": "app/controllers/alchemy/admin/elements_controller.rb",
66
- "rendered": {
67
- "name": "alchemy/admin/elements/fold",
68
- "file": "app/views/alchemy/admin/elements/fold.js.erb"
69
- }
70
- }
71
- ],
72
- "location": {
73
- "type": "template",
74
- "template": "alchemy/admin/elements/fold"
75
- },
76
- "user_input": "params[:id]",
77
- "confidence": "Weak",
78
- "cwe_id": [
79
- 22
80
- ],
81
- "note": ""
82
- },
83
49
  {
84
50
  "warning_type": "Cross-Site Scripting",
85
51
  "warning_code": 4,
data/config/importmap.rb CHANGED
@@ -1,17 +1,12 @@
1
- pin "@ungap/custom-elements", to: "https://ga.jspm.io/npm:@ungap/custom-elements@1.3.0/index.js", preload: true
2
- pin "flatpickr", to: "https://ga.jspm.io/npm:flatpickr@4.6.13/dist/esm/index.js", preload: true
3
- pin "lodash-es/debounce", to: "https://ga.jspm.io/npm:lodash-es@4.17.21/debounce.js", preload: true
4
- pin "lodash-es/max", to: "https://ga.jspm.io/npm:lodash-es@4.17.21/max.js", preload: true
5
- pin "sortablejs", to: "https://ga.jspm.io/npm:sortablejs@1.15.1/modular/sortable.esm.js", preload: true
1
+ pin "@ungap/custom-elements", to: "ungap-custom-elements.min.js", preload: true # @1.3.0
2
+ pin "clipboard", to: "clipboard.min.js", preload: true
3
+ pin "flatpickr", to: "flatpickr.min.js", preload: true # @4.6.13
4
+ pin "keymaster", to: "keymaster.min.js", preload: true
5
+ pin "sortablejs", to: "sortable.min.js", preload: true # @1.15.1
6
6
  pin "@hotwired/turbo-rails", to: "turbo.min.js", preload: true
7
- pin "@shoelace/animation-registry", to: "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.12.0/cdn/utilities/animation-registry.js", preload: true
8
- pin "@shoelace/switch", to: "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.12.0/cdn/components/switch/switch.js", preload: true
9
- pin "@shoelace/tab", to: "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.12.0/cdn/components/tab/tab.js", preload: true
10
- pin "@shoelace/tab-group", to: "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.12.0/cdn/components/tab-group/tab-group.js", preload: true
11
- pin "@shoelace/tab-panel", to: "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.12.0/cdn/components/tab-panel/tab-panel.js", preload: true
12
- pin "@shoelace/tooltip", to: "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.12.0/cdn/components/tooltip/tooltip.js", preload: true
13
- pin "@shoelace/progress-bar", to: "https://cdn.jsdelivr.net/npm/@shoelace-style/shoelace@2.12.0/cdn/components/progress-bar/progress-bar.js", preload: true
14
- pin "@rails/ujs", to: "https://ga.jspm.io/npm:@rails/ujs@7.1.2/app/assets/javascripts/rails-ujs.esm.js"
7
+ pin "shoelace", to: "shoelace.min.js", preload: true
8
+ pin "@rails/ujs", to: "rails-ujs.min.js", preload: true # @7.1.2
9
+ pin "tinymce", to: "tinymce.min.js", preload: true
15
10
 
16
11
  pin "alchemy_admin", to: "alchemy_admin.js", preload: true
17
- pin_all_from File.expand_path("../app/javascript/alchemy_admin", __dir__), under: "alchemy_admin"
12
+ pin_all_from File.expand_path("../app/javascript/alchemy_admin", __dir__), under: "alchemy_admin", preload: true
@@ -16,6 +16,7 @@ end
16
16
 
17
17
  # Dragonfly 1.4.0 only allows `quality` as argument to `encode`
18
18
  Dragonfly::ImageMagick::Processors::Encode::WHITELISTED_ARGS << "flatten"
19
+ Dragonfly::ImageMagick::Processors::Encode::WHITELISTED_ARGS << "background"
19
20
 
20
21
  Rails.application.config.after_initialize do
21
22
  Dragonfly.app(:alchemy_pictures).add_processor(:crop_resize, Alchemy::Dragonfly::Processors::CropResize.new)
@@ -118,7 +118,9 @@ en:
118
118
  gif: GIF Image
119
119
  jpeg: JPG Image
120
120
  png: PNG Image
121
+ svg: SVG Image
121
122
  tiff: TIFF Image
123
+ webp: WebP Image
122
124
  misc:
123
125
  name: Miscellaneous
124
126
  values:
@@ -9,7 +9,8 @@ module Alchemy
9
9
  #
10
10
  def get(name)
11
11
  check_deprecation(name)
12
- show[name.to_s]
12
+ key = check_replacement(name)
13
+ show[key.to_s]
13
14
  end
14
15
 
15
16
  alias_method :parameter, :get
@@ -27,13 +28,20 @@ module Alchemy
27
28
  @config ||= merge_configs!(alchemy_config, main_app_config, env_specific_config)
28
29
  end
29
30
 
30
- # A list of deprecated configurations
31
+ # A list of deprecated configuration values
31
32
  # a value of nil means there is no new default
32
33
  # any not nil value is the new default
33
34
  def deprecated_configs
34
35
  {}
35
36
  end
36
37
 
38
+ # A list of replaced configuration keys
39
+ def replaced_config_keys
40
+ {
41
+ output_image_quality: :output_image_jpg_quality
42
+ }
43
+ end
44
+
37
45
  private
38
46
 
39
47
  # Alchemy default configuration
@@ -87,6 +95,20 @@ module Alchemy
87
95
  end
88
96
  end
89
97
  end
98
+
99
+ def check_replacement(name)
100
+ if replaced_config_keys.key?(name.to_sym)
101
+ old_key = replaced_config_keys[name.to_sym]
102
+ if show[old_key.to_s]
103
+ Alchemy::Deprecation.warn("Using #{old_key} configuration is deprecated and will be removed in Alchemy #{Alchemy::Deprecation.deprecation_horizon}. Please use #{name} instead.")
104
+ old_key
105
+ else
106
+ name
107
+ end
108
+ else
109
+ name
110
+ end
111
+ end
90
112
  end
91
113
  end
92
114
  end
@@ -24,7 +24,8 @@ module Alchemy
24
24
  Alchemy.importmap.draw(Engine.root.join("config", "importmap.rb"))
25
25
 
26
26
  package_path = Engine.root.join("app/javascript")
27
- app.config.assets.paths << package_path
27
+ vendor_packages_path = Engine.root.join("vendor/javascript")
28
+ app.config.assets.paths += [package_path, vendor_packages_path]
28
29
 
29
30
  if app.config.importmap.sweep_cache
30
31
  Alchemy.importmap.cache_sweeper(watches: package_path)