44 lines
1.4 KiB
TypeScript
44 lines
1.4 KiB
TypeScript
/** Remove marketing preheader blocks before display (bluemonday strips display:none). */
|
|
|
|
const HIDDEN_STYLE =
|
|
/display\s*:\s*none|mso-hide\s*:\s*all|max-height\s*:\s*0|opacity\s*:\s*0|font-size\s*:\s*0|visibility\s*:\s*hidden/i
|
|
|
|
const HIDDEN_CLASS = /mcnPreviewText|preheader|preview-text/i
|
|
|
|
const INVISIBLE_RUN = /[\u034f\u200b-\u200f\ufeff\u00a0]{4,}/g
|
|
|
|
function shouldStripElement(el: Element): boolean {
|
|
if (el.hasAttribute("hidden")) return true
|
|
if (el.getAttribute("aria-hidden") === "true") return true
|
|
const cls = el.className?.toString() ?? ""
|
|
if (HIDDEN_CLASS.test(cls)) return true
|
|
const style = el.getAttribute("style") ?? ""
|
|
if (!style) return false
|
|
const compact = style.replace(/\s+/g, "")
|
|
return (
|
|
HIDDEN_STYLE.test(style) ||
|
|
(compact.includes("overflow:hidden") && /max-height\s*:\s*0/.test(style))
|
|
)
|
|
}
|
|
|
|
export function stripHiddenEmailHtml(html: string): string {
|
|
if (!html.trim() || typeof DOMParser === "undefined") {
|
|
return html
|
|
}
|
|
try {
|
|
const doc = new DOMParser().parseFromString(html, "text/html")
|
|
const remove: Element[] = []
|
|
doc.body.querySelectorAll("*").forEach((el) => {
|
|
if (shouldStripElement(el)) remove.push(el)
|
|
})
|
|
for (const el of remove) el.remove()
|
|
return doc.body.innerHTML
|
|
} catch {
|
|
return html
|
|
}
|
|
}
|
|
|
|
export function stripInvisibleTextRuns(text: string): string {
|
|
return text.replace(INVISIBLE_RUN, " ").replace(/\s+/g, " ").trim()
|
|
}
|