fix: button/card syntax mismatch between blocksToMarkdown and markdownToBlocks
ROOT CAUSE: Complete flow trace revealed syntax mismatch:
- blocksToMarkdown outputs NEW syntax: [card:type], [button:style](url)Text[/button]
- markdownToBlocks ONLY parsed OLD syntax: [card type="..."], [button url="..."]
This caused buttons/cards to be lost when:
1. User adds button in Visual mode
2. blocksToMarkdown converts to [button:solid]({url})Text[/button]
3. handleBlocksChange stores this in markdownContent
4. When switching tabs/previewing, markdownToBlocks runs
5. It FAILED to parse new syntax, buttons disappear!
FIX: Added handlers for NEW syntax in markdownToBlocks (converter.ts):
- [card:type]...[/card] pattern (before old syntax)
- [button:style](url)Text[/button] pattern (before old syntax)
Now both syntaxes work correctly in round-trip conversion.
This commit is contained in:
@@ -320,7 +320,24 @@ export function markdownToBlocks(markdown: string): EmailBlock[] {
|
||||
|
||||
const id = `block-${Date.now()}-${blockId++}`;
|
||||
|
||||
// Check for [card] blocks - match with proper boundaries
|
||||
// Check for [card] blocks - NEW syntax [card:type]...[/card]
|
||||
const newCardMatch = remaining.match(/^\[card:(\w+)\]([\s\S]*?)\[\/card\]/);
|
||||
if (newCardMatch) {
|
||||
const cardType = newCardMatch[1] as CardType;
|
||||
const content = newCardMatch[2].trim();
|
||||
|
||||
blocks.push({
|
||||
id,
|
||||
type: 'card',
|
||||
cardType,
|
||||
content,
|
||||
});
|
||||
|
||||
remaining = remaining.substring(newCardMatch[0].length);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for [card] blocks - OLD syntax [card type="..."]...[/card]
|
||||
const cardMatch = remaining.match(/^\[card([^\]]*)\]([\s\S]*?)\[\/card\]/);
|
||||
if (cardMatch) {
|
||||
const attributes = cardMatch[1].trim();
|
||||
@@ -347,7 +364,24 @@ export function markdownToBlocks(markdown: string): EmailBlock[] {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for [button] blocks
|
||||
// Check for [button] blocks - NEW syntax [button:style](url)Text[/button]
|
||||
const newButtonMatch = remaining.match(/^\[button:(\w+)\]\(([^)]+)\)([^\[]+)\[\/button\]/);
|
||||
if (newButtonMatch) {
|
||||
blocks.push({
|
||||
id,
|
||||
type: 'button',
|
||||
text: newButtonMatch[3].trim(),
|
||||
link: newButtonMatch[2],
|
||||
style: newButtonMatch[1] as ButtonStyle,
|
||||
align: 'center',
|
||||
widthMode: 'fit',
|
||||
});
|
||||
|
||||
remaining = remaining.substring(newButtonMatch[0].length);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for [button] blocks - OLD syntax [button url="..." style="..."]Text[/button]
|
||||
const buttonMatch = remaining.match(/^\[button\s+url=["']([^"']+)["'](?:\s+style=["'](solid|outline)["'])?\]([^\[]+)\[\/button\]/);
|
||||
if (buttonMatch) {
|
||||
blocks.push({
|
||||
|
||||
Reference in New Issue
Block a user