Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ckedito5 patch for table cell resize #533

Merged
merged 11 commits into from
Nov 25, 2024
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,8 @@
},
"config": {
"allow-plugins": {
"composer/installers": true
"composer/installers": true,
"oomphinc/composer-installers-extender": true
}
}
}
2 changes: 1 addition & 1 deletion config/install/filter.format.rich_text.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ filters:
status: true
weight: -49
settings:
allowed_html: '<embedded-content data-plugin-config data-plugin-id> <a title class id target rel data-entity-type data-entity-uuid data-entity-substitution hreflang href> <div class> <p class="wysiwyg-callout quotation__quote text-align-left text-align-center text-align-right text-align-justify"> <br> <h2 id class="text-align-left text-align-center text-align-right text-align-justify"> <h3 id class="text-align-left text-align-center text-align-right text-align-justify"> <h4 id class="text-align-left text-align-center text-align-right text-align-justify"> <h5 id class="text-align-left text-align-center text-align-right text-align-justify"> <ol class type reversed start> <ul class type> <cite> <dl> <dt> <dd> <footer> <span class> <img src alt data-entity-type data-entity-uuid data-align data-caption> <iframe frameborder height scrolling src width title> <drupal-entity data-caption data-align data-entity-uuid data-entity-embed-display data-entity-embed-display-settings data-show-last-updated title alt data-embed-button="node tide_media" data-entity-type="node media"> <blockquote cite class> <th align class rowspan colspan> <td align class rowspan colspan> <strong> <em> <code class="language-*"> <pre class="text-align-left text-align-center text-align-right text-align-justify"> <s> <sub> <sup> <li> <hr> <table> <tr> <thead> <tbody> <tfoot> <caption>'
allowed_html: '<embedded-content data-plugin-config data-plugin-id> <a title class id target rel data-entity-type data-entity-uuid data-entity-substitution hreflang href> <div class> <p class="wysiwyg-callout quotation__quote text-align-left text-align-center text-align-right text-align-justify"> <br> <h2 id class="text-align-left text-align-center text-align-right text-align-justify"> <h3 id class="text-align-left text-align-center text-align-right text-align-justify"> <h4 id class="text-align-left text-align-center text-align-right text-align-justify"> <h5 id class="text-align-left text-align-center text-align-right text-align-justify"> <ol class type reversed start> <ul class type> <cite> <dl> <dt> <dd> <footer> <span class> <img src alt data-entity-type data-entity-uuid data-align data-caption> <iframe frameborder height scrolling src width title> <drupal-entity data-caption data-align data-entity-uuid data-entity-embed-display data-entity-embed-display-settings data-show-last-updated title alt data-embed-button="node tide_media" data-entity-type="node media"> <blockquote cite class> <th align class rowspan colspan> <td align class rowspan colspan> <strong> <em> <code class="language-*"> <pre class="text-align-left text-align-center text-align-right text-align-justify"> <s> <sub> <sup> <li> <hr> <table> <tr> <thead> <tbody> <tfoot> <caption> <colgroup> <col> <col style>'
filter_html_help: true
filter_html_nofollow: false
filter_autop:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
yarn-error.log
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
ckeditor_tablecol_resize_tableColResize:
ckeditor5:
plugins:
- table.TableColumnResize
- tableColResize.TableColResize
config:
tableColResize:
dataAttribute: data-resize-width
drupal:
label: Table Column Resize
library: ckeditor_tablecol_resize/editor
conditions:
filter: filter_resize_tablecolumns
plugins:
- ckeditor5_table
elements:
- <table data-resize-width>
- <colgroup>
- <col>
- <col data-resize-width>
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
name: Ckeditor Table Column Resize
type: module
description: Provides a ckeditor5 plugin that allows resizing of table columns
package: Custom
core_version_requirement: ^9.4 || ^10
dependencies:
- drupal:tide_ckeditor
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
editor:
js:
js/build/tableColResize.js: { preprocess: false, minified: true }
dependencies:
- ckeditor5/ckeditor5
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "drupal/ckeditor_tablecol_resize",
"description": "Provides a ckeditor5 plugin that allows resizing of table columns.",
"type": "drupal-module",
"homepage": "https://drupal.org/project/ckeditor_tablecol_resize",
"authors": [
{
"name": "Sebastian Leu",
"homepage": "https://www.drupal.org/u/s_leu",
"role": "Maintainer"
}
],
"license": "GPL-2.0-or-later",
"minimum-stability": "dev"
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Plugin } from 'ckeditor5/src/core';
import TableColResizeEditing from './tablecolresizeediting';

class TableColResize extends Plugin {
/**
* @inheritDoc
*/
static get requires() {
return [ TableColResizeEditing ];
}

/**
* @inheritDoc
*/
static get pluginName() {
return 'TableColResize';
}
}

export default {
TableColResize,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import { Plugin } from 'ckeditor5/src/core';

export default class TableColResizeEditing extends Plugin {

/**
* @inheritDoc
*/
static get pluginName() {
return 'TableColResizeEditing';
}

/**
* @inheritDoc
*/
afterInit() {
if ( this.editor.plugins.has( 'TableColumnResizeEditing' ) ) {
this._registerConverters();
}
}

/**
* Registers converters necessary for column resizing.
*/
_registerConverters() {
const editor = this.editor;
const dataAttribute = editor.config._config.tableColResize.dataAttribute;

// Converts the width style of a tableColumn model into a data attribute on
// the <col> view.
editor.conversion.for( 'downcast' ).add( dispatcher =>
dispatcher.on( 'attribute:columnWidth:tableColumn', ( evt, data, conversionApi ) => {
const viewWriter = conversionApi.writer;
const elementView = conversionApi.mapper.toViewElement( data.item );

if ( data.attributeNewValue !== null ) {
// The data attribute is set for applying the width via a style
// attribute when drupal renders the WYSIWYG content via the
// resize_tablecolumns_filter. We use a data attribute to work around
// the filter_html restriction that prohibits usage of the style
// attribute.
viewWriter.setAttribute( dataAttribute, data.attributeNewValue, elementView );
} else {
viewWriter.removeAttribute( dataAttribute, elementView );
}
} )
);

// Ensures that the value of the data-resize-width attribute is added to the
// ckeditor model when the editor loads.
editor.conversion.for( 'upcast' ).add( dispatcher =>
dispatcher.on( `element:col`, ( evt, data, conversionApi ) => {
const { schema, writer } = conversionApi;
const colWidth = data.viewItem.getAttribute( dataAttribute );
console.log('col upcast', colWidth);
sharmasahil marked this conversation as resolved.
Show resolved Hide resolved

// Do not go for the model element after data.modelCursor because it might happen
// that a single view element was converted to multiple model elements. Get all of them.
for ( const item of data.modelRange.getItems( { shallow: true } ) ) {
if ( schema.checkAttribute( item, 'columnWidth' ) ) {
writer.setAttribute( 'columnWidth', colWidth, item );
}
}
})
);

// Converts the width style of a table model into a data attribute on the
// <table> view.
editor.conversion.for( 'downcast' ).add( dispatcher =>
dispatcher.on( 'attribute:tableWidth:table', ( evt, data, conversionApi ) => {
const viewWriter = conversionApi.writer;
const elementView = conversionApi.mapper.toViewElement( data.item );

if ( data.attributeNewValue !== null ) {
// The data attribute is set for applying the width via a style
// attribute when drupal renders the WYSIWYG content via the
// resize_tablecolumns_filter. We use a data attribute to work around
// the filter_html restriction that prohibits usage of the style
// attribute.
viewWriter.setAttribute( dataAttribute, data.attributeNewValue, elementView );
} else {
viewWriter.removeAttribute( dataAttribute, elementView );
}
} )
);

// Ensures that the value of the data-resize-width attribute is added to the
// ckeditor model when the editor loads.
editor.conversion.for( 'upcast' ).add( dispatcher =>
dispatcher.on( `element:table`, ( evt, data, conversionApi ) => {
const { schema, writer } = conversionApi;
const tableWidth = data.viewItem.getAttribute( dataAttribute );

// Do not go for the model element after data.modelCursor because it might happen
// that a single view element was converted to multiple model elements. Get all of them.
for ( const item of data.modelRange.getItems( { shallow: true } ) ) {
if ( schema.checkAttribute( item, 'tableWidth' ) ) {
writer.setAttribute( 'tableWidth', tableWidth, item );
}
}
})
);

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "drupal-editor-material-icons",
"version": "2.0.0",
"description": "Add material icons to ckeditor.",
"author": "",
"license": "GPL-2.0-or-later",
"scripts": {
"watch": "webpack --mode development --watch",
"build": "webpack"
},
"devDependencies": {
"@ckeditor/ckeditor5-dev-utils": "^30.0.0",
"ckeditor5": "~35.1.0",
"css-loader": "^6.8.1",
"raw-loader": "^4.0.2",
"style-loader": "^3.3.3",
"terser-webpack-plugin": "^5.3.3",
"webpack": "^5.51.1",
"webpack-cli": "^4.4.0"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
<?php

namespace Drupal\ckeditor_tablecol_resize\Plugin\Filter;

use Drupal\ckeditor5\Plugin\CKEditor5PluginManagerInterface;
use Drupal\Component\Utility\Html;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Routing\CurrentRouteMatch;
use Drupal\filter\FilterProcessResult;
use Drupal\filter\Plugin\FilterBase;
use Psr\Container\ContainerInterface;

/**
* Provides a filter to apply resizing of table columns.
*
* @Filter(
* id = "filter_resize_tablecolumns",
* title = @Translation("Resize table columns"),
* description = @Translation("Uses a <code>data-resize-width</code> attribute on <code>&lt;col&gt;</code> tags to apply resizing of table columns. This filter needs to run after the <strong>Limit allowed HTML tags and correct faulty HTML</strong> filter."),
* type = Drupal\filter\Plugin\FilterInterface::TYPE_TRANSFORM_REVERSIBLE,
* weight = 99,
* )
*/
class FilterResizeTableColumns extends FilterBase implements ContainerFactoryPluginInterface {

protected CKEditor5PluginManagerInterface $ckeditor5PluginManager;

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
$instance = new static($configuration, $plugin_id, $plugin_definition);
$instance->ckeditor5PluginManager = $container->get('plugin.manager.ckeditor5.plugin');
return $instance;
}

/**
* {@inheritdoc}
*/
public function process($text, $langcode) {
$ckeditor5_plugin = $this->ckeditor5PluginManager
->createInstance('ckeditor_tablecol_resize_tableColResize');
$ckeditor5_plugin_config = $ckeditor5_plugin->getPluginDefinition()->getCkeditor5Config()['tableColResize'];
$column_data_attribute = $ckeditor5_plugin_config['dataAttribute'];
$result = new FilterProcessResult($text);

if (stristr($text, $column_data_attribute) !== FALSE) {
$dom = Html::load($text);
$xpath = new \DOMXPath($dom);

/** @var \DOMNode $node */
foreach ($xpath->query('//*[@' . $column_data_attribute . ']') as $node) {
$this->processDomNode($node, $column_data_attribute);
}

$result->setProcessedText(Html::serialize($dom));
}

return $result;
}

/**
* Adds a style and class attributes to passed DOMNode.
*/
private function processDomNode(\DOMNode $node, string $attribute) : void {
[, $attribute_value] = $this->getStyleAttributeFromNode($node, $attribute);
$node->setAttribute('style', $attribute_value);

// Set a class that allows targetting resized columns in CSS/JS.
$node->setAttribute(
'class',
$node->getAttribute('class')
? $node->getAttribute('class') . ' ckeditor-tablecol-resized'
: 'ckeditor-tablecol-resized'
);
}

/**
* {@inheritdoc}
*/
public function tips($long = FALSE) {
if ($long) {
return $this->t('
<p>Applies the resizing of tables and columns when rendering the ckeditor content in Drupal.</p>
<p>This works via a the <code>data-resize-width</code> attribute on <code><col></code> tags, for example: <code><col data-resize-width="99%"</code>.</p>
');
}
else {
return $this->t('Allows resizing of table columns by adding the <code>data-resize-width</code> attribute on <code><col></code> tags, for example: <code><col data-resize-width="99%"</code>.');
}
}

/**
* Gets $width from style attribute on given node and attribute.
*/
public function getStyleAttributeFromNode(\DOMNode $node, string $attribute): array {
$width = $node->getAttribute($attribute);
$node->removeAttribute($attribute);
$attribute_value = $node->getAttribute('style');

// Replace existing width style with new one.
$styles = \explode(';', $attribute_value);
$to_replace = '';
foreach ($styles as $style) {
if (\mb_strpos($style, 'width') === 0) {
$to_replace = $style;
break;
}
}
if ($to_replace) {
$attribute_value = \str_replace($to_replace, 'width:' . $width, $attribute_value);
}
else {
$attribute_value .= 'width:' . $width . ';';
}

return [(int) $width, $attribute_value];
}

}
Loading
Loading