Neah/lib/utils/email-formatter.ts
2025-05-01 10:31:52 +02:00

154 lines
4.0 KiB
TypeScript

/**
* DEPRECATED - USE email-utils.ts INSTEAD
*
* This file is maintained for backward compatibility only.
* New code should import directly from email-utils.ts, which contains
* the canonical implementations of these functions.
*/
import { sanitizeHtml } from './dom-purify-config';
import { formatEmailAddresses, formatEmailDate, formatReplyEmail, formatForwardedEmail, formatEmailForReplyOrForward } from './email-utils';
import { applyTextDirection } from './text-direction';
import type { EmailMessage, EmailAddress } from '@/types/email';
// Re-export the functions from email-utils for backward compatibility
export {
formatEmailAddresses,
formatEmailDate,
formatReplyEmail,
formatForwardedEmail,
formatEmailForReplyOrForward,
sanitizeHtml
};
// Re-export types for backward compatibility
export type { EmailAddress, EmailMessage };
/**
* Format a date in a relative format
* Simple implementation for email display
*/
function formatDateRelative(date: Date): string {
if (!date) return '';
try {
return date.toLocaleString('en-US', {
weekday: 'short',
year: 'numeric',
month: 'short',
day: 'numeric',
hour: '2-digit',
minute: '2-digit'
});
} catch (e) {
return date.toString();
}
}
/**
* Parse text and find URLs to turn into clickable links
* This is a utility function used only in this file
*/
function parseUrlsToLinks(text: string): string {
const urlRegex = /(https?:\/\/[^\s]+)/g;
return text.replace(
urlRegex,
url => `<a href="${url}" target="_blank" rel="noopener noreferrer">${url}</a>`
);
}
/**
* Convert plain text email content to HTML with proper line breaks
* This is a utility function used only in this file
*/
function textToHtml(text: string): string {
if (!text) return '';
// Escape HTML characters first
const escaped = text
.replace(/&/g, '&amp;')
.replace(/</g, '&lt;')
.replace(/>/g, '&gt;')
.replace(/"/g, '&quot;')
.replace(/'/g, '&#39;');
// Convert line breaks and wrap in a div
const withLineBreaks = escaped.replace(/\n/g, '<br>');
// Parse URLs to make them clickable
const withLinks = parseUrlsToLinks(withLineBreaks);
return withLinks;
}
/**
* Decode compose content from MIME format to HTML and text
*/
export async function decodeComposeContent(content: string): Promise<{
html: string | null;
text: string | null;
}> {
if (!content.trim()) {
return { html: null, text: null };
}
try {
const response = await fetch('/api/parse-email', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ email: content }),
});
if (!response.ok) {
throw new Error('Failed to parse email');
}
const parsed = await response.json();
// Apply sanitization to the parsed content
return {
html: parsed.html ? sanitizeHtml(parsed.html) : null,
text: parsed.text || null
};
} catch (error) {
console.error('Error parsing email content:', error);
// Fallback to basic content handling with sanitization
return {
html: sanitizeHtml(content),
text: content
};
}
}
/**
* Encode compose content to MIME format for sending
*/
export function encodeComposeContent(content: string): string {
if (!content.trim()) {
throw new Error('Email content is empty');
}
// Create MIME headers
const mimeHeaders = {
'MIME-Version': '1.0',
'Content-Type': 'text/html; charset="utf-8"',
'Content-Transfer-Encoding': 'quoted-printable'
};
// Combine headers and content
return Object.entries(mimeHeaders)
.map(([key, value]) => `${key}: ${value}`)
.join('\n') + '\n\n' + content;
}
// Utility function to get the reply subject line
export function getReplySubject(subject: string): string {
return subject.startsWith('Re:') ? subject : `Re: ${subject}`;
}
// Utility function to get the forward subject line
export function getForwardSubject(subject: string): string {
return subject.startsWith('Fwd:') ? subject : `Fwd: ${subject}`;
}