Skip to content

Commit 8553eea

Browse files
authored
Merge branch 'dev' into rss1102/milkdown-engine-editor
2 parents 15e7fe9 + 8c4f17b commit 8553eea

9 files changed

Lines changed: 1450 additions & 15 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'cherry-markdown': patch
3+
---
4+
5+
fix: apply heading levels consistently across multiline selections

‎.changeset/quiet-lists-exit.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'cherry-markdown': patch
3+
---
4+
5+
fix: Markdown loose 列表回车续写不额外插入空行;协调同一有序列表多光标续写、退出和退级的编号,并合并为一次最终事务。空列表项直接退出或退级,不自动补段落空行。修复 Vim 普通模式按键优先级。

‎packages/cherry-markdown/src/Editor.js‎

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,15 @@ import {
2828
rectangularSelection,
2929
dropCursor,
3030
} from '@codemirror/view';
31-
import { EditorState, StateEffect, StateField, EditorSelection, Transaction, Compartment } from '@codemirror/state';
31+
import {
32+
EditorState,
33+
StateEffect,
34+
StateField,
35+
EditorSelection,
36+
Transaction,
37+
Compartment,
38+
Prec,
39+
} from '@codemirror/state';
3240
import { markdown } from '@codemirror/lang-markdown';
3341
import { search, searchKeymap, SearchQuery } from '@codemirror/search';
3442
import {
@@ -52,6 +60,7 @@ import { createElement } from './utils/dom';
5260
import { base64Reg, imgDrawioXmlReg, createUrlReg, getCodeBlockRule } from './utils/regexp';
5361
import { addEvent, removeEvent } from './utils/event';
5462
import { handleNewlineIndentList } from './utils/autoindent';
63+
import { createMarkdownKeymap } from './utils/markdownKeymap';
5564
import diff from 'fast-diff';
5665

5766
/**
@@ -651,7 +660,8 @@ class CM6Adapter {
651660
try {
652661
const vimMod = await loadVimModule();
653662
this.view.dispatch({
654-
effects: this.vimCompartment.reconfigure(vimMod.vim()),
663+
// Vim handles normal-mode keys before Markdown; unhandled insert-mode keys fall through.
664+
effects: this.vimCompartment.reconfigure(Prec.highest(vimMod.vim())),
655665
});
656666
this.currentKeyMap = 'vim';
657667
} catch (e) {
@@ -1909,14 +1919,6 @@ export default class Editor {
19091919
{ key: 'ArrowUp', run: () => self.arrowKeyInterceptor?.('ArrowUp') || false },
19101920
{ key: 'ArrowDown', run: () => self.arrowKeyInterceptor?.('ArrowDown') || false },
19111921
{ key: 'Escape', run: () => self.arrowKeyInterceptor?.('Escape') || false },
1912-
{
1913-
key: 'Enter',
1914-
run: (view) => {
1915-
if (self.arrowKeyInterceptor?.('Enter')) return true;
1916-
const adapter = self.editor || new CM6Adapter(view, self.vimCompartment, self.readOnlyCompartment);
1917-
return handleNewlineIndentList(adapter);
1918-
},
1919-
},
19201922
// Sublime Text style keybindings
19211923
// Ctrl-Shift-L / Cmd-Shift-L: 将选区拆分为多个光标,在每行末尾各放一个光标(Sublime split into lines)
19221924
{
@@ -1961,7 +1963,18 @@ export default class Editor {
19611963

19621964
const extensions = [
19631965
cachedCherryHighlighting,
1964-
markdown(),
1966+
markdown({ addKeymap: false }),
1967+
Prec.high(
1968+
keymap.of(
1969+
createMarkdownKeymap({
1970+
interceptEnter: () => self.arrowKeyInterceptor?.('Enter') || false,
1971+
continueCustomList: (view) => {
1972+
const adapter = self.editor || new CM6Adapter(view, self.vimCompartment, self.readOnlyCompartment);
1973+
return handleNewlineIndentList(adapter);
1974+
},
1975+
}),
1976+
),
1977+
),
19651978
this.historyCompartment.of(history()),
19661979
search(),
19671980
closeBrackets(),

‎packages/cherry-markdown/src/toolbars/hooks/Header.js‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export default class Header extends MenuBase {
7171
}
7272

7373
$testIsHead(selection) {
74-
return /^\s*(#+)\s*.+/.test(selection);
74+
return /^[ \t]*#+[ \t]*.+/m.test(selection);
7575
}
7676

7777
/**
@@ -99,9 +99,9 @@ export default class Header extends MenuBase {
9999
// 如果选中的内容里有标题语法,并且标记级别与目标一致,则去掉标题语法
100100
// 反之,修改标题级别与目标一致
101101
let needClean = true;
102-
const tmp = $selection.replace(/(^\s*)(#+)(\s*)(.+$)/gm, (w, m1, m2, m3, m4) => {
103-
needClean = needClean ? m2.length === header.length : false;
104-
return `${m1}${header}${m3}${m4}`;
102+
const tmp = $selection.replace(/^([ \t]*)(#+)?([ \t]*)(.+)$/gm, (w, m1, m2, m3, m4) => {
103+
needClean = needClean && !!m2 && m2.length === header.length;
104+
return `${m1}${header}${m2 ? m3 : ' '}${m4}`;
105105
});
106106
if (needClean) {
107107
return $selection.replace(/(^\s*)(#+)(\s*)(.+$)/gm, '$1$4');

0 commit comments

Comments
 (0)