Skip to content

feat: render images in RichText via a custom Lexical image node - #3448

Open
carolvalenca wants to merge 4 commits into
devfrom
feat/rich-text-embed-images
Open

feat: render images in RichText via a custom Lexical image node#3448
carolvalenca wants to merge 4 commits into
devfrom
feat/rich-text-embed-images

Conversation

@carolvalenca

@carolvalenca carolvalenca commented Aug 12, 2026

Copy link
Copy Markdown

What's the purpose of this pull request?

This pull request introduces support for custom image nodes in the rich text editor, allowing images with alignment and width options to be rendered and styled consistently. The main changes include the implementation of a new RichTextImageNode for image handling, its integration into the editor pipeline, and corresponding styling updates.

Rich Text Image Node Implementation and Integration:

  • Added the new RichTextImageNode class to RichTextImageNode.ts, supporting image source, alt text, alignment (left, center, right), and width percentage, with logic for exporting to and importing from JSON and DOM, and automatic image resizing for VTEX assets.
  • Registered RichTextImageNode in the lexicalToHtml function, enabling the rich text editor to recognize and handle image nodes.
  • Imported RichTextImageNode into RichText.tsx to ensure it is available for use in the editor.

Styling Enhancements:

  • Updated styles.scss to add styles for [data-fs-rich-text-image-wrapper], ensuring images are displayed with correct alignment and responsive sizing according to their alignment and width settings.

How it works?

An image inserted via Content Platform's RichTextWidget gets serialized as a Lexical image node (src, altText, alignment, widthPercent) inside the rich text field's content. RichText's headless Lexical editor didn't recognize that node type, so images were dropped or broke parsing.

Added RichTextImageNode, registered in lexicalToHtml(), to close that gap: it parses the node (sanitizing alignment/widthPercent, capping width at 100%) and renders it to <div data-fs-rich-text-image-wrapper> + <img data-fs-rich-text-image loading="lazy">. VTEX file-manager URLs get resized via query params (same convention as faststoreLoader). A missing/invalid src makes the node skip itself instead of breaking the block. Styling was added to @faststore/ui's RichText/styles.scss.

(Check this PR to get more context)

How to test it?

This should be tested using Content Platform as content source. It can be tested using the Newsletter component. Simply set up a store that uses the code from this PR on CP and create a new entry with the Newsletter component. The preview feature can then be used to test the rendering of the Newsletter rich text.

Checklist

PR Title and Commit Messages

  • PR title and commit messages follow the Conventional Commits specification
    • Available prefixes: feat, fix, chore, docs, style, refactor, ci and test

PR Description

  • Added a label according to the PR goal - breaking change, bug, contributing, performance, documentation..

Dependencies

  • Committed the pnpm-lock.yaml file when there were changes to the packages

Documentation

  • PR description
  • For documentation changes, ping @Mariana-Caetano to review and update (Or submit a doc request)

Summary by CodeRabbit

  • New Features

    • Added support for displaying images within rich-text content.
    • Images now support left, center, and right alignment.
    • Image widths are responsive and constrained to valid values.
    • Images include descriptive alternative text and optimized loading behavior.
    • Rich-text content preserves image placement alongside text and supports external image URLs.
  • Bug Fixes

    • Improved handling of missing or malformed image data without disrupting rich-text rendering.

@carolvalenca
carolvalenca requested a review from a team as a code owner August 12, 2026 17:59
@carolvalenca
carolvalenca requested review from eduardoformiga and renatomaurovtex and removed request for a team August 12, 2026 17:59
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 785e565f-2de7-4b89-abfa-03d5b81e2847

📥 Commits

Reviewing files that changed from the base of the PR and between a561416 and 0d700bb.

📒 Files selected for processing (1)
  • packages/core/test/components/ui/RichText/RichText.browser.test.tsx

Walkthrough

RichText now processes Lexical image nodes. The new node validates and serializes image metadata, transforms supported VTEX URLs, exports responsive HTML, and supports alignment styling. Browser tests cover valid, invalid, legacy, and image-free content.

Changes

Rich-text image support

Layer / File(s) Summary
Image node contract and serialization
packages/core/src/components/ui/RichText/RichTextImageNode.ts
Adds RichTextImageNode, alignment and width validation, cloning, JSON serialization, and Lexical lifecycle methods.
Lexical registration and image rendering
packages/core/src/components/ui/RichText/RichText.tsx, packages/core/src/components/ui/RichText/RichTextImageNode.ts, packages/ui/src/components/atoms/RichText/styles.scss
Registers the image node, exports lazy-loaded responsive HTML, applies supported VTEX resizing, and adds alignment styles.
Browser rendering validation
packages/core/test/components/ui/RichText/RichText.browser.test.tsx
Tests image rendering, ordering, invalid data handling, defaults, width clamping, URL passthrough, and existing content formats.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Mergeability Score: 🟡 Moderate · up to 0d700

The change adds image rendering to RichText, but the associated test suite may fail to load because its mock references an uninitialized variable. This should be fixed before merging.

Suggested reviewers: eduardoformiga, renatomaurovtex

Sequence Diagram(s)

sequenceDiagram
  participant RichText
  participant HeadlessLexicalEditor
  participant RichTextImageNode
  participant BrowserDOM
  RichText->>HeadlessLexicalEditor: register RichTextImageNode
  HeadlessLexicalEditor->>RichTextImageNode: process serialized image data
  RichTextImageNode->>RichTextImageNode: validate metadata and transform supported VTEX URL
  RichTextImageNode-->>RichText: export responsive image HTML
  RichText->>BrowserDOM: render HTML with alignment wrapper
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: rendering images in RichText with a custom Lexical image node.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/rich-text-embed-images

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@codesandbox-ci

codesandbox-ci Bot commented Aug 12, 2026

Copy link
Copy Markdown

This pull request is automatically built and testable in CodeSandbox.

To see build info of the built libraries, click here or the icon next to each commit SHA.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/src/components/ui/RichText/RichTextImageNode.ts`:
- Around line 37-40: Update resolveWidthPercent so it accepts only finite,
positive numeric width values; reject Infinity, -Infinity, and NaN before
returning the value, while preserving DEFAULT_WIDTH_PERCENT for invalid inputs.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 1db129b2-2d82-4b71-a422-0b302abe1cb1

📥 Commits

Reviewing files that changed from the base of the PR and between 17d1209 and 2c8459e.

📒 Files selected for processing (3)
  • packages/core/src/components/ui/RichText/RichText.tsx
  • packages/core/src/components/ui/RichText/RichTextImageNode.ts
  • packages/ui/src/components/atoms/RichText/styles.scss

Comment thread packages/core/src/components/ui/RichText/RichTextImageNode.ts Outdated
@pkg-pr-new

pkg-pr-new Bot commented Aug 12, 2026

Copy link
Copy Markdown

Open in StackBlitz

@faststore/api

npm i https://pkg.pr.new/vtex/faststore/@faststore/api@0d700bb

@faststore/cli

npm i https://pkg.pr.new/vtex/faststore/@faststore/cli@0d700bb

@faststore/components

npm i https://pkg.pr.new/vtex/faststore/@faststore/components@0d700bb

@faststore/core

npm i https://pkg.pr.new/vtex/faststore/@faststore/core@0d700bb

@faststore/diagnostics

npm i https://pkg.pr.new/vtex/faststore/@faststore/diagnostics@0d700bb

@faststore/lighthouse

npm i https://pkg.pr.new/vtex/faststore/@faststore/lighthouse@0d700bb

@faststore/sdk

npm i https://pkg.pr.new/vtex/faststore/@faststore/sdk@0d700bb

@faststore/ui

npm i https://pkg.pr.new/vtex/faststore/@faststore/ui@0d700bb

commit: 0d700bb

@carolvalenca carolvalenca added the enhancement New feature or request label Aug 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/core/test/components/ui/RichText/RichText.test.tsx`:
- Around line 8-12: Hoist isContentPlatformSourceMock with vi.hoisted before the
vi.mock factory uses it, preserving the existing mock behavior. Rename the test
file from RichText.test.tsx to RichText.browser.test.tsx so it is collected by
the browser project instead of the node project.

Apply the same fix in
`@packages/core/test/components/ui/RichText/RichText.test.tsx` around lines 1 - 3.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: acf386cc-3ea9-4d43-86b5-e06088ccdc2f

📥 Commits

Reviewing files that changed from the base of the PR and between d49fd8a and a561416.

📒 Files selected for processing (2)
  • packages/core/src/components/ui/RichText/RichTextImageNode.ts
  • packages/core/test/components/ui/RichText/RichText.test.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/core/src/components/ui/RichText/RichTextImageNode.ts

Comment thread packages/core/test/components/ui/RichText/RichText.test.tsx Outdated
@sonar-workflows

Copy link
Copy Markdown

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

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant