mdx-to-markdown.ts 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. /**
  2. * Converts raw MDX content to clean Markdown suitable for AI agents.
  3. *
  4. * Transformations:
  5. * - Remove `export` statements (metadata, etc.)
  6. * - Remove `import` statements
  7. * - Replace `<PackageInstall packages="x y" />` with a fenced bash code block
  8. * - Strip standalone JSX callout divs (the amber concept boxes)
  9. * - Pass everything else through as-is (already valid Markdown)
  10. */
  11. export function mdxToCleanMarkdown(raw: string): string {
  12. const lines = raw.split("\n");
  13. const out: string[] = [];
  14. let inJsxBlock = false;
  15. let jsxDepth = 0;
  16. for (const line of lines) {
  17. const trimmed = line.trim();
  18. // Skip export and import statements
  19. if (trimmed.startsWith("export ") || trimmed.startsWith("import ")) {
  20. continue;
  21. }
  22. // Handle PackageInstall component
  23. const pkgMatch = trimmed.match(
  24. /<PackageInstall\s+packages="([^"]+)"\s*\/>/,
  25. );
  26. if (pkgMatch) {
  27. const packages = pkgMatch[1];
  28. out.push("```bash");
  29. out.push(`pnpm add ${packages}`);
  30. out.push("```");
  31. out.push("");
  32. continue;
  33. }
  34. // Track JSX blocks (like the callout divs) and skip them
  35. if (
  36. !inJsxBlock &&
  37. trimmed.startsWith("<div ") &&
  38. trimmed.includes("className=")
  39. ) {
  40. inJsxBlock = true;
  41. jsxDepth = 1;
  42. continue;
  43. }
  44. if (inJsxBlock) {
  45. // Count opening/closing div tags to handle nesting
  46. const opens = (line.match(/<div[\s>]/g) || []).length;
  47. const closes = (line.match(/<\/div>/g) || []).length;
  48. jsxDepth += opens - closes;
  49. if (jsxDepth <= 0) {
  50. inJsxBlock = false;
  51. jsxDepth = 0;
  52. }
  53. continue;
  54. }
  55. out.push(line);
  56. }
  57. // Clean up leading blank lines
  58. let result = out.join("\n");
  59. result = result.replace(/^\n+/, "\n").trim();
  60. return result;
  61. }