-
Notifications
You must be signed in to change notification settings - Fork 132
fix: correctly set color and highlight of pasted text #2033
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
caio-pizzol
merged 7 commits into
superdoc-dev:main
from
gm1357:fix/apply-color-on-paste
Feb 23, 2026
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
3bcafbe
fix: normalize rgb color to hex to be properly applied on paste
gm1357 459e0b0
fix: parse background-color when pasting from word/docs
gm1357 dd3ee0f
chore: improve edge cases handling for cssColorToHex util
gm1357 36d4a5b
refactor: update how color and highlight is being normalized
gm1357 8611418
docs: update cssColorToHex jsdoc to better align the returned value
gm1357 7a02659
feat: explictly check for transparent/inherit/initial/unset values on…
gm1357 3cf8860
test: add behaviour tests for color and highlight pasting
gm1357 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| /** | ||
| * Converts a CSS color value to hex format (#RRGGBB). | ||
| * Handles rgb(), rgba(), hex, and returns null for empty input, transparent rgba, invalid rgb values. | ||
| * Named colors are returned as-is. | ||
| * | ||
| * @param {string|null|undefined} cssColor - A CSS color string | ||
| * @returns {string|null} Normalized color string or null | ||
| */ | ||
| export function cssColorToHex(cssColor) { | ||
| if (!cssColor) return null; | ||
| const trimmed = cssColor.trim(); | ||
| if (!trimmed) return null; | ||
|
|
||
| // Already hex — pass through | ||
| if (/^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(trimmed)) { | ||
| return trimmed; | ||
| } | ||
|
|
||
| // Parse rgb(r, g, b) or rgba(r, g, b, a) | ||
| const rgbMatch = trimmed.match(/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)(?:\s*,\s*([\d.]+))?\s*\)/); | ||
| if (rgbMatch) { | ||
| const [, r, g, b, a] = rgbMatch; | ||
|
|
||
| if (a !== undefined && parseFloat(a) === 0) return null; | ||
| if (Number(r) > 255 || Number(g) > 255 || Number(b) > 255) return null; | ||
|
|
||
| return '#' + [r, g, b].map((c) => Number(c).toString(16).padStart(2, '0')).join(''); | ||
| } | ||
|
|
||
| // Return as-is for other valid formats (named colors, etc.) | ||
| // Browsers normalize pasted colors to rgb(), so this is a rare fallback | ||
| return trimmed; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
51 changes: 51 additions & 0 deletions
51
tests/visual/tests/behavior/formatting/paste-color-and-highlight.spec.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| import { test } from '../../fixtures/superdoc.js'; | ||
|
|
||
| test('@behavior pasting html with rgb() background-color applies highlight', async ({ superdoc }) => { | ||
| await superdoc.page.evaluate(() => { | ||
| (window as any).editor.commands.insertContent( | ||
| '<span style="background-color: rgb(255, 255, 0)">Yellow highlighted text</span>', | ||
| ); | ||
| }); | ||
| await superdoc.screenshot('paste-rgb-background-color-highlight'); | ||
| }); | ||
|
|
||
| test('@behavior pasting html with transparent background-color applies no highlight', async ({ superdoc }) => { | ||
| await superdoc.page.evaluate(() => { | ||
| (window as any).editor.commands.insertContent( | ||
| '<span style="background-color: transparent">No highlight text</span>', | ||
| ); | ||
| }); | ||
| await superdoc.screenshot('paste-transparent-background-no-highlight'); | ||
| }); | ||
|
|
||
| test('@behavior pasting html with hex background-color applies highlight', async ({ superdoc }) => { | ||
| await superdoc.page.evaluate(() => { | ||
| (window as any).editor.commands.insertContent( | ||
| '<span style="background-color: #ffff00">Yellow highlighted text</span>', | ||
| ); | ||
| }); | ||
| await superdoc.screenshot('paste-hex-background-color-highlight'); | ||
| }); | ||
|
|
||
| test('@behavior pasting html with rgba zero-alpha background applies no highlight', async ({ superdoc }) => { | ||
| await superdoc.page.evaluate(() => { | ||
| (window as any).editor.commands.insertContent( | ||
| '<span style="background-color: rgba(255, 0, 0, 0)">No highlight text</span>', | ||
| ); | ||
| }); | ||
| await superdoc.screenshot('paste-rgba-zero-alpha-no-highlight'); | ||
| }); | ||
|
|
||
| test('@behavior pasting html with rgb() text color is applied', async ({ superdoc }) => { | ||
| await superdoc.page.evaluate(() => { | ||
| (window as any).editor.commands.insertContent('<span style="color: rgb(255, 0, 0)">Red text</span>'); | ||
| }); | ||
| await superdoc.screenshot('paste-rgb-text-color'); | ||
| }); | ||
|
|
||
| test('@behavior pasting html with hex text color is applied', async ({ superdoc }) => { | ||
| await superdoc.page.evaluate(() => { | ||
| (window as any).editor.commands.insertContent('<span style="color: #ff0000">Red text</span>'); | ||
| }); | ||
| await superdoc.screenshot('paste-hex-text-color'); | ||
| }); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.