From 77328f74417a9a997248815925868111dcaf0c44 Mon Sep 17 00:00:00 2001 From: Chris Wanstrath Date: Wed, 5 Nov 2025 11:37:49 -0800 Subject: [PATCH] add layout.sh support --- README.md | 4 ++-- src/server.ts | 38 ++++++++++++++++++++++++++++++-------- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 1c39679..909a53b 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,9 @@ - [x] Access to query params - [x] Serve static files in pub/ - [x] Working CLI -- [ ] Nice error messages +- [x] Nice error messages - [ ] dev mode / prod mode (caching, errors) - [ ] Form body parsing for POST - [ ] auto-serve index.sh for subdirectories (`/users` -> `/users/index.sh` if dir) -- [ ] Layouts +- [x] Layouts - [ ] Caching \ No newline at end of file diff --git a/src/server.ts b/src/server.ts index a31f648..1743e1c 100644 --- a/src/server.ts +++ b/src/server.ts @@ -21,20 +21,35 @@ export function startWeb(rootPath: string) { app.on(['GET', 'POST'], ['/', '/:page{.+}'], async (c) => { const page = c.req.param('page') || 'index' - const params = c.req.query() + if (page === 'layout') return c.text('404 Not Found', 404) + const params = c.req.query() const path = join(root, `${page}.sh`) const file = Bun.file(path) + + const layoutPath = join(root, `layout.sh`) + const layoutFile = Bun.file(layoutPath) + let layoutCode = await layoutFile.exists() ? await layoutFile.text() : '' + if (await file.exists()) { + let content = '' + try { - return c.html(await wrapAndRunCode(await file.text(), { params })) - } catch (e) { - let error = e instanceof Error ? e.message : String(e) - const ansiUp = new AnsiUp() - const errorHtml = ansiUp.ansi_to_html(error) - const blue = '#42A5F5' - return c.html(`

🫧 Error in ${path}

${errorHtml}
`) + content = await wrapAndRunCode(await file.text(), { params }) + } catch (err) { + return c.html(shrimpError(path, err), 500) } + + if (layoutCode) { + try { + return c.html(await wrapAndRunCode(layoutCode, { params, content })) + } catch (err) { + return c.html(shrimpError(layoutPath, err), 500) + } + } else { + return c.html(content) + } + } else { return c.text('404 Not Found', 404) } @@ -46,3 +61,10 @@ export function startWeb(rootPath: string) { port: 3000, }) } + +function shrimpError(path: string, error: any): string { + const ansiUp = new AnsiUp() + const errorHtml = ansiUp.ansi_to_html(error?.message ?? String(error)) + const blue = '#42A5F5' + return `

🫧 Error in ${path}

${errorHtml}
` +} \ No newline at end of file