courrier clean 2$
This commit is contained in:
parent
3e6b8cae1f
commit
4c9fcdeb29
@ -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>
|
||||
|
||||
@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user