131 lines
4.6 KiB
TypeScript
131 lines
4.6 KiB
TypeScript
/**
|
|
* 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('<div class="email-content')) {
|
|
// Replace opening div with one that includes direction
|
|
return htmlContent.replace(
|
|
/<div class="email-content([^"]*)"/,
|
|
`<div class="email-content$1" dir="${direction}"`
|
|
);
|
|
}
|
|
|
|
// Otherwise, wrap the content with a direction-aware container
|
|
return `<div class="email-content" dir="${direction}">${htmlContent}</div>`;
|
|
}
|
|
|
|
/**
|
|
* 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('<html') || content.includes('<body') || content.includes('<div'))) {
|
|
htmlContent = content;
|
|
textContent = content.replace(/<[^>]*>/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, '<br>').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, '<br>').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
|
|
};
|
|
}
|