Simplify your stack and build anything. Or everything.
Build tomorrow’s web with a modern solution you truly own.
Code-based nature means you can build on top of it to power anything.
It’s time to take back your content infrastructure.

Lexical markdown

default discord avatar
philipisawesomelast year
24

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?

  • default discord avatar
    vansofflast year

    hi, try not to mention team members directly, they will answer you if they can.


    what exactly are you trying to achieve?

  • default discord avatar
    philipisawesomelast year

    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?

  • default discord avatar
    vansofflast year

    No, I've just read the server rules😆



    Have you read these?


    https://payloadcms.com/docs/beta/lexical/converters#lexical-markdown
  • default discord avatar
    philipisawesomelast year

    Yup like I said they need editing



    For v3 the example in the docs don't work

  • default discord avatar
    vansofflast year

    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,

  • default discord avatar
    philipisawesomelast year

    When you write in lexical I want the output to be markdown

  • default discord avatar
    vansofflast year

    You mean something like this?


    https://playground.lexical.dev/

    There's an action button down in the editor M, which tranforms all nodes to markdown

  • default discord avatar
    philipisawesomelast year

    That's converting the editor state to markdown I think? I want the output to be markdown



    Actually maybe it's doing both

  • default discord avatar
    vansofflast year

    yep, it is, but an output can't understand what exactly you're meaning 🙂


    any examples?

  • default discord avatar
    philipisawesomelast year

    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.



    for example

    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

  • default discord avatar
    vansofflast year

    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

  • default discord avatar
    philipisawesomelast year

    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

  • default discord avatar
    vansofflast year

    v3?

  • default discord avatar
    philipisawesomelast year

    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

  • default discord avatar
    vansofflast year

    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/lexical

    It is mostly adaptations of playground features to payload, a bad one, but it works.

  • default discord avatar
    philipisawesomelast year

    Thank you, I will have a look in about 9 hours. Just working and then studying and I think I should be free

  • default discord avatar
    vansofflast year

    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.

  • default discord avatar
    philipisawesomelast year

    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

  • default discord avatar
    vansofflast year

    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

  • default discord avatar
    philipisawesomelast year

    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

  • default discord avatar
    vansofflast year

    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#useformfields

    And 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.

  • default discord avatar
    philipisawesomelast year

    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

  • default discord avatar
    vansofflast year

    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#usedocumentevents

    So 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

  • default discord avatar
    philipisawesomelast year

    Yeah. Ahh I think I get it now



    Thank you for all the help, I got it working!

Star on GitHub

Star

Chat on Discord

Discord

online

Can't find what you're looking for?

Get dedicated engineering support directly from the Payload team.