fix: backend email rendering for new button/card syntax
ROOT CAUSE: Frontend blocksToMarkdown outputs NEW syntax: - [card:type]...[/card] - [button:style](url)Text[/button] But backend EmailRenderer.php only had regex for OLD syntax: - [card type="..."]...[/card] - [button url="..."]Text[/button] FIXES: 1. parse_cards() now handles BOTH syntaxes: - NEW [card:type] regex first (extracts type from :type) - OLD [card type="..."] regex for backward compatibility 2. render_card() now handles BOTH button syntaxes: - NEW [button:style](url)Text[/button] regex - OLD [button url="..."] regex for backward compatibility 3. Card types properly styled with inline CSS: - hero: gradient background - success: green background + border - info: blue background + border - warning: yellow background + orange border 4. Buttons rendered with full inline styles + table wrapper for Gmail/email client compatibility
This commit is contained in:
@@ -288,21 +288,43 @@ class EmailRenderer {
|
|||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
private function parse_cards($content) {
|
private function parse_cards($content) {
|
||||||
// Match [card ...] ... [/card] patterns
|
$html = '';
|
||||||
preg_match_all('/\[card([^\]]*)\](.*?)\[\/card\]/s', $content, $matches, PREG_SET_ORDER);
|
$has_cards = false;
|
||||||
|
|
||||||
if (empty($matches)) {
|
// Match NEW syntax [card:type]...[/card] first
|
||||||
// No cards found, wrap entire content in a single card
|
preg_match_all('/\[card:(\w+)\](.*?)\[\/card\]/s', $content, $new_matches, PREG_SET_ORDER);
|
||||||
return $this->render_card($content, []);
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$html = '';
|
// Match OLD syntax [card type="..."]...[/card]
|
||||||
foreach ($matches as $match) {
|
preg_match_all('/\[card([^\]]*)\](.*?)\[\/card\]/s', $content, $old_matches, PREG_SET_ORDER);
|
||||||
$attributes = $this->parse_card_attributes($match[1]);
|
|
||||||
$card_content = $match[2];
|
|
||||||
|
|
||||||
$html .= $this->render_card($card_content, $attributes);
|
if (!empty($old_matches)) {
|
||||||
$html .= $this->render_card_spacing();
|
$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) {
|
||||||
|
// No cards found, wrap entire content in a single card
|
||||||
|
return $this->render_card($content, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove last spacing
|
// Remove last spacing
|
||||||
@@ -360,37 +382,53 @@ class EmailRenderer {
|
|||||||
$hero_text_color = $email_settings['hero_text_color'] ?? '#ffffff';
|
$hero_text_color = $email_settings['hero_text_color'] ?? '#ffffff';
|
||||||
|
|
||||||
// Parse button shortcodes with FULL INLINE STYLES for Gmail compatibility
|
// Parse button shortcodes with FULL INLINE STYLES for Gmail compatibility
|
||||||
// Format: [button url="..." style="solid|outline"]Text[/button]
|
// Helper function to generate button HTML
|
||||||
|
$generateButtonHtml = function($url, $style, $text) use ($primary_color, $secondary_color, $button_text_color) {
|
||||||
|
if ($style === 'outline') {
|
||||||
|
// Outline button - transparent background with border
|
||||||
|
$button_style = sprintf(
|
||||||
|
'display: inline-block; background-color: transparent; color: %s; padding: 14px 28px; border: 2px solid %s; border-radius: 6px; text-decoration: none; font-weight: 600; font-family: "Inter", Arial, sans-serif; font-size: 16px; text-align: center; mso-padding-alt: 0;',
|
||||||
|
esc_attr($secondary_color),
|
||||||
|
esc_attr($secondary_color)
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Solid button - full background color
|
||||||
|
$button_style = sprintf(
|
||||||
|
'display: inline-block; background-color: %s; color: %s; padding: 14px 28px; border: none; border-radius: 6px; text-decoration: none; font-weight: 600; font-family: "Inter", Arial, sans-serif; font-size: 16px; text-align: center; mso-padding-alt: 0;',
|
||||||
|
esc_attr($primary_color),
|
||||||
|
esc_attr($button_text_color)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use table-based button for better email client compatibility
|
||||||
|
return sprintf(
|
||||||
|
'<table role="presentation" border="0" cellpadding="0" cellspacing="0" style="margin: 16px auto;"><tr><td align="center"><a href="%s" style="%s">%s</a></td></tr></table>',
|
||||||
|
esc_url($url),
|
||||||
|
$button_style,
|
||||||
|
esc_html($text)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// NEW FORMAT: [button:style](url)Text[/button]
|
||||||
$content = preg_replace_callback(
|
$content = preg_replace_callback(
|
||||||
'/\[button\s+url=["\']([^"\']+)["\'](?:\s+style=["\']?(solid|outline)["\']?)?\]([^\[]+)\[\/button\]/',
|
'/\[button:(\w+)\]\(([^)]+)\)([^\[]+)\[\/button\]/',
|
||||||
function($matches) use ($primary_color, $secondary_color, $button_text_color) {
|
function($matches) use ($generateButtonHtml) {
|
||||||
|
$style = $matches[1]; // solid or outline
|
||||||
|
$url = $matches[2];
|
||||||
|
$text = trim($matches[3]);
|
||||||
|
return $generateButtonHtml($url, $style, $text);
|
||||||
|
},
|
||||||
|
$content
|
||||||
|
);
|
||||||
|
|
||||||
|
// OLD FORMAT: [button url="..." style="solid|outline"]Text[/button]
|
||||||
|
$content = preg_replace_callback(
|
||||||
|
'/\[button\s+url=["\']([^"\']+)["\'](?:\s+style=["\'](solid|outline)["\'])?\]([^\[]+)\[\/button\]/',
|
||||||
|
function($matches) use ($generateButtonHtml) {
|
||||||
$url = $matches[1];
|
$url = $matches[1];
|
||||||
$style = $matches[2] ?? 'solid';
|
$style = $matches[2] ?? 'solid';
|
||||||
$text = trim($matches[3]);
|
$text = trim($matches[3]);
|
||||||
|
return $generateButtonHtml($url, $style, $text);
|
||||||
if ($style === 'outline') {
|
|
||||||
// Outline button - transparent background with border
|
|
||||||
$button_style = sprintf(
|
|
||||||
'display: inline-block; background-color: transparent; color: %s; padding: 14px 28px; border: 2px solid %s; border-radius: 6px; text-decoration: none; font-weight: 600; font-family: "Inter", Arial, sans-serif; font-size: 16px; text-align: center; mso-padding-alt: 0;',
|
|
||||||
esc_attr($secondary_color),
|
|
||||||
esc_attr($secondary_color)
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Solid button - full background color
|
|
||||||
$button_style = sprintf(
|
|
||||||
'display: inline-block; background-color: %s; color: %s; padding: 14px 28px; border: none; border-radius: 6px; text-decoration: none; font-weight: 600; font-family: "Inter", Arial, sans-serif; font-size: 16px; text-align: center; mso-padding-alt: 0;',
|
|
||||||
esc_attr($primary_color),
|
|
||||||
esc_attr($button_text_color)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use table-based button for better email client compatibility
|
|
||||||
return sprintf(
|
|
||||||
'<table role="presentation" border="0" cellpadding="0" cellspacing="0" style="margin: 16px auto;"><tr><td align="center"><a href="%s" style="%s">%s</a></td></tr></table>',
|
|
||||||
esc_url($url),
|
|
||||||
$button_style,
|
|
||||||
esc_html($text)
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
$content
|
$content
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user