mirror of
https://github.com/the-djmaze/snappymail.git
synced 2024-09-20 07:35:55 +08:00
cleanHtml use allowedTags instead of disallowedTags and improved CSS handling
This commit is contained in:
parent
05812c6be1
commit
cfbc47488a
|
@ -17,14 +17,34 @@ const
|
||||||
"'": '''
|
"'": '''
|
||||||
},
|
},
|
||||||
|
|
||||||
disallowedTags = [
|
keepTagContent = 'form,button,data', // font
|
||||||
'svg','script','title','link','base','meta',
|
|
||||||
'input','output','select','button','textarea',
|
allowedTags = [
|
||||||
'bgsound','keygen','source','object','embed','applet','iframe','frame','frameset','video','audio','area','map'
|
// Structural Elements:
|
||||||
// not supported by <template> element
|
'blockquote','br','div','figcaption','figure','h1','h2','h3','h4','h5','h6','hgroup','hr','p','wbr',
|
||||||
// ,'html','head','body'
|
'article','aside','header','footer','main','section',
|
||||||
|
'details','summary',
|
||||||
|
// List Elements
|
||||||
|
'dd','dl','dt','li','ol','ul',
|
||||||
|
// Text Formatting Elements
|
||||||
|
'a','abbr','address','b','bdi','bdo','cite','code','del','dfn',
|
||||||
|
'em','i','ins','kbd','mark','pre','q','rp','rt','ruby','s','samp','small',
|
||||||
|
'span','strong','sub','sup','time','u','var',
|
||||||
|
// Deprecated by HTML Standard
|
||||||
|
'acronym','big','center','dir','font','marquee',
|
||||||
|
'nobr','noembed','noframes','plaintext','rb','rtc','strike','tt',
|
||||||
|
// Media Elements
|
||||||
|
'img',//'picture','source',
|
||||||
|
// Table Elements
|
||||||
|
'caption','col','colgroup','table','tbody','td','tfoot','th','thead','tr',
|
||||||
|
// Disallowed but converted later
|
||||||
|
'style','xmp'
|
||||||
].join(','),
|
].join(','),
|
||||||
|
|
||||||
|
nonEmptyTags = [
|
||||||
|
'A','B','EM','I','SPAN','STRONG'
|
||||||
|
],
|
||||||
|
|
||||||
blockquoteSwitcher = () => {
|
blockquoteSwitcher = () => {
|
||||||
SettingsUserStore.collapseBlockquotes() &&
|
SettingsUserStore.collapseBlockquotes() &&
|
||||||
// tmpl.content.querySelectorAll('blockquote').forEach(node => {
|
// tmpl.content.querySelectorAll('blockquote').forEach(node => {
|
||||||
|
@ -102,8 +122,10 @@ const
|
||||||
},
|
},
|
||||||
|
|
||||||
cleanCSS = source =>
|
cleanCSS = source =>
|
||||||
source.trim().replace(/(^|;)\s*-(ms|webkit)-[^;]+(;|$)/g, '')
|
source.trim()
|
||||||
.replace(/white-space[^;]+(;|$)/g, '')
|
.replace(/;\s*-[^;]+/g, '')
|
||||||
|
.replace(/^\s*-[^;]+(;|$)/g, '')
|
||||||
|
.replace(/white-space[^;]+/g, '')
|
||||||
// Drop Microsoft Office style properties
|
// Drop Microsoft Office style properties
|
||||||
// .replace(/mso-[^:;]+:[^;]+/gi, '')
|
// .replace(/mso-[^:;]+:[^;]+/gi, '')
|
||||||
,
|
,
|
||||||
|
@ -145,14 +167,14 @@ const
|
||||||
if (source) {
|
if (source) {
|
||||||
source = source
|
source = source
|
||||||
// strip comments
|
// strip comments
|
||||||
.replace(/\/\*[\s\S]*?\*\/|<!--|-->/gi, '')
|
.replace(/\/\*[\s\S]*?\*\//gi, '')
|
||||||
// strip import statements
|
// strip MS Word comments
|
||||||
.replace(/@import .*?;/gi , '')
|
.replace(/<!--[\s\S]*?-->/gi, '');
|
||||||
// strip keyframe statements
|
// strip HTML
|
||||||
.replace(/((@.*?keyframes [\s\S]*?){([\s\S]*?}\s*?)})/gi, '');
|
// .replace(/<\/?[a-z][\s\S]*?>/gi, '');
|
||||||
|
|
||||||
// unified regex to match css & media queries together
|
// 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,
|
let unified = /(?:(\s*?@(?:media)[\s\S]*?){([\s\S]*?)}\s*?})|(?:([\s\S]*?){([\s\S]*?)})/gi,
|
||||||
arr;
|
arr;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -161,7 +183,7 @@ const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let selector = arr[arr[2] === undefined ? 5 : 2].split('\r\n').join('\n').trim()
|
let selector = arr[arr[2] === undefined ? 3 : 1].split('\r\n').join('\n').trim()
|
||||||
// Never have more than a single line break in a row
|
// Never have more than a single line break in a row
|
||||||
.replace(/\n+/, "\n")
|
.replace(/\n+/, "\n")
|
||||||
// Remove :root and html
|
// Remove :root and html
|
||||||
|
@ -173,13 +195,14 @@ const
|
||||||
css.push({
|
css.push({
|
||||||
selector: selector,
|
selector: selector,
|
||||||
type: 'media',
|
type: 'media',
|
||||||
subStyles: parseCSS(arr[3] + '\n}') //recursively parse media query inner css
|
subStyles: parseCSS(arr[2] + '\n}') //recursively parse media query inner css
|
||||||
});
|
});
|
||||||
} else if (selector && !selector.includes('@')) {
|
} else if (selector && !selector.includes('@')) {
|
||||||
// we have standard css
|
// we have standard css
|
||||||
|
// ignores @import, @keyframe, @font-face statements
|
||||||
css.push({
|
css.push({
|
||||||
selector: selector,
|
selector: selector,
|
||||||
rules: cleanCSS(arr[6])
|
rules: cleanCSS(arr[4])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -258,9 +281,6 @@ export const
|
||||||
'abbr', 'scope',
|
'abbr', 'scope',
|
||||||
// td
|
// td
|
||||||
'colspan', 'rowspan', 'headers'
|
'colspan', 'rowspan', 'headers'
|
||||||
],
|
|
||||||
nonEmptyTags = [
|
|
||||||
'A','B','EM','I','SPAN','STRONG'
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (SettingsUserStore.allowStyles()) {
|
if (SettingsUserStore.allowStyles()) {
|
||||||
|
@ -307,13 +327,21 @@ export const
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// https://github.com/the-djmaze/snappymail/issues/1125
|
||||||
|
tmpl.content.querySelectorAll(keepTagContent).forEach(oElement => replaceWithChildren(oElement));
|
||||||
|
|
||||||
tmpl.content.querySelectorAll(
|
tmpl.content.querySelectorAll(
|
||||||
disallowedTags
|
':not('+allowedTags+')'
|
||||||
+ (0 < bqLevel ? ',' + (new Array(1 + bqLevel).fill('blockquote').join(' ')) : '')
|
+ (0 < bqLevel ? ',' + (new Array(1 + bqLevel).fill('blockquote').join(' ')) : '')
|
||||||
).forEach(oElement => oElement.remove());
|
).forEach(oElement => oElement.remove());
|
||||||
|
/* // Is this slower or faster?
|
||||||
// https://github.com/the-djmaze/snappymail/issues/1125
|
).forEach(oElement => {
|
||||||
tmpl.content.querySelectorAll('form,button').forEach(oElement => replaceWithChildren(oElement));
|
if (!node || !node.contains(oElement)) {
|
||||||
|
oElement.remove();
|
||||||
|
node = oElement;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
|
||||||
// https://github.com/the-djmaze/snappymail/issues/1641
|
// https://github.com/the-djmaze/snappymail/issues/1641
|
||||||
let body = tmpl.content.querySelector('.mail-body');
|
let body = tmpl.content.querySelector('.mail-body');
|
||||||
|
@ -346,6 +374,13 @@ export const
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ('XMP' === name) {
|
||||||
|
const pre = createElement('pre');
|
||||||
|
pre.innerHTML = encodeHtml(oElement.innerHTML);
|
||||||
|
oElement.replaceWith(pre);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// \MailSo\Base\HtmlUtils::ClearTags()
|
// \MailSo\Base\HtmlUtils::ClearTags()
|
||||||
if ('none' == oStyle.display
|
if ('none' == oStyle.display
|
||||||
|| 'hidden' == oStyle.visibility
|
|| 'hidden' == oStyle.visibility
|
||||||
|
@ -432,7 +467,7 @@ export const
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (['CENTER','FORM'].includes(name)) {
|
// if (['CENTER','FORM'].includes(name)) {
|
||||||
if ('O:P' === name || (nonEmptyTags.includes(name) && ('' == oElement.textContent.trim()))) {
|
if (nonEmptyTags.includes(name) && ('' == oElement.textContent.trim())) {
|
||||||
('A' !== name || !oElement.querySelector('IMG')) && replaceWithChildren(oElement);
|
('A' !== name || !oElement.querySelector('IMG')) && replaceWithChildren(oElement);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue