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:
dwindown
2025-11-18 21:46:06 +07:00
parent c599bce71a
commit 1225d7b0ff
3 changed files with 81 additions and 26 deletions

View File

@@ -311,6 +311,13 @@ class EmailRenderer {
esc_attr($hero_gradient_end)
);
$content_style .= sprintf(' color: %s;', esc_attr($hero_text_color));
// Add inline color to all headings and paragraphs for email client compatibility
$content = preg_replace(
'/<(h[1-6]|p)([^>]*)>/',
'<$1$2 style="color: ' . esc_attr($hero_text_color) . ';">',
$content
);
}
}

View File

@@ -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;
}

View File

@@ -99,17 +99,14 @@
.card-info {
background-color: #f0f7ff;
border: 1px solid #0071e3;
}
.card-warning {
background-color: #fff8e1;
border: 1px solid #ff9800;
}
.card-success {
background-color: #e8f5e9;
border: 1px solid #4caf50;
}
.card-bg {