import { existsSync, unlinkSync, mkdirSync, readFileSync, readdirSync, writeFileSync, } from "node:fs"; import { join } from "node:path"; export async function generateCatalogPages({ exampleRoot, pagesDir, blockComponents, componentMount, demoConfiguration, slugOf, displayName, escapeCode, resetHoistedObjects, hoistedObjectStates, }) { const write = (path, text) => { mkdirSync(join(pagesDir, path.substring(0, path.lastIndexOf("/")) || "."), { recursive: true }); writeFileSync(join(pagesDir, path), text); }; const codePanel = (source, id = "example-source") => `

Copy this example

${escapeCode(source)}
`; const page = (name, title, body) => `page ${name} {\n layout = "gallery"\n seo { title = "${title}" }\n view { ${body} }\n}\n`; const cards = (entries) => `
${entries.map((e) => `

${e.title}

${e.description}

Open example →
`).join("")}
`; const examples = [ { slug: "workspace", title: "Workspace overview", icon: "layout-dashboard", description: "A complete dashboard with navigation, metrics, and service cards.", }, { slug: "profile", title: "Profile & preferences", icon: "user-round", description: "A responsive settings form with grouped fields and save feedback.", }, { slug: "sign-in", title: "Sign in", icon: "log-in", description: "A focused authentication page with a compact form.", }, { slug: "scheduling", title: "Scheduling", icon: "calendar-days", description: "Date, date-and-time, and time controls in a practical form.", }, { slug: "custom-modal", title: "Custom modal", icon: "panels-top-left", description: "Open and close a fully controlled dialog from your own buttons.", }, { slug: "project-board", title: "Project workspace", icon: "list-checks", description: "Reorder priorities and write rich-text project updates.", }, ]; const extra = { scheduling: `page SchedulingExample {\n view {

Schedule a meeting

Choose the date and time that work for your team.

}\n}`, "custom-modal": `page CustomModalExample {\n state dialogOpen: boolean = false\n view {

Your own modal controls

}\n}`, "project-board": `page ProjectBoardExample {\n state tasks = [{label:"Review designs"},{label:"Build the dashboard"},{label:"Test accessibility"}]\n view {

Project workspace

}\n}`, }; for (const e of examples) { const old = join(pagesDir, "templates", e.slug + ".wrn"); if (existsSync(old)) unlinkSync(old); } const css = readFileSync(join(exampleRoot, "app/styles/workspace-preview.css"), "utf8"); for (const e of examples) { const source = extra[e.slug] || readFileSync(join(exampleRoot, "examples", e.slug + ".wrn"), "utf8"); const at = source.lastIndexOf("\n }"); let rendered; if (at >= 0) rendered = source.slice(0, at) + codePanel(source) + `
Page styles · copy with the example
${escapeCode(css)}
` + source.slice(at); else rendered = source.replace(/}\s*}\s*$/, codePanel(source) + " } }"); rendered = rendered.replace( /\bview\s*\{/, 'view {\n', ); write(`preview/${e.slug}.wrn`, rendered); } write( "preview/index.wrn", page( "PreviewIndex", "Examples", `
Ready to use

Page examples

Explore complete layouts, interact with the controls, and copy the source.

${cards(examples.map((e) => ({ ...e, href: "/preview/" + e.slug })))}`, ), ); const templateGroups = [ { slug: "dashboards", title: "Dashboards & admin", icon: "layout-dashboard", description: "Analytics and account operations with meaningful metrics.", heading: "Workspace performance", body: ``, }, { slug: "commerce", title: "Commerce", icon: "shopping-bag", description: "A product collection with a working shopping bag.", heading: "Everyday essentials", body: `

Thoughtfully made tools for your desk.

Shopping bag: {bag} items