Skip to content

Commit 943ba89

Browse files
authored
Markdown stability patch (#7238)
* fix: enforce empty paragraph when converting from markdown to slate * fix: handle unwrapping inline nodes in lists * style: lint code * fix: lost focus after backspace after break
1 parent 86c93a4 commit 943ba89

File tree

4 files changed

+48
-5
lines changed

4 files changed

+48
-5
lines changed

packages/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/events/keyDown.js

+9
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
import isHotkey from 'is-hotkey';
2+
import { Editor, Transforms } from 'slate';
23

34
import keyDownEnter from './keyDownEnter';
45
import keyDownBackspace from './keyDownBackspace';
56
import isCursorInNonDefaultBlock from '../locations/isCursorInNonDefaultBlock';
67
import toggleBlock from './toggleBlock';
8+
import isCursorCollapsedAfterSoftBreak from '../locations/isCursorCollapsedAfterSoftBreak';
79

810
const HEADING_HOTKEYS = {
911
'mod+1': 'heading-one',
@@ -25,6 +27,13 @@ function keyDown(event, editor) {
2527
}
2628
}
2729

30+
if (isHotkey('backspace', event) && isCursorCollapsedAfterSoftBreak(editor)) {
31+
const [, path] = Editor.previous(editor);
32+
Transforms.removeNodes(editor, { at: path });
33+
event.preventDefault();
34+
return false;
35+
}
36+
2837
if (!isCursorInNonDefaultBlock(editor)) return;
2938

3039
if (isHotkey('enter', event)) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { Editor, Range } from 'slate';
2+
3+
function isCursorCollapsedAfterSoftBreak(editor) {
4+
const { selection } = editor;
5+
if (!selection) return false;
6+
if (Range.isExpanded(selection)) return false;
7+
8+
const previous = Editor.previous(editor);
9+
10+
return previous && previous[0].type == 'break';
11+
}
12+
13+
export default isCursorCollapsedAfterSoftBreak;

packages/decap-cms-widget-markdown/src/MarkdownControl/plugins/blocks/transforms/unwrapIfCursorAtStart.js

+17-4
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,31 @@ import lowestMatchedAncestor from '../../matchers/lowestMatchedAncestor';
55
function unwrapIfCursorAtStart(editor, mergeWithPrevious = false) {
66
if (editor.selection.anchor.offset !== 0) return false;
77

8-
const node = Editor.above(editor, lowestMatchedAncestor(editor, 'non-default'));
8+
let [node, path] = Editor.above(editor, lowestMatchedAncestor(editor, 'non-default'));
99

10-
if (node[1].length == 0) return false;
10+
if (path.length == 0) return false;
1111

12-
const isHeading = `${node[0].type}`.startsWith('heading-');
12+
const isHeading = `${node.type}`.startsWith('heading-');
1313
if (isHeading) {
1414
Transforms.setNodes(editor, { type: 'paragraph' });
1515
return false;
1616
}
1717

18+
const isBlock = Editor.isBlock(editor, node);
19+
const [parentBlock, parentBlockPath] = Editor.above(
20+
editor,
21+
lowestMatchedAncestor(editor, 'block'),
22+
);
23+
if (!isBlock) {
24+
if (!Editor.isStart(editor, path, parentBlockPath)) {
25+
return false;
26+
}
27+
28+
[node, path] = [parentBlock, parentBlockPath];
29+
}
30+
1831
Editor.withoutNormalizing(editor, () => {
19-
Transforms.unwrapNodes(editor, { match: n => n.type === node[0].type, split: true });
32+
Transforms.unwrapNodes(editor, { match: n => n.type === node.type, split: true });
2033

2134
if (mergeWithPrevious) {
2235
Transforms.mergeNodes(editor);

packages/decap-cms-widget-markdown/src/serializers/remarkSlate.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -234,14 +234,22 @@ export default function remarkToSlate({ voidCodeBlock } = {}) {
234234
* Convert simple cases that only require a type and children, with no
235235
* additional properties.
236236
*/
237-
case 'root':
238237
case 'paragraph':
239238
case 'blockquote':
240239
case 'tableRow':
241240
case 'tableCell': {
242241
return createBlock(typeMap[node.type], nodes);
243242
}
244243

244+
/**
245+
* Root element
246+
* If the root node is empty, we need to add a paragraph node to it.
247+
*/
248+
case 'root': {
249+
const children = isEmpty(nodes) ? [createBlock('paragraph')] : nodes;
250+
return createBlock(typeMap[node.type], children);
251+
}
252+
245253
/**
246254
* List Items
247255
*

0 commit comments

Comments
 (0)