fix: TipTap button conversion in card save flow

ROOT CAUSE:
When saving card edit in EmailBuilder, htmlToMarkdown() was called.
The old code at line 26 converted ALL <a> tags to markdown links:
  <a href="url">text</a> → [text](url)

This lost TipTap button data-button attributes, converting buttons
to plain text instead of [button:style](url)Text[/button] shortcode.

FIX:
Added TipTap button detection BEFORE generic link conversion in
html-to-markdown.ts:
- Detects <a data-button...> elements
- Extracts style from data-style or class attribute
- Extracts URL from data-href or href attribute
- Converts to [button:style](url)Text[/button] format

FLOW NOW WORKS:
1. User adds button via TipTap toolbar
2. TipTap renders <a data-button data-style="solid"...>
3. User clicks Save Changes
4. htmlToMarkdown detects data-button → [button:solid](url)Text[/button]
5. Card content saved with proper button shortcode
6. On re-edit, button shortcode converted back to TipTap button
This commit is contained in:
Dwindi Ramadhana
2026-01-01 23:31:54 +07:00
parent 47a1e78eb7
commit 47f6370ce0

View File

@@ -22,7 +22,33 @@ export function htmlToMarkdown(html: string): string {
markdown = markdown.replace(/<em>(.*?)<\/em>/gi, '*$1*');
markdown = markdown.replace(/<i>(.*?)<\/i>/gi, '*$1*');
// Links
// TipTap buttons - detect by data-button attribute, BEFORE generic links
// Format: <a data-button data-style="solid" data-href="..." data-text="...">text</a>
// or: <a href="..." class="button..." data-button ...>text</a>
markdown = markdown.replace(/<a[^>]*data-button[^>]*>(.*?)<\/a>/gi, (match, text) => {
// Extract style from data-style or class
let style = 'solid';
const styleMatch = match.match(/data-style=["'](\w+)["']/);
if (styleMatch) {
style = styleMatch[1];
} else if (match.includes('button-outline') || match.includes('outline')) {
style = 'outline';
}
// Extract href from data-href or href attribute
let url = '#';
const dataHrefMatch = match.match(/data-href=["']([^"']+)["']/);
const hrefMatch = match.match(/href=["']([^"']+)["']/);
if (dataHrefMatch) {
url = dataHrefMatch[1];
} else if (hrefMatch) {
url = hrefMatch[1];
}
return `[button:${style}](${url})${text.trim()}[/button]`;
});
// Regular links (not buttons)
markdown = markdown.replace(/<a\s+href="([^"]+)"[^>]*>(.*?)<\/a>/gi, '[$2]($1)');
// Lists