This package transforms data of the RichText type (used by Contentful) into a data structure representing the same content in Portable Text.
npm i @portabletext/contentful-rich-text-to-portable-text
const { toPortableText } = require('@portabletext/contentful-rich-text-to-portable-text')
const richText = {
"nodeType": "document",
"data": {},
"content": [
{
"nodeType": "heading-1",
"data": {},
"content": [
{
"nodeType": "text",
"value": "Hello, everyone!",
"marks": [],
"data": {}
}
]
}
]
}
const portableText = toPortableText(richText)
// portableText is
[
{
"_type": "block",
"_key": "heading-1",
"style": "h1",
"markDefs": [],
"children": [
{
"_type": "span",
"_key": "text",
"marks": [],
"text": "Hello, everyone!"
}
]
}
]
const { toPortableText } = require('@portabletext/contentful-rich-text-to-portable-text')
const richText = {
nodeType: 'document',
data: {},
content: [
{
nodeType: 'heading-2',
data: {},
content: [
{
nodeType: 'text',
value: 'Hello',
marks: [{type: 'bold'}],
data: {}
},
{
nodeType: 'text',
value: ', ',
marks: [],
data: {}
},
{
nodeType: 'text',
value: 'everyone!',
marks: [{type: 'underline'}],
data: {}
}
]
}
]
}
const portableText = toPortableText(richText)
// portableText is
[
{
"_type": "block",
"_key": "heading-2",
"style": "h2",
"markDefs": [],
"children": [
{
"_type": "span",
"_key": "text",
"marks": [
"strong"
],
"text": "Hello"
},
{
"_type": "span",
"_key": "text",
"marks": [],
"text": ", "
},
{
"_type": "span",
"_key": "text",
"marks": [
"underline"
],
"text": "everyone!"
}
]
}
]
const uuid = require('uuid')
const { toPortableText } = require('@portabletext/contentful-rich-text-to-portable-text')
const richText = {
"nodeType": "document",
"data": {},
"content": [
{
"nodeType": "heading-1",
"data": {},
"content": [
{
"nodeType": "text",
"value": "Hello, everyone!",
"marks": [],
"data": {}
}
]
}
]
}
const portableText = toPortableText(richText, {
generateKey: (node) => [node.nodeType, uuid()].join('-')
})
// portableText is
[
{
"_type": "block",
"_key": "heading-1-83474017-970f-4450-b983-dc052027ef9b",
"style": "h1",
"markDefs": [],
"children": [
{
"_type": "span",
"_key": "text-33e92fc6-cc93-4441-8537-0eba5db9ad6a",
"marks": [],
"text": "Hello, everyone!"
}
]
}
]
const { toPortableText } = require('@portabletext/contentful-rich-text-to-portable-text')
const richText = {
nodeType: 'document',
data: {},
content: [
{
nodeType: "heading-1",
data: {},
content: [
{
nodeType: "text",
value: "Hello, everyone!",
marks: [],
data: {}
}
]
},
{
data: {},
content: [],
nodeType: 'hr'
},
{
nodeType: 'paragraph',
content: [
{
nodeType: 'text',
value: "This is a little introduction. It's just a paragraph without any fancy stuff.",
marks: [],
data: {}
}
],
data: {}
}
]
}
const portableText = toPortableText(data, {
transformers: {
hr: (node) => {
return [
{
_type: "break",
style: "lineBreak",
},
];
},
}
})
// portableText is
[
{
"_type": "block",
"_key": "heading-1",
"style": "h1",
"markDefs": [],
"children": [
{
"_type": "span",
"_key": "text",
"marks": [],
"text": "Hello, everyone!"
}
]
},
{
"_type": "break",
"style": "lineBreak"
},
{
"_type": "block",
"_key": "paragraph",
"style": "normal",
"markDefs": [],
"children": [
{
"_type": "span",
"_key": "text",
"marks": [],
"text": "This is a little introduction. It's just a paragraph without any fancy stuff."
}
]
}
]
To control the transformation of specific nodes you may pass in a function to handle these with these properties of options.transformers
link?: Function
'entry-hyperlink'?: Function
'asset-hyperlink'?: Function
'embedded-asset-block'?: Function
'embedded-entry-block'?: Function
'embedded-entry-inline'?: Function
hr?: Function
Custom key generation is a function passed as options.generateKey
which is expected to return a string
.
- You will need to specify your own serialization for HR tags. See examples.
- Blockquotes in RichText and PortableText do not currently map directly. You may lose newlines in this step and you should verify the output and make any needed adjustments.
MIT-licensed. See LICENSE.