fix: doc rendering — markdown prose styling, code blocks with copy button, proper step parsing

- Add @tailwindcss/typography plugin for prose styling
- Create CodeBlock component with copy button and language labels
- Create Md wrapper component using ReactMarkdown with custom renderers
- Replace all plain text renders with Md for proper markdown formatting
- Fix parseSteps() in pipeline to group numbered steps with code blocks
- Add First Task subtitle explaining its purpose
- Add conditional file.purpose render in module key files
This commit is contained in:
Vectry
2026-02-09 18:18:24 +00:00
parent 029cd82f1a
commit cbe52f32b3
6 changed files with 182 additions and 30 deletions

View File

@@ -0,0 +1,55 @@
"use client";
import { useState, type ReactNode } from "react";
import { Check, Copy } from "lucide-react";
interface CodeBlockProps {
children: ReactNode;
className?: string;
inline?: boolean;
}
export function CodeBlock({ children, className, inline }: CodeBlockProps) {
const [copied, setCopied] = useState(false);
if (inline) {
return (
<code className="px-1.5 py-0.5 rounded bg-white/10 text-blue-300 text-[0.85em] font-mono border border-white/5">
{children}
</code>
);
}
const language = className?.replace("language-", "") || "";
const codeString = String(children).replace(/\n$/, "");
const handleCopy = async () => {
await navigator.clipboard.writeText(codeString);
setCopied(true);
window.setTimeout(() => setCopied(false), 2000);
};
return (
<div className="relative group my-4">
{language && (
<div className="absolute top-0 left-0 px-3 py-1 text-[10px] font-medium uppercase tracking-wider text-zinc-500 bg-black/30 rounded-tl-lg rounded-br-lg border-b border-r border-white/5">
{language}
</div>
)}
<button
onClick={handleCopy}
className="absolute top-2 right-2 p-1.5 rounded-md bg-white/5 border border-white/10 text-zinc-500 hover:text-white hover:bg-white/10 transition-all opacity-0 group-hover:opacity-100 z-10"
aria-label="Copy code"
>
{copied ? (
<Check className="w-3.5 h-3.5 text-green-400" />
) : (
<Copy className="w-3.5 h-3.5" />
)}
</button>
<pre className="overflow-x-auto rounded-lg bg-black/50 border border-white/10 p-4 pt-8 text-sm leading-relaxed font-mono scrollbar-thin">
<code className={`text-zinc-300 ${className || ""}`}>{codeString}</code>
</pre>
</div>
);
}