ultisuite-client/lib/strip-hidden-email-html.ts
R3D347HR4Y 8a02c10ba3 Add environment configuration and update email view components
- Created a .cursorignore file to manage local environment files.
- Updated .env.example to reflect changes in the public app URL.
- Modified the gmail workspace configuration to include the drive-suite path.
- Enhanced email view components to support attachment handling and fallback for plain text bodies.
- Improved user experience by updating attachment display logic and integrating inline attachment support.
2026-06-04 00:12:43 +02:00

66 lines
2.0 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|visibility\s*:\s*hidden/i
const HIDDEN_CLASS = /mcnPreviewText|preheader|preview-text/i
const INVISIBLE_RUN = /[\u034f\u200b-\u200f\ufeff\u00a0]{4,}/g
function hasSignificantChildElements(el: Element): boolean {
for (const child of el.children) {
const tag = child.tagName.toLowerCase()
if (tag === "br" || tag === "wbr" || tag === "hr") continue
return true
}
return false
}
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, "")
if (
HIDDEN_STYLE.test(style) ||
(compact.includes("overflow:hidden") && /max-height\s*:\s*0/.test(style))
) {
return true
}
if (/font-size\s*:\s*0/i.test(style) && !hasSignificantChildElements(el)) {
return true
}
return false
}
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
}
}
/** Strip invisible padding; keep line breaks (do not collapse plain-text quotes). */
export function stripInvisibleTextRuns(text: string): string {
return text
.replace(INVISIBLE_RUN, " ")
.split("\n")
.map((line) => line.replace(/[^\S\n]+/g, " ").trimEnd())
.join("\n")
.replace(/\n{3,}/g, "\n\n")
.trim()
}