Налаштування Portable Text для Rich Content Sanity
Portable Text — формат зберігання rich text в Sanity. Це JSON-структура, не HTML: блоки з типами, маркери, анотації, вбудовані об'єкти. Одні й ті ж дані рендеряться в HTML, React Native, PDF через відповідні сериалізатори.
Схема Portable Text
// schemas/blockContent.ts
import { defineArrayMember, defineType } from 'sanity'
export const blockContentType = defineType({
name: 'blockContent',
type: 'array',
of: [
defineArrayMember({
type: 'block',
styles: [
{ title: 'Normal', value: 'normal' },
{ title: 'H2', value: 'h2' },
{ title: 'Quote', value: 'blockquote' },
],
marks: {
decorators: [
{ title: 'Bold', value: 'strong' },
{ title: 'Italic', value: 'em' },
{ title: 'Code', value: 'code' },
],
},
}),
defineArrayMember({
type: 'image',
options: { hotspot: true },
fields: [{ name: 'alt', type: 'string' }],
}),
defineArrayMember({
type: 'object',
name: 'callout',
title: 'Callout',
fields: [
{ name: 'type', type: 'string', options: { list: ['info', 'warning', 'tip'] } },
{ name: 'text', type: 'text' },
],
}),
],
})
Рендеринг через @portabletext/react
npm install @portabletext/react
// components/PortableTextContent.tsx
import { PortableText } from '@portabletext/react'
import type { PortableTextComponents } from '@portabletext/react'
const components: PortableTextComponents = {
types: {
image: ({ value }) => (
<img src={value.url} alt={value.alt} className="my-4 rounded-lg" />
),
},
marks: {
strong: ({ children }) => <strong className="font-bold">{children}</strong>,
link: ({ value, children }) => (
<a href={value?.href} className="text-blue-600">{children}</a>
),
},
}
export function PortableTextContent({ value }: { value: any[] }) {
return <PortableText value={value} components={components} />
}
Отримання plain text
import { toPlainText } from '@portabletext/toolkit'
const plainText = toPlainText(post.body)
const excerpt = plainText.slice(0, 160)
Терміни
Налаштування Portable Text схеми з кастомними блоками та рендерером — 1–2 дні.







