From 9a5f2fcb376f6dc2a0229c9931b15a57bc37745a Mon Sep 17 00:00:00 2001 From: MdNadimHossain Date: Wed, 29 Dec 2021 14:34:52 +1100 Subject: [PATCH 01/79] Updated tide_core. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6698135..78c97f8 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.0", "dpc-sdp/tide_api": "3.0.0", "dpc-sdp/tide_authenticated_content": "3.0.0", - "dpc-sdp/tide_core": "3.0.0", + "dpc-sdp/tide_core": "3.0.1", "dpc-sdp/tide_demo_content": "3.0.0", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", From 49e7abca8437e1ed1c575b55e0f85263fe2a7660 Mon Sep 17 00:00:00 2001 From: MdNadimHossain Date: Tue, 4 Jan 2022 12:09:29 +1100 Subject: [PATCH 02/79] Updated tide_media. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 78c97f8..5477388 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.0", "dpc-sdp/tide_landing_page": "3.0.0", - "dpc-sdp/tide_media": "3.0.0", + "dpc-sdp/tide_media": "3.0.1", "dpc-sdp/tide_monsido": "3.0.0", "dpc-sdp/tide_news": "3.0.0", "dpc-sdp/tide_page": "3.0.0", From 31a64e64c3bb3eac0768392193b2cb8696e3f45a Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Wed, 19 Jan 2022 13:51:54 +1100 Subject: [PATCH 03/79] release 3.0.2 --- composer.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 5477388..6eaaf3f 100644 --- a/composer.json +++ b/composer.json @@ -6,9 +6,9 @@ "require": { "dpc-sdp/tide_alert": "3.0.0", "dpc-sdp/tide_api": "3.0.0", - "dpc-sdp/tide_authenticated_content": "3.0.0", - "dpc-sdp/tide_core": "3.0.1", - "dpc-sdp/tide_demo_content": "3.0.0", + "dpc-sdp/tide_authenticated_content": "3.0.2", + "dpc-sdp/tide_core": "3.1.0", + "dpc-sdp/tide_demo_content": "3.0.1", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.0", @@ -20,9 +20,9 @@ "dpc-sdp/tide_profile": "3.0.0", "dpc-sdp/tide_publication": "3.0.0", "dpc-sdp/tide_search": "3.0.0", - "dpc-sdp/tide_site": "3.0.0", - "dpc-sdp/tide_test": "3.0.0", - "dpc-sdp/tide_webform": "3.0.0" + "dpc-sdp/tide_site": "3.0.1", + "dpc-sdp/tide_test": "3.0.1", + "dpc-sdp/tide_webform": "3.0.1" }, "repositories": { "drupal": { From ed6aa6102a0bc20735aede7bade33170f54a2168 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Mon, 24 Jan 2022 13:24:34 +1100 Subject: [PATCH 04/79] Bump tide_core to 3.0.2 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 6eaaf3f..25968dc 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.0", "dpc-sdp/tide_landing_page": "3.0.0", - "dpc-sdp/tide_media": "3.0.1", + "dpc-sdp/tide_media": "3.0.2", "dpc-sdp/tide_monsido": "3.0.0", "dpc-sdp/tide_news": "3.0.0", "dpc-sdp/tide_page": "3.0.0", From fa50f4cf2cdd777710607a2d0f80640eac835fd3 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Mon, 24 Jan 2022 13:46:30 +1100 Subject: [PATCH 05/79] Bump tide_demo_content to 3.0.2 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 25968dc..197009c 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "dpc-sdp/tide_api": "3.0.0", "dpc-sdp/tide_authenticated_content": "3.0.2", "dpc-sdp/tide_core": "3.1.0", - "dpc-sdp/tide_demo_content": "3.0.1", + "dpc-sdp/tide_demo_content": "3.0.2", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.0", From ddc2a6a18b2da30301505f33caf3016f8ee2f8dc Mon Sep 17 00:00:00 2001 From: Ming Quah Date: Thu, 3 Feb 2022 10:28:48 +1100 Subject: [PATCH 06/79] [SDPSUP-3951] Update tide_core (#161) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 197009c..6526d31 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.0", "dpc-sdp/tide_api": "3.0.0", "dpc-sdp/tide_authenticated_content": "3.0.2", - "dpc-sdp/tide_core": "3.1.0", + "dpc-sdp/tide_core": "3.1.1", "dpc-sdp/tide_demo_content": "3.0.2", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", From 8defb336197dae87cf78c7b5a5176620bd185704 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Mon, 7 Mar 2022 22:43:42 +1100 Subject: [PATCH 07/79] Update tide modules --- composer.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 6526d31..d7dc98b 100644 --- a/composer.json +++ b/composer.json @@ -7,22 +7,22 @@ "dpc-sdp/tide_alert": "3.0.0", "dpc-sdp/tide_api": "3.0.0", "dpc-sdp/tide_authenticated_content": "3.0.2", - "dpc-sdp/tide_core": "3.1.1", - "dpc-sdp/tide_demo_content": "3.0.2", + "dpc-sdp/tide_core": "3.1.3", + "dpc-sdp/tide_demo_content": "3.0.3", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.0", - "dpc-sdp/tide_landing_page": "3.0.0", - "dpc-sdp/tide_media": "3.0.2", + "dpc-sdp/tide_landing_page": "3.0.1", + "dpc-sdp/tide_media": "3.0.3", "dpc-sdp/tide_monsido": "3.0.0", - "dpc-sdp/tide_news": "3.0.0", + "dpc-sdp/tide_news": "3.0.1", "dpc-sdp/tide_page": "3.0.0", "dpc-sdp/tide_profile": "3.0.0", "dpc-sdp/tide_publication": "3.0.0", "dpc-sdp/tide_search": "3.0.0", - "dpc-sdp/tide_site": "3.0.1", + "dpc-sdp/tide_site": "3.0.2", "dpc-sdp/tide_test": "3.0.1", - "dpc-sdp/tide_webform": "3.0.1" + "dpc-sdp/tide_webform": "3.0.2" }, "repositories": { "drupal": { From d7f7db13cf5d32808db1a5ee9d5c918805aabfa0 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Fri, 11 Mar 2022 14:22:08 +1100 Subject: [PATCH 08/79] updates tide_search and tide_api, and retiring tide_page --- composer.json | 6 +++--- tide.info.yml | 1 - 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index d7dc98b..736c17a 100644 --- a/composer.json +++ b/composer.json @@ -5,9 +5,9 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.0", - "dpc-sdp/tide_api": "3.0.0", + "dpc-sdp/tide_api": "3.0.1", "dpc-sdp/tide_authenticated_content": "3.0.2", - "dpc-sdp/tide_core": "3.1.3", + "dpc-sdp/tide_core": "3.1.4", "dpc-sdp/tide_demo_content": "3.0.3", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", @@ -19,7 +19,7 @@ "dpc-sdp/tide_page": "3.0.0", "dpc-sdp/tide_profile": "3.0.0", "dpc-sdp/tide_publication": "3.0.0", - "dpc-sdp/tide_search": "3.0.0", + "dpc-sdp/tide_search": "3.0.2", "dpc-sdp/tide_site": "3.0.2", "dpc-sdp/tide_test": "3.0.1", "dpc-sdp/tide_webform": "3.0.2" diff --git a/tide.info.yml b/tide.info.yml index be0e4b0..2229663 100644 --- a/tide.info.yml +++ b/tide.info.yml @@ -11,7 +11,6 @@ dependencies: - dpc-sdp:tide_webform - dpc-sdp:tide_event - dpc-sdp:tide_news - - dpc-sdp:tide_page - dpc-sdp:tide_landing_page - dpc-sdp:tide_publication - dpc-sdp:tide_search From 03c6fbcbbcb474114ebc49093871be9cf4dc2297 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Wed, 30 Mar 2022 15:47:18 +1100 Subject: [PATCH 09/79] update tide modules --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 736c17a..fa735e8 100644 --- a/composer.json +++ b/composer.json @@ -12,15 +12,15 @@ "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.0", - "dpc-sdp/tide_landing_page": "3.0.1", + "dpc-sdp/tide_landing_page": "3.0.2", "dpc-sdp/tide_media": "3.0.3", "dpc-sdp/tide_monsido": "3.0.0", - "dpc-sdp/tide_news": "3.0.1", + "dpc-sdp/tide_news": "3.0.2", "dpc-sdp/tide_page": "3.0.0", "dpc-sdp/tide_profile": "3.0.0", "dpc-sdp/tide_publication": "3.0.0", "dpc-sdp/tide_search": "3.0.2", - "dpc-sdp/tide_site": "3.0.2", + "dpc-sdp/tide_site": "3.0.3", "dpc-sdp/tide_test": "3.0.1", "dpc-sdp/tide_webform": "3.0.2" }, From 782aa7a886cd4b1785b34c5f5faccc5868236aa2 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Wed, 6 Apr 2022 12:42:22 +1000 Subject: [PATCH 10/79] Bump tide_media to 3.0.4 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index fa735e8..aa976e0 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.0", "dpc-sdp/tide_landing_page": "3.0.2", - "dpc-sdp/tide_media": "3.0.3", + "dpc-sdp/tide_media": "3.0.4", "dpc-sdp/tide_monsido": "3.0.0", "dpc-sdp/tide_news": "3.0.2", "dpc-sdp/tide_page": "3.0.0", From 1a4f17820fd0fa4399ec10393de8e7ee0f650f76 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Mon, 9 May 2022 09:41:34 +1000 Subject: [PATCH 11/79] Bumps tide_authenticated_content --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index aa976e0..ba5fa82 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "require": { "dpc-sdp/tide_alert": "3.0.0", "dpc-sdp/tide_api": "3.0.1", - "dpc-sdp/tide_authenticated_content": "3.0.2", + "dpc-sdp/tide_authenticated_content": "3.0.3", "dpc-sdp/tide_core": "3.1.4", "dpc-sdp/tide_demo_content": "3.0.3", "dpc-sdp/tide_event": "3.0.0", From 6e2b227cf6021fc00a96b57de9c66b08a01bca04 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Mon, 30 May 2022 14:51:56 +1000 Subject: [PATCH 12/79] Bumps tide_core --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ba5fa82..67cbc8b 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.0", "dpc-sdp/tide_api": "3.0.1", "dpc-sdp/tide_authenticated_content": "3.0.3", - "dpc-sdp/tide_core": "3.1.4", + "dpc-sdp/tide_core": "3.1.5", "dpc-sdp/tide_demo_content": "3.0.3", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", From 06e858c3c2e6fd60d1523b80d5e7511106a33f38 Mon Sep 17 00:00:00 2001 From: Christopher Hopper Date: Fri, 10 Jun 2022 14:36:23 +1000 Subject: [PATCH 13/79] SDPA-5959: Add Tide CMS Help block to Admin theme (#168) --- .../block.block.seven_tide_cms_help.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 config/install/block.block.seven_tide_cms_help.yml diff --git a/config/install/block.block.seven_tide_cms_help.yml b/config/install/block.block.seven_tide_cms_help.yml new file mode 100644 index 0000000..8555bf3 --- /dev/null +++ b/config/install/block.block.seven_tide_cms_help.yml @@ -0,0 +1,19 @@ +langcode: en +status: true +dependencies: + module: + - tide_cms_support + theme: + - seven +id: seven_tide_cms_help +theme: seven +region: help +weight: -100 +provider: null +plugin: tide_help_block +settings: + id: tide_help_block + label: 'Tide CMS Help' + provider: tide_cms_support + label_display: '' +visibility: { } From 414a7bf1520f42c6661e3651500c59696e41bb82 Mon Sep 17 00:00:00 2001 From: Nadim Hossain Date: Fri, 10 Jun 2022 19:50:23 +1000 Subject: [PATCH 14/79] Updated tide modules with the new releases. --- composer.json | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.json b/composer.json index 67cbc8b..f236a4a 100644 --- a/composer.json +++ b/composer.json @@ -5,22 +5,22 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.0", - "dpc-sdp/tide_api": "3.0.1", + "dpc-sdp/tide_api": "3.0.2", "dpc-sdp/tide_authenticated_content": "3.0.3", - "dpc-sdp/tide_core": "3.1.5", + "dpc-sdp/tide_core": "3.1.6", "dpc-sdp/tide_demo_content": "3.0.3", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.0", - "dpc-sdp/tide_landing_page": "3.0.2", - "dpc-sdp/tide_media": "3.0.4", + "dpc-sdp/tide_landing_page": "3.0.3", + "dpc-sdp/tide_media": "3.0.5", "dpc-sdp/tide_monsido": "3.0.0", "dpc-sdp/tide_news": "3.0.2", "dpc-sdp/tide_page": "3.0.0", "dpc-sdp/tide_profile": "3.0.0", "dpc-sdp/tide_publication": "3.0.0", - "dpc-sdp/tide_search": "3.0.2", - "dpc-sdp/tide_site": "3.0.3", + "dpc-sdp/tide_search": "3.0.3", + "dpc-sdp/tide_site": "3.0.4", "dpc-sdp/tide_test": "3.0.1", "dpc-sdp/tide_webform": "3.0.2" }, From b0f4a93045d928b86fbaee78618003dedaae4719 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Tue, 14 Jun 2022 09:06:03 +1000 Subject: [PATCH 15/79] Include tide_demo_content changes --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index f236a4a..524abab 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "dpc-sdp/tide_api": "3.0.2", "dpc-sdp/tide_authenticated_content": "3.0.3", "dpc-sdp/tide_core": "3.1.6", - "dpc-sdp/tide_demo_content": "3.0.3", + "dpc-sdp/tide_demo_content": "3.0.5", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.0", From bca8c9eabe4a067106937baceeae59fd7320e9a3 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Tue, 14 Jun 2022 10:11:25 +1000 Subject: [PATCH 16/79] bumps tide_core to 3.1.7 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 524abab..3025dcd 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.0", "dpc-sdp/tide_api": "3.0.2", "dpc-sdp/tide_authenticated_content": "3.0.3", - "dpc-sdp/tide_core": "3.1.6", + "dpc-sdp/tide_core": "3.1.7", "dpc-sdp/tide_demo_content": "3.0.5", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", From be05cc1c89d68ebf370093bc0b4f21e45eb53d3d Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Wed, 15 Jun 2022 16:23:13 +1000 Subject: [PATCH 17/79] bumps tide_core to 3.1.8 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3025dcd..813ca5d 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.0", "dpc-sdp/tide_api": "3.0.2", "dpc-sdp/tide_authenticated_content": "3.0.3", - "dpc-sdp/tide_core": "3.1.7", + "dpc-sdp/tide_core": "3.1.8", "dpc-sdp/tide_demo_content": "3.0.5", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", From 0e5c7d30c40431181d6e06b0f98c19004f03e903 Mon Sep 17 00:00:00 2001 From: Nadim Hossain Date: Thu, 16 Jun 2022 15:37:31 +1000 Subject: [PATCH 18/79] Updated tide_api. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 813ca5d..9a14df9 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.0", - "dpc-sdp/tide_api": "3.0.2", + "dpc-sdp/tide_api": "3.0.3", "dpc-sdp/tide_authenticated_content": "3.0.3", "dpc-sdp/tide_core": "3.1.8", "dpc-sdp/tide_demo_content": "3.0.5", From 905ee064cb27477d2b57c102bc77a2a8fd924fd1 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Fri, 17 Jun 2022 12:33:35 +1000 Subject: [PATCH 19/79] Updated tide_landing_page --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9a14df9..142f55a 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.0", - "dpc-sdp/tide_landing_page": "3.0.3", + "dpc-sdp/tide_landing_page": "3.0.4", "dpc-sdp/tide_media": "3.0.5", "dpc-sdp/tide_monsido": "3.0.0", "dpc-sdp/tide_news": "3.0.2", From 42834193edea7933edad296d325d531ac78a40aa Mon Sep 17 00:00:00 2001 From: Nadim Hossain Date: Thu, 23 Jun 2022 09:14:34 +1000 Subject: [PATCH 20/79] Updated tide_demo_content latest version. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 142f55a..177e8ac 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "dpc-sdp/tide_api": "3.0.3", "dpc-sdp/tide_authenticated_content": "3.0.3", "dpc-sdp/tide_core": "3.1.8", - "dpc-sdp/tide_demo_content": "3.0.5", + "dpc-sdp/tide_demo_content": "3.0.6", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.0", From 58be227b34baf348db03f94ea0e0543d210fee13 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Fri, 15 Jul 2022 12:28:39 +1000 Subject: [PATCH 21/79] Updated tide_core latest version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 177e8ac..b656160 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.0", "dpc-sdp/tide_api": "3.0.3", "dpc-sdp/tide_authenticated_content": "3.0.3", - "dpc-sdp/tide_core": "3.1.8", + "dpc-sdp/tide_core": "3.1.9", "dpc-sdp/tide_demo_content": "3.0.6", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", From 1416ab12d908c4e57cd0e4612dc682aeeb6766e4 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Fri, 15 Jul 2022 13:39:37 +1000 Subject: [PATCH 22/79] Fix the release number From 34b0c42a72f9cae59a7c5c43f57bd194c8c6abeb Mon Sep 17 00:00:00 2001 From: Edward Yuen Date: Wed, 20 Jul 2022 16:02:45 +1000 Subject: [PATCH 23/79] Bumps tide_api. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index b656160..726e046 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.0", - "dpc-sdp/tide_api": "3.0.3", + "dpc-sdp/tide_api": "3.0.4", "dpc-sdp/tide_authenticated_content": "3.0.3", "dpc-sdp/tide_core": "3.1.9", "dpc-sdp/tide_demo_content": "3.0.6", From ccf1dca285bc7e2c2240b63dc15af1a5613e4786 Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Thu, 21 Jul 2022 16:51:49 +1000 Subject: [PATCH 24/79] [SDPAP-6350] Added code to remove default unused views. (#175) --- tide.install | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/tide.install b/tide.install index ee48509..04f4eb6 100644 --- a/tide.install +++ b/tide.install @@ -49,4 +49,15 @@ function tide_install() { if (file_exists(DRUPAL_ROOT . DIRECTORY_SEPARATOR . 'modules' . DIRECTORY_SEPARATOR . 'contrib' . DIRECTORY_SEPARATOR . 'redis')) { \Drupal::service('module_installer')->install(['redis']); } + // These viewes are replaced by custom views provided by tide_site. + $view_ids = [ + 'content', + 'moderated_content', + ]; + foreach ($view_ids as $view_id) { + $view = \Drupal::entityTypeManager()->getStorage('view')->load($view_id); + if ($view) { + $view->setStatus(FALSE)->save(); + } + } } From aeab71b93d290c093417283841c1176f4a6dd1ca Mon Sep 17 00:00:00 2001 From: Anthony Malkoun Date: Fri, 22 Jul 2022 16:53:00 +1000 Subject: [PATCH 25/79] Update tide_grant version to fix submission --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 726e046..57015db 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "dpc-sdp/tide_demo_content": "3.0.6", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", - "dpc-sdp/tide_grant": "3.0.0", + "dpc-sdp/tide_grant": "3.0.1", "dpc-sdp/tide_landing_page": "3.0.4", "dpc-sdp/tide_media": "3.0.5", "dpc-sdp/tide_monsido": "3.0.0", From 146aa3d8e61d1c85433db599b43dfb59d6c3a41e Mon Sep 17 00:00:00 2001 From: Nadim Hossain Date: Mon, 25 Jul 2022 13:08:32 +1000 Subject: [PATCH 26/79] Updated tide modules. --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 57015db..3dbdf15 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.0", "dpc-sdp/tide_api": "3.0.4", "dpc-sdp/tide_authenticated_content": "3.0.3", - "dpc-sdp/tide_core": "3.1.9", + "dpc-sdp/tide_core": "3.1.10", "dpc-sdp/tide_demo_content": "3.0.6", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", @@ -19,7 +19,7 @@ "dpc-sdp/tide_page": "3.0.0", "dpc-sdp/tide_profile": "3.0.0", "dpc-sdp/tide_publication": "3.0.0", - "dpc-sdp/tide_search": "3.0.3", + "dpc-sdp/tide_search": "3.0.4", "dpc-sdp/tide_site": "3.0.4", "dpc-sdp/tide_test": "3.0.1", "dpc-sdp/tide_webform": "3.0.2" From 7d907f3f105f1170deb3868c39201b3c3fc286c9 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Fri, 19 Aug 2022 14:23:03 +1000 Subject: [PATCH 27/79] upgrade tide_authenticated_content to 3.0.4 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3dbdf15..f225e4c 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "require": { "dpc-sdp/tide_alert": "3.0.0", "dpc-sdp/tide_api": "3.0.4", - "dpc-sdp/tide_authenticated_content": "3.0.3", + "dpc-sdp/tide_authenticated_content": "3.0.4", "dpc-sdp/tide_core": "3.1.10", "dpc-sdp/tide_demo_content": "3.0.6", "dpc-sdp/tide_event": "3.0.0", From b0ae0be5c909cd9ab8ac3d6f20059f52552fe463 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Mon, 22 Aug 2022 16:26:19 +1000 Subject: [PATCH 28/79] [SRM-466] Update tide module versions --- composer.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index f225e4c..aed9416 100644 --- a/composer.json +++ b/composer.json @@ -7,22 +7,22 @@ "dpc-sdp/tide_alert": "3.0.0", "dpc-sdp/tide_api": "3.0.4", "dpc-sdp/tide_authenticated_content": "3.0.4", - "dpc-sdp/tide_core": "3.1.10", - "dpc-sdp/tide_demo_content": "3.0.6", + "dpc-sdp/tide_core": "3.1.11", + "dpc-sdp/tide_demo_content": "3.0.7", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.1", - "dpc-sdp/tide_landing_page": "3.0.4", - "dpc-sdp/tide_media": "3.0.5", + "dpc-sdp/tide_landing_page": "3.0.5", + "dpc-sdp/tide_media": "3.0.6", "dpc-sdp/tide_monsido": "3.0.0", "dpc-sdp/tide_news": "3.0.2", - "dpc-sdp/tide_page": "3.0.0", + "dpc-sdp/tide_page": "3.0.1", "dpc-sdp/tide_profile": "3.0.0", - "dpc-sdp/tide_publication": "3.0.0", + "dpc-sdp/tide_publication": "3.0.1", "dpc-sdp/tide_search": "3.0.4", - "dpc-sdp/tide_site": "3.0.4", + "dpc-sdp/tide_site": "3.0.6", "dpc-sdp/tide_test": "3.0.1", - "dpc-sdp/tide_webform": "3.0.2" + "dpc-sdp/tide_webform": "3.0.3" }, "repositories": { "drupal": { From 042aea5a58310562fcb020fd982a4c9efcf41bcc Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Tue, 18 Oct 2022 09:50:07 +1100 Subject: [PATCH 29/79] Empty commit From f3dbd2b78419c411abc89a0d2e192b8623dffa88 Mon Sep 17 00:00:00 2001 From: Keith Lau Date: Wed, 26 Oct 2022 17:17:03 +1100 Subject: [PATCH 30/79] [SRM-512] Update tide demo content version to 3.0.8 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index aed9416..74002ff 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "dpc-sdp/tide_api": "3.0.4", "dpc-sdp/tide_authenticated_content": "3.0.4", "dpc-sdp/tide_core": "3.1.11", - "dpc-sdp/tide_demo_content": "3.0.7", + "dpc-sdp/tide_demo_content": "3.0.8", "dpc-sdp/tide_event": "3.0.0", "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.1", From 82312b387751ad22ea66343d43269bcfcc64749d Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Fri, 11 Nov 2022 14:41:36 +1100 Subject: [PATCH 31/79] [SRM-512] SDPAP-6730 Remove deprecated "drupal_get_path()" (#183) * [SRM-512] SDPAP-6730 Remove deprecated "drupal_get_path()" * Test and then later REVERT "Remove deprecated "drupal_get_path()"" * Fix aliases * Update dev tools hash * Remove aliasis and dev tools hash * Remove blank line in composer * Test ci updating tide module updated versions --- composer.json | 26 +++++++++++++------------- tide.install | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/composer.json b/composer.json index 74002ff..5810b52 100644 --- a/composer.json +++ b/composer.json @@ -4,25 +4,25 @@ "type": "drupal-profile", "license": "GPL-2.0-or-later", "require": { - "dpc-sdp/tide_alert": "3.0.0", - "dpc-sdp/tide_api": "3.0.4", - "dpc-sdp/tide_authenticated_content": "3.0.4", - "dpc-sdp/tide_core": "3.1.11", + "dpc-sdp/tide_alert": "3.0.1", + "dpc-sdp/tide_api": "3.0.5", + "dpc-sdp/tide_authenticated_content": "3.0.5", + "dpc-sdp/tide_core": "3.1.12", "dpc-sdp/tide_demo_content": "3.0.8", - "dpc-sdp/tide_event": "3.0.0", + "dpc-sdp/tide_event": "3.0.1", "dpc-sdp/tide_event_atdw": "3.0.0", - "dpc-sdp/tide_grant": "3.0.1", - "dpc-sdp/tide_landing_page": "3.0.5", - "dpc-sdp/tide_media": "3.0.6", + "dpc-sdp/tide_grant": "3.0.2", + "dpc-sdp/tide_landing_page": "3.0.6", + "dpc-sdp/tide_media": "3.0.7", "dpc-sdp/tide_monsido": "3.0.0", - "dpc-sdp/tide_news": "3.0.2", - "dpc-sdp/tide_page": "3.0.1", + "dpc-sdp/tide_news": "3.0.3", + "dpc-sdp/tide_page": "3.0.2", "dpc-sdp/tide_profile": "3.0.0", - "dpc-sdp/tide_publication": "3.0.1", + "dpc-sdp/tide_publication": "3.0.2", "dpc-sdp/tide_search": "3.0.4", - "dpc-sdp/tide_site": "3.0.6", + "dpc-sdp/tide_site": "3.0.7", "dpc-sdp/tide_test": "3.0.1", - "dpc-sdp/tide_webform": "3.0.3" + "dpc-sdp/tide_webform": "3.0.4" }, "repositories": { "drupal": { diff --git a/tide.install b/tide.install index 04f4eb6..387e3b1 100644 --- a/tide.install +++ b/tide.install @@ -27,7 +27,7 @@ function tide_install() { ->save(TRUE); // Set the path to the logo and favicon files based on install directory. - $profile_path = drupal_get_path('profile', 'tide'); + $profile_path = \Drupal::service('extension.list.profile')->getPath('tide'); \Drupal::configFactory() ->getEditable('system.theme.global') ->set('logo', [ From f955e39972fd2c03e2d28e3f2e35ef1323e06dac Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Fri, 11 Nov 2022 14:52:03 +1100 Subject: [PATCH 32/79] [SRM-537] Update tide module version numbers --- composer.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.json b/composer.json index 5810b52..fe936c5 100644 --- a/composer.json +++ b/composer.json @@ -5,24 +5,24 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.1", - "dpc-sdp/tide_api": "3.0.5", + "dpc-sdp/tide_api": "3.0.6", "dpc-sdp/tide_authenticated_content": "3.0.5", - "dpc-sdp/tide_core": "3.1.12", + "dpc-sdp/tide_core": "3.1.13", "dpc-sdp/tide_demo_content": "3.0.8", "dpc-sdp/tide_event": "3.0.1", "dpc-sdp/tide_event_atdw": "3.0.0", - "dpc-sdp/tide_grant": "3.0.2", + "dpc-sdp/tide_grant": "3.0.4", "dpc-sdp/tide_landing_page": "3.0.6", - "dpc-sdp/tide_media": "3.0.7", + "dpc-sdp/tide_media": "3.0.8", "dpc-sdp/tide_monsido": "3.0.0", "dpc-sdp/tide_news": "3.0.3", "dpc-sdp/tide_page": "3.0.2", "dpc-sdp/tide_profile": "3.0.0", "dpc-sdp/tide_publication": "3.0.2", - "dpc-sdp/tide_search": "3.0.4", - "dpc-sdp/tide_site": "3.0.7", + "dpc-sdp/tide_search": "3.0.5", + "dpc-sdp/tide_site": "3.0.8", "dpc-sdp/tide_test": "3.0.1", - "dpc-sdp/tide_webform": "3.0.4" + "dpc-sdp/tide_webform": "3.0.5" }, "repositories": { "drupal": { From bbeb794dea84bab9f7703b317515090431e03f5b Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Fri, 11 Nov 2022 15:01:19 +1100 Subject: [PATCH 33/79] Fix tide grant version error --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index fe936c5..ba24011 100644 --- a/composer.json +++ b/composer.json @@ -11,7 +11,7 @@ "dpc-sdp/tide_demo_content": "3.0.8", "dpc-sdp/tide_event": "3.0.1", "dpc-sdp/tide_event_atdw": "3.0.0", - "dpc-sdp/tide_grant": "3.0.4", + "dpc-sdp/tide_grant": "3.0.2", "dpc-sdp/tide_landing_page": "3.0.6", "dpc-sdp/tide_media": "3.0.8", "dpc-sdp/tide_monsido": "3.0.0", From 39997b092fc38b1df949249c040d371e04ed78d1 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Mon, 14 Nov 2022 14:23:08 +1100 Subject: [PATCH 34/79] [SRM-537] Update `tide_webform` to 3.0.6 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ba24011..38fff8e 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "dpc-sdp/tide_search": "3.0.5", "dpc-sdp/tide_site": "3.0.8", "dpc-sdp/tide_test": "3.0.1", - "dpc-sdp/tide_webform": "3.0.5" + "dpc-sdp/tide_webform": "3.0.6" }, "repositories": { "drupal": { From 736f92bdd22592b79c822f4bf64c1bb81deb6299 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Wed, 16 Nov 2022 10:10:18 +1100 Subject: [PATCH 35/79] Update `tide_landing_page` module to 3.0.7 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 38fff8e..4cf65ad 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "dpc-sdp/tide_event": "3.0.1", "dpc-sdp/tide_event_atdw": "3.0.0", "dpc-sdp/tide_grant": "3.0.2", - "dpc-sdp/tide_landing_page": "3.0.6", + "dpc-sdp/tide_landing_page": "3.0.7", "dpc-sdp/tide_media": "3.0.8", "dpc-sdp/tide_monsido": "3.0.0", "dpc-sdp/tide_news": "3.0.3", From ccb23585ddccb816aae2fac2689c890c6bc846f1 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Fri, 18 Nov 2022 15:07:17 +1100 Subject: [PATCH 36/79] [SRM-537] Update `tide_api` to `3.0.7` --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 4cf65ad..020e0b1 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.1", - "dpc-sdp/tide_api": "3.0.6", + "dpc-sdp/tide_api": "3.0.7", "dpc-sdp/tide_authenticated_content": "3.0.5", "dpc-sdp/tide_core": "3.1.13", "dpc-sdp/tide_demo_content": "3.0.8", From 31640881095fa67c44323454f666ec25f017fda4 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Mon, 21 Nov 2022 16:21:27 +1100 Subject: [PATCH 37/79] [SRM-531] [SRM-568] Update `tide_api` to `3.0.8` --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 020e0b1..e06f1ac 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.1", - "dpc-sdp/tide_api": "3.0.7", + "dpc-sdp/tide_api": "3.0.8", "dpc-sdp/tide_authenticated_content": "3.0.5", "dpc-sdp/tide_core": "3.1.13", "dpc-sdp/tide_demo_content": "3.0.8", From 85fffef79ec29dd5bfcca1913ecdbd64ad97b5a0 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Mon, 28 Nov 2022 15:04:11 +1100 Subject: [PATCH 38/79] [SRM-570] Update tide_core and tide_webform versions --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index e06f1ac..c50598a 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.1", "dpc-sdp/tide_api": "3.0.8", "dpc-sdp/tide_authenticated_content": "3.0.5", - "dpc-sdp/tide_core": "3.1.13", + "dpc-sdp/tide_core": "3.1.14", "dpc-sdp/tide_demo_content": "3.0.8", "dpc-sdp/tide_event": "3.0.1", "dpc-sdp/tide_event_atdw": "3.0.0", @@ -22,7 +22,7 @@ "dpc-sdp/tide_search": "3.0.5", "dpc-sdp/tide_site": "3.0.8", "dpc-sdp/tide_test": "3.0.1", - "dpc-sdp/tide_webform": "3.0.6" + "dpc-sdp/tide_webform": "3.0.7" }, "repositories": { "drupal": { From ced6d7c991942b9f61a4b6cf40b689adc59eb05a Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Fri, 16 Dec 2022 15:57:08 +1100 Subject: [PATCH 39/79] [SRM-526] Added new ci config to update reference branch. (#185) * [SRM-526] Added new ci config to update reference branch. Co-authored-by: Keith Lau --- .circleci/config.yml | 53 ++++++++++++++++++++++++++++++++- .circleci/merge-to-reference.sh | 21 +++++++++++++ 2 files changed, 73 insertions(+), 1 deletion(-) create mode 100755 .circleci/merge-to-reference.sh diff --git a/.circleci/config.yml b/.circleci/config.yml index f35e1f0..a7c785d 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,8 +1,18 @@ version: 2 aliases: + - &ssh_key_fingerprint "36:03:e3:ca:b3:0b:82:18:e2:e9:ae:5d:81:17:86:b1" + # Fingerprint of the SSH deploy key of the project used to pull code. + # The value can be found in CircleCI UI -> SSH Permissions. + + - &step_configure_git + run: + name: Configure git + command: | + git config --global user.email "$DEPLOY_USER_EMAIL" && git config --global user.name "$DEPLOY_USER_NAME" + # Re-usable job to run different types of builds. - &job-build - working_directory: /app + working_directory: &working-directory /app docker: - image: &builder-image singledigital/bay-ci-builder:4.x environment: @@ -25,6 +35,35 @@ aliases: - store_artifacts: path: /tmp/artifacts + # Job to perform merge to reference branch after a merge to develop. + - &merge-to-reference + working_directory: *working-directory + docker: + - image: *builder-image + auth: + username: $DOCKERHUB_USERNAME + password: $DOCKERHUB_PASSWORD + environment: + LAGOON_ENVIRONMENT_TYPE: ci + SSH_KEY_FINGERPRINT: *ssh_key_fingerprint + DEPLOY_USER_EMAIL: sdp.devs@dpc.vic.gov.au + DEPLOY_USER_NAME: sdpdeploy + steps: + - attach_workspace: + at: /workspace + - checkout + - *step_configure_git + - setup_remote_docker: + docker_layer_caching: true + - add_ssh_keys: + fingerprints: + - *ssh_key_fingerprint + - run: + name: Merge to reference branch + command: .circleci/merge-to-reference.sh + no_output_timeout: 30m + + jobs: build: <<: *job-build @@ -38,10 +77,22 @@ jobs: LAGOON_ENVIRONMENT_TYPE: ci INSTALL_SUGGEST: 1 BEHAT_PROFILE: "--profile=suggest" + + merge_to_reference: + <<: *merge-to-reference + workflows: version: 2 main: jobs: - build - build_suggest + + mergetoreference: + jobs: + - merge_to_reference: + filters: + branches: + only: + - develop diff --git a/.circleci/merge-to-reference.sh b/.circleci/merge-to-reference.sh new file mode 100755 index 0000000..db8b679 --- /dev/null +++ b/.circleci/merge-to-reference.sh @@ -0,0 +1,21 @@ +#!/usr/bin/env bash +## +# Merge develop to reference branch in CI. +# + +echo "==> Checking out reference branch" +git checkout reference +echo "==> Merging develop to reference branch" +git merge develop +git checkout develop -- composer.json +git add . +echo "==> Replacing composer require entries starting with dpc-sdp with value dev-reference" +cat composer.json | gojq '.require |= with_entries( + if (.key | test("dpc-sdp/tide")) + then .value = "dev-reference" end)' > composer.json.backup +mv -f composer.json.backup composer.json +echo "==> Add all changes" +git add . +git commit -m "Merge changes from develop." +echo "==> Push the changes to remote reference branch" +git push origin --force reference From 39b07508598aca6cb984ae3120cbf25edd866df1 Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Wed, 28 Dec 2022 13:13:07 +1100 Subject: [PATCH 40/79] Updated ci config. (#187) --- .circleci/config.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index a7c785d..3c3a464 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -87,7 +87,11 @@ workflows: main: jobs: - build - - build_suggest + - build_suggest: + filters: + branches: + ignore: + - reference mergetoreference: jobs: From 1f622dcb72c283003a02ed40cb869659c95f0cee Mon Sep 17 00:00:00 2001 From: edyuenyw <67810118+edyuenyw@users.noreply.github.com> Date: Thu, 12 Jan 2023 13:10:34 +1100 Subject: [PATCH 41/79] Update to Bay 5.x. (#188) --- .circleci/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 3c3a464..32b5c17 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -14,7 +14,7 @@ aliases: - &job-build working_directory: &working-directory /app docker: - - image: &builder-image singledigital/bay-ci-builder:4.x + - image: &builder-image singledigital/bay-ci-builder:5.x environment: INSTALL_NEW_SITE: 1 LAGOON_ENVIRONMENT_TYPE: ci From 12c416c726e3b598cf3bbe45e5dd064cc68f7726 Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Thu, 12 Jan 2023 13:15:00 +1100 Subject: [PATCH 42/79] Updated tide modules to the version that are compatible with php 8.1. --- composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index c50598a..c6671a2 100644 --- a/composer.json +++ b/composer.json @@ -10,9 +10,9 @@ "dpc-sdp/tide_core": "3.1.14", "dpc-sdp/tide_demo_content": "3.0.8", "dpc-sdp/tide_event": "3.0.1", - "dpc-sdp/tide_event_atdw": "3.0.0", + "dpc-sdp/tide_event_atdw": "3.0.1", "dpc-sdp/tide_grant": "3.0.2", - "dpc-sdp/tide_landing_page": "3.0.7", + "dpc-sdp/tide_landing_page": "3.0.8", "dpc-sdp/tide_media": "3.0.8", "dpc-sdp/tide_monsido": "3.0.0", "dpc-sdp/tide_news": "3.0.3", @@ -20,9 +20,9 @@ "dpc-sdp/tide_profile": "3.0.0", "dpc-sdp/tide_publication": "3.0.2", "dpc-sdp/tide_search": "3.0.5", - "dpc-sdp/tide_site": "3.0.8", - "dpc-sdp/tide_test": "3.0.1", - "dpc-sdp/tide_webform": "3.0.7" + "dpc-sdp/tide_site": "3.0.9", + "dpc-sdp/tide_test": "3.0.2", + "dpc-sdp/tide_webform": "3.0.8" }, "repositories": { "drupal": { From 785e4fe7623e09576f8935b308548088b21da354 Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Thu, 12 Jan 2023 15:44:30 +1100 Subject: [PATCH 43/79] Updated tide_core version. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c6671a2..1f8da87 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.1", "dpc-sdp/tide_api": "3.0.8", "dpc-sdp/tide_authenticated_content": "3.0.5", - "dpc-sdp/tide_core": "3.1.14", + "dpc-sdp/tide_core": "3.2.0", "dpc-sdp/tide_demo_content": "3.0.8", "dpc-sdp/tide_event": "3.0.1", "dpc-sdp/tide_event_atdw": "3.0.1", From cf75c0484dd5a20d1e7add5d944121f6ec31a7e2 Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Tue, 14 Feb 2023 14:24:38 +1100 Subject: [PATCH 44/79] Updated tide event and demo content module. --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 1f8da87..3b1e501 100644 --- a/composer.json +++ b/composer.json @@ -8,8 +8,8 @@ "dpc-sdp/tide_api": "3.0.8", "dpc-sdp/tide_authenticated_content": "3.0.5", "dpc-sdp/tide_core": "3.2.0", - "dpc-sdp/tide_demo_content": "3.0.8", - "dpc-sdp/tide_event": "3.0.1", + "dpc-sdp/tide_demo_content": "3.0.9", + "dpc-sdp/tide_event": "3.0.2", "dpc-sdp/tide_event_atdw": "3.0.1", "dpc-sdp/tide_grant": "3.0.2", "dpc-sdp/tide_landing_page": "3.0.8", From d1bf09755b51cec557022618945bcd1e8177a722 Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Tue, 21 Feb 2023 16:24:11 +1100 Subject: [PATCH 45/79] Updated tide_site to latest. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3b1e501..cb22b83 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ "dpc-sdp/tide_profile": "3.0.0", "dpc-sdp/tide_publication": "3.0.2", "dpc-sdp/tide_search": "3.0.5", - "dpc-sdp/tide_site": "3.0.9", + "dpc-sdp/tide_site": "3.0.10", "dpc-sdp/tide_test": "3.0.2", "dpc-sdp/tide_webform": "3.0.8" }, From e310e691c9f6907b1a4a9fd47d07609d9c3bba68 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Tue, 14 Mar 2023 15:17:26 +1100 Subject: [PATCH 46/79] Upgrade for 1.44.0 * tide_api * tide_authenticated_content * tide_core * tide_demo_content * tide_grant * tide_landing_page * tide_media * tide_monsido * tide_news * tide_page * tide_profile * tide_publication * tide_search * tide_site * tide_webform --- composer.json | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/composer.json b/composer.json index cb22b83..e6ae55b 100644 --- a/composer.json +++ b/composer.json @@ -5,24 +5,24 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.1", - "dpc-sdp/tide_api": "3.0.8", - "dpc-sdp/tide_authenticated_content": "3.0.5", - "dpc-sdp/tide_core": "3.2.0", - "dpc-sdp/tide_demo_content": "3.0.9", + "dpc-sdp/tide_api": "3.0.9", + "dpc-sdp/tide_authenticated_content": "3.0.6", + "dpc-sdp/tide_core": "3.2.3", + "dpc-sdp/tide_demo_content": "3.0.10", "dpc-sdp/tide_event": "3.0.2", "dpc-sdp/tide_event_atdw": "3.0.1", - "dpc-sdp/tide_grant": "3.0.2", - "dpc-sdp/tide_landing_page": "3.0.8", - "dpc-sdp/tide_media": "3.0.8", - "dpc-sdp/tide_monsido": "3.0.0", - "dpc-sdp/tide_news": "3.0.3", - "dpc-sdp/tide_page": "3.0.2", - "dpc-sdp/tide_profile": "3.0.0", - "dpc-sdp/tide_publication": "3.0.2", - "dpc-sdp/tide_search": "3.0.5", - "dpc-sdp/tide_site": "3.0.10", + "dpc-sdp/tide_grant": "3.0.3", + "dpc-sdp/tide_landing_page": "3.0.10", + "dpc-sdp/tide_media": "3.0.9", + "dpc-sdp/tide_monsido": "3.0.1", + "dpc-sdp/tide_news": "3.0.4", + "dpc-sdp/tide_page": "3.0.3", + "dpc-sdp/tide_profile": "3.0.1", + "dpc-sdp/tide_publication": "3.0.3", + "dpc-sdp/tide_search": "3.0.6", + "dpc-sdp/tide_site": "3.0.12", "dpc-sdp/tide_test": "3.0.2", - "dpc-sdp/tide_webform": "3.0.8" + "dpc-sdp/tide_webform": "3.0.9" }, "repositories": { "drupal": { From 3711f29b9dce066d72767a45c35492d66762537c Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Wed, 15 Mar 2023 10:16:13 +1100 Subject: [PATCH 47/79] Add "asset-packagist" to composer --- composer.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/composer.json b/composer.json index e6ae55b..ad2888e 100644 --- a/composer.json +++ b/composer.json @@ -29,5 +29,9 @@ "type": "composer", "url": "https://packages.drupal.org/9" } + }, + "asset-packagist": { + "type": "composer", + "url": "https://asset-packagist.org" } } From 0d7b4b5d72bfc5d5edf863e774303868a68d3e2a Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Wed, 15 Mar 2023 11:43:37 +1100 Subject: [PATCH 48/79] Fix `asset-packagist` issue --- composer.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/composer.json b/composer.json index ad2888e..216040e 100644 --- a/composer.json +++ b/composer.json @@ -28,10 +28,10 @@ "drupal": { "type": "composer", "url": "https://packages.drupal.org/9" + }, + "asset-packagist": { + "type": "composer", + "url": "https://asset-packagist.org" } - }, - "asset-packagist": { - "type": "composer", - "url": "https://asset-packagist.org" } } From 03f0f1a54bb82b62e240248e86a59917dafc05dd Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Wed, 15 Mar 2023 13:41:19 +1100 Subject: [PATCH 49/79] Update "tide_alert" version --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 216040e..465dc9d 100644 --- a/composer.json +++ b/composer.json @@ -4,7 +4,7 @@ "type": "drupal-profile", "license": "GPL-2.0-or-later", "require": { - "dpc-sdp/tide_alert": "3.0.1", + "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.9", "dpc-sdp/tide_authenticated_content": "3.0.6", "dpc-sdp/tide_core": "3.2.3", From 7432a4c0fe69f3b5f6a6829769aa13a01d0dd7e2 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Tue, 21 Mar 2023 11:51:35 +1100 Subject: [PATCH 50/79] Update `tide_core` to `3.2.4` * https://github.com/dpc-sdp/tide_core/releases/tag/3.2.4 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 465dc9d..f4c9407 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.9", "dpc-sdp/tide_authenticated_content": "3.0.6", - "dpc-sdp/tide_core": "3.2.3", + "dpc-sdp/tide_core": "3.2.4", "dpc-sdp/tide_demo_content": "3.0.10", "dpc-sdp/tide_event": "3.0.2", "dpc-sdp/tide_event_atdw": "3.0.1", From 7a84fb6bb9ecf81b7212af81760af24a4b9c875e Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Thu, 23 Mar 2023 13:23:01 +1100 Subject: [PATCH 51/79] Release 3.2.5 --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index f4c9407..d5024e7 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.9", "dpc-sdp/tide_authenticated_content": "3.0.6", - "dpc-sdp/tide_core": "3.2.4", + "dpc-sdp/tide_core": "3.2.5", "dpc-sdp/tide_demo_content": "3.0.10", "dpc-sdp/tide_event": "3.0.2", "dpc-sdp/tide_event_atdw": "3.0.1", @@ -20,7 +20,7 @@ "dpc-sdp/tide_profile": "3.0.1", "dpc-sdp/tide_publication": "3.0.3", "dpc-sdp/tide_search": "3.0.6", - "dpc-sdp/tide_site": "3.0.12", + "dpc-sdp/tide_site": "3.0.13", "dpc-sdp/tide_test": "3.0.2", "dpc-sdp/tide_webform": "3.0.9" }, From c55c632b3222bfed9fcd69dd8add72053fffe784 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Fri, 24 Mar 2023 09:56:13 +1100 Subject: [PATCH 52/79] Update `tide_event` version to `3.0.3` --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index d5024e7..b35c746 100644 --- a/composer.json +++ b/composer.json @@ -9,7 +9,7 @@ "dpc-sdp/tide_authenticated_content": "3.0.6", "dpc-sdp/tide_core": "3.2.5", "dpc-sdp/tide_demo_content": "3.0.10", - "dpc-sdp/tide_event": "3.0.2", + "dpc-sdp/tide_event": "3.0.3", "dpc-sdp/tide_event_atdw": "3.0.1", "dpc-sdp/tide_grant": "3.0.3", "dpc-sdp/tide_landing_page": "3.0.10", From 14a15156db082ced20afcf8b9363affbf1821719 Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Tue, 18 Apr 2023 11:19:19 +1000 Subject: [PATCH 53/79] [release/3.2.7] Updated tide modules. --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index b35c746..981598d 100644 --- a/composer.json +++ b/composer.json @@ -7,12 +7,12 @@ "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.9", "dpc-sdp/tide_authenticated_content": "3.0.6", - "dpc-sdp/tide_core": "3.2.5", + "dpc-sdp/tide_core": "3.2.6", "dpc-sdp/tide_demo_content": "3.0.10", "dpc-sdp/tide_event": "3.0.3", "dpc-sdp/tide_event_atdw": "3.0.1", "dpc-sdp/tide_grant": "3.0.3", - "dpc-sdp/tide_landing_page": "3.0.10", + "dpc-sdp/tide_landing_page": "3.0.11", "dpc-sdp/tide_media": "3.0.9", "dpc-sdp/tide_monsido": "3.0.1", "dpc-sdp/tide_news": "3.0.4", From 0c7745383763589622cfb09c89bedde622bf2b6c Mon Sep 17 00:00:00 2001 From: Anthony Malkoun Date: Tue, 2 May 2023 13:40:56 +1000 Subject: [PATCH 54/79] Bump landing page version to use new component for Budget (#195) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 981598d..b3bff2a 100644 --- a/composer.json +++ b/composer.json @@ -12,7 +12,7 @@ "dpc-sdp/tide_event": "3.0.3", "dpc-sdp/tide_event_atdw": "3.0.1", "dpc-sdp/tide_grant": "3.0.3", - "dpc-sdp/tide_landing_page": "3.0.11", + "dpc-sdp/tide_landing_page": "3.0.12", "dpc-sdp/tide_media": "3.0.9", "dpc-sdp/tide_monsido": "3.0.1", "dpc-sdp/tide_news": "3.0.4", From 12f5168cb97d3a171e31944d06ce27199b3f43f6 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Wed, 31 May 2023 16:18:06 +1000 Subject: [PATCH 55/79] Claro and Ckeditor5 upgrade --- composer.json | 34 +- patches/.gitkeep | 0 .../ckeditor_templates_4.patch | 9011 +++++++++++++++++ .../fix-applied-patches.patch | 13 + patches/embed/issues_3309747.patch | 453 + 5 files changed, 9499 insertions(+), 12 deletions(-) create mode 100644 patches/.gitkeep create mode 100644 patches/ckeditor_templates/ckeditor_templates_4.patch create mode 100644 patches/composer-patches/fix-applied-patches.patch create mode 100644 patches/embed/issues_3309747.patch diff --git a/composer.json b/composer.json index b3bff2a..70d2f28 100644 --- a/composer.json +++ b/composer.json @@ -5,29 +5,39 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.2", - "dpc-sdp/tide_api": "3.0.9", - "dpc-sdp/tide_authenticated_content": "3.0.6", - "dpc-sdp/tide_core": "3.2.6", - "dpc-sdp/tide_demo_content": "3.0.10", - "dpc-sdp/tide_event": "3.0.3", + "dpc-sdp/tide_api": "3.0.10", + "dpc-sdp/tide_authenticated_content": "3.0.7", + "dpc-sdp/tide_core": "3.2.8", + "dpc-sdp/tide_demo_content": "3.0.11", + "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", - "dpc-sdp/tide_grant": "3.0.3", - "dpc-sdp/tide_landing_page": "3.0.12", - "dpc-sdp/tide_media": "3.0.9", + "dpc-sdp/tide_grant": "3.0.4", + "dpc-sdp/tide_landing_page": "3.0.14", + "dpc-sdp/tide_media": "3.0.10", "dpc-sdp/tide_monsido": "3.0.1", "dpc-sdp/tide_news": "3.0.4", "dpc-sdp/tide_page": "3.0.3", "dpc-sdp/tide_profile": "3.0.1", - "dpc-sdp/tide_publication": "3.0.3", + "dpc-sdp/tide_publication": "3.0.4", "dpc-sdp/tide_search": "3.0.6", - "dpc-sdp/tide_site": "3.0.13", + "dpc-sdp/tide_site": "3.0.14", "dpc-sdp/tide_test": "3.0.2", - "dpc-sdp/tide_webform": "3.0.9" + "dpc-sdp/tide_webform": "3.0.11" }, "repositories": { "drupal": { "type": "composer", - "url": "https://packages.drupal.org/9" + "url": "https://packages.drupal.org/9", + "canonical": false + }, + "drupal/entity_embed": { + "type": "git", + "url": "https://git.drupalcode.org/issue/entity_embed-3272732.git" + }, + "drupal/video_embed_field": { + "type": "vcs", + "no-api": true, + "url": "https://git.drupalcode.org/issue/video_embed_field-3311063.git" }, "asset-packagist": { "type": "composer", diff --git a/patches/.gitkeep b/patches/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/patches/ckeditor_templates/ckeditor_templates_4.patch b/patches/ckeditor_templates/ckeditor_templates_4.patch new file mode 100644 index 0000000..bd9f666 --- /dev/null +++ b/patches/ckeditor_templates/ckeditor_templates_4.patch @@ -0,0 +1,9011 @@ +From 2fcbb589c7d2af5228ff0889534a723ecadf9e0e Mon Sep 17 00:00:00 2001 +From: Marcelo Hespanhol +Date: Wed, 22 Feb 2023 14:35:44 -0500 +Subject: [PATCH 01/11] Make the module compatible with CKEditor 5 + +--- + LICENSE.txt | 339 ++ + README.txt | 73 +- + ckeditor_templates.ckeditor5.yml | 23 + + ckeditor_templates.info.yml | 5 +- + ckeditor_templates.libraries.yml | 16 +- + ckeditor_templates.links.action.yml | 5 + + ckeditor_templates.links.menu.yml | 5 + + ckeditor_templates.permissions.yml | 2 + + ckeditor_templates.routing.yml | 38 + + config/schema/ckeditor_templates.schema.yml | 40 + + css/README.md | 4 + + css/cke_templates.admin.css | 1 + + css/cke_templates.dialog.css | 1 + + css/ckeditor_templates.css | 8 - + js/ckeditor_templates.admin.js | 32 - + js/ckeditor_templates.dialog.js | 22 - + js/dist/ckeditorTemplates.js | 1 + + js/plugin/src/app.js | 6 + + js/plugin/src/ckeditorTemplates.js | 26 + + js/plugin/src/ckeditorTemplatesCommand.js | 41 + + js/plugin/src/ckeditorTemplatesEditing.js | 42 + + js/plugin/src/ckeditorTemplatesUI.js | 51 + + js/plugin/theme/icons/templates.svg | 1 + + js/plugin/theme/images/placeholder.svg | 1 + + package-lock.json | 4455 +++++++++++++++++ + package.json | 32 + + sass/dialog.scss | 47 + + src/CKEditorTemplatesInterface.php | 12 + + src/CKEditorTemplatesListBuilder.php | 100 + + src/Entity/CKEditorTemplates.php | 133 + + src/Form/CKEditorTemplatesDialogForm.php | 285 ++ + src/Form/CKEditorTemplatesEntityForm.php | 139 + + .../CKEditorTemplatesDialog.php | 68 + + .../CKEditorPlugin/CkeditorTemplates.php | 183 - + templates/ckeditor_templates.js.example | 83 - + webpack.config.js | 87 + + 36 files changed, 6021 insertions(+), 386 deletions(-) + create mode 100644 LICENSE.txt + create mode 100644 ckeditor_templates.ckeditor5.yml + create mode 100644 ckeditor_templates.links.action.yml + create mode 100644 ckeditor_templates.links.menu.yml + create mode 100644 ckeditor_templates.permissions.yml + create mode 100644 ckeditor_templates.routing.yml + create mode 100644 config/schema/ckeditor_templates.schema.yml + create mode 100644 css/README.md + create mode 100644 css/cke_templates.admin.css + create mode 100644 css/cke_templates.dialog.css + delete mode 100644 css/ckeditor_templates.css + delete mode 100644 js/ckeditor_templates.admin.js + delete mode 100644 js/ckeditor_templates.dialog.js + create mode 100644 js/dist/ckeditorTemplates.js + create mode 100644 js/plugin/src/app.js + create mode 100644 js/plugin/src/ckeditorTemplates.js + create mode 100644 js/plugin/src/ckeditorTemplatesCommand.js + create mode 100644 js/plugin/src/ckeditorTemplatesEditing.js + create mode 100644 js/plugin/src/ckeditorTemplatesUI.js + create mode 100644 js/plugin/theme/icons/templates.svg + create mode 100644 js/plugin/theme/images/placeholder.svg + create mode 100644 package-lock.json + create mode 100644 package.json + create mode 100644 sass/dialog.scss + create mode 100644 src/CKEditorTemplatesInterface.php + create mode 100644 src/CKEditorTemplatesListBuilder.php + create mode 100644 src/Entity/CKEditorTemplates.php + create mode 100644 src/Form/CKEditorTemplatesDialogForm.php + create mode 100644 src/Form/CKEditorTemplatesEntityForm.php + create mode 100644 src/Plugin/CKEditor5Plugin/CKEditorTemplatesDialog.php + delete mode 100644 src/Plugin/CKEditorPlugin/CkeditorTemplates.php + delete mode 100644 templates/ckeditor_templates.js.example + create mode 100644 webpack.config.js + +diff --git a/LICENSE.txt b/LICENSE.txt +new file mode 100644 +index 0000000..d159169 +--- /dev/null ++++ b/LICENSE.txt +@@ -0,0 +1,339 @@ ++ GNU GENERAL PUBLIC LICENSE ++ Version 2, June 1991 ++ ++ Copyright (C) 1989, 1991 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. ++ ++ Preamble ++ ++ The licenses for most software are designed to take away your ++freedom to share and change it. By contrast, the GNU General Public ++License is intended to guarantee your freedom to share and change free ++software--to make sure the software is free for all its users. This ++General Public License applies to most of the Free Software ++Foundation's software and to any other program whose authors commit to ++using it. (Some other Free Software Foundation software is covered by ++the GNU Lesser General Public License instead.) You can apply it to ++your programs, too. ++ ++ When we speak of free software, we are referring to freedom, 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 or use pieces of it ++in new free programs; and that you know you can do these things. ++ ++ To protect your rights, we need to make restrictions that forbid ++anyone to deny you these rights or to ask you to surrender the rights. ++These restrictions translate to certain responsibilities for you if you ++distribute copies of the software, or if you modify it. ++ ++ For example, if you distribute copies of such a program, whether ++gratis or for a fee, you must give the recipients all the rights that ++you have. You must make sure that they, too, receive or can get the ++source code. And you must show them these terms so they know their ++rights. ++ ++ We protect your rights with two steps: (1) copyright the software, and ++(2) offer you this license which gives you legal permission to copy, ++distribute and/or modify the software. ++ ++ Also, for each author's protection and ours, we want to make certain ++that everyone understands that there is no warranty for this free ++software. If the software is modified by someone else and passed on, we ++want its recipients to know that what they have is not the original, so ++that any problems introduced by others will not reflect on the original ++authors' reputations. ++ ++ Finally, any free program is threatened constantly by software ++patents. We wish to avoid the danger that redistributors of a free ++program will individually obtain patent licenses, in effect making the ++program proprietary. To prevent this, we have made it clear that any ++patent must be licensed for everyone's free use or not licensed at all. ++ ++ The precise terms and conditions for copying, distribution and ++modification follow. ++ ++ GNU GENERAL PUBLIC LICENSE ++ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION ++ ++ 0. This License applies to any program or other work which contains ++a notice placed by the copyright holder saying it may be distributed ++under the terms of this General Public License. The "Program", below, ++refers to any such program or work, and a "work based on the Program" ++means either the Program or any derivative work under copyright law: ++that is to say, a work containing the Program or a portion of it, ++either verbatim or with modifications and/or translated into another ++language. (Hereinafter, translation is included without limitation in ++the term "modification".) Each licensee is addressed as "you". ++ ++Activities other than copying, distribution and modification are not ++covered by this License; they are outside its scope. The act of ++running the Program is not restricted, and the output from the Program ++is covered only if its contents constitute a work based on the ++Program (independent of having been made by running the Program). ++Whether that is true depends on what the Program does. ++ ++ 1. You may copy and distribute verbatim copies of the Program's ++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 give any other recipients of the Program a copy of this License ++along with the Program. ++ ++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 Program or any portion ++of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices ++ stating that you changed the files and the date of any change. ++ ++ b) You must cause any work that you distribute or publish, that in ++ whole or in part contains or is derived from the Program or any ++ part thereof, to be licensed as a whole at no charge to all third ++ parties under the terms of this License. ++ ++ c) If the modified program normally reads commands interactively ++ when run, you must cause it, when started running for such ++ interactive use in the most ordinary way, to print or display an ++ announcement including an appropriate copyright notice and a ++ notice that there is no warranty (or else, saying that you provide ++ a warranty) and that users may redistribute the program under ++ these conditions, and telling the user how to view a copy of this ++ License. (Exception: if the Program itself is interactive but ++ does not normally print such an announcement, your work based on ++ the Program is not required to print an announcement.) ++ ++These requirements apply to the modified work as a whole. If ++identifiable sections of that work are not derived from the Program, ++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 Program, 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 Program. ++ ++In addition, mere aggregation of another work not based on the Program ++with the Program (or with a work based on the Program) on a volume of ++a storage or distribution medium does not bring the other work under ++the scope of this License. ++ ++ 3. You may copy and distribute the Program (or a work based on it, ++under Section 2) in object code or executable form under the terms of ++Sections 1 and 2 above provided that you also do one of the following: ++ ++ a) 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; or, ++ ++ b) Accompany it with a written offer, valid for at least three ++ years, to give any third party, for a charge no more than your ++ cost of physically performing source distribution, a complete ++ machine-readable copy of the corresponding source code, to be ++ distributed under the terms of Sections 1 and 2 above on a medium ++ customarily used for software interchange; or, ++ ++ c) Accompany it with the information you received as to the offer ++ to distribute corresponding source code. (This alternative is ++ allowed only for noncommercial distribution and only if you ++ received the program in object code or executable form with such ++ an offer, in accord with Subsection b above.) ++ ++The source code for a work means the preferred form of the work for ++making modifications to it. For an executable work, 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 executable. However, as a ++special exception, the source code 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. ++ ++If distribution of executable or 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 counts as ++distribution of the source code, even though third parties are not ++compelled to copy the source along with the object code. ++ ++ 4. You may not copy, modify, sublicense, or distribute the Program ++except as expressly provided under this License. Any attempt ++otherwise to copy, modify, sublicense or distribute the Program 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. ++ ++ 5. 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 Program or its derivative works. These actions are ++prohibited by law if you do not accept this License. Therefore, by ++modifying or distributing the Program (or any work based on the ++Program), you indicate your acceptance of this License to do so, and ++all its terms and conditions for copying, distributing or modifying ++the Program or works based on it. ++ ++ 6. Each time you redistribute the Program (or any work based on the ++Program), the recipient automatically receives a license from the ++original licensor to copy, distribute or modify the Program 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 to ++this License. ++ ++ 7. 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 Program at all. For example, if a patent ++license would not permit royalty-free redistribution of the Program 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 Program. ++ ++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. ++ ++ 8. If the distribution and/or use of the Program is restricted in ++certain countries either by patents or by copyrighted interfaces, the ++original copyright holder who places the Program 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. ++ ++ 9. The Free Software Foundation may publish revised and/or new versions ++of the 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 Program ++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 Program does not specify a version number of ++this License, you may choose any version ever published by the Free Software ++Foundation. ++ ++ 10. If you wish to incorporate parts of the Program into other free ++programs whose distribution conditions are different, 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 ++ ++ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY ++FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN ++OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES ++PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE ++PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, ++REPAIR OR CORRECTION. ++ ++ 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER ++PROGRAMS), 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 Programs ++ ++ If you develop a new program, and you want it to be of the greatest ++possible use to the public, the best way to achieve this is to make it ++free software which everyone can redistribute and change under these terms. ++ ++ To do so, attach the following notices to the program. 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 program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program 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 General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License along ++ with this program; 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. ++ ++If the program is interactive, make it output a short notice like this ++when it starts in an interactive mode: ++ ++ Gnomovision version 69, Copyright (C) year name of author ++ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. ++ This is free software, and you are welcome to redistribute it ++ under certain conditions; type `show c' for details. ++ ++The hypothetical commands `show w' and `show c' should show the appropriate ++parts of the General Public License. Of course, the commands you use may ++be called something other than `show w' and `show c'; they could even be ++mouse-clicks or menu items--whatever suits your program. ++ ++You should also get your employer (if you work as a programmer) or your ++school, if any, to sign a "copyright disclaimer" for the program, if ++necessary. Here is a sample; alter the names: ++ ++ Yoyodyne, Inc., hereby disclaims all copyright interest in the program ++ `Gnomovision' (which makes passes at compilers) written by James Hacker. ++ ++ , 1 April 1989 ++ Ty Coon, President of Vice ++ ++This General Public License does not permit incorporating your program into ++proprietary programs. If your program is a subroutine library, you may ++consider it more useful to permit linking proprietary applications with the ++library. If this is what you want to do, use the GNU Lesser General ++Public License instead of this License. +diff --git a/README.txt b/README.txt +index 126ce0f..441c79f 100755 +--- a/README.txt ++++ b/README.txt +@@ -1,10 +1,10 @@ + INTRODUCTION + ------------ +-This module integrates the CKEditor templates plugin. ++This module provides templates for the CKEditor 5. + + It provides a dialog to offer predefined content templates - with page layout, +-text formatting and styles. Thus, end users can easily insert pre-defined +-snippets of html in CKEditor fields. ++text formatting, and styles. Thus, end users can easily insert predefined ++snippets of HTML in CKEditor fields. + + * For a full description of the module, visit the project page: + https://www.drupal.org/project/ckeditor_templates +@@ -13,65 +13,40 @@ snippets of html in CKEditor fields. + https://www.drupal.org/project/issues/ckeditor_templates?categories=All + + AUDIENCE +---------- +-This module is intended for themers who can manage custom ckeditor templates +-from their theme. As is, it doesn't provide any fonctionnality. ++-------- ++This module is intended for themers who can manage custom CKEditor templates ++from their theme. As is, it doesn't provide any functionality. + + REQUIREMENTS + ------------ +-This module requires to install the CKEditor "Templates" plugin. +-http://ckeditor.com/addon/templates ++This module requires CKEditor 5. + + INSTALLATION + ------------ +-Download the CKEditor "Templates" plugin on the project page : +-http://ckeditor.com/addon/templates +-Create a libraries folder in your drupal root if it doesn't exist +-Extract the plugin archive in the librairies folder +- +-Then install this Drupal module as you would normally install a contributed +-Drupal module. Visit: +-https://www.drupal.org/documentation/install/modules-themes/modules-8 for +-further information. ++Install this Drupal module as you would normally install a contributed ++Drupal module. For more information, visit: ++https://www.drupal.org/documentation/install/modules-themes/modules-8 + + CONFIGURATION +------------- +-- First, you need to add the plugin button in your editor toolbar. +-Go to the format and editor config page and click configure on the format your +-want to edit : +-http://drupalvm.dev/admin/config/content/formats +-- Add the templates button to the toolbar +-- copy the file ckeditor_templates.js.example from the module templates folder +-to your theme templates folder, rename it without .example and customize it : +- x edit the image_path variable to link to your thumbnail folder +- x copy the standard images from the libraries/templates/templates/images +- folder and place them in the folder created previously (image_path). +- x change the templates array in your custom ckeditor_templates.js to include +- any custom templates you want your users to have access to. +- +-If you want to place your template file in a different folder, you can set the +-path on the Editor config page. +- +-If you have a particular setup with non standard path and your template file is +-not found, you can always specify any custom path in the Editor Config Page, +-found at "Configuration", "Text formats and editors". Choose the editor type you +-want to expose the templates to and set path parameter at "Templates", +-"Templates Definition File", in the "CKEditor plugin settings" section. ++------------- ++- First, add the plugin button in your editor toolbar: go to the format and ++editor config page (/admin/config/content/formats), and click configure on the ++format your want to edit. ++- Next, create the templates: go to the CKEditor Templates config page ++(/admin/config/content/ckeditor-templates) and add as many templates as needed. + + WARNING +--------- ++------- + Depending on the configuration of your formats, CKEditor can be restrictive +-about authorized HTML tags. Make sure to use compatible HTML tags in your +-templates. ++about authorized HTML tags. Therefore, make sure to use compatible HTML tags ++in your templates. + +-ROAD MAP +---------- +-Two features could be added : +-- Allowing to add multiple template files so that you don't have to write all +-your templates in one big file +-- Allow to restrict for one editor the template displayed. Thus you could have +-10 templates in a file and display only 3 of them on a specific format. ++MIGRATING FROM CKEDITOR 4 ++------------------------- + ++If you had this module installed for CKEditor 4, all templates will not be ++migrated to the new version for CKEditor 5. Instead, you will have to manually ++create the templates in the new version, as described above. + + MAINTAINERS + ----------- +diff --git a/ckeditor_templates.ckeditor5.yml b/ckeditor_templates.ckeditor5.yml +new file mode 100644 +index 0000000..a387b3c +--- /dev/null ++++ b/ckeditor_templates.ckeditor5.yml +@@ -0,0 +1,23 @@ ++ckeditor_templates_plugin: ++ ckeditor5: ++ plugins: ++ - ckeditorTemplates.CKEditorTemplates ++ config: ++ ckeditorTemplates: ++ openDialog: ++ func: ++ name: Drupal.ckeditor5.openDialog ++ invoke: false ++ dialogSettings: ++ height: 75% ++ dialogClass: ckeditor-templates-widget-modal ++ title: Content Templates ++ drupal: ++ label: Templates ++ elements: false ++ library: ckeditor_templates/ckeditor.templates.dialog ++ admin_library: ckeditor_templates/ckeditor.templates.admin ++ class: Drupal\ckeditor_templates\Plugin\CKEditor5Plugin\CKEditorTemplatesDialog ++ toolbar_items: ++ ckeditorTemplates: ++ label: Templates +diff --git a/ckeditor_templates.info.yml b/ckeditor_templates.info.yml +index 19bbf56..6975f55 100644 +--- a/ckeditor_templates.info.yml ++++ b/ckeditor_templates.info.yml +@@ -2,7 +2,6 @@ name: CKEditor Templates + description: 'Integrates the CKEditor templates plugin.' + package: CKEditor + type: module +-core: 8.x +-core_version_requirement: ^8 || ^9 ++core_version_requirement: ^9.3 || ^10 + dependencies: +-- drupal:ckeditor ++- drupal:ckeditor5 +diff --git a/ckeditor_templates.libraries.yml b/ckeditor_templates.libraries.yml +index 6130ff9..b5ea02b 100644 +--- a/ckeditor_templates.libraries.yml ++++ b/ckeditor_templates.libraries.yml +@@ -1,12 +1,16 @@ + ckeditor.templates.dialog: +- version: 1.x ++ version: 2.x + css: + theme: +- css/ckeditor_templates.css: {} ++ css/cke_templates.dialog.css: {minified: true} + js: +- js/ckeditor_templates.dialog.js: {} ++ js/dist/ckeditorTemplates.js: {} ++ dependencies: ++ - ckeditor5/ckeditor5 ++ - editor/drupal.editor.dialog + + ckeditor.templates.admin: +- version: 1.x +- js: +- js/ckeditor_templates.admin.js: {} ++ version: 2.x ++ css: ++ theme: ++ css/cke_templates.admin.css: {} +diff --git a/ckeditor_templates.links.action.yml b/ckeditor_templates.links.action.yml +new file mode 100644 +index 0000000..52df8f1 +--- /dev/null ++++ b/ckeditor_templates.links.action.yml +@@ -0,0 +1,5 @@ ++entity.ckeditor_templates.add_form: ++ route_name: 'entity.ckeditor_templates.add_form' ++ title: 'Add Template' ++ appears_on: ++ - entity.ckeditor_templates.collection +diff --git a/ckeditor_templates.links.menu.yml b/ckeditor_templates.links.menu.yml +new file mode 100644 +index 0000000..938e2e5 +--- /dev/null ++++ b/ckeditor_templates.links.menu.yml +@@ -0,0 +1,5 @@ ++entity.ckeditor_templates.overview: ++ title: CKEditor Templates ++ parent: system.admin_config_content ++ description: 'List of CKEditor Templates to be used when editing texts.' ++ route_name: entity.ckeditor_templates.collection +diff --git a/ckeditor_templates.permissions.yml b/ckeditor_templates.permissions.yml +new file mode 100644 +index 0000000..faadbaa +--- /dev/null ++++ b/ckeditor_templates.permissions.yml +@@ -0,0 +1,2 @@ ++administer ckeditor templates: ++ title: 'Administer CKEditor Templates' +diff --git a/ckeditor_templates.routing.yml b/ckeditor_templates.routing.yml +new file mode 100644 +index 0000000..1e41357 +--- /dev/null ++++ b/ckeditor_templates.routing.yml +@@ -0,0 +1,38 @@ ++ckeditor_templates.selector: ++ path: '/admin/config/content/ckeditor-templates/template-selector/{editor_id}' ++ defaults: ++ _form: '\Drupal\ckeditor_templates\Form\CKEditorTemplatesDialogForm' ++ requirements: ++ _permission: 'use text format advanced' ++ ++entity.ckeditor_templates.collection: ++ path: '/admin/config/content/ckeditor-templates' ++ defaults: ++ _entity_list: 'ckeditor_templates' ++ _title: 'CKEditor Template Configuration' ++ requirements: ++ _permission: 'administer ckeditor templates' ++ ++entity.ckeditor_templates.add_form: ++ path: '/admin/config/content/ckeditor-templates/add' ++ defaults: ++ _entity_form: 'ckeditor_templates.add' ++ _title: 'Add a CKEditor Template' ++ requirements: ++ _permission: 'administer ckeditor templates' ++ ++entity.ckeditor_templates.edit_form: ++ path: '/admin/config/content/ckeditor-templates/{ckeditor_templates}' ++ defaults: ++ _entity_form: 'ckeditor_templates.edit' ++ _title: 'Edit a CKEditor Template' ++ requirements: ++ _permission: 'administer ckeditor templates' ++ ++entity.ckeditor_templates.delete_form: ++ path: '/admin/config/content/ckeditor-templates/{ckeditor_templates}/delete' ++ defaults: ++ _entity_form: 'ckeditor_templates.delete' ++ _title: 'Delete a CKEditor Template' ++ requirements: ++ _permission: 'administer ckeditor templates' +diff --git a/config/schema/ckeditor_templates.schema.yml b/config/schema/ckeditor_templates.schema.yml +new file mode 100644 +index 0000000..ae7514b +--- /dev/null ++++ b/config/schema/ckeditor_templates.schema.yml +@@ -0,0 +1,40 @@ ++ckeditor_templates.ckeditor_templates.*: ++ type: config_entity ++ label: CKEditor Template ++ mapping: ++ id: ++ type: string ++ label: ID ++ label: ++ type: label ++ label: Title ++ status: ++ type: boolean ++ label: Enabled ++ description: ++ type: string ++ label: Description ++ thumb: ++ type: sequence ++ label: Icon/Image ++ code: ++ type: string ++ label: HTML Code ++ formats: ++ type: sequence ++ label: Available for ++ weight: ++ type: integer ++ label: Weight ++ uuid: ++ type: string ++ ++ckeditor5.plugin.ckeditor_templates_plugin: ++ type: mapping ++ label: Replace Content ++ mapping: ++ replace_content: ++ type: boolean ++ label: 'Replace content' ++ constraints: ++ NotNull: [] +diff --git a/css/README.md b/css/README.md +new file mode 100644 +index 0000000..e78cc75 +--- /dev/null ++++ b/css/README.md +@@ -0,0 +1,4 @@ ++### Important ++ ++The **cke_templates.dialog.css** file in this folder is automatically generated by running the command ++`npm run build`. +diff --git a/css/cke_templates.admin.css b/css/cke_templates.admin.css +new file mode 100644 +index 0000000..cd52fb2 +--- /dev/null ++++ b/css/cke_templates.admin.css +@@ -0,0 +1 @@ ++.ckeditor5-toolbar-button-ckeditorTemplates {background-image: url(../js/plugin/theme/icons/templates.svg)} +diff --git a/css/cke_templates.dialog.css b/css/cke_templates.dialog.css +new file mode 100644 +index 0000000..d2bfc0f +--- /dev/null ++++ b/css/cke_templates.dialog.css +@@ -0,0 +1 @@ ++.ckeditor-templates-widget-modal .form-radios{margin:0;padding:0}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates{margin:0;padding:0}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates input,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates input{display:none}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates label,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates label{display:flex;margin-top:.75rem;padding:.75rem;border:#bcbcbc 1px solid;align-items:flex-start;user-select:none}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates label:hover,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates label:hover{background-color:#efefef}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates label img,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates label img{width:5rem;margin-right:.75rem}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates label div,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates label div{line-height:1.2rem}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates label div strong,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates label div strong{display:block}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates input:checked+label,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates input:checked+label{border:#f93 1px solid;background-color:#fffacd} +diff --git a/css/ckeditor_templates.css b/css/ckeditor_templates.css +deleted file mode 100644 +index 70a2f30..0000000 +--- a/css/ckeditor_templates.css ++++ /dev/null +@@ -1,8 +0,0 @@ +-.cke_templates_dialog .cke_dialog_ui_checkbox input { +- vertical-align: middle; +-} +- +-/* Set correct alignment for the "Replace actual content" checkbox */ +-.cke_reset_all .cke_templates_dialog .cke_dialog_ui_checkbox label { +- display: inline-block; +-} +diff --git a/js/ckeditor_templates.admin.js b/js/ckeditor_templates.admin.js +deleted file mode 100644 +index 372e6d8..0000000 +--- a/js/ckeditor_templates.admin.js ++++ /dev/null +@@ -1,32 +0,0 @@ +-/** +- * @file +- * CKEditor 'templates' plugin admin behavior. +- */ +- +-(function ($, Drupal, drupalSettings) { +- +- 'use strict'; +- +- /** +- * Provides the summary for the "templates" plugin settings vertical tab. +- * +- * @type {Drupal~behavior} +- * +- * @prop {Drupal~behaviorAttach} attach +- * Attaches summary behaviour to the "templates" settings vertical tab. +- */ +- Drupal.behaviors.ckeditorTemplatesSettingsSummary = { +- attach: function () { +- $('[data-ckeditor-plugin-id="templates"]').drupalSetSummary(function (context) { +- var templatePathValue = $('input[name="editor[settings][plugins][templates][template_path]').val(); +- var replaceContentValue = $('input[name="editor[settings][plugins][templates][replace_content]').is(':checked'); +- +- var templatePathOutput = templatePathValue ? 'Template file overridden.' : 'Default or theme template file.'; +- var replaceContentOutput = replaceContentValue ? '"Replace content" checked' : '"Replace content" unchecked'; +- +- return templatePathOutput + '
' + replaceContentOutput; +- }); +- } +- }; +- +-})(jQuery, Drupal, drupalSettings); +diff --git a/js/ckeditor_templates.dialog.js b/js/ckeditor_templates.dialog.js +deleted file mode 100644 +index 58cfa0c..0000000 +--- a/js/ckeditor_templates.dialog.js ++++ /dev/null +@@ -1,22 +0,0 @@ +-/** +- * @file +- * Override ckeditor template dialog style. +- */ +- +-(function (CKEDITOR) { +- +- 'use strict'; +- +- CKEDITOR.on('dialogDefinition', function (ev) { +- var dialogName = ev.data.name; +- var dialog = ev.data.definition.dialog; +- +- if (dialogName === 'templates') { +- dialog.on('show', function () { +- var dialogElement = dialog.getElement().getFirst(); +- dialogElement.addClass('cke_templates_dialog'); +- }); +- } +- }); +- +-})(CKEDITOR); +diff --git a/js/dist/ckeditorTemplates.js b/js/dist/ckeditorTemplates.js +new file mode 100644 +index 0000000..d56d71c +--- /dev/null ++++ b/js/dist/ckeditorTemplates.js +@@ -0,0 +1 @@ ++!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.ckeditorTemplates=t())}(self,(()=>(()=>{var e={"ckeditor5/src/core.js":(e,t,o)=>{e.exports=o("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/ui.js":(e,t,o)=>{e.exports=o("dll-reference CKEditor5.dll")("./src/ui.js")},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},t={};function o(r){var s=t[r];if(void 0!==s)return s.exports;var i=t[r]={exports:{}};return e[r](i,i.exports,o),i.exports}o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var r={};return(()=>{"use strict";o.d(r,{default:()=>d});var e=o("ckeditor5/src/core.js"),t=o("ckeditor5/src/ui.js");class s extends e.Plugin{init(){const e=this.editor,o=this.editor.config.get("ckeditorTemplates");o&&o.openDialog&&o.dialogSettings&&o.dialogUrl&&e.ui.componentFactory.add("ckeditorTemplates",(r=>{const s=new t.ButtonView(r);s.set({label:Drupal.t("Templates"),icon:'\n',tooltip:!0});const i=e.commands.get("ckeditorTemplates");return s.bind("isOn","isEnabled").to(i,"value","isEnabled"),this.listenTo(s,"execute",(()=>{const t=o.dialogUrl,r=o.dialogSettings;o.openDialog(t,(({htmlCode:t,replace:o})=>{e.execute("ckeditorTemplates",t,o)}),r)})),s}))}}class i extends e.Command{refresh(){const e=this.editor.model,t=e.document.selection,o=e.schema.findAllowedParent(t.getFirstPosition(),"ckeditorTemplates");this.isEnabled=!!o}execute(e,t){const o=this.editor,r=o.data;if(t)r.set(e);else{const t=o.model;t.change((()=>{const o=r.processor.toView(e),s=r.toModel(o);t.insertContent(s)}))}}}class n extends e.Plugin{static get requires(){return[i]}init(){const e=this.editor,t="ckeditorTemplates";this.editor.model.schema.register(t,{allowWhere:"$block",isObject:!0,isContent:!0,isBlock:!0}),this.editor.commands.add(t,new i(e))}static get pluginName(){return"ckeditorTemplatesEditing"}}class l extends e.Plugin{static get requires(){return[s,n]}static get pluginName(){return"ckeditorTemplates"}}const d={CKEditorTemplates:l}})(),r=r.default})())); +\ No newline at end of file +diff --git a/js/plugin/src/app.js b/js/plugin/src/app.js +new file mode 100644 +index 0000000..8634917 +--- /dev/null ++++ b/js/plugin/src/app.js +@@ -0,0 +1,6 @@ ++import CKEditorTemplates from './ckeditorTemplates'; ++import './../../../sass/dialog.scss'; ++ ++export default { ++ CKEditorTemplates ++}; +diff --git a/js/plugin/src/ckeditorTemplates.js b/js/plugin/src/ckeditorTemplates.js +new file mode 100644 +index 0000000..ec7505f +--- /dev/null ++++ b/js/plugin/src/ckeditorTemplates.js +@@ -0,0 +1,26 @@ ++import { Plugin } from 'ckeditor5/src/core'; ++import CKEditorTemplatesUI from './ckeditorTemplatesUI'; ++import CKEditorTemplatesEditing from './ckeditorTemplatesEditing'; ++ ++/** ++ * Generates a CKEditor 5 plugin. ++ */ ++export default class CKEditorTemplates extends Plugin { ++ ++ /** ++ * @inheritdoc ++ */ ++ static get requires() { ++ return [ ++ CKEditorTemplatesUI, ++ CKEditorTemplatesEditing ++ ]; ++ } ++ ++ /** ++ * @inheritdoc ++ */ ++ static get pluginName() { ++ return 'ckeditorTemplates'; ++ } ++} +diff --git a/js/plugin/src/ckeditorTemplatesCommand.js b/js/plugin/src/ckeditorTemplatesCommand.js +new file mode 100644 +index 0000000..33888a5 +--- /dev/null ++++ b/js/plugin/src/ckeditorTemplatesCommand.js +@@ -0,0 +1,41 @@ ++import { Command } from 'ckeditor5/src/core'; ++ ++/** ++ * Command for injecting code into the CKEditor. ++ */ ++export default class CKEditorTemplatesCommand extends Command { ++ ++ /** ++ * @inheritdoc ++ */ ++ refresh() { ++ const model = this.editor.model; ++ const selection = model.document.selection; ++ const allowedParent = model.schema.findAllowedParent( ++ selection.getFirstPosition(), ++ 'ckeditorTemplates' ++ ); ++ this.isEnabled = !!allowedParent; ++ } ++ ++ /** ++ * @inheritdoc ++ */ ++ execute(htmlCode, replace) { ++ const editor = this.editor; ++ const data = editor.data; ++ ++ if (replace) { ++ data.set(htmlCode); ++ } ++ else { ++ const model = editor.model; ++ model.change(() => { ++ const viewFragment = data.processor.toView(htmlCode); ++ const modelFragment = data.toModel(viewFragment); ++ model.insertContent(modelFragment); ++ }); ++ } ++ } ++ ++} +diff --git a/js/plugin/src/ckeditorTemplatesEditing.js b/js/plugin/src/ckeditorTemplatesEditing.js +new file mode 100644 +index 0000000..b8b387e +--- /dev/null ++++ b/js/plugin/src/ckeditorTemplatesEditing.js +@@ -0,0 +1,42 @@ ++import { Plugin } from 'ckeditor5/src/core'; ++import CKEditorTemplatesCommand from './ckeditorTemplatesCommand'; ++ ++/** ++ * Handles the plugin functionality. ++ */ ++export default class CKEditorTemplatesEditing extends Plugin { ++ ++ /** ++ * @inheritdoc ++ */ ++ static get requires() { ++ return [ ++ CKEditorTemplatesCommand ++ ]; ++ } ++ ++ /** ++ * @inheritdoc ++ */ ++ init() { ++ const editor = this.editor; ++ const plugin = 'ckeditorTemplates'; ++ ++ const schema = { ++ allowWhere: '$block', ++ isObject: true, ++ isContent: true, ++ isBlock: true ++ }; ++ ++ this.editor.model.schema.register(plugin, schema); ++ this.editor.commands.add(plugin, new CKEditorTemplatesCommand(editor)); ++ } ++ ++ /** ++ * @inheritdoc ++ */ ++ static get pluginName() { ++ return 'ckeditorTemplatesEditing'; ++ } ++} +diff --git a/js/plugin/src/ckeditorTemplatesUI.js b/js/plugin/src/ckeditorTemplatesUI.js +new file mode 100644 +index 0000000..5389325 +--- /dev/null ++++ b/js/plugin/src/ckeditorTemplatesUI.js +@@ -0,0 +1,51 @@ ++import { Plugin } from 'ckeditor5/src/core'; ++import { ButtonView } from 'ckeditor5/src/ui'; ++import CKEditorTemplatesIcon from '../theme/icons/templates.svg'; ++ ++/** ++ * Generates a toolbar button. ++ */ ++export default class EmbeddedContentUI extends Plugin { ++ ++ /** ++ * @inheritdoc ++ */ ++ init() { ++ const editor = this.editor; ++ ++ // Gets the options from the Drupal plugin. ++ const dialogOptions = this.editor.config.get('ckeditorTemplates'); ++ if (!dialogOptions || !dialogOptions.openDialog || !dialogOptions.dialogSettings || !dialogOptions.dialogUrl) { ++ return; ++ } ++ ++ // Adds a button to the CKEditor toolbar. ++ editor.ui.componentFactory.add('ckeditorTemplates', (locale) => { ++ ++ // Generates a button view. ++ const buttonView = new ButtonView(locale); ++ buttonView.set({ ++ label: Drupal.t('Templates'), ++ icon: CKEditorTemplatesIcon, ++ tooltip: true ++ }); ++ ++ // Adds a command object to the button. ++ const command = editor.commands.get('ckeditorTemplates'); ++ buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled'); ++ ++ // Adds a listener to the button click. ++ this.listenTo(buttonView, 'execute', () => { ++ const url = dialogOptions.dialogUrl; ++ const settings = dialogOptions.dialogSettings; ++ const callback = ({ htmlCode, replace }) => { ++ editor.execute('ckeditorTemplates', htmlCode, replace); ++ }; ++ ++ dialogOptions.openDialog(url, callback, settings); ++ }); ++ ++ return buttonView; ++ }); ++ } ++} +diff --git a/js/plugin/theme/icons/templates.svg b/js/plugin/theme/icons/templates.svg +new file mode 100644 +index 0000000..b60c549 +--- /dev/null ++++ b/js/plugin/theme/icons/templates.svg +@@ -0,0 +1 @@ ++ +diff --git a/js/plugin/theme/images/placeholder.svg b/js/plugin/theme/images/placeholder.svg +new file mode 100644 +index 0000000..20c435c +--- /dev/null ++++ b/js/plugin/theme/images/placeholder.svg +@@ -0,0 +1 @@ ++ +diff --git a/package-lock.json b/package-lock.json +new file mode 100644 +index 0000000..6b5aeaf +--- /dev/null ++++ b/package-lock.json +@@ -0,0 +1,4455 @@ ++{ ++ "name": "ckeditor5-templates", ++ "version": "1.0.0", ++ "lockfileVersion": 3, ++ "requires": true, ++ "packages": { ++ "": { ++ "name": "ckeditor5-templates", ++ "version": "1.0.0", ++ "license": "GPL-2.0-or-later", ++ "dependencies": { ++ "@ckeditor/ckeditor5-basic-styles": "^35.4.0", ++ "@ckeditor/ckeditor5-dev-utils": "^32.0.2", ++ "@ckeditor/ckeditor5-editor-classic": "^35.4.0", ++ "@ckeditor/ckeditor5-engine": "^35.4.0", ++ "@ckeditor/ckeditor5-essentials": "^35.4.0", ++ "@ckeditor/ckeditor5-html-support": "^35.4.0", ++ "@ckeditor/ckeditor5-paragraph": "^35.4.0", ++ "@ckeditor/ckeditor5-theme-lark": "^35.4.0", ++ "ckeditor5": "^35.4.0", ++ "css-loader": "^5.2.7", ++ "mini-css-extract-plugin": "^2.7.2", ++ "postcss-loader": "^4.3.0", ++ "raw-loader": "^4.0.2", ++ "sass": "^1.58.0", ++ "sass-loader": "^13.2.0", ++ "style-loader": "^2.0.0", ++ "terser-webpack-plugin": "^5.3.6", ++ "webpack": "^5.75.0" ++ }, ++ "devDependencies": { ++ "webpack-cli": "^5.0.1" ++ } ++ }, ++ "node_modules/@babel/code-frame": { ++ "version": "7.18.6", ++ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", ++ "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", ++ "dependencies": { ++ "@babel/highlight": "^7.18.6" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/generator": { ++ "version": "7.20.14", ++ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.14.tgz", ++ "integrity": "sha512-AEmuXHdcD3A52HHXxaTmYlb8q/xMEhoRP67B3T4Oq7lbmSoqroMZzjnGj3+i1io3pdnF8iBYVu4Ilj+c4hBxYg==", ++ "dependencies": { ++ "@babel/types": "^7.20.7", ++ "@jridgewell/gen-mapping": "^0.3.2", ++ "jsesc": "^2.5.1" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-environment-visitor": { ++ "version": "7.18.9", ++ "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", ++ "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-function-name": { ++ "version": "7.19.0", ++ "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", ++ "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", ++ "dependencies": { ++ "@babel/template": "^7.18.10", ++ "@babel/types": "^7.19.0" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-hoist-variables": { ++ "version": "7.18.6", ++ "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", ++ "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", ++ "dependencies": { ++ "@babel/types": "^7.18.6" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-split-export-declaration": { ++ "version": "7.18.6", ++ "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", ++ "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", ++ "dependencies": { ++ "@babel/types": "^7.18.6" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-string-parser": { ++ "version": "7.19.4", ++ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", ++ "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/helper-validator-identifier": { ++ "version": "7.19.1", ++ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", ++ "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/highlight": { ++ "version": "7.18.6", ++ "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", ++ "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", ++ "dependencies": { ++ "@babel/helper-validator-identifier": "^7.18.6", ++ "chalk": "^2.0.0", ++ "js-tokens": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/highlight/node_modules/ansi-styles": { ++ "version": "3.2.1", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", ++ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", ++ "dependencies": { ++ "color-convert": "^1.9.0" ++ }, ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/@babel/highlight/node_modules/chalk": { ++ "version": "2.4.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", ++ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", ++ "dependencies": { ++ "ansi-styles": "^3.2.1", ++ "escape-string-regexp": "^1.0.5", ++ "supports-color": "^5.3.0" ++ }, ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/@babel/highlight/node_modules/color-convert": { ++ "version": "1.9.3", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", ++ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", ++ "dependencies": { ++ "color-name": "1.1.3" ++ } ++ }, ++ "node_modules/@babel/highlight/node_modules/color-name": { ++ "version": "1.1.3", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", ++ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" ++ }, ++ "node_modules/@babel/highlight/node_modules/has-flag": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", ++ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/@babel/highlight/node_modules/supports-color": { ++ "version": "5.5.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", ++ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", ++ "dependencies": { ++ "has-flag": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/@babel/parser": { ++ "version": "7.20.15", ++ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.15.tgz", ++ "integrity": "sha512-DI4a1oZuf8wC+oAJA9RW6ga3Zbe8RZFt7kD9i4qAspz3I/yHet1VvC3DiSy/fsUvv5pvJuNPh0LPOdCcqinDPg==", ++ "bin": { ++ "parser": "bin/babel-parser.js" ++ }, ++ "engines": { ++ "node": ">=6.0.0" ++ } ++ }, ++ "node_modules/@babel/template": { ++ "version": "7.20.7", ++ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.20.7.tgz", ++ "integrity": "sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==", ++ "dependencies": { ++ "@babel/code-frame": "^7.18.6", ++ "@babel/parser": "^7.20.7", ++ "@babel/types": "^7.20.7" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/traverse": { ++ "version": "7.20.13", ++ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.13.tgz", ++ "integrity": "sha512-kMJXfF0T6DIS9E8cgdLCSAL+cuCK+YEZHWiLK0SXpTo8YRj5lpJu3CDNKiIBCne4m9hhTIqUg6SYTAI39tAiVQ==", ++ "dependencies": { ++ "@babel/code-frame": "^7.18.6", ++ "@babel/generator": "^7.20.7", ++ "@babel/helper-environment-visitor": "^7.18.9", ++ "@babel/helper-function-name": "^7.19.0", ++ "@babel/helper-hoist-variables": "^7.18.6", ++ "@babel/helper-split-export-declaration": "^7.18.6", ++ "@babel/parser": "^7.20.13", ++ "@babel/types": "^7.20.7", ++ "debug": "^4.1.0", ++ "globals": "^11.1.0" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@babel/types": { ++ "version": "7.20.7", ++ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.7.tgz", ++ "integrity": "sha512-69OnhBxSSgK0OzTJai4kyPDiKTIe3j+ctaHdIGVbRahTLAT7L3R9oeXHC2aVSuGYt3cVnoAMDmOCgJ2yaiLMvg==", ++ "dependencies": { ++ "@babel/helper-string-parser": "^7.19.4", ++ "@babel/helper-validator-identifier": "^7.19.1", ++ "to-fast-properties": "^2.0.0" ++ }, ++ "engines": { ++ "node": ">=6.9.0" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-basic-styles": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-35.4.0.tgz", ++ "integrity": "sha512-6JkoplYMwIHN1E/w3DoY0i95B41sbGwsNAtlvx6qaBvNKkLu4rRCtiBUJDnx8qZxxQXHih5ZOw8bUQHl4mt8hw==", ++ "dependencies": { ++ "ckeditor5": "^35.4.0" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-clipboard": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-35.4.0.tgz", ++ "integrity": "sha512-B6rIQxvOrHvO9TZRC8JA0wKk+IfN880UJkYIg1qlhf9HFNVjdVbtHaiCsPD+TzGmQN3XHXfNjgjabGRIn0iZmw==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-core": "^35.4.0", ++ "@ckeditor/ckeditor5-engine": "^35.4.0", ++ "@ckeditor/ckeditor5-utils": "^35.4.0", ++ "@ckeditor/ckeditor5-widget": "^35.4.0", ++ "lodash-es": "^4.17.11" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-core": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-35.4.0.tgz", ++ "integrity": "sha512-Rf0H7C4inCj/YC8aii0cT7TC/IuBIQ+tXmu9qd8/1BJ/rz1MCHXtBPApjTbFp33OE3aOFB5+NUaKt05k/dL3OA==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-engine": "^35.4.0", ++ "@ckeditor/ckeditor5-ui": "^35.4.0", ++ "@ckeditor/ckeditor5-utils": "^35.4.0", ++ "lodash-es": "^4.17.15" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-dev-translations": { ++ "version": "32.1.2", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-dev-translations/-/ckeditor5-dev-translations-32.1.2.tgz", ++ "integrity": "sha512-TudMnRaiYMTNuDMWExeBh0Mk96GySWzgnh4fkXfoqiABQzd9Pp/Fcl40q0LJl4jtyS3qhQGFz88GxzkxAXXU9Q==", ++ "dependencies": { ++ "@babel/parser": "^7.18.9", ++ "@babel/traverse": "^7.18.9", ++ "chalk": "^4.0.0", ++ "pofile": "^1.0.9", ++ "rimraf": "^3.0.2", ++ "webpack-sources": "^2.0.1" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-dev-translations/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "dependencies": { ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" ++ }, ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-dev-utils": { ++ "version": "32.1.2", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-dev-utils/-/ckeditor5-dev-utils-32.1.2.tgz", ++ "integrity": "sha512-C9c6EnWhOElN5c56xhJ7mYA9AsgZbaME6d8hTGJ43J5ZG6wg7MFwVlRpv0u2unu8whLO6vsjrW7yeqBrFvo65Q==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-dev-translations": "^32.1.2", ++ "chalk": "^3.0.0", ++ "cli-cursor": "^3.1.0", ++ "cli-spinners": "^2.6.1", ++ "cssnano": "^5.0.0", ++ "del": "^5.0.0", ++ "fs-extra": "^8.1.0", ++ "is-interactive": "^1.0.0", ++ "javascript-stringify": "^1.6.0", ++ "postcss": "^8.4.12", ++ "postcss-import": "^14.1.0", ++ "postcss-loader": "^4.3.0", ++ "postcss-mixins": "^9.0.2", ++ "postcss-nesting": "^10.1.4", ++ "raw-loader": "^4.0.1", ++ "shelljs": "^0.8.1", ++ "style-loader": "^2.0.0", ++ "terser-webpack-plugin": "^4.2.3", ++ "through2": "^3.0.1", ++ "ts-loader": "^9.3.0" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ }, ++ "peerDependencies": { ++ "webpack": "^4.43.0 || ^5.24.0" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-dev-utils/node_modules/jest-worker": { ++ "version": "26.6.2", ++ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", ++ "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", ++ "dependencies": { ++ "@types/node": "*", ++ "merge-stream": "^2.0.0", ++ "supports-color": "^7.0.0" ++ }, ++ "engines": { ++ "node": ">= 10.13.0" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-dev-utils/node_modules/p-limit": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", ++ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", ++ "dependencies": { ++ "yocto-queue": "^0.1.0" ++ }, ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-dev-utils/node_modules/serialize-javascript": { ++ "version": "5.0.1", ++ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", ++ "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", ++ "dependencies": { ++ "randombytes": "^2.1.0" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-dev-utils/node_modules/terser-webpack-plugin": { ++ "version": "4.2.3", ++ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", ++ "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", ++ "dependencies": { ++ "cacache": "^15.0.5", ++ "find-cache-dir": "^3.3.1", ++ "jest-worker": "^26.5.0", ++ "p-limit": "^3.0.2", ++ "schema-utils": "^3.0.0", ++ "serialize-javascript": "^5.0.1", ++ "source-map": "^0.6.1", ++ "terser": "^5.3.4", ++ "webpack-sources": "^1.4.3" ++ }, ++ "engines": { ++ "node": ">= 10.13.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/webpack" ++ }, ++ "peerDependencies": { ++ "webpack": "^4.0.0 || ^5.0.0" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-dev-utils/node_modules/webpack-sources": { ++ "version": "1.4.3", ++ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", ++ "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", ++ "dependencies": { ++ "source-list-map": "^2.0.0", ++ "source-map": "~0.6.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-editor-classic": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-35.4.0.tgz", ++ "integrity": "sha512-EqAqFD/5oPtDMU2AoH3eJaDplcS8MxfkiRQ5hzeC1JeIPT94w5FCHnB4SAkjLPDnlyZnBWOOYdZSuln2TRIbEw==", ++ "dependencies": { ++ "ckeditor5": "^35.4.0", ++ "lodash-es": "^4.17.15" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-engine": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-35.4.0.tgz", ++ "integrity": "sha512-67QKtUGJeLM072h9qURvzczYGU3ecuxR9LLmM4dffnV+PBNQ9e8RDCY7PuuEP0pplmAUI6/XqoZJIbk6h7ZV3Q==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-utils": "^35.4.0", ++ "lodash-es": "^4.17.15" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-enter": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-35.4.0.tgz", ++ "integrity": "sha512-y95RnA/Gw72e220PJKVwNbwPzX4SRs82/rXu1jVyJXty7CcEZqqfyRtW6odICAXr5eKI5XKgzFgpFYULL3D9Nw==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-core": "^35.4.0", ++ "@ckeditor/ckeditor5-engine": "^35.4.0" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-essentials": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-35.4.0.tgz", ++ "integrity": "sha512-tTtTb4NYSQi99LPDzAVUnFhW6iTqSuaylkg0XnDvO2lVR3tAA27gOOjGqc8Ri9NMGGeZkFTvXpnVkXkFnDP2nQ==", ++ "dependencies": { ++ "ckeditor5": "^35.4.0" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-html-support": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-support/-/ckeditor5-html-support-35.4.0.tgz", ++ "integrity": "sha512-h1iV/JQQwqYD6xaVvgIjvx+dat7eZ0jFksEsHhTaYSDX+Qzcr/rFFN3mocWsoaOsn3iZFylOo/dP0NjZm+Yxfw==", ++ "dependencies": { ++ "ckeditor5": "^35.4.0", ++ "lodash-es": "^4.17.15" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-paragraph": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-35.4.0.tgz", ++ "integrity": "sha512-8nhkEEFv1WClhH6q/HW8P596d+dlatSVc46kQ2+jGlYirL8P66tV/nK+OiE8z1d897oVr4QPGsqk2qGkRFUChw==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-core": "^35.4.0", ++ "@ckeditor/ckeditor5-ui": "^35.4.0", ++ "@ckeditor/ckeditor5-utils": "^35.4.0" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-select-all": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-35.4.0.tgz", ++ "integrity": "sha512-c+pIIY77SP6ux4/cyD7cCrllQAqtFVSnzNYdy7ygNPqljCGngCnpSV9xfCO/blFo6/zx2vsmzVGdRq3ArzGoMg==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-core": "^35.4.0", ++ "@ckeditor/ckeditor5-ui": "^35.4.0", ++ "@ckeditor/ckeditor5-utils": "^35.4.0" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-theme-lark": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-35.4.0.tgz", ++ "integrity": "sha512-cf6pJN96KwKrs3KIvxrKR9pGMH2/I6MAFMyliN7O1MbauKeyC6cjwui41Yan10cWwpm6a6PeadyRbwQPa9HUaw==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-ui": "^35.4.0" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-typing": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-35.4.0.tgz", ++ "integrity": "sha512-Ad/PHWbVWcnAj9oevkkfLqf6CmvCFOti466uhvfOCKRNVf2+/xuGwleOGr8W6Lir/x/qav7ojFjKPKDxqbPXhA==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-core": "^35.4.0", ++ "@ckeditor/ckeditor5-engine": "^35.4.0", ++ "@ckeditor/ckeditor5-utils": "^35.4.0", ++ "lodash-es": "^4.17.15" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-ui": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-35.4.0.tgz", ++ "integrity": "sha512-0SmYE+k1cYQPqyw2rQsPDV/RpudneBh1bNfiaTOz+rqViJIMe+TxiuK6Fz+znNZ05s0exr+ZHWvMttGqlVoQNw==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-core": "^35.4.0", ++ "@ckeditor/ckeditor5-utils": "^35.4.0", ++ "lodash-es": "^4.17.15" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-undo": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-35.4.0.tgz", ++ "integrity": "sha512-0RhsK0f/pX/7KB/JXYTLiDOswmUTQ9EKIIuewAwr7LTsBf4Q309FZSFdbeTmc0wIyX33212Xh5xsi3LyG1VJRg==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-core": "^35.4.0", ++ "@ckeditor/ckeditor5-engine": "^35.4.0", ++ "@ckeditor/ckeditor5-ui": "^35.4.0" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-upload": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-35.4.0.tgz", ++ "integrity": "sha512-+eJAluAc4mAFmx5FNuSGjkCYmbm0V9NpSleubAXEx2e+KNiLarPAnsolwRaAcYXcloNp4C9/l0D+lPEx7VRYtg==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-core": "^35.4.0", ++ "@ckeditor/ckeditor5-ui": "^35.4.0", ++ "@ckeditor/ckeditor5-utils": "^35.4.0" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-utils": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-35.4.0.tgz", ++ "integrity": "sha512-sFjbb+1VYdLbELDLWVYk86WzVN7Lo3sXHbVhdr8+kc0Ufxdr3mTFHDAkiymFt2fs1FOB5gZyWJlJU+EeJnhKUw==", ++ "dependencies": { ++ "lodash-es": "^4.17.15" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@ckeditor/ckeditor5-widget": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-35.4.0.tgz", ++ "integrity": "sha512-SNYOXXWu7XV1BZET+ar0Cea25836vzNtUqXlDPwBx/jrmK86b8GMbFR99P2bUG0NvtIsH5cSk7XCmnxb4ZQ6wA==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-core": "^35.4.0", ++ "@ckeditor/ckeditor5-engine": "^35.4.0", ++ "@ckeditor/ckeditor5-enter": "^35.4.0", ++ "@ckeditor/ckeditor5-typing": "^35.4.0", ++ "@ckeditor/ckeditor5-ui": "^35.4.0", ++ "@ckeditor/ckeditor5-utils": "^35.4.0", ++ "lodash-es": "^4.17.15" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/@csstools/selector-specificity": { ++ "version": "2.1.1", ++ "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.1.1.tgz", ++ "integrity": "sha512-jwx+WCqszn53YHOfvFMJJRd/B2GqkCBt+1MJSG6o5/s8+ytHMvDZXsJgUEWLk12UnLd7HYKac4BYU5i/Ron1Cw==", ++ "engines": { ++ "node": "^14 || ^16 || >=18" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/csstools" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.4", ++ "postcss-selector-parser": "^6.0.10" ++ } ++ }, ++ "node_modules/@discoveryjs/json-ext": { ++ "version": "0.5.7", ++ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", ++ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", ++ "dev": true, ++ "engines": { ++ "node": ">=10.0.0" ++ } ++ }, ++ "node_modules/@gar/promisify": { ++ "version": "1.1.3", ++ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", ++ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==" ++ }, ++ "node_modules/@jridgewell/gen-mapping": { ++ "version": "0.3.2", ++ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", ++ "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", ++ "dependencies": { ++ "@jridgewell/set-array": "^1.0.1", ++ "@jridgewell/sourcemap-codec": "^1.4.10", ++ "@jridgewell/trace-mapping": "^0.3.9" ++ }, ++ "engines": { ++ "node": ">=6.0.0" ++ } ++ }, ++ "node_modules/@jridgewell/resolve-uri": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz", ++ "integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==", ++ "engines": { ++ "node": ">=6.0.0" ++ } ++ }, ++ "node_modules/@jridgewell/set-array": { ++ "version": "1.1.2", ++ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", ++ "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", ++ "engines": { ++ "node": ">=6.0.0" ++ } ++ }, ++ "node_modules/@jridgewell/source-map": { ++ "version": "0.3.2", ++ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.2.tgz", ++ "integrity": "sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==", ++ "dependencies": { ++ "@jridgewell/gen-mapping": "^0.3.0", ++ "@jridgewell/trace-mapping": "^0.3.9" ++ } ++ }, ++ "node_modules/@jridgewell/sourcemap-codec": { ++ "version": "1.4.14", ++ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz", ++ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==" ++ }, ++ "node_modules/@jridgewell/trace-mapping": { ++ "version": "0.3.17", ++ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz", ++ "integrity": "sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==", ++ "dependencies": { ++ "@jridgewell/resolve-uri": "3.1.0", ++ "@jridgewell/sourcemap-codec": "1.4.14" ++ } ++ }, ++ "node_modules/@nodelib/fs.scandir": { ++ "version": "2.1.5", ++ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", ++ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", ++ "dependencies": { ++ "@nodelib/fs.stat": "2.0.5", ++ "run-parallel": "^1.1.9" ++ }, ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/@nodelib/fs.stat": { ++ "version": "2.0.5", ++ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", ++ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/@nodelib/fs.walk": { ++ "version": "1.2.8", ++ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", ++ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", ++ "dependencies": { ++ "@nodelib/fs.scandir": "2.1.5", ++ "fastq": "^1.6.0" ++ }, ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/@npmcli/fs": { ++ "version": "1.1.1", ++ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", ++ "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", ++ "dependencies": { ++ "@gar/promisify": "^1.0.1", ++ "semver": "^7.3.5" ++ } ++ }, ++ "node_modules/@npmcli/move-file": { ++ "version": "1.1.2", ++ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", ++ "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", ++ "deprecated": "This functionality has been moved to @npmcli/fs", ++ "dependencies": { ++ "mkdirp": "^1.0.4", ++ "rimraf": "^3.0.2" ++ }, ++ "engines": { ++ "node": ">=10" ++ } ++ }, ++ "node_modules/@trysound/sax": { ++ "version": "0.2.0", ++ "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", ++ "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", ++ "engines": { ++ "node": ">=10.13.0" ++ } ++ }, ++ "node_modules/@types/eslint": { ++ "version": "8.21.0", ++ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.21.0.tgz", ++ "integrity": "sha512-35EhHNOXgxnUgh4XCJsGhE7zdlDhYDN/aMG6UbkByCFFNgQ7b3U+uVoqBpicFydR8JEfgdjCF7SJ7MiJfzuiTA==", ++ "dependencies": { ++ "@types/estree": "*", ++ "@types/json-schema": "*" ++ } ++ }, ++ "node_modules/@types/eslint-scope": { ++ "version": "3.7.4", ++ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.4.tgz", ++ "integrity": "sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA==", ++ "dependencies": { ++ "@types/eslint": "*", ++ "@types/estree": "*" ++ } ++ }, ++ "node_modules/@types/estree": { ++ "version": "0.0.51", ++ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.51.tgz", ++ "integrity": "sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ==" ++ }, ++ "node_modules/@types/glob": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", ++ "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", ++ "dependencies": { ++ "@types/minimatch": "*", ++ "@types/node": "*" ++ } ++ }, ++ "node_modules/@types/json-schema": { ++ "version": "7.0.11", ++ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", ++ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" ++ }, ++ "node_modules/@types/minimatch": { ++ "version": "5.1.2", ++ "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", ++ "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==" ++ }, ++ "node_modules/@types/node": { ++ "version": "18.13.0", ++ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.13.0.tgz", ++ "integrity": "sha512-gC3TazRzGoOnoKAhUx+Q0t8S9Tzs74z7m0ipwGpSqQrleP14hKxP4/JUeEQcD3W1/aIpnWl8pHowI7WokuZpXg==" ++ }, ++ "node_modules/@types/parse-json": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", ++ "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==" ++ }, ++ "node_modules/@webassemblyjs/ast": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.1.tgz", ++ "integrity": "sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw==", ++ "dependencies": { ++ "@webassemblyjs/helper-numbers": "1.11.1", ++ "@webassemblyjs/helper-wasm-bytecode": "1.11.1" ++ } ++ }, ++ "node_modules/@webassemblyjs/floating-point-hex-parser": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz", ++ "integrity": "sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ==" ++ }, ++ "node_modules/@webassemblyjs/helper-api-error": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz", ++ "integrity": "sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg==" ++ }, ++ "node_modules/@webassemblyjs/helper-buffer": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz", ++ "integrity": "sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA==" ++ }, ++ "node_modules/@webassemblyjs/helper-numbers": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz", ++ "integrity": "sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ==", ++ "dependencies": { ++ "@webassemblyjs/floating-point-hex-parser": "1.11.1", ++ "@webassemblyjs/helper-api-error": "1.11.1", ++ "@xtuc/long": "4.2.2" ++ } ++ }, ++ "node_modules/@webassemblyjs/helper-wasm-bytecode": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz", ++ "integrity": "sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q==" ++ }, ++ "node_modules/@webassemblyjs/helper-wasm-section": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz", ++ "integrity": "sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg==", ++ "dependencies": { ++ "@webassemblyjs/ast": "1.11.1", ++ "@webassemblyjs/helper-buffer": "1.11.1", ++ "@webassemblyjs/helper-wasm-bytecode": "1.11.1", ++ "@webassemblyjs/wasm-gen": "1.11.1" ++ } ++ }, ++ "node_modules/@webassemblyjs/ieee754": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz", ++ "integrity": "sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ==", ++ "dependencies": { ++ "@xtuc/ieee754": "^1.2.0" ++ } ++ }, ++ "node_modules/@webassemblyjs/leb128": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.1.tgz", ++ "integrity": "sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw==", ++ "dependencies": { ++ "@xtuc/long": "4.2.2" ++ } ++ }, ++ "node_modules/@webassemblyjs/utf8": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.1.tgz", ++ "integrity": "sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ==" ++ }, ++ "node_modules/@webassemblyjs/wasm-edit": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz", ++ "integrity": "sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA==", ++ "dependencies": { ++ "@webassemblyjs/ast": "1.11.1", ++ "@webassemblyjs/helper-buffer": "1.11.1", ++ "@webassemblyjs/helper-wasm-bytecode": "1.11.1", ++ "@webassemblyjs/helper-wasm-section": "1.11.1", ++ "@webassemblyjs/wasm-gen": "1.11.1", ++ "@webassemblyjs/wasm-opt": "1.11.1", ++ "@webassemblyjs/wasm-parser": "1.11.1", ++ "@webassemblyjs/wast-printer": "1.11.1" ++ } ++ }, ++ "node_modules/@webassemblyjs/wasm-gen": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz", ++ "integrity": "sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA==", ++ "dependencies": { ++ "@webassemblyjs/ast": "1.11.1", ++ "@webassemblyjs/helper-wasm-bytecode": "1.11.1", ++ "@webassemblyjs/ieee754": "1.11.1", ++ "@webassemblyjs/leb128": "1.11.1", ++ "@webassemblyjs/utf8": "1.11.1" ++ } ++ }, ++ "node_modules/@webassemblyjs/wasm-opt": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz", ++ "integrity": "sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw==", ++ "dependencies": { ++ "@webassemblyjs/ast": "1.11.1", ++ "@webassemblyjs/helper-buffer": "1.11.1", ++ "@webassemblyjs/wasm-gen": "1.11.1", ++ "@webassemblyjs/wasm-parser": "1.11.1" ++ } ++ }, ++ "node_modules/@webassemblyjs/wasm-parser": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz", ++ "integrity": "sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA==", ++ "dependencies": { ++ "@webassemblyjs/ast": "1.11.1", ++ "@webassemblyjs/helper-api-error": "1.11.1", ++ "@webassemblyjs/helper-wasm-bytecode": "1.11.1", ++ "@webassemblyjs/ieee754": "1.11.1", ++ "@webassemblyjs/leb128": "1.11.1", ++ "@webassemblyjs/utf8": "1.11.1" ++ } ++ }, ++ "node_modules/@webassemblyjs/wast-printer": { ++ "version": "1.11.1", ++ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz", ++ "integrity": "sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg==", ++ "dependencies": { ++ "@webassemblyjs/ast": "1.11.1", ++ "@xtuc/long": "4.2.2" ++ } ++ }, ++ "node_modules/@webpack-cli/configtest": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.0.1.tgz", ++ "integrity": "sha512-njsdJXJSiS2iNbQVS0eT8A/KPnmyH4pv1APj2K0d1wrZcBLw+yppxOy4CGqa0OxDJkzfL/XELDhD8rocnIwB5A==", ++ "dev": true, ++ "engines": { ++ "node": ">=14.15.0" ++ }, ++ "peerDependencies": { ++ "webpack": "5.x.x", ++ "webpack-cli": "5.x.x" ++ } ++ }, ++ "node_modules/@webpack-cli/info": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.1.tgz", ++ "integrity": "sha512-fE1UEWTwsAxRhrJNikE7v4EotYflkEhBL7EbajfkPlf6E37/2QshOy/D48Mw8G5XMFlQtS6YV42vtbG9zBpIQA==", ++ "dev": true, ++ "engines": { ++ "node": ">=14.15.0" ++ }, ++ "peerDependencies": { ++ "webpack": "5.x.x", ++ "webpack-cli": "5.x.x" ++ } ++ }, ++ "node_modules/@webpack-cli/serve": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.1.tgz", ++ "integrity": "sha512-0G7tNyS+yW8TdgHwZKlDWYXFA6OJQnoLCQvYKkQP0Q2X205PSQ6RNUj0M+1OB/9gRQaUZ/ccYfaxd0nhaWKfjw==", ++ "dev": true, ++ "engines": { ++ "node": ">=14.15.0" ++ }, ++ "peerDependencies": { ++ "webpack": "5.x.x", ++ "webpack-cli": "5.x.x" ++ }, ++ "peerDependenciesMeta": { ++ "webpack-dev-server": { ++ "optional": true ++ } ++ } ++ }, ++ "node_modules/@xtuc/ieee754": { ++ "version": "1.2.0", ++ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", ++ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" ++ }, ++ "node_modules/@xtuc/long": { ++ "version": "4.2.2", ++ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", ++ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" ++ }, ++ "node_modules/acorn": { ++ "version": "8.8.2", ++ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.8.2.tgz", ++ "integrity": "sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==", ++ "bin": { ++ "acorn": "bin/acorn" ++ }, ++ "engines": { ++ "node": ">=0.4.0" ++ } ++ }, ++ "node_modules/acorn-import-assertions": { ++ "version": "1.8.0", ++ "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz", ++ "integrity": "sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==", ++ "peerDependencies": { ++ "acorn": "^8" ++ } ++ }, ++ "node_modules/aggregate-error": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", ++ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", ++ "dependencies": { ++ "clean-stack": "^2.0.0", ++ "indent-string": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/ajv": { ++ "version": "6.12.6", ++ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", ++ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", ++ "dependencies": { ++ "fast-deep-equal": "^3.1.1", ++ "fast-json-stable-stringify": "^2.0.0", ++ "json-schema-traverse": "^0.4.1", ++ "uri-js": "^4.2.2" ++ }, ++ "funding": { ++ "type": "github", ++ "url": "https://github.com/sponsors/epoberezkin" ++ } ++ }, ++ "node_modules/ajv-formats": { ++ "version": "2.1.1", ++ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", ++ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", ++ "dependencies": { ++ "ajv": "^8.0.0" ++ }, ++ "peerDependencies": { ++ "ajv": "^8.0.0" ++ }, ++ "peerDependenciesMeta": { ++ "ajv": { ++ "optional": true ++ } ++ } ++ }, ++ "node_modules/ajv-formats/node_modules/ajv": { ++ "version": "8.12.0", ++ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", ++ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", ++ "dependencies": { ++ "fast-deep-equal": "^3.1.1", ++ "json-schema-traverse": "^1.0.0", ++ "require-from-string": "^2.0.2", ++ "uri-js": "^4.2.2" ++ }, ++ "funding": { ++ "type": "github", ++ "url": "https://github.com/sponsors/epoberezkin" ++ } ++ }, ++ "node_modules/ajv-formats/node_modules/json-schema-traverse": { ++ "version": "1.0.0", ++ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", ++ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" ++ }, ++ "node_modules/ajv-keywords": { ++ "version": "3.5.2", ++ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", ++ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", ++ "peerDependencies": { ++ "ajv": "^6.9.1" ++ } ++ }, ++ "node_modules/ansi-styles": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", ++ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", ++ "dependencies": { ++ "color-convert": "^2.0.1" ++ }, ++ "engines": { ++ "node": ">=8" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/ansi-styles?sponsor=1" ++ } ++ }, ++ "node_modules/anymatch": { ++ "version": "3.1.3", ++ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", ++ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", ++ "dependencies": { ++ "normalize-path": "^3.0.0", ++ "picomatch": "^2.0.4" ++ }, ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/array-union": { ++ "version": "2.1.0", ++ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", ++ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/balanced-match": { ++ "version": "1.0.2", ++ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", ++ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" ++ }, ++ "node_modules/big.js": { ++ "version": "5.2.2", ++ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", ++ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", ++ "engines": { ++ "node": "*" ++ } ++ }, ++ "node_modules/binary-extensions": { ++ "version": "2.2.0", ++ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", ++ "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/boolbase": { ++ "version": "1.0.0", ++ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", ++ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" ++ }, ++ "node_modules/brace-expansion": { ++ "version": "1.1.11", ++ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", ++ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", ++ "dependencies": { ++ "balanced-match": "^1.0.0", ++ "concat-map": "0.0.1" ++ } ++ }, ++ "node_modules/braces": { ++ "version": "3.0.2", ++ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", ++ "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", ++ "dependencies": { ++ "fill-range": "^7.0.1" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/browserslist": { ++ "version": "4.21.5", ++ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.21.5.tgz", ++ "integrity": "sha512-tUkiguQGW7S3IhB7N+c2MV/HZPSCPAAiYBZXLsBhFB/PCy6ZKKsZrmBayHV9fdGV/ARIfJ14NkxKzRDjvp7L6w==", ++ "funding": [ ++ { ++ "type": "opencollective", ++ "url": "https://opencollective.com/browserslist" ++ }, ++ { ++ "type": "tidelift", ++ "url": "https://tidelift.com/funding/github/npm/browserslist" ++ } ++ ], ++ "dependencies": { ++ "caniuse-lite": "^1.0.30001449", ++ "electron-to-chromium": "^1.4.284", ++ "node-releases": "^2.0.8", ++ "update-browserslist-db": "^1.0.10" ++ }, ++ "bin": { ++ "browserslist": "cli.js" ++ }, ++ "engines": { ++ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" ++ } ++ }, ++ "node_modules/buffer-from": { ++ "version": "1.1.2", ++ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", ++ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" ++ }, ++ "node_modules/cacache": { ++ "version": "15.3.0", ++ "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", ++ "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", ++ "dependencies": { ++ "@npmcli/fs": "^1.0.0", ++ "@npmcli/move-file": "^1.0.1", ++ "chownr": "^2.0.0", ++ "fs-minipass": "^2.0.0", ++ "glob": "^7.1.4", ++ "infer-owner": "^1.0.4", ++ "lru-cache": "^6.0.0", ++ "minipass": "^3.1.1", ++ "minipass-collect": "^1.0.2", ++ "minipass-flush": "^1.0.5", ++ "minipass-pipeline": "^1.2.2", ++ "mkdirp": "^1.0.3", ++ "p-map": "^4.0.0", ++ "promise-inflight": "^1.0.1", ++ "rimraf": "^3.0.2", ++ "ssri": "^8.0.1", ++ "tar": "^6.0.2", ++ "unique-filename": "^1.1.1" ++ }, ++ "engines": { ++ "node": ">= 10" ++ } ++ }, ++ "node_modules/cacache/node_modules/p-map": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", ++ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", ++ "dependencies": { ++ "aggregate-error": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ }, ++ "node_modules/callsites": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", ++ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/camelcase-css": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", ++ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", ++ "engines": { ++ "node": ">= 6" ++ } ++ }, ++ "node_modules/caniuse-api": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", ++ "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", ++ "dependencies": { ++ "browserslist": "^4.0.0", ++ "caniuse-lite": "^1.0.0", ++ "lodash.memoize": "^4.1.2", ++ "lodash.uniq": "^4.5.0" ++ } ++ }, ++ "node_modules/caniuse-lite": { ++ "version": "1.0.30001451", ++ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001451.tgz", ++ "integrity": "sha512-XY7UbUpGRatZzoRft//5xOa69/1iGJRBlrieH6QYrkKLIFn3m7OVEJ81dSrKoy2BnKsdbX5cLrOispZNYo9v2w==", ++ "funding": [ ++ { ++ "type": "opencollective", ++ "url": "https://opencollective.com/browserslist" ++ }, ++ { ++ "type": "tidelift", ++ "url": "https://tidelift.com/funding/github/npm/caniuse-lite" ++ } ++ ] ++ }, ++ "node_modules/chalk": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", ++ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", ++ "dependencies": { ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/chokidar": { ++ "version": "3.5.3", ++ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", ++ "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", ++ "funding": [ ++ { ++ "type": "individual", ++ "url": "https://paulmillr.com/funding/" ++ } ++ ], ++ "dependencies": { ++ "anymatch": "~3.1.2", ++ "braces": "~3.0.2", ++ "glob-parent": "~5.1.2", ++ "is-binary-path": "~2.1.0", ++ "is-glob": "~4.0.1", ++ "normalize-path": "~3.0.0", ++ "readdirp": "~3.6.0" ++ }, ++ "engines": { ++ "node": ">= 8.10.0" ++ }, ++ "optionalDependencies": { ++ "fsevents": "~2.3.2" ++ } ++ }, ++ "node_modules/chownr": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", ++ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", ++ "engines": { ++ "node": ">=10" ++ } ++ }, ++ "node_modules/chrome-trace-event": { ++ "version": "1.0.3", ++ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz", ++ "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==", ++ "engines": { ++ "node": ">=6.0" ++ } ++ }, ++ "node_modules/ckeditor5": { ++ "version": "35.4.0", ++ "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-35.4.0.tgz", ++ "integrity": "sha512-vBEQVkFCbjYmEPVkyWsOqU44DOovUio6xBuCwroe4TuJLplqeRasCjFwB0DPknXQU8U0iM3Lh/QSKRyN92pw3Q==", ++ "dependencies": { ++ "@ckeditor/ckeditor5-clipboard": "^35.4.0", ++ "@ckeditor/ckeditor5-core": "^35.4.0", ++ "@ckeditor/ckeditor5-engine": "^35.4.0", ++ "@ckeditor/ckeditor5-enter": "^35.4.0", ++ "@ckeditor/ckeditor5-paragraph": "^35.4.0", ++ "@ckeditor/ckeditor5-select-all": "^35.4.0", ++ "@ckeditor/ckeditor5-typing": "^35.4.0", ++ "@ckeditor/ckeditor5-ui": "^35.4.0", ++ "@ckeditor/ckeditor5-undo": "^35.4.0", ++ "@ckeditor/ckeditor5-upload": "^35.4.0", ++ "@ckeditor/ckeditor5-utils": "^35.4.0", ++ "@ckeditor/ckeditor5-widget": "^35.4.0" ++ }, ++ "engines": { ++ "node": ">=14.0.0", ++ "npm": ">=5.7.1" ++ } ++ }, ++ "node_modules/clean-stack": { ++ "version": "2.2.0", ++ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", ++ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/cli-cursor": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", ++ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", ++ "dependencies": { ++ "restore-cursor": "^3.1.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/cli-spinners": { ++ "version": "2.7.0", ++ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.7.0.tgz", ++ "integrity": "sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw==", ++ "engines": { ++ "node": ">=6" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ }, ++ "node_modules/clone-deep": { ++ "version": "4.0.1", ++ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", ++ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", ++ "dev": true, ++ "dependencies": { ++ "is-plain-object": "^2.0.4", ++ "kind-of": "^6.0.2", ++ "shallow-clone": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/color-convert": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", ++ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", ++ "dependencies": { ++ "color-name": "~1.1.4" ++ }, ++ "engines": { ++ "node": ">=7.0.0" ++ } ++ }, ++ "node_modules/color-name": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", ++ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" ++ }, ++ "node_modules/colord": { ++ "version": "2.9.3", ++ "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", ++ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" ++ }, ++ "node_modules/colorette": { ++ "version": "2.0.19", ++ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", ++ "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", ++ "dev": true ++ }, ++ "node_modules/commander": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", ++ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", ++ "engines": { ++ "node": ">= 10" ++ } ++ }, ++ "node_modules/commondir": { ++ "version": "1.0.1", ++ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", ++ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" ++ }, ++ "node_modules/concat-map": { ++ "version": "0.0.1", ++ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", ++ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" ++ }, ++ "node_modules/cosmiconfig": { ++ "version": "7.1.0", ++ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", ++ "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", ++ "dependencies": { ++ "@types/parse-json": "^4.0.0", ++ "import-fresh": "^3.2.1", ++ "parse-json": "^5.0.0", ++ "path-type": "^4.0.0", ++ "yaml": "^1.10.0" ++ }, ++ "engines": { ++ "node": ">=10" ++ } ++ }, ++ "node_modules/cross-spawn": { ++ "version": "7.0.3", ++ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", ++ "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", ++ "dev": true, ++ "dependencies": { ++ "path-key": "^3.1.0", ++ "shebang-command": "^2.0.0", ++ "which": "^2.0.1" ++ }, ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/css-declaration-sorter": { ++ "version": "6.3.1", ++ "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz", ++ "integrity": "sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w==", ++ "engines": { ++ "node": "^10 || ^12 || >=14" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.0.9" ++ } ++ }, ++ "node_modules/css-loader": { ++ "version": "5.2.7", ++ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", ++ "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", ++ "dependencies": { ++ "icss-utils": "^5.1.0", ++ "loader-utils": "^2.0.0", ++ "postcss": "^8.2.15", ++ "postcss-modules-extract-imports": "^3.0.0", ++ "postcss-modules-local-by-default": "^4.0.0", ++ "postcss-modules-scope": "^3.0.0", ++ "postcss-modules-values": "^4.0.0", ++ "postcss-value-parser": "^4.1.0", ++ "schema-utils": "^3.0.0", ++ "semver": "^7.3.5" ++ }, ++ "engines": { ++ "node": ">= 10.13.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/webpack" ++ }, ++ "peerDependencies": { ++ "webpack": "^4.27.0 || ^5.0.0" ++ } ++ }, ++ "node_modules/css-select": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", ++ "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", ++ "dependencies": { ++ "boolbase": "^1.0.0", ++ "css-what": "^6.0.1", ++ "domhandler": "^4.3.1", ++ "domutils": "^2.8.0", ++ "nth-check": "^2.0.1" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/fb55" ++ } ++ }, ++ "node_modules/css-tree": { ++ "version": "1.1.3", ++ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", ++ "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", ++ "dependencies": { ++ "mdn-data": "2.0.14", ++ "source-map": "^0.6.1" ++ }, ++ "engines": { ++ "node": ">=8.0.0" ++ } ++ }, ++ "node_modules/css-what": { ++ "version": "6.1.0", ++ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", ++ "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", ++ "engines": { ++ "node": ">= 6" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/fb55" ++ } ++ }, ++ "node_modules/cssesc": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", ++ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", ++ "bin": { ++ "cssesc": "bin/cssesc" ++ }, ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/cssnano": { ++ "version": "5.1.14", ++ "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.14.tgz", ++ "integrity": "sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw==", ++ "dependencies": { ++ "cssnano-preset-default": "^5.2.13", ++ "lilconfig": "^2.0.3", ++ "yaml": "^1.10.2" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/cssnano" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/cssnano-preset-default": { ++ "version": "5.2.13", ++ "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz", ++ "integrity": "sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ==", ++ "dependencies": { ++ "css-declaration-sorter": "^6.3.1", ++ "cssnano-utils": "^3.1.0", ++ "postcss-calc": "^8.2.3", ++ "postcss-colormin": "^5.3.0", ++ "postcss-convert-values": "^5.1.3", ++ "postcss-discard-comments": "^5.1.2", ++ "postcss-discard-duplicates": "^5.1.0", ++ "postcss-discard-empty": "^5.1.1", ++ "postcss-discard-overridden": "^5.1.0", ++ "postcss-merge-longhand": "^5.1.7", ++ "postcss-merge-rules": "^5.1.3", ++ "postcss-minify-font-values": "^5.1.0", ++ "postcss-minify-gradients": "^5.1.1", ++ "postcss-minify-params": "^5.1.4", ++ "postcss-minify-selectors": "^5.2.1", ++ "postcss-normalize-charset": "^5.1.0", ++ "postcss-normalize-display-values": "^5.1.0", ++ "postcss-normalize-positions": "^5.1.1", ++ "postcss-normalize-repeat-style": "^5.1.1", ++ "postcss-normalize-string": "^5.1.0", ++ "postcss-normalize-timing-functions": "^5.1.0", ++ "postcss-normalize-unicode": "^5.1.1", ++ "postcss-normalize-url": "^5.1.0", ++ "postcss-normalize-whitespace": "^5.1.1", ++ "postcss-ordered-values": "^5.1.3", ++ "postcss-reduce-initial": "^5.1.1", ++ "postcss-reduce-transforms": "^5.1.0", ++ "postcss-svgo": "^5.1.0", ++ "postcss-unique-selectors": "^5.1.1" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/cssnano-utils": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", ++ "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/csso": { ++ "version": "4.2.0", ++ "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", ++ "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", ++ "dependencies": { ++ "css-tree": "^1.1.2" ++ }, ++ "engines": { ++ "node": ">=8.0.0" ++ } ++ }, ++ "node_modules/debug": { ++ "version": "4.3.4", ++ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", ++ "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", ++ "dependencies": { ++ "ms": "2.1.2" ++ }, ++ "engines": { ++ "node": ">=6.0" ++ }, ++ "peerDependenciesMeta": { ++ "supports-color": { ++ "optional": true ++ } ++ } ++ }, ++ "node_modules/del": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/del/-/del-5.1.0.tgz", ++ "integrity": "sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==", ++ "dependencies": { ++ "globby": "^10.0.1", ++ "graceful-fs": "^4.2.2", ++ "is-glob": "^4.0.1", ++ "is-path-cwd": "^2.2.0", ++ "is-path-inside": "^3.0.1", ++ "p-map": "^3.0.0", ++ "rimraf": "^3.0.0", ++ "slash": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/dir-glob": { ++ "version": "3.0.1", ++ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", ++ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", ++ "dependencies": { ++ "path-type": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/dom-serializer": { ++ "version": "1.4.1", ++ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", ++ "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", ++ "dependencies": { ++ "domelementtype": "^2.0.1", ++ "domhandler": "^4.2.0", ++ "entities": "^2.0.0" ++ }, ++ "funding": { ++ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" ++ } ++ }, ++ "node_modules/domelementtype": { ++ "version": "2.3.0", ++ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", ++ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", ++ "funding": [ ++ { ++ "type": "github", ++ "url": "https://github.com/sponsors/fb55" ++ } ++ ] ++ }, ++ "node_modules/domhandler": { ++ "version": "4.3.1", ++ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", ++ "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", ++ "dependencies": { ++ "domelementtype": "^2.2.0" ++ }, ++ "engines": { ++ "node": ">= 4" ++ }, ++ "funding": { ++ "url": "https://github.com/fb55/domhandler?sponsor=1" ++ } ++ }, ++ "node_modules/domutils": { ++ "version": "2.8.0", ++ "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", ++ "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", ++ "dependencies": { ++ "dom-serializer": "^1.0.1", ++ "domelementtype": "^2.2.0", ++ "domhandler": "^4.2.0" ++ }, ++ "funding": { ++ "url": "https://github.com/fb55/domutils?sponsor=1" ++ } ++ }, ++ "node_modules/electron-to-chromium": { ++ "version": "1.4.295", ++ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.295.tgz", ++ "integrity": "sha512-lEO94zqf1bDA3aepxwnWoHUjA8sZ+2owgcSZjYQy0+uOSEclJX0VieZC+r+wLpSxUHRd6gG32znTWmr+5iGzFw==" ++ }, ++ "node_modules/emojis-list": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", ++ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", ++ "engines": { ++ "node": ">= 4" ++ } ++ }, ++ "node_modules/enhanced-resolve": { ++ "version": "5.12.0", ++ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.12.0.tgz", ++ "integrity": "sha512-QHTXI/sZQmko1cbDoNAa3mJ5qhWUUNAq3vR0/YiD379fWQrcfuoX1+HW2S0MTt7XmoPLapdaDKUtelUSPic7hQ==", ++ "dependencies": { ++ "graceful-fs": "^4.2.4", ++ "tapable": "^2.2.0" ++ }, ++ "engines": { ++ "node": ">=10.13.0" ++ } ++ }, ++ "node_modules/entities": { ++ "version": "2.2.0", ++ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", ++ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", ++ "funding": { ++ "url": "https://github.com/fb55/entities?sponsor=1" ++ } ++ }, ++ "node_modules/envinfo": { ++ "version": "7.8.1", ++ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.8.1.tgz", ++ "integrity": "sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw==", ++ "dev": true, ++ "bin": { ++ "envinfo": "dist/cli.js" ++ }, ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/error-ex": { ++ "version": "1.3.2", ++ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", ++ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", ++ "dependencies": { ++ "is-arrayish": "^0.2.1" ++ } ++ }, ++ "node_modules/es-module-lexer": { ++ "version": "0.9.3", ++ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-0.9.3.tgz", ++ "integrity": "sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ==" ++ }, ++ "node_modules/escalade": { ++ "version": "3.1.1", ++ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", ++ "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/escape-string-regexp": { ++ "version": "1.0.5", ++ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", ++ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", ++ "engines": { ++ "node": ">=0.8.0" ++ } ++ }, ++ "node_modules/eslint-scope": { ++ "version": "5.1.1", ++ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", ++ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", ++ "dependencies": { ++ "esrecurse": "^4.3.0", ++ "estraverse": "^4.1.1" ++ }, ++ "engines": { ++ "node": ">=8.0.0" ++ } ++ }, ++ "node_modules/esrecurse": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", ++ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", ++ "dependencies": { ++ "estraverse": "^5.2.0" ++ }, ++ "engines": { ++ "node": ">=4.0" ++ } ++ }, ++ "node_modules/esrecurse/node_modules/estraverse": { ++ "version": "5.3.0", ++ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", ++ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", ++ "engines": { ++ "node": ">=4.0" ++ } ++ }, ++ "node_modules/estraverse": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", ++ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", ++ "engines": { ++ "node": ">=4.0" ++ } ++ }, ++ "node_modules/events": { ++ "version": "3.3.0", ++ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", ++ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", ++ "engines": { ++ "node": ">=0.8.x" ++ } ++ }, ++ "node_modules/fast-deep-equal": { ++ "version": "3.1.3", ++ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", ++ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" ++ }, ++ "node_modules/fast-glob": { ++ "version": "3.2.12", ++ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.12.tgz", ++ "integrity": "sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==", ++ "dependencies": { ++ "@nodelib/fs.stat": "^2.0.2", ++ "@nodelib/fs.walk": "^1.2.3", ++ "glob-parent": "^5.1.2", ++ "merge2": "^1.3.0", ++ "micromatch": "^4.0.4" ++ }, ++ "engines": { ++ "node": ">=8.6.0" ++ } ++ }, ++ "node_modules/fast-json-stable-stringify": { ++ "version": "2.1.0", ++ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", ++ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==" ++ }, ++ "node_modules/fastest-levenshtein": { ++ "version": "1.0.16", ++ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", ++ "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", ++ "dev": true, ++ "engines": { ++ "node": ">= 4.9.1" ++ } ++ }, ++ "node_modules/fastq": { ++ "version": "1.15.0", ++ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", ++ "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", ++ "dependencies": { ++ "reusify": "^1.0.4" ++ } ++ }, ++ "node_modules/fill-range": { ++ "version": "7.0.1", ++ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", ++ "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", ++ "dependencies": { ++ "to-regex-range": "^5.0.1" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/find-cache-dir": { ++ "version": "3.3.2", ++ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", ++ "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", ++ "dependencies": { ++ "commondir": "^1.0.1", ++ "make-dir": "^3.0.2", ++ "pkg-dir": "^4.1.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ }, ++ "funding": { ++ "url": "https://github.com/avajs/find-cache-dir?sponsor=1" ++ } ++ }, ++ "node_modules/find-up": { ++ "version": "4.1.0", ++ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", ++ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", ++ "dependencies": { ++ "locate-path": "^5.0.0", ++ "path-exists": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/fs-extra": { ++ "version": "8.1.0", ++ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", ++ "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", ++ "dependencies": { ++ "graceful-fs": "^4.2.0", ++ "jsonfile": "^4.0.0", ++ "universalify": "^0.1.0" ++ }, ++ "engines": { ++ "node": ">=6 <7 || >=8" ++ } ++ }, ++ "node_modules/fs-minipass": { ++ "version": "2.1.0", ++ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", ++ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", ++ "dependencies": { ++ "minipass": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/fs.realpath": { ++ "version": "1.0.0", ++ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", ++ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" ++ }, ++ "node_modules/fsevents": { ++ "version": "2.3.2", ++ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", ++ "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", ++ "hasInstallScript": true, ++ "optional": true, ++ "os": [ ++ "darwin" ++ ], ++ "engines": { ++ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" ++ } ++ }, ++ "node_modules/function-bind": { ++ "version": "1.1.1", ++ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", ++ "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" ++ }, ++ "node_modules/glob": { ++ "version": "7.2.3", ++ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", ++ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", ++ "dependencies": { ++ "fs.realpath": "^1.0.0", ++ "inflight": "^1.0.4", ++ "inherits": "2", ++ "minimatch": "^3.1.1", ++ "once": "^1.3.0", ++ "path-is-absolute": "^1.0.0" ++ }, ++ "engines": { ++ "node": "*" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/isaacs" ++ } ++ }, ++ "node_modules/glob-parent": { ++ "version": "5.1.2", ++ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", ++ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", ++ "dependencies": { ++ "is-glob": "^4.0.1" ++ }, ++ "engines": { ++ "node": ">= 6" ++ } ++ }, ++ "node_modules/glob-to-regexp": { ++ "version": "0.4.1", ++ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", ++ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==" ++ }, ++ "node_modules/globals": { ++ "version": "11.12.0", ++ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", ++ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/globby": { ++ "version": "10.0.2", ++ "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", ++ "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", ++ "dependencies": { ++ "@types/glob": "^7.1.1", ++ "array-union": "^2.1.0", ++ "dir-glob": "^3.0.1", ++ "fast-glob": "^3.0.3", ++ "glob": "^7.1.3", ++ "ignore": "^5.1.1", ++ "merge2": "^1.2.3", ++ "slash": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/graceful-fs": { ++ "version": "4.2.10", ++ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", ++ "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" ++ }, ++ "node_modules/has": { ++ "version": "1.0.3", ++ "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", ++ "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", ++ "dependencies": { ++ "function-bind": "^1.1.1" ++ }, ++ "engines": { ++ "node": ">= 0.4.0" ++ } ++ }, ++ "node_modules/has-flag": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", ++ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/icss-utils": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", ++ "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", ++ "engines": { ++ "node": "^10 || ^12 || >= 14" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.1.0" ++ } ++ }, ++ "node_modules/ignore": { ++ "version": "5.2.4", ++ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", ++ "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", ++ "engines": { ++ "node": ">= 4" ++ } ++ }, ++ "node_modules/immutable": { ++ "version": "4.2.4", ++ "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.2.4.tgz", ++ "integrity": "sha512-WDxL3Hheb1JkRN3sQkyujNlL/xRjAo3rJtaU5xeufUauG66JdMr32bLj4gF+vWl84DIA3Zxw7tiAjneYzRRw+w==" ++ }, ++ "node_modules/import-fresh": { ++ "version": "3.3.0", ++ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", ++ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", ++ "dependencies": { ++ "parent-module": "^1.0.0", ++ "resolve-from": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=6" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ }, ++ "node_modules/import-local": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.1.0.tgz", ++ "integrity": "sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==", ++ "dev": true, ++ "dependencies": { ++ "pkg-dir": "^4.2.0", ++ "resolve-cwd": "^3.0.0" ++ }, ++ "bin": { ++ "import-local-fixture": "fixtures/cli.js" ++ }, ++ "engines": { ++ "node": ">=8" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ }, ++ "node_modules/imurmurhash": { ++ "version": "0.1.4", ++ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", ++ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", ++ "engines": { ++ "node": ">=0.8.19" ++ } ++ }, ++ "node_modules/indent-string": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", ++ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/infer-owner": { ++ "version": "1.0.4", ++ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", ++ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==" ++ }, ++ "node_modules/inflight": { ++ "version": "1.0.6", ++ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", ++ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", ++ "dependencies": { ++ "once": "^1.3.0", ++ "wrappy": "1" ++ } ++ }, ++ "node_modules/inherits": { ++ "version": "2.0.4", ++ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", ++ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" ++ }, ++ "node_modules/interpret": { ++ "version": "1.4.0", ++ "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", ++ "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", ++ "engines": { ++ "node": ">= 0.10" ++ } ++ }, ++ "node_modules/is-arrayish": { ++ "version": "0.2.1", ++ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", ++ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" ++ }, ++ "node_modules/is-binary-path": { ++ "version": "2.1.0", ++ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", ++ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", ++ "dependencies": { ++ "binary-extensions": "^2.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/is-core-module": { ++ "version": "2.11.0", ++ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.11.0.tgz", ++ "integrity": "sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==", ++ "dependencies": { ++ "has": "^1.0.3" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/ljharb" ++ } ++ }, ++ "node_modules/is-extglob": { ++ "version": "2.1.1", ++ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", ++ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", ++ "engines": { ++ "node": ">=0.10.0" ++ } ++ }, ++ "node_modules/is-glob": { ++ "version": "4.0.3", ++ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", ++ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", ++ "dependencies": { ++ "is-extglob": "^2.1.1" ++ }, ++ "engines": { ++ "node": ">=0.10.0" ++ } ++ }, ++ "node_modules/is-interactive": { ++ "version": "1.0.0", ++ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", ++ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/is-number": { ++ "version": "7.0.0", ++ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", ++ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", ++ "engines": { ++ "node": ">=0.12.0" ++ } ++ }, ++ "node_modules/is-path-cwd": { ++ "version": "2.2.0", ++ "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", ++ "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/is-path-inside": { ++ "version": "3.0.3", ++ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", ++ "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/is-plain-object": { ++ "version": "2.0.4", ++ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", ++ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", ++ "dev": true, ++ "dependencies": { ++ "isobject": "^3.0.1" ++ }, ++ "engines": { ++ "node": ">=0.10.0" ++ } ++ }, ++ "node_modules/isexe": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", ++ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", ++ "dev": true ++ }, ++ "node_modules/isobject": { ++ "version": "3.0.1", ++ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", ++ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", ++ "dev": true, ++ "engines": { ++ "node": ">=0.10.0" ++ } ++ }, ++ "node_modules/javascript-stringify": { ++ "version": "1.6.0", ++ "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-1.6.0.tgz", ++ "integrity": "sha512-fnjC0up+0SjEJtgmmG+teeel68kutkvzfctO/KxE3qJlbunkJYAshgH3boU++gSBHP8z5/r0ts0qRIrHf0RTQQ==" ++ }, ++ "node_modules/jest-worker": { ++ "version": "27.5.1", ++ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", ++ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", ++ "dependencies": { ++ "@types/node": "*", ++ "merge-stream": "^2.0.0", ++ "supports-color": "^8.0.0" ++ }, ++ "engines": { ++ "node": ">= 10.13.0" ++ } ++ }, ++ "node_modules/jest-worker/node_modules/supports-color": { ++ "version": "8.1.1", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", ++ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", ++ "dependencies": { ++ "has-flag": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/supports-color?sponsor=1" ++ } ++ }, ++ "node_modules/js-tokens": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", ++ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" ++ }, ++ "node_modules/jsesc": { ++ "version": "2.5.2", ++ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", ++ "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", ++ "bin": { ++ "jsesc": "bin/jsesc" ++ }, ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/json-parse-even-better-errors": { ++ "version": "2.3.1", ++ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", ++ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==" ++ }, ++ "node_modules/json-schema-traverse": { ++ "version": "0.4.1", ++ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", ++ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==" ++ }, ++ "node_modules/json5": { ++ "version": "2.2.3", ++ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", ++ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", ++ "bin": { ++ "json5": "lib/cli.js" ++ }, ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/jsonfile": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", ++ "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", ++ "optionalDependencies": { ++ "graceful-fs": "^4.1.6" ++ } ++ }, ++ "node_modules/kind-of": { ++ "version": "6.0.3", ++ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", ++ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", ++ "dev": true, ++ "engines": { ++ "node": ">=0.10.0" ++ } ++ }, ++ "node_modules/klona": { ++ "version": "2.0.6", ++ "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", ++ "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/lilconfig": { ++ "version": "2.0.6", ++ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.6.tgz", ++ "integrity": "sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==", ++ "engines": { ++ "node": ">=10" ++ } ++ }, ++ "node_modules/lines-and-columns": { ++ "version": "1.2.4", ++ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", ++ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" ++ }, ++ "node_modules/loader-runner": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", ++ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", ++ "engines": { ++ "node": ">=6.11.5" ++ } ++ }, ++ "node_modules/loader-utils": { ++ "version": "2.0.4", ++ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", ++ "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", ++ "dependencies": { ++ "big.js": "^5.2.2", ++ "emojis-list": "^3.0.0", ++ "json5": "^2.1.2" ++ }, ++ "engines": { ++ "node": ">=8.9.0" ++ } ++ }, ++ "node_modules/locate-path": { ++ "version": "5.0.0", ++ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", ++ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", ++ "dependencies": { ++ "p-locate": "^4.1.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/lodash-es": { ++ "version": "4.17.21", ++ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", ++ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" ++ }, ++ "node_modules/lodash.memoize": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", ++ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" ++ }, ++ "node_modules/lodash.uniq": { ++ "version": "4.5.0", ++ "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", ++ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" ++ }, ++ "node_modules/lru-cache": { ++ "version": "6.0.0", ++ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", ++ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", ++ "dependencies": { ++ "yallist": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=10" ++ } ++ }, ++ "node_modules/make-dir": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", ++ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", ++ "dependencies": { ++ "semver": "^6.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ }, ++ "node_modules/make-dir/node_modules/semver": { ++ "version": "6.3.0", ++ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", ++ "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", ++ "bin": { ++ "semver": "bin/semver.js" ++ } ++ }, ++ "node_modules/mdn-data": { ++ "version": "2.0.14", ++ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", ++ "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" ++ }, ++ "node_modules/merge-stream": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", ++ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==" ++ }, ++ "node_modules/merge2": { ++ "version": "1.4.1", ++ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", ++ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/micromatch": { ++ "version": "4.0.5", ++ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", ++ "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", ++ "dependencies": { ++ "braces": "^3.0.2", ++ "picomatch": "^2.3.1" ++ }, ++ "engines": { ++ "node": ">=8.6" ++ } ++ }, ++ "node_modules/mime-db": { ++ "version": "1.52.0", ++ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", ++ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", ++ "engines": { ++ "node": ">= 0.6" ++ } ++ }, ++ "node_modules/mime-types": { ++ "version": "2.1.35", ++ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", ++ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", ++ "dependencies": { ++ "mime-db": "1.52.0" ++ }, ++ "engines": { ++ "node": ">= 0.6" ++ } ++ }, ++ "node_modules/mimic-fn": { ++ "version": "2.1.0", ++ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", ++ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/mini-css-extract-plugin": { ++ "version": "2.7.2", ++ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.7.2.tgz", ++ "integrity": "sha512-EdlUizq13o0Pd+uCp+WO/JpkLvHRVGt97RqfeGhXqAcorYo1ypJSpkV+WDT0vY/kmh/p7wRdJNJtuyK540PXDw==", ++ "dependencies": { ++ "schema-utils": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">= 12.13.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/webpack" ++ }, ++ "peerDependencies": { ++ "webpack": "^5.0.0" ++ } ++ }, ++ "node_modules/mini-css-extract-plugin/node_modules/ajv": { ++ "version": "8.12.0", ++ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", ++ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", ++ "dependencies": { ++ "fast-deep-equal": "^3.1.1", ++ "json-schema-traverse": "^1.0.0", ++ "require-from-string": "^2.0.2", ++ "uri-js": "^4.2.2" ++ }, ++ "funding": { ++ "type": "github", ++ "url": "https://github.com/sponsors/epoberezkin" ++ } ++ }, ++ "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", ++ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", ++ "dependencies": { ++ "fast-deep-equal": "^3.1.3" ++ }, ++ "peerDependencies": { ++ "ajv": "^8.8.2" ++ } ++ }, ++ "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": { ++ "version": "1.0.0", ++ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", ++ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==" ++ }, ++ "node_modules/mini-css-extract-plugin/node_modules/schema-utils": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz", ++ "integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==", ++ "dependencies": { ++ "@types/json-schema": "^7.0.9", ++ "ajv": "^8.8.0", ++ "ajv-formats": "^2.1.1", ++ "ajv-keywords": "^5.0.0" ++ }, ++ "engines": { ++ "node": ">= 12.13.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/webpack" ++ } ++ }, ++ "node_modules/minimatch": { ++ "version": "3.1.2", ++ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", ++ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", ++ "dependencies": { ++ "brace-expansion": "^1.1.7" ++ }, ++ "engines": { ++ "node": "*" ++ } ++ }, ++ "node_modules/minipass": { ++ "version": "3.3.6", ++ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", ++ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", ++ "dependencies": { ++ "yallist": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/minipass-collect": { ++ "version": "1.0.2", ++ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", ++ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", ++ "dependencies": { ++ "minipass": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/minipass-flush": { ++ "version": "1.0.5", ++ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", ++ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", ++ "dependencies": { ++ "minipass": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/minipass-pipeline": { ++ "version": "1.2.4", ++ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", ++ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", ++ "dependencies": { ++ "minipass": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/minizlib": { ++ "version": "2.1.2", ++ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", ++ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", ++ "dependencies": { ++ "minipass": "^3.0.0", ++ "yallist": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/mkdirp": { ++ "version": "1.0.4", ++ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", ++ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", ++ "bin": { ++ "mkdirp": "bin/cmd.js" ++ }, ++ "engines": { ++ "node": ">=10" ++ } ++ }, ++ "node_modules/ms": { ++ "version": "2.1.2", ++ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", ++ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" ++ }, ++ "node_modules/nanoid": { ++ "version": "3.3.4", ++ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz", ++ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==", ++ "bin": { ++ "nanoid": "bin/nanoid.cjs" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" ++ } ++ }, ++ "node_modules/neo-async": { ++ "version": "2.6.2", ++ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", ++ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" ++ }, ++ "node_modules/node-releases": { ++ "version": "2.0.10", ++ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.10.tgz", ++ "integrity": "sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==" ++ }, ++ "node_modules/normalize-path": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", ++ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", ++ "engines": { ++ "node": ">=0.10.0" ++ } ++ }, ++ "node_modules/normalize-url": { ++ "version": "6.1.0", ++ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", ++ "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ }, ++ "node_modules/nth-check": { ++ "version": "2.1.1", ++ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", ++ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", ++ "dependencies": { ++ "boolbase": "^1.0.0" ++ }, ++ "funding": { ++ "url": "https://github.com/fb55/nth-check?sponsor=1" ++ } ++ }, ++ "node_modules/once": { ++ "version": "1.4.0", ++ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", ++ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", ++ "dependencies": { ++ "wrappy": "1" ++ } ++ }, ++ "node_modules/onetime": { ++ "version": "5.1.2", ++ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", ++ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", ++ "dependencies": { ++ "mimic-fn": "^2.1.0" ++ }, ++ "engines": { ++ "node": ">=6" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ }, ++ "node_modules/p-limit": { ++ "version": "2.3.0", ++ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", ++ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", ++ "dependencies": { ++ "p-try": "^2.0.0" ++ }, ++ "engines": { ++ "node": ">=6" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ }, ++ "node_modules/p-locate": { ++ "version": "4.1.0", ++ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", ++ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", ++ "dependencies": { ++ "p-limit": "^2.2.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/p-map": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", ++ "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", ++ "dependencies": { ++ "aggregate-error": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/p-try": { ++ "version": "2.2.0", ++ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", ++ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/parent-module": { ++ "version": "1.0.1", ++ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", ++ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", ++ "dependencies": { ++ "callsites": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/parse-json": { ++ "version": "5.2.0", ++ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", ++ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", ++ "dependencies": { ++ "@babel/code-frame": "^7.0.0", ++ "error-ex": "^1.3.1", ++ "json-parse-even-better-errors": "^2.3.0", ++ "lines-and-columns": "^1.1.6" ++ }, ++ "engines": { ++ "node": ">=8" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ }, ++ "node_modules/path-exists": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", ++ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/path-is-absolute": { ++ "version": "1.0.1", ++ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", ++ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", ++ "engines": { ++ "node": ">=0.10.0" ++ } ++ }, ++ "node_modules/path-key": { ++ "version": "3.1.1", ++ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", ++ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", ++ "dev": true, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/path-parse": { ++ "version": "1.0.7", ++ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", ++ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" ++ }, ++ "node_modules/path-type": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", ++ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/picocolors": { ++ "version": "1.0.0", ++ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", ++ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" ++ }, ++ "node_modules/picomatch": { ++ "version": "2.3.1", ++ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", ++ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", ++ "engines": { ++ "node": ">=8.6" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/jonschlinkert" ++ } ++ }, ++ "node_modules/pify": { ++ "version": "2.3.0", ++ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", ++ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", ++ "engines": { ++ "node": ">=0.10.0" ++ } ++ }, ++ "node_modules/pkg-dir": { ++ "version": "4.2.0", ++ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", ++ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", ++ "dependencies": { ++ "find-up": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/pofile": { ++ "version": "1.1.4", ++ "resolved": "https://registry.npmjs.org/pofile/-/pofile-1.1.4.tgz", ++ "integrity": "sha512-r6Q21sKsY1AjTVVjOuU02VYKVNQGJNQHjTIvs4dEbeuuYfxgYk/DGD2mqqq4RDaVkwdSq0VEtmQUOPe/wH8X3g==" ++ }, ++ "node_modules/postcss": { ++ "version": "8.4.21", ++ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz", ++ "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==", ++ "funding": [ ++ { ++ "type": "opencollective", ++ "url": "https://opencollective.com/postcss/" ++ }, ++ { ++ "type": "tidelift", ++ "url": "https://tidelift.com/funding/github/npm/postcss" ++ } ++ ], ++ "dependencies": { ++ "nanoid": "^3.3.4", ++ "picocolors": "^1.0.0", ++ "source-map-js": "^1.0.2" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14" ++ } ++ }, ++ "node_modules/postcss-calc": { ++ "version": "8.2.4", ++ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", ++ "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", ++ "dependencies": { ++ "postcss-selector-parser": "^6.0.9", ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.2" ++ } ++ }, ++ "node_modules/postcss-colormin": { ++ "version": "5.3.0", ++ "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.0.tgz", ++ "integrity": "sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg==", ++ "dependencies": { ++ "browserslist": "^4.16.6", ++ "caniuse-api": "^3.0.0", ++ "colord": "^2.9.1", ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-convert-values": { ++ "version": "5.1.3", ++ "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", ++ "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", ++ "dependencies": { ++ "browserslist": "^4.21.4", ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-discard-comments": { ++ "version": "5.1.2", ++ "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", ++ "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-discard-duplicates": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", ++ "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-discard-empty": { ++ "version": "5.1.1", ++ "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", ++ "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-discard-overridden": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", ++ "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-import": { ++ "version": "14.1.0", ++ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", ++ "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", ++ "dependencies": { ++ "postcss-value-parser": "^4.0.0", ++ "read-cache": "^1.0.0", ++ "resolve": "^1.1.7" ++ }, ++ "engines": { ++ "node": ">=10.0.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.0.0" ++ } ++ }, ++ "node_modules/postcss-js": { ++ "version": "4.0.1", ++ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", ++ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", ++ "dependencies": { ++ "camelcase-css": "^2.0.1" ++ }, ++ "engines": { ++ "node": "^12 || ^14 || >= 16" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/postcss/" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.4.21" ++ } ++ }, ++ "node_modules/postcss-loader": { ++ "version": "4.3.0", ++ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", ++ "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", ++ "dependencies": { ++ "cosmiconfig": "^7.0.0", ++ "klona": "^2.0.4", ++ "loader-utils": "^2.0.0", ++ "schema-utils": "^3.0.0", ++ "semver": "^7.3.4" ++ }, ++ "engines": { ++ "node": ">= 10.13.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/webpack" ++ }, ++ "peerDependencies": { ++ "postcss": "^7.0.0 || ^8.0.1", ++ "webpack": "^4.0.0 || ^5.0.0" ++ } ++ }, ++ "node_modules/postcss-merge-longhand": { ++ "version": "5.1.7", ++ "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", ++ "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", ++ "dependencies": { ++ "postcss-value-parser": "^4.2.0", ++ "stylehacks": "^5.1.1" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-merge-rules": { ++ "version": "5.1.3", ++ "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz", ++ "integrity": "sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA==", ++ "dependencies": { ++ "browserslist": "^4.21.4", ++ "caniuse-api": "^3.0.0", ++ "cssnano-utils": "^3.1.0", ++ "postcss-selector-parser": "^6.0.5" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-minify-font-values": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", ++ "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", ++ "dependencies": { ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-minify-gradients": { ++ "version": "5.1.1", ++ "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", ++ "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", ++ "dependencies": { ++ "colord": "^2.9.1", ++ "cssnano-utils": "^3.1.0", ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-minify-params": { ++ "version": "5.1.4", ++ "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", ++ "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", ++ "dependencies": { ++ "browserslist": "^4.21.4", ++ "cssnano-utils": "^3.1.0", ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-minify-selectors": { ++ "version": "5.2.1", ++ "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", ++ "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", ++ "dependencies": { ++ "postcss-selector-parser": "^6.0.5" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-mixins": { ++ "version": "9.0.4", ++ "resolved": "https://registry.npmjs.org/postcss-mixins/-/postcss-mixins-9.0.4.tgz", ++ "integrity": "sha512-XVq5jwQJDRu5M1XGkdpgASqLk37OqkH4JCFDXl/Dn7janOJjCTEKL+36cnRVy7bMtoBzALfO7bV7nTIsFnUWLA==", ++ "dependencies": { ++ "fast-glob": "^3.2.11", ++ "postcss-js": "^4.0.0", ++ "postcss-simple-vars": "^7.0.0", ++ "sugarss": "^4.0.1" ++ }, ++ "engines": { ++ "node": ">=14.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/postcss/" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.14" ++ } ++ }, ++ "node_modules/postcss-modules-extract-imports": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz", ++ "integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==", ++ "engines": { ++ "node": "^10 || ^12 || >= 14" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.1.0" ++ } ++ }, ++ "node_modules/postcss-modules-local-by-default": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz", ++ "integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==", ++ "dependencies": { ++ "icss-utils": "^5.0.0", ++ "postcss-selector-parser": "^6.0.2", ++ "postcss-value-parser": "^4.1.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >= 14" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.1.0" ++ } ++ }, ++ "node_modules/postcss-modules-scope": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz", ++ "integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==", ++ "dependencies": { ++ "postcss-selector-parser": "^6.0.4" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >= 14" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.1.0" ++ } ++ }, ++ "node_modules/postcss-modules-values": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", ++ "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", ++ "dependencies": { ++ "icss-utils": "^5.0.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >= 14" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.1.0" ++ } ++ }, ++ "node_modules/postcss-nesting": { ++ "version": "10.2.0", ++ "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", ++ "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", ++ "dependencies": { ++ "@csstools/selector-specificity": "^2.0.0", ++ "postcss-selector-parser": "^6.0.10" ++ }, ++ "engines": { ++ "node": "^12 || ^14 || >=16" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/csstools" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2" ++ } ++ }, ++ "node_modules/postcss-normalize-charset": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", ++ "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-normalize-display-values": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", ++ "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", ++ "dependencies": { ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-normalize-positions": { ++ "version": "5.1.1", ++ "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", ++ "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", ++ "dependencies": { ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-normalize-repeat-style": { ++ "version": "5.1.1", ++ "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", ++ "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", ++ "dependencies": { ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-normalize-string": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", ++ "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", ++ "dependencies": { ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-normalize-timing-functions": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", ++ "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", ++ "dependencies": { ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-normalize-unicode": { ++ "version": "5.1.1", ++ "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", ++ "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", ++ "dependencies": { ++ "browserslist": "^4.21.4", ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-normalize-url": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", ++ "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", ++ "dependencies": { ++ "normalize-url": "^6.0.1", ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-normalize-whitespace": { ++ "version": "5.1.1", ++ "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", ++ "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", ++ "dependencies": { ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-ordered-values": { ++ "version": "5.1.3", ++ "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", ++ "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", ++ "dependencies": { ++ "cssnano-utils": "^3.1.0", ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-reduce-initial": { ++ "version": "5.1.1", ++ "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz", ++ "integrity": "sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w==", ++ "dependencies": { ++ "browserslist": "^4.21.4", ++ "caniuse-api": "^3.0.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-reduce-transforms": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", ++ "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", ++ "dependencies": { ++ "postcss-value-parser": "^4.2.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-selector-parser": { ++ "version": "6.0.11", ++ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.11.tgz", ++ "integrity": "sha512-zbARubNdogI9j7WY4nQJBiNqQf3sLS3wCP4WfOidu+p28LofJqDH1tcXypGrcmMHhDk2t9wGhCsYe/+szLTy1g==", ++ "dependencies": { ++ "cssesc": "^3.0.0", ++ "util-deprecate": "^1.0.2" ++ }, ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/postcss-simple-vars": { ++ "version": "7.0.1", ++ "resolved": "https://registry.npmjs.org/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz", ++ "integrity": "sha512-5GLLXaS8qmzHMOjVxqkk1TZPf1jMqesiI7qLhnlyERalG0sMbHIbJqrcnrpmZdKCLglHnRHoEBB61RtGTsj++A==", ++ "engines": { ++ "node": ">=14.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/postcss/" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.1" ++ } ++ }, ++ "node_modules/postcss-svgo": { ++ "version": "5.1.0", ++ "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", ++ "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", ++ "dependencies": { ++ "postcss-value-parser": "^4.2.0", ++ "svgo": "^2.7.0" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-unique-selectors": { ++ "version": "5.1.1", ++ "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", ++ "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", ++ "dependencies": { ++ "postcss-selector-parser": "^6.0.5" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/postcss-value-parser": { ++ "version": "4.2.0", ++ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", ++ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" ++ }, ++ "node_modules/promise-inflight": { ++ "version": "1.0.1", ++ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", ++ "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==" ++ }, ++ "node_modules/punycode": { ++ "version": "2.3.0", ++ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", ++ "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/queue-microtask": { ++ "version": "1.2.3", ++ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", ++ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", ++ "funding": [ ++ { ++ "type": "github", ++ "url": "https://github.com/sponsors/feross" ++ }, ++ { ++ "type": "patreon", ++ "url": "https://www.patreon.com/feross" ++ }, ++ { ++ "type": "consulting", ++ "url": "https://feross.org/support" ++ } ++ ] ++ }, ++ "node_modules/randombytes": { ++ "version": "2.1.0", ++ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", ++ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", ++ "dependencies": { ++ "safe-buffer": "^5.1.0" ++ } ++ }, ++ "node_modules/raw-loader": { ++ "version": "4.0.2", ++ "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", ++ "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", ++ "dependencies": { ++ "loader-utils": "^2.0.0", ++ "schema-utils": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">= 10.13.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/webpack" ++ }, ++ "peerDependencies": { ++ "webpack": "^4.0.0 || ^5.0.0" ++ } ++ }, ++ "node_modules/read-cache": { ++ "version": "1.0.0", ++ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", ++ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", ++ "dependencies": { ++ "pify": "^2.3.0" ++ } ++ }, ++ "node_modules/readable-stream": { ++ "version": "3.6.0", ++ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", ++ "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", ++ "dependencies": { ++ "inherits": "^2.0.3", ++ "string_decoder": "^1.1.1", ++ "util-deprecate": "^1.0.1" ++ }, ++ "engines": { ++ "node": ">= 6" ++ } ++ }, ++ "node_modules/readdirp": { ++ "version": "3.6.0", ++ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", ++ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", ++ "dependencies": { ++ "picomatch": "^2.2.1" ++ }, ++ "engines": { ++ "node": ">=8.10.0" ++ } ++ }, ++ "node_modules/rechoir": { ++ "version": "0.6.2", ++ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", ++ "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", ++ "dependencies": { ++ "resolve": "^1.1.6" ++ }, ++ "engines": { ++ "node": ">= 0.10" ++ } ++ }, ++ "node_modules/require-from-string": { ++ "version": "2.0.2", ++ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", ++ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", ++ "engines": { ++ "node": ">=0.10.0" ++ } ++ }, ++ "node_modules/resolve": { ++ "version": "1.22.1", ++ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", ++ "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", ++ "dependencies": { ++ "is-core-module": "^2.9.0", ++ "path-parse": "^1.0.7", ++ "supports-preserve-symlinks-flag": "^1.0.0" ++ }, ++ "bin": { ++ "resolve": "bin/resolve" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/ljharb" ++ } ++ }, ++ "node_modules/resolve-cwd": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", ++ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", ++ "dev": true, ++ "dependencies": { ++ "resolve-from": "^5.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/resolve-cwd/node_modules/resolve-from": { ++ "version": "5.0.0", ++ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", ++ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", ++ "dev": true, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/resolve-from": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", ++ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/restore-cursor": { ++ "version": "3.1.0", ++ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", ++ "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", ++ "dependencies": { ++ "onetime": "^5.1.0", ++ "signal-exit": "^3.0.2" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/reusify": { ++ "version": "1.0.4", ++ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", ++ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", ++ "engines": { ++ "iojs": ">=1.0.0", ++ "node": ">=0.10.0" ++ } ++ }, ++ "node_modules/rimraf": { ++ "version": "3.0.2", ++ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", ++ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", ++ "dependencies": { ++ "glob": "^7.1.3" ++ }, ++ "bin": { ++ "rimraf": "bin.js" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/isaacs" ++ } ++ }, ++ "node_modules/run-parallel": { ++ "version": "1.2.0", ++ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", ++ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", ++ "funding": [ ++ { ++ "type": "github", ++ "url": "https://github.com/sponsors/feross" ++ }, ++ { ++ "type": "patreon", ++ "url": "https://www.patreon.com/feross" ++ }, ++ { ++ "type": "consulting", ++ "url": "https://feross.org/support" ++ } ++ ], ++ "dependencies": { ++ "queue-microtask": "^1.2.2" ++ } ++ }, ++ "node_modules/safe-buffer": { ++ "version": "5.2.1", ++ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", ++ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", ++ "funding": [ ++ { ++ "type": "github", ++ "url": "https://github.com/sponsors/feross" ++ }, ++ { ++ "type": "patreon", ++ "url": "https://www.patreon.com/feross" ++ }, ++ { ++ "type": "consulting", ++ "url": "https://feross.org/support" ++ } ++ ] ++ }, ++ "node_modules/sass": { ++ "version": "1.58.0", ++ "resolved": "https://registry.npmjs.org/sass/-/sass-1.58.0.tgz", ++ "integrity": "sha512-PiMJcP33DdKtZ/1jSjjqVIKihoDc6yWmYr9K/4r3fVVIEDAluD0q7XZiRKrNJcPK3qkLRF/79DND1H5q1LBjgg==", ++ "dependencies": { ++ "chokidar": ">=3.0.0 <4.0.0", ++ "immutable": "^4.0.0", ++ "source-map-js": ">=0.6.2 <2.0.0" ++ }, ++ "bin": { ++ "sass": "sass.js" ++ }, ++ "engines": { ++ "node": ">=12.0.0" ++ } ++ }, ++ "node_modules/sass-loader": { ++ "version": "13.2.0", ++ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.2.0.tgz", ++ "integrity": "sha512-JWEp48djQA4nbZxmgC02/Wh0eroSUutulROUusYJO9P9zltRbNN80JCBHqRGzjd4cmZCa/r88xgfkjGD0TXsHg==", ++ "dependencies": { ++ "klona": "^2.0.4", ++ "neo-async": "^2.6.2" ++ }, ++ "engines": { ++ "node": ">= 14.15.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/webpack" ++ }, ++ "peerDependencies": { ++ "fibers": ">= 3.1.0", ++ "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", ++ "sass": "^1.3.0", ++ "sass-embedded": "*", ++ "webpack": "^5.0.0" ++ }, ++ "peerDependenciesMeta": { ++ "fibers": { ++ "optional": true ++ }, ++ "node-sass": { ++ "optional": true ++ }, ++ "sass": { ++ "optional": true ++ }, ++ "sass-embedded": { ++ "optional": true ++ } ++ } ++ }, ++ "node_modules/schema-utils": { ++ "version": "3.1.1", ++ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz", ++ "integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==", ++ "dependencies": { ++ "@types/json-schema": "^7.0.8", ++ "ajv": "^6.12.5", ++ "ajv-keywords": "^3.5.2" ++ }, ++ "engines": { ++ "node": ">= 10.13.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/webpack" ++ } ++ }, ++ "node_modules/semver": { ++ "version": "7.3.8", ++ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", ++ "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", ++ "dependencies": { ++ "lru-cache": "^6.0.0" ++ }, ++ "bin": { ++ "semver": "bin/semver.js" ++ }, ++ "engines": { ++ "node": ">=10" ++ } ++ }, ++ "node_modules/serialize-javascript": { ++ "version": "6.0.1", ++ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.1.tgz", ++ "integrity": "sha512-owoXEFjWRllis8/M1Q+Cw5k8ZH40e3zhp/ovX+Xr/vi1qj6QesbyXXViFbpNvWvPNAD62SutwEXavefrLJWj7w==", ++ "dependencies": { ++ "randombytes": "^2.1.0" ++ } ++ }, ++ "node_modules/shallow-clone": { ++ "version": "3.0.1", ++ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", ++ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", ++ "dev": true, ++ "dependencies": { ++ "kind-of": "^6.0.2" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/shebang-command": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", ++ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", ++ "dev": true, ++ "dependencies": { ++ "shebang-regex": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/shebang-regex": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", ++ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", ++ "dev": true, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/shelljs": { ++ "version": "0.8.5", ++ "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", ++ "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", ++ "dependencies": { ++ "glob": "^7.0.0", ++ "interpret": "^1.0.0", ++ "rechoir": "^0.6.2" ++ }, ++ "bin": { ++ "shjs": "bin/shjs" ++ }, ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/signal-exit": { ++ "version": "3.0.7", ++ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", ++ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" ++ }, ++ "node_modules/slash": { ++ "version": "3.0.0", ++ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", ++ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/source-list-map": { ++ "version": "2.0.1", ++ "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", ++ "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==" ++ }, ++ "node_modules/source-map": { ++ "version": "0.6.1", ++ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", ++ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", ++ "engines": { ++ "node": ">=0.10.0" ++ } ++ }, ++ "node_modules/source-map-js": { ++ "version": "1.0.2", ++ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", ++ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", ++ "engines": { ++ "node": ">=0.10.0" ++ } ++ }, ++ "node_modules/source-map-support": { ++ "version": "0.5.21", ++ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", ++ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", ++ "dependencies": { ++ "buffer-from": "^1.0.0", ++ "source-map": "^0.6.0" ++ } ++ }, ++ "node_modules/ssri": { ++ "version": "8.0.1", ++ "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", ++ "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", ++ "dependencies": { ++ "minipass": "^3.1.1" ++ }, ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/stable": { ++ "version": "0.1.8", ++ "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", ++ "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", ++ "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" ++ }, ++ "node_modules/string_decoder": { ++ "version": "1.3.0", ++ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", ++ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", ++ "dependencies": { ++ "safe-buffer": "~5.2.0" ++ } ++ }, ++ "node_modules/style-loader": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", ++ "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", ++ "dependencies": { ++ "loader-utils": "^2.0.0", ++ "schema-utils": "^3.0.0" ++ }, ++ "engines": { ++ "node": ">= 10.13.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/webpack" ++ }, ++ "peerDependencies": { ++ "webpack": "^4.0.0 || ^5.0.0" ++ } ++ }, ++ "node_modules/stylehacks": { ++ "version": "5.1.1", ++ "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", ++ "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", ++ "dependencies": { ++ "browserslist": "^4.21.4", ++ "postcss-selector-parser": "^6.0.4" ++ }, ++ "engines": { ++ "node": "^10 || ^12 || >=14.0" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.2.15" ++ } ++ }, ++ "node_modules/sugarss": { ++ "version": "4.0.1", ++ "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-4.0.1.tgz", ++ "integrity": "sha512-WCjS5NfuVJjkQzK10s8WOBY+hhDxxNt/N6ZaGwxFZ+wN3/lKKFSaaKUNecULcTTvE4urLcKaZFQD8vO0mOZujw==", ++ "engines": { ++ "node": ">=12.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/postcss/" ++ }, ++ "peerDependencies": { ++ "postcss": "^8.3.3" ++ } ++ }, ++ "node_modules/supports-color": { ++ "version": "7.2.0", ++ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", ++ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", ++ "dependencies": { ++ "has-flag": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/supports-preserve-symlinks-flag": { ++ "version": "1.0.0", ++ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", ++ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", ++ "engines": { ++ "node": ">= 0.4" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/ljharb" ++ } ++ }, ++ "node_modules/svgo": { ++ "version": "2.8.0", ++ "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", ++ "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", ++ "dependencies": { ++ "@trysound/sax": "0.2.0", ++ "commander": "^7.2.0", ++ "css-select": "^4.1.3", ++ "css-tree": "^1.1.3", ++ "csso": "^4.2.0", ++ "picocolors": "^1.0.0", ++ "stable": "^0.1.8" ++ }, ++ "bin": { ++ "svgo": "bin/svgo" ++ }, ++ "engines": { ++ "node": ">=10.13.0" ++ } ++ }, ++ "node_modules/tapable": { ++ "version": "2.2.1", ++ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", ++ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", ++ "engines": { ++ "node": ">=6" ++ } ++ }, ++ "node_modules/tar": { ++ "version": "6.1.13", ++ "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.13.tgz", ++ "integrity": "sha512-jdIBIN6LTIe2jqzay/2vtYLlBHa3JF42ot3h1dW8Q0PaAG4v8rm0cvpVePtau5C6OKXGGcgO9q2AMNSWxiLqKw==", ++ "dependencies": { ++ "chownr": "^2.0.0", ++ "fs-minipass": "^2.0.0", ++ "minipass": "^4.0.0", ++ "minizlib": "^2.1.1", ++ "mkdirp": "^1.0.3", ++ "yallist": "^4.0.0" ++ }, ++ "engines": { ++ "node": ">=10" ++ } ++ }, ++ "node_modules/tar/node_modules/minipass": { ++ "version": "4.0.3", ++ "resolved": "https://registry.npmjs.org/minipass/-/minipass-4.0.3.tgz", ++ "integrity": "sha512-OW2r4sQ0sI+z5ckEt5c1Tri4xTgZwYDxpE54eqWlQloQRoWtXjqt9udJ5Z4dSv7wK+nfFI7FRXyCpBSft+gpFw==", ++ "engines": { ++ "node": ">=8" ++ } ++ }, ++ "node_modules/terser": { ++ "version": "5.16.3", ++ "resolved": "https://registry.npmjs.org/terser/-/terser-5.16.3.tgz", ++ "integrity": "sha512-v8wWLaS/xt3nE9dgKEWhNUFP6q4kngO5B8eYFUuebsu7Dw/UNAnpUod6UHo04jSSkv8TzKHjZDSd7EXdDQAl8Q==", ++ "dependencies": { ++ "@jridgewell/source-map": "^0.3.2", ++ "acorn": "^8.5.0", ++ "commander": "^2.20.0", ++ "source-map-support": "~0.5.20" ++ }, ++ "bin": { ++ "terser": "bin/terser" ++ }, ++ "engines": { ++ "node": ">=10" ++ } ++ }, ++ "node_modules/terser-webpack-plugin": { ++ "version": "5.3.6", ++ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz", ++ "integrity": "sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ==", ++ "dependencies": { ++ "@jridgewell/trace-mapping": "^0.3.14", ++ "jest-worker": "^27.4.5", ++ "schema-utils": "^3.1.1", ++ "serialize-javascript": "^6.0.0", ++ "terser": "^5.14.1" ++ }, ++ "engines": { ++ "node": ">= 10.13.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/webpack" ++ }, ++ "peerDependencies": { ++ "webpack": "^5.1.0" ++ }, ++ "peerDependenciesMeta": { ++ "@swc/core": { ++ "optional": true ++ }, ++ "esbuild": { ++ "optional": true ++ }, ++ "uglify-js": { ++ "optional": true ++ } ++ } ++ }, ++ "node_modules/terser/node_modules/commander": { ++ "version": "2.20.3", ++ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", ++ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" ++ }, ++ "node_modules/through2": { ++ "version": "3.0.2", ++ "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", ++ "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", ++ "dependencies": { ++ "inherits": "^2.0.4", ++ "readable-stream": "2 || 3" ++ } ++ }, ++ "node_modules/to-fast-properties": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", ++ "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", ++ "engines": { ++ "node": ">=4" ++ } ++ }, ++ "node_modules/to-regex-range": { ++ "version": "5.0.1", ++ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", ++ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", ++ "dependencies": { ++ "is-number": "^7.0.0" ++ }, ++ "engines": { ++ "node": ">=8.0" ++ } ++ }, ++ "node_modules/ts-loader": { ++ "version": "9.4.2", ++ "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.4.2.tgz", ++ "integrity": "sha512-OmlC4WVmFv5I0PpaxYb+qGeGOdm5giHU7HwDDUjw59emP2UYMHy9fFSDcYgSNoH8sXcj4hGCSEhlDZ9ULeDraA==", ++ "dependencies": { ++ "chalk": "^4.1.0", ++ "enhanced-resolve": "^5.0.0", ++ "micromatch": "^4.0.0", ++ "semver": "^7.3.4" ++ }, ++ "engines": { ++ "node": ">=12.0.0" ++ }, ++ "peerDependencies": { ++ "typescript": "*", ++ "webpack": "^5.0.0" ++ } ++ }, ++ "node_modules/ts-loader/node_modules/chalk": { ++ "version": "4.1.2", ++ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", ++ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", ++ "dependencies": { ++ "ansi-styles": "^4.1.0", ++ "supports-color": "^7.1.0" ++ }, ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/chalk/chalk?sponsor=1" ++ } ++ }, ++ "node_modules/typescript": { ++ "version": "4.9.5", ++ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", ++ "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", ++ "peer": true, ++ "bin": { ++ "tsc": "bin/tsc", ++ "tsserver": "bin/tsserver" ++ }, ++ "engines": { ++ "node": ">=4.2.0" ++ } ++ }, ++ "node_modules/unique-filename": { ++ "version": "1.1.1", ++ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", ++ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", ++ "dependencies": { ++ "unique-slug": "^2.0.0" ++ } ++ }, ++ "node_modules/unique-slug": { ++ "version": "2.0.2", ++ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", ++ "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", ++ "dependencies": { ++ "imurmurhash": "^0.1.4" ++ } ++ }, ++ "node_modules/universalify": { ++ "version": "0.1.2", ++ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", ++ "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", ++ "engines": { ++ "node": ">= 4.0.0" ++ } ++ }, ++ "node_modules/update-browserslist-db": { ++ "version": "1.0.10", ++ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz", ++ "integrity": "sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ==", ++ "funding": [ ++ { ++ "type": "opencollective", ++ "url": "https://opencollective.com/browserslist" ++ }, ++ { ++ "type": "tidelift", ++ "url": "https://tidelift.com/funding/github/npm/browserslist" ++ } ++ ], ++ "dependencies": { ++ "escalade": "^3.1.1", ++ "picocolors": "^1.0.0" ++ }, ++ "bin": { ++ "browserslist-lint": "cli.js" ++ }, ++ "peerDependencies": { ++ "browserslist": ">= 4.21.0" ++ } ++ }, ++ "node_modules/uri-js": { ++ "version": "4.4.1", ++ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", ++ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", ++ "dependencies": { ++ "punycode": "^2.1.0" ++ } ++ }, ++ "node_modules/util-deprecate": { ++ "version": "1.0.2", ++ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", ++ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" ++ }, ++ "node_modules/watchpack": { ++ "version": "2.4.0", ++ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", ++ "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", ++ "dependencies": { ++ "glob-to-regexp": "^0.4.1", ++ "graceful-fs": "^4.1.2" ++ }, ++ "engines": { ++ "node": ">=10.13.0" ++ } ++ }, ++ "node_modules/webpack": { ++ "version": "5.75.0", ++ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.75.0.tgz", ++ "integrity": "sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ==", ++ "dependencies": { ++ "@types/eslint-scope": "^3.7.3", ++ "@types/estree": "^0.0.51", ++ "@webassemblyjs/ast": "1.11.1", ++ "@webassemblyjs/wasm-edit": "1.11.1", ++ "@webassemblyjs/wasm-parser": "1.11.1", ++ "acorn": "^8.7.1", ++ "acorn-import-assertions": "^1.7.6", ++ "browserslist": "^4.14.5", ++ "chrome-trace-event": "^1.0.2", ++ "enhanced-resolve": "^5.10.0", ++ "es-module-lexer": "^0.9.0", ++ "eslint-scope": "5.1.1", ++ "events": "^3.2.0", ++ "glob-to-regexp": "^0.4.1", ++ "graceful-fs": "^4.2.9", ++ "json-parse-even-better-errors": "^2.3.1", ++ "loader-runner": "^4.2.0", ++ "mime-types": "^2.1.27", ++ "neo-async": "^2.6.2", ++ "schema-utils": "^3.1.0", ++ "tapable": "^2.1.1", ++ "terser-webpack-plugin": "^5.1.3", ++ "watchpack": "^2.4.0", ++ "webpack-sources": "^3.2.3" ++ }, ++ "bin": { ++ "webpack": "bin/webpack.js" ++ }, ++ "engines": { ++ "node": ">=10.13.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/webpack" ++ }, ++ "peerDependenciesMeta": { ++ "webpack-cli": { ++ "optional": true ++ } ++ } ++ }, ++ "node_modules/webpack-cli": { ++ "version": "5.0.1", ++ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.0.1.tgz", ++ "integrity": "sha512-S3KVAyfwUqr0Mo/ur3NzIp6jnerNpo7GUO6so51mxLi1spqsA17YcMXy0WOIJtBSnj748lthxC6XLbNKh/ZC+A==", ++ "dev": true, ++ "dependencies": { ++ "@discoveryjs/json-ext": "^0.5.0", ++ "@webpack-cli/configtest": "^2.0.1", ++ "@webpack-cli/info": "^2.0.1", ++ "@webpack-cli/serve": "^2.0.1", ++ "colorette": "^2.0.14", ++ "commander": "^9.4.1", ++ "cross-spawn": "^7.0.3", ++ "envinfo": "^7.7.3", ++ "fastest-levenshtein": "^1.0.12", ++ "import-local": "^3.0.2", ++ "interpret": "^3.1.1", ++ "rechoir": "^0.8.0", ++ "webpack-merge": "^5.7.3" ++ }, ++ "bin": { ++ "webpack-cli": "bin/cli.js" ++ }, ++ "engines": { ++ "node": ">=14.15.0" ++ }, ++ "funding": { ++ "type": "opencollective", ++ "url": "https://opencollective.com/webpack" ++ }, ++ "peerDependencies": { ++ "webpack": "5.x.x" ++ }, ++ "peerDependenciesMeta": { ++ "@webpack-cli/generators": { ++ "optional": true ++ }, ++ "webpack-bundle-analyzer": { ++ "optional": true ++ }, ++ "webpack-dev-server": { ++ "optional": true ++ } ++ } ++ }, ++ "node_modules/webpack-cli/node_modules/commander": { ++ "version": "9.5.0", ++ "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", ++ "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", ++ "dev": true, ++ "engines": { ++ "node": "^12.20.0 || >=14" ++ } ++ }, ++ "node_modules/webpack-cli/node_modules/interpret": { ++ "version": "3.1.1", ++ "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz", ++ "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==", ++ "dev": true, ++ "engines": { ++ "node": ">=10.13.0" ++ } ++ }, ++ "node_modules/webpack-cli/node_modules/rechoir": { ++ "version": "0.8.0", ++ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", ++ "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", ++ "dev": true, ++ "dependencies": { ++ "resolve": "^1.20.0" ++ }, ++ "engines": { ++ "node": ">= 10.13.0" ++ } ++ }, ++ "node_modules/webpack-merge": { ++ "version": "5.8.0", ++ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.8.0.tgz", ++ "integrity": "sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q==", ++ "dev": true, ++ "dependencies": { ++ "clone-deep": "^4.0.1", ++ "wildcard": "^2.0.0" ++ }, ++ "engines": { ++ "node": ">=10.0.0" ++ } ++ }, ++ "node_modules/webpack-sources": { ++ "version": "2.3.1", ++ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", ++ "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", ++ "dependencies": { ++ "source-list-map": "^2.0.1", ++ "source-map": "^0.6.1" ++ }, ++ "engines": { ++ "node": ">=10.13.0" ++ } ++ }, ++ "node_modules/webpack/node_modules/webpack-sources": { ++ "version": "3.2.3", ++ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", ++ "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", ++ "engines": { ++ "node": ">=10.13.0" ++ } ++ }, ++ "node_modules/which": { ++ "version": "2.0.2", ++ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", ++ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", ++ "dev": true, ++ "dependencies": { ++ "isexe": "^2.0.0" ++ }, ++ "bin": { ++ "node-which": "bin/node-which" ++ }, ++ "engines": { ++ "node": ">= 8" ++ } ++ }, ++ "node_modules/wildcard": { ++ "version": "2.0.0", ++ "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.0.tgz", ++ "integrity": "sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==", ++ "dev": true ++ }, ++ "node_modules/wrappy": { ++ "version": "1.0.2", ++ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", ++ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" ++ }, ++ "node_modules/yallist": { ++ "version": "4.0.0", ++ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", ++ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" ++ }, ++ "node_modules/yaml": { ++ "version": "1.10.2", ++ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", ++ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", ++ "engines": { ++ "node": ">= 6" ++ } ++ }, ++ "node_modules/yocto-queue": { ++ "version": "0.1.0", ++ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", ++ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", ++ "engines": { ++ "node": ">=10" ++ }, ++ "funding": { ++ "url": "https://github.com/sponsors/sindresorhus" ++ } ++ } ++ } ++} +diff --git a/package.json b/package.json +new file mode 100644 +index 0000000..48fe874 +--- /dev/null ++++ b/package.json +@@ -0,0 +1,32 @@ ++{ ++ "name": "ckeditor5-templates", ++ "version": "1.0.0", ++ "description": "CKEditor 5 plugin development.", ++ "scripts": { ++ "start": "webpack --mode development --watch", ++ "build": "webpack" ++ }, ++ "author": "", ++ "license": "GPL-2.0-or-later", ++ "dependencies": { ++ "@ckeditor/ckeditor5-basic-styles": "^35.4.0", ++ "@ckeditor/ckeditor5-dev-utils": "^32.0.2", ++ "@ckeditor/ckeditor5-editor-classic": "^35.4.0", ++ "@ckeditor/ckeditor5-engine": "^35.4.0", ++ "@ckeditor/ckeditor5-essentials": "^35.4.0", ++ "@ckeditor/ckeditor5-html-support": "^35.4.0", ++ "@ckeditor/ckeditor5-paragraph": "^35.4.0", ++ "@ckeditor/ckeditor5-theme-lark": "^35.4.0", ++ "ckeditor5": "^35.4.0", ++ "css-loader": "^5.2.7", ++ "mini-css-extract-plugin": "^2.7.2", ++ "postcss-loader": "^4.3.0", ++ "raw-loader": "^4.0.2", ++ "sass": "^1.58.0", ++ "sass-loader": "^13.2.0", ++ "style-loader": "^2.0.0", ++ "terser-webpack-plugin": "^5.3.6", ++ "webpack": "^5.75.0", ++ "webpack-cli": "^5.0.1" ++ } ++} +diff --git a/sass/dialog.scss b/sass/dialog.scss +new file mode 100644 +index 0000000..8460c4a +--- /dev/null ++++ b/sass/dialog.scss +@@ -0,0 +1,47 @@ ++.ckeditor-templates-widget-modal { ++ .form-radios { ++ margin: 0; ++ padding: 0; ++ ++ .form-type-radio.form-item-templates, ++ .form-type--radio.form-item--templates { ++ margin: 0; ++ padding: 0; ++ ++ input { ++ display: none; ++ } ++ ++ label { ++ display: flex; ++ margin-top: 0.75rem; ++ padding: 0.75rem; ++ border: #bcbcbc 1px solid; ++ align-items: flex-start; ++ user-select: none; ++ ++ &:hover { ++ background-color: #efefef; ++ } ++ ++ img { ++ width: 5rem; ++ margin-right: 0.75rem; ++ } ++ ++ div { ++ line-height: 1.2rem; ++ ++ strong { ++ display: block; ++ } ++ } ++ } ++ ++ input:checked + label { ++ border: #ff9933 1px solid; ++ background-color: #fffacd; ++ } ++ } ++ } ++} +diff --git a/src/CKEditorTemplatesInterface.php b/src/CKEditorTemplatesInterface.php +new file mode 100644 +index 0000000..e66ee54 +--- /dev/null ++++ b/src/CKEditorTemplatesInterface.php +@@ -0,0 +1,12 @@ ++messenger = $messenger; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public static function createInstance(ContainerInterface $container, EntityTypeInterface $entity_type): CKEditorTemplatesListBuilder | EntityListBuilder | EntityHandlerInterface | static { ++ return new static( ++ $entity_type, ++ $container->get('entity_type.manager')->getStorage($entity_type->id()), ++ $container->get('messenger') ++ ); ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function getFormId(): string { ++ return 'ckeditor_templates_entity_list'; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function buildHeader(): array { ++ $header['label'] = $this->t('Label'); ++ $header['id'] = $this->t('Machine name'); ++ $header['status'] = $this->t('Status'); ++ $header['formats'] = $this->t('Formats'); ++ ++ return $header + parent::buildHeader(); ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function buildRow(EntityInterface $entity): array { ++ $formats = []; ++ $formatOptions = $entity->get('formats'); ++ foreach (filter_formats() as $format) { ++ if (in_array($format->id(), $formatOptions)) { ++ $formats[] = $format->label(); ++ } ++ } ++ ++ $row['label'] = $entity->label(); ++ $row['id']['#markup'] = $entity->id(); ++ $row['status']['#markup'] = $entity->status() ? $this->t('Enabled') : $this->t('Disabled'); ++ $row['formats']['#markup'] = implode(', ', $formats); ++ ++ return $row + parent::buildRow($entity); ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function submitForm(array &$form, FormStateInterface $form_state) { ++ parent::submitForm($form, $form_state); ++ $this->messenger->addStatus($this->t('The CKEditor Template Configuration settings have been updated.')); ++ } ++ ++} +diff --git a/src/Entity/CKEditorTemplates.php b/src/Entity/CKEditorTemplates.php +new file mode 100644 +index 0000000..3ed62ec +--- /dev/null ++++ b/src/Entity/CKEditorTemplates.php +@@ -0,0 +1,133 @@ ++weight)) { ++ $templates = $storage->loadMultiple(); ++ if (empty($templates)) { ++ $this->weight = 0; ++ } ++ else { ++ $weights = array_column($templates, 'weight'); ++ $this->weight = max($weights) + 1; ++ } ++ } ++ } ++ ++} +diff --git a/src/Form/CKEditorTemplatesDialogForm.php b/src/Form/CKEditorTemplatesDialogForm.php +new file mode 100644 +index 0000000..b9b5b62 +--- /dev/null ++++ b/src/Form/CKEditorTemplatesDialogForm.php +@@ -0,0 +1,285 @@ ++entityTypeManager = $entity_type_manager; ++ $this->fileUrlGenerator = $file_url_generator; ++ $this->moduleFolder = '/' . $extension_list_module->getPath('ckeditor_templates'); ++ $this->templates = []; ++ ++ // Load the templates. ++ $templates = $this->getTemplates(); ++ foreach ($templates as $format) { ++ $this->templates[$format->id()] = [ ++ 'label' => $format->label(), ++ 'formats' => $format->get('formats') ?? [], ++ 'thumb' => $this->getThumb($format->get('thumb')[0] ?? ''), ++ 'description' => $format->get('description') ?? '', ++ 'code' => $format->get('code') ?? '', ++ ]; ++ } ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public static function create(ContainerInterface $container): CKEditorTemplatesDialogForm | static { ++ return new static( ++ $container->get('entity_type.manager'), ++ $container->get('file_url_generator'), ++ $container->get('extension.list.module') ++ ); ++ } ++ ++ /** ++ * Loads the CKEditor Templates. ++ * ++ * @return \Drupal\Core\Entity\EntityInterface[] ++ * A list of CKEditor Template entities. ++ * ++ * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException ++ * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException ++ */ ++ private function getTemplates(): array { ++ $storage = $this->entityTypeManager ++ ->getStorage('ckeditor_templates'); ++ ++ $nids = $storage->getQuery() ++ ->condition('status', 1) ++ ->sort('weight', 'ASC') ++ ->execute(); ++ ++ return $storage->loadMultiple($nids); ++ } ++ ++ /** ++ * Gets the thumbnail for an image. ++ * ++ * @param string $thumb ++ * The thumb image id. ++ * ++ * @return string ++ * The thumb image URL. ++ * ++ * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException ++ * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException ++ */ ++ private function getThumb(string $thumb): string { ++ $image = ''; ++ ++ if (!empty($thumb)) { ++ $file = $this->entityTypeManager ++ ->getStorage('file') ++ ->load($thumb); ++ ++ if (isset($file)) { ++ $fileUri = $file->getFileUri(); ++ ++ $style = $this->entityTypeManager ++ ->getStorage('image_style') ++ ->load('thumbnail'); ++ if (isset($style)) { ++ $image = $style->buildUrl($fileUri) ?? ''; ++ } ++ else { ++ $image = $this->fileUrlGenerator->generateAbsoluteString($fileUri) ?? ''; ++ } ++ } ++ } ++ ++ if (empty($image)) { ++ $image = $this->moduleFolder . '/js/plugin/theme/images/placeholder.svg'; ++ } ++ ++ return $image; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function getFormId(): string { ++ return 'ckeditor_templates__dialog_form'; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function buildForm(array $form, FormStateInterface $form_state, string $editor_id = ''): array { ++ $templates = []; ++ ++ // Gets the templates. ++ foreach ($this->templates as $key => $template) { ++ if (in_array($editor_id, $template['formats'])) { ++ $templates[$key] = ' ++ ' . $template['label'] . ' ++
++ ' . $template['label'] . ' ++ ' . $template['description'] . ' ++
++ '; ++ } ++ } ++ ++ // Gets the editor. ++ try { ++ $editor = $this->entityTypeManager ++ ->getStorage('editor') ++ ->load($editor_id); ++ } ++ catch (InvalidPluginDefinitionException | PluginNotFoundException $e) { ++ $this->logger('templates')->critical($e->getMessage()); ++ } ++ ++ // Validate there are templates. ++ if (empty($templates) || !isset($editor)) { ++ $form['warning'] = [ ++ '#type' => 'markup', ++ '#markup' => $this->t('There is no template available for the @formatLabel text format.', [ ++ '@formatLabel' => $editor?->label() ?? $editor_id, ++ ]), ++ ]; ++ ++ return $form; ++ } ++ ++ // List the templates. ++ $form['label'] = [ ++ '#type' => 'html_tag', ++ '#tag' => 'div', ++ '#value' => 'Select the template to open in the editor:', ++ ]; ++ ++ $form['templates'] = [ ++ '#type' => 'radios', ++ '#options' => $templates, ++ ]; ++ ++ $settings = $editor->getSettings(); ++ $replace_content = $settings['plugins']['ckeditor_templates_plugin']['replace_content'] ?? FALSE; ++ $form['replace_content'] = [ ++ '#title' => $this->t('Replace actual contents'), ++ '#type' => 'checkbox', ++ '#default_value' => $replace_content, ++ '#description' => $this->t('Remove the actual contents, keeping only the selected template.'), ++ ]; ++ ++ $form['actions'] = [ ++ '#type' => 'actions', ++ 'submit' => [ ++ '#type' => 'submit', ++ '#value' => $this->t('Insert'), ++ '#ajax' => [ ++ 'callback' => [$this, 'ajaxSubmitForm'], ++ 'wrapper' => $this->ajaxWrapper, ++ ], ++ ], ++ ]; ++ ++ return $form; ++ } ++ ++ /** ++ * AJAX callback function for inserting HTML code into the CKEditor. ++ * ++ * @param array $form ++ * The form. ++ * @param \Drupal\Core\Form\FormStateInterface $form_state ++ * The form state. ++ * ++ * @return \Drupal\Core\Ajax\AjaxResponse|array ++ * AJAX response. ++ */ ++ public function ajaxSubmitForm(array &$form, FormStateInterface $form_state): AjaxResponse | array { ++ $response = new AjaxResponse(); ++ ++ $template = $form_state->getValue('templates'); ++ if (isset($template)) { ++ $htmlCode = $this->templates[$template]['code'] ?? ''; ++ if (!empty($htmlCode)) { ++ $response->addCommand(new EditorDialogSave([ ++ 'htmlCode' => $htmlCode, ++ 'replace' => $form_state->getValue('replace_content'), ++ ])); ++ } ++ } ++ ++ $response->addCommand(new CloseModalDialogCommand()); ++ ++ return $response; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function submitForm(array &$form, FormStateInterface $form_state) { ++ // This function is required by Drupal, but the request is being ++ // handled in the ajaxSubmitForm() function. ++ } ++ ++} +diff --git a/src/Form/CKEditorTemplatesEntityForm.php b/src/Form/CKEditorTemplatesEntityForm.php +new file mode 100644 +index 0000000..21eda65 +--- /dev/null ++++ b/src/Form/CKEditorTemplatesEntityForm.php +@@ -0,0 +1,139 @@ ++fileSystem = $file_system; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public static function create(ContainerInterface $container) { ++ return new static( ++ $container->get('file_system') ++ ); ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function form(array $form, FormStateInterface $form_state) { ++ $form = parent::form($form, $form_state); ++ ++ // Gets the allowed format options. ++ $allowedFormatOptions = []; ++ foreach (filter_formats() as $format) { ++ $editor = editor_load($format->id()); ++ if (isset($editor) && $editor->getEditor() === 'ckeditor5') { ++ $allowedFormatOptions[$format->id()] = $format->label(); ++ } ++ } ++ ++ $form['label'] = [ ++ '#type' => 'textfield', ++ '#title' => $this->t('Label'), ++ '#maxlength' => 255, ++ '#default_value' => $this->entity->label(), ++ '#required' => TRUE, ++ ]; ++ ++ $form['id'] = [ ++ '#type' => 'machine_name', ++ '#default_value' => $this->entity->id(), ++ '#machine_name' => [ ++ 'exists' => '\Drupal\ckeditor_templates\Entity\CKEditorTemplates::load', ++ ], ++ '#disabled' => !$this->entity->isNew(), ++ '#required' => TRUE, ++ ]; ++ ++ $form['description'] = [ ++ '#type' => 'textarea', ++ '#title' => $this->t('Description'), ++ '#default_value' => $this->entity->get('description'), ++ ]; ++ ++ $form['thumb'] = [ ++ '#type' => 'managed_file', ++ '#title' => $this->t('Illustration Image/Icon'), ++ '#default_value' => $this->entity->get('thumb'), ++ '#description' => $this->t('Allowed types: png jpeg jpg gif'), ++ '#upload_location' => 'public://ckeditor-templates', ++ '#upload_validators' => [ ++ 'file_validate_extensions' => ['gif png jpg jpeg'], ++ ], ++ '#cardinality' => 1, ++ ]; ++ ++ $form['code'] = [ ++ '#type' => 'textarea', ++ '#title' => $this->t('HTML Code'), ++ '#default_value' => $this->entity->get('code'), ++ '#description' => $this->t('The HTML code to be injected into the CKEditor.'), ++ '#required' => TRUE, ++ ]; ++ ++ $form['formats'] = [ ++ '#type' => 'checkboxes', ++ '#title' => $this->t('Available For'), ++ '#default_value' => $this->entity->get('formats') ?? [], ++ '#options' => $allowedFormatOptions, ++ '#required' => TRUE, ++ ]; ++ ++ $form['status'] = [ ++ '#type' => 'checkbox', ++ '#title' => $this->t('Enabled'), ++ '#default_value' => $this->entity->status(), ++ ]; ++ ++ return $form; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function save(array $form, FormStateInterface $form_state) { ++ $template = $this->entity; ++ $status = $template->save(); ++ ++ if ($status) { ++ $this->messenger()->addMessage($this->t('Saved the %label CKEditor Template.', [ ++ '%label' => $template->label(), ++ ])); ++ } ++ else { ++ $this->messenger()->addMessage($this->t('The %label CKEditor Template was not saved.', [ ++ '%label' => $template->label(), ++ ])); ++ } ++ ++ $form_state->setRedirectUrl($this->entity->toUrl('collection')); ++ ++ return $status; ++ } ++ ++} +diff --git a/src/Plugin/CKEditor5Plugin/CKEditorTemplatesDialog.php b/src/Plugin/CKEditor5Plugin/CKEditorTemplatesDialog.php +new file mode 100644 +index 0000000..d504e0a +--- /dev/null ++++ b/src/Plugin/CKEditor5Plugin/CKEditorTemplatesDialog.php +@@ -0,0 +1,68 @@ ++ FALSE]; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function buildConfigurationForm(array $form, FormStateInterface $form_state): array { ++ $form['replace_content'] = [ ++ '#type' => 'checkbox', ++ '#title' => $this->t('Replace content default value'), ++ '#default_value' => $this->configuration['replace_content'] ?? FALSE, ++ '#description' => $this->t('Whether the "Replace actual contents" checkbox is checked by default in the Templates dialog.'), ++ ]; ++ ++ return $form; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function validateConfigurationForm(array &$form, FormStateInterface $form_state) { ++ $form_value = $form_state->getValue('replace_content'); ++ $form_state->setValue('replace_content', (bool) $form_value); ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function submitConfigurationForm(array &$form, FormStateInterface $form_state) { ++ $this->configuration['replace_content'] = $form_state->getValue('replace_content'); ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array { ++ $dialogUrl = Url::fromRoute('ckeditor_templates.selector', [ ++ 'editor_id' => $editor->id(), ++ ])->toString(); ++ ++ $static_plugin_config['ckeditorTemplates']['dialogUrl'] = $dialogUrl; ++ ++ return $static_plugin_config; ++ } ++ ++} +diff --git a/src/Plugin/CKEditorPlugin/CkeditorTemplates.php b/src/Plugin/CKEditorPlugin/CkeditorTemplates.php +deleted file mode 100644 +index 79e1789..0000000 +--- a/src/Plugin/CKEditorPlugin/CkeditorTemplates.php ++++ /dev/null +@@ -1,183 +0,0 @@ +-get('config.factory') +- ); +- } +- +- /** +- * Constructs a Drupal\Component\Plugin\PluginBase object. +- * +- * @param array $configuration +- * A configuration array containing information about the plugin instance. +- * @param string $plugin_id +- * The plugin_id for the plugin instance. +- * @param mixed $plugin_definition +- * The plugin implementation definition. +- * @param \Drupal\Core\Config\ConfigFactory $configFactoryService +- * Drupal Configuration Factory Service. +- */ +- public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactory $configFactoryService) { +- parent::__construct($configuration, $plugin_id, $plugin_definition); +- +- $this->configFactoryService = $configFactoryService; +- } +- +- /** +- * {@inheritdoc} +- */ +- public function getFile() { +- return $this->getTemplatesPluginPath() . '/plugin.js'; +- } +- +- /** +- * {@inheritdoc} +- */ +- public function getLibraries(Editor $editor) { +- return ['ckeditor_templates/ckeditor.templates.dialog']; +- } +- +- /** +- * {@inheritdoc} +- */ +- public function getButtons() { +- return [ +- 'Templates' => [ +- 'label' => t('Templates'), +- 'image' => $this->getTemplatesPluginPath() . '/icons/templates.png', +- ], +- ]; +- } +- +- /** +- * {@inheritdoc} +- */ +- public function getConfig(Editor $editor) { +- $config = []; +- $settings = $editor->getSettings(); +- // Set replace content default value if set. +- if (isset($settings['plugins']['templates']['replace_content'])) { +- $config['templates_replaceContent'] = $settings['plugins']['templates']['replace_content']; +- } +- // Set template files default value if set. +- if (isset($settings['plugins']['templates']['template_path']) && !empty($settings['plugins']['templates']['template_path'])) { +- $config['templates_files'] = [$settings['plugins']['templates']['template_path']]; +- } +- else { +- // Use templates plugin default file. +- $config['templates_files'] = $this->getTemplatesDefaultPath(); +- } +- return $config; +- } +- +- /** +- * {@inheritdoc} +- */ +- public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor) { +- // Defaults. +- $config = [ +- 'replace_content' => FALSE, +- 'template_path' => '', +- ]; +- +- $settings = $editor->getSettings(); +- +- if (isset($settings['plugins']['templates'])) { +- $config = $settings['plugins']['templates']; +- } +- +- $form['template_path'] = [ +- '#title' => t('Template definition file'), +- '#type' => 'textfield', +- '#default_value' => $config['template_path'], +- '#description' => t('Path to the javascript file defining the templates, relative to drupal root (starting with "/"). By default, it looks in your default theme directory for a file named "templates/ckeditor_templates.js"'), +- ]; +- +- $form['replace_content'] = [ +- '#title' => t('Replace content default value'), +- '#type' => 'checkbox', +- '#default_value' => $config['replace_content'], +- '#description' => t('Whether the "Replace actual contents" checkbox is checked by default in the Templates dialog'), +- ]; +- +- $form['#attached']['library'][] = 'ckeditor_templates/ckeditor.templates.admin'; +- +- return $form; +- } +- +- /** +- * Return ckeditor templates plugin path relative to drupal root. +- * +- * @return string +- * Relative path to the ckeditor plugin folder +- */ +- private function getTemplatesPluginPath() { +- $pluginPath = 'libraries/ckeditor/plugins/templates'; +- +- if (!file_exists(DRUPAL_ROOT . '/' . $pluginPath)) { +- // keep supporting module legacy path to avoid breaking change +- // using this path is deprecated +- $pluginPath = 'libraries/templates'; +- } +- +- return $pluginPath; +- } +- +- /** +- * Generate the path to the template file. +- * +- * The file will be picked from : +- * - the default theme if the file exists +- * - the ckeditor template directory otherwise. +- * +- * @return array +- * List of path to the template file +- */ +- private function getTemplatesDefaultPath() { +- // Default to module folder. +- $defaultPath = base_path() . $this->getTemplatesPluginPath() . '/templates/default.js'; +- +- // Get site default theme name. +- $defaultThemConfig = $this->configFactoryService->get('system.theme'); +- $defaultThemeName = $defaultThemConfig->get('default'); +- +- $defaultThemeFileAbsolutePath = DRUPAL_ROOT . '/' . drupal_get_path('theme', $defaultThemeName) . '/templates/ckeditor_templates.js'; +- if (file_exists($defaultThemeFileAbsolutePath)) { +- $defaultPath = base_path() . drupal_get_path('theme', $defaultThemeName) . '/templates/ckeditor_templates.js'; +- } +- +- return [$defaultPath]; +- } +- +-} +diff --git a/templates/ckeditor_templates.js.example b/templates/ckeditor_templates.js.example +deleted file mode 100644 +index ffafdbc..0000000 +--- a/templates/ckeditor_templates.js.example ++++ /dev/null +@@ -1,83 +0,0 @@ +-// Override the default template set +-CKEDITOR.addTemplates( 'default', { +- // The name of sub folder which hold the shortcut preview images of the +- // templates. Determine base path of drupal installation if any +- // (ckeditor could possibly be loaded w/o drupalSettings). +- imagesPath: ((drupalSettings && drupalSettings.path) ? drupalSettings.path.baseUrl : '/') + 'themes/custom/mytheme/images/ckeditor/', +- +- // The templates definitions. +- templates: [ { +- title: 'Image and Title module', +- image: 'template1.gif', +- description: 'One main image with a title and text that surround the image.', +- html: '

' + +- // Use src=" " so image is not filtered out by the editor as incorrect (src is required). +- '' + +- 'Type the title here' + +- '

' + +- '

' + +- 'Type the text here' + +- '

' +- }, +- { +- title: 'Strange Template', +- image: 'template2.gif', +- description: 'A template that defines two colums, each one with a title, and some text.', +- html: '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '
' + +- '

Title 1

' + +- '
' + +- '

Title 2

' + +- '
' + +- 'Text 1' + +- '' + +- 'Text 2' + +- '
' + +- '

' + +- 'More text goes here.' + +- '

' +- }, +- { +- title: 'Text and Table', +- image: 'template3.gif', +- description: 'A title with some text and a table.', +- html: '
' + +- '

' + +- 'Title goes here' + +- '

' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '' + +- '
' + +- 'Table title' + +- '
   
   
   
' + +- '

' + +- 'Type the text here' + +- '

' + +- '
' +- } ] +-} ); +diff --git a/webpack.config.js b/webpack.config.js +new file mode 100644 +index 0000000..e27ce74 +--- /dev/null ++++ b/webpack.config.js +@@ -0,0 +1,87 @@ ++const path = require('path'); ++const webpack = require('webpack'); ++const { styles } = require('@ckeditor/ckeditor5-dev-utils'); ++const TerserPlugin = require('terser-webpack-plugin'); ++const MiniCssExtractPlugin = require('mini-css-extract-plugin'); ++ ++const pluginName = 'ckeditorTemplates'; ++ ++module.exports = [ ++ { ++ mode: 'production', ++ optimization: { ++ minimize: true, ++ minimizer: [ ++ new TerserPlugin({ ++ terserOptions: { ++ format: { ++ comments: false ++ } ++ }, ++ test: /\.js(\?.*)?$/i, ++ extractComments: false ++ }) ++ ], ++ moduleIds: 'named' ++ }, ++ entry: { ++ path: path.resolve(__dirname, 'js/plugin/src/app.js') ++ }, ++ output: { ++ path: path.resolve(__dirname, 'js/dist'), ++ filename: `${pluginName}.js`, ++ library: ['CKEditor5', pluginName], ++ libraryTarget: 'umd', ++ libraryExport: 'default' ++ }, ++ plugins: [ ++ new webpack.DllReferencePlugin({ ++ manifest: require('./node_modules/ckeditor5/build/ckeditor5-dll.manifest.json'), ++ scope: 'ckeditor5/src', ++ name: 'CKEditor5.dll' ++ }), ++ new MiniCssExtractPlugin({ ++ filename: '../../css/cke_templates.dialog.css' ++ }) ++ ], ++ module: { ++ rules: [ ++ { ++ test: /js[/\\]plugin[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/, ++ use: ['raw-loader'] ++ }, ++ { ++ test: /js[/\\]plugin[/\\]theme[/\\][^/\\]+\.css$/, ++ use: [ ++ { ++ loader: 'style-loader', ++ options: { ++ injectType: 'singletonStyleTag', ++ attributes: { ++ 'data-cke': true ++ } ++ } ++ }, ++ { ++ loader: 'postcss-loader', ++ options: styles.getPostCssConfig({ ++ themeImporter: { ++ themePath: require.resolve('@ckeditor/ckeditor5-theme-lark') ++ }, ++ minify: true ++ }) ++ } ++ ] ++ }, ++ { ++ test: /sass[/\\][^/\\]+\.s[ac]ss$/, ++ use: [ ++ MiniCssExtractPlugin.loader, ++ 'css-loader', ++ 'sass-loader' ++ ] ++ } ++ ] ++ } ++ } ++]; +-- +GitLab + + +From 0c57ea2b14d6d737a5182820368f9cbd5dcaa656 Mon Sep 17 00:00:00 2001 +From: Marcelo Hespanhol <61546-mhespanhol@users.noreply.drupalcode.org> +Date: Tue, 7 Mar 2023 18:37:22 +0000 +Subject: [PATCH 02/11] Sets the image as permanent + +--- + src/Form/CKEditorTemplatesEntityForm.php | 61 ++++++++++++++++++++++-- + 1 file changed, 56 insertions(+), 5 deletions(-) + +diff --git a/src/Form/CKEditorTemplatesEntityForm.php b/src/Form/CKEditorTemplatesEntityForm.php +index 21eda65..6682d35 100644 +--- a/src/Form/CKEditorTemplatesEntityForm.php ++++ b/src/Form/CKEditorTemplatesEntityForm.php +@@ -3,8 +3,12 @@ + namespace Drupal\ckeditor_templates\Form; + + use Drupal\Core\Entity\EntityForm; +-use Drupal\Core\Form\FormStateInterface; ++use Drupal\Core\Entity\EntityTypeManagerInterface; + use Drupal\Core\File\FileSystemInterface; ++use Drupal\file\FileUsage\FileUsageInterface; ++use Drupal\Core\Form\FormStateInterface; ++use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException; ++use Drupal\Component\Plugin\Exception\PluginNotFoundException; + use Psr\Container\ContainerInterface; + + /** +@@ -19,13 +23,36 @@ class CKEditorTemplatesEntityForm extends EntityForm { + * + * @var \Drupal\Core\File\FileSystemInterface + */ +- protected $fileSystem; ++ protected FileSystemInterface $fileSystem; + + /** +- * {@inheritdoc} ++ * Entity Type Manager. ++ * ++ * @var \Drupal\Core\Entity\EntityTypeManagerInterface ++ */ ++ protected $entityTypeManager; ++ ++ /** ++ * The file usage service. ++ * ++ * @var \Drupal\file\FileUsage\FileUsageInterface + */ +- public function __construct(FileSystemInterface $file_system) { ++ protected FileUsageInterface $fileUsage; ++ ++ /** ++ * Constructs a new entity form. ++ * ++ * @param \Drupal\Core\File\FileSystemInterface $file_system ++ * The file system service. ++ * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager ++ * The Entity type manager. ++ * @param \Drupal\file\FileUsage\FileUsageInterface $file_usage ++ * The file usage service. ++ */ ++ public function __construct(FileSystemInterface $file_system, EntityTypeManagerInterface $entity_type_manager, FileUsageInterface $file_usage) { + $this->fileSystem = $file_system; ++ $this->entityTypeManager = $entity_type_manager; ++ $this->fileUsage = $file_usage; + } + + /** +@@ -33,7 +60,9 @@ class CKEditorTemplatesEntityForm extends EntityForm { + */ + public static function create(ContainerInterface $container) { + return new static( +- $container->get('file_system') ++ $container->get('file_system'), ++ $container->get('entity_type.manager'), ++ $container->get('file.usage') + ); + } + +@@ -121,6 +150,28 @@ class CKEditorTemplatesEntityForm extends EntityForm { + $status = $template->save(); + + if ($status) { ++ ++ // Sets the image as permanent. ++ try { ++ $thumb = $form_state->getValue('thumb'); ++ if (!empty($thumb)) { ++ $thumb = reset($thumb); ++ ++ /** @var Drupal\file\Entity\File $file */ ++ $file = $this->entityTypeManager->getStorage('file')->load($thumb); ++ if (isset($file)) { ++ $file->setPermanent(); ++ $file->save(); ++ ++ // Add the file to the usage calculation. ++ $this->fileUsage->add($file, 'ckeditor_templates', 'media', $file->id()); ++ } ++ } ++ } ++ catch (InvalidPluginDefinitionException | PluginNotFoundException $e) { ++ $this->logger('templates')->critical($e->getMessage()); ++ } ++ + $this->messenger()->addMessage($this->t('Saved the %label CKEditor Template.', [ + '%label' => $template->label(), + ])); +-- +GitLab + + +From 47a0f901cb16846c02cd37197fc5596a3847540e Mon Sep 17 00:00:00 2001 +From: Gordon Heydon +Date: Mon, 13 Mar 2023 11:28:45 +1100 +Subject: [PATCH 03/11] Remove LICENSE.txt + +--- + LICENSE.txt | 339 ---------------------------------------------------- + 1 file changed, 339 deletions(-) + delete mode 100644 LICENSE.txt + +diff --git a/LICENSE.txt b/LICENSE.txt +deleted file mode 100644 +index d159169..0000000 +--- a/LICENSE.txt ++++ /dev/null +@@ -1,339 +0,0 @@ +- GNU GENERAL PUBLIC LICENSE +- Version 2, June 1991 +- +- Copyright (C) 1989, 1991 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. +- +- Preamble +- +- The licenses for most software are designed to take away your +-freedom to share and change it. By contrast, the GNU General Public +-License is intended to guarantee your freedom to share and change free +-software--to make sure the software is free for all its users. This +-General Public License applies to most of the Free Software +-Foundation's software and to any other program whose authors commit to +-using it. (Some other Free Software Foundation software is covered by +-the GNU Lesser General Public License instead.) You can apply it to +-your programs, too. +- +- When we speak of free software, we are referring to freedom, 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 or use pieces of it +-in new free programs; and that you know you can do these things. +- +- To protect your rights, we need to make restrictions that forbid +-anyone to deny you these rights or to ask you to surrender the rights. +-These restrictions translate to certain responsibilities for you if you +-distribute copies of the software, or if you modify it. +- +- For example, if you distribute copies of such a program, whether +-gratis or for a fee, you must give the recipients all the rights that +-you have. You must make sure that they, too, receive or can get the +-source code. And you must show them these terms so they know their +-rights. +- +- We protect your rights with two steps: (1) copyright the software, and +-(2) offer you this license which gives you legal permission to copy, +-distribute and/or modify the software. +- +- Also, for each author's protection and ours, we want to make certain +-that everyone understands that there is no warranty for this free +-software. If the software is modified by someone else and passed on, we +-want its recipients to know that what they have is not the original, so +-that any problems introduced by others will not reflect on the original +-authors' reputations. +- +- Finally, any free program is threatened constantly by software +-patents. We wish to avoid the danger that redistributors of a free +-program will individually obtain patent licenses, in effect making the +-program proprietary. To prevent this, we have made it clear that any +-patent must be licensed for everyone's free use or not licensed at all. +- +- The precise terms and conditions for copying, distribution and +-modification follow. +- +- GNU GENERAL PUBLIC LICENSE +- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION +- +- 0. This License applies to any program or other work which contains +-a notice placed by the copyright holder saying it may be distributed +-under the terms of this General Public License. The "Program", below, +-refers to any such program or work, and a "work based on the Program" +-means either the Program or any derivative work under copyright law: +-that is to say, a work containing the Program or a portion of it, +-either verbatim or with modifications and/or translated into another +-language. (Hereinafter, translation is included without limitation in +-the term "modification".) Each licensee is addressed as "you". +- +-Activities other than copying, distribution and modification are not +-covered by this License; they are outside its scope. The act of +-running the Program is not restricted, and the output from the Program +-is covered only if its contents constitute a work based on the +-Program (independent of having been made by running the Program). +-Whether that is true depends on what the Program does. +- +- 1. You may copy and distribute verbatim copies of the Program's +-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 give any other recipients of the Program a copy of this License +-along with the Program. +- +-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 Program or any portion +-of it, thus forming a work based on the Program, 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) You must cause the modified files to carry prominent notices +- stating that you changed the files and the date of any change. +- +- b) You must cause any work that you distribute or publish, that in +- whole or in part contains or is derived from the Program or any +- part thereof, to be licensed as a whole at no charge to all third +- parties under the terms of this License. +- +- c) If the modified program normally reads commands interactively +- when run, you must cause it, when started running for such +- interactive use in the most ordinary way, to print or display an +- announcement including an appropriate copyright notice and a +- notice that there is no warranty (or else, saying that you provide +- a warranty) and that users may redistribute the program under +- these conditions, and telling the user how to view a copy of this +- License. (Exception: if the Program itself is interactive but +- does not normally print such an announcement, your work based on +- the Program is not required to print an announcement.) +- +-These requirements apply to the modified work as a whole. If +-identifiable sections of that work are not derived from the Program, +-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 Program, 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 Program. +- +-In addition, mere aggregation of another work not based on the Program +-with the Program (or with a work based on the Program) on a volume of +-a storage or distribution medium does not bring the other work under +-the scope of this License. +- +- 3. You may copy and distribute the Program (or a work based on it, +-under Section 2) in object code or executable form under the terms of +-Sections 1 and 2 above provided that you also do one of the following: +- +- a) 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; or, +- +- b) Accompany it with a written offer, valid for at least three +- years, to give any third party, for a charge no more than your +- cost of physically performing source distribution, a complete +- machine-readable copy of the corresponding source code, to be +- distributed under the terms of Sections 1 and 2 above on a medium +- customarily used for software interchange; or, +- +- c) Accompany it with the information you received as to the offer +- to distribute corresponding source code. (This alternative is +- allowed only for noncommercial distribution and only if you +- received the program in object code or executable form with such +- an offer, in accord with Subsection b above.) +- +-The source code for a work means the preferred form of the work for +-making modifications to it. For an executable work, 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 executable. However, as a +-special exception, the source code 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. +- +-If distribution of executable or 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 counts as +-distribution of the source code, even though third parties are not +-compelled to copy the source along with the object code. +- +- 4. You may not copy, modify, sublicense, or distribute the Program +-except as expressly provided under this License. Any attempt +-otherwise to copy, modify, sublicense or distribute the Program 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. +- +- 5. 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 Program or its derivative works. These actions are +-prohibited by law if you do not accept this License. Therefore, by +-modifying or distributing the Program (or any work based on the +-Program), you indicate your acceptance of this License to do so, and +-all its terms and conditions for copying, distributing or modifying +-the Program or works based on it. +- +- 6. Each time you redistribute the Program (or any work based on the +-Program), the recipient automatically receives a license from the +-original licensor to copy, distribute or modify the Program 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 to +-this License. +- +- 7. 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 Program at all. For example, if a patent +-license would not permit royalty-free redistribution of the Program 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 Program. +- +-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. +- +- 8. If the distribution and/or use of the Program is restricted in +-certain countries either by patents or by copyrighted interfaces, the +-original copyright holder who places the Program 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. +- +- 9. The Free Software Foundation may publish revised and/or new versions +-of the 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 Program +-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 Program does not specify a version number of +-this License, you may choose any version ever published by the Free Software +-Foundation. +- +- 10. If you wish to incorporate parts of the Program into other free +-programs whose distribution conditions are different, 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 +- +- 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +-FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +-OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +-PROVIDE THE PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE +-PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +-REPAIR OR CORRECTION. +- +- 12. 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 PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER +-PROGRAMS), 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 Programs +- +- If you develop a new program, and you want it to be of the greatest +-possible use to the public, the best way to achieve this is to make it +-free software which everyone can redistribute and change under these terms. +- +- To do so, attach the following notices to the program. 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 program is free software; you can redistribute it and/or modify +- it under the terms of the GNU General Public License as published by +- the Free Software Foundation; either version 2 of the License, or +- (at your option) any later version. +- +- This program 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 General Public License for more details. +- +- You should have received a copy of the GNU General Public License along +- with this program; 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. +- +-If the program is interactive, make it output a short notice like this +-when it starts in an interactive mode: +- +- Gnomovision version 69, Copyright (C) year name of author +- Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. +- This is free software, and you are welcome to redistribute it +- under certain conditions; type `show c' for details. +- +-The hypothetical commands `show w' and `show c' should show the appropriate +-parts of the General Public License. Of course, the commands you use may +-be called something other than `show w' and `show c'; they could even be +-mouse-clicks or menu items--whatever suits your program. +- +-You should also get your employer (if you work as a programmer) or your +-school, if any, to sign a "copyright disclaimer" for the program, if +-necessary. Here is a sample; alter the names: +- +- Yoyodyne, Inc., hereby disclaims all copyright interest in the program +- `Gnomovision' (which makes passes at compilers) written by James Hacker. +- +- , 1 April 1989 +- Ty Coon, President of Vice +- +-This General Public License does not permit incorporating your program into +-proprietary programs. If your program is a subroutine library, you may +-consider it more useful to permit linking proprietary applications with the +-library. If this is what you want to do, use the GNU Lesser General +-Public License instead of this License. +-- +GitLab + + +From d56fa512410bda7c11c2f445e25aaa570addb940 Mon Sep 17 00:00:00 2001 +From: Gordon Heydon +Date: Mon, 13 Mar 2023 12:12:25 +1100 +Subject: [PATCH 04/11] Restore ckeditor 4 version and organise ckeditor5 + version to be in line with other project. + +--- + ckeditor_templates.ckeditor5.yml | 4 +- + ckeditor_templates.info.yml | 4 +- + ckeditor_templates.libraries.yml | 21 +- + css/cke5_templates.admin.css | 1 + + ...s.dialog.css => cke5_templates.dialog.css} | 0 + css/cke_templates.admin.css | 1 - + css/ckeditor_templates.css | 8 + + .../ckeditor_templates/sass}/dialog.scss | 0 + .../ckeditor_templates}/src/app.js | 2 +- + .../src/ckeditorTemplates.js | 0 + .../src/ckeditorTemplatesCommand.js | 0 + .../src/ckeditorTemplatesEditing.js | 0 + .../src/ckeditorTemplatesUI.js | 0 + .../theme/icons/templates.svg | 0 + .../theme/images/placeholder.svg | 0 + js/ckeditor_templates.admin.js | 32 +++ + js/ckeditor_templates.dialog.js | 22 +++ + js/dist/ckeditorTemplates.js | 2 +- + .../CKEditorPlugin/CkeditorTemplates.php | 183 ++++++++++++++++++ + templates/ckeditor_templates.js.example | 83 ++++++++ + webpack.config.js | 8 +- + 21 files changed, 354 insertions(+), 17 deletions(-) + create mode 100644 css/cke5_templates.admin.css + rename css/{cke_templates.dialog.css => cke5_templates.dialog.css} (100%) + delete mode 100644 css/cke_templates.admin.css + create mode 100644 css/ckeditor_templates.css + rename {sass => js/ckeditor5_plugins/ckeditor_templates/sass}/dialog.scss (100%) + rename js/{plugin => ckeditor5_plugins/ckeditor_templates}/src/app.js (71%) + rename js/{plugin => ckeditor5_plugins/ckeditor_templates}/src/ckeditorTemplates.js (100%) + rename js/{plugin => ckeditor5_plugins/ckeditor_templates}/src/ckeditorTemplatesCommand.js (100%) + rename js/{plugin => ckeditor5_plugins/ckeditor_templates}/src/ckeditorTemplatesEditing.js (100%) + rename js/{plugin => ckeditor5_plugins/ckeditor_templates}/src/ckeditorTemplatesUI.js (100%) + rename js/{plugin => ckeditor5_plugins/ckeditor_templates}/theme/icons/templates.svg (100%) + rename js/{plugin => ckeditor5_plugins/ckeditor_templates}/theme/images/placeholder.svg (100%) + create mode 100644 js/ckeditor_templates.admin.js + create mode 100644 js/ckeditor_templates.dialog.js + create mode 100644 src/Plugin/CKEditorPlugin/CkeditorTemplates.php + create mode 100644 templates/ckeditor_templates.js.example + +diff --git a/ckeditor_templates.ckeditor5.yml b/ckeditor_templates.ckeditor5.yml +index a387b3c..f5caec4 100644 +--- a/ckeditor_templates.ckeditor5.yml ++++ b/ckeditor_templates.ckeditor5.yml +@@ -15,8 +15,8 @@ ckeditor_templates_plugin: + drupal: + label: Templates + elements: false +- library: ckeditor_templates/ckeditor.templates.dialog +- admin_library: ckeditor_templates/ckeditor.templates.admin ++ library: ckeditor_templates/ckeditor5.templates.dialog ++ admin_library: ckeditor_templates/ckeditor5.templates.admin + class: Drupal\ckeditor_templates\Plugin\CKEditor5Plugin\CKEditorTemplatesDialog + toolbar_items: + ckeditorTemplates: +diff --git a/ckeditor_templates.info.yml b/ckeditor_templates.info.yml +index 6975f55..b34cca3 100644 +--- a/ckeditor_templates.info.yml ++++ b/ckeditor_templates.info.yml +@@ -2,6 +2,4 @@ name: CKEditor Templates + description: 'Integrates the CKEditor templates plugin.' + package: CKEditor + type: module +-core_version_requirement: ^9.3 || ^10 +-dependencies: +-- drupal:ckeditor5 ++core_version_requirement: ^8 || ^9 || ^10 +diff --git a/ckeditor_templates.libraries.yml b/ckeditor_templates.libraries.yml +index b5ea02b..ef128b5 100644 +--- a/ckeditor_templates.libraries.yml ++++ b/ckeditor_templates.libraries.yml +@@ -1,16 +1,27 @@ + ckeditor.templates.dialog: +- version: 2.x ++ version: 1.x + css: + theme: +- css/cke_templates.dialog.css: {minified: true} ++ css/ckeditor_templates.css: {} ++ js: ++ js/ckeditor_templates.dialog.js: {} ++ ++ckeditor.templates.admin: ++ version: 1.x ++ js: ++ js/ckeditor_templates.admin.js: {} ++ ++ckeditor5.templates.dialog: ++ css: ++ theme: ++ css/cke5_templates.dialog.css: {minified: true} + js: + js/dist/ckeditorTemplates.js: {} + dependencies: + - ckeditor5/ckeditor5 + - editor/drupal.editor.dialog + +-ckeditor.templates.admin: +- version: 2.x ++ckeditor5.templates.admin: + css: + theme: +- css/cke_templates.admin.css: {} ++ css/cke5_templates.admin.css: {} +\ No newline at end of file +diff --git a/css/cke5_templates.admin.css b/css/cke5_templates.admin.css +new file mode 100644 +index 0000000..850f058 +--- /dev/null ++++ b/css/cke5_templates.admin.css +@@ -0,0 +1 @@ ++.ckeditor5-toolbar-button-ckeditorTemplates {background-image: url(../js/ckeditor5_plugins/ckeditor_templates/theme/icons/templates.svg)} +diff --git a/css/cke_templates.dialog.css b/css/cke5_templates.dialog.css +similarity index 100% +rename from css/cke_templates.dialog.css +rename to css/cke5_templates.dialog.css +diff --git a/css/cke_templates.admin.css b/css/cke_templates.admin.css +deleted file mode 100644 +index cd52fb2..0000000 +--- a/css/cke_templates.admin.css ++++ /dev/null +@@ -1 +0,0 @@ +-.ckeditor5-toolbar-button-ckeditorTemplates {background-image: url(../js/plugin/theme/icons/templates.svg)} +diff --git a/css/ckeditor_templates.css b/css/ckeditor_templates.css +new file mode 100644 +index 0000000..70a2f30 +--- /dev/null ++++ b/css/ckeditor_templates.css +@@ -0,0 +1,8 @@ ++.cke_templates_dialog .cke_dialog_ui_checkbox input { ++ vertical-align: middle; ++} ++ ++/* Set correct alignment for the "Replace actual content" checkbox */ ++.cke_reset_all .cke_templates_dialog .cke_dialog_ui_checkbox label { ++ display: inline-block; ++} +diff --git a/sass/dialog.scss b/js/ckeditor5_plugins/ckeditor_templates/sass/dialog.scss +similarity index 100% +rename from sass/dialog.scss +rename to js/ckeditor5_plugins/ckeditor_templates/sass/dialog.scss +diff --git a/js/plugin/src/app.js b/js/ckeditor5_plugins/ckeditor_templates/src/app.js +similarity index 71% +rename from js/plugin/src/app.js +rename to js/ckeditor5_plugins/ckeditor_templates/src/app.js +index 8634917..520fecb 100644 +--- a/js/plugin/src/app.js ++++ b/js/ckeditor5_plugins/ckeditor_templates/src/app.js +@@ -1,5 +1,5 @@ + import CKEditorTemplates from './ckeditorTemplates'; +-import './../../../sass/dialog.scss'; ++import './../sass/dialog.scss'; + + export default { + CKEditorTemplates +diff --git a/js/plugin/src/ckeditorTemplates.js b/js/ckeditor5_plugins/ckeditor_templates/src/ckeditorTemplates.js +similarity index 100% +rename from js/plugin/src/ckeditorTemplates.js +rename to js/ckeditor5_plugins/ckeditor_templates/src/ckeditorTemplates.js +diff --git a/js/plugin/src/ckeditorTemplatesCommand.js b/js/ckeditor5_plugins/ckeditor_templates/src/ckeditorTemplatesCommand.js +similarity index 100% +rename from js/plugin/src/ckeditorTemplatesCommand.js +rename to js/ckeditor5_plugins/ckeditor_templates/src/ckeditorTemplatesCommand.js +diff --git a/js/plugin/src/ckeditorTemplatesEditing.js b/js/ckeditor5_plugins/ckeditor_templates/src/ckeditorTemplatesEditing.js +similarity index 100% +rename from js/plugin/src/ckeditorTemplatesEditing.js +rename to js/ckeditor5_plugins/ckeditor_templates/src/ckeditorTemplatesEditing.js +diff --git a/js/plugin/src/ckeditorTemplatesUI.js b/js/ckeditor5_plugins/ckeditor_templates/src/ckeditorTemplatesUI.js +similarity index 100% +rename from js/plugin/src/ckeditorTemplatesUI.js +rename to js/ckeditor5_plugins/ckeditor_templates/src/ckeditorTemplatesUI.js +diff --git a/js/plugin/theme/icons/templates.svg b/js/ckeditor5_plugins/ckeditor_templates/theme/icons/templates.svg +similarity index 100% +rename from js/plugin/theme/icons/templates.svg +rename to js/ckeditor5_plugins/ckeditor_templates/theme/icons/templates.svg +diff --git a/js/plugin/theme/images/placeholder.svg b/js/ckeditor5_plugins/ckeditor_templates/theme/images/placeholder.svg +similarity index 100% +rename from js/plugin/theme/images/placeholder.svg +rename to js/ckeditor5_plugins/ckeditor_templates/theme/images/placeholder.svg +diff --git a/js/ckeditor_templates.admin.js b/js/ckeditor_templates.admin.js +new file mode 100644 +index 0000000..372e6d8 +--- /dev/null ++++ b/js/ckeditor_templates.admin.js +@@ -0,0 +1,32 @@ ++/** ++ * @file ++ * CKEditor 'templates' plugin admin behavior. ++ */ ++ ++(function ($, Drupal, drupalSettings) { ++ ++ 'use strict'; ++ ++ /** ++ * Provides the summary for the "templates" plugin settings vertical tab. ++ * ++ * @type {Drupal~behavior} ++ * ++ * @prop {Drupal~behaviorAttach} attach ++ * Attaches summary behaviour to the "templates" settings vertical tab. ++ */ ++ Drupal.behaviors.ckeditorTemplatesSettingsSummary = { ++ attach: function () { ++ $('[data-ckeditor-plugin-id="templates"]').drupalSetSummary(function (context) { ++ var templatePathValue = $('input[name="editor[settings][plugins][templates][template_path]').val(); ++ var replaceContentValue = $('input[name="editor[settings][plugins][templates][replace_content]').is(':checked'); ++ ++ var templatePathOutput = templatePathValue ? 'Template file overridden.' : 'Default or theme template file.'; ++ var replaceContentOutput = replaceContentValue ? '"Replace content" checked' : '"Replace content" unchecked'; ++ ++ return templatePathOutput + '
' + replaceContentOutput; ++ }); ++ } ++ }; ++ ++})(jQuery, Drupal, drupalSettings); +diff --git a/js/ckeditor_templates.dialog.js b/js/ckeditor_templates.dialog.js +new file mode 100644 +index 0000000..58cfa0c +--- /dev/null ++++ b/js/ckeditor_templates.dialog.js +@@ -0,0 +1,22 @@ ++/** ++ * @file ++ * Override ckeditor template dialog style. ++ */ ++ ++(function (CKEDITOR) { ++ ++ 'use strict'; ++ ++ CKEDITOR.on('dialogDefinition', function (ev) { ++ var dialogName = ev.data.name; ++ var dialog = ev.data.definition.dialog; ++ ++ if (dialogName === 'templates') { ++ dialog.on('show', function () { ++ var dialogElement = dialog.getElement().getFirst(); ++ dialogElement.addClass('cke_templates_dialog'); ++ }); ++ } ++ }); ++ ++})(CKEDITOR); +diff --git a/js/dist/ckeditorTemplates.js b/js/dist/ckeditorTemplates.js +index d56d71c..fb6ebc3 100644 +--- a/js/dist/ckeditorTemplates.js ++++ b/js/dist/ckeditorTemplates.js +@@ -1 +1 @@ +-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.ckeditorTemplates=t())}(self,(()=>(()=>{var e={"ckeditor5/src/core.js":(e,t,o)=>{e.exports=o("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/ui.js":(e,t,o)=>{e.exports=o("dll-reference CKEditor5.dll")("./src/ui.js")},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},t={};function o(r){var s=t[r];if(void 0!==s)return s.exports;var i=t[r]={exports:{}};return e[r](i,i.exports,o),i.exports}o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var r={};return(()=>{"use strict";o.d(r,{default:()=>d});var e=o("ckeditor5/src/core.js"),t=o("ckeditor5/src/ui.js");class s extends e.Plugin{init(){const e=this.editor,o=this.editor.config.get("ckeditorTemplates");o&&o.openDialog&&o.dialogSettings&&o.dialogUrl&&e.ui.componentFactory.add("ckeditorTemplates",(r=>{const s=new t.ButtonView(r);s.set({label:Drupal.t("Templates"),icon:'\n',tooltip:!0});const i=e.commands.get("ckeditorTemplates");return s.bind("isOn","isEnabled").to(i,"value","isEnabled"),this.listenTo(s,"execute",(()=>{const t=o.dialogUrl,r=o.dialogSettings;o.openDialog(t,(({htmlCode:t,replace:o})=>{e.execute("ckeditorTemplates",t,o)}),r)})),s}))}}class i extends e.Command{refresh(){const e=this.editor.model,t=e.document.selection,o=e.schema.findAllowedParent(t.getFirstPosition(),"ckeditorTemplates");this.isEnabled=!!o}execute(e,t){const o=this.editor,r=o.data;if(t)r.set(e);else{const t=o.model;t.change((()=>{const o=r.processor.toView(e),s=r.toModel(o);t.insertContent(s)}))}}}class n extends e.Plugin{static get requires(){return[i]}init(){const e=this.editor,t="ckeditorTemplates";this.editor.model.schema.register(t,{allowWhere:"$block",isObject:!0,isContent:!0,isBlock:!0}),this.editor.commands.add(t,new i(e))}static get pluginName(){return"ckeditorTemplatesEditing"}}class l extends e.Plugin{static get requires(){return[s,n]}static get pluginName(){return"ckeditorTemplates"}}const d={CKEditorTemplates:l}})(),r=r.default})())); +\ No newline at end of file ++!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.ckeditorTemplates=t())}(self,(()=>(()=>{var e={"ckeditor5/src/core.js":(e,t,o)=>{e.exports=o("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/ui.js":(e,t,o)=>{e.exports=o("dll-reference CKEditor5.dll")("./src/ui.js")},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},t={};function o(r){var s=t[r];if(void 0!==s)return s.exports;var i=t[r]={exports:{}};return e[r](i,i.exports,o),i.exports}o.d=(e,t)=>{for(var r in t)o.o(t,r)&&!o.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},o.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var r={};return(()=>{"use strict";o.d(r,{default:()=>d});var e=o("ckeditor5/src/core.js"),t=o("ckeditor5/src/ui.js");class s extends e.Plugin{init(){const e=this.editor,o=this.editor.config.get("ckeditorTemplates");o&&o.openDialog&&o.dialogSettings&&o.dialogUrl&&e.ui.componentFactory.add("ckeditorTemplates",(r=>{const s=new t.ButtonView(r);s.set({label:Drupal.t("Templates"),icon:'\r\n',tooltip:!0});const i=e.commands.get("ckeditorTemplates");return s.bind("isOn","isEnabled").to(i,"value","isEnabled"),this.listenTo(s,"execute",(()=>{const t=o.dialogUrl,r=o.dialogSettings;o.openDialog(t,(({htmlCode:t,replace:o})=>{e.execute("ckeditorTemplates",t,o)}),r)})),s}))}}class i extends e.Command{refresh(){const e=this.editor.model,t=e.document.selection,o=e.schema.findAllowedParent(t.getFirstPosition(),"ckeditorTemplates");this.isEnabled=!!o}execute(e,t){const o=this.editor,r=o.data;if(t)r.set(e);else{const t=o.model;t.change((()=>{const o=r.processor.toView(e),s=r.toModel(o);t.insertContent(s)}))}}}class n extends e.Plugin{static get requires(){return[i]}init(){const e=this.editor,t="ckeditorTemplates";this.editor.model.schema.register(t,{allowWhere:"$block",isObject:!0,isContent:!0,isBlock:!0}),this.editor.commands.add(t,new i(e))}static get pluginName(){return"ckeditorTemplatesEditing"}}class l extends e.Plugin{static get requires(){return[s,n]}static get pluginName(){return"ckeditorTemplates"}}const d={CKEditorTemplates:l}})(),r=r.default})())); +\ No newline at end of file +diff --git a/src/Plugin/CKEditorPlugin/CkeditorTemplates.php b/src/Plugin/CKEditorPlugin/CkeditorTemplates.php +new file mode 100644 +index 0000000..79e1789 +--- /dev/null ++++ b/src/Plugin/CKEditorPlugin/CkeditorTemplates.php +@@ -0,0 +1,183 @@ ++get('config.factory') ++ ); ++ } ++ ++ /** ++ * Constructs a Drupal\Component\Plugin\PluginBase object. ++ * ++ * @param array $configuration ++ * A configuration array containing information about the plugin instance. ++ * @param string $plugin_id ++ * The plugin_id for the plugin instance. ++ * @param mixed $plugin_definition ++ * The plugin implementation definition. ++ * @param \Drupal\Core\Config\ConfigFactory $configFactoryService ++ * Drupal Configuration Factory Service. ++ */ ++ public function __construct(array $configuration, $plugin_id, $plugin_definition, ConfigFactory $configFactoryService) { ++ parent::__construct($configuration, $plugin_id, $plugin_definition); ++ ++ $this->configFactoryService = $configFactoryService; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function getFile() { ++ return $this->getTemplatesPluginPath() . '/plugin.js'; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function getLibraries(Editor $editor) { ++ return ['ckeditor_templates/ckeditor.templates.dialog']; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function getButtons() { ++ return [ ++ 'Templates' => [ ++ 'label' => t('Templates'), ++ 'image' => $this->getTemplatesPluginPath() . '/icons/templates.png', ++ ], ++ ]; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function getConfig(Editor $editor) { ++ $config = []; ++ $settings = $editor->getSettings(); ++ // Set replace content default value if set. ++ if (isset($settings['plugins']['templates']['replace_content'])) { ++ $config['templates_replaceContent'] = $settings['plugins']['templates']['replace_content']; ++ } ++ // Set template files default value if set. ++ if (isset($settings['plugins']['templates']['template_path']) && !empty($settings['plugins']['templates']['template_path'])) { ++ $config['templates_files'] = [$settings['plugins']['templates']['template_path']]; ++ } ++ else { ++ // Use templates plugin default file. ++ $config['templates_files'] = $this->getTemplatesDefaultPath(); ++ } ++ return $config; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function settingsForm(array $form, FormStateInterface $form_state, Editor $editor) { ++ // Defaults. ++ $config = [ ++ 'replace_content' => FALSE, ++ 'template_path' => '', ++ ]; ++ ++ $settings = $editor->getSettings(); ++ ++ if (isset($settings['plugins']['templates'])) { ++ $config = $settings['plugins']['templates']; ++ } ++ ++ $form['template_path'] = [ ++ '#title' => t('Template definition file'), ++ '#type' => 'textfield', ++ '#default_value' => $config['template_path'], ++ '#description' => t('Path to the javascript file defining the templates, relative to drupal root (starting with "/"). By default, it looks in your default theme directory for a file named "templates/ckeditor_templates.js"'), ++ ]; ++ ++ $form['replace_content'] = [ ++ '#title' => t('Replace content default value'), ++ '#type' => 'checkbox', ++ '#default_value' => $config['replace_content'], ++ '#description' => t('Whether the "Replace actual contents" checkbox is checked by default in the Templates dialog'), ++ ]; ++ ++ $form['#attached']['library'][] = 'ckeditor_templates/ckeditor.templates.admin'; ++ ++ return $form; ++ } ++ ++ /** ++ * Return ckeditor templates plugin path relative to drupal root. ++ * ++ * @return string ++ * Relative path to the ckeditor plugin folder ++ */ ++ private function getTemplatesPluginPath() { ++ $pluginPath = 'libraries/ckeditor/plugins/templates'; ++ ++ if (!file_exists(DRUPAL_ROOT . '/' . $pluginPath)) { ++ // keep supporting module legacy path to avoid breaking change ++ // using this path is deprecated ++ $pluginPath = 'libraries/templates'; ++ } ++ ++ return $pluginPath; ++ } ++ ++ /** ++ * Generate the path to the template file. ++ * ++ * The file will be picked from : ++ * - the default theme if the file exists ++ * - the ckeditor template directory otherwise. ++ * ++ * @return array ++ * List of path to the template file ++ */ ++ private function getTemplatesDefaultPath() { ++ // Default to module folder. ++ $defaultPath = base_path() . $this->getTemplatesPluginPath() . '/templates/default.js'; ++ ++ // Get site default theme name. ++ $defaultThemConfig = $this->configFactoryService->get('system.theme'); ++ $defaultThemeName = $defaultThemConfig->get('default'); ++ ++ $defaultThemeFileAbsolutePath = DRUPAL_ROOT . '/' . drupal_get_path('theme', $defaultThemeName) . '/templates/ckeditor_templates.js'; ++ if (file_exists($defaultThemeFileAbsolutePath)) { ++ $defaultPath = base_path() . drupal_get_path('theme', $defaultThemeName) . '/templates/ckeditor_templates.js'; ++ } ++ ++ return [$defaultPath]; ++ } ++ ++} +diff --git a/templates/ckeditor_templates.js.example b/templates/ckeditor_templates.js.example +new file mode 100644 +index 0000000..ffafdbc +--- /dev/null ++++ b/templates/ckeditor_templates.js.example +@@ -0,0 +1,83 @@ ++// Override the default template set ++CKEDITOR.addTemplates( 'default', { ++ // The name of sub folder which hold the shortcut preview images of the ++ // templates. Determine base path of drupal installation if any ++ // (ckeditor could possibly be loaded w/o drupalSettings). ++ imagesPath: ((drupalSettings && drupalSettings.path) ? drupalSettings.path.baseUrl : '/') + 'themes/custom/mytheme/images/ckeditor/', ++ ++ // The templates definitions. ++ templates: [ { ++ title: 'Image and Title module', ++ image: 'template1.gif', ++ description: 'One main image with a title and text that surround the image.', ++ html: '

' + ++ // Use src=" " so image is not filtered out by the editor as incorrect (src is required). ++ '' + ++ 'Type the title here' + ++ '

' + ++ '

' + ++ 'Type the text here' + ++ '

' ++ }, ++ { ++ title: 'Strange Template', ++ image: 'template2.gif', ++ description: 'A template that defines two colums, each one with a title, and some text.', ++ html: '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '
' + ++ '

Title 1

' + ++ '
' + ++ '

Title 2

' + ++ '
' + ++ 'Text 1' + ++ '' + ++ 'Text 2' + ++ '
' + ++ '

' + ++ 'More text goes here.' + ++ '

' ++ }, ++ { ++ title: 'Text and Table', ++ image: 'template3.gif', ++ description: 'A title with some text and a table.', ++ html: '
' + ++ '

' + ++ 'Title goes here' + ++ '

' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '' + ++ '
' + ++ 'Table title' + ++ '
   
   
   
' + ++ '

' + ++ 'Type the text here' + ++ '

' + ++ '
' ++ } ] ++} ); +diff --git a/webpack.config.js b/webpack.config.js +index e27ce74..ababa70 100644 +--- a/webpack.config.js ++++ b/webpack.config.js +@@ -25,7 +25,7 @@ module.exports = [ + moduleIds: 'named' + }, + entry: { +- path: path.resolve(__dirname, 'js/plugin/src/app.js') ++ path: path.resolve(__dirname, 'js/ckeditor5_plugins/ckeditor_templates/src/app.js') + }, + output: { + path: path.resolve(__dirname, 'js/dist'), +@@ -41,17 +41,17 @@ module.exports = [ + name: 'CKEditor5.dll' + }), + new MiniCssExtractPlugin({ +- filename: '../../css/cke_templates.dialog.css' ++ filename: '../../css/cke5_templates.dialog.css' + }) + ], + module: { + rules: [ + { +- test: /js[/\\]plugin[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/, ++ test: /js[/\\]ckeditor5_plugins[/\\].*?[/\\]theme[/\\]icons[/\\][^/\\]+\.svg$/, + use: ['raw-loader'] + }, + { +- test: /js[/\\]plugin[/\\]theme[/\\][^/\\]+\.css$/, ++ test: /js[/\\]ckeditor5_plugins[/\\].*?[/\\]theme[/\\][^/\\]+\.css$/, + use: [ + { + loader: 'style-loader', +-- +GitLab + + +From 92f3d832c65f1a9631cf2f9a07ae15172e0bbe6e Mon Sep 17 00:00:00 2001 +From: Gordon Heydon +Date: Mon, 13 Mar 2023 15:25:39 +1100 +Subject: [PATCH 05/11] Fix up path to the placeholder image. + +--- + src/Form/CKEditorTemplatesDialogForm.php | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/Form/CKEditorTemplatesDialogForm.php b/src/Form/CKEditorTemplatesDialogForm.php +index b9b5b62..f2ca7e3 100644 +--- a/src/Form/CKEditorTemplatesDialogForm.php ++++ b/src/Form/CKEditorTemplatesDialogForm.php +@@ -154,7 +154,7 @@ class CKEditorTemplatesDialogForm extends FormBase { + } + + if (empty($image)) { +- $image = $this->moduleFolder . '/js/plugin/theme/images/placeholder.svg'; ++ $image = $this->moduleFolder . '/js/ckeditor5_plugins/ckeditor_templates/theme/images/placeholder.svg'; + } + + return $image; +-- +GitLab + + +From 67e724f165837b2f153427a15f72d2d7d810df4a Mon Sep 17 00:00:00 2001 +From: Gordon Heydon +Date: Mon, 13 Mar 2023 16:35:24 +1100 +Subject: [PATCH 06/11] Add conversion object to allow upgrade from CKEditor 4 + to 5 + +--- + .../CKEditorTemplatesDialog.php | 63 +++++++++++++++++++ + 1 file changed, 63 insertions(+) + create mode 100644 src/Plugin/CKEditor4To5Upgrade/CKEditorTemplatesDialog.php + +diff --git a/src/Plugin/CKEditor4To5Upgrade/CKEditorTemplatesDialog.php b/src/Plugin/CKEditor4To5Upgrade/CKEditorTemplatesDialog.php +new file mode 100644 +index 0000000..bbe7600 +--- /dev/null ++++ b/src/Plugin/CKEditor4To5Upgrade/CKEditorTemplatesDialog.php +@@ -0,0 +1,63 @@ ++ $sanitized]; ++ break; ++ ++ default: ++ throw new \OutOfBoundsException(); ++ } ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ public function computeCKEditor5PluginSubsetConfiguration(string $cke5_plugin_id, FilterFormatInterface $text_format): ?array { ++ throw new \OutOfBoundsException(); ++ } ++ ++} +-- +GitLab + + +From 9008e302e5c694aae1d50d79f79c835497a75ac0 Mon Sep 17 00:00:00 2001 +From: Dylan Donkersgoed <12239-DylanDonkersgoed@users.noreply.drupalcode.org> +Date: Wed, 22 Mar 2023 18:42:54 +0000 +Subject: [PATCH 07/11] Remove D10 compatibility change from .info.yml + +--- + ckeditor_templates.info.yml | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ckeditor_templates.info.yml b/ckeditor_templates.info.yml +index b34cca3..91e3d1e 100644 +--- a/ckeditor_templates.info.yml ++++ b/ckeditor_templates.info.yml +@@ -2,4 +2,5 @@ name: CKEditor Templates + description: 'Integrates the CKEditor templates plugin.' + package: CKEditor + type: module +-core_version_requirement: ^8 || ^9 || ^10 ++core: 8.x ++core_version_requirement: ^8 || ^9 +-- +GitLab + + +From 67da69513518cd680c83a61c6232d798e6becfaa Mon Sep 17 00:00:00 2001 +From: Marcelo Hespanhol +Date: Mon, 24 Apr 2023 13:36:34 -0400 +Subject: [PATCH 08/11] Include an alternative thumb field + +--- + src/Entity/CKEditorTemplates.php | 8 ++++++++ + src/Form/CKEditorTemplatesDialogForm.php | 11 ++++++++--- + src/Form/CKEditorTemplatesEntityForm.php | 11 ++++++++++- + 3 files changed, 26 insertions(+), 4 deletions(-) + +diff --git a/src/Entity/CKEditorTemplates.php b/src/Entity/CKEditorTemplates.php +index 3ed62ec..d8930a8 100644 +--- a/src/Entity/CKEditorTemplates.php ++++ b/src/Entity/CKEditorTemplates.php +@@ -48,6 +48,7 @@ use Drupal\Core\Entity\EntityStorageInterface; + * "status", + * "description", + * "thumb", ++ * "thumb_alternative", + * "code", + * "formats", + * "weight" +@@ -91,6 +92,13 @@ class CKEditorTemplates extends ConfigEntityBase implements CKEditorTemplatesInt + */ + protected $thumb; + ++ /** ++ * The template thumb_alternative. ++ * ++ * @var string ++ */ ++ protected $thumb_alternative; ++ + /** + * The template HTML code. + * +diff --git a/src/Form/CKEditorTemplatesDialogForm.php b/src/Form/CKEditorTemplatesDialogForm.php +index f2ca7e3..ac863c0 100644 +--- a/src/Form/CKEditorTemplatesDialogForm.php ++++ b/src/Form/CKEditorTemplatesDialogForm.php +@@ -79,7 +79,7 @@ class CKEditorTemplatesDialogForm extends FormBase { + $this->templates[$format->id()] = [ + 'label' => $format->label(), + 'formats' => $format->get('formats') ?? [], +- 'thumb' => $this->getThumb($format->get('thumb')[0] ?? ''), ++ 'thumb' => $this->getThumb($format->get('thumb')[0] ?? '', $format->get('thumb_alternative')), + 'description' => $format->get('description') ?? '', + 'code' => $format->get('code') ?? '', + ]; +@@ -124,13 +124,16 @@ class CKEditorTemplatesDialogForm extends FormBase { + * @param string $thumb + * The thumb image id. + * ++ * @param string $thumb_alternative ++ * The alternative thumb image url. ++ * + * @return string + * The thumb image URL. + * + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + */ +- private function getThumb(string $thumb): string { ++ private function getThumb(string $thumb, string $thumb_alternative): string { + $image = ''; + + if (!empty($thumb)) { +@@ -154,7 +157,9 @@ class CKEditorTemplatesDialogForm extends FormBase { + } + + if (empty($image)) { +- $image = $this->moduleFolder . '/js/ckeditor5_plugins/ckeditor_templates/theme/images/placeholder.svg'; ++ $image = empty($thumb_alternative) ++ ? $this->moduleFolder . '/js/ckeditor5_plugins/ckeditor_templates/theme/images/placeholder.svg' ++ : $thumb_alternative; + } + + return $image; +diff --git a/src/Form/CKEditorTemplatesEntityForm.php b/src/Form/CKEditorTemplatesEntityForm.php +index 6682d35..bae938c 100644 +--- a/src/Form/CKEditorTemplatesEntityForm.php ++++ b/src/Form/CKEditorTemplatesEntityForm.php +@@ -107,7 +107,7 @@ class CKEditorTemplatesEntityForm extends EntityForm { + + $form['thumb'] = [ + '#type' => 'managed_file', +- '#title' => $this->t('Illustration Image/Icon'), ++ '#title' => $this->t('Illustrative Image/Icon'), + '#default_value' => $this->entity->get('thumb'), + '#description' => $this->t('Allowed types: png jpeg jpg gif'), + '#upload_location' => 'public://ckeditor-templates', +@@ -117,6 +117,15 @@ class CKEditorTemplatesEntityForm extends EntityForm { + '#cardinality' => 1, + ]; + ++ $form['thumb_alternative'] = [ ++ '#type' => 'textfield', ++ '#title' => $this->t('Alternative Image/Icon'), ++ '#maxlength' => 255, ++ '#default_value' => $this->entity->get('thumb_alternative'), ++ '#description' => $this->t('Use this field as an alternative to uploading an illustrative image/icon. You can provide a URL or path to an image file (i.e., //domain.com/icon.png, public://icon.png, /modules/my_module/icon.png, /themes/my_theme/icon.png, etc.).'), ++ '#required' => FALSE, ++ ]; ++ + $form['code'] = [ + '#type' => 'textarea', + '#title' => $this->t('HTML Code'), +-- +GitLab + + +From d8262219ead37319e9ba455fb7e8c7e7fe898cb0 Mon Sep 17 00:00:00 2001 +From: Harlor +Date: Tue, 25 Apr 2023 18:47:19 +0200 +Subject: [PATCH 09/11] Add gordons changes from 3273358-46 - 3273358-48 + +--- + ckeditor_templates.libraries.yml | 6 ++++-- + ckeditor_templates.module | 28 ++++++++++++++++++++++++ + css/cke5_templates.dialog.css | 37 +++++++++++++++++++++++++++++++- + 3 files changed, 68 insertions(+), 3 deletions(-) + create mode 100644 ckeditor_templates.module + +diff --git a/ckeditor_templates.libraries.yml b/ckeditor_templates.libraries.yml +index ef128b5..a81ef89 100644 +--- a/ckeditor_templates.libraries.yml ++++ b/ckeditor_templates.libraries.yml +@@ -12,9 +12,10 @@ ckeditor.templates.admin: + js/ckeditor_templates.admin.js: {} + + ckeditor5.templates.dialog: ++ version: 2.x + css: + theme: +- css/cke5_templates.dialog.css: {minified: true} ++ css/cke5_templates.dialog.css: {} + js: + js/dist/ckeditorTemplates.js: {} + dependencies: +@@ -22,6 +23,7 @@ ckeditor5.templates.dialog: + - editor/drupal.editor.dialog + + ckeditor5.templates.admin: ++ version: 2.x + css: + theme: +- css/cke5_templates.admin.css: {} +\ No newline at end of file ++ css/cke5_templates.admin.css: {} +diff --git a/ckeditor_templates.module b/ckeditor_templates.module +new file mode 100644 +index 0000000..4e6c40a +--- /dev/null ++++ b/ckeditor_templates.module +@@ -0,0 +1,28 @@ ++ $value) { ++ if (!isset($variables['attributes'][$delta])) { ++ $variables['attributes'][$delta] = $value; ++ } ++ elseif (is_array($value)) { ++ $variables['attributes'][$delta] = array_merge($variables['attributes'][$delta], $value); ++ } ++ } ++ } ++} +diff --git a/css/cke5_templates.dialog.css b/css/cke5_templates.dialog.css +index d2bfc0f..fc08941 100644 +--- a/css/cke5_templates.dialog.css ++++ b/css/cke5_templates.dialog.css +@@ -1 +1,36 @@ +-.ckeditor-templates-widget-modal .form-radios{margin:0;padding:0}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates{margin:0;padding:0}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates input,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates input{display:none}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates label,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates label{display:flex;margin-top:.75rem;padding:.75rem;border:#bcbcbc 1px solid;align-items:flex-start;user-select:none}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates label:hover,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates label:hover{background-color:#efefef}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates label img,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates label img{width:5rem;margin-right:.75rem}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates label div,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates label div{line-height:1.2rem}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates label div strong,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates label div strong{display:block}.ckeditor-templates-widget-modal .form-radios .form-type-radio.form-item-templates input:checked+label,.ckeditor-templates-widget-modal .form-radios .form-type--radio.form-item--templates input:checked+label{border:#f93 1px solid;background-color:#fffacd} ++.ckeditor-templates-widget-modal .form-radios--templates { ++ margin: 0; ++ padding: 0; ++} ++.ckeditor-templates-widget-modal .form-radios--templates .js-form-type-radio.js-form-item-templates { ++ margin: 0; ++ padding: 0; ++} ++.ckeditor-templates-widget-modal .form-radios--templates .js-form-type-radio.js-form-item-templates input { ++ display: none; ++} ++.ckeditor-templates-widget-modal .form-radios--templates .js-form-type-radio.js-form-item-templates label { ++ display: flex; ++ margin-top: 0.75rem; ++ padding: 0.75rem; ++ border: #bcbcbc 1px solid; ++ align-items: flex-start; ++ user-select: none; ++} ++.ckeditor-templates-widget-modal .form-radios--templates .js-form-type-radio.js-form-item-templates label:hover { ++ background-color: #efefef; ++} ++.ckeditor-templates-widget-modal .form-radios--templates .js-form-type-radio.js-form-item-templates label img { ++ width: 5rem; ++ margin-right: 0.75rem; ++} ++.ckeditor-templates-widget-modal .form-radios--templates .js-form-type-radio.js-form-item-templates label div { ++ line-height: 1.2rem; ++} ++.ckeditor-templates-widget-modal .form-radios--templates .js-form-type-radio.js-form-item-templates label div strong { ++ display: block; ++} ++.ckeditor-templates-widget-modal .form-radios--templates .js-form-type-radio.js-form-item-templates input:checked+label { ++ border: #f93 1px solid; ++ background-color: #fffacd; ++} +-- +GitLab + + +From a8ec97f4412f8654003a690a27528f654a4b26c8 Mon Sep 17 00:00:00 2001 +From: Harlor +Date: Wed, 26 Apr 2023 17:17:43 +0200 +Subject: [PATCH 10/11] Introduce CkeditorTemplate annotation plugin + +--- + ckeditor_templates.routing.yml | 5 +- + ckeditor_templates.services.yml | 4 + + src/Annotation/CkeditorTemplate.php | 48 +++++ + src/CkeditorTemplateInterface.php | 50 +++++ + src/CkeditorTemplatePluginBase.php | 62 +++++++ + src/CkeditorTemplatePluginManager.php | 54 ++++++ + src/Entity/CKEditorTemplates.php | 8 + + src/Form/CKEditorTemplatesDialogForm.php | 175 ++++-------------- + .../CKEditorTemplatesDialog.php | 6 +- + .../CkeditorTemplate/ConfigTemplate.php | 140 ++++++++++++++ + .../Derivative/ConfigTemplateDeriver.php | 78 ++++++++ + 11 files changed, 484 insertions(+), 146 deletions(-) + create mode 100644 ckeditor_templates.services.yml + create mode 100644 src/Annotation/CkeditorTemplate.php + create mode 100644 src/CkeditorTemplateInterface.php + create mode 100644 src/CkeditorTemplatePluginBase.php + create mode 100644 src/CkeditorTemplatePluginManager.php + create mode 100644 src/Plugin/CkeditorTemplate/ConfigTemplate.php + create mode 100644 src/Plugin/Derivative/ConfigTemplateDeriver.php + +diff --git a/ckeditor_templates.routing.yml b/ckeditor_templates.routing.yml +index 1e41357..558b854 100644 +--- a/ckeditor_templates.routing.yml ++++ b/ckeditor_templates.routing.yml +@@ -1,9 +1,12 @@ + ckeditor_templates.selector: +- path: '/admin/config/content/ckeditor-templates/template-selector/{editor_id}' ++ path: '/admin/config/content/ckeditor-templates/template-selector/{editor}' + defaults: + _form: '\Drupal\ckeditor_templates\Form\CKEditorTemplatesDialogForm' + requirements: + _permission: 'use text format advanced' ++ parameters: ++ editor: ++ type: entity:editor + + entity.ckeditor_templates.collection: + path: '/admin/config/content/ckeditor-templates' +diff --git a/ckeditor_templates.services.yml b/ckeditor_templates.services.yml +new file mode 100644 +index 0000000..f129b74 +--- /dev/null ++++ b/ckeditor_templates.services.yml +@@ -0,0 +1,4 @@ ++services: ++ plugin.manager.ckeditor_template: ++ class: Drupal\ckeditor_templates\CkeditorTemplatePluginManager ++ parent: default_plugin_manager +diff --git a/src/Annotation/CkeditorTemplate.php b/src/Annotation/CkeditorTemplate.php +new file mode 100644 +index 0000000..83ca5aa +--- /dev/null ++++ b/src/Annotation/CkeditorTemplate.php +@@ -0,0 +1,48 @@ ++moduleFolder = '/' . $extension_list_module->getPath('ckeditor_templates'); ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function label(): string { ++ // Cast the label to a string since it is a TranslatableMarkup object. ++ return (string) $this->pluginDefinition['label']; ++ } ++ ++ /** ++ * Gets the thumbnail for an image. ++ * ++ * @return string ++ * The thumb image URL. ++ */ ++ public function getThumb(): string { ++ return $this->moduleFolder . '/js/ckeditor5_plugins/ckeditor_templates/theme/images/placeholder.svg'; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function getDescription(): string { ++ return $this->pluginDefinition['description']; ++ } ++ ++} +diff --git a/src/CkeditorTemplatePluginManager.php b/src/CkeditorTemplatePluginManager.php +new file mode 100644 +index 0000000..edfde5c +--- /dev/null ++++ b/src/CkeditorTemplatePluginManager.php +@@ -0,0 +1,54 @@ ++alterInfo('ckeditor_template_info'); ++ $this->setCacheBackend($cache_backend, 'ckeditor_template_plugins'); ++ } ++ ++ /** ++ * Get all available templates. ++ * ++ * @return CkeditorTemplateInterface[] ++ */ ++ public function getTemplates() { ++ $templates = []; ++ $template_definitions = $this->getDefinitions(); ++ uasort($template_definitions, [\Drupal\Component\Utility\SortArray::class, 'sortByWeightElement']); ++ ++ foreach ($template_definitions as $id => $definition) { ++ $templates[$id] = $this->createInstance($id); ++ } ++ ++ return $templates; ++ } ++ ++} +diff --git a/src/Entity/CKEditorTemplates.php b/src/Entity/CKEditorTemplates.php +index d8930a8..3ea0d4b 100644 +--- a/src/Entity/CKEditorTemplates.php ++++ b/src/Entity/CKEditorTemplates.php +@@ -138,4 +138,12 @@ class CKEditorTemplates extends ConfigEntityBase implements CKEditorTemplatesInt + } + } + ++ /** ++ * {@inheritdoc} ++ */ ++ public function save() { ++ parent::save(); ++ \Drupal::service('plugin.manager.ckeditor_template')->clearCachedDefinitions(); ++ } ++ + } +diff --git a/src/Form/CKEditorTemplatesDialogForm.php b/src/Form/CKEditorTemplatesDialogForm.php +index ac863c0..00f5bfe 100644 +--- a/src/Form/CKEditorTemplatesDialogForm.php ++++ b/src/Form/CKEditorTemplatesDialogForm.php +@@ -2,16 +2,13 @@ + + namespace Drupal\ckeditor_templates\Form; + +-use Drupal\Core\Ajax\AjaxResponse; +-use Drupal\Core\Ajax\CloseModalDialogCommand; +-use Drupal\Core\Entity\EntityTypeManagerInterface; +-use Drupal\Core\Extension\ModuleExtensionList; + use Drupal\Core\Form\FormBase; ++use Drupal\Core\Ajax\AjaxResponse; ++use Drupal\editor\EditorInterface; + use Drupal\Core\Form\FormStateInterface; +-use Drupal\Core\File\FileUrlGeneratorInterface; + use Drupal\editor\Ajax\EditorDialogSave; +-use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException; +-use Drupal\Component\Plugin\Exception\PluginNotFoundException; ++use Drupal\Core\Ajax\CloseModalDialogCommand; ++use Drupal\Component\Plugin\PluginManagerInterface; + use Symfony\Component\DependencyInjection\ContainerInterface; + + /** +@@ -20,25 +17,11 @@ use Symfony\Component\DependencyInjection\ContainerInterface; + class CKEditorTemplatesDialogForm extends FormBase { + + /** +- * The entity type manager instance. ++ * The template plugin manager. + * +- * @var \Drupal\Core\Entity\EntityTypeManagerInterface +- */ +- protected EntityTypeManagerInterface $entityTypeManager; +- +- /** +- * The file url generator instance. +- * +- * @var \Drupal\Core\File\FileUrlGeneratorInterface +- */ +- protected FileUrlGeneratorInterface $fileUrlGenerator; +- +- /** +- * The path for the current module folder. +- * +- * @var string ++ * @var PluginManagerInterface + */ +- protected string $moduleFolder; ++ protected $ckeditorTemplateManager; + + /** + * The available templates. +@@ -47,6 +30,13 @@ class CKEditorTemplatesDialogForm extends FormBase { + */ + protected array $templates; + ++ /** ++ * Determines wheter the available templates need to beloaded. ++ * ++ * @var boolean ++ */ ++ protected bool $templatesLoaded = FALSE; ++ + /** + * The AJAX wrapper id. + * +@@ -57,33 +47,11 @@ class CKEditorTemplatesDialogForm extends FormBase { + /** + * Create a new dialog instance. + * +- * @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager +- * The entity type manager instance. +- * @param \Drupal\Core\File\FileUrlGeneratorInterface $file_url_generator +- * The file url generator instance. +- * @param \Drupal\Core\Extension\ModuleExtensionList $extension_list_module +- * The provider for a list of available modules. +- * + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + */ +- public function __construct(EntityTypeManagerInterface $entity_type_manager, FileUrlGeneratorInterface $file_url_generator, ModuleExtensionList $extension_list_module) { +- $this->entityTypeManager = $entity_type_manager; +- $this->fileUrlGenerator = $file_url_generator; +- $this->moduleFolder = '/' . $extension_list_module->getPath('ckeditor_templates'); +- $this->templates = []; +- +- // Load the templates. +- $templates = $this->getTemplates(); +- foreach ($templates as $format) { +- $this->templates[$format->id()] = [ +- 'label' => $format->label(), +- 'formats' => $format->get('formats') ?? [], +- 'thumb' => $this->getThumb($format->get('thumb')[0] ?? '', $format->get('thumb_alternative')), +- 'description' => $format->get('description') ?? '', +- 'code' => $format->get('code') ?? '', +- ]; +- } ++ public function __construct(PluginManagerInterface $ckeditor_template_plugin_manager) { ++ $this->ckeditorTemplateManager = $ckeditor_template_plugin_manager; + } + + /** +@@ -91,80 +59,10 @@ class CKEditorTemplatesDialogForm extends FormBase { + */ + public static function create(ContainerInterface $container): CKEditorTemplatesDialogForm | static { + return new static( +- $container->get('entity_type.manager'), +- $container->get('file_url_generator'), +- $container->get('extension.list.module') ++ $container->get('plugin.manager.ckeditor_template') + ); + } + +- /** +- * Loads the CKEditor Templates. +- * +- * @return \Drupal\Core\Entity\EntityInterface[] +- * A list of CKEditor Template entities. +- * +- * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException +- * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException +- */ +- private function getTemplates(): array { +- $storage = $this->entityTypeManager +- ->getStorage('ckeditor_templates'); +- +- $nids = $storage->getQuery() +- ->condition('status', 1) +- ->sort('weight', 'ASC') +- ->execute(); +- +- return $storage->loadMultiple($nids); +- } +- +- /** +- * Gets the thumbnail for an image. +- * +- * @param string $thumb +- * The thumb image id. +- * +- * @param string $thumb_alternative +- * The alternative thumb image url. +- * +- * @return string +- * The thumb image URL. +- * +- * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException +- * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException +- */ +- private function getThumb(string $thumb, string $thumb_alternative): string { +- $image = ''; +- +- if (!empty($thumb)) { +- $file = $this->entityTypeManager +- ->getStorage('file') +- ->load($thumb); +- +- if (isset($file)) { +- $fileUri = $file->getFileUri(); +- +- $style = $this->entityTypeManager +- ->getStorage('image_style') +- ->load('thumbnail'); +- if (isset($style)) { +- $image = $style->buildUrl($fileUri) ?? ''; +- } +- else { +- $image = $this->fileUrlGenerator->generateAbsoluteString($fileUri) ?? ''; +- } +- } +- } +- +- if (empty($image)) { +- $image = empty($thumb_alternative) +- ? $this->moduleFolder . '/js/ckeditor5_plugins/ckeditor_templates/theme/images/placeholder.svg' +- : $thumb_alternative; +- } +- +- return $image; +- } +- + /** + * {@inheritdoc} + */ +@@ -175,38 +73,28 @@ class CKEditorTemplatesDialogForm extends FormBase { + /** + * {@inheritdoc} + */ +- public function buildForm(array $form, FormStateInterface $form_state, string $editor_id = ''): array { ++ public function buildForm(array $form, FormStateInterface $form_state, EditorInterface $editor = NULL): array { + $templates = []; + + // Gets the templates. +- foreach ($this->templates as $key => $template) { +- if (in_array($editor_id, $template['formats'])) { ++ foreach ($this->ckeditorTemplateManager->getTemplates() as $key => $template) { ++ if (in_array($editor->id(), $template->allowedFormats())) { + $templates[$key] = ' +- ' . $template['label'] . ' ++ ' . $template->label() . ' +
+- ' . $template['label'] . ' +- ' . $template['description'] . ' ++ ' . $template->label() . ' ++ ' . $template->getDescription() . ' +
+ '; + } + } + +- // Gets the editor. +- try { +- $editor = $this->entityTypeManager +- ->getStorage('editor') +- ->load($editor_id); +- } +- catch (InvalidPluginDefinitionException | PluginNotFoundException $e) { +- $this->logger('templates')->critical($e->getMessage()); +- } +- + // Validate there are templates. +- if (empty($templates) || !isset($editor)) { ++ if (empty($templates)) { + $form['warning'] = [ + '#type' => 'markup', + '#markup' => $this->t('There is no template available for the @formatLabel text format.', [ +- '@formatLabel' => $editor?->label() ?? $editor_id, ++ '@formatLabel' => $editor->label(), + ]), + ]; + +@@ -223,6 +111,9 @@ class CKEditorTemplatesDialogForm extends FormBase { + $form['templates'] = [ + '#type' => 'radios', + '#options' => $templates, ++ '#wrapper_attributes' => [ ++ 'class' => ['form-radios--templates'], ++ ], + ]; + + $settings = $editor->getSettings(); +@@ -263,12 +154,12 @@ class CKEditorTemplatesDialogForm extends FormBase { + public function ajaxSubmitForm(array &$form, FormStateInterface $form_state): AjaxResponse | array { + $response = new AjaxResponse(); + +- $template = $form_state->getValue('templates'); +- if (isset($template)) { +- $htmlCode = $this->templates[$template]['code'] ?? ''; +- if (!empty($htmlCode)) { ++ $template_id = $form_state->getValue('templates'); ++ if (isset($template_id)) { ++ $html_code = $this->ckeditorTemplateManager->createInstance($template_id)->getHtml(); ++ if (!empty($html_code)) { + $response->addCommand(new EditorDialogSave([ +- 'htmlCode' => $htmlCode, ++ 'htmlCode' => $html_code, + 'replace' => $form_state->getValue('replace_content'), + ])); + } +diff --git a/src/Plugin/CKEditor5Plugin/CKEditorTemplatesDialog.php b/src/Plugin/CKEditor5Plugin/CKEditorTemplatesDialog.php +index d504e0a..a8fd29c 100644 +--- a/src/Plugin/CKEditor5Plugin/CKEditorTemplatesDialog.php ++++ b/src/Plugin/CKEditor5Plugin/CKEditorTemplatesDialog.php +@@ -56,11 +56,11 @@ class CKEditorTemplatesDialog extends CKEditor5PluginDefault implements CKEditor + * {@inheritdoc} + */ + public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array { +- $dialogUrl = Url::fromRoute('ckeditor_templates.selector', [ +- 'editor_id' => $editor->id(), ++ $dialog_url = Url::fromRoute('ckeditor_templates.selector', [ ++ 'editor' => $editor->id(), + ])->toString(); + +- $static_plugin_config['ckeditorTemplates']['dialogUrl'] = $dialogUrl; ++ $static_plugin_config['ckeditorTemplates']['dialogUrl'] = $dialog_url; + + return $static_plugin_config; + } +diff --git a/src/Plugin/CkeditorTemplate/ConfigTemplate.php b/src/Plugin/CkeditorTemplate/ConfigTemplate.php +new file mode 100644 +index 0000000..3c684fd +--- /dev/null ++++ b/src/Plugin/CkeditorTemplate/ConfigTemplate.php +@@ -0,0 +1,140 @@ ++entityTypeManager = $entity_type_manager; ++ $this->fileUrlGenerator = $file_url_generator; ++ $this->ckeditorTemplateConfig = $entity_type_manager ++ ->getStorage('ckeditor_templates') ++ ->load($plugin_definition['ckeditor_template_id']); ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { ++ return new static( ++ $configuration, ++ $plugin_id, ++ $plugin_definition, ++ $container->get('extension.list.module'), ++ $container->get('entity_type.manager'), ++ $container->get('file_url_generator') ++ ); ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function getThumb(): string { ++ $image = ''; ++ $thumb = $this->ckeditorTemplateConfig->get('thumb')[0]; ++ $thumb_alternative = $this->ckeditorTemplateConfig->get('thumb_alternative'); ++ ++ if (!empty($thumb)) { ++ $file = $this->entityTypeManager ++ ->getStorage('file') ++ ->load($thumb); ++ ++ if (isset($file)) { ++ $fileUri = $file->getFileUri(); ++ ++ $style = $this->entityTypeManager ++ ->getStorage('image_style') ++ ->load('thumbnail'); ++ if (isset($style)) { ++ $image = $style->buildUrl($fileUri) ?? ''; ++ } ++ else { ++ $image = $this->fileUrlGenerator->generateAbsoluteString($fileUri) ?? ''; ++ } ++ } ++ } ++ ++ if (empty($image)) { ++ $image = empty($thumb_alternative) ++ ? parent::getThumb() ++ : $thumb_alternative; ++ } ++ ++ return $image; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function allowedFormats(): array { ++ return $this->ckeditorTemplateConfig->get('formats'); ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function getHtml(): string { ++ return $this->ckeditorTemplateConfig->get('code'); ++ } ++} +diff --git a/src/Plugin/Derivative/ConfigTemplateDeriver.php b/src/Plugin/Derivative/ConfigTemplateDeriver.php +new file mode 100644 +index 0000000..65e3de8 +--- /dev/null ++++ b/src/Plugin/Derivative/ConfigTemplateDeriver.php +@@ -0,0 +1,78 @@ ++entityTypeManager = $entity_type_manager; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public static function create(ContainerInterface $container, $base_plugin_id) { ++ return new static( ++ $container->get('entity_type.manager') ++ ); ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function getDerivativeDefinitions($base_plugin_definition) { ++ foreach ($this->getTemplates() as $ckeditor_template) { ++ $derivative = $base_plugin_definition; ++ $derivative['ckeditor_template_id'] = $ckeditor_template->id(); ++ $derivative['label'] = $ckeditor_template->label(); ++ $derivative['description'] = $ckeditor_template->get('description') ?? ''; ++ $derivative['weight'] = $ckeditor_template->get('weight'); ++ $this->derivatives[$ckeditor_template->id()] = $derivative; ++ } ++ ++ return $this->derivatives; ++ } ++ ++ /** ++ * Loads the CKEditor Templates. ++ * ++ * @return \Drupal\ckeditor_templates\CKEditorTemplatesInterface[] ++ * A list of CKEditor Template entities. ++ * ++ * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException ++ * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException ++ */ ++ private function getTemplates(): array { ++ $storage = $this->entityTypeManager ++ ->getStorage('ckeditor_templates'); ++ ++ $ids = $storage->getQuery() ++ ->condition('status', 1) ++ ->sort('weight', 'ASC') ++ ->execute(); ++ ++ return $storage->loadMultiple($ids); ++ } ++ ++} +-- +GitLab + + +From f569e353a5943caa31c2aa0e47dd97ececdf65f5 Mon Sep 17 00:00:00 2001 +From: Harlor +Date: Wed, 26 Apr 2023 18:14:17 +0200 +Subject: [PATCH 11/11] Minor cleanups to make patch work + +--- + src/CkeditorTemplateInterface.php | 2 +- + src/Form/CKEditorTemplatesDialogForm.php | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/CkeditorTemplateInterface.php b/src/CkeditorTemplateInterface.php +index 478ca86..a235902 100644 +--- a/src/CkeditorTemplateInterface.php ++++ b/src/CkeditorTemplateInterface.php +@@ -25,7 +25,7 @@ interface CkeditorTemplateInterface { + + /** + * Gets the thumbnail for an image. +- * ++ * + * @return string + * The thumb image URL. + */ +diff --git a/src/Form/CKEditorTemplatesDialogForm.php b/src/Form/CKEditorTemplatesDialogForm.php +index 00f5bfe..a88c6ab 100644 +--- a/src/Form/CKEditorTemplatesDialogForm.php ++++ b/src/Form/CKEditorTemplatesDialogForm.php +@@ -36,7 +36,7 @@ class CKEditorTemplatesDialogForm extends FormBase { + * @var boolean + */ + protected bool $templatesLoaded = FALSE; +- ++ + /** + * The AJAX wrapper id. + * +-- +GitLab + diff --git a/patches/composer-patches/fix-applied-patches.patch b/patches/composer-patches/fix-applied-patches.patch new file mode 100644 index 0000000..efb4e79 --- /dev/null +++ b/patches/composer-patches/fix-applied-patches.patch @@ -0,0 +1,13 @@ +diff --git a/src/Patches.php b/src/Patches.php +index 70c5b83..53da82c 100644 +--- a/src/Patches.php ++++ b/src/Patches.php +@@ -115,7 +115,7 @@ class Patches implements PluginInterface, EventSubscriberInterface { + $this->installedPatches[$package->getName()] = $extra['patches']; + } + $patches = isset($extra['patches']) ? $extra['patches'] : array(); +- $tmp_patches = array_merge_recursive($tmp_patches, $patches); ++ $tmp_patches = $this->arrayMergeRecursiveDistinct($tmp_patches, $patches); + } + + if ($tmp_patches == FALSE) { diff --git a/patches/embed/issues_3309747.patch b/patches/embed/issues_3309747.patch new file mode 100644 index 0000000..dad1b99 --- /dev/null +++ b/patches/embed/issues_3309747.patch @@ -0,0 +1,453 @@ +From 28b1923cbc23d87e6181aae29b0f5e9d53a5a51e Mon Sep 17 00:00:00 2001 +From: Balint Pekker +Date: Mon, 19 Sep 2022 07:42:12 +0200 +Subject: [PATCH 1/6] Issue #3309747: Support CKEditor4 and CKEditor5 + +--- + src/Access/EmbedButtonEditorAccessCheck.php | 21 +++++++++++++++------ + 1 file changed, 15 insertions(+), 6 deletions(-) + +diff --git a/src/Access/EmbedButtonEditorAccessCheck.php b/src/Access/EmbedButtonEditorAccessCheck.php +index 01463b6..6415109 100644 +--- a/src/Access/EmbedButtonEditorAccessCheck.php ++++ b/src/Access/EmbedButtonEditorAccessCheck.php +@@ -78,20 +78,29 @@ class EmbedButtonEditorAccessCheck implements AccessInterface { + * currently only capable of detecting buttons used by CKEditor. + */ + protected function checkButtonEditorAccess(EmbedButtonInterface $embed_button, EditorInterface $editor) { +- if ($editor->getEditor() !== 'ckeditor') { ++ if (!in_array($editor->getEditor(), ['ckeditor', 'ckeditor5'])) { + throw new HttpException(500, 'Currently, only CKEditor is supported.'); + } + + $has_button = FALSE; + $settings = $editor->getSettings(); +- foreach ($settings['toolbar']['rows'] as $row) { +- foreach ($row as $group) { +- if (in_array($embed_button->id(), $group['items'])) { +- $has_button = TRUE; +- break 2; ++ if ($editor->getEditor() === 'ckeditor') { ++ foreach ($settings['toolbar']['rows'] as $row) { ++ foreach ($row as $group) { ++ if (in_array($embed_button->id(), $group['items'])) { ++ $has_button = TRUE; ++ break 2; ++ } + } + } + } ++ elseif ($editor->getEditor() === 'ckeditor5') { ++ // The schema for CKEditor5 has changed, therefore we need to check for ++ // the toolbar items differently. ++ if ($settings['toolbar']['items'] && in_array($embed_button->id(), $settings['toolbar']['items'])) { ++ $has_button = TRUE; ++ } ++ } + + return AccessResult::allowedIf($has_button) + ->addCacheableDependency($embed_button) +-- +GitLab + + +From 4816e59c99d99b093432176cdacc668456c4438a Mon Sep 17 00:00:00 2001 +From: leet +Date: Mon, 30 Jan 2023 15:43:05 +0000 +Subject: [PATCH 2/6] added composer.json + +--- + composer.json | 7 +++++++ + 1 file changed, 7 insertions(+) + create mode 100644 composer.json + +diff --git a/composer.json b/composer.json +new file mode 100644 +index 0000000..3da6f15 +--- /dev/null ++++ b/composer.json +@@ -0,0 +1,7 @@ ++{ ++ "name": "drupal/embed", ++ "type": "drupal-module", ++ "license": "GPL-2.0-or-later", ++ "minimum-stability": "stable", ++ "require": {} ++} +-- +GitLab + + +From bce0441fbd18dc653b9af4031c2bb261b0edaa00 Mon Sep 17 00:00:00 2001 +From: znerol +Date: Thu, 4 May 2023 20:53:38 +0200 +Subject: [PATCH 3/6] Add basic CKE5 access test + +--- + .../EmbedButtonCKEditor5AccessCheckTest.php | 133 ++++++++++++++++++ + 1 file changed, 133 insertions(+) + create mode 100644 tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php + +diff --git a/tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php b/tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php +new file mode 100644 +index 0000000..830c23b +--- /dev/null ++++ b/tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php +@@ -0,0 +1,133 @@ ++markTestSkipped('This test requires Drupal 9.3 or higher'); ++ } ++ } ++ ++ /** ++ * Tests \Drupal\embed\Access\EmbedButtonEditorAccessCheck. ++ */ ++ public function testEmbedButtonEditorAccessCheck() { ++ // The anonymous user should have access to the plain_text format, but it ++ // hasn't been configured to use an editor yet. ++ $this->getRoute('plain_text', 'embed_test_default'); ++ $this->assertSession()->statusCodeEquals(404); ++ $this->assertCacheContext('route'); ++ $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:editor.editor.embed_test'); ++ $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:embed.button.embed_test_default'); ++ ++ // The anonymous user should not have permission to use embed_test format. ++ $this->getRoute('embed_test', 'embed_test_default'); ++ $this->assertSession()->statusCodeEquals(403); ++ $this->assertCacheContext('route'); ++ $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:editor.editor.embed_test'); ++ $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:embed.button.embed_test_default'); ++ ++ // Now login a user that can use the embed_test format. ++ $this->drupalLogin($this->webUser); ++ ++ $this->getRoute('plain_text', 'embed_test_default'); ++ $this->assertSession()->statusCodeEquals(404); ++ $this->assertCacheContext('route'); ++ $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:editor.editor.plain_text'); ++ $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:embed.button.embed_test_default'); ++ ++ // Add an empty configuration for the plain_text editor configuration. ++ $editor = Editor::create([ ++ 'format' => 'plain_text', ++ 'editor' => 'ckeditor5', ++ ]); ++ $editor->save(); ++ $this->getRoute('plain_text', 'embed_test_default'); ++ $this->assertSession()->statusCodeEquals(403); ++ $this->assertCacheContext('route'); ++ $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'config:editor.editor.plain_text'); ++ $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'config:embed.button.embed_test_default'); ++ ++ $this->getRoute('embed_test', 'embed_test_default'); ++ $this->assertSession()->statusCodeEquals(200); ++ $this->assertCacheContext('route'); ++ $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'config:editor.editor.embed_test'); ++ $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'config:embed.button.embed_test_default'); ++ $this->assertSession()->pageTextContains(static::SUCCESS); ++ ++ // Test route with an empty request. ++ $this->getRoute('embed_test', 'embed_test_default', ''); ++ $this->assertSession()->statusCodeEquals(404); ++ $this->assertCacheContext('route'); ++ $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'config:editor.editor.embed_test'); ++ $this->assertSession()->responseHeaderContains('X-Drupal-Cache-Tags', 'config:embed.button.embed_test_default'); ++ ++ // Test route with an invalid text format. ++ $this->getRoute('invalid_editor', 'embed_test_default'); ++ $this->assertSession()->statusCodeEquals(404); ++ $this->assertCacheContext('route'); ++ $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:editor.editor.invalid_editor'); ++ $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:embed.button.embed_test_default'); ++ ++ // Test route with an invalid embed button. ++ $this->getRoute('embed_test', 'invalid_button'); ++ $this->assertSession()->statusCodeEquals(404); ++ $this->assertCacheContext('route'); ++ $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:editor.editor.embed_test'); ++ $this->assertSession()->responseHeaderNotContains('X-Drupal-Cache-Tags', 'config:embed.button.invalid_button'); ++ } ++ ++ /** ++ * Performs a request to the embed_test.test_access route. ++ * ++ * @param string $editor_id ++ * ID of the editor. ++ * @param string $embed_button_id ++ * ID of the embed button. ++ * @param string $value ++ * The query string value to include. ++ * ++ * @return string ++ * The retrieved HTML string. ++ */ ++ public function getRoute($editor_id, $embed_button_id, $value = NULL) { ++ $url = 'embed-test/access/' . $editor_id . '/' . $embed_button_id; ++ if (!isset($value)) { ++ $value = static::SUCCESS; ++ } ++ return $this->drupalGet($url, ['query' => ['value' => $value]]); ++ } ++ ++} +-- +GitLab + + +From aff2aa50ebe359f9bffc0b294d6927c81139923b Mon Sep 17 00:00:00 2001 +From: znerol +Date: Thu, 4 May 2023 22:53:24 +0200 +Subject: [PATCH 4/6] Ensure that CKE4 is not enabled in CKE5 test + +--- + .../EmbedButtonCKEditor5AccessCheckTest.php | 25 +++++++++++----- + .../EmbedButtonEditorAccessCheckTest.php | 30 +++++++++++++++++++ + tests/src/Functional/EmbedTestBase.php | 18 ----------- + 3 files changed, 48 insertions(+), 25 deletions(-) + +diff --git a/tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php b/tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php +index 830c23b..268617c 100644 +--- a/tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php ++++ b/tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php +@@ -3,6 +3,7 @@ + namespace Drupal\Tests\embed\Functional; + + use Drupal\editor\Entity\Editor; ++use Drupal\filter\Entity\FilterFormat; + use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait; + + /** +@@ -17,13 +18,9 @@ class EmbedButtonCKEditor5AccessCheckTest extends EmbedTestBase { + const SUCCESS = 'Success!'; + + /** +- * Modules to enable. +- * +- * @var array ++ * {@inheritdoc} + */ +- public static $modules = [ +- 'ckeditor5', +- ]; ++ public static $modules = ['ckeditor5']; + + /** + * {@inheritdoc} +@@ -34,10 +31,24 @@ class EmbedButtonCKEditor5AccessCheckTest extends EmbedTestBase { + * {@inheritdoc} + */ + public function setUp(): void { +- parent::setUp(); + if (version_compare(\Drupal::VERSION, '9.3', '<')) { + $this->markTestSkipped('This test requires Drupal 9.3 or higher'); + } ++ ++ parent::setUp(); ++ ++ $editor = Editor::create([ ++ 'format' => 'embed_test', ++ 'editor' => 'ckeditor5', ++ 'settings' => [ ++ 'toolbar' => [ ++ 'items' => [ ++ 'embed_test_default', ++ ], ++ ], ++ ], ++ ]); ++ $editor->save(); + } + + /** +diff --git a/tests/src/Functional/EmbedButtonEditorAccessCheckTest.php b/tests/src/Functional/EmbedButtonEditorAccessCheckTest.php +index e8cdf78..219ff74 100644 +--- a/tests/src/Functional/EmbedButtonEditorAccessCheckTest.php ++++ b/tests/src/Functional/EmbedButtonEditorAccessCheckTest.php +@@ -3,6 +3,7 @@ + namespace Drupal\Tests\embed\Functional; + + use Drupal\editor\Entity\Editor; ++use Drupal\filter\Entity\FilterFormat; + use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait; + + /** +@@ -16,11 +17,40 @@ class EmbedButtonEditorAccessCheckTest extends EmbedTestBase { + + const SUCCESS = 'Success!'; + ++ /** ++ * {@inheritdoc} ++ */ ++ public static $modules = ['ckeditor']; ++ + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + ++ /** ++ * {@inheritdoc} ++ */ ++ public function setUp(): void { ++ parent::setUp(); ++ ++ $editor_group = [ ++ 'name' => 'Embed', ++ 'items' => [ ++ 'embed_test_default', ++ ], ++ ]; ++ $editor = Editor::create([ ++ 'format' => 'embed_test', ++ 'editor' => 'ckeditor', ++ 'settings' => [ ++ 'toolbar' => [ ++ 'rows' => [[$editor_group]], ++ ], ++ ], ++ ]); ++ $editor->save(); ++ } ++ + /** + * Tests \Drupal\embed\Access\EmbedButtonEditorAccessCheck. + */ +diff --git a/tests/src/Functional/EmbedTestBase.php b/tests/src/Functional/EmbedTestBase.php +index 312a828..6a082fa 100644 +--- a/tests/src/Functional/EmbedTestBase.php ++++ b/tests/src/Functional/EmbedTestBase.php +@@ -25,7 +25,6 @@ abstract class EmbedTestBase extends BrowserTestBase { + 'embed', + 'embed_test', + 'editor', +- 'ckeditor', + ]; + + /** +@@ -61,23 +60,6 @@ abstract class EmbedTestBase extends BrowserTestBase { + ]); + $format->save(); + +- $editor_group = [ +- 'name' => 'Embed', +- 'items' => [ +- 'embed_test_default', +- ], +- ]; +- $editor = Editor::create([ +- 'format' => 'embed_test', +- 'editor' => 'ckeditor', +- 'settings' => [ +- 'toolbar' => [ +- 'rows' => [[$editor_group]], +- ], +- ], +- ]); +- $editor->save(); +- + // Create a user with required permissions. + $this->adminUser = $this->drupalCreateUser([ + 'administer embed buttons', +-- +GitLab + + +From f5be4cb2692692b086b2a7be973791efc8754552 Mon Sep 17 00:00:00 2001 +From: znerol +Date: Thu, 4 May 2023 22:57:11 +0200 +Subject: [PATCH 5/6] Remove spurious use statement + +--- + tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php | 1 - + tests/src/Functional/EmbedButtonEditorAccessCheckTest.php | 1 - + 2 files changed, 2 deletions(-) + +diff --git a/tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php b/tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php +index 268617c..2ea10c5 100644 +--- a/tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php ++++ b/tests/src/Functional/EmbedButtonCKEditor5AccessCheckTest.php +@@ -3,7 +3,6 @@ + namespace Drupal\Tests\embed\Functional; + + use Drupal\editor\Entity\Editor; +-use Drupal\filter\Entity\FilterFormat; + use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait; + + /** +diff --git a/tests/src/Functional/EmbedButtonEditorAccessCheckTest.php b/tests/src/Functional/EmbedButtonEditorAccessCheckTest.php +index 219ff74..2d3cf5b 100644 +--- a/tests/src/Functional/EmbedButtonEditorAccessCheckTest.php ++++ b/tests/src/Functional/EmbedButtonEditorAccessCheckTest.php +@@ -3,7 +3,6 @@ + namespace Drupal\Tests\embed\Functional; + + use Drupal\editor\Entity\Editor; +-use Drupal\filter\Entity\FilterFormat; + use Drupal\Tests\system\Functional\Cache\AssertPageCacheContextsAndTagsTrait; + + /** +-- +GitLab + + +From 6d6362916c28426bb3dca2e688e45125feb9ab79 Mon Sep 17 00:00:00 2001 +From: znerol +Date: Thu, 4 May 2023 23:02:37 +0200 +Subject: [PATCH 6/6] Remove another spurious use statement + +--- + tests/src/Functional/EmbedTestBase.php | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/tests/src/Functional/EmbedTestBase.php b/tests/src/Functional/EmbedTestBase.php +index 6a082fa..7ecafb6 100644 +--- a/tests/src/Functional/EmbedTestBase.php ++++ b/tests/src/Functional/EmbedTestBase.php +@@ -2,7 +2,6 @@ + + namespace Drupal\Tests\embed\Functional; + +-use Drupal\editor\Entity\Editor; + use Drupal\file\Entity\File; + use Drupal\filter\Entity\FilterFormat; + use Drupal\Tests\BrowserTestBase; +-- +GitLab + From db7a7ce52b17bc25bcd993f20f5d466ca86378ce Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Fri, 2 Jun 2023 17:07:33 +1000 Subject: [PATCH 56/79] Update tide modules * "dpc-sdp/tide_api": "3.0.11" * "dpc-sdp/tide_demo_content": "3.0.12" * "dpc-sdp/tide_search": "3.0.8" --- composer.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/composer.json b/composer.json index 70d2f28..124a1e4 100644 --- a/composer.json +++ b/composer.json @@ -5,10 +5,10 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.2", - "dpc-sdp/tide_api": "3.0.10", + "dpc-sdp/tide_api": "3.0.11", "dpc-sdp/tide_authenticated_content": "3.0.7", "dpc-sdp/tide_core": "3.2.8", - "dpc-sdp/tide_demo_content": "3.0.11", + "dpc-sdp/tide_demo_content": "3.0.12", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", "dpc-sdp/tide_grant": "3.0.4", @@ -19,7 +19,7 @@ "dpc-sdp/tide_page": "3.0.3", "dpc-sdp/tide_profile": "3.0.1", "dpc-sdp/tide_publication": "3.0.4", - "dpc-sdp/tide_search": "3.0.6", + "dpc-sdp/tide_search": "3.0.8", "dpc-sdp/tide_site": "3.0.14", "dpc-sdp/tide_test": "3.0.2", "dpc-sdp/tide_webform": "3.0.11" From b02f3f4203a45cce67c5ffe25aa13de4e093209c Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Tue, 6 Jun 2023 13:14:02 +1000 Subject: [PATCH 57/79] Remove noncanonical repos ### Motivation Using a noncanonical repository (fork) that originates from a Drupal ticket for issue resolution can potentially lead to a broken composer. This may happen if the changes are merged into the main branch and the forked repository is subsequently closed and deleted. --- composer.json | 20 +- .../video_embed_field_6.patch | 5263 +++++++++++++++++ 2 files changed, 5268 insertions(+), 15 deletions(-) create mode 100644 patches/video_embed_field/video_embed_field_6.patch diff --git a/composer.json b/composer.json index 124a1e4..629b2f0 100644 --- a/composer.json +++ b/composer.json @@ -6,38 +6,28 @@ "require": { "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.11", - "dpc-sdp/tide_authenticated_content": "3.0.7", - "dpc-sdp/tide_core": "3.2.8", + "dpc-sdp/tide_authenticated_content": "3.0.8", + "dpc-sdp/tide_core": "3.2.9", "dpc-sdp/tide_demo_content": "3.0.12", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", "dpc-sdp/tide_grant": "3.0.4", "dpc-sdp/tide_landing_page": "3.0.14", - "dpc-sdp/tide_media": "3.0.10", + "dpc-sdp/tide_media": "3.0.12", "dpc-sdp/tide_monsido": "3.0.1", "dpc-sdp/tide_news": "3.0.4", "dpc-sdp/tide_page": "3.0.3", "dpc-sdp/tide_profile": "3.0.1", "dpc-sdp/tide_publication": "3.0.4", "dpc-sdp/tide_search": "3.0.8", - "dpc-sdp/tide_site": "3.0.14", + "dpc-sdp/tide_site": "3.0.15", "dpc-sdp/tide_test": "3.0.2", "dpc-sdp/tide_webform": "3.0.11" }, "repositories": { "drupal": { "type": "composer", - "url": "https://packages.drupal.org/9", - "canonical": false - }, - "drupal/entity_embed": { - "type": "git", - "url": "https://git.drupalcode.org/issue/entity_embed-3272732.git" - }, - "drupal/video_embed_field": { - "type": "vcs", - "no-api": true, - "url": "https://git.drupalcode.org/issue/video_embed_field-3311063.git" + "url": "https://packages.drupal.org/9" }, "asset-packagist": { "type": "composer", diff --git a/patches/video_embed_field/video_embed_field_6.patch b/patches/video_embed_field/video_embed_field_6.patch new file mode 100644 index 0000000..4d5be00 --- /dev/null +++ b/patches/video_embed_field/video_embed_field_6.patch @@ -0,0 +1,5263 @@ +From db7b466c5691f68332b3ade5e50fd4075bb2b5bf Mon Sep 17 00:00:00 2001 +From: Alexandre Dias +Date: Wed, 26 Oct 2022 17:11:54 +0100 +Subject: [PATCH 01/16] Add media_library support. + +--- + .../src/Form/VideoEmbedFieldForm.php | 180 ++++++++++++++++++ + .../Plugin/media/Source/VideoEmbedField.php | 18 +- + .../media/Source/VideoEmbedFieldInterface.php | 11 ++ + .../video_embed_media.module | 17 ++ + 4 files changed, 221 insertions(+), 5 deletions(-) + create mode 100644 modules/video_embed_media/src/Form/VideoEmbedFieldForm.php + create mode 100644 modules/video_embed_media/src/Plugin/media/Source/VideoEmbedFieldInterface.php + create mode 100644 modules/video_embed_media/video_embed_media.module + +diff --git a/modules/video_embed_media/src/Form/VideoEmbedFieldForm.php b/modules/video_embed_media/src/Form/VideoEmbedFieldForm.php +new file mode 100644 +index 0000000..c726e0f +--- /dev/null ++++ b/modules/video_embed_media/src/Form/VideoEmbedFieldForm.php +@@ -0,0 +1,180 @@ ++providerManager = $provider_manager; ++ $this->renderer = $renderer; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public static function create(ContainerInterface $container) { ++ return new static( ++ $container->get('entity_type.manager'), ++ $container->get('media_library.ui_builder'), ++ $container->get('video_embed_field.provider_manager'), ++ $container->get('renderer'), ++ $container->get('media_library.opener_resolver') ++ ); ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ public function getFormId(): string { ++ return $this->getBaseFormId() . '_video_embed'; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ protected function getMediaType(FormStateInterface $form_state) { ++ if ($this->mediaType) { ++ return $this->mediaType; ++ } ++ ++ $media_type = parent::getMediaType($form_state); ++ if (!$media_type->getSource() instanceof VideoEmbedFieldInterface) { ++ throw new \InvalidArgumentException('Can only add media types which use an Video Embed source plugin.'); ++ } ++ return $media_type; ++ } ++ ++ /** ++ * {@inheritdoc} ++ */ ++ protected function buildInputElement(array $form, FormStateInterface $form_state) { ++ $media_type = $this->getMediaType($form_state); ++ $data_definition = $media_type->getSource()->getSourceFieldDefinition($media_type) ++ ->getItemDefinition(); ++ ++ // Add a container to group the input elements for styling purposes. ++ $form['container'] = [ ++ '#type' => 'container', ++ ]; ++ ++ $form['container']['video_url'] = [ ++ '#type' => 'textfield', ++ '#title' => $this->t('Add @type URL', [ ++ '@type' => $this->getMediaType($form_state)->label(), ++ ]), ++ '#allowed_providers' => $data_definition->getSetting('allowed_providers'), ++ '#theme' => 'input__video', ++ '#required' => TRUE, ++ ]; ++ ++ $form['container']['submit'] = [ ++ '#type' => 'submit', ++ '#value' => $this->t('Add'), ++ '#button_type' => 'primary', ++ '#validate' => ['::validateUrl'], ++ '#submit' => ['::addButtonSubmit'], ++ // @todo Move validation in https://www.drupal.org/node/2988215 ++ '#ajax' => [ ++ 'callback' => '::updateFormCallback', ++ 'wrapper' => 'media-library-wrapper', ++ // Add a fixed URL to post the form since AJAX forms are automatically ++ // posted to instead of $form['#action']. ++ // @todo Remove when https://www.drupal.org/project/drupal/issues/2504115 ++ // is fixed. ++ 'url' => Url::fromRoute('media_library.ui'), ++ 'options' => [ ++ 'query' => $this->getMediaLibraryState($form_state)->all() + [ ++ FormBuilderInterface::AJAX_FORM_REQUEST => TRUE, ++ ], ++ ], ++ ], ++ ]; ++ return $form; ++ } ++ ++ /** ++ * Validates the oEmbed URL. ++ * ++ * @param array $form ++ * The complete form. ++ * @param \Drupal\Core\Form\FormStateInterface $form_state ++ * The current form state. ++ */ ++ public function validateUrl(array &$form, FormStateInterface $form_state) { ++ $provider = $this->getProvider($form_state->getValue('video_url')); ++ // Display an error if no provider can be loaded for this video. ++ if (!$provider) { ++ $form_state->setErrorByName('video_url', $this->t('Could not find a video provider to handle the given URL.')); ++ } ++ } ++ ++ /** ++ * Submit handler for the add button. ++ * ++ * @param array $form ++ * The form render array. ++ * @param \Drupal\Core\Form\FormStateInterface $form_state ++ * The form state. ++ */ ++ public function addButtonSubmit(array $form, FormStateInterface $form_state) { ++ $this->processInputValues([$form_state->getValue('video_url')], $form, $form_state); ++ } ++ ++ /** ++ * Get a provider from some input. ++ * ++ * @param string $input ++ * The input string. ++ * ++ * @return bool|\Drupal\video_embed_field\ProviderPluginInterface ++ * A video provider or FALSE on failure. ++ */ ++ protected function getProvider(string $input) { ++ return $this->providerManager->loadProviderFromInput($input); ++ } ++ ++} +diff --git a/modules/video_embed_media/src/Plugin/media/Source/VideoEmbedField.php b/modules/video_embed_media/src/Plugin/media/Source/VideoEmbedField.php +index 566f0f3..08d71a9 100644 +--- a/modules/video_embed_media/src/Plugin/media/Source/VideoEmbedField.php ++++ b/modules/video_embed_media/src/Plugin/media/Source/VideoEmbedField.php +@@ -5,6 +5,7 @@ namespace Drupal\video_embed_media\Plugin\media\Source; + use Drupal\Core\Config\ConfigFactoryInterface; + use Drupal\Core\Entity\EntityFieldManagerInterface; + use Drupal\Core\Entity\EntityTypeManagerInterface; ++use Drupal\Core\Field\FieldDefinitionInterface; + use Drupal\Core\Field\FieldTypePluginManagerInterface; + use Drupal\media\MediaInterface; + use Drupal\media\MediaSourceBase; +@@ -23,7 +24,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; + * default_thumbnail_filename = "video.png" + * ) + */ +-class VideoEmbedField extends MediaSourceBase { ++class VideoEmbedField extends MediaSourceBase implements VideoEmbedFieldInterface { + + /** + * The video provider manager. +@@ -84,7 +85,7 @@ class VideoEmbedField extends MediaSourceBase { + /** + * {@inheritdoc} + */ +- public function defaultConfiguration() { ++ public function defaultConfiguration(): array { + return [ + 'source_field' => 'field_media_video_embed_field', + ]; +@@ -142,7 +143,7 @@ class VideoEmbedField extends MediaSourceBase { + /** + * {@inheritdoc} + */ +- public function getMetadataAttributes() { ++ public function getMetadataAttributes(): array { + return [ + 'id' => $this->t('Video ID.'), + 'source' => $this->t('Video source machine name.'), +@@ -181,7 +182,7 @@ class VideoEmbedField extends MediaSourceBase { + /** + * {@inheritdoc} + */ +- public function getSourceFieldDefinition(MediaTypeInterface $type) { ++ public function getSourceFieldDefinition(MediaTypeInterface $type): ?FieldDefinitionInterface { + // video_embed_media has not historically had a value in + // $this->configuration['source_field'], instead just creating + // field_media_video_embed_field on install and treating that as the source. +@@ -191,9 +192,16 @@ class VideoEmbedField extends MediaSourceBase { + if ($field) { + // Be sure that the suggested source field actually exists. + $fields = $this->entityFieldManager->getFieldDefinitions('media', $type->id()); +- return isset($fields[$field]) ? $fields[$field] : NULL; ++ return $fields[$field] ?? NULL; + } + return NULL; + } + ++ /** ++ * {@inheritdoc} ++ */ ++ public function getSourceFieldConstraints(): array { ++ return []; ++ } ++ + } +diff --git a/modules/video_embed_media/src/Plugin/media/Source/VideoEmbedFieldInterface.php b/modules/video_embed_media/src/Plugin/media/Source/VideoEmbedFieldInterface.php +new file mode 100644 +index 0000000..b8225a6 +--- /dev/null ++++ b/modules/video_embed_media/src/Plugin/media/Source/VideoEmbedFieldInterface.php +@@ -0,0 +1,11 @@ ++ +Date: Thu, 27 Oct 2022 13:06:43 +0100 +Subject: [PATCH 02/16] Add missing maxlength. + +--- + modules/video_embed_media/src/Form/VideoEmbedFieldForm.php | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/modules/video_embed_media/src/Form/VideoEmbedFieldForm.php b/modules/video_embed_media/src/Form/VideoEmbedFieldForm.php +index c726e0f..bb32167 100644 +--- a/modules/video_embed_media/src/Form/VideoEmbedFieldForm.php ++++ b/modules/video_embed_media/src/Form/VideoEmbedFieldForm.php +@@ -106,6 +106,7 @@ class VideoEmbedFieldForm extends AddFormBase { + '#title' => $this->t('Add @type URL', [ + '@type' => $this->getMediaType($form_state)->label(), + ]), ++ '#maxlength' => $data_definition->getSetting('max_length'), + '#allowed_providers' => $data_definition->getSetting('allowed_providers'), + '#theme' => 'input__video', + '#required' => TRUE, +-- +GitLab + + +From 461f9848b049a820a5f0cf6716a95f91f5ffd042 Mon Sep 17 00:00:00 2001 +From: Alexandre Dias +Date: Sun, 30 Oct 2022 16:43:15 +0000 +Subject: [PATCH 03/16] Replace TYPE_MARKUP_LANGUAGE with + TYPE_TRANSFORM_IRREVERSIBLE. + +--- + .../src/Plugin/Filter/VideoEmbedWysiwyg.php | 2 +- + modules/video_embed_wysiwyg/video_embed_wysiwyg.module | 3 ++- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/modules/video_embed_wysiwyg/src/Plugin/Filter/VideoEmbedWysiwyg.php b/modules/video_embed_wysiwyg/src/Plugin/Filter/VideoEmbedWysiwyg.php +index f0c50e7..4486bc0 100644 +--- a/modules/video_embed_wysiwyg/src/Plugin/Filter/VideoEmbedWysiwyg.php ++++ b/modules/video_embed_wysiwyg/src/Plugin/Filter/VideoEmbedWysiwyg.php +@@ -19,7 +19,7 @@ use Drupal\Core\Render\RendererInterface; + * title = @Translation("Video Embed WYSIWYG"), + * id = "video_embed_wysiwyg", + * description = @Translation("Enables the use of video_embed_wysiwyg."), +- * type = Drupal\filter\Plugin\FilterInterface::TYPE_MARKUP_LANGUAGE ++ * type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_IRREVERSIBLE + * ) + */ + class VideoEmbedWysiwyg extends FilterBase implements ContainerFactoryPluginInterface { +diff --git a/modules/video_embed_wysiwyg/video_embed_wysiwyg.module b/modules/video_embed_wysiwyg/video_embed_wysiwyg.module +index bd05974..586d49b 100644 +--- a/modules/video_embed_wysiwyg/video_embed_wysiwyg.module ++++ b/modules/video_embed_wysiwyg/video_embed_wysiwyg.module +@@ -34,6 +34,7 @@ function video_embed_wysiwyg_toolbar_filter_validate($form, FormStateInterface $ + $button_enabled = FALSE; + $key = ['editor', 'settings', 'toolbar', 'button_groups']; + $button_rows = $form_state->hasValue($key) ? json_decode($form_state->getValue($key), TRUE) : []; ++ + if (!empty($button_rows)) { + foreach ($button_rows as $button_row) { + foreach ($button_row as $button_group) { +@@ -47,7 +48,7 @@ function video_embed_wysiwyg_toolbar_filter_validate($form, FormStateInterface $ + } + } + // The button and filter can either both be enabled or disabled. +- if ($filter_enabled !== $button_enabled) { ++ if ($filter_enabled !== $button_enabled && $form_state->getValue('editor')['editor'] === 'ckeditor') { + $form_state->setError($form['filters']['status']['video_embed_wysiwyg'], t('To embed videos, make sure you have enabled the "Video Embed WYSIWYG" filter and dragged the video icon into the WYSIWYG toolbar. For more information read the documentation.', ['@url' => VIDEO_EMBED_WYSIWYG_DOCUMENTATION_URL])); + } + } +-- +GitLab + + +From 35a77a281339364c6b4cf33d515fca19f5d243ae Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ga=C3=ABlG?= +Date: Tue, 14 Feb 2023 17:37:45 +0100 +Subject: [PATCH 04/16] WIP, see @todo for lasting work + +--- + modules/video_embed_wysiwyg/.gitignore | 1 + + .../css/video_embed.admin.css | 4 + + modules/video_embed_wysiwyg/icons/film.svg | 1 + + .../icons/play-circle (copie).svg | 1 + + .../video_embed_wysiwyg/icons/play-circle.svg | 1 + + modules/video_embed_wysiwyg/icons/play.svg | 1 + + modules/video_embed_wysiwyg/icons/video.svg | 1 + + .../video_embed_wysiwyg/js/build/README.txt | 1 + + .../ckeditor5_plugins/videoEmbed/src/index.js | 5 + + .../videoEmbed/src/insertvideoembedcommand.js | 47 + + .../videoEmbed/src/videoembed.js | 10 + + .../videoEmbed/src/videoembedediting.js | 102 + + .../videoEmbed/src/videoembedui.js | 38 + + modules/video_embed_wysiwyg/package.json | 19 + + .../CKEditor5Plugin/VideoEmbedWysiwyg.php | 37 + + .../video_embed_wysiwyg.ckeditor5.yml | 17 + + .../video_embed_wysiwyg.info.yml | 2 +- + .../video_embed_wysiwyg.libraries.yml | 12 + + .../video_embed_wysiwyg.module | 3 + + modules/video_embed_wysiwyg/webpack.config.js | 66 + + modules/video_embed_wysiwyg/yarn.lock | 2589 +++++++++++++++++ + 21 files changed, 2957 insertions(+), 1 deletion(-) + create mode 100644 modules/video_embed_wysiwyg/.gitignore + create mode 100644 modules/video_embed_wysiwyg/css/video_embed.admin.css + create mode 100644 modules/video_embed_wysiwyg/icons/film.svg + create mode 100644 modules/video_embed_wysiwyg/icons/play-circle (copie).svg + create mode 100644 modules/video_embed_wysiwyg/icons/play-circle.svg + create mode 100644 modules/video_embed_wysiwyg/icons/play.svg + create mode 100644 modules/video_embed_wysiwyg/icons/video.svg + create mode 100644 modules/video_embed_wysiwyg/js/build/README.txt + create mode 100644 modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/index.js + create mode 100644 modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js + create mode 100644 modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembed.js + create mode 100644 modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js + create mode 100644 modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js + create mode 100644 modules/video_embed_wysiwyg/package.json + create mode 100644 modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php + create mode 100644 modules/video_embed_wysiwyg/video_embed_wysiwyg.ckeditor5.yml + create mode 100644 modules/video_embed_wysiwyg/video_embed_wysiwyg.libraries.yml + create mode 100644 modules/video_embed_wysiwyg/webpack.config.js + create mode 100644 modules/video_embed_wysiwyg/yarn.lock + +diff --git a/modules/video_embed_wysiwyg/.gitignore b/modules/video_embed_wysiwyg/.gitignore +new file mode 100644 +index 0000000..b512c09 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/.gitignore +@@ -0,0 +1 @@ ++node_modules +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/css/video_embed.admin.css b/modules/video_embed_wysiwyg/css/video_embed.admin.css +new file mode 100644 +index 0000000..7ef5780 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/css/video_embed.admin.css +@@ -0,0 +1,4 @@ ++.ckeditor5-toolbar-button-videoEmbed { ++ /* @todo Choose the best icon and remove others. */ ++ background-image: url(../icons/film.svg); ++} +diff --git a/modules/video_embed_wysiwyg/icons/film.svg b/modules/video_embed_wysiwyg/icons/film.svg +new file mode 100644 +index 0000000..ccf8983 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/icons/film.svg +@@ -0,0 +1 @@ ++ +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/icons/play-circle (copie).svg b/modules/video_embed_wysiwyg/icons/play-circle (copie).svg +new file mode 100644 +index 0000000..778c5fa +--- /dev/null ++++ b/modules/video_embed_wysiwyg/icons/play-circle (copie).svg +@@ -0,0 +1 @@ ++ +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/icons/play-circle.svg b/modules/video_embed_wysiwyg/icons/play-circle.svg +new file mode 100644 +index 0000000..0ce0085 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/icons/play-circle.svg +@@ -0,0 +1 @@ ++ +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/icons/play.svg b/modules/video_embed_wysiwyg/icons/play.svg +new file mode 100644 +index 0000000..e817cc8 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/icons/play.svg +@@ -0,0 +1 @@ ++ +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/icons/video.svg b/modules/video_embed_wysiwyg/icons/video.svg +new file mode 100644 +index 0000000..92f4988 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/icons/video.svg +@@ -0,0 +1 @@ ++ +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/build/README.txt b/modules/video_embed_wysiwyg/js/build/README.txt +new file mode 100644 +index 0000000..c21c74d +--- /dev/null ++++ b/modules/video_embed_wysiwyg/js/build/README.txt +@@ -0,0 +1 @@ ++This is the default destination folder for CKEditor 5 plugin builds. +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/index.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/index.js +new file mode 100644 +index 0000000..6fcd277 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/index.js +@@ -0,0 +1,5 @@ ++import VideoEmbed from './videoembed'; ++ ++export default { ++ VideoEmbed, ++}; +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js +new file mode 100644 +index 0000000..97ad84a +--- /dev/null ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js +@@ -0,0 +1,47 @@ ++/** ++ * @file defines InsertVideoEmbedCommand, which is executed when the videoEmbed ++ * toolbar button is pressed. ++ */ ++ ++import { Command } from 'ckeditor5/src/core'; ++ ++export default class InsertVideoEmbedCommand extends Command { ++ execute() { ++ const { model } = this.editor; ++ ++ model.change((writer) => { ++ // Insert at the current selection position ++ // in a way that will result in creating a valid model structure. ++ model.insertContent(createVideoEmbed(writer)); ++ }); ++ } ++ ++ refresh() { ++ const { model } = this.editor; ++ const { selection } = model.document; ++ ++ // Determine if the cursor (selection) is in a position where adding a ++ // videoEmbed is permitted. This is based on the schema of the model(s) ++ // currently containing the cursor. ++ const allowedIn = model.schema.findAllowedParent( ++ selection.getFirstPosition(), ++ 'videoEmbed', ++ ); ++ ++ // If the cursor is not in a location where a videoEmbed can be added, ++ // return null so the addition doesn't happen. ++ this.isEnabled = allowedIn !== null; ++ } ++} ++ ++function createVideoEmbed(writer) { ++ // Create instances of the element registered with the editor in ++ // videoembedediting.js. ++ const videoEmbed = writer.createElement('videoEmbed'); ++ ++ // @todo ++ ++ // Return the element to be added to the editor. ++ return videoEmbed; ++} ++ +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembed.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembed.js +new file mode 100644 +index 0000000..c6f5bff +--- /dev/null ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembed.js +@@ -0,0 +1,10 @@ ++import VideoEmbedEditing from './videoembedediting'; ++import VideoEmbedUI from './videoembedui'; ++import { Plugin } from 'ckeditor5/src/core'; ++ ++export default class VideoEmbed extends Plugin { ++ ++static get requires() { ++ return [VideoEmbedEditing, VideoEmbedUI]; ++ } ++} +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js +new file mode 100644 +index 0000000..3153259 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js +@@ -0,0 +1,102 @@ ++import { Plugin } from 'ckeditor5/src/core'; ++import { toWidget, toWidgetEditable } from 'ckeditor5/src/widget'; ++import { Widget } from 'ckeditor5/src/widget'; ++import InsertVideoEmbedCommand from './insertvideoembedcommand'; ++ ++ ++/** ++ * CKEditor 5 plugins do not work directly with the DOM. They are defined as ++ * plugin-specific data models that are then converted to markup that ++ * is inserted in the DOM. ++ * ++ * CKEditor 5 internally interacts with videoEmbed as this model: ++ * @todo List attributes in this doc. ++ * ++ * ++ * Which is converted in database (dataDowncast) as this markup: ++ *

{"video_url":"https://some.video.url","settings":{"responsive":0or1,"width":"42","height":"42","autoplay":0or1}}

++ * ++ * The Drupal video_embed_wysiwyg format filter will then convert this into a ++ * real HTML video embed, on PHP frontend rendering. ++ * ++ * videoEmbed model elements are also converted to HTML for preview in CKE5 UI ++ * (editingDowncast). ++ * ++ * And the database markup can be converted back to model (upcast). ++ * ++ * This file has the logic for defining the videoEmbed model, and for how it is ++ * converted from/to standard DOM markup for database/UI. ++ */ ++export default class VideoEmbedEditing extends Plugin { ++ static get requires() { ++ return [Widget]; ++ } ++ ++ init() { ++ this._defineSchema(); ++ this._defineConverters(); ++ this.editor.commands.add( ++ 'insertVideoEmbed', ++ new InsertVideoEmbedCommand(this.editor), ++ ); ++ } ++ ++ /* ++ * This registers the structure that will be seen by CKEditor 5 as ++ * ++ * ++ * The logic in _defineConverters() will determine how this is converted to ++ * markup. ++ */ ++ _defineSchema() { ++ // Schemas are registered via the central `editor` object. ++ const schema = this.editor.model.schema; ++ ++ ++ // @todo register allowed model attributes. ++ schema.register('videoEmbed', { ++ // Behaves like a self-contained object (e.g. an image). ++ isObject: true, ++ // Allow in places where other blocks are allowed (e.g. directly in the root). ++ allowWhere: '$block', ++ }); ++ } ++ ++ /** ++ * Converters determine how CKEditor 5 models are converted into markup and ++ * vice-versa. ++ */ ++ _defineConverters() { ++ // Converters are registered via the central editor object. ++ const { conversion } = this.editor; ++ ++ // Upcast Converters: determine how existing HTML is interpreted by the ++ // editor. These trigger when an editor instance loads. ++ // ++ // If {"video_url":...} is present in the existing markup ++ // processed by CKEditor, then CKEditor recognizes and loads it as a ++ // model. ++ // @todo Implement this, see video_embed_wysiwyg/plugin/plugin.js ++ //conversion.for('upcast').[...] ++ ++ ++ // Data Downcast Converters: converts stored model data into HTML. ++ // These trigger when content is saved. ++ // ++ // Instances of are saved as ++ //

{{"video_url":...}

. ++ // @todo Implement this, see video_embed_wysiwyg/plugin/plugin.js ++ //conversion.for('dataDowncast').[...] ++ ++ ++ // Editing Downcast Converters. These render the content to the user for ++ // editing, i.e. this determines what gets seen in the editor. These trigger ++ // after the Data Upcast Converters, and are re-triggered any time there ++ // are changes to any of the models' properties. ++ // ++ // Convert the model into a container widget in the editor UI. ++ // @todo Implement this, see video_embed_wysiwyg/plugin/plugin.js ++ //conversion.for('editingDowncast').[...] ++ } ++} ++ +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js +new file mode 100644 +index 0000000..94ba981 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js +@@ -0,0 +1,38 @@ ++/** ++ * @file registers the videoEmbed toolbar button and binds functionality to it. ++ */ ++ ++import { Plugin } from 'ckeditor5/src/core'; ++import { ButtonView } from 'ckeditor5/src/ui'; ++/* @todo Choose the best icon and remove others. */ ++import icon from '../../../../icons/film.svg'; ++ ++export default class VideoEmbedUI extends Plugin { ++ init() { ++ const editor = this.editor; ++ ++ // This will register the videoEmbed toolbar button. ++ editor.ui.componentFactory.add('videoEmbed', (locale) => { ++ const command = editor.commands.get('insertVideoEmbed'); ++ const buttonView = new ButtonView(locale); ++ ++ // Create the toolbar button. ++ buttonView.set({ ++ label: editor.t('Video Embed'), ++ icon, ++ tooltip: true, ++ }); ++ ++ // Bind the state of the button to the command. ++ buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled'); ++ ++ // Execute the command when the button is clicked (executed). ++ this.listenTo(buttonView, 'execute', () => ++ editor.execute('insertVideoEmbed'), ++ ); ++ ++ return buttonView; ++ }); ++ } ++} ++ +diff --git a/modules/video_embed_wysiwyg/package.json b/modules/video_embed_wysiwyg/package.json +new file mode 100644 +index 0000000..529a8ff +--- /dev/null ++++ b/modules/video_embed_wysiwyg/package.json +@@ -0,0 +1,19 @@ ++{ ++ "name": "drupal-ckeditor5", ++ "version": "1.0.0", ++ "description": "Drupal CKEditor 5 integration", ++ "author": "", ++ "license": "GPL-2.0-or-later", ++ "scripts": { ++ "watch": "webpack --mode development --watch", ++ "build": "webpack" ++ }, ++ "devDependencies": { ++ "@ckeditor/ckeditor5-dev-utils": "^30.0.0", ++ "ckeditor5": "~34.1.0", ++ "raw-loader": "^4.0.2", ++ "terser-webpack-plugin": "^5.2.0", ++ "webpack": "^5.51.1", ++ "webpack-cli": "^4.4.0" ++ } ++} +diff --git a/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php b/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php +new file mode 100644 +index 0000000..dd57409 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php +@@ -0,0 +1,37 @@ ++getFilterFormat(); ++ /** @var \Drupal\filter\Plugin\FilterInterface $filter */ ++ $filter = $format->filters('video_embed_wysiwyg'); ++ $filter_config = $filter->getConfiguration(); ++ $parent_config = parent::getDynamicPluginConfig($static_plugin_config, $editor); ++ // @todo Ensure this is the info the plugin needs. ++ return array_merge_recursive($parent_config, ++ [ ++ 'VideoEmbed' => $filter_config['settings'] ++ ]); ++ } ++ ++} +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/video_embed_wysiwyg.ckeditor5.yml b/modules/video_embed_wysiwyg/video_embed_wysiwyg.ckeditor5.yml +new file mode 100644 +index 0000000..6f75201 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/video_embed_wysiwyg.ckeditor5.yml +@@ -0,0 +1,17 @@ ++video_embed_wysiwyg_video_embed: ++ provider: video_embed_wysiwyg ++ ckeditor5: ++ plugins: ++ - videoEmbed.VideoEmbed ++ drupal: ++ label: Video Embed WYSIWYG ++ library: video_embed_wysiwyg/video_embed ++ admin_library: video_embed_wysiwyg/admin.video_embed ++ toolbar_items: ++ videoEmbed: ++ label: Video embed ++ elements: ++ -

++ conditions: ++ filter: video_embed_wysiwyg ++ class: Drupal\video_embed_wysiwyg\Plugin\CKEditor5Plugin\VideoEmbedWysiwyg +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/video_embed_wysiwyg.info.yml b/modules/video_embed_wysiwyg/video_embed_wysiwyg.info.yml +index 40b8f94..c2a6ac5 100644 +--- a/modules/video_embed_wysiwyg/video_embed_wysiwyg.info.yml ++++ b/modules/video_embed_wysiwyg/video_embed_wysiwyg.info.yml +@@ -5,5 +5,5 @@ package: Video Embed Field + core_version_requirement: ^9.2 || ^10 + dependencies: + - drupal:field +- - drupal:ckeditor ++ - drupal:editor + - video_embed_field:video_embed_field +diff --git a/modules/video_embed_wysiwyg/video_embed_wysiwyg.libraries.yml b/modules/video_embed_wysiwyg/video_embed_wysiwyg.libraries.yml +new file mode 100644 +index 0000000..0b134bf +--- /dev/null ++++ b/modules/video_embed_wysiwyg/video_embed_wysiwyg.libraries.yml +@@ -0,0 +1,12 @@ ++video_embed: ++ js: ++ js/build/videoEmbed.js: { preprocess: false, minified: true } ++ dependencies: ++ - core/ckeditor5 ++ ++# Loaded in the text format configuration form to provide styling for the icon ++# used in toolbar config. ++admin.video_embed: ++ css: ++ theme: ++ css/video_embed.admin.css: { } +diff --git a/modules/video_embed_wysiwyg/video_embed_wysiwyg.module b/modules/video_embed_wysiwyg/video_embed_wysiwyg.module +index 586d49b..223cc9a 100644 +--- a/modules/video_embed_wysiwyg/video_embed_wysiwyg.module ++++ b/modules/video_embed_wysiwyg/video_embed_wysiwyg.module +@@ -3,6 +3,9 @@ + /** + * @file + * Module file for video_embed_wysiwyg. ++ * @todo test and fix CKE5 plugin. ++ * @todo CKE5 upgrade path if needed. ++ * @todo Add a comment on code that runs only for CKE4. + */ + + use Drupal\editor\Entity\Editor; +diff --git a/modules/video_embed_wysiwyg/webpack.config.js b/modules/video_embed_wysiwyg/webpack.config.js +new file mode 100644 +index 0000000..a10c7c2 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/webpack.config.js +@@ -0,0 +1,66 @@ ++const path = require('path'); ++const fs = require('fs'); ++const webpack = require('webpack'); ++const { styles, builds } = require('@ckeditor/ckeditor5-dev-utils'); ++const TerserPlugin = require('terser-webpack-plugin'); ++ ++function getDirectories(srcpath) { ++ return fs ++ .readdirSync(srcpath) ++ .filter((item) => fs.statSync(path.join(srcpath, item)).isDirectory()); ++} ++ ++module.exports = []; ++// Loop through every subdirectory in src, each a different plugin, and build ++// each one in ./build. ++getDirectories('./js/ckeditor5_plugins').forEach((dir) => { ++ const bc = { ++ mode: 'production', ++ optimization: { ++ minimize: true, ++ minimizer: [ ++ new TerserPlugin({ ++ terserOptions: { ++ format: { ++ comments: false, ++ }, ++ }, ++ test: /\.js(\?.*)?$/i, ++ extractComments: false, ++ }), ++ ], ++ moduleIds: 'named', ++ }, ++ entry: { ++ path: path.resolve( ++ __dirname, ++ 'js/ckeditor5_plugins', ++ dir, ++ 'src/index.js', ++ ), ++ }, ++ output: { ++ path: path.resolve(__dirname, './js/build'), ++ filename: `${dir}.js`, ++ library: ['CKEditor5', dir], ++ libraryTarget: 'umd', ++ libraryExport: 'default', ++ }, ++ plugins: [ ++ // It is possible to require the ckeditor5-dll.manifest.json used in ++ // core/node_modules rather than having to install CKEditor 5 here. ++ // However, that requires knowing the location of that file relative to ++ // where your module code is located. ++ new webpack.DllReferencePlugin({ ++ manifest: require('./node_modules/ckeditor5/build/ckeditor5-dll.manifest.json'), // eslint-disable-line global-require, import/no-unresolved ++ scope: 'ckeditor5/src', ++ name: 'CKEditor5.dll', ++ }), ++ ], ++ module: { ++ rules: [{ test: /\.svg$/, use: 'raw-loader' }], ++ }, ++ }; ++ ++ module.exports.push(bc); ++}); +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/yarn.lock b/modules/video_embed_wysiwyg/yarn.lock +new file mode 100644 +index 0000000..569df04 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/yarn.lock +@@ -0,0 +1,2589 @@ ++# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. ++# yarn lockfile v1 ++ ++ ++"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.18.6": ++ version "7.18.6" ++ resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.18.6.tgz#3b25d38c89600baa2dcc219edfa88a74eb2c427a" ++ integrity sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q== ++ dependencies: ++ "@babel/highlight" "^7.18.6" ++ ++"@babel/generator@^7.20.1": ++ version "7.20.1" ++ resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.20.1.tgz#ef32ecd426222624cbd94871a7024639cf61a9fa" ++ integrity sha512-u1dMdBUmA7Z0rBB97xh8pIhviK7oItYOkjbsCxTWMknyvbQRBwX7/gn4JXurRdirWMFh+ZtYARqkA6ydogVZpg== ++ dependencies: ++ "@babel/types" "^7.20.0" ++ "@jridgewell/gen-mapping" "^0.3.2" ++ jsesc "^2.5.1" ++ ++"@babel/helper-environment-visitor@^7.18.9": ++ version "7.18.9" ++ resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz#0c0cee9b35d2ca190478756865bb3528422f51be" ++ integrity sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg== ++ ++"@babel/helper-function-name@^7.19.0": ++ version "7.19.0" ++ resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz#941574ed5390682e872e52d3f38ce9d1bef4648c" ++ integrity sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w== ++ dependencies: ++ "@babel/template" "^7.18.10" ++ "@babel/types" "^7.19.0" ++ ++"@babel/helper-hoist-variables@^7.18.6": ++ version "7.18.6" ++ resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz#d4d2c8fb4baeaa5c68b99cc8245c56554f926678" ++ integrity sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q== ++ dependencies: ++ "@babel/types" "^7.18.6" ++ ++"@babel/helper-split-export-declaration@^7.18.6": ++ version "7.18.6" ++ resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz#7367949bc75b20c6d5a5d4a97bba2824ae8ef075" ++ integrity sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA== ++ dependencies: ++ "@babel/types" "^7.18.6" ++ ++"@babel/helper-string-parser@^7.19.4": ++ version "7.19.4" ++ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz#38d3acb654b4701a9b77fb0615a96f775c3a9e63" ++ integrity sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw== ++ ++"@babel/helper-validator-identifier@^7.18.6", "@babel/helper-validator-identifier@^7.19.1": ++ version "7.19.1" ++ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz#7eea834cf32901ffdc1a7ee555e2f9c27e249ca2" ++ integrity sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w== ++ ++"@babel/highlight@^7.18.6": ++ version "7.18.6" ++ resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.18.6.tgz#81158601e93e2563795adcbfbdf5d64be3f2ecdf" ++ integrity sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g== ++ dependencies: ++ "@babel/helper-validator-identifier" "^7.18.6" ++ chalk "^2.0.0" ++ js-tokens "^4.0.0" ++ ++"@babel/parser@^7.18.10", "@babel/parser@^7.18.9", "@babel/parser@^7.20.1": ++ version "7.20.1" ++ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.20.1.tgz#3e045a92f7b4623cafc2425eddcb8cf2e54f9cc5" ++ integrity sha512-hp0AYxaZJhxULfM1zyp7Wgr+pSUKBcP3M+PHnSzWGdXOzg/kHWIgiUWARvubhUKGOEw3xqY4x+lyZ9ytBVcELw== ++ ++"@babel/template@^7.18.10": ++ version "7.18.10" ++ resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.18.10.tgz#6f9134835970d1dbf0835c0d100c9f38de0c5e71" ++ integrity sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA== ++ dependencies: ++ "@babel/code-frame" "^7.18.6" ++ "@babel/parser" "^7.18.10" ++ "@babel/types" "^7.18.10" ++ ++"@babel/traverse@^7.18.9": ++ version "7.20.1" ++ resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.20.1.tgz#9b15ccbf882f6d107eeeecf263fbcdd208777ec8" ++ integrity sha512-d3tN8fkVJwFLkHkBN479SOsw4DMZnz8cdbL/gvuDuzy3TS6Nfw80HuQqhw1pITbIruHyh7d1fMA47kWzmcUEGA== ++ dependencies: ++ "@babel/code-frame" "^7.18.6" ++ "@babel/generator" "^7.20.1" ++ "@babel/helper-environment-visitor" "^7.18.9" ++ "@babel/helper-function-name" "^7.19.0" ++ "@babel/helper-hoist-variables" "^7.18.6" ++ "@babel/helper-split-export-declaration" "^7.18.6" ++ "@babel/parser" "^7.20.1" ++ "@babel/types" "^7.20.0" ++ debug "^4.1.0" ++ globals "^11.1.0" ++ ++"@babel/types@^7.18.10", "@babel/types@^7.18.6", "@babel/types@^7.19.0", "@babel/types@^7.20.0": ++ version "7.20.0" ++ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.20.0.tgz#52c94cf8a7e24e89d2a194c25c35b17a64871479" ++ integrity sha512-Jlgt3H0TajCW164wkTOTzHkZb075tMQMULzrLUoUeKmO7eFL96GgDxf7/Axhc5CAuKE3KFyVW1p6ysKsi2oXAg== ++ dependencies: ++ "@babel/helper-string-parser" "^7.19.4" ++ "@babel/helper-validator-identifier" "^7.19.1" ++ to-fast-properties "^2.0.0" ++ ++"@ckeditor/ckeditor5-clipboard@^35.4.0": ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-35.4.0.tgz#8529fd45d06a7edea0f73cd0b5b3052f2272335c" ++ integrity sha512-B6rIQxvOrHvO9TZRC8JA0wKk+IfN880UJkYIg1qlhf9HFNVjdVbtHaiCsPD+TzGmQN3XHXfNjgjabGRIn0iZmw== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^35.4.0" ++ "@ckeditor/ckeditor5-engine" "^35.4.0" ++ "@ckeditor/ckeditor5-utils" "^35.4.0" ++ "@ckeditor/ckeditor5-widget" "^35.4.0" ++ lodash-es "^4.17.11" ++ ++"@ckeditor/ckeditor5-core@^35.4.0": ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-core/-/ckeditor5-core-35.4.0.tgz#39390445c8363a80d4ce0e45d93efa13b8523f6e" ++ integrity sha512-Rf0H7C4inCj/YC8aii0cT7TC/IuBIQ+tXmu9qd8/1BJ/rz1MCHXtBPApjTbFp33OE3aOFB5+NUaKt05k/dL3OA== ++ dependencies: ++ "@ckeditor/ckeditor5-engine" "^35.4.0" ++ "@ckeditor/ckeditor5-ui" "^35.4.0" ++ "@ckeditor/ckeditor5-utils" "^35.4.0" ++ lodash-es "^4.17.15" ++ ++"@ckeditor/ckeditor5-dev-utils@^30.0.0", "@ckeditor/ckeditor5-dev-utils@^30.5.0": ++ version "30.5.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-dev-utils/-/ckeditor5-dev-utils-30.5.0.tgz#798291a79183db716b667591a2ccebe6fcb7a7f8" ++ integrity sha512-R5oC9ka68X7NwafM5rFvIv6q0qT2kMsBkRikdEygx7cmGkV4dy7uM5HuOBUuIoLW7Md2o3QfkD3dnk6OdzuuJw== ++ dependencies: ++ "@babel/parser" "^7.18.9" ++ "@babel/traverse" "^7.18.9" ++ "@ckeditor/ckeditor5-dev-webpack-plugin" "^30.5.0" ++ chalk "^3.0.0" ++ cli-cursor "^3.1.0" ++ cli-spinners "^2.6.1" ++ cssnano "^5.0.0" ++ del "^5.0.0" ++ escodegen "^1.9.0" ++ fs-extra "^8.1.0" ++ is-interactive "^1.0.0" ++ javascript-stringify "^1.6.0" ++ pofile "^1.0.9" ++ postcss "^8.4.12" ++ postcss-import "^14.1.0" ++ postcss-loader "^4.3.0" ++ postcss-mixins "^9.0.2" ++ postcss-nesting "^10.1.4" ++ raw-loader "^4.0.1" ++ shelljs "^0.8.1" ++ style-loader "^2.0.0" ++ terser-webpack-plugin "^4.2.3" ++ through2 "^3.0.1" ++ ts-loader "^9.3.0" ++ ++"@ckeditor/ckeditor5-dev-webpack-plugin@^30.5.0": ++ version "30.5.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-dev-webpack-plugin/-/ckeditor5-dev-webpack-plugin-30.5.0.tgz#732033e117ce0b00cb0efaf009495ab767ec47de" ++ integrity sha512-mErNKfGd8XBjJxB7K7yCDnNq4pLQKbEjwJHf9g2EW4gOD1U55rgPc1XpmgfxhMj44QQ8YOZXAQ/Y/55AN7GATA== ++ dependencies: ++ "@ckeditor/ckeditor5-dev-utils" "^30.5.0" ++ chalk "^4.0.0" ++ rimraf "^3.0.2" ++ semver "^7.3.4" ++ webpack-sources "^2.0.1" ++ ++"@ckeditor/ckeditor5-engine@^35.4.0": ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-35.4.0.tgz#cb0ed9f0c5a9ef00b24ffbd8d2100fff1e0e90cb" ++ integrity sha512-67QKtUGJeLM072h9qURvzczYGU3ecuxR9LLmM4dffnV+PBNQ9e8RDCY7PuuEP0pplmAUI6/XqoZJIbk6h7ZV3Q== ++ dependencies: ++ "@ckeditor/ckeditor5-utils" "^35.4.0" ++ lodash-es "^4.17.15" ++ ++"@ckeditor/ckeditor5-enter@^35.4.0": ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-35.4.0.tgz#c0f967dc3f48faeb07d839ac0426227e118ade56" ++ integrity sha512-y95RnA/Gw72e220PJKVwNbwPzX4SRs82/rXu1jVyJXty7CcEZqqfyRtW6odICAXr5eKI5XKgzFgpFYULL3D9Nw== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^35.4.0" ++ "@ckeditor/ckeditor5-engine" "^35.4.0" ++ ++"@ckeditor/ckeditor5-paragraph@^35.4.0": ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-35.4.0.tgz#db6babd19eb37c66771b7355d0cd0880cb9b599c" ++ integrity sha512-8nhkEEFv1WClhH6q/HW8P596d+dlatSVc46kQ2+jGlYirL8P66tV/nK+OiE8z1d897oVr4QPGsqk2qGkRFUChw== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^35.4.0" ++ "@ckeditor/ckeditor5-ui" "^35.4.0" ++ "@ckeditor/ckeditor5-utils" "^35.4.0" ++ ++"@ckeditor/ckeditor5-select-all@^35.4.0": ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-35.4.0.tgz#b7c20e9f686e59497e84825c4786dd874e22d4e2" ++ integrity sha512-c+pIIY77SP6ux4/cyD7cCrllQAqtFVSnzNYdy7ygNPqljCGngCnpSV9xfCO/blFo6/zx2vsmzVGdRq3ArzGoMg== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^35.4.0" ++ "@ckeditor/ckeditor5-ui" "^35.4.0" ++ "@ckeditor/ckeditor5-utils" "^35.4.0" ++ ++"@ckeditor/ckeditor5-typing@^35.4.0": ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-35.4.0.tgz#b786032a541cfd102562eb07c21c62e0b6d502c6" ++ integrity sha512-Ad/PHWbVWcnAj9oevkkfLqf6CmvCFOti466uhvfOCKRNVf2+/xuGwleOGr8W6Lir/x/qav7ojFjKPKDxqbPXhA== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^35.4.0" ++ "@ckeditor/ckeditor5-engine" "^35.4.0" ++ "@ckeditor/ckeditor5-utils" "^35.4.0" ++ lodash-es "^4.17.15" ++ ++"@ckeditor/ckeditor5-ui@^35.4.0": ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-35.4.0.tgz#76e59032aee6652c6bd717f30fc330a064b3451e" ++ integrity sha512-0SmYE+k1cYQPqyw2rQsPDV/RpudneBh1bNfiaTOz+rqViJIMe+TxiuK6Fz+znNZ05s0exr+ZHWvMttGqlVoQNw== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^35.4.0" ++ "@ckeditor/ckeditor5-utils" "^35.4.0" ++ lodash-es "^4.17.15" ++ ++"@ckeditor/ckeditor5-undo@^35.4.0": ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-35.4.0.tgz#f79b19be69b8b9ab57592cfe4ec4645b3728b773" ++ integrity sha512-0RhsK0f/pX/7KB/JXYTLiDOswmUTQ9EKIIuewAwr7LTsBf4Q309FZSFdbeTmc0wIyX33212Xh5xsi3LyG1VJRg== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^35.4.0" ++ "@ckeditor/ckeditor5-engine" "^35.4.0" ++ "@ckeditor/ckeditor5-ui" "^35.4.0" ++ ++"@ckeditor/ckeditor5-upload@^35.4.0": ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-35.4.0.tgz#57944a4e824cdee37bb53d795dbe98055e11d748" ++ integrity sha512-+eJAluAc4mAFmx5FNuSGjkCYmbm0V9NpSleubAXEx2e+KNiLarPAnsolwRaAcYXcloNp4C9/l0D+lPEx7VRYtg== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^35.4.0" ++ "@ckeditor/ckeditor5-ui" "^35.4.0" ++ "@ckeditor/ckeditor5-utils" "^35.4.0" ++ ++"@ckeditor/ckeditor5-utils@^35.4.0": ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-35.4.0.tgz#c5c296a2c1883684e674b1a710fcc41b745e156b" ++ integrity sha512-sFjbb+1VYdLbELDLWVYk86WzVN7Lo3sXHbVhdr8+kc0Ufxdr3mTFHDAkiymFt2fs1FOB5gZyWJlJU+EeJnhKUw== ++ dependencies: ++ lodash-es "^4.17.15" ++ ++"@ckeditor/ckeditor5-widget@^35.4.0": ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-35.4.0.tgz#a80ed4c4f57a1198b47c4e93090f8ebe62f70ecb" ++ integrity sha512-SNYOXXWu7XV1BZET+ar0Cea25836vzNtUqXlDPwBx/jrmK86b8GMbFR99P2bUG0NvtIsH5cSk7XCmnxb4ZQ6wA== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^35.4.0" ++ "@ckeditor/ckeditor5-engine" "^35.4.0" ++ "@ckeditor/ckeditor5-enter" "^35.4.0" ++ "@ckeditor/ckeditor5-typing" "^35.4.0" ++ "@ckeditor/ckeditor5-ui" "^35.4.0" ++ "@ckeditor/ckeditor5-utils" "^35.4.0" ++ lodash-es "^4.17.15" ++ ++"@csstools/selector-specificity@^2.0.0": ++ version "2.0.2" ++ resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.2.tgz#1bfafe4b7ed0f3e4105837e056e0a89b108ebe36" ++ integrity sha512-IkpVW/ehM1hWKln4fCA3NzJU8KwD+kIOvPZA4cqxoJHtE21CCzjyp+Kxbu0i5I4tBNOlXPL9mjwnWlL0VEG4Fg== ++ ++"@discoveryjs/json-ext@^0.5.0": ++ version "0.5.7" ++ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" ++ integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== ++ ++"@gar/promisify@^1.0.1": ++ version "1.1.3" ++ resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" ++ integrity sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw== ++ ++"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": ++ version "0.3.2" ++ resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz#c1aedc61e853f2bb9f5dfe6d4442d3b565b253b9" ++ integrity sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A== ++ dependencies: ++ "@jridgewell/set-array" "^1.0.1" ++ "@jridgewell/sourcemap-codec" "^1.4.10" ++ "@jridgewell/trace-mapping" "^0.3.9" ++ ++"@jridgewell/resolve-uri@3.1.0": ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" ++ integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== ++ ++"@jridgewell/set-array@^1.0.1": ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" ++ integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== ++ ++"@jridgewell/source-map@^0.3.2": ++ version "0.3.2" ++ resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb" ++ integrity sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw== ++ dependencies: ++ "@jridgewell/gen-mapping" "^0.3.0" ++ "@jridgewell/trace-mapping" "^0.3.9" ++ ++"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": ++ version "1.4.14" ++ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" ++ integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== ++ ++"@jridgewell/trace-mapping@^0.3.14", "@jridgewell/trace-mapping@^0.3.9": ++ version "0.3.17" ++ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" ++ integrity sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g== ++ dependencies: ++ "@jridgewell/resolve-uri" "3.1.0" ++ "@jridgewell/sourcemap-codec" "1.4.14" ++ ++"@nodelib/fs.scandir@2.1.5": ++ version "2.1.5" ++ resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" ++ integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== ++ dependencies: ++ "@nodelib/fs.stat" "2.0.5" ++ run-parallel "^1.1.9" ++ ++"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": ++ version "2.0.5" ++ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" ++ integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== ++ ++"@nodelib/fs.walk@^1.2.3": ++ version "1.2.8" ++ resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" ++ integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== ++ dependencies: ++ "@nodelib/fs.scandir" "2.1.5" ++ fastq "^1.6.0" ++ ++"@npmcli/fs@^1.0.0": ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/@npmcli/fs/-/fs-1.1.1.tgz#72f719fe935e687c56a4faecf3c03d06ba593257" ++ integrity sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ== ++ dependencies: ++ "@gar/promisify" "^1.0.1" ++ semver "^7.3.5" ++ ++"@npmcli/move-file@^1.0.1": ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/@npmcli/move-file/-/move-file-1.1.2.tgz#1a82c3e372f7cae9253eb66d72543d6b8685c674" ++ integrity sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg== ++ dependencies: ++ mkdirp "^1.0.4" ++ rimraf "^3.0.2" ++ ++"@trysound/sax@0.2.0": ++ version "0.2.0" ++ resolved "https://registry.yarnpkg.com/@trysound/sax/-/sax-0.2.0.tgz#cccaab758af56761eb7bf37af6f03f326dd798ad" ++ integrity sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA== ++ ++"@types/eslint-scope@^3.7.3": ++ version "3.7.4" ++ resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.4.tgz#37fc1223f0786c39627068a12e94d6e6fc61de16" ++ integrity sha512-9K4zoImiZc3HlIp6AVUDE4CWYx22a+lhSZMYNpbjW04+YF0KWj4pJXnEMjdnFTiQibFFmElcsasJXDbdI/EPhA== ++ dependencies: ++ "@types/eslint" "*" ++ "@types/estree" "*" ++ ++"@types/eslint@*": ++ version "8.4.9" ++ resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.9.tgz#f7371980148697f4b582b086630319b55324b5aa" ++ integrity sha512-jFCSo4wJzlHQLCpceUhUnXdrPuCNOjGFMQ8Eg6JXxlz3QaCKOb7eGi2cephQdM4XTYsNej69P9JDJ1zqNIbncQ== ++ dependencies: ++ "@types/estree" "*" ++ "@types/json-schema" "*" ++ ++"@types/estree@*": ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.0.tgz#5fb2e536c1ae9bf35366eed879e827fa59ca41c2" ++ integrity sha512-WulqXMDUTYAXCjZnk6JtIHPigp55cVtDgDrO2gHRwhyJto21+1zbVCtOYB2L1F9w4qCQ0rOGWBnBe0FNTiEJIQ== ++ ++"@types/estree@^0.0.51": ++ version "0.0.51" ++ resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" ++ integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== ++ ++"@types/glob@^7.1.1": ++ version "7.2.0" ++ resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.2.0.tgz#bc1b5bf3aa92f25bd5dd39f35c57361bdce5b2eb" ++ integrity sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA== ++ dependencies: ++ "@types/minimatch" "*" ++ "@types/node" "*" ++ ++"@types/json-schema@*", "@types/json-schema@^7.0.8": ++ version "7.0.11" ++ resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" ++ integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== ++ ++"@types/minimatch@*": ++ version "5.1.2" ++ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-5.1.2.tgz#07508b45797cb81ec3f273011b054cd0755eddca" ++ integrity sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA== ++ ++"@types/node@*": ++ version "18.11.9" ++ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4" ++ integrity sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg== ++ ++"@types/parse-json@^4.0.0": ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" ++ integrity sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA== ++ ++"@webassemblyjs/ast@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" ++ integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== ++ dependencies: ++ "@webassemblyjs/helper-numbers" "1.11.1" ++ "@webassemblyjs/helper-wasm-bytecode" "1.11.1" ++ ++"@webassemblyjs/floating-point-hex-parser@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" ++ integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== ++ ++"@webassemblyjs/helper-api-error@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" ++ integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== ++ ++"@webassemblyjs/helper-buffer@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" ++ integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== ++ ++"@webassemblyjs/helper-numbers@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" ++ integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== ++ dependencies: ++ "@webassemblyjs/floating-point-hex-parser" "1.11.1" ++ "@webassemblyjs/helper-api-error" "1.11.1" ++ "@xtuc/long" "4.2.2" ++ ++"@webassemblyjs/helper-wasm-bytecode@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" ++ integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== ++ ++"@webassemblyjs/helper-wasm-section@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" ++ integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== ++ dependencies: ++ "@webassemblyjs/ast" "1.11.1" ++ "@webassemblyjs/helper-buffer" "1.11.1" ++ "@webassemblyjs/helper-wasm-bytecode" "1.11.1" ++ "@webassemblyjs/wasm-gen" "1.11.1" ++ ++"@webassemblyjs/ieee754@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" ++ integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== ++ dependencies: ++ "@xtuc/ieee754" "^1.2.0" ++ ++"@webassemblyjs/leb128@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" ++ integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== ++ dependencies: ++ "@xtuc/long" "4.2.2" ++ ++"@webassemblyjs/utf8@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" ++ integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== ++ ++"@webassemblyjs/wasm-edit@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" ++ integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== ++ dependencies: ++ "@webassemblyjs/ast" "1.11.1" ++ "@webassemblyjs/helper-buffer" "1.11.1" ++ "@webassemblyjs/helper-wasm-bytecode" "1.11.1" ++ "@webassemblyjs/helper-wasm-section" "1.11.1" ++ "@webassemblyjs/wasm-gen" "1.11.1" ++ "@webassemblyjs/wasm-opt" "1.11.1" ++ "@webassemblyjs/wasm-parser" "1.11.1" ++ "@webassemblyjs/wast-printer" "1.11.1" ++ ++"@webassemblyjs/wasm-gen@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" ++ integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== ++ dependencies: ++ "@webassemblyjs/ast" "1.11.1" ++ "@webassemblyjs/helper-wasm-bytecode" "1.11.1" ++ "@webassemblyjs/ieee754" "1.11.1" ++ "@webassemblyjs/leb128" "1.11.1" ++ "@webassemblyjs/utf8" "1.11.1" ++ ++"@webassemblyjs/wasm-opt@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" ++ integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== ++ dependencies: ++ "@webassemblyjs/ast" "1.11.1" ++ "@webassemblyjs/helper-buffer" "1.11.1" ++ "@webassemblyjs/wasm-gen" "1.11.1" ++ "@webassemblyjs/wasm-parser" "1.11.1" ++ ++"@webassemblyjs/wasm-parser@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" ++ integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== ++ dependencies: ++ "@webassemblyjs/ast" "1.11.1" ++ "@webassemblyjs/helper-api-error" "1.11.1" ++ "@webassemblyjs/helper-wasm-bytecode" "1.11.1" ++ "@webassemblyjs/ieee754" "1.11.1" ++ "@webassemblyjs/leb128" "1.11.1" ++ "@webassemblyjs/utf8" "1.11.1" ++ ++"@webassemblyjs/wast-printer@1.11.1": ++ version "1.11.1" ++ resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" ++ integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== ++ dependencies: ++ "@webassemblyjs/ast" "1.11.1" ++ "@xtuc/long" "4.2.2" ++ ++"@webpack-cli/configtest@^1.2.0": ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/@webpack-cli/configtest/-/configtest-1.2.0.tgz#7b20ce1c12533912c3b217ea68262365fa29a6f5" ++ integrity sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg== ++ ++"@webpack-cli/info@^1.5.0": ++ version "1.5.0" ++ resolved "https://registry.yarnpkg.com/@webpack-cli/info/-/info-1.5.0.tgz#6c78c13c5874852d6e2dd17f08a41f3fe4c261b1" ++ integrity sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ== ++ dependencies: ++ envinfo "^7.7.3" ++ ++"@webpack-cli/serve@^1.7.0": ++ version "1.7.0" ++ resolved "https://registry.yarnpkg.com/@webpack-cli/serve/-/serve-1.7.0.tgz#e1993689ac42d2b16e9194376cfb6753f6254db1" ++ integrity sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q== ++ ++"@xtuc/ieee754@^1.2.0": ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" ++ integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== ++ ++"@xtuc/long@4.2.2": ++ version "4.2.2" ++ resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" ++ integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== ++ ++acorn-import-assertions@^1.7.6: ++ version "1.8.0" ++ resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" ++ integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== ++ ++acorn@^8.5.0, acorn@^8.7.1: ++ version "8.8.1" ++ resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" ++ integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== ++ ++aggregate-error@^3.0.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" ++ integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== ++ dependencies: ++ clean-stack "^2.0.0" ++ indent-string "^4.0.0" ++ ++ajv-keywords@^3.5.2: ++ version "3.5.2" ++ resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" ++ integrity sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ== ++ ++ajv@^6.12.5: ++ version "6.12.6" ++ resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" ++ integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== ++ dependencies: ++ fast-deep-equal "^3.1.1" ++ fast-json-stable-stringify "^2.0.0" ++ json-schema-traverse "^0.4.1" ++ uri-js "^4.2.2" ++ ++ansi-styles@^3.2.1: ++ version "3.2.1" ++ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" ++ integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== ++ dependencies: ++ color-convert "^1.9.0" ++ ++ansi-styles@^4.1.0: ++ version "4.3.0" ++ resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" ++ integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== ++ dependencies: ++ color-convert "^2.0.1" ++ ++array-union@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" ++ integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== ++ ++balanced-match@^1.0.0: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" ++ integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== ++ ++big.js@^5.2.2: ++ version "5.2.2" ++ resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" ++ integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== ++ ++boolbase@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" ++ integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== ++ ++brace-expansion@^1.1.7: ++ version "1.1.11" ++ resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" ++ integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== ++ dependencies: ++ balanced-match "^1.0.0" ++ concat-map "0.0.1" ++ ++braces@^3.0.2: ++ version "3.0.2" ++ resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" ++ integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== ++ dependencies: ++ fill-range "^7.0.1" ++ ++browserslist@^4.0.0, browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.21.4: ++ version "4.21.4" ++ resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.21.4.tgz#e7496bbc67b9e39dd0f98565feccdcb0d4ff6987" ++ integrity sha512-CBHJJdDmgjl3daYjN5Cp5kbTf1mUhZoS+beLklHIvkOWscs83YAhLlF3Wsh/lciQYAcbBJgTOD44VtG31ZM4Hw== ++ dependencies: ++ caniuse-lite "^1.0.30001400" ++ electron-to-chromium "^1.4.251" ++ node-releases "^2.0.6" ++ update-browserslist-db "^1.0.9" ++ ++buffer-from@^1.0.0: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" ++ integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== ++ ++cacache@^15.0.5: ++ version "15.3.0" ++ resolved "https://registry.yarnpkg.com/cacache/-/cacache-15.3.0.tgz#dc85380fb2f556fe3dda4c719bfa0ec875a7f1eb" ++ integrity sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ== ++ dependencies: ++ "@npmcli/fs" "^1.0.0" ++ "@npmcli/move-file" "^1.0.1" ++ chownr "^2.0.0" ++ fs-minipass "^2.0.0" ++ glob "^7.1.4" ++ infer-owner "^1.0.4" ++ lru-cache "^6.0.0" ++ minipass "^3.1.1" ++ minipass-collect "^1.0.2" ++ minipass-flush "^1.0.5" ++ minipass-pipeline "^1.2.2" ++ mkdirp "^1.0.3" ++ p-map "^4.0.0" ++ promise-inflight "^1.0.1" ++ rimraf "^3.0.2" ++ ssri "^8.0.1" ++ tar "^6.0.2" ++ unique-filename "^1.1.1" ++ ++callsites@^3.0.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" ++ integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== ++ ++camelcase-css@^2.0.1: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" ++ integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== ++ ++caniuse-api@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" ++ integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== ++ dependencies: ++ browserslist "^4.0.0" ++ caniuse-lite "^1.0.0" ++ lodash.memoize "^4.1.2" ++ lodash.uniq "^4.5.0" ++ ++caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001400: ++ version "1.0.30001429" ++ resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001429.tgz#70cdae959096756a85713b36dd9cb82e62325639" ++ integrity sha512-511ThLu1hF+5RRRt0zYCf2U2yRr9GPF6m5y90SBCWsvSoYoW7yAGlv/elyPaNfvGCkp6kj/KFZWU0BMA69Prsg== ++ ++chalk@^2.0.0: ++ version "2.4.2" ++ resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" ++ integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== ++ dependencies: ++ ansi-styles "^3.2.1" ++ escape-string-regexp "^1.0.5" ++ supports-color "^5.3.0" ++ ++chalk@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" ++ integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== ++ dependencies: ++ ansi-styles "^4.1.0" ++ supports-color "^7.1.0" ++ ++chalk@^4.0.0, chalk@^4.1.0: ++ version "4.1.2" ++ resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" ++ integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== ++ dependencies: ++ ansi-styles "^4.1.0" ++ supports-color "^7.1.0" ++ ++chownr@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece" ++ integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ== ++ ++chrome-trace-event@^1.0.2: ++ version "1.0.3" ++ resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" ++ integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== ++ ++ckeditor5@~35.4.0: ++ version "35.4.0" ++ resolved "https://registry.yarnpkg.com/ckeditor5/-/ckeditor5-35.4.0.tgz#0ce67af211551b96856b780e3729481cadbb34df" ++ integrity sha512-vBEQVkFCbjYmEPVkyWsOqU44DOovUio6xBuCwroe4TuJLplqeRasCjFwB0DPknXQU8U0iM3Lh/QSKRyN92pw3Q== ++ dependencies: ++ "@ckeditor/ckeditor5-clipboard" "^35.4.0" ++ "@ckeditor/ckeditor5-core" "^35.4.0" ++ "@ckeditor/ckeditor5-engine" "^35.4.0" ++ "@ckeditor/ckeditor5-enter" "^35.4.0" ++ "@ckeditor/ckeditor5-paragraph" "^35.4.0" ++ "@ckeditor/ckeditor5-select-all" "^35.4.0" ++ "@ckeditor/ckeditor5-typing" "^35.4.0" ++ "@ckeditor/ckeditor5-ui" "^35.4.0" ++ "@ckeditor/ckeditor5-undo" "^35.4.0" ++ "@ckeditor/ckeditor5-upload" "^35.4.0" ++ "@ckeditor/ckeditor5-utils" "^35.4.0" ++ "@ckeditor/ckeditor5-widget" "^35.4.0" ++ ++clean-stack@^2.0.0: ++ version "2.2.0" ++ resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" ++ integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== ++ ++cli-cursor@^3.1.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-3.1.0.tgz#264305a7ae490d1d03bf0c9ba7c925d1753af307" ++ integrity sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw== ++ dependencies: ++ restore-cursor "^3.1.0" ++ ++cli-spinners@^2.6.1: ++ version "2.7.0" ++ resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.7.0.tgz#f815fd30b5f9eaac02db604c7a231ed7cb2f797a" ++ integrity sha512-qu3pN8Y3qHNgE2AFweciB1IfMnmZ/fsNTEE+NOFjmGB2F/7rLhnhzppvpCnN4FovtP26k8lHyy9ptEbNwWFLzw== ++ ++clone-deep@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-4.0.1.tgz#c19fd9bdbbf85942b4fd979c84dcf7d5f07c2387" ++ integrity sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ== ++ dependencies: ++ is-plain-object "^2.0.4" ++ kind-of "^6.0.2" ++ shallow-clone "^3.0.0" ++ ++color-convert@^1.9.0: ++ version "1.9.3" ++ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" ++ integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== ++ dependencies: ++ color-name "1.1.3" ++ ++color-convert@^2.0.1: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" ++ integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== ++ dependencies: ++ color-name "~1.1.4" ++ ++color-name@1.1.3: ++ version "1.1.3" ++ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" ++ integrity sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw== ++ ++color-name@~1.1.4: ++ version "1.1.4" ++ resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" ++ integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== ++ ++colord@^2.9.1: ++ version "2.9.3" ++ resolved "https://registry.yarnpkg.com/colord/-/colord-2.9.3.tgz#4f8ce919de456f1d5c1c368c307fe20f3e59fb43" ++ integrity sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw== ++ ++colorette@^2.0.14: ++ version "2.0.19" ++ resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.19.tgz#cdf044f47ad41a0f4b56b3a0d5b4e6e1a2d5a798" ++ integrity sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ== ++ ++commander@^2.20.0: ++ version "2.20.3" ++ resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" ++ integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== ++ ++commander@^7.0.0, commander@^7.2.0: ++ version "7.2.0" ++ resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7" ++ integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw== ++ ++commondir@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" ++ integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== ++ ++concat-map@0.0.1: ++ version "0.0.1" ++ resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" ++ integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== ++ ++cosmiconfig@^7.0.0: ++ version "7.0.1" ++ resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.0.1.tgz#714d756522cace867867ccb4474c5d01bbae5d6d" ++ integrity sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ== ++ dependencies: ++ "@types/parse-json" "^4.0.0" ++ import-fresh "^3.2.1" ++ parse-json "^5.0.0" ++ path-type "^4.0.0" ++ yaml "^1.10.0" ++ ++cross-spawn@^7.0.3: ++ version "7.0.3" ++ resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" ++ integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== ++ dependencies: ++ path-key "^3.1.0" ++ shebang-command "^2.0.0" ++ which "^2.0.1" ++ ++css-declaration-sorter@^6.3.1: ++ version "6.3.1" ++ resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-6.3.1.tgz#be5e1d71b7a992433fb1c542c7a1b835e45682ec" ++ integrity sha512-fBffmak0bPAnyqc/HO8C3n2sHrp9wcqQz6ES9koRF2/mLOVAx9zIQ3Y7R29sYCteTPqMCwns4WYQoCX91Xl3+w== ++ ++css-select@^4.1.3: ++ version "4.3.0" ++ resolved "https://registry.yarnpkg.com/css-select/-/css-select-4.3.0.tgz#db7129b2846662fd8628cfc496abb2b59e41529b" ++ integrity sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ== ++ dependencies: ++ boolbase "^1.0.0" ++ css-what "^6.0.1" ++ domhandler "^4.3.1" ++ domutils "^2.8.0" ++ nth-check "^2.0.1" ++ ++css-tree@^1.1.2, css-tree@^1.1.3: ++ version "1.1.3" ++ resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.1.3.tgz#eb4870fb6fd7707327ec95c2ff2ab09b5e8db91d" ++ integrity sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q== ++ dependencies: ++ mdn-data "2.0.14" ++ source-map "^0.6.1" ++ ++css-what@^6.0.1: ++ version "6.1.0" ++ resolved "https://registry.yarnpkg.com/css-what/-/css-what-6.1.0.tgz#fb5effcf76f1ddea2c81bdfaa4de44e79bac70f4" ++ integrity sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw== ++ ++cssesc@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" ++ integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== ++ ++cssnano-preset-default@^5.2.13: ++ version "5.2.13" ++ resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-5.2.13.tgz#e7353b0c57975d1bdd97ac96e68e5c1b8c68e990" ++ integrity sha512-PX7sQ4Pb+UtOWuz8A1d+Rbi+WimBIxJTRyBdgGp1J75VU0r/HFQeLnMYgHiCAp6AR4rqrc7Y4R+1Rjk3KJz6DQ== ++ dependencies: ++ css-declaration-sorter "^6.3.1" ++ cssnano-utils "^3.1.0" ++ postcss-calc "^8.2.3" ++ postcss-colormin "^5.3.0" ++ postcss-convert-values "^5.1.3" ++ postcss-discard-comments "^5.1.2" ++ postcss-discard-duplicates "^5.1.0" ++ postcss-discard-empty "^5.1.1" ++ postcss-discard-overridden "^5.1.0" ++ postcss-merge-longhand "^5.1.7" ++ postcss-merge-rules "^5.1.3" ++ postcss-minify-font-values "^5.1.0" ++ postcss-minify-gradients "^5.1.1" ++ postcss-minify-params "^5.1.4" ++ postcss-minify-selectors "^5.2.1" ++ postcss-normalize-charset "^5.1.0" ++ postcss-normalize-display-values "^5.1.0" ++ postcss-normalize-positions "^5.1.1" ++ postcss-normalize-repeat-style "^5.1.1" ++ postcss-normalize-string "^5.1.0" ++ postcss-normalize-timing-functions "^5.1.0" ++ postcss-normalize-unicode "^5.1.1" ++ postcss-normalize-url "^5.1.0" ++ postcss-normalize-whitespace "^5.1.1" ++ postcss-ordered-values "^5.1.3" ++ postcss-reduce-initial "^5.1.1" ++ postcss-reduce-transforms "^5.1.0" ++ postcss-svgo "^5.1.0" ++ postcss-unique-selectors "^5.1.1" ++ ++cssnano-utils@^3.1.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/cssnano-utils/-/cssnano-utils-3.1.0.tgz#95684d08c91511edfc70d2636338ca37ef3a6861" ++ integrity sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA== ++ ++cssnano@^5.0.0: ++ version "5.1.14" ++ resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-5.1.14.tgz#07b0af6da73641276fe5a6d45757702ebae2eb05" ++ integrity sha512-Oou7ihiTocbKqi0J1bB+TRJIQX5RMR3JghA8hcWSw9mjBLQ5Y3RWqEDoYG3sRNlAbCIXpqMoZGbq5KDR3vdzgw== ++ dependencies: ++ cssnano-preset-default "^5.2.13" ++ lilconfig "^2.0.3" ++ yaml "^1.10.2" ++ ++csso@^4.2.0: ++ version "4.2.0" ++ resolved "https://registry.yarnpkg.com/csso/-/csso-4.2.0.tgz#ea3a561346e8dc9f546d6febedd50187cf389529" ++ integrity sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA== ++ dependencies: ++ css-tree "^1.1.2" ++ ++debug@^4.1.0: ++ version "4.3.4" ++ resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" ++ integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== ++ dependencies: ++ ms "2.1.2" ++ ++deep-is@~0.1.3: ++ version "0.1.4" ++ resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" ++ integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== ++ ++del@^5.0.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/del/-/del-5.1.0.tgz#d9487c94e367410e6eff2925ee58c0c84a75b3a7" ++ integrity sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA== ++ dependencies: ++ globby "^10.0.1" ++ graceful-fs "^4.2.2" ++ is-glob "^4.0.1" ++ is-path-cwd "^2.2.0" ++ is-path-inside "^3.0.1" ++ p-map "^3.0.0" ++ rimraf "^3.0.0" ++ slash "^3.0.0" ++ ++dir-glob@^3.0.1: ++ version "3.0.1" ++ resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" ++ integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== ++ dependencies: ++ path-type "^4.0.0" ++ ++dom-serializer@^1.0.1: ++ version "1.4.1" ++ resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-1.4.1.tgz#de5d41b1aea290215dc45a6dae8adcf1d32e2d30" ++ integrity sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag== ++ dependencies: ++ domelementtype "^2.0.1" ++ domhandler "^4.2.0" ++ entities "^2.0.0" ++ ++domelementtype@^2.0.1, domelementtype@^2.2.0: ++ version "2.3.0" ++ resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.3.0.tgz#5c45e8e869952626331d7aab326d01daf65d589d" ++ integrity sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw== ++ ++domhandler@^4.2.0, domhandler@^4.3.1: ++ version "4.3.1" ++ resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-4.3.1.tgz#8d792033416f59d68bc03a5aa7b018c1ca89279c" ++ integrity sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ== ++ dependencies: ++ domelementtype "^2.2.0" ++ ++domutils@^2.8.0: ++ version "2.8.0" ++ resolved "https://registry.yarnpkg.com/domutils/-/domutils-2.8.0.tgz#4437def5db6e2d1f5d6ee859bd95ca7d02048135" ++ integrity sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A== ++ dependencies: ++ dom-serializer "^1.0.1" ++ domelementtype "^2.2.0" ++ domhandler "^4.2.0" ++ ++electron-to-chromium@^1.4.251: ++ version "1.4.284" ++ resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" ++ integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== ++ ++emojis-list@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" ++ integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== ++ ++enhanced-resolve@^5.0.0, enhanced-resolve@^5.10.0: ++ version "5.10.0" ++ resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" ++ integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== ++ dependencies: ++ graceful-fs "^4.2.4" ++ tapable "^2.2.0" ++ ++entities@^2.0.0: ++ version "2.2.0" ++ resolved "https://registry.yarnpkg.com/entities/-/entities-2.2.0.tgz#098dc90ebb83d8dffa089d55256b351d34c4da55" ++ integrity sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A== ++ ++envinfo@^7.7.3: ++ version "7.8.1" ++ resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.8.1.tgz#06377e3e5f4d379fea7ac592d5ad8927e0c4d475" ++ integrity sha512-/o+BXHmB7ocbHEAs6F2EnG0ogybVVUdkRunTT2glZU9XAaGmhqskrvKwqXuDfNjEO0LZKWdejEEpnq8aM0tOaw== ++ ++error-ex@^1.3.1: ++ version "1.3.2" ++ resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" ++ integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== ++ dependencies: ++ is-arrayish "^0.2.1" ++ ++es-module-lexer@^0.9.0: ++ version "0.9.3" ++ resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" ++ integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== ++ ++escalade@^3.1.1: ++ version "3.1.1" ++ resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" ++ integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== ++ ++escape-string-regexp@^1.0.5: ++ version "1.0.5" ++ resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" ++ integrity sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg== ++ ++escodegen@^1.9.0: ++ version "1.14.3" ++ resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-1.14.3.tgz#4e7b81fba61581dc97582ed78cab7f0e8d63f503" ++ integrity sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw== ++ dependencies: ++ esprima "^4.0.1" ++ estraverse "^4.2.0" ++ esutils "^2.0.2" ++ optionator "^0.8.1" ++ optionalDependencies: ++ source-map "~0.6.1" ++ ++eslint-scope@5.1.1: ++ version "5.1.1" ++ resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" ++ integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== ++ dependencies: ++ esrecurse "^4.3.0" ++ estraverse "^4.1.1" ++ ++esprima@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" ++ integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== ++ ++esrecurse@^4.3.0: ++ version "4.3.0" ++ resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" ++ integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== ++ dependencies: ++ estraverse "^5.2.0" ++ ++estraverse@^4.1.1, estraverse@^4.2.0: ++ version "4.3.0" ++ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" ++ integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== ++ ++estraverse@^5.2.0: ++ version "5.3.0" ++ resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" ++ integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== ++ ++esutils@^2.0.2: ++ version "2.0.3" ++ resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" ++ integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== ++ ++events@^3.2.0: ++ version "3.3.0" ++ resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" ++ integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== ++ ++fast-deep-equal@^3.1.1: ++ version "3.1.3" ++ resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" ++ integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== ++ ++fast-glob@^3.0.3, fast-glob@^3.2.11: ++ version "3.2.12" ++ resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" ++ integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== ++ dependencies: ++ "@nodelib/fs.stat" "^2.0.2" ++ "@nodelib/fs.walk" "^1.2.3" ++ glob-parent "^5.1.2" ++ merge2 "^1.3.0" ++ micromatch "^4.0.4" ++ ++fast-json-stable-stringify@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" ++ integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== ++ ++fast-levenshtein@~2.0.6: ++ version "2.0.6" ++ resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" ++ integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== ++ ++fastest-levenshtein@^1.0.12: ++ version "1.0.16" ++ resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz#210e61b6ff181de91ea9b3d1b84fdedd47e034e5" ++ integrity sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg== ++ ++fastq@^1.6.0: ++ version "1.13.0" ++ resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" ++ integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== ++ dependencies: ++ reusify "^1.0.4" ++ ++fill-range@^7.0.1: ++ version "7.0.1" ++ resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" ++ integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== ++ dependencies: ++ to-regex-range "^5.0.1" ++ ++find-cache-dir@^3.3.1: ++ version "3.3.2" ++ resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" ++ integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== ++ dependencies: ++ commondir "^1.0.1" ++ make-dir "^3.0.2" ++ pkg-dir "^4.1.0" ++ ++find-up@^4.0.0: ++ version "4.1.0" ++ resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" ++ integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== ++ dependencies: ++ locate-path "^5.0.0" ++ path-exists "^4.0.0" ++ ++fs-extra@^8.1.0: ++ version "8.1.0" ++ resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" ++ integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== ++ dependencies: ++ graceful-fs "^4.2.0" ++ jsonfile "^4.0.0" ++ universalify "^0.1.0" ++ ++fs-minipass@^2.0.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" ++ integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== ++ dependencies: ++ minipass "^3.0.0" ++ ++fs.realpath@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" ++ integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== ++ ++function-bind@^1.1.1: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" ++ integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== ++ ++glob-parent@^5.1.2: ++ version "5.1.2" ++ resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" ++ integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== ++ dependencies: ++ is-glob "^4.0.1" ++ ++glob-to-regexp@^0.4.1: ++ version "0.4.1" ++ resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" ++ integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== ++ ++glob@^7.0.0, glob@^7.1.3, glob@^7.1.4: ++ version "7.2.3" ++ resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" ++ integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== ++ dependencies: ++ fs.realpath "^1.0.0" ++ inflight "^1.0.4" ++ inherits "2" ++ minimatch "^3.1.1" ++ once "^1.3.0" ++ path-is-absolute "^1.0.0" ++ ++globals@^11.1.0: ++ version "11.12.0" ++ resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" ++ integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== ++ ++globby@^10.0.1: ++ version "10.0.2" ++ resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" ++ integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== ++ dependencies: ++ "@types/glob" "^7.1.1" ++ array-union "^2.1.0" ++ dir-glob "^3.0.1" ++ fast-glob "^3.0.3" ++ glob "^7.1.3" ++ ignore "^5.1.1" ++ merge2 "^1.2.3" ++ slash "^3.0.0" ++ ++graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2, graceful-fs@^4.2.4, graceful-fs@^4.2.9: ++ version "4.2.10" ++ resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" ++ integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== ++ ++has-flag@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" ++ integrity sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw== ++ ++has-flag@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" ++ integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== ++ ++has@^1.0.3: ++ version "1.0.3" ++ resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" ++ integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== ++ dependencies: ++ function-bind "^1.1.1" ++ ++ignore@^5.1.1: ++ version "5.2.0" ++ resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" ++ integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== ++ ++import-fresh@^3.2.1: ++ version "3.3.0" ++ resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" ++ integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== ++ dependencies: ++ parent-module "^1.0.0" ++ resolve-from "^4.0.0" ++ ++import-local@^3.0.2: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/import-local/-/import-local-3.1.0.tgz#b4479df8a5fd44f6cdce24070675676063c95cb4" ++ integrity sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg== ++ dependencies: ++ pkg-dir "^4.2.0" ++ resolve-cwd "^3.0.0" ++ ++imurmurhash@^0.1.4: ++ version "0.1.4" ++ resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" ++ integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== ++ ++indent-string@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" ++ integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== ++ ++infer-owner@^1.0.4: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" ++ integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== ++ ++inflight@^1.0.4: ++ version "1.0.6" ++ resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" ++ integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== ++ dependencies: ++ once "^1.3.0" ++ wrappy "1" ++ ++inherits@2, inherits@^2.0.3, inherits@^2.0.4: ++ version "2.0.4" ++ resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" ++ integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== ++ ++interpret@^1.0.0: ++ version "1.4.0" ++ resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" ++ integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== ++ ++interpret@^2.2.0: ++ version "2.2.0" ++ resolved "https://registry.yarnpkg.com/interpret/-/interpret-2.2.0.tgz#1a78a0b5965c40a5416d007ad6f50ad27c417df9" ++ integrity sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw== ++ ++is-arrayish@^0.2.1: ++ version "0.2.1" ++ resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" ++ integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== ++ ++is-core-module@^2.9.0: ++ version "2.11.0" ++ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" ++ integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== ++ dependencies: ++ has "^1.0.3" ++ ++is-extglob@^2.1.1: ++ version "2.1.1" ++ resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" ++ integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== ++ ++is-glob@^4.0.1: ++ version "4.0.3" ++ resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" ++ integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== ++ dependencies: ++ is-extglob "^2.1.1" ++ ++is-interactive@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" ++ integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== ++ ++is-number@^7.0.0: ++ version "7.0.0" ++ resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" ++ integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== ++ ++is-path-cwd@^2.2.0: ++ version "2.2.0" ++ resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" ++ integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== ++ ++is-path-inside@^3.0.1: ++ version "3.0.3" ++ resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" ++ integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== ++ ++is-plain-object@^2.0.4: ++ version "2.0.4" ++ resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" ++ integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== ++ dependencies: ++ isobject "^3.0.1" ++ ++isexe@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" ++ integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== ++ ++isobject@^3.0.1: ++ version "3.0.1" ++ resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" ++ integrity sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg== ++ ++javascript-stringify@^1.6.0: ++ version "1.6.0" ++ resolved "https://registry.yarnpkg.com/javascript-stringify/-/javascript-stringify-1.6.0.tgz#142d111f3a6e3dae8f4a9afd77d45855b5a9cce3" ++ integrity sha512-fnjC0up+0SjEJtgmmG+teeel68kutkvzfctO/KxE3qJlbunkJYAshgH3boU++gSBHP8z5/r0ts0qRIrHf0RTQQ== ++ ++jest-worker@^26.5.0: ++ version "26.6.2" ++ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-26.6.2.tgz#7f72cbc4d643c365e27b9fd775f9d0eaa9c7a8ed" ++ integrity sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ== ++ dependencies: ++ "@types/node" "*" ++ merge-stream "^2.0.0" ++ supports-color "^7.0.0" ++ ++jest-worker@^27.4.5: ++ version "27.5.1" ++ resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" ++ integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== ++ dependencies: ++ "@types/node" "*" ++ merge-stream "^2.0.0" ++ supports-color "^8.0.0" ++ ++js-tokens@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" ++ integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== ++ ++jsesc@^2.5.1: ++ version "2.5.2" ++ resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" ++ integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== ++ ++json-parse-even-better-errors@^2.3.0, json-parse-even-better-errors@^2.3.1: ++ version "2.3.1" ++ resolved "https://registry.yarnpkg.com/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz#7c47805a94319928e05777405dc12e1f7a4ee02d" ++ integrity sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w== ++ ++json-schema-traverse@^0.4.1: ++ version "0.4.1" ++ resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" ++ integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== ++ ++json5@^2.1.2: ++ version "2.2.1" ++ resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" ++ integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== ++ ++jsonfile@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" ++ integrity sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg== ++ optionalDependencies: ++ graceful-fs "^4.1.6" ++ ++kind-of@^6.0.2: ++ version "6.0.3" ++ resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" ++ integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== ++ ++klona@^2.0.4: ++ version "2.0.5" ++ resolved "https://registry.yarnpkg.com/klona/-/klona-2.0.5.tgz#d166574d90076395d9963aa7a928fabb8d76afbc" ++ integrity sha512-pJiBpiXMbt7dkzXe8Ghj/u4FfXOOa98fPW+bihOJ4SjnoijweJrNThJfd3ifXpXhREjpoF2mZVH1GfS9LV3kHQ== ++ ++levn@~0.3.0: ++ version "0.3.0" ++ resolved "https://registry.yarnpkg.com/levn/-/levn-0.3.0.tgz#3b09924edf9f083c0490fdd4c0bc4421e04764ee" ++ integrity sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA== ++ dependencies: ++ prelude-ls "~1.1.2" ++ type-check "~0.3.2" ++ ++lilconfig@^2.0.3: ++ version "2.0.6" ++ resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-2.0.6.tgz#32a384558bd58af3d4c6e077dd1ad1d397bc69d4" ++ integrity sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg== ++ ++lines-and-columns@^1.1.6: ++ version "1.2.4" ++ resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" ++ integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg== ++ ++loader-runner@^4.2.0: ++ version "4.3.0" ++ resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1" ++ integrity sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg== ++ ++loader-utils@^2.0.0: ++ version "2.0.3" ++ resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-2.0.3.tgz#d4b15b8504c63d1fc3f2ade52d41bc8459d6ede1" ++ integrity sha512-THWqIsn8QRnvLl0shHYVBN9syumU8pYWEHPTmkiVGd+7K5eFNVSY6AJhRvgGF70gg1Dz+l/k8WicvFCxdEs60A== ++ dependencies: ++ big.js "^5.2.2" ++ emojis-list "^3.0.0" ++ json5 "^2.1.2" ++ ++locate-path@^5.0.0: ++ version "5.0.0" ++ resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" ++ integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== ++ dependencies: ++ p-locate "^4.1.0" ++ ++lodash-es@^4.17.11, lodash-es@^4.17.15: ++ version "4.17.21" ++ resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" ++ integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== ++ ++lodash.memoize@^4.1.2: ++ version "4.1.2" ++ resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" ++ integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== ++ ++lodash.uniq@^4.5.0: ++ version "4.5.0" ++ resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" ++ integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ== ++ ++lru-cache@^6.0.0: ++ version "6.0.0" ++ resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" ++ integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== ++ dependencies: ++ yallist "^4.0.0" ++ ++make-dir@^3.0.2: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" ++ integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== ++ dependencies: ++ semver "^6.0.0" ++ ++mdn-data@2.0.14: ++ version "2.0.14" ++ resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" ++ integrity sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow== ++ ++merge-stream@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" ++ integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== ++ ++merge2@^1.2.3, merge2@^1.3.0: ++ version "1.4.1" ++ resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" ++ integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== ++ ++micromatch@^4.0.0, micromatch@^4.0.4: ++ version "4.0.5" ++ resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" ++ integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== ++ dependencies: ++ braces "^3.0.2" ++ picomatch "^2.3.1" ++ ++mime-db@1.52.0: ++ version "1.52.0" ++ resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" ++ integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== ++ ++mime-types@^2.1.27: ++ version "2.1.35" ++ resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" ++ integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== ++ dependencies: ++ mime-db "1.52.0" ++ ++mimic-fn@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" ++ integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== ++ ++minimatch@^3.1.1: ++ version "3.1.2" ++ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" ++ integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== ++ dependencies: ++ brace-expansion "^1.1.7" ++ ++minipass-collect@^1.0.2: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" ++ integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== ++ dependencies: ++ minipass "^3.0.0" ++ ++minipass-flush@^1.0.5: ++ version "1.0.5" ++ resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" ++ integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== ++ dependencies: ++ minipass "^3.0.0" ++ ++minipass-pipeline@^1.2.2: ++ version "1.2.4" ++ resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz#68472f79711c084657c067c5c6ad93cddea8214c" ++ integrity sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A== ++ dependencies: ++ minipass "^3.0.0" ++ ++minipass@^3.0.0, minipass@^3.1.1: ++ version "3.3.4" ++ resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.3.4.tgz#ca99f95dd77c43c7a76bf51e6d200025eee0ffae" ++ integrity sha512-I9WPbWHCGu8W+6k1ZiGpPu0GkoKBeorkfKNuAFBNS1HNFJvke82sxvI5bzcCNpWPorkOO5QQ+zomzzwRxejXiw== ++ dependencies: ++ yallist "^4.0.0" ++ ++minizlib@^2.1.1: ++ version "2.1.2" ++ resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931" ++ integrity sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg== ++ dependencies: ++ minipass "^3.0.0" ++ yallist "^4.0.0" ++ ++mkdirp@^1.0.3, mkdirp@^1.0.4: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" ++ integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== ++ ++ms@2.1.2: ++ version "2.1.2" ++ resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" ++ integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== ++ ++nanoid@^3.3.4: ++ version "3.3.4" ++ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" ++ integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== ++ ++neo-async@^2.6.2: ++ version "2.6.2" ++ resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" ++ integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== ++ ++node-releases@^2.0.6: ++ version "2.0.6" ++ resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.6.tgz#8a7088c63a55e493845683ebf3c828d8c51c5503" ++ integrity sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg== ++ ++normalize-url@^6.0.1: ++ version "6.1.0" ++ resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a" ++ integrity sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A== ++ ++nth-check@^2.0.1: ++ version "2.1.1" ++ resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" ++ integrity sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w== ++ dependencies: ++ boolbase "^1.0.0" ++ ++once@^1.3.0: ++ version "1.4.0" ++ resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" ++ integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== ++ dependencies: ++ wrappy "1" ++ ++onetime@^5.1.0: ++ version "5.1.2" ++ resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" ++ integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== ++ dependencies: ++ mimic-fn "^2.1.0" ++ ++optionator@^0.8.1: ++ version "0.8.3" ++ resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495" ++ integrity sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA== ++ dependencies: ++ deep-is "~0.1.3" ++ fast-levenshtein "~2.0.6" ++ levn "~0.3.0" ++ prelude-ls "~1.1.2" ++ type-check "~0.3.2" ++ word-wrap "~1.2.3" ++ ++p-limit@^2.2.0: ++ version "2.3.0" ++ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" ++ integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== ++ dependencies: ++ p-try "^2.0.0" ++ ++p-limit@^3.0.2: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" ++ integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== ++ dependencies: ++ yocto-queue "^0.1.0" ++ ++p-locate@^4.1.0: ++ version "4.1.0" ++ resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" ++ integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== ++ dependencies: ++ p-limit "^2.2.0" ++ ++p-map@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" ++ integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== ++ dependencies: ++ aggregate-error "^3.0.0" ++ ++p-map@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" ++ integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== ++ dependencies: ++ aggregate-error "^3.0.0" ++ ++p-try@^2.0.0: ++ version "2.2.0" ++ resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" ++ integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== ++ ++parent-module@^1.0.0: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" ++ integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== ++ dependencies: ++ callsites "^3.0.0" ++ ++parse-json@^5.0.0: ++ version "5.2.0" ++ resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-5.2.0.tgz#c76fc66dee54231c962b22bcc8a72cf2f99753cd" ++ integrity sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg== ++ dependencies: ++ "@babel/code-frame" "^7.0.0" ++ error-ex "^1.3.1" ++ json-parse-even-better-errors "^2.3.0" ++ lines-and-columns "^1.1.6" ++ ++path-exists@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" ++ integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== ++ ++path-is-absolute@^1.0.0: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" ++ integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== ++ ++path-key@^3.1.0: ++ version "3.1.1" ++ resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" ++ integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== ++ ++path-parse@^1.0.7: ++ version "1.0.7" ++ resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" ++ integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== ++ ++path-type@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" ++ integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== ++ ++picocolors@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" ++ integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== ++ ++picomatch@^2.3.1: ++ version "2.3.1" ++ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" ++ integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== ++ ++pify@^2.3.0: ++ version "2.3.0" ++ resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" ++ integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog== ++ ++pkg-dir@^4.1.0, pkg-dir@^4.2.0: ++ version "4.2.0" ++ resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" ++ integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== ++ dependencies: ++ find-up "^4.0.0" ++ ++pofile@^1.0.9: ++ version "1.1.3" ++ resolved "https://registry.yarnpkg.com/pofile/-/pofile-1.1.3.tgz#e2c0d4052b9829f171b888bfb35c87791dbea297" ++ integrity sha512-sk96pUvpNwDV6PLrnhr68Uu1S5NohsxqLKz0GuracgrDo40BdF/r1RhHnjakUk6Q4Z0OKIybOQ7GevLKGN1iYw== ++ ++postcss-calc@^8.2.3: ++ version "8.2.4" ++ resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-8.2.4.tgz#77b9c29bfcbe8a07ff6693dc87050828889739a5" ++ integrity sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q== ++ dependencies: ++ postcss-selector-parser "^6.0.9" ++ postcss-value-parser "^4.2.0" ++ ++postcss-colormin@^5.3.0: ++ version "5.3.0" ++ resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-5.3.0.tgz#3cee9e5ca62b2c27e84fce63affc0cfb5901956a" ++ integrity sha512-WdDO4gOFG2Z8n4P8TWBpshnL3JpmNmJwdnfP2gbk2qBA8PWwOYcmjmI/t3CmMeL72a7Hkd+x/Mg9O2/0rD54Pg== ++ dependencies: ++ browserslist "^4.16.6" ++ caniuse-api "^3.0.0" ++ colord "^2.9.1" ++ postcss-value-parser "^4.2.0" ++ ++postcss-convert-values@^5.1.3: ++ version "5.1.3" ++ resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz#04998bb9ba6b65aa31035d669a6af342c5f9d393" ++ integrity sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA== ++ dependencies: ++ browserslist "^4.21.4" ++ postcss-value-parser "^4.2.0" ++ ++postcss-discard-comments@^5.1.2: ++ version "5.1.2" ++ resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz#8df5e81d2925af2780075840c1526f0660e53696" ++ integrity sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ== ++ ++postcss-discard-duplicates@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz#9eb4fe8456706a4eebd6d3b7b777d07bad03e848" ++ integrity sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw== ++ ++postcss-discard-empty@^5.1.1: ++ version "5.1.1" ++ resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz#e57762343ff7f503fe53fca553d18d7f0c369c6c" ++ integrity sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A== ++ ++postcss-discard-overridden@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz#7e8c5b53325747e9d90131bb88635282fb4a276e" ++ integrity sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw== ++ ++postcss-import@^14.1.0: ++ version "14.1.0" ++ resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-14.1.0.tgz#a7333ffe32f0b8795303ee9e40215dac922781f0" ++ integrity sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw== ++ dependencies: ++ postcss-value-parser "^4.0.0" ++ read-cache "^1.0.0" ++ resolve "^1.1.7" ++ ++postcss-js@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-4.0.0.tgz#31db79889531b80dc7bc9b0ad283e418dce0ac00" ++ integrity sha512-77QESFBwgX4irogGVPgQ5s07vLvFqWr228qZY+w6lW599cRlK/HmnlivnnVUxkjHnCu4J16PDMHcH+e+2HbvTQ== ++ dependencies: ++ camelcase-css "^2.0.1" ++ ++postcss-loader@^4.3.0: ++ version "4.3.0" ++ resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-4.3.0.tgz#2c4de9657cd4f07af5ab42bd60a673004da1b8cc" ++ integrity sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q== ++ dependencies: ++ cosmiconfig "^7.0.0" ++ klona "^2.0.4" ++ loader-utils "^2.0.0" ++ schema-utils "^3.0.0" ++ semver "^7.3.4" ++ ++postcss-merge-longhand@^5.1.7: ++ version "5.1.7" ++ resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz#24a1bdf402d9ef0e70f568f39bdc0344d568fb16" ++ integrity sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ== ++ dependencies: ++ postcss-value-parser "^4.2.0" ++ stylehacks "^5.1.1" ++ ++postcss-merge-rules@^5.1.3: ++ version "5.1.3" ++ resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-5.1.3.tgz#8f97679e67cc8d08677a6519afca41edf2220894" ++ integrity sha512-LbLd7uFC00vpOuMvyZop8+vvhnfRGpp2S+IMQKeuOZZapPRY4SMq5ErjQeHbHsjCUgJkRNrlU+LmxsKIqPKQlA== ++ dependencies: ++ browserslist "^4.21.4" ++ caniuse-api "^3.0.0" ++ cssnano-utils "^3.1.0" ++ postcss-selector-parser "^6.0.5" ++ ++postcss-minify-font-values@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz#f1df0014a726083d260d3bd85d7385fb89d1f01b" ++ integrity sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA== ++ dependencies: ++ postcss-value-parser "^4.2.0" ++ ++postcss-minify-gradients@^5.1.1: ++ version "5.1.1" ++ resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz#f1fe1b4f498134a5068240c2f25d46fcd236ba2c" ++ integrity sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw== ++ dependencies: ++ colord "^2.9.1" ++ cssnano-utils "^3.1.0" ++ postcss-value-parser "^4.2.0" ++ ++postcss-minify-params@^5.1.4: ++ version "5.1.4" ++ resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz#c06a6c787128b3208b38c9364cfc40c8aa5d7352" ++ integrity sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw== ++ dependencies: ++ browserslist "^4.21.4" ++ cssnano-utils "^3.1.0" ++ postcss-value-parser "^4.2.0" ++ ++postcss-minify-selectors@^5.2.1: ++ version "5.2.1" ++ resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz#d4e7e6b46147b8117ea9325a915a801d5fe656c6" ++ integrity sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg== ++ dependencies: ++ postcss-selector-parser "^6.0.5" ++ ++postcss-mixins@^9.0.2: ++ version "9.0.4" ++ resolved "https://registry.yarnpkg.com/postcss-mixins/-/postcss-mixins-9.0.4.tgz#75cd3cdb619a7e08c4c51ebb094db5f6d65b3831" ++ integrity sha512-XVq5jwQJDRu5M1XGkdpgASqLk37OqkH4JCFDXl/Dn7janOJjCTEKL+36cnRVy7bMtoBzALfO7bV7nTIsFnUWLA== ++ dependencies: ++ fast-glob "^3.2.11" ++ postcss-js "^4.0.0" ++ postcss-simple-vars "^7.0.0" ++ sugarss "^4.0.1" ++ ++postcss-nesting@^10.1.4: ++ version "10.2.0" ++ resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-10.2.0.tgz#0b12ce0db8edfd2d8ae0aaf86427370b898890be" ++ integrity sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA== ++ dependencies: ++ "@csstools/selector-specificity" "^2.0.0" ++ postcss-selector-parser "^6.0.10" ++ ++postcss-normalize-charset@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz#9302de0b29094b52c259e9b2cf8dc0879879f0ed" ++ integrity sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg== ++ ++postcss-normalize-display-values@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz#72abbae58081960e9edd7200fcf21ab8325c3da8" ++ integrity sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA== ++ dependencies: ++ postcss-value-parser "^4.2.0" ++ ++postcss-normalize-positions@^5.1.1: ++ version "5.1.1" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz#ef97279d894087b59325b45c47f1e863daefbb92" ++ integrity sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg== ++ dependencies: ++ postcss-value-parser "^4.2.0" ++ ++postcss-normalize-repeat-style@^5.1.1: ++ version "5.1.1" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz#e9eb96805204f4766df66fd09ed2e13545420fb2" ++ integrity sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g== ++ dependencies: ++ postcss-value-parser "^4.2.0" ++ ++postcss-normalize-string@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz#411961169e07308c82c1f8c55f3e8a337757e228" ++ integrity sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w== ++ dependencies: ++ postcss-value-parser "^4.2.0" ++ ++postcss-normalize-timing-functions@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz#d5614410f8f0b2388e9f240aa6011ba6f52dafbb" ++ integrity sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg== ++ dependencies: ++ postcss-value-parser "^4.2.0" ++ ++postcss-normalize-unicode@^5.1.1: ++ version "5.1.1" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz#f67297fca3fea7f17e0d2caa40769afc487aa030" ++ integrity sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA== ++ dependencies: ++ browserslist "^4.21.4" ++ postcss-value-parser "^4.2.0" ++ ++postcss-normalize-url@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz#ed9d88ca82e21abef99f743457d3729a042adcdc" ++ integrity sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew== ++ dependencies: ++ normalize-url "^6.0.1" ++ postcss-value-parser "^4.2.0" ++ ++postcss-normalize-whitespace@^5.1.1: ++ version "5.1.1" ++ resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz#08a1a0d1ffa17a7cc6efe1e6c9da969cc4493cfa" ++ integrity sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA== ++ dependencies: ++ postcss-value-parser "^4.2.0" ++ ++postcss-ordered-values@^5.1.3: ++ version "5.1.3" ++ resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz#b6fd2bd10f937b23d86bc829c69e7732ce76ea38" ++ integrity sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ== ++ dependencies: ++ cssnano-utils "^3.1.0" ++ postcss-value-parser "^4.2.0" ++ ++postcss-reduce-initial@^5.1.1: ++ version "5.1.1" ++ resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-5.1.1.tgz#c18b7dfb88aee24b1f8e4936541c29adbd35224e" ++ integrity sha512-//jeDqWcHPuXGZLoolFrUXBDyuEGbr9S2rMo19bkTIjBQ4PqkaO+oI8wua5BOUxpfi97i3PCoInsiFIEBfkm9w== ++ dependencies: ++ browserslist "^4.21.4" ++ caniuse-api "^3.0.0" ++ ++postcss-reduce-transforms@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz#333b70e7758b802f3dd0ddfe98bb1ccfef96b6e9" ++ integrity sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ== ++ dependencies: ++ postcss-value-parser "^4.2.0" ++ ++postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.4, postcss-selector-parser@^6.0.5, postcss-selector-parser@^6.0.9: ++ version "6.0.10" ++ resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" ++ integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== ++ dependencies: ++ cssesc "^3.0.0" ++ util-deprecate "^1.0.2" ++ ++postcss-simple-vars@^7.0.0: ++ version "7.0.0" ++ resolved "https://registry.yarnpkg.com/postcss-simple-vars/-/postcss-simple-vars-7.0.0.tgz#f1d10a979762aa4e7e3450a35a32885112893d1b" ++ integrity sha512-SPSkKQK7mKjD/tqcTbZkDi3KP+C/cTGXnKQmSt3AisJtnZE6ZxHEUoOGRfpV0B5dW1Y36EETfRHx10WLHpXThA== ++ ++postcss-svgo@^5.1.0: ++ version "5.1.0" ++ resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-5.1.0.tgz#0a317400ced789f233a28826e77523f15857d80d" ++ integrity sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA== ++ dependencies: ++ postcss-value-parser "^4.2.0" ++ svgo "^2.7.0" ++ ++postcss-unique-selectors@^5.1.1: ++ version "5.1.1" ++ resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz#a9f273d1eacd09e9aa6088f4b0507b18b1b541b6" ++ integrity sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA== ++ dependencies: ++ postcss-selector-parser "^6.0.5" ++ ++postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0: ++ version "4.2.0" ++ resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" ++ integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== ++ ++postcss@^8.4.12: ++ version "8.4.18" ++ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.18.tgz#6d50046ea7d3d66a85e0e782074e7203bc7fbca2" ++ integrity sha512-Wi8mWhncLJm11GATDaQKobXSNEYGUHeQLiQqDFG1qQ5UTDPTEvKw0Xt5NsTpktGTwLps3ByrWsBrG0rB8YQ9oA== ++ dependencies: ++ nanoid "^3.3.4" ++ picocolors "^1.0.0" ++ source-map-js "^1.0.2" ++ ++prelude-ls@~1.1.2: ++ version "1.1.2" ++ resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" ++ integrity sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w== ++ ++promise-inflight@^1.0.1: ++ version "1.0.1" ++ resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" ++ integrity sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g== ++ ++punycode@^2.1.0: ++ version "2.1.1" ++ resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" ++ integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== ++ ++queue-microtask@^1.2.2: ++ version "1.2.3" ++ resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" ++ integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== ++ ++randombytes@^2.1.0: ++ version "2.1.0" ++ resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" ++ integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== ++ dependencies: ++ safe-buffer "^5.1.0" ++ ++raw-loader@^4.0.1, raw-loader@^4.0.2: ++ version "4.0.2" ++ resolved "https://registry.yarnpkg.com/raw-loader/-/raw-loader-4.0.2.tgz#1aac6b7d1ad1501e66efdac1522c73e59a584eb6" ++ integrity sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA== ++ dependencies: ++ loader-utils "^2.0.0" ++ schema-utils "^3.0.0" ++ ++read-cache@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774" ++ integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA== ++ dependencies: ++ pify "^2.3.0" ++ ++"readable-stream@2 || 3": ++ version "3.6.0" ++ resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" ++ integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== ++ dependencies: ++ inherits "^2.0.3" ++ string_decoder "^1.1.1" ++ util-deprecate "^1.0.1" ++ ++rechoir@^0.6.2: ++ version "0.6.2" ++ resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" ++ integrity sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw== ++ dependencies: ++ resolve "^1.1.6" ++ ++rechoir@^0.7.0: ++ version "0.7.1" ++ resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.7.1.tgz#9478a96a1ca135b5e88fc027f03ee92d6c645686" ++ integrity sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg== ++ dependencies: ++ resolve "^1.9.0" ++ ++resolve-cwd@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-3.0.0.tgz#0f0075f1bb2544766cf73ba6a6e2adfebcb13f2d" ++ integrity sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg== ++ dependencies: ++ resolve-from "^5.0.0" ++ ++resolve-from@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" ++ integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== ++ ++resolve-from@^5.0.0: ++ version "5.0.0" ++ resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" ++ integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== ++ ++resolve@^1.1.6, resolve@^1.1.7, resolve@^1.9.0: ++ version "1.22.1" ++ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" ++ integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== ++ dependencies: ++ is-core-module "^2.9.0" ++ path-parse "^1.0.7" ++ supports-preserve-symlinks-flag "^1.0.0" ++ ++restore-cursor@^3.1.0: ++ version "3.1.0" ++ resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" ++ integrity sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA== ++ dependencies: ++ onetime "^5.1.0" ++ signal-exit "^3.0.2" ++ ++reusify@^1.0.4: ++ version "1.0.4" ++ resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" ++ integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== ++ ++rimraf@^3.0.0, rimraf@^3.0.2: ++ version "3.0.2" ++ resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" ++ integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== ++ dependencies: ++ glob "^7.1.3" ++ ++run-parallel@^1.1.9: ++ version "1.2.0" ++ resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" ++ integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== ++ dependencies: ++ queue-microtask "^1.2.2" ++ ++safe-buffer@^5.1.0, safe-buffer@~5.2.0: ++ version "5.2.1" ++ resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" ++ integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== ++ ++schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: ++ version "3.1.1" ++ resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" ++ integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== ++ dependencies: ++ "@types/json-schema" "^7.0.8" ++ ajv "^6.12.5" ++ ajv-keywords "^3.5.2" ++ ++semver@^6.0.0: ++ version "6.3.0" ++ resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" ++ integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== ++ ++semver@^7.3.4, semver@^7.3.5: ++ version "7.3.8" ++ resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.8.tgz#07a78feafb3f7b32347d725e33de7e2a2df67798" ++ integrity sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A== ++ dependencies: ++ lru-cache "^6.0.0" ++ ++serialize-javascript@^5.0.1: ++ version "5.0.1" ++ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" ++ integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== ++ dependencies: ++ randombytes "^2.1.0" ++ ++serialize-javascript@^6.0.0: ++ version "6.0.0" ++ resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" ++ integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== ++ dependencies: ++ randombytes "^2.1.0" ++ ++shallow-clone@^3.0.0: ++ version "3.0.1" ++ resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" ++ integrity sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA== ++ dependencies: ++ kind-of "^6.0.2" ++ ++shebang-command@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" ++ integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== ++ dependencies: ++ shebang-regex "^3.0.0" ++ ++shebang-regex@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" ++ integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== ++ ++shelljs@^0.8.1: ++ version "0.8.5" ++ resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.5.tgz#de055408d8361bed66c669d2f000538ced8ee20c" ++ integrity sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow== ++ dependencies: ++ glob "^7.0.0" ++ interpret "^1.0.0" ++ rechoir "^0.6.2" ++ ++signal-exit@^3.0.2: ++ version "3.0.7" ++ resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" ++ integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== ++ ++slash@^3.0.0: ++ version "3.0.0" ++ resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" ++ integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== ++ ++source-list-map@^2.0.0, source-list-map@^2.0.1: ++ version "2.0.1" ++ resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" ++ integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== ++ ++source-map-js@^1.0.2: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" ++ integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== ++ ++source-map-support@~0.5.20: ++ version "0.5.21" ++ resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" ++ integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== ++ dependencies: ++ buffer-from "^1.0.0" ++ source-map "^0.6.0" ++ ++source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1: ++ version "0.6.1" ++ resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" ++ integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== ++ ++ssri@^8.0.1: ++ version "8.0.1" ++ resolved "https://registry.yarnpkg.com/ssri/-/ssri-8.0.1.tgz#638e4e439e2ffbd2cd289776d5ca457c4f51a2af" ++ integrity sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ== ++ dependencies: ++ minipass "^3.1.1" ++ ++stable@^0.1.8: ++ version "0.1.8" ++ resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" ++ integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== ++ ++string_decoder@^1.1.1: ++ version "1.3.0" ++ resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" ++ integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== ++ dependencies: ++ safe-buffer "~5.2.0" ++ ++style-loader@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-2.0.0.tgz#9669602fd4690740eaaec137799a03addbbc393c" ++ integrity sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ== ++ dependencies: ++ loader-utils "^2.0.0" ++ schema-utils "^3.0.0" ++ ++stylehacks@^5.1.1: ++ version "5.1.1" ++ resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-5.1.1.tgz#7934a34eb59d7152149fa69d6e9e56f2fc34bcc9" ++ integrity sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw== ++ dependencies: ++ browserslist "^4.21.4" ++ postcss-selector-parser "^6.0.4" ++ ++sugarss@^4.0.1: ++ version "4.0.1" ++ resolved "https://registry.yarnpkg.com/sugarss/-/sugarss-4.0.1.tgz#128a783ed71ee0fc3b489ce1f7d5a89bc1e24383" ++ integrity sha512-WCjS5NfuVJjkQzK10s8WOBY+hhDxxNt/N6ZaGwxFZ+wN3/lKKFSaaKUNecULcTTvE4urLcKaZFQD8vO0mOZujw== ++ ++supports-color@^5.3.0: ++ version "5.5.0" ++ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" ++ integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== ++ dependencies: ++ has-flag "^3.0.0" ++ ++supports-color@^7.0.0, supports-color@^7.1.0: ++ version "7.2.0" ++ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" ++ integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== ++ dependencies: ++ has-flag "^4.0.0" ++ ++supports-color@^8.0.0: ++ version "8.1.1" ++ resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" ++ integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== ++ dependencies: ++ has-flag "^4.0.0" ++ ++supports-preserve-symlinks-flag@^1.0.0: ++ version "1.0.0" ++ resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" ++ integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== ++ ++svgo@^2.7.0: ++ version "2.8.0" ++ resolved "https://registry.yarnpkg.com/svgo/-/svgo-2.8.0.tgz#4ff80cce6710dc2795f0c7c74101e6764cfccd24" ++ integrity sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg== ++ dependencies: ++ "@trysound/sax" "0.2.0" ++ commander "^7.2.0" ++ css-select "^4.1.3" ++ css-tree "^1.1.3" ++ csso "^4.2.0" ++ picocolors "^1.0.0" ++ stable "^0.1.8" ++ ++tapable@^2.1.1, tapable@^2.2.0: ++ version "2.2.1" ++ resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" ++ integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== ++ ++tar@^6.0.2: ++ version "6.1.12" ++ resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.12.tgz#3b742fb05669b55671fb769ab67a7791ea1a62e6" ++ integrity sha512-jU4TdemS31uABHd+Lt5WEYJuzn+TJTCBLljvIAHZOz6M9Os5pJ4dD+vRFLxPa/n3T0iEFzpi+0x1UfuDZYbRMw== ++ dependencies: ++ chownr "^2.0.0" ++ fs-minipass "^2.0.0" ++ minipass "^3.0.0" ++ minizlib "^2.1.1" ++ mkdirp "^1.0.3" ++ yallist "^4.0.0" ++ ++terser-webpack-plugin@^4.2.3: ++ version "4.2.3" ++ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz#28daef4a83bd17c1db0297070adc07fc8cfc6a9a" ++ integrity sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ== ++ dependencies: ++ cacache "^15.0.5" ++ find-cache-dir "^3.3.1" ++ jest-worker "^26.5.0" ++ p-limit "^3.0.2" ++ schema-utils "^3.0.0" ++ serialize-javascript "^5.0.1" ++ source-map "^0.6.1" ++ terser "^5.3.4" ++ webpack-sources "^1.4.3" ++ ++terser-webpack-plugin@^5.1.3, terser-webpack-plugin@^5.2.0: ++ version "5.3.6" ++ resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.6.tgz#5590aec31aa3c6f771ce1b1acca60639eab3195c" ++ integrity sha512-kfLFk+PoLUQIbLmB1+PZDMRSZS99Mp+/MHqDNmMA6tOItzRt+Npe3E+fsMs5mfcM0wCtrrdU387UnV+vnSffXQ== ++ dependencies: ++ "@jridgewell/trace-mapping" "^0.3.14" ++ jest-worker "^27.4.5" ++ schema-utils "^3.1.1" ++ serialize-javascript "^6.0.0" ++ terser "^5.14.1" ++ ++terser@^5.14.1, terser@^5.3.4: ++ version "5.15.1" ++ resolved "https://registry.yarnpkg.com/terser/-/terser-5.15.1.tgz#8561af6e0fd6d839669c73b92bdd5777d870ed6c" ++ integrity sha512-K1faMUvpm/FBxjBXud0LWVAGxmvoPbZbfTCYbSgaaYQaIXI3/TdI7a7ZGA73Zrou6Q8Zmz3oeUTsp/dj+ag2Xw== ++ dependencies: ++ "@jridgewell/source-map" "^0.3.2" ++ acorn "^8.5.0" ++ commander "^2.20.0" ++ source-map-support "~0.5.20" ++ ++through2@^3.0.1: ++ version "3.0.2" ++ resolved "https://registry.yarnpkg.com/through2/-/through2-3.0.2.tgz#99f88931cfc761ec7678b41d5d7336b5b6a07bf4" ++ integrity sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ== ++ dependencies: ++ inherits "^2.0.4" ++ readable-stream "2 || 3" ++ ++to-fast-properties@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" ++ integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== ++ ++to-regex-range@^5.0.1: ++ version "5.0.1" ++ resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" ++ integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== ++ dependencies: ++ is-number "^7.0.0" ++ ++ts-loader@^9.3.0: ++ version "9.4.1" ++ resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-9.4.1.tgz#b6f3d82db0eac5a8295994f8cb5e4940ff6b1060" ++ integrity sha512-384TYAqGs70rn9F0VBnh6BPTfhga7yFNdC5gXbQpDrBj9/KsT4iRkGqKXhziofHOlE2j6YEaiTYVGKKvPhGWvw== ++ dependencies: ++ chalk "^4.1.0" ++ enhanced-resolve "^5.0.0" ++ micromatch "^4.0.0" ++ semver "^7.3.4" ++ ++type-check@~0.3.2: ++ version "0.3.2" ++ resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.3.2.tgz#5884cab512cf1d355e3fb784f30804b2b520db72" ++ integrity sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg== ++ dependencies: ++ prelude-ls "~1.1.2" ++ ++unique-filename@^1.1.1: ++ version "1.1.1" ++ resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" ++ integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== ++ dependencies: ++ unique-slug "^2.0.0" ++ ++unique-slug@^2.0.0: ++ version "2.0.2" ++ resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" ++ integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== ++ dependencies: ++ imurmurhash "^0.1.4" ++ ++universalify@^0.1.0: ++ version "0.1.2" ++ resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" ++ integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== ++ ++update-browserslist-db@^1.0.9: ++ version "1.0.10" ++ resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.0.10.tgz#0f54b876545726f17d00cd9a2561e6dade943ff3" ++ integrity sha512-OztqDenkfFkbSG+tRxBeAnCVPckDBcvibKd35yDONx6OU8N7sqgwc7rCbkJ/WcYtVRZ4ba68d6byhC21GFh7sQ== ++ dependencies: ++ escalade "^3.1.1" ++ picocolors "^1.0.0" ++ ++uri-js@^4.2.2: ++ version "4.4.1" ++ resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" ++ integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== ++ dependencies: ++ punycode "^2.1.0" ++ ++util-deprecate@^1.0.1, util-deprecate@^1.0.2: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" ++ integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== ++ ++watchpack@^2.4.0: ++ version "2.4.0" ++ resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" ++ integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== ++ dependencies: ++ glob-to-regexp "^0.4.1" ++ graceful-fs "^4.1.2" ++ ++webpack-cli@^4.4.0: ++ version "4.10.0" ++ resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-4.10.0.tgz#37c1d69c8d85214c5a65e589378f53aec64dab31" ++ integrity sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w== ++ dependencies: ++ "@discoveryjs/json-ext" "^0.5.0" ++ "@webpack-cli/configtest" "^1.2.0" ++ "@webpack-cli/info" "^1.5.0" ++ "@webpack-cli/serve" "^1.7.0" ++ colorette "^2.0.14" ++ commander "^7.0.0" ++ cross-spawn "^7.0.3" ++ fastest-levenshtein "^1.0.12" ++ import-local "^3.0.2" ++ interpret "^2.2.0" ++ rechoir "^0.7.0" ++ webpack-merge "^5.7.3" ++ ++webpack-merge@^5.7.3: ++ version "5.8.0" ++ resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-5.8.0.tgz#2b39dbf22af87776ad744c390223731d30a68f61" ++ integrity sha512-/SaI7xY0831XwP6kzuwhKWVKDP9t1QY1h65lAFLbZqMPIuYcD9QAW4u9STIbU9kaJbPBB/geU/gLr1wDjOhQ+Q== ++ dependencies: ++ clone-deep "^4.0.1" ++ wildcard "^2.0.0" ++ ++webpack-sources@^1.4.3: ++ version "1.4.3" ++ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" ++ integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== ++ dependencies: ++ source-list-map "^2.0.0" ++ source-map "~0.6.1" ++ ++webpack-sources@^2.0.1: ++ version "2.3.1" ++ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-2.3.1.tgz#570de0af163949fe272233c2cefe1b56f74511fd" ++ integrity sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA== ++ dependencies: ++ source-list-map "^2.0.1" ++ source-map "^0.6.1" ++ ++webpack-sources@^3.2.3: ++ version "3.2.3" ++ resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" ++ integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== ++ ++webpack@^5.51.1: ++ version "5.74.0" ++ resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.74.0.tgz#02a5dac19a17e0bb47093f2be67c695102a55980" ++ integrity sha512-A2InDwnhhGN4LYctJj6M1JEaGL7Luj6LOmyBHjcI8529cm5p6VXiTIW2sn6ffvEAKmveLzvu4jrihwXtPojlAA== ++ dependencies: ++ "@types/eslint-scope" "^3.7.3" ++ "@types/estree" "^0.0.51" ++ "@webassemblyjs/ast" "1.11.1" ++ "@webassemblyjs/wasm-edit" "1.11.1" ++ "@webassemblyjs/wasm-parser" "1.11.1" ++ acorn "^8.7.1" ++ acorn-import-assertions "^1.7.6" ++ browserslist "^4.14.5" ++ chrome-trace-event "^1.0.2" ++ enhanced-resolve "^5.10.0" ++ es-module-lexer "^0.9.0" ++ eslint-scope "5.1.1" ++ events "^3.2.0" ++ glob-to-regexp "^0.4.1" ++ graceful-fs "^4.2.9" ++ json-parse-even-better-errors "^2.3.1" ++ loader-runner "^4.2.0" ++ mime-types "^2.1.27" ++ neo-async "^2.6.2" ++ schema-utils "^3.1.0" ++ tapable "^2.1.1" ++ terser-webpack-plugin "^5.1.3" ++ watchpack "^2.4.0" ++ webpack-sources "^3.2.3" ++ ++which@^2.0.1: ++ version "2.0.2" ++ resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" ++ integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== ++ dependencies: ++ isexe "^2.0.0" ++ ++wildcard@^2.0.0: ++ version "2.0.0" ++ resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec" ++ integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw== ++ ++word-wrap@~1.2.3: ++ version "1.2.3" ++ resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" ++ integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== ++ ++wrappy@1: ++ version "1.0.2" ++ resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" ++ integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== ++ ++yallist@^4.0.0: ++ version "4.0.0" ++ resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" ++ integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== ++ ++yaml@^1.10.0, yaml@^1.10.2: ++ version "1.10.2" ++ resolved "https://registry.yarnpkg.com/yaml/-/yaml-1.10.2.tgz#2301c5ffbf12b467de8da2333a459e29e7920e4b" ++ integrity sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg== ++ ++yocto-queue@^0.1.0: ++ version "0.1.0" ++ resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" ++ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +\ No newline at end of file +-- +GitLab + + +From b2688a94e1f3ca70d31fbfe4e12b06eae3754581 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ga=C3=ABlG?= +Date: Fri, 17 Feb 2023 09:07:51 +0100 +Subject: [PATCH 05/16] WIP, see @todo for lasting work + +--- + .../css/video_embed.admin.css | 2 +- + .../icons/play-circle (copie).svg | 1 - + .../video_embed_wysiwyg/icons/play-circle.svg | 2 +- + modules/video_embed_wysiwyg/icons/play.svg | 1 - + .../js/build/videoEmbed.js | 1 + + .../ckeditor5_plugins/videoEmbed/src/index.js | 1 + + .../videoEmbed/src/videoembedediting.js | 9 +- + .../videoEmbed/src/videoembedui.js | 100 +++++++- + .../CKEditor5Plugin/VideoEmbedWysiwyg.php | 8 +- + modules/video_embed_wysiwyg/yarn.lock | 217 +++++++++--------- + 10 files changed, 219 insertions(+), 123 deletions(-) + delete mode 100644 modules/video_embed_wysiwyg/icons/play-circle (copie).svg + delete mode 100644 modules/video_embed_wysiwyg/icons/play.svg + create mode 100644 modules/video_embed_wysiwyg/js/build/videoEmbed.js + +diff --git a/modules/video_embed_wysiwyg/css/video_embed.admin.css b/modules/video_embed_wysiwyg/css/video_embed.admin.css +index 7ef5780..abf5b07 100644 +--- a/modules/video_embed_wysiwyg/css/video_embed.admin.css ++++ b/modules/video_embed_wysiwyg/css/video_embed.admin.css +@@ -1,4 +1,4 @@ + .ckeditor5-toolbar-button-videoEmbed { + /* @todo Choose the best icon and remove others. */ +- background-image: url(../icons/film.svg); ++ background-image: url(../icons/play-circle.svg); + } +diff --git a/modules/video_embed_wysiwyg/icons/play-circle (copie).svg b/modules/video_embed_wysiwyg/icons/play-circle (copie).svg +deleted file mode 100644 +index 778c5fa..0000000 +--- a/modules/video_embed_wysiwyg/icons/play-circle (copie).svg ++++ /dev/null +@@ -1 +0,0 @@ +- +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/icons/play-circle.svg b/modules/video_embed_wysiwyg/icons/play-circle.svg +index 0ce0085..778c5fa 100644 +--- a/modules/video_embed_wysiwyg/icons/play-circle.svg ++++ b/modules/video_embed_wysiwyg/icons/play-circle.svg +@@ -1 +1 @@ +- +\ No newline at end of file ++ +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/icons/play.svg b/modules/video_embed_wysiwyg/icons/play.svg +deleted file mode 100644 +index e817cc8..0000000 +--- a/modules/video_embed_wysiwyg/icons/play.svg ++++ /dev/null +@@ -1 +0,0 @@ +- +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/build/videoEmbed.js b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +new file mode 100644 +index 0000000..6f05a06 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +@@ -0,0 +1 @@ ++!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var __webpack_modules__={"./js/ckeditor5_plugins/videoEmbed/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _videoembed__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembed */ "./js/ckeditor5_plugins/videoEmbed/src/videoembed.js");\n\n\n// @todo Remove console.log calls.\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n VideoEmbed: _videoembed__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/index.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembed.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ VideoEmbed)\n/* harmony export */ });\n/* harmony import */ var _videoembedediting__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembedediting */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js");\n/* harmony import */ var _videoembedui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./videoembedui */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js");\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n\n\n\n\nclass VideoEmbed extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\nstatic get requires() {\n return [_videoembedediting__WEBPACK_IMPORTED_MODULE_0__["default"], _videoembedui__WEBPACK_IMPORTED_MODULE_1__["default"]];\n }\n}\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembed.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js":()=>{eval('throw new Error("Module parse failed: Unexpected token (61:4)\\nYou may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders\\n| // @todo register allowed model attributes.\\n| allowAttributes:\\n> });\\n| }\\n| ");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedUI)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../icons/play-circle.svg */ \"./icons/play-circle.svg\");\n/**\n * @file registers the videoEmbed toolbar button and binds functionality to it.\n */\n\n\n\n\n/* @todo Choose the best icon and remove others. */\n\n\nclass VideoEmbedUI extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const editor = this.editor;\n\n // This will register the videoEmbed toolbar button.\n editor.ui.componentFactory.add('videoEmbed', (locale) => {\n const command = editor.commands.get('insertVideoEmbed');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n\n // Create the toolbar button.\n buttonView.set({\n label: editor.t('Video Embed'),\n icon: _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n // Execute the command when the button is clicked (executed).\n this.listenTo(buttonView, 'execute', () => {\n console.log('button execution');\n this.openEditingDialog();\n }\n );\n\n return buttonView;\n });\n }\n\n /**\n * Opens video embed form when the editing button is clicked.\n */\n openEditingDialog() {\n console.log('dialog opening');\n const {editor} = this;\n\n // If the selected element while we click the button is an instance\n // of the video_embed widget, extract it's values so they can be\n // sent to the server to prime the configuration form.\n let existingValues = {};\n const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement()\n if (selectedVideoEmbedElement) {\n // @todo adapt this copy-pasted code.\n existingValues = selectedVideoEmbedElement.hasAttribute('data-entity-uuid') ? {\n 'data-entity-uuid': selectedVideoEmbedElement.getAttribute('data-entity-uuid'),\n 'data-entity-type': selectedVideoEmbedElement.getAttribute('data-entity-type'),\n } : {};\n }\n\n this._openDialog(\n Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format),\n existingValues,\n ({attributes}) => {\n editor.execute('insertVideoEmbed', attributes);\n },\n {\n title: Drupal.t('Video Embed'),\n dialogClass: 'video-embed-dialog'\n }\n );\n }\n\n /**\n * @todo Return the focused videoEmbed element (the cke5 widget system may\n * help with that).\n *\n * @private\n */\n _getSelectedVideoEmbedElement() {\n return null;\n }\n\n /**\n * This method is adopted from drupal's ckeditor5.js file due to an issue\n * where the \"editor_object\" isn't passed to the ajax request.\n *\n * See https://www.drupal.org/project/drupal/issues/3303191\n *\n * @param {string} url\n * The URL that contains the contents of the dialog.\n * @param {object} existingValues\n * Existing values that will be sent via POST to the url for the dialog\n * contents.\n * @param {function} saveCallback\n * A function to be called upon saving the dialog.\n * @param {object} dialogSettings\n * An object containing settings to be passed to the jQuery UI.\n */\n _openDialog(url, existingValues, saveCallback, dialogSettings = {}) {\n // Add a consistent dialog class.\n const classes = dialogSettings.dialogClass\n ? dialogSettings.dialogClass.split(' ')\n : [];\n classes.push('ui-dialog--narrow');\n dialogSettings.dialogClass = classes.join(' ');\n dialogSettings.autoResize =\n window.matchMedia('(min-width: 600px)').matches;\n dialogSettings.width = 'auto';\n\n const ckeditorAjaxDialog = Drupal.ajax({\n dialog: dialogSettings,\n dialogType: 'modal',\n selector: '.ckeditor5-dialog-loading-link',\n url,\n progress: {type: 'fullscreen'},\n submit: {\n editor_object: existingValues,\n },\n });\n ckeditorAjaxDialog.execute();\n\n // Store the save callback to be executed when this dialog is closed.\n Drupal.ckeditor5.saveCallback = saveCallback;\n }\n\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js?")},"./icons/play-circle.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./icons/play-circle.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var _=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](_,_.exports,__webpack_require__),_.exports}__webpack_require__.d=(e,t)=>{for(var _ in t)__webpack_require__.o(t,_)&&!__webpack_require__.o(e,_)&&Object.defineProperty(e,_,{enumerable:!0,get:t[_]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./js/ckeditor5_plugins/videoEmbed/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})())); +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/index.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/index.js +index 6fcd277..d56de08 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/index.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/index.js +@@ -1,5 +1,6 @@ + import VideoEmbed from './videoembed'; + ++// @todo Remove console.log calls. + export default { + VideoEmbed, + }; +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js +index 3153259..8fd9b0b 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js +@@ -53,12 +53,11 @@ export default class VideoEmbedEditing extends Plugin { + const schema = this.editor.model.schema; + + +- // @todo register allowed model attributes. ++ + schema.register('videoEmbed', { +- // Behaves like a self-contained object (e.g. an image). +- isObject: true, +- // Allow in places where other blocks are allowed (e.g. directly in the root). +- allowWhere: '$block', ++ inheritAllFrom: '$blockObject', ++ // @todo register allowed model attributes. ++ // allowAttributes: + }); + } + +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js +index 94ba981..dab160d 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js +@@ -2,10 +2,11 @@ + * @file registers the videoEmbed toolbar button and binds functionality to it. + */ + +-import { Plugin } from 'ckeditor5/src/core'; +-import { ButtonView } from 'ckeditor5/src/ui'; ++import {Plugin} from 'ckeditor5/src/core'; ++import {ButtonView} from 'ckeditor5/src/ui'; ++ + /* @todo Choose the best icon and remove others. */ +-import icon from '../../../../icons/film.svg'; ++import icon from '../../../../icons/play-circle.svg'; + + export default class VideoEmbedUI extends Plugin { + init() { +@@ -27,12 +28,101 @@ export default class VideoEmbedUI extends Plugin { + buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled'); + + // Execute the command when the button is clicked (executed). +- this.listenTo(buttonView, 'execute', () => +- editor.execute('insertVideoEmbed'), ++ this.listenTo(buttonView, 'execute', () => { ++ console.log('button execution'); ++ this.openEditingDialog(); ++ } + ); + + return buttonView; + }); + } ++ ++ /** ++ * Opens video embed form when the editing button is clicked. ++ */ ++ openEditingDialog() { ++ console.log('dialog opening'); ++ const {editor} = this; ++ ++ // If the selected element while we click the button is an instance ++ // of the video_embed widget, extract its values so they can be ++ // sent to the server to prime the configuration form. ++ let existingValues = {}; ++ const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement() ++ if (selectedVideoEmbedElement) { ++ // @todo adapt this copy-pasted code. ++ existingValues = selectedVideoEmbedElement.hasAttribute('data-entity-uuid') ? { ++ 'data-entity-uuid': selectedVideoEmbedElement.getAttribute('data-entity-uuid'), ++ 'data-entity-type': selectedVideoEmbedElement.getAttribute('data-entity-type'), ++ } : {}; ++ } ++ ++ this._openDialog( ++ Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format), ++ existingValues, ++ ({attributes}) => { ++ editor.execute('insertVideoEmbed', attributes); ++ }, ++ { ++ title: Drupal.t('Video Embed'), ++ dialogClass: 'video-embed-dialog' ++ } ++ ); ++ } ++ ++ /** ++ * @todo Return the focused videoEmbed element (the cke5 widget system may ++ * help with that). ++ * ++ * @private ++ */ ++ _getSelectedVideoEmbedElement() { ++ return null; ++ } ++ ++ /** ++ * This method is adopted from drupal's ckeditor5.js file due to an issue ++ * where the "editor_object" isn't passed to the ajax request. ++ * ++ * See https://www.drupal.org/project/drupal/issues/3303191 ++ * ++ * @param {string} url ++ * The URL that contains the contents of the dialog. ++ * @param {object} existingValues ++ * Existing values that will be sent via POST to the url for the dialog ++ * contents. ++ * @param {function} saveCallback ++ * A function to be called upon saving the dialog. ++ * @param {object} dialogSettings ++ * An object containing settings to be passed to the jQuery UI. ++ */ ++ _openDialog(url, existingValues, saveCallback, dialogSettings = {}) { ++ // Add a consistent dialog class. ++ const classes = dialogSettings.dialogClass ++ ? dialogSettings.dialogClass.split(' ') ++ : []; ++ classes.push('ui-dialog--narrow'); ++ dialogSettings.dialogClass = classes.join(' '); ++ dialogSettings.autoResize = ++ window.matchMedia('(min-width: 600px)').matches; ++ dialogSettings.width = 'auto'; ++ ++ const ckeditorAjaxDialog = Drupal.ajax({ ++ dialog: dialogSettings, ++ dialogType: 'modal', ++ selector: '.ckeditor5-dialog-loading-link', ++ url, ++ progress: {type: 'fullscreen'}, ++ submit: { ++ editor_object: existingValues, ++ }, ++ }); ++ ckeditorAjaxDialog.execute(); ++ ++ // Store the save callback to be executed when this dialog is closed. ++ Drupal.ckeditor5.saveCallback = saveCallback; ++ } ++ + } + +diff --git a/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php b/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php +index dd57409..13f1f19 100644 +--- a/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php ++++ b/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php +@@ -10,6 +10,8 @@ use Drupal\editor\EditorInterface; + + /** + * This class transmits the Drupal config to the javascript plugin. ++ * ++ * @todo Add the settings form for the plugin. + */ + class VideoEmbedWysiwyg extends CKEditor5PluginDefault { + +@@ -22,15 +24,19 @@ class VideoEmbedWysiwyg extends CKEditor5PluginDefault { + * @return mixed[] + */ + public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array { ++ $plugin_config = [ ++ 'format' => $editor->id(), ++ ]; + $format = $editor->getFilterFormat(); + /** @var \Drupal\filter\Plugin\FilterInterface $filter */ + $filter = $format->filters('video_embed_wysiwyg'); + $filter_config = $filter->getConfiguration(); ++ $plugin_config += $filter_config['settings']; + $parent_config = parent::getDynamicPluginConfig($static_plugin_config, $editor); + // @todo Ensure this is the info the plugin needs. + return array_merge_recursive($parent_config, + [ +- 'VideoEmbed' => $filter_config['settings'] ++ 'videoEmbed' => $plugin_config, + ]); + } + +diff --git a/modules/video_embed_wysiwyg/yarn.lock b/modules/video_embed_wysiwyg/yarn.lock +index 569df04..eace212 100644 +--- a/modules/video_embed_wysiwyg/yarn.lock ++++ b/modules/video_embed_wysiwyg/yarn.lock +@@ -103,25 +103,25 @@ + "@babel/helper-validator-identifier" "^7.19.1" + to-fast-properties "^2.0.0" + +-"@ckeditor/ckeditor5-clipboard@^35.4.0": +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-35.4.0.tgz#8529fd45d06a7edea0f73cd0b5b3052f2272335c" +- integrity sha512-B6rIQxvOrHvO9TZRC8JA0wKk+IfN880UJkYIg1qlhf9HFNVjdVbtHaiCsPD+TzGmQN3XHXfNjgjabGRIn0iZmw== +- dependencies: +- "@ckeditor/ckeditor5-core" "^35.4.0" +- "@ckeditor/ckeditor5-engine" "^35.4.0" +- "@ckeditor/ckeditor5-utils" "^35.4.0" +- "@ckeditor/ckeditor5-widget" "^35.4.0" ++"@ckeditor/ckeditor5-clipboard@^34.1.0": ++ version "34.2.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-34.2.0.tgz#ab69636365b0bd95631817fe4f5c3cc22bc6fce3" ++ integrity sha512-OcdFj9yT7C5yKPHtTKWvjGMJLpigrkdJN4AZhdJJPigiuYG0c5mnCuTvOYxp2kVijFWRjhPlwIyPVTtDZ0vnzw== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^34.2.0" ++ "@ckeditor/ckeditor5-engine" "^34.2.0" ++ "@ckeditor/ckeditor5-utils" "^34.2.0" ++ "@ckeditor/ckeditor5-widget" "^34.2.0" + lodash-es "^4.17.11" + +-"@ckeditor/ckeditor5-core@^35.4.0": +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-core/-/ckeditor5-core-35.4.0.tgz#39390445c8363a80d4ce0e45d93efa13b8523f6e" +- integrity sha512-Rf0H7C4inCj/YC8aii0cT7TC/IuBIQ+tXmu9qd8/1BJ/rz1MCHXtBPApjTbFp33OE3aOFB5+NUaKt05k/dL3OA== ++"@ckeditor/ckeditor5-core@^34.1.0", "@ckeditor/ckeditor5-core@^34.2.0": ++ version "34.2.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-core/-/ckeditor5-core-34.2.0.tgz#4ba72e3407310843a784630c598501ccc42a585b" ++ integrity sha512-6K0aToibRt28sCVYpMqdSKGvMifjwziqxLxyEh38CyDZJBUf7QPEAPlEpKAFTisHNEmC4471tr8UPpvNgqUXGA== + dependencies: +- "@ckeditor/ckeditor5-engine" "^35.4.0" +- "@ckeditor/ckeditor5-ui" "^35.4.0" +- "@ckeditor/ckeditor5-utils" "^35.4.0" ++ "@ckeditor/ckeditor5-engine" "^34.2.0" ++ "@ckeditor/ckeditor5-ui" "^34.2.0" ++ "@ckeditor/ckeditor5-utils" "^34.2.0" + lodash-es "^4.17.15" + + "@ckeditor/ckeditor5-dev-utils@^30.0.0", "@ckeditor/ckeditor5-dev-utils@^30.5.0": +@@ -165,95 +165,96 @@ + semver "^7.3.4" + webpack-sources "^2.0.1" + +-"@ckeditor/ckeditor5-engine@^35.4.0": +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-35.4.0.tgz#cb0ed9f0c5a9ef00b24ffbd8d2100fff1e0e90cb" +- integrity sha512-67QKtUGJeLM072h9qURvzczYGU3ecuxR9LLmM4dffnV+PBNQ9e8RDCY7PuuEP0pplmAUI6/XqoZJIbk6h7ZV3Q== ++"@ckeditor/ckeditor5-engine@^34.1.0", "@ckeditor/ckeditor5-engine@^34.2.0": ++ version "34.2.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-34.2.0.tgz#449376625bad9e8beea9e89e201dd4fb599fc38f" ++ integrity sha512-9/i6TZ+Sy5T6hnuCtmeLTfwLSY8LaS7qFkW6gsM9NEB+LSSu930GP0Ss30Nw6dYo/JmYiQEpkiRJzKYIjrH8Pg== + dependencies: +- "@ckeditor/ckeditor5-utils" "^35.4.0" ++ "@ckeditor/ckeditor5-utils" "^34.2.0" + lodash-es "^4.17.15" + +-"@ckeditor/ckeditor5-enter@^35.4.0": +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-35.4.0.tgz#c0f967dc3f48faeb07d839ac0426227e118ade56" +- integrity sha512-y95RnA/Gw72e220PJKVwNbwPzX4SRs82/rXu1jVyJXty7CcEZqqfyRtW6odICAXr5eKI5XKgzFgpFYULL3D9Nw== +- dependencies: +- "@ckeditor/ckeditor5-core" "^35.4.0" +- "@ckeditor/ckeditor5-engine" "^35.4.0" +- +-"@ckeditor/ckeditor5-paragraph@^35.4.0": +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-35.4.0.tgz#db6babd19eb37c66771b7355d0cd0880cb9b599c" +- integrity sha512-8nhkEEFv1WClhH6q/HW8P596d+dlatSVc46kQ2+jGlYirL8P66tV/nK+OiE8z1d897oVr4QPGsqk2qGkRFUChw== +- dependencies: +- "@ckeditor/ckeditor5-core" "^35.4.0" +- "@ckeditor/ckeditor5-ui" "^35.4.0" +- "@ckeditor/ckeditor5-utils" "^35.4.0" +- +-"@ckeditor/ckeditor5-select-all@^35.4.0": +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-35.4.0.tgz#b7c20e9f686e59497e84825c4786dd874e22d4e2" +- integrity sha512-c+pIIY77SP6ux4/cyD7cCrllQAqtFVSnzNYdy7ygNPqljCGngCnpSV9xfCO/blFo6/zx2vsmzVGdRq3ArzGoMg== +- dependencies: +- "@ckeditor/ckeditor5-core" "^35.4.0" +- "@ckeditor/ckeditor5-ui" "^35.4.0" +- "@ckeditor/ckeditor5-utils" "^35.4.0" +- +-"@ckeditor/ckeditor5-typing@^35.4.0": +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-35.4.0.tgz#b786032a541cfd102562eb07c21c62e0b6d502c6" +- integrity sha512-Ad/PHWbVWcnAj9oevkkfLqf6CmvCFOti466uhvfOCKRNVf2+/xuGwleOGr8W6Lir/x/qav7ojFjKPKDxqbPXhA== +- dependencies: +- "@ckeditor/ckeditor5-core" "^35.4.0" +- "@ckeditor/ckeditor5-engine" "^35.4.0" +- "@ckeditor/ckeditor5-utils" "^35.4.0" ++"@ckeditor/ckeditor5-enter@^34.1.0", "@ckeditor/ckeditor5-enter@^34.2.0": ++ version "34.2.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-34.2.0.tgz#6d90a374396ef05ecde7f6cb0fcd6d3ca38e20b1" ++ integrity sha512-QxaT3jH0qsZaE0Egj1D19o6YBz/EJKs0am5ny5hDnd5sntvIUk9PNGEu/v3mRmNqZqrhRu4BuedvdRzYWseUjw== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^34.2.0" ++ "@ckeditor/ckeditor5-engine" "^34.2.0" ++ "@ckeditor/ckeditor5-utils" "^34.2.0" ++ ++"@ckeditor/ckeditor5-paragraph@^34.1.0": ++ version "34.2.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-34.2.0.tgz#cf981adb76bf40649ce04358674d2c1262b8753a" ++ integrity sha512-xcXUsXz3PY355gJ8u+y0qFLWcScYo0CZPZSbs5YwDz7g9lV8foVVzzdW7ITYwr5/YIpJsjjxYC+dDUqsH6EpBQ== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^34.2.0" ++ "@ckeditor/ckeditor5-ui" "^34.2.0" ++ "@ckeditor/ckeditor5-utils" "^34.2.0" ++ ++"@ckeditor/ckeditor5-select-all@^34.1.0": ++ version "34.2.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-34.2.0.tgz#49ca1e239dda9d6045716ebd6707a4cf1a8a6203" ++ integrity sha512-/Va85RwNlmpgQ7vWxiAFLyzXhXrWiA5Pde7yCNcc6hJpqnaGcqvscOJoZLMk5oASTvMnPhQIgNSMDN/oq6ej0Q== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^34.2.0" ++ "@ckeditor/ckeditor5-ui" "^34.2.0" ++ "@ckeditor/ckeditor5-utils" "^34.2.0" ++ ++"@ckeditor/ckeditor5-typing@^34.1.0", "@ckeditor/ckeditor5-typing@^34.2.0": ++ version "34.2.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-34.2.0.tgz#6f408e671ef5acf526076128f9422a13d914776f" ++ integrity sha512-Eq8mhb8M7RwUmeVUantN+PrqxDELXCvLCcpixy+ge/5lM8wxVcn/SonfUL9PLqs2eluRc4Bx+mstMQySglkVkw== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^34.2.0" ++ "@ckeditor/ckeditor5-engine" "^34.2.0" ++ "@ckeditor/ckeditor5-utils" "^34.2.0" + lodash-es "^4.17.15" + +-"@ckeditor/ckeditor5-ui@^35.4.0": +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-35.4.0.tgz#76e59032aee6652c6bd717f30fc330a064b3451e" +- integrity sha512-0SmYE+k1cYQPqyw2rQsPDV/RpudneBh1bNfiaTOz+rqViJIMe+TxiuK6Fz+znNZ05s0exr+ZHWvMttGqlVoQNw== ++"@ckeditor/ckeditor5-ui@^34.1.0", "@ckeditor/ckeditor5-ui@^34.2.0": ++ version "34.2.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-34.2.0.tgz#56a0fe2eb87c2e44b6c6d9440e6b6077a244214c" ++ integrity sha512-XL561G/e3b1YLGHNjLxS9IgoVn4BSugHmidEXYNUTMLATRCKld1XMUKFsB/wm3DwLBUfWn4d2j3qdcO2CnDuBg== + dependencies: +- "@ckeditor/ckeditor5-core" "^35.4.0" +- "@ckeditor/ckeditor5-utils" "^35.4.0" ++ "@ckeditor/ckeditor5-core" "^34.2.0" ++ "@ckeditor/ckeditor5-utils" "^34.2.0" + lodash-es "^4.17.15" + +-"@ckeditor/ckeditor5-undo@^35.4.0": +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-35.4.0.tgz#f79b19be69b8b9ab57592cfe4ec4645b3728b773" +- integrity sha512-0RhsK0f/pX/7KB/JXYTLiDOswmUTQ9EKIIuewAwr7LTsBf4Q309FZSFdbeTmc0wIyX33212Xh5xsi3LyG1VJRg== ++"@ckeditor/ckeditor5-undo@^34.1.0": ++ version "34.2.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-34.2.0.tgz#7ea368fc46d4f1f663a2e59cba7390bd90b62017" ++ integrity sha512-WW3f6ku36DpKhUxXACfNFm2DaKcJ2Rz0EFEkol0+offpOjltJnUEJ7LvfOthGdMvGz+5lmnySTbkvOvNruq1Ew== + dependencies: +- "@ckeditor/ckeditor5-core" "^35.4.0" +- "@ckeditor/ckeditor5-engine" "^35.4.0" +- "@ckeditor/ckeditor5-ui" "^35.4.0" ++ "@ckeditor/ckeditor5-core" "^34.2.0" ++ "@ckeditor/ckeditor5-engine" "^34.2.0" ++ "@ckeditor/ckeditor5-ui" "^34.2.0" + +-"@ckeditor/ckeditor5-upload@^35.4.0": +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-35.4.0.tgz#57944a4e824cdee37bb53d795dbe98055e11d748" +- integrity sha512-+eJAluAc4mAFmx5FNuSGjkCYmbm0V9NpSleubAXEx2e+KNiLarPAnsolwRaAcYXcloNp4C9/l0D+lPEx7VRYtg== ++"@ckeditor/ckeditor5-upload@^34.1.0": ++ version "34.2.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-34.2.0.tgz#8a55065bba3e2e3f6134872f0735a4ed0257bf6b" ++ integrity sha512-HBJr0/wFE+R13aIXRF/xJVQqo6Yh34EgbnrNYYhlNiHG40Vr6079eCuoZrnY3vwEsjtFNnTRQ433+RqxJ652zw== + dependencies: +- "@ckeditor/ckeditor5-core" "^35.4.0" +- "@ckeditor/ckeditor5-ui" "^35.4.0" +- "@ckeditor/ckeditor5-utils" "^35.4.0" ++ "@ckeditor/ckeditor5-core" "^34.2.0" ++ "@ckeditor/ckeditor5-ui" "^34.2.0" ++ "@ckeditor/ckeditor5-utils" "^34.2.0" + +-"@ckeditor/ckeditor5-utils@^35.4.0": +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-35.4.0.tgz#c5c296a2c1883684e674b1a710fcc41b745e156b" +- integrity sha512-sFjbb+1VYdLbELDLWVYk86WzVN7Lo3sXHbVhdr8+kc0Ufxdr3mTFHDAkiymFt2fs1FOB5gZyWJlJU+EeJnhKUw== ++"@ckeditor/ckeditor5-utils@^34.1.0", "@ckeditor/ckeditor5-utils@^34.2.0": ++ version "34.2.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-34.2.0.tgz#d84177671afbc849b0435075f00311f9cc181288" ++ integrity sha512-jHJV2S8DzmpVvd3jdercY6HsGRAwpm/MK79Rs/Mrc3NNYKzN9SVFs/NLbrELNoMZeJ1WKt5BwKgBY+PEOpfyLw== + dependencies: + lodash-es "^4.17.15" + +-"@ckeditor/ckeditor5-widget@^35.4.0": +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-35.4.0.tgz#a80ed4c4f57a1198b47c4e93090f8ebe62f70ecb" +- integrity sha512-SNYOXXWu7XV1BZET+ar0Cea25836vzNtUqXlDPwBx/jrmK86b8GMbFR99P2bUG0NvtIsH5cSk7XCmnxb4ZQ6wA== +- dependencies: +- "@ckeditor/ckeditor5-core" "^35.4.0" +- "@ckeditor/ckeditor5-engine" "^35.4.0" +- "@ckeditor/ckeditor5-enter" "^35.4.0" +- "@ckeditor/ckeditor5-typing" "^35.4.0" +- "@ckeditor/ckeditor5-ui" "^35.4.0" +- "@ckeditor/ckeditor5-utils" "^35.4.0" ++"@ckeditor/ckeditor5-widget@^34.1.0", "@ckeditor/ckeditor5-widget@^34.2.0": ++ version "34.2.0" ++ resolved "https://registry.yarnpkg.com/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-34.2.0.tgz#0df140bc4c40287251cf5f5a970f616bdbd470e3" ++ integrity sha512-h2iF/RRK+GjvVHb6VY7+slnIV+IdWdLfZS83OECQNYp2e+6kN/JZp+PxiyYC4asPTraL43zJGzlgT53Jof77vw== ++ dependencies: ++ "@ckeditor/ckeditor5-core" "^34.2.0" ++ "@ckeditor/ckeditor5-engine" "^34.2.0" ++ "@ckeditor/ckeditor5-enter" "^34.2.0" ++ "@ckeditor/ckeditor5-typing" "^34.2.0" ++ "@ckeditor/ckeditor5-ui" "^34.2.0" ++ "@ckeditor/ckeditor5-utils" "^34.2.0" + lodash-es "^4.17.15" + + "@csstools/selector-specificity@^2.0.0": +@@ -736,23 +737,23 @@ chrome-trace-event@^1.0.2: + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" + integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== + +-ckeditor5@~35.4.0: +- version "35.4.0" +- resolved "https://registry.yarnpkg.com/ckeditor5/-/ckeditor5-35.4.0.tgz#0ce67af211551b96856b780e3729481cadbb34df" +- integrity sha512-vBEQVkFCbjYmEPVkyWsOqU44DOovUio6xBuCwroe4TuJLplqeRasCjFwB0DPknXQU8U0iM3Lh/QSKRyN92pw3Q== +- dependencies: +- "@ckeditor/ckeditor5-clipboard" "^35.4.0" +- "@ckeditor/ckeditor5-core" "^35.4.0" +- "@ckeditor/ckeditor5-engine" "^35.4.0" +- "@ckeditor/ckeditor5-enter" "^35.4.0" +- "@ckeditor/ckeditor5-paragraph" "^35.4.0" +- "@ckeditor/ckeditor5-select-all" "^35.4.0" +- "@ckeditor/ckeditor5-typing" "^35.4.0" +- "@ckeditor/ckeditor5-ui" "^35.4.0" +- "@ckeditor/ckeditor5-undo" "^35.4.0" +- "@ckeditor/ckeditor5-upload" "^35.4.0" +- "@ckeditor/ckeditor5-utils" "^35.4.0" +- "@ckeditor/ckeditor5-widget" "^35.4.0" ++ckeditor5@~34.1.0: ++ version "34.1.0" ++ resolved "https://registry.yarnpkg.com/ckeditor5/-/ckeditor5-34.1.0.tgz#3bd10c603f877891ee57e210fdd918762e2b865a" ++ integrity sha512-bWcmXEx4C7AC+FywiTrhbs63mUc8vwEualSDzyJIZLd5HULLznqJwjeON/icKtzCiBLEeUFoeDHLC5yWAEj8sA== ++ dependencies: ++ "@ckeditor/ckeditor5-clipboard" "^34.1.0" ++ "@ckeditor/ckeditor5-core" "^34.1.0" ++ "@ckeditor/ckeditor5-engine" "^34.1.0" ++ "@ckeditor/ckeditor5-enter" "^34.1.0" ++ "@ckeditor/ckeditor5-paragraph" "^34.1.0" ++ "@ckeditor/ckeditor5-select-all" "^34.1.0" ++ "@ckeditor/ckeditor5-typing" "^34.1.0" ++ "@ckeditor/ckeditor5-ui" "^34.1.0" ++ "@ckeditor/ckeditor5-undo" "^34.1.0" ++ "@ckeditor/ckeditor5-upload" "^34.1.0" ++ "@ckeditor/ckeditor5-utils" "^34.1.0" ++ "@ckeditor/ckeditor5-widget" "^34.1.0" + + clean-stack@^2.0.0: + version "2.2.0" +@@ -2586,4 +2587,4 @@ yaml@^1.10.0, yaml@^1.10.2: + yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" +- integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +\ No newline at end of file ++ integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +-- +GitLab + + +From e891499204b0979028eca44532e0b111dcc694d6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ga=C3=ABlG?= +Date: Thu, 23 Feb 2023 14:50:59 +0100 +Subject: [PATCH 06/16] WIP, see @todo for lasting work + +--- + .../js/build/videoEmbed.js | 2 +- + .../videoEmbed/src/insertvideoembedcommand.js | 24 +++---- + .../videoEmbed/src/videoembedediting.js | 65 ++++++++++++++----- + .../videoEmbed/src/videoembedui.js | 41 +++++++++--- + .../video_embed_wysiwyg.libraries.yml | 3 + + 5 files changed, 96 insertions(+), 39 deletions(-) + +diff --git a/modules/video_embed_wysiwyg/js/build/videoEmbed.js b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +index 6f05a06..28adbef 100644 +--- a/modules/video_embed_wysiwyg/js/build/videoEmbed.js ++++ b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +@@ -1 +1 @@ +-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var __webpack_modules__={"./js/ckeditor5_plugins/videoEmbed/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _videoembed__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembed */ "./js/ckeditor5_plugins/videoEmbed/src/videoembed.js");\n\n\n// @todo Remove console.log calls.\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n VideoEmbed: _videoembed__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/index.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembed.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ VideoEmbed)\n/* harmony export */ });\n/* harmony import */ var _videoembedediting__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembedediting */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js");\n/* harmony import */ var _videoembedui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./videoembedui */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js");\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n\n\n\n\nclass VideoEmbed extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\nstatic get requires() {\n return [_videoembedediting__WEBPACK_IMPORTED_MODULE_0__["default"], _videoembedui__WEBPACK_IMPORTED_MODULE_1__["default"]];\n }\n}\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembed.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js":()=>{eval('throw new Error("Module parse failed: Unexpected token (61:4)\\nYou may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders\\n| // @todo register allowed model attributes.\\n| allowAttributes:\\n> });\\n| }\\n| ");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedUI)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../icons/play-circle.svg */ \"./icons/play-circle.svg\");\n/**\n * @file registers the videoEmbed toolbar button and binds functionality to it.\n */\n\n\n\n\n/* @todo Choose the best icon and remove others. */\n\n\nclass VideoEmbedUI extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const editor = this.editor;\n\n // This will register the videoEmbed toolbar button.\n editor.ui.componentFactory.add('videoEmbed', (locale) => {\n const command = editor.commands.get('insertVideoEmbed');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n\n // Create the toolbar button.\n buttonView.set({\n label: editor.t('Video Embed'),\n icon: _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n // Execute the command when the button is clicked (executed).\n this.listenTo(buttonView, 'execute', () => {\n console.log('button execution');\n this.openEditingDialog();\n }\n );\n\n return buttonView;\n });\n }\n\n /**\n * Opens video embed form when the editing button is clicked.\n */\n openEditingDialog() {\n console.log('dialog opening');\n const {editor} = this;\n\n // If the selected element while we click the button is an instance\n // of the video_embed widget, extract it's values so they can be\n // sent to the server to prime the configuration form.\n let existingValues = {};\n const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement()\n if (selectedVideoEmbedElement) {\n // @todo adapt this copy-pasted code.\n existingValues = selectedVideoEmbedElement.hasAttribute('data-entity-uuid') ? {\n 'data-entity-uuid': selectedVideoEmbedElement.getAttribute('data-entity-uuid'),\n 'data-entity-type': selectedVideoEmbedElement.getAttribute('data-entity-type'),\n } : {};\n }\n\n this._openDialog(\n Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format),\n existingValues,\n ({attributes}) => {\n editor.execute('insertVideoEmbed', attributes);\n },\n {\n title: Drupal.t('Video Embed'),\n dialogClass: 'video-embed-dialog'\n }\n );\n }\n\n /**\n * @todo Return the focused videoEmbed element (the cke5 widget system may\n * help with that).\n *\n * @private\n */\n _getSelectedVideoEmbedElement() {\n return null;\n }\n\n /**\n * This method is adopted from drupal's ckeditor5.js file due to an issue\n * where the \"editor_object\" isn't passed to the ajax request.\n *\n * See https://www.drupal.org/project/drupal/issues/3303191\n *\n * @param {string} url\n * The URL that contains the contents of the dialog.\n * @param {object} existingValues\n * Existing values that will be sent via POST to the url for the dialog\n * contents.\n * @param {function} saveCallback\n * A function to be called upon saving the dialog.\n * @param {object} dialogSettings\n * An object containing settings to be passed to the jQuery UI.\n */\n _openDialog(url, existingValues, saveCallback, dialogSettings = {}) {\n // Add a consistent dialog class.\n const classes = dialogSettings.dialogClass\n ? dialogSettings.dialogClass.split(' ')\n : [];\n classes.push('ui-dialog--narrow');\n dialogSettings.dialogClass = classes.join(' ');\n dialogSettings.autoResize =\n window.matchMedia('(min-width: 600px)').matches;\n dialogSettings.width = 'auto';\n\n const ckeditorAjaxDialog = Drupal.ajax({\n dialog: dialogSettings,\n dialogType: 'modal',\n selector: '.ckeditor5-dialog-loading-link',\n url,\n progress: {type: 'fullscreen'},\n submit: {\n editor_object: existingValues,\n },\n });\n ckeditorAjaxDialog.execute();\n\n // Store the save callback to be executed when this dialog is closed.\n Drupal.ckeditor5.saveCallback = saveCallback;\n }\n\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js?")},"./icons/play-circle.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./icons/play-circle.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var _=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](_,_.exports,__webpack_require__),_.exports}__webpack_require__.d=(e,t)=>{for(var _ in t)__webpack_require__.o(t,_)&&!__webpack_require__.o(e,_)&&Object.defineProperty(e,_,{enumerable:!0,get:t[_]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./js/ckeditor5_plugins/videoEmbed/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})())); +\ No newline at end of file ++!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var __webpack_modules__={"./js/ckeditor5_plugins/videoEmbed/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _videoembed__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembed */ "./js/ckeditor5_plugins/videoEmbed/src/videoembed.js");\n\n\n// @todo Remove console.log calls.\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n VideoEmbed: _videoembed__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/index.js?')},"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InsertVideoEmbedCommand)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/**\n * @file defines InsertVideoEmbedCommand, which is executed when the videoEmbed\n * toolbar button is pressed.\n */\n\n\n\nclass InsertVideoEmbedCommand extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Command {\n execute(attributes) {\n console.log('command execution');\n console.log(attributes);\n const {model} = this.editor;\n\n model.change((writer) => {\n // Insert at the current selection position\n // in a way that will result in creating a valid model structure.\n model.insertContent(createVideoEmbed(writer, attributes));\n });\n }\n\n refresh() {\n const {model} = this.editor;\n const {selection} = model.document;\n\n // Determine if the cursor (selection) is in a position where adding a\n // videoEmbed is permitted. This is based on the schema of the model(s)\n // currently containing the cursor.\n const allowedIn = model.schema.findAllowedParent(\n selection.getFirstPosition(),\n 'videoEmbed',\n );\n\n // If the cursor is not in a location where a videoEmbed can be added,\n // return null so the addition doesn't happen.\n this.isEnabled = allowedIn !== null;\n }\n}\n\nfunction createVideoEmbed(writer, attributes) {\n // Create instances of the element registered with the editor in\n // videoembedediting.js.\n const videoEmbed = writer.createElement('videoEmbed', attributes);\nconsole.log('createVideoEmbed');\nconsole.log(videoEmbed);\n\n // Return the element to be added to the editor.\n return videoEmbed;\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembed.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ VideoEmbed)\n/* harmony export */ });\n/* harmony import */ var _videoembedediting__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembedediting */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js");\n/* harmony import */ var _videoembedui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./videoembedui */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js");\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n\n\n\n\nclass VideoEmbed extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\nstatic get requires() {\n return [_videoembedediting__WEBPACK_IMPORTED_MODULE_0__["default"], _videoembedui__WEBPACK_IMPORTED_MODULE_1__["default"]];\n }\n}\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembed.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedEditing)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/widget */ \"ckeditor5/src/widget.js\");\n/* harmony import */ var _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./insertvideoembedcommand */ \"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js\");\n\n\n\n\n\n\n/**\n * CKEditor 5 plugins do not work directly with the DOM. They are defined as\n * plugin-specific data models that are then converted to markup that\n * is inserted in the DOM.\n *\n * CKEditor 5 internally interacts with videoEmbed as this model:\n * \n *\n * Which is converted in database (dataDowncast) as this \"text\":\n * {\"preview_thumbnail\":\"/some/image/path.jpg\",\n * \"video_url\":\"https://some.video.url\",\"settings\":{\"responsive\":0or1,\"width\":\"42\",\"height\":\"42\",\"autoplay\":0or1}\",\n * settings_summary\":[\"Some help text.\"]}\n *\n * The Drupal video_embed_wysiwyg format filter will then convert this into a\n * real HTML video embed, on PHP frontend rendering.\n *\n * videoEmbed model elements are also converted to HTML for preview in CKE5 UI\n * (editingDowncast).\n *\n * And the database markup can be converted back to model (upcast).\n *\n * This file has the logic for defining the videoEmbed model, and for how it is\n * converted from/to standard DOM markup for database/UI.\n */\nclass VideoEmbedEditing extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n static get requires() {\n return [ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.Widget];\n }\n\n init() {\n this._defineSchema();\n this._defineConverters();\n this.editor.commands.add(\n 'insertVideoEmbed',\n new _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this.editor),\n );\n }\n\n /*\n * This registers the structure that will be seen by CKEditor 5 as\n * \n *\n * The logic in _defineConverters() will determine how this is converted to\n * markup.\n */\n _defineSchema() {\n // Schemas are registered via the central `editor` object.\n const schema = this.editor.model.schema;\n\n\n schema.register('videoEmbed', {\n inheritAllFrom: '$blockObject',\n allowAttributes: ['videoUrl', 'responsive', 'width', 'height', 'autoplay', 'previewThumbnail', 'settingsSummary']\n });\n }\n\n /**\n * Converters determine how CKEditor 5 models are converted into markup and\n * vice-versa.\n */\n _defineConverters() {\n // Converters are registered via the central editor object.\n const {conversion} = this.editor;\n\n // Upcast Converters: determine how existing HTML is interpreted by the\n // editor. These trigger when an editor instance loads.\n //\n // If {\"preview_thumbnail\":......} is present in the existing markup\n // processed by CKEditor, then CKEditor recognizes and loads it as a\n // model.\n // @todo Implement this, see video_embed_wysiwyg/plugin/plugin.js\n //conversion.for('upcast').[...]\n\n\n // Data Downcast Converters: converts stored model data into HTML.\n // These trigger when content is saved.\n //\n // Instances of are saved as\n // {\"preview_thumbnail\":......}.\n conversion.for('dataDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const data = {};\n data.preview_thumbnail = modelElement.getAttribute('previewThumbnail');\n data.video_url = modelElement.getAttribute('videoUrl');\n data.settings = {};\n ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) {\n data.settings[attributeName] = modelElement.getAttribute(attributeName);\n });\n data.settings_summary = [modelElement.getAttribute('settingsSummary')];\n return writer.createText(JSON.stringify(data));\n }\n });\n\n\n // Editing Downcast Converters. These render the content to the user for\n // editing, i.e. this determines what gets seen in the editor. These trigger\n // after the Data Upcast Converters, and are re-triggered any time there\n // are changes to any of the models' properties.\n //\n // Convert the model into a container widget in the editor UI.\n conversion.for('editingDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const preview = writer.createContainerElement('span', {class: 'video-embed-widget'}, [\n writer.createEmptyElement('img', {\n class: 'video-embed-widget__image',\n src: modelElement.getAttribute('previewThumbnail')\n }),\n writer.createContainerElement('span', {class: 'video-embed-widget__summary'}, [\n writer.createText(modelElement.getAttribute('settingsSummary'))\n ])\n ]);\n\n return (0,ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.toWidget)(preview, writer, {label: Drupal.t('Video Embed')});\n }\n }\n );\n }\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedUI)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../icons/play-circle.svg */ \"./icons/play-circle.svg\");\n/**\n * @file registers the videoEmbed toolbar button and binds functionality to it.\n */\n\n\n\n\n/* @todo Choose the best icon and remove others. */\n\n\nclass VideoEmbedUI extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const editor = this.editor;\n\n // This will register the videoEmbed toolbar button.\n editor.ui.componentFactory.add('videoEmbed', (locale) => {\n const command = editor.commands.get('insertVideoEmbed');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n\n // Create the toolbar button.\n buttonView.set({\n label: editor.t('Video Embed'),\n icon: _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n // Execute the command when the button is clicked (executed).\n this.listenTo(buttonView, 'execute', () => {\n console.log('button execution');\n this.openEditingDialog();\n }\n );\n\n return buttonView;\n });\n }\n\n /**\n * Opens video embed form when the editing button is clicked.\n */\n openEditingDialog() {\n console.log('dialog opening');\n const {editor} = this;\n\n // If the selected element while we click the button is an instance\n // of the video_embed widget, extract its values so they can be\n // sent to the server to prime the configuration form.\n let existingValues = {settings: {}};\n const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement()\n if (selectedVideoEmbedElement) {\n // @todo ensure this is the right way to implement this (ensure the\n // element is indeed a model one, not a view one).\n if (selectedVideoEmbedElement.hasAttribute('videoUrl')) {\n existingValues.video_url = selectedVideoEmbedElement.getAttribute('videoUrl');\n }\n ['responsive', 'width', 'height', 'autoplay'].foreach(function (attributeName) {\n if (selectedVideoEmbedElement.hasAttribute(attributeName)) {\n existingValues.settings.attributeName = selectedVideoEmbedElement.getAttribute(attributeName);\n }\n });\n }\n console.log('calling this._openDialog');\n this._openDialog(\n Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format),\n existingValues,\n (newValues) => {\n\n const attributes = {\n videoUrl: newValues.video_url,\n responsive: newValues.settings.responsive,\n width: newValues.settings.width,\n height: newValues.settings.height,\n autoplay: newValues.settings.autoplay,\n // These attributes are useful only for editor preview, but are\n // keeped on dataDowncast so that they can be retrieved on later\n // upcast+editingDowncast.\n settingsSummary: newValues.settings_summary[0],\n previewThumbnail: newValues.preview_thumbnail,\n }\n console.log('attributes:');\n console.log(attributes);\n editor.execute('insertVideoEmbed', attributes);\n },\n {\n title: Drupal.t('Video Embed'),\n dialogClass: 'video-embed-dialog'\n }\n );\n }\n\n /**\n * @todo Return the focused videoEmbed element (the cke5 widget system may\n * help with that).\n *\n * @private\n */\n _getSelectedVideoEmbedElement() {\n return null;\n }\n\n /**\n * This method is adapted from drupal's ckeditor5.js file due to an issue\n * where the \"editor_object\" isn't passed to the ajax request.\n *\n * See https://www.drupal.org/project/drupal/issues/3303191\n *\n * @param {string} url\n * The URL that contains the contents of the dialog.\n * @param {object} existingValues\n * Existing values that will be sent via POST to the url for the dialog\n * contents.\n * @param {function} saveCallback\n * A function to be called upon saving the dialog.\n * @param {object} dialogSettings\n * An object containing settings to be passed to the jQuery UI.\n */\n _openDialog(url, existingValues, saveCallback, dialogSettings = {}) {\n console.log('_openDialog');\n // Add a consistent dialog class.\n const classes = dialogSettings.dialogClass\n ? dialogSettings.dialogClass.split(' ')\n : [];\n classes.push('ui-dialog--narrow');\n dialogSettings.dialogClass = classes.join(' ');\n dialogSettings.autoResize =\n window.matchMedia('(min-width: 600px)').matches;\n dialogSettings.width = 'auto';\n\n const ckeditorAjaxDialog = Drupal.ajax({\n dialog: dialogSettings,\n dialogType: 'modal',\n selector: '.ckeditor5-dialog-loading-link',\n url,\n progress: {type: 'fullscreen'},\n submit: {\n editor_object: existingValues,\n },\n });\n console.log('ckeditorAjaxDialog.execute()');\n ckeditorAjaxDialog.execute();\n\n // Store the save callback to be executed when this dialog is closed.\n console.log('storing the right callback');\n Drupal.ckeditor5.saveCallback = saveCallback;\n }\n\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js?")},"./icons/play-circle.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./icons/play-circle.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/widget.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/widget.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./widget.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./js/ckeditor5_plugins/videoEmbed/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})())); +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js +index 97ad84a..ff01ffd 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js +@@ -3,22 +3,24 @@ + * toolbar button is pressed. + */ + +-import { Command } from 'ckeditor5/src/core'; ++import {Command} from 'ckeditor5/src/core'; + + export default class InsertVideoEmbedCommand extends Command { +- execute() { +- const { model } = this.editor; ++ execute(attributes) { ++ console.log('command execution'); ++ console.log(attributes); ++ const {model} = this.editor; + + model.change((writer) => { +- // Insert at the current selection position ++ // Insert at the current selection position + // in a way that will result in creating a valid model structure. +- model.insertContent(createVideoEmbed(writer)); ++ model.insertContent(createVideoEmbed(writer, attributes)); + }); + } + + refresh() { +- const { model } = this.editor; +- const { selection } = model.document; ++ const {model} = this.editor; ++ const {selection} = model.document; + + // Determine if the cursor (selection) is in a position where adding a + // videoEmbed is permitted. This is based on the schema of the model(s) +@@ -34,12 +36,12 @@ export default class InsertVideoEmbedCommand extends Command { + } + } + +-function createVideoEmbed(writer) { ++function createVideoEmbed(writer, attributes) { + // Create instances of the element registered with the editor in + // videoembedediting.js. +- const videoEmbed = writer.createElement('videoEmbed'); +- +- // @todo ++ const videoEmbed = writer.createElement('videoEmbed', attributes); ++console.log('createVideoEmbed'); ++console.log(videoEmbed); + + // Return the element to be added to the editor. + return videoEmbed; +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js +index 8fd9b0b..23a878b 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js +@@ -1,6 +1,6 @@ +-import { Plugin } from 'ckeditor5/src/core'; +-import { toWidget, toWidgetEditable } from 'ckeditor5/src/widget'; +-import { Widget } from 'ckeditor5/src/widget'; ++import {Plugin} from 'ckeditor5/src/core'; ++import {toWidget, toWidgetEditable} from 'ckeditor5/src/widget'; ++import {Widget} from 'ckeditor5/src/widget'; + import InsertVideoEmbedCommand from './insertvideoembedcommand'; + + +@@ -10,11 +10,15 @@ import InsertVideoEmbedCommand from './insertvideoembedcommand'; + * is inserted in the DOM. + * + * CKEditor 5 internally interacts with videoEmbed as this model: +- * @todo List attributes in this doc. +- * ++ * + * +- * Which is converted in database (dataDowncast) as this markup: +- *

{"video_url":"https://some.video.url","settings":{"responsive":0or1,"width":"42","height":"42","autoplay":0or1}}

++ * Which is converted in database (dataDowncast) as this "text": ++ * {"preview_thumbnail":"/some/image/path.jpg", ++ * "video_url":"https://some.video.url","settings":{"responsive":0or1,"width":"42","height":"42","autoplay":0or1}", ++ * settings_summary":["Some help text."]} + * + * The Drupal video_embed_wysiwyg format filter will then convert this into a + * real HTML video embed, on PHP frontend rendering. +@@ -43,7 +47,7 @@ export default class VideoEmbedEditing extends Plugin { + + /* + * This registers the structure that will be seen by CKEditor 5 as +- * ++ * + * + * The logic in _defineConverters() will determine how this is converted to + * markup. +@@ -53,11 +57,9 @@ export default class VideoEmbedEditing extends Plugin { + const schema = this.editor.model.schema; + + +- + schema.register('videoEmbed', { + inheritAllFrom: '$blockObject', +- // @todo register allowed model attributes. +- // allowAttributes: ++ allowAttributes: ['videoUrl', 'responsive', 'width', 'height', 'autoplay', 'previewThumbnail', 'settingsSummary'] + }); + } + +@@ -67,12 +69,12 @@ export default class VideoEmbedEditing extends Plugin { + */ + _defineConverters() { + // Converters are registered via the central editor object. +- const { conversion } = this.editor; ++ const {conversion} = this.editor; + + // Upcast Converters: determine how existing HTML is interpreted by the + // editor. These trigger when an editor instance loads. + // +- // If {"video_url":...} is present in the existing markup ++ // If {"preview_thumbnail":......} is present in the existing markup + // processed by CKEditor, then CKEditor recognizes and loads it as a + // model. + // @todo Implement this, see video_embed_wysiwyg/plugin/plugin.js +@@ -83,9 +85,21 @@ export default class VideoEmbedEditing extends Plugin { + // These trigger when content is saved. + // + // Instances of are saved as +- //

{{"video_url":...}

. +- // @todo Implement this, see video_embed_wysiwyg/plugin/plugin.js +- //conversion.for('dataDowncast').[...] ++ // {"preview_thumbnail":......}. ++ conversion.for('dataDowncast').elementToElement({ ++ model: 'videoEmbed', ++ view: (modelElement, {writer}) => { ++ const data = {}; ++ data.preview_thumbnail = modelElement.getAttribute('previewThumbnail'); ++ data.video_url = modelElement.getAttribute('videoUrl'); ++ data.settings = {}; ++ ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) { ++ data.settings[attributeName] = modelElement.getAttribute(attributeName); ++ }); ++ data.settings_summary = [modelElement.getAttribute('settingsSummary')]; ++ return writer.createText(JSON.stringify(data)); ++ } ++ }); + + + // Editing Downcast Converters. These render the content to the user for +@@ -94,8 +108,23 @@ export default class VideoEmbedEditing extends Plugin { + // are changes to any of the models' properties. + // + // Convert the model into a container widget in the editor UI. +- // @todo Implement this, see video_embed_wysiwyg/plugin/plugin.js +- //conversion.for('editingDowncast').[...] ++ conversion.for('editingDowncast').elementToElement({ ++ model: 'videoEmbed', ++ view: (modelElement, {writer}) => { ++ const preview = writer.createContainerElement('span', {class: 'video-embed-widget'}, [ ++ writer.createEmptyElement('img', { ++ class: 'video-embed-widget__image', ++ src: modelElement.getAttribute('previewThumbnail') ++ }), ++ writer.createContainerElement('span', {class: 'video-embed-widget__summary'}, [ ++ writer.createText(modelElement.getAttribute('settingsSummary')) ++ ]) ++ ]); ++ ++ return toWidget(preview, writer, {label: Drupal.t('Video Embed')}); ++ } ++ } ++ ); + } + } + +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js +index dab160d..6367950 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js +@@ -48,20 +48,40 @@ export default class VideoEmbedUI extends Plugin { + // If the selected element while we click the button is an instance + // of the video_embed widget, extract its values so they can be + // sent to the server to prime the configuration form. +- let existingValues = {}; ++ let existingValues = {settings: {}}; + const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement() + if (selectedVideoEmbedElement) { +- // @todo adapt this copy-pasted code. +- existingValues = selectedVideoEmbedElement.hasAttribute('data-entity-uuid') ? { +- 'data-entity-uuid': selectedVideoEmbedElement.getAttribute('data-entity-uuid'), +- 'data-entity-type': selectedVideoEmbedElement.getAttribute('data-entity-type'), +- } : {}; ++ // @todo ensure this is the right way to implement this (ensure the ++ // element is indeed a model one, not a view one). ++ if (selectedVideoEmbedElement.hasAttribute('videoUrl')) { ++ existingValues.video_url = selectedVideoEmbedElement.getAttribute('videoUrl'); ++ } ++ ['responsive', 'width', 'height', 'autoplay'].foreach(function (attributeName) { ++ if (selectedVideoEmbedElement.hasAttribute(attributeName)) { ++ existingValues.settings.attributeName = selectedVideoEmbedElement.getAttribute(attributeName); ++ } ++ }); + } +- ++ console.log('calling this._openDialog'); + this._openDialog( + Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format), + existingValues, +- ({attributes}) => { ++ (newValues) => { ++ ++ const attributes = { ++ videoUrl: newValues.video_url, ++ responsive: newValues.settings.responsive, ++ width: newValues.settings.width, ++ height: newValues.settings.height, ++ autoplay: newValues.settings.autoplay, ++ // These attributes are useful only for editor preview, but are ++ // keeped on dataDowncast so that they can be retrieved on later ++ // upcast+editingDowncast. ++ settingsSummary: newValues.settings_summary[0], ++ previewThumbnail: newValues.preview_thumbnail, ++ } ++ console.log('attributes:'); ++ console.log(attributes); + editor.execute('insertVideoEmbed', attributes); + }, + { +@@ -82,7 +102,7 @@ export default class VideoEmbedUI extends Plugin { + } + + /** +- * This method is adopted from drupal's ckeditor5.js file due to an issue ++ * This method is adapted from drupal's ckeditor5.js file due to an issue + * where the "editor_object" isn't passed to the ajax request. + * + * See https://www.drupal.org/project/drupal/issues/3303191 +@@ -98,6 +118,7 @@ export default class VideoEmbedUI extends Plugin { + * An object containing settings to be passed to the jQuery UI. + */ + _openDialog(url, existingValues, saveCallback, dialogSettings = {}) { ++ console.log('_openDialog'); + // Add a consistent dialog class. + const classes = dialogSettings.dialogClass + ? dialogSettings.dialogClass.split(' ') +@@ -118,9 +139,11 @@ export default class VideoEmbedUI extends Plugin { + editor_object: existingValues, + }, + }); ++ console.log('ckeditorAjaxDialog.execute()'); + ckeditorAjaxDialog.execute(); + + // Store the save callback to be executed when this dialog is closed. ++ console.log('storing the right callback'); + Drupal.ckeditor5.saveCallback = saveCallback; + } + +diff --git a/modules/video_embed_wysiwyg/video_embed_wysiwyg.libraries.yml b/modules/video_embed_wysiwyg/video_embed_wysiwyg.libraries.yml +index 0b134bf..13c3a4d 100644 +--- a/modules/video_embed_wysiwyg/video_embed_wysiwyg.libraries.yml ++++ b/modules/video_embed_wysiwyg/video_embed_wysiwyg.libraries.yml +@@ -1,6 +1,9 @@ + video_embed: + js: + js/build/videoEmbed.js: { preprocess: false, minified: true } ++ css: ++ theme: ++ plugin/plugin.css: { } + dependencies: + - core/ckeditor5 + +-- +GitLab + + +From 6dfc028186507398d06d4e85a95a7a2ac356a5e3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ga=C3=ABlG?= +Date: Thu, 2 Mar 2023 18:00:26 +0100 +Subject: [PATCH 07/16] WIP, see @todo for lasting work + +--- + .../js/build/videoEmbed.js | 2 +- + .../videoEmbed/src/videoembedediting.js | 41 +++++++++++++++---- + 2 files changed, 33 insertions(+), 10 deletions(-) + +diff --git a/modules/video_embed_wysiwyg/js/build/videoEmbed.js b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +index 28adbef..069d21e 100644 +--- a/modules/video_embed_wysiwyg/js/build/videoEmbed.js ++++ b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +@@ -1 +1 @@ +-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var __webpack_modules__={"./js/ckeditor5_plugins/videoEmbed/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _videoembed__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembed */ "./js/ckeditor5_plugins/videoEmbed/src/videoembed.js");\n\n\n// @todo Remove console.log calls.\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n VideoEmbed: _videoembed__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/index.js?')},"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InsertVideoEmbedCommand)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/**\n * @file defines InsertVideoEmbedCommand, which is executed when the videoEmbed\n * toolbar button is pressed.\n */\n\n\n\nclass InsertVideoEmbedCommand extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Command {\n execute(attributes) {\n console.log('command execution');\n console.log(attributes);\n const {model} = this.editor;\n\n model.change((writer) => {\n // Insert at the current selection position\n // in a way that will result in creating a valid model structure.\n model.insertContent(createVideoEmbed(writer, attributes));\n });\n }\n\n refresh() {\n const {model} = this.editor;\n const {selection} = model.document;\n\n // Determine if the cursor (selection) is in a position where adding a\n // videoEmbed is permitted. This is based on the schema of the model(s)\n // currently containing the cursor.\n const allowedIn = model.schema.findAllowedParent(\n selection.getFirstPosition(),\n 'videoEmbed',\n );\n\n // If the cursor is not in a location where a videoEmbed can be added,\n // return null so the addition doesn't happen.\n this.isEnabled = allowedIn !== null;\n }\n}\n\nfunction createVideoEmbed(writer, attributes) {\n // Create instances of the element registered with the editor in\n // videoembedediting.js.\n const videoEmbed = writer.createElement('videoEmbed', attributes);\nconsole.log('createVideoEmbed');\nconsole.log(videoEmbed);\n\n // Return the element to be added to the editor.\n return videoEmbed;\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembed.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ VideoEmbed)\n/* harmony export */ });\n/* harmony import */ var _videoembedediting__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembedediting */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js");\n/* harmony import */ var _videoembedui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./videoembedui */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js");\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n\n\n\n\nclass VideoEmbed extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\nstatic get requires() {\n return [_videoembedediting__WEBPACK_IMPORTED_MODULE_0__["default"], _videoembedui__WEBPACK_IMPORTED_MODULE_1__["default"]];\n }\n}\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembed.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedEditing)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/widget */ \"ckeditor5/src/widget.js\");\n/* harmony import */ var _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./insertvideoembedcommand */ \"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js\");\n\n\n\n\n\n\n/**\n * CKEditor 5 plugins do not work directly with the DOM. They are defined as\n * plugin-specific data models that are then converted to markup that\n * is inserted in the DOM.\n *\n * CKEditor 5 internally interacts with videoEmbed as this model:\n * \n *\n * Which is converted in database (dataDowncast) as this \"text\":\n * {\"preview_thumbnail\":\"/some/image/path.jpg\",\n * \"video_url\":\"https://some.video.url\",\"settings\":{\"responsive\":0or1,\"width\":\"42\",\"height\":\"42\",\"autoplay\":0or1}\",\n * settings_summary\":[\"Some help text.\"]}\n *\n * The Drupal video_embed_wysiwyg format filter will then convert this into a\n * real HTML video embed, on PHP frontend rendering.\n *\n * videoEmbed model elements are also converted to HTML for preview in CKE5 UI\n * (editingDowncast).\n *\n * And the database markup can be converted back to model (upcast).\n *\n * This file has the logic for defining the videoEmbed model, and for how it is\n * converted from/to standard DOM markup for database/UI.\n */\nclass VideoEmbedEditing extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n static get requires() {\n return [ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.Widget];\n }\n\n init() {\n this._defineSchema();\n this._defineConverters();\n this.editor.commands.add(\n 'insertVideoEmbed',\n new _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this.editor),\n );\n }\n\n /*\n * This registers the structure that will be seen by CKEditor 5 as\n * \n *\n * The logic in _defineConverters() will determine how this is converted to\n * markup.\n */\n _defineSchema() {\n // Schemas are registered via the central `editor` object.\n const schema = this.editor.model.schema;\n\n\n schema.register('videoEmbed', {\n inheritAllFrom: '$blockObject',\n allowAttributes: ['videoUrl', 'responsive', 'width', 'height', 'autoplay', 'previewThumbnail', 'settingsSummary']\n });\n }\n\n /**\n * Converters determine how CKEditor 5 models are converted into markup and\n * vice-versa.\n */\n _defineConverters() {\n // Converters are registered via the central editor object.\n const {conversion} = this.editor;\n\n // Upcast Converters: determine how existing HTML is interpreted by the\n // editor. These trigger when an editor instance loads.\n //\n // If {\"preview_thumbnail\":......} is present in the existing markup\n // processed by CKEditor, then CKEditor recognizes and loads it as a\n // model.\n // @todo Implement this, see video_embed_wysiwyg/plugin/plugin.js\n //conversion.for('upcast').[...]\n\n\n // Data Downcast Converters: converts stored model data into HTML.\n // These trigger when content is saved.\n //\n // Instances of are saved as\n // {\"preview_thumbnail\":......}.\n conversion.for('dataDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const data = {};\n data.preview_thumbnail = modelElement.getAttribute('previewThumbnail');\n data.video_url = modelElement.getAttribute('videoUrl');\n data.settings = {};\n ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) {\n data.settings[attributeName] = modelElement.getAttribute(attributeName);\n });\n data.settings_summary = [modelElement.getAttribute('settingsSummary')];\n return writer.createText(JSON.stringify(data));\n }\n });\n\n\n // Editing Downcast Converters. These render the content to the user for\n // editing, i.e. this determines what gets seen in the editor. These trigger\n // after the Data Upcast Converters, and are re-triggered any time there\n // are changes to any of the models' properties.\n //\n // Convert the model into a container widget in the editor UI.\n conversion.for('editingDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const preview = writer.createContainerElement('span', {class: 'video-embed-widget'}, [\n writer.createEmptyElement('img', {\n class: 'video-embed-widget__image',\n src: modelElement.getAttribute('previewThumbnail')\n }),\n writer.createContainerElement('span', {class: 'video-embed-widget__summary'}, [\n writer.createText(modelElement.getAttribute('settingsSummary'))\n ])\n ]);\n\n return (0,ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.toWidget)(preview, writer, {label: Drupal.t('Video Embed')});\n }\n }\n );\n }\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedUI)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../icons/play-circle.svg */ \"./icons/play-circle.svg\");\n/**\n * @file registers the videoEmbed toolbar button and binds functionality to it.\n */\n\n\n\n\n/* @todo Choose the best icon and remove others. */\n\n\nclass VideoEmbedUI extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const editor = this.editor;\n\n // This will register the videoEmbed toolbar button.\n editor.ui.componentFactory.add('videoEmbed', (locale) => {\n const command = editor.commands.get('insertVideoEmbed');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n\n // Create the toolbar button.\n buttonView.set({\n label: editor.t('Video Embed'),\n icon: _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n // Execute the command when the button is clicked (executed).\n this.listenTo(buttonView, 'execute', () => {\n console.log('button execution');\n this.openEditingDialog();\n }\n );\n\n return buttonView;\n });\n }\n\n /**\n * Opens video embed form when the editing button is clicked.\n */\n openEditingDialog() {\n console.log('dialog opening');\n const {editor} = this;\n\n // If the selected element while we click the button is an instance\n // of the video_embed widget, extract its values so they can be\n // sent to the server to prime the configuration form.\n let existingValues = {settings: {}};\n const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement()\n if (selectedVideoEmbedElement) {\n // @todo ensure this is the right way to implement this (ensure the\n // element is indeed a model one, not a view one).\n if (selectedVideoEmbedElement.hasAttribute('videoUrl')) {\n existingValues.video_url = selectedVideoEmbedElement.getAttribute('videoUrl');\n }\n ['responsive', 'width', 'height', 'autoplay'].foreach(function (attributeName) {\n if (selectedVideoEmbedElement.hasAttribute(attributeName)) {\n existingValues.settings.attributeName = selectedVideoEmbedElement.getAttribute(attributeName);\n }\n });\n }\n console.log('calling this._openDialog');\n this._openDialog(\n Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format),\n existingValues,\n (newValues) => {\n\n const attributes = {\n videoUrl: newValues.video_url,\n responsive: newValues.settings.responsive,\n width: newValues.settings.width,\n height: newValues.settings.height,\n autoplay: newValues.settings.autoplay,\n // These attributes are useful only for editor preview, but are\n // keeped on dataDowncast so that they can be retrieved on later\n // upcast+editingDowncast.\n settingsSummary: newValues.settings_summary[0],\n previewThumbnail: newValues.preview_thumbnail,\n }\n console.log('attributes:');\n console.log(attributes);\n editor.execute('insertVideoEmbed', attributes);\n },\n {\n title: Drupal.t('Video Embed'),\n dialogClass: 'video-embed-dialog'\n }\n );\n }\n\n /**\n * @todo Return the focused videoEmbed element (the cke5 widget system may\n * help with that).\n *\n * @private\n */\n _getSelectedVideoEmbedElement() {\n return null;\n }\n\n /**\n * This method is adapted from drupal's ckeditor5.js file due to an issue\n * where the \"editor_object\" isn't passed to the ajax request.\n *\n * See https://www.drupal.org/project/drupal/issues/3303191\n *\n * @param {string} url\n * The URL that contains the contents of the dialog.\n * @param {object} existingValues\n * Existing values that will be sent via POST to the url for the dialog\n * contents.\n * @param {function} saveCallback\n * A function to be called upon saving the dialog.\n * @param {object} dialogSettings\n * An object containing settings to be passed to the jQuery UI.\n */\n _openDialog(url, existingValues, saveCallback, dialogSettings = {}) {\n console.log('_openDialog');\n // Add a consistent dialog class.\n const classes = dialogSettings.dialogClass\n ? dialogSettings.dialogClass.split(' ')\n : [];\n classes.push('ui-dialog--narrow');\n dialogSettings.dialogClass = classes.join(' ');\n dialogSettings.autoResize =\n window.matchMedia('(min-width: 600px)').matches;\n dialogSettings.width = 'auto';\n\n const ckeditorAjaxDialog = Drupal.ajax({\n dialog: dialogSettings,\n dialogType: 'modal',\n selector: '.ckeditor5-dialog-loading-link',\n url,\n progress: {type: 'fullscreen'},\n submit: {\n editor_object: existingValues,\n },\n });\n console.log('ckeditorAjaxDialog.execute()');\n ckeditorAjaxDialog.execute();\n\n // Store the save callback to be executed when this dialog is closed.\n console.log('storing the right callback');\n Drupal.ckeditor5.saveCallback = saveCallback;\n }\n\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js?")},"./icons/play-circle.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./icons/play-circle.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/widget.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/widget.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./widget.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./js/ckeditor5_plugins/videoEmbed/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})())); +\ No newline at end of file ++!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var __webpack_modules__={"./js/ckeditor5_plugins/videoEmbed/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _videoembed__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembed */ "./js/ckeditor5_plugins/videoEmbed/src/videoembed.js");\n\n\n// @todo Remove console.log calls.\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n VideoEmbed: _videoembed__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/index.js?')},"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InsertVideoEmbedCommand)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/**\n * @file defines InsertVideoEmbedCommand, which is executed when the videoEmbed\n * toolbar button is pressed.\n */\n\n\n\nclass InsertVideoEmbedCommand extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Command {\n execute(attributes) {\n console.log('command execution');\n console.log(attributes);\n const {model} = this.editor;\n\n model.change((writer) => {\n // Insert at the current selection position\n // in a way that will result in creating a valid model structure.\n model.insertContent(createVideoEmbed(writer, attributes));\n });\n }\n\n refresh() {\n const {model} = this.editor;\n const {selection} = model.document;\n\n // Determine if the cursor (selection) is in a position where adding a\n // videoEmbed is permitted. This is based on the schema of the model(s)\n // currently containing the cursor.\n const allowedIn = model.schema.findAllowedParent(\n selection.getFirstPosition(),\n 'videoEmbed',\n );\n\n // If the cursor is not in a location where a videoEmbed can be added,\n // return null so the addition doesn't happen.\n this.isEnabled = allowedIn !== null;\n }\n}\n\nfunction createVideoEmbed(writer, attributes) {\n // Create instances of the element registered with the editor in\n // videoembedediting.js.\n const videoEmbed = writer.createElement('videoEmbed', attributes);\nconsole.log('createVideoEmbed');\nconsole.log(videoEmbed);\n\n // Return the element to be added to the editor.\n return videoEmbed;\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembed.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ VideoEmbed)\n/* harmony export */ });\n/* harmony import */ var _videoembedediting__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembedediting */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js");\n/* harmony import */ var _videoembedui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./videoembedui */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js");\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n\n\n\n\nclass VideoEmbed extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\nstatic get requires() {\n return [_videoembedediting__WEBPACK_IMPORTED_MODULE_0__["default"], _videoembedui__WEBPACK_IMPORTED_MODULE_1__["default"]];\n }\n}\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembed.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedEditing)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/widget */ \"ckeditor5/src/widget.js\");\n/* harmony import */ var _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./insertvideoembedcommand */ \"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js\");\n\n\n\n\n\n\n/**\n * CKEditor 5 plugins do not work directly with the DOM. They are defined as\n * plugin-specific data models that are then converted to markup that\n * is inserted in the DOM.\n *\n * CKEditor 5 internally interacts with videoEmbed as this model:\n * \n *\n * Which is converted in database (dataDowncast) as this:\n *

{\"preview_thumbnail\":\"/some/image/path.jpg\",\n * \"video_url\":\"https://some.video.url\",\"settings\":{\"responsive\":0or1,\"width\":\"42\",\"height\":\"42\",\"autoplay\":0or1}\",\n * settings_summary\":[\"Some help text.\"]}

\n *\n * The Drupal video_embed_wysiwyg format filter will then convert this into a\n * real HTML video embed, on PHP frontend rendering.\n *\n * videoEmbed model elements are also converted to HTML for preview in CKE5 UI\n * (editingDowncast).\n *\n * And the database markup can be converted back to model (upcast).\n *\n * This file has the logic for defining the videoEmbed model, and for how it is\n * converted from/to standard DOM markup for database/UI.\n */\nclass VideoEmbedEditing extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n static get requires() {\n return [ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.Widget];\n }\n\n init() {\n this._defineSchema();\n this._defineConverters();\n this.editor.commands.add(\n 'insertVideoEmbed',\n new _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this.editor),\n );\n }\n\n /*\n * This registers the structure that will be seen by CKEditor 5 as\n * \n *\n * The logic in _defineConverters() will determine how this is converted to\n * markup.\n */\n _defineSchema() {\n // Schemas are registered via the central `editor` object.\n const schema = this.editor.model.schema;\n\n\n schema.register('videoEmbed', {\n inheritAllFrom: '$blockObject',\n allowAttributes: ['videoUrl', 'responsive', 'width', 'height', 'autoplay', 'previewThumbnail', 'settingsSummary']\n });\n }\n\n /**\n * Converters determine how CKEditor 5 models are converted into markup and\n * vice-versa.\n */\n _defineConverters() {\n // Converters are registered via the central editor object.\n const {conversion} = this.editor;\n\n // Upcast Converters: determine how existing HTML is interpreted by the\n // editor. These trigger when an editor instance loads.\n //\n // If

{\"preview_thumbnail\":......}

is present in the existing markup\n // processed by CKEditor, then CKEditor recognizes and loads it as a\n // model.\n\n const pattern = function (element) {\n if (element.name === 'p') {\n if (element.getChild(0).is('text')) {\n // @todo debug this:\n let text = element.getChild(0).data;\n console.log('text:');console.log(text);\n if (text.match(/^({(?=.*preview_thumbnail\\b)(?=.*settings\\b)(?=.*video_url\\b)(?=.*settings_summary)(.*)})$/)) {\n console.log('data:');console.log(data);\n return {name: true};\n }\n }\n }\n\n return null;\n };\n\n conversion.for('upcast').elementToElement({\n view: pattern,\n // @todo convert json text to model attributes\n model: 'videoEmbed',\n // Avoid it's converted to a normal paragraph.\n converterPriority: 'high'\n });\n\n\n // Data Downcast Converters: converts stored model data into HTML.\n // These trigger when content is saved.\n //\n // Instances of are saved as\n //

{\"preview_thumbnail\":......}

.\n conversion.for('dataDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const data = {};\n data.preview_thumbnail = modelElement.getAttribute('previewThumbnail');\n data.video_url = modelElement.getAttribute('videoUrl');\n data.settings = {};\n ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) {\n data.settings[attributeName] = modelElement.getAttribute(attributeName);\n });\n data.settings_summary = [modelElement.getAttribute('settingsSummary')];\n let p = writer.createElement('paragraph');\n writer.insertText(JSON.stringify(data), p);\n return p;\n }\n });\n\n\n // Editing Downcast Converters. These render the content to the user for\n // editing, i.e. this determines what gets seen in the editor. These trigger\n // after the Data Upcast Converters, and are re-triggered any time there\n // are changes to any of the models' properties.\n //\n // Convert the model into a container widget in the editor UI.\n conversion.for('editingDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const preview = writer.createContainerElement('span', {class: 'video-embed-widget'}, [\n writer.createEmptyElement('img', {\n class: 'video-embed-widget__image',\n src: modelElement.getAttribute('previewThumbnail')\n }),\n writer.createContainerElement('span', {class: 'video-embed-widget__summary'}, [\n writer.createText(modelElement.getAttribute('settingsSummary'))\n ])\n ]);\n\n return (0,ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.toWidget)(preview, writer, {label: Drupal.t('Video Embed')});\n }\n }\n );\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedUI)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../icons/play-circle.svg */ \"./icons/play-circle.svg\");\n/**\n * @file registers the videoEmbed toolbar button and binds functionality to it.\n */\n\n\n\n\n/* @todo Choose the best icon and remove others. */\n\n\nclass VideoEmbedUI extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const editor = this.editor;\n\n // This will register the videoEmbed toolbar button.\n editor.ui.componentFactory.add('videoEmbed', (locale) => {\n const command = editor.commands.get('insertVideoEmbed');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n\n // Create the toolbar button.\n buttonView.set({\n label: editor.t('Video Embed'),\n icon: _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n // Execute the command when the button is clicked (executed).\n this.listenTo(buttonView, 'execute', () => {\n console.log('button execution');\n this.openEditingDialog();\n }\n );\n\n return buttonView;\n });\n }\n\n /**\n * Opens video embed form when the editing button is clicked.\n */\n openEditingDialog() {\n console.log('dialog opening');\n const {editor} = this;\n\n // If the selected element while we click the button is an instance\n // of the video_embed widget, extract its values so they can be\n // sent to the server to prime the configuration form.\n let existingValues = {settings: {}};\n const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement()\n if (selectedVideoEmbedElement) {\n // @todo ensure this is the right way to implement this (ensure the\n // element is indeed a model one, not a view one).\n if (selectedVideoEmbedElement.hasAttribute('videoUrl')) {\n existingValues.video_url = selectedVideoEmbedElement.getAttribute('videoUrl');\n }\n ['responsive', 'width', 'height', 'autoplay'].foreach(function (attributeName) {\n if (selectedVideoEmbedElement.hasAttribute(attributeName)) {\n existingValues.settings.attributeName = selectedVideoEmbedElement.getAttribute(attributeName);\n }\n });\n }\n console.log('calling this._openDialog');\n this._openDialog(\n Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format),\n existingValues,\n (newValues) => {\n\n const attributes = {\n videoUrl: newValues.video_url,\n responsive: newValues.settings.responsive,\n width: newValues.settings.width,\n height: newValues.settings.height,\n autoplay: newValues.settings.autoplay,\n // These attributes are useful only for editor preview, but are\n // keeped on dataDowncast so that they can be retrieved on later\n // upcast+editingDowncast.\n settingsSummary: newValues.settings_summary[0],\n previewThumbnail: newValues.preview_thumbnail,\n }\n console.log('attributes:');\n console.log(attributes);\n editor.execute('insertVideoEmbed', attributes);\n },\n {\n title: Drupal.t('Video Embed'),\n dialogClass: 'video-embed-dialog'\n }\n );\n }\n\n /**\n * @todo Return the focused videoEmbed element (the cke5 widget system may\n * help with that).\n *\n * @private\n */\n _getSelectedVideoEmbedElement() {\n return null;\n }\n\n /**\n * This method is adapted from drupal's ckeditor5.js file due to an issue\n * where the \"editor_object\" isn't passed to the ajax request.\n *\n * See https://www.drupal.org/project/drupal/issues/3303191\n *\n * @param {string} url\n * The URL that contains the contents of the dialog.\n * @param {object} existingValues\n * Existing values that will be sent via POST to the url for the dialog\n * contents.\n * @param {function} saveCallback\n * A function to be called upon saving the dialog.\n * @param {object} dialogSettings\n * An object containing settings to be passed to the jQuery UI.\n */\n _openDialog(url, existingValues, saveCallback, dialogSettings = {}) {\n console.log('_openDialog');\n // Add a consistent dialog class.\n const classes = dialogSettings.dialogClass\n ? dialogSettings.dialogClass.split(' ')\n : [];\n classes.push('ui-dialog--narrow');\n dialogSettings.dialogClass = classes.join(' ');\n dialogSettings.autoResize =\n window.matchMedia('(min-width: 600px)').matches;\n dialogSettings.width = 'auto';\n\n const ckeditorAjaxDialog = Drupal.ajax({\n dialog: dialogSettings,\n dialogType: 'modal',\n selector: '.ckeditor5-dialog-loading-link',\n url,\n progress: {type: 'fullscreen'},\n submit: {\n editor_object: existingValues,\n },\n });\n console.log('ckeditorAjaxDialog.execute()');\n ckeditorAjaxDialog.execute();\n\n // Store the save callback to be executed when this dialog is closed.\n console.log('storing the right callback');\n Drupal.ckeditor5.saveCallback = saveCallback;\n }\n\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js?")},"./icons/play-circle.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./icons/play-circle.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/widget.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/widget.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./widget.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./js/ckeditor5_plugins/videoEmbed/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})())); +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js +index 23a878b..1b960c7 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js +@@ -15,10 +15,10 @@ import InsertVideoEmbedCommand from './insertvideoembedcommand'; + * previewThumbnail="/some/image/path.jpg" settingsSummary="Some help + * text."> + * +- * Which is converted in database (dataDowncast) as this "text": +- * {"preview_thumbnail":"/some/image/path.jpg", ++ * Which is converted in database (dataDowncast) as this: ++ *

{"preview_thumbnail":"/some/image/path.jpg", + * "video_url":"https://some.video.url","settings":{"responsive":0or1,"width":"42","height":"42","autoplay":0or1}", +- * settings_summary":["Some help text."]} ++ * settings_summary":["Some help text."]}

+ * + * The Drupal video_embed_wysiwyg format filter will then convert this into a + * real HTML video embed, on PHP frontend rendering. +@@ -74,18 +74,40 @@ export default class VideoEmbedEditing extends Plugin { + // Upcast Converters: determine how existing HTML is interpreted by the + // editor. These trigger when an editor instance loads. + // +- // If {"preview_thumbnail":......} is present in the existing markup ++ // If

{"preview_thumbnail":......}

is present in the existing markup + // processed by CKEditor, then CKEditor recognizes and loads it as a + // model. +- // @todo Implement this, see video_embed_wysiwyg/plugin/plugin.js +- //conversion.for('upcast').[...] ++ ++ const pattern = function (element) { ++ if (element.name === 'p') { ++ if (element.getChild(0).is('text')) { ++ // @todo debug this: ++ let text = element.getChild(0).data; ++ console.log('text:');console.log(text); ++ if (text.match(/^({(?=.*preview_thumbnail\b)(?=.*settings\b)(?=.*video_url\b)(?=.*settings_summary)(.*)})$/)) { ++ console.log('data:');console.log(data); ++ return {name: true}; ++ } ++ } ++ } ++ ++ return null; ++ }; ++ ++ conversion.for('upcast').elementToElement({ ++ view: pattern, ++ // @todo convert json text to model attributes ++ model: 'videoEmbed', ++ // Avoid it's converted to a normal paragraph. ++ converterPriority: 'high' ++ }); + + + // Data Downcast Converters: converts stored model data into HTML. + // These trigger when content is saved. + // + // Instances of are saved as +- // {"preview_thumbnail":......}. ++ //

{"preview_thumbnail":......}

. + conversion.for('dataDowncast').elementToElement({ + model: 'videoEmbed', + view: (modelElement, {writer}) => { +@@ -97,7 +119,9 @@ export default class VideoEmbedEditing extends Plugin { + data.settings[attributeName] = modelElement.getAttribute(attributeName); + }); + data.settings_summary = [modelElement.getAttribute('settingsSummary')]; +- return writer.createText(JSON.stringify(data)); ++ let p = writer.createElement('paragraph'); ++ writer.insertText(JSON.stringify(data), p); ++ return p; + } + }); + +@@ -127,4 +151,3 @@ export default class VideoEmbedEditing extends Plugin { + ); + } + } +- +-- +GitLab + + +From 56b997d3dfbdab3437c42d290eede597545733c7 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ga=C3=ABlG?= +Date: Thu, 9 Mar 2023 18:12:28 +0100 +Subject: [PATCH 08/16] WIP, see @todo for lasting work + +--- + .../js/build/videoEmbed.js | 2 +- + .../videoEmbed/src/videoembedediting.js | 45 +++++++++++-------- + 2 files changed, 27 insertions(+), 20 deletions(-) + +diff --git a/modules/video_embed_wysiwyg/js/build/videoEmbed.js b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +index 069d21e..c4956ee 100644 +--- a/modules/video_embed_wysiwyg/js/build/videoEmbed.js ++++ b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +@@ -1 +1 @@ +-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var __webpack_modules__={"./js/ckeditor5_plugins/videoEmbed/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _videoembed__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembed */ "./js/ckeditor5_plugins/videoEmbed/src/videoembed.js");\n\n\n// @todo Remove console.log calls.\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n VideoEmbed: _videoembed__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/index.js?')},"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InsertVideoEmbedCommand)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/**\n * @file defines InsertVideoEmbedCommand, which is executed when the videoEmbed\n * toolbar button is pressed.\n */\n\n\n\nclass InsertVideoEmbedCommand extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Command {\n execute(attributes) {\n console.log('command execution');\n console.log(attributes);\n const {model} = this.editor;\n\n model.change((writer) => {\n // Insert at the current selection position\n // in a way that will result in creating a valid model structure.\n model.insertContent(createVideoEmbed(writer, attributes));\n });\n }\n\n refresh() {\n const {model} = this.editor;\n const {selection} = model.document;\n\n // Determine if the cursor (selection) is in a position where adding a\n // videoEmbed is permitted. This is based on the schema of the model(s)\n // currently containing the cursor.\n const allowedIn = model.schema.findAllowedParent(\n selection.getFirstPosition(),\n 'videoEmbed',\n );\n\n // If the cursor is not in a location where a videoEmbed can be added,\n // return null so the addition doesn't happen.\n this.isEnabled = allowedIn !== null;\n }\n}\n\nfunction createVideoEmbed(writer, attributes) {\n // Create instances of the element registered with the editor in\n // videoembedediting.js.\n const videoEmbed = writer.createElement('videoEmbed', attributes);\nconsole.log('createVideoEmbed');\nconsole.log(videoEmbed);\n\n // Return the element to be added to the editor.\n return videoEmbed;\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembed.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ VideoEmbed)\n/* harmony export */ });\n/* harmony import */ var _videoembedediting__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembedediting */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js");\n/* harmony import */ var _videoembedui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./videoembedui */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js");\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n\n\n\n\nclass VideoEmbed extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\nstatic get requires() {\n return [_videoembedediting__WEBPACK_IMPORTED_MODULE_0__["default"], _videoembedui__WEBPACK_IMPORTED_MODULE_1__["default"]];\n }\n}\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembed.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedEditing)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/widget */ \"ckeditor5/src/widget.js\");\n/* harmony import */ var _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./insertvideoembedcommand */ \"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js\");\n\n\n\n\n\n\n/**\n * CKEditor 5 plugins do not work directly with the DOM. They are defined as\n * plugin-specific data models that are then converted to markup that\n * is inserted in the DOM.\n *\n * CKEditor 5 internally interacts with videoEmbed as this model:\n * \n *\n * Which is converted in database (dataDowncast) as this:\n *

{\"preview_thumbnail\":\"/some/image/path.jpg\",\n * \"video_url\":\"https://some.video.url\",\"settings\":{\"responsive\":0or1,\"width\":\"42\",\"height\":\"42\",\"autoplay\":0or1}\",\n * settings_summary\":[\"Some help text.\"]}

\n *\n * The Drupal video_embed_wysiwyg format filter will then convert this into a\n * real HTML video embed, on PHP frontend rendering.\n *\n * videoEmbed model elements are also converted to HTML for preview in CKE5 UI\n * (editingDowncast).\n *\n * And the database markup can be converted back to model (upcast).\n *\n * This file has the logic for defining the videoEmbed model, and for how it is\n * converted from/to standard DOM markup for database/UI.\n */\nclass VideoEmbedEditing extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n static get requires() {\n return [ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.Widget];\n }\n\n init() {\n this._defineSchema();\n this._defineConverters();\n this.editor.commands.add(\n 'insertVideoEmbed',\n new _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this.editor),\n );\n }\n\n /*\n * This registers the structure that will be seen by CKEditor 5 as\n * \n *\n * The logic in _defineConverters() will determine how this is converted to\n * markup.\n */\n _defineSchema() {\n // Schemas are registered via the central `editor` object.\n const schema = this.editor.model.schema;\n\n\n schema.register('videoEmbed', {\n inheritAllFrom: '$blockObject',\n allowAttributes: ['videoUrl', 'responsive', 'width', 'height', 'autoplay', 'previewThumbnail', 'settingsSummary']\n });\n }\n\n /**\n * Converters determine how CKEditor 5 models are converted into markup and\n * vice-versa.\n */\n _defineConverters() {\n // Converters are registered via the central editor object.\n const {conversion} = this.editor;\n\n // Upcast Converters: determine how existing HTML is interpreted by the\n // editor. These trigger when an editor instance loads.\n //\n // If

{\"preview_thumbnail\":......}

is present in the existing markup\n // processed by CKEditor, then CKEditor recognizes and loads it as a\n // model.\n\n const pattern = function (element) {\n if (element.name === 'p') {\n if (element.getChild(0).is('text')) {\n // @todo debug this:\n let text = element.getChild(0).data;\n console.log('text:');console.log(text);\n if (text.match(/^({(?=.*preview_thumbnail\\b)(?=.*settings\\b)(?=.*video_url\\b)(?=.*settings_summary)(.*)})$/)) {\n console.log('data:');console.log(data);\n return {name: true};\n }\n }\n }\n\n return null;\n };\n\n conversion.for('upcast').elementToElement({\n view: pattern,\n // @todo convert json text to model attributes\n model: 'videoEmbed',\n // Avoid it's converted to a normal paragraph.\n converterPriority: 'high'\n });\n\n\n // Data Downcast Converters: converts stored model data into HTML.\n // These trigger when content is saved.\n //\n // Instances of are saved as\n //

{\"preview_thumbnail\":......}

.\n conversion.for('dataDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const data = {};\n data.preview_thumbnail = modelElement.getAttribute('previewThumbnail');\n data.video_url = modelElement.getAttribute('videoUrl');\n data.settings = {};\n ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) {\n data.settings[attributeName] = modelElement.getAttribute(attributeName);\n });\n data.settings_summary = [modelElement.getAttribute('settingsSummary')];\n let p = writer.createElement('paragraph');\n writer.insertText(JSON.stringify(data), p);\n return p;\n }\n });\n\n\n // Editing Downcast Converters. These render the content to the user for\n // editing, i.e. this determines what gets seen in the editor. These trigger\n // after the Data Upcast Converters, and are re-triggered any time there\n // are changes to any of the models' properties.\n //\n // Convert the model into a container widget in the editor UI.\n conversion.for('editingDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const preview = writer.createContainerElement('span', {class: 'video-embed-widget'}, [\n writer.createEmptyElement('img', {\n class: 'video-embed-widget__image',\n src: modelElement.getAttribute('previewThumbnail')\n }),\n writer.createContainerElement('span', {class: 'video-embed-widget__summary'}, [\n writer.createText(modelElement.getAttribute('settingsSummary'))\n ])\n ]);\n\n return (0,ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.toWidget)(preview, writer, {label: Drupal.t('Video Embed')});\n }\n }\n );\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedUI)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../icons/play-circle.svg */ \"./icons/play-circle.svg\");\n/**\n * @file registers the videoEmbed toolbar button and binds functionality to it.\n */\n\n\n\n\n/* @todo Choose the best icon and remove others. */\n\n\nclass VideoEmbedUI extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const editor = this.editor;\n\n // This will register the videoEmbed toolbar button.\n editor.ui.componentFactory.add('videoEmbed', (locale) => {\n const command = editor.commands.get('insertVideoEmbed');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n\n // Create the toolbar button.\n buttonView.set({\n label: editor.t('Video Embed'),\n icon: _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n // Execute the command when the button is clicked (executed).\n this.listenTo(buttonView, 'execute', () => {\n console.log('button execution');\n this.openEditingDialog();\n }\n );\n\n return buttonView;\n });\n }\n\n /**\n * Opens video embed form when the editing button is clicked.\n */\n openEditingDialog() {\n console.log('dialog opening');\n const {editor} = this;\n\n // If the selected element while we click the button is an instance\n // of the video_embed widget, extract its values so they can be\n // sent to the server to prime the configuration form.\n let existingValues = {settings: {}};\n const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement()\n if (selectedVideoEmbedElement) {\n // @todo ensure this is the right way to implement this (ensure the\n // element is indeed a model one, not a view one).\n if (selectedVideoEmbedElement.hasAttribute('videoUrl')) {\n existingValues.video_url = selectedVideoEmbedElement.getAttribute('videoUrl');\n }\n ['responsive', 'width', 'height', 'autoplay'].foreach(function (attributeName) {\n if (selectedVideoEmbedElement.hasAttribute(attributeName)) {\n existingValues.settings.attributeName = selectedVideoEmbedElement.getAttribute(attributeName);\n }\n });\n }\n console.log('calling this._openDialog');\n this._openDialog(\n Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format),\n existingValues,\n (newValues) => {\n\n const attributes = {\n videoUrl: newValues.video_url,\n responsive: newValues.settings.responsive,\n width: newValues.settings.width,\n height: newValues.settings.height,\n autoplay: newValues.settings.autoplay,\n // These attributes are useful only for editor preview, but are\n // keeped on dataDowncast so that they can be retrieved on later\n // upcast+editingDowncast.\n settingsSummary: newValues.settings_summary[0],\n previewThumbnail: newValues.preview_thumbnail,\n }\n console.log('attributes:');\n console.log(attributes);\n editor.execute('insertVideoEmbed', attributes);\n },\n {\n title: Drupal.t('Video Embed'),\n dialogClass: 'video-embed-dialog'\n }\n );\n }\n\n /**\n * @todo Return the focused videoEmbed element (the cke5 widget system may\n * help with that).\n *\n * @private\n */\n _getSelectedVideoEmbedElement() {\n return null;\n }\n\n /**\n * This method is adapted from drupal's ckeditor5.js file due to an issue\n * where the \"editor_object\" isn't passed to the ajax request.\n *\n * See https://www.drupal.org/project/drupal/issues/3303191\n *\n * @param {string} url\n * The URL that contains the contents of the dialog.\n * @param {object} existingValues\n * Existing values that will be sent via POST to the url for the dialog\n * contents.\n * @param {function} saveCallback\n * A function to be called upon saving the dialog.\n * @param {object} dialogSettings\n * An object containing settings to be passed to the jQuery UI.\n */\n _openDialog(url, existingValues, saveCallback, dialogSettings = {}) {\n console.log('_openDialog');\n // Add a consistent dialog class.\n const classes = dialogSettings.dialogClass\n ? dialogSettings.dialogClass.split(' ')\n : [];\n classes.push('ui-dialog--narrow');\n dialogSettings.dialogClass = classes.join(' ');\n dialogSettings.autoResize =\n window.matchMedia('(min-width: 600px)').matches;\n dialogSettings.width = 'auto';\n\n const ckeditorAjaxDialog = Drupal.ajax({\n dialog: dialogSettings,\n dialogType: 'modal',\n selector: '.ckeditor5-dialog-loading-link',\n url,\n progress: {type: 'fullscreen'},\n submit: {\n editor_object: existingValues,\n },\n });\n console.log('ckeditorAjaxDialog.execute()');\n ckeditorAjaxDialog.execute();\n\n // Store the save callback to be executed when this dialog is closed.\n console.log('storing the right callback');\n Drupal.ckeditor5.saveCallback = saveCallback;\n }\n\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js?")},"./icons/play-circle.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./icons/play-circle.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/widget.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/widget.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./widget.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./js/ckeditor5_plugins/videoEmbed/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})())); +\ No newline at end of file ++!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var __webpack_modules__={"./js/ckeditor5_plugins/videoEmbed/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _videoembed__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembed */ "./js/ckeditor5_plugins/videoEmbed/src/videoembed.js");\n\n\n// @todo Remove console.log calls.\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n VideoEmbed: _videoembed__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/index.js?')},"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InsertVideoEmbedCommand)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/**\n * @file defines InsertVideoEmbedCommand, which is executed when the videoEmbed\n * toolbar button is pressed.\n */\n\n\n\nclass InsertVideoEmbedCommand extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Command {\n execute(attributes) {\n console.log('command execution');\n console.log(attributes);\n const {model} = this.editor;\n\n model.change((writer) => {\n // Insert at the current selection position\n // in a way that will result in creating a valid model structure.\n model.insertContent(createVideoEmbed(writer, attributes));\n });\n }\n\n refresh() {\n const {model} = this.editor;\n const {selection} = model.document;\n\n // Determine if the cursor (selection) is in a position where adding a\n // videoEmbed is permitted. This is based on the schema of the model(s)\n // currently containing the cursor.\n const allowedIn = model.schema.findAllowedParent(\n selection.getFirstPosition(),\n 'videoEmbed',\n );\n\n // If the cursor is not in a location where a videoEmbed can be added,\n // return null so the addition doesn't happen.\n this.isEnabled = allowedIn !== null;\n }\n}\n\nfunction createVideoEmbed(writer, attributes) {\n // Create instances of the element registered with the editor in\n // videoembedediting.js.\n const videoEmbed = writer.createElement('videoEmbed', attributes);\nconsole.log('createVideoEmbed');\nconsole.log(videoEmbed);\n\n // Return the element to be added to the editor.\n return videoEmbed;\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembed.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ VideoEmbed)\n/* harmony export */ });\n/* harmony import */ var _videoembedediting__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembedediting */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js");\n/* harmony import */ var _videoembedui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./videoembedui */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js");\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n\n\n\n\nclass VideoEmbed extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\nstatic get requires() {\n return [_videoembedediting__WEBPACK_IMPORTED_MODULE_0__["default"], _videoembedui__WEBPACK_IMPORTED_MODULE_1__["default"]];\n }\n}\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembed.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedEditing)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/widget */ \"ckeditor5/src/widget.js\");\n/* harmony import */ var _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./insertvideoembedcommand */ \"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js\");\n\n\n\n\n\n\n/**\n * CKEditor 5 plugins do not work directly with the DOM. They are defined as\n * plugin-specific data models that are then converted to markup that\n * is inserted in the DOM.\n *\n * CKEditor 5 internally interacts with videoEmbed as this model:\n * \n *\n * Which is converted in database (dataDowncast) as this:\n *

{\"preview_thumbnail\":\"/some/image/path.jpg\",\n * \"video_url\":\"https://some.video.url\",\"settings\":{\"responsive\":0or1,\"width\":\"42\",\"height\":\"42\",\"autoplay\":0or1}\",\n * settings_summary\":[\"Some help text.\"]}

\n *\n * The Drupal video_embed_wysiwyg format filter will then convert this into a\n * real HTML video embed, on PHP frontend rendering.\n *\n * videoEmbed model elements are also converted to HTML for preview in CKE5 UI\n * (editingDowncast).\n *\n * And the database markup can be converted back to model (upcast).\n *\n * This file has the logic for defining the videoEmbed model, and for how it is\n * converted from/to standard DOM markup for database/UI.\n */\nclass VideoEmbedEditing extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n static get requires() {\n return [ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.Widget];\n }\n\n init() {\n this._defineSchema();\n this._defineConverters();\n this.editor.commands.add(\n 'insertVideoEmbed',\n new _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this.editor),\n );\n }\n\n /*\n * This registers the structure that will be seen by CKEditor 5 as\n * \n *\n * The logic in _defineConverters() will determine how this is converted to\n * markup.\n */\n _defineSchema() {\n // Schemas are registered via the central `editor` object.\n const schema = this.editor.model.schema;\n\n\n schema.register('videoEmbed', {\n inheritAllFrom: '$blockObject',\n allowAttributes: ['videoUrl', 'responsive', 'width', 'height', 'autoplay', 'previewThumbnail', 'settingsSummary']\n });\n }\n\n /**\n * Converters determine how CKEditor 5 models are converted into markup and\n * vice-versa.\n */\n _defineConverters() {\n // Converters are registered via the central editor object.\n const {conversion} = this.editor;\n\n // Upcast Converters: determine how existing HTML is interpreted by the\n // editor. These trigger when an editor instance loads.\n //\n // If

{\"preview_thumbnail\":......}

is present in the existing markup\n // processed by CKEditor, then CKEditor recognizes and loads it as a\n // model.\n // @todo debug error in console at upcast (it works if I remove upcast\n // conversion).\n // @see https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_conversion_conversion-ConverterDefinition.html\n conversion.for('upcast').elementToElement({\n view: function (element) {\n if (element.name === 'p') {\n if (element.getChild(0).is('text')) {\n let text = element.getChild(0).data;\n if (text.match(/^({(?=.*preview_thumbnail\\b)(?=.*settings\\b)(?=.*video_url\\b)(?=.*settings_summary)(.*)})$/)) {\n return {name: true};\n }\n }\n }\n return null;\n },\n model: (viewElement, {writer}) => {\n let data = JSON.parse(viewElement.getChild(0).data);\n return writer.createElement('videoEmbed',\n {\n 'videoUrl': data.video_url,\n 'responsive': !!data.settings.responsive,\n 'width': data.settings.width,\n 'height': data.settings.height,\n 'autoplay': !!data.settings.autoplay,\n 'previewThumbnail': data.preview_thumbnail,\n 'settingsSummary': data.settings_summary,\n });\n },\n // Avoid it's converted to a normal paragraph.\n converterPriority: 'high'\n });\n\n\n // Data Downcast Converters: converts stored model data into HTML.\n // These trigger when content is saved.\n //\n // Instances of are saved as\n //

{\"preview_thumbnail\":......}

.\n conversion.for('dataDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const data = {};\n data.preview_thumbnail = modelElement.getAttribute('previewThumbnail');\n data.video_url = modelElement.getAttribute('videoUrl');\n data.settings = {};\n ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) {\n data.settings[attributeName] = modelElement.getAttribute(attributeName);\n });\n data.settings_summary = [modelElement.getAttribute('settingsSummary')];\n let p = writer.createElement('paragraph');\n writer.insertText(JSON.stringify(data), p);\n return p;\n }\n });\n\n\n // Editing Downcast Converters. These render the content to the user for\n // editing, i.e. this determines what gets seen in the editor. These trigger\n // after the Data Upcast Converters, and are re-triggered any time there\n // are changes to any of the models' properties.\n //\n // Convert the model into a container widget in the editor UI.\n conversion.for('editingDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const preview = writer.createContainerElement('span', {class: 'video-embed-widget'}, [\n writer.createEmptyElement('img', {\n class: 'video-embed-widget__image',\n src: modelElement.getAttribute('previewThumbnail')\n }),\n writer.createContainerElement('span', {class: 'video-embed-widget__summary'}, [\n writer.createText(modelElement.getAttribute('settingsSummary'))\n ])\n ]);\n\n return (0,ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.toWidget)(preview, writer, {label: Drupal.t('Video Embed')});\n }\n }\n );\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedUI)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../icons/play-circle.svg */ \"./icons/play-circle.svg\");\n/**\n * @file registers the videoEmbed toolbar button and binds functionality to it.\n */\n\n\n\n\n/* @todo Choose the best icon and remove others. */\n\n\nclass VideoEmbedUI extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const editor = this.editor;\n\n // This will register the videoEmbed toolbar button.\n editor.ui.componentFactory.add('videoEmbed', (locale) => {\n const command = editor.commands.get('insertVideoEmbed');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n\n // Create the toolbar button.\n buttonView.set({\n label: editor.t('Video Embed'),\n icon: _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n // Execute the command when the button is clicked (executed).\n this.listenTo(buttonView, 'execute', () => {\n console.log('button execution');\n this.openEditingDialog();\n }\n );\n\n return buttonView;\n });\n }\n\n /**\n * Opens video embed form when the editing button is clicked.\n */\n openEditingDialog() {\n console.log('dialog opening');\n const {editor} = this;\n\n // If the selected element while we click the button is an instance\n // of the video_embed widget, extract its values so they can be\n // sent to the server to prime the configuration form.\n let existingValues = {settings: {}};\n const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement()\n if (selectedVideoEmbedElement) {\n // @todo ensure this is the right way to implement this (ensure the\n // element is indeed a model one, not a view one).\n if (selectedVideoEmbedElement.hasAttribute('videoUrl')) {\n existingValues.video_url = selectedVideoEmbedElement.getAttribute('videoUrl');\n }\n ['responsive', 'width', 'height', 'autoplay'].foreach(function (attributeName) {\n if (selectedVideoEmbedElement.hasAttribute(attributeName)) {\n existingValues.settings.attributeName = selectedVideoEmbedElement.getAttribute(attributeName);\n }\n });\n }\n console.log('calling this._openDialog');\n this._openDialog(\n Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format),\n existingValues,\n (newValues) => {\n\n const attributes = {\n videoUrl: newValues.video_url,\n responsive: newValues.settings.responsive,\n width: newValues.settings.width,\n height: newValues.settings.height,\n autoplay: newValues.settings.autoplay,\n // These attributes are useful only for editor preview, but are\n // keeped on dataDowncast so that they can be retrieved on later\n // upcast+editingDowncast.\n settingsSummary: newValues.settings_summary[0],\n previewThumbnail: newValues.preview_thumbnail,\n }\n console.log('attributes:');\n console.log(attributes);\n editor.execute('insertVideoEmbed', attributes);\n },\n {\n title: Drupal.t('Video Embed'),\n dialogClass: 'video-embed-dialog'\n }\n );\n }\n\n /**\n * @todo Return the focused videoEmbed element (the cke5 widget system may\n * help with that).\n *\n * @private\n */\n _getSelectedVideoEmbedElement() {\n return null;\n }\n\n /**\n * This method is adapted from drupal's ckeditor5.js file due to an issue\n * where the \"editor_object\" isn't passed to the ajax request.\n *\n * See https://www.drupal.org/project/drupal/issues/3303191\n *\n * @param {string} url\n * The URL that contains the contents of the dialog.\n * @param {object} existingValues\n * Existing values that will be sent via POST to the url for the dialog\n * contents.\n * @param {function} saveCallback\n * A function to be called upon saving the dialog.\n * @param {object} dialogSettings\n * An object containing settings to be passed to the jQuery UI.\n */\n _openDialog(url, existingValues, saveCallback, dialogSettings = {}) {\n console.log('_openDialog');\n // Add a consistent dialog class.\n const classes = dialogSettings.dialogClass\n ? dialogSettings.dialogClass.split(' ')\n : [];\n classes.push('ui-dialog--narrow');\n dialogSettings.dialogClass = classes.join(' ');\n dialogSettings.autoResize =\n window.matchMedia('(min-width: 600px)').matches;\n dialogSettings.width = 'auto';\n\n const ckeditorAjaxDialog = Drupal.ajax({\n dialog: dialogSettings,\n dialogType: 'modal',\n selector: '.ckeditor5-dialog-loading-link',\n url,\n progress: {type: 'fullscreen'},\n submit: {\n editor_object: existingValues,\n },\n });\n console.log('ckeditorAjaxDialog.execute()');\n ckeditorAjaxDialog.execute();\n\n // Store the save callback to be executed when this dialog is closed.\n console.log('storing the right callback');\n Drupal.ckeditor5.saveCallback = saveCallback;\n }\n\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js?")},"./icons/play-circle.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./icons/play-circle.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/widget.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/widget.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./widget.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./js/ckeditor5_plugins/videoEmbed/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})())); +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js +index 1b960c7..f0dd37e 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js +@@ -77,27 +77,34 @@ export default class VideoEmbedEditing extends Plugin { + // If

{"preview_thumbnail":......}

is present in the existing markup + // processed by CKEditor, then CKEditor recognizes and loads it as a + // model. +- +- const pattern = function (element) { +- if (element.name === 'p') { +- if (element.getChild(0).is('text')) { +- // @todo debug this: +- let text = element.getChild(0).data; +- console.log('text:');console.log(text); +- if (text.match(/^({(?=.*preview_thumbnail\b)(?=.*settings\b)(?=.*video_url\b)(?=.*settings_summary)(.*)})$/)) { +- console.log('data:');console.log(data); +- return {name: true}; ++ // @todo debug error in console at upcast (it works if I remove upcast ++ // conversion). ++ // @see https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_conversion_conversion-ConverterDefinition.html ++ conversion.for('upcast').elementToElement({ ++ view: function (element) { ++ if (element.name === 'p') { ++ if (element.getChild(0).is('text')) { ++ let text = element.getChild(0).data; ++ if (text.match(/^({(?=.*preview_thumbnail\b)(?=.*settings\b)(?=.*video_url\b)(?=.*settings_summary)(.*)})$/)) { ++ return {name: true}; ++ } + } + } +- } +- +- return null; +- }; +- +- conversion.for('upcast').elementToElement({ +- view: pattern, +- // @todo convert json text to model attributes +- model: 'videoEmbed', ++ return null; ++ }, ++ model: (viewElement, {writer}) => { ++ let data = JSON.parse(viewElement.getChild(0).data); ++ return writer.createElement('videoEmbed', ++ { ++ 'videoUrl': data.video_url, ++ 'responsive': !!data.settings.responsive, ++ 'width': data.settings.width, ++ 'height': data.settings.height, ++ 'autoplay': !!data.settings.autoplay, ++ 'previewThumbnail': data.preview_thumbnail, ++ 'settingsSummary': data.settings_summary, ++ }); ++ }, + // Avoid it's converted to a normal paragraph. + converterPriority: 'high' + }); +-- +GitLab + + +From a66f421ab5714f0df12647fdf76d819c3f852181 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ga=C3=ABlG?= +Date: Thu, 16 Mar 2023 11:11:06 +0100 +Subject: [PATCH 09/16] WIP, see @todo for lasting work + +--- + modules/video_embed_wysiwyg/js/build/videoEmbed.js | 2 +- + .../js/ckeditor5_plugins/videoEmbed/src/index.js | 1 - + .../videoEmbed/src/insertvideoembedcommand.js | 4 ---- + .../videoEmbed/src/videoembedediting.js | 12 ++++-------- + .../ckeditor5_plugins/videoEmbed/src/videoembedui.js | 8 -------- + 5 files changed, 5 insertions(+), 22 deletions(-) + +diff --git a/modules/video_embed_wysiwyg/js/build/videoEmbed.js b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +index c4956ee..0040b53 100644 +--- a/modules/video_embed_wysiwyg/js/build/videoEmbed.js ++++ b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +@@ -1 +1 @@ +-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var __webpack_modules__={"./js/ckeditor5_plugins/videoEmbed/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _videoembed__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembed */ "./js/ckeditor5_plugins/videoEmbed/src/videoembed.js");\n\n\n// @todo Remove console.log calls.\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n VideoEmbed: _videoembed__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/index.js?')},"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InsertVideoEmbedCommand)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/**\n * @file defines InsertVideoEmbedCommand, which is executed when the videoEmbed\n * toolbar button is pressed.\n */\n\n\n\nclass InsertVideoEmbedCommand extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Command {\n execute(attributes) {\n console.log('command execution');\n console.log(attributes);\n const {model} = this.editor;\n\n model.change((writer) => {\n // Insert at the current selection position\n // in a way that will result in creating a valid model structure.\n model.insertContent(createVideoEmbed(writer, attributes));\n });\n }\n\n refresh() {\n const {model} = this.editor;\n const {selection} = model.document;\n\n // Determine if the cursor (selection) is in a position where adding a\n // videoEmbed is permitted. This is based on the schema of the model(s)\n // currently containing the cursor.\n const allowedIn = model.schema.findAllowedParent(\n selection.getFirstPosition(),\n 'videoEmbed',\n );\n\n // If the cursor is not in a location where a videoEmbed can be added,\n // return null so the addition doesn't happen.\n this.isEnabled = allowedIn !== null;\n }\n}\n\nfunction createVideoEmbed(writer, attributes) {\n // Create instances of the element registered with the editor in\n // videoembedediting.js.\n const videoEmbed = writer.createElement('videoEmbed', attributes);\nconsole.log('createVideoEmbed');\nconsole.log(videoEmbed);\n\n // Return the element to be added to the editor.\n return videoEmbed;\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembed.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ VideoEmbed)\n/* harmony export */ });\n/* harmony import */ var _videoembedediting__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembedediting */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js");\n/* harmony import */ var _videoembedui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./videoembedui */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js");\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n\n\n\n\nclass VideoEmbed extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\nstatic get requires() {\n return [_videoembedediting__WEBPACK_IMPORTED_MODULE_0__["default"], _videoembedui__WEBPACK_IMPORTED_MODULE_1__["default"]];\n }\n}\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembed.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedEditing)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/widget */ \"ckeditor5/src/widget.js\");\n/* harmony import */ var _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./insertvideoembedcommand */ \"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js\");\n\n\n\n\n\n\n/**\n * CKEditor 5 plugins do not work directly with the DOM. They are defined as\n * plugin-specific data models that are then converted to markup that\n * is inserted in the DOM.\n *\n * CKEditor 5 internally interacts with videoEmbed as this model:\n * \n *\n * Which is converted in database (dataDowncast) as this:\n *

{\"preview_thumbnail\":\"/some/image/path.jpg\",\n * \"video_url\":\"https://some.video.url\",\"settings\":{\"responsive\":0or1,\"width\":\"42\",\"height\":\"42\",\"autoplay\":0or1}\",\n * settings_summary\":[\"Some help text.\"]}

\n *\n * The Drupal video_embed_wysiwyg format filter will then convert this into a\n * real HTML video embed, on PHP frontend rendering.\n *\n * videoEmbed model elements are also converted to HTML for preview in CKE5 UI\n * (editingDowncast).\n *\n * And the database markup can be converted back to model (upcast).\n *\n * This file has the logic for defining the videoEmbed model, and for how it is\n * converted from/to standard DOM markup for database/UI.\n */\nclass VideoEmbedEditing extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n static get requires() {\n return [ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.Widget];\n }\n\n init() {\n this._defineSchema();\n this._defineConverters();\n this.editor.commands.add(\n 'insertVideoEmbed',\n new _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this.editor),\n );\n }\n\n /*\n * This registers the structure that will be seen by CKEditor 5 as\n * \n *\n * The logic in _defineConverters() will determine how this is converted to\n * markup.\n */\n _defineSchema() {\n // Schemas are registered via the central `editor` object.\n const schema = this.editor.model.schema;\n\n\n schema.register('videoEmbed', {\n inheritAllFrom: '$blockObject',\n allowAttributes: ['videoUrl', 'responsive', 'width', 'height', 'autoplay', 'previewThumbnail', 'settingsSummary']\n });\n }\n\n /**\n * Converters determine how CKEditor 5 models are converted into markup and\n * vice-versa.\n */\n _defineConverters() {\n // Converters are registered via the central editor object.\n const {conversion} = this.editor;\n\n // Upcast Converters: determine how existing HTML is interpreted by the\n // editor. These trigger when an editor instance loads.\n //\n // If

{\"preview_thumbnail\":......}

is present in the existing markup\n // processed by CKEditor, then CKEditor recognizes and loads it as a\n // model.\n // @todo debug error in console at upcast (it works if I remove upcast\n // conversion).\n // @see https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_conversion_conversion-ConverterDefinition.html\n conversion.for('upcast').elementToElement({\n view: function (element) {\n if (element.name === 'p') {\n if (element.getChild(0).is('text')) {\n let text = element.getChild(0).data;\n if (text.match(/^({(?=.*preview_thumbnail\\b)(?=.*settings\\b)(?=.*video_url\\b)(?=.*settings_summary)(.*)})$/)) {\n return {name: true};\n }\n }\n }\n return null;\n },\n model: (viewElement, {writer}) => {\n let data = JSON.parse(viewElement.getChild(0).data);\n return writer.createElement('videoEmbed',\n {\n 'videoUrl': data.video_url,\n 'responsive': !!data.settings.responsive,\n 'width': data.settings.width,\n 'height': data.settings.height,\n 'autoplay': !!data.settings.autoplay,\n 'previewThumbnail': data.preview_thumbnail,\n 'settingsSummary': data.settings_summary,\n });\n },\n // Avoid it's converted to a normal paragraph.\n converterPriority: 'high'\n });\n\n\n // Data Downcast Converters: converts stored model data into HTML.\n // These trigger when content is saved.\n //\n // Instances of are saved as\n //

{\"preview_thumbnail\":......}

.\n conversion.for('dataDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const data = {};\n data.preview_thumbnail = modelElement.getAttribute('previewThumbnail');\n data.video_url = modelElement.getAttribute('videoUrl');\n data.settings = {};\n ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) {\n data.settings[attributeName] = modelElement.getAttribute(attributeName);\n });\n data.settings_summary = [modelElement.getAttribute('settingsSummary')];\n let p = writer.createElement('paragraph');\n writer.insertText(JSON.stringify(data), p);\n return p;\n }\n });\n\n\n // Editing Downcast Converters. These render the content to the user for\n // editing, i.e. this determines what gets seen in the editor. These trigger\n // after the Data Upcast Converters, and are re-triggered any time there\n // are changes to any of the models' properties.\n //\n // Convert the model into a container widget in the editor UI.\n conversion.for('editingDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const preview = writer.createContainerElement('span', {class: 'video-embed-widget'}, [\n writer.createEmptyElement('img', {\n class: 'video-embed-widget__image',\n src: modelElement.getAttribute('previewThumbnail')\n }),\n writer.createContainerElement('span', {class: 'video-embed-widget__summary'}, [\n writer.createText(modelElement.getAttribute('settingsSummary'))\n ])\n ]);\n\n return (0,ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.toWidget)(preview, writer, {label: Drupal.t('Video Embed')});\n }\n }\n );\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedUI)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../icons/play-circle.svg */ \"./icons/play-circle.svg\");\n/**\n * @file registers the videoEmbed toolbar button and binds functionality to it.\n */\n\n\n\n\n/* @todo Choose the best icon and remove others. */\n\n\nclass VideoEmbedUI extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const editor = this.editor;\n\n // This will register the videoEmbed toolbar button.\n editor.ui.componentFactory.add('videoEmbed', (locale) => {\n const command = editor.commands.get('insertVideoEmbed');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n\n // Create the toolbar button.\n buttonView.set({\n label: editor.t('Video Embed'),\n icon: _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n // Execute the command when the button is clicked (executed).\n this.listenTo(buttonView, 'execute', () => {\n console.log('button execution');\n this.openEditingDialog();\n }\n );\n\n return buttonView;\n });\n }\n\n /**\n * Opens video embed form when the editing button is clicked.\n */\n openEditingDialog() {\n console.log('dialog opening');\n const {editor} = this;\n\n // If the selected element while we click the button is an instance\n // of the video_embed widget, extract its values so they can be\n // sent to the server to prime the configuration form.\n let existingValues = {settings: {}};\n const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement()\n if (selectedVideoEmbedElement) {\n // @todo ensure this is the right way to implement this (ensure the\n // element is indeed a model one, not a view one).\n if (selectedVideoEmbedElement.hasAttribute('videoUrl')) {\n existingValues.video_url = selectedVideoEmbedElement.getAttribute('videoUrl');\n }\n ['responsive', 'width', 'height', 'autoplay'].foreach(function (attributeName) {\n if (selectedVideoEmbedElement.hasAttribute(attributeName)) {\n existingValues.settings.attributeName = selectedVideoEmbedElement.getAttribute(attributeName);\n }\n });\n }\n console.log('calling this._openDialog');\n this._openDialog(\n Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format),\n existingValues,\n (newValues) => {\n\n const attributes = {\n videoUrl: newValues.video_url,\n responsive: newValues.settings.responsive,\n width: newValues.settings.width,\n height: newValues.settings.height,\n autoplay: newValues.settings.autoplay,\n // These attributes are useful only for editor preview, but are\n // keeped on dataDowncast so that they can be retrieved on later\n // upcast+editingDowncast.\n settingsSummary: newValues.settings_summary[0],\n previewThumbnail: newValues.preview_thumbnail,\n }\n console.log('attributes:');\n console.log(attributes);\n editor.execute('insertVideoEmbed', attributes);\n },\n {\n title: Drupal.t('Video Embed'),\n dialogClass: 'video-embed-dialog'\n }\n );\n }\n\n /**\n * @todo Return the focused videoEmbed element (the cke5 widget system may\n * help with that).\n *\n * @private\n */\n _getSelectedVideoEmbedElement() {\n return null;\n }\n\n /**\n * This method is adapted from drupal's ckeditor5.js file due to an issue\n * where the \"editor_object\" isn't passed to the ajax request.\n *\n * See https://www.drupal.org/project/drupal/issues/3303191\n *\n * @param {string} url\n * The URL that contains the contents of the dialog.\n * @param {object} existingValues\n * Existing values that will be sent via POST to the url for the dialog\n * contents.\n * @param {function} saveCallback\n * A function to be called upon saving the dialog.\n * @param {object} dialogSettings\n * An object containing settings to be passed to the jQuery UI.\n */\n _openDialog(url, existingValues, saveCallback, dialogSettings = {}) {\n console.log('_openDialog');\n // Add a consistent dialog class.\n const classes = dialogSettings.dialogClass\n ? dialogSettings.dialogClass.split(' ')\n : [];\n classes.push('ui-dialog--narrow');\n dialogSettings.dialogClass = classes.join(' ');\n dialogSettings.autoResize =\n window.matchMedia('(min-width: 600px)').matches;\n dialogSettings.width = 'auto';\n\n const ckeditorAjaxDialog = Drupal.ajax({\n dialog: dialogSettings,\n dialogType: 'modal',\n selector: '.ckeditor5-dialog-loading-link',\n url,\n progress: {type: 'fullscreen'},\n submit: {\n editor_object: existingValues,\n },\n });\n console.log('ckeditorAjaxDialog.execute()');\n ckeditorAjaxDialog.execute();\n\n // Store the save callback to be executed when this dialog is closed.\n console.log('storing the right callback');\n Drupal.ckeditor5.saveCallback = saveCallback;\n }\n\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js?")},"./icons/play-circle.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./icons/play-circle.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/widget.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/widget.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./widget.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./js/ckeditor5_plugins/videoEmbed/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})())); +\ No newline at end of file ++!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var __webpack_modules__={"./js/ckeditor5_plugins/videoEmbed/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _videoembed__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembed */ "./js/ckeditor5_plugins/videoEmbed/src/videoembed.js");\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n VideoEmbed: _videoembed__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/index.js?')},"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InsertVideoEmbedCommand)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/**\n * @file defines InsertVideoEmbedCommand, which is executed when the videoEmbed\n * toolbar button is pressed.\n */\n\n\n\nclass InsertVideoEmbedCommand extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Command {\n execute(attributes) {\n const {model} = this.editor;\n\n model.change((writer) => {\n // Insert at the current selection position\n // in a way that will result in creating a valid model structure.\n model.insertContent(createVideoEmbed(writer, attributes));\n });\n }\n\n refresh() {\n const {model} = this.editor;\n const {selection} = model.document;\n\n // Determine if the cursor (selection) is in a position where adding a\n // videoEmbed is permitted. This is based on the schema of the model(s)\n // currently containing the cursor.\n const allowedIn = model.schema.findAllowedParent(\n selection.getFirstPosition(),\n 'videoEmbed',\n );\n\n // If the cursor is not in a location where a videoEmbed can be added,\n // return null so the addition doesn't happen.\n this.isEnabled = allowedIn !== null;\n }\n}\n\nfunction createVideoEmbed(writer, attributes) {\n // Create instances of the element registered with the editor in\n // videoembedediting.js.\n const videoEmbed = writer.createElement('videoEmbed', attributes);\n\n // Return the element to be added to the editor.\n return videoEmbed;\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembed.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ VideoEmbed)\n/* harmony export */ });\n/* harmony import */ var _videoembedediting__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembedediting */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js");\n/* harmony import */ var _videoembedui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./videoembedui */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js");\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n\n\n\n\nclass VideoEmbed extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\nstatic get requires() {\n return [_videoembedediting__WEBPACK_IMPORTED_MODULE_0__["default"], _videoembedui__WEBPACK_IMPORTED_MODULE_1__["default"]];\n }\n}\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembed.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedEditing)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/widget */ \"ckeditor5/src/widget.js\");\n/* harmony import */ var _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./insertvideoembedcommand */ \"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js\");\n\n\n\n\n\n\n/**\n * CKEditor 5 plugins do not work directly with the DOM. They are defined as\n * plugin-specific data models that are then converted to markup that\n * is inserted in the DOM.\n *\n * CKEditor 5 internally interacts with videoEmbed as this model:\n * \n *\n * Which is converted in database (dataDowncast) as this:\n *

{\"preview_thumbnail\":\"/some/image/path.jpg\",\n * \"video_url\":\"https://some.video.url\",\"settings\":{\"responsive\":0or1,\"width\":\"42\",\"height\":\"42\",\"autoplay\":0or1}\",\n * settings_summary\":[\"Some help text.\"]}

\n *\n * The Drupal video_embed_wysiwyg format filter will then convert this into a\n * real HTML video embed, on PHP frontend rendering.\n *\n * videoEmbed model elements are also converted to HTML for preview in CKE5 UI\n * (editingDowncast).\n *\n * And the database markup can be converted back to model (upcast).\n *\n * This file has the logic for defining the videoEmbed model, and for how it is\n * converted from/to standard DOM markup for database/UI.\n */\nclass VideoEmbedEditing extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n static get requires() {\n return [ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.Widget];\n }\n\n init() {\n this._defineSchema();\n this._defineConverters();\n this.editor.commands.add(\n 'insertVideoEmbed',\n new _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this.editor),\n );\n }\n\n /*\n * This registers the structure that will be seen by CKEditor 5 as\n * \n *\n * The logic in _defineConverters() will determine how this is converted to\n * markup.\n */\n _defineSchema() {\n // Schemas are registered via the central `editor` object.\n const schema = this.editor.model.schema;\n\n\n schema.register('videoEmbed', {\n inheritAllFrom: '$blockObject',\n allowAttributes: ['videoUrl', 'responsive', 'width', 'height', 'autoplay', 'previewThumbnail', 'settingsSummary']\n });\n }\n\n /**\n * Converters determine how CKEditor 5 models are converted into markup and\n * vice-versa.\n */\n _defineConverters() {\n // Converters are registered via the central editor object.\n const {conversion} = this.editor;\n\n // Upcast Converters: determine how existing HTML is interpreted by the\n // editor. These trigger when an editor instance loads.\n //\n // If

{\"preview_thumbnail\":......}

is present in the existing markup\n // processed by CKEditor, then CKEditor recognizes and loads it as a\n // model.\n // @see\n // https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_conversion_conversion-ConverterDefinition.html\n conversion.for('upcast').elementToElement({\n view: function (element) {\n if (element.name === 'p') {\n if (element.getChild(0).is('text')) {\n let text = element.getChild(0).data;\n if (text.match(/^({(?=.*preview_thumbnail\\b)(?=.*settings\\b)(?=.*video_url\\b)(?=.*settings_summary)(.*)})$/)) {\n return {name: true};\n }\n }\n }\n return null;\n },\n model: (viewElement, {writer}) => {\n let data = JSON.parse(viewElement.getChild(0).data);\n return writer.createElement('videoEmbed',\n {\n 'videoUrl': data.video_url,\n 'responsive': !!data.settings.responsive,\n 'width': data.settings.width,\n 'height': data.settings.height,\n 'autoplay': !!data.settings.autoplay,\n 'previewThumbnail': data.preview_thumbnail,\n 'settingsSummary': data.settings_summary[0],\n });\n },\n // Avoid it's converted to a normal paragraph.\n converterPriority: 'high'\n });\n\n\n // Data Downcast Converters: converts stored model data into HTML.\n // These trigger when content is saved.\n //\n // Instances of are saved as\n //

{\"preview_thumbnail\":......}

.\n conversion.for('dataDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const data = {};\n data.preview_thumbnail = modelElement.getAttribute('previewThumbnail');\n data.video_url = modelElement.getAttribute('videoUrl');\n data.settings = {};\n ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) {\n data.settings[attributeName] = modelElement.getAttribute(attributeName);\n });\n data.settings_summary = [modelElement.getAttribute('settingsSummary')];\n return writer.createContainerElement('p', {}, [writer.createText(JSON.stringify(data))]);\n }\n });\n\n\n // Editing Downcast Converters. These render the content to the user for\n // editing, i.e. this determines what gets seen in the editor. These trigger\n // after the Data Upcast Converters, and are re-triggered any time there\n // are changes to any of the models' properties.\n //\n // Convert the model into a container widget in the editor UI.\n conversion.for('editingDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const preview = writer.createContainerElement('span', {class: 'video-embed-widget'}, [\n writer.createEmptyElement('img', {\n class: 'video-embed-widget__image',\n src: modelElement.getAttribute('previewThumbnail')\n }),\n writer.createContainerElement('span', {class: 'video-embed-widget__summary'}, [\n writer.createText(modelElement.getAttribute('settingsSummary'))\n ])\n ]);\n return (0,ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.toWidget)(preview, writer, {label: Drupal.t('Video Embed')});\n }\n }\n );\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedUI)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../icons/play-circle.svg */ \"./icons/play-circle.svg\");\n/**\n * @file registers the videoEmbed toolbar button and binds functionality to it.\n */\n\n\n\n\n/* @todo Choose the best icon and remove others. */\n\n\nclass VideoEmbedUI extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const editor = this.editor;\n\n // This will register the videoEmbed toolbar button.\n editor.ui.componentFactory.add('videoEmbed', (locale) => {\n const command = editor.commands.get('insertVideoEmbed');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n\n // Create the toolbar button.\n buttonView.set({\n label: editor.t('Video Embed'),\n icon: _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n // Execute the command when the button is clicked (executed).\n this.listenTo(buttonView, 'execute', () => {\n this.openEditingDialog();\n }\n );\n\n return buttonView;\n });\n }\n\n /**\n * Opens video embed form when the editing button is clicked.\n */\n openEditingDialog() {\n const {editor} = this;\n\n // If the selected element while we click the button is an instance\n // of the video_embed widget, extract its values so they can be\n // sent to the server to prime the configuration form.\n let existingValues = {settings: {}};\n const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement()\n if (selectedVideoEmbedElement) {\n // @todo ensure this is the right way to implement this (ensure the\n // element is indeed a model one, not a view one).\n if (selectedVideoEmbedElement.hasAttribute('videoUrl')) {\n existingValues.video_url = selectedVideoEmbedElement.getAttribute('videoUrl');\n }\n ['responsive', 'width', 'height', 'autoplay'].foreach(function (attributeName) {\n if (selectedVideoEmbedElement.hasAttribute(attributeName)) {\n existingValues.settings.attributeName = selectedVideoEmbedElement.getAttribute(attributeName);\n }\n });\n }\n this._openDialog(\n Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format),\n existingValues,\n (newValues) => {\n\n const attributes = {\n videoUrl: newValues.video_url,\n responsive: newValues.settings.responsive,\n width: newValues.settings.width,\n height: newValues.settings.height,\n autoplay: newValues.settings.autoplay,\n // These attributes are useful only for editor preview, but are\n // keeped on dataDowncast so that they can be retrieved on later\n // upcast+editingDowncast.\n settingsSummary: newValues.settings_summary[0],\n previewThumbnail: newValues.preview_thumbnail,\n }\n editor.execute('insertVideoEmbed', attributes);\n },\n {\n title: Drupal.t('Video Embed'),\n dialogClass: 'video-embed-dialog'\n }\n );\n }\n\n /**\n * @todo Return the focused videoEmbed element (the cke5 widget system may\n * help with that).\n *\n * @private\n */\n _getSelectedVideoEmbedElement() {\n return null;\n }\n\n /**\n * This method is adapted from drupal's ckeditor5.js file due to an issue\n * where the \"editor_object\" isn't passed to the ajax request.\n *\n * See https://www.drupal.org/project/drupal/issues/3303191\n *\n * @param {string} url\n * The URL that contains the contents of the dialog.\n * @param {object} existingValues\n * Existing values that will be sent via POST to the url for the dialog\n * contents.\n * @param {function} saveCallback\n * A function to be called upon saving the dialog.\n * @param {object} dialogSettings\n * An object containing settings to be passed to the jQuery UI.\n */\n _openDialog(url, existingValues, saveCallback, dialogSettings = {}) {\n // Add a consistent dialog class.\n const classes = dialogSettings.dialogClass\n ? dialogSettings.dialogClass.split(' ')\n : [];\n classes.push('ui-dialog--narrow');\n dialogSettings.dialogClass = classes.join(' ');\n dialogSettings.autoResize =\n window.matchMedia('(min-width: 600px)').matches;\n dialogSettings.width = 'auto';\n\n const ckeditorAjaxDialog = Drupal.ajax({\n dialog: dialogSettings,\n dialogType: 'modal',\n selector: '.ckeditor5-dialog-loading-link',\n url,\n progress: {type: 'fullscreen'},\n submit: {\n editor_object: existingValues,\n },\n });\n ckeditorAjaxDialog.execute();\n\n // Store the save callback to be executed when this dialog is closed.\n Drupal.ckeditor5.saveCallback = saveCallback;\n }\n\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js?")},"./icons/play-circle.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./icons/play-circle.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/widget.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/widget.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./widget.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./js/ckeditor5_plugins/videoEmbed/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})())); +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/index.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/index.js +index d56de08..6fcd277 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/index.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/index.js +@@ -1,6 +1,5 @@ + import VideoEmbed from './videoembed'; + +-// @todo Remove console.log calls. + export default { + VideoEmbed, + }; +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js +index ff01ffd..71126f7 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js +@@ -7,8 +7,6 @@ import {Command} from 'ckeditor5/src/core'; + + export default class InsertVideoEmbedCommand extends Command { + execute(attributes) { +- console.log('command execution'); +- console.log(attributes); + const {model} = this.editor; + + model.change((writer) => { +@@ -40,8 +38,6 @@ function createVideoEmbed(writer, attributes) { + // Create instances of the element registered with the editor in + // videoembedediting.js. + const videoEmbed = writer.createElement('videoEmbed', attributes); +-console.log('createVideoEmbed'); +-console.log(videoEmbed); + + // Return the element to be added to the editor. + return videoEmbed; +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js +index f0dd37e..38918a9 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js +@@ -77,9 +77,8 @@ export default class VideoEmbedEditing extends Plugin { + // If

{"preview_thumbnail":......}

is present in the existing markup + // processed by CKEditor, then CKEditor recognizes and loads it as a + // model. +- // @todo debug error in console at upcast (it works if I remove upcast +- // conversion). +- // @see https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_conversion_conversion-ConverterDefinition.html ++ // @see ++ // https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_conversion_conversion-ConverterDefinition.html + conversion.for('upcast').elementToElement({ + view: function (element) { + if (element.name === 'p') { +@@ -102,7 +101,7 @@ export default class VideoEmbedEditing extends Plugin { + 'height': data.settings.height, + 'autoplay': !!data.settings.autoplay, + 'previewThumbnail': data.preview_thumbnail, +- 'settingsSummary': data.settings_summary, ++ 'settingsSummary': data.settings_summary[0], + }); + }, + // Avoid it's converted to a normal paragraph. +@@ -126,9 +125,7 @@ export default class VideoEmbedEditing extends Plugin { + data.settings[attributeName] = modelElement.getAttribute(attributeName); + }); + data.settings_summary = [modelElement.getAttribute('settingsSummary')]; +- let p = writer.createElement('paragraph'); +- writer.insertText(JSON.stringify(data), p); +- return p; ++ return writer.createContainerElement('p', {}, [writer.createText(JSON.stringify(data))]); + } + }); + +@@ -151,7 +148,6 @@ export default class VideoEmbedEditing extends Plugin { + writer.createText(modelElement.getAttribute('settingsSummary')) + ]) + ]); +- + return toWidget(preview, writer, {label: Drupal.t('Video Embed')}); + } + } +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js +index 6367950..5554a6c 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js +@@ -29,7 +29,6 @@ export default class VideoEmbedUI extends Plugin { + + // Execute the command when the button is clicked (executed). + this.listenTo(buttonView, 'execute', () => { +- console.log('button execution'); + this.openEditingDialog(); + } + ); +@@ -42,7 +41,6 @@ export default class VideoEmbedUI extends Plugin { + * Opens video embed form when the editing button is clicked. + */ + openEditingDialog() { +- console.log('dialog opening'); + const {editor} = this; + + // If the selected element while we click the button is an instance +@@ -62,7 +60,6 @@ export default class VideoEmbedUI extends Plugin { + } + }); + } +- console.log('calling this._openDialog'); + this._openDialog( + Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format), + existingValues, +@@ -80,8 +77,6 @@ export default class VideoEmbedUI extends Plugin { + settingsSummary: newValues.settings_summary[0], + previewThumbnail: newValues.preview_thumbnail, + } +- console.log('attributes:'); +- console.log(attributes); + editor.execute('insertVideoEmbed', attributes); + }, + { +@@ -118,7 +113,6 @@ export default class VideoEmbedUI extends Plugin { + * An object containing settings to be passed to the jQuery UI. + */ + _openDialog(url, existingValues, saveCallback, dialogSettings = {}) { +- console.log('_openDialog'); + // Add a consistent dialog class. + const classes = dialogSettings.dialogClass + ? dialogSettings.dialogClass.split(' ') +@@ -139,11 +133,9 @@ export default class VideoEmbedUI extends Plugin { + editor_object: existingValues, + }, + }); +- console.log('ckeditorAjaxDialog.execute()'); + ckeditorAjaxDialog.execute(); + + // Store the save callback to be executed when this dialog is closed. +- console.log('storing the right callback'); + Drupal.ckeditor5.saveCallback = saveCallback; + } + +-- +GitLab + + +From 690ba9a16a1f4f6ff4c2fa1d577d89efa3e45bb1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ga=C3=ABlG?= +Date: Thu, 16 Mar 2023 11:26:19 +0100 +Subject: [PATCH 10/16] WIP, see @todo for lasting work + +--- + .../video_embed_wysiwyg/js/build/videoEmbed.js | 2 +- + .../videoEmbed/src/videoembedui.js | 18 +++--------------- + 2 files changed, 4 insertions(+), 16 deletions(-) + +diff --git a/modules/video_embed_wysiwyg/js/build/videoEmbed.js b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +index 0040b53..8958a01 100644 +--- a/modules/video_embed_wysiwyg/js/build/videoEmbed.js ++++ b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +@@ -1 +1 @@ +-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var __webpack_modules__={"./js/ckeditor5_plugins/videoEmbed/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _videoembed__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembed */ "./js/ckeditor5_plugins/videoEmbed/src/videoembed.js");\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n VideoEmbed: _videoembed__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/index.js?')},"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InsertVideoEmbedCommand)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/**\n * @file defines InsertVideoEmbedCommand, which is executed when the videoEmbed\n * toolbar button is pressed.\n */\n\n\n\nclass InsertVideoEmbedCommand extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Command {\n execute(attributes) {\n const {model} = this.editor;\n\n model.change((writer) => {\n // Insert at the current selection position\n // in a way that will result in creating a valid model structure.\n model.insertContent(createVideoEmbed(writer, attributes));\n });\n }\n\n refresh() {\n const {model} = this.editor;\n const {selection} = model.document;\n\n // Determine if the cursor (selection) is in a position where adding a\n // videoEmbed is permitted. This is based on the schema of the model(s)\n // currently containing the cursor.\n const allowedIn = model.schema.findAllowedParent(\n selection.getFirstPosition(),\n 'videoEmbed',\n );\n\n // If the cursor is not in a location where a videoEmbed can be added,\n // return null so the addition doesn't happen.\n this.isEnabled = allowedIn !== null;\n }\n}\n\nfunction createVideoEmbed(writer, attributes) {\n // Create instances of the element registered with the editor in\n // videoembedediting.js.\n const videoEmbed = writer.createElement('videoEmbed', attributes);\n\n // Return the element to be added to the editor.\n return videoEmbed;\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembed.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ VideoEmbed)\n/* harmony export */ });\n/* harmony import */ var _videoembedediting__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembedediting */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js");\n/* harmony import */ var _videoembedui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./videoembedui */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js");\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n\n\n\n\nclass VideoEmbed extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\nstatic get requires() {\n return [_videoembedediting__WEBPACK_IMPORTED_MODULE_0__["default"], _videoembedui__WEBPACK_IMPORTED_MODULE_1__["default"]];\n }\n}\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembed.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedEditing)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/widget */ \"ckeditor5/src/widget.js\");\n/* harmony import */ var _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./insertvideoembedcommand */ \"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js\");\n\n\n\n\n\n\n/**\n * CKEditor 5 plugins do not work directly with the DOM. They are defined as\n * plugin-specific data models that are then converted to markup that\n * is inserted in the DOM.\n *\n * CKEditor 5 internally interacts with videoEmbed as this model:\n * \n *\n * Which is converted in database (dataDowncast) as this:\n *

{\"preview_thumbnail\":\"/some/image/path.jpg\",\n * \"video_url\":\"https://some.video.url\",\"settings\":{\"responsive\":0or1,\"width\":\"42\",\"height\":\"42\",\"autoplay\":0or1}\",\n * settings_summary\":[\"Some help text.\"]}

\n *\n * The Drupal video_embed_wysiwyg format filter will then convert this into a\n * real HTML video embed, on PHP frontend rendering.\n *\n * videoEmbed model elements are also converted to HTML for preview in CKE5 UI\n * (editingDowncast).\n *\n * And the database markup can be converted back to model (upcast).\n *\n * This file has the logic for defining the videoEmbed model, and for how it is\n * converted from/to standard DOM markup for database/UI.\n */\nclass VideoEmbedEditing extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n static get requires() {\n return [ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.Widget];\n }\n\n init() {\n this._defineSchema();\n this._defineConverters();\n this.editor.commands.add(\n 'insertVideoEmbed',\n new _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this.editor),\n );\n }\n\n /*\n * This registers the structure that will be seen by CKEditor 5 as\n * \n *\n * The logic in _defineConverters() will determine how this is converted to\n * markup.\n */\n _defineSchema() {\n // Schemas are registered via the central `editor` object.\n const schema = this.editor.model.schema;\n\n\n schema.register('videoEmbed', {\n inheritAllFrom: '$blockObject',\n allowAttributes: ['videoUrl', 'responsive', 'width', 'height', 'autoplay', 'previewThumbnail', 'settingsSummary']\n });\n }\n\n /**\n * Converters determine how CKEditor 5 models are converted into markup and\n * vice-versa.\n */\n _defineConverters() {\n // Converters are registered via the central editor object.\n const {conversion} = this.editor;\n\n // Upcast Converters: determine how existing HTML is interpreted by the\n // editor. These trigger when an editor instance loads.\n //\n // If

{\"preview_thumbnail\":......}

is present in the existing markup\n // processed by CKEditor, then CKEditor recognizes and loads it as a\n // model.\n // @see\n // https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_conversion_conversion-ConverterDefinition.html\n conversion.for('upcast').elementToElement({\n view: function (element) {\n if (element.name === 'p') {\n if (element.getChild(0).is('text')) {\n let text = element.getChild(0).data;\n if (text.match(/^({(?=.*preview_thumbnail\\b)(?=.*settings\\b)(?=.*video_url\\b)(?=.*settings_summary)(.*)})$/)) {\n return {name: true};\n }\n }\n }\n return null;\n },\n model: (viewElement, {writer}) => {\n let data = JSON.parse(viewElement.getChild(0).data);\n return writer.createElement('videoEmbed',\n {\n 'videoUrl': data.video_url,\n 'responsive': !!data.settings.responsive,\n 'width': data.settings.width,\n 'height': data.settings.height,\n 'autoplay': !!data.settings.autoplay,\n 'previewThumbnail': data.preview_thumbnail,\n 'settingsSummary': data.settings_summary[0],\n });\n },\n // Avoid it's converted to a normal paragraph.\n converterPriority: 'high'\n });\n\n\n // Data Downcast Converters: converts stored model data into HTML.\n // These trigger when content is saved.\n //\n // Instances of are saved as\n //

{\"preview_thumbnail\":......}

.\n conversion.for('dataDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const data = {};\n data.preview_thumbnail = modelElement.getAttribute('previewThumbnail');\n data.video_url = modelElement.getAttribute('videoUrl');\n data.settings = {};\n ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) {\n data.settings[attributeName] = modelElement.getAttribute(attributeName);\n });\n data.settings_summary = [modelElement.getAttribute('settingsSummary')];\n return writer.createContainerElement('p', {}, [writer.createText(JSON.stringify(data))]);\n }\n });\n\n\n // Editing Downcast Converters. These render the content to the user for\n // editing, i.e. this determines what gets seen in the editor. These trigger\n // after the Data Upcast Converters, and are re-triggered any time there\n // are changes to any of the models' properties.\n //\n // Convert the model into a container widget in the editor UI.\n conversion.for('editingDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const preview = writer.createContainerElement('span', {class: 'video-embed-widget'}, [\n writer.createEmptyElement('img', {\n class: 'video-embed-widget__image',\n src: modelElement.getAttribute('previewThumbnail')\n }),\n writer.createContainerElement('span', {class: 'video-embed-widget__summary'}, [\n writer.createText(modelElement.getAttribute('settingsSummary'))\n ])\n ]);\n return (0,ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.toWidget)(preview, writer, {label: Drupal.t('Video Embed')});\n }\n }\n );\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedUI)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../icons/play-circle.svg */ \"./icons/play-circle.svg\");\n/**\n * @file registers the videoEmbed toolbar button and binds functionality to it.\n */\n\n\n\n\n/* @todo Choose the best icon and remove others. */\n\n\nclass VideoEmbedUI extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const editor = this.editor;\n\n // This will register the videoEmbed toolbar button.\n editor.ui.componentFactory.add('videoEmbed', (locale) => {\n const command = editor.commands.get('insertVideoEmbed');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n\n // Create the toolbar button.\n buttonView.set({\n label: editor.t('Video Embed'),\n icon: _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n // Execute the command when the button is clicked (executed).\n this.listenTo(buttonView, 'execute', () => {\n this.openEditingDialog();\n }\n );\n\n return buttonView;\n });\n }\n\n /**\n * Opens video embed form when the editing button is clicked.\n */\n openEditingDialog() {\n const {editor} = this;\n\n // If the selected element while we click the button is an instance\n // of the video_embed widget, extract its values so they can be\n // sent to the server to prime the configuration form.\n let existingValues = {settings: {}};\n const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement()\n if (selectedVideoEmbedElement) {\n // @todo ensure this is the right way to implement this (ensure the\n // element is indeed a model one, not a view one).\n if (selectedVideoEmbedElement.hasAttribute('videoUrl')) {\n existingValues.video_url = selectedVideoEmbedElement.getAttribute('videoUrl');\n }\n ['responsive', 'width', 'height', 'autoplay'].foreach(function (attributeName) {\n if (selectedVideoEmbedElement.hasAttribute(attributeName)) {\n existingValues.settings.attributeName = selectedVideoEmbedElement.getAttribute(attributeName);\n }\n });\n }\n this._openDialog(\n Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format),\n existingValues,\n (newValues) => {\n\n const attributes = {\n videoUrl: newValues.video_url,\n responsive: newValues.settings.responsive,\n width: newValues.settings.width,\n height: newValues.settings.height,\n autoplay: newValues.settings.autoplay,\n // These attributes are useful only for editor preview, but are\n // keeped on dataDowncast so that they can be retrieved on later\n // upcast+editingDowncast.\n settingsSummary: newValues.settings_summary[0],\n previewThumbnail: newValues.preview_thumbnail,\n }\n editor.execute('insertVideoEmbed', attributes);\n },\n {\n title: Drupal.t('Video Embed'),\n dialogClass: 'video-embed-dialog'\n }\n );\n }\n\n /**\n * @todo Return the focused videoEmbed element (the cke5 widget system may\n * help with that).\n *\n * @private\n */\n _getSelectedVideoEmbedElement() {\n return null;\n }\n\n /**\n * This method is adapted from drupal's ckeditor5.js file due to an issue\n * where the \"editor_object\" isn't passed to the ajax request.\n *\n * See https://www.drupal.org/project/drupal/issues/3303191\n *\n * @param {string} url\n * The URL that contains the contents of the dialog.\n * @param {object} existingValues\n * Existing values that will be sent via POST to the url for the dialog\n * contents.\n * @param {function} saveCallback\n * A function to be called upon saving the dialog.\n * @param {object} dialogSettings\n * An object containing settings to be passed to the jQuery UI.\n */\n _openDialog(url, existingValues, saveCallback, dialogSettings = {}) {\n // Add a consistent dialog class.\n const classes = dialogSettings.dialogClass\n ? dialogSettings.dialogClass.split(' ')\n : [];\n classes.push('ui-dialog--narrow');\n dialogSettings.dialogClass = classes.join(' ');\n dialogSettings.autoResize =\n window.matchMedia('(min-width: 600px)').matches;\n dialogSettings.width = 'auto';\n\n const ckeditorAjaxDialog = Drupal.ajax({\n dialog: dialogSettings,\n dialogType: 'modal',\n selector: '.ckeditor5-dialog-loading-link',\n url,\n progress: {type: 'fullscreen'},\n submit: {\n editor_object: existingValues,\n },\n });\n ckeditorAjaxDialog.execute();\n\n // Store the save callback to be executed when this dialog is closed.\n Drupal.ckeditor5.saveCallback = saveCallback;\n }\n\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js?")},"./icons/play-circle.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./icons/play-circle.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/widget.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/widget.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./widget.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./js/ckeditor5_plugins/videoEmbed/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})())); +\ No newline at end of file ++!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var __webpack_modules__={"./js/ckeditor5_plugins/videoEmbed/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _videoembed__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembed */ "./js/ckeditor5_plugins/videoEmbed/src/videoembed.js");\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n VideoEmbed: _videoembed__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/index.js?')},"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InsertVideoEmbedCommand)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/**\n * @file defines InsertVideoEmbedCommand, which is executed when the videoEmbed\n * toolbar button is pressed.\n */\n\n\n\nclass InsertVideoEmbedCommand extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Command {\n execute(attributes) {\n const {model} = this.editor;\n\n model.change((writer) => {\n // Insert at the current selection position\n // in a way that will result in creating a valid model structure.\n model.insertContent(createVideoEmbed(writer, attributes));\n });\n }\n\n refresh() {\n const {model} = this.editor;\n const {selection} = model.document;\n\n // Determine if the cursor (selection) is in a position where adding a\n // videoEmbed is permitted. This is based on the schema of the model(s)\n // currently containing the cursor.\n const allowedIn = model.schema.findAllowedParent(\n selection.getFirstPosition(),\n 'videoEmbed',\n );\n\n // If the cursor is not in a location where a videoEmbed can be added,\n // return null so the addition doesn't happen.\n this.isEnabled = allowedIn !== null;\n }\n}\n\nfunction createVideoEmbed(writer, attributes) {\n // Create instances of the element registered with the editor in\n // videoembedediting.js.\n const videoEmbed = writer.createElement('videoEmbed', attributes);\n\n // Return the element to be added to the editor.\n return videoEmbed;\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembed.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ VideoEmbed)\n/* harmony export */ });\n/* harmony import */ var _videoembedediting__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembedediting */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js");\n/* harmony import */ var _videoembedui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./videoembedui */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js");\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n\n\n\n\nclass VideoEmbed extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\nstatic get requires() {\n return [_videoembedediting__WEBPACK_IMPORTED_MODULE_0__["default"], _videoembedui__WEBPACK_IMPORTED_MODULE_1__["default"]];\n }\n}\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembed.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedEditing)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/widget */ \"ckeditor5/src/widget.js\");\n/* harmony import */ var _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./insertvideoembedcommand */ \"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js\");\n\n\n\n\n\n\n/**\n * CKEditor 5 plugins do not work directly with the DOM. They are defined as\n * plugin-specific data models that are then converted to markup that\n * is inserted in the DOM.\n *\n * CKEditor 5 internally interacts with videoEmbed as this model:\n * \n *\n * Which is converted in database (dataDowncast) as this:\n *

{\"preview_thumbnail\":\"/some/image/path.jpg\",\n * \"video_url\":\"https://some.video.url\",\"settings\":{\"responsive\":0or1,\"width\":\"42\",\"height\":\"42\",\"autoplay\":0or1}\",\n * settings_summary\":[\"Some help text.\"]}

\n *\n * The Drupal video_embed_wysiwyg format filter will then convert this into a\n * real HTML video embed, on PHP frontend rendering.\n *\n * videoEmbed model elements are also converted to HTML for preview in CKE5 UI\n * (editingDowncast).\n *\n * And the database markup can be converted back to model (upcast).\n *\n * This file has the logic for defining the videoEmbed model, and for how it is\n * converted from/to standard DOM markup for database/UI.\n */\nclass VideoEmbedEditing extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n static get requires() {\n return [ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.Widget];\n }\n\n init() {\n this._defineSchema();\n this._defineConverters();\n this.editor.commands.add(\n 'insertVideoEmbed',\n new _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this.editor),\n );\n }\n\n /*\n * This registers the structure that will be seen by CKEditor 5 as\n * \n *\n * The logic in _defineConverters() will determine how this is converted to\n * markup.\n */\n _defineSchema() {\n // Schemas are registered via the central `editor` object.\n const schema = this.editor.model.schema;\n\n\n schema.register('videoEmbed', {\n inheritAllFrom: '$blockObject',\n allowAttributes: ['videoUrl', 'responsive', 'width', 'height', 'autoplay', 'previewThumbnail', 'settingsSummary']\n });\n }\n\n /**\n * Converters determine how CKEditor 5 models are converted into markup and\n * vice-versa.\n */\n _defineConverters() {\n // Converters are registered via the central editor object.\n const {conversion} = this.editor;\n\n // Upcast Converters: determine how existing HTML is interpreted by the\n // editor. These trigger when an editor instance loads.\n //\n // If

{\"preview_thumbnail\":......}

is present in the existing markup\n // processed by CKEditor, then CKEditor recognizes and loads it as a\n // model.\n // @see\n // https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_conversion_conversion-ConverterDefinition.html\n conversion.for('upcast').elementToElement({\n view: function (element) {\n if (element.name === 'p') {\n if (element.getChild(0).is('text')) {\n let text = element.getChild(0).data;\n if (text.match(/^({(?=.*preview_thumbnail\\b)(?=.*settings\\b)(?=.*video_url\\b)(?=.*settings_summary)(.*)})$/)) {\n return {name: true};\n }\n }\n }\n return null;\n },\n model: (viewElement, {writer}) => {\n let data = JSON.parse(viewElement.getChild(0).data);\n return writer.createElement('videoEmbed',\n {\n 'videoUrl': data.video_url,\n 'responsive': !!data.settings.responsive,\n 'width': data.settings.width,\n 'height': data.settings.height,\n 'autoplay': !!data.settings.autoplay,\n 'previewThumbnail': data.preview_thumbnail,\n 'settingsSummary': data.settings_summary[0],\n });\n },\n // Avoid it's converted to a normal paragraph.\n converterPriority: 'high'\n });\n\n\n // Data Downcast Converters: converts stored model data into HTML.\n // These trigger when content is saved.\n //\n // Instances of are saved as\n //

{\"preview_thumbnail\":......}

.\n conversion.for('dataDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const data = {};\n data.preview_thumbnail = modelElement.getAttribute('previewThumbnail');\n data.video_url = modelElement.getAttribute('videoUrl');\n data.settings = {};\n ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) {\n data.settings[attributeName] = modelElement.getAttribute(attributeName);\n });\n data.settings_summary = [modelElement.getAttribute('settingsSummary')];\n return writer.createContainerElement('p', {}, [writer.createText(JSON.stringify(data))]);\n }\n });\n\n\n // Editing Downcast Converters. These render the content to the user for\n // editing, i.e. this determines what gets seen in the editor. These trigger\n // after the Data Upcast Converters, and are re-triggered any time there\n // are changes to any of the models' properties.\n //\n // Convert the model into a container widget in the editor UI.\n conversion.for('editingDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const preview = writer.createContainerElement('span', {class: 'video-embed-widget'}, [\n writer.createEmptyElement('img', {\n class: 'video-embed-widget__image',\n src: modelElement.getAttribute('previewThumbnail')\n }),\n writer.createContainerElement('span', {class: 'video-embed-widget__summary'}, [\n writer.createText(modelElement.getAttribute('settingsSummary'))\n ])\n ]);\n return (0,ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.toWidget)(preview, writer, {label: Drupal.t('Video Embed')});\n }\n }\n );\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedUI)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../icons/play-circle.svg */ \"./icons/play-circle.svg\");\n/**\n * @file registers the videoEmbed toolbar button and binds functionality to it.\n */\n\n\n\n\n/* @todo Choose the best icon and remove others. */\n\n\nclass VideoEmbedUI extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const editor = this.editor;\n\n // This will register the videoEmbed toolbar button.\n editor.ui.componentFactory.add('videoEmbed', (locale) => {\n const command = editor.commands.get('insertVideoEmbed');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n\n // Create the toolbar button.\n buttonView.set({\n label: editor.t('Video Embed'),\n icon: _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n // Execute the command when the button is clicked (executed).\n this.listenTo(buttonView, 'execute', () => {\n this.openEditingDialog();\n }\n );\n\n return buttonView;\n });\n }\n\n /**\n * Opens video embed form when the editing button is clicked.\n */\n openEditingDialog() {\n const {editor} = this;\n\n // If the selected element while we click the button is an instance\n // of the video_embed widget, extract its values so they can be\n // sent to the server to prime the configuration form.\n let existingValues = {settings: {}};\n const selectedVideoEmbedElement = editor.model.document.selection.getSelectedElement();\n if (selectedVideoEmbedElement) {\n if (selectedVideoEmbedElement.hasAttribute('videoUrl')) {\n existingValues.video_url = selectedVideoEmbedElement.getAttribute('videoUrl');\n }\n ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) {\n if (selectedVideoEmbedElement.hasAttribute(attributeName)) {\n existingValues.settings[attributeName] = selectedVideoEmbedElement.getAttribute(attributeName);\n }\n });\n }\n this._openDialog(\n Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format),\n existingValues,\n (newValues) => {\n\n const attributes = {\n videoUrl: newValues.video_url,\n responsive: newValues.settings.responsive,\n width: newValues.settings.width,\n height: newValues.settings.height,\n autoplay: newValues.settings.autoplay,\n // These attributes are useful only for editor preview, but are\n // keeped on dataDowncast so that they can be retrieved on later\n // upcast+editingDowncast.\n settingsSummary: newValues.settings_summary[0],\n previewThumbnail: newValues.preview_thumbnail,\n }\n editor.execute('insertVideoEmbed', attributes);\n },\n {\n title: Drupal.t('Video Embed'),\n dialogClass: 'video-embed-dialog'\n }\n );\n }\n\n /**\n * This method is adapted from drupal's ckeditor5.js file due to an issue\n * where the \"editor_object\" isn't passed to the ajax request.\n *\n * See https://www.drupal.org/project/drupal/issues/3303191\n *\n * @param {string} url\n * The URL that contains the contents of the dialog.\n * @param {object} existingValues\n * Existing values that will be sent via POST to the url for the dialog\n * contents.\n * @param {function} saveCallback\n * A function to be called upon saving the dialog.\n * @param {object} dialogSettings\n * An object containing settings to be passed to the jQuery UI.\n */\n _openDialog(url, existingValues, saveCallback, dialogSettings = {}) {\n // Add a consistent dialog class.\n const classes = dialogSettings.dialogClass\n ? dialogSettings.dialogClass.split(' ')\n : [];\n classes.push('ui-dialog--narrow');\n dialogSettings.dialogClass = classes.join(' ');\n dialogSettings.autoResize =\n window.matchMedia('(min-width: 600px)').matches;\n dialogSettings.width = 'auto';\n\n const ckeditorAjaxDialog = Drupal.ajax({\n dialog: dialogSettings,\n dialogType: 'modal',\n selector: '.ckeditor5-dialog-loading-link',\n url,\n progress: {type: 'fullscreen'},\n submit: {\n editor_object: existingValues,\n },\n });\n ckeditorAjaxDialog.execute();\n\n // Store the save callback to be executed when this dialog is closed.\n Drupal.ckeditor5.saveCallback = saveCallback;\n }\n\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js?")},"./icons/play-circle.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./icons/play-circle.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/widget.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/widget.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./widget.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./js/ckeditor5_plugins/videoEmbed/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})())); +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js +index 5554a6c..ecd5411 100644 +--- a/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js ++++ b/modules/video_embed_wysiwyg/js/ckeditor5_plugins/videoEmbed/src/videoembedui.js +@@ -47,16 +47,14 @@ export default class VideoEmbedUI extends Plugin { + // of the video_embed widget, extract its values so they can be + // sent to the server to prime the configuration form. + let existingValues = {settings: {}}; +- const selectedVideoEmbedElement = this._getSelectedVideoEmbedElement() ++ const selectedVideoEmbedElement = editor.model.document.selection.getSelectedElement(); + if (selectedVideoEmbedElement) { +- // @todo ensure this is the right way to implement this (ensure the +- // element is indeed a model one, not a view one). + if (selectedVideoEmbedElement.hasAttribute('videoUrl')) { + existingValues.video_url = selectedVideoEmbedElement.getAttribute('videoUrl'); + } +- ['responsive', 'width', 'height', 'autoplay'].foreach(function (attributeName) { ++ ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) { + if (selectedVideoEmbedElement.hasAttribute(attributeName)) { +- existingValues.settings.attributeName = selectedVideoEmbedElement.getAttribute(attributeName); ++ existingValues.settings[attributeName] = selectedVideoEmbedElement.getAttribute(attributeName); + } + }); + } +@@ -86,16 +84,6 @@ export default class VideoEmbedUI extends Plugin { + ); + } + +- /** +- * @todo Return the focused videoEmbed element (the cke5 widget system may +- * help with that). +- * +- * @private +- */ +- _getSelectedVideoEmbedElement() { +- return null; +- } +- + /** + * This method is adapted from drupal's ckeditor5.js file due to an issue + * where the "editor_object" isn't passed to the ajax request. +-- +GitLab + + +From abb6ee35f659820f34497abf0310bd6a10341dd4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ga=C3=ABlG?= +Date: Thu, 16 Mar 2023 17:17:52 +0100 +Subject: [PATCH 11/16] WIP, see @todo for lasting work + +--- + .../schema/video_embed_wysiwyg.schema.yml | 25 ++++++ + .../CKEditor5Plugin/VideoEmbedWysiwyg.php | 79 ++++++++++++++----- + .../video_embed_wysiwyg.module | 3 +- + 3 files changed, 85 insertions(+), 22 deletions(-) + +diff --git a/modules/video_embed_wysiwyg/config/schema/video_embed_wysiwyg.schema.yml b/modules/video_embed_wysiwyg/config/schema/video_embed_wysiwyg.schema.yml +index f571d64..ee27f6b 100644 +--- a/modules/video_embed_wysiwyg/config/schema/video_embed_wysiwyg.schema.yml ++++ b/modules/video_embed_wysiwyg/config/schema/video_embed_wysiwyg.schema.yml +@@ -22,3 +22,28 @@ ckeditor.plugin.video_embed: + height: + label: 'Height' + type: string ++ ++ckeditor5.plugin.video_embed_wysiwyg_video_embed: ++ label: 'Video Embed' ++ type: mapping ++ mapping: ++ defaults: ++ label: 'Defaults' ++ type: mapping ++ mapping: ++ children: ++ label: 'Children' ++ type: mapping ++ mapping: ++ autoplay: ++ label: 'Autoplay' ++ type: boolean ++ responsive: ++ label: 'Responsive' ++ type: boolean ++ width: ++ label: 'Width' ++ type: string ++ height: ++ label: 'Height' ++ type: string +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php b/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php +index 13f1f19..5335f2b 100644 +--- a/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php ++++ b/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php +@@ -4,40 +4,79 @@ declare(strict_types=1); + + namespace Drupal\video_embed_wysiwyg\Plugin\CKEditor5Plugin; + ++use Drupal\ckeditor5\Plugin\CKEditor5PluginConfigurableInterface; + use Drupal\ckeditor5\Plugin\CKEditor5PluginConfigurableTrait; + use Drupal\ckeditor5\Plugin\CKEditor5PluginDefault; ++use Drupal\Core\Form\FormState; ++use Drupal\Core\Form\FormStateInterface; + use Drupal\editor\EditorInterface; ++use Drupal\video_embed_field\Plugin\Field\FieldFormatter\Video; + +-/** +- * This class transmits the Drupal config to the javascript plugin. +- * +- * @todo Add the settings form for the plugin. +- */ +-class VideoEmbedWysiwyg extends CKEditor5PluginDefault { ++class VideoEmbedWysiwyg extends CKEditor5PluginDefault implements CKEditor5PluginConfigurableInterface { + + use CKEditor5PluginConfigurableTrait; + + /** +- * @param mixed[] $static_plugin_config +- * @param \Drupal\editor\EditorInterface $editor +- * +- * @return mixed[] ++ * @inheritDoc + */ + public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array { +- $plugin_config = [ +- 'format' => $editor->id(), +- ]; +- $format = $editor->getFilterFormat(); +- /** @var \Drupal\filter\Plugin\FilterInterface $filter */ +- $filter = $format->filters('video_embed_wysiwyg'); +- $filter_config = $filter->getConfiguration(); +- $plugin_config += $filter_config['settings']; ++ // Transmit some useful Drupal data to the javascript plugin. + $parent_config = parent::getDynamicPluginConfig($static_plugin_config, $editor); +- // @todo Ensure this is the info the plugin needs. + return array_merge_recursive($parent_config, + [ +- 'videoEmbed' => $plugin_config, ++ 'videoEmbed' => [ ++ // Used by VideoEmbedUi.openEditingDialog(). ++ 'format' => $editor->id(), ++ ], + ]); + } + ++ /** ++ * @inheritDoc ++ */ ++ public function defaultConfiguration(): array { ++ return [ ++ 'defaults' => [ ++ 'children' => [ ++ 'autoplay' => FALSE, ++ 'responsive' => FALSE, ++ 'width' => '', ++ 'height' => '', ++ ], ++ ], ++ ]; ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ public function buildConfigurationForm(array $form, FormStateInterface $form_state): array { ++ $form['defaults'] = [ ++ '#title' => $this->t('Default Settings'), ++ '#type' => 'fieldset', ++ '#tree' => TRUE, ++ 'children' => Video::mockInstance($this->configuration['defaults']['children']) ++ ->settingsForm([], new FormState()), ++ ]; ++ return $form; ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void { ++ $value = $form_state->getValue('defaults'); ++ $value['children']['autoplay'] = (bool) $value['children']['autoplay']; ++ $value['children']['responsive'] = (bool) $value['children']['responsive']; ++ $form_state->setValue('defaults', $value); ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void { ++ $this->configuration['defaults'] = $form_state->getValue('defaults'); ++ } ++ ++ + } +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/video_embed_wysiwyg.module b/modules/video_embed_wysiwyg/video_embed_wysiwyg.module +index 223cc9a..a79ca60 100644 +--- a/modules/video_embed_wysiwyg/video_embed_wysiwyg.module ++++ b/modules/video_embed_wysiwyg/video_embed_wysiwyg.module +@@ -3,8 +3,7 @@ + /** + * @file + * Module file for video_embed_wysiwyg. +- * @todo test and fix CKE5 plugin. +- * @todo CKE5 upgrade path if needed. ++ * @todo CKE5 upgrade path for plugin config. + * @todo Add a comment on code that runs only for CKE4. + */ + +-- +GitLab + + +From 1688efe85c5baa0ede3bbfe392d867307f544c6a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ga=C3=ABlG?= +Date: Thu, 16 Mar 2023 17:25:02 +0100 +Subject: [PATCH 12/16] Add comments on code parts that run only for CKE4 + +--- + .../config/schema/video_embed_wysiwyg.schema.yml | 2 ++ + modules/video_embed_wysiwyg/plugin/README.md | 1 + + .../src/Plugin/CKEditorPlugin/VideoEmbedWysiwyg.php | 2 +- + modules/video_embed_wysiwyg/video_embed_wysiwyg.module | 3 ++- + 4 files changed, 6 insertions(+), 2 deletions(-) + create mode 100644 modules/video_embed_wysiwyg/plugin/README.md + +diff --git a/modules/video_embed_wysiwyg/config/schema/video_embed_wysiwyg.schema.yml b/modules/video_embed_wysiwyg/config/schema/video_embed_wysiwyg.schema.yml +index ee27f6b..117c374 100644 +--- a/modules/video_embed_wysiwyg/config/schema/video_embed_wysiwyg.schema.yml ++++ b/modules/video_embed_wysiwyg/config/schema/video_embed_wysiwyg.schema.yml +@@ -1,3 +1,4 @@ ++# CKE4 + ckeditor.plugin.video_embed: + label: 'Video Embed' + type: mapping +@@ -23,6 +24,7 @@ ckeditor.plugin.video_embed: + label: 'Height' + type: string + ++# CKE5 + ckeditor5.plugin.video_embed_wysiwyg_video_embed: + label: 'Video Embed' + type: mapping +diff --git a/modules/video_embed_wysiwyg/plugin/README.md b/modules/video_embed_wysiwyg/plugin/README.md +new file mode 100644 +index 0000000..fa35e60 +--- /dev/null ++++ b/modules/video_embed_wysiwyg/plugin/README.md +@@ -0,0 +1 @@ ++This folder contains the CKE4 plugin. +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/src/Plugin/CKEditorPlugin/VideoEmbedWysiwyg.php b/modules/video_embed_wysiwyg/src/Plugin/CKEditorPlugin/VideoEmbedWysiwyg.php +index 7cb37ea..6c84502 100644 +--- a/modules/video_embed_wysiwyg/src/Plugin/CKEditorPlugin/VideoEmbedWysiwyg.php ++++ b/modules/video_embed_wysiwyg/src/Plugin/CKEditorPlugin/VideoEmbedWysiwyg.php +@@ -11,7 +11,7 @@ use Drupal\editor\Entity\Editor; + use Drupal\video_embed_field\Plugin\Field\FieldFormatter\Video; + + /** +- * The media_entity plugin for video_embed_field. ++ * The CKE4 plugin for video_embed_field. + * + * @CKEditorPlugin( + * id = "video_embed", +diff --git a/modules/video_embed_wysiwyg/video_embed_wysiwyg.module b/modules/video_embed_wysiwyg/video_embed_wysiwyg.module +index a79ca60..2409951 100644 +--- a/modules/video_embed_wysiwyg/video_embed_wysiwyg.module ++++ b/modules/video_embed_wysiwyg/video_embed_wysiwyg.module +@@ -4,7 +4,6 @@ + * @file + * Module file for video_embed_wysiwyg. + * @todo CKE5 upgrade path for plugin config. +- * @todo Add a comment on code that runs only for CKE4. + */ + + use Drupal\editor\Entity\Editor; +@@ -17,6 +16,7 @@ define('VIDEO_EMBED_WYSIWYG_DOCUMENTATION_URL', 'https://www.drupal.org/node/280 + * Implements hook_ckeditor_css_alter(). + */ + function video_embed_wysiwyg_ckeditor_css_alter(array &$css, Editor $editor) { ++ // For CKE4. + $css[] = \Drupal::service('extension.list.module')->getPath('video_embed_wysiwyg') . '/plugin/plugin.css'; + } + +@@ -30,6 +30,7 @@ function video_embed_wysiwyg_form_filter_format_form_alter(&$form, $form_state, + + /** + * Validate callback to check if the filter and button are both enabled. ++ * For CKE4. + */ + function video_embed_wysiwyg_toolbar_filter_validate($form, FormStateInterface $form_state) { + $filter_enabled = !empty($form_state->getValue(['filters', 'video_embed_wysiwyg', 'status'])); +-- +GitLab + + +From b0e758544d13aab0175cac0ceb2473900838ecdd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ga=C3=ABlG?= +Date: Thu, 16 Mar 2023 17:39:13 +0100 +Subject: [PATCH 13/16] Upgrade path from CKE4 + +--- + .../Plugin/CKEditor4To5Upgrade/VideoEmbed.php | 66 +++++++++++++++++++ + .../video_embed_wysiwyg.module | 1 - + 2 files changed, 66 insertions(+), 1 deletion(-) + create mode 100644 modules/video_embed_wysiwyg/src/Plugin/CKEditor4To5Upgrade/VideoEmbed.php + +diff --git a/modules/video_embed_wysiwyg/src/Plugin/CKEditor4To5Upgrade/VideoEmbed.php b/modules/video_embed_wysiwyg/src/Plugin/CKEditor4To5Upgrade/VideoEmbed.php +new file mode 100644 +index 0000000..038c63f +--- /dev/null ++++ b/modules/video_embed_wysiwyg/src/Plugin/CKEditor4To5Upgrade/VideoEmbed.php +@@ -0,0 +1,66 @@ ++ $cke4_plugin_settings]; ++ ++ default: ++ throw new \OutOfBoundsException(); ++ } ++ } ++ ++ /** ++ * @inheritDoc ++ */ ++ public function computeCKEditor5PluginSubsetConfiguration(string $cke5_plugin_id, FilterFormatInterface $text_format): ?array { ++ throw new \OutOfBoundsException(); ++ } ++ ++} +\ No newline at end of file +diff --git a/modules/video_embed_wysiwyg/video_embed_wysiwyg.module b/modules/video_embed_wysiwyg/video_embed_wysiwyg.module +index 2409951..7c8c350 100644 +--- a/modules/video_embed_wysiwyg/video_embed_wysiwyg.module ++++ b/modules/video_embed_wysiwyg/video_embed_wysiwyg.module +@@ -3,7 +3,6 @@ + /** + * @file + * Module file for video_embed_wysiwyg. +- * @todo CKE5 upgrade path for plugin config. + */ + + use Drupal\editor\Entity\Editor; +-- +GitLab + + +From e97538c76e0731b2649a72ac7edf7fd1b88f1075 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ga=C3=ABl=20Gosset?= + <14850-gaelg@users.noreply.drupalcode.org> +Date: Thu, 16 Mar 2023 17:00:18 +0000 +Subject: [PATCH 14/16] Upgrade path sucessfully tested :) + +--- + .../src/Plugin/CKEditor4To5Upgrade/VideoEmbed.php | 4 +--- + 1 file changed, 1 insertion(+), 3 deletions(-) + +diff --git a/modules/video_embed_wysiwyg/src/Plugin/CKEditor4To5Upgrade/VideoEmbed.php b/modules/video_embed_wysiwyg/src/Plugin/CKEditor4To5Upgrade/VideoEmbed.php +index 038c63f..d9c9d90 100644 +--- a/modules/video_embed_wysiwyg/src/Plugin/CKEditor4To5Upgrade/VideoEmbed.php ++++ b/modules/video_embed_wysiwyg/src/Plugin/CKEditor4To5Upgrade/VideoEmbed.php +@@ -27,8 +27,6 @@ use Drupal\filter\FilterFormatInterface; + */ + class VideoEmbed extends PluginBase implements CKEditor4To5UpgradePluginInterface { + +- // @todo Test this upgrade path. +- + /** + * {@inheritdoc} + */ +@@ -63,4 +61,4 @@ class VideoEmbed extends PluginBase implements CKEditor4To5UpgradePluginInterfac + throw new \OutOfBoundsException(); + } + +-} +\ No newline at end of file ++} +-- +GitLab + + +From c58a73a53ab08b505cee98e26563ba1f30f72799 Mon Sep 17 00:00:00 2001 +From: Barbara Bombachini +Date: Fri, 19 May 2023 10:54:46 -0400 +Subject: [PATCH 15/16] Add default value to height and width as ckeditor was + erroring out with missing required field. + +--- + .../CKEditor5Plugin/VideoEmbedWysiwyg.php | 20 ++++++++++--------- + 1 file changed, 11 insertions(+), 9 deletions(-) + +diff --git a/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php b/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php +index 5335f2b..c97962e 100644 +--- a/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php ++++ b/modules/video_embed_wysiwyg/src/Plugin/CKEditor5Plugin/VideoEmbedWysiwyg.php +@@ -12,12 +12,15 @@ use Drupal\Core\Form\FormStateInterface; + use Drupal\editor\EditorInterface; + use Drupal\video_embed_field\Plugin\Field\FieldFormatter\Video; + ++/** ++ * CKEditor 5 VideoEmbedWysiwyg plugin configuration. ++ */ + class VideoEmbedWysiwyg extends CKEditor5PluginDefault implements CKEditor5PluginConfigurableInterface { + + use CKEditor5PluginConfigurableTrait; + + /** +- * @inheritDoc ++ * {@inheritDoc} + */ + public function getDynamicPluginConfig(array $static_plugin_config, EditorInterface $editor): array { + // Transmit some useful Drupal data to the javascript plugin. +@@ -32,7 +35,7 @@ class VideoEmbedWysiwyg extends CKEditor5PluginDefault implements CKEditor5Plugi + } + + /** +- * @inheritDoc ++ * {@inheritDoc} + */ + public function defaultConfiguration(): array { + return [ +@@ -40,15 +43,15 @@ class VideoEmbedWysiwyg extends CKEditor5PluginDefault implements CKEditor5Plugi + 'children' => [ + 'autoplay' => FALSE, + 'responsive' => FALSE, +- 'width' => '', +- 'height' => '', ++ 'width' => '42', ++ 'height' => '42', + ], + ], + ]; + } + + /** +- * @inheritDoc ++ * {@inheritDoc} + */ + public function buildConfigurationForm(array $form, FormStateInterface $form_state): array { + $form['defaults'] = [ +@@ -62,7 +65,7 @@ class VideoEmbedWysiwyg extends CKEditor5PluginDefault implements CKEditor5Plugi + } + + /** +- * @inheritDoc ++ * {@inheritDoc} + */ + public function validateConfigurationForm(array &$form, FormStateInterface $form_state): void { + $value = $form_state->getValue('defaults'); +@@ -72,11 +75,10 @@ class VideoEmbedWysiwyg extends CKEditor5PluginDefault implements CKEditor5Plugi + } + + /** +- * @inheritDoc ++ * {@inheritDoc} + */ + public function submitConfigurationForm(array &$form, FormStateInterface $form_state): void { + $this->configuration['defaults'] = $form_state->getValue('defaults'); + } + +- +-} +\ No newline at end of file ++} +-- +GitLab + + +From a55fb9e1d3fb8940954affaa00f76643d129fdd6 Mon Sep 17 00:00:00 2001 +From: Barbara Bombachini +Date: Fri, 19 May 2023 11:11:48 -0400 +Subject: [PATCH 16/16] Run webpack build and remove debug from file. + +--- + modules/video_embed_wysiwyg/js/build/videoEmbed.js | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/modules/video_embed_wysiwyg/js/build/videoEmbed.js b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +index 8958a01..d7fba87 100644 +--- a/modules/video_embed_wysiwyg/js/build/videoEmbed.js ++++ b/modules/video_embed_wysiwyg/js/build/videoEmbed.js +@@ -1 +1 @@ +-!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var __webpack_modules__={"./js/ckeditor5_plugins/videoEmbed/src/index.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony import */ var _videoembed__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembed */ "./js/ckeditor5_plugins/videoEmbed/src/videoembed.js");\n\n\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({\n VideoEmbed: _videoembed__WEBPACK_IMPORTED_MODULE_0__["default"],\n});\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/index.js?')},"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ InsertVideoEmbedCommand)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/**\n * @file defines InsertVideoEmbedCommand, which is executed when the videoEmbed\n * toolbar button is pressed.\n */\n\n\n\nclass InsertVideoEmbedCommand extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Command {\n execute(attributes) {\n const {model} = this.editor;\n\n model.change((writer) => {\n // Insert at the current selection position\n // in a way that will result in creating a valid model structure.\n model.insertContent(createVideoEmbed(writer, attributes));\n });\n }\n\n refresh() {\n const {model} = this.editor;\n const {selection} = model.document;\n\n // Determine if the cursor (selection) is in a position where adding a\n // videoEmbed is permitted. This is based on the schema of the model(s)\n // currently containing the cursor.\n const allowedIn = model.schema.findAllowedParent(\n selection.getFirstPosition(),\n 'videoEmbed',\n );\n\n // If the cursor is not in a location where a videoEmbed can be added,\n // return null so the addition doesn't happen.\n this.isEnabled = allowedIn !== null;\n }\n}\n\nfunction createVideoEmbed(writer, attributes) {\n // Create instances of the element registered with the editor in\n // videoembedediting.js.\n const videoEmbed = writer.createElement('videoEmbed', attributes);\n\n // Return the element to be added to the editor.\n return videoEmbed;\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembed.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (/* binding */ VideoEmbed)\n/* harmony export */ });\n/* harmony import */ var _videoembedediting__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./videoembedediting */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js");\n/* harmony import */ var _videoembedui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./videoembedui */ "./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js");\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ckeditor5/src/core */ "ckeditor5/src/core.js");\n\n\n\n\nclass VideoEmbed extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_2__.Plugin {\n\nstatic get requires() {\n return [_videoembedediting__WEBPACK_IMPORTED_MODULE_0__["default"], _videoembedui__WEBPACK_IMPORTED_MODULE_1__["default"]];\n }\n}\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembed.js?')},"./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedEditing)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/widget */ \"ckeditor5/src/widget.js\");\n/* harmony import */ var _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./insertvideoembedcommand */ \"./js/ckeditor5_plugins/videoEmbed/src/insertvideoembedcommand.js\");\n\n\n\n\n\n\n/**\n * CKEditor 5 plugins do not work directly with the DOM. They are defined as\n * plugin-specific data models that are then converted to markup that\n * is inserted in the DOM.\n *\n * CKEditor 5 internally interacts with videoEmbed as this model:\n * \n *\n * Which is converted in database (dataDowncast) as this:\n *

{\"preview_thumbnail\":\"/some/image/path.jpg\",\n * \"video_url\":\"https://some.video.url\",\"settings\":{\"responsive\":0or1,\"width\":\"42\",\"height\":\"42\",\"autoplay\":0or1}\",\n * settings_summary\":[\"Some help text.\"]}

\n *\n * The Drupal video_embed_wysiwyg format filter will then convert this into a\n * real HTML video embed, on PHP frontend rendering.\n *\n * videoEmbed model elements are also converted to HTML for preview in CKE5 UI\n * (editingDowncast).\n *\n * And the database markup can be converted back to model (upcast).\n *\n * This file has the logic for defining the videoEmbed model, and for how it is\n * converted from/to standard DOM markup for database/UI.\n */\nclass VideoEmbedEditing extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n static get requires() {\n return [ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.Widget];\n }\n\n init() {\n this._defineSchema();\n this._defineConverters();\n this.editor.commands.add(\n 'insertVideoEmbed',\n new _insertvideoembedcommand__WEBPACK_IMPORTED_MODULE_2__[\"default\"](this.editor),\n );\n }\n\n /*\n * This registers the structure that will be seen by CKEditor 5 as\n * \n *\n * The logic in _defineConverters() will determine how this is converted to\n * markup.\n */\n _defineSchema() {\n // Schemas are registered via the central `editor` object.\n const schema = this.editor.model.schema;\n\n\n schema.register('videoEmbed', {\n inheritAllFrom: '$blockObject',\n allowAttributes: ['videoUrl', 'responsive', 'width', 'height', 'autoplay', 'previewThumbnail', 'settingsSummary']\n });\n }\n\n /**\n * Converters determine how CKEditor 5 models are converted into markup and\n * vice-versa.\n */\n _defineConverters() {\n // Converters are registered via the central editor object.\n const {conversion} = this.editor;\n\n // Upcast Converters: determine how existing HTML is interpreted by the\n // editor. These trigger when an editor instance loads.\n //\n // If

{\"preview_thumbnail\":......}

is present in the existing markup\n // processed by CKEditor, then CKEditor recognizes and loads it as a\n // model.\n // @see\n // https://ckeditor.com/docs/ckeditor5/latest/api/module_engine_conversion_conversion-ConverterDefinition.html\n conversion.for('upcast').elementToElement({\n view: function (element) {\n if (element.name === 'p') {\n if (element.getChild(0).is('text')) {\n let text = element.getChild(0).data;\n if (text.match(/^({(?=.*preview_thumbnail\\b)(?=.*settings\\b)(?=.*video_url\\b)(?=.*settings_summary)(.*)})$/)) {\n return {name: true};\n }\n }\n }\n return null;\n },\n model: (viewElement, {writer}) => {\n let data = JSON.parse(viewElement.getChild(0).data);\n return writer.createElement('videoEmbed',\n {\n 'videoUrl': data.video_url,\n 'responsive': !!data.settings.responsive,\n 'width': data.settings.width,\n 'height': data.settings.height,\n 'autoplay': !!data.settings.autoplay,\n 'previewThumbnail': data.preview_thumbnail,\n 'settingsSummary': data.settings_summary[0],\n });\n },\n // Avoid it's converted to a normal paragraph.\n converterPriority: 'high'\n });\n\n\n // Data Downcast Converters: converts stored model data into HTML.\n // These trigger when content is saved.\n //\n // Instances of are saved as\n //

{\"preview_thumbnail\":......}

.\n conversion.for('dataDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const data = {};\n data.preview_thumbnail = modelElement.getAttribute('previewThumbnail');\n data.video_url = modelElement.getAttribute('videoUrl');\n data.settings = {};\n ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) {\n data.settings[attributeName] = modelElement.getAttribute(attributeName);\n });\n data.settings_summary = [modelElement.getAttribute('settingsSummary')];\n return writer.createContainerElement('p', {}, [writer.createText(JSON.stringify(data))]);\n }\n });\n\n\n // Editing Downcast Converters. These render the content to the user for\n // editing, i.e. this determines what gets seen in the editor. These trigger\n // after the Data Upcast Converters, and are re-triggered any time there\n // are changes to any of the models' properties.\n //\n // Convert the model into a container widget in the editor UI.\n conversion.for('editingDowncast').elementToElement({\n model: 'videoEmbed',\n view: (modelElement, {writer}) => {\n const preview = writer.createContainerElement('span', {class: 'video-embed-widget'}, [\n writer.createEmptyElement('img', {\n class: 'video-embed-widget__image',\n src: modelElement.getAttribute('previewThumbnail')\n }),\n writer.createContainerElement('span', {class: 'video-embed-widget__summary'}, [\n writer.createText(modelElement.getAttribute('settingsSummary'))\n ])\n ]);\n return (0,ckeditor5_src_widget__WEBPACK_IMPORTED_MODULE_1__.toWidget)(preview, writer, {label: Drupal.t('Video Embed')});\n }\n }\n );\n }\n}\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedediting.js?")},"./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ VideoEmbedUI)\n/* harmony export */ });\n/* harmony import */ var ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ckeditor5/src/core */ \"ckeditor5/src/core.js\");\n/* harmony import */ var ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ckeditor5/src/ui */ \"ckeditor5/src/ui.js\");\n/* harmony import */ var _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../../../icons/play-circle.svg */ \"./icons/play-circle.svg\");\n/**\n * @file registers the videoEmbed toolbar button and binds functionality to it.\n */\n\n\n\n\n/* @todo Choose the best icon and remove others. */\n\n\nclass VideoEmbedUI extends ckeditor5_src_core__WEBPACK_IMPORTED_MODULE_0__.Plugin {\n init() {\n const editor = this.editor;\n\n // This will register the videoEmbed toolbar button.\n editor.ui.componentFactory.add('videoEmbed', (locale) => {\n const command = editor.commands.get('insertVideoEmbed');\n const buttonView = new ckeditor5_src_ui__WEBPACK_IMPORTED_MODULE_1__.ButtonView(locale);\n\n // Create the toolbar button.\n buttonView.set({\n label: editor.t('Video Embed'),\n icon: _icons_play_circle_svg__WEBPACK_IMPORTED_MODULE_2__[\"default\"],\n tooltip: true,\n });\n\n // Bind the state of the button to the command.\n buttonView.bind('isOn', 'isEnabled').to(command, 'value', 'isEnabled');\n\n // Execute the command when the button is clicked (executed).\n this.listenTo(buttonView, 'execute', () => {\n this.openEditingDialog();\n }\n );\n\n return buttonView;\n });\n }\n\n /**\n * Opens video embed form when the editing button is clicked.\n */\n openEditingDialog() {\n const {editor} = this;\n\n // If the selected element while we click the button is an instance\n // of the video_embed widget, extract its values so they can be\n // sent to the server to prime the configuration form.\n let existingValues = {settings: {}};\n const selectedVideoEmbedElement = editor.model.document.selection.getSelectedElement();\n if (selectedVideoEmbedElement) {\n if (selectedVideoEmbedElement.hasAttribute('videoUrl')) {\n existingValues.video_url = selectedVideoEmbedElement.getAttribute('videoUrl');\n }\n ['responsive', 'width', 'height', 'autoplay'].forEach(function (attributeName) {\n if (selectedVideoEmbedElement.hasAttribute(attributeName)) {\n existingValues.settings[attributeName] = selectedVideoEmbedElement.getAttribute(attributeName);\n }\n });\n }\n this._openDialog(\n Drupal.url('video-embed-wysiwyg/dialog/' + editor.config.get('videoEmbed').format),\n existingValues,\n (newValues) => {\n\n const attributes = {\n videoUrl: newValues.video_url,\n responsive: newValues.settings.responsive,\n width: newValues.settings.width,\n height: newValues.settings.height,\n autoplay: newValues.settings.autoplay,\n // These attributes are useful only for editor preview, but are\n // keeped on dataDowncast so that they can be retrieved on later\n // upcast+editingDowncast.\n settingsSummary: newValues.settings_summary[0],\n previewThumbnail: newValues.preview_thumbnail,\n }\n editor.execute('insertVideoEmbed', attributes);\n },\n {\n title: Drupal.t('Video Embed'),\n dialogClass: 'video-embed-dialog'\n }\n );\n }\n\n /**\n * This method is adapted from drupal's ckeditor5.js file due to an issue\n * where the \"editor_object\" isn't passed to the ajax request.\n *\n * See https://www.drupal.org/project/drupal/issues/3303191\n *\n * @param {string} url\n * The URL that contains the contents of the dialog.\n * @param {object} existingValues\n * Existing values that will be sent via POST to the url for the dialog\n * contents.\n * @param {function} saveCallback\n * A function to be called upon saving the dialog.\n * @param {object} dialogSettings\n * An object containing settings to be passed to the jQuery UI.\n */\n _openDialog(url, existingValues, saveCallback, dialogSettings = {}) {\n // Add a consistent dialog class.\n const classes = dialogSettings.dialogClass\n ? dialogSettings.dialogClass.split(' ')\n : [];\n classes.push('ui-dialog--narrow');\n dialogSettings.dialogClass = classes.join(' ');\n dialogSettings.autoResize =\n window.matchMedia('(min-width: 600px)').matches;\n dialogSettings.width = 'auto';\n\n const ckeditorAjaxDialog = Drupal.ajax({\n dialog: dialogSettings,\n dialogType: 'modal',\n selector: '.ckeditor5-dialog-loading-link',\n url,\n progress: {type: 'fullscreen'},\n submit: {\n editor_object: existingValues,\n },\n });\n ckeditorAjaxDialog.execute();\n\n // Store the save callback to be executed when this dialog is closed.\n Drupal.ckeditor5.saveCallback = saveCallback;\n }\n\n}\n\n\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./js/ckeditor5_plugins/videoEmbed/src/videoembedui.js?")},"./icons/play-circle.svg":(__unused_webpack_module,__webpack_exports__,__webpack_require__)=>{"use strict";eval('__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)\n/* harmony export */ });\n/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ("\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/./icons/play-circle.svg?')},"ckeditor5/src/core.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/core.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./core.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/ui.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/ui.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./ui.js_from_dll-reference_CKEditor5.dll?')},"ckeditor5/src/widget.js":(module,__unused_webpack_exports,__webpack_require__)=>{eval('module.exports = (__webpack_require__(/*! dll-reference CKEditor5.dll */ "dll-reference CKEditor5.dll"))("./src/widget.js");\n\n//# sourceURL=webpack://CKEditor5.videoEmbed/delegated_./widget.js_from_dll-reference_CKEditor5.dll?')},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},__webpack_module_cache__={};function __webpack_require__(e){var t=__webpack_module_cache__[e];if(void 0!==t)return t.exports;var n=__webpack_module_cache__[e]={exports:{}};return __webpack_modules__[e](n,n.exports,__webpack_require__),n.exports}__webpack_require__.d=(e,t)=>{for(var n in t)__webpack_require__.o(t,n)&&!__webpack_require__.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},__webpack_require__.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),__webpack_require__.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})};var __webpack_exports__=__webpack_require__("./js/ckeditor5_plugins/videoEmbed/src/index.js");return __webpack_exports__=__webpack_exports__.default,__webpack_exports__})())); +\ No newline at end of file ++!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.CKEditor5=t():(e.CKEditor5=e.CKEditor5||{},e.CKEditor5.videoEmbed=t())}(self,(()=>(()=>{var e={"ckeditor5/src/core.js":(e,t,i)=>{e.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/ui.js":(e,t,i)=>{e.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/widget.js":(e,t,i)=>{e.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":e=>{"use strict";e.exports=CKEditor5.dll}},t={};function i(o){var s=t[o];if(void 0!==s)return s.exports;var r=t[o]={exports:{}};return e[o](r,r.exports,i),r.exports}i.d=(e,t)=>{for(var o in t)i.o(t,o)&&!i.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var o={};return(()=>{"use strict";i.d(o,{default:()=>a});var e=i("ckeditor5/src/core.js"),t=i("ckeditor5/src/widget.js");class s extends e.Command{execute(e){const{model:t}=this.editor;t.change((i=>{t.insertContent(function(e,t){return e.createElement("videoEmbed",t)}(i,e))}))}refresh(){const{model:e}=this.editor,{selection:t}=e.document,i=e.schema.findAllowedParent(t.getFirstPosition(),"videoEmbed");this.isEnabled=null!==i}}class r extends e.Plugin{static get requires(){return[t.Widget]}init(){this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertVideoEmbed",new s(this.editor))}_defineSchema(){this.editor.model.schema.register("videoEmbed",{inheritAllFrom:"$blockObject",allowAttributes:["videoUrl","responsive","width","height","autoplay","previewThumbnail","settingsSummary"]})}_defineConverters(){const{conversion:e}=this.editor;e.for("upcast").elementToElement({view:function(e){if("p"===e.name&&e.getChild(0).is("text")){if(e.getChild(0).data.match(/^({(?=.*preview_thumbnail\b)(?=.*settings\b)(?=.*video_url\b)(?=.*settings_summary)(.*)})$/))return{name:!0}}return null},model:(e,{writer:t})=>{let i=JSON.parse(e.getChild(0).data);return t.createElement("videoEmbed",{videoUrl:i.video_url,responsive:!!i.settings.responsive,width:i.settings.width,height:i.settings.height,autoplay:!!i.settings.autoplay,previewThumbnail:i.preview_thumbnail,settingsSummary:i.settings_summary[0]})},converterPriority:"high"}),e.for("dataDowncast").elementToElement({model:"videoEmbed",view:(e,{writer:t})=>{const i={};return i.preview_thumbnail=e.getAttribute("previewThumbnail"),i.video_url=e.getAttribute("videoUrl"),i.settings={},["responsive","width","height","autoplay"].forEach((function(t){i.settings[t]=e.getAttribute(t)})),i.settings_summary=[e.getAttribute("settingsSummary")],t.createContainerElement("p",{},[t.createText(JSON.stringify(i))])}}),e.for("editingDowncast").elementToElement({model:"videoEmbed",view:(e,{writer:i})=>{const o=i.createContainerElement("span",{class:"video-embed-widget"},[i.createEmptyElement("img",{class:"video-embed-widget__image",src:e.getAttribute("previewThumbnail")}),i.createContainerElement("span",{class:"video-embed-widget__summary"},[i.createText(e.getAttribute("settingsSummary"))])]);return(0,t.toWidget)(o,i,{label:Drupal.t("Video Embed")})}})}}var n=i("ckeditor5/src/ui.js");class d extends e.Plugin{init(){const e=this.editor;e.ui.componentFactory.add("videoEmbed",(t=>{const i=e.commands.get("insertVideoEmbed"),o=new n.ButtonView(t);return o.set({label:e.t("Video Embed"),icon:'\x3c!-- Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) --\x3e',tooltip:!0}),o.bind("isOn","isEnabled").to(i,"value","isEnabled"),this.listenTo(o,"execute",(()=>{this.openEditingDialog()})),o}))}openEditingDialog(){const{editor:e}=this;let t={settings:{}};const i=e.model.document.selection.getSelectedElement();i&&(i.hasAttribute("videoUrl")&&(t.video_url=i.getAttribute("videoUrl")),["responsive","width","height","autoplay"].forEach((function(e){i.hasAttribute(e)&&(t.settings[e]=i.getAttribute(e))}))),this._openDialog(Drupal.url("video-embed-wysiwyg/dialog/"+e.config.get("videoEmbed").format),t,(t=>{const i={videoUrl:t.video_url,responsive:t.settings.responsive,width:t.settings.width,height:t.settings.height,autoplay:t.settings.autoplay,settingsSummary:t.settings_summary[0],previewThumbnail:t.preview_thumbnail};e.execute("insertVideoEmbed",i)}),{title:Drupal.t("Video Embed"),dialogClass:"video-embed-dialog"})}_openDialog(e,t,i,o={}){const s=o.dialogClass?o.dialogClass.split(" "):[];s.push("ui-dialog--narrow"),o.dialogClass=s.join(" "),o.autoResize=window.matchMedia("(min-width: 600px)").matches,o.width="auto";Drupal.ajax({dialog:o,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:e,progress:{type:"fullscreen"},submit:{editor_object:t}}).execute(),Drupal.ckeditor5.saveCallback=i}}class l extends e.Plugin{static get requires(){return[r,d]}}const a={VideoEmbed:l}})(),o=o.default})())); +\ No newline at end of file +-- +GitLab + From a30eb86c7d9cabebb7155321b75658603a126935 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Fri, 9 Jun 2023 14:44:07 +1000 Subject: [PATCH 58/79] release/3.2.12 --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 629b2f0..1adb74d 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.11", "dpc-sdp/tide_authenticated_content": "3.0.8", - "dpc-sdp/tide_core": "3.2.9", + "dpc-sdp/tide_core": "3.2.10", "dpc-sdp/tide_demo_content": "3.0.12", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", From 361584f721b0ead9d2d9ffdd9e843564e05cfb33 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Tue, 13 Jun 2023 15:56:57 +1000 Subject: [PATCH 59/79] Update `tide_webform` version to `3.0.12` --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 1adb74d..b3664e2 100644 --- a/composer.json +++ b/composer.json @@ -22,7 +22,7 @@ "dpc-sdp/tide_search": "3.0.8", "dpc-sdp/tide_site": "3.0.15", "dpc-sdp/tide_test": "3.0.2", - "dpc-sdp/tide_webform": "3.0.11" + "dpc-sdp/tide_webform": "3.0.12" }, "repositories": { "drupal": { From d8afe5a31ed9fd9b4a9e34a12be6f27ca3adde20 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Wed, 28 Jun 2023 15:39:31 +1000 Subject: [PATCH 60/79] Update tide modules * "dpc-sdp/tide_core": "3.2.11", * "dpc-sdp/tide_landing_page": "3.0.15", * "dpc-sdp/tide_news": "3.0.5", * "dpc-sdp/tide_search": "3.0.9", * "dpc-sdp/tide_webform": "3.0.13" --- composer.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/composer.json b/composer.json index b3664e2..3125978 100644 --- a/composer.json +++ b/composer.json @@ -7,22 +7,22 @@ "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.11", "dpc-sdp/tide_authenticated_content": "3.0.8", - "dpc-sdp/tide_core": "3.2.10", + "dpc-sdp/tide_core": "3.2.11", "dpc-sdp/tide_demo_content": "3.0.12", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", "dpc-sdp/tide_grant": "3.0.4", - "dpc-sdp/tide_landing_page": "3.0.14", + "dpc-sdp/tide_landing_page": "3.0.15", "dpc-sdp/tide_media": "3.0.12", "dpc-sdp/tide_monsido": "3.0.1", - "dpc-sdp/tide_news": "3.0.4", + "dpc-sdp/tide_news": "3.0.5", "dpc-sdp/tide_page": "3.0.3", "dpc-sdp/tide_profile": "3.0.1", "dpc-sdp/tide_publication": "3.0.4", - "dpc-sdp/tide_search": "3.0.8", + "dpc-sdp/tide_search": "3.0.9", "dpc-sdp/tide_site": "3.0.15", "dpc-sdp/tide_test": "3.0.2", - "dpc-sdp/tide_webform": "3.0.12" + "dpc-sdp/tide_webform": "3.0.13" }, "repositories": { "drupal": { From fb84207165c931869af4b16453b17a436a72bf8a Mon Sep 17 00:00:00 2001 From: Ming Date: Fri, 30 Jun 2023 12:13:34 +1000 Subject: [PATCH 61/79] [DDS-1474] Bump tide_core (#199) --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 3125978..1c99b66 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.11", "dpc-sdp/tide_authenticated_content": "3.0.8", - "dpc-sdp/tide_core": "3.2.11", + "dpc-sdp/tide_core": "3.2.12", "dpc-sdp/tide_demo_content": "3.0.12", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", From 4dce47bc4de5b037ea66dbc43d4ee1fc4b324f5d Mon Sep 17 00:00:00 2001 From: Anthony Malkoun Date: Mon, 10 Jul 2023 10:35:48 +1000 Subject: [PATCH 62/79] Bump tide_api to fix JSON:API returning wrong revision detail --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 1c99b66..281704d 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.2", - "dpc-sdp/tide_api": "3.0.11", + "dpc-sdp/tide_api": "3.0.12", "dpc-sdp/tide_authenticated_content": "3.0.8", "dpc-sdp/tide_core": "3.2.12", "dpc-sdp/tide_demo_content": "3.0.12", From 16037f28558eb3ccb506eb4dc20fb7a81dbd6bfd Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Tue, 18 Jul 2023 19:29:26 +1000 Subject: [PATCH 63/79] [hotfix/1.45.2] Updated tide_core and tide_webform. --- composer.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/composer.json b/composer.json index 281704d..358c234 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.12", "dpc-sdp/tide_authenticated_content": "3.0.8", - "dpc-sdp/tide_core": "3.2.12", + "dpc-sdp/tide_core": "3.2.13", "dpc-sdp/tide_demo_content": "3.0.12", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", @@ -22,7 +22,7 @@ "dpc-sdp/tide_search": "3.0.9", "dpc-sdp/tide_site": "3.0.15", "dpc-sdp/tide_test": "3.0.2", - "dpc-sdp/tide_webform": "3.0.13" + "dpc-sdp/tide_webform": "3.0.14" }, "repositories": { "drupal": { From 2f315a8c0b09c42c5c8ac64c8d5d146f9ef6bd6f Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Fri, 28 Jul 2023 12:27:23 +1000 Subject: [PATCH 64/79] Update `tide_demo_content` to `v3.0.13` --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 358c234..6fc8fdc 100644 --- a/composer.json +++ b/composer.json @@ -8,7 +8,7 @@ "dpc-sdp/tide_api": "3.0.12", "dpc-sdp/tide_authenticated_content": "3.0.8", "dpc-sdp/tide_core": "3.2.13", - "dpc-sdp/tide_demo_content": "3.0.12", + "dpc-sdp/tide_demo_content": "3.0.13", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", "dpc-sdp/tide_grant": "3.0.4", From 3895ea2b04fa1d8b02e3dd79577bfd130129469f Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Fri, 28 Jul 2023 12:48:25 +1000 Subject: [PATCH 65/79] release/3.2.18 (#201) From 60e5c958606317754aa9d090127ae6c9efc01b11 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Tue, 22 Aug 2023 00:04:52 +1000 Subject: [PATCH 66/79] Update tide package versions * tide_api: 3.0.13 * tide_core: 3.2.14 * tide_grant: 3.0.5 * tide_landing_page: 3.0.16 * tide_media: 3.0.13 * tide_publication: 3.0.5 * tide_search: 3.0.10 * tide_site: 3.0.16 --- composer.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/composer.json b/composer.json index 6fc8fdc..78396ce 100644 --- a/composer.json +++ b/composer.json @@ -5,22 +5,22 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.2", - "dpc-sdp/tide_api": "3.0.12", + "dpc-sdp/tide_api": "3.0.13", "dpc-sdp/tide_authenticated_content": "3.0.8", - "dpc-sdp/tide_core": "3.2.13", + "dpc-sdp/tide_core": "3.2.14", "dpc-sdp/tide_demo_content": "3.0.13", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", - "dpc-sdp/tide_grant": "3.0.4", - "dpc-sdp/tide_landing_page": "3.0.15", - "dpc-sdp/tide_media": "3.0.12", + "dpc-sdp/tide_grant": "3.0.5", + "dpc-sdp/tide_landing_page": "3.0.16", + "dpc-sdp/tide_media": "3.0.13", "dpc-sdp/tide_monsido": "3.0.1", "dpc-sdp/tide_news": "3.0.5", "dpc-sdp/tide_page": "3.0.3", "dpc-sdp/tide_profile": "3.0.1", - "dpc-sdp/tide_publication": "3.0.4", - "dpc-sdp/tide_search": "3.0.9", - "dpc-sdp/tide_site": "3.0.15", + "dpc-sdp/tide_publication": "3.0.5", + "dpc-sdp/tide_search": "3.0.10", + "dpc-sdp/tide_site": "3.0.16", "dpc-sdp/tide_test": "3.0.2", "dpc-sdp/tide_webform": "3.0.14" }, From b15794836b9151840ac45749bda4802f3424622c Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Thu, 24 Aug 2023 13:33:45 +1000 Subject: [PATCH 67/79] [release/3.2.20] Updated tide api. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 78396ce..644575a 100644 --- a/composer.json +++ b/composer.json @@ -5,7 +5,7 @@ "license": "GPL-2.0-or-later", "require": { "dpc-sdp/tide_alert": "3.0.2", - "dpc-sdp/tide_api": "3.0.13", + "dpc-sdp/tide_api": "3.0.14", "dpc-sdp/tide_authenticated_content": "3.0.8", "dpc-sdp/tide_core": "3.2.14", "dpc-sdp/tide_demo_content": "3.0.13", From e31626f1be97f62cdb90cf47ca0a6b457ef52fbb Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Mon, 28 Aug 2023 09:57:21 +1000 Subject: [PATCH 68/79] Update `tide_search` version to `3.0.10` --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 644575a..9049ee6 100644 --- a/composer.json +++ b/composer.json @@ -19,7 +19,7 @@ "dpc-sdp/tide_page": "3.0.3", "dpc-sdp/tide_profile": "3.0.1", "dpc-sdp/tide_publication": "3.0.5", - "dpc-sdp/tide_search": "3.0.10", + "dpc-sdp/tide_search": "3.0.11", "dpc-sdp/tide_site": "3.0.16", "dpc-sdp/tide_test": "3.0.2", "dpc-sdp/tide_webform": "3.0.14" From eb5f247cee4ecad81ee9c37e3b7d1c567b0e2448 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Tue, 10 Oct 2023 12:37:11 +1100 Subject: [PATCH 69/79] Update `tide_core` to `3.2.15` --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9049ee6..ebf4db1 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.14", "dpc-sdp/tide_authenticated_content": "3.0.8", - "dpc-sdp/tide_core": "3.2.14", + "dpc-sdp/tide_core": "3.2.15", "dpc-sdp/tide_demo_content": "3.0.13", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", From 827ba0aadb84e026ccffb6d48b0e1c55bbb73448 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Thu, 26 Oct 2023 10:34:35 +1100 Subject: [PATCH 70/79] Update `tide_media` version to `3.0.14-p1` --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index ebf4db1..17ae492 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "dpc-sdp/tide_event_atdw": "3.0.1", "dpc-sdp/tide_grant": "3.0.5", "dpc-sdp/tide_landing_page": "3.0.16", - "dpc-sdp/tide_media": "3.0.13", + "dpc-sdp/tide_media": "3.0.14-p1", "dpc-sdp/tide_monsido": "3.0.1", "dpc-sdp/tide_news": "3.0.5", "dpc-sdp/tide_page": "3.0.3", From c355e150b07d0d27b2d7f1a70a08a68e3dcf5865 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Thu, 26 Oct 2023 11:43:05 +1100 Subject: [PATCH 71/79] Update `tide_core` to `3.2.16-p1` --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 17ae492..8b8d040 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.14", "dpc-sdp/tide_authenticated_content": "3.0.8", - "dpc-sdp/tide_core": "3.2.15", + "dpc-sdp/tide_core": "3.2.16-p1", "dpc-sdp/tide_demo_content": "3.0.13", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", From 74b35efaab5ba3dd49c7d38f2841cfe796928055 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Thu, 26 Oct 2023 13:48:21 +1100 Subject: [PATCH 72/79] Revert "Update `tide_core` to `3.2.16-p1`" This reverts commit c355e150b07d0d27b2d7f1a70a08a68e3dcf5865. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 8b8d040..17ae492 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.14", "dpc-sdp/tide_authenticated_content": "3.0.8", - "dpc-sdp/tide_core": "3.2.16-p1", + "dpc-sdp/tide_core": "3.2.15", "dpc-sdp/tide_demo_content": "3.0.13", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", From 566ffd81e1d0feeb3bdfcf4b253c101466586324 Mon Sep 17 00:00:00 2001 From: Mayur Gondhkar Date: Thu, 26 Oct 2023 15:06:33 +1100 Subject: [PATCH 73/79] Update `tide_core` to `3.2.15-p1` --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 17ae492..41330af 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.14", "dpc-sdp/tide_authenticated_content": "3.0.8", - "dpc-sdp/tide_core": "3.2.15", + "dpc-sdp/tide_core": "3.2.15-p1", "dpc-sdp/tide_demo_content": "3.0.13", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", From dd7d76bd131f6aeb76593838cc56627aa732b464 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Wed, 1 Nov 2023 09:53:07 +1100 Subject: [PATCH 74/79] release/3.2.24 --- composer.json | 2 +- .../3396133-ckeditor-5-interface_26.patch | 122 ++++++++++++++++++ 2 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 patches/entity_embed/3396133-ckeditor-5-interface_26.patch diff --git a/composer.json b/composer.json index 41330af..6a3b306 100644 --- a/composer.json +++ b/composer.json @@ -7,7 +7,7 @@ "dpc-sdp/tide_alert": "3.0.2", "dpc-sdp/tide_api": "3.0.14", "dpc-sdp/tide_authenticated_content": "3.0.8", - "dpc-sdp/tide_core": "3.2.15-p1", + "dpc-sdp/tide_core": "3.2.15-p2", "dpc-sdp/tide_demo_content": "3.0.13", "dpc-sdp/tide_event": "3.0.4", "dpc-sdp/tide_event_atdw": "3.0.1", diff --git a/patches/entity_embed/3396133-ckeditor-5-interface_26.patch b/patches/entity_embed/3396133-ckeditor-5-interface_26.patch new file mode 100644 index 0000000..e3a32fd --- /dev/null +++ b/patches/entity_embed/3396133-ckeditor-5-interface_26.patch @@ -0,0 +1,122 @@ + From 91633515fac9ef6db5c141451d97986b30c25f47 Mon Sep 17 00:00:00 2001 +From: bnjmnm +Date: Tue, 24 Oct 2023 15:29:18 -0400 +Subject: [PATCH 1/3] check for attribute existience before using them + +--- + js/build/drupalentity.js | 2 +- + js/ckeditor5_plugins/drupalentity/src/toolbar.js | 6 ++++++ + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/js/build/drupalentity.js b/js/build/drupalentity.js +index 4a151d7..37bdb23 100644 +--- a/js/build/drupalentity.js ++++ b/js/build/drupalentity.js +@@ -1 +1 @@ +-!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement(),o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); +\ No newline at end of file ++!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();n.hasAttribute("drupalEntityEntityUuid")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),n.hasAttribute("drupalEntityEntityType")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type."));const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); +\ No newline at end of file +diff --git a/js/ckeditor5_plugins/drupalentity/src/toolbar.js b/js/ckeditor5_plugins/drupalentity/src/toolbar.js +index 1541fcc..1413b57 100644 +--- a/js/ckeditor5_plugins/drupalentity/src/toolbar.js ++++ b/js/ckeditor5_plugins/drupalentity/src/toolbar.js +@@ -60,6 +60,12 @@ export default class EntityEmbedToolbar extends Plugin { + editor.ui.componentFactory.add('editEmbeddedEntity', (locale) => { + const button = new ButtonView(locale); + const element = editor.model.document.selection.getSelectedElement(); ++ if (!element.hasAttribute('drupalEntityEntityUuid')) { ++ console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-uuid.')) ++ } ++ if (!element.hasAttribute('drupalEntityEntityType')) { ++ console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-type.')) ++ } + const uuid = element.getAttribute('drupalEntityEntityUuid'); + const type = element.getAttribute('drupalEntityEntityType'); + const editUrl = Drupal.url(`entity-embed/edit-embedded/${type}/${uuid}`) +-- +GitLab + + +From fa9277e5cfaa41fff56944f58d0ef7686c5963af Mon Sep 17 00:00:00 2001 +From: bnjmnm +Date: Tue, 24 Oct 2023 15:37:11 -0400 +Subject: [PATCH 2/3] return early if no selected element + +--- + js/build/drupalentity.js | 2 +- + js/ckeditor5_plugins/drupalentity/src/toolbar.js | 3 +++ + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/js/build/drupalentity.js b/js/build/drupalentity.js +index 37bdb23..52a33de 100644 +--- a/js/build/drupalentity.js ++++ b/js/build/drupalentity.js +@@ -1 +1 @@ +-!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();n.hasAttribute("drupalEntityEntityUuid")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),n.hasAttribute("drupalEntityEntityType")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type."));const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); +\ No newline at end of file ++!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();if(!n)return;n.hasAttribute("drupalEntityEntityUuid")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),n.hasAttribute("drupalEntityEntityType")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type."));const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); +\ No newline at end of file +diff --git a/js/ckeditor5_plugins/drupalentity/src/toolbar.js b/js/ckeditor5_plugins/drupalentity/src/toolbar.js +index 1413b57..c8e9673 100644 +--- a/js/ckeditor5_plugins/drupalentity/src/toolbar.js ++++ b/js/ckeditor5_plugins/drupalentity/src/toolbar.js +@@ -60,6 +60,9 @@ export default class EntityEmbedToolbar extends Plugin { + editor.ui.componentFactory.add('editEmbeddedEntity', (locale) => { + const button = new ButtonView(locale); + const element = editor.model.document.selection.getSelectedElement(); ++ if (!element) { ++ return; ++ } + if (!element.hasAttribute('drupalEntityEntityUuid')) { + console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-uuid.')) + } +-- +GitLab + + +From 1cf7eae7239c19d56f0afb4b98f86aa14085f39a Mon Sep 17 00:00:00 2001 +From: bnjmnm +Date: Tue, 24 Oct 2023 15:38:58 -0400 +Subject: [PATCH 3/3] return null if any essential is unavailable + +--- + js/build/drupalentity.js | 2 +- + js/ckeditor5_plugins/drupalentity/src/toolbar.js | 8 +++++--- + 2 files changed, 6 insertions(+), 4 deletions(-) + +diff --git a/js/build/drupalentity.js b/js/build/drupalentity.js +index 52a33de..273ea45 100644 +--- a/js/build/drupalentity.js ++++ b/js/build/drupalentity.js +@@ -1 +1 @@ +-!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();if(!n)return;n.hasAttribute("drupalEntityEntityUuid")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),n.hasAttribute("drupalEntityEntityType")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type."));const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); +\ No newline at end of file ++!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();if(!n)return null;if(!n.hasAttribute("drupalEntityEntityUuid"))return console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),null;if(!n.hasAttribute("drupalEntityEntityType"))return console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type.")),null;const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class f extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class w extends t.Plugin{static get requires(){return[o,l,s,c,f]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:w}})(),r=r.default})())); +\ No newline at end of file +diff --git a/js/ckeditor5_plugins/drupalentity/src/toolbar.js b/js/ckeditor5_plugins/drupalentity/src/toolbar.js +index c8e9673..ef9ea7f 100644 +--- a/js/ckeditor5_plugins/drupalentity/src/toolbar.js ++++ b/js/ckeditor5_plugins/drupalentity/src/toolbar.js +@@ -61,13 +61,15 @@ export default class EntityEmbedToolbar extends Plugin { + const button = new ButtonView(locale); + const element = editor.model.document.selection.getSelectedElement(); + if (!element) { +- return; ++ return null; + } + if (!element.hasAttribute('drupalEntityEntityUuid')) { +- console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-uuid.')) ++ console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-uuid.')); ++ return null; + } + if (!element.hasAttribute('drupalEntityEntityType')) { +- console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-type.')) ++ console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-type.')); ++ return null; + } + const uuid = element.getAttribute('drupalEntityEntityUuid'); + const type = element.getAttribute('drupalEntityEntityType'); +-- +GitLab + From 4c449a9a05e9a12e105e35b6e35648b537c225e8 Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Mon, 20 Nov 2023 15:19:53 +1100 Subject: [PATCH 75/79] [SRM-982] Updated profile to be compatible with drupal 10. (#202) * [SRM-982] Updated profile to be compatible with drupal 10. --- composer.json | 38 +++--- .../3396133-ckeditor-5-interface_26.patch | 122 ------------------ tide.info.yml | 3 +- 3 files changed, 18 insertions(+), 145 deletions(-) delete mode 100644 patches/entity_embed/3396133-ckeditor-5-interface_26.patch diff --git a/composer.json b/composer.json index 6a3b306..33561f2 100644 --- a/composer.json +++ b/composer.json @@ -1,33 +1,29 @@ { "name": "dpc-sdp/tide", - "description": "Tide Drupal 9 profile", + "description": "Tide Drupal 10 profile", "type": "drupal-profile", "license": "GPL-2.0-or-later", "require": { - "dpc-sdp/tide_alert": "3.0.2", - "dpc-sdp/tide_api": "3.0.14", - "dpc-sdp/tide_authenticated_content": "3.0.8", - "dpc-sdp/tide_core": "3.2.15-p2", - "dpc-sdp/tide_demo_content": "3.0.13", - "dpc-sdp/tide_event": "3.0.4", - "dpc-sdp/tide_event_atdw": "3.0.1", - "dpc-sdp/tide_grant": "3.0.5", - "dpc-sdp/tide_landing_page": "3.0.16", - "dpc-sdp/tide_media": "3.0.14-p1", - "dpc-sdp/tide_monsido": "3.0.1", - "dpc-sdp/tide_news": "3.0.5", - "dpc-sdp/tide_page": "3.0.3", - "dpc-sdp/tide_profile": "3.0.1", - "dpc-sdp/tide_publication": "3.0.5", - "dpc-sdp/tide_search": "3.0.11", - "dpc-sdp/tide_site": "3.0.16", - "dpc-sdp/tide_test": "3.0.2", - "dpc-sdp/tide_webform": "3.0.14" + "dpc-sdp/tide_alert": "4.0.0", + "dpc-sdp/tide_api": "4.0.0", + "dpc-sdp/tide_core": "4.0.0", + "dpc-sdp/tide_demo_content": "4.0.0", + "dpc-sdp/tide_event": "4.0.0", + "dpc-sdp/tide_grant": "4.0.0", + "dpc-sdp/tide_landing_page": "4.0.0", + "dpc-sdp/tide_media": "4.0.0", + "dpc-sdp/tide_news": "4.0.0", + "dpc-sdp/tide_profile": "4.0.0", + "dpc-sdp/tide_publication": "4.0.0", + "dpc-sdp/tide_search": "4.0.0", + "dpc-sdp/tide_site": "4.0.0", + "dpc-sdp/tide_test": "4.0.0", + "dpc-sdp/tide_webform": "4.0.0" }, "repositories": { "drupal": { "type": "composer", - "url": "https://packages.drupal.org/9" + "url": "https://packages.drupal.org/10" }, "asset-packagist": { "type": "composer", diff --git a/patches/entity_embed/3396133-ckeditor-5-interface_26.patch b/patches/entity_embed/3396133-ckeditor-5-interface_26.patch deleted file mode 100644 index e3a32fd..0000000 --- a/patches/entity_embed/3396133-ckeditor-5-interface_26.patch +++ /dev/null @@ -1,122 +0,0 @@ - From 91633515fac9ef6db5c141451d97986b30c25f47 Mon Sep 17 00:00:00 2001 -From: bnjmnm -Date: Tue, 24 Oct 2023 15:29:18 -0400 -Subject: [PATCH 1/3] check for attribute existience before using them - ---- - js/build/drupalentity.js | 2 +- - js/ckeditor5_plugins/drupalentity/src/toolbar.js | 6 ++++++ - 2 files changed, 7 insertions(+), 1 deletion(-) - -diff --git a/js/build/drupalentity.js b/js/build/drupalentity.js -index 4a151d7..37bdb23 100644 ---- a/js/build/drupalentity.js -+++ b/js/build/drupalentity.js -@@ -1 +1 @@ --!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement(),o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); -\ No newline at end of file -+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();n.hasAttribute("drupalEntityEntityUuid")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),n.hasAttribute("drupalEntityEntityType")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type."));const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); -\ No newline at end of file -diff --git a/js/ckeditor5_plugins/drupalentity/src/toolbar.js b/js/ckeditor5_plugins/drupalentity/src/toolbar.js -index 1541fcc..1413b57 100644 ---- a/js/ckeditor5_plugins/drupalentity/src/toolbar.js -+++ b/js/ckeditor5_plugins/drupalentity/src/toolbar.js -@@ -60,6 +60,12 @@ export default class EntityEmbedToolbar extends Plugin { - editor.ui.componentFactory.add('editEmbeddedEntity', (locale) => { - const button = new ButtonView(locale); - const element = editor.model.document.selection.getSelectedElement(); -+ if (!element.hasAttribute('drupalEntityEntityUuid')) { -+ console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-uuid.')) -+ } -+ if (!element.hasAttribute('drupalEntityEntityType')) { -+ console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-type.')) -+ } - const uuid = element.getAttribute('drupalEntityEntityUuid'); - const type = element.getAttribute('drupalEntityEntityType'); - const editUrl = Drupal.url(`entity-embed/edit-embedded/${type}/${uuid}`) --- -GitLab - - -From fa9277e5cfaa41fff56944f58d0ef7686c5963af Mon Sep 17 00:00:00 2001 -From: bnjmnm -Date: Tue, 24 Oct 2023 15:37:11 -0400 -Subject: [PATCH 2/3] return early if no selected element - ---- - js/build/drupalentity.js | 2 +- - js/ckeditor5_plugins/drupalentity/src/toolbar.js | 3 +++ - 2 files changed, 4 insertions(+), 1 deletion(-) - -diff --git a/js/build/drupalentity.js b/js/build/drupalentity.js -index 37bdb23..52a33de 100644 ---- a/js/build/drupalentity.js -+++ b/js/build/drupalentity.js -@@ -1 +1 @@ --!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();n.hasAttribute("drupalEntityEntityUuid")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),n.hasAttribute("drupalEntityEntityType")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type."));const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); -\ No newline at end of file -+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();if(!n)return;n.hasAttribute("drupalEntityEntityUuid")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),n.hasAttribute("drupalEntityEntityType")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type."));const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); -\ No newline at end of file -diff --git a/js/ckeditor5_plugins/drupalentity/src/toolbar.js b/js/ckeditor5_plugins/drupalentity/src/toolbar.js -index 1413b57..c8e9673 100644 ---- a/js/ckeditor5_plugins/drupalentity/src/toolbar.js -+++ b/js/ckeditor5_plugins/drupalentity/src/toolbar.js -@@ -60,6 +60,9 @@ export default class EntityEmbedToolbar extends Plugin { - editor.ui.componentFactory.add('editEmbeddedEntity', (locale) => { - const button = new ButtonView(locale); - const element = editor.model.document.selection.getSelectedElement(); -+ if (!element) { -+ return; -+ } - if (!element.hasAttribute('drupalEntityEntityUuid')) { - console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-uuid.')) - } --- -GitLab - - -From 1cf7eae7239c19d56f0afb4b98f86aa14085f39a Mon Sep 17 00:00:00 2001 -From: bnjmnm -Date: Tue, 24 Oct 2023 15:38:58 -0400 -Subject: [PATCH 3/3] return null if any essential is unavailable - ---- - js/build/drupalentity.js | 2 +- - js/ckeditor5_plugins/drupalentity/src/toolbar.js | 8 +++++--- - 2 files changed, 6 insertions(+), 4 deletions(-) - -diff --git a/js/build/drupalentity.js b/js/build/drupalentity.js -index 52a33de..273ea45 100644 ---- a/js/build/drupalentity.js -+++ b/js/build/drupalentity.js -@@ -1 +1 @@ --!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();if(!n)return;n.hasAttribute("drupalEntityEntityUuid")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),n.hasAttribute("drupalEntityEntityType")||console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type."));const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class w extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class f extends t.Plugin{static get requires(){return[o,l,s,c,w]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:f}})(),r=r.default})())); -\ No newline at end of file -+!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.CKEditor5=e():(t.CKEditor5=t.CKEditor5||{},t.CKEditor5.drupalentity=e())}(self,(()=>(()=>{var t={"ckeditor5/src/core.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/core.js")},"ckeditor5/src/engine.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/engine.js")},"ckeditor5/src/ui.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/ui.js")},"ckeditor5/src/utils.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/utils.js")},"ckeditor5/src/widget.js":(t,e,i)=>{t.exports=i("dll-reference CKEditor5.dll")("./src/widget.js")},"dll-reference CKEditor5.dll":t=>{"use strict";t.exports=CKEditor5.dll}},e={};function i(r){var n=e[r];if(void 0!==n)return n.exports;var o=e[r]={exports:{}};return t[r](o,o.exports,i),o.exports}i.d=(t,e)=>{for(var r in e)i.o(e,r)&&!i.o(t,r)&&Object.defineProperty(t,r,{enumerable:!0,get:e[r]})},i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e);var r={};return(()=>{"use strict";i.d(r,{default:()=>A});var t=i("ckeditor5/src/core.js"),e=i("ckeditor5/src/widget.js");class n extends t.Command{execute(t){const{model:e}=this.editor,i=this.editor.plugins.get("EntityEmbedEditing"),r=Object.fromEntries(Object.entries(i.attrs).map((([t,e])=>[e,t]))),n=Object.fromEntries(Object.keys(r).filter((e=>t[e])).map((e=>[r[e],t[e]])));e.change((t=>{e.insertContent(function(t,e){return t.createElement("drupalEntity",e)}(t,n))}))}refresh(){const t=this.editor.model,e=t.document.selection,i=t.schema.findAllowedParent(e.getFirstPosition(),"drupalEntity");this.isEnabled=null!==i}}class o extends t.Plugin{static get requires(){return[e.Widget]}init(){this.attrs={alt:"alt",title:"title",dataCaption:"data-caption",dataAlign:"data-align",drupalEntityLangCode:"data-langcode",drupalEntityEntityType:"data-entity-type",drupalEntityEntityUuid:"data-entity-uuid",drupalEntityViewMode:"data-view-mode",drupalEntityEmbedButton:"data-embed-button",drupalEntityEmbedDisplay:"data-entity-embed-display",drupalEntityEmbedDisplaySettings:"data-entity-embed-display-settings"};const t=this.editor.config.get("entityEmbed");if(!t)throw new Error("Error on initializing entityEmbed plugin: entityEmbed config is required.");this.options=t,this.labelError=Drupal.t("Preview failed"),this.previewError=`\n

${Drupal.t("An error occurred while trying to preview the embedded content. Please save your work and reload this page.")}

\n `,this._defineSchema(),this._defineConverters(),this.editor.commands.add("insertEntityEmbed",new n(this.editor))}_defineSchema(){this.editor.model.schema.register("drupalEntity",{isObject:!0,isContent:!0,isBlock:!0,allowWhere:"$block",allowAttributes:Object.keys(this.attrs)}),this.editor.editing.view.domConverter.blockElements.push("drupal-entity")}_defineConverters(){const{conversion:t}=this.editor,i={model:"drupalEntity",view:{name:"drupal-entity"}};t.for("upcast").elementToElement(i),t.for("dataDowncast").elementToElement(i),t.for("editingDowncast").elementToElement({...i,view:(t,{writer:i})=>{const r=t.hasAttribute("dataAlign")?` align-${t.getAttribute("dataAlign")}`:"",n=i.createContainerElement("figure",{class:`drupal-entity${r}`});return i.setCustomProperty("drupalEntity",!0,n),(0,e.toWidget)(n,i,{label:Drupal.t("Entity Embed widget")})}}).add((t=>(t.on("attribute:drupalEntityEntityUuid:drupalEntity",((t,e,i)=>{const r=i.writer,n=e.item,o=i.mapper.toViewElement(e.item);let a=this._getPreviewContainer(o.getChildren());if(a){if("ready"!==a.getAttribute("data-drupal-entity-preview"))return;r.setAttribute("data-drupal-entity-preview","loading",a)}else a=r.createRawElement("div",{"data-drupal-entity-preview":"loading"}),r.insert(r.createPositionAt(o,0),a);this._loadPreview(n).then((({label:t,preview:e})=>{a&&this.editor.editing.view.change((i=>{const r=i.createRawElement("div",{"data-drupal-entity-preview":"ready","aria-label":t},(t=>{t.innerHTML=e}));i.insert(i.createPositionBefore(a),r),i.remove(a)}))}))})),t))),Object.keys(this.attrs).forEach((e=>{const i={model:{key:e,name:"drupalEntity"},view:{name:"drupal-entity",key:this.attrs[e]}};t.for("dataDowncast").attributeToAttribute(i),t.for("upcast").attributeToAttribute(i)}))}async _loadPreview(t){const e={text:this._renderElement(t)},i=await fetch(Drupal.url("embed/preview/"+this.options.format+"?"+new URLSearchParams(e)),{headers:{"X-Drupal-EmbedPreview-CSRF-Token":this.options.previewCsrfToken}});if(i.ok){return{label:Drupal.t("Entity Embed widget"),preview:await i.text()}}return{label:this.labelError,preview:this.previewError}}_renderElement(t){const e=this.editor.model.change((e=>{const i=e.createDocumentFragment(),r=e.cloneElement(t,!1);return["linkHref","dataAlign"].forEach((t=>{e.removeAttribute(t,r)})),e.append(r,i),i}));return this.editor.data.stringify(e)}_getPreviewContainer(t){for(const e of t){if(e.hasAttribute("data-drupal-entity-preview"))return e;if(e.childCount){const t=this._getPreviewContainer(e.getChildren());if(t)return t}}return null}static get pluginName(){return"EntityEmbedEditing"}}var a=i("ckeditor5/src/ui.js");class s extends t.Plugin{static get requires(){return[e.WidgetToolbarRepository]}init(){const e=this.editor,i=e.plugins.get("EntityEmbedEditing"),r=e.config.get("entityEmbed"),{dialogSettings:n={}}=r;e.ui.componentFactory.add("entityEmbedEdit",(o=>{let s=new a.ButtonView(o);return s.set({label:e.t("Edit"),icon:t.icons.pencil,tooltip:!0}),this.listenTo(s,"execute",(t=>{const o=e.model.document.selection.getSelectedElement(),a=Drupal.url("entity-embed/dialog/"+r.format+"/"+o.getAttribute("drupalEntityEmbedButton"));let s={};for(let[t,e]of o.getAttributes()){let r=i.attrs[t];r&&(s[r]=e)}this._openDialog(a,s,(({attributes:t})=>{e.execute("insertEntityEmbed",t),e.editing.view.focus()}),n)})),s})),e.ui.componentFactory.add("editEmbeddedEntity",(i=>{const r=new a.ButtonView(i),n=e.model.document.selection.getSelectedElement();if(!n)return null;if(!n.hasAttribute("drupalEntityEntityUuid"))return console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-uuid.")),null;if(!n.hasAttribute("drupalEntityEntityType"))return console.warn(Drupal.t("Unable to create edit link. There must be a value for data-entity-type.")),null;const o=n.getAttribute("drupalEntityEntityUuid"),s=n.getAttribute("drupalEntityEntityType"),l=Drupal.url(`entity-embed/edit-embedded/${s}/${o}`);return r.set({isEnabled:!0,label:Drupal.t("Edit the embedded entity (opens in new tab)"),icon:t.icons.cog,tooltip:!0}),fetch(l).then((t=>{t.ok||r.set({label:Drupal.t(`You do not have the permissions needed to edit this ${s}.`),isEnabled:!1})})),this.listenTo(r,"execute",(()=>{window.open(l,"_blank")})),r}))}afterInit(){const{editor:t}=this;if(!t.plugins.has("WidgetToolbarRepository"))return;t.plugins.get(e.WidgetToolbarRepository).register("entityEmbed",{ariaLabel:Drupal.t("Entity Embed toolbar"),items:["entityEmbedEdit","entityEmbedLink","editEmbeddedEntity"],getRelatedElement(t){const i=t.getSelectedElement();return i&&(0,e.isWidget)(i)&&i.getCustomProperty("drupalEntity")?i:null}})}_openDialog(t,e,i,r){const n=r.dialogClass?r.dialogClass.split(" "):[];n.push("ui-dialog--narrow"),r.dialogClass=n.join(" "),r.autoResize=window.matchMedia("(min-width: 600px)").matches,r.width="auto";Drupal.ajax({dialog:r,dialogType:"modal",selector:".ckeditor5-dialog-loading-link",url:t,progress:{type:"fullscreen"},submit:{editor_object:e}}).execute(),Drupal.ckeditor5.saveCallback=i}static get pluginName(){return"EntityEmbedToolbar"}}class l extends t.Plugin{static get requires(){return["Widget"]}init(){const t=this.editor,e=t.commands.get("insertEntityEmbed"),i=t.config.get("entityEmbed");if(!i)return;const{dialogSettings:r={}}=i,n=i.buttons;Object.keys(n).forEach((o=>{const s=Drupal.url("entity-embed/dialog/"+i.format+"/"+o);t.ui.componentFactory.add(o,(i=>{const l=n[o],d=new a.ButtonView(i);let u=null;if(l.icon.endsWith("svg")){let t=new XMLHttpRequest;t.open("GET",l.icon,!1),t.send(null),u=t.response}else console.warn(`CKEditor 5 only supports enity embed icons in SVG format. The icon provided is ${l.icon}`);return d.set({label:l.label,icon:u??'\n\n \n\n',tooltip:!0}),d.bind("isOn","isEnabled").to(e,"value","isEnabled"),this.listenTo(d,"execute",(()=>Drupal.ckeditor5.openDialog(s,(({attributes:e})=>{t.execute("insertEntityEmbed",e)}),r))),d}))}))}static get pluginName(){return"EntityEmbedUI"}}function d(t,e,i){if(e.attributes)for(const[r,n]of Object.entries(e.attributes))t.setAttribute(r,n,i);e.styles&&t.setStyle(e.styles,i),e.classes&&t.addClass(e.classes,i)}function u(t,e,i){if(!i.consumable.consume(e.item,t.name))return;const r=i.mapper.toViewElement(e.item);d(i.writer,e.attributeNewValue,r)}class c extends t.Plugin{constructor(t){if(super(t),!t.plugins.has("GeneralHtmlSupport"))return;t.plugins.has("DataFilter")&&t.plugins.has("DataSchema")||console.error("DataFilter and DataSchema plugins are required for Entity Embed to integrate with General HTML Support plugin.");const{schema:e}=t.model,{conversion:i}=t,r=this.editor.plugins.get("DataFilter");this.editor.plugins.get("DataSchema").registerBlockElement({model:"drupalEntity",view:"drupal-entity"}),r.on("register:drupal-entity",((t,n)=>{"drupalEntity"===n.model&&(e.extend("drupalEntity",{allowAttributes:["htmlLinkAttributes","htmlAttributes"]}),i.for("upcast").add(function(t){return e=>{e.on("element:drupal-entity",((e,i,r)=>{function n(e,n){const o=t.processViewAttributes(e,r);o&&r.writer.setAttribute(n,o,i.modelRange)}const o=i.viewItem,a=o.parent;n(o,"htmlAttributes"),a.is("element","a")&&n(a,"htmlLinkAttributes")}),{priority:"low"})}}(r)),i.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item),n=function(t,e,i){const r=t.createRangeOn(e);for(const{item:t}of r.getWalker())if(t.is("element",i))return t}(i.writer,r,"a");d(i.writer,e.item.getAttribute("htmlLinkAttributes"),n)}),{priority:"low"})})),i.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{if(!i.consumable.consume(e.item,"attribute:htmlLinkAttributes:drupalEntity"))return;const r=i.mapper.toViewElement(e.item).parent;d(i.writer,e.item.getAttribute("htmlLinkAttributes"),r)}),{priority:"low"}),t.on("attribute:htmlAttributes:drupalEntity",u,{priority:"low"})})),t.stop())}))}static get pluginName(){return"EntityEmbedGeneralHtmlSupport"}}var m=i("ckeditor5/src/engine.js"),p=i("ckeditor5/src/utils.js");function g(t){return Array.from(t.getChildren()).find((t=>"drupal-entity"===t.name))}function E(t){return e=>{e.on(`attribute:${t.id}:drupalEntity`,((e,i,r)=>{const n=r.mapper.toViewElement(i.item);let o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o=!o&&n.is("element","a")?n:Array.from(n.getAncestors()).find((t=>"a"===t.name)),o){for(const[e,i]of(0,p.toMap)(t.attributes))r.writer.setAttribute(e,i,o);t.classes&&r.writer.addClass(t.classes,o);for(const e in t.styles)Object.prototype.hasOwnProperty.call(t.styles,e)&&r.writer.setStyle(e,t.styles[e],o)}}))}}function b(t,e){return t=>{t.on("element:a",((t,i,r)=>{const n=i.viewItem;if(!g(n))return;const o=new m.Matcher(e._createPattern()).match(n);if(!o)return;if(!r.consumable.consume(n,o.match))return;const a=i.modelCursor.nodeBefore;r.writer.setAttribute(e.id,!0,a)}),{priority:"high"})}}class y extends t.Plugin{static get requires(){return["EntityEmbedEditing"]}static get pluginName(){return"EntityEmbedLinkEditing"}init(){const{editor:t}=this;t.model.schema.extend("drupalEntity",{allowAttributes:["linkHref"]}),t.conversion.for("upcast").add((t=>{t.on("element:a",((t,e,i)=>{const r=e.viewItem,n=g(r);if(!n)return;if(!i.consumable.consume(r,{attributes:["href"],name:!0}))return;const o=r.getAttribute("href");if(!o)return;const a=i.convertItem(n,e.modelCursor);e.modelRange=a.modelRange,e.modelCursor=a.modelCursor;const s=e.modelCursor.nodeBefore;s&&s.is("element","drupalEntity")&&i.writer.setAttribute("linkHref",o,s)}),{priority:"high"})})),t.conversion.for("editingDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=Array.from(n.getChildren()).find((t=>"a"===t.name));if(o)e.attributeNewValue?r.setAttribute("href",e.attributeNewValue,o):(r.move(r.createRangeIn(o),r.createPositionAt(n,0)),r.remove(o));else{const t=Array.from(n.getChildren()).find((t=>t.getAttribute("data-drupal-entity-preview"))),i=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionAt(n,0),i),r.move(r.createRangeOn(t),r.createPositionAt(i,0))}}),{priority:"high"})})),t.conversion.for("dataDowncast").add((t=>{t.on("attribute:linkHref:drupalEntity",((t,e,i)=>{const{writer:r}=i;if(!i.consumable.consume(e.item,t.name))return;const n=i.mapper.toViewElement(e.item),o=r.createContainerElement("a",{href:e.attributeNewValue});r.insert(r.createPositionBefore(n),o),r.move(r.createRangeOn(n),r.createPositionAt(o,0))}),{priority:"high"})})),this._enableManualDecorators();if(t.commands.get("link").automaticDecorators.length>0)throw new Error("The Drupal Entity plugin is not compatible with automatic link decorators. To use Drupal Entity, disable any plugins providing automatic link decorators.")}_enableManualDecorators(){const t=this.editor,e=t.commands.get("link");for(const i of e.manualDecorators)t.model.schema.extend("drupalEntity",{allowAttributes:i.id}),t.conversion.for("downcast").add(E(i)),t.conversion.for("upcast").add(b(0,i))}}class h extends t.Plugin{static get requires(){return["LinkEditing","LinkUI","EntityEmbedEditing","EntityEmbedUI"]}static get pluginName(){return"EntityEmbedLinkUi"}init(){const{editor:t}=this,e=t.editing.view.document;this.listenTo(e,"click",((e,i)=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)&&(i.preventDefault(),e.stop())}),{priority:"high"}),this._createToolbarLinkEntityEmbedButton()}_createToolbarLinkEntityEmbedButton(){const{editor:t}=this;t.ui.componentFactory.add("entityEmbedLink",(e=>{const i=new a.ButtonView(e),r=t.plugins.get("LinkUI"),n=t.commands.get("link");return i.set({isEnabled:!0,label:Drupal.t("Link entity embed"),icon:'',keystroke:"Ctrl+K",tooltip:!0,isToggleable:!0}),i.bind("isEnabled").to(n,"isEnabled"),i.bind("isOn").to(n,"value",(t=>!!t)),this.listenTo(i,"execute",(()=>{this._isSelectedLinkedEntityEmbed(t.model.document.selection)?r._addActionsView():r._showUI(!0)})),i}))}_isSelectedLinkedEntityEmbed(t){const e=t.getSelectedElement();return!!e&&e.is("element","drupalEntity")&&e.hasAttribute("linkHref")}}class f extends t.Plugin{static get requires(){return[y,h]}static get pluginName(){return"EntityEmbedLink"}}class w extends t.Plugin{static get requires(){return[o,l,s,c,f]}static get pluginName(){return"EntityEmbed"}}const A={EntityEmbed:w}})(),r=r.default})())); -\ No newline at end of file -diff --git a/js/ckeditor5_plugins/drupalentity/src/toolbar.js b/js/ckeditor5_plugins/drupalentity/src/toolbar.js -index c8e9673..ef9ea7f 100644 ---- a/js/ckeditor5_plugins/drupalentity/src/toolbar.js -+++ b/js/ckeditor5_plugins/drupalentity/src/toolbar.js -@@ -61,13 +61,15 @@ export default class EntityEmbedToolbar extends Plugin { - const button = new ButtonView(locale); - const element = editor.model.document.selection.getSelectedElement(); - if (!element) { -- return; -+ return null; - } - if (!element.hasAttribute('drupalEntityEntityUuid')) { -- console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-uuid.')) -+ console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-uuid.')); -+ return null; - } - if (!element.hasAttribute('drupalEntityEntityType')) { -- console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-type.')) -+ console.warn(Drupal.t('Unable to create edit link. There must be a value for data-entity-type.')); -+ return null; - } - const uuid = element.getAttribute('drupalEntityEntityUuid'); - const type = element.getAttribute('drupalEntityEntityType'); --- -GitLab - diff --git a/tide.info.yml b/tide.info.yml index 2229663..28b0e7f 100644 --- a/tide.info.yml +++ b/tide.info.yml @@ -2,7 +2,7 @@ name: 'Tide' description: 'Tide profile.' type: profile package: Tide -core_version_requirement: ^8.9 || ^9 +core_version_requirement: ^9 || ^10 dependencies: - dpc-sdp:tide_core - dpc-sdp:tide_alert @@ -15,6 +15,5 @@ dependencies: - dpc-sdp:tide_publication - dpc-sdp:tide_search - dpc-sdp:tide_site - - dpc-sdp:tide_site_simple_sitemap themes: - seven From 677a9015067bdffbb36e0179c6f8bd19746d6b6a Mon Sep 17 00:00:00 2001 From: sdpdeploy <33045904+sdpdeploy@users.noreply.github.com> Date: Fri, 8 Dec 2023 15:59:00 +1100 Subject: [PATCH 76/79] Add GitHub Actions workflow files (#211) Co-authored-by: SDP Robot --- .github/workflows/build.yml | 36 ++++++++++++++++++++++++ .github/workflows/dorg_git_sync.yml | 14 +++++++++ .github/workflows/merge_to_reference.yml | 31 ++++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 .github/workflows/build.yml create mode 100644 .github/workflows/dorg_git_sync.yml create mode 100644 .github/workflows/merge_to_reference.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..45eee5e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,36 @@ +name: build + +on: push + +jobs: + set_status_in_progress: + name: set_status_in_progress + if: always() + uses: dpc-sdp/github-actions/.github/workflows/set_status.yml@main + secrets: inherit + with: + context: 'tide_build' + description: 'Tide Build running...' + state: 'pending' + target_url: ${{ github.event.repository.html_url }}/actions/runs/${{ github.run_id }} + tide_build: + name: tide_build + secrets: inherit + uses: dpc-sdp/github-actions/.github/workflows/tide_build.yml@main + with: + module_build: true + runner: biggy-tide + export_config: + name: export_config + secrets: inherit + uses: dpc-sdp/github-actions/.github/workflows/export_config.yml@main + set_status: + name: set_status + needs: [tide_build] + if: always() + uses: dpc-sdp/github-actions/.github/workflows/set_status.yml@main + secrets: inherit + with: + context: 'tide_build' + description: 'Tide Build' + target_url: ${{ github.event.repository.html_url }}/actions/runs/${{ github.run_id }} diff --git a/.github/workflows/dorg_git_sync.yml b/.github/workflows/dorg_git_sync.yml new file mode 100644 index 0000000..d831b2c --- /dev/null +++ b/.github/workflows/dorg_git_sync.yml @@ -0,0 +1,14 @@ +name: dorg_git_sync + +on: + push: + branches: + - master + tags: + - '*' + +jobs: + dorg_git_sync: + name: dorg_git_sync + uses: dpc-sdp/github-actions/.github/workflows/dorg_git_sync.yml@main + secrets: inherit diff --git a/.github/workflows/merge_to_reference.yml b/.github/workflows/merge_to_reference.yml new file mode 100644 index 0000000..3c04229 --- /dev/null +++ b/.github/workflows/merge_to_reference.yml @@ -0,0 +1,31 @@ +name: merge_to_reference + +on: + push: + branches: + - develop + +jobs: + set_status_in_progress: + name: set_status_in_progress + if: always() + uses: dpc-sdp/github-actions/.github/workflows/set_status.yml@main + secrets: inherit + with: + context: 'tide_merge_to_reference' + description: 'Merge to reference running...' + state: 'pending' + target_url: ${{ github.event.repository.html_url }}/actions/runs/${{ github.run_id }} + tide_merge_to_reference: + name: tide_merge_to_reference + uses: dpc-sdp/github-actions/.github/workflows/tide_merge_to_reference.yml@main + set_status: + name: set_status + needs: [tide_merge_to_reference] + if: always() + uses: dpc-sdp/github-actions/.github/workflows/set_status.yml@main + secrets: inherit + with: + context: 'tide_merge_to_reference' + description: 'Merge to reference running...' + target_url: ${{ github.event.repository.html_url }}/actions/runs/${{ github.run_id }} From 5fbe49324768152f1536ed3f6a6a29769377c868 Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Thu, 15 Feb 2024 15:13:53 +1100 Subject: [PATCH 77/79] Updated tide_Core. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 33561f2..c35a9d6 100644 --- a/composer.json +++ b/composer.json @@ -6,7 +6,7 @@ "require": { "dpc-sdp/tide_alert": "4.0.0", "dpc-sdp/tide_api": "4.0.0", - "dpc-sdp/tide_core": "4.0.0", + "dpc-sdp/tide_core": "4.0.1", "dpc-sdp/tide_demo_content": "4.0.0", "dpc-sdp/tide_event": "4.0.0", "dpc-sdp/tide_grant": "4.0.0", From 3043851dc28c410aea37d34f34712f4619b02655 Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Thu, 22 Feb 2024 17:57:52 +1100 Subject: [PATCH 78/79] Updated tide_search to fix the missing update hook which adds the new component to search listing content type. --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index c35a9d6..fb8ef3c 100644 --- a/composer.json +++ b/composer.json @@ -15,7 +15,7 @@ "dpc-sdp/tide_news": "4.0.0", "dpc-sdp/tide_profile": "4.0.0", "dpc-sdp/tide_publication": "4.0.0", - "dpc-sdp/tide_search": "4.0.0", + "dpc-sdp/tide_search": "4.0.1", "dpc-sdp/tide_site": "4.0.0", "dpc-sdp/tide_test": "4.0.0", "dpc-sdp/tide_webform": "4.0.0" From a280d5a93513cfaa3ca6be013974bd7c0e41f06b Mon Sep 17 00:00:00 2001 From: Md Nadim Hossain Date: Wed, 6 Mar 2024 13:44:54 +1100 Subject: [PATCH 79/79] Bug/update theme for fresh profile install (#213) * Updated theme from seven to claro for fresh install. * Removed tide cms help block. --- .../install/block.block.seven_breadcrumbs.yml | 4 ++-- config/install/block.block.seven_content.yml | 4 ++-- .../block.block.seven_local_actions.yml | 4 ++-- config/install/block.block.seven_login.yml | 4 ++-- config/install/block.block.seven_messages.yml | 4 ++-- .../install/block.block.seven_page_title.yml | 4 ++-- .../block.block.seven_primary_local_tasks.yml | 4 ++-- ...lock.block.seven_secondary_local_tasks.yml | 4 ++-- .../block.block.seven_tide_cms_help.yml | 19 ------------------- tide.info.yml | 2 +- tide.install | 8 ++++---- 11 files changed, 21 insertions(+), 40 deletions(-) delete mode 100644 config/install/block.block.seven_tide_cms_help.yml diff --git a/config/install/block.block.seven_breadcrumbs.yml b/config/install/block.block.seven_breadcrumbs.yml index edbdfbd..5a3d848 100644 --- a/config/install/block.block.seven_breadcrumbs.yml +++ b/config/install/block.block.seven_breadcrumbs.yml @@ -4,9 +4,9 @@ dependencies: module: - system theme: - - seven + - claro id: seven_breadcrumbs -theme: seven +theme: claro region: breadcrumb weight: 0 provider: null diff --git a/config/install/block.block.seven_content.yml b/config/install/block.block.seven_content.yml index d92214c..7a4567e 100644 --- a/config/install/block.block.seven_content.yml +++ b/config/install/block.block.seven_content.yml @@ -4,9 +4,9 @@ dependencies: module: - system theme: - - seven + - claro id: seven_content -theme: seven +theme: claro region: content weight: 0 provider: null diff --git a/config/install/block.block.seven_local_actions.yml b/config/install/block.block.seven_local_actions.yml index 61cdb17..b130479 100644 --- a/config/install/block.block.seven_local_actions.yml +++ b/config/install/block.block.seven_local_actions.yml @@ -2,9 +2,9 @@ langcode: en status: true dependencies: theme: - - seven + - claro id: seven_local_actions -theme: seven +theme: claro region: content weight: -10 provider: null diff --git a/config/install/block.block.seven_login.yml b/config/install/block.block.seven_login.yml index 110e8fd..b65c6f0 100644 --- a/config/install/block.block.seven_login.yml +++ b/config/install/block.block.seven_login.yml @@ -4,9 +4,9 @@ dependencies: module: - user theme: - - seven + - claro id: seven_login -theme: seven +theme: claro region: content weight: 10 provider: null diff --git a/config/install/block.block.seven_messages.yml b/config/install/block.block.seven_messages.yml index f7b6038..0c9be95 100644 --- a/config/install/block.block.seven_messages.yml +++ b/config/install/block.block.seven_messages.yml @@ -4,9 +4,9 @@ dependencies: module: - system theme: - - seven + - claro id: seven_messages -theme: seven +theme: claro region: highlighted weight: 0 provider: null diff --git a/config/install/block.block.seven_page_title.yml b/config/install/block.block.seven_page_title.yml index 56df293..07cb0f1 100644 --- a/config/install/block.block.seven_page_title.yml +++ b/config/install/block.block.seven_page_title.yml @@ -2,9 +2,9 @@ langcode: en status: true dependencies: theme: - - seven + - claro id: seven_page_title -theme: seven +theme: claro region: header weight: -30 provider: null diff --git a/config/install/block.block.seven_primary_local_tasks.yml b/config/install/block.block.seven_primary_local_tasks.yml index d0017c2..d0dd191 100644 --- a/config/install/block.block.seven_primary_local_tasks.yml +++ b/config/install/block.block.seven_primary_local_tasks.yml @@ -2,9 +2,9 @@ langcode: en status: true dependencies: theme: - - seven + - claro id: seven_primary_local_tasks -theme: seven +theme: claro region: header weight: 0 provider: null diff --git a/config/install/block.block.seven_secondary_local_tasks.yml b/config/install/block.block.seven_secondary_local_tasks.yml index 3339199..7266bec 100644 --- a/config/install/block.block.seven_secondary_local_tasks.yml +++ b/config/install/block.block.seven_secondary_local_tasks.yml @@ -2,9 +2,9 @@ langcode: en status: true dependencies: theme: - - seven + - claro id: seven_secondary_local_tasks -theme: seven +theme: claro region: pre_content weight: 0 provider: null diff --git a/config/install/block.block.seven_tide_cms_help.yml b/config/install/block.block.seven_tide_cms_help.yml deleted file mode 100644 index 8555bf3..0000000 --- a/config/install/block.block.seven_tide_cms_help.yml +++ /dev/null @@ -1,19 +0,0 @@ -langcode: en -status: true -dependencies: - module: - - tide_cms_support - theme: - - seven -id: seven_tide_cms_help -theme: seven -region: help -weight: -100 -provider: null -plugin: tide_help_block -settings: - id: tide_help_block - label: 'Tide CMS Help' - provider: tide_cms_support - label_display: '' -visibility: { } diff --git a/tide.info.yml b/tide.info.yml index 28b0e7f..7fc5693 100644 --- a/tide.info.yml +++ b/tide.info.yml @@ -16,4 +16,4 @@ dependencies: - dpc-sdp:tide_search - dpc-sdp:tide_site themes: - - seven + - claro diff --git a/tide.install b/tide.install index 387e3b1..5b79aae 100644 --- a/tide.install +++ b/tide.install @@ -18,12 +18,12 @@ function tide_install() { return; } - // Set the default and admin theme to Seven. It is important to set themes - // only to enabled ones (and we are enabling Seven in profile dependencies). + // Set the default and admin theme to Claro. It is important to set themes + // only to enabled ones (and we are enabling Claro in profile dependencies). \Drupal::configFactory() ->getEditable('system.theme') - ->set('default', 'seven') - ->set('admin', 'seven') + ->set('default', 'claro') + ->set('admin', 'claro') ->save(TRUE); // Set the path to the logo and favicon files based on install directory.