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)
This commit is contained in:
Markos Gogoulos 2025-09-21 15:38:43 +03:00 committed by GitHub
parent cbef629baf
commit 208f0b338b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
209 changed files with 7399 additions and 14 deletions

View File

@ -34,6 +34,7 @@ INSTALLED_APPS = [
"allauth.socialaccount.providers.saml",
"saml_auth.apps.SamlAuthConfig",
"corsheaders",
"tinymce",
]
MIDDLEWARE = [

View File

@ -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

View File

@ -30,6 +30,7 @@ urlpatterns = [
re_path(r'^swagger(?P<format>\.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"

View File

@ -1 +1 @@
VERSION = "6.6.0"
VERSION = "6.7.0"

View File

@ -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`.

View File

@ -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('<iframe ', '<iframe sandbox="allow-scripts allow-same-origin allow-presentation" ')
return content
class Meta:
model = Page
fields = "__all__"
class PageAdmin(admin.ModelAdmin):
form = PageAdminForm
@admin.register(TinyMCEMedia)
class TinyMCEMediaAdmin(admin.ModelAdmin):
list_display = ['original_filename', 'file_type', 'uploaded_at', 'user']
list_filter = ['file_type', 'uploaded_at']
search_fields = ['original_filename']
readonly_fields = ['uploaded_at']
date_hierarchy = 'uploaded_at'
admin.site.register(EncodeProfile, EncodeProfileAdmin)
admin.site.register(Comment, CommentAdmin)
admin.site.register(Media, MediaAdmin)
admin.site.register(Encoding, EncodingAdmin)
admin.site.register(Category, CategoryAdmin)
admin.site.register(Page, PageAdmin)
admin.site.register(Tag, TagAdmin)
admin.site.register(Subtitle, SubtitleAdmin)
admin.site.register(Language, LanguageAdmin)

View File

@ -429,6 +429,9 @@ def user_allowed_to_upload(request):
def can_transcribe_video(user):
"""Checks if a user can transcribe a video."""
if not getattr(settings, 'USE_WHISPER_TRANSCRIBE', False):
return False
if is_mediacms_editor(user):
return True
if getattr(settings, 'USER_CAN_TRANSCRIBE_VIDEO', False):

View File

@ -0,0 +1,42 @@
# Generated by Django 5.2.6 on 2025-09-21 11:49
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('files', '0012_media_allow_whisper_transcribe_and_more'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Page',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slug', models.SlugField(max_length=200, unique=True)),
('title', models.CharField(max_length=200)),
('description', models.TextField(blank=True)),
('add_date', models.DateTimeField(auto_now_add=True)),
('edit_date', models.DateTimeField(auto_now=True)),
],
),
migrations.CreateModel(
name='TinyMCEMedia',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('file', models.FileField(upload_to='tinymce_media/')),
('uploaded_at', models.DateTimeField(auto_now_add=True)),
('file_type', models.CharField(choices=[('image', 'Image'), ('media', 'Media')], max_length=10)),
('original_filename', models.CharField(max_length=255)),
('user', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'TinyMCE Media',
'verbose_name_plural': 'TinyMCE Media',
'ordering': ['-uploaded_at'],
},
),
]

View File

@ -4,6 +4,7 @@ from .comment import Comment # noqa: F401
from .encoding import EncodeProfile, Encoding # noqa: F401
from .license import License # noqa: F401
from .media import Media, MediaPermission # noqa: F401
from .page import Page, TinyMCEMedia # noqa: F401
from .playlist import Playlist, PlaylistMedia # noqa: F401
from .rating import Rating, RatingCategory # noqa: F401
from .subtitle import Language, Subtitle, TranscriptionRequest # noqa: F401

42
files/models/page.py Normal file
View File

@ -0,0 +1,42 @@
from django.db import models
from django.urls import reverse
class Page(models.Model):
slug = models.SlugField(max_length=200, unique=True)
title = models.CharField(max_length=200)
description = models.TextField(blank=True)
add_date = models.DateTimeField(auto_now_add=True)
edit_date = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("get_page", args=[str(self.slug)])
class TinyMCEMedia(models.Model):
file = models.FileField(upload_to='tinymce_media/')
uploaded_at = models.DateTimeField(auto_now_add=True)
file_type = models.CharField(
max_length=10,
choices=(
('image', 'Image'),
('media', 'Media'),
),
)
original_filename = models.CharField(max_length=255)
user = models.ForeignKey("users.User", on_delete=models.CASCADE, null=True, blank=True)
class Meta:
verbose_name = 'TinyMCE Media'
verbose_name_plural = 'TinyMCE Media'
ordering = ['-uploaded_at']
def __str__(self):
return f"{self.original_filename} ({self.file_type})"
@property
def url(self):
return self.file.url

20
files/tinymce_handlers.py Normal file
View File

@ -0,0 +1,20 @@
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from .models import TinyMCEMedia
@csrf_exempt
def upload_image(request):
if not (request.user.is_authenticated and request.user.is_active and request.user.is_staff and request.user.is_superuser):
return JsonResponse({'error': 'Admin access required'}, status=403)
if request.method == "POST":
file_obj = request.FILES.get('file')
if file_obj:
# Create a new TinyMCEMedia instance for the image
media = TinyMCEMedia(file=file_obj, file_type='image', original_filename=file_obj.name, user=request.user if request.user.is_authenticated else None)
media.save()
return JsonResponse({'location': media.url})
return JsonResponse({'error': 'Invalid request'}, status=400)

View File

@ -4,7 +4,7 @@ from django.conf.urls import include
from django.conf.urls.static import static
from django.urls import path, re_path
from . import management_views, views
from . import management_views, tinymce_handlers, views
from .feeds import IndexRSSFeed, SearchRSSFeed
friendly_token = r"(?P<friendly_token>[\w\-_]*)"
@ -12,7 +12,6 @@ friendly_token = r"(?P<friendly_token>[\w\-_]*)"
urlpatterns = [
path("i18n/", include("django.conf.urls.i18n")),
re_path(r"^$", views.index),
re_path(r"^about", views.about, name="about"),
re_path(r"^setlanguage", views.setlanguage, name="setlanguage"),
re_path(r"^add_subtitle", views.add_subtitle, name="add_subtitle"),
re_path(r"^edit_subtitle", views.edit_subtitle, name="edit_subtitle"),
@ -108,8 +107,13 @@ urlpatterns = [
re_path(r"^manage/comments$", views.manage_comments, name="manage_comments"),
re_path(r"^manage/media$", views.manage_media, name="manage_media"),
re_path(r"^manage/users$", views.manage_users, name="manage_users"),
# Media uploads in ADMIN created pages
re_path(r"^tinymce/upload/", tinymce_handlers.upload_image, name="tinymce_upload_image"),
re_path("^(?P<slug>[\w.-]*)$", views.get_page, name="get_page"), # noqa: W605
re_path(r"^about", views.about, name="about"),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
if settings.USERS_NEEDS_TO_BE_APPROVED:
urlpatterns.append(re_path(r"^approval_required", views.approval_required, name="approval_required"))

View File

@ -20,6 +20,7 @@ from .pages import edit_subtitle # noqa: F401
from .pages import edit_video # noqa: F401
from .pages import embed_media # noqa: F401
from .pages import featured_media # noqa: F401
from .pages import get_page # noqa: F401
from .pages import history # noqa: F401
from .pages import index # noqa: F401
from .pages import latest_media # noqa: F401

View File

@ -31,10 +31,20 @@ from ..methods import (
is_media_allowed_type,
is_mediacms_editor,
)
from ..models import Category, Media, Playlist, Subtitle, Tag, VideoTrimRequest
from ..models import Category, Media, Page, Playlist, Subtitle, Tag, VideoTrimRequest
from ..tasks import save_user_action, video_trim_task
def get_page(request, slug):
context = {}
page = Page.objects.filter(slug=slug).first()
if page:
context["page"] = page
else:
return render(request, "404.html", context)
return render(request, "cms/page.html", context)
@login_required
def record_screen(request):
"""Record screen view"""

View File

@ -1,5 +1,5 @@
Django==5.1.6
djangorestframework==3.15.2
Django==5.2.6
djangorestframework==3.16.1
python3-saml==1.16.0
django-allauth==65.4.1
psycopg[binary,pool]==3.2.4
@ -22,3 +22,4 @@ pre-commit==4.1.0
django-jazzmin==3.0.1
pysubs2==1.8.0
sentry-sdk[django]==2.23.1
django-tinymce==4.1.0

View File

@ -0,0 +1,82 @@
'use strict';
{
function initTinyMCE(el) {
if (el.closest('.empty-form') === null) { // Don't do empty inlines
var mce_conf = JSON.parse(el.dataset.mceConf);
// There is no way to pass a JavaScript function as an option
// because all options are serialized as JSON.
const fns = [
'color_picker_callback',
'file_browser_callback',
'file_picker_callback',
'images_dataimg_filter',
'images_upload_handler',
'paste_postprocess',
'paste_preprocess',
'setup',
'urlconverter_callback',
];
fns.forEach((fn_name) => {
if (typeof mce_conf[fn_name] != 'undefined') {
if (mce_conf[fn_name].includes('(')) {
mce_conf[fn_name] = eval('(' + mce_conf[fn_name] + ')');
}
else {
mce_conf[fn_name] = window[mce_conf[fn_name]];
}
}
});
// replace default prefix of 'empty-form' if used in selector
if (mce_conf.selector && mce_conf.selector.includes('__prefix__')) {
mce_conf.selector = `#${el.id}`;
}
else if (!('selector' in mce_conf)) {
mce_conf['target'] = el;
}
if (el.dataset.mceGzConf) {
tinyMCE_GZ.init(JSON.parse(el.dataset.mceGzConf));
}
if (!tinyMCE.get(el.id)) {
tinyMCE.init(mce_conf);
}
}
}
// Call function fn when the DOM is loaded and ready. If it is already
// loaded, call the function now.
function ready(fn) {
if (document.readyState !== 'loading') {
fn();
} else {
document.addEventListener('DOMContentLoaded', fn);
}
}
function initializeTinyMCE(element, formsetName) {
Array.from(element.querySelectorAll('.tinymce')).forEach(area => initTinyMCE(area));
}
ready(function() {
if (!tinyMCE) {
throw 'tinyMCE is not loaded. If you customized TINYMCE_JS_URL, double-check its content.';
}
// initialize the TinyMCE editors on load
initializeTinyMCE(document);
// initialize the TinyMCE editor after adding an inline in the django admin context.
if (typeof(django) !== 'undefined' && typeof(django.jQuery) !== 'undefined') {
django.jQuery(document).on('formset:added', (event, $row, formsetName) => {
if (event.detail && event.detail.formsetName) {
// Django >= 4.1
initializeTinyMCE(event.target);
} else {
// Django < 4.1, use $row
initializeTinyMCE($row.get(0));
}
});
}
});
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
This is where language files should be placed.
Please DO NOT translate these directly, use this service instead: https://crowdin.com/project/tinymce

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 Ephox Corporation DBA Tiny Technologies, Inc.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
/**
* TinyMCE version 6.8.4 (2024-06-19)
*/
!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=(t,e,s)=>{const r="UL"===e?"InsertUnorderedList":"InsertOrderedList";t.execCommand(r,!1,!1===s?null:{"list-style-type":s})},s=t=>e=>e.options.get(t),r=s("advlist_number_styles"),n=s("advlist_bullet_styles"),i=t=>null==t,l=t=>!i(t);var o=tinymce.util.Tools.resolve("tinymce.util.Tools");class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return l(t)?a.some(t):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const u=t=>e=>l(e)&&t.test(e.nodeName),d=u(/^(OL|UL|DL)$/),g=u(/^(TH|TD)$/),c=t=>i(t)||"default"===t?"":t,h=(t,e)=>s=>((t,e)=>{const s=t.selection.getNode();return e({parents:t.dom.getParents(s),element:s}),t.on("NodeChange",e),()=>t.off("NodeChange",e)})(t,(r=>((t,r)=>{const n=t.selection.getStart(!0);s.setActive(((t,e,s)=>((t,e,s)=>{for(let e=0,n=t.length;e<n;e++){const n=t[e];if(d(r=n)&&!/\btox\-/.test(r.className))return a.some(n);if(s(n,e))break}var r;return a.none()})(e,0,g).exists((e=>e.nodeName===s&&((t,e)=>t.dom.isChildOf(e,t.getBody()))(t,e))))(t,r,e)),s.setEnabled(!((t,e)=>{const s=t.dom.getParent(e,"ol,ul,dl");return((t,e)=>null!==e&&!t.dom.isEditable(e))(t,s)&&t.selection.isEditable()})(t,n)&&t.selection.isEditable())})(t,r.parents))),m=(t,s,r,n,i,l)=>{l.length>1?((t,s,r,n,i,l)=>{t.ui.registry.addSplitButton(s,{tooltip:r,icon:"OL"===i?"ordered-list":"unordered-list",presets:"listpreview",columns:3,fetch:t=>{t(o.map(l,(t=>{const e="OL"===i?"num":"bull",s="disc"===t||"decimal"===t?"default":t,r=c(t),n=(t=>t.replace(/\-/g," ").replace(/\b\w/g,(t=>t.toUpperCase())))(t);return{type:"choiceitem",value:r,icon:"list-"+e+"-"+s,text:n}})))},onAction:()=>t.execCommand(n),onItemAction:(s,r)=>{e(t,i,r)},select:e=>{const s=(t=>{const e=t.dom.getParent(t.selection.getNode(),"ol,ul"),s=t.dom.getStyle(e,"listStyleType");return a.from(s)})(t);return s.map((t=>e===t)).getOr(!1)},onSetup:h(t,i)})})(t,s,r,n,i,l):((t,s,r,n,i,l)=>{t.ui.registry.addToggleButton(s,{active:!1,tooltip:r,icon:"OL"===i?"ordered-list":"unordered-list",onSetup:h(t,i),onAction:()=>t.queryCommandState(n)||""===l?t.execCommand(n):e(t,i,l)})})(t,s,r,n,i,c(l[0]))};t.add("advlist",(t=>{t.hasPlugin("lists")?((t=>{const e=t.options.register;e("advlist_number_styles",{processor:"string[]",default:"default,lower-alpha,lower-greek,lower-roman,upper-alpha,upper-roman".split(",")}),e("advlist_bullet_styles",{processor:"string[]",default:"default,circle,square".split(",")})})(t),(t=>{m(t,"numlist","Numbered list","InsertOrderedList","OL",r(t)),m(t,"bullist","Bullet list","InsertUnorderedList","UL",n(t))})(t),(t=>{t.addCommand("ApplyUnorderedListStyle",((s,r)=>{e(t,"UL",r["list-style-type"])})),t.addCommand("ApplyOrderedListStyle",((s,r)=>{e(t,"OL",r["list-style-type"])}))})(t)):console.error("Please use the Lists plugin together with the Advanced List plugin.")}))}();

View File

@ -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.dom.RangeUtils"),o=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=("allow_html_in_named_anchor",e=>e.options.get("allow_html_in_named_anchor"));const a="a:not([href])",r=e=>!e,i=e=>e.getAttribute("id")||e.getAttribute("name")||"",l=e=>(e=>"a"===e.nodeName.toLowerCase())(e)&&!e.getAttribute("href")&&""!==i(e),s=e=>e.dom.getParent(e.selection.getStart(),a),d=(e,a)=>{const r=s(e);r?((e,t,o)=>{o.removeAttribute("name"),o.id=t,e.addVisual(),e.undoManager.add()})(e,a,r):((e,a)=>{e.undoManager.transact((()=>{n(e)||e.selection.collapse(!0),e.selection.isCollapsed()?e.insertContent(e.dom.createHTML("a",{id:a})):((e=>{const n=e.dom;t(n).walk(e.selection.getRng(),(e=>{o.each(e,(e=>{var t;l(t=e)&&!t.firstChild&&n.remove(e,!1)}))}))})(e),e.formatter.remove("namedAnchor",void 0,void 0,!0),e.formatter.apply("namedAnchor",{value:a}),e.addVisual())}))})(e,a),e.focus()},c=e=>(e=>r(e.attr("href"))&&!r(e.attr("id")||e.attr("name")))(e)&&!e.firstChild,m=e=>t=>{for(let o=0;o<t.length;o++){const n=t[o];c(n)&&n.attr("contenteditable",e)}},u=e=>t=>{const o=()=>{t.setEnabled(e.selection.isEditable())};return e.on("NodeChange",o),o(),()=>{e.off("NodeChange",o)}};e.add("anchor",(e=>{(e=>{(0,e.options.register)("allow_html_in_named_anchor",{processor:"boolean",default:!1})})(e),(e=>{e.on("PreInit",(()=>{e.parser.addNodeFilter("a",m("false")),e.serializer.addNodeFilter("a",m(null))}))})(e),(e=>{e.addCommand("mceAnchor",(()=>{(e=>{const t=(e=>{const t=s(e);return t?i(t):""})(e);e.windowManager.open({title:"Anchor",size:"normal",body:{type:"panel",items:[{name:"id",type:"input",label:"ID",placeholder:"example"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{id:t},onSubmit:t=>{((e,t)=>/^[A-Za-z][A-Za-z0-9\-:._]*$/.test(t)?(d(e,t),!0):(e.windowManager.alert("ID should start with a letter, followed only by letters, numbers, dashes, dots, colons or underscores."),!1))(e,t.getData().id)&&t.close()}})})(e)}))})(e),(e=>{const t=()=>e.execCommand("mceAnchor");e.ui.registry.addToggleButton("anchor",{icon:"bookmark",tooltip:"Anchor",onAction:t,onSetup:t=>{const o=e.selection.selectorChangedWithUnbind("a:not([href])",t.setActive).unbind,n=u(e)(t);return()=>{o(),n()}}}),e.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:t,onSetup:u(e)})})(e),e.on("PreInit",(()=>{(e=>{e.formatter.register("namedAnchor",{inline:"a",selector:a,remove:"all",split:!0,deep:!0,attributes:{id:"%value"},onmatch:(e,t,o)=>l(e)})})(e)}))}))}();

View File

@ -0,0 +1,4 @@
/**
* TinyMCE version 6.8.4 (2024-06-19)
*/
!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>t.options.get(e),n=t("autolink_pattern"),o=t("link_default_target"),r=t("link_default_protocol"),a=t("allow_unsafe_link_target"),s=("string",e=>"string"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=o=e,(r=String).prototype.isPrototypeOf(n)||(null===(a=o.constructor)||void 0===a?void 0:a.name)===r.name)?"string":t;var n,o,r,a})(e));const l=(void 0,e=>undefined===e);const i=e=>!(e=>null==e)(e),c=Object.hasOwnProperty,d=e=>"\ufeff"===e;var u=tinymce.util.Tools.resolve("tinymce.dom.TextSeeker");const f=e=>/^[(\[{ \u00a0]$/.test(e),g=(e,t,n)=>{for(let o=t-1;o>=0;o--){const t=e.charAt(o);if(!d(t)&&n(t))return o}return-1},m=(e,t)=>{var o;const a=e.schema.getVoidElements(),s=n(e),{dom:i,selection:d}=e;if(null!==i.getParent(d.getNode(),"a[href]"))return null;const m=d.getRng(),k=u(i,(e=>{return i.isBlock(e)||(t=a,n=e.nodeName.toLowerCase(),c.call(t,n))||"false"===i.getContentEditable(e);var t,n})),{container:p,offset:y}=((e,t)=>{let n=e,o=t;for(;1===n.nodeType&&n.childNodes[o];)n=n.childNodes[o],o=3===n.nodeType?n.data.length:n.childNodes.length;return{container:n,offset:o}})(m.endContainer,m.endOffset),w=null!==(o=i.getParent(p,i.isBlock))&&void 0!==o?o:i.getRoot(),h=k.backwards(p,y+t,((e,t)=>{const n=e.data,o=g(n,t,(r=f,e=>!r(e)));var r,a;return-1===o||(a=n[o],/[?!,.;:]/.test(a))?o:o+1}),w);if(!h)return null;let v=h.container;const _=k.backwards(h.container,h.offset,((e,t)=>{v=e;const n=g(e.data,t,f);return-1===n?n:n+1}),w),A=i.createRng();_?A.setStart(_.container,_.offset):A.setStart(v,0),A.setEnd(h.container,h.offset);const C=A.toString().replace(/\uFEFF/g,"").match(s);if(C){let t=C[0];return $="www.",(b=t).length>=4&&b.substr(0,4)===$?t=r(e)+"://"+t:((e,t,n=0,o)=>{const r=e.indexOf(t,n);return-1!==r&&(!!l(o)||r+t.length<=o)})(t,"@")&&!(e=>/^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(e))(t)&&(t="mailto:"+t),{rng:A,url:t}}var b,$;return null},k=(e,t)=>{const{dom:n,selection:r}=e,{rng:l,url:i}=t,c=r.getBookmark();r.setRng(l);const d="createlink",u={command:d,ui:!1,value:i};if(!e.dispatch("BeforeExecCommand",u).isDefaultPrevented()){e.getDoc().execCommand(d,!1,i),e.dispatch("ExecCommand",u);const t=o(e);if(s(t)){const o=r.getNode();n.setAttrib(o,"target",t),"_blank"!==t||a(e)||n.setAttrib(o,"rel","noopener")}}r.moveToBookmark(c),e.nodeChanged()},p=e=>{const t=m(e,-1);i(t)&&k(e,t)},y=p;e.add("autolink",(e=>{(e=>{const t=e.options.register;t("autolink_pattern",{processor:"regexp",default:new RegExp("^"+/(?:[A-Za-z][A-Za-z\d.+-]{0,14}:\/\/(?:[-.~*+=!&;:'%@?^${}(),\w]+@)?|www\.|[-;:&=+$,.\w]+@)[A-Za-z\d-]+(?:\.[A-Za-z\d-]+)*(?::\d+)?(?:\/(?:[-.~*+=!;:'%@$(),\/\w]*[-~*+=%@$()\/\w])?)?(?:\?(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?(?:#(?:[-.~*+=!&;:'%@?^${}(),\/\w]+))?/g.source+"$","i")}),t("link_default_target",{processor:"string"}),t("link_default_protocol",{processor:"string",default:"https"})})(e),(e=>{e.on("keydown",(t=>{13!==t.keyCode||t.isDefaultPrevented()||(e=>{const t=m(e,0);i(t)&&k(e,t)})(e)})),e.on("keyup",(t=>{32===t.keyCode?p(e):(48===t.keyCode&&t.shiftKey||221===t.keyCode)&&y(e)}))})(e)}))}();

View File

@ -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");const o=e=>t=>t.options.get(e),s=o("min_height"),i=o("max_height"),n=o("autoresize_overflow_padding"),r=o("autoresize_bottom_margin"),l=(e,t)=>{const o=e.getBody();o&&(o.style.overflowY=t?"":"hidden",t||(o.scrollTop=0))},g=(e,t,o,s)=>{var i;const n=parseInt(null!==(i=e.getStyle(t,o,s))&&void 0!==i?i:"",10);return isNaN(n)?0:n},a=(e,o,r,c)=>{var d;const f=e.dom,u=e.getDoc();if(!u)return;if((e=>e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen())(e))return void l(e,!0);const m=u.documentElement,h=c?c():n(e),p=null!==(d=s(e))&&void 0!==d?d:e.getElement().offsetHeight;let y=p;const S=g(f,m,"margin-top",!0),v=g(f,m,"margin-bottom",!0);let C=m.offsetHeight+S+v+h;C<0&&(C=0);const b=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight;C+b>p&&(y=C+b);const w=i(e);if(w&&y>w?(y=w,l(e,!0)):l(e,!1),y!==o.get()){const s=y-o.get();if(f.setStyle(e.getContainer(),"height",y+"px"),o.set(y),(e=>{e.dispatch("ResizeEditor")})(e),t.browser.isSafari()&&(t.os.isMacOS()||t.os.isiOS())){const t=e.getWin();t.scrollTo(t.pageXOffset,t.pageYOffset)}e.hasFocus()&&(e=>{if("setcontent"===(null==e?void 0:e.type.toLowerCase())){const t=e;return!0===t.selection||!0===t.paste}return!1})(r)&&e.selection.scrollIntoView(),(t.browser.isSafari()||t.browser.isChromium())&&s<0&&a(e,o,r,c)}};e.add("autoresize",(e=>{if((e=>{const t=e.options.register;t("autoresize_overflow_padding",{processor:"number",default:1}),t("autoresize_bottom_margin",{processor:"number",default:50})})(e),e.options.isSet("resize")||e.options.set("resize",!1),!e.inline){const o=(e=>{let t=0;return{get:()=>t,set:e=>{t=e}}})();((e,t)=>{e.addCommand("mceAutoResize",(()=>{a(e,t)}))})(e,o),((e,o)=>{let s,i,l=()=>r(e);e.on("init",(i=>{s=0;const r=n(e),g=e.dom;g.setStyles(e.getDoc().documentElement,{height:"auto"}),t.browser.isEdge()||t.browser.isIE()?g.setStyles(e.getBody(),{paddingLeft:r,paddingRight:r,"min-height":0}):g.setStyles(e.getBody(),{paddingLeft:r,paddingRight:r}),a(e,o,i,l),s+=1})),e.on("NodeChange SetContent keyup FullscreenStateChanged ResizeContent",(t=>{if(1===s)i=e.getContainer().offsetHeight,a(e,o,t,l),s+=1;else if(2===s){const t=i<e.getContainer().offsetHeight;if(t){const t=e.dom,o=e.getDoc();t.setStyles(o.documentElement,{"min-height":0}),t.setStyles(e.getBody(),{"min-height":"inherit"})}l=t?(0,()=>0):l,s+=1}else a(e,o,t,l)}))})(e,o)}}))}();

View File

@ -0,0 +1,4 @@
/**
* TinyMCE version 6.8.4 (2024-06-19)
*/
!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=("string",t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(r=o=t,(a=String).prototype.isPrototypeOf(r)||(null===(s=o.constructor)||void 0===s?void 0:s.name)===a.name)?"string":e;var r,o,a,s})(t));const r=(void 0,t=>undefined===t);var o=tinymce.util.Tools.resolve("tinymce.util.Delay"),a=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),s=tinymce.util.Tools.resolve("tinymce.util.Tools");const n=t=>{const e=/^(\d+)([ms]?)$/.exec(t);return(e&&e[2]?{s:1e3,m:6e4}[e[2]]:1)*parseInt(t,10)},i=t=>e=>e.options.get(t),u=i("autosave_ask_before_unload"),l=i("autosave_restore_when_empty"),c=i("autosave_interval"),d=i("autosave_retention"),m=t=>{const e=document.location;return t.options.get("autosave_prefix").replace(/{path}/g,e.pathname).replace(/{query}/g,e.search).replace(/{hash}/g,e.hash).replace(/{id}/g,t.id)},v=(t,e)=>{if(r(e))return t.dom.isEmpty(t.getBody());{const r=s.trim(e);if(""===r)return!0;{const e=(new DOMParser).parseFromString(r,"text/html");return t.dom.isEmpty(e)}}},f=t=>{var e;const r=parseInt(null!==(e=a.getItem(m(t)+"time"))&&void 0!==e?e:"0",10)||0;return!((new Date).getTime()-r>d(t)&&(p(t,!1),1))},p=(t,e)=>{const r=m(t);a.removeItem(r+"draft"),a.removeItem(r+"time"),!1!==e&&(t=>{t.dispatch("RemoveDraft")})(t)},g=t=>{const e=m(t);!v(t)&&t.isDirty()&&(a.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),a.setItem(e+"time",(new Date).getTime().toString()),(t=>{t.dispatch("StoreDraft")})(t))},y=t=>{var e;const r=m(t);f(t)&&(t.setContent(null!==(e=a.getItem(r+"draft"))&&void 0!==e?e:"",{format:"raw"}),(t=>{t.dispatch("RestoreDraft")})(t))};var D=tinymce.util.Tools.resolve("tinymce.EditorManager");const h=t=>e=>{e.setEnabled(f(t));const r=()=>e.setEnabled(f(t));return t.on("StoreDraft RestoreDraft RemoveDraft",r),()=>t.off("StoreDraft RestoreDraft RemoveDraft",r)};t.add("autosave",(t=>((t=>{const r=t.options.register,o=t=>{const r=e(t);return r?{value:n(t),valid:r}:{valid:!1,message:"Must be a string."}};r("autosave_ask_before_unload",{processor:"boolean",default:!0}),r("autosave_prefix",{processor:"string",default:"tinymce-autosave-{path}{query}{hash}-{id}-"}),r("autosave_restore_when_empty",{processor:"boolean",default:!1}),r("autosave_interval",{processor:o,default:"30s"}),r("autosave_retention",{processor:o,default:"20m"})})(t),(t=>{t.editorManager.on("BeforeUnload",(t=>{let e;s.each(D.get(),(t=>{t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&u(t)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))})),e&&(t.preventDefault(),t.returnValue=e)}))})(t),(t=>{(t=>{const e=c(t);o.setEditorInterval(t,(()=>{g(t)}),e)})(t);const e=()=>{(t=>{t.undoManager.transact((()=>{y(t),p(t)})),t.focus()})(t)};t.ui.registry.addButton("restoredraft",{tooltip:"Restore last draft",icon:"restore-draft",onAction:e,onSetup:h(t)}),t.ui.registry.addMenuItem("restoredraft",{text:"Restore last draft",icon:"restore-draft",onAction:e,onSetup:h(t)})})(t),t.on("init",(()=>{l(t)&&t.dom.isEmpty(t.getBody())&&y(t)})),(t=>({hasDraft:()=>f(t),storeDraft:()=>g(t),restoreDraft:()=>y(t),removeDraft:e=>p(t,e),isEmpty:e=>v(t,e)}))(t))))}();

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
/**
* TinyMCE version 6.8.4 (2024-06-19)
*/
!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("code",(e=>((e=>{e.addCommand("mceCodeEditor",(()=>{(e=>{const o=(e=>e.getContent({source_view:!0}))(e);e.windowManager.open({title:"Source Code",size:"large",body:{type:"panel",items:[{type:"textarea",name:"code"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{code:o},onSubmit:o=>{((e,o)=>{e.focus(),e.undoManager.transact((()=>{e.setContent(o)})),e.selection.setCursorLocation(),e.nodeChanged()})(e,o.getData().code),o.close()}})})(e)}))})(e),(e=>{const o=()=>e.execCommand("mceCodeEditor");e.ui.registry.addButton("code",{icon:"sourcecode",tooltip:"Source code",onAction:o}),e.ui.registry.addMenuItem("code",{icon:"sourcecode",text:"Source code",onAction:o})})(e),{})))}();

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,4 @@
/**
* TinyMCE version 6.8.4 (2024-06-19)
*/
!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=t=>e=>typeof e===t,o=t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(o=r=t,(n=String).prototype.isPrototypeOf(o)||(null===(i=r.constructor)||void 0===i?void 0:i.name)===n.name)?"string":e;var o,r,n,i})(t),r=e("boolean"),n=t=>!(t=>null==t)(t),i=e("function"),s=e("number"),l=(!1,()=>false);class a{constructor(t,e){this.tag=t,this.value=e}static some(t){return new a(!0,t)}static none(){return a.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?a.some(t(this.value)):a.none()}bind(t){return this.tag?t(this.value):a.none()}exists(t){return this.tag&&t(this.value)}forall(t){return!this.tag||t(this.value)}filter(t){return!this.tag||t(this.value)?this:a.none()}getOr(t){return this.tag?this.value:t}or(t){return this.tag?this:t}getOrThunk(t){return this.tag?this.value:t()}orThunk(t){return this.tag?this:t()}getOrDie(t){if(this.tag)return this.value;throw new Error(null!=t?t:"Called getOrDie on None")}static from(t){return n(t)?a.some(t):a.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(t){this.tag&&t(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}a.singletonNone=new a(!1);const u=(t,e)=>{for(let o=0,r=t.length;o<r;o++)e(t[o],o)},c=t=>{if(null==t)throw new Error("Node cannot be null or undefined");return{dom:t}},d=c,h=(t,e)=>{const o=t.dom;if(1!==o.nodeType)return!1;{const t=o;if(void 0!==t.matches)return t.matches(e);if(void 0!==t.msMatchesSelector)return t.msMatchesSelector(e);if(void 0!==t.webkitMatchesSelector)return t.webkitMatchesSelector(e);if(void 0!==t.mozMatchesSelector)return t.mozMatchesSelector(e);throw new Error("Browser lacks native selectors")}};"undefined"!=typeof window?window:Function("return this;")();const m=t=>e=>(t=>t.dom.nodeType)(e)===t,g=m(1),f=m(3),v=m(9),y=m(11),p=(t,e)=>{t.dom.removeAttribute(e)},w=i(Element.prototype.attachShadow)&&i(Node.prototype.getRootNode)?t=>d(t.dom.getRootNode()):t=>v(t)?t:d(t.dom.ownerDocument),b=t=>d(t.dom.host),N=t=>{const e=f(t)?t.dom.parentNode:t.dom;if(null==e||null===e.ownerDocument)return!1;const o=e.ownerDocument;return(t=>{const e=w(t);return y(o=e)&&n(o.dom.host)?a.some(e):a.none();var o})(d(e)).fold((()=>o.body.contains(e)),(r=N,i=b,t=>r(i(t))));var r,i},S=t=>"rtl"===((t,e)=>{const o=t.dom,r=window.getComputedStyle(o).getPropertyValue(e);return""!==r||N(t)?r:((t,e)=>(t=>void 0!==t.style&&i(t.style.getPropertyValue))(t)?t.style.getPropertyValue(e):"")(o,e)})(t,"direction")?"rtl":"ltr",A=(t,e)=>((t,o)=>((t,e)=>{const o=[];for(let r=0,n=t.length;r<n;r++){const n=t[r];e(n,r)&&o.push(n)}return o})(((t,e)=>{const o=t.length,r=new Array(o);for(let n=0;n<o;n++){const o=t[n];r[n]=e(o,n)}return r})(t.dom.childNodes,d),(t=>h(t,e))))(t),E=("li",t=>g(t)&&"li"===t.dom.nodeName.toLowerCase());const T=(t,e,n)=>{u(e,(e=>{const c=d(e),m=E(c),f=((t,e)=>{return(e?(o=t,r="ol,ul",((t,e,o)=>{let n=t.dom;const s=i(o)?o:l;for(;n.parentNode;){n=n.parentNode;const t=d(n);if(h(t,r))return a.some(t);if(s(t))break}return a.none()})(o,0,n)):a.some(t)).getOr(t);var o,r,n})(c,m);var v;(v=f,(t=>a.from(t.dom.parentNode).map(d))(v).filter(g)).each((e=>{if(t.setStyle(f.dom,"direction",null),S(e)===n?p(f,"dir"):((t,e,n)=>{((t,e,n)=>{if(!(o(n)||r(n)||s(n)))throw console.error("Invalid call to Attribute.set. Key ",e,":: Value ",n,":: Element ",t),new Error("Attribute value was not simple");t.setAttribute(e,n+"")})(t.dom,e,n)})(f,"dir",n),S(f)!==n&&t.setStyle(f.dom,"direction",n),m){const e=A(f,"li[dir],li[style]");u(e,(e=>{p(e,"dir"),t.setStyle(e.dom,"direction",null)}))}}))}))},C=(t,e)=>{t.selection.isEditable()&&(T(t.dom,t.selection.getSelectedBlocks(),e),t.nodeChanged())},D=(t,e)=>o=>{const r=r=>{const n=d(r.element);o.setActive(S(n)===e),o.setEnabled(t.selection.isEditable())};return t.on("NodeChange",r),o.setEnabled(t.selection.isEditable()),()=>t.off("NodeChange",r)};t.add("directionality",(t=>{(t=>{t.addCommand("mceDirectionLTR",(()=>{C(t,"ltr")})),t.addCommand("mceDirectionRTL",(()=>{C(t,"rtl")}))})(t),(t=>{t.ui.registry.addToggleButton("ltr",{tooltip:"Left to right",icon:"ltr",onAction:()=>t.execCommand("mceDirectionLTR"),onSetup:D(t,"ltr")}),t.ui.registry.addToggleButton("rtl",{tooltip:"Right to left",icon:"rtl",onAction:()=>t.execCommand("mceDirectionRTL"),onSetup:D(t,"rtl")})})(t)}))}();

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More