1// The markdown editing keymap shared by every preset: fence-aware Enter (auto-close, newline
2// inside code), Tab list indentation, and the inline-mark toggles. Hosts layer their own bindings
3// (submit, pickers) at higher precedence; the composer factory does exactly that.
4import { defaultKeymap, historyKeymap } from "@codemirror/commands";
5import { type Extension, Prec } from "@codemirror/state";
6import { keymap } from "@codemirror/view";
7
8import {
9 codeBlockEnter,
10 continueList,
11 cycleEmphasis,
12 dedentListItem,
13 indentListItem,
14 surroundSelection,
15 toggleInlineMark,
16} from "./commands.ts";
17
18/** Fence/list-aware Enter, Tab list indent/dedent, Mod-b/Mod-i, and selection surrounds. */
19export function markdownKeymap(): Extension {
20 return Prec.high(
21 keymap.of([
22 { key: "Enter", run: (target) => codeBlockEnter(target) || continueList(target) },
23 { key: "Tab", run: indentListItem },
24 { key: "Shift-Tab", run: dedentListItem },
25 { key: "Mod-b", run: toggleInlineMark("**") },
26 { key: "Mod-i", run: toggleInlineMark("*") },
27 { key: "`", run: surroundSelection("`") },
28 { key: "*", run: cycleEmphasis },
29 ]),
30 );
31}
32
33/**
34 * History plus the CodeMirror defaults, minus bindings that make no sense in markdown: Mod-/
35 * toggles an HTML comment (markdown's only comment syntax), which no markdown editor wants.
36 */
37export function baseKeymap(): Extension {
38 return keymap.of([...historyKeymap, ...defaultKeymap.filter((b) => b.key !== "Mod-/")]);
39}