')) {
// Content is likely HTML, sanitize using the centralized cleaner
- const sanitizedHtml = cleanHtmlContent(formattedEmail);
+ const sanitizedHtml = sanitizeHtml(formattedEmail);
setContent(
')) {
@@ -453,15 +453,15 @@ function EmailPreview({ email }: { email: Email }) {
try {
// If we have the content already, extract preview from it
if (email.content) {
- // Use cleanHtmlContent to safely extract text from HTML
- const cleanContent = cleanHtmlContent(email.content);
+ // Use sanitizeHtml to safely extract text from HTML
+ const cleanContent = sanitizeHtml(email.content);
const plainText = cleanContent.replace(/<[^>]*>/g, ' ').trim();
if (mounted) {
setPreview(plainText.substring(0, 150) + '...');
}
} else {
// Use the centralized cleaner instead of decodeEmail
- const cleanContent = cleanHtmlContent(email.content || '');
+ const cleanContent = sanitizeHtml(email.content || '');
const plainText = cleanContent.replace(/<[^>]*>/g, ' ').trim();
if (mounted) {
diff --git a/app/globals.css b/app/globals.css
index b870f517..4b2d1293 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -88,7 +88,15 @@
.email-content .header { margin-bottom: 1em; }
.email-content .footer { font-size: 0.875rem; color: #6b7280; margin-top: 1em; }
-/* Force email content direction */
+/* Email editor styles */
+.email-editor {
+ /* Allow text direction to be controlled by component */
+ direction: inherit;
+ unicode-bidi: isolate;
+ text-align: inherit;
+}
+
+/* Email content wrapper should still force LTR for quoted content */
.email-content-wrapper {
direction: ltr !important;
unicode-bidi: isolate !important;
@@ -101,10 +109,3 @@
text-align: left !important;
}
-/* Email editor styles */
-.email-editor {
- direction: ltr !important;
- unicode-bidi: isolate !important;
- text-align: left !important;
-}
-
diff --git a/components/email/ComposeEmail.tsx b/components/email/ComposeEmail.tsx
index 432af0bf..68d90eae 100644
--- a/components/email/ComposeEmail.tsx
+++ b/components/email/ComposeEmail.tsx
@@ -16,7 +16,8 @@ import {
formatForwardedEmail,
formatReplyEmail,
formatEmailForReplyOrForward,
- EmailMessage as FormatterEmailMessage
+ EmailMessage as FormatterEmailMessage,
+ sanitizeHtml
} from '@/lib/utils/email-formatter';
// Define EmailMessage interface locally instead of importing from server-only file
@@ -87,6 +88,7 @@ interface LegacyComposeEmailProps {
interface ComposeEmailProps {
initialEmail?: EmailMessage | null;
type?: 'new' | 'reply' | 'reply-all' | 'forward';
+ initialRTL?: boolean;
onClose: () => void;
onSend: (emailData: {
to: string;
@@ -110,14 +112,6 @@ function isLegacyProps(props: ComposeEmailAllProps): props is LegacyComposeEmail
return 'showCompose' in props && 'setShowCompose' in props;
}
-// Configure DOMPurify to preserve certain attributes
-DOMPurify.addHook('afterSanitizeAttributes', function(node) {
- // Preserve direction attributes
- if (node.hasAttribute('dir')) {
- node.setAttribute('dir', node.getAttribute('dir') || 'ltr');
- }
-});
-
export default function ComposeEmail(props: ComposeEmailAllProps) {
// Handle legacy props by adapting them to new component
if (isLegacyProps(props)) {
@@ -125,7 +119,7 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
}
// Continue with modern implementation for new props
- const { initialEmail, type = 'new', onClose, onSend } = props;
+ const { initialEmail, type = 'new', initialRTL, onClose, onSend } = props;
// Email form state
const [to, setTo] = useState
('');
@@ -136,7 +130,7 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
const [showCc, setShowCc] = useState(false);
const [showBcc, setShowBcc] = useState(false);
const [sending, setSending] = useState(false);
- const [isRTL, setIsRTL] = useState(false);
+ const [isRTL, setIsRTL] = useState(initialRTL || false);
const [attachments, setAttachments] = useState(null);
const attachmentInputRef = useRef(null);
+ // Initialize RTL state from prop if provided
+ useEffect(() => {
+ if (initialRTL !== undefined) {
+ setIsRTL(initialRTL);
+ }
+ }, [initialRTL]);
+
// Initialize the form when replying to or forwarding an email
useEffect(() => {
if (initialEmail && type !== 'new') {
@@ -264,7 +265,19 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
// Toggle text direction for the entire editor
const toggleTextDirection = () => {
- setIsRTL(!isRTL);
+ // Toggle the RTL state
+ const newRTL = !isRTL;
+ setIsRTL(newRTL);
+
+ // Apply the direction to the editor content immediately
+ if (editorRef.current) {
+ // Preserve the content but update the direction attributes
+ editorRef.current.dir = newRTL ? 'rtl' : 'ltr';
+ editorRef.current.style.textAlign = newRTL ? 'right' : 'left';
+ editorRef.current.style.direction = newRTL ? 'rtl' : 'ltr';
+
+ // No need to modify the content, just let the user edit with proper directionality
+ }
};
// Send email without modifying pre-formatted content
@@ -418,7 +431,9 @@ export default function ComposeEmail(props: ComposeEmailAllProps) {
dangerouslySetInnerHTML={{ __html: emailContent }}
dir={isRTL ? 'rtl' : 'ltr'}
style={{
- textAlign: isRTL ? 'right' : 'left'
+ textAlign: isRTL ? 'right' : 'left',
+ direction: isRTL ? 'rtl' : 'ltr',
+ unicodeBidi: 'isolate'
}}
/>
@@ -514,6 +529,23 @@ function LegacyAdapter({
replyTo,
forwardFrom
}: LegacyComposeEmailProps) {
+ // Check if the user has RTL preference
+ const [preferRTL, setPreferRTL] = useState