d5837e03cc
## Documentation / Examples - [X] Make sure the linting passes by running `pnpm lint` - [X] The "examples guidelines" are followed from [our contributing doc](https://github.com/vercel/next.js/blob/canary/contributing/examples/adding-examples.md) Co-authored-by: Balázs Orbán <info@balazsorban.com>
185 lines
4 KiB
TypeScript
185 lines
4 KiB
TypeScript
import * as React from 'react'
|
|
import classNames from 'classnames'
|
|
|
|
const renderParagraph = (block) => {
|
|
const props = { style: {}, className: '' }
|
|
|
|
if (block.data.textAlign) {
|
|
props.style['textAlign'] = block.data.textAlign
|
|
}
|
|
if (block.data.className) {
|
|
props.className = block.data.className
|
|
}
|
|
return (
|
|
<p
|
|
{...props}
|
|
className={classNames('rte-block-paragraph', props.className)}
|
|
dangerouslySetInnerHTML={{ __html: block.data.text }}
|
|
/>
|
|
)
|
|
}
|
|
|
|
const renderDelimiter = () => {
|
|
return <div className="rte-block-delimiter" />
|
|
}
|
|
|
|
const renderHeader = (block) => {
|
|
const props = { style: {}, className: '' }
|
|
|
|
if (block.data.textAlign) {
|
|
props.style['textAlign'] = block.data.textAlign
|
|
}
|
|
if (block.data.className) {
|
|
props.className = block.data.className
|
|
}
|
|
|
|
switch (block.data.level) {
|
|
case 1:
|
|
return (
|
|
<h1
|
|
{...props}
|
|
className={classNames(
|
|
props.className,
|
|
'rte-block-heading rte-block-heading--h1'
|
|
)}
|
|
dangerouslySetInnerHTML={{ __html: block.data.text }}
|
|
/>
|
|
)
|
|
|
|
case 2:
|
|
return (
|
|
<h2
|
|
{...props}
|
|
className={classNames(
|
|
props.className,
|
|
'rte-block-heading rte-block-heading--h2'
|
|
)}
|
|
dangerouslySetInnerHTML={{ __html: block.data.text }}
|
|
/>
|
|
)
|
|
|
|
case 3:
|
|
return (
|
|
<h3
|
|
{...props}
|
|
className={classNames(
|
|
props.className,
|
|
'rte-block-heading rte-block-heading--h3'
|
|
)}
|
|
dangerouslySetInnerHTML={{ __html: block.data.text }}
|
|
/>
|
|
)
|
|
|
|
case 4:
|
|
return (
|
|
<h4
|
|
{...props}
|
|
className={classNames(
|
|
props.className,
|
|
'rte-block-heading rte-block-heading--h4'
|
|
)}
|
|
dangerouslySetInnerHTML={{ __html: block.data.text }}
|
|
/>
|
|
)
|
|
|
|
case 5:
|
|
return (
|
|
<h5
|
|
{...props}
|
|
className={classNames(
|
|
props.className,
|
|
'rte-block-heading rte-block-heading--h5'
|
|
)}
|
|
dangerouslySetInnerHTML={{ __html: block.data.text }}
|
|
/>
|
|
)
|
|
|
|
case 6:
|
|
return (
|
|
<h6
|
|
{...props}
|
|
className={classNames(
|
|
props.className,
|
|
'rte-block-heading rte-block-heading--h6'
|
|
)}
|
|
dangerouslySetInnerHTML={{ __html: block.data.text }}
|
|
/>
|
|
)
|
|
default:
|
|
return null
|
|
}
|
|
}
|
|
|
|
function renderImage(block) {
|
|
return (
|
|
<img
|
|
className={'rte-block-image'}
|
|
alt={block.data.caption}
|
|
src={block.data.file}
|
|
/>
|
|
)
|
|
}
|
|
|
|
function renderList(block) {
|
|
switch (block.data.style) {
|
|
case 'unordered':
|
|
return (
|
|
<ul className={'rte-block-list'}>
|
|
{block.data.items.map((text, i) => (
|
|
<li key={i}>{text}</li>
|
|
))}
|
|
</ul>
|
|
)
|
|
|
|
case 'ordered':
|
|
return (
|
|
<ol className={'rte-block-list'}>
|
|
{block.data.items.map((text, i) => (
|
|
<li key={i}>{text}</li>
|
|
))}
|
|
</ol>
|
|
)
|
|
default:
|
|
return null
|
|
}
|
|
}
|
|
|
|
function renderQuote(block) {
|
|
return (
|
|
<blockquote className={'rte-block-blockquote'}>
|
|
<p>{block.data.text}</p>
|
|
</blockquote>
|
|
)
|
|
}
|
|
|
|
const defaultRenderers = {
|
|
delimiter: renderDelimiter,
|
|
header: renderHeader,
|
|
image: renderImage,
|
|
list: renderList,
|
|
paragraph: renderParagraph,
|
|
quote: renderQuote,
|
|
}
|
|
|
|
export const RichTextRenderer = (props) => {
|
|
// Combine default renderers with custom renderers
|
|
const renderers = Object.assign({}, defaultRenderers, props.renderers)
|
|
|
|
return (
|
|
<React.Fragment>
|
|
{props.data.map((block, index) => {
|
|
const renderer = renderers[block.type]
|
|
if (!renderer) {
|
|
return null
|
|
}
|
|
|
|
const node = renderer(block)
|
|
if (React.isValidElement(node)) {
|
|
return React.cloneElement(node, { key: index })
|
|
}
|
|
|
|
return null
|
|
})}
|
|
</React.Fragment>
|
|
)
|
|
}
|