-
Notifications
You must be signed in to change notification settings - Fork 7
VxDesign: Keep at least one nbsp when stripping trailing; don't strip only whitespace #7858
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
base: main
Are you sure you want to change the base?
Conversation
…t strip only whitespace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR updates rich text paste sanitization to prevent ProseMirror/TipTap table paste crashes by ensuring trailing NBSP cleanup never produces an empty fragment, and by only trimming whitespace when an NBSP is actually present.
Changes:
- Update trailing-NBSP stripping logic to require an NBSP in the trimmed suffix and to fall back to a single NBSP instead of an empty string.
- Refresh and expand tests to cover the new “don’t strip plain trailing spaces” behavior and the NBSP-only fallback case.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| apps/design/frontend/src/rich_text_editor.tsx | Adjusts trailing NBSP stripping regex and adds a non-empty fallback to avoid empty fragments during paste. |
| apps/design/frontend/src/rich_text_editor.test.tsx | Updates/extends unit tests to match the new trimming rules and NBSP-only fallback output. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return text.replace(/[\u00A0\s]*\u00A0[\u00A0\s]*$/, '') || ' '; | ||
| } | ||
|
|
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fallback uses a literal NBSP character (' '), which is visually ambiguous and easy to accidentally modify during edits/reformatting. Consider using an explicit escape ('\u00A0') or a named constant (e.g., const NBSP = '\u00A0') for readability and to avoid hidden-character issues.
| return text.replace(/[\u00A0\s]*\u00A0[\u00A0\s]*$/, '') || ' '; | |
| } | |
| return text.replace(/[\u00A0\s]*\u00A0[\u00A0\s]*$/, '') || NBSP; | |
| } | |
| const NBSP = '\u00A0'; |
| // one NBSP (unicode U+00A0). Falls back to a single NBSP rather than empty to | ||
| // avoid producing empty fragments that crash ProseMirror's pastedCells function. |
Copilot
AI
Jan 29, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment references ProseMirror's pastedCells function, but the PR description mentions a TipTap/ProseMirror internal named pasteCells. To make this easier to search/verify later, please align the function name here to the actual upstream identifier (or link to the upstream source).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed PR description pasteCells -> pastedCells
Overview
https://votingworks.slack.com/archives/C08AWNY93PB/p1769698111533159
We had a slack alert where an internal function of TipTap is crashing within
pastedCells. Based on the error message indicating the function is finding an empty fragment when it didn't expect to, I think it has to do with the sanitize function returning an empty string. I haven't been able to reproduce as I've tried copying tables/cells which I had expected to trigger the issue.That being said, I think there are two clear improvements to make to this function:
Demo Video or Screenshot
Testing Plan
Tried manual testing by creating html files with table cells with nbsps, but I wasn't able to reproduce. I think it's probably worth just keeping an eye on it rather than continuing to try and repro, but open to suggestions for sure.
Checklist