Skip to content

feat(richtext-lexical): add markdown transformer for upload nodes#15630

Merged
GermanJablo merged 3 commits intopayloadcms:mainfrom
veeceey:fix/issue-13086-upload-markdown-transformer
Feb 19, 2026
Merged

feat(richtext-lexical): add markdown transformer for upload nodes#15630
GermanJablo merged 3 commits intopayloadcms:mainfrom
veeceey:fix/issue-13086-upload-markdown-transformer

Conversation

@veeceey
Copy link
Copy Markdown
Contributor

@veeceey veeceey commented Feb 14, 2026

Problem

When converting Lexical rich text content to markdown using convertLexicalToMarkdown, upload nodes (images and files) are completely stripped from the output. There's no markdown transformer registered for the upload feature, so the converter silently drops them.

This means any content that includes uploaded images loses those images entirely when exported to markdown - which is unexpected since other node types like links, headings, and horizontal rules all have proper markdown transformers.

Fix

Added an ElementTransformer for upload nodes that handles three cases:

  1. Populated image uploads - outputs standard markdown image syntax:

    ![alt text](/uploads/image.jpg)
    
  2. Populated non-image uploads (PDFs, docs, etc.) - outputs a link:

    [document.pdf](/uploads/document.pdf)
    
  3. Non-populated uploads (value is just an ID) - outputs a reference placeholder so the data isn't silently lost:

    ![media:abc123]()
    

The transformer is registered in the UploadFeature server configuration alongside the existing HTML converter.

The import side (markdown -> Lexical) uses a never-matching regex because upload nodes should be created through the upload UI/drawer, not parsed from markdown text.

Test plan

  • Verified that upload nodes with populated data (containing url, alt, filename) produce valid markdown image syntax
  • Verified that non-image uploads produce link syntax
  • Verified that non-populated uploads produce a reference placeholder instead of being dropped

Fixes #13086

Upload nodes were silently dropped when converting Lexical content to
markdown. This adds an ElementTransformer that outputs upload nodes
as standard markdown image syntax when the value is populated:

  ![alt text](/uploads/image.jpg)

For non-image uploads, it outputs a link instead:

  [document.pdf](/uploads/document.pdf)

When the upload value is not populated (just an ID), a reference
placeholder is output so the data is not silently lost:

  ![collection:id]()

Fixes payloadcms#13086
Copy link
Copy Markdown
Contributor

@GermanJablo GermanJablo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Test plan

  • Verified that upload nodes with populated data (containing url, alt, filename) produce valid markdown image syntax
  • Verified that non-image uploads produce link syntax
  • Verified that non-populated uploads produce a reference placeholder instead of being dropped

Thank you. For next time, if possible, it would be very helpful to include the tests.


As a separate note, we've discussed internally with @AlessioGr how we can further improve the Markdown conversion experience in the future. Ideas to explore:

  • Intelligent URL recognition (including Link Nodes, if possible).
  • Do the same for internal links in LinkNode
  • A new parameter in convertLexicalToMarkdown that allows adding or customizing transformers.

@GermanJablo GermanJablo enabled auto-merge (squash) February 19, 2026 18:00
@GermanJablo GermanJablo merged commit 4af5a85 into payloadcms:main Feb 19, 2026
150 checks passed
@github-actions
Copy link
Copy Markdown
Contributor

🚀 This is included in version v3.78.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Lexical to Markdown converter strips out uploaded Image elements

2 participants