124 lines
3.8 KiB
Markdown
124 lines
3.8 KiB
Markdown
---
|
||
title: Serialize Portable Text to Markdown
|
||
description: Convert Portable Text to Markdown strings using @portabletext/markdown
|
||
tags: [portable-text, markdown, serialization, conversion]
|
||
---
|
||
|
||
# Serialize Portable Text to Markdown
|
||
|
||
Use `@portabletext/markdown` to convert PT blocks to Markdown strings. Useful for AI/LLM pipelines, static site generators, README generation, and anywhere Markdown is the target format.
|
||
|
||
```bash
|
||
npm install @portabletext/markdown
|
||
```
|
||
|
||
## Basic Usage
|
||
|
||
```ts
|
||
import {portableTextToMarkdown} from '@portabletext/markdown'
|
||
|
||
const markdown = portableTextToMarkdown(portableTextBlocks)
|
||
```
|
||
|
||
## Built-in Support
|
||
|
||
Out of the box, `portableTextToMarkdown` handles:
|
||
|
||
- Headings (h1–h6)
|
||
- Paragraphs
|
||
- Bold (`**`), italic (`_`), inline code (`` ` ``), strikethrough (`~~`)
|
||
- Links (`[text](url)`)
|
||
- Blockquotes (`>`)
|
||
- Ordered and unordered lists (including nested)
|
||
- Code blocks (fenced with language)
|
||
- Horizontal rules (`---`)
|
||
- Images (``)
|
||
- Tables (GFM)
|
||
|
||
## Built-in Type Renderers
|
||
|
||
The library exports default renderers for common block object types. Enable them explicitly:
|
||
|
||
```ts
|
||
import {
|
||
portableTextToMarkdown,
|
||
DefaultCodeBlockRenderer,
|
||
DefaultImageRenderer,
|
||
DefaultHorizontalRuleRenderer,
|
||
DefaultTableRenderer,
|
||
DefaultHtmlRenderer,
|
||
} from '@portabletext/markdown'
|
||
|
||
const markdown = portableTextToMarkdown(blocks, {
|
||
types: {
|
||
'code': DefaultCodeBlockRenderer, // {code, language?} → fenced code block
|
||
'image': DefaultImageRenderer, // {src, alt?, title?} → 
|
||
'horizontal-rule': DefaultHorizontalRuleRenderer, // → ---
|
||
'table': DefaultTableRenderer, // {rows, headerRows?} → GFM table
|
||
'html': DefaultHtmlRenderer, // {html} → raw HTML
|
||
},
|
||
})
|
||
```
|
||
|
||
## Custom Renderers
|
||
|
||
Handle custom block types and marks with renderer functions:
|
||
|
||
```ts
|
||
const markdown = portableTextToMarkdown(blocks, {
|
||
// Custom block types — receives {value, index, isInline}
|
||
types: {
|
||
callout: ({value}) => `> **${value.title}**\n> ${value.text}`,
|
||
image: ({value, isInline}) => {
|
||
if (isInline) return ''
|
||
return ``
|
||
},
|
||
},
|
||
|
||
// Custom block style renderers — receives {value, children, index}
|
||
block: {
|
||
h1: ({children}) => `# ${children}`,
|
||
blockquote: ({children}) => `> ${children}`,
|
||
},
|
||
|
||
// Custom mark renderers — receives {value, children, text, markType, markKey}
|
||
marks: {
|
||
highlight: ({children}) => `==${children}==`,
|
||
internalLink: ({children, value}) => `[${children}](/docs/${value.slug})`,
|
||
},
|
||
|
||
// Custom list item renderer — receives {value, children, listIndex}
|
||
listItem: ({children}) => children,
|
||
|
||
// Control spacing between blocks — function, not string
|
||
blockSpacing: ({current, next}) => {
|
||
if (current.listItem && next.listItem) return '\n'
|
||
return undefined // use default (\n\n)
|
||
},
|
||
|
||
// Handle unknown types gracefully
|
||
unknownType: ({value}) => `<!-- Unknown type: ${value._type} -->`,
|
||
unknownMark: ({children}) => children,
|
||
})
|
||
```
|
||
|
||
## Use Cases
|
||
|
||
| Use Case | Why Markdown |
|
||
|----------|-------------|
|
||
| AI/LLM context | Models work well with Markdown input |
|
||
| Static site generators | Hugo, Jekyll, Eleventy consume Markdown |
|
||
| README generation | Generate docs from Sanity content |
|
||
| Email (with converter) | Markdown → HTML for email templates |
|
||
| Export/backup | Human-readable content export |
|
||
| Documentation pipelines | Sanity as docs CMS, output as Markdown |
|
||
|
||
## Bidirectional: Also Converts Markdown → PT
|
||
|
||
The same package also provides `markdownToPortableText()` for the reverse direction. See the `portable-text-conversion` skill for details.
|
||
|
||
## Reference
|
||
|
||
- [@portabletext/markdown](https://github.com/portabletext/editor/tree/main/packages/markdown)
|
||
- Part of the [portabletext/editor](https://github.com/portabletext/editor) monorepo
|