Skip to main content

Function: richText()

richText(): StandardDataSchema<RichText>

Defined in: packages/core/src/richText.ts:60

The schema for a rich-text field: an ordered array of blocks, each an ordered array of spans, over closed mark and kind sets. Declare it as a block's field to give an author inline emphasis and links without giving anyone markup.

Nothing in the value is parsed or evaluated at render, so an artifact carrying one is as inert as an artifact carrying a string. Both sets and both object shapes are closed: a key the shape does not declare is reported, never dropped.

Returns

StandardDataSchema<RichText>

The rich-text schema — a StandardDataSchema<RichText> whose ~standard.validate is synchronous and whose ~standard.jsonSchema converter is always present. Every call yields the same value, so a registry keyed by schema identity sees one schema across every field that declares it.

Examples

const schema = richText();

const body: RichText = [
{
kind: "paragraph",
spans: [
{ text: "How we keep that safe is on our " },
{ text: "security page", href: "/security" },
{ text: ", not in a PDF.", marks: ["strong", "em"] },
],
},
{ kind: "listItem", spans: [{ text: "encrypted", marks: ["code"] }] },
];

schema["~standard"].validate(body).issues; // undefined

// A refusal names the offending path rather than throwing.
schema["~standard"].validate([{ kind: "heading", spans: [] }]).issues;
// [{ path: [0, "kind"], message: 'unknown kind "heading"; expected one of paragraph, listItem' }]

Seating it in a validator that will not hold a foreign schema — zod rejects one inside an object shape, so the field is carried as unknown and core decides what is valid:

const spec = richText();

const body = z
.unknown()
.check((ctx) => {
for (const issue of spec["~standard"].validate(ctx.value).issues ?? []) {
ctx.issues.push({ code: "custom", message: issue.message, input: ctx.value });
}
})
.pipe(z.custom<RichText>())
.meta(spec["~standard"].jsonSchema.input({ target: "draft-2020-12" }));