- 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.
66 lines
2.0 KiB
TypeScript
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()
|
|
}
|