diff --git a/.changeset/serialize-node-materials.md b/.changeset/serialize-node-materials.md new file mode 100644 index 00000000..67d68ba2 --- /dev/null +++ b/.changeset/serialize-node-materials.md @@ -0,0 +1,5 @@ +--- +"@design-intelligence/ghost": patch +--- + +serializeNode preserves the materials frontmatter field instead of dropping it. diff --git a/packages/ghost/src/ghost-core/node/serialize.ts b/packages/ghost/src/ghost-core/node/serialize.ts index 50998fcd..48cab403 100644 --- a/packages/ghost/src/ghost-core/node/serialize.ts +++ b/packages/ghost/src/ghost-core/node/serialize.ts @@ -3,8 +3,8 @@ import type { GhostNodeDocument, GhostNodeFrontmatter } from "./types.js"; /** * Serialize a node back to its `---\n\n---\n` markdown form. Keys - * are emitted in a stable order (description) so round-trips and diffs are - * deterministic. Identity and kind are not serialized — they come from the + * are emitted in a stable order (description, materials) so round-trips and + * diffs are deterministic. Identity and kind are not serialized — they come from the * node's file path and optional filename prefix. Undefined fields are omitted; a node * with no frontmatter fields emits an empty block. */ @@ -12,6 +12,7 @@ export function serializeNode(node: GhostNodeDocument): string { const fm = node.frontmatter; const ordered: Record = {}; if (fm.description !== undefined) ordered.description = fm.description; + if (fm.materials !== undefined) ordered.materials = fm.materials; // An empty frontmatter object stringifies to "{}"; emit a bare block instead. const yaml = diff --git a/packages/ghost/test/ghost-core/node-schema.test.ts b/packages/ghost/test/ghost-core/node-schema.test.ts index 1df7e67f..d273c499 100644 --- a/packages/ghost/test/ghost-core/node-schema.test.ts +++ b/packages/ghost/test/ghost-core/node-schema.test.ts @@ -52,6 +52,23 @@ describe("ghost.node/v1 schema", () => { expect(reparsed.node?.body).toBe(original.body); }); + it("round-trips materials frontmatter through serialize/parse", () => { + const original: GhostNodeDocument = { + frontmatter: { + description: "Checkout trust signals.", + materials: [ + "src/components/checkout/**", + "https://example.com/logo.svg", + ], + }, + body: "Near payment, reduce felt risk.", + }; + const reparsed = parseNode(serializeNode(original)); + expect(reparsed.report.errors).toBe(0); + expect(reparsed.node?.frontmatter).toEqual(original.frontmatter); + expect(reparsed.node?.body).toBe(original.body); + }); + it("round-trips an empty-frontmatter node", () => { const original: GhostNodeDocument = { frontmatter: {},