Fix Slides manual edit issues#2355
Conversation
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…a4d630b36ac64b0f9252
…a4d630b36ac64b0f9252
|
Here's a visual recap of what changed: Open the full interactive recap |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
…a4d630b36ac64b0f9252
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Builder reviewed your changes and found 1 potential issue 🟡
Review Details
Code Review Summary
This revision adds boundary clamping intended to protect marker glyphs when a non-collapsed selection includes a bullet. The collapsed-caret fix remains covered, and formatted-fragment handling is still present. However, the clamping introduces an unhandled same-marker selection case: moving the start after a marker and then the end before that same marker collapses the range at a row boundary, which can cause the subsequent tail extraction to include/remove the marker unexpectedly.
Key Findings
Medium severity:
- Selecting the marker glyph itself and pressing Enter is not safely handled by the latest clamping logic. Add an explicit same-marker selection path and a regression test.
The previously reported global U+200B stripping issue remains open and was not resubmitted.
🧪 Browser testing: Attempted full verification, but browser automation tools were unavailable; all 16 planned UI cases were blocked as environment issues despite a healthy dev server.
| const startMarker = enclosingMarker(range.startContainer, list); | ||
| if (startMarker) range.setStartAfter(startMarker); | ||
| const endMarker = enclosingMarker(range.endContainer, list); | ||
| if (endMarker) range.setEndBefore(endMarker); |
There was a problem hiding this comment.
🟡 Handle selections wholly inside one marker explicitly
When both selection endpoints are inside the same marker, setStartAfter(startMarker) followed by setEndBefore(endMarker) collapses the range at the row boundary before the marker. The later container === row tail extraction can then treat the marker as editable content, causing the original and inserted rows to lose their bullet glyph. Detect the same-marker case before clamping and treat it like a protected marker selection; add a test that selects the marker text itself rather than only placing a collapsed caret there.
Additional Info
Confirmed by reproducing the boundary operations with a standard marker text range: after clamping, the range collapses at row offset 0, before the marker. The existing tests cover only collapsed marker carets and do not exercise this path.

Summary
Fixes bullet-list editing in the slide editor so pressing Enter at the end of a bullet correctly adds a new bullet item, and clicking a bullet list selects/edits the whole list instead of a single row.
Problem
Slide bullet lists are rendered as styled
div/spanrows (marker + text) rather than native<ul>/<li>markup. Because of this, contentEditable had no way to know these rows belonged together: pressing Enter inside a bullet row was trapped within that single row instead of creating a new bullet, and clicking into a bullet edited only the individual line rather than the full list, breaking highlighting, inline formatting shortcuts, and the style dock.Solution
Added a dedicated
bullet-editingmodule that recognizes styled bullet rows/lists by their marker glyph structure, resolves the enclosing list from a caret position or clicked element, and manually inserts a new bullet row (cloning the current row's styling) when Enter is pressed at the end of a bullet. Wired this logic intoSlideEditor's smart-block detection, keydown handling, and click handling so bullet lists are treated as a single editable/selectable block.Key Changes
bullet-editing.ts(new): utilitiesisBulletMarker,isBulletRow,bulletRowCount,isBulletList,findEnclosingList, andinsertBulletAfterCaretto detect styled bullet structures and insert a new row after the caret, preserving marker glyph and font styling, with a zero-width space to keep the caret inside an empty new bullet's font context.bullet-editing.test.tsx(new): unit tests covering row/list detection, resolving a bullet text span to its list, inserting a new row on Enter, splitting trailing text into the new bullet, handling bare text nodes, and tolerating a stray non-bullet child.SlideEditor.tsx:findSmartBlocknow returns the enclosing bullet list (not just the single text leaf) so the whole list is treated as one editable block.stripBuilderIdsalso strips stray zero-width spaces from cleaned HTML.insertBulletAfterCaretto add a new bullet instead of falling through to native Enter behavior or committing the edit.To clone this PR locally use the Github CLI with command
gh pr checkout 2355You can tag me at @BuilderIO for anything you want me to fix or change