/** * Text Direction Utilities * * Core utilities for handling text direction (RTL/LTR) * to ensure consistent behavior across the application. */ /** * Detects if text contains RTL characters and should be displayed right-to-left * Uses a comprehensive regex pattern that covers Arabic, Hebrew, and other RTL scripts * * @param text Text to analyze for direction * @returns 'rtl' if RTL characters are detected, otherwise 'ltr' */ export function detectTextDirection(text: string | undefined | null): 'ltr' | 'rtl' { if (!text) return 'ltr'; // Comprehensive pattern for RTL languages: // - Arabic (0600-06FF, FB50-FDFF, FE70-FEFF) // - Hebrew (0590-05FF, FB1D-FB4F) // - RTL marks and controls (200F, 202B, 202E) const rtlPattern = /[\u0591-\u07FF\u200F\u202B\u202E\uFB1D-\uFDFD\uFE70-\uFEFC]/; return rtlPattern.test(text) ? 'rtl' : 'ltr'; } /** * Adds appropriate direction attribute to HTML content based on content analysis * * @param htmlContent HTML content to analyze and enhance with direction * @param textContent Plain text version for direction analysis (optional) * @returns HTML with appropriate direction attribute */ export function applyTextDirection(htmlContent: string, textContent?: string): string { if (!htmlContent) return ''; // If text content is provided, use it for direction detection // Otherwise extract text from HTML for direction detection const textForAnalysis = textContent || htmlContent.replace(/<[^>]*>/g, '') .replace(/ /g, ' ') .replace(/</g, '<') .replace(/>/g, '>') .replace(/&/g, '&'); const direction = detectTextDirection(textForAnalysis); // If the HTML already has a dir attribute, don't override it if (htmlContent.includes('dir="rtl"') || htmlContent.includes('dir="ltr"')) { return htmlContent; } // Check if we already have an email-content wrapper if (htmlContent.startsWith('
${htmlContent}
`; } /** * Process content to determine direction and return direction-enhanced HTML * * @param content Content to process (HTML or plain text) * @returns Object containing processed HTML, plain text, and detected direction */ export function processContentWithDirection(content: string | undefined | { html?: string; text?: string }): { html: string; text: string; direction: 'ltr' | 'rtl' } { if (!content) { return { html: '', text: '', direction: 'ltr' }; } let htmlContent = ''; let textContent = ''; // Handle different content types if (typeof content === 'string') { // String content might be HTML or plain text if (content.includes('<') && (content.includes(']*>/g, '') .replace(/ /g, ' ') .replace(/</g, '<') .replace(/>/g, '>') .replace(/&/g, '&'); } else { // It's plain text textContent = content; // Create simple HTML from the plain text (preserve whitespace) htmlContent = content.replace(/\n/g, '
').replace(/\s\s/g, '  '); } } else { // It's an object with html and/or text properties htmlContent = content.html || ''; textContent = content.text || ''; // If we have HTML but no text, extract text from HTML if (htmlContent && !textContent) { textContent = htmlContent.replace(/<[^>]*>/g, '') .replace(/ /g, ' ') .replace(/</g, '<') .replace(/>/g, '>') .replace(/&/g, '&'); } // If we have text but no HTML, create simple HTML from the text if (textContent && !htmlContent) { htmlContent = textContent.replace(/\n/g, '
').replace(/\s\s/g, '  '); } } // Detect the direction of the text const direction = detectTextDirection(textContent); // Apply the direction to the HTML content const directionEnhancedHtml = applyTextDirection(htmlContent, textContent); return { html: directionEnhancedHtml, text: textContent, direction }; }