diff --git a/scripts/generate-docs.ts b/scripts/generate-docs.ts index a19f0a74..ab43483b 100644 --- a/scripts/generate-docs.ts +++ b/scripts/generate-docs.ts @@ -11,6 +11,24 @@ const pages = join(root, "app", "pages"); const packagePages = join(pages, "packages"); mkdirSync(packagePages, { recursive: true }); +interface UiComponentReference { + count: number; + components: Array<{ + name: string; + mount: string; + category: string; + purpose: string; + props: Array<{ name: string; type: string; required: boolean; default: string | null }>; + slots: string[]; + events: string[]; + }>; +} + +const uiReferencePath = join(root, "node_modules", "@wrnexus", "ui", "component-reference.json"); +const uiReference: UiComponentReference | undefined = existsSync(uiReferencePath) + ? JSON.parse(readFileSync(uiReferencePath, "utf8")) + : undefined; + const catalog = [ ["ai", "AI", "Server-side Anthropic client with generation and streaming."], ["authz", "Security", "Role, permission, policy, and authorization guards."], @@ -299,11 +317,30 @@ for (const [name, category, summary] of catalog) { .replace(/\bWrNexus\b/g, "WRNexusJS"); const types = readFileSync(typesPath, "utf8"); const guide = markdown(readme); + const componentReference = + name === "ui" && uiReference + ? `

All ${uiReference.count} UI components and props

This reference is generated from the exact installed .wrn sources. Required props have no default; optional props show their default value.

${[ + ...new Set(uiReference.components.map((component) => component.category)), + ] + .sort() + .map( + (componentCategory) => + `

${escape(componentCategory[0]!.toUpperCase() + componentCategory.slice(1))}

${uiReference.components + .filter((component) => component.category === componentCategory) + .map( + (component) => + ``, + ) + .join("")}
ComponentPropsSlotsEvents
${escape(component.name)}
data-component="${escape(component.mount)}"
${escape(component.purpose)}
${component.props.length ? component.props.map((prop) => `${escape(prop.name)}: ${escape(prop.type)}${prop.required ? " (required)" : ` = ${escape(prop.default ?? "")}`}`).join("
") : "None"}
${component.slots.length ? component.slots.map((slot) => `${escape(slot)}`).join("
") : "None"}
${component.events.length ? component.events.map((event) => `${escape(event)}`).join("
") : "None"}
`, + ) + .join("")}
` + : ""; const toc = [ { id: "guide", title: "Guide", level: 2 }, ...guide.headings, { id: "api", title: "Complete API", level: 2 }, { id: "examples", title: "Examples", level: 2 }, + ...(componentReference ? [{ id: "components", title: "All UI components", level: 2 }] : []), ] .map( (heading) => @@ -312,7 +349,7 @@ for (const [name, category, summary] of catalog) { .join(""); const content = `
-
${category} · Preview

@wrnexus/${name}

${summary}

Private registry access required

This package is not available from the public npm registry. After WorkRoot approves access and supplies private registry instructions, install the release-aligned package:

bun add @wrnexus/${name}@${frameworkVersion}

Request preview access. Never put registry tokens in source control.

${guide.html}

Complete TypeScript API

This declaration comes from the exact installed package and lists its exported functions, classes, interfaces, and types.

${escape(types)}

Examples

Examples are taken from this package's installed documentation and must be evaluated with its requirements and stability notes.

${examplesFrom(readme, name)}
+
${category} · Preview

@wrnexus/${name}

${summary}

Private registry access required

This package is not available from the public npm registry. After WorkRoot approves access and supplies private registry instructions, install the release-aligned package:

bun add @wrnexus/${name}@${frameworkVersion}

Request preview access. Never put registry tokens in source control.

${guide.html}

Complete TypeScript API

This declaration comes from the exact installed package and lists its exported functions, classes, interfaces, and types.

${escape(types)}

Examples

Examples are taken from this package's installed documentation and must be evaluated with its requirements and stability notes.

${examplesFrom(readme, name)}
${componentReference}
`; writeFileSync(join(packagePages, `${name}.wrn`), shell(`@wrnexus/${name}`, summary, content)); diff --git a/scripts/generate-portal.ts b/scripts/generate-portal.ts index 567b021c..cbdddac6 100644 --- a/scripts/generate-portal.ts +++ b/scripts/generate-portal.ts @@ -1,4 +1,4 @@ -import { mkdirSync, readFileSync, writeFileSync } from "node:fs"; +import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs"; import { join, resolve } from "node:path"; import { format } from "prettier"; @@ -15,6 +15,28 @@ const packageNames = [...Object.keys(pkg.dependencies), ...Object.keys(pkg.devDe .filter((name, index, all) => all.indexOf(name) === index) .sort(); const packageCount = packageNames.length; +const uiReferencePath = join(root, "node_modules", "@wrnexus", "ui", "component-reference.json"); +const uiReference = existsSync(uiReferencePath) + ? (JSON.parse(readFileSync(uiReferencePath, "utf8")) as { + count: number; + components: Array<{ + name: string; + mount: string; + category: string; + props: Array<{ name: string; type: string; required: boolean; default: string | null }>; + slots: string[]; + events: string[]; + }>; + }) + : undefined; +const uiReferenceText = uiReference + ? uiReference.components + .map( + (component) => + `### ${component.name}\nMount: data-component="${component.mount}"\nCategory: ${component.category}\nProps: ${component.props.length ? component.props.map((prop) => `${prop.name}: ${prop.type}${prop.required ? " (required)" : ` = ${prop.default}`}`).join(", ") : "none"}\nSlots: ${component.slots.join(", ") || "none"}\nEvents: ${component.events.join(", ") || "none"}`, + ) + .join("\n\n") + : "UI component reference unavailable; install the release-aligned @wrnexus/ui package."; async function writeFormatted(path: string, source: string) { writeFileSync(path, await format(source, { filepath: path })); @@ -487,7 +509,7 @@ await writeFormatted( ); writeFileSync( join(pub, "llms-full.txt"), - `# WRNexusJS ${version} comprehensive documentation index\n\nStatus: Private Developer Preview. Runtime: Bun. UI language: .wrn.\nThis is the documentation application, not the framework monorepo.\n\n${urls.map((x) => `- https://wrnexusjs.dev${x}`).join("\n")}\n\nFor exact APIs, use installed package README files followed by exported declarations.\n`, + `# WRNexusJS ${version} comprehensive documentation index\n\nStatus: Private Developer Preview. Runtime: Bun. UI language: .wrn.\nThis is the documentation application, not the framework monorepo.\n\n${urls.map((x) => `- https://wrnexusjs.dev${x}`).join("\n")}\n\nFor exact APIs, use installed package README files followed by exported declarations.\n\n# Complete @wrnexus/ui component reference\n\n${uiReferenceText}\n`, ); const packageMarker = "# Installed package documentation"; @@ -511,7 +533,7 @@ const installedPackageDocs = packageNames .join("\n\n---\n\n"); writeFileSync( join(pub, "llms.txt"), - `${frameworkGuide}\n\n${packageMarker}\n\nThe following README files and declarations come from the installed private ${version} release.\n\n${installedPackageDocs}\n`, + `${frameworkGuide}\n\n# UI component catalog\n\nThe installed @wrnexus/ui release contains ${uiReference?.count ?? 0} documented components. Every mount name, prop type, required/default status, slot, and event is included below and in llms-full.txt.\n\n${uiReferenceText}\n\n${packageMarker}\n\nThe following README files and declarations come from the installed private ${version} release.\n\n${installedPackageDocs}\n`, ); const auditDocs: Record = {