Skip to content

Commit d51f25b

Browse files
just-be-devclaude
andauthored
feat: add games content kind support (#242)
Add support for a new "games" content kind with prefix "G". Updates code generation, URL manifest, content configuration, schemas, middleware pattern matching, and test coverage. Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
1 parent 81de6fe commit d51f25b

6 files changed

Lines changed: 29 additions & 3 deletions

File tree

scripts/gen-codes.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { join } from "node:path";
55
import { Code, type Kind } from "../src/utils/code";
66

77
const CONTENT_DIR = `${import.meta.dir}/../src/content`;
8-
const DEFAULT_DIRS = ["blog", "research", "projects", "talks"];
8+
const DEFAULT_DIRS = ["blog", "games", "research", "projects", "talks"];
99

1010
/**
1111
* Infer kind prefix from directory name
@@ -14,6 +14,8 @@ function inferKind(dir: string): Kind {
1414
switch (dir) {
1515
case "blog":
1616
return "B";
17+
case "games":
18+
return "G";
1719
case "research":
1820
return "R";
1921
case "projects":

scripts/gen-url-manifest.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { YAML } from "bun";
66

77
const CONTENT_DIR = `${import.meta.dir}/../src/content`;
88
const MANIFEST_PATH = `${import.meta.dir}/../src/content/url-manifest.yaml`;
9-
const DEFAULT_COLLECTIONS = ["blog", "research", "projects", "talks"];
9+
const DEFAULT_COLLECTIONS = ["blog", "games", "research", "projects", "talks"];
1010

1111
interface UrlManifest {
1212
version: string;

src/content.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { join } from "node:path";
66
import { load as loadYAML } from "js-yaml";
77
import {
88
blogSchema,
9+
gamesSchema,
910
projectsSchema,
1011
researchSchema,
1112
talksSchema,
@@ -22,6 +23,11 @@ const blog = defineCollection({
2223
schema: blogSchema,
2324
});
2425

26+
const games = defineCollection({
27+
loader: glob({ base: "./src/content/games", pattern: "**/*.{md,mdx}" }),
28+
schema: gamesSchema,
29+
});
30+
2531
const projects = defineCollection({
2632
loader: glob({ base: "./src/content/projects", pattern: "**/*.{md,mdx}" }),
2733
schema: projectsSchema,
@@ -131,6 +137,7 @@ const tags = defineCollection({
131137

132138
export const collections = {
133139
blog,
140+
games,
134141
projects,
135142
research,
136143
pages,

src/content/schemas.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ export const blogSchema = z.object({
1111
slugs: z.array(z.string()).optional(),
1212
});
1313

14+
export const gamesSchema = z.object({
15+
title: z.string(),
16+
description: z.string().optional(),
17+
date: z.coerce.date(),
18+
tags: z.array(z.string()).default([]),
19+
draft: z.boolean().default(false),
20+
code: z.string().optional(),
21+
slugs: z.array(z.string()).optional(),
22+
});
23+
1424
export const projectsSchema = z.object({
1525
title: z.string(),
1626
description: z.string().optional(),

src/middleware.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export const onRequest = defineMiddleware(async (context, next) => {
3030
}
3131

3232
// Check if first or second path segment is a code (format: [brpt][0-9a-f]{4})
33-
const codePattern = /^[brpt][0-9a-f]{4}$/i;
33+
const codePattern = /^[bgrpt][0-9a-f]{4}$/i;
3434
const firstSegmentIsCode = pathSegments[0] && codePattern.test(pathSegments[0]);
3535
const secondSegmentIsCode = pathSegments[1] && codePattern.test(pathSegments[1]);
3636

src/utils/code.test.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ describe("Code.fromDate()", () => {
3131
it("should support different kinds", () => {
3232
const date = new Date(Date.UTC(2024, 11, 6));
3333
expect(Code.fromDate(date, "B").toString()).toBe("B2392");
34+
expect(Code.fromDate(date, "G").toString()).toBe("G2392");
3435
expect(Code.fromDate(date, "R").toString()).toBe("R2392");
3536
expect(Code.fromDate(date, "P").toString()).toBe("P2392");
3637
expect(Code.fromDate(date, "T").toString()).toBe("T2392");
@@ -108,6 +109,7 @@ describe("Code.fromCode()", () => {
108109

109110
it("should accept all valid kinds", () => {
110111
expect(Code.fromCode("B2391").getKind()).toBe("B");
112+
expect(Code.fromCode("G2391").getKind()).toBe("G");
111113
expect(Code.fromCode("R2391").getKind()).toBe("R");
112114
expect(Code.fromCode("P2391").getKind()).toBe("P");
113115
expect(Code.fromCode("T2391").getKind()).toBe("T");
@@ -174,6 +176,7 @@ describe("Code.fromId()", () => {
174176
describe("getters", () => {
175177
it("should return kind via getKind()", () => {
176178
expect(Code.fromCode("B2392").getKind()).toBe("B");
179+
expect(Code.fromCode("G2392").getKind()).toBe("G");
177180
expect(Code.fromCode("R2392").getKind()).toBe("R");
178181
expect(Code.fromCode("P2392").getKind()).toBe("P");
179182
expect(Code.fromCode("T2392").getKind()).toBe("T");
@@ -232,6 +235,10 @@ describe("Code.getCollection()", () => {
232235
expect(Code.fromCode("P2392").getCollection()).toBe("projects");
233236
});
234237

238+
it("should return 'games' for kind G", () => {
239+
expect(Code.fromCode("G2392").getCollection()).toBe("games");
240+
});
241+
235242
it("should return 'talks' for kind T", () => {
236243
expect(Code.fromCode("T2392").getCollection()).toBe("talks");
237244
});

0 commit comments

Comments
 (0)