Skip to content

Commit b32e335

Browse files
committed
fix(mdviewer): backspace at start of heading converts to paragraph
1 parent b95d8ce commit b32e335

2 files changed

Lines changed: 46 additions & 0 deletions

File tree

src-mdviewer/src/components/editor.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,6 +1701,42 @@ function enterEditMode(content) {
17011701
return;
17021702
}
17031703

1704+
// Backspace at start of heading → convert to paragraph
1705+
if (e.key === "Backspace" && !mod) {
1706+
const sel2 = window.getSelection();
1707+
if (sel2 && sel2.rangeCount) {
1708+
const range2 = sel2.getRangeAt(0);
1709+
const block2 = range2.startContainer.nodeType === Node.TEXT_NODE
1710+
? range2.startContainer.parentElement : range2.startContainer;
1711+
const heading = block2?.closest("h1, h2, h3, h4, h5, h6");
1712+
if (heading && heading.closest("#viewer-content")) {
1713+
const atStart = range2.collapsed &&
1714+
range2.startOffset === 0 &&
1715+
(range2.startContainer === heading ||
1716+
range2.startContainer === heading.firstChild ||
1717+
(range2.startContainer.nodeType === Node.TEXT_NODE &&
1718+
!range2.startContainer.previousSibling));
1719+
if (atStart) {
1720+
e.preventDefault();
1721+
// Convert heading to <p>, preserving content
1722+
const p = document.createElement("p");
1723+
while (heading.firstChild) {
1724+
p.appendChild(heading.firstChild);
1725+
}
1726+
heading.parentNode.replaceChild(p, heading);
1727+
// Restore cursor at start of new <p>
1728+
const r = document.createRange();
1729+
r.setStart(p, 0);
1730+
r.collapse(true);
1731+
sel2.removeAllRanges();
1732+
sel2.addRange(r);
1733+
content.dispatchEvent(new Event("input", { bubbles: true }));
1734+
return;
1735+
}
1736+
}
1737+
}
1738+
}
1739+
17041740
if (e.key === "Enter") {
17051741
// Inside table: block Enter except on last cell or outside cells where it exits
17061742
if (isInsideTableOrWrapper()) {

src-mdviewer/to-create-tests.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,16 @@
161161
- [ ] List buttons remain visible when cursor is in list (for UL/OL switching)
162162
- [ ] Moving cursor out of list restores all toolbar buttons
163163

164+
## Heading Editing
165+
- [ ] Enter at start of heading (|Heading) inserts empty `<p>` above, heading shifts down
166+
- [ ] Enter in middle of heading creates new `<p>` below with trailing content
167+
- [ ] Enter at end of heading creates new empty `<p>` below
168+
- [ ] Backspace at start of heading converts heading to `<p>` (strips ### prefix in CM)
169+
- [ ] Backspace at start of heading preserves content and cursor position
170+
- [ ] Backspace at start of heading updates toolbar from "Heading N" to "Paragraph"
171+
- [ ] Heading-to-paragraph conversion syncs correctly to CM source
172+
- [ ] Backspace in middle of heading works normally (deletes character)
173+
164174
## Undo/Redo
165175
- [ ] Ctrl+Z undoes change in both md editor and CM (single undo stack)
166176
- [ ] Ctrl+Shift+Z / Ctrl+Y redoes change in both

0 commit comments

Comments
 (0)