UNPKG

@cosmicjs/sdk

Version:

The official client module for Cosmic. This module helps you easily add dynamic content to your website or application using the Cosmic headless CMS.

141 lines (101 loc) 4.11 kB
# @cosmicjs/rich-text Official React renderer for Cosmic `rich-text` metafields. Rich-text values are stored as markdown prose interleaved with `{{shortcode}}` block tokens. Each block is a reusable content snippet defined in your bucket settings. This package parses the value, resolves blocks against their definitions, and renders to React, with an overridable component per block. ## Install ```bash npm install @cosmicjs/rich-text ``` `react` is a peer dependency. ## Usage Pass the bucket's block definitions (`settings.content_blocks`) so `{{name}}` tokens can be expanded. ```tsx import { RichText } from '@cosmicjs/rich-text'; export default function Post({ post, blocks }) { return <RichText value={post.metadata.content} blocks={blocks} />; } ``` ### Overriding block rendering By default each block renders as a `data-block` div wrapping its content. Provide a `components` map keyed by block name to customize rendering. ```tsx import { RichText, BlockProps } from '@cosmicjs/rich-text'; const Callout = ({ contentHtml }: BlockProps) => ( <aside className="my-callout" dangerouslySetInnerHTML={{ __html: contentHtml }} /> ); <RichText value={value} blocks={blocks} components={{ callout: Callout }} />; ``` Each component receives `{ name, definition, contentHtml }`, where `contentHtml` is the block's content already rendered to HTML (markdown or plain text). ### Inline object embeds A rich-text value can also reference a live Cosmic object inline with the reserved `{{ object ... /}}` token (distinct from a block: the content lives in the referenced object, not in bucket settings): ``` {{ object type="posts" id="64f0...abc" slug="hello-world" /}} ``` Render embeds by providing an `objects` component map (keyed by object type slug) and a `resolveObject` function. Fetch the parent object with relationship depth so the referenced objects are available, then resolve by `id`: ```tsx import { RichText, ObjectBlockProps } from '@cosmicjs/rich-text'; const PostCard = ({ object }: ObjectBlockProps) => object ? <a href={`/posts/${object.slug}`}>{object.title}</a> : null; const related = post.metadata?.related ?? []; const byId = new Map(related.map((o) => [o.id, o])); <RichText value={value} blocks={blocks} objects={{ posts: PostCard }} resolveObject={({ id }) => byId.get(id)} />; ``` Each object component receives `{ id, type, slug, object }`. When no component is registered for a type, a default placeholder renders (the reference is never silently dropped). ### Imperative API ```tsx import { renderRichText } from '@cosmicjs/rich-text'; const nodes = renderRichText(value, { blocks }); ``` ## Block definitions A block definition has this shape (stored in `settings.content_blocks`): ```ts interface BlockDefinition { name: string; // shortcode, e.g. "callout" title?: string; description?: string; content: string; // markdown, plain text, or raw HTML editor: 'rich-text' | 'plain' | 'html'; } ``` ## Shortcode grammar ``` {{ name /}} block reference {{ object type="posts" id="..." slug="..." /}} inline object embed ``` Blocks reference content by name; the content lives in the block definition. Unknown blocks (no matching definition) are dropped unless `keepUnknown` is set. The `object` (and `objects`) names are reserved for inline object embeds. ## Fetching block definitions Rich-text values are served verbatim (markdown + `{{shortcode}}` tokens); the API never pre-renders them. Fetch the bucket's block definitions once and reuse them across objects. The easiest way is the official SDK: ```ts import { createBucketClient } from '@cosmicjs/sdk'; const cosmic = createBucketClient({ bucketSlug, readKey }); const { blocks } = await cosmic.blocks.find(); ``` Or call the endpoint directly: ``` GET buckets/{slug}/blocks -> { "blocks": [ ...BlockDefinition ] } ``` The endpoint is read-key authed and Fastly-cached on the bucket. The same data is also available on the bucket object at `settings.content_blocks`. Pass the result as the `blocks` prop above.