Skip to content

[lexical-html][lexical-table] Feature: Inline CSS from <style> tags#8326

Merged
etrepum merged 4 commits intofacebook:mainfrom
tomsarduy:lexical-html/inline-styles-from-style-tags
Apr 12, 2026
Merged

[lexical-html][lexical-table] Feature: Inline CSS from <style> tags#8326
etrepum merged 4 commits intofacebook:mainfrom
tomsarduy:lexical-html/inline-styles-from-style-tags

Conversation

@tomsarduy
Copy link
Copy Markdown
Contributor

@tomsarduy tomsarduy commented Apr 10, 2026

Address #8318

Apps like Excel and Outlook generate HTML where styles live in <style> class rules (e.g. .xl65 { background: #FFFF00; color: blue; }) rather than inline styles. Lexical's import converters only read inline styles, so all class-based formatting was silently lost on paste.

Add inlineStylesFromStyleSheets() as a preprocessing step in $generateNodesFromDOM that resolves CSS rules from <style> tags into inline styles on matching elements before any converters run. This is generic — all existing converters automatically benefit for any CSS property (background-color, color, font-weight, font-size, margins, etc.).

Also extend the table cell import converter's after callback to propagate color from <td> elements to child TextNodes, matching the existing pattern for bold/italic/underline/strikethrough. This is needed because CSS color on a is inherited by child text, but Lexical models text color on TextNode, not on the cell — so the converter must bridge this gap explicitly.

Pasted table from Excel

Before After
Before After

Note: This just parse <style> definitions, and I agree with the comment from @etrepum, to support MS Word for example, need a normalise step (something the outlook client does very well btw) but that's a big task.

Fixes facebook#8318

Apps like Excel and Outlook generate HTML where styles live in <style>
class rules (e.g. `.xl65 { background: #FFFF00; color: blue; }`) rather
than inline styles. Lexical's import converters only read inline styles,
so all class-based formatting was silently lost on paste.

Add `inlineStylesFromStyleSheets()` as a preprocessing step in
`$generateNodesFromDOM` that resolves CSS rules from `<style>` tags into
inline styles on matching elements before any converters run. This is
generic — all existing converters automatically benefit for any CSS
property (background-color, color, font-weight, font-size, margins,
etc.).

Also extend the table cell import converter's `after` callback to
propagate `color` from `<td>` elements to child TextNodes, matching the
existing pattern for bold/italic/underline/strikethrough. This is needed
because CSS color on a <td> is inherited by child text, but Lexical
models text color on TextNode, not on the cell — so the converter must
bridge this gap explicitly.
@vercel
Copy link
Copy Markdown

vercel bot commented Apr 10, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
lexical Ready Ready Preview, Comment Apr 12, 2026 5:10pm
lexical-playground Ready Ready Preview, Comment Apr 12, 2026 5:10pm

Request Review

@meta-cla meta-cla bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Apr 10, 2026
}
if (color) {
const existingStyle = child.getStyle();
if (!existingStyle.includes('color:')) {
Copy link
Copy Markdown
Contributor Author

@tomsarduy tomsarduy Apr 10, 2026

Choose a reason for hiding this comment

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

Propagate color from <td> to child TextNodes

@tomsarduy tomsarduy changed the title [lexical-html][lexical-table] Bug Fix: Inline CSS from <style> tags [lexical-html][lexical-table] Feature: Inline CSS from <style> tags Apr 10, 2026
@etrepum etrepum added the extended-tests Run extended e2e tests on a PR label Apr 11, 2026
Copy link
Copy Markdown
Collaborator

@etrepum etrepum left a comment

Choose a reason for hiding this comment

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

Overall I think this looks good and is a worthwhile approach for the current importDOM API, but it doesn't appear to test the functionality it's adding. I only see tests that check to make sure it doesn't crash, not that the styles are actually propagated in a way that lexical imports correctly.

@etrepum etrepum added this pull request to the merge queue Apr 12, 2026
Merged via the queue into facebook:main with commit e4bee6d Apr 12, 2026
37 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. extended-tests Run extended e2e tests on a PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants