From 208f0b338b9e07c186f82b2581def4411531b0d8 Mon Sep 17 00:00:00 2001 From: Markos Gogoulos Date: Sun, 21 Sep 2025 15:38:43 +0300 Subject: [PATCH] feat: update versions for python packages, add Pages functionality (#1386) This PR updates Django core version and also brings html pages support (that admins can create) --- cms/dev_settings.py | 1 + cms/settings.py | 48 +- cms/urls.py | 1 + cms/version.py | 2 +- docs/admins_docs.md | 3 +- files/admin.py | 31 + files/methods.py | 3 + files/migrations/0013_page_tinymcemedia.py | 42 + files/models/__init__.py | 1 + files/models/page.py | 42 + files/tinymce_handlers.py | 20 + files/urls.py | 8 +- files/views/__init__.py | 1 + files/views/pages.py | 12 +- requirements.txt | 5 +- static/django_tinymce/init_tinymce.js | 82 + static/tinymce/icons/default/icons.min.js | 1 + static/tinymce/langs/README.md | 3 + static/tinymce/langs/ar.js | 1 + static/tinymce/langs/ar_SA.js | 1 + static/tinymce/langs/az.js | 1 + static/tinymce/langs/be.js | 1 + static/tinymce/langs/bg_BG.js | 1 + static/tinymce/langs/bn_BD.js | 1 + static/tinymce/langs/ca.js | 1 + static/tinymce/langs/cs.js | 1 + static/tinymce/langs/cy.js | 1 + static/tinymce/langs/da.js | 1 + static/tinymce/langs/de.js | 1 + static/tinymce/langs/dv.js | 1 + static/tinymce/langs/el.js | 1 + static/tinymce/langs/eo.js | 1 + static/tinymce/langs/es.js | 1 + static/tinymce/langs/es_MX.js | 1 + static/tinymce/langs/et.js | 1 + static/tinymce/langs/eu.js | 1 + static/tinymce/langs/fa.js | 1 + static/tinymce/langs/fi.js | 1 + static/tinymce/langs/fr_FR.js | 1 + static/tinymce/langs/ga.js | 1 + static/tinymce/langs/gl.js | 1 + static/tinymce/langs/he_IL.js | 1 + static/tinymce/langs/hi.js | 1 + static/tinymce/langs/hr.js | 1 + static/tinymce/langs/hu_HU.js | 1 + static/tinymce/langs/hy.js | 1 + static/tinymce/langs/id.js | 1 + static/tinymce/langs/is_IS.js | 1 + static/tinymce/langs/it.js | 1 + static/tinymce/langs/ja.js | 1 + static/tinymce/langs/ka_GE.js | 1 + static/tinymce/langs/kab.js | 1 + static/tinymce/langs/kk.js | 1 + static/tinymce/langs/ko_KR.js | 1 + static/tinymce/langs/ku.js | 1 + static/tinymce/langs/lt.js | 1 + static/tinymce/langs/lv.js | 1 + static/tinymce/langs/nb_NO.js | 1 + static/tinymce/langs/ne.js | 1 + static/tinymce/langs/nl.js | 1 + static/tinymce/langs/nl_BE.js | 1 + static/tinymce/langs/oc.js | 1 + static/tinymce/langs/pl.js | 1 + static/tinymce/langs/pt_BR.js | 1 + static/tinymce/langs/ro.js | 1 + static/tinymce/langs/ru.js | 1 + static/tinymce/langs/sk.js | 1 + static/tinymce/langs/sl_SI.js | 1 + static/tinymce/langs/sq.js | 1 + static/tinymce/langs/sr.js | 1 + static/tinymce/langs/sv_SE.js | 1 + static/tinymce/langs/ta.js | 1 + static/tinymce/langs/tg.js | 1 + static/tinymce/langs/th_TH.js | 1 + static/tinymce/langs/tr.js | 1 + static/tinymce/langs/ug.js | 1 + static/tinymce/langs/uk.js | 1 + static/tinymce/langs/uz.js | 1 + static/tinymce/langs/vi.js | 1 + static/tinymce/langs/zh-Hans.js | 1 + static/tinymce/langs/zh-Hant.js | 1 + static/tinymce/langs/zh_HK.js | 1 + static/tinymce/langs/zh_MO.js | 1 + static/tinymce/langs/zh_SG.js | 1 + static/tinymce/license.txt | 21 + static/tinymce/models/dom/model.min.js | 4 + .../tinymce/plugins/accordion/plugin.min.js | 4 + static/tinymce/plugins/advlist/plugin.min.js | 4 + static/tinymce/plugins/anchor/plugin.min.js | 4 + static/tinymce/plugins/autolink/plugin.min.js | 4 + .../tinymce/plugins/autoresize/plugin.min.js | 4 + static/tinymce/plugins/autosave/plugin.min.js | 4 + static/tinymce/plugins/charmap/plugin.min.js | 4 + static/tinymce/plugins/code/plugin.min.js | 4 + .../tinymce/plugins/codesample/plugin.min.js | 4 + .../plugins/directionality/plugin.min.js | 4 + .../plugins/emoticons/js/emojiimages.js | 1 + .../plugins/emoticons/js/emojiimages.min.js | 3 + static/tinymce/plugins/emoticons/js/emojis.js | 1 + .../plugins/emoticons/js/emojis.min.js | 2 + .../tinymce/plugins/emoticons/plugin.min.js | 4 + .../tinymce/plugins/fullscreen/plugin.min.js | 4 + .../tinymce/plugins/help/js/i18n/keynav/ar.js | 90 + .../plugins/help/js/i18n/keynav/bg_BG.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/ca.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/cs.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/da.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/de.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/el.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/en.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/es.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/eu.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/fa.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/fi.js | 90 + .../plugins/help/js/i18n/keynav/fr_FR.js | 90 + .../plugins/help/js/i18n/keynav/he_IL.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/hi.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/hr.js | 90 + .../plugins/help/js/i18n/keynav/hu_HU.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/id.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/it.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/ja.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/kk.js | 90 + .../plugins/help/js/i18n/keynav/ko_KR.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/ms.js | 90 + .../plugins/help/js/i18n/keynav/nb_NO.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/nl.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/pl.js | 90 + .../plugins/help/js/i18n/keynav/pt_BR.js | 90 + .../plugins/help/js/i18n/keynav/pt_PT.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/ro.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/ru.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/sk.js | 90 + .../plugins/help/js/i18n/keynav/sl_SI.js | 90 + .../plugins/help/js/i18n/keynav/sv_SE.js | 90 + .../plugins/help/js/i18n/keynav/th_TH.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/tr.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/uk.js | 90 + .../tinymce/plugins/help/js/i18n/keynav/vi.js | 90 + .../plugins/help/js/i18n/keynav/zh_CN.js | 84 + .../plugins/help/js/i18n/keynav/zh_TW.js | 90 + static/tinymce/plugins/help/plugin.min.js | 4 + static/tinymce/plugins/image/plugin.min.js | 4 + .../tinymce/plugins/importcss/plugin.min.js | 4 + .../plugins/insertdatetime/plugin.min.js | 4 + static/tinymce/plugins/link/plugin.min.js | 4 + static/tinymce/plugins/lists/plugin.min.js | 4 + static/tinymce/plugins/media/plugin.min.js | 4 + .../tinymce/plugins/nonbreaking/plugin.min.js | 4 + .../tinymce/plugins/pagebreak/plugin.min.js | 4 + static/tinymce/plugins/preview/plugin.min.js | 4 + .../tinymce/plugins/quickbars/plugin.min.js | 4 + static/tinymce/plugins/save/plugin.min.js | 4 + .../plugins/searchreplace/plugin.min.js | 4 + static/tinymce/plugins/table/plugin.min.js | 4 + static/tinymce/plugins/template/plugin.min.js | 4 + .../plugins/visualblocks/plugin.min.js | 4 + .../tinymce/plugins/visualchars/plugin.min.js | 4 + .../tinymce/plugins/wordcount/plugin.min.js | 4 + static/tinymce/skins/content/dark/content.js | 2 + .../skins/content/dark/content.min.css | 1 + .../tinymce/skins/content/default/content.js | 2 + .../skins/content/default/content.min.css | 1 + .../tinymce/skins/content/document/content.js | 2 + .../skins/content/document/content.min.css | 1 + .../skins/content/tinymce-5-dark/content.js | 2 + .../content/tinymce-5-dark/content.min.css | 1 + .../skins/content/tinymce-5/content.js | 2 + .../skins/content/tinymce-5/content.min.css | 1 + .../tinymce/skins/content/writer/content.js | 2 + .../skins/content/writer/content.min.css | 1 + .../skins/ui/oxide-dark/content.inline.js | 2 + .../ui/oxide-dark/content.inline.min.css | 1 + static/tinymce/skins/ui/oxide-dark/content.js | 2 + .../skins/ui/oxide-dark/content.min.css | 1 + static/tinymce/skins/ui/oxide-dark/skin.js | 2 + .../tinymce/skins/ui/oxide-dark/skin.min.css | 1 + .../skins/ui/oxide-dark/skin.shadowdom.js | 2 + .../ui/oxide-dark/skin.shadowdom.min.css | 1 + .../tinymce/skins/ui/oxide/content.inline.js | 2 + .../skins/ui/oxide/content.inline.min.css | 1 + static/tinymce/skins/ui/oxide/content.js | 2 + static/tinymce/skins/ui/oxide/content.min.css | 1 + static/tinymce/skins/ui/oxide/skin.js | 2 + static/tinymce/skins/ui/oxide/skin.min.css | 1 + .../tinymce/skins/ui/oxide/skin.shadowdom.js | 2 + .../skins/ui/oxide/skin.shadowdom.min.css | 1 + .../skins/ui/tinymce-5-dark/content.inline.js | 2 + .../ui/tinymce-5-dark/content.inline.min.css | 1 + .../skins/ui/tinymce-5-dark/content.js | 2 + .../skins/ui/tinymce-5-dark/content.min.css | 1 + .../tinymce/skins/ui/tinymce-5-dark/skin.js | 2 + .../skins/ui/tinymce-5-dark/skin.min.css | 1 + .../skins/ui/tinymce-5-dark/skin.shadowdom.js | 2 + .../ui/tinymce-5-dark/skin.shadowdom.min.css | 1 + .../skins/ui/tinymce-5/content.inline.js | 2 + .../skins/ui/tinymce-5/content.inline.min.css | 1 + static/tinymce/skins/ui/tinymce-5/content.js | 2 + .../skins/ui/tinymce-5/content.min.css | 1 + static/tinymce/skins/ui/tinymce-5/skin.js | 2 + .../tinymce/skins/ui/tinymce-5/skin.min.css | 1 + .../skins/ui/tinymce-5/skin.shadowdom.js | 2 + .../skins/ui/tinymce-5/skin.shadowdom.min.css | 1 + static/tinymce/themes/silver/theme.min.js | 4 + static/tinymce/tinymce.d.ts | 3238 +++++++++++++++++ static/tinymce/tinymce.min.js | 4 + templates/cms/edit_subtitle.html | 9 + templates/cms/media_nav.html | 12 +- templates/cms/page.html | 52 + 209 files changed, 7399 insertions(+), 14 deletions(-) create mode 100644 files/migrations/0013_page_tinymcemedia.py create mode 100644 files/models/page.py create mode 100644 files/tinymce_handlers.py create mode 100644 static/django_tinymce/init_tinymce.js create mode 100644 static/tinymce/icons/default/icons.min.js create mode 100644 static/tinymce/langs/README.md create mode 100644 static/tinymce/langs/ar.js create mode 100644 static/tinymce/langs/ar_SA.js create mode 100644 static/tinymce/langs/az.js create mode 100644 static/tinymce/langs/be.js create mode 100644 static/tinymce/langs/bg_BG.js create mode 100644 static/tinymce/langs/bn_BD.js create mode 100644 static/tinymce/langs/ca.js create mode 100644 static/tinymce/langs/cs.js create mode 100644 static/tinymce/langs/cy.js create mode 100644 static/tinymce/langs/da.js create mode 100644 static/tinymce/langs/de.js create mode 100644 static/tinymce/langs/dv.js create mode 100644 static/tinymce/langs/el.js create mode 100644 static/tinymce/langs/eo.js create mode 100644 static/tinymce/langs/es.js create mode 100644 static/tinymce/langs/es_MX.js create mode 100644 static/tinymce/langs/et.js create mode 100644 static/tinymce/langs/eu.js create mode 100644 static/tinymce/langs/fa.js create mode 100644 static/tinymce/langs/fi.js create mode 100644 static/tinymce/langs/fr_FR.js create mode 100644 static/tinymce/langs/ga.js create mode 100644 static/tinymce/langs/gl.js create mode 100644 static/tinymce/langs/he_IL.js create mode 100644 static/tinymce/langs/hi.js create mode 100644 static/tinymce/langs/hr.js create mode 100644 static/tinymce/langs/hu_HU.js create mode 100644 static/tinymce/langs/hy.js create mode 100644 static/tinymce/langs/id.js create mode 100644 static/tinymce/langs/is_IS.js create mode 100644 static/tinymce/langs/it.js create mode 100644 static/tinymce/langs/ja.js create mode 100644 static/tinymce/langs/ka_GE.js create mode 100644 static/tinymce/langs/kab.js create mode 100644 static/tinymce/langs/kk.js create mode 100644 static/tinymce/langs/ko_KR.js create mode 100644 static/tinymce/langs/ku.js create mode 100644 static/tinymce/langs/lt.js create mode 100644 static/tinymce/langs/lv.js create mode 100644 static/tinymce/langs/nb_NO.js create mode 100644 static/tinymce/langs/ne.js create mode 100644 static/tinymce/langs/nl.js create mode 100644 static/tinymce/langs/nl_BE.js create mode 100644 static/tinymce/langs/oc.js create mode 100644 static/tinymce/langs/pl.js create mode 100644 static/tinymce/langs/pt_BR.js create mode 100644 static/tinymce/langs/ro.js create mode 100644 static/tinymce/langs/ru.js create mode 100644 static/tinymce/langs/sk.js create mode 100644 static/tinymce/langs/sl_SI.js create mode 100644 static/tinymce/langs/sq.js create mode 100644 static/tinymce/langs/sr.js create mode 100644 static/tinymce/langs/sv_SE.js create mode 100644 static/tinymce/langs/ta.js create mode 100644 static/tinymce/langs/tg.js create mode 100644 static/tinymce/langs/th_TH.js create mode 100644 static/tinymce/langs/tr.js create mode 100644 static/tinymce/langs/ug.js create mode 100644 static/tinymce/langs/uk.js create mode 100644 static/tinymce/langs/uz.js create mode 100644 static/tinymce/langs/vi.js create mode 100644 static/tinymce/langs/zh-Hans.js create mode 100644 static/tinymce/langs/zh-Hant.js create mode 100644 static/tinymce/langs/zh_HK.js create mode 100644 static/tinymce/langs/zh_MO.js create mode 100644 static/tinymce/langs/zh_SG.js create mode 100644 static/tinymce/license.txt create mode 100644 static/tinymce/models/dom/model.min.js create mode 100644 static/tinymce/plugins/accordion/plugin.min.js create mode 100644 static/tinymce/plugins/advlist/plugin.min.js create mode 100644 static/tinymce/plugins/anchor/plugin.min.js create mode 100644 static/tinymce/plugins/autolink/plugin.min.js create mode 100644 static/tinymce/plugins/autoresize/plugin.min.js create mode 100644 static/tinymce/plugins/autosave/plugin.min.js create mode 100644 static/tinymce/plugins/charmap/plugin.min.js create mode 100644 static/tinymce/plugins/code/plugin.min.js create mode 100644 static/tinymce/plugins/codesample/plugin.min.js create mode 100644 static/tinymce/plugins/directionality/plugin.min.js create mode 100644 static/tinymce/plugins/emoticons/js/emojiimages.js create mode 100644 static/tinymce/plugins/emoticons/js/emojiimages.min.js create mode 100644 static/tinymce/plugins/emoticons/js/emojis.js create mode 100644 static/tinymce/plugins/emoticons/js/emojis.min.js create mode 100644 static/tinymce/plugins/emoticons/plugin.min.js create mode 100644 static/tinymce/plugins/fullscreen/plugin.min.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/ar.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/bg_BG.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/ca.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/cs.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/da.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/de.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/el.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/en.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/es.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/eu.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/fa.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/fi.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/fr_FR.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/he_IL.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/hi.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/hr.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/hu_HU.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/id.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/it.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/ja.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/kk.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/ko_KR.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/ms.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/nb_NO.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/nl.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/pl.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/pt_BR.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/pt_PT.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/ro.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/ru.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/sk.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/sl_SI.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/sv_SE.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/th_TH.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/tr.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/uk.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/vi.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/zh_CN.js create mode 100644 static/tinymce/plugins/help/js/i18n/keynav/zh_TW.js create mode 100644 static/tinymce/plugins/help/plugin.min.js create mode 100644 static/tinymce/plugins/image/plugin.min.js create mode 100644 static/tinymce/plugins/importcss/plugin.min.js create mode 100644 static/tinymce/plugins/insertdatetime/plugin.min.js create mode 100644 static/tinymce/plugins/link/plugin.min.js create mode 100644 static/tinymce/plugins/lists/plugin.min.js create mode 100644 static/tinymce/plugins/media/plugin.min.js create mode 100644 static/tinymce/plugins/nonbreaking/plugin.min.js create mode 100644 static/tinymce/plugins/pagebreak/plugin.min.js create mode 100644 static/tinymce/plugins/preview/plugin.min.js create mode 100644 static/tinymce/plugins/quickbars/plugin.min.js create mode 100644 static/tinymce/plugins/save/plugin.min.js create mode 100644 static/tinymce/plugins/searchreplace/plugin.min.js create mode 100644 static/tinymce/plugins/table/plugin.min.js create mode 100644 static/tinymce/plugins/template/plugin.min.js create mode 100644 static/tinymce/plugins/visualblocks/plugin.min.js create mode 100644 static/tinymce/plugins/visualchars/plugin.min.js create mode 100644 static/tinymce/plugins/wordcount/plugin.min.js create mode 100644 static/tinymce/skins/content/dark/content.js create mode 100644 static/tinymce/skins/content/dark/content.min.css create mode 100644 static/tinymce/skins/content/default/content.js create mode 100644 static/tinymce/skins/content/default/content.min.css create mode 100644 static/tinymce/skins/content/document/content.js create mode 100644 static/tinymce/skins/content/document/content.min.css create mode 100644 static/tinymce/skins/content/tinymce-5-dark/content.js create mode 100644 static/tinymce/skins/content/tinymce-5-dark/content.min.css create mode 100644 static/tinymce/skins/content/tinymce-5/content.js create mode 100644 static/tinymce/skins/content/tinymce-5/content.min.css create mode 100644 static/tinymce/skins/content/writer/content.js create mode 100644 static/tinymce/skins/content/writer/content.min.css create mode 100644 static/tinymce/skins/ui/oxide-dark/content.inline.js create mode 100644 static/tinymce/skins/ui/oxide-dark/content.inline.min.css create mode 100644 static/tinymce/skins/ui/oxide-dark/content.js create mode 100644 static/tinymce/skins/ui/oxide-dark/content.min.css create mode 100644 static/tinymce/skins/ui/oxide-dark/skin.js create mode 100644 static/tinymce/skins/ui/oxide-dark/skin.min.css create mode 100644 static/tinymce/skins/ui/oxide-dark/skin.shadowdom.js create mode 100644 static/tinymce/skins/ui/oxide-dark/skin.shadowdom.min.css create mode 100644 static/tinymce/skins/ui/oxide/content.inline.js create mode 100644 static/tinymce/skins/ui/oxide/content.inline.min.css create mode 100644 static/tinymce/skins/ui/oxide/content.js create mode 100644 static/tinymce/skins/ui/oxide/content.min.css create mode 100644 static/tinymce/skins/ui/oxide/skin.js create mode 100644 static/tinymce/skins/ui/oxide/skin.min.css create mode 100644 static/tinymce/skins/ui/oxide/skin.shadowdom.js create mode 100644 static/tinymce/skins/ui/oxide/skin.shadowdom.min.css create mode 100644 static/tinymce/skins/ui/tinymce-5-dark/content.inline.js create mode 100644 static/tinymce/skins/ui/tinymce-5-dark/content.inline.min.css create mode 100644 static/tinymce/skins/ui/tinymce-5-dark/content.js create mode 100644 static/tinymce/skins/ui/tinymce-5-dark/content.min.css create mode 100644 static/tinymce/skins/ui/tinymce-5-dark/skin.js create mode 100644 static/tinymce/skins/ui/tinymce-5-dark/skin.min.css create mode 100644 static/tinymce/skins/ui/tinymce-5-dark/skin.shadowdom.js create mode 100644 static/tinymce/skins/ui/tinymce-5-dark/skin.shadowdom.min.css create mode 100644 static/tinymce/skins/ui/tinymce-5/content.inline.js create mode 100644 static/tinymce/skins/ui/tinymce-5/content.inline.min.css create mode 100644 static/tinymce/skins/ui/tinymce-5/content.js create mode 100644 static/tinymce/skins/ui/tinymce-5/content.min.css create mode 100644 static/tinymce/skins/ui/tinymce-5/skin.js create mode 100644 static/tinymce/skins/ui/tinymce-5/skin.min.css create mode 100644 static/tinymce/skins/ui/tinymce-5/skin.shadowdom.js create mode 100644 static/tinymce/skins/ui/tinymce-5/skin.shadowdom.min.css create mode 100644 static/tinymce/themes/silver/theme.min.js create mode 100644 static/tinymce/tinymce.d.ts create mode 100644 static/tinymce/tinymce.min.js create mode 100644 templates/cms/page.html diff --git a/cms/dev_settings.py b/cms/dev_settings.py index 5af81c8b..c3a45a19 100644 --- a/cms/dev_settings.py +++ b/cms/dev_settings.py @@ -34,6 +34,7 @@ INSTALLED_APPS = [ "allauth.socialaccount.providers.saml", "saml_auth.apps.SamlAuthConfig", "corsheaders", + "tinymce", ] MIDDLEWARE = [ diff --git a/cms/settings.py b/cms/settings.py index 9f61e32d..10374063 100644 --- a/cms/settings.py +++ b/cms/settings.py @@ -289,6 +289,7 @@ INSTALLED_APPS = [ "drf_yasg", "allauth.socialaccount.providers.saml", "saml_auth.apps.SamlAuthConfig", + "tinymce", ] MIDDLEWARE = [ @@ -472,6 +473,46 @@ LANGUAGES = [ LANGUAGE_CODE = 'en' # default language +TINYMCE_DEFAULT_CONFIG = { + "theme": "silver", + "height": 500, + "resize": "both", + "menubar": "file edit view insert format tools table help", + "menu": { + "format": { + "title": "Format", + "items": "blocks | bold italic underline strikethrough superscript subscript code | " "fontfamily fontsize align lineheight | " "forecolor backcolor removeformat", + }, + }, + "plugins": "advlist,autolink,autosave,lists,link,image,charmap,print,preview,anchor," + "searchreplace,visualblocks,code,fullscreen,insertdatetime,media,table,paste,directionality," + "code,help,wordcount,emoticons,file,image,media", + "toolbar": "undo redo | code preview | blocks | " + "bold italic | alignleft aligncenter " + "alignright alignjustify ltr rtl | bullist numlist outdent indent | " + "removeformat | restoredraft help | image media", + "branding": False, # remove branding + "promotion": False, # remove promotion + "body_class": "page-main-inner custom-page-wrapper", # class of the body element in tinymce + "block_formats": "Paragraph=p; Heading 1=h1; Heading 2=h2; Heading 3=h3;", + "formats": { # customize h2 to always have emphasis-large class + "h2": {"block": "h2", "classes": "emphasis-large"}, + }, + "font_size_formats": "16px 18px 24px 32px", + "images_upload_url": "/tinymce/upload/", + "images_upload_handler": "tinymce.views.upload_image", + "automatic_uploads": True, + "file_picker_types": "image", + "paste_data_images": True, + "paste_as_text": False, + "paste_enable_default_filters": True, + "paste_word_valid_elements": "b,strong,i,em,h1,h2,h3,h4,h5,h6,p,br,a,ul,ol,li", + "paste_retain_style_properties": "all", + "paste_remove_styles": False, + "paste_merge_formats": True, + "sandbox_iframes": False, +} + SPRITE_NUM_SECS = 10 # number of seconds for sprite image. # If you plan to change this, you must also follow the instructions on admins_docs.md @@ -519,7 +560,12 @@ FFMPEG_DEFAULT_PRESET = "medium" # see https://trac.ffmpeg.org/wiki/Encode/H.26 ALLOWED_MEDIA_UPLOAD_TYPES = ["video", "audio", "image", "pdf"] # transcription options -# the full docker image needs to be used in order to be able to use transcription +# the mediacms-full docker image needs to be used in order to be able to use transcription +# if you are using the mediacms-full image, change USE_WHISPER_TRANSCRIBE to True +USE_WHISPER_TRANSCRIBE = False + +# by default all users can request a video to be transcribed. If you want to +# allow only editors, set this to False USER_CAN_TRANSCRIBE_VIDEO = True # Whisper transcribe options - https://github.com/openai/whisper diff --git a/cms/urls.py b/cms/urls.py index 7d472f13..6444f677 100644 --- a/cms/urls.py +++ b/cms/urls.py @@ -30,6 +30,7 @@ urlpatterns = [ re_path(r'^swagger(?P\.json|\.yaml)$', schema_view.without_ui(cache_timeout=0), name='schema-json'), re_path(r'^swagger/$', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'), path('docs/api/', schema_view.with_ui('redoc', cache_timeout=0), name='schema-redoc'), + path("tinymce/", include("tinymce.urls")), ] admin.site.site_header = "MediaCMS Admin" diff --git a/cms/version.py b/cms/version.py index 03ef4fc0..f802725a 100644 --- a/cms/version.py +++ b/cms/version.py @@ -1 +1 @@ -VERSION = "6.6.0" +VERSION = "6.7.0" diff --git a/docs/admins_docs.md b/docs/admins_docs.md index 3fd931d9..c66b4cbc 100644 --- a/docs/admins_docs.md +++ b/docs/admins_docs.md @@ -129,6 +129,7 @@ or if you have set the ADMIN_PASSWORD variable on docker-compose file you have u * either use the docker-compose.full.yaml, so in this case run `docker-compose -f docker-compose.yaml -f docker-compose.full.yaml up` * or edit the docker-compose.yaml file and set the image for the celery_worker service as mediacms/mediacms:full instead of mediacms/mediacms:latest +Plus set variable `USE_WHISPER_TRANSCRIBE = True` in the settings.py file ### Update @@ -1027,7 +1028,7 @@ When the whisper transcribe task is triggered for a media file, MediaCMS runs th ### Configuration -Transcription functionality is available only for the Docker installation. To enable this feature, you must either use the `docker-compose.full.yaml` file, as it contains an image with the necessary requirements, or you can also set that celery_worker service is usine mediacms:full image instead of mediacms:latest. +Transcription functionality is available only for the Docker installation. To enable this feature, you must either use the `docker-compose.full.yaml` file, as it contains an image with the necessary requirements, or you can also set that celery_worker service is usine mediacms:full image instead of mediacms:latest. Then you also have to set the setting: `USE_WHISPER_TRANSCRIBE = True` in your local_settings.py file. By default, all users have the ability to send a request for a video to be transcribed, as well as transcribed and translated to English. If you wish to change this behavior, you can edit the `settings.py` file and set `USER_CAN_TRANSCRIBE_VIDEO=False`. diff --git a/files/admin.py b/files/admin.py index 0ed921bb..f97ffd29 100644 --- a/files/admin.py +++ b/files/admin.py @@ -3,6 +3,7 @@ from django.conf import settings from django.contrib import admin from django.core.exceptions import ValidationError from django.db import transaction +from tinymce.widgets import TinyMCE from rbac.models import RBACGroup @@ -13,8 +14,10 @@ from .models import ( Encoding, Language, Media, + Page, Subtitle, Tag, + TinyMCEMedia, TranscriptionRequest, VideoTrimRequest, ) @@ -224,11 +227,39 @@ class TranscriptionRequestAdmin(admin.ModelAdmin): pass +class PageAdminForm(forms.ModelForm): + description = forms.CharField(widget=TinyMCE()) + + def clean_description(self): + content = self.cleaned_data['description'] + # Add sandbox attribute to all iframes + content = content.replace('"}})(o,a):"application/x-shockwave-flash"===o.sourcemime?(e=>{let t='';return e.poster&&(t+=''),t+="",t})(o):-1!==o.sourcemime.indexOf("audio")?((e,t)=>t?t(e):'")(o,t):((e,t)=>t?t(e):'")(o,r)}},W=e=>e.hasAttribute("data-mce-object")||e.hasAttribute("data-ephox-embed-iri"),q={},H=e=>t=>G(e,t),J=(e,t)=>{const r=y(e);return r?((e,t,r)=>new Promise(((o,a)=>{const s=r=>(r.html&&(q[e.source]=r),o({url:e.source,html:r.html?r.html:t(e)}));q[e.source]?s(q[e.source]):r({url:e.source},s,a)})))(t,H(e),r):((e,t)=>Promise.resolve({html:t(e),url:e.source}))(t,H(e))},K=(e,t)=>{const r={};return d(e,"dimensions").each((e=>{l(["width","height"],(o=>{d(t,o).orThunk((()=>d(e,o))).each((e=>r[o]=e))}))})),r},Q=(e,t)=>{const r=t&&"dimensions"!==t?((e,t)=>d(t,e).bind((e=>d(e,"meta"))))(t,e).getOr({}):{},a=((e,t,r)=>a=>{const s=()=>d(e,a),n=()=>d(t,a),l=e=>d(e,"value").bind((e=>e.length>0?i.some(e):i.none()));return{[a]:(a===r?s().bind((e=>o(e)?l(e).orThunk(n):n().orThunk((()=>i.from(e))))):n().orThunk((()=>s().bind((e=>o(e)?l(e):i.from(e)))))).getOr("")}})(e,r,t);return{...a("source"),...a("altsource"),...a("poster"),...a("embed"),...K(e,r)}},V=e=>{const t={...e,source:{value:d(e,"source").getOr("")},altsource:{value:d(e,"altsource").getOr("")},poster:{value:d(e,"poster").getOr("")}};return l(["width","height"],(r=>{d(e,r).each((e=>{const o=t.dimensions||{};o[r]=e,t.dimensions=o}))})),t},X=e=>t=>{const r=t&&t.msg?"Media embed handler error: "+t.msg:"Media embed handler threw unknown error.";e.notificationManager.open({type:"error",text:r})},Y=(e,t)=>o=>{if(r(o.url)&&o.url.trim().length>0){const r=o.html,a={...T(r,t.schema),source:o.url,embed:r};e.setData(V(a))}},Z=(e,t)=>{const r=e.dom.select("*[data-mce-object]");e.insertContent(t),((e,t)=>{const r=e.dom.select("*[data-mce-object]");for(let e=0;e=0;o--)t[e]===r[o]&&r.splice(o,1);e.selection.select(r[0])})(e,r),e.nodeChanged()},ee=(e,t)=>s(t)&&"ephox-embed-iri"===t&&s(B(e)),te=(e,t)=>((e,t)=>e.width!==t.width||e.height!==t.height)(e,t)&&ee(t.source,e.type),re=e=>{const t=(e=>{const t=e.selection.getNode(),r=W(t)?e.serializer.serialize(t,{selection:!0}):"",o=T(r,e.schema),a=(()=>{if(ee(o.source,o.type)){const r=e.dom.getRect(t);return{width:r.w.toString().replace(/px$/,""),height:r.h.toString().replace(/px$/,"")}}return{}})();return{embed:r,...o,...a}})(e),r=(e=>{let t=e;return{get:()=>t,set:e=>{t=e}}})(t),o=V(t),a=k(e)?[{type:"sizeinput",name:"dimensions",label:"Constrain proportions",constrain:!0}]:[],s={title:"General",name:"general",items:c([[{name:"source",type:"urlinput",filetype:"media",label:"Source",picker_text:"Browse files"}],a])},i=[];x(e)&&i.push({name:"altsource",type:"urlinput",filetype:"media",label:"Alternative source URL"}),_(e)&&i.push({name:"poster",type:"urlinput",filetype:"image",label:"Media poster (Image URL)"});const n={title:"Advanced",name:"advanced",items:i},l=[s,{title:"Embed",items:[{type:"textarea",name:"embed",label:"Paste your embed code below:"}]}];i.length>0&&l.push(n);const m={type:"tabpanel",tabs:l},u=e.windowManager.open({title:"Insert/Edit Media",size:"normal",body:m,buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],onSubmit:t=>{const o=Q(t.getData());((e,t,r)=>{var o,a;t.embed=te(e,t)&&k(r)?G(r,{...t,embed:""}):P(null!==(o=t.embed)&&void 0!==o?o:"",t,!1,r.schema),t.embed&&(e.source===t.source||(a=t.source,h(q,a)))?Z(r,t.embed):J(r,t).then((e=>{Z(r,e.html)})).catch(X(r))})(r.get(),o,e),t.close()},onChange:(t,o)=>{switch(o.name){case"source":((t,r)=>{const o=Q(r.getData(),"source");t.source!==o.source&&(Y(u,e)({url:o.source,html:""}),J(e,o).then(Y(u,e)).catch(X(e)))})(r.get(),t);break;case"embed":(t=>{var r;const o=Q(t.getData()),a=T(null!==(r=o.embed)&&void 0!==r?r:"",e.schema);t.setData(V(a))})(t);break;case"dimensions":case"altsource":case"poster":((t,r,o)=>{const a=Q(t.getData(),r),s=te(o,a)&&k(e)?{...a,embed:""}:a,i=G(e,s);t.setData(V({...s,embed:i}))})(t,o.name,r.get())}r.set(Q(t.getData()))},initialData:o})};var oe=tinymce.util.Tools.resolve("tinymce.Env");const ae=e=>{const t=e.name;return"iframe"===t||"video"===t||"audio"===t},se=(e,t,r,o=null)=>{const a=e.attr(r);return s(a)?a:h(t,r)?null:o},ie=(e,t,r)=>{const o="img"===t.name||"video"===e.name,a=o?"300":null,s="audio"===e.name?"30":"150",i=o?s:null;t.attr({width:se(e,r,"width",a),height:se(e,r,"height",i)})},ne=(e,t)=>{const r=t.name,o=new D("img",1);return ce(e,t,o),ie(t,o,{}),o.attr({style:t.attr("style"),src:oe.transparentSrc,"data-mce-object":r,class:"mce-object mce-object-"+r}),o},le=(e,t)=>{var r;const o=t.name,a=new D("span",1);a.attr({contentEditable:"false",style:t.attr("style"),"data-mce-object":o,class:"mce-preview-object mce-object-"+o}),ce(e,t,a);const i=e.dom.parseStyle(null!==(r=t.attr("style"))&&void 0!==r?r:""),n=new D(o,1);if(ie(t,n,i),n.attr({src:t.attr("src"),style:t.attr("style"),class:t.attr("class")}),"iframe"===o)n.attr({allowfullscreen:t.attr("allowfullscreen"),frameborder:"0",sandbox:t.attr("sandbox")});else{l(["controls","crossorigin","currentTime","loop","muted","poster","preload"],(e=>{n.attr(e,t.attr(e))}));const r=a.attr("data-mce-html");s(r)&&((e,t,r,o)=>{const a=M(e.schema).parse(o,{context:t});for(;a.firstChild;)r.append(a.firstChild)})(e,o,n,unescape(r))}const c=new D("span",1);return c.attr("class","mce-shim"),a.append(n),a.append(c),a},ce=(e,t,r)=>{var o;const a=null!==(o=t.attributes)&&void 0!==o?o:[];let s=a.length;for(;s--;){const t=a[s].name;let o=a[s].value;"width"===t||"height"===t||"style"===t||(n="data-mce-",(i=t).length>=9&&i.substr(0,9)===n)||("data"!==t&&"src"!==t||(o=e.convertURL(o,t)),r.attr("data-mce-p-"+t,o))}var i,n;const c=F({inner:!0},e.schema),m=new D("div",1);l(t.children(),(e=>m.append(e)));const u=c.serialize(m);u&&(r.attr("data-mce-html",escape(u)),r.empty())},me=e=>{const t=e.attr("class");return r(t)&&/\btiny-pageembed\b/.test(t)},ue=e=>{let t=e;for(;t=t.parent;)if(t.attr("data-ephox-embed-iri")||me(t))return!0;return!1},de=(e,t,r)=>{const o=(0,e.options.get)("xss_sanitization"),a=f(e);return M(e.schema,{sanitize:o,validate:a}).parse(r,{context:t})},he=e=>t=>{const r=()=>{t.setEnabled(e.selection.isEditable())};return e.on("NodeChange",r),r(),()=>{e.off("NodeChange",r)}};e.add("media",(e=>((e=>{const t=e.options.register;t("audio_template_callback",{processor:"function"}),t("video_template_callback",{processor:"function"}),t("iframe_template_callback",{processor:"function"}),t("media_live_embeds",{processor:"boolean",default:!0}),t("media_filter_html",{processor:"boolean",default:!0}),t("media_url_resolver",{processor:"function"}),t("media_alt_source",{processor:"boolean",default:!0}),t("media_poster",{processor:"boolean",default:!0}),t("media_dimensions",{processor:"boolean",default:!0})})(e),(e=>{e.addCommand("mceMedia",(()=>{re(e)}))})(e),(e=>{const t=()=>e.execCommand("mceMedia");e.ui.registry.addToggleButton("media",{tooltip:"Insert/edit media",icon:"embed",onAction:t,onSetup:t=>{const r=e.selection;t.setActive(W(r.getNode()));const o=r.selectorChangedWithUnbind("img[data-mce-object],span[data-mce-object],div[data-ephox-embed-iri]",t.setActive).unbind,a=he(e)(t);return()=>{o(),a()}}}),e.ui.registry.addMenuItem("media",{icon:"embed",text:"Media...",onAction:t,onSetup:he(e)})})(e),(e=>{e.on("ResolveName",(e=>{let t;1===e.target.nodeType&&(t=e.target.getAttribute("data-mce-object"))&&(e.name=t)}))})(e),(e=>{e.on("PreInit",(()=>{const{schema:t,serializer:r,parser:o}=e,a=t.getBoolAttrs();l("webkitallowfullscreen mozallowfullscreen".split(" "),(e=>{a[e]={}})),((e,t)=>{const r=m(e);for(let o=0,a=r.length;o{const o=t.getElementRule(r);o&&l(e,(e=>{o.attributes[e]={},o.attributesOrder.push(e)}))})),o.addNodeFilter("iframe,video,audio,object,embed",(e=>t=>{let r,o=t.length;for(;o--;)r=t[o],r.parent&&(r.parent.attr("data-mce-object")||(ae(r)&&v(e)?ue(r)||r.replace(le(e,r)):ue(r)||r.replace(ne(e,r))))})(e)),r.addAttributeFilter("data-mce-object",((t,r)=>{var o;let a=t.length;for(;a--;){const s=t[a];if(!s.parent)continue;const i=s.attr(r),n=new D(i,1);if("audio"!==i){const e=s.attr("class");e&&-1!==e.indexOf("mce-preview-object")&&s.firstChild?n.attr({width:s.firstChild.attr("width"),height:s.firstChild.attr("height")}):n.attr({width:s.attr("width"),height:s.attr("height")})}n.attr({style:s.attr("style")});const c=null!==(o=s.attributes)&&void 0!==o?o:[];let m=c.length;for(;m--;){const e=c[m].name;0===e.indexOf("data-mce-p-")&&n.attr(e.substr(11),c[m].value)}const u=s.attr("data-mce-html");if(u){const t=de(e,i,unescape(u));l(t.children(),(e=>n.append(e)))}s.replace(n)}}))})),e.on("SetContent",(()=>{const t=e.dom;l(t.select("span.mce-preview-object"),(e=>{0===t.select("span.mce-shim",e).length&&t.add(e,"span",{class:"mce-shim"})}))}))})(e),(e=>{e.on("click keyup touchend",(()=>{const t=e.selection.getNode();t&&e.dom.hasClass(t,"mce-preview-object")&&e.dom.getAttrib(t,"data-mce-selected")&&t.setAttribute("data-mce-selected","2")})),e.on("ObjectResized",(t=>{const r=t.target;if(r.getAttribute("data-mce-object")){let o=r.getAttribute("data-mce-html");o&&(o=unescape(o),r.setAttribute("data-mce-html",escape(P(o,{width:String(t.width),height:String(t.height)},!1,e.schema))))}}))})(e),(e=>({showDialog:()=>{re(e)}}))(e))))}(); \ No newline at end of file diff --git a/static/tinymce/plugins/nonbreaking/plugin.min.js b/static/tinymce/plugins/nonbreaking/plugin.min.js new file mode 100644 index 00000000..4baee129 --- /dev/null +++ b/static/tinymce/plugins/nonbreaking/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.8.4 (2024-06-19) + */ +!function(){"use strict";var n=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=n=>e=>typeof e===n,o=e("boolean"),a=e("number"),t=n=>e=>e.options.get(n),i=t("nonbreaking_force_tab"),s=t("nonbreaking_wrap"),r=(n,e)=>{let o="";for(let a=0;a{const o=s(n)||n.plugins.visualchars?`${r(" ",e)}`:r(" ",e);n.undoManager.transact((()=>n.insertContent(o)))};var l=tinymce.util.Tools.resolve("tinymce.util.VK");const u=n=>e=>{const o=()=>{e.setEnabled(n.selection.isEditable())};return n.on("NodeChange",o),o(),()=>{n.off("NodeChange",o)}};n.add("nonbreaking",(n=>{(n=>{const e=n.options.register;e("nonbreaking_force_tab",{processor:n=>o(n)?{value:n?3:0,valid:!0}:a(n)?{value:n,valid:!0}:{valid:!1,message:"Must be a boolean or number."},default:!1}),e("nonbreaking_wrap",{processor:"boolean",default:!0})})(n),(n=>{n.addCommand("mceNonBreaking",(()=>{c(n,1)}))})(n),(n=>{const e=()=>n.execCommand("mceNonBreaking");n.ui.registry.addButton("nonbreaking",{icon:"non-breaking",tooltip:"Nonbreaking space",onAction:e,onSetup:u(n)}),n.ui.registry.addMenuItem("nonbreaking",{icon:"non-breaking",text:"Nonbreaking space",onAction:e,onSetup:u(n)})})(n),(n=>{const e=i(n);e>0&&n.on("keydown",(o=>{if(o.keyCode===l.TAB&&!o.isDefaultPrevented()){if(o.shiftKey)return;o.preventDefault(),o.stopImmediatePropagation(),c(n,e)}}))})(n)}))}(); \ No newline at end of file diff --git a/static/tinymce/plugins/pagebreak/plugin.min.js b/static/tinymce/plugins/pagebreak/plugin.min.js new file mode 100644 index 00000000..6ed62f51 --- /dev/null +++ b/static/tinymce/plugins/pagebreak/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.8.4 (2024-06-19) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=tinymce.util.Tools.resolve("tinymce.Env");const t=e=>a=>a.options.get(e),n=t("pagebreak_separator"),o=t("pagebreak_split_block"),r="mce-pagebreak",s=e=>{const t=``;return e?`

${t}

`:t},c=e=>a=>{const t=()=>{a.setEnabled(e.selection.isEditable())};return e.on("NodeChange",t),t(),()=>{e.off("NodeChange",t)}};e.add("pagebreak",(e=>{(e=>{const a=e.options.register;a("pagebreak_separator",{processor:"string",default:"\x3c!-- pagebreak --\x3e"}),a("pagebreak_split_block",{processor:"boolean",default:!1})})(e),(e=>{e.addCommand("mcePageBreak",(()=>{e.insertContent(s(o(e)))}))})(e),(e=>{const a=()=>e.execCommand("mcePageBreak");e.ui.registry.addButton("pagebreak",{icon:"page-break",tooltip:"Page break",onAction:a,onSetup:c(e)}),e.ui.registry.addMenuItem("pagebreak",{text:"Page break",icon:"page-break",onAction:a,onSetup:c(e)})})(e),(e=>{const a=n(e),t=()=>o(e),c=new RegExp(a.replace(/[\?\.\*\[\]\(\)\{\}\+\^\$\:]/g,(e=>"\\"+e)),"gi");e.on("BeforeSetContent",(e=>{e.content=e.content.replace(c,s(t()))})),e.on("PreInit",(()=>{e.serializer.addNodeFilter("img",(n=>{let o,s,c=n.length;for(;c--;)if(o=n[c],s=o.attr("class"),s&&-1!==s.indexOf(r)){const n=o.parent;if(n&&e.schema.getBlockElements()[n.name]&&t()){n.type=3,n.value=a,n.raw=!0,o.remove();continue}o.type=3,o.value=a,o.raw=!0}}))}))})(e),(e=>{e.on("ResolveName",(a=>{"IMG"===a.target.nodeName&&e.dom.hasClass(a.target,r)&&(a.name="pagebreak")}))})(e)}))}(); \ No newline at end of file diff --git a/static/tinymce/plugins/preview/plugin.min.js b/static/tinymce/plugins/preview/plugin.min.js new file mode 100644 index 00000000..14b0af4b --- /dev/null +++ b/static/tinymce/plugins/preview/plugin.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.8.4 (2024-06-19) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),t=tinymce.util.Tools.resolve("tinymce.Env"),o=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=e=>t=>t.options.get(e),i=n("content_style"),s=n("content_css_cors"),c=n("body_class"),r=n("body_id");e.add("preview",(e=>{(e=>{e.addCommand("mcePreview",(()=>{(e=>{const n=(e=>{var n;let l="";const a=e.dom.encode,d=null!==(n=i(e))&&void 0!==n?n:"";l+='';const m=s(e)?' crossorigin="anonymous"':"";o.each(e.contentCSS,(t=>{l+='"})),d&&(l+='");const y=r(e),u=c(e),v=' + +{% endblock headermeta %} + +{% block innercontent %} +{% get_current_language as LANGUAGE_CODE %} + +
+ +

{{page.title}}

+ + {{page.description|safe}} + +
+ +{% endblock %} \ No newline at end of file