From ab52f3367a90a0e00efbeba5a74114515a7b44b8 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 29 Jun 2022 15:26:03 +0100 Subject: [PATCH 001/246] New translations editor.php (Russian) --- resources/lang/ru/editor.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lang/ru/editor.php b/resources/lang/ru/editor.php index 479b08fe2..9e91f572c 100644 --- a/resources/lang/ru/editor.php +++ b/resources/lang/ru/editor.php @@ -7,7 +7,7 @@ */ return [ // General editor terms - 'general' => 'Общее', + 'general' => 'Общие', 'advanced' => 'Дополнительно', 'none' => 'Нет', 'cancel' => 'Отмена', From 6d66682620158e9d27e218fe77d7a4f75a132d53 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 30 Jun 2022 09:36:18 +0100 Subject: [PATCH 002/246] New translations entities.php (German) --- resources/lang/de/entities.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lang/de/entities.php b/resources/lang/de/entities.php index 158697c26..61bdddfe3 100644 --- a/resources/lang/de/entities.php +++ b/resources/lang/de/entities.php @@ -357,7 +357,7 @@ return [ 'copy_consider_access' => 'Eine Veränderung der Position, Besitzers oder Berechtigungen könnte dafür sorgen, dass Unberechtigte, Zugriff bekommen.', // Conversions - 'convert_to_shelf' => 'Convert to Shelf', + 'convert_to_shelf' => 'In Regal umwandeln', 'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.', 'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.', 'convert_book' => 'Convert Book', From f4fda8d80cec8d83179795b4bd4581a4f5475551 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 2 Jul 2022 21:05:40 +0100 Subject: [PATCH 003/246] New translations activities.php (Dutch) --- resources/lang/nl/activities.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lang/nl/activities.php b/resources/lang/nl/activities.php index ab0db63b8..e8009795e 100644 --- a/resources/lang/nl/activities.php +++ b/resources/lang/nl/activities.php @@ -40,8 +40,8 @@ return [ // Bookshelves 'bookshelf_create' => 'boekenplank aangemaakt', 'bookshelf_create_notification' => 'Boekenplank succesvol aangemaakt', - 'bookshelf_create_from_book' => 'converted book to bookshelf', - 'bookshelf_create_from_book_notification' => 'Book successfully converted to a shelf', + 'bookshelf_create_from_book' => 'Boek is geconverteerd naar boekenplank', + 'bookshelf_create_from_book_notification' => 'Boek is succesvol geconverteerd naar boekenplank', 'bookshelf_update' => 'wijzigde boekenplank', 'bookshelf_update_notification' => 'Boekenplank succesvol bijgewerkt', 'bookshelf_delete' => 'verwijderde boekenplank', From f9f4a87e1be22edf1503c9898045971a7704080c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 2 Jul 2022 21:05:41 +0100 Subject: [PATCH 004/246] New translations entities.php (Dutch) --- resources/lang/nl/entities.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lang/nl/entities.php b/resources/lang/nl/entities.php index c1b2b4cfc..240282e2d 100644 --- a/resources/lang/nl/entities.php +++ b/resources/lang/nl/entities.php @@ -357,8 +357,8 @@ return [ 'copy_consider_access' => 'Een verandering van locatie, eigenaar of machtigingen kan ertoe leiden dat deze inhoud toegankelijk wordt voor personen die er voordien geen toegang tot hadden.', // Conversions - 'convert_to_shelf' => 'Convert to Shelf', - 'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.', + 'convert_to_shelf' => 'Converteer naar Boekenplank', + 'convert_to_shelf_contents_desc' => 'U kunt dit boek converteren naar een nieuwe boekenplank met dezelfde inhoud. Hoofdstukken in dit boek zullen worden geconverteerd naar nieuwe boeken. Als dit boek pagina\'s bevat, die niet in een hoofdstuk staan, zal dit boek een nieuwe naam krijgen en deze pagina\'s bevatten, en zal dit boek deel gaan uitmaken van de nieuwe boekenplank.', 'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.', 'convert_book' => 'Convert Book', 'convert_book_confirm' => 'Are you sure you want to convert this book?', From 0c8bd581aed8159446a44787fc3518faf0a48018 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 2 Jul 2022 21:05:42 +0100 Subject: [PATCH 005/246] New translations auth.php (Dutch) --- resources/lang/nl/auth.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/lang/nl/auth.php b/resources/lang/nl/auth.php index c4adb8905..1f3b39f48 100644 --- a/resources/lang/nl/auth.php +++ b/resources/lang/nl/auth.php @@ -39,9 +39,9 @@ return [ 'register_success' => 'Bedankt voor het aanmelden! Je bent nu geregistreerd en aangemeld.', // Login auto-initiation - 'auto_init_starting' => 'Attempting Login', - 'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.', - 'auto_init_start_link' => 'Proceed with authentication', + 'auto_init_starting' => 'Poging tot inloggen', + 'auto_init_starting_desc' => 'We maken contact met uw authenticatiesysteem om het inlogproces te starten. Als er na 5 seconden geen vooruitgang is, kunt u proberen op de onderstaande link te klikken.', + 'auto_init_start_link' => 'Ga verder met authenticatie', // Password Reset 'reset_password' => 'Wachtwoord herstellen', From 4487ea576fb4f9bc2055cb5dd6a613c6425e6f11 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 2 Jul 2022 22:09:55 +0100 Subject: [PATCH 006/246] New translations common.php (Dutch) --- resources/lang/nl/common.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lang/nl/common.php b/resources/lang/nl/common.php index f58cf8258..ed0e21ad5 100644 --- a/resources/lang/nl/common.php +++ b/resources/lang/nl/common.php @@ -11,7 +11,7 @@ return [ 'save' => 'Opslaan', 'continue' => 'Doorgaan', 'select' => 'Selecteer', - 'toggle_all' => 'Toggle alle', + 'toggle_all' => 'Wissel Alles', 'more' => 'Meer', // Form Labels From 459659a68021deb69c6b7c34180d8aa8a2e466a4 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 2 Jul 2022 22:09:56 +0100 Subject: [PATCH 007/246] New translations entities.php (Dutch) --- resources/lang/nl/entities.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/resources/lang/nl/entities.php b/resources/lang/nl/entities.php index 240282e2d..25cf6a2aa 100644 --- a/resources/lang/nl/entities.php +++ b/resources/lang/nl/entities.php @@ -359,12 +359,12 @@ return [ // Conversions 'convert_to_shelf' => 'Converteer naar Boekenplank', 'convert_to_shelf_contents_desc' => 'U kunt dit boek converteren naar een nieuwe boekenplank met dezelfde inhoud. Hoofdstukken in dit boek zullen worden geconverteerd naar nieuwe boeken. Als dit boek pagina\'s bevat, die niet in een hoofdstuk staan, zal dit boek een nieuwe naam krijgen en deze pagina\'s bevatten, en zal dit boek deel gaan uitmaken van de nieuwe boekenplank.', - 'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.', - 'convert_book' => 'Convert Book', - 'convert_book_confirm' => 'Are you sure you want to convert this book?', - 'convert_undo_warning' => 'This cannot be as easily undone.', - 'convert_to_book' => 'Convert to Book', - 'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.', - 'convert_chapter' => 'Convert Chapter', - 'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?', + 'convert_to_shelf_permissions_desc' => 'Elke machtiging ingesteld op dit boek zal gekopieerd worden naar de nieuwe boekenplank en naar alle nieuwe onderliggende boeken die geen eigen machtiging hebben afgedwongen. Merk op dat boekenplank-machtigingen niet automatisch overdragen naar inhoud binnenin de boekenplank, zoals dat wel gebeurd bij boeken.', + 'convert_book' => 'Converteer Boek', + 'convert_book_confirm' => 'Weet je zeker dat je dit boek wil converteren?', + 'convert_undo_warning' => 'Dit kan niet eenvoudig ongedaan gemaakt worden.', + 'convert_to_book' => 'Converteer naar Boek', + 'convert_to_book_desc' => 'Je kan dit hoofdstuk converteren naar een nieuw boek met dezelfde inhoud. Alle machtigingen ingesteld op dit hoofdstuk zullen worden gekopieerd naar het nieuwe boek, maar alle geërfde machtigingen, van het bovenliggende boek, zullen niet worden gekopieerd, wat kan leiden tot een wijziging van de toegangscontrole.', + 'convert_chapter' => 'Converteer Hoofdstuk', + 'convert_chapter_confirm' => 'Weet je zeker dat je dit hoofdstuk wil converteren?', ]; From 451300606f5659f267d35ad217d9bb9869bc9854 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 5 Jul 2022 14:30:10 +0100 Subject: [PATCH 008/246] New translations activities.php (Ukrainian) --- resources/lang/uk/activities.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/lang/uk/activities.php b/resources/lang/uk/activities.php index 7d024eb50..a4f79fa4c 100644 --- a/resources/lang/uk/activities.php +++ b/resources/lang/uk/activities.php @@ -28,8 +28,8 @@ return [ // Books 'book_create' => 'створив книгу', 'book_create_notification' => 'Книгу успішно створено', - 'book_create_from_chapter' => 'converted chapter to book', - 'book_create_from_chapter_notification' => 'Chapter successfully converted to a book', + 'book_create_from_chapter' => 'перетворений розділ в книгу', + 'book_create_from_chapter_notification' => 'Розділ успішно перетворений в книгу', 'book_update' => 'оновив книгу', 'book_update_notification' => 'Книгу успішно оновлено', 'book_delete' => 'видалив книгу', @@ -40,8 +40,8 @@ return [ // Bookshelves 'bookshelf_create' => 'створив книжкову полицю', 'bookshelf_create_notification' => 'Книжкову полицю успішно створено', - 'bookshelf_create_from_book' => 'converted book to bookshelf', - 'bookshelf_create_from_book_notification' => 'Book successfully converted to a shelf', + 'bookshelf_create_from_book' => 'конвертувати книгу на книжкову полицю', + 'bookshelf_create_from_book_notification' => 'Книжку успішно конвертовано на полицю', 'bookshelf_update' => 'оновив книжкову полицю', 'bookshelf_update_notification' => 'Книжкову полицю успішно оновлено', 'bookshelf_delete' => 'видалив книжкову полицю', From e89348b02a7d6a79c21b5c476178d549a7acdc33 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 5 Jul 2022 14:30:12 +0100 Subject: [PATCH 009/246] New translations entities.php (Ukrainian) --- resources/lang/uk/entities.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/resources/lang/uk/entities.php b/resources/lang/uk/entities.php index fe0fff425..12d305f3e 100644 --- a/resources/lang/uk/entities.php +++ b/resources/lang/uk/entities.php @@ -206,9 +206,9 @@ return [ 'pages_editor_switch_title' => 'Змінити редактор', 'pages_editor_switch_are_you_sure' => 'Ви впевнені, що хочете змінити редактор цієї сторінки?', 'pages_editor_switch_consider_following' => 'Врахуйте наступне при зміні редакторів:', - 'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.', + 'pages_editor_switch_consideration_a' => 'Після збереження нова опція редактора буде використовуватися будь-якими майбутніми редакторами, включаючи ті, які не можуть змінювати сам редактор редакторів.', 'pages_editor_switch_consideration_b' => 'Це може потенційно призвести до втрати деталізації та синтаксису за певних обставин.', - 'pages_editor_switch_consideration_c' => 'Tag or changelog changes, made since last save, won\'t persist across this change.', + 'pages_editor_switch_consideration_c' => 'Мітка або список змін, зроблених з часу останнього збереження, не буде зберігатися в цих змінах.', 'pages_save' => 'Зберегти сторінку', 'pages_title' => 'Заголовок сторінки', 'pages_name' => 'Назва сторінки', @@ -357,14 +357,14 @@ return [ 'copy_consider_access' => 'Зміна розташування або дозволів може призвести до доступу до цього вмісту без попереднього доступу.', // Conversions - 'convert_to_shelf' => 'Convert to Shelf', - 'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.', - 'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.', - 'convert_book' => 'Convert Book', - 'convert_book_confirm' => 'Are you sure you want to convert this book?', - 'convert_undo_warning' => 'This cannot be as easily undone.', - 'convert_to_book' => 'Convert to Book', - 'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.', - 'convert_chapter' => 'Convert Chapter', - 'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?', + 'convert_to_shelf' => 'Перетворити на полиця', + 'convert_to_shelf_contents_desc' => 'Ви можете перетворити цю книгу на нову полицю з одним змістом. Розділи, що містяться в цій книзі, будуть перетворені в нові книги. Якщо ця книга містить будь-які сторінки, яких немає у главі, цю книгу буде перейменовано і містить такі сторінки, а ця книга стане частиною нової полиці.', + 'convert_to_shelf_permissions_desc' => 'Будь-які дозволи, встановлені на цій книзі, будуть скопійовані в нову полицю та до всіх нових дитячих книг, які не мають прав на виконання. Зверніть увагу, що дозволи на полицях не автоматично каскад до вмісту в межах, як вони роблять для книг.', + 'convert_book' => 'Перетворити книгу', + 'convert_book_confirm' => 'Ви впевнені, що хочете конвертувати цю книгу?', + 'convert_undo_warning' => 'Це не так легко відмінити.', + 'convert_to_book' => 'Конвертувати в книгу', + 'convert_to_book_desc' => 'Ви можете конвертувати цей розділ в нову книгу з одним контентом. Будь-які дозволи, встановлені на цьому розділі, будуть скопійовані в нову книгу, але будь-які успадковані дозволи, з батьківської книги не буде скопійований, що може призвести до зміни контролю доступу.', + 'convert_chapter' => 'Перетворити розділ', + 'convert_chapter_confirm' => 'Ви впевнені, що хочете конвертувати цей розділ?', ]; From 1a224e17194a8db1a44715064382b1a01184a730 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 5 Jul 2022 14:30:13 +0100 Subject: [PATCH 010/246] New translations auth.php (Ukrainian) --- resources/lang/uk/auth.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/lang/uk/auth.php b/resources/lang/uk/auth.php index b7d55ebeb..7cda943c0 100644 --- a/resources/lang/uk/auth.php +++ b/resources/lang/uk/auth.php @@ -39,9 +39,9 @@ return [ 'register_success' => 'Дякуємо за реєстрацію! Ви зареєстровані та ввійшли в систему.', // Login auto-initiation - 'auto_init_starting' => 'Attempting Login', - 'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.', - 'auto_init_start_link' => 'Proceed with authentication', + 'auto_init_starting' => 'Спроба входу в систему', + 'auto_init_starting_desc' => 'Ми пишемо вашій системі аутентифікації, щоб запустити процес авторизації. Якщо після 5 секунд Ви можете спробувати натиснути на посилання нижче.', + 'auto_init_start_link' => 'Продовжити з автентифікацією', // Password Reset 'reset_password' => 'Скинути пароль', From 61b3bc10a3eec710a41e145d7e9a53e7026a36e6 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 5 Jul 2022 14:30:14 +0100 Subject: [PATCH 011/246] New translations common.php (Ukrainian) --- resources/lang/uk/common.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lang/uk/common.php b/resources/lang/uk/common.php index 549b22d11..8f1cac609 100644 --- a/resources/lang/uk/common.php +++ b/resources/lang/uk/common.php @@ -47,8 +47,8 @@ return [ 'previous' => 'Назад', 'filter_active' => 'Активний фільтр:', 'filter_clear' => 'Очистити фільтр', - 'download' => 'Download', - 'open_in_tab' => 'Open in Tab', + 'download' => 'Завантажити', + 'open_in_tab' => 'Відкрити в новій вкладці', // Sort Options 'sort_options' => 'Параметри сортування', From bd1971c827cd75d72141a95ed9d739cd60086072 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 5 Jul 2022 14:30:15 +0100 Subject: [PATCH 012/246] New translations editor.php (Ukrainian) --- resources/lang/uk/editor.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/resources/lang/uk/editor.php b/resources/lang/uk/editor.php index 9c9b65471..b304dd3e6 100644 --- a/resources/lang/uk/editor.php +++ b/resources/lang/uk/editor.php @@ -93,7 +93,7 @@ return [ 'cell_properties_title' => 'Властивості клітинки', 'cell_type' => 'Тип клітинки', 'cell_type_cell' => 'Комірка', - 'cell_scope' => 'Scope', + 'cell_scope' => 'Область використання', 'cell_type_header' => 'Комірка заголовка', 'merge_cells' => 'Об\'єднати комірки', 'split_cell' => 'Роз\'єднати комірку', @@ -124,16 +124,16 @@ return [ 'caption' => 'Підпис', 'show_caption' => 'Показати заголовок', 'constrain' => 'Обмеження пропорції', - 'cell_border_solid' => 'Solid', - 'cell_border_dotted' => 'Dotted', - 'cell_border_dashed' => 'Dashed', - 'cell_border_double' => 'Double', - 'cell_border_groove' => 'Groove', - 'cell_border_ridge' => 'Ridge', - 'cell_border_inset' => 'Inset', - 'cell_border_outset' => 'Outset', - 'cell_border_none' => 'None', - 'cell_border_hidden' => 'Hidden', + 'cell_border_solid' => 'Суцільний', + 'cell_border_dotted' => 'В крапку', + 'cell_border_dashed' => 'Пунктир', + 'cell_border_double' => 'Подвійна', + 'cell_border_groove' => 'Паз', + 'cell_border_ridge' => 'Рідж', + 'cell_border_inset' => 'Врізка', + 'cell_border_outset' => 'Початок', + 'cell_border_none' => 'Відсутньо', + 'cell_border_hidden' => 'Прихований', // Images, links, details/summary & embed 'source' => 'Вихідний код', From f3d7d06536c2e9d8b666f4a0dee9822440179cd1 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 5 Jul 2022 19:10:04 +0100 Subject: [PATCH 013/246] New translations activities.php (Polish) --- resources/lang/pl/activities.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lang/pl/activities.php b/resources/lang/pl/activities.php index 2634fe3ed..880dc219b 100644 --- a/resources/lang/pl/activities.php +++ b/resources/lang/pl/activities.php @@ -35,7 +35,7 @@ return [ 'book_delete' => 'usunął książkę', 'book_delete_notification' => 'Książka usunięta pomyślnie', 'book_sort' => 'posortował książkę', - 'book_sort_notification' => 'Książka przywrócona pomyślnie', + 'book_sort_notification' => 'Książka posortowana pomyślnie', // Bookshelves 'bookshelf_create' => 'utworzył półkę', From 83d2a3c763340eed765ce71ebd15da91496cf973 Mon Sep 17 00:00:00 2001 From: mcgong <88075411+GongMingCai@users.noreply.github.com> Date: Wed, 6 Jul 2022 17:30:46 +0800 Subject: [PATCH 014/246] Fixed comment count update error --- resources/lang/zh_CN/entities.php | 2 +- resources/lang/zh_TW/entities.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lang/zh_CN/entities.php b/resources/lang/zh_CN/entities.php index 6dcccac80..e535bd21e 100644 --- a/resources/lang/zh_CN/entities.php +++ b/resources/lang/zh_CN/entities.php @@ -329,7 +329,7 @@ return [ 'comments' => '评论', 'comment_add' => '添加评论', 'comment_placeholder' => '在这里评论', - 'comment_count' => '{0} 无评论|[1,*] :count条评论', + 'comment_count' => '{0} 无评论|{1} 1 条评论|[2,*] :count 条评论', 'comment_save' => '保存评论', 'comment_saving' => '正在保存评论...', 'comment_deleting' => '正在删除评论...', diff --git a/resources/lang/zh_TW/entities.php b/resources/lang/zh_TW/entities.php index 19016fe13..a932c3c19 100644 --- a/resources/lang/zh_TW/entities.php +++ b/resources/lang/zh_TW/entities.php @@ -329,7 +329,7 @@ return [ 'comments' => '評論', 'comment_add' => '新增評論', 'comment_placeholder' => '在這裡評論', - 'comment_count' => '{0} 無評論 |{1} :count 則評論 | [2,*] :count 則評論', + 'comment_count' => '{0} 無評論|{1} 1 則評論|[2,*] :count 則評論', 'comment_save' => '儲存評論', 'comment_saving' => '正在儲存評論……', 'comment_deleting' => '正在刪除評論……', From c5e9dfa168f2f02106491779349663f9c3f5827b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 10 Jul 2022 13:45:04 +0100 Subject: [PATCH 015/246] Optimized pre-joint-permission logic efficiency --- app/Auth/Permissions/PermissionService.php | 108 +++++++++++++-------- 1 file changed, 67 insertions(+), 41 deletions(-) diff --git a/app/Auth/Permissions/PermissionService.php b/app/Auth/Permissions/PermissionService.php index 59ff37dc9..1363fe86e 100644 --- a/app/Auth/Permissions/PermissionService.php +++ b/app/Auth/Permissions/PermissionService.php @@ -37,7 +37,7 @@ class PermissionService protected $db; /** - * @var array + * @var array> */ protected $entityCache; @@ -68,10 +68,12 @@ class PermissionService foreach ($entities as $entity) { $class = get_class($entity); + if (!isset($this->entityCache[$class])) { - $this->entityCache[$class] = collect(); + $this->entityCache[$class] = []; } - $this->entityCache[$class]->put($entity->id, $entity); + + $this->entityCache[$class][$entity->getRawAttribute('id')] = $entity; } } @@ -80,8 +82,8 @@ class PermissionService */ protected function getBook(int $bookId): ?Book { - if (isset($this->entityCache[Book::class]) && $this->entityCache[Book::class]->has($bookId)) { - return $this->entityCache[Book::class]->get($bookId); + if ($this->entityCache[Book::class][$bookId] ?? false) { + return $this->entityCache[Book::class][$bookId]; } return Book::query()->withTrashed()->find($bookId); @@ -92,8 +94,8 @@ class PermissionService */ protected function getChapter(int $chapterId): ?Chapter { - if (isset($this->entityCache[Chapter::class]) && $this->entityCache[Chapter::class]->has($chapterId)) { - return $this->entityCache[Chapter::class]->get($chapterId); + if ($this->entityCache[Chapter::class][$chapterId] ?? false) { + return $this->entityCache[Chapter::class][$chapterId]; } return Chapter::query() @@ -206,7 +208,7 @@ class PermissionService $entities = [$entity]; if ($entity instanceof Book) { $books = $this->bookFetchQuery()->where('id', '=', $entity->id)->get(); - $this->buildJointPermissionsForBooks($books, Role::query()->get()->all(), true); + $this->buildJointPermissionsForBooks($books, Role::query()->with('permissions')->get()->all(), true); return; } @@ -270,7 +272,7 @@ class PermissionService } /** - * Delete all of the entity jointPermissions for a list of entities. + * Delete all the entity jointPermissions for a list of entities. * * @param Role[] $roles */ @@ -283,19 +285,7 @@ class PermissionService } /** - * Delete the entity jointPermissions for a particular entity. - * - * @param Entity $entity - * - * @throws Throwable - */ - public function deleteJointPermissionsForEntity(Entity $entity) - { - $this->deleteManyJointPermissionsForEntities([$entity]); - } - - /** - * Delete all of the entity jointPermissions for a list of entities. + * Delete all the entity jointPermissions for a list of entities. * * @param Entity[] $entities * @@ -303,20 +293,16 @@ class PermissionService */ protected function deleteManyJointPermissionsForEntities(array $entities) { - if (count($entities) === 0) { - return; - } + $idsByType = $this->entitiesToTypeIdMap($entities); - $this->db->transaction(function () use ($entities) { - foreach (array_chunk($entities, 1000) as $entityChunk) { - $query = $this->db->table('joint_permissions'); - foreach ($entityChunk as $entity) { - $query->orWhere(function (QueryBuilder $query) use ($entity) { - $query->where('entity_id', '=', $entity->id) - ->where('entity_type', '=', $entity->getMorphClass()); - }); + $this->db->transaction(function () use ($idsByType) { + foreach ($idsByType as $type => $ids) { + foreach (array_chunk($ids, 1000) as $idChunk) { + $this->db->table('joint_permissions') + ->where('entity_type', '=', $type) + ->whereIn('entity_id', $idChunk) + ->delete(); } - $query->delete(); } }); } @@ -334,16 +320,14 @@ class PermissionService $this->readyEntityCache($entities); $jointPermissions = []; - // Fetch Entity Permissions and create a mapping of entity restricted statuses + // Create a mapping of entity restricted statuses $entityRestrictedMap = []; - $permissionFetch = EntityPermission::query(); foreach ($entities as $entity) { - $entityRestrictedMap[$entity->getMorphClass() . ':' . $entity->id] = boolval($entity->getRawAttribute('restricted')); - $permissionFetch->orWhere(function ($query) use ($entity) { - $query->where('restrictable_id', '=', $entity->id)->where('restrictable_type', '=', $entity->getMorphClass()); - }); + $entityRestrictedMap[$entity->getMorphClass() . ':' . $entity->getRawAttribute('id')] = boolval($entity->getRawAttribute('restricted')); } - $permissions = $permissionFetch->get(); + + // Fetch related entity permissions + $permissions = $this->getEntityPermissionsForEntities($entities); // Create a mapping of explicit entity permissions $permissionMap = []; @@ -377,6 +361,48 @@ class PermissionService }); } + /** + * From the given entity list, provide back a mapping of entity types to + * the ids of that given type. The type used is the DB morph class. + * @param Entity[] $entities + * @return array + */ + protected function entitiesToTypeIdMap(array $entities): array + { + $idsByType = []; + + foreach ($entities as $entity) { + $type = $entity->getMorphClass(); + + if (!isset($idsByType[$type])) { + $idsByType[$type] = []; + } + + $idsByType[$type][] = $entity->getRawAttribute('id'); + } + + return $idsByType; + } + + /** + * Get the entity permissions for all the given entities + * @param Entity[] $entities + * @return EloquentCollection + */ + protected function getEntityPermissionsForEntities(array $entities) + { + $idsByType = $this->entitiesToTypeIdMap($entities); + $permissionFetch = EntityPermission::query(); + + foreach ($idsByType as $type => $ids) { + $permissionFetch->orWhere(function (Builder $query) use ($type, $ids) { + $query->where('restrictable_type', '=', $type)->whereIn('restrictable_id', $ids); + }); + } + + return $permissionFetch->get(); + } + /** * Get the actions related to an entity. */ From a99cbcfe121f33486f5048c048ffee29decaa479 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Jul 2022 13:03:47 +0100 Subject: [PATCH 016/246] New translations activities.php (Portuguese) --- resources/lang/pt/activities.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/lang/pt/activities.php b/resources/lang/pt/activities.php index 96d729422..7ff77f097 100644 --- a/resources/lang/pt/activities.php +++ b/resources/lang/pt/activities.php @@ -28,8 +28,8 @@ return [ // Books 'book_create' => 'livro criado', 'book_create_notification' => 'Livro criado com sucesso', - 'book_create_from_chapter' => 'converted chapter to book', - 'book_create_from_chapter_notification' => 'Chapter successfully converted to a book', + 'book_create_from_chapter' => 'capítulo convertido para lívro', + 'book_create_from_chapter_notification' => 'Capítulo convertido em livro com sucesso', 'book_update' => 'livro atualizado', 'book_update_notification' => 'Livro atualizado com sucesso', 'book_delete' => 'livro eliminado', @@ -40,8 +40,8 @@ return [ // Bookshelves 'bookshelf_create' => 'estante criada', 'bookshelf_create_notification' => 'Estante criada com sucesso', - 'bookshelf_create_from_book' => 'converted book to bookshelf', - 'bookshelf_create_from_book_notification' => 'Book successfully converted to a shelf', + 'bookshelf_create_from_book' => 'livro convertido para estante', + 'bookshelf_create_from_book_notification' => 'Livro convertido em prateleira com sucesso', 'bookshelf_update' => 'estante atualizada', 'bookshelf_update_notification' => 'Estante atualizada com sucesso', 'bookshelf_delete' => 'excluiu a prateleira', From ddd45dde6b6f5937fc1adc35fb8a35a24de0f999 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Jul 2022 13:03:49 +0100 Subject: [PATCH 017/246] New translations entities.php (Portuguese) --- resources/lang/pt/entities.php | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/resources/lang/pt/entities.php b/resources/lang/pt/entities.php index 9ee3f575c..267aa929c 100644 --- a/resources/lang/pt/entities.php +++ b/resources/lang/pt/entities.php @@ -196,18 +196,18 @@ return [ 'pages_edit_draft_save_at' => 'Rascunho guardado em ', 'pages_edit_delete_draft' => 'Eliminar Rascunho', 'pages_edit_discard_draft' => 'Descartar Rascunho', - 'pages_edit_switch_to_markdown' => 'Switch to Markdown Editor', + 'pages_edit_switch_to_markdown' => 'Alternar para o editor Markdown', 'pages_edit_switch_to_markdown_clean' => '(Clean Content)', 'pages_edit_switch_to_markdown_stable' => '(Stable Content)', - 'pages_edit_switch_to_wysiwyg' => 'Switch to WYSIWYG Editor', + 'pages_edit_switch_to_wysiwyg' => 'Alternar para o editor WYSIWYG', 'pages_edit_set_changelog' => 'Relatar Alterações', 'pages_edit_enter_changelog_desc' => 'Digite uma breve descrição das alterações efetuadas por si', 'pages_edit_enter_changelog' => 'Inserir Alterações', - 'pages_editor_switch_title' => 'Switch Editor', - 'pages_editor_switch_are_you_sure' => 'Are you sure you want to change the editor for this page?', - 'pages_editor_switch_consider_following' => 'Consider the following when changing editors:', - 'pages_editor_switch_consideration_a' => 'Once saved, the new editor option will be used by any future editors, including those that may not be able to change editor type themselves.', - 'pages_editor_switch_consideration_b' => 'This can potentially lead to a loss of detail and syntax in certain circumstances.', + 'pages_editor_switch_title' => 'Trocar de Editor', + 'pages_editor_switch_are_you_sure' => 'Você tem certeza que deseja alterar o editor para esta página?', + 'pages_editor_switch_consider_following' => 'Considere o seguinte ao alterar editores:', + 'pages_editor_switch_consideration_a' => 'Uma vez alterada, o novo editor será usado por quaisquer editores futuros, incluindo aqueles que podem não ser capazes de mudar o tipo do editor.', + 'pages_editor_switch_consideration_b' => 'Isso pode levar a uma perda de detalhes e sintaxe em certas circunstâncias.', 'pages_editor_switch_consideration_c' => 'Tag or changelog changes, made since last save, won\'t persist across this change.', 'pages_save' => 'Guardar Página', 'pages_title' => 'Título da Página', @@ -235,7 +235,7 @@ return [ 'pages_revisions_number' => '#', 'pages_revisions_numbered' => 'Revisão #:id', 'pages_revisions_numbered_changes' => 'Alterações da Revisão #:id', - 'pages_revisions_editor' => 'Editor Type', + 'pages_revisions_editor' => 'Tipo de editor', 'pages_revisions_changelog' => 'Relatório de Alterações', 'pages_revisions_changes' => 'Alterações', 'pages_revisions_current' => 'Versão Atual', @@ -357,14 +357,14 @@ return [ 'copy_consider_access' => 'Uma alteração de localização, proprietário ou permissões pode resultar em que este conteúdo seja acessível para aqueles previamente sem acesso.', // Conversions - 'convert_to_shelf' => 'Convert to Shelf', - 'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.', - 'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.', - 'convert_book' => 'Convert Book', - 'convert_book_confirm' => 'Are you sure you want to convert this book?', - 'convert_undo_warning' => 'This cannot be as easily undone.', - 'convert_to_book' => 'Convert to Book', + 'convert_to_shelf' => 'Converter para prateleira', + 'convert_to_shelf_contents_desc' => 'Você pode converter este livro em uma nova prateleira com o mesmo conteúdo. Capítulos contidos neste livro serão convertidos em novos livros. Se este livro contiver alguma página, que não estão em um capítulo, este livro será renomeado contendo essas páginas, e o mesmo se tornará parte da nova prateleira.', + 'convert_to_shelf_permissions_desc' => 'Quaisquer permissões definidas neste livro serão copiadas para a nova prateleira e para todos os novos livros filhos que não tenham as suas próprias permissões impostas. Observe que as permissões nas prateleiras não são do tipo cascata como o são para os livros.', + 'convert_book' => 'Converter Livro', + 'convert_book_confirm' => 'Tem a certeza de que deseja converter este livro?', + 'convert_undo_warning' => 'Isto não pode ser tão facilmente desfeito.', + 'convert_to_book' => 'Converter para Livro', 'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.', - 'convert_chapter' => 'Convert Chapter', - 'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?', + 'convert_chapter' => 'Converter Capítulo', + 'convert_chapter_confirm' => 'Tem certeza de que deseja converter este capítulo?', ]; From dde2ea743f8ba3ff766e2dafbdd2687e28e51c3b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Jul 2022 13:03:50 +0100 Subject: [PATCH 018/246] New translations auth.php (Portuguese) --- resources/lang/pt/auth.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/lang/pt/auth.php b/resources/lang/pt/auth.php index ad4f0744d..a815b9cca 100644 --- a/resources/lang/pt/auth.php +++ b/resources/lang/pt/auth.php @@ -39,9 +39,9 @@ return [ 'register_success' => 'Obrigado por se registar! Você está agora registado e com a sessão iniciada.', // Login auto-initiation - 'auto_init_starting' => 'Attempting Login', - 'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.', - 'auto_init_start_link' => 'Proceed with authentication', + 'auto_init_starting' => 'Tentando inicar sessão', + 'auto_init_starting_desc' => 'Estamos a aceder ao seu sistema de autenticação para iniciar o processo de login. Se não houver progresso após 5 segundos você pode tentar clicar no link abaixo.', + 'auto_init_start_link' => 'Prosseguir com autenticação', // Password Reset 'reset_password' => 'Redefinir Senha', From 9cfded13115e2e3399a70afb8390d147d5e4c3e2 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Jul 2022 13:03:51 +0100 Subject: [PATCH 019/246] New translations common.php (Portuguese) --- resources/lang/pt/common.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lang/pt/common.php b/resources/lang/pt/common.php index afb857ac2..828c28547 100644 --- a/resources/lang/pt/common.php +++ b/resources/lang/pt/common.php @@ -47,8 +47,8 @@ return [ 'previous' => 'Anterior', 'filter_active' => 'Filtro Ativo:', 'filter_clear' => 'Limpar Filtro', - 'download' => 'Download', - 'open_in_tab' => 'Open in Tab', + 'download' => 'Transferir', + 'open_in_tab' => 'Abrir em novo separador', // Sort Options 'sort_options' => 'Opções de Ordenação', From 376640db25da3465008f67ade965eaef6bf1d9fa Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Jul 2022 13:03:52 +0100 Subject: [PATCH 020/246] New translations settings.php (Portuguese) --- resources/lang/pt/settings.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/lang/pt/settings.php b/resources/lang/pt/settings.php index 782ee494b..e6ee7ec34 100644 --- a/resources/lang/pt/settings.php +++ b/resources/lang/pt/settings.php @@ -27,8 +27,8 @@ return [ 'app_secure_images' => 'Carregamento de Imagens mais Seguro', 'app_secure_images_toggle' => 'Ativar o carregamento de imagem mais seguro', 'app_secure_images_desc' => 'Por razões de performance, todas as imagens são públicas. Esta opção adiciona uma string aleatória na frente das Urls de imagens. Certifique-se de que os diretórios não possam ser indexados para prevenir acesso indesejado.', - 'app_default_editor' => 'Default Page Editor', - 'app_default_editor_desc' => 'Select which editor will be used by default when editing new pages. This can be overridden at a page level where permissions allow.', + 'app_default_editor' => 'Editor de Página Padrão', + 'app_default_editor_desc' => 'Selecione qual editor será usado por padrão ao editar novas páginas. Isto pode ser substituído a nível de página onde as permissões estiverem disponíveis.', 'app_custom_html' => 'Conteúdo personalizado para para o Head do HTML', 'app_custom_html_desc' => 'Quaisquer conteúdos aqui adicionados serão inseridos no final da secção de cada página. Esta é uma maneira útil de sobrescrever estilos e adicionar códigos de análise de site.', 'app_custom_html_disabled_notice' => 'O conteúdo personalizado do HTML está desativado nesta página de configurações, para garantir que quaisquer alterações que acabem maliciosas possam ser revertidas.', @@ -152,7 +152,7 @@ return [ 'role_access_api' => 'Aceder à API do sistema', 'role_manage_settings' => 'Gerir as configurações da aplicação', 'role_export_content' => 'Exportar conteúdo', - 'role_editor_change' => 'Change page editor', + 'role_editor_change' => 'Alterar editor de página', 'role_asset' => 'Permissões de Ativos', 'roles_system_warning' => 'Esteja ciente de que o acesso a qualquer uma das três permissões acima pode permitir que um utilizador altere os seus próprios privilégios ou privilégios de outros no sistema. Apenas atribua cargos com essas permissões a utilizadores de confiança.', 'role_asset_desc' => 'Estas permissões controlam o acesso padrão para os ativos dentro do sistema. Permissões em Livros, Capítulos e Páginas serão sobrescritas por estas permissões.', From 2d4f708c7961f7ef7da3fd1d89d39a99581afa9e Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Jul 2022 19:38:11 +0100 Subject: [PATCH 021/246] Extracted permission building out of permission service --- .../Permissions/JointPermissionBuilder.php | 423 ++++++++++++++++ app/Auth/Permissions/PermissionService.php | 452 ------------------ app/Auth/Permissions/PermissionsRepo.php | 39 +- .../Commands/RegeneratePermissions.php | 26 +- database/seeders/DummyContentSeeder.php | 4 +- database/seeders/LargeContentSeeder.php | 4 +- tests/PublicActionTest.php | 4 +- tests/SharedTestHelpers.php | 11 +- 8 files changed, 463 insertions(+), 500 deletions(-) create mode 100644 app/Auth/Permissions/JointPermissionBuilder.php diff --git a/app/Auth/Permissions/JointPermissionBuilder.php b/app/Auth/Permissions/JointPermissionBuilder.php new file mode 100644 index 000000000..c87560fe0 --- /dev/null +++ b/app/Auth/Permissions/JointPermissionBuilder.php @@ -0,0 +1,423 @@ +> + */ + protected $entityCache; + + /** + * Prepare the local entity cache and ensure it's empty. + * + * @param Entity[] $entities + */ + protected function readyEntityCache(array $entities = []) + { + $this->entityCache = []; + + foreach ($entities as $entity) { + $class = get_class($entity); + + if (!isset($this->entityCache[$class])) { + $this->entityCache[$class] = []; + } + + $this->entityCache[$class][$entity->getRawAttribute('id')] = $entity; + } + } + + /** + * Get a book via ID, Checks local cache. + */ + protected function getBook(int $bookId): ?Book + { + if ($this->entityCache[Book::class][$bookId] ?? false) { + return $this->entityCache[Book::class][$bookId]; + } + + return Book::query()->withTrashed()->find($bookId); + } + + /** + * Get a chapter via ID, Checks local cache. + */ + protected function getChapter(int $chapterId): ?Chapter + { + if ($this->entityCache[Chapter::class][$chapterId] ?? false) { + return $this->entityCache[Chapter::class][$chapterId]; + } + + return Chapter::query() + ->withTrashed() + ->find($chapterId); + } + + /** + * Re-generate all entity permission from scratch. + */ + public function buildJointPermissions() + { + JointPermission::query()->truncate(); + $this->readyEntityCache(); + + // Get all roles (Should be the most limited dimension) + $roles = Role::query()->with('permissions')->get()->all(); + + // Chunk through all books + $this->bookFetchQuery()->chunk(5, function (EloquentCollection $books) use ($roles) { + $this->buildJointPermissionsForBooks($books, $roles); + }); + + // Chunk through all bookshelves + Bookshelf::query()->withTrashed()->select(['id', 'restricted', 'owned_by']) + ->chunk(50, function (EloquentCollection $shelves) use ($roles) { + $this->buildJointPermissionsForShelves($shelves, $roles); + }); + } + + /** + * Get a query for fetching a book with it's children. + */ + protected function bookFetchQuery(): Builder + { + return Book::query()->withTrashed() + ->select(['id', 'restricted', 'owned_by'])->with([ + 'chapters' => function ($query) { + $query->withTrashed()->select(['id', 'restricted', 'owned_by', 'book_id']); + }, + 'pages' => function ($query) { + $query->withTrashed()->select(['id', 'restricted', 'owned_by', 'book_id', 'chapter_id']); + }, + ]); + } + + /** + * Build joint permissions for the given shelf and role combinations. + * + * @throws Throwable + */ + protected function buildJointPermissionsForShelves(EloquentCollection $shelves, array $roles, bool $deleteOld = false) + { + if ($deleteOld) { + $this->deleteManyJointPermissionsForEntities($shelves->all()); + } + $this->createManyJointPermissions($shelves->all(), $roles); + } + + /** + * Build joint permissions for the given book and role combinations. + * + * @throws Throwable + */ + protected function buildJointPermissionsForBooks(EloquentCollection $books, array $roles, bool $deleteOld = false) + { + $entities = clone $books; + + /** @var Book $book */ + foreach ($books->all() as $book) { + foreach ($book->getRelation('chapters') as $chapter) { + $entities->push($chapter); + } + foreach ($book->getRelation('pages') as $page) { + $entities->push($page); + } + } + + if ($deleteOld) { + $this->deleteManyJointPermissionsForEntities($entities->all()); + } + + $this->createManyJointPermissions($entities->all(), $roles); + } + + /** + * Rebuild the entity jointPermissions for a particular entity. + * + * @throws Throwable + */ + public function buildJointPermissionsForEntity(Entity $entity) + { + $entities = [$entity]; + if ($entity instanceof Book) { + $books = $this->bookFetchQuery()->where('id', '=', $entity->id)->get(); + $this->buildJointPermissionsForBooks($books, Role::query()->with('permissions')->get()->all(), true); + + return; + } + + /** @var BookChild $entity */ + if ($entity->book) { + $entities[] = $entity->book; + } + + if ($entity instanceof Page && $entity->chapter_id) { + $entities[] = $entity->chapter; + } + + if ($entity instanceof Chapter) { + foreach ($entity->pages as $page) { + $entities[] = $page; + } + } + + $this->buildJointPermissionsForEntities($entities); + } + + /** + * Rebuild the entity jointPermissions for a collection of entities. + * + * @throws Throwable + */ + protected function buildJointPermissionsForEntities(array $entities) + { + $roles = Role::query()->get()->values()->all(); + $this->deleteManyJointPermissionsForEntities($entities); + $this->createManyJointPermissions($entities, $roles); + } + + /** + * Build the entity jointPermissions for a particular role. + */ + public function buildJointPermissionForRole(Role $role) + { + $roles = [$role]; + $role->jointPermissions()->delete(); + + // Chunk through all books + $this->bookFetchQuery()->chunk(20, function ($books) use ($roles) { + $this->buildJointPermissionsForBooks($books, $roles); + }); + + // Chunk through all bookshelves + Bookshelf::query()->select(['id', 'restricted', 'owned_by']) + ->chunk(50, function ($shelves) use ($roles) { + $this->buildJointPermissionsForShelves($shelves, $roles); + }); + } + + /** + * Delete all the entity jointPermissions for a list of entities. + * + * @param Entity[] $entities + * + * @throws Throwable + */ + protected function deleteManyJointPermissionsForEntities(array $entities) + { + $idsByType = $this->entitiesToTypeIdMap($entities); + + DB::transaction(function () use ($idsByType) { + foreach ($idsByType as $type => $ids) { + foreach (array_chunk($ids, 1000) as $idChunk) { + DB::table('joint_permissions') + ->where('entity_type', '=', $type) + ->whereIn('entity_id', $idChunk) + ->delete(); + } + } + }); + } + + /** + * Create & Save entity jointPermissions for many entities and roles. + * + * @param Entity[] $entities + * @param Role[] $roles + * + * @throws Throwable + */ + protected function createManyJointPermissions(array $entities, array $roles) + { + $this->readyEntityCache($entities); + $jointPermissions = []; + + // Create a mapping of entity restricted statuses + $entityRestrictedMap = []; + foreach ($entities as $entity) { + $entityRestrictedMap[$entity->getMorphClass() . ':' . $entity->getRawAttribute('id')] = boolval($entity->getRawAttribute('restricted')); + } + + // Fetch related entity permissions + $permissions = $this->getEntityPermissionsForEntities($entities); + + // Create a mapping of explicit entity permissions + $permissionMap = []; + foreach ($permissions as $permission) { + $key = $permission->restrictable_type . ':' . $permission->restrictable_id . ':' . $permission->role_id . ':' . $permission->action; + $isRestricted = $entityRestrictedMap[$permission->restrictable_type . ':' . $permission->restrictable_id]; + $permissionMap[$key] = $isRestricted; + } + + // Create a mapping of role permissions + $rolePermissionMap = []; + foreach ($roles as $role) { + foreach ($role->permissions as $permission) { + $rolePermissionMap[$role->getRawAttribute('id') . ':' . $permission->getRawAttribute('name')] = true; + } + } + + // Create Joint Permission Data + foreach ($entities as $entity) { + foreach ($roles as $role) { + foreach ($this->getActions($entity) as $action) { + $jointPermissions[] = $this->createJointPermissionData($entity, $role, $action, $permissionMap, $rolePermissionMap); + } + } + } + + DB::transaction(function () use ($jointPermissions) { + foreach (array_chunk($jointPermissions, 1000) as $jointPermissionChunk) { + DB::table('joint_permissions')->insert($jointPermissionChunk); + } + }); + } + + /** + * From the given entity list, provide back a mapping of entity types to + * the ids of that given type. The type used is the DB morph class. + * @param Entity[] $entities + * @return array + */ + protected function entitiesToTypeIdMap(array $entities): array + { + $idsByType = []; + + foreach ($entities as $entity) { + $type = $entity->getMorphClass(); + + if (!isset($idsByType[$type])) { + $idsByType[$type] = []; + } + + $idsByType[$type][] = $entity->getRawAttribute('id'); + } + + return $idsByType; + } + + /** + * Get the entity permissions for all the given entities + * @param Entity[] $entities + * @return EloquentCollection + */ + protected function getEntityPermissionsForEntities(array $entities) + { + $idsByType = $this->entitiesToTypeIdMap($entities); + $permissionFetch = EntityPermission::query(); + + foreach ($idsByType as $type => $ids) { + $permissionFetch->orWhere(function (Builder $query) use ($type, $ids) { + $query->where('restrictable_type', '=', $type)->whereIn('restrictable_id', $ids); + }); + } + + return $permissionFetch->get(); + } + + /** + * Get the actions related to an entity. + */ + protected function getActions(Entity $entity): array + { + $baseActions = ['view', 'update', 'delete']; + if ($entity instanceof Chapter || $entity instanceof Book) { + $baseActions[] = 'page-create'; + } + if ($entity instanceof Book) { + $baseActions[] = 'chapter-create'; + } + + return $baseActions; + } + + /** + * Create entity permission data for an entity and role + * for a particular action. + */ + protected function createJointPermissionData(Entity $entity, Role $role, string $action, array $permissionMap, array $rolePermissionMap): array + { + $permissionPrefix = (strpos($action, '-') === false ? ($entity->getType() . '-') : '') . $action; + $roleHasPermission = isset($rolePermissionMap[$role->getRawAttribute('id') . ':' . $permissionPrefix . '-all']); + $roleHasPermissionOwn = isset($rolePermissionMap[$role->getRawAttribute('id') . ':' . $permissionPrefix . '-own']); + $explodedAction = explode('-', $action); + $restrictionAction = end($explodedAction); + + if ($role->system_name === 'admin') { + return $this->createJointPermissionDataArray($entity, $role, $action, true, true); + } + + if ($entity->restricted) { + $hasAccess = $this->mapHasActiveRestriction($permissionMap, $entity, $role, $restrictionAction); + + return $this->createJointPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess); + } + + if ($entity instanceof Book || $entity instanceof Bookshelf) { + return $this->createJointPermissionDataArray($entity, $role, $action, $roleHasPermission, $roleHasPermissionOwn); + } + + // For chapters and pages, Check if explicit permissions are set on the Book. + $book = $this->getBook($entity->book_id); + $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $book, $role, $restrictionAction); + $hasPermissiveAccessToParents = !$book->restricted; + + // For pages with a chapter, Check if explicit permissions are set on the Chapter + if ($entity instanceof Page && intval($entity->chapter_id) !== 0) { + $chapter = $this->getChapter($entity->chapter_id); + $hasPermissiveAccessToParents = $hasPermissiveAccessToParents && !$chapter->restricted; + if ($chapter->restricted) { + $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $chapter, $role, $restrictionAction); + } + } + + return $this->createJointPermissionDataArray( + $entity, + $role, + $action, + ($hasExplicitAccessToParents || ($roleHasPermission && $hasPermissiveAccessToParents)), + ($hasExplicitAccessToParents || ($roleHasPermissionOwn && $hasPermissiveAccessToParents)) + ); + } + + /** + * Check for an active restriction in an entity map. + */ + protected function mapHasActiveRestriction(array $entityMap, Entity $entity, Role $role, string $action): bool + { + $key = $entity->getMorphClass() . ':' . $entity->getRawAttribute('id') . ':' . $role->getRawAttribute('id') . ':' . $action; + + return $entityMap[$key] ?? false; + } + + /** + * Create an array of data with the information of an entity jointPermissions. + * Used to build data for bulk insertion. + */ + protected function createJointPermissionDataArray(Entity $entity, Role $role, string $action, bool $permissionAll, bool $permissionOwn): array + { + return [ + 'action' => $action, + 'entity_id' => $entity->getRawAttribute('id'), + 'entity_type' => $entity->getMorphClass(), + 'has_permission' => $permissionAll, + 'has_permission_own' => $permissionOwn, + 'owned_by' => $entity->getRawAttribute('owned_by'), + 'role_id' => $role->getRawAttribute('id'), + ]; + } + +} \ No newline at end of file diff --git a/app/Auth/Permissions/PermissionService.php b/app/Auth/Permissions/PermissionService.php index 1363fe86e..bcd4a3675 100644 --- a/app/Auth/Permissions/PermissionService.php +++ b/app/Auth/Permissions/PermissionService.php @@ -4,20 +4,13 @@ namespace BookStack\Auth\Permissions; use BookStack\Auth\Role; use BookStack\Auth\User; -use BookStack\Entities\Models\Book; -use BookStack\Entities\Models\BookChild; -use BookStack\Entities\Models\Bookshelf; -use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Page; use BookStack\Model; use BookStack\Traits\HasCreatorAndUpdater; use BookStack\Traits\HasOwner; -use Illuminate\Database\Connection; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Database\Eloquent\Collection as EloquentCollection; use Illuminate\Database\Query\Builder as QueryBuilder; -use Throwable; class PermissionService { @@ -31,77 +24,6 @@ class PermissionService */ protected $currentUserModel = null; - /** - * @var Connection - */ - protected $db; - - /** - * @var array> - */ - protected $entityCache; - - /** - * PermissionService constructor. - */ - public function __construct(Connection $db) - { - $this->db = $db; - } - - /** - * Set the database connection. - */ - public function setConnection(Connection $connection) - { - $this->db = $connection; - } - - /** - * Prepare the local entity cache and ensure it's empty. - * - * @param Entity[] $entities - */ - protected function readyEntityCache(array $entities = []) - { - $this->entityCache = []; - - foreach ($entities as $entity) { - $class = get_class($entity); - - if (!isset($this->entityCache[$class])) { - $this->entityCache[$class] = []; - } - - $this->entityCache[$class][$entity->getRawAttribute('id')] = $entity; - } - } - - /** - * Get a book via ID, Checks local cache. - */ - protected function getBook(int $bookId): ?Book - { - if ($this->entityCache[Book::class][$bookId] ?? false) { - return $this->entityCache[Book::class][$bookId]; - } - - return Book::query()->withTrashed()->find($bookId); - } - - /** - * Get a chapter via ID, Checks local cache. - */ - protected function getChapter(int $chapterId): ?Chapter - { - if ($this->entityCache[Chapter::class][$chapterId] ?? false) { - return $this->entityCache[Chapter::class][$chapterId]; - } - - return Chapter::query() - ->withTrashed() - ->find($chapterId); - } /** * Get the roles for the current logged in user. @@ -121,380 +43,6 @@ class PermissionService return $this->userRoles; } - /** - * Re-generate all entity permission from scratch. - */ - public function buildJointPermissions() - { - JointPermission::query()->truncate(); - $this->readyEntityCache(); - - // Get all roles (Should be the most limited dimension) - $roles = Role::query()->with('permissions')->get()->all(); - - // Chunk through all books - $this->bookFetchQuery()->chunk(5, function (EloquentCollection $books) use ($roles) { - $this->buildJointPermissionsForBooks($books, $roles); - }); - - // Chunk through all bookshelves - Bookshelf::query()->withTrashed()->select(['id', 'restricted', 'owned_by']) - ->chunk(50, function (EloquentCollection $shelves) use ($roles) { - $this->buildJointPermissionsForShelves($shelves, $roles); - }); - } - - /** - * Get a query for fetching a book with it's children. - */ - protected function bookFetchQuery(): Builder - { - return Book::query()->withTrashed() - ->select(['id', 'restricted', 'owned_by'])->with([ - 'chapters' => function ($query) { - $query->withTrashed()->select(['id', 'restricted', 'owned_by', 'book_id']); - }, - 'pages' => function ($query) { - $query->withTrashed()->select(['id', 'restricted', 'owned_by', 'book_id', 'chapter_id']); - }, - ]); - } - - /** - * Build joint permissions for the given shelf and role combinations. - * - * @throws Throwable - */ - protected function buildJointPermissionsForShelves(EloquentCollection $shelves, array $roles, bool $deleteOld = false) - { - if ($deleteOld) { - $this->deleteManyJointPermissionsForEntities($shelves->all()); - } - $this->createManyJointPermissions($shelves->all(), $roles); - } - - /** - * Build joint permissions for the given book and role combinations. - * - * @throws Throwable - */ - protected function buildJointPermissionsForBooks(EloquentCollection $books, array $roles, bool $deleteOld = false) - { - $entities = clone $books; - - /** @var Book $book */ - foreach ($books->all() as $book) { - foreach ($book->getRelation('chapters') as $chapter) { - $entities->push($chapter); - } - foreach ($book->getRelation('pages') as $page) { - $entities->push($page); - } - } - - if ($deleteOld) { - $this->deleteManyJointPermissionsForEntities($entities->all()); - } - $this->createManyJointPermissions($entities->all(), $roles); - } - - /** - * Rebuild the entity jointPermissions for a particular entity. - * - * @throws Throwable - */ - public function buildJointPermissionsForEntity(Entity $entity) - { - $entities = [$entity]; - if ($entity instanceof Book) { - $books = $this->bookFetchQuery()->where('id', '=', $entity->id)->get(); - $this->buildJointPermissionsForBooks($books, Role::query()->with('permissions')->get()->all(), true); - - return; - } - - /** @var BookChild $entity */ - if ($entity->book) { - $entities[] = $entity->book; - } - - if ($entity instanceof Page && $entity->chapter_id) { - $entities[] = $entity->chapter; - } - - if ($entity instanceof Chapter) { - foreach ($entity->pages as $page) { - $entities[] = $page; - } - } - - $this->buildJointPermissionsForEntities($entities); - } - - /** - * Rebuild the entity jointPermissions for a collection of entities. - * - * @throws Throwable - */ - public function buildJointPermissionsForEntities(array $entities) - { - $roles = Role::query()->get()->values()->all(); - $this->deleteManyJointPermissionsForEntities($entities); - $this->createManyJointPermissions($entities, $roles); - } - - /** - * Build the entity jointPermissions for a particular role. - */ - public function buildJointPermissionForRole(Role $role) - { - $roles = [$role]; - $this->deleteManyJointPermissionsForRoles($roles); - - // Chunk through all books - $this->bookFetchQuery()->chunk(20, function ($books) use ($roles) { - $this->buildJointPermissionsForBooks($books, $roles); - }); - - // Chunk through all bookshelves - Bookshelf::query()->select(['id', 'restricted', 'owned_by']) - ->chunk(50, function ($shelves) use ($roles) { - $this->buildJointPermissionsForShelves($shelves, $roles); - }); - } - - /** - * Delete the entity jointPermissions attached to a particular role. - */ - public function deleteJointPermissionsForRole(Role $role) - { - $this->deleteManyJointPermissionsForRoles([$role]); - } - - /** - * Delete all the entity jointPermissions for a list of entities. - * - * @param Role[] $roles - */ - protected function deleteManyJointPermissionsForRoles($roles) - { - $roleIds = array_map(function ($role) { - return $role->id; - }, $roles); - JointPermission::query()->whereIn('role_id', $roleIds)->delete(); - } - - /** - * Delete all the entity jointPermissions for a list of entities. - * - * @param Entity[] $entities - * - * @throws Throwable - */ - protected function deleteManyJointPermissionsForEntities(array $entities) - { - $idsByType = $this->entitiesToTypeIdMap($entities); - - $this->db->transaction(function () use ($idsByType) { - foreach ($idsByType as $type => $ids) { - foreach (array_chunk($ids, 1000) as $idChunk) { - $this->db->table('joint_permissions') - ->where('entity_type', '=', $type) - ->whereIn('entity_id', $idChunk) - ->delete(); - } - } - }); - } - - /** - * Create & Save entity jointPermissions for many entities and roles. - * - * @param Entity[] $entities - * @param Role[] $roles - * - * @throws Throwable - */ - protected function createManyJointPermissions(array $entities, array $roles) - { - $this->readyEntityCache($entities); - $jointPermissions = []; - - // Create a mapping of entity restricted statuses - $entityRestrictedMap = []; - foreach ($entities as $entity) { - $entityRestrictedMap[$entity->getMorphClass() . ':' . $entity->getRawAttribute('id')] = boolval($entity->getRawAttribute('restricted')); - } - - // Fetch related entity permissions - $permissions = $this->getEntityPermissionsForEntities($entities); - - // Create a mapping of explicit entity permissions - $permissionMap = []; - foreach ($permissions as $permission) { - $key = $permission->restrictable_type . ':' . $permission->restrictable_id . ':' . $permission->role_id . ':' . $permission->action; - $isRestricted = $entityRestrictedMap[$permission->restrictable_type . ':' . $permission->restrictable_id]; - $permissionMap[$key] = $isRestricted; - } - - // Create a mapping of role permissions - $rolePermissionMap = []; - foreach ($roles as $role) { - foreach ($role->permissions as $permission) { - $rolePermissionMap[$role->getRawAttribute('id') . ':' . $permission->getRawAttribute('name')] = true; - } - } - - // Create Joint Permission Data - foreach ($entities as $entity) { - foreach ($roles as $role) { - foreach ($this->getActions($entity) as $action) { - $jointPermissions[] = $this->createJointPermissionData($entity, $role, $action, $permissionMap, $rolePermissionMap); - } - } - } - - $this->db->transaction(function () use ($jointPermissions) { - foreach (array_chunk($jointPermissions, 1000) as $jointPermissionChunk) { - $this->db->table('joint_permissions')->insert($jointPermissionChunk); - } - }); - } - - /** - * From the given entity list, provide back a mapping of entity types to - * the ids of that given type. The type used is the DB morph class. - * @param Entity[] $entities - * @return array - */ - protected function entitiesToTypeIdMap(array $entities): array - { - $idsByType = []; - - foreach ($entities as $entity) { - $type = $entity->getMorphClass(); - - if (!isset($idsByType[$type])) { - $idsByType[$type] = []; - } - - $idsByType[$type][] = $entity->getRawAttribute('id'); - } - - return $idsByType; - } - - /** - * Get the entity permissions for all the given entities - * @param Entity[] $entities - * @return EloquentCollection - */ - protected function getEntityPermissionsForEntities(array $entities) - { - $idsByType = $this->entitiesToTypeIdMap($entities); - $permissionFetch = EntityPermission::query(); - - foreach ($idsByType as $type => $ids) { - $permissionFetch->orWhere(function (Builder $query) use ($type, $ids) { - $query->where('restrictable_type', '=', $type)->whereIn('restrictable_id', $ids); - }); - } - - return $permissionFetch->get(); - } - - /** - * Get the actions related to an entity. - */ - protected function getActions(Entity $entity): array - { - $baseActions = ['view', 'update', 'delete']; - if ($entity instanceof Chapter || $entity instanceof Book) { - $baseActions[] = 'page-create'; - } - if ($entity instanceof Book) { - $baseActions[] = 'chapter-create'; - } - - return $baseActions; - } - - /** - * Create entity permission data for an entity and role - * for a particular action. - */ - protected function createJointPermissionData(Entity $entity, Role $role, string $action, array $permissionMap, array $rolePermissionMap): array - { - $permissionPrefix = (strpos($action, '-') === false ? ($entity->getType() . '-') : '') . $action; - $roleHasPermission = isset($rolePermissionMap[$role->getRawAttribute('id') . ':' . $permissionPrefix . '-all']); - $roleHasPermissionOwn = isset($rolePermissionMap[$role->getRawAttribute('id') . ':' . $permissionPrefix . '-own']); - $explodedAction = explode('-', $action); - $restrictionAction = end($explodedAction); - - if ($role->system_name === 'admin') { - return $this->createJointPermissionDataArray($entity, $role, $action, true, true); - } - - if ($entity->restricted) { - $hasAccess = $this->mapHasActiveRestriction($permissionMap, $entity, $role, $restrictionAction); - - return $this->createJointPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess); - } - - if ($entity instanceof Book || $entity instanceof Bookshelf) { - return $this->createJointPermissionDataArray($entity, $role, $action, $roleHasPermission, $roleHasPermissionOwn); - } - - // For chapters and pages, Check if explicit permissions are set on the Book. - $book = $this->getBook($entity->book_id); - $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $book, $role, $restrictionAction); - $hasPermissiveAccessToParents = !$book->restricted; - - // For pages with a chapter, Check if explicit permissions are set on the Chapter - if ($entity instanceof Page && intval($entity->chapter_id) !== 0) { - $chapter = $this->getChapter($entity->chapter_id); - $hasPermissiveAccessToParents = $hasPermissiveAccessToParents && !$chapter->restricted; - if ($chapter->restricted) { - $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $chapter, $role, $restrictionAction); - } - } - - return $this->createJointPermissionDataArray( - $entity, - $role, - $action, - ($hasExplicitAccessToParents || ($roleHasPermission && $hasPermissiveAccessToParents)), - ($hasExplicitAccessToParents || ($roleHasPermissionOwn && $hasPermissiveAccessToParents)) - ); - } - - /** - * Check for an active restriction in an entity map. - */ - protected function mapHasActiveRestriction(array $entityMap, Entity $entity, Role $role, string $action): bool - { - $key = $entity->getMorphClass() . ':' . $entity->getRawAttribute('id') . ':' . $role->getRawAttribute('id') . ':' . $action; - - return $entityMap[$key] ?? false; - } - - /** - * Create an array of data with the information of an entity jointPermissions. - * Used to build data for bulk insertion. - */ - protected function createJointPermissionDataArray(Entity $entity, Role $role, string $action, bool $permissionAll, bool $permissionOwn): array - { - return [ - 'role_id' => $role->getRawAttribute('id'), - 'entity_id' => $entity->getRawAttribute('id'), - 'entity_type' => $entity->getMorphClass(), - 'action' => $action, - 'has_permission' => $permissionAll, - 'has_permission_own' => $permissionOwn, - 'owned_by' => $entity->getRawAttribute('owned_by'), - ]; - } - /** * Checks if an entity has a restriction set upon it. * diff --git a/app/Auth/Permissions/PermissionsRepo.php b/app/Auth/Permissions/PermissionsRepo.php index 988146700..0527875ae 100644 --- a/app/Auth/Permissions/PermissionsRepo.php +++ b/app/Auth/Permissions/PermissionsRepo.php @@ -11,20 +11,15 @@ use Illuminate\Database\Eloquent\Collection; class PermissionsRepo { - protected $permission; - protected $role; - protected $permissionService; - + protected JointPermissionBuilder $permissionBuilder; protected $systemRoles = ['admin', 'public']; /** * PermissionsRepo constructor. */ - public function __construct(RolePermission $permission, Role $role, PermissionService $permissionService) + public function __construct(JointPermissionBuilder $permissionBuilder) { - $this->permission = $permission; - $this->role = $role; - $this->permissionService = $permissionService; + $this->permissionBuilder = $permissionBuilder; } /** @@ -32,7 +27,7 @@ class PermissionsRepo */ public function getAllRoles(): Collection { - return $this->role->all(); + return Role::query()->all(); } /** @@ -40,7 +35,7 @@ class PermissionsRepo */ public function getAllRolesExcept(Role $role): Collection { - return $this->role->where('id', '!=', $role->id)->get(); + return Role::query()->where('id', '!=', $role->id)->get(); } /** @@ -48,7 +43,7 @@ class PermissionsRepo */ public function getRoleById($id): Role { - return $this->role->newQuery()->findOrFail($id); + return Role::query()->findOrFail($id); } /** @@ -56,13 +51,14 @@ class PermissionsRepo */ public function saveNewRole(array $roleData): Role { - $role = $this->role->newInstance($roleData); + $role = new Role($roleData); $role->mfa_enforced = ($roleData['mfa_enforced'] ?? 'false') === 'true'; $role->save(); $permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : []; $this->assignRolePermissions($role, $permissions); - $this->permissionService->buildJointPermissionForRole($role); + $this->permissionBuilder->buildJointPermissionForRole($role); + Activity::add(ActivityType::ROLE_CREATE, $role); return $role; @@ -74,8 +70,7 @@ class PermissionsRepo */ public function updateRole($roleId, array $roleData) { - /** @var Role $role */ - $role = $this->role->newQuery()->findOrFail($roleId); + $role = $this->getRoleById($roleId); $permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : []; if ($role->system_name === 'admin') { @@ -93,12 +88,13 @@ class PermissionsRepo $role->fill($roleData); $role->mfa_enforced = ($roleData['mfa_enforced'] ?? 'false') === 'true'; $role->save(); - $this->permissionService->buildJointPermissionForRole($role); + $this->permissionBuilder->buildJointPermissionForRole($role); + Activity::add(ActivityType::ROLE_UPDATE, $role); } /** - * Assign an list of permission names to an role. + * Assign a list of permission names to a role. */ protected function assignRolePermissions(Role $role, array $permissionNameArray = []) { @@ -106,7 +102,7 @@ class PermissionsRepo $permissionNameArray = array_values($permissionNameArray); if ($permissionNameArray) { - $permissions = $this->permission->newQuery() + $permissions = EntityPermission::query() ->whereIn('name', $permissionNameArray) ->pluck('id') ->toArray(); @@ -126,8 +122,7 @@ class PermissionsRepo */ public function deleteRole($roleId, $migrateRoleId) { - /** @var Role $role */ - $role = $this->role->newQuery()->findOrFail($roleId); + $role = $this->getRoleById($roleId); // Prevent deleting admin role or default registration role. if ($role->system_name && in_array($role->system_name, $this->systemRoles)) { @@ -137,14 +132,14 @@ class PermissionsRepo } if ($migrateRoleId) { - $newRole = $this->role->newQuery()->find($migrateRoleId); + $newRole = Role::query()->find($migrateRoleId); if ($newRole) { $users = $role->users()->pluck('id')->toArray(); $newRole->users()->sync($users); } } - $this->permissionService->deleteJointPermissionsForRole($role); + $role->jointPermissions()->delete(); Activity::add(ActivityType::ROLE_DELETE, $role); $role->delete(); } diff --git a/app/Console/Commands/RegeneratePermissions.php b/app/Console/Commands/RegeneratePermissions.php index 4fde08e6b..558ae9fea 100644 --- a/app/Console/Commands/RegeneratePermissions.php +++ b/app/Console/Commands/RegeneratePermissions.php @@ -2,8 +2,9 @@ namespace BookStack\Console\Commands; -use BookStack\Auth\Permissions\PermissionService; +use BookStack\Auth\Permissions\JointPermissionBuilder; use Illuminate\Console\Command; +use Illuminate\Support\Facades\DB; class RegeneratePermissions extends Command { @@ -21,19 +22,14 @@ class RegeneratePermissions extends Command */ protected $description = 'Regenerate all system permissions'; - /** - * The service to handle the permission system. - * - * @var PermissionService - */ - protected $permissionService; + protected JointPermissionBuilder $permissionBuilder; /** * Create a new command instance. */ - public function __construct(PermissionService $permissionService) + public function __construct(JointPermissionBuilder $permissionBuilder) { - $this->permissionService = $permissionService; + $this->permissionBuilder = $permissionBuilder; parent::__construct(); } @@ -44,15 +40,15 @@ class RegeneratePermissions extends Command */ public function handle() { - $connection = \DB::getDefaultConnection(); - if ($this->option('database') !== null) { - \DB::setDefaultConnection($this->option('database')); - $this->permissionService->setConnection(\DB::connection($this->option('database'))); + $connection = DB::getDefaultConnection(); + + if ($this->hasOption('database')) { + DB::setDefaultConnection($this->option('database')); } - $this->permissionService->buildJointPermissions(); + $this->permissionBuilder->buildJointPermissions(); - \DB::setDefaultConnection($connection); + DB::setDefaultConnection($connection); $this->comment('Permissions regenerated'); } } diff --git a/database/seeders/DummyContentSeeder.php b/database/seeders/DummyContentSeeder.php index d54732b26..cb9987df7 100644 --- a/database/seeders/DummyContentSeeder.php +++ b/database/seeders/DummyContentSeeder.php @@ -3,7 +3,7 @@ namespace Database\Seeders; use BookStack\Api\ApiToken; -use BookStack\Auth\Permissions\PermissionService; +use BookStack\Auth\Permissions\JointPermissionBuilder; use BookStack\Auth\Permissions\RolePermission; use BookStack\Auth\Role; use BookStack\Auth\User; @@ -69,7 +69,7 @@ class DummyContentSeeder extends Seeder ]); $token->save(); - app(PermissionService::class)->buildJointPermissions(); + app(JointPermissionBuilder::class)->buildJointPermissions(); app(SearchIndex::class)->indexAllEntities(); } } diff --git a/database/seeders/LargeContentSeeder.php b/database/seeders/LargeContentSeeder.php index dd9165978..041b3161a 100644 --- a/database/seeders/LargeContentSeeder.php +++ b/database/seeders/LargeContentSeeder.php @@ -2,7 +2,7 @@ namespace Database\Seeders; -use BookStack\Auth\Permissions\PermissionService; +use BookStack\Auth\Permissions\JointPermissionBuilder; use BookStack\Auth\Role; use BookStack\Auth\User; use BookStack\Entities\Models\Book; @@ -35,7 +35,7 @@ class LargeContentSeeder extends Seeder $largeBook->chapters()->saveMany($chapters); $all = array_merge([$largeBook], array_values($pages->all()), array_values($chapters->all())); - app()->make(PermissionService::class)->buildJointPermissionsForEntity($largeBook); + app()->make(JointPermissionBuilder::class)->buildJointPermissionsForEntity($largeBook); app()->make(SearchIndex::class)->indexEntities($all); } } diff --git a/tests/PublicActionTest.php b/tests/PublicActionTest.php index 499c0c9f9..745fa7660 100644 --- a/tests/PublicActionTest.php +++ b/tests/PublicActionTest.php @@ -2,7 +2,7 @@ namespace Tests; -use BookStack\Auth\Permissions\PermissionService; +use BookStack\Auth\Permissions\JointPermissionBuilder; use BookStack\Auth\Permissions\RolePermission; use BookStack\Auth\Role; use BookStack\Auth\User; @@ -89,7 +89,7 @@ class PublicActionTest extends TestCase foreach (RolePermission::all() as $perm) { $publicRole->attachPermission($perm); } - $this->app[PermissionService::class]->buildJointPermissionForRole($publicRole); + $this->app->make(JointPermissionBuilder::class)->buildJointPermissionForRole($publicRole); /** @var Chapter $chapter */ $chapter = Chapter::query()->first(); diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php index ce57d56f5..2d05b0520 100644 --- a/tests/SharedTestHelpers.php +++ b/tests/SharedTestHelpers.php @@ -2,6 +2,7 @@ namespace Tests; +use BookStack\Auth\Permissions\JointPermissionBuilder; use BookStack\Auth\Permissions\PermissionService; use BookStack\Auth\Permissions\PermissionsRepo; use BookStack\Auth\Permissions\RolePermission; @@ -176,7 +177,7 @@ trait SharedTestHelpers $entity->save(); $entity->load('permissions'); - $this->app[PermissionService::class]->buildJointPermissionsForEntity($entity); + $this->app->make(JointPermissionBuilder::class)->buildJointPermissionsForEntity($entity); $entity->load('jointPermissions'); } @@ -196,7 +197,7 @@ trait SharedTestHelpers */ protected function removePermissionFromUser(User $user, string $permissionName) { - $permissionService = app()->make(PermissionService::class); + $permissionBuilder = app()->make(JointPermissionBuilder::class); /** @var RolePermission $permission */ $permission = RolePermission::query()->where('name', '=', $permissionName)->firstOrFail(); @@ -208,7 +209,7 @@ trait SharedTestHelpers /** @var Role $role */ foreach ($roles as $role) { $role->detachPermission($permission); - $permissionService->buildJointPermissionForRole($role); + $permissionBuilder->buildJointPermissionForRole($role); } $user->clearPermissionCache(); @@ -241,8 +242,8 @@ trait SharedTestHelpers $book = Book::factory()->create($userAttrs); $chapter = Chapter::factory()->create(array_merge(['book_id' => $book->id], $userAttrs)); $page = Page::factory()->create(array_merge(['book_id' => $book->id, 'chapter_id' => $chapter->id], $userAttrs)); - $restrictionService = $this->app[PermissionService::class]; - $restrictionService->buildJointPermissionsForEntity($book); + + $this->app->make(JointPermissionBuilder::class)->buildJointPermissionsForEntity($book); return compact('book', 'chapter', 'page'); } From 943cb7810b51999dae00c179975416c6954cfe60 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Jul 2022 20:02:15 +0100 Subject: [PATCH 022/246] New translations activities.php (Croatian) --- resources/lang/hr/activities.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/lang/hr/activities.php b/resources/lang/hr/activities.php index 79f4af04e..65ab1594f 100644 --- a/resources/lang/hr/activities.php +++ b/resources/lang/hr/activities.php @@ -7,13 +7,13 @@ return [ // Pages 'page_create' => 'stvorena stranica', - 'page_create_notification' => 'Page successfully created', + 'page_create_notification' => 'Stranica uspješno kreirana', 'page_update' => 'ažurirana stranica', - 'page_update_notification' => 'Page successfully updated', + 'page_update_notification' => 'Stranica uspješno ažurirana', 'page_delete' => 'izbrisana stranica', - 'page_delete_notification' => 'Page successfully deleted', + 'page_delete_notification' => 'Stranica je uspješno izbrisana', 'page_restore' => 'obnovljena stranica', - 'page_restore_notification' => 'Page successfully restored', + 'page_restore_notification' => 'Stranica je uspješno obnovljena', 'page_move' => 'premještena stranica', // Chapters From b0a4d3d0597dcdbe2cd15261ecc874f2d5a7f666 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Jul 2022 20:15:41 +0100 Subject: [PATCH 023/246] Renamed and cleaned up existing permission service classes use --- app/Actions/ActivityLogger.php | 8 - app/Actions/ActivityQueries.php | 12 +- app/Actions/TagRepo.php | 15 +- .../Permissions/JointPermissionBuilder.php | 164 ++++++++---------- ...onService.php => PermissionApplicator.php} | 5 +- app/Auth/Permissions/PermissionsRepo.php | 8 +- app/Config/app.php | 1 - .../Commands/RegeneratePermissions.php | 4 +- app/Entities/Models/Entity.php | 12 +- app/Entities/Models/Page.php | 4 +- app/Entities/Queries/EntityQuery.php | 6 +- app/Entities/Tools/SearchRunner.php | 20 +-- app/Facades/Permissions.php | 18 -- app/Providers/CustomFacadeProvider.php | 10 +- app/Uploads/Attachment.php | 6 +- app/Uploads/ImageRepo.php | 12 +- app/helpers.php | 10 +- database/seeders/DummyContentSeeder.php | 2 +- database/seeders/LargeContentSeeder.php | 2 +- .../RegeneratePermissionsCommandTest.php | 5 +- tests/PublicActionTest.php | 2 +- tests/SharedTestHelpers.php | 8 +- 22 files changed, 140 insertions(+), 194 deletions(-) rename app/Auth/Permissions/{PermissionService.php => PermissionApplicator.php} (99%) delete mode 100644 app/Facades/Permissions.php diff --git a/app/Actions/ActivityLogger.php b/app/Actions/ActivityLogger.php index 0d1391b43..eea5409fb 100644 --- a/app/Actions/ActivityLogger.php +++ b/app/Actions/ActivityLogger.php @@ -2,7 +2,6 @@ namespace BookStack\Actions; -use BookStack\Auth\Permissions\PermissionService; use BookStack\Entities\Models\Entity; use BookStack\Interfaces\Loggable; use Illuminate\Database\Eloquent\Builder; @@ -10,13 +9,6 @@ use Illuminate\Support\Facades\Log; class ActivityLogger { - protected $permissionService; - - public function __construct(PermissionService $permissionService) - { - $this->permissionService = $permissionService; - } - /** * Add a generic activity event to the database. * diff --git a/app/Actions/ActivityQueries.php b/app/Actions/ActivityQueries.php index f900fbb05..0b8cd3b5e 100644 --- a/app/Actions/ActivityQueries.php +++ b/app/Actions/ActivityQueries.php @@ -2,7 +2,7 @@ namespace BookStack\Actions; -use BookStack\Auth\Permissions\PermissionService; +use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Auth\User; use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Chapter; @@ -13,11 +13,11 @@ use Illuminate\Database\Eloquent\Relations\Relation; class ActivityQueries { - protected $permissionService; + protected PermissionApplicator $permissions; - public function __construct(PermissionService $permissionService) + public function __construct(PermissionApplicator $permissions) { - $this->permissionService = $permissionService; + $this->permissions = $permissions; } /** @@ -25,7 +25,7 @@ class ActivityQueries */ public function latest(int $count = 20, int $page = 0): array { - $activityList = $this->permissionService + $activityList = $this->permissions ->filterRestrictedEntityRelations(Activity::query(), 'activities', 'entity_id', 'entity_type') ->orderBy('created_at', 'desc') ->with(['user', 'entity']) @@ -78,7 +78,7 @@ class ActivityQueries */ public function userActivity(User $user, int $count = 20, int $page = 0): array { - $activityList = $this->permissionService + $activityList = $this->permissions ->filterRestrictedEntityRelations(Activity::query(), 'activities', 'entity_id', 'entity_type') ->orderBy('created_at', 'desc') ->where('user_id', '=', $user->id) diff --git a/app/Actions/TagRepo.php b/app/Actions/TagRepo.php index 8cf107601..c5807108e 100644 --- a/app/Actions/TagRepo.php +++ b/app/Actions/TagRepo.php @@ -2,7 +2,7 @@ namespace BookStack\Actions; -use BookStack\Auth\Permissions\PermissionService; +use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Entities\Models\Entity; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Collection; @@ -10,12 +10,11 @@ use Illuminate\Support\Facades\DB; class TagRepo { - protected $tag; - protected $permissionService; + protected PermissionApplicator $permissions; - public function __construct(PermissionService $ps) + public function __construct(PermissionApplicator $permissions) { - $this->permissionService = $ps; + $this->permissions = $permissions; } /** @@ -51,7 +50,7 @@ class TagRepo }); } - return $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); + return $this->permissions->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); } /** @@ -70,7 +69,7 @@ class TagRepo $query = $query->orderBy('count', 'desc')->take(50); } - $query = $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); + $query = $this->permissions->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); return $query->get(['name'])->pluck('name'); } @@ -96,7 +95,7 @@ class TagRepo $query = $query->where('name', '=', $tagName); } - $query = $this->permissionService->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); + $query = $this->permissions->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); return $query->get(['value'])->pluck('value'); } diff --git a/app/Auth/Permissions/JointPermissionBuilder.php b/app/Auth/Permissions/JointPermissionBuilder.php index c87560fe0..fbf77741a 100644 --- a/app/Auth/Permissions/JointPermissionBuilder.php +++ b/app/Auth/Permissions/JointPermissionBuilder.php @@ -20,6 +20,82 @@ class JointPermissionBuilder */ protected $entityCache; + /** + * Re-generate all entity permission from scratch. + */ + public function rebuildForAll() + { + JointPermission::query()->truncate(); + $this->readyEntityCache(); + + // Get all roles (Should be the most limited dimension) + $roles = Role::query()->with('permissions')->get()->all(); + + // Chunk through all books + $this->bookFetchQuery()->chunk(5, function (EloquentCollection $books) use ($roles) { + $this->buildJointPermissionsForBooks($books, $roles); + }); + + // Chunk through all bookshelves + Bookshelf::query()->withTrashed()->select(['id', 'restricted', 'owned_by']) + ->chunk(50, function (EloquentCollection $shelves) use ($roles) { + $this->createManyJointPermissions($shelves->all(), $roles); + }); + } + + /** + * Rebuild the entity jointPermissions for a particular entity. + * + * @throws Throwable + */ + public function rebuildForEntity(Entity $entity) + { + $entities = [$entity]; + if ($entity instanceof Book) { + $books = $this->bookFetchQuery()->where('id', '=', $entity->id)->get(); + $this->buildJointPermissionsForBooks($books, Role::query()->with('permissions')->get()->all(), true); + + return; + } + + /** @var BookChild $entity */ + if ($entity->book) { + $entities[] = $entity->book; + } + + if ($entity instanceof Page && $entity->chapter_id) { + $entities[] = $entity->chapter; + } + + if ($entity instanceof Chapter) { + foreach ($entity->pages as $page) { + $entities[] = $page; + } + } + + $this->buildJointPermissionsForEntities($entities); + } + + /** + * Build the entity jointPermissions for a particular role. + */ + public function rebuildForRole(Role $role) + { + $roles = [$role]; + $role->jointPermissions()->delete(); + + // Chunk through all books + $this->bookFetchQuery()->chunk(20, function ($books) use ($roles) { + $this->buildJointPermissionsForBooks($books, $roles); + }); + + // Chunk through all bookshelves + Bookshelf::query()->select(['id', 'restricted', 'owned_by']) + ->chunk(50, function ($shelves) use ($roles) { + $this->createManyJointPermissions($shelves->all(), $roles); + }); + } + /** * Prepare the local entity cache and ensure it's empty. * @@ -66,29 +142,6 @@ class JointPermissionBuilder ->find($chapterId); } - /** - * Re-generate all entity permission from scratch. - */ - public function buildJointPermissions() - { - JointPermission::query()->truncate(); - $this->readyEntityCache(); - - // Get all roles (Should be the most limited dimension) - $roles = Role::query()->with('permissions')->get()->all(); - - // Chunk through all books - $this->bookFetchQuery()->chunk(5, function (EloquentCollection $books) use ($roles) { - $this->buildJointPermissionsForBooks($books, $roles); - }); - - // Chunk through all bookshelves - Bookshelf::query()->withTrashed()->select(['id', 'restricted', 'owned_by']) - ->chunk(50, function (EloquentCollection $shelves) use ($roles) { - $this->buildJointPermissionsForShelves($shelves, $roles); - }); - } - /** * Get a query for fetching a book with it's children. */ @@ -105,18 +158,6 @@ class JointPermissionBuilder ]); } - /** - * Build joint permissions for the given shelf and role combinations. - * - * @throws Throwable - */ - protected function buildJointPermissionsForShelves(EloquentCollection $shelves, array $roles, bool $deleteOld = false) - { - if ($deleteOld) { - $this->deleteManyJointPermissionsForEntities($shelves->all()); - } - $this->createManyJointPermissions($shelves->all(), $roles); - } /** * Build joint permissions for the given book and role combinations. @@ -144,39 +185,6 @@ class JointPermissionBuilder $this->createManyJointPermissions($entities->all(), $roles); } - /** - * Rebuild the entity jointPermissions for a particular entity. - * - * @throws Throwable - */ - public function buildJointPermissionsForEntity(Entity $entity) - { - $entities = [$entity]; - if ($entity instanceof Book) { - $books = $this->bookFetchQuery()->where('id', '=', $entity->id)->get(); - $this->buildJointPermissionsForBooks($books, Role::query()->with('permissions')->get()->all(), true); - - return; - } - - /** @var BookChild $entity */ - if ($entity->book) { - $entities[] = $entity->book; - } - - if ($entity instanceof Page && $entity->chapter_id) { - $entities[] = $entity->chapter; - } - - if ($entity instanceof Chapter) { - foreach ($entity->pages as $page) { - $entities[] = $page; - } - } - - $this->buildJointPermissionsForEntities($entities); - } - /** * Rebuild the entity jointPermissions for a collection of entities. * @@ -189,26 +197,6 @@ class JointPermissionBuilder $this->createManyJointPermissions($entities, $roles); } - /** - * Build the entity jointPermissions for a particular role. - */ - public function buildJointPermissionForRole(Role $role) - { - $roles = [$role]; - $role->jointPermissions()->delete(); - - // Chunk through all books - $this->bookFetchQuery()->chunk(20, function ($books) use ($roles) { - $this->buildJointPermissionsForBooks($books, $roles); - }); - - // Chunk through all bookshelves - Bookshelf::query()->select(['id', 'restricted', 'owned_by']) - ->chunk(50, function ($shelves) use ($roles) { - $this->buildJointPermissionsForShelves($shelves, $roles); - }); - } - /** * Delete all the entity jointPermissions for a list of entities. * diff --git a/app/Auth/Permissions/PermissionService.php b/app/Auth/Permissions/PermissionApplicator.php similarity index 99% rename from app/Auth/Permissions/PermissionService.php rename to app/Auth/Permissions/PermissionApplicator.php index bcd4a3675..3dc529e32 100644 --- a/app/Auth/Permissions/PermissionService.php +++ b/app/Auth/Permissions/PermissionApplicator.php @@ -12,10 +12,10 @@ use BookStack\Traits\HasOwner; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\Builder as QueryBuilder; -class PermissionService +class PermissionApplicator { /** - * @var ?array + * @var ?array */ protected $userRoles = null; @@ -24,7 +24,6 @@ class PermissionService */ protected $currentUserModel = null; - /** * Get the roles for the current logged in user. */ diff --git a/app/Auth/Permissions/PermissionsRepo.php b/app/Auth/Permissions/PermissionsRepo.php index 0527875ae..2c2bedb72 100644 --- a/app/Auth/Permissions/PermissionsRepo.php +++ b/app/Auth/Permissions/PermissionsRepo.php @@ -27,7 +27,7 @@ class PermissionsRepo */ public function getAllRoles(): Collection { - return Role::query()->all(); + return Role::query()->get(); } /** @@ -57,7 +57,7 @@ class PermissionsRepo $permissions = isset($roleData['permissions']) ? array_keys($roleData['permissions']) : []; $this->assignRolePermissions($role, $permissions); - $this->permissionBuilder->buildJointPermissionForRole($role); + $this->permissionBuilder->rebuildForRole($role); Activity::add(ActivityType::ROLE_CREATE, $role); @@ -88,7 +88,7 @@ class PermissionsRepo $role->fill($roleData); $role->mfa_enforced = ($roleData['mfa_enforced'] ?? 'false') === 'true'; $role->save(); - $this->permissionBuilder->buildJointPermissionForRole($role); + $this->permissionBuilder->rebuildForRole($role); Activity::add(ActivityType::ROLE_UPDATE, $role); } @@ -102,7 +102,7 @@ class PermissionsRepo $permissionNameArray = array_values($permissionNameArray); if ($permissionNameArray) { - $permissions = EntityPermission::query() + $permissions = RolePermission::query() ->whereIn('name', $permissionNameArray) ->pluck('id') ->toArray(); diff --git a/app/Config/app.php b/app/Config/app.php index 2b1de6f45..5f516f4ad 100644 --- a/app/Config/app.php +++ b/app/Config/app.php @@ -202,7 +202,6 @@ return [ // Custom BookStack 'Activity' => BookStack\Facades\Activity::class, - 'Permissions' => BookStack\Facades\Permissions::class, 'Theme' => BookStack\Facades\Theme::class, ], diff --git a/app/Console/Commands/RegeneratePermissions.php b/app/Console/Commands/RegeneratePermissions.php index 558ae9fea..3396a445f 100644 --- a/app/Console/Commands/RegeneratePermissions.php +++ b/app/Console/Commands/RegeneratePermissions.php @@ -42,11 +42,11 @@ class RegeneratePermissions extends Command { $connection = DB::getDefaultConnection(); - if ($this->hasOption('database')) { + if ($this->option('database')) { DB::setDefaultConnection($this->option('database')); } - $this->permissionBuilder->buildJointPermissions(); + $this->permissionBuilder->rebuildForAll(); DB::setDefaultConnection($connection); $this->comment('Permissions regenerated'); diff --git a/app/Entities/Models/Entity.php b/app/Entities/Models/Entity.php index 7ad78f1d1..84d31d82d 100644 --- a/app/Entities/Models/Entity.php +++ b/app/Entities/Models/Entity.php @@ -9,9 +9,10 @@ use BookStack\Actions\Tag; use BookStack\Actions\View; use BookStack\Auth\Permissions\EntityPermission; use BookStack\Auth\Permissions\JointPermission; +use BookStack\Auth\Permissions\JointPermissionBuilder; +use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Entities\Tools\SearchIndex; use BookStack\Entities\Tools\SlugGenerator; -use BookStack\Facades\Permissions; use BookStack\Interfaces\Deletable; use BookStack\Interfaces\Favouritable; use BookStack\Interfaces\Loggable; @@ -76,7 +77,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable */ public function scopeHasPermission(Builder $query, string $permission) { - return Permissions::restrictEntityQuery($query, $permission); + return app()->make(PermissionApplicator::class)->restrictEntityQuery($query, $permission); } /** @@ -284,8 +285,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable */ public function rebuildPermissions() { - /** @noinspection PhpUnhandledExceptionInspection */ - Permissions::buildJointPermissionsForEntity(clone $this); + app()->make(JointPermissionBuilder::class)->rebuildForEntity(clone $this); } /** @@ -293,7 +293,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable */ public function indexForSearch() { - app(SearchIndex::class)->indexEntity(clone $this); + app()->make(SearchIndex::class)->indexEntity(clone $this); } /** @@ -301,7 +301,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable */ public function refreshSlug(): string { - $this->slug = app(SlugGenerator::class)->generate($this); + $this->slug = app()->make(SlugGenerator::class)->generate($this); return $this->slug; } diff --git a/app/Entities/Models/Page.php b/app/Entities/Models/Page.php index ed69bcf8b..a2690b2a0 100644 --- a/app/Entities/Models/Page.php +++ b/app/Entities/Models/Page.php @@ -2,8 +2,8 @@ namespace BookStack\Entities\Models; +use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Entities\Tools\PageContent; -use BookStack\Facades\Permissions; use BookStack\Uploads\Attachment; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection; @@ -51,7 +51,7 @@ class Page extends BookChild */ public function scopeVisible(Builder $query): Builder { - $query = Permissions::enforceDraftVisibilityOnQuery($query); + $query = app()->make(PermissionApplicator::class)->enforceDraftVisibilityOnQuery($query); return parent::scopeVisible($query); } diff --git a/app/Entities/Queries/EntityQuery.php b/app/Entities/Queries/EntityQuery.php index 76ab16ffc..5ab882ca8 100644 --- a/app/Entities/Queries/EntityQuery.php +++ b/app/Entities/Queries/EntityQuery.php @@ -2,14 +2,14 @@ namespace BookStack\Entities\Queries; -use BookStack\Auth\Permissions\PermissionService; +use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Entities\EntityProvider; abstract class EntityQuery { - protected function permissionService(): PermissionService + protected function permissionService(): PermissionApplicator { - return app()->make(PermissionService::class); + return app()->make(PermissionApplicator::class); } protected function entityProvider(): EntityProvider diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index a591914f3..5d94379c9 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -2,7 +2,7 @@ namespace BookStack\Entities\Tools; -use BookStack\Auth\Permissions\PermissionService; +use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Auth\User; use BookStack\Entities\EntityProvider; use BookStack\Entities\Models\BookChild; @@ -21,20 +21,14 @@ use SplObjectStorage; class SearchRunner { - /** - * @var EntityProvider - */ - protected $entityProvider; - /** - * @var PermissionService - */ - protected $permissionService; + protected EntityProvider $entityProvider; + protected PermissionApplicator $permissions; /** * Acceptable operators to be used in a query. * - * @var array + * @var string[] */ protected $queryOperators = ['<=', '>=', '=', '<', '>', 'like', '!=']; @@ -46,10 +40,10 @@ class SearchRunner */ protected $termAdjustmentCache; - public function __construct(EntityProvider $entityProvider, PermissionService $permissionService) + public function __construct(EntityProvider $entityProvider, PermissionApplicator $permissions) { $this->entityProvider = $entityProvider; - $this->permissionService = $permissionService; + $this->permissions = $permissions; $this->termAdjustmentCache = new SplObjectStorage(); } @@ -199,7 +193,7 @@ class SearchRunner } } - return $this->permissionService->enforceEntityRestrictions($entityModelInstance, $entityQuery, $action); + return $this->permissions->enforceEntityRestrictions($entityModelInstance, $entityQuery, $action); } /** diff --git a/app/Facades/Permissions.php b/app/Facades/Permissions.php deleted file mode 100644 index 74cbe46fe..000000000 --- a/app/Facades/Permissions.php +++ /dev/null @@ -1,18 +0,0 @@ -app->make(ActivityLogger::class); }); - $this->app->singleton('images', function () { - return $this->app->make(ImageService::class); - }); - - $this->app->singleton('permissions', function () { - return $this->app->make(PermissionService::class); - }); - $this->app->singleton('theme', function () { return $this->app->make(ThemeService::class); }); diff --git a/app/Uploads/Attachment.php b/app/Uploads/Attachment.php index 5e637246a..d9e0ce7e1 100644 --- a/app/Uploads/Attachment.php +++ b/app/Uploads/Attachment.php @@ -2,7 +2,7 @@ namespace BookStack\Uploads; -use BookStack\Auth\Permissions\PermissionService; +use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Auth\User; use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Page; @@ -89,9 +89,9 @@ class Attachment extends Model */ public function scopeVisible(): Builder { - $permissionService = app()->make(PermissionService::class); + $permissions = app()->make(PermissionApplicator::class); - return $permissionService->filterRelatedEntity( + return $permissions->filterRelatedEntity( Page::class, self::query(), 'attachments', diff --git a/app/Uploads/ImageRepo.php b/app/Uploads/ImageRepo.php index bfe4b5977..13d3344dd 100644 --- a/app/Uploads/ImageRepo.php +++ b/app/Uploads/ImageRepo.php @@ -2,7 +2,7 @@ namespace BookStack\Uploads; -use BookStack\Auth\Permissions\PermissionService; +use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Entities\Models\Page; use BookStack\Exceptions\ImageUploadException; use Exception; @@ -11,16 +11,16 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; class ImageRepo { - protected $imageService; - protected $restrictionService; + protected ImageService $imageService; + protected PermissionApplicator $permissions; /** * ImageRepo constructor. */ - public function __construct(ImageService $imageService, PermissionService $permissionService) + public function __construct(ImageService $imageService, PermissionApplicator $permissions) { $this->imageService = $imageService; - $this->restrictionService = $permissionService; + $this->permissions = $permissions; } /** @@ -74,7 +74,7 @@ class ImageRepo } // Filter by page access - $imageQuery = $this->restrictionService->filterRelatedEntity(Page::class, $imageQuery, 'images', 'uploaded_to'); + $imageQuery = $this->permissions->filterRelatedEntity(Page::class, $imageQuery, 'images', 'uploaded_to'); if ($whereClause !== null) { $imageQuery = $imageQuery->where($whereClause); diff --git a/app/helpers.php b/app/helpers.php index 9edc22c40..cfdf55445 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -1,6 +1,6 @@ checkOwnableUserAccess($ownable, $permission); + return $permissions->checkOwnableUserAccess($ownable, $permission); } /** @@ -76,9 +76,9 @@ function userCan(string $permission, Model $ownable = null): bool */ function userCanOnAny(string $permission, string $entityClass = null): bool { - $permissionService = app(PermissionService::class); + $permissions = app(PermissionApplicator::class); - return $permissionService->checkUserHasPermissionOnAnything($permission, $entityClass); + return $permissions->checkUserHasPermissionOnAnything($permission, $entityClass); } /** diff --git a/database/seeders/DummyContentSeeder.php b/database/seeders/DummyContentSeeder.php index cb9987df7..e97069e7f 100644 --- a/database/seeders/DummyContentSeeder.php +++ b/database/seeders/DummyContentSeeder.php @@ -69,7 +69,7 @@ class DummyContentSeeder extends Seeder ]); $token->save(); - app(JointPermissionBuilder::class)->buildJointPermissions(); + app(JointPermissionBuilder::class)->rebuildForAll(); app(SearchIndex::class)->indexAllEntities(); } } diff --git a/database/seeders/LargeContentSeeder.php b/database/seeders/LargeContentSeeder.php index 041b3161a..b2d8a4d1b 100644 --- a/database/seeders/LargeContentSeeder.php +++ b/database/seeders/LargeContentSeeder.php @@ -35,7 +35,7 @@ class LargeContentSeeder extends Seeder $largeBook->chapters()->saveMany($chapters); $all = array_merge([$largeBook], array_values($pages->all()), array_values($chapters->all())); - app()->make(JointPermissionBuilder::class)->buildJointPermissionsForEntity($largeBook); + app()->make(JointPermissionBuilder::class)->rebuildForEntity($largeBook); app()->make(SearchIndex::class)->indexEntities($all); } } diff --git a/tests/Commands/RegeneratePermissionsCommandTest.php b/tests/Commands/RegeneratePermissionsCommandTest.php index 2090c991b..d514e5f9d 100644 --- a/tests/Commands/RegeneratePermissionsCommandTest.php +++ b/tests/Commands/RegeneratePermissionsCommandTest.php @@ -4,6 +4,7 @@ namespace Tests\Commands; use BookStack\Auth\Permissions\JointPermission; use BookStack\Entities\Models\Page; +use Illuminate\Support\Facades\Artisan; use Illuminate\Support\Facades\DB; use Tests\TestCase; @@ -11,13 +12,13 @@ class RegeneratePermissionsCommandTest extends TestCase { public function test_regen_permissions_command() { - \DB::rollBack(); + DB::rollBack(); JointPermission::query()->truncate(); $page = Page::first(); $this->assertDatabaseMissing('joint_permissions', ['entity_id' => $page->id]); - $exitCode = \Artisan::call('bookstack:regenerate-permissions'); + $exitCode = Artisan::call('bookstack:regenerate-permissions'); $this->assertTrue($exitCode === 0, 'Command executed successfully'); DB::beginTransaction(); diff --git a/tests/PublicActionTest.php b/tests/PublicActionTest.php index 745fa7660..2841f4ef4 100644 --- a/tests/PublicActionTest.php +++ b/tests/PublicActionTest.php @@ -89,7 +89,7 @@ class PublicActionTest extends TestCase foreach (RolePermission::all() as $perm) { $publicRole->attachPermission($perm); } - $this->app->make(JointPermissionBuilder::class)->buildJointPermissionForRole($publicRole); + $this->app->make(JointPermissionBuilder::class)->rebuildForRole($publicRole); /** @var Chapter $chapter */ $chapter = Chapter::query()->first(); diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php index 2d05b0520..99bc92494 100644 --- a/tests/SharedTestHelpers.php +++ b/tests/SharedTestHelpers.php @@ -3,7 +3,7 @@ namespace Tests; use BookStack\Auth\Permissions\JointPermissionBuilder; -use BookStack\Auth\Permissions\PermissionService; +use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Auth\Permissions\PermissionsRepo; use BookStack\Auth\Permissions\RolePermission; use BookStack\Auth\Role; @@ -177,7 +177,7 @@ trait SharedTestHelpers $entity->save(); $entity->load('permissions'); - $this->app->make(JointPermissionBuilder::class)->buildJointPermissionsForEntity($entity); + $this->app->make(JointPermissionBuilder::class)->rebuildForEntity($entity); $entity->load('jointPermissions'); } @@ -209,7 +209,7 @@ trait SharedTestHelpers /** @var Role $role */ foreach ($roles as $role) { $role->detachPermission($permission); - $permissionBuilder->buildJointPermissionForRole($role); + $permissionBuilder->rebuildForRole($role); } $user->clearPermissionCache(); @@ -243,7 +243,7 @@ trait SharedTestHelpers $chapter = Chapter::factory()->create(array_merge(['book_id' => $book->id], $userAttrs)); $page = Page::factory()->create(array_merge(['book_id' => $book->id, 'chapter_id' => $chapter->id], $userAttrs)); - $this->app->make(JointPermissionBuilder::class)->buildJointPermissionsForEntity($book); + $this->app->make(JointPermissionBuilder::class)->rebuildForEntity($book); return compact('book', 'chapter', 'page'); } From 82baab66cc68c0954fd4413d98bde39cedf3f794 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Jul 2022 21:07:48 +0100 Subject: [PATCH 024/246] New translations activities.php (Croatian) --- resources/lang/hr/activities.php | 56 ++++++++++++++++---------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/resources/lang/hr/activities.php b/resources/lang/hr/activities.php index 65ab1594f..b8dd50a13 100644 --- a/resources/lang/hr/activities.php +++ b/resources/lang/hr/activities.php @@ -6,7 +6,7 @@ return [ // Pages - 'page_create' => 'stvorena stranica', + 'page_create' => 'kreirana stranica', 'page_create_notification' => 'Stranica uspješno kreirana', 'page_update' => 'ažurirana stranica', 'page_update_notification' => 'Stranica uspješno ažurirana', @@ -18,54 +18,54 @@ return [ // Chapters 'chapter_create' => 'stvoreno poglavlje', - 'chapter_create_notification' => 'Chapter successfully created', + 'chapter_create_notification' => 'Poglavlje je uspješno stvoreno', 'chapter_update' => 'ažurirano poglavlje', - 'chapter_update_notification' => 'Chapter successfully updated', + 'chapter_update_notification' => 'Poglavlje je uspješno ažurirano', 'chapter_delete' => 'izbrisano poglavlje', - 'chapter_delete_notification' => 'Chapter successfully deleted', + 'chapter_delete_notification' => 'Poglavlje je uspješno izbrisano', 'chapter_move' => 'premiješteno poglavlje', // Books 'book_create' => 'stvorena knjiga', - 'book_create_notification' => 'Book successfully created', - 'book_create_from_chapter' => 'converted chapter to book', - 'book_create_from_chapter_notification' => 'Chapter successfully converted to a book', + 'book_create_notification' => 'Knjiga je uspješno stvorena', + 'book_create_from_chapter' => 'pretvori poglavlje u knjigu', + 'book_create_from_chapter_notification' => 'Poglavlje je uspješno pretvoreno u knjigu', 'book_update' => 'ažurirana knjiga', - 'book_update_notification' => 'Book successfully updated', + 'book_update_notification' => 'Knjiga je uspješno ažurirana', 'book_delete' => 'izbrisana knjiga', - 'book_delete_notification' => 'Book successfully deleted', + 'book_delete_notification' => 'Knjiga je uspješno izbrisana', 'book_sort' => 'razvrstana knjiga', - 'book_sort_notification' => 'Book successfully re-sorted', + 'book_sort_notification' => 'Knjiga je uspješno razvrstana', // Bookshelves - 'bookshelf_create' => 'created bookshelf', - 'bookshelf_create_notification' => 'Bookshelf successfully created', - 'bookshelf_create_from_book' => 'converted book to bookshelf', - 'bookshelf_create_from_book_notification' => 'Book successfully converted to a shelf', + 'bookshelf_create' => 'stvorena polica za knjige', + 'bookshelf_create_notification' => 'Polica za knjige je uspješno stvorena', + 'bookshelf_create_from_book' => 'prebaci knjigu na policu', + 'bookshelf_create_from_book_notification' => 'Poglavlje je uspješno pretvoreno u knjigu', 'bookshelf_update' => 'ažurirana polica za knjige', - 'bookshelf_update_notification' => 'Bookshelf successfully updated', + 'bookshelf_update_notification' => 'Polica za knjige je uspješno ažurirana', 'bookshelf_delete' => 'izbrisana polica za knjige', - 'bookshelf_delete_notification' => 'Bookshelf successfully deleted', + 'bookshelf_delete_notification' => 'Polica za knjige je uspješno izbrisana', // Favourites - 'favourite_add_notification' => '":name" has been added to your favourites', - 'favourite_remove_notification' => '":name" has been removed from your favourites', + 'favourite_add_notification' => '".ime" će biti dodano u tvoje favorite', + 'favourite_remove_notification' => '".ime" je uspješno maknuta iz tvojih favorita', // MFA - 'mfa_setup_method_notification' => 'Multi-factor method successfully configured', - 'mfa_remove_method_notification' => 'Multi-factor method successfully removed', + 'mfa_setup_method_notification' => 'Metoda više-čimbenika je uspješno konfigurirana', + 'mfa_remove_method_notification' => 'Metoda više-čimbenika je uspješno izbrisana', // Webhooks - 'webhook_create' => 'created webhook', - 'webhook_create_notification' => 'Webhook successfully created', - 'webhook_update' => 'updated webhook', - 'webhook_update_notification' => 'Webhook successfully updated', - 'webhook_delete' => 'deleted webhook', - 'webhook_delete_notification' => 'Webhook successfully deleted', + 'webhook_create' => 'web knjiga je kreirana', + 'webhook_create_notification' => 'Web knjiga je uspješno kreirana', + 'webhook_update' => 'web knjiga je ažurirana', + 'webhook_update_notification' => 'Web knjiga je uspješno ažurirana', + 'webhook_delete' => 'web knjiga je izbrisana', + 'webhook_delete_notification' => 'Web knjga je uspješno izbrisana', // Users - 'user_update_notification' => 'User successfully updated', - 'user_delete_notification' => 'User successfully removed', + 'user_update_notification' => 'Korisnik je uspješno ažuriran', + 'user_delete_notification' => 'Korisnik je uspješno uklonjen', // Other 'commented_on' => 'komentirano', From 4daac5a114899d2144c1652b07ff038dcd4a6cb1 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Jul 2022 21:07:49 +0100 Subject: [PATCH 025/246] New translations auth.php (Croatian) --- resources/lang/hr/auth.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lang/hr/auth.php b/resources/lang/hr/auth.php index bbaf9dede..bd7f2b06e 100644 --- a/resources/lang/hr/auth.php +++ b/resources/lang/hr/auth.php @@ -18,10 +18,10 @@ return [ 'name' => 'Ime', 'username' => 'Korisničko ime', - 'email' => 'Email', + 'email' => 'E-pošta', 'password' => 'Lozinka', 'password_confirm' => 'Potvrdite lozinku', - 'password_hint' => 'Must be at least 8 characters', + 'password_hint' => 'Mora biti najmanje 8 znakova', 'forgot_password' => 'Zaboravili ste lozinku?', 'remember_me' => 'Zapamti me', 'ldap_email_hint' => 'Molimo upišite mail korišten za ovaj račun.', From 2989852520ee05581abbf156a0b6aa8aad2cc910 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Tue, 12 Jul 2022 21:13:02 +0100 Subject: [PATCH 026/246] Added simple data model for faster permission generation --- .../Permissions/JointPermissionBuilder.php | 153 +++++++++--------- app/Auth/Permissions/SimpleEntityData.php | 13 ++ tests/Api/AttachmentsApiTest.php | 2 +- 3 files changed, 95 insertions(+), 73 deletions(-) create mode 100644 app/Auth/Permissions/SimpleEntityData.php diff --git a/app/Auth/Permissions/JointPermissionBuilder.php b/app/Auth/Permissions/JointPermissionBuilder.php index fbf77741a..fe25e02ff 100644 --- a/app/Auth/Permissions/JointPermissionBuilder.php +++ b/app/Auth/Permissions/JointPermissionBuilder.php @@ -16,7 +16,7 @@ use Illuminate\Support\Facades\DB; class JointPermissionBuilder { /** - * @var array> + * @var array> */ protected $entityCache; @@ -26,7 +26,6 @@ class JointPermissionBuilder public function rebuildForAll() { JointPermission::query()->truncate(); - $this->readyEntityCache(); // Get all roles (Should be the most limited dimension) $roles = Role::query()->with('permissions')->get()->all(); @@ -45,8 +44,6 @@ class JointPermissionBuilder /** * Rebuild the entity jointPermissions for a particular entity. - * - * @throws Throwable */ public function rebuildForEntity(Entity $entity) { @@ -99,51 +96,39 @@ class JointPermissionBuilder /** * Prepare the local entity cache and ensure it's empty. * - * @param Entity[] $entities + * @param SimpleEntityData[] $entities */ - protected function readyEntityCache(array $entities = []) + protected function readyEntityCache(array $entities) { $this->entityCache = []; foreach ($entities as $entity) { - $class = get_class($entity); - - if (!isset($this->entityCache[$class])) { - $this->entityCache[$class] = []; + if (!isset($this->entityCache[$entity->type])) { + $this->entityCache[$entity->type] = []; } - $this->entityCache[$class][$entity->getRawAttribute('id')] = $entity; + $this->entityCache[$entity->type][$entity->id] = $entity; } } /** * Get a book via ID, Checks local cache. */ - protected function getBook(int $bookId): ?Book + protected function getBook(int $bookId): SimpleEntityData { - if ($this->entityCache[Book::class][$bookId] ?? false) { - return $this->entityCache[Book::class][$bookId]; - } - - return Book::query()->withTrashed()->find($bookId); + return $this->entityCache['book'][$bookId]; } /** * Get a chapter via ID, Checks local cache. */ - protected function getChapter(int $chapterId): ?Chapter + protected function getChapter(int $chapterId): SimpleEntityData { - if ($this->entityCache[Chapter::class][$chapterId] ?? false) { - return $this->entityCache[Chapter::class][$chapterId]; - } - - return Chapter::query() - ->withTrashed() - ->find($chapterId); + return $this->entityCache['chapter'][$chapterId]; } /** - * Get a query for fetching a book with it's children. + * Get a query for fetching a book with its children. */ protected function bookFetchQuery(): Builder { @@ -161,8 +146,6 @@ class JointPermissionBuilder /** * Build joint permissions for the given book and role combinations. - * - * @throws Throwable */ protected function buildJointPermissionsForBooks(EloquentCollection $books, array $roles, bool $deleteOld = false) { @@ -187,8 +170,6 @@ class JointPermissionBuilder /** * Rebuild the entity jointPermissions for a collection of entities. - * - * @throws Throwable */ protected function buildJointPermissionsForEntities(array $entities) { @@ -201,12 +182,11 @@ class JointPermissionBuilder * Delete all the entity jointPermissions for a list of entities. * * @param Entity[] $entities - * - * @throws Throwable */ protected function deleteManyJointPermissionsForEntities(array $entities) { - $idsByType = $this->entitiesToTypeIdMap($entities); + $simpleEntities = $this->entitiesToSimpleEntities($entities); + $idsByType = $this->entitiesToTypeIdMap($simpleEntities); DB::transaction(function () use ($idsByType) { foreach ($idsByType as $type => $ids) { @@ -220,23 +200,45 @@ class JointPermissionBuilder }); } + /** + * @param Entity[] $entities + * @return SimpleEntityData[] + */ + protected function entitiesToSimpleEntities(array $entities): array + { + $simpleEntities = []; + + foreach ($entities as $entity) { + $attrs = $entity->getAttributes(); + $simple = new SimpleEntityData(); + $simple->id = $attrs['id']; + $simple->type = $entity->getMorphClass(); + $simple->restricted = boolval($attrs['restricted'] ?? 0); + $simple->owned_by = $attrs['owned_by'] ?? 0; + $simple->book_id = $attrs['book_id'] ?? null; + $simple->chapter_id = $attrs['chapter_id'] ?? null; + $simpleEntities[] = $simple; + } + + return $simpleEntities; + } + /** * Create & Save entity jointPermissions for many entities and roles. * * @param Entity[] $entities * @param Role[] $roles - * - * @throws Throwable */ - protected function createManyJointPermissions(array $entities, array $roles) + protected function createManyJointPermissions(array $originalEntities, array $roles) { + $entities = $this->entitiesToSimpleEntities($originalEntities); $this->readyEntityCache($entities); $jointPermissions = []; // Create a mapping of entity restricted statuses $entityRestrictedMap = []; foreach ($entities as $entity) { - $entityRestrictedMap[$entity->getMorphClass() . ':' . $entity->getRawAttribute('id')] = boolval($entity->getRawAttribute('restricted')); + $entityRestrictedMap[$entity->type . ':' . $entity->id] = $entity->restricted; } // Fetch related entity permissions @@ -262,7 +264,14 @@ class JointPermissionBuilder foreach ($entities as $entity) { foreach ($roles as $role) { foreach ($this->getActions($entity) as $action) { - $jointPermissions[] = $this->createJointPermissionData($entity, $role, $action, $permissionMap, $rolePermissionMap); + $jointPermissions[] = $this->createJointPermissionData( + $entity, + $role->getRawAttribute('id'), + $action, + $permissionMap, + $rolePermissionMap, + $role->system_name === 'admin' + ); } } } @@ -277,7 +286,7 @@ class JointPermissionBuilder /** * From the given entity list, provide back a mapping of entity types to * the ids of that given type. The type used is the DB morph class. - * @param Entity[] $entities + * @param SimpleEntityData[] $entities * @return array */ protected function entitiesToTypeIdMap(array $entities): array @@ -285,13 +294,11 @@ class JointPermissionBuilder $idsByType = []; foreach ($entities as $entity) { - $type = $entity->getMorphClass(); - - if (!isset($idsByType[$type])) { - $idsByType[$type] = []; + if (!isset($idsByType[$entity->type])) { + $idsByType[$entity->type] = []; } - $idsByType[$type][] = $entity->getRawAttribute('id'); + $idsByType[$entity->type][] = $entity->id; } return $idsByType; @@ -299,10 +306,10 @@ class JointPermissionBuilder /** * Get the entity permissions for all the given entities - * @param Entity[] $entities - * @return EloquentCollection + * @param SimpleEntityData[] $entities + * @return EntityPermission[] */ - protected function getEntityPermissionsForEntities(array $entities) + protected function getEntityPermissionsForEntities(array $entities): array { $idsByType = $this->entitiesToTypeIdMap($entities); $permissionFetch = EntityPermission::query(); @@ -313,19 +320,21 @@ class JointPermissionBuilder }); } - return $permissionFetch->get(); + return $permissionFetch->get()->all(); } /** * Get the actions related to an entity. */ - protected function getActions(Entity $entity): array + protected function getActions(SimpleEntityData $entity): array { $baseActions = ['view', 'update', 'delete']; - if ($entity instanceof Chapter || $entity instanceof Book) { + + if ($entity->type === 'chapter' || $entity->type === 'book') { $baseActions[] = 'page-create'; } - if ($entity instanceof Book) { + + if ($entity->type === 'book') { $baseActions[] = 'chapter-create'; } @@ -336,45 +345,45 @@ class JointPermissionBuilder * Create entity permission data for an entity and role * for a particular action. */ - protected function createJointPermissionData(Entity $entity, Role $role, string $action, array $permissionMap, array $rolePermissionMap): array + protected function createJointPermissionData(SimpleEntityData $entity, int $roleId, string $action, array $permissionMap, array $rolePermissionMap, bool $isAdminRole): array { - $permissionPrefix = (strpos($action, '-') === false ? ($entity->getType() . '-') : '') . $action; - $roleHasPermission = isset($rolePermissionMap[$role->getRawAttribute('id') . ':' . $permissionPrefix . '-all']); - $roleHasPermissionOwn = isset($rolePermissionMap[$role->getRawAttribute('id') . ':' . $permissionPrefix . '-own']); + $permissionPrefix = (strpos($action, '-') === false ? ($entity->type . '-') : '') . $action; + $roleHasPermission = isset($rolePermissionMap[$roleId . ':' . $permissionPrefix . '-all']); + $roleHasPermissionOwn = isset($rolePermissionMap[$roleId . ':' . $permissionPrefix . '-own']); $explodedAction = explode('-', $action); $restrictionAction = end($explodedAction); - if ($role->system_name === 'admin') { - return $this->createJointPermissionDataArray($entity, $role, $action, true, true); + if ($isAdminRole) { + return $this->createJointPermissionDataArray($entity, $roleId, $action, true, true); } if ($entity->restricted) { - $hasAccess = $this->mapHasActiveRestriction($permissionMap, $entity, $role, $restrictionAction); + $hasAccess = $this->mapHasActiveRestriction($permissionMap, $entity, $roleId, $restrictionAction); - return $this->createJointPermissionDataArray($entity, $role, $action, $hasAccess, $hasAccess); + return $this->createJointPermissionDataArray($entity, $roleId, $action, $hasAccess, $hasAccess); } - if ($entity instanceof Book || $entity instanceof Bookshelf) { - return $this->createJointPermissionDataArray($entity, $role, $action, $roleHasPermission, $roleHasPermissionOwn); + if ($entity->type === 'book' || $entity->type === 'bookshelf') { + return $this->createJointPermissionDataArray($entity, $roleId, $action, $roleHasPermission, $roleHasPermissionOwn); } // For chapters and pages, Check if explicit permissions are set on the Book. $book = $this->getBook($entity->book_id); - $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $book, $role, $restrictionAction); + $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $book, $roleId, $restrictionAction); $hasPermissiveAccessToParents = !$book->restricted; // For pages with a chapter, Check if explicit permissions are set on the Chapter - if ($entity instanceof Page && intval($entity->chapter_id) !== 0) { + if ($entity->type === 'page' && $entity->chapter_id !== 0) { $chapter = $this->getChapter($entity->chapter_id); $hasPermissiveAccessToParents = $hasPermissiveAccessToParents && !$chapter->restricted; if ($chapter->restricted) { - $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $chapter, $role, $restrictionAction); + $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $chapter, $roleId, $restrictionAction); } } return $this->createJointPermissionDataArray( $entity, - $role, + $roleId, $action, ($hasExplicitAccessToParents || ($roleHasPermission && $hasPermissiveAccessToParents)), ($hasExplicitAccessToParents || ($roleHasPermissionOwn && $hasPermissiveAccessToParents)) @@ -384,9 +393,9 @@ class JointPermissionBuilder /** * Check for an active restriction in an entity map. */ - protected function mapHasActiveRestriction(array $entityMap, Entity $entity, Role $role, string $action): bool + protected function mapHasActiveRestriction(array $entityMap, SimpleEntityData $entity, int $roleId, string $action): bool { - $key = $entity->getMorphClass() . ':' . $entity->getRawAttribute('id') . ':' . $role->getRawAttribute('id') . ':' . $action; + $key = $entity->type . ':' . $entity->id . ':' . $roleId . ':' . $action; return $entityMap[$key] ?? false; } @@ -395,16 +404,16 @@ class JointPermissionBuilder * Create an array of data with the information of an entity jointPermissions. * Used to build data for bulk insertion. */ - protected function createJointPermissionDataArray(Entity $entity, Role $role, string $action, bool $permissionAll, bool $permissionOwn): array + protected function createJointPermissionDataArray(SimpleEntityData $entity, int $roleId, string $action, bool $permissionAll, bool $permissionOwn): array { return [ 'action' => $action, - 'entity_id' => $entity->getRawAttribute('id'), - 'entity_type' => $entity->getMorphClass(), + 'entity_id' => $entity->id, + 'entity_type' => $entity->type, 'has_permission' => $permissionAll, 'has_permission_own' => $permissionOwn, - 'owned_by' => $entity->getRawAttribute('owned_by'), - 'role_id' => $role->getRawAttribute('id'), + 'owned_by' => $entity->owned_by, + 'role_id' => $roleId, ]; } diff --git a/app/Auth/Permissions/SimpleEntityData.php b/app/Auth/Permissions/SimpleEntityData.php new file mode 100644 index 000000000..0d1c94b0d --- /dev/null +++ b/app/Auth/Permissions/SimpleEntityData.php @@ -0,0 +1,13 @@ +first(); $page->draft = true; - $page->owned_by = $editor; + $page->owned_by = $editor->id; $page->save(); $this->regenEntityPermissions($page); From 55dc86037f342f1edc5e1160f4c8ce5edad74b13 Mon Sep 17 00:00:00 2001 From: Jan Koid Date: Tue, 12 Jul 2022 23:05:44 +0200 Subject: [PATCH 027/246] Fixed some typos and corrected grammar. --- resources/lang/de/auth.php | 2 +- resources/lang/de/entities.php | 12 ++++++------ resources/lang/de/errors.php | 6 +++--- resources/lang/de/settings.php | 10 +++++----- resources/lang/de/validation.php | 2 +- resources/lang/de_informal/auth.php | 6 +++--- resources/lang/de_informal/common.php | 2 +- resources/lang/de_informal/entities.php | 10 +++++----- resources/lang/de_informal/errors.php | 8 ++++---- resources/lang/de_informal/settings.php | 10 +++++----- resources/lang/de_informal/validation.php | 2 +- 11 files changed, 35 insertions(+), 35 deletions(-) diff --git a/resources/lang/de/auth.php b/resources/lang/de/auth.php index 3005fd93c..13aad051b 100644 --- a/resources/lang/de/auth.php +++ b/resources/lang/de/auth.php @@ -58,7 +58,7 @@ return [ 'email_confirm_greeting' => 'Danke, dass Sie sich für :appName registriert haben!', 'email_confirm_text' => 'Bitte bestätigen Sie Ihre E-Mail-Adresse, indem Sie auf die Schaltfläche klicken:', 'email_confirm_action' => 'E-Mail-Adresse bestätigen', - 'email_confirm_send_error' => 'Leider konnte die für die Registrierung notwendige E-Mail zur bestätigung Ihrer E-Mail-Adresse nicht versandt werden. Bitte kontaktieren Sie den Systemadministrator!', + 'email_confirm_send_error' => 'Leider konnte die für die Registrierung notwendige E-Mail zur Bestätigung Ihrer E-Mail-Adresse nicht versandt werden. Bitte kontaktieren Sie den Systemadministrator!', 'email_confirm_success' => 'Ihre E-Mail wurde bestätigt! Sie sollten nun in der Lage sein, sich mit dieser E-Mail-Adresse anzumelden.', 'email_confirm_resent' => 'Bestätigungs-E-Mail wurde erneut versendet, bitte überprüfen Sie Ihren Posteingang.', diff --git a/resources/lang/de/entities.php b/resources/lang/de/entities.php index 158697c26..1b99967b8 100644 --- a/resources/lang/de/entities.php +++ b/resources/lang/de/entities.php @@ -29,9 +29,9 @@ return [ 'my_recently_viewed' => 'Kürzlich von mir angesehen', 'my_most_viewed_favourites' => 'Meine meistgesehenen Favoriten', 'my_favourites' => 'Meine Favoriten', - 'no_pages_viewed' => 'Sie haben bisher keine Seiten angesehen', - 'no_pages_recently_created' => 'Sie haben bisher keine Seiten angelegt', - 'no_pages_recently_updated' => 'Sie haben bisher keine Seiten aktualisiert', + 'no_pages_viewed' => 'Sie haben bisher keine Seiten angesehen.', + 'no_pages_recently_created' => 'Sie haben bisher keine Seiten angelegt.', + 'no_pages_recently_updated' => 'Sie haben bisher keine Seiten aktualisiert.', 'export' => 'Exportieren', 'export_html' => 'HTML-Datei', 'export_pdf' => 'PDF-Datei', @@ -168,7 +168,7 @@ return [ 'chapters_permissions' => 'Kapitel-Berechtigungen', 'chapters_empty' => 'Aktuell sind keine Kapitel diesem Buch hinzugefügt worden.', 'chapters_permissions_active' => 'Kapitel-Berechtigungen aktiv', - 'chapters_permissions_success' => 'Kapitel-Berechtigungenen aktualisisert', + 'chapters_permissions_success' => 'Kapitel-Berechtigungen aktualisiert', 'chapters_search_this' => 'Dieses Kapitel durchsuchen', // Pages @@ -185,7 +185,7 @@ return [ 'pages_delete_draft' => 'Seitenentwurf löschen', 'pages_delete_success' => 'Seite gelöscht', 'pages_delete_draft_success' => 'Seitenentwurf gelöscht', - 'pages_delete_confirm' => 'Sind Sie sicher, dass Sie diese Seite löschen möchen?', + 'pages_delete_confirm' => 'Sind Sie sicher, dass Sie diese Seite löschen möchten?', 'pages_delete_draft_confirm' => 'Sind Sie sicher, dass Sie diesen Seitenentwurf löschen möchten?', 'pages_editing_named' => 'Seite ":pageName" bearbeiten', 'pages_edit_draft_options' => 'Entwurfsoptionen', @@ -357,7 +357,7 @@ return [ 'copy_consider_access' => 'Eine Veränderung der Position, Besitzers oder Berechtigungen könnte dafür sorgen, dass Unberechtigte, Zugriff bekommen.', // Conversions - 'convert_to_shelf' => 'Convert to Shelf', + 'convert_to_shelf' => 'In Regal umwandeln', 'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.', 'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.', 'convert_book' => 'Convert Book', diff --git a/resources/lang/de/errors.php b/resources/lang/de/errors.php index cedd85ad7..5879ffc22 100644 --- a/resources/lang/de/errors.php +++ b/resources/lang/de/errors.php @@ -62,7 +62,7 @@ return [ 'book_not_found' => 'Buch nicht gefunden', 'page_not_found' => 'Seite nicht gefunden', 'chapter_not_found' => 'Kapitel nicht gefunden', - 'selected_book_not_found' => 'Das gewählte Buch wurde nicht gefunden', + 'selected_book_not_found' => 'Das gewählte Buch wurde nicht gefunden.', 'selected_book_chapter_not_found' => 'Das gewählte Buch oder Kapitel wurde nicht gefunden.', 'guests_cannot_save_drafts' => 'Gäste können keine Entwürfe speichern', @@ -74,7 +74,7 @@ return [ 'role_cannot_be_edited' => 'Diese Rolle kann nicht bearbeitet werden', 'role_system_cannot_be_deleted' => 'Dies ist eine Systemrolle und kann nicht gelöscht werden', 'role_registration_default_cannot_delete' => 'Diese Rolle kann nicht gelöscht werden, solange sie als Standardrolle für neue Registrierungen gesetzt ist', - 'role_cannot_remove_only_admin' => 'Dieser Benutzer ist der einzige Benutzer, welchem die Administratorrolle zugeordnet ist. Ordnen Sie die Administratorrolle einem anderen Benutzer zu bevor Sie versuchen sie hier zu entfernen.', + 'role_cannot_remove_only_admin' => 'Dieser Benutzer ist der einzige Benutzer, welchem die Administratorrolle zugeordnet ist. Ordnen Sie die Administratorrolle einem anderen Benutzer zu, bevor Sie versuchen, sie hier zu entfernen.', // Comments 'comment_list' => 'Beim Abrufen der Kommentare ist ein Fehler aufgetreten.', @@ -92,7 +92,7 @@ return [ 'image_not_found_details' => 'Wenn Sie erwartet haben, dass dieses Bild existiert, könnte es gelöscht worden sein.', 'return_home' => 'Zurück zur Startseite', 'error_occurred' => 'Es ist ein Fehler aufgetreten', - 'app_down' => ':appName befindet sich aktuell im Wartungsmodus', + 'app_down' => ':appName befindet sich aktuell im Wartungsmodus.', 'back_soon' => 'Wir werden so schnell wie möglich wieder online sein.', // API errors diff --git a/resources/lang/de/settings.php b/resources/lang/de/settings.php index e69f72917..3041b1de5 100644 --- a/resources/lang/de/settings.php +++ b/resources/lang/de/settings.php @@ -20,13 +20,13 @@ return [ 'app_name_desc' => 'Dieser Name wird im Header und in E-Mails angezeigt.', 'app_name_header' => 'Anwendungsname im Header anzeigen?', 'app_public_access' => 'Öffentlicher Zugriff', - 'app_public_access_desc' => 'Wenn Sie diese Option aktivieren können Besucher, die nicht angemeldet sind, auf Inhalte in Ihrer BookStack-Instanz zugreifen.', + 'app_public_access_desc' => 'Wenn Sie diese Option aktivieren, können Besucher, die nicht angemeldet sind, auf Inhalte in Ihrer BookStack-Instanz zugreifen.', 'app_public_access_desc_guest' => 'Der Zugang für öffentliche Besucher kann über den Benutzer "Guest" gesteuert werden.', 'app_public_access_toggle' => 'Öffentlichen Zugriff erlauben', 'app_public_viewing' => 'Öffentliche Ansicht erlauben?', 'app_secure_images' => 'Erhöhte Sicherheit für hochgeladene Bilder aktivieren?', 'app_secure_images_toggle' => 'Aktiviere Bild-Upload höherer Sicherheit', - 'app_secure_images_desc' => 'Aus Leistungsgründen sind alle Bilder öffentlich sichtbar. Diese Option fügt zufällige, schwer zu eratene, Zeichenketten zu Bild-URLs hinzu. Stellen sie sicher, dass Verzeichnisindizes deaktiviert sind, um einen einfachen Zugriff zu verhindern.', + 'app_secure_images_desc' => 'Aus Leistungsgründen sind alle Bilder öffentlich sichtbar. Diese Option fügt zufällige, schwer zu erratene Zeichenketten zu Bild-URLs hinzu. Stellen sie sicher, dass Verzeichnisindizes deaktiviert sind, um einen einfachen Zugriff zu verhindern.', 'app_default_editor' => 'Standard-Seiten-Editor', 'app_default_editor_desc' => 'Wählen Sie aus, welcher Editor standardmäßig beim Bearbeiten neuer Seiten verwendet wird. Dies kann auf einer Seitenebene überschrieben werden, wenn es die Berechtigungen erlauben.', 'app_custom_html' => 'Benutzerdefinierter HTML Inhalt', @@ -80,9 +80,9 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'maint_image_cleanup_desc' => 'Überprüft Seiten- und Versionsinhalte auf ungenutzte und mehrfach vorhandene Bilder. Erstellen Sie vor dem Start ein Backup Ihrer Datenbank und Bilder.', 'maint_delete_images_only_in_revisions' => 'Lösche auch Bilder, die nur in alten Seitenüberarbeitungen vorhanden sind', 'maint_image_cleanup_run' => 'Reinigung starten', - 'maint_image_cleanup_warning' => ':count eventuell unbenutze Bilder wurden gefunden. Möchten Sie diese Bilder löschen?', - 'maint_image_cleanup_success' => ':count eventuell unbenutze Bilder wurden gefunden und gelöscht.', - 'maint_image_cleanup_nothing_found' => 'Keine unbenutzen Bilder gefunden. Nichts zu löschen!', + 'maint_image_cleanup_warning' => ':count eventuell unbenutzte Bilder wurden gefunden. Möchten Sie diese Bilder löschen?', + 'maint_image_cleanup_success' => ':count eventuell unbenutzte Bilder wurden gefunden und gelöscht.', + 'maint_image_cleanup_nothing_found' => 'Keine unbenutzten Bilder gefunden. Nichts zu löschen!', 'maint_send_test_email' => 'Test Email versenden', 'maint_send_test_email_desc' => 'Dies sendet eine Test E-Mail an Ihre in Ihrem Profil angegebene E-Mail-Adresse.', 'maint_send_test_email_run' => 'Sende eine Test E-Mail', diff --git a/resources/lang/de/validation.php b/resources/lang/de/validation.php index df3995f30..53abb0099 100644 --- a/resources/lang/de/validation.php +++ b/resources/lang/de/validation.php @@ -99,7 +99,7 @@ return [ 'array' => ':attribute muss :size Elemente enthalten.', ], 'string' => ':attribute muss eine Zeichenkette sein.', - 'timezone' => ':attribute muss eine valide zeitzone sein.', + 'timezone' => ':attribute muss eine valide Zeitzone sein.', 'totp' => 'Der angegebene Code ist ungültig oder abgelaufen.', 'unique' => ':attribute wird bereits verwendet.', 'url' => ':attribute ist kein valides Format.', diff --git a/resources/lang/de_informal/auth.php b/resources/lang/de_informal/auth.php index dac76e390..af2180764 100644 --- a/resources/lang/de_informal/auth.php +++ b/resources/lang/de_informal/auth.php @@ -33,7 +33,7 @@ return [ 'social_registration_text' => 'Mit einer dieser Dienste registrieren oder anmelden', 'register_thanks' => 'Vielen Dank für deine Registrierung!', - 'register_confirm' => 'Bitte prüfe Deinen Posteingang und bestätig die Registrierung.', + 'register_confirm' => 'Bitte prüfe Deinen Posteingang und bestätige die Registrierung.', 'registrations_disabled' => 'Eine Registrierung ist momentan nicht möglich', 'registration_email_domain_invalid' => 'Du kannst dich mit dieser E-Mail nicht registrieren.', 'register_success' => 'Vielen Dank für deine Registrierung! Du bist jetzt registriert und eingeloggt.', @@ -85,11 +85,11 @@ return [ 'mfa_setup_reconfigure' => 'Umkonfigurieren', 'mfa_setup_remove_confirmation' => 'Sind Sie sicher, dass Sie diese Multi-Faktor-Authentifizierungsmethode entfernen möchten?', 'mfa_setup_action' => 'Einrichtung', - 'mfa_backup_codes_usage_limit_warning' => 'Sie haben weniger als 5 Backup-Codes übrig, Bitte erstellen und speichern Sie ein neues set bevor Sie keine codes mehr haben, um zu verhindern, dass Sie von Ihrem konto gesperrt werden.', + 'mfa_backup_codes_usage_limit_warning' => 'Sie haben weniger als 5 Backup-Codes übrig, Bitte erstellen und speichern Sie ein neues set bevor Sie keine codes mehr haben, um zu verhindern, dass Sie von Ihrem Konto gesperrt werden.', 'mfa_option_totp_title' => 'Mobile App', 'mfa_option_totp_desc' => 'Um Mehrfach-Faktor-Authentifizierung nutzen zu können, benötigen Sie eine mobile Anwendung, die TOTP unterstützt, wie Google Authenticator, Authy oder Microsoft Authenticator.', 'mfa_option_backup_codes_title' => 'Backup Code', - 'mfa_option_backup_codes_desc' => 'Speichern Sie sicher eine reihe von einmaligen Backup-Codes, die Sie eingeben können, um ihre identität zu überprüfen.', + 'mfa_option_backup_codes_desc' => 'Speichern Sie sicher eine reihe von einmaligen Backup-Codes, die Sie eingeben können, um ihre Identität zu überprüfen.', 'mfa_gen_confirm_and_enable' => 'Bestätigen und aktivieren', 'mfa_gen_backup_codes_title' => 'Backup-Codes einrichten', 'mfa_gen_backup_codes_desc' => 'Speichern Sie die folgende Liste der Codes an einem sicheren Ort. Wenn Sie auf das System zugreifen, können Sie einen der Codes als zweiten Authentifizierungsmechanismus verwenden.', diff --git a/resources/lang/de_informal/common.php b/resources/lang/de_informal/common.php index 1d92bda7c..a51e04fcf 100644 --- a/resources/lang/de_informal/common.php +++ b/resources/lang/de_informal/common.php @@ -63,7 +63,7 @@ return [ // Misc 'deleted_user' => 'Gelöschter Benutzer', 'no_activity' => 'Keine Aktivitäten zum Anzeigen', - 'no_items' => 'Keine Einträge gefunden.', + 'no_items' => 'Keine Einträge gefunden', 'back_to_top' => 'nach oben', 'skip_to_main_content' => 'Direkt zum Hauptinhalt', 'toggle_details' => 'Details zeigen/verstecken', diff --git a/resources/lang/de_informal/entities.php b/resources/lang/de_informal/entities.php index 74282a77a..6e4d2d7ff 100644 --- a/resources/lang/de_informal/entities.php +++ b/resources/lang/de_informal/entities.php @@ -36,7 +36,7 @@ return [ 'export_html' => 'HTML-Datei', 'export_pdf' => 'PDF-Datei', 'export_text' => 'Textdatei', - 'export_md' => 'Markdown-Dateir', + 'export_md' => 'Markdown-Datei', // Permissions and restrictions 'permissions' => 'Berechtigungen', @@ -168,7 +168,7 @@ return [ 'chapters_permissions' => 'Kapitel-Berechtigungen', 'chapters_empty' => 'Aktuell sind keine Kapitel diesem Buch hinzugefügt worden.', 'chapters_permissions_active' => 'Kapitel-Berechtigungen aktiv', - 'chapters_permissions_success' => 'Kapitel-Berechtigungenen aktualisisert', + 'chapters_permissions_success' => 'Kapitel-Berechtigungen aktualisiert', 'chapters_search_this' => 'Dieses Kapitel durchsuchen', // Pages @@ -247,7 +247,7 @@ return [ 'pages_permissions_active' => 'Seiten-Berechtigungen aktiv', 'pages_initial_revision' => 'Erste Veröffentlichung', 'pages_initial_name' => 'Neue Seite', - 'pages_editing_draft_notification' => 'Du bearbeitest momenten einen Entwurf, der zuletzt :timeDiff gespeichert wurde.', + 'pages_editing_draft_notification' => 'Du bearbeitest momentan einen Entwurf, der zuletzt :timeDiff gespeichert wurde.', 'pages_draft_edited_notification' => 'Diese Seite wurde seit diesem Zeitpunkt verändert. Wir empfehlen Ihnen, diesen Entwurf zu verwerfen.', 'pages_draft_page_changed_since_creation' => 'Diese Seite wurde seit der Erstellung dieses Entwurfs aktualisiert. Es wird empfohlen, diesen Entwurf zu verwerfen oder darauf zu achten, dass keine Seitenänderungen überschrieben werden.', 'pages_draft_edit_active' => [ @@ -339,7 +339,7 @@ return [ 'comment_deleted_success' => 'Kommentar gelöscht', 'comment_created_success' => 'Kommentar hinzugefügt', 'comment_updated_success' => 'Kommentar aktualisiert', - 'comment_delete_confirm' => 'Möchtst Du diesen Kommentar wirklich löschen?', + 'comment_delete_confirm' => 'Möchtest Du diesen Kommentar wirklich löschen?', 'comment_in_reply_to' => 'Antwort auf :commentId', // Revision @@ -357,7 +357,7 @@ return [ 'copy_consider_access' => 'Eine Veränderung der Position, Besitzers oder Berechtigungen könnte dafür sorgen, dass Unberechtigte, Zugriff bekommen.', // Conversions - 'convert_to_shelf' => 'Convert to Shelf', + 'convert_to_shelf' => 'In Regal umwandeln', 'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.', 'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.', 'convert_book' => 'Convert Book', diff --git a/resources/lang/de_informal/errors.php b/resources/lang/de_informal/errors.php index d44b9a65b..cb4ff7475 100644 --- a/resources/lang/de_informal/errors.php +++ b/resources/lang/de_informal/errors.php @@ -14,7 +14,7 @@ return [ 'email_confirmation_invalid' => 'Der Bestätigungslink ist nicht gültig oder wurde bereits verwendet. Bitte registriere dich erneut.', 'email_confirmation_expired' => 'Der Bestätigungslink ist abgelaufen. Es wurde eine neue Bestätigungs-E-Mail gesendet.', 'email_confirmation_awaiting' => 'Die E-Mail-Adresse für das verwendete Konto muss bestätigt werden', - 'ldap_fail_anonymous' => 'Anonymer LDAP-Zugriff ist fehlgeschlafgen', + 'ldap_fail_anonymous' => 'Anonymer LDAP-Zugriff ist fehlgeschlagen', 'ldap_fail_authed' => 'LDAP-Zugriff mit DN und Passwort ist fehlgeschlagen', 'ldap_extension_not_installed' => 'LDAP-PHP-Erweiterung ist nicht installiert', 'ldap_cannot_connect' => 'Die Verbindung zum LDAP-Server ist fehlgeschlagen. Beim initialen Verbindungsaufbau trat ein Fehler auf', @@ -67,11 +67,11 @@ return [ 'guests_cannot_save_drafts' => 'Gäste können keine Entwürfe speichern', // Users - 'users_cannot_delete_only_admin' => 'Du kannst den einzigen Administrator nicht löschen.', + 'users_cannot_delete_only_admin' => 'Du kannst den einzigen Administrator nicht löschen', 'users_cannot_delete_guest' => 'Du kannst den Gast-Benutzer nicht löschen', // Roles - 'role_cannot_be_edited' => 'Diese Rolle kann nicht bearbeitet werden.', + 'role_cannot_be_edited' => 'Diese Rolle kann nicht bearbeitet werden', 'role_system_cannot_be_deleted' => 'Dies ist eine Systemrolle und kann nicht gelöscht werden', 'role_registration_default_cannot_delete' => 'Diese Rolle kann nicht gelöscht werden, solange sie als Standardrolle für neue Registrierungen gesetzt ist', 'role_cannot_remove_only_admin' => 'Dieser Benutzer ist der einzige Benutzer, welchem die Administratorrolle zugeordnet ist. Ordnen Sie die Administratorrolle einem anderen Benutzer zu, bevor Sie versuchen, sie hier zu entfernen.', @@ -81,7 +81,7 @@ return [ 'cannot_add_comment_to_draft' => 'Du kannst keine Kommentare zu einem Entwurf hinzufügen.', 'comment_add' => 'Beim Hinzufügen des Kommentars ist ein Fehler aufgetreten.', 'comment_delete' => 'Beim Löschen des Kommentars ist ein Fehler aufgetreten.', - 'empty_comment' => 'Kann keinen leeren Kommentar hinzufügen', + 'empty_comment' => 'Kann keinen leeren Kommentar hinzufügen.', // Error pages '404_page_not_found' => 'Seite nicht gefunden', diff --git a/resources/lang/de_informal/settings.php b/resources/lang/de_informal/settings.php index 6cdeaea19..0c1b4d98a 100644 --- a/resources/lang/de_informal/settings.php +++ b/resources/lang/de_informal/settings.php @@ -20,13 +20,13 @@ return [ 'app_name_desc' => 'Dieser Name wird im Header und in E-Mails angezeigt.', 'app_name_header' => 'Anwendungsname im Header anzeigen?', 'app_public_access' => 'Öffentlicher Zugriff', - 'app_public_access_desc' => 'Wenn Sie diese Option aktivieren, können Besucher, die nicht angemeldet sind, auf Inhalte in Ihrer BookStack-Instanz zugreifen.', + 'app_public_access_desc' => 'Wenn diese Option aktiviert ist, können Besucher, die nicht angemeldet sind, auf Inhalte in Deiner BookStack-Instanz zugreifen.', 'app_public_access_desc_guest' => 'Der Zugang für öffentliche Besucher kann über den Benutzer "Guest" gesteuert werden.', 'app_public_access_toggle' => 'Öffentlichen Zugriff erlauben', 'app_public_viewing' => 'Öffentliche Ansicht erlauben?', 'app_secure_images' => 'Erhöhte Sicherheit für hochgeladene Bilder aktivieren?', 'app_secure_images_toggle' => 'Aktiviere Bild-Upload mit höherer Sicherheit', - 'app_secure_images_desc' => 'Aus Leistungsgründen sind alle Bilder öffentlich sichtbar. Diese Option fügt zufällige, schwer zu eratene, Zeichenketten zu Bild-URLs hinzu. Stellen sie sicher, dass Verzeichnisindizes deaktiviert sind, um einen einfachen Zugriff zu verhindern.', + 'app_secure_images_desc' => 'Aus Leistungsgründen sind alle Bilder öffentlich sichtbar. Diese Option fügt zufällige, schwer zu erratene Zeichenketten zu Bild-URLs hinzu. Stellen sie sicher, dass Verzeichnisindizes deaktiviert sind, um einen einfachen Zugriff zu verhindern.', 'app_default_editor' => 'Standard-Seiten-Editor', 'app_default_editor_desc' => 'Wählen Sie aus, welcher Editor standardmäßig beim Bearbeiten neuer Seiten verwendet wird. Dies kann auf einer Seitenebene überschrieben werden, wenn es die Berechtigungen erlauben.', 'app_custom_html' => 'Benutzerdefinierter HTML Inhalt', @@ -80,9 +80,9 @@ Hinweis: Benutzer können ihre E-Mail Adresse nach erfolgreicher Registrierung 'maint_image_cleanup_desc' => 'Überprüft Seiten- und Versionsinhalte auf ungenutzte und mehrfach vorhandene Bilder. Erstelle vor dem Start ein Backup Deiner Datenbank und Bilder.', 'maint_delete_images_only_in_revisions' => 'Lösche auch Bilder, die nur in alten Seitenüberarbeitungen vorhanden sind', 'maint_image_cleanup_run' => 'Reinigung starten', - 'maint_image_cleanup_warning' => ':count eventuell unbenutze Bilder wurden gefunden. Möchtest Du diese Bilder löschen?', - 'maint_image_cleanup_success' => ':count eventuell unbenutze Bilder wurden gefunden und gelöscht.', - 'maint_image_cleanup_nothing_found' => 'Keine unbenutzen Bilder gefunden. Nichts zu löschen!', + 'maint_image_cleanup_warning' => ':count eventuell unbenutzte Bilder wurden gefunden. Möchtest Du diese Bilder löschen?', + 'maint_image_cleanup_success' => ':count eventuell unbenutzte Bilder wurden gefunden und gelöscht.', + 'maint_image_cleanup_nothing_found' => 'Keine unbenutzten Bilder gefunden. Nichts zu löschen!', 'maint_send_test_email' => 'Test Email versenden', 'maint_send_test_email_desc' => 'Dies sendet eine Test E-Mail an die in deinem Profil angegebene E-Mail-Adresse.', 'maint_send_test_email_run' => 'Sende eine Test E-Mail', diff --git a/resources/lang/de_informal/validation.php b/resources/lang/de_informal/validation.php index 61cd7409b..1c94d62c6 100644 --- a/resources/lang/de_informal/validation.php +++ b/resources/lang/de_informal/validation.php @@ -99,7 +99,7 @@ return [ 'array' => ':attribute muss :size Elemente enthalten.', ], 'string' => ':attribute muss eine Zeichenkette sein.', - 'timezone' => ':attribute muss eine valide zeitzone sein.', + 'timezone' => ':attribute muss eine valide Zeitzone sein.', 'totp' => 'Der angegebene Code ist ungültig oder abgelaufen.', 'unique' => ':attribute wird bereits verwendet.', 'url' => ':attribute ist kein valides Format.', From 4fb85a9a5cd75f1f0a0f605a916d4c3a746ee672 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Wed, 13 Jul 2022 15:23:03 +0100 Subject: [PATCH 028/246] Started removal of non-view permission queries Updated ajax search and entity selector usage to display and handle items that the user does not have permission to interact with. Started logic changes to not allow permission type to be passed around, with views instead being the fixed sole permission. --- app/Auth/Permissions/PermissionApplicator.php | 5 +++-- app/Auth/User.php | 2 +- app/Entities/Queries/Popular.php | 4 ++-- app/Entities/Tools/SearchRunner.php | 8 ++++---- app/Http/Controllers/SearchController.php | 7 +++---- resources/sass/_lists.scss | 8 ++++++++ resources/sass/_variables.scss | 6 ++++++ resources/views/entities/list-item.blade.php | 8 +++++++- resources/views/search/parts/entity-ajax-list.blade.php | 7 ++++++- routes/web.php | 7 +++++++ 10 files changed, 47 insertions(+), 15 deletions(-) diff --git a/app/Auth/Permissions/PermissionApplicator.php b/app/Auth/Permissions/PermissionApplicator.php index 3dc529e32..40a7f6116 100644 --- a/app/Auth/Permissions/PermissionApplicator.php +++ b/app/Auth/Permissions/PermissionApplicator.php @@ -72,6 +72,7 @@ class PermissionApplicator $action = $permission; } + // TODO - Use a non-query based check $hasAccess = $this->entityRestrictionQuery($baseQuery, $action)->count() > 0; $this->clean(); @@ -163,14 +164,14 @@ class PermissionApplicator /** * Add restrictions for a generic entity. */ - public function enforceEntityRestrictions(Entity $entity, Builder $query, string $action = 'view'): Builder + public function enforceEntityRestrictions(Entity $entity, Builder $query): Builder { if ($entity instanceof Page) { // Prevent drafts being visible to others. $this->enforceDraftVisibilityOnQuery($query); } - return $this->entityRestrictionQuery($query, $action); + return $this->entityRestrictionQuery($query, 'view'); } /** diff --git a/app/Auth/User.php b/app/Auth/User.php index 4e2183244..c060d5ec8 100644 --- a/app/Auth/User.php +++ b/app/Auth/User.php @@ -163,7 +163,7 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon } /** - * Get all permissions belonging to a the current user. + * Get all permissions belonging to the current user. */ protected function permissions(): Collection { diff --git a/app/Entities/Queries/Popular.php b/app/Entities/Queries/Popular.php index e6b22a1c9..66006df1b 100644 --- a/app/Entities/Queries/Popular.php +++ b/app/Entities/Queries/Popular.php @@ -7,10 +7,10 @@ use Illuminate\Support\Facades\DB; class Popular extends EntityQuery { - public function run(int $count, int $page, array $filterModels = null, string $action = 'view') + public function run(int $count, int $page, array $filterModels = null) { $query = $this->permissionService() - ->filterRestrictedEntityRelations(View::query(), 'views', 'viewable_id', 'viewable_type', $action) + ->filterRestrictedEntityRelations(View::query(), 'views', 'viewable_id', 'viewable_type', 'view') ->select('*', 'viewable_id', 'viewable_type', DB::raw('SUM(views) as view_count')) ->groupBy('viewable_id', 'viewable_type') ->orderBy('view_count', 'desc'); diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index 5d94379c9..1dcc2eb44 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -54,7 +54,7 @@ class SearchRunner * * @return array{total: int, count: int, has_more: bool, results: Entity[]} */ - public function searchEntities(SearchOptions $searchOpts, string $entityType = 'all', int $page = 1, int $count = 20, string $action = 'view'): array + public function searchEntities(SearchOptions $searchOpts, string $entityType = 'all', int $page = 1, int $count = 20): array { $entityTypes = array_keys($this->entityProvider->all()); $entityTypesToSearch = $entityTypes; @@ -75,7 +75,7 @@ class SearchRunner } $entityModelInstance = $this->entityProvider->get($entityType); - $searchQuery = $this->buildQuery($searchOpts, $entityModelInstance, $action); + $searchQuery = $this->buildQuery($searchOpts, $entityModelInstance); $entityTotal = $searchQuery->count(); $searchResults = $this->getPageOfDataFromQuery($searchQuery, $entityModelInstance, $page, $count); @@ -159,7 +159,7 @@ class SearchRunner /** * Create a search query for an entity. */ - protected function buildQuery(SearchOptions $searchOpts, Entity $entityModelInstance, string $action = 'view'): EloquentBuilder + protected function buildQuery(SearchOptions $searchOpts, Entity $entityModelInstance): EloquentBuilder { $entityQuery = $entityModelInstance->newQuery(); @@ -193,7 +193,7 @@ class SearchRunner } } - return $this->permissions->enforceEntityRestrictions($entityModelInstance, $entityQuery, $action); + return $this->permissions->enforceEntityRestrictions($entityModelInstance, $entityQuery); } /** diff --git a/app/Http/Controllers/SearchController.php b/app/Http/Controllers/SearchController.php index 6b2be5a2d..4a002298c 100644 --- a/app/Http/Controllers/SearchController.php +++ b/app/Http/Controllers/SearchController.php @@ -12,7 +12,6 @@ use Illuminate\Http\Request; class SearchController extends Controller { protected $searchRunner; - protected $entityContextManager; public function __construct(SearchRunner $searchRunner) { @@ -79,12 +78,12 @@ class SearchController extends Controller // Search for entities otherwise show most popular if ($searchTerm !== false) { $searchTerm .= ' {type:' . implode('|', $entityTypes) . '}'; - $entities = $this->searchRunner->searchEntities(SearchOptions::fromString($searchTerm), 'all', 1, 20, $permission)['results']; + $entities = $this->searchRunner->searchEntities(SearchOptions::fromString($searchTerm), 'all', 1, 20)['results']; } else { - $entities = (new Popular())->run(20, 0, $entityTypes, $permission); + $entities = (new Popular())->run(20, 0, $entityTypes); } - return view('search.parts.entity-ajax-list', ['entities' => $entities]); + return view('search.parts.entity-ajax-list', ['entities' => $entities, 'permission' => $permission]); } /** diff --git a/resources/sass/_lists.scss b/resources/sass/_lists.scss index 19060fbbf..5e251f9c7 100644 --- a/resources/sass/_lists.scss +++ b/resources/sass/_lists.scss @@ -443,6 +443,14 @@ ul.pagination { } } +.entity-list-item.disabled { + pointer-events: none; + cursor: not-allowed; + opacity: 0.8; + user-select: none; + background: var(--bg-disabled); +} + .entity-list-item-path-sep { display: inline-block; vertical-align: top; diff --git a/resources/sass/_variables.scss b/resources/sass/_variables.scss index 6b57147ef..3cb2dd4ed 100644 --- a/resources/sass/_variables.scss +++ b/resources/sass/_variables.scss @@ -45,6 +45,12 @@ $fs-s: 12px; --color-chapter: #af4d0d; --color-book: #077b70; --color-bookshelf: #a94747; + + --bg-disabled: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='100%25' width='100%25'%3E%3Cdefs%3E%3Cpattern id='doodad' width='19' height='19' viewBox='0 0 40 40' patternUnits='userSpaceOnUse' patternTransform='rotate(143)'%3E%3Crect width='100%25' height='100%25' fill='rgba(42, 67, 101,0)'/%3E%3Cpath d='M-10 30h60v20h-60zM-10-10h60v20h-60' fill='rgba(26, 32, 44,0)'/%3E%3Cpath d='M-10 10h60v20h-60zM-10-30h60v20h-60z' fill='rgba(0, 0, 0,0.05)'/%3E%3C/pattern%3E%3C/defs%3E%3Crect fill='url(%23doodad)' height='200%25' width='200%25'/%3E%3C/svg%3E"); +} + +:root.dark-mode { + --bg-disabled: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' height='100%25' width='100%25'%3E%3Cdefs%3E%3Cpattern id='doodad' width='19' height='19' viewBox='0 0 40 40' patternUnits='userSpaceOnUse' patternTransform='rotate(143)'%3E%3Crect width='100%25' height='100%25' fill='rgba(42, 67, 101,0)'/%3E%3Cpath d='M-10 30h60v20h-60zM-10-10h60v20h-60' fill='rgba(26, 32, 44,0)'/%3E%3Cpath d='M-10 10h60v20h-60zM-10-30h60v20h-60z' fill='rgba(255, 255, 255,0.05)'/%3E%3C/pattern%3E%3C/defs%3E%3Crect fill='url(%23doodad)' height='200%25' width='200%25'/%3E%3C/svg%3E"); } $positive: #0f7d15; diff --git a/resources/views/entities/list-item.blade.php b/resources/views/entities/list-item.blade.php index 44e06753d..5314c8446 100644 --- a/resources/views/entities/list-item.blade.php +++ b/resources/views/entities/list-item.blade.php @@ -1,7 +1,13 @@ -@component('entities.list-item-basic', ['entity' => $entity]) +@component('entities.list-item-basic', ['entity' => $entity, 'classes' => (($locked ?? false) ? 'disabled ' : '') . ($classes ?? '') ])
+ @if($locked ?? false) +
+ @icon('lock')You don't have the required permissions to select this item. +
+ @endif + @if($showPath ?? false) @if($entity->relationLoaded('book') && $entity->book) {{ $entity->book->getShortName(42) }} diff --git a/resources/views/search/parts/entity-ajax-list.blade.php b/resources/views/search/parts/entity-ajax-list.blade.php index a4eedf75e..9340ccdc5 100644 --- a/resources/views/search/parts/entity-ajax-list.blade.php +++ b/resources/views/search/parts/entity-ajax-list.blade.php @@ -2,7 +2,12 @@ @if(count($entities) > 0) @foreach($entities as $index => $entity) - @include('entities.list-item', ['entity' => $entity, 'showPath' => true]) + @include('entities.list-item', [ + 'entity' => $entity, + 'showPath' => true, + 'locked' => $permission !== 'view' && !userCan($permission, $entity) + ]) + @if($index !== count($entities) - 1)
@endif diff --git a/routes/web.php b/routes/web.php index 5e16e5333..9b562703c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -38,6 +38,13 @@ use Illuminate\View\Middleware\ShareErrorsFromSession; Route::get('/status', [StatusController::class, 'show']); Route::get('/robots.txt', [HomeController::class, 'robots']); +Route::get('/test', function() { + $book = \BookStack\Entities\Models\Book::query()->where('slug', '=', 'k5TrhXxaNb')->firstOrFail(); + $builder= app()->make(\BookStack\Auth\Permissions\JointPermissionBuilder::class); + $builder->rebuildForEntity($book); + return 'finished'; +})->withoutMiddleware('web'); + // Authenticated routes... Route::middleware('auth')->group(function () { From 7e04f70bf3151b0e58b315ad576f4c0c4b358176 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 14 Jul 2022 01:34:57 +0100 Subject: [PATCH 029/246] Tweaked docker dev container to work with m1 apple silicon Tested on m1 macbook, needs testing on amd64 --- dev/docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/docker/Dockerfile b/dev/docker/Dockerfile index 615eb2b2a..349e315d2 100644 --- a/dev/docker/Dockerfile +++ b/dev/docker/Dockerfile @@ -6,7 +6,7 @@ WORKDIR /app # Install additional dependacnies and configure apache RUN apt-get update -y \ && apt-get install -y git zip unzip libpng-dev libldap2-dev libzip-dev wait-for-it \ - && docker-php-ext-configure ldap --with-libdir=lib/x86_64-linux-gnu \ + && docker-php-ext-configure ldap --with-libdir="lib/$(gcc -dumpmachine)" \ && docker-php-ext-install pdo_mysql gd ldap zip \ && pecl install xdebug \ && docker-php-ext-enable xdebug \ From 77b57c068fcd3a8fb7b214c37f90640d59987f0d Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 14 Jul 2022 22:50:28 +0100 Subject: [PATCH 030/246] New translations activities.php (German) --- resources/lang/de/activities.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/resources/lang/de/activities.php b/resources/lang/de/activities.php index fc7291a5d..3cf49b1a4 100644 --- a/resources/lang/de/activities.php +++ b/resources/lang/de/activities.php @@ -6,13 +6,13 @@ return [ // Pages - 'page_create' => 'hat die Seite erstellt', - 'page_create_notification' => 'Die Seite wurde erfolgreich erstellt', + 'page_create' => 'erstellte Seite', + 'page_create_notification' => 'Seite erfolgreich erstellt', 'page_update' => 'hat die Seite aktualisiert', - 'page_update_notification' => 'Die Seite wurde erfolgreich aktualisiert', - 'page_delete' => 'hat die Seite gelöscht', - 'page_delete_notification' => 'Die Seite wurde erfolgreich gelöscht', - 'page_restore' => 'hat die Seite wiederhergestellt', + 'page_update_notification' => 'Seite erfolgreich aktualisiert', + 'page_delete' => 'gelöschte Seite', + 'page_delete_notification' => 'Seite erfolgreich gelöscht', + 'page_restore' => 'wiederhergestellte Seite', 'page_restore_notification' => 'Die Seite wurde erfolgreich wiederhergestellt', 'page_move' => 'hat die Seite verschoben', @@ -28,8 +28,8 @@ return [ // Books 'book_create' => 'hat das Buch erstellt', 'book_create_notification' => 'Das Buch wurde erfolgreich erstellt', - 'book_create_from_chapter' => 'converted chapter to book', - 'book_create_from_chapter_notification' => 'Chapter successfully converted to a book', + 'book_create_from_chapter' => 'umgewandeltes Kapitel zum Buch', + 'book_create_from_chapter_notification' => 'Kapitel erfolgreich in ein Buch konvertiert', 'book_update' => 'hat das Buch aktualisiert', 'book_update_notification' => 'Das Buch wurde erfolgreich aktualisiert', 'book_delete' => 'hat das Buch gelöscht', @@ -40,8 +40,8 @@ return [ // Bookshelves 'bookshelf_create' => 'erstelltes Bücherregal', 'bookshelf_create_notification' => 'Das Bücherregal wurde erfolgreich erstellt', - 'bookshelf_create_from_book' => 'converted book to bookshelf', - 'bookshelf_create_from_book_notification' => 'Book successfully converted to a shelf', + 'bookshelf_create_from_book' => 'umgewandeltes Buch zum Regal', + 'bookshelf_create_from_book_notification' => 'Buch erfolgreich in ein Regal konvertiert', 'bookshelf_update' => 'hat das Bücherregal geändert', 'bookshelf_update_notification' => 'Das Bücherregal wurde erfolgreich geändert', 'bookshelf_delete' => 'hat das Bücherregal gelöscht', From bfbd0fc16882412ed70c964d0c0027595380497f Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Thu, 14 Jul 2022 23:50:40 +0100 Subject: [PATCH 031/246] New translations activities.php (German) --- resources/lang/de/activities.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/lang/de/activities.php b/resources/lang/de/activities.php index 3cf49b1a4..b21788161 100644 --- a/resources/lang/de/activities.php +++ b/resources/lang/de/activities.php @@ -13,11 +13,11 @@ return [ 'page_delete' => 'gelöschte Seite', 'page_delete_notification' => 'Seite erfolgreich gelöscht', 'page_restore' => 'wiederhergestellte Seite', - 'page_restore_notification' => 'Die Seite wurde erfolgreich wiederhergestellt', - 'page_move' => 'hat die Seite verschoben', + 'page_restore_notification' => 'Seite erfolgreich wiederhergestellt', + 'page_move' => 'Seite verschoben', // Chapters - 'chapter_create' => 'hat das Kapitel erstellt', + 'chapter_create' => 'erstellte Kapitel', 'chapter_create_notification' => 'Das Kapitel wurde erfolgreich erstellt', 'chapter_update' => 'hat das Kapitel geändert', 'chapter_update_notification' => 'Das Kapitel wurde erfolgreich aktualisiert', From 23f9b4d217b3e6f0f957c0864cb826186e127581 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 15 Jul 2022 07:39:06 +0100 Subject: [PATCH 032/246] New translations auth.php (German) --- resources/lang/de/auth.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/lang/de/auth.php b/resources/lang/de/auth.php index 3005fd93c..df047f914 100644 --- a/resources/lang/de/auth.php +++ b/resources/lang/de/auth.php @@ -39,9 +39,9 @@ return [ 'register_success' => 'Vielen Dank für Ihre Registrierung! Die Daten sind gespeichert und Sie sind angemeldet.', // Login auto-initiation - 'auto_init_starting' => 'Attempting Login', - 'auto_init_starting_desc' => 'We\'re contacting your authentication system to start the login process. If there\'s no progress after 5 seconds you can try clicking the link below.', - 'auto_init_start_link' => 'Proceed with authentication', + 'auto_init_starting' => 'Anmeldeversuche', + 'auto_init_starting_desc' => 'Wir verbinden und mit Ihrem Authentifizierungssystem um den Anmeldeprozess zu starten. Sollte es nach 5 Sekunden nicht weitergehen, klicken Sie bitte auf den unten stehenden Link.', + 'auto_init_start_link' => 'Mit Authentifizierung fortfahren', // Password Reset 'reset_password' => 'Passwort vergessen', From ad8d8dde2db18d2bbba742d2c38abe76c3d39dd5 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 15 Jul 2022 07:39:07 +0100 Subject: [PATCH 033/246] New translations entities.php (German) --- resources/lang/de/entities.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/resources/lang/de/entities.php b/resources/lang/de/entities.php index 61bdddfe3..8bd523b5f 100644 --- a/resources/lang/de/entities.php +++ b/resources/lang/de/entities.php @@ -360,11 +360,11 @@ return [ 'convert_to_shelf' => 'In Regal umwandeln', 'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.', 'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.', - 'convert_book' => 'Convert Book', - 'convert_book_confirm' => 'Are you sure you want to convert this book?', - 'convert_undo_warning' => 'This cannot be as easily undone.', - 'convert_to_book' => 'Convert to Book', + 'convert_book' => 'Buch umwandeln', + 'convert_book_confirm' => 'Sind Sie sicher, dass Sie dieses Buch umwandeln möchten?', + 'convert_undo_warning' => 'Dies kann nicht so einfach rückgängig gemacht werden.', + 'convert_to_book' => 'In Buch umwandeln', 'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.', - 'convert_chapter' => 'Convert Chapter', - 'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?', + 'convert_chapter' => 'Kapitel umwandeln', + 'convert_chapter_confirm' => 'Sind Sie sicher, dass Sie dieses Kapitel umwandeln möchten?', ]; From 2b4b7c68ccafafb99adf18f6f7d49ad168846775 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Fri, 15 Jul 2022 08:45:23 +0100 Subject: [PATCH 034/246] New translations entities.php (German) --- resources/lang/de/entities.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/resources/lang/de/entities.php b/resources/lang/de/entities.php index 8bd523b5f..beb984bfd 100644 --- a/resources/lang/de/entities.php +++ b/resources/lang/de/entities.php @@ -358,13 +358,13 @@ return [ // Conversions 'convert_to_shelf' => 'In Regal umwandeln', - 'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.', - 'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.', + 'convert_to_shelf_contents_desc' => 'Sie können dieses Buch in ein neues Regal mit dem gleichen Inhalt umwandeln. Kapitel in diesem Buch werden in neue Bücher umgewandelt. Wenn dieses Buch Seiten enthält, die nicht in einem Kapitel sind, wird dieses Buch entsprechend umbenannt und wird Teil des neuen Regals.', + 'convert_to_shelf_permissions_desc' => 'Alle Berechtigungen dieses Buches werden in das neue Regal kopiert und in alle darin enthaltenen neuen Bücher, die keine eigenen Berechtigungen haben. Beachten Sie, dass die Berechtigungen für Regale nicht automatisch auf die enthaltenen Inhalte angewendet werden, wie es bei Büchern der Fall ist.', 'convert_book' => 'Buch umwandeln', 'convert_book_confirm' => 'Sind Sie sicher, dass Sie dieses Buch umwandeln möchten?', 'convert_undo_warning' => 'Dies kann nicht so einfach rückgängig gemacht werden.', 'convert_to_book' => 'In Buch umwandeln', - 'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.', + 'convert_to_book_desc' => 'Sie können dieses Kapitel zu einem neuen Buch mit dem gleichen Inhalt umwandeln. Alle Berechtigungen für dieses Kapitel werden in das neue Buch übernommen, aber alle vom ursprünglichen Buch vererbten Berechtigungen werden nicht übernommen, daher kann es zu Änderungen im Zugriff kommen.', 'convert_chapter' => 'Kapitel umwandeln', 'convert_chapter_confirm' => 'Sind Sie sicher, dass Sie dieses Kapitel umwandeln möchten?', ]; From 1d875ccfb7c62854c9c3253a0d83b39310fefbf8 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 16 Jul 2022 13:17:08 +0100 Subject: [PATCH 035/246] Continued removal of joint permission non-view queries Cleaned up PermissionApplicator to remove old cache system which was hardly ever actuall caching anything since it was reset after each public method run. Changed the scope of 'userCanOnAny' to just check entity permissions, and added protections of action scope creep, in case a role permission action was passed by mistake. --- app/Auth/Permissions/PermissionApplicator.php | 109 ++++++------------ app/Entities/Models/Entity.php | 11 +- app/Entities/Queries/Popular.php | 2 +- app/Entities/Queries/RecentlyViewed.php | 3 +- app/Entities/Queries/TopFavourites.php | 2 +- app/Http/Controllers/BookshelfController.php | 4 +- app/helpers.php | 8 +- resources/views/chapters/show.blade.php | 2 +- resources/views/pages/show.blade.php | 2 +- 9 files changed, 49 insertions(+), 94 deletions(-) diff --git a/app/Auth/Permissions/PermissionApplicator.php b/app/Auth/Permissions/PermissionApplicator.php index 40a7f6116..cf95f2854 100644 --- a/app/Auth/Permissions/PermissionApplicator.php +++ b/app/Auth/Permissions/PermissionApplicator.php @@ -11,37 +11,10 @@ use BookStack\Traits\HasCreatorAndUpdater; use BookStack\Traits\HasOwner; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Query\Builder as QueryBuilder; +use InvalidArgumentException; class PermissionApplicator { - /** - * @var ?array - */ - protected $userRoles = null; - - /** - * @var ?User - */ - protected $currentUserModel = null; - - /** - * Get the roles for the current logged in user. - */ - protected function getCurrentUserRoles(): array - { - if (!is_null($this->userRoles)) { - return $this->userRoles; - } - - if (auth()->guest()) { - $this->userRoles = [Role::getSystemRole('public')->id]; - } else { - $this->userRoles = $this->currentUser()->roles->pluck('id')->values()->all(); - } - - return $this->userRoles; - } - /** * Checks if an entity has a restriction set upon it. * @@ -74,7 +47,6 @@ class PermissionApplicator // TODO - Use a non-query based check $hasAccess = $this->entityRestrictionQuery($baseQuery, $action)->count() > 0; - $this->clean(); return $hasAccess; } @@ -83,25 +55,23 @@ class PermissionApplicator * Checks if a user has the given permission for any items in the system. * Can be passed an entity instance to filter on a specific type. */ - public function checkUserHasPermissionOnAnything(string $permission, ?string $entityClass = null): bool + public function checkUserHasEntityPermissionOnAny(string $action, string $entityClass = ''): bool { - $userRoleIds = $this->currentUser()->roles()->select('id')->pluck('id')->toArray(); - $userId = $this->currentUser()->id; + if (strpos($action, '-') !== false) { + throw new InvalidArgumentException("Action should be a simple entity permission action, not a role permission"); + } - $permissionQuery = JointPermission::query() - ->where('action', '=', $permission) - ->whereIn('role_id', $userRoleIds) - ->where(function (Builder $query) use ($userId) { - $this->addJointHasPermissionCheck($query, $userId); - }); + $permissionQuery = EntityPermission::query() + ->where('action', '=', $action) + ->whereIn('role_id', $this->getCurrentUserRoleIds()); - if (!is_null($entityClass)) { - $entityInstance = app($entityClass); - $permissionQuery = $permissionQuery->where('entity_type', '=', $entityInstance->getMorphClass()); + if (!empty($entityClass)) { + /** @var Entity $entityInstance */ + $entityInstance = app()->make($entityClass); + $permissionQuery = $permissionQuery->where('restrictable_type', '=', $entityInstance->getMorphClass()); } $hasPermission = $permissionQuery->count() > 0; - $this->clean(); return $hasPermission; } @@ -114,7 +84,8 @@ class PermissionApplicator { $q = $query->where(function ($parentQuery) use ($action) { $parentQuery->whereHas('jointPermissions', function ($permissionQuery) use ($action) { - $permissionQuery->whereIn('role_id', $this->getCurrentUserRoles()) + $permissionQuery->whereIn('role_id', $this->getCurrentUserRoleIds()) + // TODO - Delete line once only views ->where('action', '=', $action) ->where(function (Builder $query) { $this->addJointHasPermissionCheck($query, $this->currentUser()->id); @@ -122,23 +93,20 @@ class PermissionApplicator }); }); - $this->clean(); - return $q; } /** * Limited the given entity query so that the query will only - * return items that the user has permission for the given ability. + * return items that the user has view permission for. */ - public function restrictEntityQuery(Builder $query, string $ability = 'view'): Builder + public function restrictEntityQuery(Builder $query): Builder { - $this->clean(); - - return $query->where(function (Builder $parentQuery) use ($ability) { - $parentQuery->whereHas('jointPermissions', function (Builder $permissionQuery) use ($ability) { - $permissionQuery->whereIn('role_id', $this->getCurrentUserRoles()) - ->where('action', '=', $ability) + return $query->where(function (Builder $parentQuery) { + $parentQuery->whereHas('jointPermissions', function (Builder $permissionQuery) { + $permissionQuery->whereIn('role_id', $this->getCurrentUserRoleIds()) + // TODO - Delete line once only views + ->where('action', '=', 'view') ->where(function (Builder $query) { $this->addJointHasPermissionCheck($query, $this->currentUser()->id); }); @@ -181,18 +149,18 @@ class PermissionApplicator * * @param Builder|QueryBuilder $query */ - public function filterRestrictedEntityRelations($query, string $tableName, string $entityIdColumn, string $entityTypeColumn, string $action = 'view') + public function filterRestrictedEntityRelations($query, string $tableName, string $entityIdColumn, string $entityTypeColumn) { $tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn]; $pageMorphClass = (new Page())->getMorphClass(); - $q = $query->whereExists(function ($permissionQuery) use (&$tableDetails, $action) { + $q = $query->whereExists(function ($permissionQuery) use (&$tableDetails) { /** @var Builder $permissionQuery */ $permissionQuery->select(['role_id'])->from('joint_permissions') ->whereColumn('joint_permissions.entity_id', '=', $tableDetails['tableName'] . '.' . $tableDetails['entityIdColumn']) ->whereColumn('joint_permissions.entity_type', '=', $tableDetails['tableName'] . '.' . $tableDetails['entityTypeColumn']) - ->where('joint_permissions.action', '=', $action) - ->whereIn('joint_permissions.role_id', $this->getCurrentUserRoles()) + ->where('joint_permissions.action', '=', 'view') + ->whereIn('joint_permissions.role_id', $this->getCurrentUserRoleIds()) ->where(function (QueryBuilder $query) { $this->addJointHasPermissionCheck($query, $this->currentUser()->id); }); @@ -207,8 +175,6 @@ class PermissionApplicator }); }); - $this->clean(); - return $q; } @@ -228,7 +194,7 @@ class PermissionApplicator ->whereColumn('joint_permissions.entity_id', '=', $fullEntityIdColumn) ->where('joint_permissions.entity_type', '=', $morphClass) ->where('joint_permissions.action', '=', 'view') - ->whereIn('joint_permissions.role_id', $this->getCurrentUserRoles()) + ->whereIn('joint_permissions.role_id', $this->getCurrentUserRoleIds()) ->where(function (QueryBuilder $query) { $this->addJointHasPermissionCheck($query, $this->currentUser()->id); }); @@ -251,8 +217,6 @@ class PermissionApplicator }); } - $this->clean(); - return $q; } @@ -273,21 +237,22 @@ class PermissionApplicator /** * Get the current user. */ - private function currentUser(): User + protected function currentUser(): User { - if (is_null($this->currentUserModel)) { - $this->currentUserModel = user(); - } - - return $this->currentUserModel; + return user(); } /** - * Clean the cached user elements. + * Get the roles for the current logged-in user. + * + * @return int[] */ - private function clean(): void + protected function getCurrentUserRoleIds(): array { - $this->currentUserModel = null; - $this->userRoles = null; + if (auth()->guest()) { + return [Role::getSystemRole('public')->id]; + } + + return $this->currentUser()->roles->pluck('id')->values()->all(); } } diff --git a/app/Entities/Models/Entity.php b/app/Entities/Models/Entity.php index 84d31d82d..17f018a56 100644 --- a/app/Entities/Models/Entity.php +++ b/app/Entities/Models/Entity.php @@ -44,7 +44,6 @@ use Illuminate\Database\Eloquent\SoftDeletes; * @property Collection $tags * * @method static Entity|Builder visible() - * @method static Entity|Builder hasPermission(string $permission) * @method static Builder withLastView() * @method static Builder withViewCount() */ @@ -69,15 +68,7 @@ abstract class Entity extends Model implements Sluggable, Favouritable, Viewable */ public function scopeVisible(Builder $query): Builder { - return $this->scopeHasPermission($query, 'view'); - } - - /** - * Scope the query to those entities that the current user has the given permission for. - */ - public function scopeHasPermission(Builder $query, string $permission) - { - return app()->make(PermissionApplicator::class)->restrictEntityQuery($query, $permission); + return app()->make(PermissionApplicator::class)->restrictEntityQuery($query); } /** diff --git a/app/Entities/Queries/Popular.php b/app/Entities/Queries/Popular.php index 66006df1b..82786e3c6 100644 --- a/app/Entities/Queries/Popular.php +++ b/app/Entities/Queries/Popular.php @@ -10,7 +10,7 @@ class Popular extends EntityQuery public function run(int $count, int $page, array $filterModels = null) { $query = $this->permissionService() - ->filterRestrictedEntityRelations(View::query(), 'views', 'viewable_id', 'viewable_type', 'view') + ->filterRestrictedEntityRelations(View::query(), 'views', 'viewable_id', 'viewable_type') ->select('*', 'viewable_id', 'viewable_type', DB::raw('SUM(views) as view_count')) ->groupBy('viewable_id', 'viewable_type') ->orderBy('view_count', 'desc'); diff --git a/app/Entities/Queries/RecentlyViewed.php b/app/Entities/Queries/RecentlyViewed.php index 5a29ecd72..38d1f1be4 100644 --- a/app/Entities/Queries/RecentlyViewed.php +++ b/app/Entities/Queries/RecentlyViewed.php @@ -18,8 +18,7 @@ class RecentlyViewed extends EntityQuery View::query(), 'views', 'viewable_id', - 'viewable_type', - 'view' + 'viewable_type' ) ->orderBy('views.updated_at', 'desc') ->where('user_id', '=', user()->id); diff --git a/app/Entities/Queries/TopFavourites.php b/app/Entities/Queries/TopFavourites.php index 7522a894d..5d138679a 100644 --- a/app/Entities/Queries/TopFavourites.php +++ b/app/Entities/Queries/TopFavourites.php @@ -15,7 +15,7 @@ class TopFavourites extends EntityQuery } $query = $this->permissionService() - ->filterRestrictedEntityRelations(Favourite::query(), 'favourites', 'favouritable_id', 'favouritable_type', 'view') + ->filterRestrictedEntityRelations(Favourite::query(), 'favourites', 'favouritable_id', 'favouritable_type') ->select('favourites.*') ->leftJoin('views', function (JoinClause $join) { $join->on('favourites.favouritable_id', '=', 'views.viewable_id'); diff --git a/app/Http/Controllers/BookshelfController.php b/app/Http/Controllers/BookshelfController.php index a294bf731..18adaa627 100644 --- a/app/Http/Controllers/BookshelfController.php +++ b/app/Http/Controllers/BookshelfController.php @@ -68,7 +68,7 @@ class BookshelfController extends Controller public function create() { $this->checkPermission('bookshelf-create-all'); - $books = Book::hasPermission('update')->get(); + $books = Book::visible()->get(); $this->setPageTitle(trans('entities.shelves_create')); return view('shelves.create', ['books' => $books]); @@ -139,7 +139,7 @@ class BookshelfController extends Controller $this->checkOwnablePermission('bookshelf-update', $shelf); $shelfBookIds = $shelf->books()->get(['id'])->pluck('id'); - $books = Book::hasPermission('update')->whereNotIn('id', $shelfBookIds)->get(); + $books = Book::visible()->whereNotIn('id', $shelfBookIds)->get(); $this->setPageTitle(trans('entities.shelves_edit_named', ['name' => $shelf->getShortName()])); diff --git a/app/helpers.php b/app/helpers.php index cfdf55445..191eddf4d 100644 --- a/app/helpers.php +++ b/app/helpers.php @@ -71,14 +71,14 @@ function userCan(string $permission, Model $ownable = null): bool } /** - * Check if the current user has the given permission - * on any item in the system. + * Check if the current user can perform the given action on any items in the system. + * Can be provided the class name of an entity to filter ability to that specific entity type. */ -function userCanOnAny(string $permission, string $entityClass = null): bool +function userCanOnAny(string $action, string $entityClass = ''): bool { $permissions = app(PermissionApplicator::class); - return $permissions->checkUserHasPermissionOnAnything($permission, $entityClass); + return $permissions->checkUserHasEntityPermissionOnAny($action, $entityClass); } /** diff --git a/resources/views/chapters/show.blade.php b/resources/views/chapters/show.blade.php index 3e015616a..8a86900fb 100644 --- a/resources/views/chapters/show.blade.php +++ b/resources/views/chapters/show.blade.php @@ -120,7 +120,7 @@ {{ trans('common.edit') }} @endif - @if(userCanOnAny('chapter-create')) + @if(userCanOnAny('create', \BookStack\Entities\Models\Book::class) || userCan('chapter-create-all') || userCan('chapter-create-own')) @icon('copy') {{ trans('common.copy') }} diff --git a/resources/views/pages/show.blade.php b/resources/views/pages/show.blade.php index 2a71c6021..f1aed730b 100644 --- a/resources/views/pages/show.blade.php +++ b/resources/views/pages/show.blade.php @@ -148,7 +148,7 @@ {{ trans('common.edit') }} @endif - @if(userCanOnAny('page-create')) + @if(userCanOnAny('create', \BookStack\Entities\Models\Book::class) || userCanOnAny('create', \BookStack\Entities\Models\Chapter::class) || userCan('page-create-all') || userCan('page-create-own')) @icon('copy') {{ trans('common.copy') }} From f459a68535fc42ef5079e2514b82bff28504fc50 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 16 Jul 2022 19:28:04 +0100 Subject: [PATCH 036/246] Removed remaining dynamic action usages in joint permission queries --- app/Auth/Permissions/PermissionApplicator.php | 100 +++++++++++------- 1 file changed, 64 insertions(+), 36 deletions(-) diff --git a/app/Auth/Permissions/PermissionApplicator.php b/app/Auth/Permissions/PermissionApplicator.php index cf95f2854..e73db5157 100644 --- a/app/Auth/Permissions/PermissionApplicator.php +++ b/app/Auth/Permissions/PermissionApplicator.php @@ -4,6 +4,7 @@ namespace BookStack\Auth\Permissions; use BookStack\Auth\Role; use BookStack\Auth\User; +use BookStack\Entities\Models\Chapter; use BookStack\Entities\Models\Entity; use BookStack\Entities\Models\Page; use BookStack\Model; @@ -23,32 +24,59 @@ class PermissionApplicator public function checkOwnableUserAccess(Model $ownable, string $permission): bool { $explodedPermission = explode('-', $permission); - - $baseQuery = $ownable->newQuery()->where('id', '=', $ownable->id); - $action = end($explodedPermission); + $action = $explodedPermission[1] ?? $explodedPermission[0]; $user = $this->currentUser(); + $userRoleIds = $this->getCurrentUserRoleIds(); + $allRolePermission = $user->can($permission . '-all'); + $ownRolePermission = $user->can($permission . '-own'); $nonJointPermissions = ['restrictions', 'image', 'attachment', 'comment']; + $ownerField = ($ownable instanceof Entity) ? 'owned_by' : 'created_by'; + $isOwner = $user->id === $ownable->getAttribute($ownerField); + $hasRolePermission = $allRolePermission || ($isOwner && $ownRolePermission); // Handle non entity specific jointPermissions if (in_array($explodedPermission[0], $nonJointPermissions)) { - $allPermission = $user && $user->can($permission . '-all'); - $ownPermission = $user && $user->can($permission . '-own'); - $ownerField = ($ownable instanceof Entity) ? 'owned_by' : 'created_by'; - $isOwner = $user && $user->id === $ownable->$ownerField; - - return $allPermission || ($isOwner && $ownPermission); + return $hasRolePermission; } - // Handle abnormal create jointPermissions - if ($action === 'create') { - $action = $permission; + $entityPermissions = $this->getApplicableEntityPermissions($ownable, $userRoleIds, $action); + if (is_null($entityPermissions)) { + return $hasRolePermission; } - // TODO - Use a non-query based check - $hasAccess = $this->entityRestrictionQuery($baseQuery, $action)->count() > 0; + return count($entityPermissions) > 0; + } - return $hasAccess; + /** + * Get the permissions that are applicable for the given entity item. + * Returns null when no entity permissions apply otherwise entity permissions + * are active, even if the returned array is empty. + * + * @returns EntityPermission[] + */ + protected function getApplicableEntityPermissions(Entity $entity, array $userRoleIds, string $action): ?array + { + $chain = [$entity]; + if ($entity instanceof Page && $entity->chapter_id) { + $chain[] = $entity->chapter; + } + + if ($entity instanceof Page || $entity instanceof Chapter) { + $chain[] = $entity->book; + } + + foreach ($chain as $currentEntity) { + if ($currentEntity->restricted) { + return $currentEntity->permissions() + ->whereIn('role_id', $userRoleIds) + ->where('action', '=', $action) + ->get() + ->all(); + } + } + + return null; } /** @@ -76,26 +104,6 @@ class PermissionApplicator return $hasPermission; } - /** - * The general query filter to remove all entities - * that the current user does not have access to. - */ - protected function entityRestrictionQuery(Builder $query, string $action): Builder - { - $q = $query->where(function ($parentQuery) use ($action) { - $parentQuery->whereHas('jointPermissions', function ($permissionQuery) use ($action) { - $permissionQuery->whereIn('role_id', $this->getCurrentUserRoleIds()) - // TODO - Delete line once only views - ->where('action', '=', $action) - ->where(function (Builder $query) { - $this->addJointHasPermissionCheck($query, $this->currentUser()->id); - }); - }); - }); - - return $q; - } - /** * Limited the given entity query so that the query will only * return items that the user has view permission for. @@ -139,7 +147,27 @@ class PermissionApplicator $this->enforceDraftVisibilityOnQuery($query); } - return $this->entityRestrictionQuery($query, 'view'); + return $this->entityRestrictionQuery($query); + } + + /** + * The general query filter to remove all entities + * that the current user does not have access to. + */ + protected function entityRestrictionQuery(Builder $query): Builder + { + $q = $query->where(function ($parentQuery) { + $parentQuery->whereHas('jointPermissions', function ($permissionQuery) { + $permissionQuery->whereIn('role_id', $this->getCurrentUserRoleIds()) + // TODO - Delete line once only views + ->where('action', '=', 'view') + ->where(function (Builder $query) { + $this->addJointHasPermissionCheck($query, $this->currentUser()->id); + }); + }); + }); + + return $q; } /** From afe1a042396454e071b4b3bb5bb0043586ba333a Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 16 Jul 2022 19:54:25 +0100 Subject: [PATCH 037/246] Aligned permission applicator method names Also removed lesser used function, that was mostly a duplicate of an existing function, and only used for search. --- app/Actions/ActivityQueries.php | 4 +- app/Actions/TagRepo.php | 6 +- app/Auth/Permissions/PermissionApplicator.php | 80 ++++++------------- app/Entities/Models/Page.php | 2 +- app/Entities/Queries/Popular.php | 2 +- app/Entities/Queries/RecentlyViewed.php | 2 +- app/Entities/Queries/TopFavourites.php | 2 +- app/Entities/Tools/SearchRunner.php | 4 +- app/Uploads/Attachment.php | 3 +- app/Uploads/ImageRepo.php | 2 +- 10 files changed, 36 insertions(+), 71 deletions(-) diff --git a/app/Actions/ActivityQueries.php b/app/Actions/ActivityQueries.php index 0b8cd3b5e..0e9cbdebb 100644 --- a/app/Actions/ActivityQueries.php +++ b/app/Actions/ActivityQueries.php @@ -26,7 +26,7 @@ class ActivityQueries public function latest(int $count = 20, int $page = 0): array { $activityList = $this->permissions - ->filterRestrictedEntityRelations(Activity::query(), 'activities', 'entity_id', 'entity_type') + ->restrictEntityRelationQuery(Activity::query(), 'activities', 'entity_id', 'entity_type') ->orderBy('created_at', 'desc') ->with(['user', 'entity']) ->skip($count * $page) @@ -79,7 +79,7 @@ class ActivityQueries public function userActivity(User $user, int $count = 20, int $page = 0): array { $activityList = $this->permissions - ->filterRestrictedEntityRelations(Activity::query(), 'activities', 'entity_id', 'entity_type') + ->restrictEntityRelationQuery(Activity::query(), 'activities', 'entity_id', 'entity_type') ->orderBy('created_at', 'desc') ->where('user_id', '=', $user->id) ->skip($count * $page) diff --git a/app/Actions/TagRepo.php b/app/Actions/TagRepo.php index c5807108e..172d8ec6e 100644 --- a/app/Actions/TagRepo.php +++ b/app/Actions/TagRepo.php @@ -50,7 +50,7 @@ class TagRepo }); } - return $this->permissions->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); + return $this->permissions->restrictEntityRelationQuery($query, 'tags', 'entity_id', 'entity_type'); } /** @@ -69,7 +69,7 @@ class TagRepo $query = $query->orderBy('count', 'desc')->take(50); } - $query = $this->permissions->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); + $query = $this->permissions->restrictEntityRelationQuery($query, 'tags', 'entity_id', 'entity_type'); return $query->get(['name'])->pluck('name'); } @@ -95,7 +95,7 @@ class TagRepo $query = $query->where('name', '=', $tagName); } - $query = $this->permissions->filterRestrictedEntityRelations($query, 'tags', 'entity_id', 'entity_type'); + $query = $this->permissions->restrictEntityRelationQuery($query, 'tags', 'entity_id', 'entity_type'); return $query->get(['value'])->pluck('value'); } diff --git a/app/Auth/Permissions/PermissionApplicator.php b/app/Auth/Permissions/PermissionApplicator.php index e73db5157..91a7c72ae 100644 --- a/app/Auth/Permissions/PermissionApplicator.php +++ b/app/Auth/Permissions/PermissionApplicator.php @@ -105,7 +105,7 @@ class PermissionApplicator } /** - * Limited the given entity query so that the query will only + * Limit the given entity query so that the query will only * return items that the user has view permission for. */ public function restrictEntityQuery(Builder $query): Builder @@ -126,7 +126,7 @@ class PermissionApplicator * Extend the given page query to ensure draft items are not visible * unless created by the given user. */ - public function enforceDraftVisibilityOnQuery(Builder $query): Builder + public function restrictDraftsOnPageQuery(Builder $query): Builder { return $query->where(function (Builder $query) { $query->where('draft', '=', false) @@ -137,39 +137,6 @@ class PermissionApplicator }); } - /** - * Add restrictions for a generic entity. - */ - public function enforceEntityRestrictions(Entity $entity, Builder $query): Builder - { - if ($entity instanceof Page) { - // Prevent drafts being visible to others. - $this->enforceDraftVisibilityOnQuery($query); - } - - return $this->entityRestrictionQuery($query); - } - - /** - * The general query filter to remove all entities - * that the current user does not have access to. - */ - protected function entityRestrictionQuery(Builder $query): Builder - { - $q = $query->where(function ($parentQuery) { - $parentQuery->whereHas('jointPermissions', function ($permissionQuery) { - $permissionQuery->whereIn('role_id', $this->getCurrentUserRoleIds()) - // TODO - Delete line once only views - ->where('action', '=', 'view') - ->where(function (Builder $query) { - $this->addJointHasPermissionCheck($query, $this->currentUser()->id); - }); - }); - }); - - return $q; - } - /** * Filter items that have entities set as a polymorphic relation. * For simplicity, this will not return results attached to draft pages. @@ -177,7 +144,7 @@ class PermissionApplicator * * @param Builder|QueryBuilder $query */ - public function filterRestrictedEntityRelations($query, string $tableName, string $entityIdColumn, string $entityTypeColumn) + public function restrictEntityRelationQuery($query, string $tableName, string $entityIdColumn, string $entityTypeColumn) { $tableDetails = ['tableName' => $tableName, 'entityIdColumn' => $entityIdColumn, 'entityTypeColumn' => $entityTypeColumn]; $pageMorphClass = (new Page())->getMorphClass(); @@ -207,19 +174,20 @@ class PermissionApplicator } /** - * Add conditions to a query to filter the selection to related entities - * where view permissions are granted. + * Add conditions to a query for a model that's a relation of a page, so only the model results + * on visible pages are returned by the query. + * Is effectively the same as "restrictEntityRelationQuery" but takes into account page drafts + * while not expecting a polymorphic relation, Just a simpler one-page-to-many-relations set-up. */ - public function filterRelatedEntity(string $entityClass, Builder $query, string $tableName, string $entityIdColumn): Builder + public function restrictPageRelationQuery(Builder $query, string $tableName, string $pageIdColumn): Builder { - $fullEntityIdColumn = $tableName . '.' . $entityIdColumn; - $instance = new $entityClass(); - $morphClass = $instance->getMorphClass(); + $fullPageIdColumn = $tableName . '.' . $pageIdColumn; + $morphClass = (new Page())->getMorphClass(); - $existsQuery = function ($permissionQuery) use ($fullEntityIdColumn, $morphClass) { + $existsQuery = function ($permissionQuery) use ($fullPageIdColumn, $morphClass) { /** @var Builder $permissionQuery */ $permissionQuery->select('joint_permissions.role_id')->from('joint_permissions') - ->whereColumn('joint_permissions.entity_id', '=', $fullEntityIdColumn) + ->whereColumn('joint_permissions.entity_id', '=', $fullPageIdColumn) ->where('joint_permissions.entity_type', '=', $morphClass) ->where('joint_permissions.action', '=', 'view') ->whereIn('joint_permissions.role_id', $this->getCurrentUserRoleIds()) @@ -228,22 +196,20 @@ class PermissionApplicator }); }; - $q = $query->where(function ($query) use ($existsQuery, $fullEntityIdColumn) { + $q = $query->where(function ($query) use ($existsQuery, $fullPageIdColumn) { $query->whereExists($existsQuery) - ->orWhere($fullEntityIdColumn, '=', 0); + ->orWhere($fullPageIdColumn, '=', 0); }); - if ($instance instanceof Page) { - // Prevent visibility of non-owned draft pages - $q->whereExists(function (QueryBuilder $query) use ($fullEntityIdColumn) { - $query->select('id')->from('pages') - ->whereColumn('pages.id', '=', $fullEntityIdColumn) - ->where(function (QueryBuilder $query) { - $query->where('pages.draft', '=', false) - ->orWhere('pages.owned_by', '=', $this->currentUser()->id); - }); - }); - } + // Prevent visibility of non-owned draft pages + $q->whereExists(function (QueryBuilder $query) use ($fullPageIdColumn) { + $query->select('id')->from('pages') + ->whereColumn('pages.id', '=', $fullPageIdColumn) + ->where(function (QueryBuilder $query) { + $query->where('pages.draft', '=', false) + ->orWhere('pages.owned_by', '=', $this->currentUser()->id); + }); + }); return $q; } diff --git a/app/Entities/Models/Page.php b/app/Entities/Models/Page.php index a2690b2a0..93729d7f2 100644 --- a/app/Entities/Models/Page.php +++ b/app/Entities/Models/Page.php @@ -51,7 +51,7 @@ class Page extends BookChild */ public function scopeVisible(Builder $query): Builder { - $query = app()->make(PermissionApplicator::class)->enforceDraftVisibilityOnQuery($query); + $query = app()->make(PermissionApplicator::class)->restrictDraftsOnPageQuery($query); return parent::scopeVisible($query); } diff --git a/app/Entities/Queries/Popular.php b/app/Entities/Queries/Popular.php index 82786e3c6..fafd60c59 100644 --- a/app/Entities/Queries/Popular.php +++ b/app/Entities/Queries/Popular.php @@ -10,7 +10,7 @@ class Popular extends EntityQuery public function run(int $count, int $page, array $filterModels = null) { $query = $this->permissionService() - ->filterRestrictedEntityRelations(View::query(), 'views', 'viewable_id', 'viewable_type') + ->restrictEntityRelationQuery(View::query(), 'views', 'viewable_id', 'viewable_type') ->select('*', 'viewable_id', 'viewable_type', DB::raw('SUM(views) as view_count')) ->groupBy('viewable_id', 'viewable_type') ->orderBy('view_count', 'desc'); diff --git a/app/Entities/Queries/RecentlyViewed.php b/app/Entities/Queries/RecentlyViewed.php index 38d1f1be4..0f5c68041 100644 --- a/app/Entities/Queries/RecentlyViewed.php +++ b/app/Entities/Queries/RecentlyViewed.php @@ -14,7 +14,7 @@ class RecentlyViewed extends EntityQuery return collect(); } - $query = $this->permissionService()->filterRestrictedEntityRelations( + $query = $this->permissionService()->restrictEntityRelationQuery( View::query(), 'views', 'viewable_id', diff --git a/app/Entities/Queries/TopFavourites.php b/app/Entities/Queries/TopFavourites.php index 5d138679a..0b9a5ba23 100644 --- a/app/Entities/Queries/TopFavourites.php +++ b/app/Entities/Queries/TopFavourites.php @@ -15,7 +15,7 @@ class TopFavourites extends EntityQuery } $query = $this->permissionService() - ->filterRestrictedEntityRelations(Favourite::query(), 'favourites', 'favouritable_id', 'favouritable_type') + ->restrictEntityRelationQuery(Favourite::query(), 'favourites', 'favouritable_id', 'favouritable_type') ->select('favourites.*') ->leftJoin('views', function (JoinClause $join) { $join->on('favourites.favouritable_id', '=', 'views.viewable_id'); diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index 1dcc2eb44..459409084 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -161,7 +161,7 @@ class SearchRunner */ protected function buildQuery(SearchOptions $searchOpts, Entity $entityModelInstance): EloquentBuilder { - $entityQuery = $entityModelInstance->newQuery(); + $entityQuery = $entityModelInstance->newQuery()->scopes('visible'); if ($entityModelInstance instanceof Page) { $entityQuery->select($entityModelInstance::$listAttributes); @@ -193,7 +193,7 @@ class SearchRunner } } - return $this->permissions->enforceEntityRestrictions($entityModelInstance, $entityQuery); + return $entityQuery; } /** diff --git a/app/Uploads/Attachment.php b/app/Uploads/Attachment.php index d9e0ce7e1..6c7066ff9 100644 --- a/app/Uploads/Attachment.php +++ b/app/Uploads/Attachment.php @@ -91,8 +91,7 @@ class Attachment extends Model { $permissions = app()->make(PermissionApplicator::class); - return $permissions->filterRelatedEntity( - Page::class, + return $permissions->restrictPageRelationQuery( self::query(), 'attachments', 'uploaded_to' diff --git a/app/Uploads/ImageRepo.php b/app/Uploads/ImageRepo.php index 13d3344dd..8770402ad 100644 --- a/app/Uploads/ImageRepo.php +++ b/app/Uploads/ImageRepo.php @@ -74,7 +74,7 @@ class ImageRepo } // Filter by page access - $imageQuery = $this->permissions->filterRelatedEntity(Page::class, $imageQuery, 'images', 'uploaded_to'); + $imageQuery = $this->permissions->restrictPageRelationQuery($imageQuery, 'images', 'uploaded_to'); if ($whereClause !== null) { $imageQuery = $imageQuery->where($whereClause); From 23324018540624d7a6beafd0514f4b7dbe327431 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 16 Jul 2022 20:55:32 +0100 Subject: [PATCH 038/246] Fixed a couple of non-intended logical permission issues Both caught in tests: Fixed loss of permissions for admin users when entity restrictions were active, since there are no entity-restrictions for the admin role but we'd force generate them in joint permissions, which would be queried. Fixed new role permission checks when permissions given with only the action (eg. 'view'), since the type prefix would be required for role permission checks. Was previously not needed as only the simpler form was used in the jointpermissions after merge & calculation. --- app/Auth/Permissions/PermissionApplicator.php | 30 +++++++++---------- app/Entities/Models/Bookshelf.php | 6 ---- app/Entities/Tools/ShelfContext.php | 1 + app/Http/Controllers/BookshelfController.php | 2 +- 4 files changed, 17 insertions(+), 22 deletions(-) diff --git a/app/Auth/Permissions/PermissionApplicator.php b/app/Auth/Permissions/PermissionApplicator.php index 91a7c72ae..4b648532a 100644 --- a/app/Auth/Permissions/PermissionApplicator.php +++ b/app/Auth/Permissions/PermissionApplicator.php @@ -25,11 +25,13 @@ class PermissionApplicator { $explodedPermission = explode('-', $permission); $action = $explodedPermission[1] ?? $explodedPermission[0]; + $fullPermission = count($explodedPermission) > 1 ? $permission : $ownable->getMorphClass() . '-' . $permission; + $user = $this->currentUser(); $userRoleIds = $this->getCurrentUserRoleIds(); - $allRolePermission = $user->can($permission . '-all'); - $ownRolePermission = $user->can($permission . '-own'); + $allRolePermission = $user->can($fullPermission . '-all'); + $ownRolePermission = $user->can($fullPermission . '-own'); $nonJointPermissions = ['restrictions', 'image', 'attachment', 'comment']; $ownerField = ($ownable instanceof Entity) ? 'owned_by' : 'created_by'; $isOwner = $user->id === $ownable->getAttribute($ownerField); @@ -40,23 +42,22 @@ class PermissionApplicator return $hasRolePermission; } - $entityPermissions = $this->getApplicableEntityPermissions($ownable, $userRoleIds, $action); - if (is_null($entityPermissions)) { - return $hasRolePermission; - } + $hasApplicableEntityPermissions = $this->hasEntityPermission($ownable, $userRoleIds, $action); - return count($entityPermissions) > 0; + return is_null($hasApplicableEntityPermissions) ? $hasRolePermission : $hasApplicableEntityPermissions; } /** - * Get the permissions that are applicable for the given entity item. - * Returns null when no entity permissions apply otherwise entity permissions - * are active, even if the returned array is empty. - * - * @returns EntityPermission[] + * Check if there are permissions that are applicable for the given entity item, action and roles. + * Returns null when no entity permissions are in force. */ - protected function getApplicableEntityPermissions(Entity $entity, array $userRoleIds, string $action): ?array + protected function hasEntityPermission(Entity $entity, array $userRoleIds, string $action): ?bool { + $adminRoleId = Role::getSystemRole('admin')->id; + if (in_array($adminRoleId, $userRoleIds)) { + return true; + } + $chain = [$entity]; if ($entity instanceof Page && $entity->chapter_id) { $chain[] = $entity->chapter; @@ -71,8 +72,7 @@ class PermissionApplicator return $currentEntity->permissions() ->whereIn('role_id', $userRoleIds) ->where('action', '=', $action) - ->get() - ->all(); + ->count() > 0; } } diff --git a/app/Entities/Models/Bookshelf.php b/app/Entities/Models/Bookshelf.php index b9ebab92e..b2dab252a 100644 --- a/app/Entities/Models/Bookshelf.php +++ b/app/Entities/Models/Bookshelf.php @@ -91,10 +91,6 @@ class Bookshelf extends Entity implements HasCoverImage /** * Check if this shelf contains the given book. - * - * @param Book $book - * - * @return bool */ public function contains(Book $book): bool { @@ -103,8 +99,6 @@ class Bookshelf extends Entity implements HasCoverImage /** * Add a book to the end of this shelf. - * - * @param Book $book */ public function appendBook(Book $book) { diff --git a/app/Entities/Tools/ShelfContext.php b/app/Entities/Tools/ShelfContext.php index 50d798171..50c7047d9 100644 --- a/app/Entities/Tools/ShelfContext.php +++ b/app/Entities/Tools/ShelfContext.php @@ -20,6 +20,7 @@ class ShelfContext return null; } + /** @var Bookshelf $shelf */ $shelf = Bookshelf::visible()->find($contextBookshelfId); $shelfContainsBook = $shelf && $shelf->contains($book); diff --git a/app/Http/Controllers/BookshelfController.php b/app/Http/Controllers/BookshelfController.php index 18adaa627..feb581c78 100644 --- a/app/Http/Controllers/BookshelfController.php +++ b/app/Http/Controllers/BookshelfController.php @@ -104,7 +104,7 @@ class BookshelfController extends Controller public function show(ActivityQueries $activities, string $slug) { $shelf = $this->bookshelfRepo->getBySlug($slug); - $this->checkOwnablePermission('book-view', $shelf); + $this->checkOwnablePermission('bookshelf-view', $shelf); $sort = setting()->getForCurrentUser('shelf_books_sort', 'default'); $order = setting()->getForCurrentUser('shelf_books_sort_order', 'asc'); From 8f90996ceff6dca02c6f80d6f7d0d3f837dd1601 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sat, 16 Jul 2022 21:50:42 +0100 Subject: [PATCH 039/246] Dropped use of non-view joint permissions --- .../Permissions/JointPermissionBuilder.php | 82 ++++++++----------- app/Auth/Permissions/PermissionApplicator.php | 4 - ...7_16_170051_drop_joint_permission_type.php | 41 ++++++++++ tests/PublicActionTest.php | 1 + 4 files changed, 74 insertions(+), 54 deletions(-) create mode 100644 database/migrations/2022_07_16_170051_drop_joint_permission_type.php diff --git a/app/Auth/Permissions/JointPermissionBuilder.php b/app/Auth/Permissions/JointPermissionBuilder.php index fe25e02ff..9ee09a3a6 100644 --- a/app/Auth/Permissions/JointPermissionBuilder.php +++ b/app/Auth/Permissions/JointPermissionBuilder.php @@ -13,6 +13,10 @@ use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Collection as EloquentCollection; use Illuminate\Support\Facades\DB; +/** + * Joint permissions provide a pre-query "cached" table of view permissions for all core entity + * types for all roles in the system. This class generates out that table for different scenarios. + */ class JointPermissionBuilder { /** @@ -80,6 +84,7 @@ class JointPermissionBuilder { $roles = [$role]; $role->jointPermissions()->delete(); + $role->load('permissions'); // Chunk through all books $this->bookFetchQuery()->chunk(20, function ($books) use ($roles) { @@ -247,7 +252,7 @@ class JointPermissionBuilder // Create a mapping of explicit entity permissions $permissionMap = []; foreach ($permissions as $permission) { - $key = $permission->restrictable_type . ':' . $permission->restrictable_id . ':' . $permission->role_id . ':' . $permission->action; + $key = $permission->restrictable_type . ':' . $permission->restrictable_id . ':' . $permission->role_id; $isRestricted = $entityRestrictedMap[$permission->restrictable_type . ':' . $permission->restrictable_id]; $permissionMap[$key] = $isRestricted; } @@ -263,16 +268,13 @@ class JointPermissionBuilder // Create Joint Permission Data foreach ($entities as $entity) { foreach ($roles as $role) { - foreach ($this->getActions($entity) as $action) { - $jointPermissions[] = $this->createJointPermissionData( - $entity, - $role->getRawAttribute('id'), - $action, - $permissionMap, - $rolePermissionMap, - $role->system_name === 'admin' - ); - } + $jointPermissions[] = $this->createJointPermissionData( + $entity, + $role->getRawAttribute('id'), + $permissionMap, + $rolePermissionMap, + $role->system_name === 'admin' + ); } } @@ -312,64 +314,46 @@ class JointPermissionBuilder protected function getEntityPermissionsForEntities(array $entities): array { $idsByType = $this->entitiesToTypeIdMap($entities); - $permissionFetch = EntityPermission::query(); - - foreach ($idsByType as $type => $ids) { - $permissionFetch->orWhere(function (Builder $query) use ($type, $ids) { - $query->where('restrictable_type', '=', $type)->whereIn('restrictable_id', $ids); + $permissionFetch = EntityPermission::query() + ->where('action', '=', 'view') + ->where(function(Builder $query) use ($idsByType) { + foreach ($idsByType as $type => $ids) { + $query->orWhere(function (Builder $query) use ($type, $ids) { + $query->where('restrictable_type', '=', $type)->whereIn('restrictable_id', $ids); + }); + } }); - } return $permissionFetch->get()->all(); } - /** - * Get the actions related to an entity. - */ - protected function getActions(SimpleEntityData $entity): array - { - $baseActions = ['view', 'update', 'delete']; - - if ($entity->type === 'chapter' || $entity->type === 'book') { - $baseActions[] = 'page-create'; - } - - if ($entity->type === 'book') { - $baseActions[] = 'chapter-create'; - } - - return $baseActions; - } - /** * Create entity permission data for an entity and role * for a particular action. */ - protected function createJointPermissionData(SimpleEntityData $entity, int $roleId, string $action, array $permissionMap, array $rolePermissionMap, bool $isAdminRole): array + protected function createJointPermissionData(SimpleEntityData $entity, int $roleId, array $permissionMap, array $rolePermissionMap, bool $isAdminRole): array { - $permissionPrefix = (strpos($action, '-') === false ? ($entity->type . '-') : '') . $action; + $permissionPrefix = $entity->type . '-view'; $roleHasPermission = isset($rolePermissionMap[$roleId . ':' . $permissionPrefix . '-all']); $roleHasPermissionOwn = isset($rolePermissionMap[$roleId . ':' . $permissionPrefix . '-own']); - $explodedAction = explode('-', $action); - $restrictionAction = end($explodedAction); if ($isAdminRole) { - return $this->createJointPermissionDataArray($entity, $roleId, $action, true, true); + return $this->createJointPermissionDataArray($entity, $roleId, true, true); } if ($entity->restricted) { - $hasAccess = $this->mapHasActiveRestriction($permissionMap, $entity, $roleId, $restrictionAction); + $hasAccess = $this->mapHasActiveRestriction($permissionMap, $entity, $roleId); - return $this->createJointPermissionDataArray($entity, $roleId, $action, $hasAccess, $hasAccess); + return $this->createJointPermissionDataArray($entity, $roleId, $hasAccess, $hasAccess); } if ($entity->type === 'book' || $entity->type === 'bookshelf') { - return $this->createJointPermissionDataArray($entity, $roleId, $action, $roleHasPermission, $roleHasPermissionOwn); + return $this->createJointPermissionDataArray($entity, $roleId, $roleHasPermission, $roleHasPermissionOwn); } // For chapters and pages, Check if explicit permissions are set on the Book. $book = $this->getBook($entity->book_id); - $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $book, $roleId, $restrictionAction); + $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $book, $roleId); $hasPermissiveAccessToParents = !$book->restricted; // For pages with a chapter, Check if explicit permissions are set on the Chapter @@ -377,14 +361,13 @@ class JointPermissionBuilder $chapter = $this->getChapter($entity->chapter_id); $hasPermissiveAccessToParents = $hasPermissiveAccessToParents && !$chapter->restricted; if ($chapter->restricted) { - $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $chapter, $roleId, $restrictionAction); + $hasExplicitAccessToParents = $this->mapHasActiveRestriction($permissionMap, $chapter, $roleId); } } return $this->createJointPermissionDataArray( $entity, $roleId, - $action, ($hasExplicitAccessToParents || ($roleHasPermission && $hasPermissiveAccessToParents)), ($hasExplicitAccessToParents || ($roleHasPermissionOwn && $hasPermissiveAccessToParents)) ); @@ -393,9 +376,9 @@ class JointPermissionBuilder /** * Check for an active restriction in an entity map. */ - protected function mapHasActiveRestriction(array $entityMap, SimpleEntityData $entity, int $roleId, string $action): bool + protected function mapHasActiveRestriction(array $entityMap, SimpleEntityData $entity, int $roleId): bool { - $key = $entity->type . ':' . $entity->id . ':' . $roleId . ':' . $action; + $key = $entity->type . ':' . $entity->id . ':' . $roleId; return $entityMap[$key] ?? false; } @@ -404,10 +387,9 @@ class JointPermissionBuilder * Create an array of data with the information of an entity jointPermissions. * Used to build data for bulk insertion. */ - protected function createJointPermissionDataArray(SimpleEntityData $entity, int $roleId, string $action, bool $permissionAll, bool $permissionOwn): array + protected function createJointPermissionDataArray(SimpleEntityData $entity, int $roleId, bool $permissionAll, bool $permissionOwn): array { return [ - 'action' => $action, 'entity_id' => $entity->id, 'entity_type' => $entity->type, 'has_permission' => $permissionAll, diff --git a/app/Auth/Permissions/PermissionApplicator.php b/app/Auth/Permissions/PermissionApplicator.php index 4b648532a..b89857c5c 100644 --- a/app/Auth/Permissions/PermissionApplicator.php +++ b/app/Auth/Permissions/PermissionApplicator.php @@ -113,8 +113,6 @@ class PermissionApplicator return $query->where(function (Builder $parentQuery) { $parentQuery->whereHas('jointPermissions', function (Builder $permissionQuery) { $permissionQuery->whereIn('role_id', $this->getCurrentUserRoleIds()) - // TODO - Delete line once only views - ->where('action', '=', 'view') ->where(function (Builder $query) { $this->addJointHasPermissionCheck($query, $this->currentUser()->id); }); @@ -154,7 +152,6 @@ class PermissionApplicator $permissionQuery->select(['role_id'])->from('joint_permissions') ->whereColumn('joint_permissions.entity_id', '=', $tableDetails['tableName'] . '.' . $tableDetails['entityIdColumn']) ->whereColumn('joint_permissions.entity_type', '=', $tableDetails['tableName'] . '.' . $tableDetails['entityTypeColumn']) - ->where('joint_permissions.action', '=', 'view') ->whereIn('joint_permissions.role_id', $this->getCurrentUserRoleIds()) ->where(function (QueryBuilder $query) { $this->addJointHasPermissionCheck($query, $this->currentUser()->id); @@ -189,7 +186,6 @@ class PermissionApplicator $permissionQuery->select('joint_permissions.role_id')->from('joint_permissions') ->whereColumn('joint_permissions.entity_id', '=', $fullPageIdColumn) ->where('joint_permissions.entity_type', '=', $morphClass) - ->where('joint_permissions.action', '=', 'view') ->whereIn('joint_permissions.role_id', $this->getCurrentUserRoleIds()) ->where(function (QueryBuilder $query) { $this->addJointHasPermissionCheck($query, $this->currentUser()->id); diff --git a/database/migrations/2022_07_16_170051_drop_joint_permission_type.php b/database/migrations/2022_07_16_170051_drop_joint_permission_type.php new file mode 100644 index 000000000..f34f73636 --- /dev/null +++ b/database/migrations/2022_07_16_170051_drop_joint_permission_type.php @@ -0,0 +1,41 @@ +where('action', '!=', 'view') + ->delete(); + + Schema::table('joint_permissions', function (Blueprint $table) { + $table->dropPrimary(['role_id', 'entity_type', 'entity_id', 'action']); + $table->dropColumn('action'); + $table->primary(['role_id', 'entity_type', 'entity_id'], 'joint_primary'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('joint_permissions', function (Blueprint $table) { + $table->string('action'); + $table->dropPrimary(['role_id', 'entity_type', 'entity_id']); + $table->primary(['role_id', 'entity_type', 'entity_id', 'action']); + }); + } +} diff --git a/tests/PublicActionTest.php b/tests/PublicActionTest.php index 2841f4ef4..ced40d0a8 100644 --- a/tests/PublicActionTest.php +++ b/tests/PublicActionTest.php @@ -90,6 +90,7 @@ class PublicActionTest extends TestCase $publicRole->attachPermission($perm); } $this->app->make(JointPermissionBuilder::class)->rebuildForRole($publicRole); + user()->clearPermissionCache(); /** @var Chapter $chapter */ $chapter = Chapter::query()->first(); From e6e6d259749f789a4a3e8b87bc6e86ed94a4df9c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:18:24 +0100 Subject: [PATCH 040/246] Removed test web route, extracted text, added test --- resources/lang/en/entities.php | 1 + resources/views/entities/list-item.blade.php | 2 +- routes/web.php | 7 ------- tests/Entity/EntitySearchTest.php | 17 ++++++++++++++++- 4 files changed, 18 insertions(+), 9 deletions(-) diff --git a/resources/lang/en/entities.php b/resources/lang/en/entities.php index 27d67487a..aa353bdac 100644 --- a/resources/lang/en/entities.php +++ b/resources/lang/en/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Updated :timeLength by :user', 'meta_owned_name' => 'Owned by :user', 'entity_select' => 'Entity Select', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Images', 'my_recent_drafts' => 'My Recent Drafts', 'my_recently_viewed' => 'My Recently Viewed', diff --git a/resources/views/entities/list-item.blade.php b/resources/views/entities/list-item.blade.php index 5314c8446..2fadef191 100644 --- a/resources/views/entities/list-item.blade.php +++ b/resources/views/entities/list-item.blade.php @@ -4,7 +4,7 @@ @if($locked ?? false)
- @icon('lock')You don't have the required permissions to select this item. + @icon('lock'){{ trans('entities.entity_select_lack_permission') }}
@endif diff --git a/routes/web.php b/routes/web.php index 9b562703c..5e16e5333 100644 --- a/routes/web.php +++ b/routes/web.php @@ -38,13 +38,6 @@ use Illuminate\View\Middleware\ShareErrorsFromSession; Route::get('/status', [StatusController::class, 'show']); Route::get('/robots.txt', [HomeController::class, 'robots']); -Route::get('/test', function() { - $book = \BookStack\Entities\Models\Book::query()->where('slug', '=', 'k5TrhXxaNb')->firstOrFail(); - $builder= app()->make(\BookStack\Auth\Permissions\JointPermissionBuilder::class); - $builder->rebuildForEntity($book); - return 'finished'; -})->withoutMiddleware('web'); - // Authenticated routes... Route::middleware('auth')->group(function () { diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index b535f5aaa..55c54695e 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -214,7 +214,7 @@ class EntitySearchTest extends TestCase $defaultListTest->assertDontSee($notVisitedPage->name); } - public function test_ajax_entity_serach_shows_breadcrumbs() + public function test_ajax_entity_search_shows_breadcrumbs() { $chapter = Chapter::first(); $page = $chapter->pages->first(); @@ -230,6 +230,21 @@ class EntitySearchTest extends TestCase $chapterSearch->assertSee($chapter->book->getShortName(42)); } + public function test_ajax_entity_search_reflects_items_without_permission() + { + $page = Page::query()->first(); + $baseSelector = 'a[data-entity-type="page"][data-entity-id="' . $page->id . '"]'; + $searchUrl = "/ajax/search/entities?permission=update&term=" . urlencode($page->name); + + $resp = $this->asEditor()->get($searchUrl); + $resp->assertElementContains($baseSelector, $page->name); + $resp->assertElementNotContains($baseSelector, "You don't have the required permissions to select this item"); + + $resp = $this->actingAs($this->getViewer())->get($searchUrl); + $resp->assertElementContains($baseSelector, $page->name); + $resp->assertElementContains($baseSelector, "You don't have the required permissions to select this item"); + } + public function test_sibling_search_for_pages() { $chapter = Chapter::query()->with('pages')->first(); From 9cf05944f6c6d74603e1be1e6c96bd7ae6d7e3fb Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:32:16 +0100 Subject: [PATCH 041/246] Applied StyleCI changes --- app/Auth/Permissions/JointPermissionBuilder.php | 13 ++++++++----- app/Auth/Permissions/PermissionApplicator.php | 2 +- app/Auth/Permissions/SimpleEntityData.php | 2 +- app/Entities/Tools/SearchRunner.php | 1 - app/Providers/CustomFacadeProvider.php | 2 -- tests/Entity/EntitySearchTest.php | 2 +- tests/SharedTestHelpers.php | 1 - 7 files changed, 11 insertions(+), 12 deletions(-) diff --git a/app/Auth/Permissions/JointPermissionBuilder.php b/app/Auth/Permissions/JointPermissionBuilder.php index 9ee09a3a6..f377eef5c 100644 --- a/app/Auth/Permissions/JointPermissionBuilder.php +++ b/app/Auth/Permissions/JointPermissionBuilder.php @@ -148,7 +148,6 @@ class JointPermissionBuilder ]); } - /** * Build joint permissions for the given book and role combinations. */ @@ -207,6 +206,7 @@ class JointPermissionBuilder /** * @param Entity[] $entities + * * @return SimpleEntityData[] */ protected function entitiesToSimpleEntities(array $entities): array @@ -288,7 +288,9 @@ class JointPermissionBuilder /** * From the given entity list, provide back a mapping of entity types to * the ids of that given type. The type used is the DB morph class. + * * @param SimpleEntityData[] $entities + * * @return array */ protected function entitiesToTypeIdMap(array $entities): array @@ -307,8 +309,10 @@ class JointPermissionBuilder } /** - * Get the entity permissions for all the given entities + * Get the entity permissions for all the given entities. + * * @param SimpleEntityData[] $entities + * * @return EntityPermission[] */ protected function getEntityPermissionsForEntities(array $entities): array @@ -316,7 +320,7 @@ class JointPermissionBuilder $idsByType = $this->entitiesToTypeIdMap($entities); $permissionFetch = EntityPermission::query() ->where('action', '=', 'view') - ->where(function(Builder $query) use ($idsByType) { + ->where(function (Builder $query) use ($idsByType) { foreach ($idsByType as $type => $ids) { $query->orWhere(function (Builder $query) use ($type, $ids) { $query->where('restrictable_type', '=', $type)->whereIn('restrictable_id', $ids); @@ -398,5 +402,4 @@ class JointPermissionBuilder 'role_id' => $roleId, ]; } - -} \ No newline at end of file +} diff --git a/app/Auth/Permissions/PermissionApplicator.php b/app/Auth/Permissions/PermissionApplicator.php index b89857c5c..d855a6170 100644 --- a/app/Auth/Permissions/PermissionApplicator.php +++ b/app/Auth/Permissions/PermissionApplicator.php @@ -86,7 +86,7 @@ class PermissionApplicator public function checkUserHasEntityPermissionOnAny(string $action, string $entityClass = ''): bool { if (strpos($action, '-') !== false) { - throw new InvalidArgumentException("Action should be a simple entity permission action, not a role permission"); + throw new InvalidArgumentException('Action should be a simple entity permission action, not a role permission'); } $permissionQuery = EntityPermission::query() diff --git a/app/Auth/Permissions/SimpleEntityData.php b/app/Auth/Permissions/SimpleEntityData.php index 0d1c94b0d..6ec0c4179 100644 --- a/app/Auth/Permissions/SimpleEntityData.php +++ b/app/Auth/Permissions/SimpleEntityData.php @@ -10,4 +10,4 @@ class SimpleEntityData public int $owned_by; public ?int $book_id; public ?int $chapter_id; -} \ No newline at end of file +} diff --git a/app/Entities/Tools/SearchRunner.php b/app/Entities/Tools/SearchRunner.php index 459409084..78659b786 100644 --- a/app/Entities/Tools/SearchRunner.php +++ b/app/Entities/Tools/SearchRunner.php @@ -21,7 +21,6 @@ use SplObjectStorage; class SearchRunner { - protected EntityProvider $entityProvider; protected PermissionApplicator $permissions; diff --git a/app/Providers/CustomFacadeProvider.php b/app/Providers/CustomFacadeProvider.php index 04de82250..6ba5632e6 100644 --- a/app/Providers/CustomFacadeProvider.php +++ b/app/Providers/CustomFacadeProvider.php @@ -3,9 +3,7 @@ namespace BookStack\Providers; use BookStack\Actions\ActivityLogger; -use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Theming\ThemeService; -use BookStack\Uploads\ImageService; use Illuminate\Support\ServiceProvider; class CustomFacadeProvider extends ServiceProvider diff --git a/tests/Entity/EntitySearchTest.php b/tests/Entity/EntitySearchTest.php index 55c54695e..a23a2fd26 100644 --- a/tests/Entity/EntitySearchTest.php +++ b/tests/Entity/EntitySearchTest.php @@ -234,7 +234,7 @@ class EntitySearchTest extends TestCase { $page = Page::query()->first(); $baseSelector = 'a[data-entity-type="page"][data-entity-id="' . $page->id . '"]'; - $searchUrl = "/ajax/search/entities?permission=update&term=" . urlencode($page->name); + $searchUrl = '/ajax/search/entities?permission=update&term=' . urlencode($page->name); $resp = $this->asEditor()->get($searchUrl); $resp->assertElementContains($baseSelector, $page->name); diff --git a/tests/SharedTestHelpers.php b/tests/SharedTestHelpers.php index 99bc92494..bc7b10266 100644 --- a/tests/SharedTestHelpers.php +++ b/tests/SharedTestHelpers.php @@ -3,7 +3,6 @@ namespace Tests; use BookStack\Auth\Permissions\JointPermissionBuilder; -use BookStack\Auth\Permissions\PermissionApplicator; use BookStack\Auth\Permissions\PermissionsRepo; use BookStack\Auth\Permissions\RolePermission; use BookStack\Auth\Role; From 6b8083244da70252c1bdfe58edc43706c6645e83 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:49:50 +0100 Subject: [PATCH 042/246] New translations entities.php (Portuguese) --- resources/lang/pt/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/pt/entities.php b/resources/lang/pt/entities.php index 267aa929c..77b4b3887 100644 --- a/resources/lang/pt/entities.php +++ b/resources/lang/pt/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Atualizado :timeLength por :user', 'meta_owned_name' => 'Propriedade de :user', 'entity_select' => 'Seleção de Entidade', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Imagens', 'my_recent_drafts' => 'Os Meus Rascunhos Recentes', 'my_recently_viewed' => 'Visualizados Recentemente Por Mim', From ce9a788fb9183a5d9d911d846870e0ca095c9337 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:49:51 +0100 Subject: [PATCH 043/246] New translations entities.php (Italian) --- resources/lang/it/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/it/entities.php b/resources/lang/it/entities.php index ba04a443a..f1f36db3c 100755 --- a/resources/lang/it/entities.php +++ b/resources/lang/it/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Aggiornato :timeLength da :user', 'meta_owned_name' => 'Creati da :user', 'entity_select' => 'Selezione Entità', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Immagini', 'my_recent_drafts' => 'Bozze Recenti', 'my_recently_viewed' => 'Visti di recente', From 86e7386db9c840973e43bcd72d8b36efd2ee4b9b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:49:52 +0100 Subject: [PATCH 044/246] New translations entities.php (Turkish) --- resources/lang/tr/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/tr/entities.php b/resources/lang/tr/entities.php index f0bf60312..d2e35b584 100644 --- a/resources/lang/tr/entities.php +++ b/resources/lang/tr/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => ':user tarafından :timeLength güncellendi', 'meta_owned_name' => 'Owned by :user', 'entity_select' => 'Öge Seçimi', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Görseller', 'my_recent_drafts' => 'Son Taslaklarım', 'my_recently_viewed' => 'Son Görüntülediklerim', From 2853feb9c4017d5c8ee97e3551dcad14e3aa8b37 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:49:52 +0100 Subject: [PATCH 045/246] New translations entities.php (Swedish) --- resources/lang/sv/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/sv/entities.php b/resources/lang/sv/entities.php index c356ea5bd..9c122514f 100644 --- a/resources/lang/sv/entities.php +++ b/resources/lang/sv/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Uppdaterad :timeLength av :user', 'meta_owned_name' => 'Ägs av :user', 'entity_select' => 'Välj enhet', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Bilder', 'my_recent_drafts' => 'Mina nyaste utkast', 'my_recently_viewed' => 'Mina senast visade sidor', From a8d933753ea15533cf9a2a36987c3e6e3311e875 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:49:53 +0100 Subject: [PATCH 046/246] New translations entities.php (Slovenian) --- resources/lang/sl/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/sl/entities.php b/resources/lang/sl/entities.php index a76bcfa26..888ad5c64 100644 --- a/resources/lang/sl/entities.php +++ b/resources/lang/sl/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Posodobil :timeLength uporabnik :user', 'meta_owned_name' => 'V lasti :user', 'entity_select' => 'Izbira entitete', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Slike', 'my_recent_drafts' => 'Moji nedavni osnutki', 'my_recently_viewed' => 'Nedavno prikazano', From 9d78af2c1d1552aa676a9cfe686e7f5abccb1aca Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:49:54 +0100 Subject: [PATCH 047/246] New translations entities.php (Slovak) --- resources/lang/sk/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/sk/entities.php b/resources/lang/sk/entities.php index cfa87e0b8..4f2010bbd 100644 --- a/resources/lang/sk/entities.php +++ b/resources/lang/sk/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Aktualizované :timeLength používateľom :user', 'meta_owned_name' => 'Vlastník :user', 'entity_select' => 'Entita vybraná', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Obrázky', 'my_recent_drafts' => 'Moje nedávne koncepty', 'my_recently_viewed' => 'Nedávno mnou zobrazené', From c47997bbb7263f6ef4041b554167153c376ed2e6 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:49:55 +0100 Subject: [PATCH 048/246] New translations entities.php (Ukrainian) --- resources/lang/uk/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/uk/entities.php b/resources/lang/uk/entities.php index 12d305f3e..f15a7ae77 100644 --- a/resources/lang/uk/entities.php +++ b/resources/lang/uk/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => ':user оновив :timeLength', 'meta_owned_name' => 'Власник :user', 'entity_select' => 'Вибір об\'єкта', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Зображення', 'my_recent_drafts' => 'Мої останні чернетки', 'my_recently_viewed' => 'Мої недавні перегляди', From 4b770ee2dc700f132c38505022761c4f75e54898 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:49:56 +0100 Subject: [PATCH 049/246] New translations entities.php (Polish) --- resources/lang/pl/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/pl/entities.php b/resources/lang/pl/entities.php index 114a2bfa9..546955fb0 100644 --- a/resources/lang/pl/entities.php +++ b/resources/lang/pl/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Zaktualizowano :timeLength przez :user', 'meta_owned_name' => 'Właściciel: :user', 'entity_select' => 'Wybór obiektu', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Obrazki', 'my_recent_drafts' => 'Moje ostatnie wersje robocze', 'my_recently_viewed' => 'Moje ostatnio wyświetlane', From 01c2c927106ab1e7f9584a076dc7e6aa6d07b614 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:49:57 +0100 Subject: [PATCH 050/246] New translations entities.php (Dutch) --- resources/lang/nl/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/nl/entities.php b/resources/lang/nl/entities.php index 25cf6a2aa..6e909b944 100644 --- a/resources/lang/nl/entities.php +++ b/resources/lang/nl/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Bijgewerkt: :timeLength door :user', 'meta_owned_name' => 'Eigendom van :user', 'entity_select' => 'Entiteit selecteren', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Afbeeldingen', 'my_recent_drafts' => 'Mijn recente concepten', 'my_recently_viewed' => 'Mijn recent bekeken', From 42c6179350b05a04a4e980e96c13388b7e7d8640 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:49:58 +0100 Subject: [PATCH 051/246] New translations entities.php (Lithuanian) --- resources/lang/lt/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/lt/entities.php b/resources/lang/lt/entities.php index 7b2a3deee..29c8c89fd 100644 --- a/resources/lang/lt/entities.php +++ b/resources/lang/lt/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Atnaujinta :timeLength naudotojo :user', 'meta_owned_name' => 'Priklauso :user', 'entity_select' => 'Pasirinkti subjektą', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Nuotraukos', 'my_recent_drafts' => 'Naujausi išsaugoti juodraščiai', 'my_recently_viewed' => 'Neseniai peržiūrėti', From 89de7a60c6ce7c4a9783bc745f4ec3173444be58 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:49:59 +0100 Subject: [PATCH 052/246] New translations entities.php (Korean) --- resources/lang/ko/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/ko/entities.php b/resources/lang/ko/entities.php index 68392b0a2..1161e7ebc 100644 --- a/resources/lang/ko/entities.php +++ b/resources/lang/ko/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => '수정함 :timeLength, :user', 'meta_owned_name' => '소유함 :user', 'entity_select' => '항목 선택', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => '이미지', 'my_recent_drafts' => '내 최근의 초안 문서', 'my_recently_viewed' => '내가 읽은 문서', From d76bdbc97608607484892f621dd27aaed5f1e6c4 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:00 +0100 Subject: [PATCH 053/246] New translations entities.php (Japanese) --- resources/lang/ja/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/ja/entities.php b/resources/lang/ja/entities.php index fbabbd1a2..c13ca2d47 100644 --- a/resources/lang/ja/entities.php +++ b/resources/lang/ja/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => '更新: :timeLength (:user)', 'meta_owned_name' => '所有者: :user', 'entity_select' => 'エンティティ選択', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => '画像', 'my_recent_drafts' => '最近の下書き', 'my_recently_viewed' => '閲覧履歴', From 387b6620e4b1ff2df80126e99c43d1e1acda44b6 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:01 +0100 Subject: [PATCH 054/246] New translations entities.php (Russian) --- resources/lang/ru/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/ru/entities.php b/resources/lang/ru/entities.php index 21a492cd5..331cad7b3 100644 --- a/resources/lang/ru/entities.php +++ b/resources/lang/ru/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => ':user обновил :timeLength', 'meta_owned_name' => 'Владелец :user', 'entity_select' => 'Выбор объекта', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Изображения', 'my_recent_drafts' => 'Мои последние черновики', 'my_recently_viewed' => 'Мои недавние просмотры', From 79e386f4570b83176ed0bef72325b860498b3649 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:02 +0100 Subject: [PATCH 055/246] New translations entities.php (Hungarian) --- resources/lang/hu/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/hu/entities.php b/resources/lang/hu/entities.php index 795c642a9..d47ebd373 100644 --- a/resources/lang/hu/entities.php +++ b/resources/lang/hu/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => ':user frissítette :timeLength', 'meta_owned_name' => ':user tulajdona', 'entity_select' => 'Entitás kiválasztása', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Képek', 'my_recent_drafts' => 'Legutóbbi vázlataim', 'my_recently_viewed' => 'Általam legutóbb megtekintett', From 0cd44a6e7d4e500d05c50c0edc9d6c5e9239a9c9 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:03 +0100 Subject: [PATCH 056/246] New translations entities.php (Arabic) --- resources/lang/ar/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/ar/entities.php b/resources/lang/ar/entities.php index 16ecb6ad9..aa55faa4e 100644 --- a/resources/lang/ar/entities.php +++ b/resources/lang/ar/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'مُحدث :timeLength بواسطة :user', 'meta_owned_name' => 'Owned by :user', 'entity_select' => 'اختيار الكيان', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'صور', 'my_recent_drafts' => 'مسوداتي الحديثة', 'my_recently_viewed' => 'ما عرضته مؤخراً', From aad2f54c159c22d7199afa452fabcb83bdbf097c Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:04 +0100 Subject: [PATCH 057/246] New translations entities.php (Hebrew) --- resources/lang/he/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/he/entities.php b/resources/lang/he/entities.php index f3fcb8688..e01d95d34 100644 --- a/resources/lang/he/entities.php +++ b/resources/lang/he/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'עודכן :timeLength על ידי :user', 'meta_owned_name' => 'Owned by :user', 'entity_select' => 'בחר יישות', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'תמונות', 'my_recent_drafts' => 'הטיוטות האחרונות שלי', 'my_recently_viewed' => 'הנצפים לאחרונה שלי', From f832a9545e83b2dafdc31054123989347c18693a Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:05 +0100 Subject: [PATCH 058/246] New translations entities.php (German) --- resources/lang/de/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/de/entities.php b/resources/lang/de/entities.php index beb984bfd..68200b63a 100644 --- a/resources/lang/de/entities.php +++ b/resources/lang/de/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Zuletzt aktualisiert: :timeLength von :user', 'meta_owned_name' => 'Im Besitz von :user', 'entity_select' => 'Eintrag auswählen', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Bilder', 'my_recent_drafts' => 'Meine kürzlichen Entwürfe', 'my_recently_viewed' => 'Kürzlich von mir angesehen', From bc8d2d82097a2983b2d632faaa5239c343b58352 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:06 +0100 Subject: [PATCH 059/246] New translations entities.php (French) --- resources/lang/fr/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/fr/entities.php b/resources/lang/fr/entities.php index ddb677725..f726e8b34 100644 --- a/resources/lang/fr/entities.php +++ b/resources/lang/fr/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Mis à jour :timeLength par :user', 'meta_owned_name' => 'Appartient à :user', 'entity_select' => 'Sélectionner l\'entité', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Images', 'my_recent_drafts' => 'Mes brouillons récents', 'my_recently_viewed' => 'Vus récemment', From 0b89642610431703e53f8640de670d13f3451317 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:07 +0100 Subject: [PATCH 060/246] New translations entities.php (Spanish) --- resources/lang/es/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/es/entities.php b/resources/lang/es/entities.php index 5aa7eff1c..e4beba40a 100644 --- a/resources/lang/es/entities.php +++ b/resources/lang/es/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Actualizado :timeLength por :user', 'meta_owned_name' => 'Propiedad de :user', 'entity_select' => 'Seleccione entidad', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Imágenes', 'my_recent_drafts' => 'Mis borradores recientes', 'my_recently_viewed' => 'Mis visualizaciones recientes', From 0143fe88d38ecff9c3cb99fb118e47074213431b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:08 +0100 Subject: [PATCH 061/246] New translations entities.php (Bulgarian) --- resources/lang/bg/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/bg/entities.php b/resources/lang/bg/entities.php index 462e9623a..ad90afaa3 100644 --- a/resources/lang/bg/entities.php +++ b/resources/lang/bg/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Актуализирано преди :timeLength от :user', 'meta_owned_name' => 'Притежавано от :user', 'entity_select' => 'Избор на обект', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Изображения', 'my_recent_drafts' => 'Моите скорошни драфтове', 'my_recently_viewed' => 'Моите скорошни преглеждания', From 76049f0cdbf4e3eebda184be54d81a7e4cada7e6 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:09 +0100 Subject: [PATCH 062/246] New translations entities.php (Catalan) --- resources/lang/ca/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/ca/entities.php b/resources/lang/ca/entities.php index be5d33948..e90eb2adf 100644 --- a/resources/lang/ca/entities.php +++ b/resources/lang/ca/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Actualitzat :timeLength per :user', 'meta_owned_name' => 'Propietat de :user', 'entity_select' => 'Selecciona una entitat', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Imatges', 'my_recent_drafts' => 'Els vostres esborranys recents', 'my_recently_viewed' => 'Les vostres visualitzacions recents', From ea0ac2a853f388b721ee7a8385e2c334cb4a44dd Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:10 +0100 Subject: [PATCH 063/246] New translations entities.php (Czech) --- resources/lang/cs/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/cs/entities.php b/resources/lang/cs/entities.php index a7e42fd4f..2af719d1c 100644 --- a/resources/lang/cs/entities.php +++ b/resources/lang/cs/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Aktualizováno :timeLength uživatelem :user', 'meta_owned_name' => 'Vlastník :user', 'entity_select' => 'Výběr entity', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Obrázky', 'my_recent_drafts' => 'Mé nedávné koncepty', 'my_recently_viewed' => 'Mé nedávno zobrazené', From 2fcb0b6db2a3f449d796840c58f5d9cafe0eafe7 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:11 +0100 Subject: [PATCH 064/246] New translations entities.php (Danish) --- resources/lang/da/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/da/entities.php b/resources/lang/da/entities.php index 529dbbcac..022a6444a 100644 --- a/resources/lang/da/entities.php +++ b/resources/lang/da/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Opdateret :timeLength af :user', 'meta_owned_name' => 'Ejet af :user', 'entity_select' => 'Vælg emne', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Billeder', 'my_recent_drafts' => 'Mine seneste kladder', 'my_recently_viewed' => 'Mine senest viste', From f3eb7c42082814764a32f240f6c5a290035ec6dd Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:12 +0100 Subject: [PATCH 065/246] New translations entities.php (Basque) --- resources/lang/eu/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/eu/entities.php b/resources/lang/eu/entities.php index 87a55e368..8da46224e 100644 --- a/resources/lang/eu/entities.php +++ b/resources/lang/eu/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => ':timeLength aldatuta. Erabiltzailea :user', 'meta_owned_name' => ':user da jabea', 'entity_select' => 'Aukeratutako entitatea', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Irudiak', 'my_recent_drafts' => 'Nire azken zirriborroak', 'my_recently_viewed' => 'Nik Ikusitako azkenak', From 7b4e36eb38e793cfd6d85ed6eca448821fee8303 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:13 +0100 Subject: [PATCH 066/246] New translations entities.php (Estonian) --- resources/lang/et/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/et/entities.php b/resources/lang/et/entities.php index ae49d2d29..7bf09782e 100644 --- a/resources/lang/et/entities.php +++ b/resources/lang/et/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Muudetud :timeLength kasutaja :user poolt', 'meta_owned_name' => 'Kuulub kasutajale :user', 'entity_select' => 'Objekti valik', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Pildid', 'my_recent_drafts' => 'Minu hiljutised mustandid', 'my_recently_viewed' => 'Minu viimati vaadatud', From cffa0a0cf382bb603d4c59f820eb12125a264d60 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:14 +0100 Subject: [PATCH 067/246] New translations entities.php (Norwegian Bokmal) --- resources/lang/nb/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/nb/entities.php b/resources/lang/nb/entities.php index 11b39a79e..88f2f1edd 100644 --- a/resources/lang/nb/entities.php +++ b/resources/lang/nb/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Oppdatert :timeLength av :user', 'meta_owned_name' => 'Eies av :user', 'entity_select' => 'Velg entitet', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Bilder', 'my_recent_drafts' => 'Mine nylige utkast', 'my_recently_viewed' => 'Mine nylige visninger', From d77c0d3dddb548e5ce8e3aaa4ded21f3dd179480 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:15 +0100 Subject: [PATCH 068/246] New translations entities.php (Uzbek) --- resources/lang/uz/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/uz/entities.php b/resources/lang/uz/entities.php index 3dd7ace47..d2337dfc2 100644 --- a/resources/lang/uz/entities.php +++ b/resources/lang/uz/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => ':user tomonidan :timeLength da yangilangan', 'meta_owned_name' => 'Egasi :user', 'entity_select' => 'Entity Select', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Rasmlar', 'my_recent_drafts' => 'Mening oxirgi qoralamalarim', 'my_recently_viewed' => 'Mening oxirgi ko\'rganlarim', From 9023487d9986825cf0037a3c792f48ccbd055d94 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:16 +0100 Subject: [PATCH 069/246] New translations entities.php (Bosnian) --- resources/lang/bs/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/bs/entities.php b/resources/lang/bs/entities.php index c9cd0bb5d..7684399f3 100644 --- a/resources/lang/bs/entities.php +++ b/resources/lang/bs/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Ažurirana :timeLength od :user', 'meta_owned_name' => 'Vlasnik je :user', 'entity_select' => 'Odaberi entitet', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Slike', 'my_recent_drafts' => 'Moje nedavne skice', 'my_recently_viewed' => 'Moji nedavni pregledi', From f3f72fde6b5e32eabf28e3a4fa45106eab1cf023 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:17 +0100 Subject: [PATCH 070/246] New translations entities.php (Welsh) --- resources/lang/cy/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/cy/entities.php b/resources/lang/cy/entities.php index 27d67487a..aa353bdac 100644 --- a/resources/lang/cy/entities.php +++ b/resources/lang/cy/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Updated :timeLength by :user', 'meta_owned_name' => 'Owned by :user', 'entity_select' => 'Entity Select', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Images', 'my_recent_drafts' => 'My Recent Drafts', 'my_recently_viewed' => 'My Recently Viewed', From a2440e20bc017a7f3754308ecd5229903ab714f7 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:18 +0100 Subject: [PATCH 071/246] New translations entities.php (Latvian) --- resources/lang/lv/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/lv/entities.php b/resources/lang/lv/entities.php index 120b64de6..2c5953ab2 100644 --- a/resources/lang/lv/entities.php +++ b/resources/lang/lv/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => ':user atjauninājis pirms :timeLength', 'meta_owned_name' => 'Īpašnieks :user', 'entity_select' => 'Izvēlēties vienumu', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Attēli', 'my_recent_drafts' => 'Mani melnraksti', 'my_recently_viewed' => 'Mani nesen skatītie', From b3b8da0fe718fb0e71a4b0402628068568fd69b8 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:19 +0100 Subject: [PATCH 072/246] New translations entities.php (Vietnamese) --- resources/lang/vi/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/vi/entities.php b/resources/lang/vi/entities.php index 516273126..765f443ee 100644 --- a/resources/lang/vi/entities.php +++ b/resources/lang/vi/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Được cập nhật :timeLength bởi :user', 'meta_owned_name' => 'Được sở hữu bởi :user', 'entity_select' => 'Chọn thực thể', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Ảnh', 'my_recent_drafts' => 'Bản nháp gần đây của tôi', 'my_recently_viewed' => 'Xem gần đây', From a48a1d80aef5e29c34056afc6a8b754233353ef0 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:20 +0100 Subject: [PATCH 073/246] New translations entities.php (Croatian) --- resources/lang/hr/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/hr/entities.php b/resources/lang/hr/entities.php index f85dbc6cf..1cc499072 100644 --- a/resources/lang/hr/entities.php +++ b/resources/lang/hr/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Ažurirano :timeLength od :user', 'meta_owned_name' => 'Vlasništvo :user', 'entity_select' => 'Odaberi subjekt', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Slike', 'my_recent_drafts' => 'Nedavne skice', 'my_recently_viewed' => 'Nedavno viđeno', From 4eb76699a9d2d8483fb1115bc07e7c4f92890300 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:21 +0100 Subject: [PATCH 074/246] New translations entities.php (Spanish, Argentina) --- resources/lang/es_AR/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/es_AR/entities.php b/resources/lang/es_AR/entities.php index af17df25e..da3a36133 100644 --- a/resources/lang/es_AR/entities.php +++ b/resources/lang/es_AR/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Actualizado el :timeLength por :user', 'meta_owned_name' => 'Propiedad de :user', 'entity_select' => 'Seleccione entidad', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Imágenes', 'my_recent_drafts' => 'Mis borradores recientes', 'my_recently_viewed' => 'Mis visualizaciones recientes', From cb5b4392f4ad0d8113b9d2dec2b477aad8cc0603 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:22 +0100 Subject: [PATCH 075/246] New translations entities.php (Persian) --- resources/lang/fa/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/fa/entities.php b/resources/lang/fa/entities.php index 5ca3b4180..36ed71be7 100644 --- a/resources/lang/fa/entities.php +++ b/resources/lang/fa/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'به روزرسانی شده :timeLength توسط :user', 'meta_owned_name' => 'توسط :user ایجاد شده‌است', 'entity_select' => 'انتخاب موجودیت', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'عکس ها', 'my_recent_drafts' => 'پیش نویس های اخیر من', 'my_recently_viewed' => 'بازدیدهای اخیر من', From b7f84171c6f6c2bdbafc709ed6314cd81751a74f Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:23 +0100 Subject: [PATCH 076/246] New translations entities.php (Indonesian) --- resources/lang/id/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/id/entities.php b/resources/lang/id/entities.php index b3e860b82..c10850765 100644 --- a/resources/lang/id/entities.php +++ b/resources/lang/id/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Diperbaharui :timeLength oleh :user', 'meta_owned_name' => 'Dimiliki oleh :user', 'entity_select' => 'Pilihan Entitas', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Gambar-gambar', 'my_recent_drafts' => 'Draf Terbaru Saya', 'my_recently_viewed' => 'Baru saja saya lihat', From f0049e346bef36127e2297e4cf22b55d8b81bf29 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:24 +0100 Subject: [PATCH 077/246] New translations entities.php (Portuguese, Brazilian) --- resources/lang/pt_BR/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/pt_BR/entities.php b/resources/lang/pt_BR/entities.php index e4dd60e7e..071cb5f7a 100644 --- a/resources/lang/pt_BR/entities.php +++ b/resources/lang/pt_BR/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Atualizado :timeLength por :user', 'meta_owned_name' => 'De :user', 'entity_select' => 'Seleção de Entidade', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Imagens', 'my_recent_drafts' => 'Meus Rascunhos Recentes', 'my_recently_viewed' => 'Visualizados por mim Recentemente', From e01a0e61d91472de43060a58fc3f6c7f98463e6a Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:24 +0100 Subject: [PATCH 078/246] New translations entities.php (Chinese Traditional) --- resources/lang/zh_TW/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/zh_TW/entities.php b/resources/lang/zh_TW/entities.php index 19016fe13..5334c8ccf 100644 --- a/resources/lang/zh_TW/entities.php +++ b/resources/lang/zh_TW/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => '由 :user 更新於 :timeLength', 'meta_owned_name' => ':user 所擁有', 'entity_select' => '選取項目', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => '圖片', 'my_recent_drafts' => '我最近的草稿', 'my_recently_viewed' => '我最近檢視', From bcd06c1d565611301f11d42bb03167d40a820897 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:26 +0100 Subject: [PATCH 079/246] New translations entities.php (Chinese Simplified) --- resources/lang/zh_CN/entities.php | 1 + 1 file changed, 1 insertion(+) diff --git a/resources/lang/zh_CN/entities.php b/resources/lang/zh_CN/entities.php index 6dcccac80..2c240d3f6 100644 --- a/resources/lang/zh_CN/entities.php +++ b/resources/lang/zh_CN/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => '由 :user 更新于 :timeLength', 'meta_owned_name' => '拥有者 :user', 'entity_select' => '选择项目', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => '图片', 'my_recent_drafts' => '我最近的草稿', 'my_recently_viewed' => '我最近看过', From 7be7caacd5075e96b60f42eede5209ce2b516a03 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 10:50:26 +0100 Subject: [PATCH 080/246] New translations entities.php (German Informal) --- resources/lang/de_informal/entities.php | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/resources/lang/de_informal/entities.php b/resources/lang/de_informal/entities.php index 74282a77a..428509ac8 100644 --- a/resources/lang/de_informal/entities.php +++ b/resources/lang/de_informal/entities.php @@ -24,6 +24,7 @@ return [ 'meta_updated_name' => 'Zuletzt aktualisiert: :timeLength von :user', 'meta_owned_name' => 'Im Besitz von :user', 'entity_select' => 'Eintrag auswählen', + 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', 'images' => 'Bilder', 'my_recent_drafts' => 'Meine kürzlichen Entwürfe', 'my_recently_viewed' => 'Kürzlich von mir angesehen', @@ -357,14 +358,14 @@ return [ 'copy_consider_access' => 'Eine Veränderung der Position, Besitzers oder Berechtigungen könnte dafür sorgen, dass Unberechtigte, Zugriff bekommen.', // Conversions - 'convert_to_shelf' => 'Convert to Shelf', - 'convert_to_shelf_contents_desc' => 'You can convert this book to a new shelf with the same contents. Chapters contained within this book will be converted to new books. If this book contains any pages, that are not in a chapter, this book will be renamed and contain such pages, and this book will become part of the new shelf.', - 'convert_to_shelf_permissions_desc' => 'Any permissions set on this book will be copied to the new shelf and to all new child books that don\'t have their own permissions enforced. Note that permissions on shelves do not auto-cascade to content within, as they do for books.', - 'convert_book' => 'Convert Book', - 'convert_book_confirm' => 'Are you sure you want to convert this book?', - 'convert_undo_warning' => 'This cannot be as easily undone.', - 'convert_to_book' => 'Convert to Book', - 'convert_to_book_desc' => 'You can convert this chapter to a new book with the same contents. Any permissions set on this chapter will be copied to the new book but any inherited permissions, from the parent book, will not be copied which could lead to a change of access control.', - 'convert_chapter' => 'Convert Chapter', - 'convert_chapter_confirm' => 'Are you sure you want to convert this chapter?', + 'convert_to_shelf' => 'In Regal umwandeln', + 'convert_to_shelf_contents_desc' => 'Sie können dieses Buch in ein neues Regal mit dem gleichen Inhalt umwandeln. Kapitel in diesem Buch werden in neue Bücher umgewandelt. Wenn dieses Buch Seiten enthält, die nicht in einem Kapitel sind, wird dieses Buch entsprechend umbenannt und wird Teil des neuen Regals.', + 'convert_to_shelf_permissions_desc' => 'Alle Berechtigungen dieses Buches werden in das neue Regal kopiert und in alle darin enthaltenen neuen Bücher, die keine eigenen Berechtigungen haben. Beachten Sie, dass die Berechtigungen für Regale nicht automatisch auf die enthaltenen Inhalte angewendet werden, wie es bei Büchern der Fall ist.', + 'convert_book' => 'Buch umwandeln', + 'convert_book_confirm' => 'Sind Sie sicher, dass Sie dieses Buch umwandeln möchten?', + 'convert_undo_warning' => 'Dies kann nicht so einfach rückgängig gemacht werden.', + 'convert_to_book' => 'In Buch umwandeln', + 'convert_to_book_desc' => 'Sie können dieses Kapitel zu einem neuen Buch mit dem gleichen Inhalt umwandeln. Alle Berechtigungen für dieses Kapitel werden in das neue Buch übernommen, aber alle vom ursprünglichen Buch vererbten Berechtigungen werden nicht übernommen, daher kann es zu Änderungen im Zugriff kommen.', + 'convert_chapter' => 'Kapitel umwandeln', + 'convert_chapter_confirm' => 'Sind Sie sicher, dass Sie dieses Kapitel umwandeln möchten?', ]; From 8f9923c7c103d1ae0870434ec07a09fa3ddb46c2 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 13:08:44 +0100 Subject: [PATCH 081/246] Re-ordered theme events to be alphabetical --- app/Theming/ThemeEvents.php | 50 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/app/Theming/ThemeEvents.php b/app/Theming/ThemeEvents.php index ce99c817c..300b26f2d 100644 --- a/app/Theming/ThemeEvents.php +++ b/app/Theming/ThemeEvents.php @@ -23,30 +23,6 @@ class ThemeEvents */ const APP_BOOT = 'app_boot'; - /** - * Web before middleware action. - * Runs before the request is handled but after all other middleware apart from those - * that depend on the current session user (Localization for example). - * Provides the original request to use. - * Return values, if provided, will be used as a new response to use. - * - * @param \Illuminate\Http\Request $request - * @returns \Illuminate\Http\Response|null - */ - const WEB_MIDDLEWARE_BEFORE = 'web_middleware_before'; - - /** - * Web after middleware action. - * Runs after the request is handled but before the response is sent. - * Provides both the original request and the currently resolved response. - * Return values, if provided, will be used as a new response to use. - * - * @param \Illuminate\Http\Request $request - * @param \Illuminate\Http\Response|Symfony\Component\HttpFoundation\BinaryFileResponse $response - * @returns \Illuminate\Http\Response|null - */ - const WEB_MIDDLEWARE_AFTER = 'web_middleware_after'; - /** * Auth login event. * Runs right after a user is logged-in to the application by any authentication @@ -72,7 +48,7 @@ class ThemeEvents /** * Commonmark environment configure. * Provides the commonmark library environment for customization - * before its used to render markdown content. + * before it's used to render markdown content. * If the listener returns a non-null value, that will be used as an environment instead. * * @param \League\CommonMark\ConfigurableEnvironmentInterface $environment @@ -80,6 +56,30 @@ class ThemeEvents */ const COMMONMARK_ENVIRONMENT_CONFIGURE = 'commonmark_environment_configure'; + /** + * Web before middleware action. + * Runs before the request is handled but after all other middleware apart from those + * that depend on the current session user (Localization for example). + * Provides the original request to use. + * Return values, if provided, will be used as a new response to use. + * + * @param \Illuminate\Http\Request $request + * @returns \Illuminate\Http\Response|null + */ + const WEB_MIDDLEWARE_BEFORE = 'web_middleware_before'; + + /** + * Web after middleware action. + * Runs after the request is handled but before the response is sent. + * Provides both the original request and the currently resolved response. + * Return values, if provided, will be used as a new response to use. + * + * @param \Illuminate\Http\Request $request + * @param \Illuminate\Http\Response|\Symfony\Component\HttpFoundation\BinaryFileResponse $response + * @returns \Illuminate\Http\Response|null + */ + const WEB_MIDDLEWARE_AFTER = 'web_middleware_after'; + /** * Webhook call before event. * Runs before a webhook endpoint is called. Allows for customization From 5f5b6ff0beac5698e9f4352fbe9ee91424b3bf5b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 13:28:56 +0100 Subject: [PATCH 082/246] Added "ACTIVITY_LOGGED" theme event Closes #3572 --- app/Actions/ActivityLogger.php | 4 ++++ app/Theming/ThemeEvents.php | 13 +++++++++++++ tests/ThemeTest.php | 19 +++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/app/Actions/ActivityLogger.php b/app/Actions/ActivityLogger.php index eea5409fb..468bb4705 100644 --- a/app/Actions/ActivityLogger.php +++ b/app/Actions/ActivityLogger.php @@ -3,7 +3,9 @@ namespace BookStack\Actions; use BookStack\Entities\Models\Entity; +use BookStack\Facades\Theme; use BookStack\Interfaces\Loggable; +use BookStack\Theming\ThemeEvents; use Illuminate\Database\Eloquent\Builder; use Illuminate\Support\Facades\Log; @@ -27,8 +29,10 @@ class ActivityLogger } $activity->save(); + $this->setNotification($type); $this->dispatchWebhooks($type, $detail); + Theme::dispatch(ThemeEvents::ACTIVITY_LOGGED, $type, $detail); } /** diff --git a/app/Theming/ThemeEvents.php b/app/Theming/ThemeEvents.php index 300b26f2d..427147146 100644 --- a/app/Theming/ThemeEvents.php +++ b/app/Theming/ThemeEvents.php @@ -15,6 +15,19 @@ namespace BookStack\Theming; */ class ThemeEvents { + /** + * Activity logged event. + * Runs right after an activity is logged by bookstack. + * These are the activities that can be seen in the audit log area of BookStack. + * Activity types can be seen listed in the \BookStack\Actions\ActivityType class. + * The provided $detail can be a string or a loggable type of model. You should check + * the type before making use of this parameter. + * + * @param string $type + * @param string|\BookStack\Interfaces\Loggable $detail + */ + const ACTIVITY_LOGGED = 'activity_logged'; + /** * Application boot-up. * After main services are registered. diff --git a/tests/ThemeTest.php b/tests/ThemeTest.php index 85b8b9d36..76be03567 100644 --- a/tests/ThemeTest.php +++ b/tests/ThemeTest.php @@ -6,6 +6,7 @@ use BookStack\Actions\ActivityType; use BookStack\Actions\DispatchWebhookJob; use BookStack\Actions\Webhook; use BookStack\Auth\User; +use BookStack\Entities\Models\Book; use BookStack\Entities\Models\Page; use BookStack\Entities\Tools\PageContent; use BookStack\Facades\Theme; @@ -196,6 +197,24 @@ class ThemeTest extends TestCase }); } + public function test_event_activity_logged() + { + $book = Book::query()->first(); + $args = []; + $callback = function (...$eventArgs) use (&$args) { + $args = $eventArgs; + }; + + Theme::listen(ThemeEvents::ACTIVITY_LOGGED, $callback); + $this->asEditor()->put($book->getUrl(), ['name' => 'My cool update book!']); + + $this->assertCount(2, $args); + $this->assertEquals(ActivityType::BOOK_UPDATE, $args[0]); + $this->assertTrue($args[1] instanceof Book); + $this->assertEquals($book->id, $args[1]->id); + } + + public function test_add_social_driver() { Theme::addSocialDriver('catnet', [ From 24f4febcd57cec3cd3378c17abd81d939a08668b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 14:01:59 +0100 Subject: [PATCH 083/246] Updated DOMPDF, and other PHP dependancies --- app/Config/app.php | 2 - app/Config/dompdf.php | 43 +++- app/Entities/Tools/PdfGenerator.php | 2 +- composer.json | 2 +- composer.lock | 317 ++++++++++++++++++---------- 5 files changed, 238 insertions(+), 128 deletions(-) diff --git a/app/Config/app.php b/app/Config/app.php index 5f516f4ad..a164de1fa 100644 --- a/app/Config/app.php +++ b/app/Config/app.php @@ -197,8 +197,6 @@ return [ // Third Party 'ImageTool' => Intervention\Image\Facades\Image::class, - 'DomPDF' => Barryvdh\DomPDF\Facade::class, - 'SnappyPDF' => Barryvdh\Snappy\Facades\SnappyPdf::class, // Custom BookStack 'Activity' => BookStack\Facades\Activity::class, diff --git a/app/Config/dompdf.php b/app/Config/dompdf.php index a8728852c..ac206a0ce 100644 --- a/app/Config/dompdf.php +++ b/app/Config/dompdf.php @@ -15,8 +15,8 @@ $dompdfPaperSizeMap = [ return [ 'show_warnings' => false, // Throw an Exception on warnings from dompdf - 'orientation' => 'portrait', - 'defines' => [ + + 'options' => [ /** * The location of the DOMPDF font directory. * @@ -77,15 +77,25 @@ return [ 'chroot' => realpath(public_path()), /** - * Whether to use Unicode fonts or not. + * Protocol whitelist * - * When set to true the PDF backend must be set to "CPDF" and fonts must be - * loaded via load_font.php. + * Protocols and PHP wrappers allowed in URIs, and the validation rules + * that determine if a resouce may be loaded. Full support is not guaranteed + * for the protocols/wrappers specified + * by this array. * - * When enabled, dompdf can support all Unicode glyphs. Any glyphs used in a - * document must be present in your fonts, however. + * @var array */ - 'unicode_enabled' => true, + 'allowed_protocols' => [ + "file://" => ["rules" => []], + "http://" => ["rules" => []], + "https://" => ["rules" => []] + ], + + /** + * @var string + */ + 'log_output_file' => null, /** * Whether to enable font subsetting or not. @@ -156,6 +166,15 @@ return [ */ 'default_paper_size' => $dompdfPaperSizeMap[env('EXPORT_PAGE_SIZE', 'a4')] ?? 'a4', + /** + * The default paper orientation. + * + * The orientation of the page (portrait or landscape). + * + * @var string + */ + 'default_paper_orientation' => "portrait", + /** * The default font family. * @@ -258,10 +277,12 @@ return [ 'enable_css_float' => true, /** - * Use the more-than-experimental HTML5 Lib parser. + * Use the HTML5 Lib parser + * + * @deprecated This feature is now always on in dompdf 2.x + * @var bool */ - 'enable_html5parser' => true, - + "enable_html5_parser" => true, ], ]; diff --git a/app/Entities/Tools/PdfGenerator.php b/app/Entities/Tools/PdfGenerator.php index 17a7da9f3..d0c9158a9 100644 --- a/app/Entities/Tools/PdfGenerator.php +++ b/app/Entities/Tools/PdfGenerator.php @@ -2,7 +2,7 @@ namespace BookStack\Entities\Tools; -use Barryvdh\DomPDF\Facade as DomPDF; +use Barryvdh\DomPDF\Facade\Pdf as DomPDF; use Barryvdh\Snappy\Facades\SnappyPdf; class PdfGenerator diff --git a/composer.json b/composer.json index a18cb216b..a54977321 100644 --- a/composer.json +++ b/composer.json @@ -17,7 +17,7 @@ "ext-mbstring": "*", "ext-xml": "*", "bacon/bacon-qr-code": "^2.0", - "barryvdh/laravel-dompdf": "^1.0", + "barryvdh/laravel-dompdf": "^2.0", "barryvdh/laravel-snappy": "^1.0", "doctrine/dbal": "^3.1", "filp/whoops": "^2.14", diff --git a/composer.lock b/composer.lock index 7135fe6e9..040bce4a1 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "02b8da6ea67b03c2b5c62da865e36b02", + "content-hash": "23657e068ced89802ea578718478da3a", "packages": [ { "name": "aws/aws-crt-php", @@ -58,16 +58,16 @@ }, { "name": "aws/aws-sdk-php", - "version": "3.228.0", + "version": "3.231.7", "source": { "type": "git", "url": "https://github.com/aws/aws-sdk-php.git", - "reference": "4ff51d01da43aa3bd36eef921a9cd4e0ff843fab" + "reference": "25f7cf72a1d7cf3075436cfbfdc4caed201df3ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/4ff51d01da43aa3bd36eef921a9cd4e0ff843fab", - "reference": "4ff51d01da43aa3bd36eef921a9cd4e0ff843fab", + "url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/25f7cf72a1d7cf3075436cfbfdc4caed201df3ec", + "reference": "25f7cf72a1d7cf3075436cfbfdc4caed201df3ec", "shasum": "" }, "require": { @@ -75,7 +75,7 @@ "ext-json": "*", "ext-pcre": "*", "ext-simplexml": "*", - "guzzlehttp/guzzle": "^6.5.7 || ^7.4.4", + "guzzlehttp/guzzle": "^6.5.8 || ^7.4.5", "guzzlehttp/promises": "^1.4.0", "guzzlehttp/psr7": "^1.8.5 || ^2.3", "mtdowling/jmespath.php": "^2.6", @@ -85,6 +85,7 @@ "andrewsville/php-token-reflection": "^1.4", "aws/aws-php-sns-message-validator": "~1.0", "behat/behat": "~3.0", + "composer/composer": "^1.10.22", "doctrine/cache": "~1.4", "ext-dom": "*", "ext-openssl": "*", @@ -143,9 +144,9 @@ "support": { "forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80", "issues": "https://github.com/aws/aws-sdk-php/issues", - "source": "https://github.com/aws/aws-sdk-php/tree/3.228.0" + "source": "https://github.com/aws/aws-sdk-php/tree/3.231.7" }, - "time": "2022-06-21T18:13:25+00:00" + "time": "2022-07-15T18:16:42+00:00" }, { "name": "bacon/bacon-qr-code", @@ -203,20 +204,20 @@ }, { "name": "barryvdh/laravel-dompdf", - "version": "v1.0.2", + "version": "v2.0.0", "source": { "type": "git", "url": "https://github.com/barryvdh/laravel-dompdf.git", - "reference": "de83130d029289e1b59f28b41c314ce1d157b4a0" + "reference": "1d47648c6cef37f715ecb8bcc5f5a656ad372e27" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/de83130d029289e1b59f28b41c314ce1d157b4a0", - "reference": "de83130d029289e1b59f28b41c314ce1d157b4a0", + "url": "https://api.github.com/repos/barryvdh/laravel-dompdf/zipball/1d47648c6cef37f715ecb8bcc5f5a656ad372e27", + "reference": "1d47648c6cef37f715ecb8bcc5f5a656ad372e27", "shasum": "" }, "require": { - "dompdf/dompdf": "^1.2.1", + "dompdf/dompdf": "^2", "illuminate/support": "^6|^7|^8|^9", "php": "^7.2 || ^8.0" }, @@ -229,13 +230,14 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" }, "laravel": { "providers": [ "Barryvdh\\DomPDF\\ServiceProvider" ], "aliases": { + "Pdf": "Barryvdh\\DomPDF\\Facade\\Pdf", "PDF": "Barryvdh\\DomPDF\\Facade\\Pdf" } } @@ -263,7 +265,7 @@ ], "support": { "issues": "https://github.com/barryvdh/laravel-dompdf/issues", - "source": "https://github.com/barryvdh/laravel-dompdf/tree/v1.0.2" + "source": "https://github.com/barryvdh/laravel-dompdf/tree/v2.0.0" }, "funding": [ { @@ -275,7 +277,7 @@ "type": "github" } ], - "time": "2022-05-19T15:08:38+00:00" + "time": "2022-07-06T11:12:10+00:00" }, { "name": "barryvdh/laravel-snappy", @@ -972,21 +974,22 @@ }, { "name": "dompdf/dompdf", - "version": "v1.2.2", + "version": "v2.0.0", "source": { "type": "git", "url": "https://github.com/dompdf/dompdf.git", - "reference": "5031045d9640b38cfc14aac9667470df09c9e090" + "reference": "79573d8b8a141ec8a17312515de8740eed014fa9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dompdf/dompdf/zipball/5031045d9640b38cfc14aac9667470df09c9e090", - "reference": "5031045d9640b38cfc14aac9667470df09c9e090", + "url": "https://api.github.com/repos/dompdf/dompdf/zipball/79573d8b8a141ec8a17312515de8740eed014fa9", + "reference": "79573d8b8a141ec8a17312515de8740eed014fa9", "shasum": "" }, "require": { "ext-dom": "*", "ext-mbstring": "*", + "masterminds/html5": "^2.0", "phenx/php-font-lib": "^0.5.4", "phenx/php-svg-lib": "^0.3.3 || ^0.4.0", "php": "^7.1 || ^8.0" @@ -1035,9 +1038,9 @@ "homepage": "https://github.com/dompdf/dompdf", "support": { "issues": "https://github.com/dompdf/dompdf/issues", - "source": "https://github.com/dompdf/dompdf/tree/v1.2.2" + "source": "https://github.com/dompdf/dompdf/tree/v2.0.0" }, - "time": "2022-04-27T13:50:54+00:00" + "time": "2022-06-21T21:14:57+00:00" }, { "name": "dragonmantank/cron-expression", @@ -1784,16 +1787,16 @@ }, { "name": "laravel/framework", - "version": "v8.83.17", + "version": "v8.83.19", "source": { "type": "git", "url": "https://github.com/laravel/framework.git", - "reference": "2cf142cd5100b02da248acad3988bdaba5635e16" + "reference": "4264f2ee12330bdb1be050998f58ba7271236395" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/laravel/framework/zipball/2cf142cd5100b02da248acad3988bdaba5635e16", - "reference": "2cf142cd5100b02da248acad3988bdaba5635e16", + "url": "https://api.github.com/repos/laravel/framework/zipball/4264f2ee12330bdb1be050998f58ba7271236395", + "reference": "4264f2ee12330bdb1be050998f58ba7271236395", "shasum": "" }, "require": { @@ -1953,7 +1956,7 @@ "issues": "https://github.com/laravel/framework/issues", "source": "https://github.com/laravel/framework" }, - "time": "2022-06-21T14:38:31+00:00" + "time": "2022-07-13T13:23:09+00:00" }, { "name": "laravel/serializable-closure", @@ -2401,16 +2404,16 @@ }, { "name": "league/flysystem-aws-s3-v3", - "version": "1.0.29", + "version": "1.0.30", "source": { "type": "git", "url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git", - "reference": "4e25cc0582a36a786c31115e419c6e40498f6972" + "reference": "af286f291ebab6877bac0c359c6c2cb017eb061d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/4e25cc0582a36a786c31115e419c6e40498f6972", - "reference": "4e25cc0582a36a786c31115e419c6e40498f6972", + "url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/af286f291ebab6877bac0c359c6c2cb017eb061d", + "reference": "af286f291ebab6877bac0c359c6c2cb017eb061d", "shasum": "" }, "require": { @@ -2446,9 +2449,23 @@ "description": "Flysystem adapter for the AWS S3 SDK v3.x", "support": { "issues": "https://github.com/thephpleague/flysystem-aws-s3-v3/issues", - "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/1.0.29" + "source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/1.0.30" }, - "time": "2020-10-08T18:58:37+00:00" + "funding": [ + { + "url": "https://offset.earth/frankdejonge", + "type": "custom" + }, + { + "url": "https://github.com/frankdejonge", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/league/flysystem", + "type": "tidelift" + } + ], + "time": "2022-07-02T13:51:38+00:00" }, { "name": "league/html-to-markdown", @@ -2741,6 +2758,75 @@ }, "time": "2021-12-22T16:42:49+00:00" }, + { + "name": "masterminds/html5", + "version": "2.7.5", + "source": { + "type": "git", + "url": "https://github.com/Masterminds/html5-php.git", + "reference": "f640ac1bdddff06ea333a920c95bbad8872429ab" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Masterminds/html5-php/zipball/f640ac1bdddff06ea333a920c95bbad8872429ab", + "reference": "f640ac1bdddff06ea333a920c95bbad8872429ab", + "shasum": "" + }, + "require": { + "ext-ctype": "*", + "ext-dom": "*", + "ext-libxml": "*", + "php": ">=5.3.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.7.21 || ^6 || ^7" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.7-dev" + } + }, + "autoload": { + "psr-4": { + "Masterminds\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Matt Butcher", + "email": "technosophos@gmail.com" + }, + { + "name": "Matt Farina", + "email": "matt@mattfarina.com" + }, + { + "name": "Asmir Mustafic", + "email": "goetas@gmail.com" + } + ], + "description": "An HTML5 parser and serializer.", + "homepage": "http://masterminds.github.io/html5-php", + "keywords": [ + "HTML5", + "dom", + "html", + "parser", + "querypath", + "serializer", + "xml" + ], + "support": { + "issues": "https://github.com/Masterminds/html5-php/issues", + "source": "https://github.com/Masterminds/html5-php/tree/2.7.5" + }, + "time": "2021-07-01T14:25:37+00:00" + }, { "name": "monolog/monolog", "version": "2.7.0", @@ -2908,16 +2994,16 @@ }, { "name": "nesbot/carbon", - "version": "2.58.0", + "version": "2.59.1", "source": { "type": "git", "url": "https://github.com/briannesbitt/Carbon.git", - "reference": "97a34af22bde8d0ac20ab34b29d7bfe360902055" + "reference": "a9000603ea337c8df16cc41f8b6be95a65f4d0f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/97a34af22bde8d0ac20ab34b29d7bfe360902055", - "reference": "97a34af22bde8d0ac20ab34b29d7bfe360902055", + "url": "https://api.github.com/repos/briannesbitt/Carbon/zipball/a9000603ea337c8df16cc41f8b6be95a65f4d0f5", + "reference": "a9000603ea337c8df16cc41f8b6be95a65f4d0f5", "shasum": "" }, "require": { @@ -2932,11 +3018,12 @@ "doctrine/orm": "^2.7", "friendsofphp/php-cs-fixer": "^3.0", "kylekatarnls/multi-tester": "^2.0", + "ondrejmirtes/better-reflection": "*", "phpmd/phpmd": "^2.9", "phpstan/extension-installer": "^1.0", - "phpstan/phpstan": "^0.12.54 || ^1.0", - "phpunit/php-file-iterator": "^2.0.5", - "phpunit/phpunit": "^7.5.20 || ^8.5.23", + "phpstan/phpstan": "^0.12.99 || ^1.7.14", + "phpunit/php-file-iterator": "^2.0.5 || ^3.0.6", + "phpunit/phpunit": "^7.5.20 || ^8.5.26 || ^9.5.20", "squizlabs/php_codesniffer": "^3.4" }, "bin": [ @@ -2993,15 +3080,19 @@ }, "funding": [ { - "url": "https://opencollective.com/Carbon", - "type": "open_collective" + "url": "https://github.com/sponsors/kylekatarnls", + "type": "github" }, { - "url": "https://tidelift.com/funding/github/packagist/nesbot/carbon", + "url": "https://opencollective.com/Carbon#sponsor", + "type": "opencollective" + }, + { + "url": "https://tidelift.com/subscription/pkg/packagist-nesbot-carbon?utm_source=packagist-nesbot-carbon&utm_medium=referral&utm_campaign=readme", "type": "tidelift" } ], - "time": "2022-04-25T19:31:17+00:00" + "time": "2022-06-29T21:43:55+00:00" }, { "name": "nikic/php-parser", @@ -3061,16 +3152,16 @@ }, { "name": "onelogin/php-saml", - "version": "4.0.1", + "version": "4.1.0", "source": { "type": "git", "url": "https://github.com/onelogin/php-saml.git", - "reference": "247a45c079e65a78185d5489bdda0f95826c014d" + "reference": "b22a57ebd13e838b90df5d3346090bc37056409d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/onelogin/php-saml/zipball/247a45c079e65a78185d5489bdda0f95826c014d", - "reference": "247a45c079e65a78185d5489bdda0f95826c014d", + "url": "https://api.github.com/repos/onelogin/php-saml/zipball/b22a57ebd13e838b90df5d3346090bc37056409d", + "reference": "b22a57ebd13e838b90df5d3346090bc37056409d", "shasum": "" }, "require": { @@ -3113,7 +3204,7 @@ "issues": "https://github.com/onelogin/php-saml/issues", "source": "https://github.com/onelogin/php-saml/" }, - "time": "2022-06-15T16:07:51+00:00" + "time": "2022-07-15T20:44:36+00:00" }, { "name": "opis/closure", @@ -4095,16 +4186,16 @@ }, { "name": "psy/psysh", - "version": "v0.11.5", + "version": "v0.11.7", "source": { "type": "git", "url": "https://github.com/bobthecow/psysh.git", - "reference": "c23686f9c48ca202710dbb967df8385a952a2daf" + "reference": "77fc7270031fbc28f9a7bea31385da5c4855cb7a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/bobthecow/psysh/zipball/c23686f9c48ca202710dbb967df8385a952a2daf", - "reference": "c23686f9c48ca202710dbb967df8385a952a2daf", + "url": "https://api.github.com/repos/bobthecow/psysh/zipball/77fc7270031fbc28f9a7bea31385da5c4855cb7a", + "reference": "77fc7270031fbc28f9a7bea31385da5c4855cb7a", "shasum": "" }, "require": { @@ -4165,9 +4256,9 @@ ], "support": { "issues": "https://github.com/bobthecow/psysh/issues", - "source": "https://github.com/bobthecow/psysh/tree/v0.11.5" + "source": "https://github.com/bobthecow/psysh/tree/v0.11.7" }, - "time": "2022-05-27T18:03:49+00:00" + "time": "2022-07-07T13:49:11+00:00" }, { "name": "ralouphie/getallheaders", @@ -4955,16 +5046,16 @@ }, { "name": "symfony/console", - "version": "v5.4.9", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb" + "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/829d5d1bf60b2efeb0887b7436873becc71a45eb", - "reference": "829d5d1bf60b2efeb0887b7436873becc71a45eb", + "url": "https://api.github.com/repos/symfony/console/zipball/4d671ab4ddac94ee439ea73649c69d9d200b5000", + "reference": "4d671ab4ddac94ee439ea73649c69d9d200b5000", "shasum": "" }, "require": { @@ -5034,7 +5125,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v5.4.9" + "source": "https://github.com/symfony/console/tree/v5.4.10" }, "funding": [ { @@ -5050,7 +5141,7 @@ "type": "tidelift" } ], - "time": "2022-05-18T06:17:34+00:00" + "time": "2022-06-26T13:00:04+00:00" }, { "name": "symfony/css-selector", @@ -5120,7 +5211,7 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", @@ -5167,7 +5258,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v2.5.2" }, "funding": [ { @@ -5343,7 +5434,7 @@ }, { "name": "symfony/event-dispatcher-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher-contracts.git", @@ -5402,7 +5493,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/event-dispatcher-contracts/tree/v2.5.2" }, "funding": [ { @@ -5485,16 +5576,16 @@ }, { "name": "symfony/http-foundation", - "version": "v5.4.9", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "6b0d0e4aca38d57605dcd11e2416994b38774522" + "reference": "e7793b7906f72a8cc51054fbca9dcff7a8af1c1e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/6b0d0e4aca38d57605dcd11e2416994b38774522", - "reference": "6b0d0e4aca38d57605dcd11e2416994b38774522", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/e7793b7906f72a8cc51054fbca9dcff7a8af1c1e", + "reference": "e7793b7906f72a8cc51054fbca9dcff7a8af1c1e", "shasum": "" }, "require": { @@ -5538,7 +5629,7 @@ "description": "Defines an object-oriented layer for the HTTP specification", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-foundation/tree/v5.4.9" + "source": "https://github.com/symfony/http-foundation/tree/v5.4.10" }, "funding": [ { @@ -5554,20 +5645,20 @@ "type": "tidelift" } ], - "time": "2022-05-17T15:07:29+00:00" + "time": "2022-06-19T13:13:40+00:00" }, { "name": "symfony/http-kernel", - "version": "v5.4.9", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "34b121ad3dc761f35fe1346d2f15618f8cbf77f8" + "reference": "255ae3b0a488d78fbb34da23d3e0c059874b5948" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/34b121ad3dc761f35fe1346d2f15618f8cbf77f8", - "reference": "34b121ad3dc761f35fe1346d2f15618f8cbf77f8", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/255ae3b0a488d78fbb34da23d3e0c059874b5948", + "reference": "255ae3b0a488d78fbb34da23d3e0c059874b5948", "shasum": "" }, "require": { @@ -5650,7 +5741,7 @@ "description": "Provides a structured process for converting a Request into a Response", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/http-kernel/tree/v5.4.9" + "source": "https://github.com/symfony/http-kernel/tree/v5.4.10" }, "funding": [ { @@ -5666,20 +5757,20 @@ "type": "tidelift" } ], - "time": "2022-05-27T07:09:08+00:00" + "time": "2022-06-26T16:57:59+00:00" }, { "name": "symfony/mime", - "version": "v5.4.9", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/mime.git", - "reference": "2b3802a24e48d0cfccf885173d2aac91e73df92e" + "reference": "02265e1e5111c3cd7480387af25e82378b7ab9cc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/mime/zipball/2b3802a24e48d0cfccf885173d2aac91e73df92e", - "reference": "2b3802a24e48d0cfccf885173d2aac91e73df92e", + "url": "https://api.github.com/repos/symfony/mime/zipball/02265e1e5111c3cd7480387af25e82378b7ab9cc", + "reference": "02265e1e5111c3cd7480387af25e82378b7ab9cc", "shasum": "" }, "require": { @@ -5733,7 +5824,7 @@ "mime-type" ], "support": { - "source": "https://github.com/symfony/mime/tree/v5.4.9" + "source": "https://github.com/symfony/mime/tree/v5.4.10" }, "funding": [ { @@ -5749,7 +5840,7 @@ "type": "tidelift" } ], - "time": "2022-05-21T10:24:18+00:00" + "time": "2022-06-09T12:22:40+00:00" }, { "name": "symfony/polyfill-ctype", @@ -6722,16 +6813,16 @@ }, { "name": "symfony/service-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c" + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/24d9dc654b83e91aa59f9d167b131bc3b5bea24c", - "reference": "24d9dc654b83e91aa59f9d167b131bc3b5bea24c", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/4b426aac47d6427cc1a1d0f7e2ac724627f5966c", + "reference": "4b426aac47d6427cc1a1d0f7e2ac724627f5966c", "shasum": "" }, "require": { @@ -6785,7 +6876,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v2.5.2" }, "funding": [ { @@ -6801,20 +6892,20 @@ "type": "tidelift" } ], - "time": "2022-03-13T20:07:29+00:00" + "time": "2022-05-30T19:17:29+00:00" }, { "name": "symfony/string", - "version": "v5.4.9", + "version": "v5.4.10", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99" + "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/985e6a9703ef5ce32ba617c9c7d97873bb7b2a99", - "reference": "985e6a9703ef5ce32ba617c9c7d97873bb7b2a99", + "url": "https://api.github.com/repos/symfony/string/zipball/4432bc7df82a554b3e413a8570ce2fea90e94097", + "reference": "4432bc7df82a554b3e413a8570ce2fea90e94097", "shasum": "" }, "require": { @@ -6871,7 +6962,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v5.4.9" + "source": "https://github.com/symfony/string/tree/v5.4.10" }, "funding": [ { @@ -6887,7 +6978,7 @@ "type": "tidelift" } ], - "time": "2022-04-19T10:40:37+00:00" + "time": "2022-06-26T15:57:47+00:00" }, { "name": "symfony/translation", @@ -6988,16 +7079,16 @@ }, { "name": "symfony/translation-contracts", - "version": "v2.5.1", + "version": "v2.5.2", "source": { "type": "git", "url": "https://github.com/symfony/translation-contracts.git", - "reference": "1211df0afa701e45a04253110e959d4af4ef0f07" + "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/1211df0afa701e45a04253110e959d4af4ef0f07", - "reference": "1211df0afa701e45a04253110e959d4af4ef0f07", + "url": "https://api.github.com/repos/symfony/translation-contracts/zipball/136b19dd05cdf0709db6537d058bcab6dd6e2dbe", + "reference": "136b19dd05cdf0709db6537d058bcab6dd6e2dbe", "shasum": "" }, "require": { @@ -7046,7 +7137,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/translation-contracts/tree/v2.5.1" + "source": "https://github.com/symfony/translation-contracts/tree/v2.5.2" }, "funding": [ { @@ -7062,7 +7153,7 @@ "type": "tidelift" } ], - "time": "2022-01-02T09:53:40+00:00" + "time": "2022-06-27T16:58:25+00:00" }, { "name": "symfony/var-dumper", @@ -7498,16 +7589,16 @@ }, { "name": "composer/composer", - "version": "2.3.7", + "version": "2.3.10", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "10cd375cf85dede2ff417ceab517ef9a0dc55407" + "reference": "ebac357c0a41359f3981098729042ed6dedc97ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/10cd375cf85dede2ff417ceab517ef9a0dc55407", - "reference": "10cd375cf85dede2ff417ceab517ef9a0dc55407", + "url": "https://api.github.com/repos/composer/composer/zipball/ebac357c0a41359f3981098729042ed6dedc97ba", + "reference": "ebac357c0a41359f3981098729042ed6dedc97ba", "shasum": "" }, "require": { @@ -7588,7 +7679,7 @@ "support": { "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", - "source": "https://github.com/composer/composer/tree/2.3.7" + "source": "https://github.com/composer/composer/tree/2.3.10" }, "funding": [ { @@ -7604,7 +7695,7 @@ "type": "tidelift" } ], - "time": "2022-06-06T14:43:28+00:00" + "time": "2022-07-13T13:48:23+00:00" }, { "name": "composer/metadata-minifier", @@ -9008,16 +9099,16 @@ }, { "name": "phpstan/phpstan", - "version": "1.7.15", + "version": "1.8.1", "source": { "type": "git", "url": "https://github.com/phpstan/phpstan.git", - "reference": "cd0202ea1b1fc6d1bbe156c6e2e18a03e0ff160a" + "reference": "8dbba631fa32f4b289404469c2afd6122fd61d67" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpstan/phpstan/zipball/cd0202ea1b1fc6d1bbe156c6e2e18a03e0ff160a", - "reference": "cd0202ea1b1fc6d1bbe156c6e2e18a03e0ff160a", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/8dbba631fa32f4b289404469c2afd6122fd61d67", + "reference": "8dbba631fa32f4b289404469c2afd6122fd61d67", "shasum": "" }, "require": { @@ -9043,7 +9134,7 @@ "description": "PHPStan - PHP Static Analysis Tool", "support": { "issues": "https://github.com/phpstan/phpstan/issues", - "source": "https://github.com/phpstan/phpstan/tree/1.7.15" + "source": "https://github.com/phpstan/phpstan/tree/1.8.1" }, "funding": [ { @@ -9063,7 +9154,7 @@ "type": "tidelift" } ], - "time": "2022-06-20T08:29:01+00:00" + "time": "2022-07-12T16:08:06+00:00" }, { "name": "phpunit/php-code-coverage", From 56da25b07a3ffce5b2140af660b244c6145d1b9b Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 14:32:09 +0100 Subject: [PATCH 084/246] Fixed failing tests from dompdf chanages --- tests/Entity/PageContentTest.php | 2 +- tests/Unit/ConfigTest.php | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/Entity/PageContentTest.php b/tests/Entity/PageContentTest.php index b9680d23f..c18ae18f7 100644 --- a/tests/Entity/PageContentTest.php +++ b/tests/Entity/PageContentTest.php @@ -527,7 +527,7 @@ class PageContentTest extends TestCase $pageView = $this->get($page->getUrl()); $pageView->assertElementExists('.page-content li.task-list-item input[type=checkbox]'); - $pageView->assertElementExists('.page-content li.task-list-item input[type=checkbox][checked=checked]'); + $pageView->assertElementExists('.page-content li.task-list-item input[type=checkbox][checked]'); } public function test_page_markdown_strikethrough_rendering() diff --git a/tests/Unit/ConfigTest.php b/tests/Unit/ConfigTest.php index 8c5b43810..3d15005af 100644 --- a/tests/Unit/ConfigTest.php +++ b/tests/Unit/ConfigTest.php @@ -78,15 +78,15 @@ class ConfigTest extends TestCase public function test_dompdf_remote_fetching_controlled_by_allow_untrusted_server_fetching_false() { - $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'false', 'dompdf.defines.enable_remote', false); - $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'true', 'dompdf.defines.enable_remote', true); + $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'false', 'dompdf.options.enable_remote', false); + $this->checkEnvConfigResult('ALLOW_UNTRUSTED_SERVER_FETCHING', 'true', 'dompdf.options.enable_remote', true); } public function test_dompdf_paper_size_options_are_limited() { - $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'cat', 'dompdf.defines.default_paper_size', 'a4'); - $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'letter', 'dompdf.defines.default_paper_size', 'letter'); - $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'a4', 'dompdf.defines.default_paper_size', 'a4'); + $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'cat', 'dompdf.options.default_paper_size', 'a4'); + $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'letter', 'dompdf.options.default_paper_size', 'letter'); + $this->checkEnvConfigResult('EXPORT_PAGE_SIZE', 'a4', 'dompdf.options.default_paper_size', 'a4'); } public function test_snappy_paper_size_options_are_limited() From e024b03a61ae758fbea7f91870e1b0fa09fcdf0a Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 17:19:51 +0100 Subject: [PATCH 085/246] New translations entities.php (Chinese Simplified) --- resources/lang/zh_CN/entities.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/lang/zh_CN/entities.php b/resources/lang/zh_CN/entities.php index 2c240d3f6..3d3988006 100644 --- a/resources/lang/zh_CN/entities.php +++ b/resources/lang/zh_CN/entities.php @@ -24,7 +24,7 @@ return [ 'meta_updated_name' => '由 :user 更新于 :timeLength', 'meta_owned_name' => '拥有者 :user', 'entity_select' => '选择项目', - 'entity_select_lack_permission' => 'You don\'t have the required permissions to select this item', + 'entity_select_lack_permission' => '您没有选择此项目所需的权限', 'images' => '图片', 'my_recent_drafts' => '我最近的草稿', 'my_recently_viewed' => '我最近看过', @@ -359,7 +359,7 @@ return [ // Conversions 'convert_to_shelf' => '转换为书架', - 'convert_to_shelf_contents_desc' => '你可以将这本书转换为具有相同内容的新书架。本书中的章节将被转换为图书。如果这本书包含任何不在章节分类中的页面,那么将会有一本图书被重命名并包含这些页面,这本书也将成为新书架的一部分。', + 'convert_to_shelf_contents_desc' => '你可以将这本书转换为具有相同内容的新书架。本书中的章节将被转换为图书。如果这本书包含有任何不在章节分类中的页面,那么将会有一本单独的图书包含这些页面,这本书也将成为新书架的一部分。', 'convert_to_shelf_permissions_desc' => '在这本书上设置的任何权限都将复制到所有未强制执行权限的新书架和新子图书上。请注意,书架上的权限不会像图书那样继承到内容物上。', 'convert_book' => '转换图书', 'convert_book_confirm' => '您确定要转换此图书吗?', From c519f707e82693cfe6d392c04dd8e2efaeca24ca Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Sun, 17 Jul 2022 18:33:03 +0100 Subject: [PATCH 086/246] Started upgrade to TinyMCE6, Untested - Merged in latest TinyMCE code. - Gone through tinymce upgrade guide, made required config changes. - Altered license references. --- .../libs/tinymce/icons/default/icons.min.js | 2 +- public/libs/tinymce/license.txt | 525 +--- public/libs/tinymce/models/dom/model.min.js | 4 + .../tinymce/plugins/advlist/plugin.min.js | 9 +- .../libs/tinymce/plugins/anchor/plugin.min.js | 9 +- .../tinymce/plugins/autolink/plugin.min.js | 9 +- .../tinymce/plugins/autoresize/plugin.min.js | 9 +- .../tinymce/plugins/autosave/plugin.min.js | 9 +- .../libs/tinymce/plugins/bbcode/plugin.min.js | 9 - .../tinymce/plugins/charmap/plugin.min.js | 9 +- .../libs/tinymce/plugins/code/plugin.min.js | 9 +- .../tinymce/plugins/codesample/plugin.min.js | 9 +- .../tinymce/plugins/colorpicker/plugin.min.js | 9 - .../tinymce/plugins/contextmenu/plugin.min.js | 9 - .../plugins/directionality/plugin.min.js | 9 +- .../tinymce/plugins/fullpage/plugin.min.js | 9 - .../tinymce/plugins/fullscreen/plugin.min.js | 9 +- .../libs/tinymce/plugins/help/plugin.min.js | 9 +- public/libs/tinymce/plugins/hr/plugin.min.js | 9 - .../libs/tinymce/plugins/image/plugin.min.js | 9 +- .../tinymce/plugins/imagetools/plugin.min.js | 9 - .../tinymce/plugins/importcss/plugin.min.js | 9 +- .../plugins/insertdatetime/plugin.min.js | 9 +- .../plugins/legacyoutput/plugin.min.js | 9 - .../libs/tinymce/plugins/link/plugin.min.js | 9 +- .../libs/tinymce/plugins/lists/plugin.min.js | 9 +- .../libs/tinymce/plugins/media/plugin.min.js | 9 +- .../tinymce/plugins/nonbreaking/plugin.min.js | 9 +- .../tinymce/plugins/noneditable/plugin.min.js | 9 - .../tinymce/plugins/pagebreak/plugin.min.js | 9 +- .../libs/tinymce/plugins/paste/plugin.min.js | 9 - .../tinymce/plugins/preview/plugin.min.js | 9 +- .../libs/tinymce/plugins/print/plugin.min.js | 9 - .../tinymce/plugins/quickbars/plugin.min.js | 9 +- .../libs/tinymce/plugins/save/plugin.min.js | 9 +- .../plugins/searchreplace/plugin.min.js | 9 +- .../plugins/spellchecker/plugin.min.js | 9 - .../tinymce/plugins/tabfocus/plugin.min.js | 9 - .../libs/tinymce/plugins/table/plugin.min.js | 9 +- .../tinymce/plugins/template/plugin.min.js | 9 +- .../tinymce/plugins/textcolor/plugin.min.js | 9 - .../tinymce/plugins/textpattern/plugin.min.js | 9 - public/libs/tinymce/plugins/toc/plugin.min.js | 9 - .../plugins/visualblocks/plugin.min.js | 9 +- .../tinymce/plugins/visualchars/plugin.min.js | 9 +- .../tinymce/plugins/wordcount/plugin.min.js | 9 +- .../skins/content/dark/content.min.css | 8 +- .../skins/content/default/content.min.css | 6 - .../skins/content/document/content.min.css | 6 - .../content/tinymce-5-dark/content.min.css | 1 + .../skins/content/tinymce-5/content.min.css | 1 + .../skins/content/writer/content.min.css | 6 - .../ui/oxide-dark/content.inline.min.css | 8 +- .../skins/ui/oxide-dark/content.min.css | 8 +- .../ui/oxide-dark/content.mobile.min.css | 7 - .../ui/oxide-dark/fonts/tinymce-mobile.woff | Bin 4624 -> 0 bytes .../tinymce/skins/ui/oxide-dark/skin.min.css | 8 +- .../skins/ui/oxide-dark/skin.mobile.min.css | 7 - .../ui/oxide-dark/skin.shadowdom.min.css | 8 +- .../skins/ui/oxide/content.inline.min.css | 8 +- .../tinymce/skins/ui/oxide/content.min.css | 8 +- .../skins/ui/oxide/content.mobile.min.css | 7 - .../skins/ui/oxide/fonts/tinymce-mobile.woff | Bin 4624 -> 0 bytes .../libs/tinymce/skins/ui/oxide/skin.min.css | 8 +- .../skins/ui/oxide/skin.mobile.min.css | 7 - .../skins/ui/oxide/skin.shadowdom.min.css | 8 +- .../ui/tinymce-5-dark/content.inline.min.css | 1 + .../skins/ui/tinymce-5-dark/content.min.css | 1 + .../skins/ui/tinymce-5-dark/skin.min.css | 1 + .../ui/tinymce-5-dark/skin.shadowdom.min.css | 1 + .../skins/ui/tinymce-5/content.inline.min.css | 1 + .../skins/ui/tinymce-5/content.min.css | 1 + .../tinymce/skins/ui/tinymce-5/skin.min.css | 1 + .../skins/ui/tinymce-5/skin.shadowdom.min.css | 1 + .../libs/tinymce/themes/mobile/theme.min.js | 9 - .../libs/tinymce/themes/silver/theme.min.js | 9 +- public/libs/tinymce/tinymce.d.ts | 2361 ++++++++--------- public/libs/tinymce/tinymce.min.js | 9 +- readme.md | 2 +- resources/js/wysiwyg/config.js | 11 +- resources/js/wysiwyg/drop-paste-handling.js | 4 +- resources/js/wysiwyg/plugin-drawio.js | 2 +- resources/js/wysiwyg/plugins-details.js | 4 +- resources/js/wysiwyg/toolbars.js | 2 +- resources/lang/en/editor.php | 2 +- 85 files changed, 1228 insertions(+), 2233 deletions(-) create mode 100644 public/libs/tinymce/models/dom/model.min.js delete mode 100644 public/libs/tinymce/plugins/bbcode/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/colorpicker/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/contextmenu/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/fullpage/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/hr/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/imagetools/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/legacyoutput/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/noneditable/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/paste/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/print/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/spellchecker/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/tabfocus/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/textcolor/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/textpattern/plugin.min.js delete mode 100644 public/libs/tinymce/plugins/toc/plugin.min.js create mode 100644 public/libs/tinymce/skins/content/tinymce-5-dark/content.min.css create mode 100644 public/libs/tinymce/skins/content/tinymce-5/content.min.css delete mode 100644 public/libs/tinymce/skins/ui/oxide-dark/content.mobile.min.css delete mode 100644 public/libs/tinymce/skins/ui/oxide-dark/fonts/tinymce-mobile.woff delete mode 100644 public/libs/tinymce/skins/ui/oxide-dark/skin.mobile.min.css delete mode 100644 public/libs/tinymce/skins/ui/oxide/content.mobile.min.css delete mode 100644 public/libs/tinymce/skins/ui/oxide/fonts/tinymce-mobile.woff delete mode 100644 public/libs/tinymce/skins/ui/oxide/skin.mobile.min.css create mode 100644 public/libs/tinymce/skins/ui/tinymce-5-dark/content.inline.min.css create mode 100644 public/libs/tinymce/skins/ui/tinymce-5-dark/content.min.css create mode 100644 public/libs/tinymce/skins/ui/tinymce-5-dark/skin.min.css create mode 100644 public/libs/tinymce/skins/ui/tinymce-5-dark/skin.shadowdom.min.css create mode 100644 public/libs/tinymce/skins/ui/tinymce-5/content.inline.min.css create mode 100644 public/libs/tinymce/skins/ui/tinymce-5/content.min.css create mode 100644 public/libs/tinymce/skins/ui/tinymce-5/skin.min.css create mode 100644 public/libs/tinymce/skins/ui/tinymce-5/skin.shadowdom.min.css delete mode 100644 public/libs/tinymce/themes/mobile/theme.min.js diff --git a/public/libs/tinymce/icons/default/icons.min.js b/public/libs/tinymce/icons/default/icons.min.js index 2cf9ef86d..144a49905 100644 --- a/public/libs/tinymce/icons/default/icons.min.js +++ b/public/libs/tinymce/icons/default/icons.min.js @@ -1 +1 @@ -tinymce.IconManager.add("default",{icons:{"accessibility-check":'',"action-next":'',"action-prev":'',"align-center":'',"align-justify":'',"align-left":'',"align-none":'',"align-right":'',"arrow-left":'',"arrow-right":'',bold:'',bookmark:'',"border-style":'',"border-width":'',brightness:'',browse:'',cancel:'',"cell-background-color":'',"cell-border-color":'',"change-case":'',"character-count":'',"checklist-rtl":'',checklist:'',checkmark:'',"chevron-down":'',"chevron-left":'',"chevron-right":'',"chevron-up":'',close:'',"code-sample":'',"color-levels":'',"color-picker":'',"color-swatch-remove-color":'',"color-swatch":'',"comment-add":'',comment:'',contrast:'',copy:'',crop:'',"cut-column":'',"cut-row":'',cut:'',"document-properties":'',drag:'',"duplicate-column":'',"duplicate-row":'',duplicate:'',"edit-block":'',"edit-image":'',"embed-page":'',embed:'',emoji:'',export:'',fill:'',"flip-horizontally":'',"flip-vertically":'',"format-painter":'',format:'',fullscreen:'',gallery:'',gamma:'',help:'',"highlight-bg-color":'',home:'',"horizontal-rule":'',"image-options":'',image:'',indent:'',info:'',"insert-character":'',"insert-time":'',invert:'',italic:'',language:'',"line-height":'',line:'',link:'',"list-bull-circle":'',"list-bull-default":'',"list-bull-square":'',"list-num-default-rtl":'',"list-num-default":'',"list-num-lower-alpha-rtl":'',"list-num-lower-alpha":'',"list-num-lower-greek-rtl":'',"list-num-lower-greek":'',"list-num-lower-roman-rtl":'',"list-num-lower-roman":'',"list-num-upper-alpha-rtl":'',"list-num-upper-alpha":'',"list-num-upper-roman-rtl":'',"list-num-upper-roman":'',lock:'',ltr:'',"more-drawer":'',"new-document":'',"new-tab":'',"non-breaking":'',notice:'',"ordered-list-rtl":'',"ordered-list":'',orientation:'',outdent:'',"page-break":'',paragraph:'',"paste-column-after":'',"paste-column-before":'',"paste-row-after":'',"paste-row-before":'',"paste-text":'',paste:'',"permanent-pen":'',plus:'',preferences:'',preview:'',print:'',quote:'',redo:'',reload:'',"remove-formatting":'',remove:'',"resize-handle":'',resize:'',"restore-draft":'',"rotate-left":'',"rotate-right":'',rtl:'',save:'',search:'',"select-all":'',selected:'',settings:'',sharpen:'',sourcecode:'',"spell-check":'',"strike-through":'',subscript:'',superscript:'',"table-caption":'',"table-cell-classes":'',"table-cell-properties":'',"table-cell-select-all":'',"table-cell-select-inner":'',"table-classes":'',"table-delete-column":'',"table-delete-row":'',"table-delete-table":'',"table-insert-column-after":'',"table-insert-column-before":'',"table-insert-row-above":'',"table-insert-row-after":'',"table-left-header":'',"table-merge-cells":'',"table-row-numbering-rtl":'',"table-row-numbering":'',"table-row-properties":'',"table-split-cells":'',"table-top-header":'',table:'',template:'',"temporary-placeholder":'',"text-color":'',toc:'',translate:'',underline:'',undo:'',unlink:'',unlock:'',"unordered-list":'',unselected:'',upload:'',user:'',"vertical-align":'',visualblocks:'',visualchars:'',warning:'',"zoom-in":'',"zoom-out":''}}); \ No newline at end of file +tinymce.IconManager.add("default",{icons:{"accessibility-check":'',"action-next":'',"action-prev":'',"align-center":'',"align-justify":'',"align-left":'',"align-none":'',"align-right":'',"arrow-left":'',"arrow-right":'',bold:'',bookmark:'',"border-style":'',"border-width":'',brightness:'',browse:'',cancel:'',"cell-background-color":'',"cell-border-color":'',"change-case":'',"character-count":'',"checklist-rtl":'',checklist:'',checkmark:'',"chevron-down":'',"chevron-left":'',"chevron-right":'',"chevron-up":'',close:'',"code-sample":'',"color-levels":'',"color-picker":'',"color-swatch-remove-color":'',"color-swatch":'',"comment-add":'',comment:'',contrast:'',copy:'',crop:'',"cut-column":'',"cut-row":'',cut:'',"document-properties":'',drag:'',"duplicate-column":'',"duplicate-row":'',duplicate:'',"edit-block":'',"edit-image":'',"embed-page":'',embed:'',emoji:'',export:'',fill:'',"flip-horizontally":'',"flip-vertically":'',"format-painter":'',format:'',fullscreen:'',gallery:'',gamma:'',help:'',"highlight-bg-color":'',home:'',"horizontal-rule":'',"image-options":'',image:'',indent:'',info:'',"insert-character":'',"insert-time":'',invert:'',italic:'',language:'',"line-height":'',line:'',link:'',"list-bull-circle":'',"list-bull-default":'',"list-bull-square":'',"list-num-default-rtl":'',"list-num-default":'',"list-num-lower-alpha-rtl":'',"list-num-lower-alpha":'',"list-num-lower-greek-rtl":'',"list-num-lower-greek":'',"list-num-lower-roman-rtl":'',"list-num-lower-roman":'',"list-num-upper-alpha-rtl":'',"list-num-upper-alpha":'',"list-num-upper-roman-rtl":'',"list-num-upper-roman":'',lock:'',ltr:'',"more-drawer":'',"new-document":'',"new-tab":'',"non-breaking":'',notice:'',"ordered-list-rtl":'',"ordered-list":'',orientation:'',outdent:'',"page-break":'',paragraph:'',"paste-column-after":'',"paste-column-before":'',"paste-row-after":'',"paste-row-before":'',"paste-text":'',paste:'',"permanent-pen":'',plus:'',preferences:'',preview:'',print:'',quote:'',redo:'',reload:'',"remove-formatting":'',remove:'',"resize-handle":'',resize:'',"restore-draft":'',"rotate-left":'',"rotate-right":'',rtl:'',save:'',search:'',"select-all":'',selected:'',settings:'',sharpen:'',sourcecode:'',"spell-check":'',"strike-through":'',subscript:'',superscript:'',"table-caption":'',"table-cell-classes":'',"table-cell-properties":'',"table-cell-select-all":'',"table-cell-select-inner":'',"table-classes":'',"table-delete-column":'',"table-delete-row":'',"table-delete-table":'',"table-insert-column-after":'',"table-insert-column-before":'',"table-insert-row-above":'',"table-insert-row-after":'',"table-left-header":'',"table-merge-cells":'',"table-row-numbering-rtl":'',"table-row-numbering":'',"table-row-properties":'',"table-split-cells":'',"table-top-header":'',table:'',template:'',"temporary-placeholder":'',"text-color":'',toc:'',translate:'',underline:'',undo:'',unlink:'',unlock:'',"unordered-list":'',unselected:'',upload:'',user:'',"vertical-align":'',visualblocks:'',visualchars:'',warning:'',"zoom-in":'',"zoom-out":''}}); \ No newline at end of file diff --git a/public/libs/tinymce/license.txt b/public/libs/tinymce/license.txt index b17fc9049..3a49f66fd 100644 --- a/public/libs/tinymce/license.txt +++ b/public/libs/tinymce/license.txt @@ -1,504 +1,21 @@ - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. - - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. - - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. - - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. - - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. - - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. - - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under any -particular circumstance, the balance of the section is intended to apply, -and the section as a whole is intended to apply in other circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License may add -an explicit geographical distribution limitation excluding those countries, -so that distribution is permitted only in or among countries not thus -excluded. In such case, this License incorporates the limitation as if -written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. - - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms of the -ordinary General Public License). - - To apply these terms, attach the following notices to the library. It is -safest to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - +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. diff --git a/public/libs/tinymce/models/dom/model.min.js b/public/libs/tinymce/models/dom/model.min.js new file mode 100644 index 000000000..8e61ada4b --- /dev/null +++ b/public/libs/tinymce/models/dom/model.min.js @@ -0,0 +1,4 @@ +/** + * TinyMCE version 6.1.0 (2022-06-29) + */ +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.ModelManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(o=n=e,(r=String).prototype.isPrototypeOf(o)||(null===(s=n.constructor)||void 0===s?void 0:s.name)===r.name)?"string":t;var o,n,r,s})(t)===e,o=e=>t=>typeof t===e,n=t("string"),r=t("object"),s=t("array"),l=(null,e=>null===e);const a=o("boolean"),c=e=>!(e=>null==e)(e),i=o("function"),m=o("number"),d=()=>{},u=e=>()=>e,f=e=>e,g=(e,t)=>e===t;function h(e,...t){return(...o)=>{const n=t.concat(o);return e.apply(null,n)}}const p=e=>t=>!e(t),w=e=>e(),b=u(!1),v=u(!0);class y{constructor(e,t){this.tag=e,this.value=t}static some(e){return new y(!0,e)}static none(){return y.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?y.some(e(this.value)):y.none()}bind(e){return this.tag?e(this.value):y.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:y.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return c(e)?y.some(e):y.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}y.singletonNone=new y(!1);const x=Array.prototype.slice,C=Array.prototype.indexOf,S=Array.prototype.push,T=(e,t)=>((e,t)=>C.call(e,t))(e,t)>-1,R=(e,t)=>{for(let o=0,n=e.length;o{const o=[];for(let n=0;n{const o=e.length,n=new Array(o);for(let r=0;r{for(let o=0,n=e.length;o{const o=[],n=[];for(let r=0,s=e.length;r{const o=[];for(let n=0,r=e.length;n(((e,t)=>{for(let o=e.length-1;o>=0;o--)t(e[o],o)})(e,((e,n)=>{o=t(o,e,n)})),o),z=(e,t,o)=>(k(e,((e,n)=>{o=t(o,e,n)})),o),A=(e,t)=>((e,t,o)=>{for(let n=0,r=e.length;n{for(let o=0,n=e.length;o{const t=[];for(let o=0,n=e.length;oL(O(e,t)),M=(e,t)=>{for(let o=0,n=e.length;o{const o={};for(let n=0,r=e.length;nt>=0&&tI(e,0),F=e=>I(e,e.length-1),H=(e,t)=>{for(let o=0;o{const o=q(e);for(let n=0,r=o.length;nG(e,((e,o)=>({k:o,v:t(e,o)}))),G=(e,t)=>{const o={};return $(e,((e,n)=>{const r=t(e,n);o[r.k]=r.v})),o},K=(e,t)=>{const o=[];return $(e,((e,n)=>{o.push(t(e,n))})),o},Y=e=>K(e,f),J=(e,t)=>V.call(e,t);"undefined"!=typeof window?window:Function("return this;")();const Q=e=>e.dom.nodeName.toLowerCase(),X=e=>e.dom.nodeType,Z=e=>t=>X(t)===e,ee=e=>8===X(e)||"#comment"===Q(e),te=Z(1),oe=Z(3),ne=Z(9),re=Z(11),se=e=>t=>te(t)&&Q(t)===e,le=(e,t,o)=>{if(!(n(o)||a(o)||m(o)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",o,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,o+"")},ae=(e,t,o)=>{le(e.dom,t,o)},ce=(e,t)=>{const o=e.dom;$(t,((e,t)=>{le(o,t,e)}))},ie=(e,t)=>{const o=e.dom.getAttribute(t);return null===o?void 0:o},me=(e,t)=>y.from(ie(e,t)),de=(e,t)=>{e.dom.removeAttribute(t)},ue=e=>z(e.dom.attributes,((e,t)=>(e[t.name]=t.value,e)),{}),fe=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},ge={fromHtml:(e,t)=>{const o=(t||document).createElement("div");if(o.innerHTML=e,!o.hasChildNodes()||o.childNodes.length>1){const t="HTML does not have a single root node";throw console.error(t,e),new Error(t)}return fe(o.childNodes[0])},fromTag:(e,t)=>{const o=(t||document).createElement(e);return fe(o)},fromText:(e,t)=>{const o=(t||document).createTextNode(e);return fe(o)},fromDom:fe,fromPoint:(e,t,o)=>y.from(e.dom.elementFromPoint(t,o)).map(fe)},he=(e,t)=>{const o=e.dom;if(1!==o.nodeType)return!1;{const e=o;if(void 0!==e.matches)return e.matches(t);if(void 0!==e.msMatchesSelector)return e.msMatchesSelector(t);if(void 0!==e.webkitMatchesSelector)return e.webkitMatchesSelector(t);if(void 0!==e.mozMatchesSelector)return e.mozMatchesSelector(t);throw new Error("Browser lacks native selectors")}},pe=e=>1!==e.nodeType&&9!==e.nodeType&&11!==e.nodeType||0===e.childElementCount,we=(e,t)=>{const o=void 0===t?document:t.dom;return pe(o)?y.none():y.from(o.querySelector(e)).map(ge.fromDom)},be=(e,t)=>e.dom===t.dom,ve=(e,t)=>{const o=e.dom,n=t.dom;return o!==n&&o.contains(n)},ye=he,xe=e=>ge.fromDom(e.dom.ownerDocument),Ce=e=>ne(e)?e:xe(e),Se=e=>y.from(e.dom.parentNode).map(ge.fromDom),Te=(e,t)=>{const o=i(t)?t:b;let n=e.dom;const r=[];for(;null!==n.parentNode&&void 0!==n.parentNode;){const e=n.parentNode,t=ge.fromDom(e);if(r.push(t),!0===o(t))break;n=e}return r},Re=e=>y.from(e.dom.previousSibling).map(ge.fromDom),De=e=>y.from(e.dom.nextSibling).map(ge.fromDom),Oe=e=>O(e.dom.childNodes,ge.fromDom),ke=(e,t)=>{const o=e.dom.childNodes;return y.from(o[t]).map(ge.fromDom)},Ee=(e,t)=>{Se(e).each((o=>{o.dom.insertBefore(t.dom,e.dom)}))},Ne=(e,t)=>{De(e).fold((()=>{Se(e).each((e=>{ze(e,t)}))}),(e=>{Ee(e,t)}))},Be=(e,t)=>{const o=(e=>ke(e,0))(e);o.fold((()=>{ze(e,t)}),(o=>{e.dom.insertBefore(t.dom,o.dom)}))},ze=(e,t)=>{e.dom.appendChild(t.dom)},Ae=(e,t)=>{Ee(e,t),ze(t,e)},We=(e,t)=>{k(t,((o,n)=>{const r=0===n?e:t[n-1];Ne(r,o)}))},Le=(e,t)=>{k(t,(t=>{ze(e,t)}))},_e=e=>{e.dom.textContent="",k(Oe(e),(e=>{Me(e)}))},Me=e=>{const t=e.dom;null!==t.parentNode&&t.parentNode.removeChild(t)},je=e=>{const t=Oe(e);t.length>0&&We(e,t),Me(e)},Ie=(e,t)=>ge.fromDom(e.dom.cloneNode(t)),Pe=e=>Ie(e,!1),Fe=e=>Ie(e,!0),He=(e,t)=>{const o=ge.fromTag(t),n=ue(e);return ce(o,n),o},qe=["tfoot","thead","tbody","colgroup"],Ve=(e,t,o)=>({element:e,rowspan:t,colspan:o}),$e=(e,t,o)=>({element:e,cells:t,section:o}),Ue=(e,t,o)=>({element:e,isNew:t,isLocked:o}),Ge=(e,t,o,n)=>({element:e,cells:t,section:o,isNew:n}),Ke=i(Element.prototype.attachShadow)&&i(Node.prototype.getRootNode),Ye=u(Ke),Je=Ke?e=>ge.fromDom(e.dom.getRootNode()):Ce,Qe=e=>ge.fromDom(e.dom.host),Xe=e=>{const t=oe(e)?e.dom.parentNode:e.dom;if(null==t||null===t.ownerDocument)return!1;const o=t.ownerDocument;return(e=>{const t=Je(e);return re(o=t)&&c(o.dom.host)?y.some(t):y.none();var o})(ge.fromDom(t)).fold((()=>o.body.contains(t)),(n=Xe,r=Qe,e=>n(r(e))));var n,r},Ze=e=>{const t=e.dom.body;if(null==t)throw new Error("Body is not available yet");return ge.fromDom(t)},et=(e,t)=>{let o=[];return k(Oe(e),(e=>{t(e)&&(o=o.concat([e])),o=o.concat(et(e,t))})),o},tt=(e,t,o)=>((e,o,n)=>N(Te(e,n),(e=>he(e,t))))(e,0,o),ot=(e,t)=>((e,o)=>N(Oe(e),(e=>he(e,t))))(e),nt=(e,t)=>((e,t)=>{const o=void 0===t?document:t.dom;return pe(o)?[]:O(o.querySelectorAll(e),ge.fromDom)})(t,e);var rt=(e,t,o,n,r)=>e(o,n)?y.some(o):i(r)&&r(o)?y.none():t(o,n,r);const st=(e,t,o)=>{let n=e.dom;const r=i(o)?o:b;for(;n.parentNode;){n=n.parentNode;const e=ge.fromDom(n);if(t(e))return y.some(e);if(r(e))break}return y.none()},lt=(e,t,o)=>st(e,(e=>he(e,t)),o),at=(e,t)=>((e,o)=>A(e.dom.childNodes,(e=>{return o=ge.fromDom(e),he(o,t);var o})).map(ge.fromDom))(e),ct=(e,t)=>we(t,e),it=(e,t,o)=>rt(((e,t)=>he(e,t)),lt,e,t,o),mt=(e,t,o=g)=>e.exists((e=>o(e,t))),dt=e=>{const t=[],o=e=>{t.push(e)};for(let t=0;te?y.some(t):y.none(),ft=(e,t,o)=>""===t||e.length>=t.length&&e.substr(o,o+t.length)===t,gt=(e,t)=>-1!==e.indexOf(t),ht=(e,t)=>ft(e,t,0),pt=(e,t)=>ft(e,t,e.length-t.length),wt=(e=>t=>t.replace(e,""))(/^\s+|\s+$/g),bt=e=>e.length>0,vt=e=>void 0!==e.style&&i(e.style.getPropertyValue),yt=(e,t,o)=>{if(!n(o))throw console.error("Invalid call to CSS.set. Property ",t,":: Value ",o,":: Element ",e),new Error("CSS value must be a string: "+o);vt(e)&&e.style.setProperty(t,o)},xt=(e,t,o)=>{const n=e.dom;yt(n,t,o)},Ct=(e,t)=>{const o=e.dom;$(t,((e,t)=>{yt(o,t,e)}))},St=(e,t)=>{const o=e.dom,n=window.getComputedStyle(o).getPropertyValue(t);return""!==n||Xe(e)?n:Tt(o,t)},Tt=(e,t)=>vt(e)?e.style.getPropertyValue(t):"",Rt=(e,t)=>{const o=e.dom,n=Tt(o,t);return y.from(n).filter((e=>e.length>0))},Dt=(e,t)=>{((e,t)=>{vt(e)&&e.style.removeProperty(t)})(e.dom,t),mt(me(e,"style").map(wt),"")&&de(e,"style")},Ot=(e,t,o=0)=>me(e,t).map((e=>parseInt(e,10))).getOr(o),kt=(e,t)=>Ot(e,t,1),Et=e=>se("col")(e)?Ot(e,"span",1)>1:kt(e,"colspan")>1,Nt=e=>kt(e,"rowspan")>1,Bt=(e,t)=>parseInt(St(e,t),10),zt=u(10),At=u(10),Wt=(e,t)=>Lt(e,t,v),Lt=(e,t,o)=>_(Oe(e),(e=>he(e,t)?o(e)?[e]:[]:Lt(e,t,o))),_t=(e,t)=>((e,t,o=b)=>o(t)?y.none():T(e,Q(t))?y.some(t):lt(t,e.join(","),(e=>he(e,"table")||o(e))))(["td","th"],e,t),Mt=e=>Wt(e,"th,td"),jt=e=>he(e,"colgroup")?ot(e,"col"):_(Ft(e),(e=>ot(e,"col"))),It=(e,t)=>it(e,"table",t),Pt=e=>Wt(e,"tr"),Ft=e=>It(e).fold(u([]),(e=>ot(e,"colgroup"))),Ht=(e,t)=>O(e,(e=>{if("colgroup"===Q(e)){const t=O(jt(e),(e=>{const t=Ot(e,"span",1);return Ve(e,1,t)}));return $e(e,t,"colgroup")}{const o=O(Mt(e),(e=>{const t=Ot(e,"rowspan",1),o=Ot(e,"colspan",1);return Ve(e,t,o)}));return $e(e,o,t(e))}})),qt=e=>Se(e).map((e=>{const t=Q(e);return(e=>T(qe,e))(t)?t:"tbody"})).getOr("tbody"),Vt=e=>{const t=Pt(e),o=[...Ft(e),...t];return Ht(o,qt)},$t=e=>{let t,o=!1;return(...n)=>(o||(o=!0,t=e.apply(null,n)),t)},Ut=()=>Gt(0,0),Gt=(e,t)=>({major:e,minor:t}),Kt={nu:Gt,detect:(e,t)=>{const o=String(t).toLowerCase();return 0===e.length?Ut():((e,t)=>{const o=((e,t)=>{for(let o=0;oNumber(t.replace(o,"$"+e));return Gt(n(1),n(2))})(e,o)},unknown:Ut},Yt=(e,t)=>{const o=String(t).toLowerCase();return A(e,(e=>e.search(o)))},Jt=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,Qt=e=>t=>gt(t,e),Xt=[{name:"Edge",versionRegexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:e=>gt(e,"edge/")&>(e,"chrome")&>(e,"safari")&>(e,"applewebkit")},{name:"Chromium",brand:"Chromium",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,Jt],search:e=>gt(e,"chrome")&&!gt(e,"chromeframe")},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:e=>gt(e,"msie")||gt(e,"trident")},{name:"Opera",versionRegexes:[Jt,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:Qt("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:Qt("firefox")},{name:"Safari",versionRegexes:[Jt,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:e=>(gt(e,"safari")||gt(e,"mobile/"))&>(e,"applewebkit")}],Zt=[{name:"Windows",search:Qt("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:e=>gt(e,"iphone")||gt(e,"ipad"),versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:Qt("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"macOS",search:Qt("mac os x"),versionRegexes:[/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:Qt("linux"),versionRegexes:[]},{name:"Solaris",search:Qt("sunos"),versionRegexes:[]},{name:"FreeBSD",search:Qt("freebsd"),versionRegexes:[]},{name:"ChromeOS",search:Qt("cros"),versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/]}],eo={browsers:u(Xt),oses:u(Zt)},to="Edge",oo="Chromium",no="Opera",ro="Firefox",so="Safari",lo=e=>{const t=e.current,o=e.version,n=e=>()=>t===e;return{current:t,version:o,isEdge:n(to),isChromium:n(oo),isIE:n("IE"),isOpera:n(no),isFirefox:n(ro),isSafari:n(so)}},ao=()=>lo({current:void 0,version:Kt.unknown()}),co=lo,io=(u(to),u(oo),u("IE"),u(no),u(ro),u(so),"Windows"),mo="Android",uo="Linux",fo="macOS",go="Solaris",ho="FreeBSD",po="ChromeOS",wo=e=>{const t=e.current,o=e.version,n=e=>()=>t===e;return{current:t,version:o,isWindows:n(io),isiOS:n("iOS"),isAndroid:n(mo),isMacOS:n(fo),isLinux:n(uo),isSolaris:n(go),isFreeBSD:n(ho),isChromeOS:n(po)}},bo=()=>wo({current:void 0,version:Kt.unknown()}),vo=wo,yo=(u(io),u("iOS"),u(mo),u(uo),u(fo),u(go),u(ho),u(po),e=>window.matchMedia(e).matches);let xo=$t((()=>((e,t,o)=>{const n=eo.browsers(),r=eo.oses(),s=t.bind((e=>((e,t)=>H(t.brands,(t=>{const o=t.brand.toLowerCase();return A(e,(e=>{var t;return o===(null===(t=e.brand)||void 0===t?void 0:t.toLowerCase())})).map((e=>({current:e.name,version:Kt.nu(parseInt(t.version,10),0)})))})))(n,e))).orThunk((()=>((e,t)=>Yt(e,t).map((e=>{const o=Kt.detect(e.versionRegexes,t);return{current:e.name,version:o}})))(n,e))).fold(ao,co),l=((e,t)=>Yt(e,t).map((e=>{const o=Kt.detect(e.versionRegexes,t);return{current:e.name,version:o}})))(r,e).fold(bo,vo),a=((e,t,o,n)=>{const r=e.isiOS()&&!0===/ipad/i.test(o),s=e.isiOS()&&!r,l=e.isiOS()||e.isAndroid(),a=l||n("(pointer:coarse)"),c=r||!s&&l&&n("(min-device-width:768px)"),i=s||l&&!c,m=t.isSafari()&&e.isiOS()&&!1===/safari/i.test(o),d=!i&&!c&&!m;return{isiPad:u(r),isiPhone:u(s),isTablet:u(c),isPhone:u(i),isTouch:u(a),isAndroid:e.isAndroid,isiOS:e.isiOS,isWebView:u(m),isDesktop:u(d)}})(l,s,e,o);return{browser:s,os:l,deviceType:a}})(navigator.userAgent,y.from(navigator.userAgentData),yo)));const Co=()=>xo(),So=(e,t)=>{const o=o=>{const n=t(o);if(n<=0||null===n){const t=St(o,e);return parseFloat(t)||0}return n},n=(e,t)=>z(t,((t,o)=>{const n=St(e,o),r=void 0===n?0:parseInt(n,10);return isNaN(r)?t:t+r}),0);return{set:(t,o)=>{if(!m(o)&&!o.match(/^[0-9]+$/))throw new Error(e+".set accepts only positive integer values. Value was "+o);const n=t.dom;vt(n)&&(n.style[e]=o+"px")},get:o,getOuter:o,aggregate:n,max:(e,t,o)=>{const r=n(e,o);return t>r?t-r:0}}},To=(e,t,o)=>((e,t)=>(e=>{const t=parseFloat(e);return isNaN(t)?y.none():y.some(t)})(e).getOr(t))(St(e,t),o),Ro=So("width",(e=>e.dom.offsetWidth)),Do=e=>Ro.get(e),Oo=e=>Ro.getOuter(e),ko=e=>((e,t)=>{const o=e.dom,n=o.getBoundingClientRect().width||o.offsetWidth;return"border-box"===t?n:((e,t,o,n)=>t-To(e,"padding-left",0)-To(e,"padding-right",0)-To(e,"border-left-width",0)-To(e,"border-right-width",0))(e,n)})(e,"content-box"),Eo=(e,t,o)=>{const n=e.cells,r=n.slice(0,t),s=n.slice(t),l=r.concat(o).concat(s);return zo(e,l)},No=(e,t,o)=>Eo(e,t,[o]),Bo=(e,t,o)=>{e.cells[t]=o},zo=(e,t)=>Ge(e.element,t,e.section,e.isNew),Ao=(e,t)=>e.cells[t],Wo=(e,t)=>Ao(e,t).element,Lo=e=>e.cells.length,_o=e=>{const t=E(e,(e=>"colgroup"===e.section));return{rows:t.fail,cols:t.pass}},Mo=(e,t,o)=>{const n=O(e.cells,o);return Ge(t(e.element),n,e.section,!0)},jo="data-snooker-locked-cols",Io=e=>me(e,jo).bind((e=>y.from(e.match(/\d+/g)))).map((e=>j(e,v))),Po=e=>{const t=z(_o(e).rows,((e,t)=>(k(t.cells,((t,o)=>{t.isLocked&&(e[o]=!0)})),e)),{}),o=K(t,((e,t)=>parseInt(t,10)));return((e,t)=>{const o=x.call(e,0);return o.sort(void 0),o})(o)},Fo=(e,t)=>e+","+t,Ho=(e,t)=>{const o=_(e.all,(e=>e.cells));return N(o,t)},qo=e=>{const t={},o=[],n=P(e).map((e=>e.element)).bind(It).bind(Io).getOr({});let r=0,s=0,l=0;const{pass:a,fail:c}=E(e,(e=>"colgroup"===e.section));k(c,(e=>{const a=[];k(e.cells,(e=>{let o=0;for(;void 0!==t[Fo(l,o)];)o++;const r=((e,t)=>J(e,t)&&void 0!==e[t]&&null!==e[t])(n,o.toString()),c=((e,t,o,n,r,s)=>({element:e,rowspan:t,colspan:o,row:n,column:r,isLocked:s}))(e.element,e.rowspan,e.colspan,l,o,r);for(let n=0;n{const t=(e=>{const t={};let o=0;return k(e.cells,(e=>{const n=e.colspan;D(n,(r=>{const s=o+r;t[s]=((e,t,o)=>({element:e,colspan:t,column:o}))(e.element,n,s)})),o+=n})),t})(e),o=((e,t)=>({element:e,columns:t}))(e.element,Y(t));return{colgroups:[o],columns:t}})).getOrThunk((()=>({colgroups:[],columns:{}}))),d=((e,t)=>({rows:e,columns:t}))(r,s);return{grid:d,access:t,all:o,columns:i,colgroups:m}},Vo=e=>{const t=Vt(e);return qo(t)},$o=qo,Uo=(e,t,o)=>y.from(e.access[Fo(t,o)]),Go=(e,t,o)=>{const n=Ho(e,(e=>o(t,e.element)));return n.length>0?y.some(n[0]):y.none()},Ko=Ho,Yo=e=>_(e.all,(e=>e.cells)),Jo=e=>Y(e.columns),Qo=e=>q(e.columns).length>0,Xo=(e,t)=>y.from(e.columns[t]),Zo=(e,t=v)=>{const o=e.grid,n=D(o.columns,f),r=D(o.rows,f);return O(n,(o=>en((()=>_(r,(t=>Uo(e,t,o).filter((e=>e.column===o)).toArray()))),(e=>1===e.colspan&&t(e.element)),(()=>Uo(e,0,o)))))},en=(e,t,o)=>{const n=e();return A(n,t).orThunk((()=>y.from(n[0]).orThunk(o))).map((e=>e.element))},tn=e=>{const t=e.grid,o=D(t.rows,f),n=D(t.columns,f);return O(o,(t=>en((()=>_(n,(o=>Uo(e,t,o).filter((e=>e.row===t)).fold(u([]),(e=>[e]))))),(e=>1===e.rowspan),(()=>Uo(e,t,0)))))},on=(e,t)=>o=>"rtl"===nn(o)?t:e,nn=e=>"rtl"===St(e,"direction")?"rtl":"ltr",rn=So("height",(e=>{const t=e.dom;return Xe(e)?t.getBoundingClientRect().height:t.offsetHeight})),sn=e=>rn.get(e),ln=e=>rn.getOuter(e),an=(e,t)=>({left:e,top:t,translate:(o,n)=>an(e+o,t+n)}),cn=an,mn=(e,t)=>void 0!==e?e:void 0!==t?t:0,dn=e=>{const t=e.dom.ownerDocument,o=t.body,n=t.defaultView,r=t.documentElement;if(o===e.dom)return cn(o.offsetLeft,o.offsetTop);const s=mn(null==n?void 0:n.pageYOffset,r.scrollTop),l=mn(null==n?void 0:n.pageXOffset,r.scrollLeft),a=mn(r.clientTop,o.clientTop),c=mn(r.clientLeft,o.clientLeft);return un(e).translate(l-c,s-a)},un=e=>{const t=e.dom,o=t.ownerDocument.body;return o===t?cn(o.offsetLeft,o.offsetTop):Xe(e)?(e=>{const t=e.getBoundingClientRect();return cn(t.left,t.top)})(t):cn(0,0)},fn=(e,t)=>({row:e,y:t}),gn=(e,t)=>({col:e,x:t}),hn=e=>dn(e).left+Oo(e),pn=e=>dn(e).left,wn=(e,t)=>gn(e,pn(t)),bn=(e,t)=>gn(e,hn(t)),vn=e=>dn(e).top,yn=(e,t)=>fn(e,vn(t)),xn=(e,t)=>fn(e,vn(t)+ln(t)),Cn=(e,t,o)=>{if(0===o.length)return[];const n=O(o.slice(1),((t,o)=>t.map((t=>e(o,t))))),r=o[o.length-1].map((e=>t(o.length-1,e)));return n.concat([r])},Sn={delta:f,positions:e=>Cn(yn,xn,e),edge:vn},Tn=on({delta:f,edge:pn,positions:e=>Cn(wn,bn,e)},{delta:e=>-e,edge:hn,positions:e=>Cn(bn,wn,e)}),Rn={delta:(e,t)=>Tn(t).delta(e,t),positions:(e,t)=>Tn(t).positions(e,t),edge:e=>Tn(e).edge(e)},Dn={unsupportedLength:["em","ex","cap","ch","ic","rem","lh","rlh","vw","vh","vi","vb","vmin","vmax","cm","mm","Q","in","pc","pt","px"],fixed:["px","pt"],relative:["%"],empty:[""]},On=(()=>{const e="[0-9]+",t="[eE][+-]?[0-9]+",o=e=>`(?:${e})?`,n=["Infinity","[0-9]+\\."+o(e)+o(t),"\\.[0-9]+"+o(t),e+o(t)].join("|");return new RegExp(`^([+-]?(?:${n}))(.*)$`)})(),kn=/(\d+(\.\d+)?)%/,En=/(\d+(\.\d+)?)px|em/,Nn=se("col"),Bn=(e,t,o)=>{const n=(r=e,y.from(r.dom.parentElement).map(ge.fromDom)).getOrThunk((()=>Ze(xe(e))));var r;return t(e)/o(n)*100},zn=(e,t)=>{xt(e,"width",t+"px")},An=(e,t)=>{xt(e,"width",t+"%")},Wn=(e,t)=>{xt(e,"height",t+"px")},Ln=e=>{const t=(e=>{return To(t=e,"height",t.dom.offsetHeight)+"px";var t})(e);return t?((e,t,o,n)=>{const r=parseFloat(e);return pt(e,"%")&&"table"!==Q(t)?((e,t,o,n)=>{const r=It(e).map((e=>{const n=o(e);return Math.floor(t/100*n)})).getOr(t);return n(e,r),r})(t,r,o,n):r})(t,e,sn,Wn):sn(e)},_n=(e,t)=>Rt(e,t).orThunk((()=>me(e,t).map((e=>e+"px")))),Mn=e=>_n(e,"width"),jn=e=>Bn(e,Do,ko),In=e=>{return Nn(e)?Do(e):To(t=e,"width",t.dom.offsetWidth);var t},Pn=e=>((e,t,o)=>o(e)/kt(e,"rowspan"))(e,0,Ln),Fn=(e,t,o)=>{xt(e,"width",t+o)},Hn=e=>Bn(e,Do,ko)+"%",qn=u(kn),Vn=se("col"),$n=e=>Mn(e).getOrThunk((()=>In(e)+"px")),Un=e=>{return(t=e,_n(t,"height")).getOrThunk((()=>Pn(e)+"px"));var t},Gn=(e,t,o,n,r,s)=>e.filter(n).fold((()=>s(((e,t)=>{if(t<0||t>=e.length-1)return y.none();const o=e[t].fold((()=>{const o=(e=>{const t=x.call(e,0);return t.reverse(),t})(e.slice(0,t));return H(o,((e,t)=>e.map((e=>({value:e,delta:t+1})))))}),(e=>y.some({value:e,delta:0}))),n=e[t+1].fold((()=>{const o=e.slice(t+1);return H(o,((e,t)=>e.map((e=>({value:e,delta:t+1})))))}),(e=>y.some({value:e,delta:1})));return o.bind((e=>n.map((t=>{const o=t.delta+e.delta;return Math.abs(t.value-e.value)/o}))))})(o,t))),(e=>r(e))),Kn=(e,t,o,n)=>{const r=Zo(e),s=Qo(e)?(e=>O(Jo(e),(e=>y.from(e.element))))(e):r,l=[y.some(Rn.edge(t))].concat(O(Rn.positions(r,t),(e=>e.map((e=>e.x))))),a=p(Et);return O(s,((e,t)=>Gn(e,t,l,a,(e=>{if((e=>{const t=Co().browser,o=t.isChromium()||t.isFirefox();return!Vn(e)||o})(e))return o(e);{const e=null!=(s=r[t])?f(s):y.none();return Gn(e,t,l,a,(e=>n(y.some(Do(e)))),n)}var s}),n)))},Yn=e=>e.map((e=>e+"px")).getOr(""),Jn=(e,t,o)=>Kn(e,t,In,(e=>e.getOrThunk(o.minCellWidth))),Qn=(e,t,o,n,r)=>{const s=tn(e),l=[y.some(o.edge(t))].concat(O(o.positions(s,t),(e=>e.map((e=>e.y)))));return O(s,((e,t)=>Gn(e,t,l,p(Nt),n,r)))},Xn=(e,t)=>()=>Xe(e)?t(e):parseFloat(Rt(e,"width").getOr("0")),Zn=e=>{const t=Xn(e,(e=>parseFloat(Hn(e)))),o=Xn(e,Do);return{width:t,pixelWidth:o,getWidths:(t,o)=>((e,t,o)=>Kn(e,t,jn,(e=>e.fold((()=>o.minCellWidth()),(e=>e/o.pixelWidth()*100)))))(t,e,o),getCellDelta:e=>e/o()*100,singleColumnWidth:(e,t)=>[100-e],minCellWidth:()=>zt()/o()*100,setElementWidth:An,adjustTableWidth:o=>{const n=t();An(e,n+o/100*n)},isRelative:!0,label:"percent"}},er=e=>{const t=Xn(e,Do);return{width:t,pixelWidth:t,getWidths:(t,o)=>Jn(t,e,o),getCellDelta:f,singleColumnWidth:(e,t)=>[Math.max(zt(),e+t)-e],minCellWidth:zt,setElementWidth:zn,adjustTableWidth:o=>{const n=t()+o;zn(e,n)},isRelative:!1,label:"pixel"}},tr=e=>Mn(e).fold((()=>(e=>{const t=Xn(e,Do),o=u(0);return{width:t,pixelWidth:t,getWidths:(t,o)=>Jn(t,e,o),getCellDelta:o,singleColumnWidth:u([0]),minCellWidth:o,setElementWidth:d,adjustTableWidth:d,isRelative:!0,label:"none"}})(e)),(t=>((e,t)=>null!==qn().exec(t)?Zn(e):er(e))(e,t))),or=er,nr=Zn,rr=(e,t,o)=>{const n=e[o].element,r=ge.fromTag("td");ze(r,ge.fromTag("br")),(t?ze:Be)(n,r)},sr=((e,t)=>{const o=t=>e(t)?y.from(t.dom.nodeValue):y.none();return{get:t=>{if(!e(t))throw new Error("Can only get text value of a text node");return o(t).getOr("")},getOption:o,set:(t,o)=>{if(!e(t))throw new Error("Can only set raw text value of a text node");t.dom.nodeValue=o}}})(oe),lr=e=>sr.get(e),ar=e=>sr.getOption(e),cr=(e,t)=>sr.set(e,t),ir=e=>"img"===Q(e)?1:ar(e).fold((()=>Oe(e).length),(e=>e.length)),mr=["img","br"],dr=e=>ar(e).filter((e=>0!==e.trim().length||e.indexOf("\xa0")>-1)).isSome()||T(mr,Q(e)),ur=e=>((e,t)=>{const o=e=>{for(let n=0;ngr(e,dr),gr=(e,t)=>{const o=e=>{const n=Oe(e);for(let e=n.length-1;e>=0;e--){const r=n[e];if(t(r))return y.some(r);const s=o(r);if(s.isSome())return s}return y.none()};return o(e)},hr={scope:["row","col"]},pr=e=>()=>{const t=ge.fromTag("td",e.dom);return ze(t,ge.fromTag("br",e.dom)),t},wr=e=>()=>ge.fromTag("col",e.dom),br=e=>()=>ge.fromTag("colgroup",e.dom),vr=e=>()=>ge.fromTag("tr",e.dom),yr=(e,t,o)=>{const n=((e,t)=>{const o=He(e,t),n=Oe(Fe(e));return Le(o,n),o})(e,t);return $(o,((e,t)=>{null===e?de(n,t):ae(n,t,e)})),n},xr=e=>e,Cr=(e,t,o)=>{const n=(e,t)=>{((e,t)=>{const o=e.dom,n=t.dom;vt(o)&&vt(n)&&(n.style.cssText=o.style.cssText)})(e.element,t),Dt(t,"height"),1!==e.colspan&&Dt(t,"width")};return{col:o=>{const r=ge.fromTag(Q(o.element),t.dom);return n(o,r),e(o.element,r),r},colgroup:br(t),row:vr(t),cell:r=>{const s=ge.fromTag(Q(r.element),t.dom),l=o.getOr(["strong","em","b","i","span","font","h1","h2","h3","h4","h5","h6","p","div"]),a=l.length>0?((e,t,o)=>ur(e).map((n=>{const r=o.join(","),s=tt(n,r,(t=>be(t,e)));return B(s,((e,t)=>{const o=Pe(t);return de(o,"contenteditable"),ze(e,o),o}),t)})).getOr(t))(r.element,s,l):s;return ze(a,ge.fromTag("br")),n(r,s),((e,t)=>{$(hr,((o,n)=>me(e,n).filter((e=>T(o,e))).each((e=>ae(t,n,e)))))})(r.element,s),e(r.element,s),s},replace:yr,colGap:wr(t),gap:pr(t)}},Sr=e=>({col:wr(e),colgroup:br(e),row:vr(e),cell:pr(e),replace:xr,colGap:wr(e),gap:pr(e)}),Tr=e=>ge.fromDom(e.getBody()),Rr=e=>t=>be(t,Tr(e)),Dr=e=>{de(e,"data-mce-style");const t=e=>de(e,"data-mce-style");k(Mt(e),t),k(jt(e),t),k(Pt(e),t)},Or=e=>ge.fromDom(e.selection.getStart()),kr=e=>e.getBoundingClientRect().width,Er=e=>e.getBoundingClientRect().height,Nr=(e,t)=>{const o=t.column,n=t.column+t.colspan-1,r=t.row,s=t.row+t.rowspan-1;return o<=e.finishCol&&n>=e.startCol&&r<=e.finishRow&&s>=e.startRow},Br=(e,t)=>t.column>=e.startCol&&t.column+t.colspan-1<=e.finishCol&&t.row>=e.startRow&&t.row+t.rowspan-1<=e.finishRow,zr=(e,t,o)=>{const n=Go(e,t,be),r=Go(e,o,be);return n.bind((e=>r.map((t=>{return o=e,n=t,{startRow:Math.min(o.row,n.row),startCol:Math.min(o.column,n.column),finishRow:Math.max(o.row+o.rowspan-1,n.row+n.rowspan-1),finishCol:Math.max(o.column+o.colspan-1,n.column+n.colspan-1)};var o,n}))))},Ar=(e,t,o)=>zr(e,t,o).map((t=>{const o=Ko(e,h(Nr,t));return O(o,(e=>e.element))})),Wr=(e,t)=>Go(e,t,((e,t)=>ve(t,e))).map((e=>e.element)),Lr=(e,t,o)=>{const n=Mr(e);return Ar(n,t,o)},_r=(e,t,o,n,r)=>{const s=Mr(e),l=be(e,o)?y.some(t):Wr(s,t),a=be(e,r)?y.some(n):Wr(s,n);return l.bind((e=>a.bind((t=>Ar(s,e,t)))))},Mr=Vo;var jr=["body","p","div","article","aside","figcaption","figure","footer","header","nav","section","ol","ul","li","table","thead","tbody","tfoot","caption","tr","td","th","h1","h2","h3","h4","h5","h6","blockquote","pre","address"],Ir=()=>({up:u({selector:lt,closest:it,predicate:st,all:Te}),down:u({selector:nt,predicate:et}),styles:u({get:St,getRaw:Rt,set:xt,remove:Dt}),attrs:u({get:ie,set:ae,remove:de,copyTo:(e,t)=>{const o=ue(e);ce(t,o)}}),insert:u({before:Ee,after:Ne,afterAll:We,append:ze,appendAll:Le,prepend:Be,wrap:Ae}),remove:u({unwrap:je,remove:Me}),create:u({nu:ge.fromTag,clone:e=>ge.fromDom(e.dom.cloneNode(!1)),text:ge.fromText}),query:u({comparePosition:(e,t)=>e.dom.compareDocumentPosition(t.dom),prevSibling:Re,nextSibling:De}),property:u({children:Oe,name:Q,parent:Se,document:e=>Ce(e).dom,isText:oe,isComment:ee,isElement:te,isSpecial:e=>{const t=Q(e);return T(["script","noscript","iframe","noframes","noembed","title","style","textarea","xmp"],t)},getLanguage:e=>te(e)?me(e,"lang"):y.none(),getText:lr,setText:cr,isBoundary:e=>!!te(e)&&("body"===Q(e)||T(jr,Q(e))),isEmptyTag:e=>!!te(e)&&T(["br","img","hr","input"],Q(e)),isNonEditable:e=>te(e)&&"false"===ie(e,"contenteditable")}),eq:be,is:ye});const Pr=(e,t,o,n)=>{const r=t(e,o);return B(n,((o,n)=>{const r=t(e,n);return Fr(e,o,r)}),r)},Fr=(e,t,o)=>t.bind((t=>o.filter(h(e.eq,t)))),Hr=Ir(),qr=(e,t)=>((e,t,o)=>o.length>0?((e,t,o,n)=>n(e,t,o[0],o.slice(1)))(e,t,o,Pr):y.none())(Hr,((t,o)=>e(o)),t),Vr=e=>lt(e,"table"),$r=(e,t,o)=>{const n=e=>t=>void 0!==o&&o(t)||be(t,e);return be(e,t)?y.some({boxes:y.some([e]),start:e,finish:t}):Vr(e).bind((r=>Vr(t).bind((s=>{if(be(r,s))return y.some({boxes:Lr(r,e,t),start:e,finish:t});if(ve(r,s)){const o=tt(t,"td,th",n(r)),l=o.length>0?o[o.length-1]:t;return y.some({boxes:_r(r,e,r,t,s),start:e,finish:l})}if(ve(s,r)){const o=tt(e,"td,th",n(s)),l=o.length>0?o[o.length-1]:e;return y.some({boxes:_r(s,e,r,t,s),start:e,finish:l})}return((e,t,o)=>((e,t,o,n=b)=>{const r=[t].concat(e.up().all(t)),s=[o].concat(e.up().all(o)),l=e=>W(e,n).fold((()=>e),(t=>e.slice(0,t+1))),a=l(r),c=l(s),i=A(a,(t=>R(c,((e,t)=>h(e.eq,t))(e,t))));return{firstpath:a,secondpath:c,shared:i}})(Hr,e,t,void 0))(e,t).shared.bind((l=>it(l,"table",o).bind((o=>{const l=tt(t,"td,th",n(o)),a=l.length>0?l[l.length-1]:t,c=tt(e,"td,th",n(o)),i=c.length>0?c[c.length-1]:e;return y.some({boxes:_r(o,e,r,t,s),start:i,finish:a})}))))}))))},Ur=(e,t)=>{const o=nt(e,t);return o.length>0?y.some(o):y.none()},Gr=(e,t,o)=>ct(e,t).bind((t=>ct(e,o).bind((e=>qr(Vr,[t,e]).map((o=>({first:t,last:e,table:o}))))))),Kr=(e,t,o,n,r)=>((e,t)=>A(e,(e=>he(e,t))))(e,r).bind((e=>((e,t,o)=>It(e).bind((n=>((e,t,o,n)=>Go(e,t,be).bind((t=>{const r=o>0?t.row+t.rowspan-1:t.row,s=n>0?t.column+t.colspan-1:t.column;return Uo(e,r+o,s+n).map((e=>e.element))})))(Mr(n),e,t,o))))(e,t,o).bind((e=>((e,t)=>lt(e,"table").bind((o=>ct(o,t).bind((t=>$r(t,e).bind((e=>e.boxes.map((t=>({boxes:t,start:e.start,finish:e.finish}))))))))))(e,n))))),Yr=(e,t)=>Ur(e,t),Jr=(e,t,o)=>Gr(e,t,o).bind((t=>{const o=t=>be(e,t),n="thead,tfoot,tbody,table",r=lt(t.first,n,o),s=lt(t.last,n,o);return r.bind((e=>s.bind((o=>be(e,o)?((e,t,o)=>((e,t,o)=>zr(e,t,o).bind((t=>((e,t)=>{let o=!0;const n=h(Br,t);for(let r=t.startRow;r<=t.finishRow;r++)for(let s=t.startCol;s<=t.finishCol;s++)o=o&&Uo(e,r,s).exists(n);return o?y.some(t):y.none()})(e,t))))(Mr(e),t,o))(t.table,t.first,t.last):y.none()))))})),Qr=f,Xr=e=>{const t=(e,t)=>me(e,t).exists((e=>parseInt(e,10)>1));return e.length>0&&M(e,(e=>t(e,"rowspan")||t(e,"colspan")))?y.some(e):y.none()},Zr=(e,t,o)=>t.length<=1?y.none():Jr(e,o.firstSelectedSelector,o.lastSelectedSelector).map((e=>({bounds:e,cells:t}))),es={selected:"data-mce-selected",selectedSelector:"td[data-mce-selected],th[data-mce-selected]",firstSelected:"data-mce-first-selected",firstSelectedSelector:"td[data-mce-first-selected],th[data-mce-first-selected]",lastSelected:"data-mce-last-selected",lastSelectedSelector:"td[data-mce-last-selected],th[data-mce-last-selected]"},ts=(e,t,o)=>({element:o,mergable:Zr(t,e,es),unmergable:Xr(e),selection:Qr(e)}),os=e=>(t,o)=>{const n=Q(t),r="col"===n||"colgroup"===n?It(s=t).bind((e=>Yr(e,es.firstSelectedSelector))).fold(u(s),(e=>e[0])):t;var s;return it(r,e,o)},ns=os("th,td,caption"),rs=os("th,td"),ss=e=>{return t=e.model.table.getSelectedCells(),O(t,ge.fromDom);var t},ls=(e,t)=>{e.on("BeforeGetContent",(t=>{const o=o=>{t.preventDefault(),(e=>It(e[0]).map((e=>{const t=((e,t)=>{const o=e=>he(e.element,t),n=Fe(e),r=Vt(n),s=tr(e),l=$o(r),a=((e,t)=>{const o=e.grid.columns;let n=e.grid.rows,r=o,s=0,l=0;const a=[],c=[];return $(e.access,(e=>{if(a.push(e),t(e)){c.push(e);const t=e.row,o=t+e.rowspan-1,a=e.column,i=a+e.colspan-1;ts&&(s=o),al&&(l=i)}})),((e,t,o,n,r,s)=>({minRow:e,minCol:t,maxRow:o,maxCol:n,allCells:r,selectedCells:s}))(n,r,s,l,a,c)})(l,o),c="th:not("+t+"),td:not("+t+")",i=Lt(n,"th,td",(e=>he(e,c)));k(i,Me),((e,t,o,n)=>{const r=N(e,(e=>"colgroup"!==e.section)),s=t.grid.columns,l=t.grid.rows;for(let e=0;eo.maxRow||ao.maxCol||(Uo(t,e,a).filter(n).isNone()?rr(r,l,e):l=!0)}})(r,l,a,o);const m=((e,t,o,n)=>{if(0===n.minCol&&t.grid.columns===n.maxCol+1)return 0;const r=Jn(t,e,o),s=z(r,((e,t)=>e+t),0),l=z(r.slice(n.minCol,n.maxCol+1),((e,t)=>e+t),0),a=l/s*o.pixelWidth()-o.pixelWidth();return o.getCellDelta(a)})(e,Vo(e),s,a);return((e,t,o,n)=>{$(o.columns,(e=>{(e.columnt.maxCol)&&Me(e.element)}));const r=N(Wt(e,"tr"),(e=>0===e.dom.childElementCount));k(r,Me),t.minCol!==t.maxCol&&t.minRow!==t.maxRow||k(Wt(e,"th,td"),(e=>{de(e,"rowspan"),de(e,"colspan")})),de(e,jo),de(e,"data-snooker-col-series"),tr(e).adjustTableWidth(n)})(n,a,l,m),n})(e,"[data-mce-selected]");return Dr(t),[t]})))(o).each((o=>{t.content="text"===t.format?(e=>O(e,(e=>e.dom.innerText)).join(""))(o):((e,t)=>O(t,(t=>e.selection.serializer.serialize(t.dom,{}))).join(""))(e,o)}))};if(!0===t.selection){const t=(e=>N(ss(e),(e=>he(e,es.selectedSelector))))(e);t.length>=1&&o(t)}})),e.on("BeforeSetContent",(o=>{if(!0===o.selection&&!0===o.paste){const n=ss(e);P(n).each((n=>{It(n).each((r=>{const s=N(((e,t)=>{const o=document.createElement("div");return o.innerHTML=e,Oe(ge.fromDom(o))})(o.content),(e=>"meta"!==Q(e))),l=se("table");if(1===s.length&&l(s[0])){o.preventDefault();const l=ge.fromDom(e.getDoc()),a=Sr(l),c=((e,t,o)=>({element:e,clipboard:t,generators:o}))(n,s[0],a);t.pasteCells(r,c).each((()=>{e.focus()}))}}))}))}}))},as=(e,t)=>({element:e,offset:t}),cs=(e,t,o)=>e.property().isText(t)&&0===e.property().getText(t).trim().length||e.property().isComment(t)?o(t).bind((t=>cs(e,t,o).orThunk((()=>y.some(t))))):y.none(),is=(e,t)=>e.property().isText(t)?e.property().getText(t).length:e.property().children(t).length,ms=(e,t)=>{const o=cs(e,t,e.query().prevSibling).getOr(t);if(e.property().isText(o))return as(o,is(e,o));const n=e.property().children(o);return n.length>0?ms(e,n[n.length-1]):as(o,is(e,o))},ds=ms,us=Ir(),fs=(e,t)=>{if(!Et(e)){const o=(e=>Mn(e).bind((e=>{return t=e,o=["fixed","relative","empty"],y.from(On.exec(t)).bind((e=>{const t=Number(e[1]),n=e[2];return((e,t)=>R(t,(t=>R(Dn[t],(t=>e===t)))))(n,o)?y.some({value:t,unit:n}):y.none()}));var t,o})))(e);o.each((o=>{const n=o.value/2;Fn(e,n,o.unit),Fn(t,n,o.unit)}))}},gs=e=>O(e,u(0)),hs=(e,t,o,n,r)=>r(e.slice(0,t)).concat(n).concat(r(e.slice(o))),ps=e=>(t,o,n,r)=>{if(e(n)){const e=Math.max(r,t[o]-Math.abs(n)),s=Math.abs(e-t[o]);return n>=0?s:-s}return n},ws=ps((e=>e<0)),bs=ps(v),vs=()=>{const e=(e,t,o,n)=>{const r=(100+o)/100,s=Math.max(n,(e[t]+o)/r);return O(e,((e,o)=>(o===t?s:e/r)-e))},t=(t,o,n,r,s,l)=>l?e(t,o,r,s):((e,t,o,n,r)=>{const s=ws(e,t,n,r);return hs(e,t,o+1,[s,0],gs)})(t,o,n,r,s);return{resizeTable:(e,t)=>e(t),clampTableDelta:ws,calcLeftEdgeDeltas:t,calcMiddleDeltas:(e,o,n,r,s,l,a)=>t(e,n,r,s,l,a),calcRightEdgeDeltas:(t,o,n,r,s,l)=>{if(l)return e(t,n,r,s);{const e=ws(t,n,r,s);return gs(t.slice(0,n)).concat([e])}},calcRedestributedWidths:(e,t,o,n)=>{if(n){const n=(t+o)/t,r=O(e,(e=>e/n));return{delta:100*n-100,newSizes:r}}return{delta:o,newSizes:e}}}},ys=()=>{const e=(e,t,o,n,r)=>{const s=bs(e,n>=0?o:t,n,r);return hs(e,t,o+1,[s,-s],gs)};return{resizeTable:(e,t,o)=>{o&&e(t)},clampTableDelta:(e,t,o,n,r)=>{if(r){if(o>=0)return o;{const t=z(e,((e,t)=>e+t-n),0);return Math.max(-t,o)}}return ws(e,t,o,n)},calcLeftEdgeDeltas:e,calcMiddleDeltas:(t,o,n,r,s,l)=>e(t,n,r,s,l),calcRightEdgeDeltas:(e,t,o,n,r,s)=>{if(s)return gs(e);{const t=n/e.length;return O(e,u(t))}},calcRedestributedWidths:(e,t,o,n)=>({delta:0,newSizes:e})}},xs=e=>Vo(e).grid,Cs=se("th"),Ss=e=>M(e,(e=>Cs(e.element))),Ts=(e,t)=>e&&t?"sectionCells":e?"section":"cells",Rs=e=>{const t="thead"===e.section,o=mt(Ds(e.cells),"th");return"tfoot"===e.section?{type:"footer"}:t||o?{type:"header",subType:Ts(t,o)}:{type:"body"}},Ds=e=>{const t=N(e,(e=>Cs(e.element)));return 0===t.length?y.some("td"):t.length===e.length?y.some("th"):y.none()},Os=(e,t,o)=>Ue(o(e.element,t),!0,e.isLocked),ks=(e,t)=>e.section!==t?Ge(e.element,e.cells,t,e.isNew):e,Es=()=>({transformRow:ks,transformCell:(e,t,o)=>{const n=o(e.element,t),r="td"!==Q(n)?((e,t)=>{const o=He(e,"td");Ne(e,o);const n=Oe(e);return Le(o,n),Me(e),o})(n):n;return Ue(r,e.isNew,e.isLocked)}}),Ns=()=>({transformRow:ks,transformCell:Os}),Bs=()=>({transformRow:(e,t)=>ks(e,"thead"===t?"tbody":t),transformCell:Os}),zs=Es,As=Ns,Ws=Bs,Ls=()=>({transformRow:f,transformCell:Os}),_s=e=>it(e,"[contenteditable]"),Ms=(e,t=!1)=>Xe(e)?e.dom.isContentEditable:_s(e).fold(u(t),(e=>"true"===js(e))),js=e=>e.dom.contentEditable,Is=(e,t,o,n)=>{o===n?de(e,t):ae(e,t,o)},Ps=(e,t,o)=>{F(ot(e,t)).fold((()=>Be(e,o)),(e=>Ne(e,o)))},Fs=(e,t)=>{const o=[],n=[],r=e=>O(e,(e=>{e.isNew&&o.push(e.element);const t=e.element;return _e(t),k(e.cells,(e=>{e.isNew&&n.push(e.element),Is(e.element,"colspan",e.colspan,1),Is(e.element,"rowspan",e.rowspan,1),ze(t,e.element)})),t})),s=e=>_(e,(e=>O(e.cells,(e=>(Is(e.element,"span",e.colspan,1),e.element))))),l=(t,o)=>{const n=((e,t)=>{const o=at(e,t).getOrThunk((()=>{const o=ge.fromTag(t,xe(e).dom);return"thead"===t?Ps(e,"caption,colgroup",o):"colgroup"===t?Ps(e,"caption",o):ze(e,o),o}));return _e(o),o})(e,o),l=("colgroup"===o?s:r)(t);Le(n,l)},a=(t,o)=>{t.length>0?l(t,o):(t=>{at(e,t).each(Me)})(o)},c=[],i=[],m=[],d=[];return k(t,(e=>{switch(e.section){case"thead":c.push(e);break;case"tbody":i.push(e);break;case"tfoot":m.push(e);break;case"colgroup":d.push(e)}})),a(d,"colgroup"),a(c,"thead"),a(i,"tbody"),a(m,"tfoot"),{newRows:o,newCells:n}},Hs=(e,t)=>{if(0===e.length)return 0;const o=e[0];return W(e,(e=>!t(o.element,e.element))).getOr(e.length)},qs=(e,t)=>{const o=O(e,(e=>O(e.cells,b)));return O(e,((n,r)=>{const s=_(n.cells,((n,s)=>{if(!1===o[r][s]){const m=((e,t,o,n)=>{const r=((e,t)=>e[t])(e,t),s="colgroup"===r.section,l=Hs(r.cells.slice(o),n),a=s?1:Hs(((e,t)=>O(e,(e=>Ao(e,t))))(e.slice(t),o),n);return{colspan:l,rowspan:a}})(e,r,s,t);return((e,t,n,r)=>{for(let s=e;s({element:e,cells:t,section:o,isNew:n}))(n.element,s,n.section,n.isNew)}))},Vs=(e,t,o)=>{const n=[];k(e.colgroups,(r=>{const s=[];for(let n=0;nUe(e.element,o,!1))).getOrThunk((()=>Ue(t.colGap(),!0,!1)));s.push(r)}n.push(Ge(r.element,s,"colgroup",o))}));for(let r=0;rUe(e.element,o,e.isLocked))).getOrThunk((()=>Ue(t.gap(),!0,!1)));s.push(l)}const l=e.all[r],a=Ge(l.element,s,l.section,o);n.push(a)}return n},$s=e=>qs(e,be),Us=(e,t)=>H(e.all,(e=>A(e.cells,(e=>be(t,e.element))))),Gs=(e,t,o)=>{const n=O(t.selection,(t=>_t(t).bind((t=>Us(e,t))).filter(o))),r=dt(n);return ut(r.length>0,r)},Ks=(e,t,o,n,r)=>(s,l,a,c)=>{const i=Vo(s),m=y.from(null==c?void 0:c.section).getOrThunk(Ls);return t(i,l).map((t=>{const o=((e,t)=>Vs(e,t,!1))(i,a),n=e(o,t,be,r(a),m),s=Po(n.grid);return{info:t,grid:$s(n.grid),cursor:n.cursor,lockedColumns:s}})).bind((e=>{const t=Fs(s,e.grid),r=y.from(null==c?void 0:c.sizing).getOrThunk((()=>tr(s))),l=y.from(null==c?void 0:c.resize).getOrThunk(ys);return o(s,e.grid,e.info,{sizing:r,resize:l,section:m}),n(s),de(s,jo),e.lockedColumns.length>0&&ae(s,jo,e.lockedColumns.join(",")),y.some({cursor:e.cursor,newRows:t.newRows,newCells:t.newCells})}))},Ys=(e,t)=>Gs(e,t,v).map((e=>({cells:e,generators:t.generators,clipboard:t.clipboard}))),Js=(e,t)=>Gs(e,t,v),Qs=(e,t)=>Gs(e,t,(e=>!e.isLocked)),Xs=(e,t)=>M(t,(t=>((e,t)=>Us(e,t).exists((e=>!e.isLocked)))(e,t))),Zs=(e,t,o,n)=>{const r=_o(e).rows;let s=!0;for(let e=0;e{const t=t=>t(e),o=u(e),n=()=>r,r={tag:!0,inner:e,fold:(t,o)=>o(e),isValue:v,isError:b,map:t=>ol.value(t(e)),mapError:n,bind:t,exists:t,forall:t,getOr:o,or:n,getOrThunk:o,orThunk:n,getOrDie:o,each:t=>{t(e)},toOptional:()=>y.some(e)};return r},tl=e=>{const t=()=>o,o={tag:!1,inner:e,fold:(t,o)=>t(e),isValue:b,isError:v,map:t,mapError:t=>ol.error(t(e)),bind:t,exists:b,forall:v,getOr:f,or:f,getOrThunk:w,orThunk:w,getOrDie:(n=String(e),()=>{throw new Error(n)}),each:d,toOptional:y.none};var n;return o},ol={value:el,error:tl,fromOption:(e,t)=>e.fold((()=>tl(t)),el)},nl=(e,t)=>({rowDelta:0,colDelta:Lo(e[0])-Lo(t[0])}),rl=(e,t)=>({rowDelta:e.length-t.length,colDelta:0}),sl=(e,t,o,n)=>{const r="colgroup"===t.section?o.col:o.cell;return D(e,(e=>Ue(r(),!0,n(e))))},ll=(e,t,o,n)=>{const r=e[e.length-1];return e.concat(D(t,(()=>{const e="colgroup"===r.section?o.colgroup:o.row,t=Mo(r,e,f),s=sl(t.cells.length,t,o,(e=>J(n,e.toString())));return zo(t,s)})))},al=(e,t,o,n)=>O(e,(e=>{const r=sl(t,e,o,b);return Eo(e,n,r)})),cl=(e,t,o)=>{const n=t.colDelta<0?al:f,r=t.rowDelta<0?ll:f,s=Po(e),l=Lo(e[0]),a=R(s,(e=>e===l-1)),c=n(e,Math.abs(t.colDelta),o,a?l-1:l),i=Po(c);return r(c,Math.abs(t.rowDelta),o,j(i,v))},il=(e,t,o,n)=>{const r=h(n,Ao(e[t],o).element),s=e[t];return e.length>1&&Lo(s)>1&&(o>0&&r(Wo(s,o-1))||o0&&r(Wo(e[t-1],o))||tN(o,(o=>o>=e.column&&o<=Lo(t[0])+e.column)),dl=(e,t,o,n,r)=>{((e,t,o,n)=>{t>0&&t{const r=e.cells[t-1];let s=0;const l=n();for(;e.cells.length>t+s&&o(r.element,e.cells[t+s].element);)Bo(e,t+s,Ue(l,!0,e.cells[t+s].isLocked)),s++}))})(t,e,r,n.cell);const s=rl(o,t),l=cl(o,s,n),a=rl(t,l),c=cl(t,a,n);return O(c,((t,o)=>Eo(t,e,l[o].cells)))},ul=(e,t,o,n,r)=>{((e,t,o,n)=>{const r=_o(e).rows;if(t>0&&tz(e,((e,o)=>R(e,(e=>t(e.element,o.element)))?e:e.concat([o])),[]))(r[t-1].cells,o);k(e,(e=>{let s=y.none();for(let l=t;l{Bo(a,t,Ue(e,!0,c.isLocked))})))}}))}})(t,e,r,n.cell);const s=Po(t),l=nl(t,o),a={...l,colDelta:l.colDelta-s.length},c=cl(t,a,n),{cols:i,rows:m}=_o(c),d=Po(c),u=nl(o,t),f={...u,colDelta:u.colDelta+d.length},g=(p=n,w=d,O(o,(e=>z(w,((t,o)=>{const n=sl(1,e,p,v)[0];return No(t,o,n)}),e)))),h=cl(g,f,n);var p,w;return[...i,...m.slice(0,e),...h,...m.slice(e,m.length)]},fl=(e,t,o,n,r)=>{const{rows:s,cols:l}=_o(e),a=s.slice(0,t),c=s.slice(t);return[...l,...a,((e,t,o,n)=>Mo(e,(e=>n(e,o)),t))(s[o],((e,o)=>t>0&&tO(e,(e=>{const s=t>0&&t{if("colgroup"!==o&&n)return Ao(e,t);{const t=Ao(e,r);return Ue(l(t.element,s),!0,!1)}})(e,t,e.section,s,o,n,r);return No(e,t,l)})),hl=(e,t,o,n)=>((e,t,o,n)=>void 0!==Wo(e[t],o)&&t>0&&n(Wo(e[t-1],o),Wo(e[t],o)))(e,t,o,n)||((e,t,o)=>t>0&&o(Wo(e,t-1),Wo(e,t)))(e[t],o,n),pl=(e,t,o,n)=>{const r=e=>(e=>"row"===e?Nt(t):Et(t))(e)?`${e}group`:e;return e?Cs(t)?r(o):null:n&&Cs(t)?r("row"===o?"col":"row"):null},wl=(e,t,o)=>Ue(o(e.element,t),!0,e.isLocked),bl=(e,t,o,n,r,s,l)=>O(e,((e,a)=>((e,c)=>{const i=e.cells,m=O(i,((e,c)=>{if((e=>R(t,(t=>o(e.element,t.element))))(e)){const t=l(e,a,c)?r(e,o,n):e;return s(t,a,c).each((e=>{var o,n;o=t.element,n={scope:y.from(e)},$(n,((e,t)=>{e.fold((()=>{de(o,t)}),(e=>{le(o.dom,t,e)}))}))})),t}return e}));return Ge(e.element,m,e.section,e.isNew)})(e))),vl=(e,t,o)=>_(e,((n,r)=>hl(e,r,t,o)?[]:[Ao(n,t)])),yl=(e,t,o,n,r)=>{const s=_o(e).rows,l=_(t,(e=>vl(s,e,n))),a=O(s,(e=>Ss(e.cells))),c=((e,t)=>M(t,f)&&Ss(e)?v:(e,o,n)=>!("th"===Q(e.element)&&t[o]))(l,a),i=((e,t)=>(o,n)=>y.some(pl(e,o.element,"row",t[n])))(o,a);return bl(e,l,n,r,wl,i,c)},xl=(e,t,o,n)=>{const r=_o(e).rows,s=O(t,(e=>Ao(r[e.row],e.column)));return bl(e,s,o,n,wl,y.none,v)},Cl=e=>{if(!s(e))throw new Error("cases must be an array");if(0===e.length)throw new Error("there must be at least one case");const t=[],o={};return k(e,((n,r)=>{const l=q(n);if(1!==l.length)throw new Error("one and only one name per case");const a=l[0],c=n[a];if(void 0!==o[a])throw new Error("duplicate key detected:"+a);if("cata"===a)throw new Error("cannot have a case named cata (sorry)");if(!s(c))throw new Error("case arguments must be an array");t.push(a),o[a]=(...o)=>{const n=o.length;if(n!==c.length)throw new Error("Wrong number of arguments to case "+a+". Expected "+c.length+" ("+c+"), got "+n);return{fold:(...t)=>{if(t.length!==e.length)throw new Error("Wrong number of arguments to fold. Expected "+e.length+", got "+t.length);return t[r].apply(null,o)},match:e=>{const n=q(e);if(t.length!==n.length)throw new Error("Wrong number of arguments to match. Expected: "+t.join(",")+"\nActual: "+n.join(","));if(!M(t,(e=>T(n,e))))throw new Error("Not all branches were specified when using match. Specified: "+n.join(", ")+"\nRequired: "+t.join(", "));return e[a].apply(null,o)},log:e=>{console.log(e,{constructors:t,constructor:a,params:o})}}}})),o},Sl={...Cl([{none:[]},{only:["index"]},{left:["index","next"]},{middle:["prev","index","next"]},{right:["prev","index"]}])},Tl=(e,t,o)=>{let n=0;for(let r=e;r{const o=Yo(e);return O(o,(e=>{const o=Tl(e.row,e.row+e.rowspan,t);return{element:e.element,height:o,rowspan:e.rowspan}}))},Dl=(e,t,o)=>{const n=((e,t)=>Qo(e)?((e,t)=>{const o=Jo(e);return O(o,((e,o)=>({element:e.element,width:t[o],colspan:e.colspan})))})(e,t):((e,t)=>{const o=Yo(e);return O(o,(e=>{const o=Tl(e.column,e.column+e.colspan,t);return{element:e.element,width:o,colspan:e.colspan}}))})(e,t))(e,t);k(n,(e=>{o.setElementWidth(e.element,e.width)}))},Ol=(e,t,o,n,r)=>{const s=Vo(e),l=r.getCellDelta(t),a=r.getWidths(s,r),c=o===s.grid.columns-1,i=n.clampTableDelta(a,o,l,r.minCellWidth(),c),m=((e,t,o,n,r)=>{const s=e.slice(0),l=((e,t)=>0===e.length?Sl.none():1===e.length?Sl.only(0):0===t?Sl.left(0,1):t===e.length-1?Sl.right(t-1,t):t>0&&tn.singleColumnWidth(s[e],o)),((e,t)=>r.calcLeftEdgeDeltas(s,e,t,o,n.minCellWidth(),n.isRelative)),((e,t,l)=>r.calcMiddleDeltas(s,e,t,l,o,n.minCellWidth(),n.isRelative)),((e,t)=>r.calcRightEdgeDeltas(s,e,t,o,n.minCellWidth(),n.isRelative)))})(a,o,i,r,n),d=O(m,((e,t)=>e+a[t]));Dl(s,d,r),n.resizeTable(r.adjustTableWidth,i,c)},kl=e=>z(e,((e,t)=>R(e,(e=>e.column===t.column))?e:e.concat([t])),[]).sort(((e,t)=>e.column-t.column)),El=se("col"),Nl=se("colgroup"),Bl=e=>"tr"===Q(e)||Nl(e),zl=e=>({element:e,colspan:Ot(e,"colspan",1),rowspan:Ot(e,"rowspan",1)}),Al=e=>me(e,"scope").map((e=>e.substr(0,3))),Wl=(e,t=zl)=>{const o=o=>{if(Bl(o))return Nl((r={element:o}).element)?e.colgroup(r):e.row(r);{const r=o,s=(t=>El(t.element)?e.col(t):e.cell(t))(t(r));return n=y.some({item:r,replacement:s}),s}var r};let n=y.none();return{getOrInit:(e,t)=>n.fold((()=>o(e)),(n=>t(e,n.item)?n.replacement:o(e)))}},Ll=e=>t=>{const o=[],n=n=>{const r="td"===e?{scope:null}:{},s=t.replace(n,e,r);return o.push({item:n,sub:s}),s};return{replaceOrInit:(e,t)=>{if(Bl(e)||El(e))return e;{const r=e;return((e,t)=>A(o,(o=>t(o.item,e))))(r,t).fold((()=>n(r)),(o=>t(e,o.item)?o.sub:n(r)))}}}},_l=e=>({unmerge:t=>{const o=Al(t);return o.each((e=>ae(t,"scope",e))),()=>{const n=e.cell({element:t,colspan:1,rowspan:1});return Dt(n,"width"),Dt(t,"width"),o.each((e=>ae(n,"scope",e))),n}},merge:e=>(Dt(e[0],"width"),(()=>{const t=dt(O(e,Al));if(0===t.length)return y.none();{const e=t[0],o=["row","col"];return R(t,(t=>t!==e&&T(o,t)))?y.none():y.from(e)}})().fold((()=>de(e[0],"scope")),(t=>ae(e[0],"scope",t+"group"))),u(e[0]))}),Ml=["body","p","div","article","aside","figcaption","figure","footer","header","nav","section","ol","ul","table","thead","tfoot","tbody","caption","tr","td","th","h1","h2","h3","h4","h5","h6","blockquote","pre","address"],jl=Ir(),Il=e=>((e,t)=>{const o=e.property().name(t);return T(Ml,o)})(jl,e),Pl=e=>((e,t)=>{const o=e.property().name(t);return T(["ol","ul"],o)})(jl,e),Fl=e=>{const t=se("br"),o=e=>fr(e).bind((o=>{const n=De(o).map((e=>!!Il(e)||!!((e,t)=>T(["br","img","hr","input"],e.property().name(t)))(jl,e)&&"img"!==Q(e))).getOr(!1);return Se(o).map((r=>{return!0===n||("li"===Q(s=r)||st(s,Pl).isSome())||t(o)||Il(r)&&!be(e,r)?[]:[ge.fromTag("br")];var s}))})).getOr([]),n=(()=>{const n=_(e,(e=>{const n=Oe(e);return(e=>M(e,(e=>t(e)||oe(e)&&0===lr(e).trim().length)))(n)?[]:n.concat(o(e))}));return 0===n.length?[ge.fromTag("br")]:n})();_e(e[0]),Le(e[0],n)},Hl=e=>Ms(e,!0),ql=e=>{0===Mt(e).length&&Me(e)},Vl=(e,t)=>({grid:e,cursor:t}),$l=(e,t,o)=>{const n=((e,t,o)=>{var n,r;const s=_o(e).rows;return y.from(null===(r=null===(n=s[t])||void 0===n?void 0:n.cells[o])||void 0===r?void 0:r.element).filter(Hl).orThunk((()=>(e=>H(e,(e=>H(e.cells,(e=>{const t=e.element;return ut(Hl(t),t)})))))(s)))})(e,t,o);return Vl(e,n)},Ul=e=>z(e,((e,t)=>R(e,(e=>e.row===t.row))?e:e.concat([t])),[]).sort(((e,t)=>e.row-t.row)),Gl=(e,t)=>(o,n,r,s,l)=>{const a=Ul(n),c=O(a,(e=>e.row)),i=((e,t,o,n,r,s,l)=>{const{cols:a,rows:c}=_o(e),i=c[t[0]],m=_(t,(e=>((e,t,o)=>{const n=e[t];return _(n.cells,((n,r)=>hl(e,t,r,o)?[]:[n]))})(c,e,r))),d=O(i.cells,((e,t)=>Ss(vl(c,t,r)))),u=[...c];k(t,(e=>{u[e]=l.transformRow(c[e],o)}));const g=[...a,...u],h=((e,t)=>M(t,f)&&Ss(e.cells)?v:(e,o,n)=>!("th"===Q(e.element)&&t[n]))(i,d),p=((e,t)=>(o,n,r)=>y.some(pl(e,o.element,"col",t[r])))(n,d);return bl(g,m,r,s,l.transformCell,p,h)})(o,c,e,t,r,s.replaceOrInit,l);return $l(i,n[0].row,n[0].column)},Kl=Gl("thead",!0),Yl=Gl("tbody",!1),Jl=Gl("tfoot",!1),Ql=(e,t,o)=>{const n=((e,t)=>Ht(e,(()=>t)))(e,o.section),r=$o(n);return Vs(r,t,!0)},Xl=(e,t,o,n)=>((e,t,o,n)=>{const r=$o(t),s=n.getWidths(r,n);Dl(r,s,n)})(0,t,0,n.sizing),Zl=(e,t,o,n)=>((e,t,o,n,r)=>{const s=$o(t),l=n.getWidths(s,n),a=n.pixelWidth(),{newSizes:c,delta:i}=r.calcRedestributedWidths(l,a,o.pixelDelta,n.isRelative);Dl(s,c,n),n.adjustTableWidth(i)})(0,t,o,n.sizing,n.resize),ea=(e,t)=>R(t,(e=>0===e.column&&e.isLocked)),ta=(e,t)=>R(t,(t=>t.column+t.colspan>=e.grid.columns&&t.isLocked)),oa=(e,t)=>{const o=Zo(e),n=kl(t);return z(n,((e,t)=>e+o[t.column].map(Oo).getOr(0)),0)},na=e=>(t,o)=>Js(t,o).filter((o=>!(e?ea:ta)(t,o))).map((e=>({details:e,pixelDelta:oa(t,e)}))),ra=e=>(t,o)=>Ys(t,o).filter((o=>!(e?ea:ta)(t,o.cells))),sa=Ll("th"),la=Ll("td"),aa=Ks(((e,t,o,n)=>{const r=t[0].row,s=Ul(t),l=B(s,((e,t)=>({grid:fl(e.grid,r,t.row+e.delta,o,n.getOrInit),delta:e.delta+1})),{grid:e,delta:0}).grid;return $l(l,r,t[0].column)}),Js,d,d,Wl),ca=Ks(((e,t,o,n)=>{const r=Ul(t),s=r[r.length-1],l=s.row+s.rowspan,a=B(r,((e,t)=>fl(e,l,t.row,o,n.getOrInit)),e);return $l(a,l,t[0].column)}),Js,d,d,Wl),ia=Ks(((e,t,o,n)=>{const r=t.details,s=kl(r),l=s[0].column,a=B(s,((e,t)=>({grid:gl(e.grid,l,t.column+e.delta,o,n.getOrInit),delta:e.delta+1})),{grid:e,delta:0}).grid;return $l(a,r[0].row,l)}),na(!0),Zl,d,Wl),ma=Ks(((e,t,o,n)=>{const r=t.details,s=r[r.length-1],l=s.column+s.colspan,a=kl(r),c=B(a,((e,t)=>gl(e,l,t.column,o,n.getOrInit)),e);return $l(c,r[0].row,l)}),na(!1),Zl,d,Wl),da=Ks(((e,t,o,n)=>{const r=kl(t.details),s=((e,t)=>_(e,(e=>{const o=e.cells,n=B(t,((e,t)=>t>=0&&t0?[Ge(e.element,n,e.section,e.isNew)]:[]})))(e,O(r,(e=>e.column))),l=s.length>0?s[0].cells.length-1:0;return $l(s,r[0].row,Math.min(r[0].column,l))}),((e,t)=>Qs(e,t).map((t=>({details:t,pixelDelta:-oa(e,t)})))),Zl,ql,Wl),ua=Ks(((e,t,o,n)=>{const r=Ul(t),s=((e,t,o)=>{const{rows:n,cols:r}=_o(e);return[...r,...n.slice(0,t),...n.slice(o+1)]})(e,r[0].row,r[r.length-1].row),l=s.length>0?s.length-1:0;return $l(s,Math.min(t[0].row,l),t[0].column)}),Js,d,ql,Wl),fa=Ks(((e,t,o,n)=>{const r=kl(t),s=O(r,(e=>e.column)),l=yl(e,s,!0,o,n.replaceOrInit);return $l(l,t[0].row,t[0].column)}),Qs,d,d,sa),ga=Ks(((e,t,o,n)=>{const r=kl(t),s=O(r,(e=>e.column)),l=yl(e,s,!1,o,n.replaceOrInit);return $l(l,t[0].row,t[0].column)}),Qs,d,d,la),ha=Ks(Kl,Qs,d,d,sa),pa=Ks(Yl,Qs,d,d,la),wa=Ks(Jl,Qs,d,d,la),ba=Ks(((e,t,o,n)=>{const r=xl(e,t,o,n.replaceOrInit);return $l(r,t[0].row,t[0].column)}),Qs,d,d,sa),va=Ks(((e,t,o,n)=>{const r=xl(e,t,o,n.replaceOrInit);return $l(r,t[0].row,t[0].column)}),Qs,d,d,la),ya=Ks(((e,t,o,n)=>{const r=t.cells;Fl(r);const s=((e,t,o,n)=>{const r=_o(e).rows;if(0===r.length)return e;for(let e=t.startRow;e<=t.finishRow;e++)for(let o=t.startCol;o<=t.finishCol;o++){const t=r[e],s=Ao(t,o).isLocked;Bo(t,o,Ue(n(),!1,s))}return e})(e,t.bounds,0,n.merge(r));return Vl(s,y.from(r[0]))}),((e,t)=>((e,t)=>t.mergable)(0,t).filter((t=>Xs(e,t.cells)))),Xl,d,_l),xa=Ks(((e,t,o,n)=>{const r=B(t,((e,t)=>Zs(e,t,o,n.unmerge(t))),e);return Vl(r,y.from(t[0]))}),((e,t)=>((e,t)=>t.unmergable)(0,t).filter((t=>Xs(e,t)))),Xl,d,_l),Ca=Ks(((e,t,o,n)=>{const r=((e,t)=>{const o=Vo(e);return Vs(o,t,!0)})(t.clipboard,t.generators);var s,l;return((e,t,o,n,r)=>{const s=Po(t),l=((e,t,o)=>{const n=Lo(t[0]),r=_o(t).cols.length+e.row,s=D(n-e.column,(t=>t+e.column));return{row:r,column:A(s,(e=>M(o,(t=>t!==e)))).getOr(n-1)}})(e,t,s),a=_o(o).rows,c=ml(l,a,s),i=((e,t,o)=>{if(e.row>=t.length||e.column>Lo(t[0]))return ol.error("invalid start address out of table bounds, row: "+e.row+", column: "+e.column);const n=t.slice(e.row),r=n[0].cells.slice(e.column),s=Lo(o[0]),l=o.length;return ol.value({rowDelta:n.length-l,colDelta:r.length-s})})(l,t,a);return i.map((e=>{const o={...e,colDelta:e.colDelta-c.length},s=cl(t,o,n),i=Po(s),m=ml(l,a,i);return((e,t,o,n,r,s)=>{const l=e.row,a=e.column,c=l+o.length,i=a+Lo(o[0])+s.length,m=j(s,v);for(let e=l;eVl(e,y.some(t.element))),(e=>$l(e,t.row,t.column)))}),((e,t)=>_t(t.element).bind((o=>Us(e,o).map((e=>({...e,generators:t.generators,clipboard:t.clipboard})))))),Xl,d,Wl),Sa=Ks(((e,t,o,n)=>{const r=_o(e).rows,s=t.cells[0].column,l=r[t.cells[0].row],a=Ql(t.clipboard,t.generators,l),c=dl(s,e,a,t.generators,o);return $l(c,t.cells[0].row,t.cells[0].column)}),ra(!0),d,d,Wl),Ta=Ks(((e,t,o,n)=>{const r=_o(e).rows,s=t.cells[t.cells.length-1].column+t.cells[t.cells.length-1].colspan,l=r[t.cells[0].row],a=Ql(t.clipboard,t.generators,l),c=dl(s,e,a,t.generators,o);return $l(c,t.cells[0].row,t.cells[0].column)}),ra(!1),d,d,Wl),Ra=Ks(((e,t,o,n)=>{const r=_o(e).rows,s=t.cells[0].row,l=r[s],a=Ql(t.clipboard,t.generators,l),c=ul(s,e,a,t.generators,o);return $l(c,t.cells[0].row,t.cells[0].column)}),Ys,d,d,Wl),Da=Ks(((e,t,o,n)=>{const r=_o(e).rows,s=t.cells[t.cells.length-1].row+t.cells[t.cells.length-1].rowspan,l=r[t.cells[0].row],a=Ql(t.clipboard,t.generators,l),c=ul(s,e,a,t.generators,o);return $l(c,t.cells[0].row,t.cells[0].column)}),Ys,d,d,Wl),Oa=(e,t)=>{const o=Vo(e);return Js(o,t).bind((e=>{const t=e[e.length-1],n=e[0].column,r=t.column+t.colspan,s=L(O(o.all,(e=>N(e.cells,(e=>e.column>=n&&e.column{const o=Vo(e);return Js(o,t).bind(Ds).getOr("")},Ea=(e,t)=>{const o=Vo(e);return Js(o,t).bind((e=>{const t=e[e.length-1],n=e[0].row,r=t.row+t.rowspan;return(e=>{const t=O(e,(e=>Rs(e).type)),o=T(t,"header"),n=T(t,"footer");if(o||n){const e=T(t,"body");return!o||e||n?o||e||!n?y.none():y.some("footer"):y.some("header")}return y.some("body")})(o.all.slice(n,r))})).getOr("")},Na=(e,t)=>e.dispatch("NewRow",{node:t}),Ba=(e,t)=>e.dispatch("NewCell",{node:t}),za=(e,t,o)=>{e.dispatch("TableModified",{...o,table:t})},Aa={structure:!1,style:!0},Wa={structure:!0,style:!1},La={structure:!0,style:!0},_a=e=>t=>t.options.get(e),Ma="100%",ja=e=>{var t;const o=e.dom,n=null!==(t=o.getParent(e.selection.getStart(),o.isBlock))&&void 0!==t?t:e.getBody();return ko(ge.fromDom(n))+"px"},Ia=e=>y.from(e.options.get("table_clone_elements")),Pa=_a("table_header_type"),Fa=_a("table_column_resizing"),Ha=e=>"preservetable"===Fa(e),qa=e=>"resizetable"===Fa(e),Va=_a("table_sizing_mode"),$a=e=>"relative"===Va(e),Ua=e=>"fixed"===Va(e),Ga=e=>"responsive"===Va(e),Ka=_a("table_resize_bars"),Ya=_a("table_style_by_css"),Ja=e=>{const t=e.options,o=t.get("table_default_attributes");return t.isSet("table_default_attributes")?o:((e,t)=>Ga(e)||Ya(e)?t:Ua(e)?{...t,width:ja(e)}:{...t,width:Ma})(e,o)},Qa=_a("table_use_colgroups"),Xa=(e,t)=>$a(e)?nr(t):Ua(e)?or(t):tr(t),Za=(e,t,o)=>{const n=e=>"table"===Q(Tr(e)),r=Ia(e),s=qa(e)?d:fs,l=t=>{switch(Pa(e)){case"section":return zs();case"sectionCells":return As();case"cells":return Ws();default:return((e,t)=>{var o;switch((o=Vo(e),H(o.all,(e=>{const t=Rs(e);return"header"===t.type?y.from(t.subType):y.none()}))).getOr(t)){case"section":return Es();case"sectionCells":return Ns();case"cells":return Bs()}})(t,"section")}},a=(n,s,a,c)=>(i,m,d=!1)=>{Dr(i);const u=ge.fromDom(e.getDoc()),f=Cr(a,u,r),g={sizing:Xa(e,i),resize:qa(e)?vs():ys(),section:l(i)};return s(i)?n(i,m,f,g).bind((n=>{t.refresh(i.dom),k(n.newRows,(t=>{Na(e,t.dom)})),k(n.newCells,(t=>{Ba(e,t.dom)}));const r=((t,n)=>n.cursor.fold((()=>{const n=Mt(t);return P(n).filter(Xe).map((n=>{o.clearSelectedCells(t.dom);const r=e.dom.createRng();return r.selectNode(n.dom),e.selection.setRng(r),ae(n,"data-mce-selected","1"),r}))}),(n=>{const r=ds(us,n),s=e.dom.createRng();return s.setStart(r.element.dom,r.offset),s.setEnd(r.element.dom,r.offset),e.selection.setRng(s),o.clearSelectedCells(t.dom),y.some(s)})))(i,n);return Xe(i)&&(Dr(i),d||za(e,i.dom,c)),r.map((e=>({rng:e,effect:c})))})):y.none()},c=a(ua,(t=>!1===n(e)||xs(t).rows>1),d,Wa),i=a(da,(t=>!1===n(e)||xs(t).columns>1),d,Wa);return{deleteRow:c,deleteColumn:i,insertRowsBefore:a(aa,v,d,Wa),insertRowsAfter:a(ca,v,d,Wa),insertColumnsBefore:a(ia,v,s,Wa),insertColumnsAfter:a(ma,v,s,Wa),mergeCells:a(ya,v,d,Wa),unmergeCells:a(xa,v,d,Wa),pasteColsBefore:a(Sa,v,d,Wa),pasteColsAfter:a(Ta,v,d,Wa),pasteRowsBefore:a(Ra,v,d,Wa),pasteRowsAfter:a(Da,v,d,Wa),pasteCells:a(Ca,v,d,La),makeCellsHeader:a(ba,v,d,Wa),unmakeCellsHeader:a(va,v,d,Wa),makeColumnsHeader:a(fa,v,d,Wa),unmakeColumnsHeader:a(ga,v,d,Wa),makeRowsHeader:a(ha,v,d,Wa),makeRowsBody:a(pa,v,d,Wa),makeRowsFooter:a(wa,v,d,Wa),getTableRowType:Ea,getTableCellType:ka,getTableColType:Oa}},ec=(e,t,o)=>{const n=Ot(e,t,1);1===o||n<=1?de(e,t):ae(e,t,Math.min(o,n))},tc=(e,t)=>o=>{const n=o.column+o.colspan-1,r=o.column;return n>=e&&r{const n=o.substring(0,o.length-e.length),r=parseFloat(n);return n===r.toString()?t(r):oc.invalid(o)},rc={...oc,from:e=>pt(e,"%")?nc("%",oc.percent,e):pt(e,"px")?nc("px",oc.pixels,e):oc.invalid(e)},sc=(e,t,o)=>{const n=rc.from(o),r=M(e,(e=>"0px"===e))?((e,t)=>{const o=e.fold((()=>u("")),(e=>u(e/t+"px")),(()=>u(100/t+"%")));return D(t,o)})(n,e.length):((e,t,o)=>e.fold((()=>t),(e=>((e,t,o)=>{const n=o/t;return O(e,(e=>rc.from(e).fold((()=>e),(e=>e*n+"px"),(e=>e/100*o+"px"))))})(t,o,e)),(e=>((e,t)=>O(e,(e=>rc.from(e).fold((()=>e),(e=>e/t*100+"%"),(e=>e+"%")))))(t,o))))(n,e,t);return cc(r)},lc=(e,t)=>0===e.length?t:B(e,((e,t)=>rc.from(t).fold(u(0),f,f)+e),0),ac=(e,t)=>rc.from(e).fold(u(e),(e=>e+t+"px"),(e=>e+t+"%")),cc=e=>{if(0===e.length)return e;const t=B(e,((e,t)=>{const o=rc.from(t).fold((()=>({value:t,remainder:0})),(e=>((e,t)=>{const o=Math.floor(e);return{value:o+"px",remainder:e-o}})(e)),(e=>({value:e+"%",remainder:0})));return{output:[o.value].concat(e.output),remainder:e.remainder+o.remainder}}),{output:[],remainder:0}),o=t.output;return o.slice(0,o.length-1).concat([ac(o[o.length-1],Math.round(t.remainder))])},ic=rc.from,mc=e=>ic(e).fold(u("px"),u("px"),u("%")),dc=(e,t,o)=>{const n=Vo(e),r=n.all,s=Yo(n),l=Jo(n);t.each((t=>{const o=mc(t),r=Do(e),a=((e,t)=>Kn(e,t,$n,Yn))(n,e),c=sc(a,r,t);Qo(n)?((e,t,o)=>{k(t,((t,n)=>{const r=lc([e[n]],zt());xt(t.element,"width",r+o)}))})(c,l,o):((e,t,o)=>{k(t,(t=>{const n=e.slice(t.column,t.colspan+t.column),r=lc(n,zt());xt(t.element,"width",r+o)}))})(c,s,o),xt(e,"width",t)})),o.each((t=>{const o=mc(t),l=sn(e),a=((e,t,o)=>Qn(e,t,o,Un,Yn))(n,e,Sn);((e,t,o,n)=>{k(o,(t=>{const o=e.slice(t.row,t.rowspan+t.row),r=lc(o,At());xt(t.element,"height",r+n)})),k(t,((t,o)=>{xt(t.element,"height",e[o])}))})(sc(a,l,t),r,s,o),xt(e,"height",t)}))},uc=e=>Mn(e).exists((e=>kn.test(e))),fc=e=>Mn(e).exists((e=>En.test(e))),gc=e=>Mn(e).isNone(),hc=e=>{de(e,"width")},pc=e=>{const t=Hn(e);dc(e,y.some(t),y.none()),hc(e)},wc=e=>{const t=(e=>Do(e)+"px")(e);dc(e,y.some(t),y.none()),hc(e)},bc=e=>{Dt(e,"width");const t=jt(e),o=t.length>0?t:Mt(e);k(o,(e=>{Dt(e,"width"),hc(e)})),hc(e)},vc={styles:{"border-collapse":"collapse",width:"100%"},attributes:{border:"1"},colGroups:!1},yc=(e,t,o,n)=>D(e,(e=>((e,t,o,n)=>{const r=ge.fromTag("tr");for(let s=0;s{e.selection.select(t.dom,!0),e.selection.collapse(!0)},Cc=(e,t,o,r,s)=>{const l=(e=>{const t=e.options,o=t.get("table_default_styles");return t.isSet("table_default_styles")?o:((e,t)=>Ga(e)||!Ya(e)?t:Ua(e)?{...t,width:ja(e)}:{...t,width:Ma})(e,o)})(e),a={styles:l,attributes:Ja(e),colGroups:Qa(e)};return e.undoManager.ignore((()=>{const n=((e,t,o,n,r,s=vc)=>{const l=ge.fromTag("table"),a="cells"!==r;Ct(l,s.styles),ce(l,s.attributes),s.colGroups&&ze(l,(e=>{const t=ge.fromTag("colgroup");return D(e,(()=>ze(t,ge.fromTag("col")))),t})(t));const c=Math.min(e,o);if(a&&o>0){const e=ge.fromTag("thead");ze(l,e);const s=yc(o,t,"sectionCells"===r?c:0,n);Le(e,s)}const i=ge.fromTag("tbody");ze(l,i);const m=yc(a?e-c:e,t,a?0:o,n);return Le(i,m),l})(o,t,s,r,Pa(e),a);ae(n,"data-mce-id","__mce");const l=(e=>{const t=ge.fromTag("div"),o=ge.fromDom(e.dom.cloneNode(!0));return ze(t,o),(e=>e.dom.innerHTML)(t)})(n);e.insertContent(l),e.addVisual()})),ct(Tr(e),'table[data-mce-id="__mce"]').map((t=>(Ua(e)?wc(t):Ga(e)?bc(t):($a(e)||(e=>n(e)&&-1!==e.indexOf("%"))(l.width))&&pc(t),Dr(t),de(t,"data-mce-id"),((e,t)=>{k(nt(t,"tr"),(t=>{Na(e,t.dom),k(nt(t,"th,td"),(t=>{Ba(e,t.dom)}))}))})(e,t),((e,t)=>{ct(t,"td,th").each(h(xc,e))})(e,t),t.dom))).getOr(null)};var Sc=tinymce.util.Tools.resolve("tinymce.FakeClipboard");const Tc="x-tinymce/dom-table-",Rc=Tc+"rows",Dc=Tc+"columns",Oc=e=>{const t=Sc.FakeClipboardItem(e);Sc.write([t])},kc=e=>{var t;const o=null!==(t=Sc.read())&&void 0!==t?t:[];return H(o,(t=>y.from(t.getType(e))))},Ec=e=>{kc(e).isSome()&&Sc.clear()},Nc=e=>{e.fold(zc,(e=>Oc({[Rc]:e})))},Bc=()=>kc(Rc),zc=()=>Ec(Rc),Ac=e=>{e.fold(Lc,(e=>Oc({[Dc]:e})))},Wc=()=>kc(Dc),Lc=()=>Ec(Dc),_c=e=>ns(Or(e),Rr(e)),Mc=(e,t)=>{const o=Rr(e),s=e=>It(e,o),l=t=>(e=>rs(Or(e),Rr(e)))(e).bind((e=>s(e).map((o=>t(o,e))))),a=t=>{e.focus()},c=(t,o=!1)=>l(((n,r)=>{const s=ts(ss(e),n,r);t(n,s,o).each(a)})),i=()=>l(((t,o)=>((e,t,o)=>{const n=Vo(e);return Js(n,t).bind((e=>{const t=Vs(n,o,!1),r=_o(t).rows.slice(e[0].row,e[e.length-1].row+e[e.length-1].rowspan),s=_(r,(e=>{const t=N(e.cells,(e=>!e.isLocked));return t.length>0?[{...e,cells:t}]:[]})),l=$s(s);return ut(l.length>0,l)})).map((e=>O(e,(e=>{const t=Pe(e.element);return k(e.cells,(e=>{const o=Fe(e.element);Is(o,"colspan",e.colspan,1),Is(o,"rowspan",e.rowspan,1),ze(t,o)})),t}))))})(t,ts(ss(e),t,o),Cr(d,ge.fromDom(e.getDoc()),y.none())))),u=()=>l(((t,o)=>((e,t)=>{const o=Vo(e);return Qs(o,t).map((e=>{const t=e[e.length-1],n=e[0].column,r=t.column+t.colspan,s=((e,t,o)=>{if(Qo(e)){const n=N(Jo(e),tc(t,o)),r=O(n,(e=>{const n=Fe(e.element);return ec(n,"span",o-t),n})),s=ge.fromTag("colgroup");return Le(s,r),[s]}return[]})(o,n,r),l=((e,t,o)=>O(e.all,(e=>{const n=N(e.cells,tc(t,o)),r=O(n,(e=>{const n=Fe(e.element);return ec(n,"colspan",o-t),n})),s=ge.fromTag("tr");return Le(s,r),s})))(o,n,r);return[...s,...l]}))})(t,ts(ss(e),t,o)))),f=(t,o)=>o().each((o=>{const n=O(o,(e=>Fe(e)));l(((o,r)=>{const s=Sr(ge.fromDom(e.getDoc())),l=((e,t,o,n)=>({selection:Qr(e),clipboard:o,generators:n}))(ss(e),0,n,s);t(o,l).each(a)}))})),g=e=>(t,o)=>((e,t)=>J(e,t)?y.from(e.type):y.none())(o,"type").each((t=>{c(e(t),o.no_events)}));$({mceTableSplitCells:()=>c(t.unmergeCells),mceTableMergeCells:()=>c(t.mergeCells),mceTableInsertRowBefore:()=>c(t.insertRowsBefore),mceTableInsertRowAfter:()=>c(t.insertRowsAfter),mceTableInsertColBefore:()=>c(t.insertColumnsBefore),mceTableInsertColAfter:()=>c(t.insertColumnsAfter),mceTableDeleteCol:()=>c(t.deleteColumn),mceTableDeleteRow:()=>c(t.deleteRow),mceTableCutCol:()=>u().each((e=>{Ac(e),c(t.deleteColumn)})),mceTableCutRow:()=>i().each((e=>{Nc(e),c(t.deleteRow)})),mceTableCopyCol:()=>u().each((e=>Ac(e))),mceTableCopyRow:()=>i().each((e=>Nc(e))),mceTablePasteColBefore:()=>f(t.pasteColsBefore,Wc),mceTablePasteColAfter:()=>f(t.pasteColsAfter,Wc),mceTablePasteRowBefore:()=>f(t.pasteRowsBefore,Bc),mceTablePasteRowAfter:()=>f(t.pasteRowsAfter,Bc),mceTableDelete:()=>_c(e).each((t=>{It(t,o).filter(p(o)).each((t=>{const o=ge.fromText("");if(Ne(t,o),Me(t),e.dom.isEmpty(e.getBody()))e.setContent(""),e.selection.setCursorLocation();else{const t=e.dom.createRng();t.setStart(o.dom,0),t.setEnd(o.dom,0),e.selection.setRng(t),e.nodeChanged()}}))})),mceTableCellToggleClass:(t,o)=>{l((t=>{const n=ss(e),r=M(n,(t=>e.formatter.match("tablecellclass",{value:o},t.dom))),s=r?e.formatter.remove:e.formatter.apply;k(n,(e=>s("tablecellclass",{value:o},e.dom))),za(e,t.dom,Aa)}))},mceTableToggleClass:(t,o)=>{l((t=>{e.formatter.toggle("tableclass",{value:o},t.dom),za(e,t.dom,Aa)}))},mceTableToggleCaption:()=>{_c(e).each((t=>{It(t,o).each((o=>{at(o,"caption").fold((()=>{const t=ge.fromTag("caption");ze(t,ge.fromText("Caption")),((e,t,o)=>{ke(e,0).fold((()=>{ze(e,t)}),(e=>{Ee(e,t)}))})(o,t),e.selection.setCursorLocation(t.dom,0)}),(n=>{se("caption")(t)&&we("td",o).each((t=>e.selection.setCursorLocation(t.dom,0))),Me(n)})),za(e,o.dom,Wa)}))}))},mceTableSizingMode:(t,n)=>(t=>_c(e).each((n=>{Ga(e)||Ua(e)||$a(e)||It(n,o).each((o=>{"relative"!==t||uc(o)?"fixed"!==t||fc(o)?"responsive"!==t||gc(o)||bc(o):wc(o):pc(o),Dr(o),za(e,o.dom,Wa)}))})))(n),mceTableCellType:g((e=>"th"===e?t.makeCellsHeader:t.unmakeCellsHeader)),mceTableColType:g((e=>"th"===e?t.makeColumnsHeader:t.unmakeColumnsHeader)),mceTableRowType:g((e=>{switch(e){case"header":return t.makeRowsHeader;case"footer":return t.makeRowsFooter;default:return t.makeRowsBody}}))},((t,o)=>e.addCommand(o,t))),e.addCommand("mceInsertTable",((t,o)=>{((e,t,o,n={})=>{const r=e=>m(e)&&e>0;if(r(t)&&r(o)){const r=n.headerRows||0,s=n.headerColumns||0;return Cc(e,o,t,s,r)}console.error("Invalid values for mceInsertTable - rows and columns values are required to insert a table.")})(e,o.rows,o.columns,o.options)})),e.addCommand("mceTableApplyCellStyle",((t,o)=>{const l=e=>"tablecell"+e.toLowerCase().replace("-","");if(!r(o))return;const a=ss(e);if(0===a.length)return;const c=((e,t)=>{const o={};return((e,t,o,n)=>{$(e,((e,r)=>{(t(e,r)?o:n)(e,r)}))})(e,t,(e=>(t,o)=>{e[o]=t})(o),d),o})(o,((t,o)=>e.formatter.has(l(o))&&n(t)));(e=>{for(const t in e)if(V.call(e,t))return!1;return!0})(c)||($(c,((t,o)=>{const n=l(o);k(a,(o=>{""===t?e.formatter.remove(n,{value:null},o.dom,!0):e.formatter.apply(n,{value:t},o.dom)}))})),s(a[0]).each((t=>za(e,t.dom,Aa))))}))},jc=Cl([{before:["element"]},{on:["element","offset"]},{after:["element"]}]),Ic={before:jc.before,on:jc.on,after:jc.after,cata:(e,t,o,n)=>e.fold(t,o,n),getStart:e=>e.fold(f,f,f)},Pc=(e,t)=>({selection:e,kill:t}),Fc=(e,t)=>{const o=e.document.createRange();return o.selectNode(t.dom),o},Hc=(e,t)=>{const o=e.document.createRange();return qc(o,t),o},qc=(e,t)=>e.selectNodeContents(t.dom),Vc=(e,t,o)=>{const n=e.document.createRange();var r;return r=n,t.fold((e=>{r.setStartBefore(e.dom)}),((e,t)=>{r.setStart(e.dom,t)}),(e=>{r.setStartAfter(e.dom)})),((e,t)=>{t.fold((t=>{e.setEndBefore(t.dom)}),((t,o)=>{e.setEnd(t.dom,o)}),(t=>{e.setEndAfter(t.dom)}))})(n,o),n},$c=(e,t,o,n,r)=>{const s=e.document.createRange();return s.setStart(t.dom,o),s.setEnd(n.dom,r),s},Uc=e=>({left:e.left,top:e.top,right:e.right,bottom:e.bottom,width:e.width,height:e.height}),Gc=Cl([{ltr:["start","soffset","finish","foffset"]},{rtl:["start","soffset","finish","foffset"]}]),Kc=(e,t,o)=>t(ge.fromDom(o.startContainer),o.startOffset,ge.fromDom(o.endContainer),o.endOffset),Yc=(e,t)=>{const o=((e,t)=>t.match({domRange:e=>({ltr:u(e),rtl:y.none}),relative:(t,o)=>({ltr:$t((()=>Vc(e,t,o))),rtl:$t((()=>y.some(Vc(e,o,t))))}),exact:(t,o,n,r)=>({ltr:$t((()=>$c(e,t,o,n,r))),rtl:$t((()=>y.some($c(e,n,r,t,o))))})}))(e,t);return((e,t)=>{const o=t.ltr();return o.collapsed?t.rtl().filter((e=>!1===e.collapsed)).map((e=>Gc.rtl(ge.fromDom(e.endContainer),e.endOffset,ge.fromDom(e.startContainer),e.startOffset))).getOrThunk((()=>Kc(0,Gc.ltr,o))):Kc(0,Gc.ltr,o)})(0,o)},Jc=(e,t)=>Yc(e,t).match({ltr:(t,o,n,r)=>{const s=e.document.createRange();return s.setStart(t.dom,o),s.setEnd(n.dom,r),s},rtl:(t,o,n,r)=>{const s=e.document.createRange();return s.setStart(n.dom,r),s.setEnd(t.dom,o),s}});Gc.ltr,Gc.rtl;const Qc=(e,t,o,n)=>({start:e,soffset:t,finish:o,foffset:n}),Xc=(e,t,o,n)=>({start:Ic.on(e,t),finish:Ic.on(o,n)}),Zc=(e,t)=>{const o=Jc(e,t);return Qc(ge.fromDom(o.startContainer),o.startOffset,ge.fromDom(o.endContainer),o.endOffset)},ei=Xc,ti=(e,t,o,n,r)=>be(o,n)?y.none():$r(o,n,t).bind((t=>{const n=t.boxes.getOr([]);return n.length>1?(r(e,n,t.start,t.finish),y.some(Pc(y.some(ei(o,0,o,ir(o))),!0))):y.none()})),oi=(e,t)=>({item:e,mode:t}),ni=(e,t,o,n=ri)=>e.property().parent(t).map((e=>oi(e,n))),ri=(e,t,o,n=si)=>o.sibling(e,t).map((e=>oi(e,n))),si=(e,t,o,n=si)=>{const r=e.property().children(t);return o.first(r).map((e=>oi(e,n)))},li=[{current:ni,next:ri,fallback:y.none()},{current:ri,next:si,fallback:y.some(ni)},{current:si,next:si,fallback:y.some(ri)}],ai=(e,t,o,n,r=li)=>A(r,(e=>e.current===o)).bind((o=>o.current(e,t,n,o.next).orThunk((()=>o.fallback.bind((o=>ai(e,t,o,n))))))),ci=(e,t,o,n,r,s)=>ai(e,t,n,r).bind((t=>s(t.item)?y.none():o(t.item)?y.some(t.item):ci(e,t.item,o,t.mode,r,s))),ii=e=>t=>0===e.property().children(t).length,mi=(e,t,o,n)=>ci(e,t,o,ri,{sibling:(e,t)=>e.query().prevSibling(t),first:e=>e.length>0?y.some(e[e.length-1]):y.none()},n),di=(e,t,o,n)=>ci(e,t,o,ri,{sibling:(e,t)=>e.query().nextSibling(t),first:e=>e.length>0?y.some(e[0]):y.none()},n),ui=Ir(),fi=(e,t)=>((e,t,o)=>mi(e,t,ii(e),o))(ui,e,t),gi=(e,t)=>((e,t,o)=>di(e,t,ii(e),o))(ui,e,t),hi=Cl([{none:["message"]},{success:[]},{failedUp:["cell"]},{failedDown:["cell"]}]),pi=e=>it(e,"tr"),wi={...hi,verify:(e,t,o,n,r,s,l)=>it(n,"td,th",l).bind((o=>it(t,"td,th",l).map((t=>be(o,t)?be(n,o)&&ir(o)===r?s(t):hi.none("in same cell"):qr(pi,[o,t]).fold((()=>((e,t,o)=>{const n=e.getRect(t),r=e.getRect(o);return r.right>n.left&&r.lefts(t))))))).getOr(hi.none("default")),cata:(e,t,o,n,r)=>e.fold(t,o,n,r)},bi=se("br"),vi=(e,t,o)=>t(e,o).bind((e=>oe(e)&&0===lr(e).trim().length?vi(e,t,o):y.some(e))),yi=(e,t,o,n)=>((e,t)=>ke(e,t).filter(bi).orThunk((()=>ke(e,t-1).filter(bi))))(t,o).bind((t=>n.traverse(t).fold((()=>vi(t,n.gather,e).map(n.relative)),(e=>(e=>Se(e).bind((t=>{const o=Oe(t);return((e,t)=>W(e,h(be,t)))(o,e).map((n=>((e,t,o,n)=>({parent:e,children:t,element:o,index:n}))(t,o,e,n)))})))(e).map((e=>Ic.on(e.parent,e.index))))))),xi=(e,t)=>({left:e.left,top:e.top+t,right:e.right,bottom:e.bottom+t}),Ci=(e,t)=>({left:e.left,top:e.top-t,right:e.right,bottom:e.bottom-t}),Si=(e,t,o)=>({left:e.left+t,top:e.top+o,right:e.right+t,bottom:e.bottom+o}),Ti=e=>({left:e.left,top:e.top,right:e.right,bottom:e.bottom}),Ri=(e,t)=>y.some(e.getRect(t)),Di=(e,t,o)=>te(t)?Ri(e,t).map(Ti):oe(t)?((e,t,o)=>o>=0&&o0?e.getRangedRect(t,o-1,t,o):y.none())(e,t,o).map(Ti):y.none(),Oi=(e,t)=>te(t)?Ri(e,t).map(Ti):oe(t)?e.getRangedRect(t,0,t,ir(t)).map(Ti):y.none(),ki=Cl([{none:[]},{retry:["caret"]}]),Ei=(e,t,o)=>{return(n=t,r=Il,rt(((e,t)=>t(e)),st,n,r,undefined)).fold(b,(t=>Oi(e,t).exists((e=>((e,t)=>e.leftt.right)(o,e)))));var n,r},Ni={point:e=>e.bottom,adjuster:(e,t,o,n,r)=>{const s=xi(r,5);return Math.abs(o.bottom-n.bottom)<1||o.top>r.bottom?ki.retry(s):o.top===r.bottom?ki.retry(xi(r,1)):Ei(e,t,r)?ki.retry(Si(s,5,0)):ki.none()},move:xi,gather:gi},Bi=(e,t,o,n,r)=>0===r?y.some(n):((e,t,o)=>e.elementFromPoint(t,o).filter((e=>"table"===Q(e))).isSome())(e,n.left,t.point(n))?((e,t,o,n,r)=>Bi(e,t,o,t.move(n,5),r))(e,t,o,n,r-1):e.situsFromPoint(n.left,t.point(n)).bind((s=>s.start.fold(y.none,(s=>Oi(e,s).bind((l=>t.adjuster(e,s,l,o,n).fold(y.none,(n=>Bi(e,t,o,n,r-1))))).orThunk((()=>y.some(n)))),y.none))),zi=(e,t,o)=>{const n=e.move(o,5),r=Bi(t,e,o,n,100).getOr(n);return((e,t,o)=>e.point(t)>o.getInnerHeight()?y.some(e.point(t)-o.getInnerHeight()):e.point(t)<0?y.some(-e.point(t)):y.none())(e,r,t).fold((()=>t.situsFromPoint(r.left,e.point(r))),(o=>(t.scrollBy(0,o),t.situsFromPoint(r.left,e.point(r)-o))))},Ai={tryUp:h(zi,{point:e=>e.top,adjuster:(e,t,o,n,r)=>{const s=Ci(r,5);return Math.abs(o.top-n.top)<1||o.bottome.getSelection().bind((n=>((e,t,o,n)=>{const r=bi(t)?((e,t,o)=>o.traverse(t).orThunk((()=>vi(t,o.gather,e))).map(o.relative))(e,t,n):yi(e,t,o,n);return r.map((e=>({start:e,finish:e})))})(t,n.finish,n.foffset,o).fold((()=>y.some(as(n.finish,n.foffset))),(r=>{const s=e.fromSitus(r);return l=wi.verify(e,n.finish,n.foffset,s.finish,s.foffset,o.failure,t),wi.cata(l,(e=>y.none()),(()=>y.none()),(e=>y.some(as(e,0))),(e=>y.some(as(e,ir(e)))));var l})))),Li=(e,t,o,n,r,s)=>0===s?y.none():ji(e,t,o,n,r).bind((l=>{const a=e.fromSitus(l),c=wi.verify(e,o,n,a.finish,a.foffset,r.failure,t);return wi.cata(c,(()=>y.none()),(()=>y.some(l)),(l=>be(o,l)&&0===n?_i(e,o,n,Ci,r):Li(e,t,l,0,r,s-1)),(l=>be(o,l)&&n===ir(l)?_i(e,o,n,xi,r):Li(e,t,l,ir(l),r,s-1)))})),_i=(e,t,o,n,r)=>Di(e,t,o).bind((t=>Mi(e,r,n(t,Ai.getJumpSize())))),Mi=(e,t,o)=>{const n=Co().browser;return n.isChromium()||n.isSafari()||n.isFirefox()?t.retry(e,o):y.none()},ji=(e,t,o,n,r)=>Di(e,o,n).bind((t=>Mi(e,r,t))),Ii=(e,t,o,n,r)=>it(n,"td,th",t).bind((n=>it(n,"table",t).bind((s=>((e,t)=>st(e,(e=>Se(e).exists((e=>be(e,t)))),void 0).isSome())(r,s)?((e,t,o)=>Wi(e,t,o).bind((n=>Li(e,t,n.element,n.offset,o,20).map(e.fromSitus))))(e,t,o).bind((e=>it(e.finish,"td,th",t).map((t=>({start:n,finish:t,range:e}))))):y.none())))),Pi=(e,t,o,n,r,s)=>s(n,t).orThunk((()=>Ii(e,t,o,n,r).map((e=>{const t=e.range;return Pc(y.some(ei(t.start,t.soffset,t.finish,t.foffset)),!0)})))),Fi=(e,t)=>it(e,"tr",t).bind((e=>it(e,"table",t).bind((o=>{const n=nt(o,"tr");return be(e,n[0])?((e,t,o)=>mi(ui,e,(e=>fr(e).isSome()),o))(o,0,t).map((e=>{const t=ir(e);return Pc(y.some(ei(e,t,e,t)),!0)})):y.none()})))),Hi=(e,t)=>it(e,"tr",t).bind((e=>it(e,"table",t).bind((o=>{const n=nt(o,"tr");return be(e,n[n.length-1])?((e,t,o)=>di(ui,e,(e=>ur(e).isSome()),o))(o,0,t).map((e=>Pc(y.some(ei(e,0,e,0)),!0))):y.none()})))),qi=(e,t,o,n,r,s,l)=>Ii(e,o,n,r,s).bind((e=>ti(t,o,e.start,e.finish,l))),Vi=e=>{let t=e;return{get:()=>t,set:e=>{t=e}}},$i=()=>{const e=(e=>{const t=Vi(y.none()),o=()=>t.get().each(e);return{clear:()=>{o(),t.set(y.none())},isSet:()=>t.get().isSome(),get:()=>t.get(),set:e=>{o(),t.set(y.some(e))}}})(d);return{...e,on:t=>e.get().each(t)}},Ui=(e,t)=>it(e,"td,th",t),Gi={traverse:De,gather:gi,relative:Ic.before,retry:Ai.tryDown,failure:wi.failedDown},Ki={traverse:Re,gather:fi,relative:Ic.before,retry:Ai.tryUp,failure:wi.failedUp},Yi=e=>t=>t===e,Ji=Yi(38),Qi=Yi(40),Xi=e=>e>=37&&e<=40,Zi={isBackward:Yi(37),isForward:Yi(39)},em={isBackward:Yi(39),isForward:Yi(37)},tm=Cl([{domRange:["rng"]},{relative:["startSitu","finishSitu"]},{exact:["start","soffset","finish","foffset"]}]),om={domRange:tm.domRange,relative:tm.relative,exact:tm.exact,exactFromRange:e=>tm.exact(e.start,e.soffset,e.finish,e.foffset),getWin:e=>{const t=(e=>e.match({domRange:e=>ge.fromDom(e.startContainer),relative:(e,t)=>Ic.getStart(e),exact:(e,t,o,n)=>e}))(e);return ge.fromDom(Ce(t).dom.defaultView)},range:Qc},nm=document.caretPositionFromPoint?(e,t,o)=>{var n,r;return y.from(null===(r=(n=e.dom).caretPositionFromPoint)||void 0===r?void 0:r.call(n,t,o)).bind((t=>{if(null===t.offsetNode)return y.none();const o=e.dom.createRange();return o.setStart(t.offsetNode,t.offset),o.collapse(),y.some(o)}))}:document.caretRangeFromPoint?(e,t,o)=>{var n,r;return y.from(null===(r=(n=e.dom).caretRangeFromPoint)||void 0===r?void 0:r.call(n,t,o))}:y.none,rm=(e,t)=>{const o=Q(e);return"input"===o?Ic.after(e):T(["br","img"],o)?0===t?Ic.before(e):Ic.after(e):Ic.on(e,t)},sm=e=>y.from(e.getSelection()),lm=(e,t)=>{sm(e).each((e=>{e.removeAllRanges(),e.addRange(t)}))},am=(e,t,o,n,r)=>{const s=$c(e,t,o,n,r);lm(e,s)},cm=(e,t)=>Yc(e,t).match({ltr:(t,o,n,r)=>{am(e,t,o,n,r)},rtl:(t,o,n,r)=>{sm(e).each((s=>{if(s.setBaseAndExtent)s.setBaseAndExtent(t.dom,o,n.dom,r);else if(s.extend)try{((e,t,o,n,r,s)=>{t.collapse(o.dom,n),t.extend(r.dom,s)})(0,s,t,o,n,r)}catch(s){am(e,n,r,t,o)}else am(e,n,r,t,o)}))}}),im=(e,t,o,n,r)=>{const s=((e,t,o,n)=>{const r=rm(e,t),s=rm(o,n);return om.relative(r,s)})(t,o,n,r);cm(e,s)},mm=(e,t,o)=>{const n=((e,t)=>{const o=e.fold(Ic.before,rm,Ic.after),n=t.fold(Ic.before,rm,Ic.after);return om.relative(o,n)})(t,o);cm(e,n)},dm=e=>{if(e.rangeCount>0){const t=e.getRangeAt(0),o=e.getRangeAt(e.rangeCount-1);return y.some(Qc(ge.fromDom(t.startContainer),t.startOffset,ge.fromDom(o.endContainer),o.endOffset))}return y.none()},um=e=>{if(null===e.anchorNode||null===e.focusNode)return dm(e);{const t=ge.fromDom(e.anchorNode),o=ge.fromDom(e.focusNode);return((e,t,o,n)=>{const r=((e,t,o,n)=>{const r=xe(e).dom.createRange();return r.setStart(e.dom,t),r.setEnd(o.dom,n),r})(e,t,o,n),s=be(e,o)&&t===n;return r.collapsed&&!s})(t,e.anchorOffset,o,e.focusOffset)?y.some(Qc(t,e.anchorOffset,o,e.focusOffset)):dm(e)}},fm=(e,t,o=!0)=>{const n=(o?Hc:Fc)(e,t);lm(e,n)},gm=e=>(e=>sm(e).filter((e=>e.rangeCount>0)).bind(um))(e).map((e=>om.exact(e.start,e.soffset,e.finish,e.foffset))),hm=e=>({elementFromPoint:(t,o)=>ge.fromPoint(ge.fromDom(e.document),t,o),getRect:e=>e.dom.getBoundingClientRect(),getRangedRect:(t,o,n,r)=>{const s=om.exact(t,o,n,r);return((e,t)=>(e=>{const t=e.getClientRects(),o=t.length>0?t[0]:e.getBoundingClientRect();return o.width>0||o.height>0?y.some(o).map(Uc):y.none()})(Jc(e,t)))(e,s)},getSelection:()=>gm(e).map((t=>Zc(e,t))),fromSitus:t=>{const o=om.relative(t.start,t.finish);return Zc(e,o)},situsFromPoint:(t,o)=>((e,t,o)=>((e,t,o)=>{const n=ge.fromDom(e.document);return nm(n,t,o).map((e=>Qc(ge.fromDom(e.startContainer),e.startOffset,ge.fromDom(e.endContainer),e.endOffset)))})(e,t,o))(e,t,o).map((e=>Xc(e.start,e.soffset,e.finish,e.foffset))),clearSelection:()=>{(e=>{sm(e).each((e=>e.removeAllRanges()))})(e)},collapseSelection:(t=!1)=>{gm(e).each((o=>o.fold((e=>e.collapse(t)),((o,n)=>{const r=t?o:n;mm(e,r,r)}),((o,n,r,s)=>{const l=t?o:r,a=t?n:s;im(e,l,a,l,a)}))))},setSelection:t=>{im(e,t.start,t.soffset,t.finish,t.foffset)},setRelativeSelection:(t,o)=>{mm(e,t,o)},selectNode:t=>{fm(e,t,!1)},selectContents:t=>{fm(e,t)},getInnerHeight:()=>e.innerHeight,getScrollY:()=>(e=>{const t=void 0!==e?e.dom:document,o=t.body.scrollLeft||t.documentElement.scrollLeft,n=t.body.scrollTop||t.documentElement.scrollTop;return cn(o,n)})(ge.fromDom(e.document)).top,scrollBy:(t,o)=>{((e,t,o)=>{const n=(void 0!==o?o.dom:document).defaultView;n&&n.scrollBy(e,t)})(t,o,ge.fromDom(e.document))}}),pm=(e,t)=>({rows:e,cols:t}),wm=e=>void 0!==e.dom.classList,bm=(e,t)=>((e,t,o)=>{const n=((e,t)=>{const o=ie(e,t);return void 0===o||""===o?[]:o.split(" ")})(e,t).concat([o]);return ae(e,t,n.join(" ")),!0})(e,"class",t),vm=(e,t)=>{wm(e)?e.dom.classList.add(t):bm(e,t)},ym=(e,t)=>wm(e)&&e.dom.classList.contains(t),xm=()=>({tag:"none"}),Cm=e=>({tag:"multiple",elements:e}),Sm=e=>({tag:"single",element:e}),Tm=e=>{const t=ge.fromDom((e=>{if(Ye()&&c(e.target)){const t=ge.fromDom(e.target);if(te(t)&&c(t.dom.shadowRoot)&&e.composed&&e.composedPath){const t=e.composedPath();if(t)return P(t)}}return y.from(e.target)})(e).getOr(e.target)),o=()=>e.stopPropagation(),n=()=>e.preventDefault(),r=(s=n,l=o,(...e)=>s(l.apply(null,e)));var s,l;return((e,t,o,n,r,s,l)=>({target:e,x:t,y:o,stop:n,prevent:r,kill:s,raw:l}))(t,e.clientX,e.clientY,o,n,r,e)},Rm=(e,t,o,n)=>{e.dom.removeEventListener(t,o,n)},Dm=v,Om=(e,t,o)=>((e,t,o,n)=>((e,t,o,n,r)=>{const s=((e,t)=>o=>{e(o)&&t(Tm(o))})(o,n);return e.dom.addEventListener(t,s,r),{unbind:h(Rm,e,t,s,r)}})(e,t,o,n,!1))(e,t,Dm,o),km=Tm,Em=e=>!1===ym(ge.fromDom(e.target),"ephox-snooker-resizer-bar"),Nm=(e,t)=>{const o=(r=es.selectedSelector,{get:()=>Yr(ge.fromDom(e.getBody()),r).fold((()=>rs(Or(e),Rr(e)).fold(xm,Sm)),Cm)}),n=((e,t,o)=>{const n=t=>{de(t,e.selected),de(t,e.firstSelected),de(t,e.lastSelected)},r=t=>{ae(t,e.selected,"1")},s=e=>{l(e),o()},l=t=>{const o=nt(t,`${e.selectedSelector},${e.firstSelectedSelector},${e.lastSelectedSelector}`);k(o,n)};return{clearBeforeUpdate:l,clear:s,selectRange:(o,n,l,a)=>{s(o),k(n,r),ae(l,e.firstSelected,"1"),ae(a,e.lastSelected,"1"),t(n,l,a)},selectedSelector:e.selectedSelector,firstSelectedSelector:e.firstSelectedSelector,lastSelectedSelector:e.lastSelectedSelector}})(es,((t,o,n)=>{It(o).each((r=>{const s=Ia(e),l=Cr(d,ge.fromDom(e.getDoc()),s),a=((e,t,o)=>{const n=Vo(e);return Js(n,t).map((e=>{const t=Vs(n,o,!1),{rows:r}=_o(t),s=((e,t)=>{const o=e.slice(0,t[t.length-1].row+1),n=$s(o);return _(n,(e=>{const o=e.cells.slice(0,t[t.length-1].column+1);return O(o,(e=>e.element))}))})(r,e),l=((e,t)=>{const o=e.slice(t[0].row+t[0].rowspan-1,e.length),n=$s(o);return _(n,(e=>{const o=e.cells.slice(t[0].column+t[0].colspan-1,e.cells.length);return O(o,(e=>e.element))}))})(r,e);return{upOrLeftCells:s,downOrRightCells:l}}))})(r,{selection:ss(e)},l);((e,t,o,n,r)=>{e.dispatch("TableSelectionChange",{cells:t,start:o,finish:n,otherCells:r})})(e,t,o,n,a)}))}),(()=>(e=>{e.dispatch("TableSelectionClear")})(e)));var r;return e.on("init",(o=>{const r=e.getWin(),s=Tr(e),l=Rr(e),a=((e,t,o,n)=>{const r=((e,t,o,n)=>{const r=$i(),s=r.clear,l=s=>{r.on((r=>{n.clearBeforeUpdate(t),Ui(s.target,o).each((l=>{$r(r,l,o).each((o=>{const r=o.boxes.getOr([]);if(1===r.length){const o=r[0],l="false"===js(o),a=mt(_s(s.target),o,be);l&&a&&(n.selectRange(t,r,o,o),e.selectContents(o))}else r.length>1&&(n.selectRange(t,r,o.start,o.finish),e.selectContents(l))}))}))}))};return{clearstate:s,mousedown:e=>{n.clear(t),Ui(e.target,o).each(r.set)},mouseover:e=>{l(e)},mouseup:e=>{l(e),s()}}})(hm(e),t,o,n);return{clearstate:r.clearstate,mousedown:r.mousedown,mouseover:r.mouseover,mouseup:r.mouseup}})(r,s,l,n),c=((e,t,o,n)=>{const r=hm(e),s=()=>(n.clear(t),y.none());return{keydown:(e,l,a,c,i,m)=>{const d=e.raw,u=d.which,f=!0===d.shiftKey,g=Ur(t,n.selectedSelector).fold((()=>(Xi(u)&&!f&&n.clearBeforeUpdate(t),Qi(u)&&f?h(qi,r,t,o,Gi,c,l,n.selectRange):Ji(u)&&f?h(qi,r,t,o,Ki,c,l,n.selectRange):Qi(u)?h(Pi,r,o,Gi,c,l,Hi):Ji(u)?h(Pi,r,o,Ki,c,l,Fi):y.none)),(e=>{const o=o=>()=>{const s=H(o,(o=>((e,t,o,n,r)=>Kr(n,e,t,r.firstSelectedSelector,r.lastSelectedSelector).map((e=>(r.clearBeforeUpdate(o),r.selectRange(o,e.boxes,e.start,e.finish),e.boxes))))(o.rows,o.cols,t,e,n)));return s.fold((()=>Gr(t,n.firstSelectedSelector,n.lastSelectedSelector).map((e=>{const o=Qi(u)||m.isForward(u)?Ic.after:Ic.before;return r.setRelativeSelection(Ic.on(e.first,0),o(e.table)),n.clear(t),Pc(y.none(),!0)}))),(e=>y.some(Pc(y.none(),!0))))};return Qi(u)&&f?o([pm(1,0)]):Ji(u)&&f?o([pm(-1,0)]):m.isBackward(u)&&f?o([pm(0,-1),pm(-1,0)]):m.isForward(u)&&f?o([pm(0,1),pm(1,0)]):Xi(u)&&!f?s:y.none}));return g()},keyup:(e,r,s,l,a)=>Ur(t,n.selectedSelector).fold((()=>{const c=e.raw,i=c.which;return!0===c.shiftKey&&Xi(i)?((e,t,o,n,r,s,l)=>be(o,r)&&n===s?y.none():it(o,"td,th",t).bind((o=>it(r,"td,th",t).bind((n=>ti(e,t,o,n,l))))))(t,o,r,s,l,a,n.selectRange):y.none()}),y.none)}})(r,s,l,n),i=((e,t,o,n)=>{const r=hm(e);return(e,s)=>{n.clearBeforeUpdate(t),$r(e,s,o).each((e=>{const o=e.boxes.getOr([]);n.selectRange(t,o,e.start,e.finish),r.selectContents(s),r.collapseSelection()}))}})(r,s,l,n);e.on("TableSelectorChange",(e=>i(e.start,e.finish)));const m=(t,o)=>{(e=>!0===e.raw.shiftKey)(t)&&(o.kill&&t.kill(),o.selection.each((t=>{const o=om.relative(t.start,t.finish),n=Jc(r,o);e.selection.setRng(n)})))},u=e=>0===e.button,f=(()=>{const e=Vi(ge.fromDom(s)),t=Vi(0);return{touchEnd:o=>{const n=ge.fromDom(o.target);if(se("td")(n)||se("th")(n)){const r=e.get(),s=t.get();be(r,n)&&o.timeStamp-s<300&&(o.preventDefault(),i(n,n))}e.set(n),t.set(o.timeStamp)}}})();e.on("dragstart",(e=>{a.clearstate()})),e.on("mousedown",(e=>{u(e)&&Em(e)&&a.mousedown(km(e))})),e.on("mouseover",(e=>{var t;void 0!==(t=e).buttons&&0==(1&t.buttons)||!Em(e)||a.mouseover(km(e))})),e.on("mouseup",(e=>{u(e)&&Em(e)&&a.mouseup(km(e))})),e.on("touchend",f.touchEnd),e.on("keyup",(t=>{const o=km(t);if(o.raw.shiftKey&&Xi(o.raw.which)){const t=e.selection.getRng(),n=ge.fromDom(t.startContainer),r=ge.fromDom(t.endContainer);c.keyup(o,n,t.startOffset,r,t.endOffset).each((e=>{m(o,e)}))}})),e.on("keydown",(o=>{const n=km(o);t.hide();const r=e.selection.getRng(),s=ge.fromDom(r.startContainer),l=ge.fromDom(r.endContainer),a=on(Zi,em)(ge.fromDom(e.selection.getStart()));c.keydown(n,s,r.startOffset,l,r.endOffset,a).each((e=>{m(n,e)})),t.show()})),e.on("NodeChange",(()=>{const t=e.selection,o=ge.fromDom(t.getStart()),r=ge.fromDom(t.getEnd());qr(It,[o,r]).fold((()=>n.clear(s)),d)}))})),e.on("PreInit",(()=>{e.serializer.addTempAttr(es.firstSelected),e.serializer.addTempAttr(es.lastSelected)})),{getSelectedCells:()=>((e,t,o,n)=>{switch(e.tag){case"none":return t();case"single":return(e=>[e.dom])(e.element);case"multiple":return(e=>O(e,(e=>e.dom)))(e.elements)}})(o.get(),u([])),clearSelectedCells:e=>n.clear(ge.fromDom(e))}},Bm=e=>{let t=[];return{bind:e=>{if(void 0===e)throw new Error("Event bind error: undefined handler");t.push(e)},unbind:e=>{t=N(t,(t=>t!==e))},trigger:(...o)=>{const n={};k(e,((e,t)=>{n[e]=o[t]})),k(t,(e=>{e(n)}))}}},zm=e=>({registry:U(e,(e=>({bind:e.bind,unbind:e.unbind}))),trigger:U(e,(e=>e.trigger))}),Am=e=>e.slice(0).sort(),Wm=(e,t)=>{const o=N(t,(t=>!T(e,t)));o.length>0&&(e=>{throw new Error("Unsupported keys for object: "+Am(e).join(", "))})(o)},Lm=e=>((e,t)=>((e,t,o)=>{if(0===t.length)throw new Error("You must specify at least one required field.");return((e,t)=>{if(!s(t))throw new Error("The required fields must be an array. Was: "+t+".");k(t,(t=>{if(!n(t))throw new Error("The value "+t+" in the "+e+" fields was not a string.")}))})("required",t),(e=>{const t=Am(e);A(t,((e,o)=>o{throw new Error("The field: "+e+" occurs more than once in the combined fields: ["+t.join(", ")+"].")}))})(t),n=>{const r=q(n);M(t,(e=>T(r,e)))||((e,t)=>{throw new Error("All required keys ("+Am(e).join(", ")+") were not specified. Specified keys were: "+Am(t).join(", ")+".")})(t,r),e(t,r);const s=N(t,(e=>!o.validate(n[e],e)));return s.length>0&&((e,t)=>{throw new Error("All values need to be of type: "+t+". Keys ("+Am(e).join(", ")+") were not.")})(s,o.label),n}})(e,t,{validate:i,label:"function"}))(Wm,e),_m=Lm(["compare","extract","mutate","sink"]),Mm=Lm(["element","start","stop","destroy"]),jm=Lm(["forceDrop","drop","move","delayDrop"]),Im=()=>{const e=(()=>{const e=zm({move:Bm(["info"])});return{onEvent:d,reset:d,events:e.registry}})(),t=(()=>{let e=y.none();const t=zm({move:Bm(["info"])});return{onEvent:(o,n)=>{n.extract(o).each((o=>{const r=((t,o)=>{const n=e.map((e=>t.compare(e,o)));return e=y.some(o),n})(n,o);r.each((e=>{t.trigger.move(e)}))}))},reset:()=>{e=y.none()},events:t.registry}})();let o=e;return{on:()=>{o.reset(),o=t},off:()=>{o.reset(),o=e},isOn:()=>o===t,onEvent:(e,t)=>{o.onEvent(e,t)},events:t.events}},Pm=e=>{const t=e.replace(/\./g,"-");return{resolve:e=>t+"-"+e}},Fm=Pm("ephox-dragster").resolve;var Hm=_m({compare:(e,t)=>cn(t.left-e.left,t.top-e.top),extract:e=>y.some(cn(e.x,e.y)),sink:(e,t)=>{const o=(e=>{const t={layerClass:Fm("blocker"),...e},o=ge.fromTag("div");return ae(o,"role","presentation"),Ct(o,{position:"fixed",left:"0px",top:"0px",width:"100%",height:"100%"}),vm(o,Fm("blocker")),vm(o,t.layerClass),{element:u(o),destroy:()=>{Me(o)}}})(t),n=Om(o.element(),"mousedown",e.forceDrop),r=Om(o.element(),"mouseup",e.drop),s=Om(o.element(),"mousemove",e.move),l=Om(o.element(),"mouseout",e.delayDrop);return Mm({element:o.element,start:e=>{ze(e,o.element())},stop:()=>{Me(o.element())},destroy:()=>{o.destroy(),r.unbind(),s.unbind(),l.unbind(),n.unbind()}})},mutate:(e,t)=>{e.mutate(t.left,t.top)}});const qm=Pm("ephox-snooker").resolve,Vm=qm("resizer-bar"),$m=qm("resizer-rows"),Um=qm("resizer-cols"),Gm=e=>{const t=nt(e.parent(),"."+Vm);k(t,Me)},Km=(e,t,o)=>{const n=e.origin();k(t,(t=>{t.each((t=>{const r=o(n,t);vm(r,Vm),ze(e.parent(),r)}))}))},Ym=(e,t,o,n,r)=>{const s=dn(o),l=t.isResizable,a=n.length>0?Sn.positions(n,o):[],c=a.length>0?((e,t)=>_(e.all,((e,o)=>t(e.element)?[o]:[])))(e,l):[];((e,t,o,n)=>{Km(e,t,((e,t)=>{const r=((e,t,o,n,r)=>{const s=ge.fromTag("div");return Ct(s,{position:"absolute",left:t+"px",top:o-3.5+"px",height:"7px",width:n+"px"}),ce(s,{"data-row":e,role:"presentation"}),s})(t.row,o.left-e.left,t.y-e.top,n);return vm(r,$m),r}))})(t,N(a,((e,t)=>R(c,(e=>t===e)))),s,Oo(o));const i=r.length>0?Rn.positions(r,o):[],m=i.length>0?((e,t)=>{const o=[];return D(e.grid.columns,(n=>{Xo(e,n).map((e=>e.element)).forall(t)&&o.push(n)})),N(o,(o=>{const n=Ko(e,(e=>e.column===o));return M(n,(e=>t(e.element)))}))})(e,l):[];((e,t,o,n)=>{Km(e,t,((e,t)=>{const r=((e,t,o,n,r)=>{const s=ge.fromTag("div");return Ct(s,{position:"absolute",left:t-3.5+"px",top:o+"px",height:r+"px",width:"7px"}),ce(s,{"data-column":e,role:"presentation"}),s})(t.col,t.x-e.left,o.top-e.top,0,n);return vm(r,Um),r}))})(t,N(i,((e,t)=>R(m,(e=>t===e)))),s,ln(o))},Jm=(e,t)=>{if(Gm(e),e.isResizable(t)){const o=Vo(t),n=tn(o),r=Zo(o);Ym(o,e,t,n,r)}},Qm=(e,t)=>{const o=nt(e.parent(),"."+Vm);k(o,t)},Xm=e=>{Qm(e,(e=>{xt(e,"display","none")}))},Zm=e=>{Qm(e,(e=>{xt(e,"display","block")}))},ed=qm("resizer-bar-dragging"),td=e=>{const t=(()=>{const e=zm({drag:Bm(["xDelta","yDelta","target"])});let t=y.none();const o=(()=>{const e=zm({drag:Bm(["xDelta","yDelta"])});return{mutate:(t,o)=>{e.trigger.drag(t,o)},events:e.registry}})();return o.events.drag.bind((o=>{t.each((t=>{e.trigger.drag(o.xDelta,o.yDelta,t)}))})),{assign:e=>{t=y.some(e)},get:()=>t,mutate:o.mutate,events:e.registry}})(),o=((e,t={})=>{var o;return((e,t,o)=>{let n=!1;const r=zm({start:Bm([]),stop:Bm([])}),s=Im(),a=()=>{m.stop(),s.isOn()&&(s.off(),r.trigger.stop())},c=((e,t)=>{let o=null;const n=()=>{l(o)||(clearTimeout(o),o=null)};return{cancel:n,throttle:(...t)=>{n(),o=setTimeout((()=>{o=null,e.apply(null,t)}),200)}}})(a);s.events.move.bind((o=>{t.mutate(e,o.info)}));const i=e=>(...t)=>{n&&e.apply(null,t)},m=t.sink(jm({forceDrop:a,drop:i(a),move:i((e=>{c.cancel(),s.onEvent(e,t)})),delayDrop:i(c.throttle)}),o);return{element:m.element,go:e=>{m.start(e),s.on(),r.trigger.start()},on:()=>{n=!0},off:()=>{n=!1},destroy:()=>{m.destroy()},events:r.registry}})(e,null!==(o=t.mode)&&void 0!==o?o:Hm,t)})(t,{});let n=y.none();const r=(e,t)=>y.from(ie(e,t));t.events.drag.bind((e=>{r(e.target,"data-row").each((t=>{const o=Bt(e.target,"top");xt(e.target,"top",o+e.yDelta+"px")})),r(e.target,"data-column").each((t=>{const o=Bt(e.target,"left");xt(e.target,"left",o+e.xDelta+"px")}))}));const s=(e,t)=>Bt(e,t)-Ot(e,"data-initial-"+t,0);o.events.stop.bind((()=>{t.get().each((t=>{n.each((o=>{r(t,"data-row").each((e=>{const n=s(t,"top");de(t,"data-initial-top"),d.trigger.adjustHeight(o,n,parseInt(e,10))})),r(t,"data-column").each((e=>{const n=s(t,"left");de(t,"data-initial-left"),d.trigger.adjustWidth(o,n,parseInt(e,10))})),Jm(e,o)}))}))}));const a=(n,r)=>{d.trigger.startAdjust(),t.assign(n),ae(n,"data-initial-"+r,Bt(n,r)),vm(n,ed),xt(n,"opacity","0.2"),o.go(e.parent())},c=Om(e.parent(),"mousedown",(e=>{var t;t=e.target,ym(t,$m)&&a(e.target,"top"),(e=>ym(e,Um))(e.target)&&a(e.target,"left")})),i=t=>be(t,e.view()),m=Om(e.view(),"mouseover",(t=>{var o;(o=t.target,it(o,"table",i).filter(Ms)).fold((()=>{Xe(t.target)&&Gm(e)}),(t=>{n=y.some(t),Jm(e,t)}))})),d=zm({adjustHeight:Bm(["table","delta","row"]),adjustWidth:Bm(["table","delta","column"]),startAdjust:Bm([])});return{destroy:()=>{c.unbind(),m.unbind(),o.destroy(),Gm(e)},refresh:t=>{Jm(e,t)},on:o.on,off:o.off,hideBars:h(Xm,e),showBars:h(Zm,e),events:d.registry}},od=(e,t,o)=>{const n=Sn,r=Rn,s=td(e),l=zm({beforeResize:Bm(["table","type"]),afterResize:Bm(["table","type"]),startDrag:Bm([])});return s.events.adjustHeight.bind((e=>{const t=e.table;l.trigger.beforeResize(t,"row");((e,t,o,n)=>{const r=Vo(e),s=((e,t,o)=>Qn(e,t,o,Pn,(e=>e.getOrThunk(At))))(r,e,n),l=O(s,((e,n)=>o===n?Math.max(t+e,At()):e)),a=Rl(r,l),c=((e,t)=>O(e.all,((e,o)=>({element:e.element,height:t[o]}))))(r,l);k(c,(e=>{Wn(e.element,e.height)})),k(a,(e=>{Wn(e.element,e.height)}));const i=B(l,((e,t)=>e+t),0);Wn(e,i)})(t,n.delta(e.delta,t),e.row,n),l.trigger.afterResize(t,"row")})),s.events.startAdjust.bind((e=>{l.trigger.startDrag()})),s.events.adjustWidth.bind((e=>{const n=e.table;l.trigger.beforeResize(n,"col");const s=r.delta(e.delta,n),a=o(n);Ol(n,s,e.column,t,a),l.trigger.afterResize(n,"col")})),{on:s.on,off:s.off,refreshBars:s.refresh,hideBars:s.hideBars,showBars:s.showBars,destroy:s.destroy,events:l.registry}},nd=e=>c(e)&&"TABLE"===e.tagName,rd="bar-",sd=e=>"false"!==ie(e,"data-mce-resize"),ld=e=>{const t=$i(),o=$i(),n=$i();let r,s;const l=t=>Xa(e,t),a=()=>Ha(e)?ys():vs();return e.on("init",(()=>{const r=((e,t)=>e.inline?((e,t,o)=>({parent:u(t),view:u(e),origin:u(cn(0,0)),isResizable:o}))(ge.fromDom(e.getBody()),(()=>{const e=ge.fromTag("div");return Ct(e,{position:"static",height:"0",width:"0",padding:"0",margin:"0",border:"0"}),ze(Ze(ge.fromDom(document)),e),e})(),t):((e,t)=>{const o=ne(e)?(e=>ge.fromDom(Ce(e).dom.documentElement))(e):e;return{parent:u(o),view:u(e),origin:u(cn(0,0)),isResizable:t}})(ge.fromDom(e.getDoc()),t))(e,sd);if(n.set(r),(e=>{const t=e.options.get("object_resizing");return T(t.split(","),"table")})(e)&&Ka(e)){const n=a(),s=od(r,n,l);s.on(),s.events.startDrag.bind((o=>{t.set(e.selection.getRng())})),s.events.beforeResize.bind((t=>{const o=t.table.dom;((e,t,o,n,r)=>{e.dispatch("ObjectResizeStart",{target:t,width:o,height:n,origin:r})})(e,o,kr(o),Er(o),rd+t.type)})),s.events.afterResize.bind((o=>{const n=o.table,r=n.dom;Dr(n),t.on((t=>{e.selection.setRng(t),e.focus()})),((e,t,o,n,r)=>{e.dispatch("ObjectResized",{target:t,width:o,height:n,origin:r})})(e,r,kr(r),Er(r),rd+o.type),e.undoManager.add()})),o.set(s)}})),e.on("ObjectResizeStart",(t=>{const o=t.target;if(nd(o)){const n=ge.fromDom(o);k(e.dom.select(".mce-clonedresizable"),(t=>{e.dom.addClass(t,"mce-"+Fa(e)+"-columns")})),!fc(n)&&Ua(e)?wc(n):!uc(n)&&$a(e)&&pc(n),gc(n)&&ht(t.origin,rd)&&pc(n),r=t.width,s=Ga(e)?"":((e,t)=>{const o=e.dom.getStyle(t,"width")||e.dom.getAttrib(t,"width");return y.from(o).filter(bt)})(e,o).getOr("")}})),e.on("ObjectResized",(t=>{const o=t.target;if(nd(o)){const n=ge.fromDom(o),c=t.origin;ht(c,"corner-")&&((t,o,n)=>{const c=pt(o,"e");if(""===s&&pc(t),n!==r&&""!==s){xt(t,"width",s);const o=a(),i=l(t),m=Ha(e)||c?(e=>xs(e).columns)(t)-1:0;Ol(t,n-r,m,o,i)}else if((e=>/^(\d+(\.\d+)?)%$/.test(e))(s)){const e=parseFloat(s.replace("%",""));xt(t,"width",n*e/r+"%")}(e=>/^(\d+(\.\d+)?)px$/.test(e))(s)&&(e=>{const t=Vo(e);Qo(t)||k(Mt(e),(e=>{const t=St(e,"width");xt(e,"width",t),de(e,"width")}))})(t)})(n,c,t.width),Dr(n),za(e,n.dom,Aa)}})),e.on("SwitchMode",(()=>{o.on((t=>{e.mode.isReadOnly()?t.hideBars():t.showBars()}))})),e.on("remove",(()=>{o.on((e=>{e.destroy()})),n.on((t=>{((e,t)=>{e.inline&&Me(t.parent())})(e,t)}))})),{refresh:e=>{o.on((t=>t.refreshBars(ge.fromDom(e))))},hide:()=>{o.on((e=>e.hideBars()))},show:()=>{o.on((e=>e.showBars()))}}},ad=e=>{(e=>{const t=e.options.register;t("table_clone_elements",{processor:"string[]"}),t("table_use_colgroups",{processor:"boolean",default:!0}),t("table_header_type",{processor:e=>{const t=T(["section","cells","sectionCells","auto"],e);return t?{value:e,valid:t}:{valid:!1,message:"Must be one of: section, cells, sectionCells or auto."}},default:"section"}),t("table_sizing_mode",{processor:"string",default:"auto"}),t("table_default_attributes",{processor:"object",default:{border:"1"}}),t("table_default_styles",{processor:"object",default:{"border-collapse":"collapse"}}),t("table_column_resizing",{processor:e=>{const t=T(["preservetable","resizetable"],e);return t?{value:e,valid:t}:{valid:!1,message:"Must be preservetable, or resizetable."}},default:"preservetable"}),t("table_resize_bars",{processor:"boolean",default:!0}),t("table_style_by_css",{processor:"boolean",default:!0})})(e);const t=ld(e),o=Nm(e,t),n=Za(e,t,o);return Mc(e,n),((e,t)=>{const o=Rr(e),n=t=>rs(Or(e)).bind((n=>It(n,o).map((o=>{const r=ts(ss(e),o,n);return t(o,r)})))).getOr("");$({mceTableRowType:()=>n(t.getTableRowType),mceTableCellType:()=>n(t.getTableCellType),mceTableColType:()=>n(t.getTableColType)},((t,o)=>e.addQueryValueHandler(o,t)))})(e,n),ls(e,n),{getSelectedCells:o.getSelectedCells,clearSelectedCells:o.clearSelectedCells}};e.add("dom",(e=>({table:ad(e)})))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/advlist/plugin.min.js b/public/libs/tinymce/plugins/advlist/plugin.min.js index 1040beb3d..a02ef61be 100644 --- a/public/libs/tinymce/plugins/advlist/plugin.min.js +++ b/public/libs/tinymce/plugins/advlist/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function f(t,e,n){t.execCommand("UL"===e?"InsertUnorderedList":"InsertOrderedList",!1,!1===n?null:{"list-style-type":n})}function i(t){return function(){return t}}function t(t){return t}function e(){return s}var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),g=tinymce.util.Tools.resolve("tinymce.util.Tools"),u=i(!1),l=i(!0),s={fold:function(t,e){return t()},isSome:u,isNone:l,getOr:t,getOrThunk:r,getOrDie:function(t){throw new Error(t||"error: getOrDie called on none.")},getOrNull:i(null),getOrUndefined:i(void 0),or:t,orThunk:r,map:e,each:function(){},bind:e,exists:u,forall:l,filter:function(){return s},toArray:function(){return[]},toString:i("none()")};function r(t){return t()}function d(t){return t&&/^(TH|TD)$/.test(t.nodeName)}function m(c,a){return function(s){function t(t){var e,n,r,o,i,u,l;s.setActive((e=c,r=a,i=-1!==(o=function(t,e){for(var n=0;n{const s="UL"===e?"InsertUnorderedList":"InsertOrderedList";t.execCommand(s,!1,!1===r?null:{"list-style-type":r})},r=t=>e=>e.options.get(t),s=r("advlist_number_styles"),n=r("advlist_bullet_styles");var i=tinymce.util.Tools.resolve("tinymce.util.Tools");class l{constructor(t,e){this.tag=t,this.value=e}static some(t){return new l(!0,t)}static none(){return l.singletonNone}fold(t,e){return this.tag?e(this.value):t()}isSome(){return this.tag}isNone(){return!this.tag}map(t){return this.tag?l.some(t(this.value)):l.none()}bind(t){return this.tag?t(this.value):l.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:l.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 null==t?l.none():l.some(t)}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()"}}l.singletonNone=new l(!1);const o=t=>t&&/^(TH|TD)$/.test(t.nodeName),a=(t,e)=>r=>{const s=s=>{r.setActive(((t,e,r)=>{const s=((t,e)=>{for(let r=0;re=>e&&/^(OL|UL|DL)$/.test(e.nodeName)&&((t,e)=>t.dom.isChildOf(e,t.getBody()))(t,e))(t));return l.length>0&&l[0].nodeName===r})(t,s,e))};return t.on("NodeChange",s),()=>t.off("NodeChange",s)},u=(t,r,s,n,o,u)=>{u.length>1?((t,r,s,n,o,u)=>{t.ui.registry.addSplitButton(r,{tooltip:s,icon:"OL"===o?"ordered-list":"unordered-list",presets:"listpreview",columns:3,fetch:t=>{t(i.map(u,(t=>{const e="OL"===o?"num":"bull",r="disc"===t||"decimal"===t?"default":t,s="default"===t?"":t,n=(t=>t.replace(/\-/g," ").replace(/\b\w/g,(t=>t.toUpperCase())))(t);return{type:"choiceitem",value:s,icon:"list-"+e+"-"+r,text:n}})))},onAction:()=>t.execCommand(n),onItemAction:(r,s)=>{e(t,o,s)},select:e=>{const r=(t=>{const e=t.dom.getParent(t.selection.getNode(),"ol,ul"),r=t.dom.getStyle(e,"listStyleType");return l.from(r)})(t);return r.map((t=>e===t)).getOr(!1)},onSetup:a(t,o)})})(t,r,s,n,o,u):((t,e,r,s,n,i)=>{t.ui.registry.addToggleButton(e,{active:!1,tooltip:r,icon:"OL"===n?"ordered-list":"unordered-list",onSetup:a(t,n),onAction:()=>t.execCommand(s)})})(t,r,s,n,o)};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=>{u(t,"numlist","Numbered list","InsertOrderedList","OL",s(t)),u(t,"bullist","Bullet list","InsertUnorderedList","UL",n(t))})(t),(t=>{t.addCommand("ApplyUnorderedListStyle",((r,s)=>{e(t,"UL",s["list-style-type"])})),t.addCommand("ApplyOrderedListStyle",((r,s)=>{e(t,"OL",s["list-style-type"])}))})(t)):console.error("Please use the Lists plugin together with the Advanced List plugin.")}))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/anchor/plugin.min.js b/public/libs/tinymce/plugins/anchor/plugin.min.js index 1b5463870..7bf78ba98 100644 --- a/public/libs/tinymce/plugins/anchor/plugin.min.js +++ b/public/libs/tinymce/plugins/anchor/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function a(e){return e.getAttribute("id")||e.getAttribute("name")||""}function c(e){return e&&"a"===e.nodeName.toLowerCase()&&!e.getAttribute("href")&&""!==a(e)}function d(e){return e.dom.getParent(e.selection.getStart(),l)}function r(e,t){var o,a,n,r,i,l=d(e);l?(n=e,r=t,(i=l).removeAttribute("name"),i.id=r,n.addVisual(),n.undoManager.add()):(a=t,(o=e).undoManager.transact(function(){var e,n;o.getParam("allow_html_in_named_anchor",!1,"boolean")||o.selection.collapse(!0),o.selection.isCollapsed()?o.insertContent(o.dom.createHTML("a",{id:a})):(n=(e=o).dom,u(n).walk(e.selection.getRng(),function(e){s.each(e,function(e){var t;c(t=e)&&!t.firstChild&&n.remove(e,!1)})}),o.formatter.remove("namedAnchor",null,null,!0),o.formatter.apply("namedAnchor",{value:a}),o.addVisual())})),e.focus()}function i(r){return function(e){for(var t,n=0;ne.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=>e&&"a"===e.nodeName.toLowerCase())(e)&&!e.getAttribute("href")&&""!==i(e),s=e=>e.dom.getParent(e.selection.getStart(),a),c=(e,a)=>{const r=s(e);r?((e,t,n)=>{n.removeAttribute("name"),n.id=t,e.addVisual(),e.undoManager.add()})(e,a,r):((e,a)=>{e.undoManager.transact((()=>{o(e)||e.selection.collapse(!0),e.selection.isCollapsed()?e.insertContent(e.dom.createHTML("a",{id:a})):((e=>{const o=e.dom;t(o).walk(e.selection.getRng(),(e=>{n.each(e,(e=>{var t;l(t=e)&&!t.firstChild&&o.remove(e,!1)}))}))})(e),e.formatter.remove("namedAnchor",null,null,!0),e.formatter.apply("namedAnchor",{value:a}),e.addVisual())}))})(e,a),e.focus()},d=e=>(e=>e&&r(e.attr("href"))&&!r(e.attr("id")||e.attr("name")))(e)&&!e.firstChild,m=e=>t=>{for(let n=0;n{(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)?(c(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=>{e.ui.registry.addToggleButton("anchor",{icon:"bookmark",tooltip:"Anchor",onAction:()=>e.execCommand("mceAnchor"),onSetup:t=>e.selection.selectorChangedWithUnbind("a:not([href])",t.setActive).unbind}),e.ui.registry.addMenuItem("anchor",{icon:"bookmark",text:"Anchor...",onAction:()=>e.execCommand("mceAnchor")})})(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,n)=>l(e)})})(e)}))}))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/autolink/plugin.min.js b/public/libs/tinymce/plugins/autolink/plugin.min.js index ea4cfab6c..f751637f7 100644 --- a/public/libs/tinymce/plugins/autolink/plugin.min.js +++ b/public/libs/tinymce/plugins/autolink/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function k(e){return/^[(\[{ \u00a0]$/.test(e)}function w(e){return 3===e.nodeType}function i(e){return 1===e.nodeType}function o(e,t){var n;return t<0&&(t=0),!w(e)||(n=e.data.length)=(h="www.").length&&g.substr(0,0+h.length)===h?c=m+"://"+c:-1===c.indexOf("@")||/^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(c)||(c="mailto:"+c),o=e.selection.getBookmark(),e.selection.setRng(d),e.execCommand("createlink",!1,c),!1!==s&&e.dom.setAttrib(e.selection.getNode(),"target",s),e.selection.moveToBookmark(o),e.nodeChanged())}}var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=tinymce.util.Tools.resolve("tinymce.Env"),A=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");e.add("autolink",function(e){var t,n;(t=e).on("keydown",function(e){if(13===e.keyCode)return r(t,-1)}),a.browser.isIE()?t.on("focus",function(){if(!n){n=!0;try{t.execCommand("AutoUrlDetect",!1,!0)}catch(e){}}}):(t.on("keypress",function(e){if(41===e.keyCode||93===e.keyCode||125===e.keyCode)return r(t,-1)}),t.on("keyup",function(e){if(32===e.keyCode)return r(t,0)}))})}(); \ No newline at end of file +!function(){"use strict";var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const e=t=>e=>e.options.get(t),n=e("autolink_pattern"),o=e("link_default_target"),r=e("link_default_protocol"),i=("string",t=>"string"===(t=>{const e=typeof t;return null===t?"null":"object"===e&&Array.isArray(t)?"array":"object"===e&&(n=o=t,(r=String).prototype.isPrototypeOf(n)||(null===(i=o.constructor)||void 0===i?void 0:i.name)===r.name)?"string":e;var n,o,r,i})(t));const s=t=>/^[(\[{ \u00a0]$/.test(t),a=t=>3===t.nodeType,l=t=>1===t.nodeType,d=(t,e)=>{if(e<0&&(e=0),a(t)){const n=t.data.length;e>n&&(e=n)}return e},f=(t,e,n)=>{!l(e)||e.hasChildNodes()?t.setStart(e,d(e,n)):t.setStartBefore(e)},g=(t,e,n)=>{!l(e)||e.hasChildNodes()?t.setEnd(e,d(e,n)):t.setEndAfter(e)},c=(t,e)=>{let l,d,c,u,h,p,k;const C=n(t),y=o(t);if(null!==t.dom.getParent(t.selection.getNode(),"a[href]"))return;const m=t.selection.getRng().cloneRange();if(m.startOffset<5){if(h=m.endContainer.previousSibling,!h){if(!m.endContainer.firstChild||!m.endContainer.firstChild.nextSibling)return;h=m.endContainer.firstChild.nextSibling}if(p=h.length,f(m,h,p),g(m,h,p),m.endOffset<5)return;l=m.endOffset,d=h}else{if(d=m.endContainer,!a(d)&&d.firstChild){for(;!a(d)&&d.firstChild;)d=d.firstChild;a(d)&&(f(m,d,0),g(m,d,d.nodeValue.length))}l=1===m.endOffset?2:m.endOffset-1-e}const w=l;do{f(m,d,l>=2?l-2:0),g(m,d,l>=1?l-1:0),l-=1,k=m.toString()}while(!s(k)&&l-2>=0);var A;s(m.toString())?(f(m,d,l),g(m,d,w),l+=1):0===m.startOffset?(f(m,d,0),g(m,d,w)):(f(m,d,l),g(m,d,w)),u=m.toString(),A=u.charAt(u.length-1),/[?!,.;:]/.test(A)&&g(m,d,w-1),u=m.toString().trim();const S=u.match(C),_=r(t);if(S){let e=S[0];O="www.",(v=e).length>=O.length&&v.substr(0,0+O.length)===O?e=_+"://"+e:((t,e)=>-1!==t.indexOf("@"))(e)&&!(t=>/^([A-Za-z][A-Za-z\d.+-]*:\/\/)|mailto:/.test(t))(e)&&(e="mailto:"+e),c=t.selection.getBookmark(),t.selection.setRng(m),t.getDoc().execCommand("createlink",!1,e),i(y)&&t.dom.setAttrib(t.selection.getNode(),"target",y),t.selection.moveToBookmark(c),t.nodeChanged()}var v,O};t.add("autolink",(t=>{(t=>{const e=t.options.register;e("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")}),e("link_default_target",{processor:"string"}),e("link_default_protocol",{processor:"string",default:"https"})})(t),(t=>{t.on("keydown",(e=>{if(13===e.keyCode)return(t=>c(t,-1))(t)})),t.on("keypress",(e=>{if(41===e.keyCode||93===e.keyCode||125===e.keyCode)return(t=>c(t,-1))(t)})),t.on("keyup",(e=>{if(32===e.keyCode)return(t=>c(t,0))(t)}))})(t)}))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/autoresize/plugin.min.js b/public/libs/tinymce/plugins/autoresize/plugin.min.js index 74710339c..e194cb179 100644 --- a/public/libs/tinymce/plugins/autoresize/plugin.min.js +++ b/public/libs/tinymce/plugins/autoresize/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function y(e){return e.getParam("min_height",e.getElement().offsetHeight,"number")}function p(e,t){var n=e.getBody();n&&(n.style.overflowY=t?"":"hidden",t||(n.scrollTop=0))}function v(e,t,n,i){var o=parseInt(e.getStyle(t,n,i),10);return isNaN(o)?0:o}var l=Object.hasOwnProperty,e=tinymce.util.Tools.resolve("tinymce.PluginManager"),b=tinymce.util.Tools.resolve("tinymce.Env"),r=tinymce.util.Tools.resolve("tinymce.util.Delay"),u=function(e,t,n,i,o){r.setEditorTimeout(e,function(){C(e,t),n--?u(e,t,n,i,o):o&&o()},i)},C=function(e,t,n){var i,o,r,s,a,l,u,g,c,m,f,d=e.dom,h=e.getDoc();h&&(e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen()?p(e,!0):(i=h.documentElement,o=e.getParam("autoresize_bottom_margin",50,"number"),r=y(e),s=v(d,i,"margin-top",!0),a=v(d,i,"margin-bottom",!0),(l=(l=i.offsetHeight+s+a+o)<0?0:l)+(u=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight)>y(e)&&(r=l+u),(g=e.getParam("max_height",0,"number"))&&gt=>t.options.get(e),n=o("min_height"),s=o("max_height"),i=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))},a=(e,t,o,n)=>{const s=parseInt(e.getStyle(t,o,n),10);return isNaN(s)?0:s},g=(e,o,i)=>{var c;const u=e.dom,d=e.getDoc();if(!d)return;if((e=>e.plugins.fullscreen&&e.plugins.fullscreen.isFullscreen())(e))return void l(e,!0);const f=d.documentElement,m=r(e),p=null!==(c=n(e))&&void 0!==c?c:e.getElement().offsetHeight;let h=p;const y=a(u,f,"margin-top",!0),v=a(u,f,"margin-bottom",!0);let C=f.offsetHeight+y+v+m;C<0&&(C=0);const S=e.getContainer().offsetHeight-e.getContentAreaContainer().offsetHeight;C+S>p&&(h=C+S);const z=s(e);if(z&&h>z?(h=z,l(e,!0)):l(e,!1),h!==o.get()){const n=h-o.get();if(u.setStyle(e.getContainer(),"height",h+"px"),o.set(h),(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})(i)&&e.selection.scrollIntoView(),(t.browser.isSafari()||t.browser.isChromium())&&n<0&&g(e,o,i)}};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 t=(e=>{let t=0;return{get:()=>t,set:e=>{t=e}}})();((e,t)=>{e.addCommand("mceAutoResize",(()=>{g(e,t)}))})(e,t),((e,t)=>{e.on("init",(()=>{const t=i(e),o=e.dom;o.setStyles(e.getDoc().documentElement,{height:"auto"}),o.setStyles(e.getBody(),{paddingLeft:t,paddingRight:t,"min-height":0})})),e.on("NodeChange SetContent keyup FullscreenStateChanged ResizeContent",(o=>{g(e,t,o)}))})(e,t)}}))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/autosave/plugin.min.js b/public/libs/tinymce/plugins/autosave/plugin.min.js index 217d938cb..a3d2884c3 100644 --- a/public/libs/tinymce/plugins/autosave/plugin.min.js +++ b/public/libs/tinymce/plugins/autosave/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function o(t,e){var r=t||e,n=/^(\d+)([ms]?)$/.exec(""+r);return(n[2]?{s:1e3,m:6e4}[n[2]]:1)*parseInt(r,10)}function n(t){var e=document.location;return t.getParam("autosave_prefix","tinymce-autosave-{path}{query}{hash}-{id}-").replace(/{path}/g,e.pathname).replace(/{query}/g,e.search).replace(/{hash}/g,e.hash).replace(/{id}/g,t.id)}function i(t,e){if(a(e))return t.dom.isEmpty(t.getBody());var r=d.trim(e);if(""===r)return!0;var n=(new DOMParser).parseFromString(r,"text/html");return t.dom.isEmpty(n)}function u(t){var e=parseInt(v.getItem(n(t)+"time"),10)||0;return!((new Date).getTime()-e>o(t.getParam("autosave_retention"),"20m")&&(g(t,!1),1))}function s(t){var e=n(t);!i(t)&&t.isDirty()&&(v.setItem(e+"draft",t.getContent({format:"raw",no_events:!0})),v.setItem(e+"time",(new Date).getTime().toString()),t.fire("StoreDraft"))}function f(t){var e=n(t);u(t)&&(t.setContent(v.getItem(e+"draft"),{format:"raw"}),t.fire("RestoreDraft"))}function c(t){t.undoManager.transact(function(){f(t),g(t)}),t.focus()}function m(r){return function(t){function e(){return t.setDisabled(!u(r))}return t.setDisabled(!u(r)),r.on("StoreDraft RestoreDraft RemoveDraft",e),function(){return r.off("StoreDraft RestoreDraft RemoveDraft",e)}}}var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=function(t){return void 0===t},l=tinymce.util.Tools.resolve("tinymce.util.Delay"),v=tinymce.util.Tools.resolve("tinymce.util.LocalStorage"),d=tinymce.util.Tools.resolve("tinymce.util.Tools"),g=function(t,e){var r=n(t);v.removeItem(r+"draft"),v.removeItem(r+"time"),!1!==e&&t.fire("RemoveDraft")},y=tinymce.util.Tools.resolve("tinymce.EditorManager");t.add("autosave",function(t){var e,r,n,a;return t.editorManager.on("BeforeUnload",function(t){var e;d.each(y.get(),function(t){t.plugins.autosave&&t.plugins.autosave.storeDraft(),!e&&t.isDirty()&&t.getParam("autosave_ask_before_unload",!0)&&(e=t.translate("You have unsaved changes are you sure you want to navigate away?"))}),e&&(t.preventDefault(),t.returnValue=e)}),n=e=t,a=o(n.getParam("autosave_interval"),"30s"),l.setEditorInterval(n,function(){s(n)},a),e.ui.registry.addButton("restoredraft",{tooltip:"Restore last draft",icon:"restore-draft",onAction:function(){c(e)},onSetup:m(e)}),e.ui.registry.addMenuItem("restoredraft",{text:"Restore last draft",icon:"restore-draft",onAction:function(){c(e)},onSetup:m(e)}),t.on("init",function(){t.getParam("autosave_restore_when_empty",!1)&&t.dom.isEmpty(t.getBody())&&f(t)}),r=t,{hasDraft:function(){return u(r)},storeDraft:function(){return s(r)},restoreDraft:function(){return f(r)},removeDraft:function(t){return g(r,t)},isEmpty:function(t){return i(r,t)}}})}(); \ No newline at end of file +!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[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"),m=i("autosave_retention"),d=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)},f=(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)}}},v=t=>{const e=parseInt(a.getItem(d(t)+"time"),10)||0;return!((new Date).getTime()-e>m(t)&&(p(t,!1),1))},p=(t,e)=>{const r=d(t);a.removeItem(r+"draft"),a.removeItem(r+"time"),!1!==e&&(t=>{t.dispatch("RemoveDraft")})(t)},g=t=>{const e=d(t);!f(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=>{const e=d(t);v(t)&&(t.setContent(a.getItem(e+"draft"),{format:"raw"}),(t=>{t.dispatch("RestoreDraft")})(t))},D=t=>{t.undoManager.transact((()=>{y(t),p(t)})),t.focus()};var h=tinymce.util.Tools.resolve("tinymce.EditorManager");const _=t=>e=>{e.setEnabled(v(t));const r=()=>e.setEnabled(v(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(h.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),t.ui.registry.addButton("restoredraft",{tooltip:"Restore last draft",icon:"restore-draft",onAction:()=>{D(t)},onSetup:_(t)}),t.ui.registry.addMenuItem("restoredraft",{text:"Restore last draft",icon:"restore-draft",onAction:()=>{D(t)},onSetup:_(t)})})(t),t.on("init",(()=>{l(t)&&t.dom.isEmpty(t.getBody())&&y(t)})),(t=>({hasDraft:()=>v(t),storeDraft:()=>g(t),restoreDraft:()=>y(t),removeDraft:e=>p(t,e),isEmpty:e=>f(t,e)}))(t))))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/bbcode/plugin.min.js b/public/libs/tinymce/plugins/bbcode/plugin.min.js deleted file mode 100644 index f461bf555..000000000 --- a/public/libs/tinymce/plugins/bbcode/plugin.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) - */ -!function(){"use strict";function i(t){function o(o,e){t=t.replace(o,e)}return t=n.trim(t),o(/\n/gi,"
"),o(/\[b\]/gi,""),o(/\[\/b\]/gi,""),o(/\[i\]/gi,""),o(/\[\/i\]/gi,""),o(/\[u\]/gi,""),o(/\[\/u\]/gi,""),o(/\[url=([^\]]+)\](.*?)\[\/url\]/gi,'
$2'),o(/\[url\](.*?)\[\/url\]/gi,'$1'),o(/\[img\](.*?)\[\/img\]/gi,''),o(/\[color=(.*?)\](.*?)\[\/color\]/gi,'$2'),o(/\[code\](.*?)\[\/code\]/gi,'$1 '),o(/\[quote.*?\](.*?)\[\/quote\]/gi,'$1 '),t}var o=tinymce.util.Tools.resolve("tinymce.PluginManager"),n=tinymce.util.Tools.resolve("tinymce.util.Tools");o.add("bbcode",function(o){o.on("BeforeSetContent",function(o){o.content=i(o.content)}),o.on("PostProcess",function(o){function e(o,e){t=t.replace(o,e)}var t;o.set&&(o.content=i(o.content)),o.get&&(o.content=(t=o.content,t=n.trim(t),e(/(.*?)<\/a>/gi,"[url=$1]$2[/url]"),e(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),e(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),e(/(.*?)<\/font>/gi,"[code][color=$1]$2[/color][/code]"),e(/(.*?)<\/font>/gi,"[quote][color=$1]$2[/color][/quote]"),e(/(.*?)<\/span>/gi,"[color=$1]$2[/color]"),e(/(.*?)<\/font>/gi,"[color=$1]$2[/color]"),e(/(.*?)<\/span>/gi,"[size=$1]$2[/size]"),e(/(.*?)<\/font>/gi,"$1"),e(//gi,"[img]$1[/img]"),e(/(.*?)<\/span>/gi,"[code]$1[/code]"),e(/(.*?)<\/span>/gi,"[quote]$1[/quote]"),e(/(.*?)<\/strong>/gi,"[code][b]$1[/b][/code]"),e(/(.*?)<\/strong>/gi,"[quote][b]$1[/b][/quote]"),e(/(.*?)<\/em>/gi,"[code][i]$1[/i][/code]"),e(/(.*?)<\/em>/gi,"[quote][i]$1[/i][/quote]"),e(/(.*?)<\/u>/gi,"[code][u]$1[/u][/code]"),e(/(.*?)<\/u>/gi,"[quote][u]$1[/u][/quote]"),e(/<\/(strong|b)>/gi,"[/b]"),e(/<(strong|b)>/gi,"[b]"),e(/<\/(em|i)>/gi,"[/i]"),e(/<(em|i)>/gi,"[i]"),e(/<\/u>/gi,"[/u]"),e(/(.*?)<\/span>/gi,"[u]$1[/u]"),e(//gi,"[u]"),e(/]*>/gi,"[quote]"),e(/<\/blockquote>/gi,"[/quote]"),e(/
/gi,"\n"),e(//gi,"\n"),e(/
/gi,"\n"),e(/

/gi,""),e(/<\/p>/gi,"\n"),e(/ |\u00a0/gi," "),e(/"/gi,'"'),e(/</gi,"<"),e(/>/gi,">"),e(/&/gi,"&"),t))})})}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/charmap/plugin.min.js b/public/libs/tinymce/plugins/charmap/plugin.min.js index e72c9ab3c..d989de6ba 100644 --- a/public/libs/tinymce/plugins/charmap/plugin.min.js +++ b/public/libs/tinymce/plugins/charmap/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function l(e,r){var n=e.fire("insertCustomChar",{chr:r}).chr;e.execCommand("mceInsertContent",!1,n)}function i(e){return function(){return e}}function e(e){return e}function r(){return c}var t,g,n=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=function(e){return n=typeof(r=e),(null===r?"null":"object"==n&&(Array.prototype.isPrototypeOf(r)||r.constructor&&"Array"===r.constructor.name)?"array":"object"==n&&(String.prototype.isPrototypeOf(r)||r.constructor&&"String"===r.constructor.name)?"string":n)===t;var r,n},m=i(!(t="array")),o=i(!(g=null)),c={fold:function(e,r){return e()},isSome:m,isNone:o,getOr:e,getOrThunk:u,getOrDie:function(e){throw new Error(e||"error: getOrDie called on none.")},getOrNull:i(null),getOrUndefined:i(void 0),or:e,orThunk:u,map:r,each:function(){},bind:r,exists:m,forall:o,filter:function(){return c},toArray:function(){return[]},toString:i("none()")};function u(e){return e()}function f(e,r){for(var n=e.length,t=new Array(n),a=0;a>>0===o))throw RangeError("Invalid code point: "+o);16383<=(o<=65535?n.push(o):(o-=65536,n.push(55296+(o>>10),o%1024+56320)))&&(t+=String.fromCharCode.apply(null,n),n.length=0)}return t+String.fromCharCode.apply(null,n)}function v(e,r){var c=[],u=r.toLowerCase();return function(e){for(var r,n,t,a,i=0,o=e.length;i{const a=((e,t)=>e.dispatch("insertCustomChar",{chr:t}))(e,t).chr;e.execCommand("mceInsertContent",!1,a)},a=("array",e=>"array"===(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(a=r=e,(n=String).prototype.isPrototypeOf(a)||(null===(i=r.constructor)||void 0===i?void 0:i.name)===n.name)?"string":t;var a,r,n,i})(e));const r=(null,e=>null===e);const n=e=>"function"==typeof e,i=(!1,()=>false);class o{constructor(e,t){this.tag=e,this.value=t}static some(e){return new o(!0,e)}static none(){return o.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?o.some(e(this.value)):o.none()}bind(e){return this.tag?e(this.value):o.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:o.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return null==e?o.none():o.some(e)}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}o.singletonNone=new o(!1);const s=Array.prototype.push,l=(e,t)=>{const a=e.length,r=new Array(a);for(let n=0;nt=>t.options.get(e),g=u("charmap"),h=u("charmap_append"),m=c.isArray,p="User Defined",d=e=>{return m(e)?(t=e,c.grep(t,(e=>m(e)&&2===e.length))):"function"==typeof e?e():[];var t},f=e=>{const t=((e,t)=>{const a=g(e);a&&(t=[{name:p,characters:d(a)}]);const r=h(e);if(r){const e=c.grep(t,(e=>e.name===p));return e.length?(e[0].characters=[].concat(e[0].characters).concat(d(r)),t):t.concat({name:p,characters:d(r)})}return t})(e,[{name:"Currency",characters:[[36,"dollar sign"],[162,"cent sign"],[8364,"euro sign"],[163,"pound sign"],[165,"yen sign"],[164,"currency sign"],[8352,"euro-currency sign"],[8353,"colon sign"],[8354,"cruzeiro sign"],[8355,"french franc sign"],[8356,"lira sign"],[8357,"mill sign"],[8358,"naira sign"],[8359,"peseta sign"],[8360,"rupee sign"],[8361,"won sign"],[8362,"new sheqel sign"],[8363,"dong sign"],[8365,"kip sign"],[8366,"tugrik sign"],[8367,"drachma sign"],[8368,"german penny symbol"],[8369,"peso sign"],[8370,"guarani sign"],[8371,"austral sign"],[8372,"hryvnia sign"],[8373,"cedi sign"],[8374,"livre tournois sign"],[8375,"spesmilo sign"],[8376,"tenge sign"],[8377,"indian rupee sign"],[8378,"turkish lira sign"],[8379,"nordic mark sign"],[8380,"manat sign"],[8381,"ruble sign"],[20870,"yen character"],[20803,"yuan character"],[22291,"yuan character, in hong kong and taiwan"],[22278,"yen/yuan character variant one"]]},{name:"Text",characters:[[169,"copyright sign"],[174,"registered sign"],[8482,"trade mark sign"],[8240,"per mille sign"],[181,"micro sign"],[183,"middle dot"],[8226,"bullet"],[8230,"three dot leader"],[8242,"minutes / feet"],[8243,"seconds / inches"],[167,"section sign"],[182,"paragraph sign"],[223,"sharp s / ess-zed"]]},{name:"Quotations",characters:[[8249,"single left-pointing angle quotation mark"],[8250,"single right-pointing angle quotation mark"],[171,"left pointing guillemet"],[187,"right pointing guillemet"],[8216,"left single quotation mark"],[8217,"right single quotation mark"],[8220,"left double quotation mark"],[8221,"right double quotation mark"],[8218,"single low-9 quotation mark"],[8222,"double low-9 quotation mark"],[60,"less-than sign"],[62,"greater-than sign"],[8804,"less-than or equal to"],[8805,"greater-than or equal to"],[8211,"en dash"],[8212,"em dash"],[175,"macron"],[8254,"overline"],[164,"currency sign"],[166,"broken bar"],[168,"diaeresis"],[161,"inverted exclamation mark"],[191,"turned question mark"],[710,"circumflex accent"],[732,"small tilde"],[176,"degree sign"],[8722,"minus sign"],[177,"plus-minus sign"],[247,"division sign"],[8260,"fraction slash"],[215,"multiplication sign"],[185,"superscript one"],[178,"superscript two"],[179,"superscript three"],[188,"fraction one quarter"],[189,"fraction one half"],[190,"fraction three quarters"]]},{name:"Mathematical",characters:[[402,"function / florin"],[8747,"integral"],[8721,"n-ary sumation"],[8734,"infinity"],[8730,"square root"],[8764,"similar to"],[8773,"approximately equal to"],[8776,"almost equal to"],[8800,"not equal to"],[8801,"identical to"],[8712,"element of"],[8713,"not an element of"],[8715,"contains as member"],[8719,"n-ary product"],[8743,"logical and"],[8744,"logical or"],[172,"not sign"],[8745,"intersection"],[8746,"union"],[8706,"partial differential"],[8704,"for all"],[8707,"there exists"],[8709,"diameter"],[8711,"backward difference"],[8727,"asterisk operator"],[8733,"proportional to"],[8736,"angle"]]},{name:"Extended Latin",characters:[[192,"A - grave"],[193,"A - acute"],[194,"A - circumflex"],[195,"A - tilde"],[196,"A - diaeresis"],[197,"A - ring above"],[256,"A - macron"],[198,"ligature AE"],[199,"C - cedilla"],[200,"E - grave"],[201,"E - acute"],[202,"E - circumflex"],[203,"E - diaeresis"],[274,"E - macron"],[204,"I - grave"],[205,"I - acute"],[206,"I - circumflex"],[207,"I - diaeresis"],[298,"I - macron"],[208,"ETH"],[209,"N - tilde"],[210,"O - grave"],[211,"O - acute"],[212,"O - circumflex"],[213,"O - tilde"],[214,"O - diaeresis"],[216,"O - slash"],[332,"O - macron"],[338,"ligature OE"],[352,"S - caron"],[217,"U - grave"],[218,"U - acute"],[219,"U - circumflex"],[220,"U - diaeresis"],[362,"U - macron"],[221,"Y - acute"],[376,"Y - diaeresis"],[562,"Y - macron"],[222,"THORN"],[224,"a - grave"],[225,"a - acute"],[226,"a - circumflex"],[227,"a - tilde"],[228,"a - diaeresis"],[229,"a - ring above"],[257,"a - macron"],[230,"ligature ae"],[231,"c - cedilla"],[232,"e - grave"],[233,"e - acute"],[234,"e - circumflex"],[235,"e - diaeresis"],[275,"e - macron"],[236,"i - grave"],[237,"i - acute"],[238,"i - circumflex"],[239,"i - diaeresis"],[299,"i - macron"],[240,"eth"],[241,"n - tilde"],[242,"o - grave"],[243,"o - acute"],[244,"o - circumflex"],[245,"o - tilde"],[246,"o - diaeresis"],[248,"o slash"],[333,"o macron"],[339,"ligature oe"],[353,"s - caron"],[249,"u - grave"],[250,"u - acute"],[251,"u - circumflex"],[252,"u - diaeresis"],[363,"u - macron"],[253,"y - acute"],[254,"thorn"],[255,"y - diaeresis"],[563,"y - macron"],[913,"Alpha"],[914,"Beta"],[915,"Gamma"],[916,"Delta"],[917,"Epsilon"],[918,"Zeta"],[919,"Eta"],[920,"Theta"],[921,"Iota"],[922,"Kappa"],[923,"Lambda"],[924,"Mu"],[925,"Nu"],[926,"Xi"],[927,"Omicron"],[928,"Pi"],[929,"Rho"],[931,"Sigma"],[932,"Tau"],[933,"Upsilon"],[934,"Phi"],[935,"Chi"],[936,"Psi"],[937,"Omega"],[945,"alpha"],[946,"beta"],[947,"gamma"],[948,"delta"],[949,"epsilon"],[950,"zeta"],[951,"eta"],[952,"theta"],[953,"iota"],[954,"kappa"],[955,"lambda"],[956,"mu"],[957,"nu"],[958,"xi"],[959,"omicron"],[960,"pi"],[961,"rho"],[962,"final sigma"],[963,"sigma"],[964,"tau"],[965,"upsilon"],[966,"phi"],[967,"chi"],[968,"psi"],[969,"omega"]]},{name:"Symbols",characters:[[8501,"alef symbol"],[982,"pi symbol"],[8476,"real part symbol"],[978,"upsilon - hook symbol"],[8472,"Weierstrass p"],[8465,"imaginary part"]]},{name:"Arrows",characters:[[8592,"leftwards arrow"],[8593,"upwards arrow"],[8594,"rightwards arrow"],[8595,"downwards arrow"],[8596,"left right arrow"],[8629,"carriage return"],[8656,"leftwards double arrow"],[8657,"upwards double arrow"],[8658,"rightwards double arrow"],[8659,"downwards double arrow"],[8660,"left right double arrow"],[8756,"therefore"],[8834,"subset of"],[8835,"superset of"],[8836,"not a subset of"],[8838,"subset of or equal to"],[8839,"superset of or equal to"],[8853,"circled plus"],[8855,"circled times"],[8869,"perpendicular"],[8901,"dot operator"],[8968,"left ceiling"],[8969,"right ceiling"],[8970,"left floor"],[8971,"right floor"],[9001,"left-pointing angle bracket"],[9002,"right-pointing angle bracket"],[9674,"lozenge"],[9824,"black spade suit"],[9827,"black club suit"],[9829,"black heart suit"],[9830,"black diamond suit"],[8194,"en space"],[8195,"em space"],[8201,"thin space"],[8204,"zero width non-joiner"],[8205,"zero width joiner"],[8206,"left-to-right mark"],[8207,"right-to-left mark"]]}]);return t.length>1?[{name:"All",characters:(r=t,n=e=>e.characters,(e=>{const t=[];for(let r=0,n=e.length;r{let t=e;return{get:()=>t,set:e=>{t=e}}},w=(e,t)=>-1!==e.indexOf(t),b=String.fromCodePoint,v=(e,t)=>{const a=[],r=t.toLowerCase();return((e,t)=>{for(let t=0,i=e.length;t!!w(b(e).toLowerCase(),a)||w(t.toLowerCase(),a)||w(t.toLowerCase().replace(/\s+/g,""),a))((n=e[t])[0],n[1],r)&&a.push(n);var n})(e.characters),l(a,(e=>({text:e[1],value:b(e[0]),icon:b(e[0])})))},k="pattern",C=(e,a)=>{const n=()=>[{label:"Search",type:"input",name:k},{type:"collection",name:"results"}],s=1===a.length?y(p):y("All"),c=((e,t)=>{let a=null;const n=()=>{r(a)||(clearTimeout(a),a=null)};return{cancel:n,throttle:(...t)=>{n(),a=setTimeout((()=>{a=null,e.apply(null,t)}),40)}}})((e=>{const t=e.getData().pattern;((e,t)=>{var r,n;(r=a,n=e=>e.name===s.get(),((e,t,a)=>{for(let r=0,n=e.length;r{const r=v(a,t);e.setData({results:r})}))})(e,t)})),u={title:"Special Character",size:"normal",body:1===a.length?{type:"panel",items:n()}:{type:"tabpanel",tabs:l(a,(e=>({title:e.name,name:e.name,items:n()})))},buttons:[{type:"cancel",name:"close",text:"Close",primary:!0}],initialData:{pattern:"",results:v(a[0],"")},onAction:(a,r)=>{"results"===r.name&&(t(e,r.value),a.close())},onTabChange:(e,t)=>{s.set(t.newTabName),c.throttle(e)},onChange:(e,t)=>{t.name===k&&c.throttle(e)}};e.windowManager.open(u).focus(k)};e.add("charmap",(e=>{(e=>{const t=e.options.register,r=e=>n(e)||a(e);t("charmap",{processor:r}),t("charmap_append",{processor:r})})(e);const r=f(e);return((e,t)=>{e.addCommand("mceShowCharmap",(()=>{C(e,t)}))})(e,r),(e=>{e.ui.registry.addButton("charmap",{icon:"insert-character",tooltip:"Special character",onAction:()=>e.execCommand("mceShowCharmap")}),e.ui.registry.addMenuItem("charmap",{icon:"insert-character",text:"Special character...",onAction:()=>e.execCommand("mceShowCharmap")})})(e),((e,t)=>{e.ui.registry.addAutocompleter("charmap",{ch:":",columns:"auto",minChars:2,fetch:(e,a)=>new Promise(((a,r)=>{a(v(t,e))})),onAction:(t,a,r)=>{e.selection.setRng(a),e.insertContent(r),t.hide()}})})(e,r[0]),(e=>({getCharMap:()=>f(e),insertChar:a=>{t(e,a)}}))(e)}))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/code/plugin.min.js b/public/libs/tinymce/plugins/code/plugin.min.js index 5651c699c..0554219ce 100644 --- a/public/libs/tinymce/plugins/code/plugin.min.js +++ b/public/libs/tinymce/plugins/code/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("code",function(e){var t,o;function n(){return o.execCommand("mceCodeEditor")}return(t=e).addCommand("mceCodeEditor",function(){var n,e;e=(n=t).getContent({source_view:!0}),n.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:e},onSubmit:function(e){var t=n,o=e.getData().code;t.focus(),t.undoManager.transact(function(){t.setContent(o)}),t.selection.setCursorLocation(),t.nodeChanged(),e.close()}})}),(o=e).ui.registry.addButton("code",{icon:"sourcecode",tooltip:"Source code",onAction:n}),o.ui.registry.addMenuItem("code",{icon:"sourcecode",text:"Source code",onAction:n}),{}})}(); \ No newline at end of file +!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),{})))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/codesample/plugin.min.js b/public/libs/tinymce/plugins/codesample/plugin.min.js index 8affcd419..ee5093bc2 100644 --- a/public/libs/tinymce/plugins/codesample/plugin.min.js +++ b/public/libs/tinymce/plugins/codesample/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function o(e){return function(){return e}}function e(e){return e}function n(){return l}var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),s=o(!1),i=o(!0),l={fold:function(e,n){return e()},isSome:s,isNone:i,getOr:e,getOrThunk:a,getOrDie:function(e){throw new Error(e||"error: getOrDie called on none.")},getOrNull:o(null),getOrUndefined:o(void 0),or:e,orThunk:a,map:n,each:function(){},bind:n,exists:s,forall:i,filter:function(){return l},toArray:function(){return[]},toString:o("none()")};function a(e){return e()}function u(e){return e&&"PRE"===e.nodeName&&-1!==e.className.indexOf("language-")}function c(t){return function(e,n){return t(n)}}var d=function(t){function e(){return r}function n(e){return e(t)}var a=o(t),r={fold:function(e,n){return n(t)},isSome:i,isNone:s,getOr:a,getOrThunk:a,getOrDie:a,getOrNull:a,getOrUndefined:a,or:e,orThunk:e,map:function(e){return d(e(t))},each:function(e){e(t)},bind:n,exists:n,forall:n,filter:function(e){return e(t)?r:l},toArray:function(){return[t]},toString:function(){return"some("+t+")"}};return r},p={some:d,none:n,from:function(e){return null==e?l:d(e)}},g=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),r="undefined"!=typeof window?window:Function("return this;")(),b={},m={exports:b},f={};function h(e){return r.Prism&&e.getParam("codesample_global_prismjs",!1,"boolean")?r.Prism:k}function y(e){var n=e.selection?e.selection.getNode():null;return u(n)?p.some(n):p.none()}function w(s){var t,e,n=s.getParam("codesample_languages")||[{text:"HTML/XML",value:"markup"},{text:"JavaScript",value:"javascript"},{text:"CSS",value:"css"},{text:"PHP",value:"php"},{text:"Ruby",value:"ruby"},{text:"Python",value:"python"},{text:"Java",value:"java"},{text:"C",value:"c"},{text:"C#",value:"csharp"},{text:"C++",value:"cpp"}],a=(0<(e=n).length?p.some(e[0]):p.none()).fold(o(""),function(e){return e.value}),r=(t=a,y(s).fold(function(){return t},function(e){var n=e.className.match(/language-(\w+)/);return n?n[1]:t})),i=y(s).fold(o(""),function(e){return e.textContent});s.windowManager.open({title:"Insert/Edit Code Sample",size:"large",body:{type:"panel",items:[{type:"selectbox",name:"language",label:"Language",items:n},{type:"textarea",name:"code",label:"Code view"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{language:r,code:i},onSubmit:function(e){var n=e.getData(),t=s,a=n.language,r=n.code;t.undoManager.transact(function(){var e=y(t);return r=g.DOM.encode(r),e.fold(function(){t.insertContent('

'+r+"
"),t.selection.select(t.$("#__new").removeAttr("id")[0])},function(e){t.dom.setAttrib(e,"class","language-"+a),e.innerHTML=r,h(t).highlightElement(e),t.selection.select(e)})}),e.close()}})}!function(e,n){var t,a,r=window.Prism;window.Prism={manual:!0},t=this,a=function(){var e,n,h,t,a,r,s,i,o,l,u="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:f,c={exports:{}};function y(e,n){return"___"+e.toUpperCase()+n+"___"}return e=c,n=function(u){var c=/\blang(?:uage)?-([\w-]+)\b/i,n=0,e={},j={manual:u.Prism&&u.Prism.manual,disableWorkerMessageHandler:u.Prism&&u.Prism.disableWorkerMessageHandler,util:{encode:function e(n){return n instanceof T?new T(n.type,e(n.content),n.alias):Array.isArray(n)?n.map(e):n.replace(/&/g,"&").replace(/=i.reach);y+=h.value.length,h=h.next){var w=h.value;if(t.length>n.length)return;if(!(w instanceof T)){var k,v=1;if(b){if(!(k=O(f,y,n,g)))break;var _=k.index,x=k.index+k[0].length,F=y;for(F+=h.value.length;F<=_;)F+=(h=h.next).value.length;if(y=F-=h.value.length,h.value instanceof T)continue;for(var P=h;P!==t.tail&&(Fi.reach&&(i.reach=z);var E=h.prev;S&&(E=N(t,E,S),y+=S.length),function(e,n,t){for(var a=n.next,r=0;ri.reach&&(i.reach=C.reach))}}}}(e,r,n,r.head,0),function(e){for(var n=[],t=e.head.next;t!==e.tail;)n.push(t.value),t=t.next;return n}(r)},hooks:{all:{},add:function(e,n){var t=j.hooks.all;t[e]=t[e]||[],t[e].push(n)},run:function(e,n){var t=j.hooks.all[e];if(t&&t.length)for(var a,r=0;a=t[r++];)a(n)}},Token:T};function T(e,n,t,a){this.type=e,this.content=n,this.alias=t,this.length=0|(a||"").length}function O(e,n,t,a){e.lastIndex=n;var r,s=e.exec(t);return s&&a&&s[1]&&(r=s[1].length,s.index+=r,s[0]=s[0].slice(r)),s}function s(){var e={value:null,prev:null,next:null},n={value:null,prev:e,next:null};e.next=n,this.head=e,this.tail=n,this.length=0}function N(e,n,t){var a=n.next,r={value:t,prev:n,next:a};return n.next=r,a.prev=r,e.length++,r}if(u.Prism=j,T.stringify=function n(e,t){if("string"==typeof e)return e;if(Array.isArray(e)){var a="";return e.forEach(function(e){a+=n(e,t)}),a}var r={type:e.type,content:n(e.content,t),tag:"span",classes:["token",e.type],attributes:{},language:t},s=e.alias;s&&(Array.isArray(s)?Array.prototype.push.apply(r.classes,s):r.classes.push(s)),j.hooks.run("wrap",r);var i,o="";for(i in r.attributes)o+=" "+i+'="'+(r.attributes[i]||"").replace(/"/g,""")+'"';return"<"+r.tag+' class="'+r.classes.join(" ")+'"'+o+">"+r.content+""},!u.document)return u.addEventListener&&(j.disableWorkerMessageHandler||u.addEventListener("message",function(e){var n=JSON.parse(e.data),t=n.language,a=n.code,r=n.immediateClose;u.postMessage(j.highlight(a,j.languages[t],t)),r&&u.close()},!1)),j;var t,a=j.util.currentScript();function r(){j.manual||j.highlightAll()}return a&&(j.filename=a.src,a.hasAttribute("data-manual")&&(j.manual=!0)),j.manual||("loading"===(t=document.readyState)||"interactive"===t&&a&&a.defer?document.addEventListener("DOMContentLoaded",r):window.requestAnimationFrame?window.requestAnimationFrame(r):window.setTimeout(r,16)),j}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{}),e.exports&&(e.exports=n),void 0!==u&&(u.Prism=n),Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|interface|extends|implements|trait|instanceof|new)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,boolean:/\b(?:true|false)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},h=Prism,Object.defineProperties(h.languages["markup-templating"]={},{buildPlaceholders:{value:function(a,r,e,s){var i;a.language===r&&(i=a.tokenStack=[],a.code=a.code.replace(e,function(e){if("function"==typeof s&&!s(e))return e;for(var n,t=i.length;-1!==a.code.indexOf(n=y(r,t));)++t;return i[t]=e,n}),a.grammar=h.languages.markup)}},tokenizePlaceholders:{value:function(g,b){var m,f;g.language===b&&g.tokenStack&&(g.grammar=h.languages[b],m=0,f=Object.keys(g.tokenStack),function e(n){for(var t=0;t=f.length);t++){var a,r,s,i,o,l,u,c,d,p=n[t];"string"==typeof p||p.content&&"string"==typeof p.content?(a=f[m],r=g.tokenStack[a],s="string"==typeof p?p:p.content,i=y(b,a),-1<(o=s.indexOf(i))&&(++m,l=s.substring(0,o),u=new h.Token(b,h.tokenize(r,g.grammar),"language-"+b,r),c=s.substring(o+i.length),d=[],l&&d.push.apply(d,e([l])),d.push(u),c&&d.push.apply(d,e([c])),"string"==typeof p?n.splice.apply(n,[t,1].concat(d)):p.content=d)):p.content&&e(p.content)}return n}(g.tokens))}}}),Prism.languages.c=Prism.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:__attribute__|_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},Prism.languages.c.string],comment:Prism.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:Prism.languages.c}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c.boolean,t=Prism,a=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char8_t|char16_t|char32_t|class|compl|concept|const|consteval|constexpr|constinit|const_cast|continue|co_await|co_return|co_yield|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,r=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,function(){return a.source}),t.languages.cpp=t.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,function(){return a.source})),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:a,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:true|false)\b/}),t.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:module|import)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,function(){return r})+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),t.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:t.languages.cpp}}}}),t.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),t.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:t.languages.extend("cpp",{})}}),t.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},t.languages.cpp["base-clause"]),function(t){function a(e,t){return e.replace(/<<(\d+)>>/g,function(e,n){return"(?:"+t[+n]+")"})}function r(e,n,t){return RegExp(a(e,n),t||"")}function e(e,n){for(var t=0;t>/g,function(){return"(?:"+e+")"});return e.replace(/<>/g,"[^\\s\\S]")}var n="bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",s="class enum interface record struct",i="add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",o="abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield";function l(e){return"\\b(?:"+e.trim().replace(/ /g,"|")+")\\b"}var u=l(s),c=RegExp(l(n+" "+s+" "+i+" "+o)),d=l(s+" "+i+" "+o),p=l(n+" "+s+" "+o),g=e(/<(?:[^<>;=+\-*/%&|^]|<>)*>/.source,2),b=e(/\((?:[^()]|<>)*\)/.source,2),m=/@?\b[A-Za-z_]\w*\b/.source,f=a(/<<0>>(?:\s*<<1>>)?/.source,[m,g]),h=a(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source,[d,f]),y=/\[\s*(?:,\s*)*\]/.source,w=a(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source,[h,y]),k=a(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source,[g,b,y]),v=a(/\(<<0>>+(?:,<<0>>+)+\)/.source,[k]),_=a(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source,[v,h,y]),x={keyword:c,punctuation:/[<>()?,.:[\]]/},F=/'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source,P=/"(?:\\.|[^\\"\r\n])*"/.source;t.languages.csharp=t.languages.extend("clike",{string:[{pattern:r(/(^|[^$\\])<<0>>/.source,[/@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source]),lookbehind:!0,greedy:!0},{pattern:r(/(^|[^@$\\])<<0>>/.source,[P]),lookbehind:!0,greedy:!0},{pattern:RegExp(F),greedy:!0,alias:"character"}],"class-name":[{pattern:r(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source,[h]),lookbehind:!0,inside:x},{pattern:r(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source,[m,_]),lookbehind:!0,inside:x},{pattern:r(/(\busing\s+)<<0>>(?=\s*=)/.source,[m]),lookbehind:!0},{pattern:r(/(\b<<0>>\s+)<<1>>/.source,[u,f]),lookbehind:!0,inside:x},{pattern:r(/(\bcatch\s*\(\s*)<<0>>/.source,[h]),lookbehind:!0,inside:x},{pattern:r(/(\bwhere\s+)<<0>>/.source,[m]),lookbehind:!0},{pattern:r(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source,[w]),lookbehind:!0,inside:x},{pattern:r(/\b<<0>>(?=\s+(?!<<1>>|with\s*\{)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source,[_,p,m]),inside:x}],keyword:c,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:ul|lu|[dflmu])?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),t.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),t.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:r(/([(,]\s*)<<0>>(?=\s*:)/.source,[m]),lookbehind:!0,alias:"punctuation"}}),t.languages.insertBefore("csharp","class-name",{namespace:{pattern:r(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source,[m]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:r(/(\b(?:default|typeof|sizeof)\s*\(\s*(?!\s))(?:[^()\s]|\s(?!\s)|<<0>>)*(?=\s*\))/.source,[b]),lookbehind:!0,alias:"class-name",inside:x},"return-type":{pattern:r(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source,[_,h]),inside:x,alias:"class-name"},"constructor-invocation":{pattern:r(/(\bnew\s+)<<0>>(?=\s*[[({])/.source,[_]),lookbehind:!0,inside:x,alias:"class-name"},"generic-method":{pattern:r(/<<0>>\s*<<1>>(?=\s*\()/.source,[m,g]),inside:{function:r(/^<<0>>/.source,[m]),generic:{pattern:RegExp(g),alias:"class-name",inside:x}}},"type-list":{pattern:r(/\b((?:<<0>>\s+<<1>>|record\s+<<1>>\s*<<5>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>|<<1>>\s*<<5>>|<<6>>)(?:\s*,\s*(?:<<3>>|<<4>>|<<6>>))*(?=\s*(?:where|[{;]|=>|$))/.source,[u,f,m,_,c.source,b,/\bnew\s*\(\s*\)/.source]),lookbehind:!0,inside:{"record-arguments":{pattern:r(/(^(?!new\s*\()<<0>>\s*)<<1>>/.source,[f,b]),lookbehind:!0,greedy:!0,inside:t.languages.csharp},keyword:c,"class-name":{pattern:RegExp(_),greedy:!0,inside:x},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var A=P+"|"+F,S=a(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source,[A]),$=e(a(/[^"'/()]|<<0>>|\(<>*\)/.source,[S]),2),z=/\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source,E=a(/<<0>>(?:\s*\(<<1>>*\))?/.source,[h,$]);t.languages.insertBefore("csharp","class-name",{attribute:{pattern:r(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source,[z,E]),lookbehind:!0,greedy:!0,inside:{target:{pattern:r(/^<<0>>(?=\s*:)/.source,[z]),alias:"keyword"},"attribute-arguments":{pattern:r(/\(<<0>>*\)/.source,[$]),inside:t.languages.csharp},"class-name":{pattern:RegExp(h),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var C=/:[^}\r\n]+/.source,j=e(a(/[^"'/()]|<<0>>|\(<>*\)/.source,[S]),2),T=a(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[j,C]),O=e(a(/[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<>*\)/.source,[A]),2),N=a(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[O,C]);function B(e,n){return{interpolation:{pattern:r(/((?:^|[^{])(?:\{\{)*)<<0>>/.source,[e]),lookbehind:!0,inside:{"format-string":{pattern:r(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source,[n,C]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:t.languages.csharp}}},string:/[\s\S]+/}}t.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:r(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source,[T]),lookbehind:!0,greedy:!0,inside:B(T,j)},{pattern:r(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source,[N]),lookbehind:!0,greedy:!0,inside:B(N,O)}]})}(Prism),Prism.languages.dotnet=Prism.languages.cs=Prism.languages.csharp,function(e){var n=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+n.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+n.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+n.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:n,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var t=e.languages.markup;t&&(t.tag.addInlined("style","css"),t.tag.addAttribute("style","css"))}(Prism),s=Prism,i=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,o=/(^|[^\w.])(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,l={pattern:RegExp(o+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}},s.languages.java=s.languages.extend("clike",{"class-name":[l,{pattern:RegExp(o+/[A-Z]\w*(?=\s+\w+\s*[;,=()])/.source),lookbehind:!0,inside:l.inside}],keyword:i,function:[s.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),s.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"}}),s.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":l,keyword:i,punctuation:/[<>(),.:]/,operator:/[?&|]/}},namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(//g,function(){return i.source})),lookbehind:!0,inside:{punctuation:/\./}}}),Prism.languages.javascript=Prism.languages.extend("clike",{"class-name":[Prism.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:prototype|constructor))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:/\b(?:(?:0[xX](?:[\dA-Fa-f](?:_[\dA-Fa-f])?)+|0[bB](?:[01](?:_[01])?)+|0[oO](?:[0-7](?:_[0-7])?)+)n?|(?:\d(?:_\d)?)+n|NaN|Infinity)\b|(?:\b(?:\d(?:_\d)?)+\.?(?:\d(?:_\d)?)*|\B\.(?:\d(?:_\d)?)+)(?:[Ee][+-]?(?:\d(?:_\d)?)+)?/,operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),Prism.languages.javascript["class-name"][0].pattern=/(\b(?:class|interface|extends|implements|instanceof|new)\s+)[\w.\\]+/,Prism.languages.insertBefore("javascript","keyword",{regex:{pattern:/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)\/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/,lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:Prism.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:Prism.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:Prism.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),Prism.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:Prism.languages.javascript}},string:/[\s\S]+/}}}),Prism.languages.markup&&(Prism.languages.markup.tag.addInlined("script","javascript"),Prism.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),Prism.languages.js=Prism.languages.javascript,Prism.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.languages.markup.doctype.inside["internal-subset"].inside=Prism.languages.markup,Prism.hooks.add("wrap",function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))}),Object.defineProperty(Prism.languages.markup.tag,"addInlined",{value:function(e,n){var t={};t["language-"+n]={pattern:/(^$)/i,lookbehind:!0,inside:Prism.languages[n]},t.cdata=/^$/i;var a={"included-cdata":{pattern://i,inside:t}};a["language-"+n]={pattern:/[\s\S]+/,inside:Prism.languages[n]};var r={};r[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,function(){return e}),"i"),lookbehind:!0,greedy:!0,inside:a},Prism.languages.insertBefore("markup","cdata",r)}}),Object.defineProperty(Prism.languages.markup.tag,"addAttribute",{value:function(e,n){Prism.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[n,"language-"+n],inside:Prism.languages[n]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup,Prism.languages.xml=Prism.languages.extend("markup",{}),Prism.languages.ssml=Prism.languages.xml,Prism.languages.atom=Prism.languages.xml,Prism.languages.rss=Prism.languages.xml,function(n){var e=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,t=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],a=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,r=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,s=/[{}\[\](),:;]/;n.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:e,variable:/\$+(?:\w+\b|(?=\{))/i,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:bool|boolean|int|integer|float|string|object|array)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:bool|int|float|string|object|array(?!\s*\()|mixed|self|static|callable|iterable|(?:null|false)(?=\s*\|))\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*[\w|]\|\s*)(?:null|false)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:bool|int|float|string|object|void|array(?!\s*\()|mixed|self|static|callable|iterable|(?:null|false)(?=\s*\|))\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?[\w|]\|\s*)(?:null|false)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:bool|int|float|string|object|void|array(?!\s*\()|mixed|iterable|(?:null|false)(?=\s*\|))\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:null|false)\b/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:__halt_compiler|abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|namespace|match|new|or|parent|print|private|protected|public|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s+)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:a,operator:r,punctuation:s};var i={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:n.languages.php},o=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:i}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:i}}];n.languages.insertBefore("php","variable",{string:o,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:e,string:o,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:t,number:a,operator:r,punctuation:s}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),n.hooks.add("before-tokenize",function(e){/<\?/.test(e.code)&&n.languages["markup-templating"].buildPlaceholders(e,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/gi)}),n.hooks.add("after-tokenize",function(e){n.languages["markup-templating"].tokenizePlaceholders(e,"php")})}(Prism),Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0},"string-interpolation":{pattern:/(?:f|rf|fr)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|rb|br)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|rb|br)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/im,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:and|as|assert|async|await|break|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:True|False|None)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?\b/i,operator:/[-+%=]=?|!=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python,function(e){e.languages.ruby=e.languages.extend("clike",{comment:[/#.*/,{pattern:/^=begin\s[\s\S]*?^=end/m,greedy:!0}],"class-name":{pattern:/(\b(?:class)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:alias|and|BEGIN|begin|break|case|class|def|define_method|defined|do|each|else|elsif|END|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|protected|private|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/});var n={pattern:/#\{[^}]+\}/,inside:{delimiter:{pattern:/^#\{|\}$/,alias:"tag"},rest:e.languages.ruby}};delete e.languages.ruby.function,e.languages.insertBefore("ruby","keyword",{regex:[{pattern:RegExp(/%r/.source+"(?:"+[/([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/\((?:[^()\\]|\\[\s\S])*\)/.source,/\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}/.source,/\[(?:[^\[\]\\]|\\[\s\S])*\]/.source,/<(?:[^<>\\]|\\[\s\S])*>/.source].join("|")+")"+/[egimnosux]{0,6}/.source),greedy:!0,inside:{interpolation:n}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:n}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:{pattern:/(^|[^:]):[a-zA-Z_]\w*(?:[?!]|\b)/,lookbehind:!0},"method-definition":{pattern:/(\bdef\s+)[\w.]+/,lookbehind:!0,inside:{function:/\w+$/,rest:e.languages.ruby}}}),e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Stat|Fixnum|Float|Hash|Integer|IO|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|String|Struct|TMS|Symbol|ThreadGroup|Thread|Time|TrueClass)\b/,constant:/\b[A-Z]\w*(?:[?!]|\b)/}),e.languages.ruby.string=[{pattern:RegExp(/%[qQiIwWxs]?/.source+"(?:"+[/([^a-zA-Z0-9\s{(\[<])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/\((?:[^()\\]|\\[\s\S])*\)/.source,/\{(?:[^#{}\\]|#(?:\{[^}]+\})?|\\[\s\S])*\}/.source,/\[(?:[^\[\]\\]|\\[\s\S])*\]/.source,/<(?:[^<>\\]|\\[\s\S])*>/.source].join("|")+")"),greedy:!0,inside:{interpolation:n}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:n}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|[a-z_]\w*$/i,alias:"symbol",inside:{punctuation:/^<<[-~]?/}},interpolation:n}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|[a-z_]\w*$/i,alias:"symbol",inside:{punctuation:/^<<[-~]?'|'$/}}}}],e.languages.rb=e.languages.ruby}(Prism),{boltExport:c.exports}},"object"==typeof e&&void 0!==n?n.exports=a():(t="undefined"!=typeof globalThis?globalThis:t||self).EphoxContactWrapper=a();window.Prism;window.Prism=r}(b,m);var k=m.exports.boltExport;t.add("codesample",function(n){var t,r,a,s;function e(){return s.execCommand("codesample")}r=(t=n).$,t.on("PreProcess",function(e){r("pre[contenteditable=false]",e.node).filter(c(u)).each(function(e,n){var t=r(n),a=n.textContent;t.attr("class",r.trim(t.attr("class"))),t.removeAttr("contentEditable"),t.empty().append(r("").each(function(){this.textContent=a}))})}),t.on("SetContent",function(){var e=r("pre").filter(c(u)).filter(function(e,n){return"false"!==n.contentEditable});e.length&&t.undoManager.transact(function(){e.each(function(e,n){r(n).find("br").each(function(e,n){n.parentNode.replaceChild(t.getDoc().createTextNode("\n"),n)}),n.contentEditable="false",n.innerHTML=t.dom.encode(n.textContent),h(t).highlightElement(n),n.className=r.trim(n.className)})})}),(s=n).ui.registry.addToggleButton("codesample",{icon:"code-sample",tooltip:"Insert/edit code sample",onAction:e,onSetup:function(t){function e(){var e,n;t.setActive((n=(e=s).selection.getStart(),e.dom.is(n,'pre[class*="language-"]')))}return s.on("NodeChange",e),function(){return s.off("NodeChange",e)}}}),s.ui.registry.addMenuItem("codesample",{text:"Code sample...",icon:"code-sample",onAction:e}),(a=n).addCommand("codesample",function(){var e=a.selection.getNode();a.selection.isCollapsed()||u(e)?w(a):a.formatter.toggle("code")}),n.on("dblclick",function(e){u(e.target)&&w(n)})})}(); \ No newline at end of file +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>()=>e;class n{constructor(e,t){this.tag=e,this.value=t}static some(e){return new n(!0,e)}static none(){return n.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?n.some(e(this.value)):n.none()}bind(e){return this.tag?e(this.value):n.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:n.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return null==e?n.none():n.some(e)}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}n.singletonNone=new n(!1);var a=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils");const s="undefined"!=typeof window?window:Function("return this;")(),r=function(e,t,n){const a=window.Prism;window.Prism={manual:!0};var s=function(e){var t=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,n=0,a={},s={manual:e.Prism&&e.Prism.manual,disableWorkerMessageHandler:e.Prism&&e.Prism.disableWorkerMessageHandler,util:{encode:function e(t){return t instanceof r?new r(t.type,e(t.content),t.alias):Array.isArray(t)?t.map(e):t.replace(/&/g,"&").replace(/=d.reach);x+=_.value.length,_=_.next){var F=_.value;if(t.length>e.length)return;if(!(F instanceof r)){var S,A=1;if(y){if(!(S=i(v,x,e,m))||S.index>=e.length)break;var $=S.index,z=S.index+S[0].length,E=x;for(E+=_.value.length;$>=E;)E+=(_=_.next).value.length;if(x=E-=_.value.length,_.value instanceof r)continue;for(var C=_;C!==t.tail&&(Ed.reach&&(d.reach=N);var P=_.prev;if(B&&(P=u(t,P,B),x+=B.length),c(t,P,A),_=u(t,P,new r(g,f?s.tokenize(j,f):j,w,j)),T&&u(t,_,T),A>1){var O={cause:g+","+b,reach:N};o(e,t,n,_.prev,x,O),d&&O.reach>d.reach&&(d.reach=O.reach)}}}}}}function l(){var e={value:null,prev:null,next:null},t={value:null,prev:e,next:null};e.next=t,this.head=e,this.tail=t,this.length=0}function u(e,t,n){var a=t.next,s={value:n,prev:t,next:a};return t.next=s,a.prev=s,e.length++,s}function c(e,t,n){for(var a=t.next,s=0;s"+r.content+""},!e.document)return e.addEventListener?(s.disableWorkerMessageHandler||e.addEventListener("message",(function(t){var n=JSON.parse(t.data),a=n.language,r=n.code,i=n.immediateClose;e.postMessage(s.highlight(r,s.languages[a],a)),i&&e.close()}),!1),s):s;var d=s.util.currentScript();function g(){s.manual||s.highlightAll()}if(d&&(s.filename=d.src,d.hasAttribute("data-manual")&&(s.manual=!0)),!s.manual){var p=document.readyState;"loading"===p||"interactive"===p&&d&&d.defer?document.addEventListener("DOMContentLoaded",g):window.requestAnimationFrame?window.requestAnimationFrame(g):window.setTimeout(g,16)}return s}("undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{});return s.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0,greedy:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/(\b(?:class|extends|implements|instanceof|interface|new|trait)\s+|\bcatch\s+\()[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:break|catch|continue|do|else|finally|for|function|if|in|instanceof|new|null|return|throw|try|while)\b/,boolean:/\b(?:false|true)\b/,function:/\b\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/[<>]=?|[!=]=?=?|--?|\+\+?|&&?|\|\|?|[?*/~^%]/,punctuation:/[{}[\];(),.:]/},function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,a,s,r){if(n.language===a){var i=n.tokenStack=[];n.code=n.code.replace(s,(function(e){if("function"==typeof r&&!r(e))return e;for(var s,o=i.length;-1!==n.code.indexOf(s=t(a,o));)++o;return i[o]=e,s})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,a){if(n.language===a&&n.tokenStack){n.grammar=e.languages[a];var s=0,r=Object.keys(n.tokenStack);!function i(o){for(var l=0;l=r.length);l++){var u=o[l];if("string"==typeof u||u.content&&"string"==typeof u.content){var c=r[s],d=n.tokenStack[c],g="string"==typeof u?u:u.content,p=t(a,c),b=g.indexOf(p);if(b>-1){++s;var h=g.substring(0,b),f=new e.Token(a,e.tokenize(d,n.grammar),"language-"+a,d),m=g.substring(b+p.length),y=[];h&&y.push.apply(y,i([h])),y.push(f),m&&y.push.apply(y,i([m])),"string"==typeof u?o.splice.apply(o,[l,1].concat(y)):u.content=y}}else u.content&&i(u.content)}return o}(n.tokens)}}}})}(s),s.languages.c=s.languages.extend("clike",{comment:{pattern:/\/\/(?:[^\r\n\\]|\\(?:\r\n?|\n|(?![\r\n])))*|\/\*[\s\S]*?(?:\*\/|$)/,greedy:!0},string:{pattern:/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"/,greedy:!0},"class-name":{pattern:/(\b(?:enum|struct)\s+(?:__attribute__\s*\(\([\s\S]*?\)\)\s*)?)\w+|\b[a-z]\w*_t\b/,lookbehind:!0},keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|__attribute__|asm|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|inline|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|typeof|union|unsigned|void|volatile|while)\b/,function:/\b[a-z_]\w*(?=\s*\()/i,number:/(?:\b0x(?:[\da-f]+(?:\.[\da-f]*)?|\.[\da-f]+)(?:p[+-]?\d+)?|(?:\b\d+(?:\.\d*)?|\B\.\d+)(?:e[+-]?\d+)?)[ful]{0,4}/i,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*/%&|^!=<>]=?/}),s.languages.insertBefore("c","string",{char:{pattern:/'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n]){0,32}'/,greedy:!0}}),s.languages.insertBefore("c","string",{macro:{pattern:/(^[\t ]*)#\s*[a-z](?:[^\r\n\\/]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,greedy:!0,alias:"property",inside:{string:[{pattern:/^(#\s*include\s*)<[^>]+>/,lookbehind:!0},s.languages.c.string],char:s.languages.c.char,comment:s.languages.c.comment,"macro-name":[{pattern:/(^#\s*define\s+)\w+\b(?!\()/i,lookbehind:!0},{pattern:/(^#\s*define\s+)\w+\b(?=\()/i,lookbehind:!0,alias:"function"}],directive:{pattern:/^(#\s*)[a-z]+/,lookbehind:!0,alias:"keyword"},"directive-hash":/^#/,punctuation:/##|\\(?=[\r\n])/,expression:{pattern:/\S[\s\S]*/,inside:s.languages.c}}}}),s.languages.insertBefore("c","function",{constant:/\b(?:EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|__DATE__|__FILE__|__LINE__|__TIMESTAMP__|__TIME__|__func__|stderr|stdin|stdout)\b/}),delete s.languages.c.boolean,function(e){var t=/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|char8_t|class|co_await|co_return|co_yield|compl|concept|const|const_cast|consteval|constexpr|constinit|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|final|float|for|friend|goto|if|import|inline|int|int16_t|int32_t|int64_t|int8_t|long|module|mutable|namespace|new|noexcept|nullptr|operator|override|private|protected|public|register|reinterpret_cast|requires|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|uint16_t|uint32_t|uint64_t|uint8_t|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,n=/\b(?!)\w+(?:\s*\.\s*\w+)*\b/.source.replace(//g,(function(){return t.source}));e.languages.cpp=e.languages.extend("c",{"class-name":[{pattern:RegExp(/(\b(?:class|concept|enum|struct|typename)\s+)(?!)\w+/.source.replace(//g,(function(){return t.source}))),lookbehind:!0},/\b[A-Z]\w*(?=\s*::\s*\w+\s*\()/,/\b[A-Z_]\w*(?=\s*::\s*~\w+\s*\()/i,/\b\w+(?=\s*<(?:[^<>]|<(?:[^<>]|<[^<>]*>)*>)*>\s*::\s*\w+\s*\()/],keyword:t,number:{pattern:/(?:\b0b[01']+|\b0x(?:[\da-f']+(?:\.[\da-f']*)?|\.[\da-f']+)(?:p[+-]?[\d']+)?|(?:\b[\d']+(?:\.[\d']*)?|\B\.[\d']+)(?:e[+-]?[\d']+)?)[ful]{0,4}/i,greedy:!0},operator:/>>=?|<<=?|->|--|\+\+|&&|\|\||[?:~]|<=>|[-+*/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/,boolean:/\b(?:false|true)\b/}),e.languages.insertBefore("cpp","string",{module:{pattern:RegExp(/(\b(?:import|module)\s+)/.source+"(?:"+/"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|<[^<>\r\n]*>/.source+"|"+/(?:\s*:\s*)?|:\s*/.source.replace(//g,(function(){return n}))+")"),lookbehind:!0,greedy:!0,inside:{string:/^[<"][\s\S]+/,operator:/:/,punctuation:/\./}},"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}}),e.languages.insertBefore("cpp","keyword",{"generic-function":{pattern:/\b(?!operator\b)[a-z_]\w*\s*<(?:[^<>]|<[^<>]*>)*>(?=\s*\()/i,inside:{function:/^\w+/,generic:{pattern:/<[\s\S]+/,alias:"class-name",inside:e.languages.cpp}}}}),e.languages.insertBefore("cpp","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}}),e.languages.insertBefore("cpp","class-name",{"base-clause":{pattern:/(\b(?:class|struct)\s+\w+\s*:\s*)[^;{}"'\s]+(?:\s+[^;{}"'\s]+)*(?=\s*[;{])/,lookbehind:!0,greedy:!0,inside:e.languages.extend("cpp",{})}}),e.languages.insertBefore("inside","double-colon",{"class-name":/\b[a-z_]\w*\b(?!\s*::)/i},e.languages.cpp["base-clause"])}(s),function(e){function t(e,t){return e.replace(/<<(\d+)>>/g,(function(e,n){return"(?:"+t[+n]+")"}))}function n(e,n,a){return RegExp(t(e,n),a||"")}function a(e,t){for(var n=0;n>/g,(function(){return"(?:"+e+")"}));return e.replace(/<>/g,"[^\\s\\S]")}var s="bool byte char decimal double dynamic float int long object sbyte short string uint ulong ushort var void",r="class enum interface record struct",i="add alias and ascending async await by descending from(?=\\s*(?:\\w|$)) get global group into init(?=\\s*;) join let nameof not notnull on or orderby partial remove select set unmanaged value when where with(?=\\s*{)",o="abstract as base break case catch checked const continue default delegate do else event explicit extern finally fixed for foreach goto if implicit in internal is lock namespace new null operator out override params private protected public readonly ref return sealed sizeof stackalloc static switch this throw try typeof unchecked unsafe using virtual volatile while yield";function l(e){return"\\b(?:"+e.trim().replace(/ /g,"|")+")\\b"}var u=l(r),c=RegExp(l(s+" "+r+" "+i+" "+o)),d=l(r+" "+i+" "+o),g=l(s+" "+r+" "+o),p=a(/<(?:[^<>;=+\-*/%&|^]|<>)*>/.source,2),b=a(/\((?:[^()]|<>)*\)/.source,2),h=/@?\b[A-Za-z_]\w*\b/.source,f=t(/<<0>>(?:\s*<<1>>)?/.source,[h,p]),m=t(/(?!<<0>>)<<1>>(?:\s*\.\s*<<1>>)*/.source,[d,f]),y=/\[\s*(?:,\s*)*\]/.source,w=t(/<<0>>(?:\s*(?:\?\s*)?<<1>>)*(?:\s*\?)?/.source,[m,y]),k=t(/[^,()<>[\];=+\-*/%&|^]|<<0>>|<<1>>|<<2>>/.source,[p,b,y]),v=t(/\(<<0>>+(?:,<<0>>+)+\)/.source,[k]),_=t(/(?:<<0>>|<<1>>)(?:\s*(?:\?\s*)?<<2>>)*(?:\s*\?)?/.source,[v,m,y]),x={keyword:c,punctuation:/[<>()?,.:[\]]/},F=/'(?:[^\r\n'\\]|\\.|\\[Uux][\da-fA-F]{1,8})'/.source,S=/"(?:\\.|[^\\"\r\n])*"/.source,A=/@"(?:""|\\[\s\S]|[^\\"])*"(?!")/.source;e.languages.csharp=e.languages.extend("clike",{string:[{pattern:n(/(^|[^$\\])<<0>>/.source,[A]),lookbehind:!0,greedy:!0},{pattern:n(/(^|[^@$\\])<<0>>/.source,[S]),lookbehind:!0,greedy:!0}],"class-name":[{pattern:n(/(\busing\s+static\s+)<<0>>(?=\s*;)/.source,[m]),lookbehind:!0,inside:x},{pattern:n(/(\busing\s+<<0>>\s*=\s*)<<1>>(?=\s*;)/.source,[h,_]),lookbehind:!0,inside:x},{pattern:n(/(\busing\s+)<<0>>(?=\s*=)/.source,[h]),lookbehind:!0},{pattern:n(/(\b<<0>>\s+)<<1>>/.source,[u,f]),lookbehind:!0,inside:x},{pattern:n(/(\bcatch\s*\(\s*)<<0>>/.source,[m]),lookbehind:!0,inside:x},{pattern:n(/(\bwhere\s+)<<0>>/.source,[h]),lookbehind:!0},{pattern:n(/(\b(?:is(?:\s+not)?|as)\s+)<<0>>/.source,[w]),lookbehind:!0,inside:x},{pattern:n(/\b<<0>>(?=\s+(?!<<1>>|with\s*\{)<<2>>(?:\s*[=,;:{)\]]|\s+(?:in|when)\b))/.source,[_,g,h]),inside:x}],keyword:c,number:/(?:\b0(?:x[\da-f_]*[\da-f]|b[01_]*[01])|(?:\B\.\d+(?:_+\d+)*|\b\d+(?:_+\d+)*(?:\.\d+(?:_+\d+)*)?)(?:e[-+]?\d+(?:_+\d+)*)?)(?:[dflmu]|lu|ul)?\b/i,operator:/>>=?|<<=?|[-=]>|([-+&|])\1|~|\?\?=?|[-+*/%&|^!=<>]=?/,punctuation:/\?\.?|::|[{}[\];(),.:]/}),e.languages.insertBefore("csharp","number",{range:{pattern:/\.\./,alias:"operator"}}),e.languages.insertBefore("csharp","punctuation",{"named-parameter":{pattern:n(/([(,]\s*)<<0>>(?=\s*:)/.source,[h]),lookbehind:!0,alias:"punctuation"}}),e.languages.insertBefore("csharp","class-name",{namespace:{pattern:n(/(\b(?:namespace|using)\s+)<<0>>(?:\s*\.\s*<<0>>)*(?=\s*[;{])/.source,[h]),lookbehind:!0,inside:{punctuation:/\./}},"type-expression":{pattern:n(/(\b(?:default|sizeof|typeof)\s*\(\s*(?!\s))(?:[^()\s]|\s(?!\s)|<<0>>)*(?=\s*\))/.source,[b]),lookbehind:!0,alias:"class-name",inside:x},"return-type":{pattern:n(/<<0>>(?=\s+(?:<<1>>\s*(?:=>|[({]|\.\s*this\s*\[)|this\s*\[))/.source,[_,m]),inside:x,alias:"class-name"},"constructor-invocation":{pattern:n(/(\bnew\s+)<<0>>(?=\s*[[({])/.source,[_]),lookbehind:!0,inside:x,alias:"class-name"},"generic-method":{pattern:n(/<<0>>\s*<<1>>(?=\s*\()/.source,[h,p]),inside:{function:n(/^<<0>>/.source,[h]),generic:{pattern:RegExp(p),alias:"class-name",inside:x}}},"type-list":{pattern:n(/\b((?:<<0>>\s+<<1>>|record\s+<<1>>\s*<<5>>|where\s+<<2>>)\s*:\s*)(?:<<3>>|<<4>>|<<1>>\s*<<5>>|<<6>>)(?:\s*,\s*(?:<<3>>|<<4>>|<<6>>))*(?=\s*(?:where|[{;]|=>|$))/.source,[u,f,h,_,c.source,b,/\bnew\s*\(\s*\)/.source]),lookbehind:!0,inside:{"record-arguments":{pattern:n(/(^(?!new\s*\()<<0>>\s*)<<1>>/.source,[f,b]),lookbehind:!0,greedy:!0,inside:e.languages.csharp},keyword:c,"class-name":{pattern:RegExp(_),greedy:!0,inside:x},punctuation:/[,()]/}},preprocessor:{pattern:/(^[\t ]*)#.*/m,lookbehind:!0,alias:"property",inside:{directive:{pattern:/(#)\b(?:define|elif|else|endif|endregion|error|if|line|nullable|pragma|region|undef|warning)\b/,lookbehind:!0,alias:"keyword"}}}});var $=S+"|"+F,z=t(/\/(?![*/])|\/\/[^\r\n]*[\r\n]|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>/.source,[$]),E=a(t(/[^"'/()]|<<0>>|\(<>*\)/.source,[z]),2),C=/\b(?:assembly|event|field|method|module|param|property|return|type)\b/.source,j=t(/<<0>>(?:\s*\(<<1>>*\))?/.source,[m,E]);e.languages.insertBefore("csharp","class-name",{attribute:{pattern:n(/((?:^|[^\s\w>)?])\s*\[\s*)(?:<<0>>\s*:\s*)?<<1>>(?:\s*,\s*<<1>>)*(?=\s*\])/.source,[C,j]),lookbehind:!0,greedy:!0,inside:{target:{pattern:n(/^<<0>>(?=\s*:)/.source,[C]),alias:"keyword"},"attribute-arguments":{pattern:n(/\(<<0>>*\)/.source,[E]),inside:e.languages.csharp},"class-name":{pattern:RegExp(m),inside:{punctuation:/\./}},punctuation:/[:,]/}}});var B=/:[^}\r\n]+/.source,T=a(t(/[^"'/()]|<<0>>|\(<>*\)/.source,[z]),2),N=t(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[T,B]),P=a(t(/[^"'/()]|\/(?!\*)|\/\*(?:[^*]|\*(?!\/))*\*\/|<<0>>|\(<>*\)/.source,[$]),2),O=t(/\{(?!\{)(?:(?![}:])<<0>>)*<<1>>?\}/.source,[P,B]);function R(t,a){return{interpolation:{pattern:n(/((?:^|[^{])(?:\{\{)*)<<0>>/.source,[t]),lookbehind:!0,inside:{"format-string":{pattern:n(/(^\{(?:(?![}:])<<0>>)*)<<1>>(?=\}$)/.source,[a,B]),lookbehind:!0,inside:{punctuation:/^:/}},punctuation:/^\{|\}$/,expression:{pattern:/[\s\S]+/,alias:"language-csharp",inside:e.languages.csharp}}},string:/[\s\S]+/}}e.languages.insertBefore("csharp","string",{"interpolation-string":[{pattern:n(/(^|[^\\])(?:\$@|@\$)"(?:""|\\[\s\S]|\{\{|<<0>>|[^\\{"])*"/.source,[N]),lookbehind:!0,greedy:!0,inside:R(N,T)},{pattern:n(/(^|[^@\\])\$"(?:\\.|\{\{|<<0>>|[^\\"{])*"/.source,[O]),lookbehind:!0,greedy:!0,inside:R(O,P)}],char:{pattern:RegExp(F),greedy:!0}}),e.languages.dotnet=e.languages.cs=e.languages.csharp}(s),function(e){var t=/(?:"(?:\\(?:\r\n|[\s\S])|[^"\\\r\n])*"|'(?:\\(?:\r\n|[\s\S])|[^'\\\r\n])*')/;e.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-](?:[^;{\s]|\s+(?![\s{]))*(?:;|(?=\s*\{))/,inside:{rule:/^@[\w-]+/,"selector-function-argument":{pattern:/(\bselector\s*\(\s*(?![\s)]))(?:[^()\s]|\s+(?![\s)])|\((?:[^()]|\([^()]*\))*\))+(?=\s*\))/,lookbehind:!0,alias:"selector"},keyword:{pattern:/(^|[^\w-])(?:and|not|only|or)(?![\w-])/,lookbehind:!0}}},url:{pattern:RegExp("\\burl\\((?:"+t.source+"|"+/(?:[^\\\r\n()"']|\\[\s\S])*/.source+")\\)","i"),greedy:!0,inside:{function:/^url/i,punctuation:/^\(|\)$/,string:{pattern:RegExp("^"+t.source+"$"),alias:"url"}}},selector:{pattern:RegExp("(^|[{}\\s])[^{}\\s](?:[^{};\"'\\s]|\\s+(?![\\s{])|"+t.source+")*(?=\\s*\\{)"),lookbehind:!0},string:{pattern:t,greedy:!0},property:{pattern:/(^|[^-\w\xA0-\uFFFF])(?!\s)[-_a-z\xA0-\uFFFF](?:(?!\s)[-\w\xA0-\uFFFF])*(?=\s*:)/i,lookbehind:!0},important:/!important\b/i,function:{pattern:/(^|[^-a-z0-9])[-a-z0-9]+(?=\()/i,lookbehind:!0},punctuation:/[(){};:,]/},e.languages.css.atrule.inside.rest=e.languages.css;var n=e.languages.markup;n&&(n.tag.addInlined("style","css"),n.tag.addAttribute("style","css"))}(s),function(e){var t=/\b(?:abstract|assert|boolean|break|byte|case|catch|char|class|const|continue|default|do|double|else|enum|exports|extends|final|finally|float|for|goto|if|implements|import|instanceof|int|interface|long|module|native|new|non-sealed|null|open|opens|package|permits|private|protected|provides|public|record(?!\s*[(){}[\]<>=%~.:,;?+\-*/&|^])|requires|return|sealed|short|static|strictfp|super|switch|synchronized|this|throw|throws|to|transient|transitive|try|uses|var|void|volatile|while|with|yield)\b/,n=/(?:[a-z]\w*\s*\.\s*)*(?:[A-Z]\w*\s*\.\s*)*/.source,a={pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z](?:[\d_A-Z]*[a-z]\w*)?\b/.source),lookbehind:!0,inside:{namespace:{pattern:/^[a-z]\w*(?:\s*\.\s*[a-z]\w*)*(?:\s*\.)?/,inside:{punctuation:/\./}},punctuation:/\./}};e.languages.java=e.languages.extend("clike",{string:{pattern:/(^|[^\\])"(?:\\.|[^"\\\r\n])*"/,lookbehind:!0,greedy:!0},"class-name":[a,{pattern:RegExp(/(^|[^\w.])/.source+n+/[A-Z]\w*(?=\s+\w+\s*[;,=()]|\s*(?:\[[\s,]*\]\s*)?::\s*new\b)/.source),lookbehind:!0,inside:a.inside},{pattern:RegExp(/(\b(?:class|enum|extends|implements|instanceof|interface|new|record|throws)\s+)/.source+n+/[A-Z]\w*\b/.source),lookbehind:!0,inside:a.inside}],keyword:t,function:[e.languages.clike.function,{pattern:/(::\s*)[a-z_]\w*/,lookbehind:!0}],number:/\b0b[01][01_]*L?\b|\b0x(?:\.[\da-f_p+-]+|[\da-f_]+(?:\.[\da-f_p+-]+)?)\b|(?:\b\d[\d_]*(?:\.[\d_]*)?|\B\.\d[\d_]*)(?:e[+-]?\d[\d_]*)?[dfl]?/i,operator:{pattern:/(^|[^.])(?:<<=?|>>>?=?|->|--|\+\+|&&|\|\||::|[?:~]|[-+*/%&|^!=<>]=?)/m,lookbehind:!0}}),e.languages.insertBefore("java","string",{"triple-quoted-string":{pattern:/"""[ \t]*[\r\n](?:(?:"|"")?(?:\\.|[^"\\]))*"""/,greedy:!0,alias:"string"},char:{pattern:/'(?:\\.|[^'\\\r\n]){1,6}'/,greedy:!0}}),e.languages.insertBefore("java","class-name",{annotation:{pattern:/(^|[^.])@\w+(?:\s*\.\s*\w+)*/,lookbehind:!0,alias:"punctuation"},generics:{pattern:/<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&)|<(?:[\w\s,.?]|&(?!&))*>)*>)*>)*>/,inside:{"class-name":a,keyword:t,punctuation:/[<>(),.:]/,operator:/[?&|]/}},import:[{pattern:RegExp(/(\bimport\s+)/.source+n+/(?:[A-Z]\w*|\*)(?=\s*;)/.source),lookbehind:!0,inside:{namespace:a.inside.namespace,punctuation:/\./,operator:/\*/,"class-name":/\w+/}},{pattern:RegExp(/(\bimport\s+static\s+)/.source+n+/(?:\w+|\*)(?=\s*;)/.source),lookbehind:!0,alias:"static",inside:{namespace:a.inside.namespace,static:/\b\w+$/,punctuation:/\./,operator:/\*/,"class-name":/\w+/}}],namespace:{pattern:RegExp(/(\b(?:exports|import(?:\s+static)?|module|open|opens|package|provides|requires|to|transitive|uses|with)\s+)(?!)[a-z]\w*(?:\.[a-z]\w*)*\.?/.source.replace(//g,(function(){return t.source}))),lookbehind:!0,inside:{punctuation:/\./}}})}(s),s.languages.javascript=s.languages.extend("clike",{"class-name":[s.languages.clike["class-name"],{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$A-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\.(?:constructor|prototype))/,lookbehind:!0}],keyword:[{pattern:/((?:^|\})\s*)catch\b/,lookbehind:!0},{pattern:/(^|[^.]|\.\.\.\s*)\b(?:as|assert(?=\s*\{)|async(?=\s*(?:function\b|\(|[$\w\xA0-\uFFFF]|$))|await|break|case|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally(?=\s*(?:\{|$))|for|from(?=\s*(?:['"]|$))|function|(?:get|set)(?=\s*(?:[#\[$\w\xA0-\uFFFF]|$))|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)\b/,lookbehind:!0}],function:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*(?:\.\s*(?:apply|bind|call)\s*)?\()/,number:{pattern:RegExp(/(^|[^\w$])/.source+"(?:"+/NaN|Infinity/.source+"|"+/0[bB][01]+(?:_[01]+)*n?/.source+"|"+/0[oO][0-7]+(?:_[0-7]+)*n?/.source+"|"+/0[xX][\dA-Fa-f]+(?:_[\dA-Fa-f]+)*n?/.source+"|"+/\d+(?:_\d+)*n/.source+"|"+/(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[Ee][+-]?\d+(?:_\d+)*)?/.source+")"+/(?![\w$])/.source),lookbehind:!0},operator:/--|\+\+|\*\*=?|=>|&&=?|\|\|=?|[!=]==|<<=?|>>>?=?|[-+*/%&|^!=<>]=?|\.{3}|\?\?=?|\?\.?|[~:]/}),s.languages.javascript["class-name"][0].pattern=/(\b(?:class|extends|implements|instanceof|interface|new)\s+)[\w.\\]+/,s.languages.insertBefore("javascript","keyword",{regex:{pattern:RegExp(/((?:^|[^$\w\xA0-\uFFFF."'\])\s]|\b(?:return|yield))\s*)/.source+/\//.source+"(?:"+/(?:\[(?:[^\]\\\r\n]|\\.)*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}/.source+"|"+/(?:\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.|\[(?:[^[\]\\\r\n]|\\.)*\])*\])*\]|\\.|[^/\\\[\r\n])+\/[dgimyus]{0,7}v[dgimyus]{0,7}/.source+")"+/(?=(?:\s|\/\*(?:[^*]|\*(?!\/))*\*\/)*(?:$|[\r\n,.;:})\]]|\/\/))/.source),lookbehind:!0,greedy:!0,inside:{"regex-source":{pattern:/^(\/)[\s\S]+(?=\/[a-z]*$)/,lookbehind:!0,alias:"language-regex",inside:s.languages.regex},"regex-delimiter":/^\/|\/$/,"regex-flags":/^[a-z]+$/}},"function-variable":{pattern:/#?(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*[=:]\s*(?:async\s*)?(?:\bfunction\b|(?:\((?:[^()]|\([^()]*\))*\)|(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)\s*=>))/,alias:"function"},parameter:[{pattern:/(function(?:\s+(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*)?\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\))/,lookbehind:!0,inside:s.languages.javascript},{pattern:/(^|[^$\w\xA0-\uFFFF])(?!\s)[_$a-z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*=>)/i,lookbehind:!0,inside:s.languages.javascript},{pattern:/(\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*=>)/,lookbehind:!0,inside:s.languages.javascript},{pattern:/((?:\b|\s|^)(?!(?:as|async|await|break|case|catch|class|const|continue|debugger|default|delete|do|else|enum|export|extends|finally|for|from|function|get|if|implements|import|in|instanceof|interface|let|new|null|of|package|private|protected|public|return|set|static|super|switch|this|throw|try|typeof|undefined|var|void|while|with|yield)(?![$\w\xA0-\uFFFF]))(?:(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*\s*)\(\s*|\]\s*\(\s*)(?!\s)(?:[^()\s]|\s+(?![\s)])|\([^()]*\))+(?=\s*\)\s*\{)/,lookbehind:!0,inside:s.languages.javascript}],constant:/\b[A-Z](?:[A-Z_]|\dx?)*\b/}),s.languages.insertBefore("javascript","string",{hashbang:{pattern:/^#!.*/,greedy:!0,alias:"comment"},"template-string":{pattern:/`(?:\\[\s\S]|\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}|(?!\$\{)[^\\`])*`/,greedy:!0,inside:{"template-punctuation":{pattern:/^`|`$/,alias:"string"},interpolation:{pattern:/((?:^|[^\\])(?:\\{2})*)\$\{(?:[^{}]|\{(?:[^{}]|\{[^}]*\})*\})+\}/,lookbehind:!0,inside:{"interpolation-punctuation":{pattern:/^\$\{|\}$/,alias:"punctuation"},rest:s.languages.javascript}},string:/[\s\S]+/}},"string-property":{pattern:/((?:^|[,{])[ \t]*)(["'])(?:\\(?:\r\n|[\s\S])|(?!\2)[^\\\r\n])*\2(?=\s*:)/m,lookbehind:!0,greedy:!0,alias:"property"}}),s.languages.insertBefore("javascript","operator",{"literal-property":{pattern:/((?:^|[,{])[ \t]*)(?!\s)[_$a-zA-Z\xA0-\uFFFF](?:(?!\s)[$\w\xA0-\uFFFF])*(?=\s*:)/m,lookbehind:!0,alias:"property"}}),s.languages.markup&&(s.languages.markup.tag.addInlined("script","javascript"),s.languages.markup.tag.addAttribute(/on(?:abort|blur|change|click|composition(?:end|start|update)|dblclick|error|focus(?:in|out)?|key(?:down|up)|load|mouse(?:down|enter|leave|move|out|over|up)|reset|resize|scroll|select|slotchange|submit|unload|wheel)/.source,"javascript")),s.languages.js=s.languages.javascript,s.languages.markup={comment:{pattern://,greedy:!0},prolog:{pattern:/<\?[\s\S]+?\?>/,greedy:!0},doctype:{pattern:/"'[\]]|"[^"]*"|'[^']*')+(?:\[(?:[^<"'\]]|"[^"]*"|'[^']*'|<(?!!--)|)*\]\s*)?>/i,greedy:!0,inside:{"internal-subset":{pattern:/(^[^\[]*\[)[\s\S]+(?=\]>$)/,lookbehind:!0,greedy:!0,inside:null},string:{pattern:/"[^"]*"|'[^']*'/,greedy:!0},punctuation:/^$|[[\]]/,"doctype-tag":/^DOCTYPE/i,name:/[^\s<>'"]+/}},cdata:{pattern://i,greedy:!0},tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s(?:\s*[^\s>\/=]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))|(?=[\s/>])))+)?\s*\/?>/,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"special-attr":[],"attr-value":{pattern:/=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+)/,inside:{punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:[{pattern:/&[\da-z]{1,8};/i,alias:"named-entity"},/&#x?[\da-f]{1,8};/i]},s.languages.markup.tag.inside["attr-value"].inside.entity=s.languages.markup.entity,s.languages.markup.doctype.inside["internal-subset"].inside=s.languages.markup,s.hooks.add("wrap",(function(e){"entity"===e.type&&(e.attributes.title=e.content.replace(/&/,"&"))})),Object.defineProperty(s.languages.markup.tag,"addInlined",{value:function(e,t){var n={};n["language-"+t]={pattern:/(^$)/i,lookbehind:!0,inside:s.languages[t]},n.cdata=/^$/i;var a={"included-cdata":{pattern://i,inside:n}};a["language-"+t]={pattern:/[\s\S]+/,inside:s.languages[t]};var r={};r[e]={pattern:RegExp(/(<__[^>]*>)(?:))*\]\]>|(?!)/.source.replace(/__/g,(function(){return e})),"i"),lookbehind:!0,greedy:!0,inside:a},s.languages.insertBefore("markup","cdata",r)}}),Object.defineProperty(s.languages.markup.tag,"addAttribute",{value:function(e,t){s.languages.markup.tag.inside["special-attr"].push({pattern:RegExp(/(^|["'\s])/.source+"(?:"+e+")"+/\s*=\s*(?:"[^"]*"|'[^']*'|[^\s'">=]+(?=[\s>]))/.source,"i"),lookbehind:!0,inside:{"attr-name":/^[^\s=]+/,"attr-value":{pattern:/=[\s\S]+/,inside:{value:{pattern:/(^=\s*(["']|(?!["'])))\S[\s\S]*(?=\2$)/,lookbehind:!0,alias:[t,"language-"+t],inside:s.languages[t]},punctuation:[{pattern:/^=/,alias:"attr-equals"},/"|'/]}}}})}}),s.languages.html=s.languages.markup,s.languages.mathml=s.languages.markup,s.languages.svg=s.languages.markup,s.languages.xml=s.languages.extend("markup",{}),s.languages.ssml=s.languages.xml,s.languages.atom=s.languages.xml,s.languages.rss=s.languages.xml,function(e){var t=/\/\*[\s\S]*?\*\/|\/\/.*|#(?!\[).*/,n=[{pattern:/\b(?:false|true)\b/i,alias:"boolean"},{pattern:/(::\s*)\b[a-z_]\w*\b(?!\s*\()/i,greedy:!0,lookbehind:!0},{pattern:/(\b(?:case|const)\s+)\b[a-z_]\w*(?=\s*[;=])/i,greedy:!0,lookbehind:!0},/\b(?:null)\b/i,/\b[A-Z_][A-Z0-9_]*\b(?!\s*\()/],a=/\b0b[01]+(?:_[01]+)*\b|\b0o[0-7]+(?:_[0-7]+)*\b|\b0x[\da-f]+(?:_[\da-f]+)*\b|(?:\b\d+(?:_\d+)*\.?(?:\d+(?:_\d+)*)?|\B\.\d+)(?:e[+-]?\d+)?/i,s=/|\?\?=?|\.{3}|\??->|[!=]=?=?|::|\*\*=?|--|\+\+|&&|\|\||<<|>>|[?~]|[/^|%*&<>.+-]=?/,r=/[{}\[\](),:;]/;e.languages.php={delimiter:{pattern:/\?>$|^<\?(?:php(?=\s)|=)?/i,alias:"important"},comment:t,variable:/\$+(?:\w+\b|(?=\{))/,package:{pattern:/(namespace\s+|use\s+(?:function\s+)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,lookbehind:!0,inside:{punctuation:/\\/}},"class-name-definition":{pattern:/(\b(?:class|enum|interface|trait)\s+)\b[a-z_]\w*(?!\\)\b/i,lookbehind:!0,alias:"class-name"},"function-definition":{pattern:/(\bfunction\s+)[a-z_]\w*(?=\s*\()/i,lookbehind:!0,alias:"function"},keyword:[{pattern:/(\(\s*)\b(?:array|bool|boolean|float|int|integer|object|string)\b(?=\s*\))/i,alias:"type-casting",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|object|self|static|string)\b(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b(?:array(?!\s*\()|bool|callable|(?:false|null)(?=\s*\|)|float|int|iterable|mixed|never|object|self|static|string|void)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/\b(?:array(?!\s*\()|bool|float|int|iterable|mixed|object|string|void)\b/i,alias:"type-declaration",greedy:!0},{pattern:/(\|\s*)(?:false|null)\b|\b(?:false|null)(?=\s*\|)/i,alias:"type-declaration",greedy:!0,lookbehind:!0},{pattern:/\b(?:parent|self|static)(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(\byield\s+)from\b/i,lookbehind:!0},/\bclass\b/i,{pattern:/((?:^|[^\s>:]|(?:^|[^-])>|(?:^|[^:]):)\s*)\b(?:abstract|and|array|as|break|callable|case|catch|clone|const|continue|declare|default|die|do|echo|else|elseif|empty|enddeclare|endfor|endforeach|endif|endswitch|endwhile|enum|eval|exit|extends|final|finally|fn|for|foreach|function|global|goto|if|implements|include|include_once|instanceof|insteadof|interface|isset|list|match|namespace|never|new|or|parent|print|private|protected|public|readonly|require|require_once|return|self|static|switch|throw|trait|try|unset|use|var|while|xor|yield|__halt_compiler)\b/i,lookbehind:!0}],"argument-name":{pattern:/([(,]\s*)\b[a-z_]\w*(?=\s*:(?!:))/i,lookbehind:!0},"class-name":[{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self|\s+static))\s+|\bcatch\s*\()\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/(\|\s*)\b[a-z_]\w*(?!\\)\b/i,greedy:!0,lookbehind:!0},{pattern:/\b[a-z_]\w*(?!\\)\b(?=\s*\|)/i,greedy:!0},{pattern:/(\|\s*)(?:\\?\b[a-z_]\w*)+\b/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(?:\\?\b[a-z_]\w*)+\b(?=\s*\|)/i,alias:"class-name-fully-qualified",greedy:!0,inside:{punctuation:/\\/}},{pattern:/(\b(?:extends|implements|instanceof|new(?!\s+self\b|\s+static\b))\s+|\bcatch\s*\()(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:"class-name-fully-qualified",greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*\$)/i,alias:"type-declaration",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-declaration"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/\b[a-z_]\w*(?=\s*::)/i,alias:"static-context",greedy:!0},{pattern:/(?:\\?\b[a-z_]\w*)+(?=\s*::)/i,alias:["class-name-fully-qualified","static-context"],greedy:!0,inside:{punctuation:/\\/}},{pattern:/([(,?]\s*)[a-z_]\w*(?=\s*\$)/i,alias:"type-hint",greedy:!0,lookbehind:!0},{pattern:/([(,?]\s*)(?:\\?\b[a-z_]\w*)+(?=\s*\$)/i,alias:["class-name-fully-qualified","type-hint"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}},{pattern:/(\)\s*:\s*(?:\?\s*)?)\b[a-z_]\w*(?!\\)\b/i,alias:"return-type",greedy:!0,lookbehind:!0},{pattern:/(\)\s*:\s*(?:\?\s*)?)(?:\\?\b[a-z_]\w*)+\b(?!\\)/i,alias:["class-name-fully-qualified","return-type"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:n,function:{pattern:/(^|[^\\\w])\\?[a-z_](?:[\w\\]*\w)?(?=\s*\()/i,lookbehind:!0,inside:{punctuation:/\\/}},property:{pattern:/(->\s*)\w+/,lookbehind:!0},number:a,operator:s,punctuation:r};var i={pattern:/\{\$(?:\{(?:\{[^{}]+\}|[^{}]+)\}|[^{}])+\}|(^|[^\\{])\$+(?:\w+(?:\[[^\r\n\[\]]+\]|->\w+)?)/,lookbehind:!0,inside:e.languages.php},o=[{pattern:/<<<'([^']+)'[\r\n](?:.*[\r\n])*?\1;/,alias:"nowdoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<'[^']+'|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<'?|[';]$/}}}},{pattern:/<<<(?:"([^"]+)"[\r\n](?:.*[\r\n])*?\1;|([a-z_]\w*)[\r\n](?:.*[\r\n])*?\2;)/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<<(?:"[^"]+"|[a-z_]\w*)|[a-z_]\w*;$/i,alias:"symbol",inside:{punctuation:/^<<<"?|[";]$/}},interpolation:i}},{pattern:/`(?:\\[\s\S]|[^\\`])*`/,alias:"backtick-quoted-string",greedy:!0},{pattern:/'(?:\\[\s\S]|[^\\'])*'/,alias:"single-quoted-string",greedy:!0},{pattern:/"(?:\\[\s\S]|[^\\"])*"/,alias:"double-quoted-string",greedy:!0,inside:{interpolation:i}}];e.languages.insertBefore("php","variable",{string:o,attribute:{pattern:/#\[(?:[^"'\/#]|\/(?![*/])|\/\/.*$|#(?!\[).*$|\/\*(?:[^*]|\*(?!\/))*\*\/|"(?:\\[\s\S]|[^\\"])*"|'(?:\\[\s\S]|[^\\'])*')+\](?=\s*[a-z$#])/im,greedy:!0,inside:{"attribute-content":{pattern:/^(#\[)[\s\S]+(?=\]$)/,lookbehind:!0,inside:{comment:t,string:o,"attribute-class-name":[{pattern:/([^:]|^)\b[a-z_]\w*(?!\\)\b/i,alias:"class-name",greedy:!0,lookbehind:!0},{pattern:/([^:]|^)(?:\\?\b[a-z_]\w*)+/i,alias:["class-name","class-name-fully-qualified"],greedy:!0,lookbehind:!0,inside:{punctuation:/\\/}}],constant:n,number:a,operator:s,punctuation:r}},delimiter:{pattern:/^#\[|\]$/,alias:"punctuation"}}}}),e.hooks.add("before-tokenize",(function(t){/<\?/.test(t.code)&&e.languages["markup-templating"].buildPlaceholders(t,"php",/<\?(?:[^"'/#]|\/(?![*/])|("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|(?:\/\/|#(?!\[))(?:[^?\n\r]|\?(?!>))*(?=$|\?>|[\r\n])|#\[|\/\*(?:[^*]|\*(?!\/))*(?:\*\/|$))*?(?:\?>|$)/g)})),e.hooks.add("after-tokenize",(function(t){e.languages["markup-templating"].tokenizePlaceholders(t,"php")}))}(s),s.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},s.languages.python["string-interpolation"].inside.interpolation.inside.rest=s.languages.python,s.languages.py=s.languages.python,function(e){e.languages.ruby=e.languages.extend("clike",{comment:{pattern:/#.*|^=begin\s[\s\S]*?^=end/m,greedy:!0},"class-name":{pattern:/(\b(?:class|module)\s+|\bcatch\s+\()[\w.\\]+|\b[A-Z_]\w*(?=\s*\.\s*new\b)/,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:BEGIN|END|alias|and|begin|break|case|class|def|define_method|defined|do|each|else|elsif|end|ensure|extend|for|if|in|include|module|new|next|nil|not|or|prepend|private|protected|public|raise|redo|require|rescue|retry|return|self|super|then|throw|undef|unless|until|when|while|yield)\b/,operator:/\.{2,3}|&\.|===||[!=]?~|(?:&&|\|\||<<|>>|\*\*|[+\-*/%<>!^&|=])=?|[?:]/,punctuation:/[(){}[\].,;]/}),e.languages.insertBefore("ruby","operator",{"double-colon":{pattern:/::/,alias:"punctuation"}});var t={pattern:/((?:^|[^\\])(?:\\{2})*)#\{(?:[^{}]|\{[^{}]*\})*\}/,lookbehind:!0,inside:{content:{pattern:/^(#\{)[\s\S]+(?=\}$)/,lookbehind:!0,inside:e.languages.ruby},delimiter:{pattern:/^#\{|\}$/,alias:"punctuation"}}};delete e.languages.ruby.function;var n="(?:"+[/([^a-zA-Z0-9\s{(\[<=])(?:(?!\1)[^\\]|\\[\s\S])*\1/.source,/\((?:[^()\\]|\\[\s\S]|\((?:[^()\\]|\\[\s\S])*\))*\)/.source,/\{(?:[^{}\\]|\\[\s\S]|\{(?:[^{}\\]|\\[\s\S])*\})*\}/.source,/\[(?:[^\[\]\\]|\\[\s\S]|\[(?:[^\[\]\\]|\\[\s\S])*\])*\]/.source,/<(?:[^<>\\]|\\[\s\S]|<(?:[^<>\\]|\\[\s\S])*>)*>/.source].join("|")+")",a=/(?:"(?:\\.|[^"\\\r\n])*"|(?:\b[a-zA-Z_]\w*|[^\s\0-\x7F]+)[?!]?|\$.)/.source;e.languages.insertBefore("ruby","keyword",{"regex-literal":[{pattern:RegExp(/%r/.source+n+/[egimnosux]{0,6}/.source),greedy:!0,inside:{interpolation:t,regex:/[\s\S]+/}},{pattern:/(^|[^/])\/(?!\/)(?:\[[^\r\n\]]+\]|\\.|[^[/\\\r\n])+\/[egimnosux]{0,6}(?=\s*(?:$|[\r\n,.;})#]))/,lookbehind:!0,greedy:!0,inside:{interpolation:t,regex:/[\s\S]+/}}],variable:/[@$]+[a-zA-Z_]\w*(?:[?!]|\b)/,symbol:[{pattern:RegExp(/(^|[^:]):/.source+a),lookbehind:!0,greedy:!0},{pattern:RegExp(/([\r\n{(,][ \t]*)/.source+a+/(?=:(?!:))/.source),lookbehind:!0,greedy:!0}],"method-definition":{pattern:/(\bdef\s+)\w+(?:\s*\.\s*\w+)?/,lookbehind:!0,inside:{function:/\b\w+$/,keyword:/^self\b/,"class-name":/^\w+/,punctuation:/\./}}}),e.languages.insertBefore("ruby","string",{"string-literal":[{pattern:RegExp(/%[qQiIwWs]?/.source+n),greedy:!0,inside:{interpolation:t,string:/[\s\S]+/}},{pattern:/("|')(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|(?!\1)[^\\#\r\n])*\1/,greedy:!0,inside:{interpolation:t,string:/[\s\S]+/}},{pattern:/<<[-~]?([a-z_]\w*)[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?[a-z_]\w*|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?/}},interpolation:t,string:/[\s\S]+/}},{pattern:/<<[-~]?'([a-z_]\w*)'[\r\n](?:.*[\r\n])*?[\t ]*\1/i,alias:"heredoc-string",greedy:!0,inside:{delimiter:{pattern:/^<<[-~]?'[a-z_]\w*'|\b[a-z_]\w*$/i,inside:{symbol:/\b\w+/,punctuation:/^<<[-~]?'|'$/}},string:/[\s\S]+/}}],"command-literal":[{pattern:RegExp(/%x/.source+n),greedy:!0,inside:{interpolation:t,command:{pattern:/[\s\S]+/,alias:"string"}}},{pattern:/`(?:#\{[^}]+\}|#(?!\{)|\\(?:\r\n|[\s\S])|[^\\`#\r\n])*`/,greedy:!0,inside:{interpolation:t,command:{pattern:/[\s\S]+/,alias:"string"}}}]}),delete e.languages.ruby.string,e.languages.insertBefore("ruby","number",{builtin:/\b(?:Array|Bignum|Binding|Class|Continuation|Dir|Exception|FalseClass|File|Fixnum|Float|Hash|IO|Integer|MatchData|Method|Module|NilClass|Numeric|Object|Proc|Range|Regexp|Stat|String|Struct|Symbol|TMS|Thread|ThreadGroup|Time|TrueClass)\b/,constant:/\b[A-Z][A-Z0-9_]*(?:[?!]|\b)/}),e.languages.rb=e.languages.ruby}(s),window.Prism=a,s}(),i=e=>t=>t.options.get(e),o=i("codesample_languages"),l=i("codesample_global_prismjs"),u=e=>s.Prism&&l(e)?s.Prism:r,c=e=>e&&"PRE"===e.nodeName&&-1!==e.className.indexOf("language-"),d=e=>{const t=e.selection?e.selection.getNode():null;return a=t,c(t)?n.some(a):n.none();var a},g=e=>{const s=(e=>o(e)||[{text:"HTML/XML",value:"markup"},{text:"JavaScript",value:"javascript"},{text:"CSS",value:"css"},{text:"PHP",value:"php"},{text:"Ruby",value:"ruby"},{text:"Python",value:"python"},{text:"Java",value:"java"},{text:"C",value:"c"},{text:"C#",value:"csharp"},{text:"C++",value:"cpp"}])(e),r=(c=s,((e,t)=>0e.value)),i=((e,t)=>d(e).fold((()=>t),(e=>{const n=e.className.match(/language-(\w+)/);return n?n[1]:t})))(e,r),l=(e=>d(e).fold(t(""),(e=>e.textContent)))(e);var c;e.windowManager.open({title:"Insert/Edit Code Sample",size:"large",body:{type:"panel",items:[{type:"selectbox",name:"language",label:"Language",items:s},{type:"textarea",name:"code",label:"Code view"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:{language:i,code:l},onSubmit:t=>{const n=t.getData();((e,t,n)=>{const s=e.dom;e.undoManager.transact((()=>{const r=d(e);return n=a.DOM.encode(n),r.fold((()=>{e.insertContent('
'+n+"
");const a=s.select("#__new")[0];s.setAttrib(a,"id",null),e.selection.select(a)}),(a=>{s.setAttrib(a,"class","language-"+t),a.innerHTML=n,u(e).highlightElement(a),e.selection.select(a)}))}))})(e,n.language,n.code),t.close()}})},p=(b=/^\s+|\s+$/g,e=>e.replace(b,""));var b,h=tinymce.util.Tools.resolve("tinymce.util.Tools");e.add("codesample",(e=>{(e=>{const t=e.options.register;t("codesample_languages",{processor:"object[]"}),t("codesample_global_prismjs",{processor:"boolean",default:!1})})(e),(e=>{e.on("PreProcess",(t=>{const n=e.dom,a=n.select("pre[contenteditable=false]",t.node);h.each(h.grep(a,c),(e=>{const t=e.textContent;let a;for(n.setAttrib(e,"class",p(n.getAttrib(e,"class"))),n.setAttrib(e,"contentEditable",null);a=e.firstChild;)e.removeChild(a);n.add(e,"code").textContent=t}))})),e.on("SetContent",(()=>{const t=e.dom,n=h.grep(t.select("pre"),(e=>c(e)&&"false"!==e.contentEditable));n.length&&e.undoManager.transact((()=>{h.each(n,(n=>{h.each(t.select("br",n),(t=>{t.parentNode.replaceChild(e.getDoc().createTextNode("\n"),t)})),n.contentEditable="false",n.innerHTML=t.encode(n.textContent),u(e).highlightElement(n),n.className=p(n.className)}))}))}))})(e),(e=>{const t=()=>e.execCommand("codesample");e.ui.registry.addToggleButton("codesample",{icon:"code-sample",tooltip:"Insert/edit code sample",onAction:t,onSetup:t=>{const n=()=>{t.setActive((e=>{const t=e.selection.getStart();return e.dom.is(t,'pre[class*="language-"]')})(e))};return e.on("NodeChange",n),()=>e.off("NodeChange",n)}}),e.ui.registry.addMenuItem("codesample",{text:"Code sample...",icon:"code-sample",onAction:t})})(e),(e=>{e.addCommand("codesample",(()=>{const t=e.selection.getNode();e.selection.isCollapsed()||c(t)?g(e):e.formatter.toggle("code")}))})(e),e.on("dblclick",(t=>{c(t.target)&&g(e)}))}))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/colorpicker/plugin.min.js b/public/libs/tinymce/plugins/colorpicker/plugin.min.js deleted file mode 100644 index f4c857c96..000000000 --- a/public/libs/tinymce/plugins/colorpicker/plugin.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) - */ -!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("colorpicker",function(){})}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/contextmenu/plugin.min.js b/public/libs/tinymce/plugins/contextmenu/plugin.min.js deleted file mode 100644 index 7a7f35893..000000000 --- a/public/libs/tinymce/plugins/contextmenu/plugin.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) - */ -!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("contextmenu",function(){})}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/directionality/plugin.min.js b/public/libs/tinymce/plugins/directionality/plugin.min.js index 82039cd79..d1c9b85c9 100644 --- a/public/libs/tinymce/plugins/directionality/plugin.min.js +++ b/public/libs/tinymce/plugins/directionality/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function n(t){return function(n){return typeof n===t}}function u(n){return function(){return n}}function t(n){return n}function r(){return d}var o,e=tinymce.util.Tools.resolve("tinymce.PluginManager"),i=function(n){return r=typeof(t=n),(null===t?"null":"object"==r&&(Array.prototype.isPrototypeOf(t)||t.constructor&&"Array"===t.constructor.name)?"array":"object"==r&&(String.prototype.isPrototypeOf(t)||t.constructor&&"String"===t.constructor.name)?"string":r)===o;var t,r},c=n("boolean"),f=n("function"),l=n("number"),a=u(!(o="string")),m=u(!0),d={fold:function(n,t){return n()},isSome:a,isNone:m,getOr:t,getOrThunk:s,getOrDie:function(n){throw new Error(n||"error: getOrDie called on none.")},getOrNull:u(null),getOrUndefined:u(void 0),or:t,orThunk:s,map:r,each:function(){},bind:r,exists:a,forall:m,filter:function(){return d},toArray:function(){return[]},toString:u("none()")};function s(n){return n()}function g(n,t){for(var r=0,o=n.length;re=>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{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),p=m(11),y=(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),N=t=>d(t.dom.host),b=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 p(o=e)&&n(o.dom.host)?a.some(e):a.none();var o})(d(e)).fold((()=>o.body.contains(e)),(r=b,i=N,t=>r(i(t))));var r,i},S=t=>"rtl"===((t,e)=>{const o=t.dom,r=window.getComputedStyle(o).getPropertyValue(e);return""!==r||b(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{const o=t.length,r=new Array(o);for(let n=0;nh(t,e))))(t),T=("li",t=>g(t)&&"li"===t.dom.nodeName.toLowerCase());const C=(t,e)=>{const n=t.selection.getSelectedBlocks();n.length>0&&(u(n,(t=>{const n=d(t),c=T(n),m=((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})(n,c);var f;(f=m,(t=>a.from(t.dom.parentNode).map(d))(f).filter(g)).each((t=>{if(S(t)!==e?((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)})(m,"dir",e):S(m)!==e&&y(m,"dir"),c){const t=A(m,"li[dir]");u(t,(t=>y(t,"dir")))}}))})),t.nodeChanged())},D=(t,e)=>o=>{const r=t=>{const r=d(t.element);o.setActive(S(r)===e)};return t.on("NodeChange",r),()=>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)}))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/fullpage/plugin.min.js b/public/libs/tinymce/plugins/fullpage/plugin.min.js deleted file mode 100644 index 9a7ae61f4..000000000 --- a/public/libs/tinymce/plugins/fullpage/plugin.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) - */ -!function(){"use strict";function i(e){var t=e;return{get:function(){return t},set:function(e){t=e}}}function _(e){return e.getParam("fullpage_hide_in_source_view")}function b(e){return e.getParam("fullpage_default_encoding")}function x(e){return e.getParam("fullpage_default_font_family")}function k(e){return e.getParam("fullpage_default_font_size")}function C(e,t){return n({validate:!1,root_name:"#document"},e.schema).parse(t,{format:"xhtml"})}function c(u,m){u.addCommand("mceFullPageProperties",function(){var l,i,o,e,t,n,r,a,c,s;function d(e,t){return e.attr(t)||""}t=l=u,n=(i=m).get(),c=C(t,n),(s={}).fontface=x(t),s.fontsize=k(t),7===(r=c.firstChild).type&&(s.xml_pi=!0,(a=/encoding="([^"]+)"/.exec(r.value))&&(s.docencoding=a[1])),(r=c.getAll("#doctype")[0])&&(s.doctype=""),(r=c.getAll("title")[0])&&r.firstChild&&(s.title=r.firstChild.value),w.each(c.getAll("meta"),function(e){var t,n=e.attr("name"),l=e.attr("http-equiv");n?s[n.toLowerCase()]=e.attr("content"):"Content-Type"===l&&(t=/charset\s*=\s*(.*)\s*/gi.exec(e.attr("content")))&&(s.docencoding=t[1])}),(r=c.getAll("html")[0])&&(s.langcode=d(r,"lang")||d(r,"xml:lang")),s.stylesheets=[],w.each(c.getAll("link"),function(e){"stylesheet"===e.attr("rel")&&s.stylesheets.push(e.attr("href"))}),(r=c.getAll("body")[0])&&(s.langdir=d(r,"dir"),s.style=d(r,"style"),s.visited_color=d(r,"vlink"),s.link_color=d(r,"link"),s.active_color=d(r,"alink")),o=s,e=g(g({},{title:"",keywords:"",description:"",robots:"",author:"",docencoding:""}),o),l.windowManager.open({title:"Metadata and Document Properties",size:"normal",body:{type:"panel",items:[{name:"title",type:"input",label:"Title"},{name:"keywords",type:"input",label:"Keywords"},{name:"description",type:"input",label:"Description"},{name:"robots",type:"input",label:"Robots"},{name:"author",type:"input",label:"Author"},{name:"docencoding",type:"input",label:"Encoding"}]},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:e,onSubmit:function(e){var t=e.getData(),n=function(e,o,t){function n(e,t,n){e.attr(t,n||void 0)}function r(e){s.firstChild?s.insert(e,s.firstChild):s.append(e)}var a,l,i=e.dom,c=C(e,t),s=c.getAll("head")[0];s||(a=c.getAll("html")[0],s=new f("head",1),a.firstChild?a.insert(s,a.firstChild,!0):a.append(s)),a=c.firstChild,o.xml_pi?(l='version="1.0"',o.docencoding&&(l+=' encoding="'+o.docencoding+'"'),7!==a.type&&(a=new f("xml",7),c.insert(a,c.firstChild,!0)),a.value=l):a&&7===a.type&&a.remove(),a=c.getAll("#doctype")[0],o.doctype?(a||(a=new f("#doctype",10),o.xml_pi?c.insert(a,c.firstChild):r(a)),a.value=o.doctype.substring(9,o.doctype.length-1)):a&&a.remove(),a=null,w.each(c.getAll("meta"),function(e){"Content-Type"===e.attr("http-equiv")&&(a=e)}),o.docencoding?(a||((a=new f("meta",1)).attr("http-equiv","Content-Type"),a.shortEnded=!0,r(a)),a.attr("content","text/html; charset="+o.docencoding)):a&&a.remove(),a=c.getAll("title")[0],o.title?(a?a.empty():r(a=new f("title",1)),a.append(new f("#text",3)).value=o.title):a&&a.remove(),w.each("keywords,description,author,copyright,robots".split(","),function(e){for(var t,n=c.getAll("meta"),l=o[e],i=0;i"))}(l,w.extend(o,t),i.get());i.set(n),e.close()}})})}function A(e){return e.replace(/<\/?[A-Z]+/g,function(e){return e.toLowerCase()})}function s(e,t,n,l){var i,o,r,a,c,s,d,u,m,g,f,p,h,y="",v=e.dom;l.selection||(a=e.getParam("protect"),c=l.content,w.each(a,function(e){c=c.replace(e,function(e){return"\x3c!--mce:protected "+escape(e)+"--\x3e"})}),r=c,"raw"===l.format&&t.get()||l.source_view&&_(e)||(-1!==(i=(r=(r=0!==r.length||l.source_view?r:w.trim(t.get())+"\n"+w.trim(r)+"\n"+w.trim(n.get())).replace(/<(\/?)BODY/gi,"<$1body")).indexOf("",i),t.set(A(r.substring(0,i+1))),-1===(o=r.indexOf("\n'),p+=g.getParam("fullpage_default_doctype",""),p+="\n\n\n",(f=g.getParam("fullpage_default_title"))&&(p+=""+f+"\n"),(f=b(g))&&(p+='\n'),(f=x(g))&&(h+="font-family: "+f+";"),(f=k(g))&&(h+="font-size: "+f+";"),(f=g.getParam("fullpage_default_text_color"))&&(h+="color: "+f+";"),p+="\n\n")),n.set("\n\n")),s=C(e,t.get()),P(s.getAll("style"),function(e){e.firstChild&&(y+=e.firstChild.value)}),(d=s.getAll("body")[0])&&v.setAttribs(e.getBody(),{style:d.attr("style")||"",dir:d.attr("dir")||"",vLink:d.attr("vlink")||"",link:d.attr("link")||"",aLink:d.attr("alink")||""}),v.remove("fullpage_styles"),u=e.getDoc().getElementsByTagName("head")[0],y&&v.add(u,"style",{id:"fullpage_styles"}).appendChild(document.createTextNode(y)),m={},w.each(u.getElementsByTagName("link"),function(e){"stylesheet"===e.rel&&e.getAttribute("data-mce-fullpage")&&(m[e.href]=e)}),w.each(s.getAll("link"),function(e){var t=e.attr("href");if(!t)return!0;m[t]||"stylesheet"!==e.attr("rel")||v.add(u,"link",{rel:"stylesheet",text:"text/css",href:t,"data-mce-fullpage":"1"}),delete m[t]}),w.each(m,function(e){e.parentNode.removeChild(e)})))}var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),g=function(){return(g=Object.assign||function(e){for(var t,n=1,l=arguments.length;n/g,function(e,t){return unescape(t)}))})})}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/fullscreen/plugin.min.js b/public/libs/tinymce/plugins/fullscreen/plugin.min.js index bb226baf1..4ec2cc3e4 100644 --- a/public/libs/tinymce/plugins/fullscreen/plugin.min.js +++ b/public/libs/tinymce/plugins/fullscreen/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function a(e){var n=e;return{get:function(){return n},set:function(e){n=e}}}function e(t){return function(e){return r=typeof(n=e),(null===n?"null":"object"==r&&(Array.prototype.isPrototypeOf(n)||n.constructor&&"Array"===n.constructor.name)?"array":"object"==r&&(String.prototype.isPrototypeOf(n)||n.constructor&&"String"===n.constructor.name)?"string":r)===t;var n,r}}function n(n){return function(e){return typeof e===n}}function c(e){return!(null==e)}function s(){}function y(e){return function(){return e}}function r(e){return e}var t=tinymce.util.Tools.resolve("tinymce.PluginManager"),l=e("string"),d=e("array"),o=n("boolean"),h=n("function"),i=n("number");function u(){return m}var v=y(!1),f=y(!0),m={fold:function(e,n){return e()},isSome:v,isNone:f,getOr:r,getOrThunk:g,getOrDie:function(e){throw new Error(e||"error: getOrDie called on none.")},getOrNull:y(null),getOrUndefined:y(void 0),or:r,orThunk:g,map:u,each:s,bind:u,exists:v,forall:f,filter:function(){return m},toArray:function(){return[]},toString:y("none()")};function g(e){return e()}function p(e){function n(){return r.get().each(e)}var r=a(A.none());return{clear:function(){n(),r.set(A.none())},isSet:function(){return r.get().isSome()},get:function(){return r.get()},set:function(e){n(),r.set(A.some(e))}}}function w(){return p(function(e){return e.unbind()})}function C(e,n){for(var r=e.length,t=new Array(r),o=0;o{let t=e;return{get:()=>t,set:e=>{t=e}}};var t=tinymce.util.Tools.resolve("tinymce.PluginManager");const n=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=r=e,(o=String).prototype.isPrototypeOf(n)||(null===(s=r.constructor)||void 0===s?void 0:s.name)===o.name)?"string":t;var n,r,o,s})(t)===e,r=e=>t=>typeof t===e,o=n("string"),s=n("array"),i=(null,e=>null===e);const l=r("boolean"),a=e=>!(e=>null==e)(e),c=r("function"),u=r("number"),d=()=>{},m=e=>()=>e;function h(e,...t){return(...n)=>{const r=t.concat(n);return e.apply(null,r)}}const g=m(!1),p=m(!0);class f{constructor(e,t){this.tag=e,this.value=t}static some(e){return new f(!0,e)}static none(){return f.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?f.some(e(this.value)):f.none()}bind(e){return this.tag?e(this.value):f.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:f.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return a(e)?f.some(e):f.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}f.singletonNone=new f(!1);const v=t=>{const n=e(f.none()),r=()=>n.get().each(t);return{clear:()=>{r(),n.set(f.none())},isSet:()=>n.get().isSome(),get:()=>n.get(),set:e=>{r(),n.set(f.some(e))}}},w=()=>v((e=>e.unbind())),y=Array.prototype.push,b=(e,t)=>{const n=e.length,r=new Array(n);for(let o=0;o{for(let n=0,r=e.length;n{const n=[];for(let r=0,o=e.length;r((e,t,n)=>{for(let r=0,o=e.length;r-1!==e.indexOf(t),T=e=>void 0!==e.style&&c(e.style.getPropertyValue),k=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},C=k;"undefined"!=typeof window?window:Function("return this;")();const A=e=>t=>(e=>e.dom.nodeType)(t)===e,R=A(1),L=A(3),M=A(9),N=A(11),P=(e,t)=>{const n=e.dom;if(1!==n.nodeType)return!1;{const e=n;if(void 0!==e.matches)return e.matches(t);if(void 0!==e.msMatchesSelector)return e.msMatchesSelector(t);if(void 0!==e.webkitMatchesSelector)return e.webkitMatchesSelector(t);if(void 0!==e.mozMatchesSelector)return e.mozMatchesSelector(t);throw new Error("Browser lacks native selectors")}},D=e=>C(e.dom.ownerDocument),W=e=>b(e.dom.childNodes,C),q=c(Element.prototype.attachShadow)&&c(Node.prototype.getRootNode),H=m(q),I=q?e=>C(e.dom.getRootNode()):e=>M(e)?e:D(e),B=e=>{const t=I(e);return N(n=t)&&a(n.dom.host)?f.some(t):f.none();var n},V=e=>C(e.dom.host),_=e=>{const t=L(e)?e.dom.parentNode:e.dom;if(null==t||null===t.ownerDocument)return!1;const n=t.ownerDocument;return B(C(t)).fold((()=>n.body.contains(t)),(r=_,o=V,e=>r(o(e))));var r,o},j=(e,t)=>{const n=e.dom.getAttribute(t);return null===n?void 0:n},z=(e,t)=>{e.dom.removeAttribute(t)},$=(e,t)=>{const n=e.dom;((e,t)=>{const n=F(e);for(let r=0,o=n.length;r{((e,t,n)=>{if(!o(n))throw console.error("Invalid call to CSS.set. Property ",t,":: Value ",n,":: Element ",e),new Error("CSS value must be a string: "+n);T(e)&&e.style.setProperty(t,n)})(n,t,e)}))},U=e=>{const t=C((e=>{if(H()&&a(e.target)){const t=C(e.target);if(R(t)&&a(t.dom.shadowRoot)&&e.composed&&e.composedPath){const t=e.composedPath();if(t)return((e,t)=>0e.stopPropagation(),r=()=>e.preventDefault(),o=(s=r,i=n,(...e)=>s(i.apply(null,e)));var s,i;return((e,t,n,r,o,s,i)=>({target:e,x:t,y:n,stop:r,prevent:o,kill:s,raw:i}))(t,e.clientX,e.clientY,n,r,o,e)},K=(e,t,n,r)=>{e.dom.removeEventListener(t,n,r)},X=p,Y=(e,t,n)=>((e,t,n,r)=>((e,t,n,r,o)=>{const s=((e,t)=>n=>{e(n)&&t(U(n))})(n,r);return e.dom.addEventListener(t,s,o),{unbind:h(K,e,t,s,o)}})(e,t,n,r,!1))(e,t,X,n),G=()=>J(0,0),J=(e,t)=>({major:e,minor:t}),Q={nu:J,detect:(e,t)=>{const n=String(t).toLowerCase();return 0===e.length?G():((e,t)=>{const n=((e,t)=>{for(let n=0;nNumber(t.replace(n,"$"+e));return J(r(1),r(2))})(e,n)},unknown:G},Z=(e,t)=>{const n=String(t).toLowerCase();return E(e,(e=>e.search(n)))},ee=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,te=e=>t=>O(t,e),ne=[{name:"Edge",versionRegexes:[/.*?edge\/ ?([0-9]+)\.([0-9]+)$/],search:e=>O(e,"edge/")&&O(e,"chrome")&&O(e,"safari")&&O(e,"applewebkit")},{name:"Chromium",brand:"Chromium",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,ee],search:e=>O(e,"chrome")&&!O(e,"chromeframe")},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/,/.*?rv:([0-9]+)\.([0-9]+).*/],search:e=>O(e,"msie")||O(e,"trident")},{name:"Opera",versionRegexes:[ee,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:te("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:te("firefox")},{name:"Safari",versionRegexes:[ee,/.*?cpu os ([0-9]+)_([0-9]+).*/],search:e=>(O(e,"safari")||O(e,"mobile/"))&&O(e,"applewebkit")}],re=[{name:"Windows",search:te("win"),versionRegexes:[/.*?windows\ nt\ ?([0-9]+)\.([0-9]+).*/]},{name:"iOS",search:e=>O(e,"iphone")||O(e,"ipad"),versionRegexes:[/.*?version\/\ ?([0-9]+)\.([0-9]+).*/,/.*cpu os ([0-9]+)_([0-9]+).*/,/.*cpu iphone os ([0-9]+)_([0-9]+).*/]},{name:"Android",search:te("android"),versionRegexes:[/.*?android\ ?([0-9]+)\.([0-9]+).*/]},{name:"macOS",search:te("mac os x"),versionRegexes:[/.*?mac\ os\ x\ ?([0-9]+)_([0-9]+).*/]},{name:"Linux",search:te("linux"),versionRegexes:[]},{name:"Solaris",search:te("sunos"),versionRegexes:[]},{name:"FreeBSD",search:te("freebsd"),versionRegexes:[]},{name:"ChromeOS",search:te("cros"),versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/]}],oe={browsers:m(ne),oses:m(re)},se="Edge",ie="Chromium",le="Opera",ae="Firefox",ce="Safari",ue=e=>{const t=e.current,n=e.version,r=e=>()=>t===e;return{current:t,version:n,isEdge:r(se),isChromium:r(ie),isIE:r("IE"),isOpera:r(le),isFirefox:r(ae),isSafari:r(ce)}},de=()=>ue({current:void 0,version:Q.unknown()}),me=ue,he=(m(se),m(ie),m("IE"),m(le),m(ae),m(ce),"Windows"),ge="Android",pe="Linux",fe="macOS",ve="Solaris",we="FreeBSD",ye="ChromeOS",be=e=>{const t=e.current,n=e.version,r=e=>()=>t===e;return{current:t,version:n,isWindows:r(he),isiOS:r("iOS"),isAndroid:r(ge),isMacOS:r(fe),isLinux:r(pe),isSolaris:r(ve),isFreeBSD:r(we),isChromeOS:r(ye)}},Se=()=>be({current:void 0,version:Q.unknown()}),xe=be,Ee=(m(he),m("iOS"),m(ge),m(pe),m(fe),m(ve),m(we),m(ye),(e,t,n)=>{const r=oe.browsers(),o=oe.oses(),s=t.bind((e=>((e,t)=>((e,t)=>{for(let n=0;n{const n=t.brand.toLowerCase();return E(e,(e=>{var t;return n===(null===(t=e.brand)||void 0===t?void 0:t.toLowerCase())})).map((e=>({current:e.name,version:Q.nu(parseInt(t.version,10),0)})))})))(r,e))).orThunk((()=>((e,t)=>Z(e,t).map((e=>{const n=Q.detect(e.versionRegexes,t);return{current:e.name,version:n}})))(r,e))).fold(de,me),i=((e,t)=>Z(e,t).map((e=>{const n=Q.detect(e.versionRegexes,t);return{current:e.name,version:n}})))(o,e).fold(Se,xe),l=((e,t,n,r)=>{const o=e.isiOS()&&!0===/ipad/i.test(n),s=e.isiOS()&&!o,i=e.isiOS()||e.isAndroid(),l=i||r("(pointer:coarse)"),a=o||!s&&i&&r("(min-device-width:768px)"),c=s||i&&!a,u=t.isSafari()&&e.isiOS()&&!1===/safari/i.test(n),d=!c&&!a&&!u;return{isiPad:m(o),isiPhone:m(s),isTablet:m(a),isPhone:m(c),isTouch:m(l),isAndroid:e.isAndroid,isiOS:e.isiOS,isWebView:m(u),isDesktop:m(d)}})(i,s,e,n);return{browser:s,os:i,deviceType:l}}),Fe=e=>window.matchMedia(e).matches;let Oe=(e=>{let t,n=!1;return(...r)=>(n||(n=!0,t=e.apply(null,r)),t)})((()=>Ee(navigator.userAgent,f.from(navigator.userAgentData),Fe)));const Te=(e,t)=>({left:e,top:t,translate:(n,r)=>Te(e+n,t+r)}),ke=Te,Ce=e=>{const t=void 0===e?window:e;return Oe().browser.isFirefox()?f.none():f.from(t.visualViewport)},Ae=(e,t,n,r)=>({x:e,y:t,width:n,height:r,right:e+n,bottom:t+r}),Re=e=>{const t=void 0===e?window:e,n=t.document,r=(e=>{const t=void 0!==e?e.dom:document,n=t.body.scrollLeft||t.documentElement.scrollLeft,r=t.body.scrollTop||t.documentElement.scrollTop;return ke(n,r)})(C(n));return Ce(t).fold((()=>{const e=t.document.documentElement,n=e.clientWidth,o=e.clientHeight;return Ae(r.left,r.top,n,o)}),(e=>Ae(Math.max(e.pageLeft,r.left),Math.max(e.pageTop,r.top),e.width,e.height)))},Le=(e,t,n)=>Ce(n).map((n=>{const r=e=>t(U(e));return n.addEventListener(e,r),{unbind:()=>n.removeEventListener(e,r)}})).getOrThunk((()=>({unbind:d})));var Me=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),Ne=tinymce.util.Tools.resolve("tinymce.Env");const Pe=(e,t)=>{e.dispatch("FullscreenStateChanged",{state:t}),e.dispatch("ResizeEditor")},De=("fullscreen_native",e=>e.options.get("fullscreen_native"));const We=e=>{return e.dom===(void 0!==(t=D(e).dom).fullscreenElement?t.fullscreenElement:void 0!==t.msFullscreenElement?t.msFullscreenElement:void 0!==t.webkitFullscreenElement?t.webkitFullscreenElement:null);var t},qe=(e,t,n)=>((e,t,n)=>x(((e,t)=>{const n=c(t)?t:g;let r=e.dom;const o=[];for(;null!==r.parentNode&&void 0!==r.parentNode;){const e=r.parentNode,t=C(e);if(o.push(t),!0===n(t))break;r=e}return o})(e,n),t))(e,(e=>P(e,t)),n),He=(e,t)=>((e,n)=>{return x((e=>f.from(e.dom.parentNode).map(C))(r=e).map(W).map((e=>x(e,(e=>{return t=e,!(r.dom===t.dom);var t})))).getOr([]),(e=>P(e,t)));var r})(e),Ie="data-ephox-mobile-fullscreen-style",Be="position:absolute!important;",Ve="top:0!important;left:0!important;margin:0!important;padding:0!important;width:100%!important;height:100%!important;overflow:visible!important;",_e=Ne.os.isAndroid(),je=e=>{const t=((e,t)=>{const n=e.dom,r=window.getComputedStyle(n).getPropertyValue(t);return""!==r||_(e)?r:((e,t)=>T(e)?e.style.getPropertyValue(t):"")(n,t)})(e,"background-color");return void 0!==t&&""!==t?"background-color:"+t+"!important":"background-color:rgb(255,255,255)!important;"},ze=Me.DOM,$e=Ce().fold((()=>({bind:d,unbind:d})),(e=>{const t=(()=>{const e=v(d);return{...e,on:t=>e.get().each(t)}})(),n=w(),r=w(),o=((e,t)=>{let n=null;return{cancel:()=>{i(n)||(clearTimeout(n),n=null)},throttle:(...t)=>{i(n)&&(n=setTimeout((()=>{n=null,e.apply(null,t)}),50))}}})((()=>{document.body.scrollTop=0,document.documentElement.scrollTop=0,window.requestAnimationFrame((()=>{t.on((t=>$(t,{top:e.offsetTop+"px",left:e.offsetLeft+"px",height:e.height+"px",width:e.width+"px"})))}))}));return{bind:e=>{t.set(e),o.throttle(),n.set(Le("resize",o.throttle)),r.set(Le("scroll",o.throttle))},unbind:()=>{t.on((()=>{n.clear(),r.clear()})),t.clear()}}})),Ue=(e,t)=>{const n=document.body,r=document.documentElement,i=e.getContainer(),a=C(i),c=(e=>{const t=C(e.getElement());return B(t).map(V).getOrThunk((()=>(e=>{const t=e.dom.body;if(null==t)throw new Error("Body is not available yet");return C(t)})(D(t))))})(e),d=t.get(),m=C(e.getBody()),h=Ne.deviceType.isTouch(),g=i.style,p=e.iframeElement.style,v=e=>{e(n,"tox-fullscreen"),e(r,"tox-fullscreen"),e(i,"tox-fullscreen"),B(a).map((e=>V(e).dom)).each((t=>{e(t,"tox-fullscreen"),e(t,"tox-shadowhost")}))},w=()=>{h&&(e=>{const t=((e,t)=>{const n=document;return 1!==(r=n).nodeType&&9!==r.nodeType&&11!==r.nodeType||0===r.childElementCount?[]:b(n.querySelectorAll(e),C);var r})("["+Ie+"]");S(t,(t=>{const n=j(t,Ie);"no-styles"!==n?$(t,e.parseStyle(n)):z(t,"style"),z(t,Ie)}))})(e.dom),v(ze.removeClass),$e.unbind(),f.from(t.get()).each((e=>e.fullscreenChangeHandler.unbind()))};if(d)d.fullscreenChangeHandler.unbind(),De(e)&&We(c)&&(e=>{const t=e.dom;t.exitFullscreen?t.exitFullscreen():t.msExitFullscreen?t.msExitFullscreen():t.webkitCancelFullScreen&&t.webkitCancelFullScreen()})(D(c)),p.width=d.iframeWidth,p.height=d.iframeHeight,g.width=d.containerWidth,g.height=d.containerHeight,g.top=d.containerTop,g.left=d.containerLeft,w(),x=d.scrollPos,window.scrollTo(x.x,x.y),t.set(null),Pe(e,!1),e.off("remove",w);else{const n=Y(D(c),void 0!==document.fullscreenElement?"fullscreenchange":void 0!==document.msFullscreenElement?"MSFullscreenChange":void 0!==document.webkitFullscreenElement?"webkitfullscreenchange":"fullscreenchange",(n=>{De(e)&&(We(c)||null===t.get()||Ue(e,t))})),r={scrollPos:Re(window),containerWidth:g.width,containerHeight:g.height,containerTop:g.top,containerLeft:g.left,iframeWidth:p.width,iframeHeight:p.height,fullscreenChangeHandler:n};h&&((e,t,n)=>{const r=t=>n=>{const r=j(n,"style"),s=void 0===r?"no-styles":r.trim();s!==t&&(((e,t,n)=>{((e,t,n)=>{if(!(o(n)||l(n)||u(n)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",n,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,n+"")})(e.dom,t,n)})(n,Ie,s),$(n,e.parseStyle(t)))},i=qe(t,"*"),a=(e=>{const t=[];for(let n=0,r=e.length;nHe(e,"*:not(.tox-silver-sink)")))),c=je(n);S(a,r("display:none!important;")),S(i,r(Be+Ve+c)),r((!0===_e?"":Be)+Ve+c)(t)})(e.dom,a,m),p.width=p.height="100%",g.width=g.height="",v(ze.addClass),$e.bind(a),e.on("remove",w),t.set(r),De(e)&&(e=>{const t=e.dom;t.requestFullscreen?t.requestFullscreen():t.msRequestFullscreen?t.msRequestFullscreen():t.webkitRequestFullScreen&&t.webkitRequestFullScreen()})(c),Pe(e,!0)}var x},Ke=(e,t)=>n=>{n.setActive(null!==t.get());const r=e=>n.setActive(e.state);return e.on("FullscreenStateChanged",r),()=>e.off("FullscreenStateChanged",r)};t.add("fullscreen",(t=>{const n=e(null);return t.inline||((e=>{(0,e.options.register)("fullscreen_native",{processor:"boolean",default:!1})})(t),((e,t)=>{e.addCommand("mceFullScreen",(()=>{Ue(e,t)}))})(t,n),((e,t)=>{const n=()=>e.execCommand("mceFullScreen");e.ui.registry.addToggleMenuItem("fullscreen",{text:"Fullscreen",icon:"fullscreen",shortcut:"Meta+Shift+F",onAction:n,onSetup:Ke(e,t)}),e.ui.registry.addToggleButton("fullscreen",{tooltip:"Fullscreen",icon:"fullscreen",onAction:n,onSetup:Ke(e,t)})})(t,n),t.addShortcut("Meta+Shift+F","","mceFullScreen")),(e=>({isFullscreen:()=>null!==e.get()}))(n)}))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/help/plugin.min.js b/public/libs/tinymce/plugins/help/plugin.min.js index 5adf025bd..0479d2788 100644 --- a/public/libs/tinymce/plugins/help/plugin.min.js +++ b/public/libs/tinymce/plugins/help/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function i(e){return function(){return e}}function e(e){return e}function t(){return s}var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),g=function(){return(g=Object.assign||function(e){for(var t,n=1,a=arguments.length;n'+e.name+""}var t,o,n,i,r,s,l,c;return{name:"plugins",title:"Plugins",items:[{type:"htmlpanel",presets:"document",html:[null==e?"":'
'+(s=b((i=w((n=o=e).plugins),void 0===(r=n.getParam("forced_plugins"))?i:m(i,function(e){return!(-1"+(t=o,n=e,function(e,t,n){for(var a=0,o=e.length;a";var t,n}),l=s.length,c=s.join(""),"

"+T.translate(["Plugins installed ({0}):",l])+"

    "+c+"
")+"
",(t=b(m(d,function(e){var t=e.key,n=e.type;return"autocorrect"!==t&&"premium"===n}),function(e){return"
  • "+T.translate(e.name)+"
  • "}).join(""),'

    '+T.translate("Premium plugins:")+"

    ")].join("")}]}}function l(d,y){return function(){var e,t,n,a,o,i,r,s,l,c,u,m=(e=d,t=y,r={name:"shortcuts",title:"Handy Shortcuts",items:[{type:"table",header:["Action","Shortcut"],cells:b(x,function(e){var t=b(e.shortcuts,f).join(" or ");return[e.action,t]})}]},s={name:"keyboardnav",title:"Keyboard Navigation",items:[{type:"htmlpanel",presets:"document",html:"

    Editor UI keyboard navigation

    \n\n

    Activating keyboard navigation

    \n\n

    The sections of the outer UI of the editor - the menubar, toolbar, sidebar and footer - are all keyboard navigable. As such, there are multiple ways to activate keyboard navigation:

    \n
      \n
    • Focus the menubar: Alt + F9 (Windows) or ⌥F9 (MacOS)
    • \n
    • Focus the toolbar: Alt + F10 (Windows) or ⌥F10 (MacOS)
    • \n
    • Focus the footer: Alt + F11 (Windows) or ⌥F11 (MacOS)
    • \n
    \n\n

    Focusing the menubar or toolbar will start keyboard navigation at the first item in the menubar or toolbar, which will be highlighted with a gray background. Focusing the footer will start keyboard navigation at the first item in the element path, which will be highlighted with an underline.

    \n\n

    Moving between UI sections

    \n\n

    When keyboard navigation is active, pressing tab will move the focus to the next major section of the UI, where applicable. These sections are:

    \n
      \n
    • the menubar
    • \n
    • each group of the toolbar
    • \n
    • the sidebar
    • \n
    • the element path in the footer
    • \n
    • the wordcount toggle button in the footer
    • \n
    • the branding link in the footer
    • \n
    • the editor resize handle in the footer
    • \n
    \n\n

    Pressing shift + tab will move backwards through the same sections, except when moving from the footer to the toolbar. Focusing the element path then pressing shift + tab will move focus to the first toolbar group, not the last.

    \n\n

    Moving within UI sections

    \n\n

    Keyboard navigation within UI sections can usually be achieved using the left and right arrow keys. This includes:

    \n
      \n
    • moving between menus in the menubar
    • \n
    • moving between buttons in a toolbar group
    • \n
    • moving between items in the element path
    • \n
    \n\n

    In all these UI sections, keyboard navigation will cycle within the section. For example, focusing the last button in a toolbar group then pressing right arrow will move focus to the first item in the same toolbar group.

    \n\n

    Executing buttons

    \n\n

    To execute a button, navigate the selection to the desired button and hit space or enter.

    \n\n

    Opening, navigating and closing menus

    \n\n

    When focusing a menubar button or a toolbar button with a menu, pressing space, enter or down arrow will open the menu. When the menu opens the first item will be selected. To move up or down the menu, press the up or down arrow key respectively. This is the same for submenus, which can also be opened and closed using the left and right arrow keys.

    \n\n

    To close any active menu, hit the escape key. When a menu is closed the selection will be restored to its previous selection. This also works for closing submenus.

    \n\n

    Context toolbars and menus

    \n\n

    To focus an open context toolbar such as the table context toolbar, press Ctrl + F9 (Windows) or ⌃F9 (MacOS).

    \n\n

    Context toolbar navigation is the same as toolbar navigation, and context menu navigation is the same as standard menu navigation.

    \n\n

    Dialog navigation

    \n\n

    There are two types of dialog UIs in TinyMCE: tabbed dialogs and non-tabbed dialogs.

    \n\n

    When a non-tabbed dialog is opened, the first interactive component in the dialog will be focused. Users can navigate between interactive components by pressing tab. This includes any footer buttons. Navigation will cycle back to the first dialog component if tab is pressed while focusing the last component in the dialog. Pressing shift + tab will navigate backwards.

    \n\n

    When a tabbed dialog is opened, the first button in the tab menu is focused. Pressing tab will navigate to the first interactive component in that tab, and will cycle through the tab\u2019s components, the footer buttons, then back to the tab button. To switch to another tab, focus the tab button for the current tab, then use the arrow keys to cycle through the tab buttons.

    "}]},l=k(e),a=C.majorVersion,o=C.minorVersion,i=0===a.indexOf("@")?"X.X.X":a+"."+o,c={name:"versions",title:"Version",items:[{type:"htmlpanel",html:"

    "+T.translate(["You are using {0}",'TinyMCE '+i+""])+"

    ",presets:"document"}]},u=g(((n={})[r.name]=r,n[s.name]=s,n[l.name]=l,n[c.name]=c,n),t.get()),v.from(e.getParam("help_tabs")).fold(function(){return-1!==(n=(t=w(e=u)).indexOf("versions"))&&(t.splice(n,1),t.push("versions")),{tabs:e,names:t};var e,t,n},function(e){return t=u,n={},a=b(e,function(e){return"string"==typeof e?(A(t,e)&&(n[e]=t[e]),e):(n[e.name]=e).name}),{tabs:n,names:a};var t,n,a})),h=m.tabs,p=function(e){for(var t=[],n=function(e){t.push(e)},a=0;at=>t.options.get(e),n=t("help_tabs"),a=t("forced_plugins"),o=(void 0,e=>undefined===e);const i=(!1,()=>false);class r{constructor(e,t){this.tag=e,this.value=t}static some(e){return new r(!0,e)}static none(){return r.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?r.some(e(this.value)):r.none()}bind(e){return this.tag?e(this.value):r.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:r.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return null==e?r.none():r.some(e)}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}r.singletonNone=new r(!1);const s=Array.prototype.indexOf,l=(e,t)=>{const n=e.length,a=new Array(n);for(let o=0;o{const n=[];for(let a=0,o=e.length;ah.call(e,t);var p=tinymce.util.Tools.resolve("tinymce.Env");const d=e=>{const t=p.os.isMacOS()||p.os.isiOS(),n=t?{alt:"⌥",ctrl:"⌃",shift:"⇧",meta:"⌘",access:"⌃⌥"}:{meta:"Ctrl ",access:"Shift + Alt "},a=e.split("+"),o=l(a,(e=>{const t=e.toLowerCase().trim();return m(n,t)?n[t]:e}));return t?o.join("").replace(/\s/,""):o.join("+")},g=[{shortcuts:["Meta + B"],action:"Bold"},{shortcuts:["Meta + I"],action:"Italic"},{shortcuts:["Meta + U"],action:"Underline"},{shortcuts:["Meta + A"],action:"Select all"},{shortcuts:["Meta + Y","Meta + Shift + Z"],action:"Redo"},{shortcuts:["Meta + Z"],action:"Undo"},{shortcuts:["Access + 1"],action:"Heading 1"},{shortcuts:["Access + 2"],action:"Heading 2"},{shortcuts:["Access + 3"],action:"Heading 3"},{shortcuts:["Access + 4"],action:"Heading 4"},{shortcuts:["Access + 5"],action:"Heading 5"},{shortcuts:["Access + 6"],action:"Heading 6"},{shortcuts:["Access + 7"],action:"Paragraph"},{shortcuts:["Access + 8"],action:"Div"},{shortcuts:["Access + 9"],action:"Address"},{shortcuts:["Alt + 0"],action:"Open help dialog"},{shortcuts:["Alt + F9"],action:"Focus to menubar"},{shortcuts:["Alt + F10"],action:"Focus to toolbar"},{shortcuts:["Alt + F11"],action:"Focus to element path"},{shortcuts:["Ctrl + F9"],action:"Focus to contextual toolbar"},{shortcuts:["Shift + Enter"],action:"Open popup menu for split buttons"},{shortcuts:["Meta + K"],action:"Insert link (if link plugin activated)"},{shortcuts:["Meta + S"],action:"Save (if save plugin activated)"},{shortcuts:["Meta + F"],action:"Find (if searchreplace plugin activated)"},{shortcuts:["Meta + Shift + F"],action:"Switch to or from fullscreen mode"}],y=()=>({name:"shortcuts",title:"Handy Shortcuts",items:[{type:"table",header:["Action","Shortcut"],cells:l(g,(e=>{const t=l(e.shortcuts,d).join(" or ");return[e.action,t]}))}]});var b=tinymce.util.Tools.resolve("tinymce.util.I18n");const k=l([{key:"advlist",name:"Advanced List"},{key:"anchor",name:"Anchor"},{key:"autolink",name:"Autolink"},{key:"autoresize",name:"Autoresize"},{key:"autosave",name:"Autosave"},{key:"charmap",name:"Character Map"},{key:"code",name:"Code"},{key:"codesample",name:"Code Sample"},{key:"colorpicker",name:"Color Picker"},{key:"directionality",name:"Directionality"},{key:"emoticons",name:"Emoticons"},{key:"fullscreen",name:"Full Screen"},{key:"help",name:"Help"},{key:"image",name:"Image"},{key:"importcss",name:"Import CSS"},{key:"insertdatetime",name:"Insert Date/Time"},{key:"link",name:"Link"},{key:"lists",name:"Lists"},{key:"media",name:"Media"},{key:"nonbreaking",name:"Nonbreaking"},{key:"pagebreak",name:"Page Break"},{key:"preview",name:"Preview"},{key:"quickbars",name:"Quick Toolbars"},{key:"save",name:"Save"},{key:"searchreplace",name:"Search and Replace"},{key:"table",name:"Table"},{key:"template",name:"Template"},{key:"textcolor",name:"Text Color"},{key:"visualblocks",name:"Visual Blocks"},{key:"visualchars",name:"Visual Characters"},{key:"wordcount",name:"Word Count"},{key:"a11ychecker",name:"Accessibility Checker",type:"premium"},{key:"advcode",name:"Advanced Code Editor",type:"premium"},{key:"advtable",name:"Advanced Tables",type:"premium"},{key:"autocorrect",name:"Autocorrect",type:"premium"},{key:"casechange",name:"Case Change",type:"premium"},{key:"checklist",name:"Checklist",type:"premium"},{key:"editimage",name:"Enhanced Image Editing",type:"premium"},{key:"mediaembed",name:"Enhanced Media Embed",type:"premium",slug:"introduction-to-mediaembed"},{key:"export",name:"Export",type:"premium"},{key:"formatpainter",name:"Format Painter",type:"premium"},{key:"linkchecker",name:"Link Checker",type:"premium"},{key:"mentions",name:"Mentions",type:"premium"},{key:"pageembed",name:"Page Embed",type:"premium"},{key:"permanentpen",name:"Permanent Pen",type:"premium"},{key:"powerpaste",name:"PowerPaste",type:"premium",slug:"introduction-to-powerpaste"},{key:"rtc",name:"Real-Time Collaboration",type:"premium",slug:"rtc-introduction"},{key:"tinymcespellchecker",name:"Spell Checker Pro",type:"premium",slug:"introduction-to-tiny-spellchecker"},{key:"tinycomments",name:"Tiny Comments",type:"premium",slug:"introduction-to-tiny-comments"},{key:"tinydrive",name:"Tiny Drive",type:"premium",slug:"tinydrive-introduction"},{key:"tableofcontents",name:"Table of Contents",type:"premium"}],(e=>({...e,type:e.type||"opensource",slug:e.slug||e.key}))),v=e=>{const t=e=>`${e.name}`,n=e=>{const n=(e=>{const t=u(e.plugins),n=a(e);return o(n)?t:c(t,(e=>!(((e,t)=>s.call(e,t))(n,e)>-1)))})(e),h=l(n,(n=>"
  • "+((e,n)=>{return(a=k,o=e=>e.key===n,((e,t,n)=>{for(let a=0,o=e.length;a{const a=e.plugins[n].getMetadata;return"function"==typeof a?t(a()):n}),(e=>{const n="premium"===e.type?`${e.name}*`:e.name;return t({name:n,url:`https://www.tiny.cloud/docs/tinymce/6/${e.slug}/`})}));var a,o})(e,n)+"
  • ")),m=h.length,p=h.join("");return"

    "+b.translate(["Plugins installed ({0}):",m])+"

      "+p+"
    "},h={type:"htmlpanel",presets:"document",html:[(e=>null==e?"":'
    '+n(e)+"
    ")(e),(()=>{const e=c(k,(({key:e,type:t})=>"autocorrect"!==e&&"premium"===t)),t=l(e,(e=>"
  • "+b.translate(e.name)+"
  • ")).join("");return'

    '+b.translate("Premium plugins:")+"

    "})()].join("")};return{name:"plugins",title:"Plugins",items:[h]}};var f=tinymce.util.Tools.resolve("tinymce.EditorManager");const w=(e,t)=>()=>{const{tabs:a,names:o}=((e,t)=>{const a=y(),o={name:"keyboardnav",title:"Keyboard Navigation",items:[{type:"htmlpanel",presets:"document",html:"

    Editor UI keyboard navigation

    \n\n

    Activating keyboard navigation

    \n\n

    The sections of the outer UI of the editor - the menubar, toolbar, sidebar and footer - are all keyboard navigable. As such, there are multiple ways to activate keyboard navigation:

    \n
      \n
    • Focus the menubar: Alt + F9 (Windows) or ⌥F9 (MacOS)
    • \n
    • Focus the toolbar: Alt + F10 (Windows) or ⌥F10 (MacOS)
    • \n
    • Focus the footer: Alt + F11 (Windows) or ⌥F11 (MacOS)
    • \n
    \n\n

    Focusing the menubar or toolbar will start keyboard navigation at the first item in the menubar or toolbar, which will be highlighted with a gray background. Focusing the footer will start keyboard navigation at the first item in the element path, which will be highlighted with an underline.

    \n\n

    Moving between UI sections

    \n\n

    When keyboard navigation is active, pressing tab will move the focus to the next major section of the UI, where applicable. These sections are:

    \n
      \n
    • the menubar
    • \n
    • each group of the toolbar
    • \n
    • the sidebar
    • \n
    • the element path in the footer
    • \n
    • the wordcount toggle button in the footer
    • \n
    • the branding link in the footer
    • \n
    • the editor resize handle in the footer
    • \n
    \n\n

    Pressing shift + tab will move backwards through the same sections, except when moving from the footer to the toolbar. Focusing the element path then pressing shift + tab will move focus to the first toolbar group, not the last.

    \n\n

    Moving within UI sections

    \n\n

    Keyboard navigation within UI sections can usually be achieved using the left and right arrow keys. This includes:

    \n
      \n
    • moving between menus in the menubar
    • \n
    • moving between buttons in a toolbar group
    • \n
    • moving between items in the element path
    • \n
    \n\n

    In all these UI sections, keyboard navigation will cycle within the section. For example, focusing the last button in a toolbar group then pressing right arrow will move focus to the first item in the same toolbar group.

    \n\n

    Executing buttons

    \n\n

    To execute a button, navigate the selection to the desired button and hit space or enter.

    \n\n

    Opening, navigating and closing menus

    \n\n

    When focusing a menubar button or a toolbar button with a menu, pressing space, enter or down arrow will open the menu. When the menu opens the first item will be selected. To move up or down the menu, press the up or down arrow key respectively. This is the same for submenus, which can also be opened and closed using the left and right arrow keys.

    \n\n

    To close any active menu, hit the escape key. When a menu is closed the selection will be restored to its previous selection. This also works for closing submenus.

    \n\n

    Context toolbars and menus

    \n\n

    To focus an open context toolbar such as the table context toolbar, press Ctrl + F9 (Windows) or ⌃F9 (MacOS).

    \n\n

    Context toolbar navigation is the same as toolbar navigation, and context menu navigation is the same as standard menu navigation.

    \n\n

    Dialog navigation

    \n\n

    There are two types of dialog UIs in TinyMCE: tabbed dialogs and non-tabbed dialogs.

    \n\n

    When a non-tabbed dialog is opened, the first interactive component in the dialog will be focused. Users can navigate between interactive components by pressing tab. This includes any footer buttons. Navigation will cycle back to the first dialog component if tab is pressed while focusing the last component in the dialog. Pressing shift + tab will navigate backwards.

    \n\n

    When a tabbed dialog is opened, the first button in the tab menu is focused. Pressing tab will navigate to the first interactive component in that tab, and will cycle through the tab\u2019s components, the footer buttons, then back to the tab button. To switch to another tab, focus the tab button for the current tab, then use the arrow keys to cycle through the tab buttons.

    "}]},i=v(e),s=(()=>{var e,t;const n='TinyMCE '+(e=f.majorVersion,t=f.minorVersion,(0===e.indexOf("@")?"X.X.X":e+"."+t)+"");return{name:"versions",title:"Version",items:[{type:"htmlpanel",html:"

    "+b.translate(["You are using {0}",n])+"

    ",presets:"document"}]}})(),c={[a.name]:a,[o.name]:o,[i.name]:i,[s.name]:s,...t.get()};return r.from(n(e)).fold((()=>(e=>{const t=u(e),n=t.indexOf("versions");return-1!==n&&(t.splice(n,1),t.push("versions")),{tabs:e,names:t}})(c)),(e=>((e,t)=>{const n={},a=l(e,(e=>"string"==typeof e?(m(t,e)&&(n[e]=t[e]),e):(n[e.name]=e,e.name)));return{tabs:n,names:a}})(e,c)))})(e,t),i={type:"tabpanel",tabs:(e=>{const t=[],n=e=>{t.push(e)};for(let t=0;t{return m(t=a,n=e)?r.from(t[n]):r.none();var t,n})))};e.windowManager.open({title:"Help",size:"medium",body:i,buttons:[{type:"cancel",name:"close",text:"Close",primary:!0}],initialData:{}})};e.add("help",(e=>{const t=(e=>{let t={};return{get:()=>t,set:e=>{t=e}}})(),n=(e=>({addTab:t=>{const n=e.get();n[t.name]=t,e.set(n)}}))(t);(e=>{(0,e.options.register)("help_tabs",{processor:"array"})})(e);const a=w(e,t);return((e,t)=>{e.ui.registry.addButton("help",{icon:"help",tooltip:"Help",onAction:t}),e.ui.registry.addMenuItem("help",{text:"Help",icon:"help",shortcut:"Alt+0",onAction:t})})(e,a),((e,t)=>{e.addCommand("mceHelp",t)})(e,a),e.shortcuts.add("Alt+0","Open help dialog","mceHelp"),n}))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/hr/plugin.min.js b/public/libs/tinymce/plugins/hr/plugin.min.js deleted file mode 100644 index 8296a1507..000000000 --- a/public/libs/tinymce/plugins/hr/plugin.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) - */ -!function(){"use strict";tinymce.util.Tools.resolve("tinymce.PluginManager").add("hr",function(n){var o,t;function e(){return t.execCommand("InsertHorizontalRule")}(o=n).addCommand("InsertHorizontalRule",function(){o.execCommand("mceInsertContent",!1,"
    ")}),(t=n).ui.registry.addButton("hr",{icon:"horizontal-rule",tooltip:"Horizontal line",onAction:e}),t.ui.registry.addMenuItem("hr",{icon:"horizontal-rule",text:"Horizontal line",onAction:e})})}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/image/plugin.min.js b/public/libs/tinymce/plugins/image/plugin.min.js index 7a90a25da..7ea35a5a7 100644 --- a/public/libs/tinymce/plugins/image/plugin.min.js +++ b/public/libs/tinymce/plugins/image/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function e(r){return function(e){return n=typeof(t=e),(null===t?"null":"object"==n&&(Array.prototype.isPrototypeOf(t)||t.constructor&&"Array"===t.constructor.name)?"array":"object"==n&&(String.prototype.isPrototypeOf(t)||t.constructor&&"String"===t.constructor.name)?"string":n)===r;var t,n}}function t(t){return function(e){return typeof e===t}}function D(e){return!(null==e)}function l(){}function a(e){return function(){return e}}function n(e){return e}function r(){return g}var i,o=tinymce.util.Tools.resolve("tinymce.PluginManager"),v=function(){return(v=Object.assign||function(e){for(var t,n=1,r=arguments.length;n{var i;return!!a(e,t.prototype)||(null===(i=e.constructor)||void 0===i?void 0:i.name)===t.name},i=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&a(e,String,((e,t)=>t.isPrototypeOf(e)))?"string":t})(t)===e,s=e=>t=>typeof t===e,r=i("string"),o=i("object"),n=e=>((e,i)=>o(e)&&a(e,i,((e,a)=>t(e)===a)))(e,Object),l=i("array"),c=(null,e=>null===e);const m=s("boolean"),d=e=>!(e=>null==e)(e),g=s("function"),p=s("number"),u=()=>{};class h{constructor(e,t){this.tag=e,this.value=t}static some(e){return new h(!0,e)}static none(){return h.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?h.some(e(this.value)):h.none()}bind(e){return this.tag?e(this.value):h.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:h.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return d(e)?h.some(e):h.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}h.singletonNone=new h(!1);const b=Object.keys,y=Object.hasOwnProperty,v=(e,t)=>y.call(e,t),f=Array.prototype.push,w=e=>{const t=[];for(let a=0,i=e.length;a{((e,t,a)=>{if(!(r(a)||m(a)||p(a)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",a,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,a+"")})(e.dom,t,a)},D=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},_=D;var C=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),I=tinymce.util.Tools.resolve("tinymce.util.URI");const U=e=>e.length>0,x=e=>t=>t.options.get(e),S=x("image_dimensions"),N=x("image_advtab"),T=x("image_uploadtab"),O=x("image_prepend_url"),L=x("image_class_list"),E=x("image_description"),j=x("image_title"),M=x("image_caption"),R=x("image_list"),k=x("a11y_advanced_options"),z=x("automatic_uploads"),P=(e,t)=>Math.max(parseInt(e,10),parseInt(t,10)),B=e=>(e&&(e=e.replace(/px$/,"")),e),F=e=>(e.length>0&&/^[0-9]+$/.test(e)&&(e+="px"),e),H=e=>"IMG"===e.nodeName&&(e.hasAttribute("data-mce-object")||e.hasAttribute("data-mce-placeholder")),G=(e,t)=>{const a=e.options.get;return I.isDomSafe(t,"img",{allow_html_data_urls:a("allow_html_data_urls"),allow_script_urls:a("allow_script_urls"),allow_svg_data_urls:a("allow_svg_data_urls")})},W=C.DOM,$=e=>e.style.marginLeft&&e.style.marginRight&&e.style.marginLeft===e.style.marginRight?B(e.style.marginLeft):"",V=e=>e.style.marginTop&&e.style.marginBottom&&e.style.marginTop===e.style.marginBottom?B(e.style.marginTop):"",K=e=>e.style.borderWidth?B(e.style.borderWidth):"",Z=(e,t)=>e.hasAttribute(t)?e.getAttribute(t):"",q=(e,t)=>e.style[t]?e.style[t]:"",J=e=>null!==e.parentNode&&"FIGURE"===e.parentNode.nodeName,Q=(e,t,a)=>{""===a?e.removeAttribute(t):e.setAttribute(t,a)},X=(e,t)=>{const a=e.getAttribute("style"),i=t(null!==a?a:"");i.length>0?(e.setAttribute("style",i),e.setAttribute("data-mce-style",i)):e.removeAttribute("style")},Y=(e,t)=>(e,a,i)=>{e.style[a]?(e.style[a]=F(i),X(e,t)):Q(e,a,i)},ee=(e,t)=>e.style[t]?B(e.style[t]):Z(e,t),te=(e,t)=>{const a=F(t);e.style.marginLeft=a,e.style.marginRight=a},ae=(e,t)=>{const a=F(t);e.style.marginTop=a,e.style.marginBottom=a},ie=(e,t)=>{const a=F(t);e.style.borderWidth=a},se=(e,t)=>{e.style.borderStyle=t},re=e=>"FIGURE"===e.nodeName,oe=e=>0===W.getAttrib(e,"alt").length&&"presentation"===W.getAttrib(e,"role"),ne=e=>oe(e)?"":Z(e,"alt"),le=(e,t)=>{const a=document.createElement("img");return Q(a,"style",t.style),($(a)||""!==t.hspace)&&te(a,t.hspace),(V(a)||""!==t.vspace)&&ae(a,t.vspace),(K(a)||""!==t.border)&&ie(a,t.border),((e=>q(e,"borderStyle"))(a)||""!==t.borderStyle)&&se(a,t.borderStyle),e(a.getAttribute("style"))},ce=(e,t)=>({src:Z(t,"src"),alt:ne(t),title:Z(t,"title"),width:ee(t,"width"),height:ee(t,"height"),class:Z(t,"class"),style:e(Z(t,"style")),caption:J(t),hspace:$(t),vspace:V(t),border:K(t),borderStyle:q(t,"borderStyle"),isDecorative:oe(t)}),me=(e,t,a,i,s)=>{a[i]!==t[i]&&s(e,i,a[i])},de=(e,t,a)=>{if(a){W.setAttrib(e,"role","presentation");const t=_(e);A(t,"alt","")}else{if(c(t)){"alt",_(e).dom.removeAttribute("alt")}else{const a=_(e);A(a,"alt",t)}"presentation"===W.getAttrib(e,"role")&&W.setAttrib(e,"role","")}},ge=(e,t)=>(a,i,s)=>{e(a,s),X(a,t)},pe=(e,t,a)=>{const i=ce(e,a);me(a,i,t,"caption",((e,t,a)=>(e=>{J(e)?(e=>{const t=e.parentNode;W.insertAfter(e,t),W.remove(t)})(e):(e=>{const t=W.create("figure",{class:"image"});W.insertAfter(t,e),t.appendChild(e),t.appendChild(W.create("figcaption",{contentEditable:"true"},"Caption")),t.contentEditable="false"})(e)})(e))),me(a,i,t,"src",Q),me(a,i,t,"title",Q),me(a,i,t,"width",Y(0,e)),me(a,i,t,"height",Y(0,e)),me(a,i,t,"class",Q),me(a,i,t,"style",ge(((e,t)=>Q(e,"style",t)),e)),me(a,i,t,"hspace",ge(te,e)),me(a,i,t,"vspace",ge(ae,e)),me(a,i,t,"border",ge(ie,e)),me(a,i,t,"borderStyle",ge(se,e)),((e,t,a)=>{a.alt===t.alt&&a.isDecorative===t.isDecorative||de(e,a.alt,a.isDecorative)})(a,i,t)},ue=(e,t)=>{const a=(e=>{if(e.margin){const t=String(e.margin).split(" ");switch(t.length){case 1:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[0],e["margin-bottom"]=e["margin-bottom"]||t[0],e["margin-left"]=e["margin-left"]||t[0];break;case 2:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[0],e["margin-left"]=e["margin-left"]||t[1];break;case 3:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[2],e["margin-left"]=e["margin-left"]||t[1];break;case 4:e["margin-top"]=e["margin-top"]||t[0],e["margin-right"]=e["margin-right"]||t[1],e["margin-bottom"]=e["margin-bottom"]||t[2],e["margin-left"]=e["margin-left"]||t[3]}delete e.margin}return e})(e.dom.styles.parse(t)),i=e.dom.styles.parse(e.dom.styles.serialize(a));return e.dom.styles.serialize(i)},he=e=>{const t=e.selection.getNode(),a=e.dom.getParent(t,"figure.image");return a?e.dom.select("img",a)[0]:t&&("IMG"!==t.nodeName||H(t))?null:t},be=(e,t)=>{const a=e.dom,i=((t,a)=>{const i={};var s;return((e,t,a,i)=>{((e,t)=>{const a=b(e);for(let i=0,s=a.length;i{(t(e,s)?a:i)(e,s)}))})(t,((t,a)=>!e.schema.isValidChild(a,"figure")),(s=i,(e,t)=>{s[t]=e}),u),i})(e.schema.getTextBlockElements()),s=a.getParent(t.parentNode,(e=>{return t=i,a=e.nodeName,v(t,a)&&void 0!==t[a]&&null!==t[a];var t,a}),e.getBody());return s?a.split(s,t):t},ye=(e,t)=>{const a=((t,a)=>{const i=document.createElement("img");if(pe((t=>ue(e,t)),{...a,caption:!1},i),de(i,a.alt,a.isDecorative),a.caption){const e=W.create("figure",{class:"image"});return e.appendChild(i),e.appendChild(W.create("figcaption",{contentEditable:"true"},"Caption")),e.contentEditable="false",e}return i})(0,t);e.dom.setAttrib(a,"data-mce-id","__mcenew"),e.focus(),e.selection.setContent(a.outerHTML);const i=e.dom.select('*[data-mce-id="__mcenew"]')[0];if(e.dom.setAttrib(i,"data-mce-id",null),re(i)){const t=be(e,i);e.selection.select(t)}else e.selection.select(i)},ve=(e,t)=>{const a=he(e);if(a){const i={...ce((t=>ue(e,t)),a),...t},s=((e,t)=>{const a=t.src;return{...t,src:G(e,a)?a:""}})(e,i);i.src?((e,t)=>{const a=he(e);if(pe((t=>ue(e,t)),t,a),((e,t)=>{e.dom.setAttrib(t,"src",t.getAttribute("src"))})(e,a),re(a.parentNode)){const t=a.parentNode;be(e,t),e.selection.select(a.parentNode)}else e.selection.select(a),((e,t,a)=>{const i=()=>{a.onload=a.onerror=null,e.selection&&(e.selection.select(a),e.nodeChanged())};a.onload=()=>{t.width||t.height||!S(e)||e.dom.setAttribs(a,{width:String(a.clientWidth),height:String(a.clientHeight)}),i()},a.onerror=i})(e,t,a)})(e,s):((e,t)=>{if(t){const a=e.dom.is(t.parentNode,"figure.image")?t.parentNode:t;e.dom.remove(a),e.focus(),e.nodeChanged(),e.dom.isEmpty(e.getBody())&&(e.setContent(""),e.selection.setCursorLocation())}})(e,a)}else t.src&&ye(e,{src:"",alt:"",title:"",width:"",height:"",class:"",style:"",caption:!1,hspace:"",vspace:"",border:"",borderStyle:"",isDecorative:!1,...t})},fe=(we=(e,t)=>n(e)&&n(t)?fe(e,t):t,(...e)=>{if(0===e.length)throw new Error("Can't merge zero objects");const t={};for(let a=0;ar(e.value)?e.value:"",Ce=(e,t)=>{const a=[];return De.each(e,(e=>{const i=(e=>r(e.text)?e.text:r(e.title)?e.title:"")(e);if(void 0!==e.menu){const s=Ce(e.menu,t);a.push({text:i,items:s})}else{const s=t(e);a.push({text:i,value:s})}})),a},Ie=(e=_e)=>t=>t?h.from(t).map((t=>Ce(t,e))):h.none(),Ue=(e,t)=>((e,a)=>{for(let a=0;av(e,"items"))(i=e[a])?Ue(i.items,t):i.value===t?h.some(i):h.none();if(s.isSome())return s}var i;return h.none()})(e),xe=Ie,Se=(e,t)=>e.bind((e=>Ue(e,t))),Ne=e=>{const t=xe((t=>e.convertURL(t.value||t.url,"src"))),a=new Promise((a=>{((e,t)=>{const a=R(e);r(a)?fetch(a).then((e=>{e.ok&&e.json().then(t)})):g(a)?a(t):t(a)})(e,(e=>{a(t(e).map((e=>w([[{text:"None",value:""}],e]))))}))})),i=(A=L(e),Ie(_e)(A)),s=N(e),o=T(e),n=(e=>U(e.options.get("images_upload_url")))(e),l=(e=>d(e.options.get("images_upload_handler")))(e),c=(e=>{const t=he(e);return t?ce((t=>ue(e,t)),t):{src:"",alt:"",title:"",width:"",height:"",class:"",style:"",caption:!1,hspace:"",vspace:"",border:"",borderStyle:"",isDecorative:!1}})(e),m=E(e),p=j(e),u=S(e),b=M(e),y=k(e),v=z(e),f=h.some(O(e)).filter((e=>r(e)&&e.length>0));var A;return a.then((e=>({image:c,imageList:e,classList:i,hasAdvTab:s,hasUploadTab:o,hasUploadUrl:n,hasUploadHandler:l,hasDescription:m,hasImageTitle:p,hasDimensions:u,hasImageCaption:b,prependURL:f,hasAccessibilityOptions:y,automaticUploads:v})))},Te=e=>{const t=e.imageList.map((e=>({name:"images",type:"listbox",label:"Image list",items:e}))),a={name:"alt",type:"input",label:"Alternative description",enabled:!(e.hasAccessibilityOptions&&e.image.isDecorative)},i=e.classList.map((e=>({name:"classes",type:"listbox",label:"Class",items:e})));return w([[{name:"src",type:"urlinput",filetype:"image",label:"Source"}],t.toArray(),e.hasAccessibilityOptions&&e.hasDescription?[{type:"label",label:"Accessibility",items:[{name:"isDecorative",type:"checkbox",label:"Image is decorative"}]}]:[],e.hasDescription?[a]:[],e.hasImageTitle?[{name:"title",type:"input",label:"Image title"}]:[],e.hasDimensions?[{name:"dimensions",type:"sizeinput"}]:[],[{...(s=e.classList.isSome()&&e.hasImageCaption,s?{type:"grid",columns:2}:{type:"panel"}),items:w([i.toArray(),e.hasImageCaption?[{type:"label",label:"Caption",items:[{type:"checkbox",name:"caption",label:"Show caption"}]}]:[]])}]]);var s},Oe=e=>({title:"General",name:"general",items:Te(e)}),Le=Te,Ee=e=>({src:{value:e.src,meta:{}},images:e.src,alt:e.alt,title:e.title,dimensions:{width:e.width,height:e.height},classes:e.class,caption:e.caption,style:e.style,vspace:e.vspace,border:e.border,hspace:e.hspace,borderstyle:e.borderStyle,fileinput:[],isDecorative:e.isDecorative}),je=(e,t)=>({src:e.src.value,alt:0===e.alt.length&&t?null:e.alt,title:e.title,width:e.dimensions.width,height:e.dimensions.height,class:e.classes,style:e.style,caption:e.caption,hspace:e.hspace,vspace:e.vspace,border:e.border,borderStyle:e.borderstyle,isDecorative:e.isDecorative}),Me=(e,t,a,i)=>{((e,t)=>{const a=t.getData();((e,t)=>/^(?:[a-zA-Z]+:)?\/\//.test(t)?h.none():e.prependURL.bind((e=>t.substring(0,e.length)!==e?h.some(e+t):h.none())))(e,a.src.value).each((e=>{t.setData({src:{value:e,meta:a.src.meta}})}))})(t,i),((e,t)=>{const a=t.getData(),i=a.src.meta;if(void 0!==i){const s=fe({},a);((e,t,a)=>{e.hasDescription&&r(a.alt)&&(t.alt=a.alt),e.hasAccessibilityOptions&&(t.isDecorative=a.isDecorative||t.isDecorative||!1),e.hasImageTitle&&r(a.title)&&(t.title=a.title),e.hasDimensions&&(r(a.width)&&(t.dimensions.width=a.width),r(a.height)&&(t.dimensions.height=a.height)),r(a.class)&&Se(e.classList,a.class).each((e=>{t.classes=e.value})),e.hasImageCaption&&m(a.caption)&&(t.caption=a.caption),e.hasAdvTab&&(r(a.style)&&(t.style=a.style),r(a.vspace)&&(t.vspace=a.vspace),r(a.border)&&(t.border=a.border),r(a.hspace)&&(t.hspace=a.hspace),r(a.borderstyle)&&(t.borderstyle=a.borderstyle))})(e,s,i),t.setData(s)}})(t,i),((e,t,a,i)=>{const s=i.getData(),r=s.src.value,o=s.src.meta||{};o.width||o.height||!t.hasDimensions||(U(r)?e.imageSize(r).then((e=>{a.open&&i.setData({dimensions:e})})).catch((e=>console.error(e))):i.setData({dimensions:{width:"",height:""}}))})(e,t,a,i),((e,t,a)=>{const i=a.getData(),s=Se(e.imageList,i.src.value);t.prevImage=s,a.setData({images:s.map((e=>e.value)).getOr("")})})(t,a,i)},Re=(e,t,a,i)=>{const s=i.getData();var r;i.block("Uploading image"),(r=s.fileinput,((e,t)=>0{i.unblock()}),(s=>{const r=URL.createObjectURL(s),o=()=>{i.unblock(),URL.revokeObjectURL(r)},n=s=>{i.setData({src:{value:s,meta:{}}}),i.showTab("general"),Me(e,t,a,i)};var l;(l=s,new Promise(((e,t)=>{const a=new FileReader;a.onload=()=>{e(a.result)},a.onerror=()=>{t(a.error.message)},a.readAsDataURL(l)}))).then((a=>{const l=e.createBlobCache(s,r,a);t.automaticUploads?e.uploadImage(l).then((e=>{n(e.url),o()})).catch((t=>{o(),e.alertErr(t)})):(e.addToBlobCache(l),n(l.blobUri()),i.unblock())}))}))},ke=(e,t,a)=>(i,s)=>{"src"===s.name?Me(e,t,a,i):"images"===s.name?((e,t,a,i)=>{const s=i.getData(),r=Se(t.imageList,s.images);r.each((e=>{const t=""===s.alt||a.prevImage.map((e=>e.text===s.alt)).getOr(!1);t?""===e.value?i.setData({src:e,alt:a.prevAlt}):i.setData({src:e,alt:e.text}):i.setData({src:e})})),a.prevImage=r,Me(e,t,a,i)})(e,t,a,i):"alt"===s.name?a.prevAlt=i.getData().alt:"fileinput"===s.name?Re(e,t,a,i):"isDecorative"===s.name&&i.setEnabled("alt",!i.getData().isDecorative)},ze=e=>()=>{e.open=!1},Pe=e=>e.hasAdvTab||e.hasUploadUrl||e.hasUploadHandler?{type:"tabpanel",tabs:w([[Oe(e)],e.hasAdvTab?[{title:"Advanced",name:"advanced",items:[{type:"grid",columns:2,items:[{type:"input",label:"Vertical space",name:"vspace",inputMode:"numeric"},{type:"input",label:"Horizontal space",name:"hspace",inputMode:"numeric"},{type:"input",label:"Border width",name:"border",inputMode:"numeric"},{type:"listbox",name:"borderstyle",label:"Border style",items:[{text:"Select...",value:""},{text:"Solid",value:"solid"},{text:"Dotted",value:"dotted"},{text:"Dashed",value:"dashed"},{text:"Double",value:"double"},{text:"Groove",value:"groove"},{text:"Ridge",value:"ridge"},{text:"Inset",value:"inset"},{text:"Outset",value:"outset"},{text:"None",value:"none"},{text:"Hidden",value:"hidden"}]}]}]}]:[],e.hasUploadTab&&(e.hasUploadUrl||e.hasUploadHandler)?[{title:"Upload",name:"upload",items:[{type:"dropzone",name:"fileinput"}]}]:[]])}:{type:"panel",items:Le(e)},Be=(e,t,a)=>i=>{const s=fe(Ee(t.image),i.getData()),r={...s,style:le(a.normalizeCss,je(s,!1))};e.execCommand("mceUpdateImage",!1,je(r,t.hasAccessibilityOptions)),e.editorUpload.uploadImagesAuto(),i.close()},Fe=e=>t=>G(e,t)?(e=>new Promise((t=>{const a=document.createElement("img"),i=e=>{a.onload=a.onerror=null,a.parentNode&&a.parentNode.removeChild(a),t(e)};a.onload=()=>{const e={width:P(a.width,a.clientWidth),height:P(a.height,a.clientHeight)};i(Promise.resolve(e))},a.onerror=()=>{i(Promise.reject(`Failed to get image dimensions for: ${e}`))};const s=a.style;s.visibility="hidden",s.position="fixed",s.bottom=s.left="0px",s.width=s.height="auto",document.body.appendChild(a),a.src=e})))(e.documentBaseURI.toAbsolute(t)).then((e=>({width:String(e.width),height:String(e.height)}))):Promise.resolve({width:"",height:""}),He=e=>(t,a,i)=>e.editorUpload.blobCache.create({blob:t,blobUri:a,name:t.name?t.name.replace(/\.[^\.]+$/,""):null,filename:t.name,base64:i.split(",")[1]}),Ge=e=>t=>{e.editorUpload.blobCache.add(t)},We=e=>t=>{e.windowManager.alert(t)},$e=e=>t=>ue(e,t),Ve=e=>t=>e.dom.parseStyle(t),Ke=e=>(t,a)=>e.dom.serializeStyle(t,a),Ze=e=>t=>Ae(e).upload([t],!1).then((e=>0===e.length?Promise.reject("Failed to upload image"):!1===e[0].status?Promise.reject(e[0].error.message):e[0])),qe=e=>{const t={imageSize:Fe(e),addToBlobCache:Ge(e),createBlobCache:He(e),alertErr:We(e),normalizeCss:$e(e),parseStyle:Ve(e),serializeStyle:Ke(e),uploadImage:Ze(e)};return{open:()=>{Ne(e).then((a=>{const i=(e=>({prevImage:Se(e.imageList,e.image.src),prevAlt:e.image.alt,open:!0}))(a);return{title:"Insert/Edit Image",size:"normal",body:Pe(a),buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:Ee(a.image),onSubmit:Be(e,a,t),onChange:ke(t,a,i),onClose:ze(i)}})).then(e.windowManager.open)}}},Je=e=>{const t=e.attr("class");return t&&/\bimage\b/.test(t)},Qe=e=>t=>{let a=t.length;const i=t=>{t.attr("contenteditable",e?"true":null)};for(;a--;){const s=t[a];Je(s)&&(s.attr("contenteditable",e?"false":null),De.each(s.getAll("figcaption"),i))}};e.add("image",(e=>{(e=>{const t=e.options.register;t("image_dimensions",{processor:"boolean",default:!0}),t("image_advtab",{processor:"boolean",default:!1}),t("image_uploadtab",{processor:"boolean",default:!0}),t("image_prepend_url",{processor:"string",default:""}),t("image_class_list",{processor:"object[]"}),t("image_description",{processor:"boolean",default:!0}),t("image_title",{processor:"boolean",default:!1}),t("image_caption",{processor:"boolean",default:!1}),t("image_list",{processor:e=>{const t=!1===e||r(e)||((e,t)=>{if(l(e)){for(let a=0,i=e.length;a{e.on("PreInit",(()=>{e.parser.addNodeFilter("figure",Qe(!0)),e.serializer.addNodeFilter("figure",Qe(!1))}))})(e),(e=>{e.ui.registry.addToggleButton("image",{icon:"image",tooltip:"Insert/edit image",onAction:qe(e).open,onSetup:t=>(t.setActive(d(he(e))),e.selection.selectorChangedWithUnbind("img:not([data-mce-object]):not([data-mce-placeholder]),figure.image",t.setActive).unbind)}),e.ui.registry.addMenuItem("image",{icon:"image",text:"Image...",onAction:qe(e).open}),e.ui.registry.addContextMenu("image",{update:e=>re(e)||"IMG"===e.nodeName&&!H(e)?["image"]:[]})})(e),(e=>{e.addCommand("mceImage",qe(e).open),e.addCommand("mceUpdateImage",((t,a)=>{e.undoManager.transact((()=>ve(e,a)))}))})(e)}))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/imagetools/plugin.min.js b/public/libs/tinymce/plugins/imagetools/plugin.min.js deleted file mode 100644 index 731dca88b..000000000 --- a/public/libs/tinymce/plugins/imagetools/plugin.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) - */ -!function(){"use strict";function c(e){var t=e;return{get:function(){return t},set:function(e){t=e}}}function h(e){return null!=e}function r(){}function i(e){return function(){return e}}function e(e){return e}function t(){return d}function s(e){return n=typeof(t=e),"array"==(null===t?"null":"object"==n&&(Array.prototype.isPrototypeOf(t)||t.constructor&&"Array"===t.constructor.name)?"array":"object"==n&&(String.prototype.isPrototypeOf(t)||t.constructor&&"String"===t.constructor.name)?"string":n);var t,n}var n,o=tinymce.util.Tools.resolve("tinymce.PluginManager"),f=tinymce.util.Tools.resolve("tinymce.util.Tools"),a=function(e){return typeof e===n},u=i(!(n="function")),l=i(!0),d={fold:function(e,t){return e()},isSome:u,isNone:l,getOr:e,getOrThunk:m,getOrDie:function(e){throw new Error(e||"error: getOrDie called on none.")},getOrNull:i(null),getOrUndefined:i(void 0),or:e,orThunk:m,map:t,each:r,bind:t,exists:u,forall:l,filter:function(){return d},toArray:function(){return[]},toString:i("none()")};function m(e){return e()}var g=function(n){function e(){return o}function t(e){return e(n)}var r=i(n),o={fold:function(e,t){return t(n)},isSome:l,isNone:u,getOr:r,getOrThunk:r,getOrDie:r,getOrNull:r,getOrUndefined:r,or:e,orThunk:e,map:function(e){return g(e(n))},each:function(e){e(n)},bind:t,exists:t,forall:t,filter:function(e){return e(n)?o:d},toArray:function(){return[n]},toString:function(){return"some("+n+")"}};return o},p={some:g,none:t,from:function(e){return null==e?d:g(e)}},v={},y={exports:v};function w(e,t){return U(document.createElement("canvas"),e,t)}function b(e){var t=w(e.width,e.height);return R(t).drawImage(e,0,0),t}function _(u){return new I(function(e,t){function n(){o.removeEventListener("load",i),o.removeEventListener("error",a)}var r=URL.createObjectURL(u),o=new Image,i=function(){n(),e(o)},a=function(){n(),t("Unable to load data of type "+u.type+": "+r)};o.addEventListener("load",i),o.addEventListener("error",a),o.src=r,o.complete&&setTimeout(i,0)})}function E(e,r,o){return r=r||"image/png",a(HTMLCanvasElement.prototype.toBlob)?new I(function(t,n){e.toBlob(function(e){e?t(e):n()},r,o)}):j(e.toDataURL(r,o))}function T(e,t){for(var n=0,r=e.length;nt=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(s=r=e,(o=String).prototype.isPrototypeOf(s)||(null===(n=r.constructor)||void 0===n?void 0:n.name)===o.name)?"string":t;var s,r,o,n})(t)===e,s=t("string"),r=t("object"),o=t("array"),n=("function",e=>"function"==typeof e);var c=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),i=tinymce.util.Tools.resolve("tinymce.EditorManager"),l=tinymce.util.Tools.resolve("tinymce.Env"),a=tinymce.util.Tools.resolve("tinymce.util.Tools");const p=e=>t=>t.options.get(e),u=p("importcss_merge_classes"),m=p("importcss_exclusive"),f=p("importcss_selector_converter"),y=p("importcss_selector_filter"),d=p("importcss_groups"),h=p("importcss_append"),_=p("importcss_file_filter"),g=p("skin"),v=p("skin_url"),b=Array.prototype.push,x=/^\.(?:ephox|tiny-pageembed|mce)(?:[.-]+\w+)+$/,T=e=>s(e)?t=>-1!==t.indexOf(e):e instanceof RegExp?t=>e.test(t):e,S=(e,t)=>{let s;const r=/^(?:([a-z0-9\-_]+))?(\.[a-z0-9_\-\.]+)$/i.exec(t);if(!r)return;const o=r[1],n=r[2].substr(1).split(".").join(" "),c=a.makeMap("a,img");return r[1]?(s={title:t},e.schema.getTextBlockElements()[o]?s.block=o:e.schema.getBlockElements()[o]||c[o.toLowerCase()]?s.selector=o:s.inline=o):r[2]&&(s={inline:"span",title:t.substr(1),classes:n}),u(e)?s.classes=n:s.attributes={class:n},s},k=(e,t)=>null===t||m(e),w=e=>{e.on("init",(()=>{const t=(()=>{const e=[],t=[],s={};return{addItemToGroup:(e,r)=>{s[e]?s[e].push(r):(t.push(e),s[e]=[r])},addItem:t=>{e.push(t)},toFormats:()=>{return(r=t,n=e=>{const t=s[e];return 0===t.length?[]:[{title:e,items:t}]},(e=>{const t=[];for(let s=0,r=e.length;s{const s=e.length,r=new Array(s);for(let o=0;oa.map(e,(e=>a.extend({},e,{original:e,selectors:{},filter:T(e.filter)}))))(d(e)),u=(t,s)=>{if(((e,t,s,r)=>!(k(e,s)?t in r:t in s.selectors))(e,t,s,r)){((e,t,s,r)=>{k(e,s)?r[t]=!0:s.selectors[t]=!0})(e,t,s,r);const o=((e,t,s,r)=>{let o;return o=r&&r.selector_converter?r.selector_converter:f(e)?f(e):()=>S(e,s),o.call(t,s,r)})(e,e.plugins.importcss,t,s);if(o){const t=o.name||c.DOM.uniqueId();return e.formatter.register(t,o),{title:o.title,format:t}}}return null};a.each(((e,t,r)=>{const o=[],n={},c=(t,n)=>{let p,u=t.href;if(u=(e=>{const t=l.cacheSuffix;return s(e)&&(e=e.replace("?"+t,"").replace("&"+t,"")),e})(u),u&&r(u,n)&&!((e,t)=>{const s=g(e);if(s){const r=v(e),o=r?e.documentBaseURI.toAbsolute(r):i.baseURL+"/skins/ui/"+s,n=i.baseURL+"/skins/content/";return t===o+"/content"+(e.inline?".inline":"")+".min.css"||-1!==t.indexOf(n)}return!1})(e,u)){a.each(t.imports,(e=>{c(e,!0)}));try{p=t.cssRules||t.rules}catch(e){}a.each(p,(e=>{e.styleSheet?c(e.styleSheet,!0):e.selectorText&&a.each(e.selectorText.split(","),(e=>{o.push(a.trim(e))}))}))}};a.each(e.contentCSS,(e=>{n[e]=!0})),r||(r=(e,t)=>t||n[e]);try{a.each(t.styleSheets,(e=>{c(e)}))}catch(e){}return o})(e,e.getDoc(),T(_(e))),(e=>{if(!x.test(e)&&(!n||n(e))){const s=((e,t)=>a.grep(e,(e=>!e.filter||e.filter(t))))(p,e);if(s.length>0)a.each(s,(s=>{const r=u(e,s);r&&t.addItemToGroup(s.title,r)}));else{const s=u(e,null);s&&t.addItem(s)}}}));const m=t.toFormats();e.dispatch("addStyleModifications",{items:m,replace:!h(e)})}))};e.add("importcss",(e=>((e=>{const t=e.options.register,o=e=>s(e)||n(e)||r(e);t("importcss_merge_classes",{processor:"boolean",default:!0}),t("importcss_exclusive",{processor:"boolean",default:!0}),t("importcss_selector_converter",{processor:"function"}),t("importcss_selector_filter",{processor:o}),t("importcss_file_filter",{processor:o}),t("importcss_groups",{processor:"object[]"}),t("importcss_append",{processor:"boolean",default:!1})})(e),w(e),(e=>({convertSelectorToFormat:t=>S(e,t)}))(e))))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/insertdatetime/plugin.min.js b/public/libs/tinymce/plugins/insertdatetime/plugin.min.js index ac13cc1a3..71cdd0d82 100644 --- a/public/libs/tinymce/plugins/insertdatetime/plugin.min.js +++ b/public/libs/tinymce/plugins/insertdatetime/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function l(e){return e.getParam("insertdatetime_timeformat",e.translate("%H:%M:%S"))}function s(e){return e.getParam("insertdatetime_formats",["%H:%M:%S","%Y-%m-%d","%I:%M:%S %p","%D"])}function r(e,t){if((e=""+e).length'+n+"")):e.insertContent(d(e,t))}var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),a="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),i="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),o="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),u="January February March April May June July August September October November December".split(" "),g=tinymce.util.Tools.resolve("tinymce.util.Tools");e.add("insertdatetime",function(e){var n,r,t,a,i,o,u,c;function m(e){return r.execCommand("mceInsertDate",!1,e)}(n=e).addCommand("mceInsertDate",function(e,t){p(n,null!=t?t:n.getParam("insertdatetime_dateformat",n.translate("%Y-%m-%d")))}),n.addCommand("mceInsertTime",function(e,t){p(n,null!=t?t:l(n))}),u=s(r=e),t=0<(o=s(i=r)).length?o[0]:l(i),a=t,c={get:function(){return a},set:function(e){a=e}},r.ui.registry.addSplitButton("insertdatetime",{icon:"insert-time",tooltip:"Insert date/time",select:function(e){return e===c.get()},fetch:function(e){e(g.map(u,function(e){return{type:"choiceitem",text:d(r,e),value:e}}))},onAction:function(e){m(c.get())},onItemAction:function(e,t){c.set(t),m(t)}}),r.ui.registry.addNestedMenuItem("insertdatetime",{icon:"insert-time",text:"Date/time",getSubmenuItems:function(){return g.map(u,function(e){return{type:"menuitem",text:d(r,e),onAction:(t=e,function(){c.set(t),m(t)})};var t})}})})}(); \ No newline at end of file +!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>t.options.get(e),r=t("insertdatetime_dateformat"),a=t("insertdatetime_timeformat"),n=t("insertdatetime_formats"),s=t("insertdatetime_element"),i="Sun Mon Tue Wed Thu Fri Sat Sun".split(" "),o="Sunday Monday Tuesday Wednesday Thursday Friday Saturday Sunday".split(" "),l="Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec".split(" "),m="January February March April May June July August September October November December".split(" "),c=(e,t)=>{if((e=""+e).length(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=(t=t.replace("%D","%m/%d/%Y")).replace("%r","%I:%M:%S %p")).replace("%Y",""+r.getFullYear())).replace("%y",""+r.getYear())).replace("%m",c(r.getMonth()+1,2))).replace("%d",c(r.getDate(),2))).replace("%H",""+c(r.getHours(),2))).replace("%M",""+c(r.getMinutes(),2))).replace("%S",""+c(r.getSeconds(),2))).replace("%I",""+((r.getHours()+11)%12+1))).replace("%p",r.getHours()<12?"AM":"PM")).replace("%B",""+e.translate(m[r.getMonth()]))).replace("%b",""+e.translate(l[r.getMonth()]))).replace("%A",""+e.translate(o[r.getDay()]))).replace("%a",""+e.translate(i[r.getDay()]))).replace("%%","%"),u=(e,t)=>{if(s(e)){const r=d(e,t);let a;a=/%[HMSIp]/.test(t)?d(e,"%Y-%m-%dT%H:%M"):d(e,"%Y-%m-%d");const n=e.dom.getParent(e.selection.getStart(),"time");n?((e,t,r,a)=>{const n=e.dom.create("time",{datetime:r},a);t.parentNode.insertBefore(n,t),e.dom.remove(t),e.selection.select(n,!0),e.selection.collapse(!1)})(e,n,a,r):e.insertContent('")}else e.insertContent(d(e,t))};var p=tinymce.util.Tools.resolve("tinymce.util.Tools");e.add("insertdatetime",(e=>{(e=>{const t=e.options.register;t("insertdatetime_dateformat",{processor:"string",default:e.translate("%Y-%m-%d")}),t("insertdatetime_timeformat",{processor:"string",default:e.translate("%H:%M:%S")}),t("insertdatetime_formats",{processor:"string[]",default:["%H:%M:%S","%Y-%m-%d","%I:%M:%S %p","%D"]}),t("insertdatetime_element",{processor:"boolean",default:!1})})(e),(e=>{e.addCommand("mceInsertDate",((t,a)=>{u(e,null!=a?a:r(e))})),e.addCommand("mceInsertTime",((t,r)=>{u(e,null!=r?r:a(e))}))})(e),(e=>{const t=n(e),r=(e=>{let t=e;return{get:()=>t,set:e=>{t=e}}})((e=>{const t=n(e);return t.length>0?t[0]:a(e)})(e)),s=t=>e.execCommand("mceInsertDate",!1,t);e.ui.registry.addSplitButton("insertdatetime",{icon:"insert-time",tooltip:"Insert date/time",select:e=>e===r.get(),fetch:r=>{r(p.map(t,(t=>({type:"choiceitem",text:d(e,t),value:t}))))},onAction:e=>{s(r.get())},onItemAction:(e,t)=>{r.set(t),s(t)}});const i=e=>()=>{r.set(e),s(e)};e.ui.registry.addNestedMenuItem("insertdatetime",{icon:"insert-time",text:"Date/time",getSubmenuItems:()=>p.map(t,(t=>({type:"menuitem",text:d(e,t),onAction:i(t)})))})})(e)}))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/legacyoutput/plugin.min.js b/public/libs/tinymce/plugins/legacyoutput/plugin.min.js deleted file mode 100644 index dd8d0a23e..000000000 --- a/public/libs/tinymce/plugins/legacyoutput/plugin.min.js +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) - */ -!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager"),l=tinymce.util.Tools.resolve("tinymce.util.Tools");e.add("legacyoutput",function(e){var s,t;(t=s=e).settings.inline_styles=!1,t.getParam("fontsize_formats")||(t.settings.fontsize_formats="8pt=1 10pt=2 12pt=3 14pt=4 18pt=5 24pt=6 36pt=7"),t.getParam("font_formats")||(t.settings.font_formats="Andale Mono=andale mono,monospace;Arial=arial,helvetica,sans-serif;Arial Black=arial black,sans-serif;Book Antiqua=book antiqua,palatino,serif;Comic Sans MS=comic sans ms,sans-serif;Courier New=courier new,courier,monospace;Georgia=georgia,palatino,serif;Helvetica=helvetica,arial,sans-serif;Impact=impact,sans-serif;Symbol=symbol;Tahoma=tahoma,arial,helvetica,sans-serif;Terminal=terminal,monaco,monospace;Times New Roman=times new roman,times,serif;Trebuchet MS=trebuchet ms,geneva,sans-serif;Verdana=verdana,geneva,sans-serif;Webdings=webdings;Wingdings=wingdings,zapf dingbats"),s.on("PreInit",function(){var e=s,t="p,h1,h2,h3,h4,h5,h6,td,th,div,ul,ol,li,table",i=l.explode(e.getParam("font_size_style_values","xx-small,x-small,small,medium,large,x-large,xx-large")),a=e.schema;e.formatter.register({alignleft:{selector:t,attributes:{align:"left"}},aligncenter:{selector:t,attributes:{align:"center"}},alignright:{selector:t,attributes:{align:"right"}},alignjustify:{selector:t,attributes:{align:"justify"}},bold:[{inline:"b",remove:"all",preserve_attributes:["class","style"]},{inline:"strong",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{fontWeight:"bold"}}],italic:[{inline:"i",remove:"all",preserve_attributes:["class","style"]},{inline:"em",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{fontStyle:"italic"}}],underline:[{inline:"u",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{textDecoration:"underline"},exact:!0}],strikethrough:[{inline:"strike",remove:"all",preserve_attributes:["class","style"]},{inline:"span",styles:{textDecoration:"line-through"},exact:!0}],fontname:{inline:"font",toggle:!1,attributes:{face:"%value"}},fontsize:{inline:"font",toggle:!1,attributes:{size:function(e){return String(l.inArray(i,e.value)+1)}}},forecolor:{inline:"font",attributes:{color:"%value"},links:!0,remove_similar:!0,clear_child_styles:!0},hilitecolor:{inline:"font",styles:{backgroundColor:"%value"},links:!0,remove_similar:!0,clear_child_styles:!0}}),l.each("b,i,u,strike".split(","),function(e){a.addValidElements(e+"[*]")}),a.getElementRule("font")||a.addValidElements("font[face|size|color|style]"),l.each(t.split(","),function(e){var t=a.getElementRule(e);t&&(t.attributes.align||(t.attributes.align={},t.attributesOrder.push("align")))})})})}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/link/plugin.min.js b/public/libs/tinymce/plugins/link/plugin.min.js index 643f57ff9..03c4ad928 100644 --- a/public/libs/tinymce/plugins/link/plugin.min.js +++ b/public/libs/tinymce/plugins/link/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function t(r){return function(t){return e=typeof(n=t),(null===n?"null":"object"==e&&(Array.prototype.isPrototypeOf(n)||n.constructor&&"Array"===n.constructor.name)?"array":"object"==e&&(String.prototype.isPrototypeOf(n)||n.constructor&&"String"===n.constructor.name)?"string":e)===r;var n,e}}function n(n){return function(t){return typeof t===n}}function h(){}function i(t){return function(){return t}}function e(t){return t}function r(t,n){return t===n}function o(){return v}var u,a=tinymce.util.Tools.resolve("tinymce.PluginManager"),c=tinymce.util.Tools.resolve("tinymce.util.VK"),l=t("string"),d=t("array"),p=function(t){return u===t},f=n("boolean"),s=n("function"),m=i(!1),g=i(!(u=null)),v={fold:function(t,n){return t()},isSome:m,isNone:g,getOr:e,getOrThunk:y,getOrDie:function(t){throw new Error(t||"error: getOrDie called on none.")},getOrNull:i(null),getOrUndefined:i(void 0),or:e,orThunk:y,map:o,each:h,bind:o,exists:m,forall:g,filter:function(){return v},toArray:function(){return[]},toString:i("none()")};function y(t){return t()}function k(t,o,i){return function(t){for(var n,e=0,r=t.length;et=>(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===(l=o.constructor)||void 0===l?void 0:l.name)===r.name)?"string":t;var n,o,r,l})(t)===e,n=e=>t=>typeof t===e,o=t("string"),r=t("object"),l=t("array"),a=(null,e=>null===e);const s=n("boolean"),i=n("function"),c=(e,t)=>{if(l(e)){for(let n=0,o=e.length;n{},g=(e,t)=>e===t;class m{constructor(e,t){this.tag=e,this.value=t}static some(e){return new m(!0,e)}static none(){return m.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?m.some(e(this.value)):m.none()}bind(e){return this.tag?e(this.value):m.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:m.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return null==e?m.none():m.some(e)}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}m.singletonNone=new m(!1);const d=Array.prototype.indexOf,h=Array.prototype.push,p=e=>{const t=[];for(let n=0,o=e.length;n{for(let n=0;ne.exists((e=>n(e,t))),v=e=>{const t=[],n=e=>{t.push(e)};for(let t=0;te?m.some(t):m.none(),x=e=>t=>t.options.get(e),_=x("link_assume_external_targets"),b=x("link_context_toolbar"),w=x("link_list"),C=x("link_default_target"),O=x("link_default_protocol"),N=x("link_target_list"),A=x("link_rel_list"),T=x("link_class_list"),S=x("link_title"),E=x("allow_unsafe_link_target"),P=x("link_quicklink");var R=tinymce.util.Tools.resolve("tinymce.util.Tools");const L=e=>o(e.value)?e.value:"",M=(e,t)=>{const n=[];return R.each(e,(e=>{const r=(e=>o(e.text)?e.text:o(e.title)?e.title:"")(e);if(void 0!==e.menu){const o=M(e.menu,t);n.push({text:r,items:o})}else{const o=t(e);n.push({text:r,value:o})}})),n},D=(e=L)=>t=>m.from(t).map((t=>M(t,e))),B=e=>D(L)(e),I=D,j=(e,t)=>n=>({name:e,type:"listbox",label:t,items:n}),K=L,U=Object.keys,q=Object.hasOwnProperty,F=(e,t)=>q.call(e,t);var V=tinymce.util.Tools.resolve("tinymce.dom.TreeWalker"),$=tinymce.util.Tools.resolve("tinymce.util.URI");const z=e=>e&&"a"===e.nodeName.toLowerCase(),G=e=>z(e)&&!!W(e),H=(e,t)=>{if(e.collapsed)return[];{const n=e.cloneContents(),o=new V(n.firstChild,n),r=[];let l=n.firstChild;do{t(l)&&r.push(l)}while(l=o.next());return r}},J=e=>/^\w+:/i.test(e),W=e=>e.getAttribute("data-mce-href")||e.getAttribute("href"),Q=(e,t)=>{const n=["noopener"],o=e?e.split(/\s+/):[],r=e=>e.filter((e=>-1===R.inArray(n,e))),l=t?(e=>(e=r(e)).length>0?e.concat(n):n)(o):r(o);return l.length>0?(e=>R.trim(e.sort().join(" ")))(l):""},X=(e,t)=>(t=t||e.selection.getNode(),te(t)?e.dom.select("a[href]",t)[0]:e.dom.getParent(t,"a[href]")),Y=(e,t)=>(t?t.innerText||t.textContent:e.getContent({format:"text"})).replace(/\uFEFF/g,""),Z=e=>R.grep(e,G).length>0,ee=e=>{const t=e.schema.getTextInlineElements();return 0===H(e.selection.getRng(),(e=>1===e.nodeType&&!z(e)&&!F(t,e.nodeName.toLowerCase()))).length},te=e=>e&&"FIGURE"===e.nodeName&&/\bimage\b/i.test(e.className),ne=(e,t,n)=>{const o=e.selection.getNode(),r=X(e,o),l=((e,t)=>{const n={...t};if(0===A(e).length&&!E(e)){const e=Q(n.rel,"_blank"===n.target);n.rel=e||null}return m.from(n.target).isNone()&&!1===N(e)&&(n.target=C(e)),n.href=((e,t)=>"http"!==t&&"https"!==t||J(e)?e:t+"://"+e)(n.href,_(e)),n})(e,(e=>{return t=["title","rel","class","target"],n=(t,n)=>(e[n].each((e=>{t[n]=e.length>0?e:null})),t),o={href:e.href},((e,t)=>{for(let n=0,o=e.length;n{o=n(o,e)})),o;var t,n,o})(n));e.undoManager.transact((()=>{n.href===t.href&&t.attach(),r?(e.focus(),((e,t,n,o)=>{n.each((e=>{F(t,"innerText")?t.innerText=e:t.textContent=e})),e.dom.setAttribs(t,o),e.selection.select(t)})(e,r,n.text,l)):((e,t,n,o)=>{te(t)?se(e,t,o):n.fold((()=>{e.execCommand("mceInsertLink",!1,o)}),(t=>{e.insertContent(e.dom.createHTML("a",o,e.dom.encode(t)))}))})(e,o,n.text,l)}))},oe=e=>{const{class:t,href:n,rel:o,target:r,text:l,title:s}=e;return((e,t)=>{const n={};var o;return((e,t,n,o)=>{((e,t)=>{const n=U(e);for(let o=0,r=n.length;o{(t(e,r)?n:o)(e,r)}))})(e,((e,t)=>!1===a(e)),(o=n,(e,t)=>{o[t]=e}),u),n})({class:t.getOrNull(),href:n,rel:o.getOrNull(),target:r.getOrNull(),text:l.getOrNull(),title:s.getOrNull()})},re=(e,t,n)=>{const o=((e,t)=>{const n=e.options.get,o={allow_html_data_urls:n("allow_html_data_urls"),allow_script_urls:n("allow_script_urls"),allow_svg_data_urls:n("allow_svg_data_urls")},r=t.href;return{...t,href:$.isDomSafe(r,"a",o)?r:""}})(e,n);e.hasPlugin("rtc",!0)?e.execCommand("createlink",!1,oe(o)):ne(e,t,o)},le=e=>{e.hasPlugin("rtc",!0)?e.execCommand("unlink"):(e=>{e.undoManager.transact((()=>{const t=e.selection.getNode();te(t)?ae(e,t):(e=>{const t=e.dom,n=e.selection,o=n.getBookmark(),r=n.getRng().cloneRange(),l=t.getParent(r.startContainer,"a[href]",e.getBody()),a=t.getParent(r.endContainer,"a[href]",e.getBody());l&&r.setStartBefore(l),a&&r.setEndAfter(a),n.setRng(r),e.execCommand("unlink"),n.moveToBookmark(o)})(e),e.focus()}))})(e)},ae=(e,t)=>{const n=e.dom.select("img",t)[0];if(n){const o=e.dom.getParents(n,"a[href]",t)[0];o&&(o.parentNode.insertBefore(n,o),e.dom.remove(o))}},se=(e,t,n)=>{const o=e.dom.select("img",t)[0];if(o){const t=e.dom.create("a",n);o.parentNode.insertBefore(t,o),t.appendChild(o)}},ie=(e,t)=>f(t,(t=>(e=>{return F(t=e,n="items")&&void 0!==t[n]&&null!==t[n];var t,n})(t)?ie(e,t.items):y(t.value===e,t))),ce=(e,t)=>{const n={text:e.text,title:e.title},o=(e,o)=>{const r=(l=t,a=o.name,"link"===a?l.link:"anchor"===a?l.anchor:m.none()).getOr([]);var l,a;return((e,t,n,o)=>{const r=o[t],l=e.length>0;return void 0!==r?ie(r,n).map((t=>({url:{value:t.value,meta:{text:l?e:t.text,attach:u}},text:l?e:t.text}))):m.none()})(n.text,o.name,r,e)};return{onChange:(e,t)=>{const r=t.name;return"url"===r?(e=>{const t=(o=e.url,y(n.text.length<=0,m.from(o.meta.text).getOr(o.value)));var o;const r=(e=>y(n.title.length<=0,m.from(e.meta.title).getOr("")))(e.url);return t.isSome()||r.isSome()?m.some({...t.map((e=>({text:e}))).getOr({}),...r.map((e=>({title:e}))).getOr({})}):m.none()})(e()):((e,t)=>d.call(e,t))(["anchor","link"],r)>-1?o(e(),t):"text"===r||"title"===r?(n[r]=e()[r],m.none()):m.none()}}};var ue=tinymce.util.Tools.resolve("tinymce.util.Delay");const ge=e=>{const t=e.href;return t.indexOf("@")>0&&-1===t.indexOf("/")&&-1===t.indexOf("mailto:")?m.some({message:"The URL you entered seems to be an email address. Do you want to add the required mailto: prefix?",preprocess:e=>({...e,href:"mailto:"+t})}):m.none()},me=(e,t)=>n=>{const o=n.href;return 1===e&&!J(o)||0===e&&/^\s*www(\.|\d\.)/i.test(o)?m.some({message:`The URL you entered seems to be an external link. Do you want to add the required ${t}:// prefix?`,preprocess:e=>({...e,href:t+"://"+o})}):m.none()},de=e=>{const t=e.dom.select("a:not([href])"),n=p(((e,t)=>{const n=e.length,o=new Array(n);for(let r=0;r{const t=e.name||e.id;return t?[{text:t,value:"#"+t}]:[]})));return n.length>0?m.some([{text:"None",value:""}].concat(n)):m.none()},he=e=>{const t=T(e);return t.length>0?B(t):m.none()},pe=e=>{try{return m.some(JSON.parse(e))}catch(e){return m.none()}},fe=(e,t)=>{const n=A(e);if(n.length>0){const o=k(t,"_blank"),r=e=>Q(K(e),o);return(!1===E(e)?I(r):B)(n)}return m.none()},ke=[{text:"Current window",value:""},{text:"New window",value:"_blank"}],ve=e=>{const t=N(e);return l(t)?B(t).orThunk((()=>m.some(ke))):!1===t?m.none():m.some(ke)},ye=(e,t,n)=>{const o=e.getAttrib(t,n);return null!==o&&o.length>0?m.some(o):m.none()},xe=(e,t)=>(e=>{const t=t=>e.convertURL(t.value||t.url,"href"),n=w(e);return new Promise((e=>{o(n)?fetch(n).then((e=>e.ok?e.text().then(pe):Promise.reject())).then(e,(()=>e(m.none()))):i(n)?n((t=>e(m.some(t)))):e(m.from(n))})).then((e=>e.bind(I(t)).map((e=>e.length>0?[{text:"None",value:""}].concat(e):e))))})(e).then((n=>{const o=((e,t)=>{const n=e.dom,o=ee(e)?m.some(Y(e.selection,t)):m.none(),r=t?m.some(n.getAttrib(t,"href")):m.none(),l=t?m.from(n.getAttrib(t,"target")):m.none(),a=ye(n,t,"rel"),s=ye(n,t,"class");return{url:r,text:o,title:ye(n,t,"title"),target:l,rel:a,linkClass:s}})(e,t);return{anchor:o,catalogs:{targets:ve(e),rels:fe(e,o.target),classes:he(e),anchor:de(e),link:n},optNode:m.from(t),flags:{titleEnabled:S(e)}}})),_e=e=>{const t=(e=>{const t=X(e);return xe(e,t)})(e);t.then((t=>{const n=((e,t)=>n=>{const o=n.getData();if(!o.url.value)return le(e),void n.close();const r=e=>m.from(o[e]).filter((n=>!k(t.anchor[e],n))),l={href:o.url.value,text:r("text"),target:r("target"),rel:r("rel"),class:r("linkClass"),title:r("title")},a={href:o.url.value,attach:void 0!==o.url.meta&&o.url.meta.attach?o.url.meta.attach:u};((e,t)=>f([ge,me(_(e),O(e))],(e=>e(t))).fold((()=>Promise.resolve(t)),(n=>new Promise((o=>{((e,t,n)=>{const o=e.selection.getRng();ue.setEditorTimeout(e,(()=>{e.windowManager.confirm(t,(t=>{e.selection.setRng(o),n(t)}))}))})(e,n.message,(e=>{o(e?n.preprocess(t):t)}))})))))(e,l).then((t=>{re(e,a,t)})),n.close()})(e,t);return((e,t,n)=>{const o=e.anchor.text.map((()=>({name:"text",type:"input",label:"Text to display"}))).toArray(),r=e.flags.titleEnabled?[{name:"title",type:"input",label:"Title"}]:[],l=((e,t)=>{const n=e.anchor,o=n.url.getOr("");return{url:{value:o,meta:{original:{value:o}}},text:n.text.getOr(""),title:n.title.getOr(""),anchor:o,link:o,rel:n.rel.getOr(""),target:n.target.or(t).getOr(""),linkClass:n.linkClass.getOr("")}})(e,m.from(C(n))),a=e.catalogs,s=ce(l,a);return{title:"Insert/Edit Link",size:"normal",body:{type:"panel",items:p([[{name:"url",type:"urlinput",filetype:"file",label:"URL"}],o,r,v([a.anchor.map(j("anchor","Anchors")),a.rels.map(j("rel","Rel")),a.targets.map(j("target","Open link in...")),a.link.map(j("link","Link list")),a.classes.map(j("linkClass","Class"))])])},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],initialData:l,onChange:(e,{name:t})=>{s.onChange(e.getData,{name:t}).each((t=>{e.setData(t)}))},onSubmit:t}})(t,n,e)})).then((t=>{e.windowManager.open(t)}))};var be=tinymce.util.Tools.resolve("tinymce.util.VK");const we=(e,t)=>e.dom.getParent(t,"a[href]"),Ce=e=>we(e,e.selection.getStart()),Oe=(e,t)=>{if(t){const n=W(t);if(/^#/.test(n)){const t=e.dom.select(n);t.length&&e.selection.scrollIntoView(t[0],!0)}else(e=>{const t=document.createElement("a");t.target="_blank",t.href=e,t.rel="noreferrer noopener";const n=document.createEvent("MouseEvents");n.initMouseEvent("click",!0,!0,window,0,0,0,0,0,!1,!1,!1,!1,0,null),((e,t)=>{document.body.appendChild(e),e.dispatchEvent(t),document.body.removeChild(e)})(t,n)})(t.href)}},Ne=e=>()=>{e.execCommand("mceLink",!1,{dialog:!0})},Ae=e=>()=>{Oe(e,Ce(e))},Te=(e,t)=>(e.on("NodeChange",t),()=>e.off("NodeChange",t)),Se=e=>t=>{const n=()=>t.setActive(!e.mode.isReadOnly()&&null!==X(e,e.selection.getNode()));return n(),Te(e,n)},Ee=e=>t=>{const n=()=>t.setEnabled(null!==X(e,e.selection.getNode()));return n(),Te(e,n)},Pe=e=>t=>{const n=t=>{return Z(t)||(n=e.selection.getRng(),H(n,G).length>0);var n},o=e.dom.getParents(e.selection.getStart());return t.setEnabled(n(o)),Te(e,(e=>t.setEnabled(n(e.parents))))};e.add("link",(e=>{(e=>{const t=e.options.register;t("link_assume_external_targets",{processor:e=>{const t=o(e)||s(e);return t?!0===e?{value:1,valid:t}:"http"===e||"https"===e?{value:e,valid:t}:{value:0,valid:t}:{valid:!1,message:"Must be a string or a boolean."}},default:!1}),t("link_context_toolbar",{processor:"boolean",default:!1}),t("link_list",{processor:e=>o(e)||i(e)||c(e,r)}),t("link_default_target",{processor:"string"}),t("link_default_protocol",{processor:"string",default:"https"}),t("link_target_list",{processor:e=>s(e)||c(e,r),default:!0}),t("link_rel_list",{processor:"object[]",default:[]}),t("link_class_list",{processor:"object[]",default:[]}),t("link_title",{processor:"boolean",default:!0}),t("allow_unsafe_link_target",{processor:"boolean",default:!1}),t("link_quicklink",{processor:"boolean",default:!1})})(e),(e=>{e.ui.registry.addToggleButton("link",{icon:"link",tooltip:"Insert/edit link",onAction:Ne(e),onSetup:Se(e)}),e.ui.registry.addButton("openlink",{icon:"new-tab",tooltip:"Open link",onAction:Ae(e),onSetup:Ee(e)}),e.ui.registry.addButton("unlink",{icon:"unlink",tooltip:"Remove link",onAction:()=>le(e),onSetup:Pe(e)})})(e),(e=>{e.ui.registry.addMenuItem("openlink",{text:"Open link",icon:"new-tab",onAction:Ae(e),onSetup:Ee(e)}),e.ui.registry.addMenuItem("link",{icon:"link",text:"Link...",shortcut:"Meta+K",onAction:Ne(e)}),e.ui.registry.addMenuItem("unlink",{icon:"unlink",text:"Remove link",onAction:()=>le(e),onSetup:Pe(e)})})(e),(e=>{e.ui.registry.addContextMenu("link",{update:t=>Z(e.dom.getParents(t,"a"))?"link unlink openlink":"link"})})(e),(e=>{const t=t=>{const n=e.selection.getNode();return t.setEnabled(null!==X(e,n)),u};e.ui.registry.addContextForm("quicklink",{launch:{type:"contextformtogglebutton",icon:"link",tooltip:"Link",onSetup:Se(e)},label:"Link",predicate:t=>!!X(e,t)&&b(e),initValue:()=>{const t=X(e);return t?W(t):""},commands:[{type:"contextformtogglebutton",icon:"link",tooltip:"Link",primary:!0,onSetup:t=>{const n=e.selection.getNode();return t.setActive(!!X(e,n)),Se(e)(t)},onAction:t=>{const n=t.getValue(),o=(t=>{const n=X(e),o=ee(e);if(!n&&o){const o=Y(e.selection,n);return m.some(o.length>0?o:t)}return m.none()})(n);re(e,{href:n,attach:u},{href:n,text:o,title:m.none(),rel:m.none(),target:m.none(),class:m.none()}),(e=>{e.selection.collapse(!1)})(e),t.hide()}},{type:"contextformbutton",icon:"unlink",tooltip:"Remove link",onSetup:t,onAction:t=>{le(e),t.hide()}},{type:"contextformbutton",icon:"new-tab",tooltip:"Open link",onSetup:t,onAction:t=>{Ae(e)(),t.hide()}}]})})(e),(e=>{e.on("click",(t=>{const n=we(e,t.target);n&&be.metaKeyPressed(t)&&(t.preventDefault(),Oe(e,n))})),e.on("keydown",(t=>{if(!t.isDefaultPrevented()&&13===t.keyCode&&(e=>!0===e.altKey&&!1===e.shiftKey&&!1===e.ctrlKey&&!1===e.metaKey)(t)){const n=Ce(e);n&&(t.preventDefault(),Oe(e,n))}}))})(e),(e=>{e.addCommand("mceLink",((t,n)=>{!0!==(null==n?void 0:n.dialog)&&P(e)?e.dispatch("contexttoolbar-show",{toolbarKey:"quicklink"}):_e(e)}))})(e),(e=>{e.addShortcut("Meta+K","",(()=>{e.execCommand("mceLink")}))})(e)}))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/lists/plugin.min.js b/public/libs/tinymce/plugins/lists/plugin.min.js index 35811f5b7..3abc58b35 100644 --- a/public/libs/tinymce/plugins/lists/plugin.min.js +++ b/public/libs/tinymce/plugins/lists/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function e(r){return function(e){return n=typeof(t=e),(null===t?"null":"object"==n&&(Array.prototype.isPrototypeOf(t)||t.constructor&&"Array"===t.constructor.name)?"array":"object"==n&&(String.prototype.isPrototypeOf(t)||t.constructor&&"String"===t.constructor.name)?"string":n)===r;var t,n}}function t(t){return function(e){return typeof e===t}}function u(){}function S(e){return function(){return e}}function n(e){return e}function r(e,t){return e===t}function y(t){return function(e){return!t(e)}}function o(){return p}var i=tinymce.util.Tools.resolve("tinymce.PluginManager"),a=e("string"),O=e("object"),s=e("array"),c=t("boolean"),f=t("function"),d=t("number"),l=S(!1),m=S(!0),p={fold:function(e,t){return e()},isSome:l,isNone:m,getOr:n,getOrThunk:g,getOrDie:function(e){throw new Error(e||"error: getOrDie called on none.")},getOrNull:S(null),getOrUndefined:S(void 0),or:n,orThunk:g,map:o,each:u,bind:o,exists:l,forall:m,filter:function(){return p},toArray:function(){return[]},toString:S("none()")};function g(e){return e()}function C(e,t){for(var n=e.length,r=new Array(n),o=0;o=e.childNodes.length?n.data.length:0}:n.previousSibling&&Me(n.previousSibling)?{container:n.previousSibling,offset:n.previousSibling.data.length}:n.nextSibling&&Me(n.nextSibling)?{container:n.nextSibling,offset:0}:{container:e,offset:t}}function We(e){var t=e.cloneRange(),n=Ve(e.startContainer,e.startOffset);t.setStart(n.container,n.offset);var r=Ve(e.endContainer,e.endOffset);return t.setEnd(r.container,r.offset),t}function Qe(e,t){var n=t||e.selection.getStart(!0);return e.dom.getParent(n,"OL,UL,DL",qt(e,n))}function Xe(e){var t,n,r=e.selection.getSelectedBlocks();return L((t=e,n=Mt.map(r,function(e){return t.dom.getParent(e,"li,dd,dt",qt(t,e))||e}),Xt.unique(n)),Ft)}function qe(e,t){return w(e.dom.getParents(t,"ol,ul",qt(e,t)))}function ze(e,t,n){return void 0===n&&(n=r),e.exists(function(e){return n(e,t)})}function Ye(e,t,n){return e.isSome()&&t.isSome()?E.some(n(e.getOrDie(),t.getOrDie())):E.none()}function Ze(e,t,n){return e.fire("ListMutation",{action:t,element:n})}function Ge(e,t){we(e.item,t.list)}function Je(e,t){for(var n=0;ne.length?tt:et)(r,e,t)},[])).map(function(e){return e.list}).toArray()}function ft(e,t){b(L(e,it),function(e){return function(e){switch(t){case"Indent":e.depth++;break;case"Outdent":e.depth--;break;case"Flatten":e.depth=0}e.dirty=!0}(e),0})}function dt(e,t){var n,r,o,i,a,s,u,c,f,d,l,m,p,g=C((i=qe(o=r=e,o.selection.getStart()),a=L(o.selection.getSelectedBlocks(),_t),s=i.toArray().concat(a),zt(r,s)),me.fromDom),v=C(L(Xe(e),Ht),me.fromDom),h=!1;return(g.length||v.length)&&(n=e.selection.getBookmark(),c=t,b((f=g,p=C(Xe(u=e),me.fromDom),d=Ye(N(p,y(rt)),N(D(p),y(rt)),function(e,t){return{start:e,end:t}}),l=!1,m={get:function(){return l},set:function(e){l=e}},C(f,function(e){return{sourceList:e,entries:Yt(0,d,m,e)}})),function(e){ft(e.entries,c);var t,n,r=(t=u,T(function(e,t){if(0===e.length)return[];for(var n=t(e[0]),r=[],o=[],i=0,a=e.length;it=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(n=r=e,(o=String).prototype.isPrototypeOf(n)||(null===(s=r.constructor)||void 0===s?void 0:s.name)===o.name)?"string":t;var n,r,o,s})(t)===e,n=e=>t=>typeof t===e,r=t("string"),o=t("object"),s=t("array"),i=n("boolean"),a=n("function"),l=n("number"),d=()=>{},c=(e,t)=>e===t,u=e=>t=>!e(t),m=(!1,()=>false);class p{constructor(e,t){this.tag=e,this.value=t}static some(e){return new p(!0,e)}static none(){return p.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?p.some(e(this.value)):p.none()}bind(e){return this.tag?e(this.value):p.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:p.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(null!=e?e:"Called getOrDie on None")}static from(e){return null==e?p.none():p.some(e)}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}p.singletonNone=new p(!1);const g=Array.prototype.slice,h=Array.prototype.indexOf,f=Array.prototype.push,y=(e,t)=>{return n=e,r=t,h.call(n,r)>-1;var n,r},C=(e,t)=>{for(let n=0,r=e.length;n{const n=e.length,r=new Array(n);for(let o=0;o{for(let n=0,r=e.length;n{const n=[];for(let r=0,o=e.length;r(b(e,((e,r)=>{n=t(n,e,r)})),n),L=(e,t,n)=>{for(let r=0,o=e.length;rL(e,t,m),T=(e,t)=>(e=>{const t=[];for(let n=0,r=e.length;n{const t=g.call(e,0);return t.reverse(),t},A=(e,t)=>t>=0&&tA(e,0),D=e=>A(e,e.length-1),B=(e,t)=>{const n=[],r=a(t)?e=>C(n,(n=>t(n,e))):e=>y(n,e);for(let t=0,o=e.length;te.exists((e=>n(e,t))),E=(e,t,n)=>e.isSome()&&t.isSome()?p.some(n(e.getOrDie(),t.getOrDie())):p.none(),I=e=>{if(null==e)throw new Error("Node cannot be null or undefined");return{dom:e}},M=(e,t)=>{const n=(t||document).createElement(e);return I(n)},P=I,R=(e,t)=>e.dom===t.dom;"undefined"!=typeof window?window:Function("return this;")();const U=e=>e.dom.nodeName.toLowerCase(),$=(1,e=>1===(e=>e.dom.nodeType)(e));const _=e=>t=>$(t)&&U(t)===e,H=e=>p.from(e.dom.parentNode).map(P),j=e=>v(e.dom.childNodes,P),F=(e,t)=>{const n=e.dom.childNodes;return p.from(n[t]).map(P)},K=e=>F(e,0),V=e=>F(e,e.dom.childNodes.length-1),z=(e,t,n)=>{let r=e.dom;const o=a(n)?n:m;for(;r.parentNode;){r=r.parentNode;const e=P(r);if(t(e))return p.some(e);if(o(e))break}return p.none()},Q=(e,t,n)=>((e,t,n,r,o)=>r(n)?p.some(n):a(o)&&o(n)?p.none():t(n,r,o))(0,z,e,t,n),q=(e,t)=>{H(e).each((n=>{n.dom.insertBefore(t.dom,e.dom)}))},W=(e,t)=>{e.dom.appendChild(t.dom)},Z=(e,t)=>{b(t,(t=>{W(e,t)}))},G=e=>{e.dom.textContent="",b(j(e),(e=>{J(e)}))},J=e=>{const t=e.dom;null!==t.parentNode&&t.parentNode.removeChild(t)};var X=tinymce.util.Tools.resolve("tinymce.dom.RangeUtils"),Y=tinymce.util.Tools.resolve("tinymce.dom.TreeWalker"),ee=tinymce.util.Tools.resolve("tinymce.util.VK");const te=Object.keys,ne=(e,t)=>{const n=te(e);for(let r=0,o=n.length;r{const n=e.dom;ne(t,((e,t)=>{((e,t,n)=>{if(!(r(n)||i(n)||l(n)))throw console.error("Invalid call to Attribute.set. Key ",t,":: Value ",n,":: Element ",e),new Error("Attribute value was not simple");e.setAttribute(t,n+"")})(n,t,e)}))},oe=e=>N(e.dom.attributes,((e,t)=>(e[t.name]=t.value,e)),{}),se=e=>((e,t)=>P(e.dom.cloneNode(!0)))(e),ie=(e,t)=>{const n=((e,t)=>{const n=M(t),r=oe(e);return re(n,r),n})(e,t);((e,t)=>{const n=(e=>p.from(e.dom.nextSibling).map(P))(e);n.fold((()=>{H(e).each((e=>{W(e,t)}))}),(e=>{q(e,t)}))})(e,n);const r=j(e);return Z(n,r),J(e),n};var ae=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),le=tinymce.util.Tools.resolve("tinymce.util.Tools");const de=e=>t=>t&&t.nodeName.toLowerCase()===e,ce=e=>t=>t&&e.test(t.nodeName),ue=e=>e&&3===e.nodeType,me=ce(/^(OL|UL|DL)$/),pe=ce(/^(OL|UL)$/),ge=de("ol"),he=ce(/^(LI|DT|DD)$/),fe=ce(/^(DT|DD)$/),ye=ce(/^(TH|TD)$/),Ce=de("br"),ve=(e,t)=>t&&!!e.schema.getTextBlockElements()[t.nodeName],be=(e,t)=>e&&e.nodeName in t,Se=(e,t,n)=>{const r=e.isEmpty(t);return!(n&&e.select("span[data-mce-type=bookmark]",t).length>0)&&r},Ne=(e,t)=>e.isChildOf(t,e.getRoot()),Le=e=>t=>t.options.get(e),Oe=Le("lists_indent_on_tab"),Te=Le("forced_root_block"),ke=Le("forced_root_block_attrs"),Ae=(e,t)=>{const n=e.dom,r=e.schema.getBlockElements(),o=n.createFragment(),s=Te(e),i=ke(e);let a,l,d;for(l=n.create(s,i),be(t.firstChild,r)||o.appendChild(l);a=t.firstChild;){const e=a.nodeName;d||"SPAN"===e&&"bookmark"===a.getAttribute("data-mce-type")||(d=!0),be(a,r)?(o.appendChild(a),l=null):(l||(l=n.create(s,i),o.appendChild(l)),l.appendChild(a))}return d||l.appendChild(n.create("br",{"data-mce-bogus":"1"})),o},we=ae.DOM,De=_("dd"),Be=_("dt"),xe=e=>{Be(e)&&ie(e,"dd")},Ee=(e,t,n)=>{b(n,"Indent"===t?xe:t=>((e,t)=>{De(t)?ie(t,"dt"):Be(t)&&H(t).each((n=>((e,t,n)=>{const r=we.select('span[data-mce-type="bookmark"]',t),o=Ae(e,n),s=we.createRng();s.setStartAfter(n),s.setEndAfter(t);const i=s.extractContents();for(let t=i.firstChild;t;t=t.firstChild)if("LI"===t.nodeName&&e.dom.isEmpty(t)){we.remove(t);break}var a;e.dom.isEmpty(i)||we.insertAfter(i,t),we.insertAfter(o,t),Se(e.dom,n.parentNode)&&(a=n.parentNode,le.each(r,(e=>{a.parentNode.insertBefore(e,n.parentNode)})),we.remove(a)),we.remove(n),Se(e.dom,t)&&we.remove(t)})(e,n.dom,t.dom)))})(e,t))},Ie=(e,t)=>{if(ue(e))return{container:e,offset:t};const n=X.getNode(e,t);return ue(n)?{container:n,offset:t>=e.childNodes.length?n.data.length:0}:n.previousSibling&&ue(n.previousSibling)?{container:n.previousSibling,offset:n.previousSibling.data.length}:n.nextSibling&&ue(n.nextSibling)?{container:n.nextSibling,offset:0}:{container:e,offset:t}},Me=e=>{const t=e.cloneRange(),n=Ie(e.startContainer,e.startOffset);t.setStart(n.container,n.offset);const r=Ie(e.endContainer,e.endOffset);return t.setEnd(r.container,r.offset),t},Pe=["OL","UL","DL"],Re=Pe.join(","),Ue=(e,t)=>{const n=t||e.selection.getStart(!0);return e.dom.getParent(n,Re,He(e,n))},$e=e=>{const t=e.selection.getSelectedBlocks();return S(((e,t)=>{const n=le.map(t,(t=>e.dom.getParent(t,"li,dd,dt",He(e,t))||t));return B(n)})(e,t),he)},_e=(e,t)=>{const n=e.dom.getParents(t,"TD,TH");return n.length>0?n[0]:e.getBody()},He=(e,t)=>{const n=e.dom.getParents(t,e.dom.isBlock),r=O(n,(t=>{return n=e.schema,!me(r=t)&&!he(r)&&C(Pe,(e=>n.isValidChild(r.nodeName,e)));var n,r}));return r.getOr(e.getBody())},je=(e,t)=>{const n=e.dom.getParents(t,"ol,ul",He(e,t));return D(n)},Fe=(e,t)=>{const n=v(t,(t=>je(e,t).getOr(t)));return B(n)},Ke=(e,t,n)=>e.dispatch("ListMutation",{action:t,element:n}),Ve=(ze=/^\s+|\s+$/g,e=>e.replace(ze,""));var ze;const Qe=(e,t,n)=>{((e,t,n)=>{if(!r(n))throw console.error("Invalid call to CSS.set. Property ",t,":: Value ",n,":: Element ",e),new Error("CSS value must be a string: "+n);(e=>void 0!==e.style&&a(e.style.getPropertyValue))(e)&&e.style.setProperty(t,n)})(e.dom,t,n)},qe=(e,t)=>{W(e.item,t.list)},We=(e,t)=>{const n={list:M(t,e),item:M("li",e)};return W(n.list,n.item),n},Ze=e=>((e,t)=>{const n=e.dom;if(1!==n.nodeType)return!1;{const e=n;if(void 0!==e.matches)return e.matches(t);if(void 0!==e.msMatchesSelector)return e.msMatchesSelector(t);if(void 0!==e.webkitMatchesSelector)return e.webkitMatchesSelector(t);if(void 0!==e.mozMatchesSelector)return e.mozMatchesSelector(t);throw new Error("Browser lacks native selectors")}})(e,"OL,UL"),Ge=e=>K(e).exists(Ze),Je=e=>e.depth>0,Xe=e=>e.isSelected,Ye=e=>{const t=j(e),n=V(e).exists(Ze)?t.slice(0,-1):t;return v(n,se)},et=e=>(b(e,((t,n)=>{((e,t)=>{const n=e[t].depth,r=e=>e.depth===n&&!e.dirty,o=e=>e.depthL(e.slice(t+1),r,o)))})(e,n).fold((()=>{t.dirty&&(e=>{e.listAttributes=((e,t)=>{const n={};var r;return((e,t,n,r)=>{ne(e,((e,o)=>{(t(e,o)?n:r)(e,o)}))})(e,t,(r=n,(e,t)=>{r[t]=e}),d),n})(e.listAttributes,((e,t)=>"start"!==t))})(t)}),(e=>{return r=e,(n=t).listType=r.listType,void(n.listAttributes={...r.listAttributes});var n,r}))})),e),tt=(e,t,n,r)=>K(r).filter(Ze).fold((()=>{t.each((e=>{R(e.start,r)&&n.set(!0)}));const o=((e,t,n)=>H(e).filter($).map((r=>({depth:t,dirty:!1,isSelected:n,content:Ye(e),itemAttributes:oe(e),listAttributes:oe(r),listType:U(r)}))))(r,e,n.get());t.each((e=>{R(e.end,r)&&n.set(!1)}));const s=V(r).filter(Ze).map((r=>nt(e,t,n,r))).getOr([]);return o.toArray().concat(s)}),(r=>nt(e,t,n,r))),nt=(e,t,n,r)=>T(j(r),(r=>(Ze(r)?nt:tt)(e+1,t,n,r))),rt=(e,t)=>{const n=et(t);return((e,t)=>{const n=N(t,((t,n)=>n.depth>t.length?((e,t,n)=>{const r=((e,t,n)=>{const r=[];for(let o=0;o{for(let t=1;t{for(let t=0;t{re(e.list,t.listAttributes),re(e.item,t.itemAttributes),Z(e.item,t.content)}))})(r,n),o=r,E(D(t),w(o),qe),t.concat(r)})(e,t,n):((e,t,n)=>{const r=t.slice(0,n.depth);return D(r).each((t=>{const r=((e,t,n)=>{const r=M("li",e);return re(r,t),Z(r,n),r})(e,n.itemAttributes,n.content);((e,t)=>{W(e.list,t),e.item=t})(t,r),((e,t)=>{U(e.list)!==t.listType&&(e.list=ie(e.list,t.listType)),re(e.list,t.listAttributes)})(t,n)})),r})(e,t,n)),[]);return w(n).map((e=>e.list))})(e.contentDocument,n).toArray()},ot=(e,t,n)=>{const r=((e,t)=>{const n=(e=>{let t=!1;return{get:()=>t,set:e=>{t=e}}})();return v(e,(e=>({sourceList:e,entries:nt(0,t,n,e)})))})(t,(e=>{const t=v($e(e),P);return E(O(t,u(Ge)),O(k(t),u(Ge)),((e,t)=>({start:e,end:t})))})(e));b(r,(t=>{((e,t)=>{b(S(e,Xe),(e=>((e,t)=>{switch(e){case"Indent":t.depth++;break;case"Outdent":t.depth--;break;case"Flatten":t.depth=0}t.dirty=!0})(t,e)))})(t.entries,n);const r=((e,t)=>T(((e,t)=>{if(0===e.length)return[];{let n=t(e[0]);const r=[];let o=[];for(let s=0,i=e.length;sw(t).exists(Je)?rt(e,t):((e,t)=>{const n=et(t);return v(n,(t=>{const n=((e,t)=>{const n=document.createDocumentFragment();return b(e,(e=>{n.appendChild(e.dom)})),P(n)})(t.content);return P(Ae(e,n.dom))}))})(e,t))))(e,t.entries);var o;b(r,(t=>{Ke(e,"Indent"===n?"IndentList":"OutdentList",t.dom)})),o=t.sourceList,b(r,(e=>{q(o,e)})),J(t.sourceList)}))},st=(e,t)=>{const n=v((e=>{const t=(e=>{const t=je(e,e.selection.getStart()),n=S(e.selection.getSelectedBlocks(),pe);return t.toArray().concat(n)})(e);return Fe(e,t)})(e),P),r=v((e=>S($e(e),fe))(e),P);let o=!1;if(n.length||r.length){const s=e.selection.getBookmark();ot(e,n,t),Ee(e,t,r),e.selection.moveToBookmark(s),e.selection.setRng(Me(e.selection.getRng())),e.nodeChanged(),o=!0}return o},it=e=>st(e,"Indent"),at=e=>st(e,"Outdent"),lt=e=>st(e,"Flatten");var dt=tinymce.util.Tools.resolve("tinymce.dom.BookmarkManager");const ct=ae.DOM,ut=e=>{const t={},n=n=>{let r=e[n?"startContainer":"endContainer"],o=e[n?"startOffset":"endOffset"];if(1===r.nodeType){const e=ct.create("span",{"data-mce-type":"bookmark"});r.hasChildNodes()?(o=Math.min(o,r.childNodes.length-1),n?r.insertBefore(e,r.childNodes[o]):ct.insertAfter(e,r.childNodes[o])):r.appendChild(e),r=e,o=0}t[n?"startContainer":"endContainer"]=r,t[n?"startOffset":"endOffset"]=o};return n(!0),e.collapsed||n(),t},mt=e=>{const t=t=>{let n,r=n=e[t?"startContainer":"endContainer"],o=e[t?"startOffset":"endOffset"];r&&(1===r.nodeType&&(o=(e=>{let t=e.parentNode.firstChild,n=0;for(;t;){if(t===e)return n;1===t.nodeType&&"bookmark"===t.getAttribute("data-mce-type")||n++,t=t.nextSibling}return-1})(r),r=r.parentNode,ct.remove(n),!r.hasChildNodes()&&ct.isBlock(r)&&r.appendChild(ct.create("br"))),e[t?"startContainer":"endContainer"]=r,e[t?"startOffset":"endOffset"]=o)};t(!0),t();const n=ct.createRng();return n.setStart(e.startContainer,e.startOffset),e.endContainer&&n.setEnd(e.endContainer,e.endOffset),Me(n)},pt=e=>{switch(e){case"UL":return"ToggleUlList";case"OL":return"ToggleOlList";case"DL":return"ToggleDLList"}},gt=e=>/\btox\-/.test(e.className),ht=(e,t,n)=>{const r=e=>{const r=L(e.parents,me,ye).filter((e=>e.nodeName===t&&!gt(e))).isSome();n(r)},o=e.dom.getParents(e.selection.getNode());return r({parents:o}),e.on("NodeChange",r),()=>e.off("NodeChange",r)},ft=(e,t)=>{le.each(t,((t,n)=>{e.setAttribute(n,t)}))},yt=(e,t,n)=>{((e,t,n)=>{const r=n["list-style-type"]?n["list-style-type"]:null;e.setStyle(t,"list-style-type",r)})(e,t,n),((e,t,n)=>{ft(t,n["list-attributes"]),le.each(e.select("li",t),(e=>{ft(e,n["list-item-attributes"])}))})(e,t,n)},Ct=(e,t,n,r)=>{let o=t[n?"startContainer":"endContainer"];const s=t[n?"startOffset":"endOffset"];for(1===o.nodeType&&(o=o.childNodes[Math.min(s,o.childNodes.length-1)]||o),!n&&Ce(o.nextSibling)&&(o=o.nextSibling);o.parentNode!==r;){if(ve(e,o))return o;if(/^(TD|TH)$/.test(o.parentNode.nodeName))return o;o=o.parentNode}return o},vt=(e,t,n)=>{const r=e.selection.getRng();let o="LI";const s=He(e,e.selection.getStart(!0)),i=e.dom;if("false"===i.getContentEditable(e.selection.getNode()))return;"DL"===(t=t.toUpperCase())&&(o="DT");const a=ut(r),l=((e,t,n)=>{const r=[],o=e.dom,s=Ct(e,t,!0,n),i=Ct(e,t,!1,n);let a;const l=[];for(let e=s;e&&(l.push(e),e!==i);e=e.nextSibling);return le.each(l,(t=>{if(ve(e,t))return r.push(t),void(a=null);if(o.isBlock(t)||Ce(t))return Ce(t)&&o.remove(t),void(a=null);const s=t.nextSibling;dt.isBookmarkNode(t)&&(me(s)||ve(e,s)||!s&&t.parentNode===n)?a=null:(a||(a=o.create("p"),t.parentNode.insertBefore(a,t),r.push(a)),a.appendChild(t))})),r})(e,r,s);le.each(l,(r=>{let s;const a=r.previousSibling,l=r.parentNode;he(l)||(a&&me(a)&&a.nodeName===t&&((e,t,n)=>{const r=e.getStyle(t,"list-style-type");let o=n?n["list-style-type"]:"";return o=null===o?"":o,r===o})(i,a,n)?(s=a,r=i.rename(r,o),a.appendChild(r)):(s=i.create(t),r.parentNode.insertBefore(s,r),s.appendChild(r),r=i.rename(r,o)),((e,t,n)=>{le.each(["margin","margin-right","margin-bottom","margin-left","margin-top","padding","padding-right","padding-bottom","padding-left","padding-top"],(n=>e.setStyle(t,n,"")))})(i,r),yt(i,s,n),St(e.dom,s))})),e.selection.setRng(mt(a))},bt=(e,t,n)=>{return((e,t)=>e&&t&&me(e)&&e.nodeName===t.nodeName)(t,n)&&((e,t,n)=>e.getStyle(t,"list-style-type",!0)===e.getStyle(n,"list-style-type",!0))(e,t,n)&&(r=n,t.className===r.className);var r},St=(e,t)=>{let n,r;if(n=t.nextSibling,bt(e,t,n)){for(;r=n.firstChild;)t.appendChild(r);e.remove(n)}if(n=t.previousSibling,bt(e,t,n)){for(;r=n.lastChild;)t.insertBefore(r,t.firstChild);e.remove(n)}},Nt=e=>"list-style-type"in e,Lt=(e,t,n)=>{const r=Ue(e),s=(e=>{const t=Ue(e),n=e.selection.getSelectedBlocks();return((e,t)=>e&&1===t.length&&t[0]===e)(t,n)?(e=>S(e.querySelectorAll(Re),me))(t):S(n,(e=>me(e)&&t!==e))})(e),i=o(n)?n:{};s.length>0?((e,t,n,r,o)=>{const s=me(t);if(s&&t.nodeName===r&&!Nt(o))lt(e);else{vt(e,r,o);const i=ut(e.selection.getRng()),a=s?[t,...n]:n;le.each(a,(t=>{((e,t,n,r)=>{if(t.nodeName!==n){const o=e.dom.rename(t,n);yt(e.dom,o,r),Ke(e,pt(n),o)}else yt(e.dom,t,r),Ke(e,pt(n),t)})(e,t,r,o)})),e.selection.setRng(mt(i))}})(e,r,s,t,i):((e,t,n,r)=>{if(t!==e.getBody())if(t)if(t.nodeName!==n||Nt(r)||gt(t)){const o=ut(e.selection.getRng());yt(e.dom,t,r);const s=e.dom.rename(t,n);St(e.dom,s),e.selection.setRng(mt(o)),vt(e,n,r),Ke(e,pt(n),s)}else lt(e);else vt(e,n,r),Ke(e,pt(n),t)})(e,r,t,i)},Ot=ae.DOM,Tt=(e,t)=>{const n=le.grep(e.select("ol,ul",t));le.each(n,(t=>{((e,t)=>{const n=t.parentNode;if("LI"===n.nodeName&&n.firstChild===t){const r=n.previousSibling;r&&"LI"===r.nodeName?(r.appendChild(t),Se(e,n)&&Ot.remove(n)):Ot.setStyle(n,"listStyleType","none")}if(me(n)){const e=n.previousSibling;e&&"LI"===e.nodeName&&e.appendChild(t)}})(e,t)}))},kt=(e,t,n,r)=>{let o=t.startContainer;const s=t.startOffset;if(ue(o)&&(n?s0))return o;const i=e.schema.getNonEmptyElements();1===o.nodeType&&(o=X.getNode(o,s));const a=new Y(o,r);n&&((e,t)=>!!Ce(t)&&e.isBlock(t.nextSibling)&&!Ce(t.previousSibling))(e.dom,o)&&a.next();const l=n?a.next.bind(a):a.prev2.bind(a);for(;o=l();){if("LI"===o.nodeName&&!o.hasChildNodes())return o;if(i[o.nodeName])return o;if(ue(o)&&o.data.length>0)return o}},At=(e,t)=>{const n=t.childNodes;return 1===n.length&&!me(n[0])&&e.isBlock(n[0])},wt=(e,t,n)=>{let r;const o=t.parentNode;if(!Ne(e,t)||!Ne(e,n))return;me(n.lastChild)&&(r=n.lastChild),o===n.lastChild&&Ce(o.previousSibling)&&e.remove(o.previousSibling);const s=n.lastChild;s&&Ce(s)&&t.hasChildNodes()&&e.remove(s),Se(e,n,!0)&&G(P(n)),((e,t,n)=>{let r;const o=At(e,n)?n.firstChild:n;if(((e,t)=>{At(e,t)&&e.remove(t.firstChild,!0)})(e,t),!Se(e,t,!0))for(;r=t.firstChild;)o.appendChild(r)})(e,t,n),r&&n.appendChild(r);const i=((e,t)=>{const n=e.dom,r=t.dom;return n!==r&&n.contains(r)})(P(n),P(t))?e.getParents(t,me,n):[];e.remove(t),b(i,(t=>{Se(e,t)&&t!==e.getRoot()&&e.remove(t)}))},Dt=(e,t)=>{const n=e.dom,r=e.selection,o=r.getStart(),s=_e(e,o),i=n.getParent(r.getStart(),"LI",s);if(i){const o=i.parentNode;if(o===e.getBody()&&Se(n,o))return!0;const a=Me(r.getRng()),l=n.getParent(kt(e,a,t,s),"LI",s);if(l&&l!==i)return e.undoManager.transact((()=>{var n;t?((e,t,n,r)=>{const o=e.dom;if(o.isEmpty(r))((e,t,n)=>{G(P(n)),wt(e.dom,t,n),e.selection.setCursorLocation(n,0)})(e,n,r);else{const s=ut(t);wt(o,n,r),e.selection.setRng(mt(s))}})(e,a,l,i):(n=i).parentNode.firstChild===n?at(e):((e,t,n,r)=>{const o=ut(t);wt(e.dom,n,r);const s=mt(o);e.selection.setRng(s)})(e,a,i,l)})),!0;if(!l&&!t&&0===a.startOffset&&0===a.endOffset)return e.undoManager.transact((()=>{lt(e)})),!0}return!1},Bt=e=>{const t=e.selection.getStart(),n=_e(e,t);return e.dom.getParent(t,"LI,DT,DD",n)||$e(e).length>0},xt=(e,t)=>e.selection.isCollapsed()?((e,t)=>Dt(e,t)||((e,t)=>{const n=e.dom,r=e.selection.getStart(),o=_e(e,r),s=n.getParent(r,n.isBlock,o);if(s&&n.isEmpty(s)){const r=Me(e.selection.getRng()),i=n.getParent(kt(e,r,t,o),"LI",o);if(i){const a=e=>y(["td","th","caption"],U(e)),l=e=>e.dom===o;return!!((e,t,n=c)=>E(e,t,n).getOr(e.isNone()&&t.isNone()))(Q(P(i),a,l),Q(P(r.startContainer),a,l),R)&&(e.undoManager.transact((()=>{((e,t,n)=>{const r=e.getParent(t.parentNode,e.isBlock,n);e.remove(t),r&&e.isEmpty(r)&&e.remove(r)})(n,s,o),St(n,i.parentNode),e.selection.select(i,!0),e.selection.collapse(t)})),!0)}}return!1})(e,t))(e,t):(e=>!!Bt(e)&&(e.undoManager.transact((()=>{e.execCommand("Delete"),Tt(e.dom,e.getBody())})),!0))(e),Et=e=>{const t=k(Ve(e).split("")),n=v(t,((e,t)=>{const n=e.toUpperCase().charCodeAt(0)-"A".charCodeAt(0)+1;return Math.pow(26,t)*n}));return N(n,((e,t)=>e+t),0)},It=e=>{if(--e<0)return"";{const t=e%26,n=Math.floor(e/26);return It(n)+String.fromCharCode("A".charCodeAt(0)+t)}},Mt=e=>{const t=parseInt(e.start,10);return x(e.listStyleType,"upper-alpha")?It(t):x(e.listStyleType,"lower-alpha")?It(t).toLowerCase():e.start},Pt=(e,t)=>()=>{const n=Ue(e);return n&&n.nodeName===t},Rt=e=>{e.addCommand("mceListProps",(()=>{(e=>{const t=Ue(e);ge(t)&&e.windowManager.open({title:"List Properties",body:{type:"panel",items:[{type:"input",name:"start",label:"Start list at number",inputMode:"numeric"}]},initialData:{start:Mt({start:e.dom.getAttrib(t,"start","1"),listStyleType:p.some(e.dom.getStyle(t,"list-style-type"))})},buttons:[{type:"cancel",name:"cancel",text:"Cancel"},{type:"submit",name:"save",text:"Save",primary:!0}],onSubmit:t=>{(e=>{switch((e=>/^[0-9]+$/.test(e)?2:/^[A-Z]+$/.test(e)?0:/^[a-z]+$/.test(e)?1:e.length>0?4:3)(e)){case 2:return p.some({listStyleType:p.none(),start:e});case 0:return p.some({listStyleType:p.some("upper-alpha"),start:Et(e).toString()});case 1:return p.some({listStyleType:p.some("lower-alpha"),start:Et(e).toString()});case 3:return p.some({listStyleType:p.none(),start:""});case 4:return p.none()}})(t.getData().start).each((t=>{e.execCommand("mceListUpdate",!1,{attrs:{start:"1"===t.start?"":t.start},styles:{"list-style-type":t.listStyleType.getOr("")}})})),t.close()}})})(e)}))};e.add("lists",(e=>((e=>{(0,e.options.register)("lists_indent_on_tab",{processor:"boolean",default:!0})})(e),!1===e.hasPlugin("rtc",!0)?((e=>{Oe(e)&&(e=>{e.on("keydown",(t=>{t.keyCode!==ee.TAB||ee.metaKeyPressed(t)||e.undoManager.transact((()=>{(t.shiftKey?at(e):it(e))&&t.preventDefault()}))}))})(e),(e=>{e.on("ExecCommand",(t=>{const n=t.command.toLowerCase();"delete"!==n&&"forwarddelete"!==n||!Bt(e)||Tt(e.dom,e.getBody())})),e.on("keydown",(t=>{t.keyCode===ee.BACKSPACE?xt(e,!1)&&t.preventDefault():t.keyCode===ee.DELETE&&xt(e,!0)&&t.preventDefault()}))})(e)})(e),(e=>{e.on("BeforeExecCommand",(t=>{const n=t.command.toLowerCase();"indent"===n?it(e):"outdent"===n&&at(e)})),e.addCommand("InsertUnorderedList",((t,n)=>{Lt(e,"UL",n)})),e.addCommand("InsertOrderedList",((t,n)=>{Lt(e,"OL",n)})),e.addCommand("InsertDefinitionList",((t,n)=>{Lt(e,"DL",n)})),e.addCommand("RemoveList",(()=>{lt(e)})),Rt(e),e.addCommand("mceListUpdate",((t,n)=>{o(n)&&((e,t)=>{const n=Ue(e);e.undoManager.transact((()=>{o(t.styles)&&e.dom.setStyles(n,t.styles),o(t.attrs)&&ne(t.attrs,((t,r)=>e.dom.setAttrib(n,r,t)))}))})(e,n)})),e.addQueryStateHandler("InsertUnorderedList",Pt(e,"UL")),e.addQueryStateHandler("InsertOrderedList",Pt(e,"OL")),e.addQueryStateHandler("InsertDefinitionList",Pt(e,"DL"))})(e)):Rt(e),(e=>{const t=t=>()=>e.execCommand(t);e.hasPlugin("advlist")||(e.ui.registry.addToggleButton("numlist",{icon:"ordered-list",active:!1,tooltip:"Numbered list",onAction:t("InsertOrderedList"),onSetup:t=>ht(e,"OL",t.setActive)}),e.ui.registry.addToggleButton("bullist",{icon:"unordered-list",active:!1,tooltip:"Bullet list",onAction:t("InsertUnorderedList"),onSetup:t=>ht(e,"UL",t.setActive)}))})(e),(e=>{const t={text:"List properties...",icon:"ordered-list",onAction:()=>e.execCommand("mceListProps"),onSetup:t=>ht(e,"OL",t.setEnabled)};e.ui.registry.addMenuItem("listprops",t),e.ui.registry.addContextMenu("lists",{update:t=>{const n=Ue(e,t);return ge(n)?["listprops"]:[]}})})(e),(e=>({backspaceDelete:t=>{xt(e,t)}}))(e))))}(); \ No newline at end of file diff --git a/public/libs/tinymce/plugins/media/plugin.min.js b/public/libs/tinymce/plugins/media/plugin.min.js index 0e9e7c5e5..00c9993c2 100644 --- a/public/libs/tinymce/plugins/media/plugin.min.js +++ b/public/libs/tinymce/plugins/media/plugin.min.js @@ -1,9 +1,4 @@ /** - * Copyright (c) Tiny Technologies, Inc. All rights reserved. - * Licensed under the LGPL or a commercial license. - * For LGPL see License.txt in the project root for license information. - * For commercial licenses see https://www.tiny.cloud/ - * - * Version: 5.10.2 (2021-11-17) + * TinyMCE version 6.1.0 (2022-06-29) */ -!function(){"use strict";function e(n){return function(e){return r=typeof(t=e),(null===t?"null":"object"==r&&(Array.prototype.isPrototypeOf(t)||t.constructor&&"Array"===t.constructor.name)?"array":"object"==r&&(String.prototype.isPrototypeOf(t)||t.constructor&&"String"===t.constructor.name)?"string":r)===n;var t,r}}function s(e){return null!=e}function o(e){return function(){return e}}function t(e){return e}function r(){return d}var n=tinymce.util.Tools.resolve("tinymce.PluginManager"),p=function(){return(p=Object.assign||function(e){for(var t,r=1,n=arguments.length;r"):"application/x-shockwave-flash"===n.sourcemime?(u='',n.poster&&(u+=''),u+""):-1!==n.sourcemime.indexOf("audio")?(s=n,m?m(s):'"):"script"===n.type?''); + $this->withHtml($pageView)->assertElementNotContains('.page-content', ''); } } @@ -185,13 +185,14 @@ class PageContentTest extends TestCase $pageView = $this->get($page->getUrl()); $pageView->assertStatus(200); - $pageView->assertElementNotContains('.page-content', ''); - $pageView->assertElementNotContains('.page-content', 'src='); - $pageView->assertElementNotContains('.page-content', 'javascript:'); - $pageView->assertElementNotContains('.page-content', 'data:'); - $pageView->assertElementNotContains('.page-content', 'base64'); + $html = $this->withHtml($pageView); + $html->assertElementNotContains('.page-content', ''); + $html->assertElementNotContains('.page-content', 'src='); + $html->assertElementNotContains('.page-content', 'javascript:'); + $html->assertElementNotContains('.page-content', 'data:'); + $html->assertElementNotContains('.page-content', 'base64'); } } @@ -213,8 +214,8 @@ class PageContentTest extends TestCase $pageView = $this->get($page->getUrl()); $pageView->assertStatus(200); - $pageView->assertElementNotContains('.page-content', 'assertElementNotContains('.page-content', 'href=javascript:'); + $this->withHtml($pageView)->assertElementNotContains('.page-content', 'withHtml($pageView)->assertElementNotContains('.page-content', 'href=javascript:'); } } @@ -237,11 +238,11 @@ class PageContentTest extends TestCase $pageView = $this->get($page->getUrl()); $pageView->assertStatus(200); - $pageView->assertElementNotContains('.page-content', ' - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @php + $languages = [ + 'Bash', 'CSS', 'C', 'C++', 'C#', 'Diff', 'Fortran', 'F#', 'Go', 'Haskell', 'HTML', 'INI', + 'Java', 'JavaScript', 'JSON', 'Julia', 'Kotlin', 'LaTeX', 'Lua', 'MarkDown', 'Nginx', 'OCaml', + 'Pascal', 'Perl', 'PHP', 'Powershell', 'Python', 'Ruby', 'Rust', 'Shell', 'SQL', 'TypeScript', + 'VBScript', 'VB.NET', 'XML', 'YAML', + ]; + @endphp + + @foreach($languages as $language) +
    + + +
    + @endforeach
    From 3fa43c804b3e9ee46e8c5e3cdcb3e985d686d319 Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 25 Jul 2022 00:23:51 +0100 Subject: [PATCH 191/246] New translations activities.php (Indonesian) --- resources/lang/id/activities.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/lang/id/activities.php b/resources/lang/id/activities.php index e7b065c8a..3ea6da17c 100644 --- a/resources/lang/id/activities.php +++ b/resources/lang/id/activities.php @@ -7,7 +7,7 @@ return [ // Pages 'page_create' => 'telah membuat halaman', - 'page_create_notification' => 'Page successfully created', + 'page_create_notification' => 'Jenis Halaman berhasil dibuat', 'page_update' => 'halaman telah diperbaharui', 'page_update_notification' => 'Page successfully updated', 'page_delete' => 'halaman dihapus', From 0df5ae0658b5ff409c2cc3d3da278692f80c790d Mon Sep 17 00:00:00 2001 From: Dan Brown Date: Mon, 25 Jul 2022 13:10:27 +0100 Subject: [PATCH 192/246] Added core code-lang-favourites JS, PHP & CSS logic - Got the functionality now working to favourite items and store that status within the system for the user. - Improved CSS display for usability. --- app/Http/Controllers/UserController.php | 21 ++++++++++ resources/js/components/code-editor.js | 39 +++++++++++++++++++ resources/sass/_components.scss | 11 +++++- .../views/pages/parts/code-editor.blade.php | 12 +++--- routes/web.php | 1 + 5 files changed, 76 insertions(+), 8 deletions(-) diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 2c9203687..9a2f2c867 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -289,6 +289,27 @@ class UserController extends Controller return response('', 204); } + public function updateCodeLanguageFavourite(Request $request) + { + $validated = $this->validate($request, [ + 'language' => ['required', 'string', 'max:20'], + 'active' => ['required', 'bool'], + ]); + + $currentFavoritesStr = setting()->getForCurrentUser('code-language-favourites', ''); + $currentFavorites = array_filter(explode(',', $currentFavoritesStr)); + + $isFav = in_array($validated['language'], $currentFavorites); + if (!$isFav && $validated['active']) { + $currentFavorites[] = $validated['language']; + } else if ($isFav && !$validated['active']) { + $index = array_search($validated['language'], $currentFavorites); + array_splice($currentFavorites, $index, 1); + } + + setting()->putUser(user(), 'code-language-favourites', implode(',', $currentFavorites)); + } + /** * Changed the stored preference for a list sort order. */ diff --git a/resources/js/components/code-editor.js b/resources/js/components/code-editor.js index 7ed5a1cbe..022deafef 100644 --- a/resources/js/components/code-editor.js +++ b/resources/js/components/code-editor.js @@ -15,12 +15,14 @@ class CodeEditor { this.languageInput = this.$refs.languageInput; this.historyDropDown = this.$refs.historyDropDown; this.historyList = this.$refs.historyList; + this.favourites = new Set(this.$opts.favourites.split(',')); this.callback = null; this.editor = null; this.history = {}; this.historyKey = 'code_history'; this.setupListeners(); + this.setupFavourites(); } setupListeners() { @@ -49,6 +51,43 @@ class CodeEditor { }); } + setupFavourites() { + for (const button of this.languageLinks) { + this.setupFavouritesForButton(button); + } + + this.sortLanguageList(); + } + + /** + * @param {HTMLButtonElement} button + */ + setupFavouritesForButton(button) { + const language = button.dataset.lang; + let isFavorite = this.favourites.has(language); + button.setAttribute('data-favourite', isFavorite ? 'true' : 'false'); + + onChildEvent(button.parentElement, '.lang-option-favorite-toggle', 'click', () => { + isFavorite = !isFavorite; + isFavorite ? this.favourites.add(language) : this.favourites.delete(language); + button.setAttribute('data-favourite', isFavorite ? 'true' : 'false'); + + window.$http.patch('/settings/users/update-code-language-favourite', { + language: language, + active: isFavorite + }); + + this.sortLanguageList(); + if (isFavorite) { + button.scrollIntoView({block: "center", behavior: "smooth"}); + } + }); + } + + sortLanguageList() { + // TODO + } + save() { if (this.callback) { this.callback(this.editor.getValue(), this.languageInput.value); diff --git a/resources/sass/_components.scss b/resources/sass/_components.scss index 9b6d624c1..74a3ac8bc 100644 --- a/resources/sass/_components.scss +++ b/resources/sass/_components.scss @@ -666,7 +666,7 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { text-align: left; font-family: $mono; font-size: 0.7rem; - padding-right: 24px + $-m; + padding-left: 24px + $-s; &:hover, &.active { background-color: var(--color-primary-light); color: var(--color-primary); @@ -675,7 +675,8 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { .code-editor button.lang-option-favorite-toggle { position: absolute; - right: 0; + top: 0; + left: 0; width: 28px; font-size: 1rem; border: 0; @@ -684,11 +685,17 @@ body.flexbox-support #entity-selector-wrap .popup-body .form-group { z-index: 2; height: 100%; text-align: center; + color: var(--color-primary); svg { margin: 0; } } +.code-editor button[data-favourite="true"] ~ .action-favourite, +.code-editor button[data-favourite="false"] ~ .action-unfavourite { + display: none; +} + .code-editor label { background-color: var(--color-primary-light); width: 100%; diff --git a/resources/views/pages/parts/code-editor.blade.php b/resources/views/pages/parts/code-editor.blade.php index 93c76dc22..1ae85957c 100644 --- a/resources/views/pages/parts/code-editor.blade.php +++ b/resources/views/pages/parts/code-editor.blade.php @@ -1,5 +1,7 @@
    -