From 44c6a836fffda26976465d29cb09648249e5daee Mon Sep 17 00:00:00 2001 From: Heath Stewart Date: Tue, 2 Jun 2026 23:38:50 -0700 Subject: [PATCH] Always atUri to frontmatter root Fixes #46 --- packages/cli/src/lib/markdown.ts | 26 ++----- packages/cli/test/markdown.test.ts | 119 +++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 20 deletions(-) diff --git a/packages/cli/src/lib/markdown.ts b/packages/cli/src/lib/markdown.ts index e66d70b..e26acaa 100644 --- a/packages/cli/src/lib/markdown.ts +++ b/packages/cli/src/lib/markdown.ts @@ -376,29 +376,15 @@ export function updateFrontmatterWithAtUri( const delimiterMatch = rawContent.match(/^(---|\+\+\+|\*\*\*)/); const delimiter = delimiterMatch?.[1] ?? "---"; const isToml = delimiter === "+++"; + const { body, rawFrontmatter } = parseFrontmatter(rawContent); - // Format the atUri entry based on frontmatter type - const atUriEntry = isToml ? `atUri = "${atUri}"` : `atUri: "${atUri}"`; + rawFrontmatter.atUri = atUri; - // Check if atUri already exists in frontmatter (handle both formats) - if (rawContent.includes("atUri:") || rawContent.includes("atUri =")) { - // Replace existing atUri (match both YAML and TOML formats) - return rawContent.replace( - /atUri\s*[=:]\s*["']?[^"'\n]+["']?\n?/, - `${atUriEntry}\n`, - ); - } - - // Insert atUri before the closing delimiter - const frontmatterEndIndex = rawContent.indexOf(delimiter, 4); - if (frontmatterEndIndex === -1) { - throw new Error("Could not find frontmatter end"); - } - - const beforeEnd = rawContent.slice(0, frontmatterEndIndex); - const afterEnd = rawContent.slice(frontmatterEndIndex); + const serializedFrontmatter = isToml + ? toml.stringify(rawFrontmatter).trimEnd() + : yaml.dump(rawFrontmatter, { lineWidth: -1 }).trimEnd(); - return `${beforeEnd}${atUriEntry}\n${afterEnd}`; + return `${delimiter}\n${serializedFrontmatter}\n${delimiter}\n${body}`; } export function stripMarkdownForText(markdown: string): string { diff --git a/packages/cli/test/markdown.test.ts b/packages/cli/test/markdown.test.ts index 6967530..65c7069 100644 --- a/packages/cli/test/markdown.test.ts +++ b/packages/cli/test/markdown.test.ts @@ -4,6 +4,7 @@ import { parseFrontmatter, resolvePostPath, stripMarkdownForText, + updateFrontmatterWithAtUri, } from "../src/lib/markdown"; import type { BlogPost } from "../src/lib/types"; import type { BlobOptions } from "node:buffer"; @@ -390,6 +391,27 @@ title: Post const { body } = parseFrontmatter(content); expect(body).toBe(""); }); + + it("preserves TOML tables", () => { + const content = `+++ +title = "Example" +coverImage = "static/covers/example.png" + +[cover] + image = "/covers/example.png" + alt = "…" + hidden = true ++++ +Body content here.`; + const { frontmatter, body, rawFrontmatter } = parseFrontmatter(content); + expect(frontmatter.title).toBe("Example"); + expect(body).toBe("Body content here."); + + const coverTable = rawFrontmatter?.["cover"] as Record | undefined; + expect(coverTable).not.toBe(undefined); + const coverImageField = coverTable?.["image"] as string | undefined; + expect(coverImageField).toBe("/covers/example.png"); + }); }); }); @@ -495,6 +517,103 @@ describe("stripMarkdownForText", () => { }); }); +describe("updateFrontmatterWithAtUri", () => { + it("inserts atUri into YAML frontmatter when it does not exist", () => { + const content = `--- +title: Hello World +--- +Body content here.`; + const updatedContent = updateFrontmatterWithAtUri( + content, + "at://did:plc:abc123/app.bsky.feed.post/xyz", + ); + + expect(updatedContent).toBe(`--- +title: Hello World +atUri: at://did:plc:abc123/app.bsky.feed.post/xyz +--- +Body content here.`); + }); + + it("replaces an existing atUri in YAML frontmatter", () => { + const content = `--- +title: Hello World +atUri: "at://did:plc:old/app.bsky.feed.post/old" +--- +Body content here.`; + const updatedContent = updateFrontmatterWithAtUri( + content, + "at://did:plc:new/app.bsky.feed.post/new", + ); + + expect(updatedContent).toBe(`--- +title: Hello World +atUri: at://did:plc:new/app.bsky.feed.post/new +--- +Body content here.`); + }); + + it("inserts atUri into TOML frontmatter when it does not exist", () => { + const content = `+++ +title = "Hello World" ++++ +Body content here.`; + const updatedContent = updateFrontmatterWithAtUri( + content, + "at://did:plc:abc123/app.bsky.feed.post/xyz", + ); + + expect(updatedContent).toBe(`+++ +title = "Hello World" +atUri = "at://did:plc:abc123/app.bsky.feed.post/xyz" ++++ +Body content here.`); + }); + + it("replaces an existing atUri in TOML frontmatter", () => { + const content = `+++ +title = "Hello World" +atUri = "at://did:plc:old/app.bsky.feed.post/old" ++++ +Body content here.`; + const updatedContent = updateFrontmatterWithAtUri( + content, + "at://did:plc:new/app.bsky.feed.post/new", + ); + + expect(updatedContent).toBe(`+++ +title = "Hello World" +atUri = "at://did:plc:new/app.bsky.feed.post/new" ++++ +Body content here.`); + }); + + it("inserts atUri into TOML frontmatter when it include another table", () => { + const content = `+++ +title = "Example" +coverImage = "static/covers/example.png" + +[cover] + image = "/covers/example.png" + alt = "…" + hidden = true ++++ +Body content here.`; + const updatedContent = updateFrontmatterWithAtUri(content, "at://did:plc:new/app.bsky.feed.post/new"); + expect(updatedContent).toBe(`+++ +title = "Example" +coverImage = "static/covers/example.png" +atUri = "at://did:plc:new/app.bsky.feed.post/new" + +[cover] +image = "/covers/example.png" +alt = "…" +hidden = true ++++ +Body content here.`); + }); +}); + describe("getContentHash", () => { it("returns the expected SHA-256 hash as lowercase hex", async () => { const post: Partial = { -- 2.51.2