Are there any example repos in v3 of markdown in lexical? I'm a bit confused by the docs
alessiogr, I am struggling with this, do you plan to provide part 2 to your video you uploaded on lexical?
hi, try not to mention team members directly, they will answer you if they can.
what exactly are you trying to achieve?
I'm trying to create a feature for lexical that outputs markdown but the docs are incomplete/assume knowledge.
I'd like to contribute by editing the docs but I can't until I learn it properly myself so it's catch 22 haha
You're a moderator here?
No, I've just read the server rules😆
Have you read these?
https://payloadcms.com/docs/beta/lexical/converters#lexical-markdown
Yup like I said they need editing
For v3 the example in the docs don't work
What kind of feature? Can you describe what it has to do?
there's a bit of a difference on how to make features for 2.0 and 3.0, but the core of the lexical stays the same,
When you write in lexical I want the output to be markdown
You mean something like this?
There's an action button down in the editor M, which tranforms all nodes to markdown
That's converting the editor state to markdown I think? I want the output to be markdown
Actually maybe it's doing both
yep, it is, but an output can't understand what exactly you're meaning 🙂
any examples?
I want the editor to look normal and output in markdown
The reverse of discord would be an example? You write in markdown and it looks normal.
what I'm now writing is markdown but the output looks normal. I want the opposite of this
Like this except I don't want the editor to look like markdown during the writing process. Only output it
now I think I understand, but yes, you'll have to create a custom feature for it, something like a popup with markdown output? or do it the same way playground does - have an action button that transforms editor state to markdown
I do something similar for AI Assistant: llm outputs response via api as a markdown string and I transform it back to regular html and then set editor's state, you should do something similar but the opposite
There's a couple ways to do it. Output is converted to a different field (I don't like this approach) or output from lexical is directly markdown. The latter I'm trying to do
v3?
But it's hard to understand because payload is like a language in itself and for v3 the docs are not written accurately.
Yes
So this brings me back to my original question--are there any example repos? I could learn from that
I've got mine, but it for 2.0 and integrated to an example website for now, I'm currently working on making it standalone, but for 2.0 only for now. Should not be to hard to adapt it to 3.0.
Here you go:
https://github.com/vans37/lexical-playground-payload-2.x/tree/main/src/payload/lexicalIt is mostly adaptations of playground features to payload, a bad one, but it works.
Thank you, I will have a look in about 9 hours. Just working and then studying and I think I should be free
I've made a basic demo for you, stripped down my ai assistant component and adopted to your needs, plus ported to 3.0.
Turns out there was a bit of a change in lexical api since Alessio posted tutorial on youtube for 3.0 feature development: in a server feature ClientComponent now is this type: PayloadComponent<never, BaseClientFeatureProps<ClientFeatureProps>>;
and not React.FC<T>, which took me a while to understand that it is a string which is a path to your client feature, and # refers to a name of an export from that file, if I'm not mistaken.
Here's the code:
It uses lates payload 3.0 beta(lexical is pinned to 0.18.0, don't use older or newer plugins, or it won't work).
Just install npm packages in the folder and get up and running basic mongodb database, you can explore .env to know exactly what you need.
thank you!! i will have a look. and yeah the tutorial didn't work for me at all when I tried, it was driving me mad lol
I am now looking at this, thanks again; is it possible to have the editor default to markdown? So that I don't have to click the markdown button each time
Yes, if you mean by typing and transforming on the fly it is possible, but probably too computationally intensive, maybe implement debounce or something similar
hmm at the moment it's storing to a list of nodes, and i only need markdown
so i wonder if i am going about it the wrong way. on their website they have a nodes file
at the moment ill be saving a lot of extra information to the db that i won't be using. this also isn't saving anywhere, so I don't think it's the right way to do it
import { useEffect } from 'react'
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
import { mergeRegister } from '@lexical/utils'
import { COMMAND_PRIORITY_EDITOR, createCommand } from 'lexical'
import { $convertToMarkdownString } from '@lexical/markdown'
import { useEditorConfigContext } from '@payloadcms/richtext-lexical/client'
// Define the command for converting to markdown
export const MARKDOWN_COMMAND = createCommand<null>()
export function ConvertToMarkdownPlugin(): null {
const [editor] = useLexicalComposerContext()
const { editorConfig } = useEditorConfigContext()
const handleMarkdownConversion = () => {
const transformers = editorConfig?.features?.markdownTransformers || []
editor.getEditorState().read(() => {
const markdown = $convertToMarkdownString(transformers)
console.log('Converted Markdown:', markdown)
})
}
useEffect(() => {
// Function to handle the save button click
const handleSaveButtonClick = () => {
handleMarkdownConversion()
}
// Get the save button and add the click event listener
const saveButton = document.getElementById('action-save')
if (saveButton) {
saveButton.addEventListener('click', handleSaveButtonClick)
}
// Cleanup function to remove the event listener
return () => {
if (saveButton) {
saveButton.removeEventListener('click', handleSaveButtonClick)
}
}
}, [editor, editorConfig])
return null
}'use client'
import {
createClientFeature,
slashMenuBasicGroupWithItems,
} from '@payloadcms/richtext-lexical/client'
import { TextIcon } from '../icons/Text'
import { ConvertToMarkdownPlugin, MARKDOWN_COMMAND } from './plugin'
export const MarkdownOutputFeatureClient = createClientFeature<never, any>({
plugins: [
{
Component: ConvertToMarkdownPlugin,
position: 'top',
},
],
slashMenu: {
groups: [
slashMenuBasicGroupWithItems([
{
Icon: TextIcon,
key: 'markdown',
keywords: ['transform', 'markdown'],
label: ({ i18n }) => {
return i18n.t('lexical:markdownOutput:label')
},
onSelect: ({ editor }) => {
editor.update(() => {
editor.dispatchCommand(MARKDOWN_COMMAND, null)
})
},
},
]),
],
},I have trimmed it down, and it console logs when you hit the command. I'm not sure how you pass that data into a field though? With hooks, you'd use siblingdata.fieldname but hm. Do I just use localapi? I guess I could modify the dom. But I'd rather it function like regular lexical, except it saves markdown to one field. I will look into it tomorrow, and see if I can use context provider
If you have another field into which you want to store a markdown, you can utilize payload's admin hooks for this purpose:
https://payloadcms.com/docs/admin/hooks#useformfieldsAnd you can do it not just by attaching event listener to the save button in your document, but every time lexical state changes, but as I said erlier this could be resource intensive.
Thank you! I think I'll settle on it storing extra info in the db and send to another field when I hit the publish button
I think my last question, is there a best practise to get info about the publish button? I've been using query selector since a before validate hook wont work
Or I think that's what the above link is for? I might have misunderstood
you mean a method to detect event of user saving a document?
The only thing that comes into my mind is this hook:
https://payloadcms.com/docs/admin/hooks#usedocumenteventsSo you probably can utilize it every time a document and updatedAt prop changes
but it will fire after user saved a document, not before, if I'm not wrong
Yeah. Ahh I think I get it now
Thank you for all the help, I got it working!
Star
Discord
online
Get dedicated engineering support directly from the Payload team.