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:
@@ -12,6 +12,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codeboard/shared": "*",
|
"@codeboard/shared": "*",
|
||||||
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"bullmq": "^5.34.0",
|
"bullmq": "^5.34.0",
|
||||||
"ioredis": "^5.4.0",
|
"ioredis": "^5.4.0",
|
||||||
"lucide-react": "^0.563.0",
|
"lucide-react": "^0.563.0",
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
@import "tailwindcss";
|
@import "tailwindcss";
|
||||||
|
@plugin "@tailwindcss/typography";
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
--background: #0a0a0f;
|
--background: #0a0a0f;
|
||||||
|
|||||||
55
apps/web/src/components/code-block.tsx
Normal file
55
apps/web/src/components/code-block.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useState } from "react";
|
import { useState, type ComponentPropsWithoutRef } from "react";
|
||||||
import type { GeneratedDocs, DocsModule } from "@codeboard/shared";
|
import type { GeneratedDocs, DocsModule } from "@codeboard/shared";
|
||||||
import { MermaidDiagram } from "./mermaid-diagram";
|
import { MermaidDiagram } from "./mermaid-diagram";
|
||||||
|
import { CodeBlock } from "./code-block";
|
||||||
import ReactMarkdown from "react-markdown";
|
import ReactMarkdown from "react-markdown";
|
||||||
import {
|
import {
|
||||||
BookOpen,
|
BookOpen,
|
||||||
@@ -21,6 +22,31 @@ interface DocViewerProps {
|
|||||||
docs: GeneratedDocs;
|
docs: GeneratedDocs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const markdownComponents = {
|
||||||
|
pre({ children, ...props }: ComponentPropsWithoutRef<"pre">) {
|
||||||
|
return <>{children}</>;
|
||||||
|
},
|
||||||
|
code({ children, className, ...props }: ComponentPropsWithoutRef<"code"> & { inline?: boolean }) {
|
||||||
|
const isBlock =
|
||||||
|
className?.startsWith("language-") ||
|
||||||
|
(typeof children === "string" && children.includes("\n"));
|
||||||
|
if (isBlock) {
|
||||||
|
return (
|
||||||
|
<CodeBlock className={className}>{children}</CodeBlock>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return <CodeBlock inline>{children}</CodeBlock>;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
function Md({ children }: { children: string }) {
|
||||||
|
return (
|
||||||
|
<div className="prose prose-invert prose-sm max-w-none prose-p:text-zinc-300 prose-p:leading-relaxed prose-headings:text-white prose-strong:text-white prose-a:text-blue-400 prose-a:no-underline hover:prose-a:underline prose-li:text-zinc-300 prose-code:before:content-none prose-code:after:content-none prose-pre:bg-transparent prose-pre:p-0">
|
||||||
|
<ReactMarkdown components={markdownComponents}>{children}</ReactMarkdown>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export function DocViewer({ docs }: DocViewerProps) {
|
export function DocViewer({ docs }: DocViewerProps) {
|
||||||
const [activeSection, setActiveSection] = useState("overview");
|
const [activeSection, setActiveSection] = useState("overview");
|
||||||
const [expandedModules, setExpandedModules] = useState<Set<string>>(
|
const [expandedModules, setExpandedModules] = useState<Set<string>>(
|
||||||
@@ -116,9 +142,7 @@ export function DocViewer({ docs }: DocViewerProps) {
|
|||||||
<h1 className="text-3xl sm:text-4xl font-bold text-white mb-4">
|
<h1 className="text-3xl sm:text-4xl font-bold text-white mb-4">
|
||||||
{docs.sections.overview.title}
|
{docs.sections.overview.title}
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-zinc-400">
|
<Md>{docs.sections.overview.description}</Md>
|
||||||
{docs.sections.overview.description}
|
|
||||||
</p>
|
|
||||||
<div className="flex flex-wrap gap-2 mt-4">
|
<div className="flex flex-wrap gap-2 mt-4">
|
||||||
{docs.sections.overview.techStack.map((tech: string) => (
|
{docs.sections.overview.techStack.map((tech: string) => (
|
||||||
<span
|
<span
|
||||||
@@ -195,7 +219,9 @@ export function DocViewer({ docs }: DocViewerProps) {
|
|||||||
|
|
||||||
{expandedModules.has(module.name) && (
|
{expandedModules.has(module.name) && (
|
||||||
<div className="px-5 pb-5 border-t border-white/10">
|
<div className="px-5 pb-5 border-t border-white/10">
|
||||||
<p className="text-zinc-300 mt-4 mb-4">{module.summary}</p>
|
<div className="mt-4 mb-4">
|
||||||
|
<Md>{module.summary}</Md>
|
||||||
|
</div>
|
||||||
|
|
||||||
{module.keyFiles.length > 0 && (
|
{module.keyFiles.length > 0 && (
|
||||||
<div className="mb-4">
|
<div className="mb-4">
|
||||||
@@ -211,7 +237,9 @@ export function DocViewer({ docs }: DocViewerProps) {
|
|||||||
<FileCode className="w-4 h-4 text-zinc-500 mt-0.5 flex-shrink-0" />
|
<FileCode className="w-4 h-4 text-zinc-500 mt-0.5 flex-shrink-0" />
|
||||||
<div>
|
<div>
|
||||||
<code className="text-blue-300">{file.path}</code>
|
<code className="text-blue-300">{file.path}</code>
|
||||||
<p className="text-zinc-500">{file.purpose}</p>
|
{file.purpose && (
|
||||||
|
<p className="text-zinc-500">{file.purpose}</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
@@ -252,11 +280,11 @@ export function DocViewer({ docs }: DocViewerProps) {
|
|||||||
<div className="grid gap-6 md:grid-cols-2">
|
<div className="grid gap-6 md:grid-cols-2">
|
||||||
<div className="glass rounded-xl p-6">
|
<div className="glass rounded-xl p-6">
|
||||||
<h3 className="font-semibold text-white mb-4">Coding Conventions</h3>
|
<h3 className="font-semibold text-white mb-4">Coding Conventions</h3>
|
||||||
<ul className="space-y-2">
|
<ul className="space-y-3">
|
||||||
{docs.sections.patterns.conventions.map((convention: string, i: number) => (
|
{docs.sections.patterns.conventions.map((convention: string, i: number) => (
|
||||||
<li key={i} className="flex items-start gap-2 text-sm text-zinc-300">
|
<li key={i} className="flex items-start gap-2 text-sm">
|
||||||
<span className="text-blue-400 mt-1">•</span>
|
<span className="text-blue-400 mt-1 flex-shrink-0">•</span>
|
||||||
{convention}
|
<Md>{convention}</Md>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -264,11 +292,11 @@ export function DocViewer({ docs }: DocViewerProps) {
|
|||||||
|
|
||||||
<div className="glass rounded-xl p-6">
|
<div className="glass rounded-xl p-6">
|
||||||
<h3 className="font-semibold text-white mb-4">Design Patterns</h3>
|
<h3 className="font-semibold text-white mb-4">Design Patterns</h3>
|
||||||
<ul className="space-y-2">
|
<ul className="space-y-3">
|
||||||
{docs.sections.patterns.designPatterns.map((pattern: string, i: number) => (
|
{docs.sections.patterns.designPatterns.map((pattern: string, i: number) => (
|
||||||
<li key={i} className="flex items-start gap-2 text-sm text-zinc-300">
|
<li key={i} className="flex items-start gap-2 text-sm">
|
||||||
<span className="text-blue-400 mt-1">•</span>
|
<span className="text-blue-400 mt-1 flex-shrink-0">•</span>
|
||||||
{pattern}
|
<Md>{pattern}</Md>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -282,9 +310,9 @@ export function DocViewer({ docs }: DocViewerProps) {
|
|||||||
</h3>
|
</h3>
|
||||||
<ul className="space-y-3">
|
<ul className="space-y-3">
|
||||||
{docs.sections.patterns.architecturalDecisions.map((decision: string, i: number) => (
|
{docs.sections.patterns.architecturalDecisions.map((decision: string, i: number) => (
|
||||||
<li key={i} className="flex items-start gap-3 text-zinc-300">
|
<li key={i} className="flex items-start gap-3">
|
||||||
<GitBranch className="w-5 h-5 text-blue-400 flex-shrink-0 mt-0.5" />
|
<GitBranch className="w-5 h-5 text-blue-400 flex-shrink-0 mt-0.5" />
|
||||||
{decision}
|
<Md>{decision}</Md>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -303,9 +331,9 @@ export function DocViewer({ docs }: DocViewerProps) {
|
|||||||
<h3 className="font-semibold text-white mb-4">Prerequisites</h3>
|
<h3 className="font-semibold text-white mb-4">Prerequisites</h3>
|
||||||
<ul className="space-y-2">
|
<ul className="space-y-2">
|
||||||
{docs.sections.gettingStarted.prerequisites.map((prereq: string, i: number) => (
|
{docs.sections.gettingStarted.prerequisites.map((prereq: string, i: number) => (
|
||||||
<li key={i} className="flex items-center gap-2 text-sm text-zinc-300">
|
<li key={i} className="flex items-start gap-2 text-sm">
|
||||||
<span className="w-1.5 h-1.5 rounded-full bg-green-400" />
|
<span className="w-1.5 h-1.5 rounded-full bg-green-400 mt-1.5 flex-shrink-0" />
|
||||||
{prereq}
|
<Md>{prereq}</Md>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
@@ -313,25 +341,26 @@ export function DocViewer({ docs }: DocViewerProps) {
|
|||||||
|
|
||||||
<div className="glass rounded-xl p-6">
|
<div className="glass rounded-xl p-6">
|
||||||
<h3 className="font-semibold text-white mb-4">Setup Steps</h3>
|
<h3 className="font-semibold text-white mb-4">Setup Steps</h3>
|
||||||
<ol className="space-y-4">
|
<ol className="space-y-6">
|
||||||
{docs.sections.gettingStarted.setupSteps.map((step: string, i: number) => (
|
{docs.sections.gettingStarted.setupSteps.map((step: string, i: number) => (
|
||||||
<li key={i} className="flex gap-4">
|
<li key={i} className="flex gap-4">
|
||||||
<span className="flex-shrink-0 w-6 h-6 rounded-full bg-blue-500/20 text-blue-300 text-sm flex items-center justify-center font-medium">
|
<span className="flex-shrink-0 w-7 h-7 rounded-full bg-blue-500/20 text-blue-300 text-sm flex items-center justify-center font-medium mt-0.5">
|
||||||
{i + 1}
|
{i + 1}
|
||||||
</span>
|
</span>
|
||||||
<div className="prose prose-invert prose-sm max-w-none">
|
<div className="flex-1 min-w-0">
|
||||||
<ReactMarkdown>{step}</ReactMarkdown>
|
<Md>{step}</Md>
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="glass rounded-xl p-6 border-blue-500/20">
|
<div className="glass rounded-xl p-6 border border-blue-500/20">
|
||||||
<h3 className="font-semibold text-white mb-3">First Task</h3>
|
<h3 className="font-semibold text-white mb-1">First Task</h3>
|
||||||
<div className="prose prose-invert prose-sm max-w-none">
|
<p className="text-sm text-zinc-500 mb-4">
|
||||||
<ReactMarkdown>{docs.sections.gettingStarted.firstTask}</ReactMarkdown>
|
A suggested first contribution to help you learn the codebase
|
||||||
</div>
|
</p>
|
||||||
|
<Md>{docs.sections.gettingStarted.firstTask}</Md>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|||||||
45
package-lock.json
generated
45
package-lock.json
generated
@@ -24,6 +24,7 @@
|
|||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@codeboard/shared": "*",
|
"@codeboard/shared": "*",
|
||||||
|
"@tailwindcss/typography": "^0.5.19",
|
||||||
"bullmq": "^5.34.0",
|
"bullmq": "^5.34.0",
|
||||||
"ioredis": "^5.4.0",
|
"ioredis": "^5.4.0",
|
||||||
"lucide-react": "^0.563.0",
|
"lucide-react": "^0.563.0",
|
||||||
@@ -1491,6 +1492,18 @@
|
|||||||
"tailwindcss": "4.1.18"
|
"tailwindcss": "4.1.18"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/typography": {
|
||||||
|
"version": "0.5.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.19.tgz",
|
||||||
|
"integrity": "sha512-w31dd8HOx3k9vPtcQh5QHP9GwKcgbMp87j58qi6xgiBnFFtKEAgCWnDw4qUT8aHwkCp8bKvb/KGKWWHedP0AAg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"postcss-selector-parser": "6.0.10"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20 || >=4.0.0-beta.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@types/babel__traverse": {
|
"node_modules/@types/babel__traverse": {
|
||||||
"version": "7.28.0",
|
"version": "7.28.0",
|
||||||
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
|
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz",
|
||||||
@@ -2236,6 +2249,18 @@
|
|||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/cssesc": {
|
||||||
|
"version": "3.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
|
||||||
|
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"cssesc": "bin/cssesc"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/csstype": {
|
"node_modules/csstype": {
|
||||||
"version": "3.2.3",
|
"version": "3.2.3",
|
||||||
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
|
||||||
@@ -5030,6 +5055,19 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/postcss-selector-parser": {
|
||||||
|
"version": "6.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
|
||||||
|
"integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"cssesc": "^3.0.0",
|
||||||
|
"util-deprecate": "^1.0.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/prisma": {
|
"node_modules/prisma": {
|
||||||
"version": "6.19.2",
|
"version": "6.19.2",
|
||||||
"resolved": "https://registry.npmjs.org/prisma/-/prisma-6.19.2.tgz",
|
"resolved": "https://registry.npmjs.org/prisma/-/prisma-6.19.2.tgz",
|
||||||
@@ -5421,7 +5459,6 @@
|
|||||||
"version": "4.1.18",
|
"version": "4.1.18",
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz",
|
||||||
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
|
"integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==",
|
||||||
"dev": true,
|
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/tapable": {
|
"node_modules/tapable": {
|
||||||
@@ -5723,6 +5760,12 @@
|
|||||||
"url": "https://opencollective.com/unified"
|
"url": "https://opencollective.com/unified"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/util-deprecate": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/uuid": {
|
"node_modules/uuid": {
|
||||||
"version": "11.1.0",
|
"version": "11.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
|
||||||
|
|||||||
@@ -23,6 +23,29 @@ function parseList(text: string): string[] {
|
|||||||
.filter(Boolean);
|
.filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function parseSteps(text: string): string[] {
|
||||||
|
const lines = text.split("\n");
|
||||||
|
const steps: string[] = [];
|
||||||
|
let current = "";
|
||||||
|
|
||||||
|
for (const line of lines) {
|
||||||
|
if (/^\d+\.\s/.test(line)) {
|
||||||
|
if (current.trim()) {
|
||||||
|
steps.push(current.trim());
|
||||||
|
}
|
||||||
|
current = line.replace(/^\d+\.\s*/, "");
|
||||||
|
} else {
|
||||||
|
current += "\n" + line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current.trim()) {
|
||||||
|
steps.push(current.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
return steps.filter(Boolean);
|
||||||
|
}
|
||||||
|
|
||||||
export async function generateDocumentation(
|
export async function generateDocumentation(
|
||||||
codeStructure: CodeStructure,
|
codeStructure: CodeStructure,
|
||||||
provider: LLMProvider,
|
provider: LLMProvider,
|
||||||
@@ -112,7 +135,7 @@ export async function generateDocumentation(
|
|||||||
const gsResponse = await provider.chat(gsMessages);
|
const gsResponse = await provider.chat(gsMessages);
|
||||||
|
|
||||||
const prerequisites = parseList(parseSection(gsResponse, "Prerequisites"));
|
const prerequisites = parseList(parseSection(gsResponse, "Prerequisites"));
|
||||||
const setupSteps = parseList(parseSection(gsResponse, "Setup Steps"));
|
const setupSteps = parseSteps(parseSection(gsResponse, "Setup Steps"));
|
||||||
const firstTask = parseSection(gsResponse, "Your First Task");
|
const firstTask = parseSection(gsResponse, "Your First Task");
|
||||||
|
|
||||||
onProgress?.("complete", 100);
|
onProgress?.("complete", 100);
|
||||||
|
|||||||
Reference in New Issue
Block a user