diff --git a/addons/web_editor/static/src/js/backend/convert_inline.js b/addons/web_editor/static/src/js/backend/convert_inline.js
index fdaf3d9d7f0..2172d7731c9 100644
--- a/addons/web_editor/static/src/js/backend/convert_inline.js
+++ b/addons/web_editor/static/src/js/backend/convert_inline.js
@@ -23,9 +23,10 @@ const FONT_PROPERTIES_TO_INHERIT = [
'font-style',
'text-decoration',
'text-transform',
+ 'text-align',
];
// Attributes all tables should have in a mailing.
-const TABLE_ATTRIBUTES = {
+export const TABLE_ATTRIBUTES = {
cellspacing: 0,
cellpadding: 0,
border: 0,
@@ -34,11 +35,11 @@ const TABLE_ATTRIBUTES = {
role: 'presentation',
};
// Cancel tables default styles.
-const TABLE_STYLES = {
+export const TABLE_STYLES = {
'border-collapse': 'collapse',
'text-align': 'inherit',
'font-size': 'unset',
- 'line-height': 'unset',
+ 'line-height': 'inherit',
};
//--------------------------------------------------------------------------
@@ -450,11 +451,24 @@ function classToStyle($editable, cssRules) {
// Compute dynamic styles (var, calc).
writes.push(() => {
let computedStyle;
- for (let styleName of node.style) {
+ for (const styleName of node.style) {
const styleValue = node.style.getPropertyValue(styleName);
if (styleValue.includes('var(') || styleValue.includes('calc(')) {
computedStyle = computedStyle || getComputedStyle(node);
- node.style.setProperty(styleName, computedStyle[styleName]);
+ const prop = styleValue.includes('var(') ? styleValue.replace(/var\((.*)\)/, '$1') : styleName;
+ const value = computedStyle.getPropertyValue(prop) || computedStyle.getPropertyValue(styleName);
+ node.style.setProperty(styleName, value);
+ }
+ }
+ });
+
+ // Fix inheritance of font properties on Outlook.
+ writes.push(() => {
+ const propsToConvert = FONT_PROPERTIES_TO_INHERIT.filter(prop => node.style[prop] === 'inherit');
+ if (propsToConvert.length) {
+ const computedStyle = getComputedStyle(node);
+ for (const prop of propsToConvert) {
+ node.style.setProperty(prop, computedStyle[prop]);
}
}
});
@@ -668,7 +682,6 @@ async function toInline($editable, cssRules, $iframe) {
listGroupToTable(editable);
addTables($editable);
handleMasonry(editable);
- normalizeColors($editable);
const rootFontSizeProperty = getComputedStyle(editable.ownerDocument.documentElement).fontSize;
const rootFontSize = parseFloat(rootFontSizeProperty.replace(/[^\d\.]/g, ''));
normalizeRem($editable, rootFontSize);
@@ -676,6 +689,7 @@ async function toInline($editable, cssRules, $iframe) {
enforceTablesResponsivity(editable);
flattenBackgroundImages(editable);
formatTables($editable);
+ normalizeColors($editable);
responsiveToStaticForOutlook(editable);
// Fix Outlook image rendering bug.
for (const attributeName of ['width', 'height']) {
@@ -936,15 +950,18 @@ function formatTables($editable) {
}
}
}
- // Tables don't properly inherit alignments from their ancestors in Outlook.
+ // Tables don't properly inherit certain styles from their ancestors in Outlook.
for (const table of editable.querySelectorAll('table')) {
- if (table.style.textAlign === 'inherit') {
- let ancestor = table;
- while (ancestor && (!ancestor.style.textAlign || ancestor.style.textAlign === 'inherit')) {
- ancestor = ancestor.parentElement;
- }
- if (ancestor) {
- table.style.setProperty('text-align', ancestor.style.textAlign);
+ const propsToConvert = FONT_PROPERTIES_TO_INHERIT.filter(prop => table.style[prop] === 'inherit' || !table.style[prop]);
+ if (propsToConvert.length) {
+ for (const prop of propsToConvert) {
+ let ancestor = table;
+ while (ancestor && (!ancestor.style[prop] || ancestor.style[prop] === 'inherit')) {
+ ancestor = ancestor.parentElement;
+ }
+ if (ancestor) {
+ table.style.setProperty(prop, ancestor.style[prop]);
+ }
}
}
}
diff --git a/addons/web_editor/static/tests/convert_inline_tests.js b/addons/web_editor/static/tests/convert_inline_tests.js
index ca50c37d748..8455ef76bdd 100644
--- a/addons/web_editor/static/tests/convert_inline_tests.js
+++ b/addons/web_editor/static/tests/convert_inline_tests.js
@@ -308,21 +308,21 @@ QUnit.module('convert_inline', {}, function () {
`
` +
`` +
+ `font-size: unset; line-height: inherit;\"> ` +
`` +
`
| `)
.replace(/]*>\(1, 0\)<\/td>/,
` | ` +
`` +
+ `font-size: unset; line-height: inherit;\"> ` +
`TITLEBODY ![]() | ` +
`
| `)
.replace(/]*>\(2, 0\)<\/td>/,
` | ` +
`` +
+ `font-size: unset; line-height: inherit;\"> ` +
`` +
`
| `),
});
@@ -603,7 +603,7 @@ QUnit.module('convert_inline', {}, function () {
assert.strictEqual($editable.html(),
getRegularTableHtml(1, 1, 12, 100)
.split('style=').join('class="o_layout" style=')
- .replace(' font-size: unset; line-height: unset;', '') // o_layout keeps those default values
+ .replace(' font-size: unset; line-height: inherit;', '') // o_layout keeps those default values
.replace(/]*>\(0, 0\)/, ' | ' + getRegularTableHtml(1, 1, 12, 100).replace(/ | ]*>\(0, 0\)/, ' | Mailing ')),
"should have converted .o_layout to a special table structure with a table in it"
);
@@ -617,7 +617,7 @@ QUnit.module('convert_inline', {}, function () {
assert.strictEqual($editable.html(),
getRegularTableHtml(1, 1, 12, 100)
.split('style=').join('class="o_layout" style=')
- .replace(' font-size: unset; line-height: unset;', '') // o_layout keeps those default values
+ .replace(' font-size: unset; line-height: inherit;', '') // o_layout keeps those default values
.replace(/ | ]*>\(0, 0\)/, ' | '),
"should have converted .o_layout to a special table structure, keeping the table in it"
);
diff --git a/addons/web_editor/static/tests/test_utils.js b/addons/web_editor/static/tests/test_utils.js
index 66dc4683560..8e7df76622b 100644
--- a/addons/web_editor/static/tests/test_utils.js
+++ b/addons/web_editor/static/tests/test_utils.js
@@ -8,6 +8,7 @@ import Widget from "web.Widget";
import Wysiwyg from "web_editor.wysiwyg";
import options from "web_editor.snippets.options";
import { range } from "@web/core/utils/numbers";
+import { TABLE_ATTRIBUTES, TABLE_STYLES } from '@web_editor/js/backend/convert_inline';
const COLOR_PICKER_TEMPLATE = `
@@ -727,22 +728,8 @@ var textInput = function (target, char) {
// Convert Inline
//--------------------------------------------------------------------------
-const tableAttributes = {
- cellspacing: 0,
- cellpadding: 0,
- border: 0,
- width: '100%',
- align: 'center',
- role: 'presentation',
-};
-const tableAttributesString = Object.keys(tableAttributes).map(key => `${key}="${tableAttributes[key]}"`).join(' ');
-const tableStyles = {
- 'border-collapse': 'collapse',
- 'text-align': 'inherit',
- 'font-size': 'unset',
- 'line-height': 'unset',
-};
-const tableStylesString = Object.keys(tableStyles).map(key => `${key}: ${tableStyles[key]};`).join(' ');
+const tableAttributesString = Object.keys(TABLE_ATTRIBUTES).map(key => `${key}="${TABLE_ATTRIBUTES[key]}"`).join(' ');
+const tableStylesString = Object.keys(TABLE_STYLES).map(key => `${key}: ${TABLE_STYLES[key]};`).join(' ');
/**
* Take a matrix representing a grid and return an HTML string of the Bootstrap
* grid. The matrix is an array of rows, with each row being an array of cells.
|