UNPKG

@ryhrm-gz/xincodo-lib

Version:

Utilities for working with Xincodo body documents.

226 lines (165 loc) 5.6 kB
--- name: building-and-parsing-body description: > Load when creating Xincodo Body data with createBody, paragraph, heading, text, richText, list, table, pageLink, image, or gallery builders; when handling Body block shapes; or when accepting persisted JSON with safeMigrateBody instead of defaulting to parseBody. type: core library: "@ryhrm-gz/xincodo-lib" library_version: "0.1.0" sources: - "ryhrm-gz/xincodo-lib:README.md" - "ryhrm-gz/xincodo-lib:src/types.ts" - "ryhrm-gz/xincodo-lib:src/builders.ts" - "ryhrm-gz/xincodo-lib:src/schemas.ts" - "ryhrm-gz/xincodo-lib:src/migration.ts" - "ryhrm-gz/xincodo-lib:tests/builders.test.ts" - "ryhrm-gz/xincodo-lib:tests/migration.test.ts" --- # Building and Parsing Body Use typed builders to create `Body` data. Treat saved or external JSON as unknown input and pass it through `safeMigrateBody` before using it. ## Setup ```ts import { createBody, heading, paragraph, safeMigrateBody, text } from "@ryhrm-gz/xincodo-lib"; const body = createBody([ heading(1, "Getting started", { id: "getting-started" }), paragraph("Create content with ", text("typed helpers", { annotations: { bold: true } })), ]); const migrated = safeMigrateBody(JSON.parse(JSON.stringify(body))); if (!migrated.success) { throw new Error(migrated.issue.message); } const currentBody = migrated.output; ``` ## Core Patterns ### Build rich text with helper inputs ```ts import { lineBreak, paragraph, text } from "@ryhrm-gz/xincodo-lib"; const intro = paragraph( "Read ", text("the docs", { annotations: { underline: true }, link: { href: "https://example.com/docs", title: "Documentation" }, }), lineBreak(), "before publishing.", ); ``` `paragraph`, `heading`, `callout`, `quote`, `listItem`, and similar helpers normalize strings into `{ type: "text" }` inline values. ### Build structured blocks through builders ```ts import { bulletedList, callout, createBody, image, listItem, table, tableCell, tableRow, } from "@ryhrm-gz/xincodo-lib"; const body = createBody([ bulletedList([listItem("Draft"), listItem("Review"), listItem("Publish")]), callout("Remember image alt text.", { icon: { type: "emoji", emoji: "!" }, color: "yellow", }), table([tableRow([tableCell("Status"), tableCell("Ready")])]), image({ type: "file", url: "/uploads/cover.png" }, { alt: "Article cover" }), ]); ``` Prefer builders over handwritten JSON. Builders keep the serialized block type names and nested shapes aligned with the library types. ### Accept persisted JSON with safeMigrateBody ```ts import { safeMigrateBody } from "@ryhrm-gz/xincodo-lib"; export function readPersistedBody(value: unknown) { const result = safeMigrateBody(value); if (!result.success) { return { ok: false as const, issue: result.issue }; } return { ok: true as const, body: result.output, migrated: result.migrated }; } ``` `parseBody` is a lower-level schema API. Use `safeMigrateBody` at saved-data or external-input boundaries so version handling is included. ### Use parseBody only for lower-level schema checks ```ts import { parseBody } from "@ryhrm-gz/xincodo-lib"; const result = parseBody({ version: 1, content: [], }); if (!result.success) { console.error(result.issues); } ``` Use this when the calling code deliberately wants Valibot safe-parse issues instead of migration-aware handling. ## Common Mistakes ### HIGH Defaulting to parseBody for saved JSON Wrong: ```ts import { parseBody } from "@ryhrm-gz/xincodo-lib"; const result = parseBody(JSON.parse(serializedBody)); if (!result.success) { throw new Error("Invalid Xincodo body"); } renderPreview(result.output); ``` Correct: ```ts import { safeMigrateBody } from "@ryhrm-gz/xincodo-lib"; const result = safeMigrateBody(JSON.parse(serializedBody)); if (!result.success) { throw new Error(result.issue.message); } renderPreview(result.output); ``` `parseBody` checks only the current schema; `safeMigrateBody` is the default boundary for persisted or external Body JSON. Source: maintainer interview; `src/schemas.ts`; `src/migration.ts`; `tests/migration.test.ts` ### HIGH Handwriting display block names Wrong: ```ts import { safeMigrateBody } from "@ryhrm-gz/xincodo-lib"; const result = safeMigrateBody({ version: 1, content: [{ type: "paragraph", richText: [{ type: "text", text: "Intro" }] }], }); ``` Correct: ```ts import { createBody, paragraph } from "@ryhrm-gz/xincodo-lib"; const body = createBody([paragraph("Intro")]); ``` Serialized block type values are fixed snake_case literals such as `"text"` and `"heading_1"`; builders avoid mismatching UI labels with stored shapes. Source: maintainer interview; `src/types.ts`; `src/builders.ts`; `tests/builders.test.ts` ### HIGH Omitting the Body version Wrong: ```ts import { paragraph, safeMigrateBody } from "@ryhrm-gz/xincodo-lib"; const result = safeMigrateBody({ content: [paragraph("Intro")], }); ``` Correct: ```ts import { createBody, paragraph, safeMigrateBody } from "@ryhrm-gz/xincodo-lib"; const body = createBody([paragraph("Intro")]); const result = safeMigrateBody(body); ``` `Body` values must include `version: 1`; missing or non-integer versions are reported as invalid migration input. Source: `src/types.ts`; `src/migration.ts`; `tests/migration.test.ts` ## References - [Body block shapes](references/body-block-shapes.md) - [Builder signatures](references/builder-signatures.md) See also: `validating-body/SKILL.md` — migrated or built Body values often need lint checks before save or publish.