diff --git a/core/modules/ckeditor5/ckeditor5.api.php b/core/modules/ckeditor5/ckeditor5.api.php index 2e9d801c736..523ee574e39 100644 --- a/core/modules/ckeditor5/ckeditor5.api.php +++ b/core/modules/ckeditor5/ckeditor5.api.php @@ -119,11 +119,12 @@ use Drupal\ckeditor5\Plugin\CKEditor5PluginDefinition; * make it discoverable. * - drupal.elements: A list of elements and attributes the plugin allows use of * within CKEditor 5. This uses the same syntax as the 'filter_html' plugin - * with an additional special keyword: '<$block>' . Using - * '<$block [attribute(s)]>` will permit the provided attributes in all block - * level tags that are explicitly enabled in any plugin. i.e. if only '
', - * '
', '
', '
', '
in the first operand and - // <$block class="text-align-center"> in the second operand. + // <$text-container class="text-align-center"> in the second + // operand. $a_concrete = self::resolveWildcards($a); $b_concrete = self::resolveWildcards($b); $concrete_op_result = $a_concrete->$operation_method_name($b_concrete); @@ -901,15 +901,16 @@ final class HTMLRestrictions { // let ::merge() pick the most permissive one. // This is necessary because resolving wildcards may result in concrete tags // becoming either more permissive: - // - if $r is `
<$block class="foo">` + // - if $r is `
<$text-container class="foo">` // - then $naive will be `
` - // - merging them yields `
<$block class="foo">` + // - merging them yields `
<$text-container class="foo">` // - diffing the wildcard subsets yields just `
` // Or it could result in concrete tags being unaffected by the resolved // wildcards: - // - if $r is `
<$block class="foo">` + // - if $r is `
<$text-container class="foo">` // - then $naive will be `
` - // - merging them yields `
<$block class="foo">` again + // - merging them yields `
<$text-container class="foo">` + // again // - diffing the wildcard subsets yields just `
` return $r->merge($naive_resolution)->doDiff($r->getWildcardSubset()); } @@ -996,12 +997,7 @@ final class HTMLRestrictions { $allowed = []; // Resolve any remaining wildcards based on Drupal's assumptions on // wildcards to ensure all HTML tags that Drupal thinks are supported are - // truly supported by CKEditor 5. For example: the <$block> wildcard does - // NOT correspond to block-level HTML tags, but to CKEditor 5 elements that - // behave like blocks. Knowing the list of concrete HTML tags this maps to - // is impossible without executing JavaScript, which PHP cannot do. By - // generating this GHS configuration, we can guarantee that Drupal's only - // possible interpretation also actually works. + // truly supported by CKEditor 5. $elements = self::resolveWildcards($this)->getAllowedElements(); foreach ($elements as $tag => $attributes) { $to_allow = ['name' => $tag]; @@ -1048,25 +1044,51 @@ final class HTMLRestrictions { } /** - * Gets a list of block-level elements. + * Gets a list of CKEditor 5's `$block` text container elements. + * + * This is a hard coded list of known elements that CKEditor 5 uses as + * `$block` text container elements. The elements listed here are registered + * with `inheritAllFrom: "$block"` to the CKEditor 5 schema. This list + * corresponds to the `$text-container` wildcard in Drupal configuration. + * + * + * This group of elements is special because they allow text as an immediate + * child node. These elements are also allowed to be used for text styles that + * must be applied to the wrapper instead of inline to the text, such as text + * alignment. + * + * This list is highly opinionated. It is based on decisions made upstream in + * CKEditor 5. For example, `
` is not considered as a `$block` + * text container, meaning that text inside `` needs to always be + * wrapped by an element that is `$block` text container such as ``. This + * list also excludes some special case text container elements like + * `
` that allow containing text directly inside the element, yet do + * not fully implement the `$block` text container interface. + * + * It is acceptable to list the elements here because the list of elements is + * not likely to change often. If the list changed, an upgrade path would be + * required anyway. In most cases, missing elements would only impact new + * functionality shipped in upstream. + * + * @see https://ckeditor.com/docs/ckeditor5/latest/framework/guides/deep-dive/schema.html#generic-items * * @return string[] * An array of block-level element tags. */ - private static function getBlockElementList(): array { - return array_filter(array_keys(Elements::$html5), function (string $element): bool { - return Elements::isA($element, Elements::BLOCK_TAG); - }); + private static function getTextContainerElementList(): array { + return [ + 'div', 'p', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'pre', 'li', + ]; } /** * Computes the tags that match the provided wildcard. * * A wildcard tag in element config is a way of representing multiple tags - * with a single item, such as `<$block>` to represent all block tags. Each - * wildcard should have a corresponding callback method listed in - * WILDCARD_ELEMENT_METHODS that returns the set of tags represented by the - * wildcard. + * with a single item, such as `<$text-container>` to represent CKEditor 5's + * `$block` text container tags. Each wildcard should have a corresponding + * callback method listed in WILDCARD_ELEMENT_METHODS that returns the set of + * tags represented by the wildcard. * * @param string $wildcard * The wildcard that represents multiple tags. diff --git a/core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php b/core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php index a3df9c9cb44..8f628a90351 100644 --- a/core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php +++ b/core/modules/ckeditor5/src/Plugin/CKEditor5PluginManager.php @@ -179,8 +179,8 @@ class CKEditor5PluginManager extends DefaultPluginManager implements CKEditor5Pl $restrictions = new HTMLRestrictions($this->getProvidedElements(array_keys($definitions), $editor, FALSE)); if ($restrictions->getWildcardSubset()->isEmpty()) { // This is only reached if arbitrary HTML is not enabled. If wildcard - // tags (such as $block) are present, they need to be resolved via the - // wildcardHtmlSupport plugin. + // tags (such as $text-container) are present, they need to + // be resolved via the wildcardHtmlSupport plugin. // @see \Drupal\ckeditor5\Plugin\CKEditor5PluginManager::getCKEditor5PluginConfig() unset($definitions['ckeditor5_wildcardHtmlSupport']); } diff --git a/core/modules/ckeditor5/tests/modules/ckeditor5_plugin_elements_test/ckeditor5_plugin_elements_test.ckeditor5.yml b/core/modules/ckeditor5/tests/modules/ckeditor5_plugin_elements_test/ckeditor5_plugin_elements_test.ckeditor5.yml index 37a8c85c107..86cc935a960 100644 --- a/core/modules/ckeditor5/tests/modules/ckeditor5_plugin_elements_test/ckeditor5_plugin_elements_test.ckeditor5.yml +++ b/core/modules/ckeditor5/tests/modules/ckeditor5_plugin_elements_test/ckeditor5_plugin_elements_test.ckeditor5.yml @@ -1,12 +1,12 @@ -# cspell:ignore everyblock justblockquote -ckeditor5_plugin_elements_test_blockquoteCombo: +# cspell:ignore everytextcontainer justheading +ckeditor5_plugin_elements_test_headingCombo: ckeditor5: plugins: [] drupal: label: TEST — block quote combo elements: - - - - <$block data-everyblock> + -+ - <$text-container data-everytextcontainer> ckeditor5_plugin_elements_test_headingsWithOtherAttributes: ckeditor5: diff --git a/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTest.php b/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTest.php index 4542392e7d8..7fe10f2e1e3 100644 --- a/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTest.php +++ b/core/modules/ckeditor5/tests/src/FunctionalJavascript/SourceEditingTest.php @@ -200,15 +200,17 @@ class SourceEditingTest extends CKEditor5TestBase { '', ], - // Edge case: $block wildcard with additional attribute. - '<$block data-llama>' => [ + // Edge case: $text-container wildcard with additional + // attribute. + '<$text-container data-llama>' => [ '', - '<$block data-llama>', + '<$text-container data-llama>', ], - // Edge case: $block wildcard with stricter attribute constrain. - '<$block class="not-llama">' => [ + // Edge case: $text-container wildcard with stricter attribute + // constrain. + '<$text-container class="not-llama">' => [ '', - '<$block class="not-llama">', + '<$text-container class="not-llama">', ], // Edge case: wildcard attribute names: diff --git a/core/modules/ckeditor5/tests/src/Kernel/CKEditor5PluginManagerTest.php b/core/modules/ckeditor5/tests/src/Kernel/CKEditor5PluginManagerTest.php index 98654422b0c..d9b24457f8e 100644 --- a/core/modules/ckeditor5/tests/src/Kernel/CKEditor5PluginManagerTest.php +++ b/core/modules/ckeditor5/tests/src/Kernel/CKEditor5PluginManagerTest.php @@ -15,7 +15,7 @@ use org\bovigo\vfs\vfsStream; use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag; use Symfony\Component\Yaml\Yaml; -// cspell:ignore layercake everyblock justblockquote +// cspell:ignore layercake everytextcontainer justheading /** * Tests different ways of enabling CKEditor 5 plugins. @@ -1303,26 +1303,24 @@ PHP, ], 'expected_readable_string' => '
', ], - 'blockquote combo' => [ + 'heading text container combo' => [ 'plugins' => [ - 'ckeditor5_plugin_elements_test_blockquoteCombo', + 'ckeditor5_plugin_elements_test_headingCombo', 'ckeditor5_paragraph', ], 'text_editor_settings' => [ - 'plugins' => [ - 'ckeditor5_heading' => Heading::DEFAULT_CONFIGURATION, - ], + 'plugins' => [], ], 'expected_elements' => [ 'p' => [ - 'data-everyblock' => TRUE, + 'data-everytextcontainer' => TRUE, ], - 'blockquote' => [ - 'data-justblockquote' => TRUE, - 'data-everyblock' => TRUE, + 'h1' => [ + 'data-justheading' => TRUE, + 'data-everytextcontainer' => TRUE, ], ], - 'expected_readable_string' => '
', + 'expected_readable_string' => '
', ], 'headings plus headings with attributes' => [ 'plugins' => [ diff --git a/core/modules/ckeditor5/tests/src/Kernel/SmartDefaultSettingsTest.php b/core/modules/ckeditor5/tests/src/Kernel/SmartDefaultSettingsTest.php index 513dbd72896..c5f76baf838 100644 --- a/core/modules/ckeditor5/tests/src/Kernel/SmartDefaultSettingsTest.php +++ b/core/modules/ckeditor5/tests/src/Kernel/SmartDefaultSettingsTest.php @@ -604,7 +604,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { // Note that aligning left and right is being added, on top of what the // original format allowed: center and justify. // Note that aligning left/center/right/justify is possible on *all* - // allowed block-level HTML5 tags. + // allowed CKEditor 5 `$block` text container tags. // @todo When https://www.drupal.org/project/drupal/issues/3259367 // lands, none of the tags below should appear. '
', @@ -612,11 +612,7 @@ class SmartDefaultSettingsTest extends KernelTestBase { '
', '
', '
', - '
', - '
- ', - '
', - '', - '
', + '
- ', $basic_html_test_case['expected_superset'], ]), 'expected_fundamental_compatibility_violations' => $basic_html_test_case['expected_fundamental_compatibility_violations'], diff --git a/core/modules/ckeditor5/tests/src/Kernel/ValidatorsTest.php b/core/modules/ckeditor5/tests/src/Kernel/ValidatorsTest.php index 948cb61056b..e841b391a76 100644 --- a/core/modules/ckeditor5/tests/src/Kernel/ValidatorsTest.php +++ b/core/modules/ckeditor5/tests/src/Kernel/ValidatorsTest.php @@ -844,7 +844,7 @@ class ValidatorsTest extends KernelTestBase { ], 'plugins' => [ 'ckeditor5_sourceEditing' => [ - 'allowed_tags' => ['<$block data-llama>'], + 'allowed_tags' => ['<$text-container data-llama>'], ], ], ], diff --git a/core/modules/ckeditor5/tests/src/Kernel/WildcardHtmlSupportTest.php b/core/modules/ckeditor5/tests/src/Kernel/WildcardHtmlSupportTest.php index f936d37ab1f..746b42e1f9d 100644 --- a/core/modules/ckeditor5/tests/src/Kernel/WildcardHtmlSupportTest.php +++ b/core/modules/ckeditor5/tests/src/Kernel/WildcardHtmlSupportTest.php @@ -111,9 +111,9 @@ class WildcardHtmlSupportTest extends KernelTestBase { ], ['link', 'blockQuote'], ], - '<$block> minimal configuration' => [ + '<$text-container> minimal configuration' => [ '
', - ['<$block data-llama>'], + ['<$text-container data-llama>'], [ [ 'name' => 'p', @@ -126,9 +126,9 @@ class WildcardHtmlSupportTest extends KernelTestBase { ], ], ], - '<$block> from multiple plugins' => [ + '<$text-container> from multiple plugins' => [ '
', - ['<$block data-llama>'], + ['<$text-container data-llama>'], [ [ 'name' => 'p', @@ -147,9 +147,9 @@ class WildcardHtmlSupportTest extends KernelTestBase { ], ['alignment'], ], - '<$block> with attribute from multiple plugins' => [ + '<$text-container> with attribute from multiple plugins' => [ '
', - ['<$block data-llama>', ''], + ['<$text-container data-llama>', '
'], [ [ 'name' => 'p', @@ -172,9 +172,9 @@ class WildcardHtmlSupportTest extends KernelTestBase { ], ['alignment'], ], - '<$block> realistic configuration' => [ - '