[FIX] web_editor: ensure valid RPC call to font_to_img

When inlining e-mails, we convert font icons to images by calling the
font_to_img route with the icon's dimensions. To get the icon's
dimensions, a call is made to `convert_inline`'s `_getWidth` and
`_getHeight` functions. These functions assume that calling
`getComputedStyle` on the icon to get its width/height will return a
value in pixels. However, this is not always the case. For example, if
the icon is in a hidden element, `getComputedStyle` can return "auto"
or whatever value is set in the icon's `style` attribute (e.g.,
"fit-content"). This commit ensures the return values of `_getWidth` and
`_getHeight` are always numbers as expected.

Doing this also reveals a false negative in the tests where the grid to
convert is not added to the DOM before calling `bootstrapToTable`. Since
`_getWidth` returned `NaN` in this case, `style.setProperty` failed
silently and no max-width was set on the cells. The tests didn't account
for the missing max-width, which now suddenly appeared with this fix
(NaN failed but 0 doesn't). This commit fixes the tests by adding the
grid to the DOM before calling `bootstrapToTable`, and adding the
expected max-width to the expected result.

X-original-commit: 73b404df9be1ba28a784711174cc19e7c599099e
Part-of: odoo/odoo#113784
This commit is contained in:
Antoine Guenet
2023-02-27 18:12:23 +01:00
parent ecfe8c890b
commit 282face688
3 changed files with 147 additions and 134 deletions
@@ -144,7 +144,7 @@ function bootstrapToTable($editable) {
for (const container of [...containers].filter(n => [...n.children].some(c => c.classList.contains('row')))) {
// The width of the table was stored in a temporary attribute. Fetch it
// for use in `_applyColspan` and remove the attribute at the end.
const containerWidth = container.getAttribute('o-temp-width');
const containerWidth = parseFloat(container.getAttribute('o-temp-width'));
// TABLE
const table = _createTable(container.attributes);
@@ -713,8 +713,8 @@ function fontToImg($editable) {
font.style.setProperty('line-height', 'normal');
const intrinsicWidth = _getWidth(font);
const intrinsicHeight = _getHeight(font);
const hPadding = width && (width - intrinsicWidth) / 2;
const vPadding = height && (height - intrinsicHeight) / 2;
const hPadding = width && intrinsicWidth && (width - intrinsicWidth) / 2;
const vPadding = height && intrinsicHeight && (height - intrinsicHeight) / 2;
let padding = '';
if (hPadding || vPadding) {
padding = vPadding ? vPadding + 'px ' : '0 ';
@@ -1338,7 +1338,7 @@ function _getStylePropertyValue(element, propertyName) {
* @returns {Number}
*/
function _getWidth(element) {
return parseFloat(getComputedStyle(element).width.replace('px', ''));
return parseFloat(getComputedStyle(element).width.replace('px', '')) || 0;
}
/**
* Equivalent to JQuery's `height` method. Returns the element's visible height.
@@ -1347,7 +1347,7 @@ function _getWidth(element) {
* @returns {Number}
*/
function _getHeight(element) {
return parseFloat(getComputedStyle(element).height.replace('px', ''));
return parseFloat(getComputedStyle(element).height.replace('px', '')) || 0;
}
/**
* Return true if the given element is hidden.
@@ -2,80 +2,89 @@
import convertInline from '@web_editor/js/backend/convert_inline';
import {getGridHtml, getTableHtml, getRegularGridHtml, getRegularTableHtml, removeComments} from 'web_editor.test_utils';
const TEST_WIDTH = 800;
const TEST_HEIGHT = 600;
const round = (value, precision = 2) => Math.round(value * 10**precision)/10**precision;
QUnit.module('web_editor', {}, function () {
QUnit.module('convert_inline', {}, function () {
QUnit.module('Convert Bootstrap grids to tables');
QUnit.module('Convert Bootstrap grids to tables', {
beforeEach: function () {
this.$editable = $(`<div style="width: ${TEST_WIDTH}px; height: ${TEST_HEIGHT}px;"/>`);
$('#qunit-fixture').append(this.$editable);
}
});
// Test bootstrapToTable, cardToTable and listGroupToTable
QUnit.test('convert a single-row regular grid', async function (assert) {
assert.expect(4);
// 1x1
let $editable = $(`<div>${getRegularGridHtml(1, 1)}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getRegularTableHtml(1, 1, 12, 100),
this.$editable.html(getRegularGridHtml(1, 1));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getRegularTableHtml(1, 1, 12, 100, TEST_WIDTH),
"should have converted a 1x1 grid to an equivalent table");
// 1x2
$editable = $(`<div>${getRegularGridHtml(1, 2)}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getRegularTableHtml(1, 2, 6, 50),
this.$editable.html(getRegularGridHtml(1, 2));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getRegularTableHtml(1, 2, 6, 50, TEST_WIDTH),
"should have converted a 1x2 grid to an equivalent table");
// 1x3
$editable = $(`<div>${getRegularGridHtml(1, 3)}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getRegularTableHtml(1, 3, 4, 33.33),
this.$editable.html(getRegularGridHtml(1, 3));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getRegularTableHtml(1, 3, 4, 33.33, TEST_WIDTH),
"should have converted a 1x3 grid to an equivalent table");
// 1x12
$editable = $(`<div>${getRegularGridHtml(1, 12)}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getRegularTableHtml(1, 12, 1, 8.33),
this.$editable.html(getRegularGridHtml(1, 12));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getRegularTableHtml(1, 12, 1, 8.33, TEST_WIDTH),
"should have converted a 1x12 grid to an equivalent table");
});
QUnit.test('convert a single-row regular overflowing grid', async function (assert) {
assert.expect(4);
// 1x13
let $editable = $(`<div>${getRegularGridHtml(1, 13)}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()),
getRegularTableHtml(1, 12, 1, 8.33).slice(0, -8) +
`<tr><td colspan="1">(0, 12)</td>` +
this.$editable.html(getRegularGridHtml(1, 13));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()),
getRegularTableHtml(1, 12, 1, 8.33, TEST_WIDTH).slice(0, -8) +
`<tr><td colspan="1" style="max-width: ${round(TEST_WIDTH/12)}px;">(0, 12)</td>` +
`<td colspan="11"></td></tr></table>`,
"should have converted a 1x13 grid to an equivalent table (overflowing)");
// 1x14
$editable = $(`<div>${getRegularGridHtml(1, 14)}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()),
getRegularTableHtml(1, 12, 1, 8.33).slice(0, -8) +
`<tr><td colspan="1">(0, 12)</td>` +
`<td colspan="1">(0, 13)</td>` +
this.$editable.html(getRegularGridHtml(1, 14));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()),
getRegularTableHtml(1, 12, 1, 8.33, TEST_WIDTH).slice(0, -8) +
`<tr><td colspan="1" style="max-width: ${round(TEST_WIDTH/12)}px;">(0, 12)</td>` +
`<td colspan="1" style="max-width: ${round(TEST_WIDTH/12)}px;">(0, 13)</td>` +
`<td colspan="10"></td></tr></table>`,
"should have converted a 1x14 grid to an equivalent table (overflowing)");
// 1x25
$editable = $(`<div>${getRegularGridHtml(1, 25)}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()),
getRegularTableHtml(1, 12, 1, 8.33).slice(0, -8) +
getRegularTableHtml(1, 12, 1, 8.33).replace(/\(0, (\d+)\)/g, (s, c) => `(0, ${+c + 12})`)
this.$editable.html(getRegularGridHtml(1, 25));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()),
getRegularTableHtml(1, 12, 1, 8.33, TEST_WIDTH).slice(0, -8) +
getRegularTableHtml(1, 12, 1, 8.33, TEST_WIDTH).replace(/\(0, (\d+)\)/g, (s, c) => `(0, ${+c + 12})`)
.replace(/^<table[^<]*>/, '').slice(0, -8) +
`<tr><td colspan="1">(0, 24)</td>` +
`<tr><td colspan="1" style="max-width: ${round(TEST_WIDTH/12)}px;">(0, 24)</td>` +
`<td colspan="11"></td></tr></table>`,
"should have converted a 1x25 grid to an equivalent table (overflowing)");
// 1x26
$editable = $(`<div>${getRegularGridHtml(1, 26)}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()),
getRegularTableHtml(1, 12, 1, 8.33).slice(0, -8) +
getRegularTableHtml(1, 12, 1, 8.33).replace(/\(0, (\d+)\)/g, (s, c) => `(0, ${+c + 12})`)
this.$editable.html(getRegularGridHtml(1, 26));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()),
getRegularTableHtml(1, 12, 1, 8.33, TEST_WIDTH).slice(0, -8) +
getRegularTableHtml(1, 12, 1, 8.33, TEST_WIDTH).replace(/\(0, (\d+)\)/g, (s, c) => `(0, ${+c + 12})`)
.replace(/^<table[^<]*>/, '').slice(0, -8) +
`<tr><td colspan="1">(0, 24)</td>` +
`<td colspan="1">(0, 25)</td>` +
`<tr><td colspan="1" style="max-width: ${round(TEST_WIDTH/12)}px;">(0, 24)</td>` +
`<td colspan="1" style="max-width: ${round(TEST_WIDTH/12)}px;">(0, 25)</td>` +
`<td colspan="10"></td></tr></table>`,
"should have converted a 1x26 grid to an equivalent table (overflowing)");
});
@@ -83,67 +92,67 @@ QUnit.module('convert_inline', {}, function () {
assert.expect(4);
// 2x1
let $editable = $(`<div>${getRegularGridHtml(2, 1)}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getRegularTableHtml(2, 1, 12, 100),
this.$editable.html(getRegularGridHtml(2, 1));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getRegularTableHtml(2, 1, 12, 100, TEST_WIDTH),
"should have converted a 2x1 grid to an equivalent table");
// 2x[1,2]
$editable = $(`<div>${getRegularGridHtml(2, [1, 2])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getRegularTableHtml(2, [1, 2], [12, 6], [100, 50], true),
this.$editable.html(getRegularGridHtml(2, [1, 2]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getRegularTableHtml(2, [1, 2], [12, 6], [100, 50], TEST_WIDTH),
"should have converted a 2x[1,2] grid to an equivalent table");
// 3x3
$editable = $(`<div>${getRegularGridHtml(3, 3)}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getRegularTableHtml(3, 3, 4, 33.33),
this.$editable.html(getRegularGridHtml(3, 3));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getRegularTableHtml(3, 3, 4, 33.33, TEST_WIDTH),
"should have converted a 3x3 grid to an equivalent table");
// 3x[3,2,1]
$editable = $(`<div>${getRegularGridHtml(3, [3,2,1])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getRegularTableHtml(3, [3, 2, 1], [4, 6, 12], [33.33, 50, 100], true),
this.$editable.html(getRegularGridHtml(3, [3,2,1]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getRegularTableHtml(3, [3, 2, 1], [4, 6, 12], [33.33, 50, 100], TEST_WIDTH),
"should have converted a 3x[3,2,1] grid to an equivalent table");
});
QUnit.test('convert a multi-row regular overflowing grid', async function (assert) {
assert.expect(4);
// 2x[13,1]
let $editable = $(`<div>${getRegularGridHtml(2, [13, 1])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()),
getRegularTableHtml(1, 12, 1, 8.33).slice(0, -8) +
`<tr><td colspan="1">(0, 12)</td>` +
this.$editable.html(getRegularGridHtml(2, [13, 1]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()),
getRegularTableHtml(1, 12, 1, 8.33, TEST_WIDTH).slice(0, -8) +
`<tr><td colspan="1" style="max-width: ${round(TEST_WIDTH/12)}px;">(0, 12)</td>` +
`<td colspan="11"></td></tr>` + // 13 overflowed the row by 1 -> fill up
`<tr><td colspan="12">(1, 0)</td></tr></table>`, // 1 col with no size == col-12
`<tr><td colspan="12" style="max-width: ${round(TEST_WIDTH)}px;">(1, 0)</td></tr></table>`, // 1 col with no size == col-12
"should have converted a 2x[13,1] grid to an equivalent table (overflowing)");
// 2x[1,13]
$editable = $(`<div>${getRegularGridHtml(2, [1, 13])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual($editable.html(),
getRegularTableHtml(2, [1, 12], [12, 1], [100, 8.33]).slice(0, -8) +
`<tr><td colspan="1">(1, 12)</td>` +
this.$editable.html(getRegularGridHtml(2, [1, 13]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(this.$editable.html(),
getRegularTableHtml(2, [1, 12], [12, 1], [100, 8.33], TEST_WIDTH).slice(0, -8) +
`<tr><td colspan="1" style="max-width: ${round(TEST_WIDTH/12)}px;">(1, 12)</td>` +
`<td colspan="11"></td></tr></table>`, // 13 overflowed the row by 1 -> fill up
"should have converted a 2x[1,13] grid to an equivalent table (overflowing)");
// 3x[1,13,6]
$editable = $(`<div>${getRegularGridHtml(3, [1, 13, 6])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual($editable.html(),
getRegularTableHtml(2, [1, 12], [12, 1], [100, 8.33]).slice(0, -8) +
`<tr><td colspan="1">(1, 12)</td>` +
this.$editable.html(getRegularGridHtml(3, [1, 13, 6]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(this.$editable.html(),
getRegularTableHtml(2, [1, 12], [12, 1], [100, 8.33], TEST_WIDTH).slice(0, -8) +
`<tr><td colspan="1" style="max-width: ${round(TEST_WIDTH/12)}px;">(1, 12)</td>` +
`<td colspan="11"></td></tr>` + // 13 overflowed the row by 1 -> fill up
getRegularTableHtml(1, 6, 2, 16.67).replace(/\(0,/g, `(2,`).replace(/^<table[^<]*>/, ''),
getRegularTableHtml(1, 6, 2, 16.67, TEST_WIDTH).replace(/\(0,/g, `(2,`).replace(/^<table[^<]*>/, ''),
"should have converted a 3x[1,13,6] grid to an equivalent table (overflowing)");
// 3x[1,6,13]
$editable = $(`<div>${getRegularGridHtml(3, [1, 6, 13])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual($editable.html(),
getRegularTableHtml(3, [1, 6, 12], [12, 2, 1], [100, 16.67, 8.33]).slice(0, -8) +
`<tr><td colspan="1">(2, 12)</td>` +
this.$editable.html(getRegularGridHtml(3, [1, 6, 13]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(this.$editable.html(),
getRegularTableHtml(3, [1, 6, 12], [12, 2, 1], [100, 16.67, 8.33], TEST_WIDTH).slice(0, -8) +
`<tr><td colspan="1" style="max-width: ${round(TEST_WIDTH/12)}px;">(2, 12)</td>` +
`<td colspan="11"></td></tr>` + // 13 overflowed the row by 1 -> fill up
`</table>`,
"should have converted a 3x[1,6,13] grid to an equivalent table (overflowing)");
@@ -152,96 +161,96 @@ QUnit.module('convert_inline', {}, function () {
assert.expect(2);
// 1x2
let $editable = $(`<div>${getGridHtml([[8, 4]])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getTableHtml([[[8, 66.67], [4, 33.33]]], true),
this.$editable.html(getGridHtml([[8, 4]]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getTableHtml([[[8, 66.67], [4, 33.33]]], TEST_WIDTH),
"should have converted a 1x2 irregular grid to an equivalent table");
// 1x3
$editable = $(`<div>${getGridHtml([[2, 3, 7]])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getTableHtml([[[2, 16.67], [3, 25], [7, 58.33]]], true),
this.$editable.html(getGridHtml([[2, 3, 7]]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getTableHtml([[[2, 16.67], [3, 25], [7, 58.33]]], TEST_WIDTH),
"should have converted a 1x3 grid to an equivalent table");
});
QUnit.test('convert a single-row irregular overflowing grid', async function (assert) {
assert.expect(2);
// 1x2
let $editable = $(`<div>${getGridHtml([[8, 5]])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getTableHtml([
this.$editable.html(getGridHtml([[8, 5]]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getTableHtml([
[[8, 66.67], [4, 33.33, '']],
[[5, 41.67, '(0, 1)'], [7, 58.33, '']],
], true),
], TEST_WIDTH),
"should have converted a 1x2 irregular overflowing grid to an equivalent table");
// 1x3
$editable = $(`<div>${getGridHtml([[7, 6, 9]])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getTableHtml([
this.$editable.html(getGridHtml([[7, 6, 9]]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getTableHtml([
[[7, 58.33], [5, 41.67, '']],
[[6, 50, '(0, 1)'], [6, 50, '']],
[[9, 75, '(0, 2)'], [3, 25, '']],
], true),
], TEST_WIDTH),
"should have converted a 1x3 irregular overflowing grid to an equivalent table");
});
QUnit.test('convert a multi-row irregular grid', async function (assert) {
assert.expect(2);
// 2x2
let $editable = $(`<div>${getGridHtml([[1, 11], [2, 10]])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getTableHtml([[[1, 8.33], [11, 91.67]], [[2, 16.67], [10, 83.33]]], true),
this.$editable.html(getGridHtml([[1, 11], [2, 10]]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getTableHtml([[[1, 8.33], [11, 91.67]], [[2, 16.67], [10, 83.33]]], TEST_WIDTH),
"should have converted a 2x2 irregular grid to an equivalent table");
// 2x[2,3]
$editable = $(`<div>${getGridHtml([[3, 9], [4, 6, 2]])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()), getTableHtml([[[3, 25], [9, 75]], [[4, 33.33], [6, 50], [2, 16.67]]], true),
this.$editable.html(getGridHtml([[3, 9], [4, 6, 2]]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()), getTableHtml([[[3, 25], [9, 75]], [[4, 33.33], [6, 50], [2, 16.67]]], TEST_WIDTH),
"should have converted a 2x[2,3] irregular grid to an equivalent table");
});
QUnit.test('convert a multi-row irregular overflowing grid', async function (assert) {
assert.expect(3);
// 2x2 (both rows overflow)
let $editable = $(`<div>${getGridHtml([[6, 8], [7, 9]])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()),
this.$editable.html(getGridHtml([[6, 8], [7, 9]]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()),
getTableHtml([
[[6, 50], [6, 50, '']],
[[8, 66.67, '(0, 1)'], [4, 33.33, '']],
[[7, 58.33, '(1, 0)'], [5, 41.67, '']],
[[9, 75, '(1, 1)'], [3, 25, '']],
], true),
], TEST_WIDTH),
"should have converted a 2x[1,13] irregular grid to an equivalent table (both rows overflowing)");
// 2x[2,3] (first row overflows)
$editable = $(`<div>${getGridHtml([[5, 8], [4, 2, 6]])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()),
this.$editable.html(getGridHtml([[5, 8], [4, 2, 6]]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()),
getTableHtml([
[[5, 41.67], [7, 58.33, '']],
[[8, 66.67, '(0, 1)'], [4, 33.33, '']],
[[4, 33.33, '(1, 0)'], [2, 16.67, '(1, 1)'], [6, 50, '(1, 2)']],
], true),
], TEST_WIDTH),
"should have converted a 2x[2,3] irregular grid to an equivalent table (first row overflowing)");
// 2x[3,2] (second row overflows)
$editable = $(`<div>${getGridHtml([[4, 2, 6], [5, 8]])}</div>`);
convertInline.bootstrapToTable($editable);
assert.strictEqual(removeComments($editable.html()),
this.$editable.html(getGridHtml([[4, 2, 6], [5, 8]]));
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(removeComments(this.$editable.html()),
getTableHtml([
[[4, 33.33], [2, 16.67], [6, 50]],
[[5, 41.67], [7, 58.33, '']],
[[8, 66.67, '(1, 1)'], [4, 33.33, '']],
], true),
], TEST_WIDTH),
"should have converted a 2x[3,2] irregular grid to an equivalent table (second row overflowing)");
});
QUnit.test('convert a card to a table', async function (assert) {
assert.expect(1);
const $editable = $(
`<div><div class="card">` +
this.$editable.html(
`<div class="card">` +
`<div class="card-header">` +
`<span>HEADER</span>` +
`</div>` +
@@ -252,9 +261,9 @@ QUnit.module('convert_inline', {}, function () {
`<div class="card-footer">` +
`<a href="#" class="btn">FOOTER</a>` +
`</div>` +
`</div></div>`);
convertInline.cardToTable($editable);
assert.strictEqual($editable.html(),
`</div>`);
convertInline.cardToTable(this.$editable);
assert.strictEqual(this.$editable.html(),
getRegularTableHtml(3, 1, 12, 100)
.replace('role=\"presentation\"', 'role=\"presentation\" class=\"card\"')
.replace(/<td[^>]*>\(0, 0\)<\/td>/,
@@ -283,8 +292,8 @@ QUnit.module('convert_inline', {}, function () {
QUnit.test('convert a list group to a table', async function (assert) {
assert.expect(1);
const $editable = $(
`<div><ul class="list-group list-group-flush">` +
this.$editable.html(
`<ul class="list-group list-group-flush">` +
`<li class="list-group-item">` +
`<strong>(0, 0)</strong>` +
`</li>` +
@@ -295,9 +304,9 @@ QUnit.module('convert_inline', {}, function () {
`<li class="list-group-item">` +
`<strong class="b">(2, 0)</strong>` +
`</li>` +
`</ul></div>`);
convertInline.listGroupToTable($editable);
assert.strictEqual($editable.html(),
`</ul>`);
convertInline.listGroupToTable(this.$editable);
assert.strictEqual(this.$editable.html(),
getRegularTableHtml(3, 1, 12, 100)
.split('style="').join('class="list-group-flush" style="')
.replace(/<td[^>]*>(\(0, 0\))<\/td>/, '<td><strong>$1</strong></td>')
@@ -308,19 +317,20 @@ QUnit.module('convert_inline', {}, function () {
QUnit.test('convert a grid with offsets to a table', async function (assert) {
assert.expect(2);
let $editable = $('<div><div class="container"><div class="row"><div class="col-6 offset-4">(0, 0)</div></div></div>');
convertInline.bootstrapToTable($editable);
assert.strictEqual($editable.html(),
getTableHtml([[[4, 33.33, ''], [6, 50, '(0, 0)'], [2, 16.67, '']]]),
this.$editable.html('<div class="container"><div class="row"><div class="col-6 offset-4">(0, 0)</div></div>');
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(this.$editable.html(),
getTableHtml([[[4, 33.33, ''], [6, 50, '(0, 0)'], [2, 16.67, '']]], TEST_WIDTH)
.replace(`<td colspan="2" style="max-width: ${round(TEST_WIDTH*2/12)}px;"></td>`, '<td colspan="2"></td>'),
"should have converted a column with an offset to two columns, then completed the column");
$editable = $('<div><div class="container"><div class="row"><div class="col-6 offset-4">(0, 0)</div><div class="col-6 offset-1">(0, 1)</div></div></div>');
convertInline.bootstrapToTable($editable);
assert.strictEqual($editable.html(),
this.$editable.html('<div class="container"><div class="row"><div class="col-6 offset-4">(0, 0)</div><div class="col-6 offset-1">(0, 1)</div></div>');
convertInline.bootstrapToTable(this.$editable);
assert.strictEqual(this.$editable.html(),
getTableHtml([
[[4, 33.33, ''], [6, 50, '(0, 0)'], [1, 8.33, ''], [1, 8.33, '']],
[[6, 50, '(0, 1)'], [6, 50, '']],
]),
[[6, 50, '(0, 1)'], [6, 50, '']]
], TEST_WIDTH),
"should have converted a column with an offset to two columns, then completed the column (overflowing)");
});
+10 -7
View File
@@ -780,7 +780,8 @@ function getGridHtml(matrix) {
* cell is represented by a tuple of numbers [colspan, width (in percent)]. A
* cell can have a string as third value to represent its text content. The
* default text content of each cell is its coordinates `(row index, column
* index)`.
* index)`. If the cell has a number as third value, it will be used as the
* max-width of the cell (in pixels).
* Eg: [ // <table> (note: extra attrs and styles apply)
* [ // <tr>
* [1, 8], // <td colspan="1" width="8%">(0, 0)</td>
@@ -792,17 +793,18 @@ function getGridHtml(matrix) {
* ], // </tr>
* ] // </table>
*
* @param {Array<Array<Array<[Number, Number, string?]>>>} matrix
* @param {Array<Array<Array<[Number, Number, string?, number?]>>>} matrix
* @param {Number} [containerWidth]
* @returns {string}
*/
function getTableHtml(matrix) {
function getTableHtml(matrix, containerWidth) {
return (
`<table ${tableAttributesString} style="width: 100% !important; ${tableStylesString}">` +
matrix.map((row, iRow) => (
`<tr>` +
row.map((col, iCol) => (
`<td colspan="${col[0]}">` +
(col.length === 3 ? col[2] : `(${iRow}, ${iCol})`) +
`<td colspan="${col[0]}"${containerWidth ? ` style="max-width: ${Math.round(containerWidth*col[0]/12*100)/100}px;"` : ''}>` +
(typeof col[2] === 'string' ? col[2] : `(${iRow}, ${iCol})`) +
`</td>`
)).join('') +
`</tr>`
@@ -841,16 +843,17 @@ function getRegularGridHtml(nRows, nCols) {
* @param {Number|Number[]} nCols
* @param {Number|Number[]} colspan
* @param {Number|Number[]} width
* @param {Number} containerWidth
* @returns {string}
*/
function getRegularTableHtml(nRows, nCols, colspan, width) {
function getRegularTableHtml(nRows, nCols, colspan, width, containerWidth) {
const matrix = new Array(nRows).fill().map((_, iRow) => (
new Array(Array.isArray(nCols) ? nCols[iRow] : nCols).fill().map(() => ([
Array.isArray(colspan) ? colspan[iRow] : colspan,
Array.isArray(width) ? width[iRow] : width,
])))
);
return getTableHtml(matrix);
return getTableHtml(matrix, containerWidth);
}
/**
* Take an HTML string and returns that string stripped from any HTML comments.