diff --git a/admin-spa/src/lib/markdown-utils.ts b/admin-spa/src/lib/markdown-utils.ts
index 6ba1597..3377fa1 100644
--- a/admin-spa/src/lib/markdown-utils.ts
+++ b/admin-spa/src/lib/markdown-utils.ts
@@ -87,7 +87,7 @@ export function markdownToHtml(markdown: string): string {
const parsedContent = parseMarkdownBasics(content.trim());
return `
${parsedContent}
`;
});
-
+
// Parse [card type="..."] blocks (old syntax - backward compatibility)
html = html.replace(/\[card(?:\s+type="([^"]+)")?\]([\s\S]*?)\[\/card\]/g, (match, type, content) => {
const cardClass = type ? `card card-${type}` : 'card';
@@ -100,7 +100,7 @@ export function markdownToHtml(markdown: string): string {
const buttonClass = style === 'outline' ? 'button-outline' : 'button';
return `${text.trim()}
`;
});
-
+
// Parse [button url="..."] shortcodes (old syntax - backward compatibility)
html = html.replace(/\[button\s+url="([^"]+)"(?:\s+style="([^"]+)")?\]([^\[]+)\[\/button\]/g, (match, url, style, text) => {
const buttonClass = style === 'outline' ? 'button-outline' : 'button';
@@ -155,7 +155,7 @@ export function parseMarkdownBasics(text: string): string {
const buttonClass = style === 'outline' ? 'button-outline' : 'button';
return `${text.trim()}
`;
});
-
+
// Parse [button url="..."] shortcodes (old syntax - backward compatibility)
html = html.replace(/\[button\s+url="([^"]+)"(?:\s+style="([^"]+)")?\]([^\[]+)\[\/button\]/g, (match, url, style, text) => {
const buttonClass = style === 'outline' ? 'button-outline' : 'button';
@@ -267,8 +267,33 @@ export function htmlToMarkdown(html: string): string {
});
// Convert buttons back to [button] syntax
+ // TipTap button format with data attributes: text
+ markdown = markdown.replace(/]*data-button[^>]*data-href="([^"]+)"[^>]*data-style="([^"]*)"[^>]*>([^<]+)<\/a>/gi, (match, url, style, text) => {
+ const styleAttr = style === 'outline' ? ' style="outline"' : ' style="solid"';
+ return `[button url="${url}"${styleAttr}]${text.trim()}[/button]`;
+ });
+
+ // Alternate order: data-style before data-href
+ markdown = markdown.replace(/]*data-button[^>]*data-style="([^"]*)"[^>]*data-href="([^"]+)"[^>]*>([^<]+)<\/a>/gi, (match, style, url, text) => {
+ const styleAttr = style === 'outline' ? ' style="outline"' : ' style="solid"';
+ return `[button url="${url}"${styleAttr}]${text.trim()}[/button]`;
+ });
+
+ // Simple data-button fallback (just has href and class)
+ markdown = markdown.replace(/]*href="([^"]+)"[^>]*class="(button[^"]*)"[^>]*data-button[^>]*>([^<]+)<\/a>/gi, (match, url, className, text) => {
+ const style = className.includes('outline') ? ' style="outline"' : ' style="solid"';
+ return `[button url="${url}"${style}]${text.trim()}[/button]`;
+ });
+
+ // Buttons wrapped in p tags (from preview HTML): text
markdown = markdown.replace(/]*>]*>([^<]+)<\/a><\/p>/g, (match, url, className, text) => {
- const style = className.includes('outline') ? ' style="outline"' : '';
+ const style = className.includes('outline') ? ' style="outline"' : ' style="solid"';
+ return `[button url="${url}"${style}]${text.trim()}[/button]`;
+ });
+
+ // Direct button links without p wrapper
+ markdown = markdown.replace(/]*>([^<]+)<\/a>/g, (match, url, className, text) => {
+ const style = className.includes('outline') ? ' style="outline"' : ' style="solid"';
return `[button url="${url}"${style}]${text.trim()}[/button]`;
});