courrier clean 2$

This commit is contained in:
alma 2025-04-26 19:20:52 +02:00
parent 3e6b8cae1f
commit 4c9fcdeb29
2 changed files with 71 additions and 14 deletions

View File

@ -11,10 +11,11 @@ import { Input } from '@/components/ui/input';
import { Card, CardContent, CardHeader, CardTitle, CardFooter } from '@/components/ui/card';
import DOMPurify from 'isomorphic-dompurify';
// Import the new email formatter utilities
// Import ONLY from the centralized formatter
import {
formatForwardedEmail,
formatReplyEmail,
formatReplyEmail,
formatEmailForReplyOrForward,
EmailMessage as FormatterEmailMessage
} from '@/lib/utils/email-formatter';
@ -169,7 +170,6 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
// For forwarding, use the dedicated formatter
const { subject, content } = formatForwardedEmail(formatterEmail);
setSubject(subject);
// Apply the formatted content directly without additional sanitization
setEmailContent(content);
} else {
// For reply/reply-all, use the reply formatter
@ -180,7 +180,6 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
setShowCc(true);
}
setSubject(subject);
// Apply the formatted content directly without additional sanitization
setEmailContent(content);
}
@ -258,7 +257,7 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
// Handle editor input without re-sanitizing content
const handleEditorInput = () => {
if (editorRef.current) {
// Capture innerHTML directly without reapplying DOMPurify
// Capture innerHTML directly without reapplying sanitization
setEmailContent(editorRef.current.innerHTML);
}
};
@ -307,7 +306,7 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
{/* Recipients, Subject fields remain the same */}
{/* Recipients, Subject fields */}
<div className="p-3 border-b space-y-2">
<div className="flex items-center">
<span className="w-16 text-sm font-medium">To:</span>
@ -391,7 +390,7 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
</div>
</div>
{/* Updated Email Body Editor */}
{/* Email Body Editor */}
<div className="space-y-2">
<div className="flex items-center justify-between">
<label htmlFor="body" className="text-sm font-medium">Message</label>
@ -415,7 +414,7 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
contentEditable={!sending}
className="w-full p-4 min-h-[300px] focus:outline-none"
onInput={handleEditorInput}
// Use dangerouslySetInnerHTML without sanitizing again
// Use dangerouslySetInnerHTML without sanitizing again to preserve our formatting
dangerouslySetInnerHTML={{ __html: emailContent }}
dir={isRTL ? 'rtl' : 'ltr'}
style={{
@ -425,7 +424,7 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
</div>
</div>
{/* Attachments section remains the same */}
{/* Attachments section */}
{attachments.length > 0 && (
<div className="border-t p-2">
<div className="text-sm font-medium mb-1">Attachments:</div>

View File

@ -1,9 +1,30 @@
/**
* Utilities for email formatting with proper text direction handling
* CENTRAL EMAIL FORMATTER
*
* This is the primary and only email formatting utility to be used.
* All email formatting should go through here to ensure consistent
* handling of text direction and HTML sanitization.
*/
import DOMPurify from 'isomorphic-dompurify';
// Configure DOMPurify to preserve direction attributes
DOMPurify.addHook('afterSanitizeAttributes', function(node) {
// Preserve direction attributes
if (node.hasAttribute('dir')) {
node.setAttribute('dir', node.getAttribute('dir') || 'ltr');
}
// Preserve text-align in styles
if (node.hasAttribute('style')) {
const style = node.getAttribute('style') || '';
if (style.includes('text-align')) {
// Keep existing alignment
} else if (node.hasAttribute('dir') && node.getAttribute('dir') === 'rtl') {
node.setAttribute('style', style + '; text-align: right;');
}
}
});
// Interface definitions
export interface EmailAddress {
name: string;
@ -73,17 +94,19 @@ export function formatEmailDate(date: Date | string | undefined): string {
/**
* Clean HTML content to prevent RTL/LTR issues
* This is the ONLY function that should be used for cleaning HTML content
*/
export function cleanHtmlContent(content: string): string {
if (!content) return '';
// First sanitize the HTML
// First sanitize the HTML with our configured DOMPurify
const sanitized = DOMPurify.sanitize(content);
// Process content to ensure consistent direction
let processed = sanitized;
// Replace RTL attributes with LTR
// Replace RTL attributes with LTR if needed
// We're now more careful to only modify direction attributes if needed
processed = processed.replace(/dir\s*=\s*["']rtl["']/gi, 'dir="ltr"');
processed = processed.replace(/style\s*=\s*["']([^"']*)direction\s*:\s*rtl;?([^"']*)["']/gi,
(match, before, after) => `style="${before}direction: ltr;${after}"`);
@ -92,7 +115,8 @@ export function cleanHtmlContent(content: string): string {
}
/**
* Format an email for forwarding
* Format an email for forwarding - CENTRAL IMPLEMENTATION
* All other formatting functions should be deprecated in favor of this one
*/
export function formatForwardedEmail(email: EmailMessage): {
subject: string;
@ -135,7 +159,8 @@ export function formatForwardedEmail(email: EmailMessage): {
}
/**
* Format an email for reply or reply-all
* Format an email for reply or reply-all - CENTRAL IMPLEMENTATION
* All other formatting functions should be deprecated in favor of this one
*/
export function formatReplyEmail(email: EmailMessage, type: 'reply' | 'reply-all'): {
to: string;
@ -205,4 +230,37 @@ export function formatReplyEmail(email: EmailMessage, type: 'reply' | 'reply-all
subject,
content
};
}
/**
* COMPATIBILITY LAYER: For backward compatibility with the old email-formatter.ts
* These functions map to our new implementation but preserve the old interface
*/
// For compatibility with old code that might be using the other email-formatter.ts
export function formatEmailForReplyOrForward(
email: EmailMessage,
type: 'reply' | 'reply-all' | 'forward'
): {
to: string;
cc?: string;
subject: string;
body: string;
} {
if (type === 'forward') {
const { subject, content } = formatForwardedEmail(email);
return {
to: '',
subject,
body: content
};
} else {
const { to, cc, subject, content } = formatReplyEmail(email, type as 'reply' | 'reply-all');
return {
to,
cc,
subject,
body: content
};
}
}