fix: Email rendering - newlines, hero text color, and card borders
🐛 Three Critical Email Issues Fixed: 1. Newlines Not Working ❌ "Order Number: #359 Order Total: Rp129.000" on same line ✅ Fixed by adding <br> for line continuations in paragraphs Key change in MarkdownParser.php: - Accumulate paragraph content with <br> between lines - Match TypeScript behavior exactly - Protect variables from markdown parsing Before: $paragraph_content = $trimmed; After: if ($paragraph_content) { $paragraph_content .= '<br>' . $trimmed; } else { $paragraph_content = $trimmed; } 2. Hero Card Text Color ❌ Heading black instead of white in Gmail ✅ Add inline color styles to all headings/paragraphs Problem: Gmail doesn't inherit color from parent Solution: Add style="color: white;" to each element $content = preg_replace( '/<(h[1-6]|p)([^>]*)>/', '<$1$2 style="color: ' . $hero_text_color . ';">', $content ); 3. Blue Border on Cards ❌ Unwanted blue border in Gmail (screenshot 2) ✅ Removed borders from .card-info, .card-warning, .card-success Problem: CSS template had borders Solution: Removed border declarations Before: .card-info { border: 1px solid #0071e3; } After: .card-info { background-color: #f0f7ff; } �� Additional Improvements: - Variable protection during markdown parsing - Don't match bold/italic across newlines - Proper list handling - Block-level tag detection - Paragraph accumulation with line breaks 🎯 Result: - ✅ Proper line breaks in paragraphs - ✅ White text in hero cards (Gmail compatible) - ✅ No unwanted borders - ✅ Variables preserved during parsing - ✅ Professional email appearance Test: Create order, check email - should now show: - Order Number: #359 - Order Total: Rp129.000 - Estimated Delivery: 3-5 business days (Each on separate line with proper spacing)
This commit is contained in:
@@ -71,59 +71,110 @@ class MarkdownParser {
|
||||
private static function parse_basics($text) {
|
||||
$html = $text;
|
||||
|
||||
// Protect variables from markdown parsing by temporarily replacing them
|
||||
$variables = [];
|
||||
$var_index = 0;
|
||||
$html = preg_replace_callback('/\{([^}]+)\}/', function($matches) use (&$variables, &$var_index) {
|
||||
$placeholder = '<!--VAR' . $var_index . '-->';
|
||||
$variables[$placeholder] = $matches[0];
|
||||
$var_index++;
|
||||
return $placeholder;
|
||||
}, $html);
|
||||
|
||||
// Headings (must be done in order from h4 to h1 to avoid conflicts)
|
||||
$html = preg_replace('/^#### (.*)$/m', '<h4>$1</h4>', $html);
|
||||
$html = preg_replace('/^### (.*)$/m', '<h3>$1</h3>', $html);
|
||||
$html = preg_replace('/^## (.*)$/m', '<h2>$1</h2>', $html);
|
||||
$html = preg_replace('/^# (.*)$/m', '<h1>$1</h1>', $html);
|
||||
|
||||
// Bold
|
||||
$html = preg_replace('/\*\*(.*?)\*\*/s', '<strong>$1</strong>', $html);
|
||||
$html = preg_replace('/__(.*?)__/s', '<strong>$1</strong>', $html);
|
||||
// Bold (don't match across newlines)
|
||||
$html = preg_replace('/\*\*([^\n*]+?)\*\*/', '<strong>$1</strong>', $html);
|
||||
$html = preg_replace('/__([^\n_]+?)__/', '<strong>$1</strong>', $html);
|
||||
|
||||
// Italic
|
||||
$html = preg_replace('/\*([^\*]+?)\*/', '<em>$1</em>', $html);
|
||||
$html = preg_replace('/_([^_]+?)_/', '<em>$1</em>', $html);
|
||||
// Italic (don't match across newlines)
|
||||
$html = preg_replace('/\*([^\n*]+?)\*/', '<em>$1</em>', $html);
|
||||
$html = preg_replace('/_([^\n_]+?)_/', '<em>$1</em>', $html);
|
||||
|
||||
// Horizontal rules
|
||||
$html = preg_replace('/^---$/m', '<hr>', $html);
|
||||
|
||||
// Links (but not button syntax)
|
||||
$html = preg_replace('/\[(?!button)([^\]]+)\]\(([^)]+)\)/', '<a href="$2">$1</a>', $html);
|
||||
|
||||
// Unordered lists (including checkmarks and bullets)
|
||||
$html = preg_replace('/^[\*\-•✓✔] (.*)$/m', '<li>$1</li>', $html);
|
||||
|
||||
// Wrap consecutive <li> in <ul>
|
||||
$html = preg_replace('/(<li>.*?<\/li>\s*)+/s', '<ul>$0</ul>', $html);
|
||||
|
||||
// Ordered lists
|
||||
$html = preg_replace('/^\d+\. (.*)$/m', '<li>$1</li>', $html);
|
||||
|
||||
// Paragraphs (lines not already in tags)
|
||||
// Process lines for paragraphs and lists
|
||||
$lines = explode("\n", $html);
|
||||
$in_list = false;
|
||||
$paragraph_content = '';
|
||||
$processed_lines = [];
|
||||
|
||||
$close_paragraph = function() use (&$paragraph_content, &$processed_lines) {
|
||||
if ($paragraph_content) {
|
||||
$processed_lines[] = '<p>' . $paragraph_content . '</p>';
|
||||
$paragraph_content = '';
|
||||
}
|
||||
};
|
||||
|
||||
foreach ($lines as $line) {
|
||||
$trimmed = trim($line);
|
||||
|
||||
// Skip empty lines
|
||||
// Empty line - close paragraph or list
|
||||
if (empty($trimmed)) {
|
||||
if ($in_list) {
|
||||
$processed_lines[] = '</ul>';
|
||||
$in_list = false;
|
||||
}
|
||||
$close_paragraph();
|
||||
$processed_lines[] = '';
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip lines that are already HTML tags or shortcodes
|
||||
if (preg_match('/^</', $trimmed) || preg_match('/^\[/', $trimmed)) {
|
||||
// Check if line is a list item
|
||||
if (preg_match('/^[\*\-•✓✔]\s/', $trimmed)) {
|
||||
$close_paragraph();
|
||||
$content = preg_replace('/^[\*\-•✓✔]\s/', '', $trimmed);
|
||||
if (!$in_list) {
|
||||
$processed_lines[] = '<ul>';
|
||||
$in_list = true;
|
||||
}
|
||||
$processed_lines[] = '<li>' . $content . '</li>';
|
||||
continue;
|
||||
}
|
||||
|
||||
// Close list if we're in one
|
||||
if ($in_list) {
|
||||
$processed_lines[] = '</ul>';
|
||||
$in_list = false;
|
||||
}
|
||||
|
||||
// Block-level HTML tags - don't wrap in paragraph
|
||||
if (preg_match('/^<(div|h1|h2|h3|h4|h5|h6|p|ul|ol|li|hr|table|blockquote)/i', $trimmed)) {
|
||||
$close_paragraph();
|
||||
$processed_lines[] = $line;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Wrap in paragraph
|
||||
$processed_lines[] = '<p>' . $line . '</p>';
|
||||
// Regular text line - accumulate in paragraph
|
||||
if ($paragraph_content) {
|
||||
// Add line break before continuation (THIS IS THE KEY FIX!)
|
||||
$paragraph_content .= '<br>' . $trimmed;
|
||||
} else {
|
||||
// Start new paragraph
|
||||
$paragraph_content = $trimmed;
|
||||
}
|
||||
}
|
||||
|
||||
// Close any open tags
|
||||
if ($in_list) {
|
||||
$processed_lines[] = '</ul>';
|
||||
}
|
||||
$close_paragraph();
|
||||
|
||||
$html = implode("\n", $processed_lines);
|
||||
|
||||
// Clean up extra newlines in HTML
|
||||
$html = preg_replace('/\n{3,}/', "\n\n", $html);
|
||||
// Restore variables
|
||||
foreach ($variables as $placeholder => $original) {
|
||||
$html = str_replace($placeholder, $original, $html);
|
||||
}
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user