import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import rehypeKatex from "rehype-katex";
import type { Components } from "react-markdown";
function preprocessMarkdown(content: string): string {
let result = content.replace(/\|\|/g, "|\n|");
const lines = result.split("\n");
const processed = lines.map((line) => {
const tableStart = line.indexOf("|");
if (tableStart > 0) {
const tableContent = line.slice(tableStart);
if ((tableContent.match(/\|/g) ?? []).length >= 2) {
return line.slice(0, tableStart).trimEnd() + "\n\n" + tableContent;
}
}
return line;
});
result = processed.join("\n");
result = result.replace(/([^|\n])\n(\|)/g, "$1\n\n$2");
return result;
}
const components: Components = {
p: ({ children }) => (
{children}
),
h1: ({ children }) => (
{children}
),
h2: ({ children }) => (
{children}
),
h3: ({ children }) => (
{children}
),
ul: ({ children }) => (
),
ol: ({ children }) => (
{children}
),
li: ({ children }) => {children},
code: ({ children, className }) => {
const isBlock = className?.startsWith("language-");
const language = className?.replace("language-", "") ?? "";
if (isBlock) {
return (
{language && (
{language}
)}
{children}
);
}
return (
{children}
);
},
pre: ({ children }) => <>{children}>,
blockquote: ({ children }) => (
{children}
),
a: ({ children, href }) => (
{children}
),
strong: ({ children }) => {children},
hr: () =>
,
table: ({ children }) => (
),
thead: ({ children }) => (
{children}
),
th: ({ children }) => (
{children}
|
),
td: ({ children }) => (
{children} |
),
tr: ({ children }) => (
{children}
),
};
interface MarkdownRendererProps {
content: string;
skipPreprocess?: boolean;
}
export default function MarkdownRenderer({ content, skipPreprocess }: MarkdownRendererProps) {
const processed = skipPreprocess ? content : preprocessMarkdown(content);
if (!skipPreprocess) {
const hasCR = content.includes("\r");
const hasDoubleNewline = content.includes("\n\n");
// console.log(
// `[MarkdownRenderer] skipPreprocess=false contentLen=${content.length} same=${content === processed} hasCR=${hasCR} hasDoubleNewline=${hasDoubleNewline}`
// );
// console.log("[MarkdownRenderer] CONTENT JSON →", JSON.stringify(content.slice(0, 600)));
}
return (
{processed}
);
}