Skip to content

Commit 2189de1

Browse files
authored
feat(Breaks): replace double breaks with new paragraph (#149)
1 parent 8253496 commit 2189de1

File tree

1 file changed

+40
-1
lines changed

1 file changed

+40
-1
lines changed

src/extensions/markdown/Breaks/index.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
import type {NodeType} from 'prosemirror-model';
1+
import type {Node, NodeType} from 'prosemirror-model';
2+
import {TextSelection} from 'prosemirror-state';
23
import {chainCommands, exitCode} from 'prosemirror-commands';
34
import {logger} from '../../../logger';
45
import type {ExtensionAuto, Keymap} from '../../../core';
56
import {isMac} from '../../../utils/platform';
7+
import {isTextSelection} from '../../../utils/selection';
68
import {BreaksSpecs, BreaksSpecsOptions, hbType, sbType} from './BreaksSpecs';
9+
import {pType} from '../../base/BaseSchema/BaseSchemaSpecs';
710

811
export {BreaksSpecs, BreakNodeName, hbType, sbType} from './BreaksSpecs';
912

@@ -45,6 +48,38 @@ export const Breaks: ExtensionAuto<BreaksOptions> = (builder, opts) => {
4548

4649
const addBr = (br: NodeType) =>
4750
chainCommands(exitCode, (state, dispatch) => {
51+
const {selection: sel, schema} = state;
52+
if (
53+
!isTextSelection(sel) ||
54+
!sel.empty ||
55+
// breaks can only be in the paragraph
56+
sel.$cursor?.parent.type !== pType(schema)
57+
)
58+
return false;
59+
60+
if (isBreakNode(sel.$cursor.nodeBefore)) {
61+
if (dispatch) {
62+
const {
63+
$cursor,
64+
$cursor: {pos},
65+
} = sel;
66+
const from = isBreakNode($cursor.nodeAfter) ? pos + 1 : pos;
67+
const posEnd = $cursor.end();
68+
const posAfter = $cursor.after();
69+
70+
const contentAfter = state.doc.slice(from, posEnd, false).content;
71+
72+
let tr = state.tr.insert(posAfter, pType(schema).create(null, contentAfter));
73+
tr = tr
74+
.setSelection(TextSelection.create(tr.doc, posAfter + 1))
75+
.scrollIntoView()
76+
.delete(pos, posEnd) // remove content after current pos (it's moved to next para)
77+
.delete(pos - 1, pos); // remove break before current pos ($cursor.nodeBefore)
78+
dispatch(tr);
79+
}
80+
return true;
81+
}
82+
4883
dispatch?.(state.tr.replaceSelectionWith(br.create()).scrollIntoView());
4984
return true;
5085
});
@@ -59,3 +94,7 @@ declare global {
5994
}
6095
}
6196
}
97+
98+
function isBreakNode(node?: Node | null | undefined): boolean {
99+
return Boolean(node?.type.spec.isBreak);
100+
}

0 commit comments

Comments
 (0)