export function fixMdxDataProps(content: string): string { let fixedContent = content; let dataIndex = fixedContent.indexOf('data={{'); while (dataIndex !== -1) { let openCount = 0; let endIndex = -1; const startObj = dataIndex + 6; // index of the first '{' in 'data={{' let inString = false; let isEscaped = false; for (let i = startObj; i < fixedContent.length; i++) { const char = fixedContent[i]; if (isEscaped) { isEscaped = false; continue; } if (char === '\\') { isEscaped = true; continue; } if (char === '"') { inString = !inString; continue; } if (!inString) { if (char === '{') { openCount++; } else if (char === '}') { openCount--; if (openCount === 0) { endIndex = i; break; } } } } if (endIndex !== -1) { // jsonStr is the content INSIDE the outer curly braces const jsonStr = fixedContent.substring(startObj + 1, endIndex); const safeJsonStr = jsonStr.replace(/"/g, '"'); const replacement = `data="{${safeJsonStr}}"`; // We also need to consume the closing `}` of the `data={{` const nextCharIndex = endIndex + 1; const skipChars = nextCharIndex < fixedContent.length && fixedContent[nextCharIndex] === '}' ? 2 : 1; fixedContent = fixedContent.substring(0, dataIndex) + replacement + fixedContent.substring(endIndex + skipChars); dataIndex = fixedContent.indexOf('data={{', dataIndex + replacement.length); } else { // Malformed braces, prevent infinite loop break; } } return fixedContent; } export function lexicalToMarkdown(node: any, depth = 0): string { if (!node) return ''; if (typeof node === 'string') return node; if (node.type === 'text') { let text = node.text || ''; if (node.format === 1) text = `**${text}**`; // Bold if (node.format === 2) text = `*${text}*`; // Italic return text; } if (node.type === 'heading') { const level = parseInt((node.tag || 'h1').replace('h', '')) || 1; const prefix = '#'.repeat(level); const text = (node.children || []).map((c: any) => lexicalToMarkdown(c, depth)).join(''); return `${prefix} ${text}\n\n`; } if (node.type === 'paragraph') { const text = (node.children || []).map((c: any) => lexicalToMarkdown(c, depth)).join(''); return text.trim() ? `${text}\n\n` : '\n'; } if (node.type === 'list') { const isOrdered = node.tag === 'ol'; const items = (node.children || []) .map((c: any, index: number) => { const prefix = isOrdered ? `${index + 1}.` : '-'; return `${prefix} ${lexicalToMarkdown(c, depth + 1).trim()}`; }) .join('\n'); return `${items}\n\n`; } if (node.type === 'listitem') { return (node.children || []).map((c: any) => lexicalToMarkdown(c, depth)).join(''); } if (node.type === 'quote') { const text = (node.children || []).map((c: any) => lexicalToMarkdown(c, depth)).join(''); return `> ${text}\n\n`; } if (node.type === 'link') { const url = node.fields?.url || node.url || ''; const text = (node.children || []).map((c: any) => lexicalToMarkdown(c, depth)).join(''); return `[${text}](${url})`; } if (node.type === 'upload') { const url = node.value?.url || ''; const alt = node.value?.alt || node.value?.filename || ''; return `![${alt}](${url})\n\n`; } if (node.type === 'block') { const blockType = node.fields?.blockType; if (blockType === 'contactSection') { return `\n\n`; } if (blockType === 'heroSection') { return `\n\n`; } if (blockType === 'features') { return `\n\n`; } // Generic MDX block wrapper if unknown return `\n\n`; } if (node.children && Array.isArray(node.children)) { return node.children.map((c: any) => lexicalToMarkdown(c, depth)).join(''); } return ''; }