import React, { useState, useEffect, createElement } from 'react';
import { MDXProvider } from '@mdx-js/react';
import { compile } from '@mdx-js/mdx';
import * as runtime from 'react/jsx-runtime';
import { ComponentProps } from 'react';
interface CodeProps extends ComponentProps<'code'> {
className?: string;
children?: React.ReactNode;
}
interface BlockquoteProps extends ComponentProps<'blockquote'> { }
interface UlProps extends ComponentProps<'ul'> { }
interface OlProps extends ComponentProps<'ol'> { }
interface ListItemProps extends ComponentProps<'li'> { }
const components = {
h1: (props: ComponentProps<'h1'>) =>
,
h2: (props: ComponentProps<'h2'>) => ,
p: (props: ComponentProps<'p'>) => ,
code: ({ className, children, ...props }: CodeProps) => (
{children}
),
pre: (props: ComponentProps<'pre'>) => (
),
blockquote: (props: BlockquoteProps) => (
),
ul: (props: UlProps) => ,
ol: (props: OlProps) =>
,
li: (props: ListItemProps) =>
};
const App = () => {
const [Content, setContent] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [reloading, setReloading] = useState(false);
useEffect(() => {
const loadMDX = async () => {
if (!loading) {
setReloading(true);
}
try {
const response = await fetch('/example.mdx?t=' + Date.now());
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const text = await response.text();
const compiledCode = await compile(text, {
outputFormat: 'function-body',
development: import.meta.env.DEV,
});
const code = String(compiledCode);
console.log('Raw compiled code:', code);
try {
// Define basic HTML components for missing ones
const htmlComponents = {
h3: (props: any) => ,
h4: (props: any) => ,
h5: (props: any) => ,
h6: (props: any) => ,
a: (props: any) => ,
img: (props: any) =>
,
hr: (props: any) =>
,
br: (props: any) =>
,
em: (props: any) => ,
strong: (props: any) => ,
table: (props: any) => ,
thead: (props: any) => ,
tbody: (props: any) => ,
tr: (props: any) =>
,
th: (props: any) => | ,
td: (props: any) => | ,
div: (props: any) => ,
span: (props: any) => ,
};
// Merge all components
const allComponents = { ...components, ...htmlComponents };
const scope = {
React,
components: allComponents,
createElement,
Fragment: React.Fragment,
jsx: runtime.jsx,
jsxs: runtime.jsxs,
// Include all components directly in scope
h1: allComponents.h1,
h2: allComponents.h2,
h3: allComponents.h3,
h4: allComponents.h4,
h5: allComponents.h5,
h6: allComponents.h6,
p: allComponents.p,
a: allComponents.a,
img: allComponents.img,
ul: allComponents.ul,
ol: allComponents.ol,
li: allComponents.li,
blockquote: allComponents.blockquote,
hr: allComponents.hr,
br: allComponents.br,
em: allComponents.em,
strong: allComponents.strong,
code: allComponents.code,
pre: allComponents.pre,
table: allComponents.table,
thead: allComponents.thead,
tbody: allComponents.tbody,
tr: allComponents.tr,
th: allComponents.th,
td: allComponents.td,
div: allComponents.div,
span: allComponents.span,
};
const keys = Object.keys(scope);
const values = Object.values(scope);
// Try to evaluate the code using a more robust approach
try {
// First, try to execute as function body
const fn1 = new Function(
...keys,
`${code}; return MDXContent;`
);
const Component1 = fn1(...values);
const MDXComponent1 = Component1.default || Component1;
if (MDXComponent1) {
setContent(() => MDXComponent1);
setLoading(false);
return;
}
} catch (e1) {
console.log('First evaluation method failed, trying second...');
}
try {
// Second, try to execute as function expression
const fn2 = new Function(
...keys,
`return ${code}`
);
const Component2 = fn2(...values);
const MDXComponent2 = Component2.default || Component2;
if (MDXComponent2) {
setContent(() => MDXComponent2);
setLoading(false);
return;
}
} catch (e2) {
console.log('Second evaluation method failed, trying third...');
}
try {
// Third, try to execute directly with eval-like approach
const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
const fn3 = new AsyncFunction(
...keys,
code
);
const result = await fn3(...values);
const MDXComponent3 = result.default || result;
if (MDXComponent3) {
setContent(() => MDXComponent3);
setLoading(false);
return;
}
} catch (e3) {
console.log('Third evaluation method failed');
}
throw new Error('All evaluation methods failed');
} catch (evalError) {
console.error('Evaluation error:', evalError);
console.error('Compiled code sample:', code.substring(0, 500));
const errorMessage = evalError instanceof Error ? evalError.message : String(evalError);
throw new Error(`MDX evaluation failed: ${errorMessage}`);
}
} catch (err) {
console.error('Error loading MDX:', err);
setError(err instanceof Error ? err.message : String(err));
setLoading(false);
} finally {
setReloading(false);
}
};
loadMDX();
// Set up interval for auto-reloading during development
let intervalId: NodeJS.Timeout;
if (import.meta.env.DEV) {
intervalId = setInterval(loadMDX, 2000); // Check every 2 seconds
}
return () => {
if (intervalId) {
clearInterval(intervalId);
}
};
}, [loading]);
if (loading) {
return (
MDX Viewer
Loading MDX content...
);
}
if (error) {
return (
MDX Viewer
Error loading MDX:
{error}
);
}
return (
MDX Viewer
{reloading && (
🔄 Reloading...
)}
{Content &&
}
);
};
export default App;