[FIX] mass_mailing: prevent overriding font awesome font-family
When changing a font-family style in the design tab, we need to make sure we don't override the font-family of font awesome icons or it will break them. This takes font-family out of its selector and applies it to special selectors that exclude `.fa`. task-2821155 X-original-commit: d25b38969d1d0f2f791ad33f2591ea4f3b7b5ed8 Part-of: odoo/odoo#92138
This commit is contained in:
@@ -33,6 +33,16 @@ export const PRIORITY_STYLES = {
|
||||
export const RE_CSS_TEXT_MATCH = /([^{]+)([^}]+)/;
|
||||
export const RE_SELECTOR_ENDS_WITH_GT_STAR = />\s*\*\s*$/;
|
||||
|
||||
export const transformFontFamilySelector = selector => {
|
||||
if (selector.trim().endsWith(':not(.fa)')) {
|
||||
return [selector];
|
||||
}
|
||||
if (!selector.endsWith('*')) {
|
||||
return [`${selector.trim()}:not(.fa)`, `${selector.trim()} :not(.fa)`];
|
||||
} else if (RE_SELECTOR_ENDS_WITH_GT_STAR.test(selector)) {
|
||||
return [`${selector.replace(RE_SELECTOR_ENDS_WITH_GT_STAR, '').trim()} :not(.fa)`];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Take a css text and splits each comma-separated selector into separate
|
||||
* styles, applying the css prefix to each. Return the modified css text.
|
||||
@@ -47,16 +57,32 @@ export const splitCss = css => {
|
||||
document.head.appendChild(styleElement);
|
||||
const rules = [...styleElement.sheet.cssRules];
|
||||
styleElement.remove();
|
||||
const result = rules.map(rule => {
|
||||
const [, fullSelector, styles] = rule.cssText.match(RE_CSS_TEXT_MATCH);
|
||||
return fullSelector.split(',').map(selector => {
|
||||
const stylesToWrite = {};
|
||||
for (const rule of rules) {
|
||||
const styles = rule.style;
|
||||
for (let selector of rule.selectorText.split(',')) {
|
||||
if (!selector.trim().startsWith(CSS_PREFIX)) {
|
||||
selector = `${CSS_PREFIX} ${selector.trim()}`;
|
||||
}
|
||||
return `${selector.trim()} {${styles.replace('{', '').trim()}}`;
|
||||
}).join('');
|
||||
}).join('');
|
||||
return result;
|
||||
for (const style of rule.style) {
|
||||
let selectors = [selector];
|
||||
if (style === 'font-family') {
|
||||
// Ensure font-family gets passed to all descendants and never
|
||||
// overwrite font awesome.
|
||||
selectors = transformFontFamilySelector(selector);
|
||||
}
|
||||
for (const selectorToWriteTo of selectors) {
|
||||
if (!stylesToWrite[selectorToWriteTo]) {
|
||||
stylesToWrite[selectorToWriteTo] = [];
|
||||
}
|
||||
stylesToWrite[selectorToWriteTo].push([style, styles[style]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Object.entries(stylesToWrite).map(([selector, styles]) => (
|
||||
`${selector.trim()} {\n${styles.map(([styleName, style]) => ` ${styleName}: ${style};`).join('\n')}\n}`
|
||||
)).join('\n');
|
||||
};
|
||||
export const getFontName = fontFamily => fontFamily.split(',')[0].replace(/"/g, '').replace(/([a-z])([A-Z])/g, (v, a, b) => `${a} ${b}`).trim();
|
||||
export const normalizeFontFamily = fontFamily => fontFamily.replace(/"/g, '').replace(/, /g, ',');
|
||||
@@ -90,4 +116,5 @@ export default {
|
||||
CSS_PREFIX, BTN_SIZE_STYLES, DEFAULT_BUTTON_SIZE, PRIORITY_STYLES,
|
||||
RE_CSS_TEXT_MATCH, FONT_FAMILIES, RE_SELECTOR_ENDS_WITH_GT_STAR,
|
||||
splitCss, getFontName, normalizeFontFamily, initializeDesignTabCss,
|
||||
transformFontFamilySelector,
|
||||
}
|
||||
|
||||
@@ -6,9 +6,10 @@ const {ColorpickerWidget} = require('web.Colorpicker');
|
||||
const SelectUserValueWidget = options.userValueWidgetsRegistry['we-select'];
|
||||
const weUtils = require('web_editor.utils');
|
||||
const {
|
||||
CSS_PREFIX, BTN_SIZE_STYLES, RE_SELECTOR_ENDS_WITH_GT_STAR,
|
||||
CSS_PREFIX, BTN_SIZE_STYLES,
|
||||
DEFAULT_BUTTON_SIZE, PRIORITY_STYLES, FONT_FAMILIES,
|
||||
getFontName, normalizeFontFamily, initializeDesignTabCss
|
||||
getFontName, normalizeFontFamily, initializeDesignTabCss,
|
||||
transformFontFamilySelector,
|
||||
} = require('mass_mailing.design_constants');
|
||||
|
||||
|
||||
@@ -237,18 +238,16 @@ options.registry.DesignTab = options.Class.extend({
|
||||
if (params.cssProperty.includes('color')) {
|
||||
value = weUtils.normalizeColor(value);
|
||||
}
|
||||
const selectors = this._getSelectors(params.selectorText);
|
||||
let selectors = this._getSelectors(params.selectorText);
|
||||
const firstSelector = selectors[0].replace(CSS_PREFIX, '').trim();
|
||||
if (params.cssProperty === 'font-family') {
|
||||
// Ensure font-family gets passed to all descendants.
|
||||
selectors.push(...selectors.map(selector => selector + ' *'));
|
||||
// Ensure font-family gets passed to all descendants and never
|
||||
// overwrite font awesome.
|
||||
const newSelectors = [];
|
||||
for (const selector of selectors) {
|
||||
if (!selector.endsWith('*')) {
|
||||
selectors.push(`${selector} *`);
|
||||
} else if (RE_SELECTOR_ENDS_WITH_GT_STAR.test(selector)) {
|
||||
selectors.push(selector.replace(RE_SELECTOR_ENDS_WITH_GT_STAR, ' *'));
|
||||
}
|
||||
newSelectors.push(...transformFontFamilySelector(selector));
|
||||
}
|
||||
selectors = [...new Set(newSelectors)];
|
||||
}
|
||||
for (const selector of selectors) {
|
||||
const priority = PRIORITY_STYLES[firstSelector].includes(params.cssProperty) ? ' !important' : '';
|
||||
|
||||
Reference in New Issue
Block a user