Skip to content
Snippets Groups Projects
Unverified Commit 613b8627 authored by Lauri Timmanee's avatar Lauri Timmanee
Browse files

Issue #3230230 by bnjmnm, johnwebdev, Wim Leers, lauriii, Anna_CKSource,...

Issue #3230230 by bnjmnm, johnwebdev, Wim Leers, lauriii, Anna_CKSource, Reinmar: Enable table captions; override CKE5's default downcast to generate <table><caption></table> instead of <figure><table><figcaption></figure>
parent 1d5995a2
No related branches found
No related tags found
37 merge requests!12227Issue #3181946 by jonmcl, mglaman,!7471uncessary 5 files are moved from media-library folder to misc folder,!7452Issue #1797438. HTML5 validation is preventing form submit and not fully...,!54479.5.x SF update,!5014Issue #3071143: Table Render Array Example Is Incorrect,!4868Issue #1428520: Improve menu parent link selection,!4289Issue #1344552 by marcingy, Niklas Fiekas, Ravi.J, aleevas, Eduardo Morales...,!4114Issue #2707291: Disable body-level scrolling when a dialog is open as a modal,!3630Issue #2815301 by Chi, DanielVeza, kostyashupenko, smustgrave: Allow to create...,!3291Issue #3336463: Rewrite rules for gzipped CSS and JavaScript aggregates never match,!3143Issue #3313342: [PHP 8.1] Deprecated function: strpos(): Passing null to parameter #1 LayoutBuilderUiCacheContext.php on line 28,!3102Issue #3164428 by DonAtt, longwave, sahil.goyal, Anchal_gupta, alexpott: Use...,!2853#3274419 Makes BaseFieldOverride inherit the internal property from the base field.,!2719Issue #3110137: Remove Classy from core.,!2437Issue #3238257 by hooroomoo, Wim Leers: Fragment link pointing to <textarea>...,!2378Issue #2875033: Optimize joins and table selection in SQL entity query implementation,!2074Issue #2707689: NodeForm::actions() checks for delete access on new entities,!2062Issue #3246454: Add weekly granularity to views date sort,!1591Issue #3199697: Add JSON:API Translation experimental module,!1484Exposed filters get values from URL when Ajax is on,!1255Issue #3238922: Refactor (if feasible) uses of the jQuery serialize function to use vanillaJS,!1254Issue #3238915: Refactor (if feasible) uses of the jQuery ready function to use VanillaJS,!1162Issue #3100350: Unable to save '/' root path alias,!1073issue #3191727: Focus states on mobile second level navigation items fixed,!10223132456: Fix issue where views instances are emptied before an ajax request is complete,!957Added throwing of InvalidPluginDefinitionException from getDefinition().,!925Issue #2339235: Remove taxonomy hard dependency on node module,!877Issue #2708101: Default value for link text is not saved,!873Issue #2875228: Site install not using batch API service,!872Draft: Issue #3221319: Race condition when creating menu links and editing content deletes menu links,!844Resolve #3036010 "Updaters",!712Issue #2909128: Autocomplete intermittent on Chrome Android,!579Issue #2230909: Simple decimals fail to pass validation,!560Move callback classRemove outside of the loop,!555Issue #3202493,!485Sets the autocomplete attribute for username/password input field on login form.,!30Issue #3182188: Updates composer usage to point at ./vendor/bin/composer
......@@ -427,9 +427,11 @@ ckeditor5_table:
plugins:
- table.Table
- table.TableToolbar
- table.TableCaption
- table.PlainTableOutput
config:
table:
contentToolbar: [tableColumn, tableRow, mergeTableCells]
contentToolbar: [tableColumn, tableRow, mergeTableCells, toggleTableCaption]
drupal:
label: Table
library: core/ckeditor5.table
......@@ -445,6 +447,7 @@ ckeditor5_table:
- <thead>
- <tbody>
- <tfoot>
- <caption>
ckeditor5_image:
ckeditor5:
......
<?php
namespace Drupal\Tests\ckeditor5\FunctionalJavascript;
use Drupal\ckeditor5\Plugin\Editor\CKEditor5;
use Drupal\editor\Entity\Editor;
use Drupal\filter\Entity\FilterFormat;
use Drupal\Tests\ckeditor5\Traits\CKEditor5TestTrait;
use Symfony\Component\Validator\ConstraintViolation;
/**
* For testing the table plugin.
*
* @group ckeditor5
* @internal
*/
class TableTest extends CKEditor5TestBase {
use CKEditor5TestTrait;
/**
* A host entity with a body field to embed images in.
*
* @var \Drupal\node\NodeInterface
*/
protected $host;
/**
* Text added to captions.
*
* @var string
*/
protected $captionText = 'some caption';
/**
* Text added to table cells.
*
* @var string
*/
protected $tableCellText = 'table cell';
/**
* {@inheritdoc}
*/
protected static $modules = [
'ckeditor5',
'node',
'text',
];
/**
* {@inheritdoc}
*/
protected $defaultTheme = 'stark';
protected function setUp(): void {
parent::setUp();
FilterFormat::create([
'format' => 'test_format',
'name' => 'Test format',
'filters' => [
'filter_html' => [
'status' => TRUE,
'settings' => [
'allowed_html' => '<br> <p> <table> <tr> <td rowspan colspan> <th rowspan colspan> <thead> <tbody> <tfoot> <caption>',
],
],
],
])->save();
Editor::create([
'editor' => 'ckeditor5',
'format' => 'test_format',
'settings' => [
'toolbar' => [
'items' => [
'insertTable',
'sourceEditing',
],
],
'plugins' => [
'ckeditor5_sourceEditing' => [
'allowed_tags' => [],
],
],
],
])->save();
$this->assertSame([], array_map(
function (ConstraintViolation $v) {
return (string) $v->getMessage();
},
iterator_to_array(CKEditor5::validatePair(
Editor::load('test_format'),
FilterFormat::load('test_format')
))
));
// Create a sample host entity.
$this->host = $this->createNode([
'type' => 'page',
'title' => 'Animals with strange names',
'body' => [
'value' => '<p>some content that will likely change</p>',
'format' => 'test_format',
],
]);
$this->host->save();
$this->drupalLogin($this->drupalCreateUser([
'use text format test_format',
'bypass node access',
]));
}
/**
* Confirms tables convert to the expected markup.
*/
public function testTableConversion() {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
// This is CKEditor 5's default table markup, but uses elements that are
// not allowed by the text format.
$this->host->body->value = '<figure class="table"><table><tbody><tr><td>table cell</td></tr></tbody></table> <figcaption>some caption</figcaption></figure>';
$this->host->save();
$this->drupalGet($this->host->toUrl('edit-form'));
$this->captionText = 'some caption';
$this->tableCellText = 'table cell';
$table_container = $assert_session->waitForElementVisible('css', 'figure.table');
$this->assertNotNull($table_container);
$caption = $page->find('css', 'figure.table > figcaption');
$this->assertEquals($this->captionText, $caption->getText());
$table = $page->find('css', 'figure.table > table');
$this->assertEquals($this->tableCellText, $table->getText());
$this->assertTableStructureInEditorData();
$this->assertTableStructureInRenderedPage();
}
/**
* Tests creating a table with caption in the UI.
*/
public function testTableCaptionUi() {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
$this->drupalGet($this->host->toUrl('edit-form'));
$this->waitForEditor();
// Add a table via the editor buttons.
$table_button = $page->find('css', '.ck-dropdown button');
$table_button->click();
// Add a single table cell.
$grid_button = $assert_session->waitForElementVisible('css', '.ck-insert-table-dropdown-grid-box[data-row="1"][data-column="1"]');
$grid_button->click();
// Confirm the table has been added and no caption is present.
$this->assertNotNull($table_figure = $assert_session->waitForElementVisible('css', 'figure.table'));
$assert_session->elementNotExists('css', 'figure.table > figcaption');
// Enable captions and update caption content.
$caption_button = $this->getBalloonButton('Toggle caption on');
$caption_button->click();
$caption = $assert_session->waitForElementVisible('css', 'figure.table > figcaption');
$this->assertEmpty($caption->getText());
$this->getSession()->getDriver()->executeScript("document.querySelector('figure.table > figcaption').innerText = '$this->captionText'");
$this->assertEquals($this->captionText, $caption->getText());
// Update table cell content.
$this->getSession()->getDriver()->executeScript("document.querySelector('.ck-editor__nested-editable .ck-table-bogus-paragraph').innerText = '$this->tableCellText'");
$table_cell = $page->find('css', 'figure.table > table > tbody > tr > td');
$this->assertEquals($this->tableCellText, $table_cell->getText());
$this->assertTableStructureInEditorData();
// Disable caption, confirm the caption is no longer present.
$table_figure->click();
$caption_off_button = $this->getBalloonButton('Toggle caption off');
$caption_off_button->click();
$assert_session->assertNoElementAfterWait('css', 'figure.table > figcaption');
// Re-enable caption and confirm the value was retained.
$table_figure->click();
$caption_on_button = $this->getBalloonButton('Toggle caption on');
$caption_on_button->click();
$caption = $assert_session->waitForElementVisible('css', 'figure.table > figcaption');
$this->assertEquals($this->captionText, $caption->getText());
$this->assertTableStructureInRenderedPage();
}
/**
* Confirms the structure of the table within the editor data.
*/
public function assertTableStructureInEditorData(): void {
$xpath = new \DOMXPath($this->getEditorDataAsDom());
$this->assertEmpty($xpath->query('//figure'), 'There should be no figure tag in editor data');
$this->assertNotEmpty($xpath->query('//table/caption'), 'A caption should be the immediate child of <table>');
$this->assertEquals($this->captionText, (string) $xpath->query('//table/caption')[0]->nodeValue, "The caption should say {$this->captionText}");
$this->assertNotEmpty($xpath->query('//table/tbody/tr/td'), 'There is an expected table structure.');
$this->assertEquals($this->tableCellText, (string) $xpath->query('//table/tbody/tr/td')[0]->nodeValue, "The table cell should say {$this->tableCellText}");
}
/**
* Confirms the saved page has the expected table structure.
*/
public function assertTableStructureInRenderedPage(): void {
$assert_session = $this->assertSession();
$page = $this->getSession()->getPage();
$page->pressButton('Save');
$assert_session->waitForText('has been updated');
$assert_session->pageTextContains($this->tableCellText);
$assert_session->pageTextContains($this->captionText);
$assert_session->elementNotExists('css', 'figure');
$this->assertNotNull($table_cell = $page->find('css', 'table > tbody > tr > td'), 'Table on rendered page has expected structure');
$this->assertEquals($this->tableCellText, $table_cell->getText(), 'Table on rendered page has expected content');
$this->assertNotNull($table_caption = $page->find('css', 'table > caption '), 'Table caption is in expected structure.');
$this->assertEquals($this->captionText, $table_caption->getText(), 'Table caption has expected text');
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment