From f597d75a8e19e8c2f751ded11317ddb20c072e1e Mon Sep 17 00:00:00 2001 From: vincent-gao Date: Tue, 6 Jun 2023 12:56:46 +1000 Subject: [PATCH] Remove noncanonical repos (#131) ### 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 | 12 +- .../video_embed_field_6.patch | 5263 +++++++++++++++++ 2 files changed, 5264 insertions(+), 11 deletions(-) create mode 100644 patches/video_embed_field/video_embed_field_6.patch diff --git a/composer.json b/composer.json index 96e7ac1..4565c13 100644 --- a/composer.json +++ b/composer.json @@ -15,17 +15,7 @@ "repositories": { "drupal": { "type": "composer", - "url": "https://packages.drupal.org/8", - "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/8" } }, "extra": { 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 +