Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 10s
Build & Deploy / 🧪 QA (push) Failing after 52s
Build & Deploy / 🏗️ Build (push) Has been skipped
Build & Deploy / 🚀 Deploy (push) Has been skipped
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 2s
147 lines
4.4 KiB
TypeScript
147 lines
4.4 KiB
TypeScript
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 `\n\n`;
|
|
}
|
|
|
|
if (node.type === 'block') {
|
|
const blockType = node.fields?.blockType;
|
|
if (blockType === 'contactSection') {
|
|
return `<ContactSection showMap={${!!node.fields?.showMap}} showForm={${!!node.fields?.showForm}} showHours={${!!node.fields?.showHours}} />\n\n`;
|
|
}
|
|
if (blockType === 'heroSection') {
|
|
return `<HeroSection badge="${node.fields?.badge || ''}" title="${node.fields?.title || ''}" subtitle="${node.fields?.subtitle || ''}" alignment="${node.fields?.alignment || 'left'}" />\n\n`;
|
|
}
|
|
if (blockType === 'features') {
|
|
return `<FeaturesSection layout="${node.fields?.layout || ''}" />\n\n`;
|
|
}
|
|
// Generic MDX block wrapper if unknown
|
|
return `<Block type="${blockType}" data={${JSON.stringify(node.fields)}} />\n\n`;
|
|
}
|
|
|
|
if (node.children && Array.isArray(node.children)) {
|
|
return node.children.map((c: any) => lexicalToMarkdown(c, depth)).join('');
|
|
}
|
|
|
|
return '';
|
|
}
|