diff --git a/src/lib/markdown/about.md b/src/lib/markdown/about.md index 038cf40..3a4685d 100644 --- a/src/lib/markdown/about.md +++ b/src/lib/markdown/about.md @@ -2,6 +2,6 @@ Hey, there! Thanks for checking out my site. I'm a full-stack software engineer, currently employed at Capital One and living in Richmond, Virgina with my wife, dog, and two cats. -My technical interests include systems programming and embedded systems (although, I don't get to work on that sort of technology much in a professional capacity these days). For work, I work with TypeScript and Node.js quite a lot, and also work on some vanilla JS web frontend stuff. I don't do a whole lot of frontend application development or design work, but I'll do it if you twist my arm - I always try to find tooling that makes it as easy as possible though. For example, this site is mostly written in markdown, and almost all of the styles come from [Tailwind](https://tailwindcss.com/). More about how this site is built over on my [blog](./blog). +My technical interests include systems programming and embedded systems (although, I don't get to work on that sort of technology much in a professional capacity these days). For work, I work with TypeScript and Node.js quite a lot, and also work on some vanilla JS web frontend stuff. I don't do a whole lot of frontend application development or design work, but I'll do it if you twist my arm - I always try to find tooling that makes it as easy as possible though. For example, this site is mostly written in markdown, and almost all of the styles come from [Tailwind](https://tailwindcss.com/). More about how this site is built over on my [blog](/blog/). -When I'm not writing code, I can usually be found sipping on a cup of coffee or pursuing one of my many hobbies. I enjoy camping, backpacking, fishing, and just generally anything that gets me outdoors - bonus points if I can bring my pup with me! I'm also an avid woodworker, motorcyclist, home mechanic, and general tinkerer. I always have a project going on (or more realisitically, several), so you'll never find me without something to work on - lately I've been juggling a few home renovation projects. You can check out my [blog pages](./blog) to find our more about my projects and hobbies. +When I'm not writing code, I can usually be found sipping on a cup of coffee or pursuing one of my many hobbies. I enjoy camping, backpacking, fishing, and just generally anything that gets me outdoors - bonus points if I can bring my pup with me! I'm also an avid woodworker, motorcyclist, home mechanic, and general tinkerer. I always have a project going on (or more realisitically, several), so you'll never find me without something to work on - lately I've been juggling a few home renovation projects. You can check out my [blog pages](/blog/) to find our more about my projects and hobbies. diff --git a/src/lib/types.ts b/src/lib/types.ts index cc932ac..1f17a9c 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -1,5 +1,3 @@ -import type { render } from "svelte/server"; - export type TagMetadata = { count: number; selected: boolean }; export type PostMetadata = { @@ -14,7 +12,7 @@ export type PostPreview = { }; export type Post = PostPreview & { - content: ReturnType; + content: string; }; export type GetPostRequest = { diff --git a/src/routes/+layout.ts b/src/routes/+layout.ts index 189f71e..e325c17 100644 --- a/src/routes/+layout.ts +++ b/src/routes/+layout.ts @@ -1 +1,2 @@ export const prerender = true; +export const trailingSlash = "always"; diff --git a/src/routes/api/post/[postId]/+server.ts b/src/routes/api/post/[postId]/+server.ts index 16dbc0a..cc6fe2c 100644 --- a/src/routes/api/post/[postId]/+server.ts +++ b/src/routes/api/post/[postId]/+server.ts @@ -12,6 +12,6 @@ export const GET: RequestHandler = async ({ return json({ id: params.postId, metadata: post.metadata, - content: render(post.default), + content: render(post.default).body, }); }; diff --git a/src/routes/blog/+layout.svelte b/src/routes/blog/+layout.svelte index bde3c64..c57305c 100644 --- a/src/routes/blog/+layout.svelte +++ b/src/routes/blog/+layout.svelte @@ -1,5 +1,5 @@
diff --git a/src/routes/blog/[postId]/+page.svelte b/src/routes/blog/[postId]/+page.svelte index df4d49a..b2514e2 100644 --- a/src/routes/blog/[postId]/+page.svelte +++ b/src/routes/blog/[postId]/+page.svelte @@ -1,13 +1,23 @@

{post.metadata.title}

-{@html post.content.html} +{#if PostContent} + +{/if} diff --git a/tests/blog-entry.spec.ts b/tests/blog-entry.spec.ts index dc551fe..ae9c49c 100644 --- a/tests/blog-entry.spec.ts +++ b/tests/blog-entry.spec.ts @@ -1,10 +1,30 @@ import { test, expect } from "@playwright/test"; -test.beforeEach(async ({ page }) => { - await page.goto("/blog/2-another-post"); +test("blog entries render correctly", async ({ page }) => { + await page.goto("/blog/2-another-post/"); + + await expect( + page.getByRole("heading", { name: "Just Messin' Around" }), + ).toBeVisible(); + await expect( + page.getByText("This is really just here for testing purposes"), + ).toBeVisible(); }); -test("blog entries render correctly", async ({ page }) => { - expect(await page.getByRole("heading").textContent()).toMatch(/.+/); - expect(await page.getByRole("paragraph").textContent()).toMatch(/.+/); +test("blog entries include prerendered content without JavaScript", async ({ + browser, + baseURL, +}) => { + const context = await browser.newContext({ javaScriptEnabled: false }); + const page = await context.newPage(); + + await page.goto(`${baseURL}/blog/2-another-post/`); + await expect( + page.getByRole("heading", { name: "Just Messin' Around" }), + ).toBeVisible(); + await expect( + page.getByText("This is really just here for testing purposes"), + ).toBeVisible(); + + await context.close(); }); diff --git a/tests/blog.spec.ts b/tests/blog.spec.ts index 9120462..b4699a1 100644 --- a/tests/blog.spec.ts +++ b/tests/blog.spec.ts @@ -1,7 +1,7 @@ import { test, expect } from "@playwright/test"; test.beforeEach(async ({ page }) => { - await page.goto("/blog"); + await page.goto("/blog/"); }); test("the Posts heading exists and has the appropriate aria role and level", async ({ @@ -43,6 +43,7 @@ test("filtering by tags works", async ({ page }) => { const tag = page.getByRole("button").filter({ hasText: "something else" }); const before = await page.getByRole("heading").count(); + await expect(tag).toBeVisible(); await tag.click(); const after = await page.getByRole("heading").count(); diff --git a/tests/layout.spec.ts b/tests/layout.spec.ts index a020d5c..7ba6d9d 100644 --- a/tests/layout.spec.ts +++ b/tests/layout.spec.ts @@ -42,15 +42,15 @@ test.describe("header navigation", () => { await Promise.all([ page.getByRole("link").filter({ hasText: "About 📕" }).click(), ]); - await expect(page).toHaveURL(new RegExp(`^${baseURL}/about$`)); + await expect(page).toHaveURL(new RegExp(`^${baseURL}/about/$`)); }); test("blog link", async ({ page, baseURL }) => { await Promise.all([ page.getByRole("link").filter({ hasText: "Blog ✍️" }).click(), - page.waitForURL(`${baseURL}/blog`), + page.waitForURL(`${baseURL}/blog/`), ]); - await expect(page).toHaveURL(new RegExp(`^${baseURL}/blog$`)); + await expect(page).toHaveURL(new RegExp(`^${baseURL}/blog/$`)); }); test("home link", async ({ page, baseURL }) => { @@ -76,9 +76,9 @@ test.describe("header navigation", () => { }); test("blog navigation works", async ({ page, baseURL }) => { - await page.goto("/blog"); + await page.goto("/blog/"); await Promise.all([page.getByRole("heading", { level: 2 }).first().click()]); - await expect(page).toHaveURL(new RegExp(`^${baseURL}/blog/.+$`)); + await expect(page).toHaveURL(new RegExp(`^${baseURL}/blog/.+/$`)); }); test("github navigation works", async ({ page }) => { diff --git a/vercel.json b/vercel.json index d582cba..1e9c7bc 100644 --- a/vercel.json +++ b/vercel.json @@ -1,9 +1,3 @@ { - "trailingSlash": false, - "rewrites": [ - { "source": "/blog", "destination": "/blog.html" }, - { "source": "/blog/:id", "destination": "/blog/:id.html" }, - { "source": "/about", "destination": "/about.html" }, - { "source": "/(.*)", "destination": "/index.html" } - ] + "trailingSlash": true }