diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dev.ts | 18 | ||||
-rw-r--r-- | src/frontend/500.astro | 128 | ||||
-rw-r--r-- | src/runtime.ts | 9 | ||||
-rw-r--r-- | src/search.ts | 18 |
4 files changed, 159 insertions, 14 deletions
diff --git a/src/dev.ts b/src/dev.ts index 505a99425..4ca8e28e9 100644 --- a/src/dev.ts +++ b/src/dev.ts @@ -72,7 +72,17 @@ export default async function dev(astroConfig: AstroConfig) { } } res.statusCode = 500; - res.end(formatErrorForBrowser(result.error)); + + let errorResult = await runtime.load(`/500?error=${encodeURIComponent(result.error.stack || result.error.toString())}`); + if(errorResult.statusCode === 200) { + if (errorResult.contentType) { + res.setHeader('Content-Type', errorResult.contentType); + } + res.write(errorResult.contents); + } else { + res.write(result.error.toString()); + } + res.end(); break; } } @@ -85,9 +95,3 @@ export default async function dev(astroConfig: AstroConfig) { info(logging, 'dev server', `${green('Local:')} http://${hostname}:${port}/`); }); } - -/** Format error message */ -function formatErrorForBrowser(err: Error) { - // TODO make this pretty. - return err.toString(); -} diff --git a/src/frontend/500.astro b/src/frontend/500.astro new file mode 100644 index 000000000..af7b901e9 --- /dev/null +++ b/src/frontend/500.astro @@ -0,0 +1,128 @@ +--- +import Prism from 'astro/components/Prism.astro'; +let title = 'Uh oh...'; + +const error = import.meta.request.url.searchParams.get('error'); +--- + +<!doctype html> +<html lang="en"> + <head> + <title>Error 500</title> + <link rel="preconnect"href="https://fonts.gstatic.com"> + <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono&family=IBM+Plex+Sans&display=swap"> + <link rel="stylesheet" href="http://cdn.skypack.dev/prism-themes/themes/prism-material-dark.css"> + + <style> + * { + box-sizing: border-box; + margin: 0; + } + + :global(:root) { + --font-sans: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif; + --font-mono: "IBM Plex Mono", Consolas, "Andale Mono WT", "Andale Mono", + "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", + "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, + "Courier New", Courier, monospace; + --color-gray-800: #1F2937; + --color-gray-500: #6B7280; + --color-gray-400: #9CA3AF; + --color-gray-100: #F3F4F6; + --color-red: #FF1639; + } + + html, body { + width: 100vw; + height: 100%; + min-height: 100vh; + + font-family: var(--font-sans); + font-weight: 400; + background: var(--color-gray-100); + text-align: center; + } + + body { + display: grid; + place-content: center; + } + + header { + display: flex; + flex-direction: column; + align-items: center; + font-family: var(--font-sans); + font-size: 2.5rem; + font-size: clamp(24px, calc(2vw + 1rem), 2.5rem); + } + + header h1 { + margin: 0.25em; + margin-right: 0; + font-weight: 400; + letter-spacing: -2px; + line-height: 1; + } + + header h1 .title { + color: var(--color-gray-400); + white-space: nowrap; + } + + header svg { + margin-bottom: -0.125em; + color: var(--color-red); + } + + p { + font-size: 1.75rem; + font-size: clamp(14px, calc(2vw + 0.5rem), 1.75rem); + flex: 1; + } + + .error-message { + display: grid; + justify-content: center; + margin-top: 4rem; + } + + .error-message :global(code[class*="language-"]) { + background: var(--color-gray-800); + } + .error-message :global(pre) { + margin: 0; + font-family: var(--font-mono); + font-size: 0.85rem; + background: var(--color-gray-800); + border-radius: 8px; + } + + .error-message :global(.token.punctuation) { + color: var(--color-gray-400); + } + + .error-message :global(.token.operator) { + color: var(--color-gray-400); + } + </style> + </head> + <body> + <main> + <header> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" width="1.75em" height="1.75em"> + <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" /> + </svg> + <h1><span class="error">500 Error </span><span class="title">{title}</span></h1> + </header> + + <article> + <p>Astro had some trouble loading this page.</p> + + <div class="error-message"> + <Prism lang="shell" code={error} /> + </div> + </article> + </main> + </body> +</html> diff --git a/src/runtime.ts b/src/runtime.ts index 330ca013b..a394d93c4 100644 --- a/src/runtime.ts +++ b/src/runtime.ts @@ -195,11 +195,20 @@ async function load(config: RuntimeConfig, rawPathname: string | undefined): Pro collection.data = data; } + const requestURL = new URL(fullurl.toString()); + + // For first release query params are not passed to components. + // An exception is made for dev server specific routes. + if(reqPath !== '/500') { + requestURL.search = ''; + } + let html = (await mod.exports.__renderPage({ request: { host: fullurl.hostname, path: fullurl.pathname, href: fullurl.toString(), + url: requestURL }, children: [], props: { collection }, diff --git a/src/search.ts b/src/search.ts index d4ed73f96..c141e4a77 100644 --- a/src/search.ts +++ b/src/search.ts @@ -91,6 +91,17 @@ export function searchForPage(url: URL, astroRoot: URL): SearchResult { } } + if(reqPath === '/500') { + return { + statusCode: 200, + location: { + fileURL: new URL('./frontend/500.astro', import.meta.url), + snowpackURL: `/_astro_internal/500.astro.js` + }, + pathname: reqPath + }; + } + return { statusCode: 404, }; @@ -128,10 +139,3 @@ function loadCollection(url: string, astroRoot: URL): { currentPage?: number; lo } } } - -/** convert a value to a number, if possible */ -function maybeNum(val: string): string | number { - const num = parseFloat(val); - if (num.toString() === val) return num; - return val; -} |