[FIX] web_editor: properly convert cards to tables

Cards need to be double wrapped in tables to be
displayed properly because of a bizarre hack by
bootstrap that uses background-color rather to give
the effect of a border, and because we can have
card-body be a sibling of a list-group.
Incidentally this also prevents the introduction of a
new row for each whitespace text node.

Part-of: odoo/odoo#83233
This commit is contained in:
Antoine Guenet
2022-01-24 15:09:27 +00:00
committed by David Monjoie
parent cc90b972f8
commit 1013b63571
2 changed files with 45 additions and 18 deletions
@@ -11,6 +11,7 @@ import { isBlock, rgbToHex } from '../../../lib/odoo-editor/src/utils/utils';
const RE_COL_MATCH = /(^| )col(-[\w\d]+)*( |$)/;
const RE_OFFSET_MATCH = /(^| )offset(-[\w\d]+)*( |$)/;
const RE_PADDING = /([\d.]+)/;
const RE_WHITESPACE = /[\s\u200b]*/;
const SELECTORS_IGNORE = /(^\*$|:hover|:before|:after|:active|:link|::|'|\([^(),]+[,(])/;
// Attributes all tables should have in a mailing.
const TABLE_ATTRIBUTES = {
@@ -248,25 +249,33 @@ function cardToTable($editable) {
const $card = $(card);
const $table = _createTable(card.attributes);
for (const child of [...card.childNodes]) {
if (child.nodeType === Node.TEXT_NODE) {
$table.append(child);
} else {
const $row = $('<tr/>');
const $col = $('<td/>');
if (child.nodeName === 'IMG') {
const $row = $('<tr/>');
const $col = $('<td/>');
if (child.nodeName === 'IMG') {
$col.append(child);
} else if (child.nodeType === Node.TEXT_NODE) {
if (child.textContent.replace(RE_WHITESPACE, '').length) {
$col.append(child);
} else {
for (const attr of child.attributes) {
$col.attr(attr.name, attr.value);
}
for (const descendant of [...child.childNodes]) {
$col.append(descendant);
}
$(child).remove();
continue;
}
$row.append($col);
$table.append($row);
} else {
for (const attr of child.attributes) {
$col.attr(attr.name, attr.value);
}
for (const descendant of [...child.childNodes]) {
$col.append(descendant);
}
$(child).remove();
}
const $subTable = _createTable();
const $superRow = $('<tr/>');
const $superCol = $('<td/>');
$row.append($col);
$subTable.append($row);
$superCol.append($subTable);
$superRow.append($superCol);
$table.append($superRow);
}
$card.before($table);
$card.remove();
@@ -251,9 +251,27 @@ QUnit.module('convert_inline', {}, function () {
assert.strictEqual($editable.html(),
getRegularTableHtml(3, 1, 12, 100)
.split('style="').join('class="card" style="')
.replace(/<td[^>]*>\(0, 0\)<\/td>/, '<td class="card-header"><span>HEADER</span></td>')
.replace(/<td[^>]*>\(1, 0\)<\/td>/, '<td class="card-body"><h2 class="card-title">TITLE</h2><small>BODY <img></small></td>')
.replace(/<td[^>]*>\(2, 0\)<\/td>/, '<td class="card-footer"><a href="#" class="btn">FOOTER</a></td>'),
.replace(/<td[^>]*>\(0, 0\)<\/td>/,
`<td>` +
`<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\" align=\"center\" ` +
`role=\"presentation\" style=\"width: 100% !important; border-collapse: collapse; text-align: inherit; ` +
`font-size: unset; line-height: unset;\"><tr>` +
`<td class="card-header"><span>HEADER</span></td>` +
`</tr></table></td>`)
.replace(/<td[^>]*>\(1, 0\)<\/td>/,
`<td>` +
`<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\" align=\"center\" ` +
`role=\"presentation\" style=\"width: 100% !important; border-collapse: collapse; text-align: inherit; ` +
`font-size: unset; line-height: unset;\"><tr>` +
`<td class="card-body"><h2 class="card-title">TITLE</h2><small>BODY <img></small></td>` +
`</tr></table></td>`)
.replace(/<td[^>]*>\(2, 0\)<\/td>/,
`<td>` +
`<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\" width=\"100%\" align=\"center\" ` +
`role=\"presentation\" style=\"width: 100% !important; border-collapse: collapse; text-align: inherit; ` +
`font-size: unset; line-height: unset;\"><tr>` +
`<td class="card-footer"><a href="#" class="btn">FOOTER</a></td>` +
`</tr></table></td>`),
"should have converted a card structure into a table");
});
QUnit.test('convert a list group to a table', async function (assert) {