Bugfix: new CSS <style> removing (background-)?color failed

This commit is contained in:
the-djmaze 2023-02-14 16:51:51 +01:00
parent 492f1d4b10
commit bd9e50f222
2 changed files with 82 additions and 89 deletions

View file

@ -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;
}
}

View file

@ -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();
}