diff --git a/includes/Core/Notifications/EmailRenderer.php b/includes/Core/Notifications/EmailRenderer.php index 06ada0c..18ddd5c 100644 --- a/includes/Core/Notifications/EmailRenderer.php +++ b/includes/Core/Notifications/EmailRenderer.php @@ -288,45 +288,37 @@ class EmailRenderer { * @return string */ private function parse_cards($content) { - $html = ''; - $has_cards = false; + // Use a single unified regex to match BOTH syntaxes in document order + // This ensures cards are rendered in the order they appear + $combined_pattern = '/\[card(?::(\w+)|([^\]]*)?)\](.*?)\[\/card\]/s'; - // Match NEW syntax [card:type]...[/card] first - preg_match_all('/\[card:(\w+)\](.*?)\[\/card\]/s', $content, $new_matches, PREG_SET_ORDER); + preg_match_all($combined_pattern, $content, $matches, PREG_SET_ORDER | PREG_OFFSET_CAPTURE); - if (!empty($new_matches)) { - $has_cards = true; - foreach ($new_matches as $match) { - $attributes = ['type' => $match[1]]; - $card_content = $match[2]; - - $html .= $this->render_card($card_content, $attributes); - $html .= $this->render_card_spacing(); - - // Remove matched content to avoid double processing - $content = str_replace($match[0], '', $content); - } - } - - // Match OLD syntax [card type="..."]...[/card] - preg_match_all('/\[card([^\]]*)\](.*?)\[\/card\]/s', $content, $old_matches, PREG_SET_ORDER); - - if (!empty($old_matches)) { - $has_cards = true; - foreach ($old_matches as $match) { - $attributes = $this->parse_card_attributes($match[1]); - $card_content = $match[2]; - - $html .= $this->render_card($card_content, $attributes); - $html .= $this->render_card_spacing(); - } - } - - if (!$has_cards) { + if (empty($matches)) { // No cards found, wrap entire content in a single card return $this->render_card($content, []); } + $html = ''; + foreach ($matches as $match) { + // Determine which syntax was matched + $full_match = $match[0][0]; + $new_syntax_type = !empty($match[1][0]) ? $match[1][0] : null; // [card:type] format + $old_syntax_attrs = $match[2][0] ?? ''; // [card type="..."] format + $card_content = $match[3][0]; + + if ($new_syntax_type) { + // NEW syntax [card:type] + $attributes = ['type' => $new_syntax_type]; + } else { + // OLD syntax [card type="..."] or [card] + $attributes = $this->parse_card_attributes($old_syntax_attrs); + } + + $html .= $this->render_card($card_content, $attributes); + $html .= $this->render_card_spacing(); + } + // Remove last spacing $html = preg_replace('/