diff --git a/includes/Core/Notifications/EmailRenderer.php b/includes/Core/Notifications/EmailRenderer.php index 95a5452..0e69fa0 100644 --- a/includes/Core/Notifications/EmailRenderer.php +++ b/includes/Core/Notifications/EmailRenderer.php @@ -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 + ); } } diff --git a/includes/Core/Notifications/MarkdownParser.php b/includes/Core/Notifications/MarkdownParser.php index a53e62b..20512ce 100644 --- a/includes/Core/Notifications/MarkdownParser.php +++ b/includes/Core/Notifications/MarkdownParser.php @@ -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 = ''; + $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', '

$1

', $html); $html = preg_replace('/^### (.*)$/m', '

$1

', $html); $html = preg_replace('/^## (.*)$/m', '

$1

', $html); $html = preg_replace('/^# (.*)$/m', '

$1

', $html); - // Bold - $html = preg_replace('/\*\*(.*?)\*\*/s', '$1', $html); - $html = preg_replace('/__(.*?)__/s', '$1', $html); + // Bold (don't match across newlines) + $html = preg_replace('/\*\*([^\n*]+?)\*\*/', '$1', $html); + $html = preg_replace('/__([^\n_]+?)__/', '$1', $html); - // Italic - $html = preg_replace('/\*([^\*]+?)\*/', '$1', $html); - $html = preg_replace('/_([^_]+?)_/', '$1', $html); + // Italic (don't match across newlines) + $html = preg_replace('/\*([^\n*]+?)\*/', '$1', $html); + $html = preg_replace('/_([^\n_]+?)_/', '$1', $html); + + // Horizontal rules + $html = preg_replace('/^---$/m', '
', $html); // Links (but not button syntax) $html = preg_replace('/\[(?!button)([^\]]+)\]\(([^)]+)\)/', '$1', $html); - // Unordered lists (including checkmarks and bullets) - $html = preg_replace('/^[\*\-•✓✔] (.*)$/m', '
  • $1
  • ', $html); - - // Wrap consecutive
  • in '; + $in_list = false; + } + $close_paragraph(); $processed_lines[] = ''; continue; } - // Skip lines that are already HTML tags or shortcodes - if (preg_match('/^'; + $in_list = true; + } + $processed_lines[] = '
  • ' . $content . '
  • '; + continue; + } + + // Close list if we're in one + if ($in_list) { + $processed_lines[] = ''; + $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[] = '

    ' . $line . '

    '; + // Regular text line - accumulate in paragraph + if ($paragraph_content) { + // Add line break before continuation (THIS IS THE KEY FIX!) + $paragraph_content .= '
    ' . $trimmed; + } else { + // Start new paragraph + $paragraph_content = $trimmed; + } } + // Close any open tags + if ($in_list) { + $processed_lines[] = ''; + } + $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; } diff --git a/templates/emails/base.html b/templates/emails/base.html index 434cdde..19e1f89 100644 --- a/templates/emails/base.html +++ b/templates/emails/base.html @@ -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 {