-
Notifications
You must be signed in to change notification settings - Fork 2.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(richtext-lexical): lexical => JSX converter #8795
Conversation
From docs:
Anything that can be done to remove the dependency to render on the server? It would be great to be able to use this in client side with live preview. |
docs/lexical/converters.mdx
Outdated
RichText, | ||
} from '@payloadcms/richtext-lexical/react' | ||
|
||
const jsxConverters: JSXConvertersFunction = ({ defaultConverters }) => [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
with this pattern, how would I override an individual element / node type?
say I wanted to adjust the h1
- how could I do that?
it seems to me like this JSXConvertersFunction
should not return an array - and should instead return an object where they keys are the node type, and then the value would be the converter which takes the node and returns JSX.
Do we really need to import a BlocksJSXConverter
? This is a pattern that is often seen in our Lexical editor but I'm not sure it's necessary all of the time.
Here is what I'm seeing in my head:
const jsxConverter: JSXConverter = ({ defaultConverters }) => ({
h1: ({ node, nodesToJSX }) => {
const children = nodesToJSX({
nodes: node.children,
})
return <h1>{children}</h1>
},
blocks: {
myTextBlock: ({ fields }) => <div style={{ backgroundColor: 'red' }}>{fields.text}</div>
}
})
Note that I also have renamed JSXConvertersFunction
to simply just be JSXConverter
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Option 1: just pass an object. This means h1 will be the ONLY converter and no other nodes will be converted. No defaultConverters included
<RichText
converters={{
h1: // h1Converter
}}
editorState={data.lexicalWithBlocks as SerializedEditorState}
/>
Option 2: spread defaultConverters. As the h1 converter is added AFTER the h1 converter added by defaultConverters, it will take precedence:
<RichText
converters={({ defaultConverters }) => ({
...defaultConverters,
h1: // h1Converter
})}
editorState={data.lexicalWithBlocks as SerializedEditorState}
/>
For consistency, this is the exact same pattern used for lexical editor features
</table> | ||
) | ||
}, | ||
tablecell: ({ node, nodesToJSX }) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the type
in Lexical called tablecell
? it's not td
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import { NodeFormat } from '../../../../../../lexical/utils/nodeFormat.js' | ||
|
||
export const TextJSXConverter: JSXConverters<SerializedTextNode> = { | ||
text: ({ node }) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be nice to make a pattern where text
could optionally return undefined, and if it did, we could assume that we should run the default converter
🚀 This is included in version v3.2.0 |
…te (#9615) In addition to requiring fewer files, it supports more nodes. If you currently initialize a website template and want to use features such as images or tables, they are not rendered. With this change that happens automatically. Credits to @AlessioGr for the [JSX serializer](#8795). --------- Co-authored-by: Paul Popus <[email protected]>
Are there any examples for rendering Rich Text on the frontend using React? I'm quiet new to Payload and I don't follow OP example. Update: Found it https://payloadcms.com/docs/rich-text/converters |
Example: ```tsx import React from 'react' import { type JSXConvertersFunction, RichText, } from '@payloadcms/richtext-lexical/react' const jsxConverters: JSXConvertersFunction = ({ defaultConverters }) => ({ ...defaultConverters, blocks: { // myTextBlock is the slug of the block myTextBlock: ({ node }) => <div style={{ backgroundColor: 'red' }}>{node.fields.text}</div>, }, }) export const MyComponent = ({ lexicalContent }) => { return ( <RichText converters={jsxConverters} data={data.lexicalWithBlocks as SerializedEditorState} /> ) } ```
…te (#9615) In addition to requiring fewer files, it supports more nodes. If you currently initialize a website template and want to use features such as images or tables, they are not rendered. With this change that happens automatically. Credits to @AlessioGr for the [JSX serializer](#8795). --------- Co-authored-by: Paul Popus <[email protected]>
This PR introduces a new lexical => JSX serializer that is meant to be used on the client. Unlike our existing HTML / MD / Plaintext serializers, it does not the editor config and complex logic to retrieve and sanitize it - it uses a simple, performant converter function.
Example Usage