@draftbase/renderer 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  **Framework-agnostic MDX renderer for [Draftbase](https://draftbase.co)** — the MDX-based headless CMS for React developers.
6
6
 
7
7
  [![npm](https://img.shields.io/npm/v/@draftbase/renderer)](https://www.npmjs.com/package/@draftbase/renderer)
8
- [![GitHub](https://img.shields.io/badge/GitHub-draftbase--monorepo-181717?logo=github)](https://github.com/draftbase-co/draftbase-monorepo/tree/main/packages/renderer)
8
+ [![GitHub](https://img.shields.io/badge/GitHub-renderer-181717?logo=github)](https://github.com/draftbase-co/renderer)
9
9
 
10
10
  </div>
11
11
 
@@ -72,6 +72,16 @@ function Entry({ source }: { source: string }) {
72
72
  }
73
73
  ```
74
74
 
75
+ `compiled.ok` only catches MDX _syntax_ errors. If the source references a JSX component you didn't pass in `components` (e.g. `<Callout>` without a `Callout` implementation), React throws while rendering `<Content>` — wrap it in the exported `MDXErrorBoundary` (React only, not React Native's non-DOM tree unless you supply an `errorTag`-equivalent fallback) to log it to the console and fail soft instead of crashing the page. `MDXContent` (the Next.js RSC helper above) already does this for you automatically.
76
+
77
+ ```tsx
78
+ import { MDXErrorBoundary } from "@draftbase/renderer";
79
+
80
+ <MDXErrorBoundary fallback={<Text>{source}</Text>}>
81
+ <Content components={{ p: Text, h1: Text /* ... */ }} />
82
+ </MDXErrorBoundary>;
83
+ ```
84
+
75
85
  Extended markdown (tables, strikethrough, task lists, autolinks) is supported out of the box via `remark-gfm`.
76
86
 
77
87
  ## Astro
@@ -192,6 +202,27 @@ import { Callout, ImageBlock } from "@/components/content";
192
202
 
193
203
  Any standard markdown element (`h1`, `table`, `a`, ...) can also be overridden the same way, by key — **required** on non-DOM renderers like React Native, which have no intrinsic `div`/`p`/`a`/`img` tags.
194
204
 
205
+ ### Entry links
206
+
207
+ The Draftbase editor can insert `<EntryLink id="...">Link text</EntryLink>` into rich text to link to another entry. It's a plain JSX component like any other — no special renderer support for the tag itself — so you must supply an `EntryLink` implementation the same way as `Callout`/`ImageBlock`. If `EntryLink` isn't supplied and the source contains one, rendering throws (same as any missing custom component).
208
+
209
+ To route `id` correctly per content type, fetch the entry with `include=1` (via `@draftbase/sdk`) — the response includes an `entryLinks` map keyed by every `EntryLink` id found in that entry's richText fields, each with its `templateId`:
210
+
211
+ ```tsx
212
+ const entry = await client.entries.get(entryId, undefined, 1);
213
+ // entry.entryLinks = { "64f1a2b3c4d5e6f7a8b9c0d1": { id, templateId, title, status } }
214
+
215
+ const ROUTE_BY_TEMPLATE: Record<string, string> = { blogPost: "/blog", product: "/products" };
216
+
217
+ function EntryLink({ id, children }: { id: string; children: React.ReactNode }) {
218
+ const link = entry.entryLinks?.[id];
219
+ const base = ROUTE_BY_TEMPLATE[link?.templateId ?? ""] ?? "/entries";
220
+ return <a href={`${base}/${id}`}>{children}</a>;
221
+ }
222
+
223
+ <MDXContent source={entry.fields.body} components={{ EntryLink }} />;
224
+ ```
225
+
195
226
  ## Styling
196
227
 
197
228
  `@draftbase/renderer/styles.css` wraps output in a `.db-content` class with slim, sensible defaults (typography, tables, code blocks). Web-only, opt-in:
@@ -234,8 +265,8 @@ React (Next.js App Router/RSC, plain client React, React Native, Remix, Astro is
234
265
  ## Links
235
266
 
236
267
  - [npm](https://www.npmjs.com/package/@draftbase/renderer)
237
- - [Source (`packages/renderer`)](https://github.com/draftbase-co/draftbase-monorepo/tree/main/packages/renderer)
238
- - [Issues](https://github.com/draftbase-co/draftbase-monorepo/issues)
268
+ - [Source](https://github.com/draftbase-co/renderer)
269
+ - [Issues](https://github.com/draftbase-co/renderer/issues)
239
270
  - [`@draftbase/sdk`](https://www.npmjs.com/package/@draftbase/sdk) — fetches the content this package renders
240
271
  - [draftbase.co](https://draftbase.co) — product site
241
272
  - [Framework support](https://draftbase.co/frameworks) — per-framework rendering guide this README is based on
@@ -2,6 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import * as runtime from "react/jsx-runtime";
3
3
  import { compileMDXCore } from "./core.js";
4
4
  import { wrapperClassName } from "./wrapperClassName.js";
5
+ import { MDXErrorBoundary } from "./MDXErrorBoundary.js";
5
6
  /**
6
7
  * Compiles raw MDX/markdown into a renderable React component — no DOM assumptions,
7
8
  * safe to call from a React Native loader, a client-side effect, or a Next.js Server
@@ -27,5 +28,5 @@ export async function MDXContent({ source, components, unstyled, className, wrap
27
28
  return (_jsx(Wrapper, { className: wrapperClass, children: _jsx(ErrorTag, { children: source }) }));
28
29
  }
29
30
  const { Content } = compiled;
30
- return (_jsx(Wrapper, { className: wrapperClass, children: _jsx(Content, { components: components }) }));
31
+ return (_jsx(Wrapper, { className: wrapperClass, children: _jsx(MDXErrorBoundary, { fallback: _jsx(ErrorTag, { children: source }), children: _jsx(Content, { components: components }) }) }));
31
32
  }
@@ -0,0 +1,17 @@
1
+ import { Component, type ReactNode } from "react";
2
+ interface MDXErrorBoundaryProps {
3
+ children: ReactNode;
4
+ fallback: ReactNode;
5
+ }
6
+ interface MDXErrorBoundaryState {
7
+ hasError: boolean;
8
+ }
9
+ export declare class MDXErrorBoundary extends Component<MDXErrorBoundaryProps, MDXErrorBoundaryState> {
10
+ state: MDXErrorBoundaryState;
11
+ static getDerivedStateFromError(): {
12
+ hasError: boolean;
13
+ };
14
+ componentDidCatch(error: unknown): void;
15
+ render(): ReactNode;
16
+ }
17
+ export {};
@@ -0,0 +1,18 @@
1
+ "use client";
2
+ import { Component } from "react";
3
+ // Catches render-time errors from compiled MDX content — most commonly a JSX component
4
+ // referenced in the source (e.g. `<Callout>`, `<EntryLink>`) that wasn't supplied in
5
+ // `components`. Without this, that throws "Element type is invalid" and crashes the whole
6
+ // page instead of just the content block.
7
+ export class MDXErrorBoundary extends Component {
8
+ state = { hasError: false };
9
+ static getDerivedStateFromError() {
10
+ return { hasError: true };
11
+ }
12
+ componentDidCatch(error) {
13
+ console.error("MDX content failed to render", error);
14
+ }
15
+ render() {
16
+ return this.state.hasError ? this.props.fallback : this.props.children;
17
+ }
18
+ }
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export { MDXContent, compileMDX } from "./MDXContent.js";
2
2
  export type { MDXContentProps, CompiledMDX, FailedMDX } from "./MDXContent.js";
3
3
  export { toHtml } from "./toHtml.js";
4
+ export { MDXErrorBoundary } from "./MDXErrorBoundary.js";
package/dist/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export { MDXContent, compileMDX } from "./MDXContent.js";
2
2
  export { toHtml } from "./toHtml.js";
3
+ export { MDXErrorBoundary } from "./MDXErrorBoundary.js";
package/dist/styles.css CHANGED
@@ -25,6 +25,12 @@
25
25
  line-height: 1.25;
26
26
  margin: 1.5em 0 0.5em;
27
27
  color: inherit;
28
+ scroll-margin-top: 96px;
29
+ }
30
+
31
+ /* Highlights a footnote/citation anchor when the URL hash lands on it, e.g. #fn-1. */
32
+ .db-content :target {
33
+ background: var(--accent-subtle, rgba(127, 127, 127, 0.15));
28
34
  }
29
35
 
30
36
  .db-content h1 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@draftbase/renderer",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Framework-agnostic MDX renderer for Draftbase content (React, Next.js RSC, React Native, Astro, Vite, Vue)",
5
5
  "keywords": [
6
6
  "draftbase",