mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-07-11 00:14:50 +03:00
Bugfix: new CSS <style> removing (background-)?color failed
This commit is contained in:
parent
492f1d4b10
commit
bd9e50f222
2 changed files with 82 additions and 89 deletions
|
|
@ -1,84 +0,0 @@
|
|||
|
||||
export class CSS
|
||||
{
|
||||
/*
|
||||
Parses given css string, and returns css object
|
||||
keys as selectors and values are css rules
|
||||
eliminates all css comments before parsing
|
||||
|
||||
@param source css string to be parsed
|
||||
|
||||
@return object css
|
||||
*/
|
||||
parse(source) {
|
||||
|
||||
const css = [];
|
||||
|
||||
css.toString = () => css.reduce(
|
||||
(ret, tmp) =>
|
||||
ret + tmp.selector + ' {\n'
|
||||
+ (tmp.type === 'media' ? tmp.subStyles.toString() : tmp.rules)
|
||||
+ '}\n'
|
||||
,
|
||||
''
|
||||
);
|
||||
|
||||
/**
|
||||
* Given css array, parses it and then for every selector,
|
||||
* prepends namespace to prevent css collision issues
|
||||
*/
|
||||
css.applyNamespace = (namespace, prefix) => css.forEach(obj => {
|
||||
if (obj.type === 'media') {
|
||||
obj.subStyles.applyNamespace(namespace, prefix);
|
||||
} else {
|
||||
obj.selector = obj.selector.split(',').map(selector =>
|
||||
namespace + ' ' + selector.replace('.', '.'+prefix)
|
||||
).join(',');
|
||||
}
|
||||
});
|
||||
|
||||
if (source) {
|
||||
source = source
|
||||
// strip comments
|
||||
.replace(/\/\*[\s\S]*?\*\/|<!--|-->/gi, '')
|
||||
// strip import statements
|
||||
.replace(/@import .*?;/gi , '')
|
||||
// strip keyframe statements
|
||||
.replace(/((@.*?keyframes [\s\S]*?){([\s\S]*?}\s*?)})/gi, '');
|
||||
|
||||
// unified regex to match css & media queries together
|
||||
let unified = /((\s*?(?:\/\*[\s\S]*?\*\/)?\s*?@media[\s\S]*?){([\s\S]*?)}\s*?})|(([\s\S]*?){([\s\S]*?)})/gi,
|
||||
arr;
|
||||
|
||||
while (true) {
|
||||
arr = unified.exec(source);
|
||||
if (arr === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
let selector = arr[arr[2] === undefined ? 5 : 2].split('\r\n').join('\n').trim()
|
||||
// Never have more than a single line break in a row
|
||||
.replace(/\n+/, "\n");
|
||||
|
||||
// determine the type
|
||||
if (selector.includes('@media')) {
|
||||
// we have a media query
|
||||
css.push({
|
||||
selector: selector,
|
||||
type: 'media',
|
||||
subStyles: this.parse(arr[3] + '\n}') //recursively parse media query inner css
|
||||
});
|
||||
} else if (!selector.includes('@') && ![':root','html','body'].includes(selector)) {
|
||||
// we have standard css
|
||||
css.push({
|
||||
selector: selector,
|
||||
rules: arr[6]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return css;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,4 @@
|
|||
import { createElement } from 'Common/Globals';
|
||||
import { CSS } from 'Common/CSS';
|
||||
import { forEachObjectEntry, pInt } from 'Common/Utils';
|
||||
import { SettingsUserStore } from 'Stores/User/Settings';
|
||||
|
||||
|
|
@ -89,6 +88,83 @@ const
|
|||
});
|
||||
}
|
||||
return url;
|
||||
},
|
||||
|
||||
/*
|
||||
Parses given css string, and returns css object
|
||||
keys as selectors and values are css rules
|
||||
eliminates all css comments before parsing
|
||||
|
||||
@param source css string to be parsed
|
||||
|
||||
@return object css
|
||||
*/
|
||||
parseCSS = source => {
|
||||
const css = [];
|
||||
css.toString = () => css.reduce(
|
||||
(ret, tmp) =>
|
||||
ret + tmp.selector + ' {\n'
|
||||
+ (tmp.type === 'media' ? tmp.subStyles.toString() : tmp.rules)
|
||||
+ '}\n'
|
||||
,
|
||||
''
|
||||
);
|
||||
/**
|
||||
* Given css array, parses it and then for every selector,
|
||||
* prepends namespace to prevent css collision issues
|
||||
*/
|
||||
css.applyNamespace = (namespace, prefix) => css.forEach(obj => {
|
||||
if (obj.type === 'media') {
|
||||
obj.subStyles.applyNamespace(namespace, prefix);
|
||||
} else {
|
||||
obj.selector = obj.selector.split(',').map(selector =>
|
||||
namespace + ' ' + selector.replace('.', '.'+prefix)
|
||||
).join(',');
|
||||
}
|
||||
});
|
||||
|
||||
if (source) {
|
||||
source = source
|
||||
// strip comments
|
||||
.replace(/\/\*[\s\S]*?\*\/|<!--|-->/gi, '')
|
||||
// strip import statements
|
||||
.replace(/@import .*?;/gi , '')
|
||||
// strip keyframe statements
|
||||
.replace(/((@.*?keyframes [\s\S]*?){([\s\S]*?}\s*?)})/gi, '');
|
||||
|
||||
// unified regex to match css & media queries together
|
||||
let unified = /((\s*?(?:\/\*[\s\S]*?\*\/)?\s*?@media[\s\S]*?){([\s\S]*?)}\s*?})|(([\s\S]*?){([\s\S]*?)})/gi,
|
||||
arr;
|
||||
|
||||
while (true) {
|
||||
arr = unified.exec(source);
|
||||
if (arr === null) {
|
||||
break;
|
||||
}
|
||||
|
||||
let selector = arr[arr[2] === undefined ? 5 : 2].split('\r\n').join('\n').trim()
|
||||
// Never have more than a single line break in a row
|
||||
.replace(/\n+/, "\n");
|
||||
|
||||
// determine the type
|
||||
if (selector.includes('@media')) {
|
||||
// we have a media query
|
||||
css.push({
|
||||
selector: selector,
|
||||
type: 'media',
|
||||
subStyles: parseCSS(arr[3] + '\n}') //recursively parse media query inner css
|
||||
});
|
||||
} else if (!selector.includes('@') && ![':root','html','body'].includes(selector)) {
|
||||
// we have standard css
|
||||
css.push({
|
||||
selector: selector,
|
||||
rules: arr[6]
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return css;
|
||||
};
|
||||
|
||||
export const
|
||||
|
|
@ -209,13 +285,14 @@ export const
|
|||
oStyle = oElement.style;
|
||||
|
||||
if ('STYLE' === name) {
|
||||
if (msgId) {
|
||||
let css = new CSS().parse(oElement.textContent);
|
||||
let css = msgId ? parseCSS(oElement.textContent) : [];
|
||||
if (css.length) {
|
||||
css.applyNamespace(msgId, 'msg-');
|
||||
oElement.textContent = css;
|
||||
css = css.toString();
|
||||
if (SettingsUserStore.removeColors()) {
|
||||
oElement.textContent = oElement.textContent.replace(/(background-)color:[^};]+/g, '');
|
||||
css = css.replace(/(background-)?color:[^};]+;?/g, '');
|
||||
}
|
||||
oElement.textContent = css;
|
||||
} else {
|
||||
oElement.remove();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue