mirror of
https://github.com/laurent22/joplin.git
synced 2024-12-21 09:38:01 +02:00
Desktop: Fixes #10020: Beta markdown editor: Support overriding built-in keyboard shortcuts (#10022)
This commit is contained in:
parent
c35085d1d5
commit
91004f5714
@ -255,27 +255,30 @@ packages/app-desktop/gui/Navigator.js
|
||||
packages/app-desktop/gui/NoteContentPropertiesDialog.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/Toolbar.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/index.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/normalizeAccelerator.test.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/normalizeAccelerator.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/types.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useContextMenu.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.test.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearchExtension.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearchHandler.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useExternalPlugins.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinCommands.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinMode.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useKeymap.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useLineSorting.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollHandler.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useStyles.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useWebviewIpcMessage.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/CodeMirror.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/Editor.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useCursorUtils.test.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useCursorUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useExternalPlugins.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useJoplinCommands.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useJoplinMode.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useKeymap.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useLineSorting.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useListIdent.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useScrollUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v6/CodeMirror.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v6/Editor.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v6/useEditorCommands.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v6/utils/useKeymap.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/PlainEditor/PlainEditor.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
||||
@ -648,6 +651,7 @@ packages/editor/CodeMirror/testUtil/createEditorSettings.js
|
||||
packages/editor/CodeMirror/testUtil/createTestEditor.js
|
||||
packages/editor/CodeMirror/testUtil/forceFullParse.js
|
||||
packages/editor/CodeMirror/testUtil/loadLanguages.js
|
||||
packages/editor/CodeMirror/testUtil/pressReleaseKey.js
|
||||
packages/editor/CodeMirror/testUtil/typeText.js
|
||||
packages/editor/CodeMirror/theme.js
|
||||
packages/editor/CodeMirror/util/isInSyntaxNode.js
|
||||
|
22
.gitignore
vendored
22
.gitignore
vendored
@ -235,27 +235,30 @@ packages/app-desktop/gui/Navigator.js
|
||||
packages/app-desktop/gui/NoteContentPropertiesDialog.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/Toolbar.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/index.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/normalizeAccelerator.test.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/normalizeAccelerator.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/types.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useContextMenu.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.test.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useCursorUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearchExtension.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useEditorSearchHandler.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useExternalPlugins.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinCommands.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useJoplinMode.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useKeymap.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useLineSorting.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useListIdent.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollHandler.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useScrollUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useStyles.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/utils/useWebviewIpcMessage.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/CodeMirror.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/Editor.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useCursorUtils.test.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useCursorUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useExternalPlugins.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useJoplinCommands.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useJoplinMode.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useKeymap.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useLineSorting.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useListIdent.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v5/utils/useScrollUtils.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v6/CodeMirror.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v6/Editor.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v6/useEditorCommands.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/CodeMirror/v6/utils/useKeymap.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/PlainEditor/PlainEditor.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/TinyMCE.js
|
||||
packages/app-desktop/gui/NoteEditor/NoteBody/TinyMCE/styles/index.js
|
||||
@ -628,6 +631,7 @@ packages/editor/CodeMirror/testUtil/createEditorSettings.js
|
||||
packages/editor/CodeMirror/testUtil/createTestEditor.js
|
||||
packages/editor/CodeMirror/testUtil/forceFullParse.js
|
||||
packages/editor/CodeMirror/testUtil/loadLanguages.js
|
||||
packages/editor/CodeMirror/testUtil/pressReleaseKey.js
|
||||
packages/editor/CodeMirror/testUtil/typeText.js
|
||||
packages/editor/CodeMirror/theme.js
|
||||
packages/editor/CodeMirror/util/isInSyntaxNode.js
|
||||
|
@ -0,0 +1,21 @@
|
||||
import normalizeAccelerator from './normalizeAccelerator';
|
||||
import { CodeMirrorVersion } from './types';
|
||||
|
||||
describe('normalizeAccelerator', () => {
|
||||
test.each([
|
||||
['Z', { v6: 'z', v5: 'Z' }],
|
||||
['Alt+A', { v6: 'Alt-a', v5: 'Alt-A' }],
|
||||
['Shift+A', { v6: 'Shift-a', v5: 'Shift-A' }],
|
||||
['Shift+Up', { v6: 'Shift-Up', v5: 'Shift-Up' }],
|
||||
])(
|
||||
'should convert single-letter key names to lowercase for CM6, keep case unchanged for CM5 (%j)',
|
||||
(original, expected) => {
|
||||
expect(normalizeAccelerator(
|
||||
original, CodeMirrorVersion.CodeMirror6,
|
||||
)).toBe(expected.v6);
|
||||
expect(normalizeAccelerator(
|
||||
original, CodeMirrorVersion.CodeMirror5,
|
||||
)).toBe(expected.v5);
|
||||
},
|
||||
);
|
||||
});
|
@ -0,0 +1,35 @@
|
||||
import { CodeMirrorVersion } from './types';
|
||||
|
||||
// CodeMirror and Electron register accelerators slightly different
|
||||
// CodeMirror requires a - between keys while Electron want's a +
|
||||
// CodeMirror doesn't recognize Option (it uses Alt instead)
|
||||
// CodeMirror requires Shift to be first
|
||||
// CodeMirror 6 requires Shift if the key name is uppercase.
|
||||
const normalizeAccelerator = (accelerator: string, editorVersion: CodeMirrorVersion) => {
|
||||
const command = accelerator.replace(/\+/g, '-').replace('Option', 'Alt');
|
||||
// From here is taken out of codemirror/lib/codemirror.js, modified
|
||||
// to also support CodeMirror 6.
|
||||
const parts = command.split(/-(?!$)/);
|
||||
let name = parts[parts.length - 1];
|
||||
|
||||
// In CodeMirror 6, an uppercase single-letter key name makes the editor
|
||||
// require the shift key to activate the shortcut. If a key name like `Up`,
|
||||
// however, `.toLowerCase` breaks the shortcut.
|
||||
if (editorVersion === CodeMirrorVersion.CodeMirror6 && name.length === 1) {
|
||||
name = name.toLowerCase();
|
||||
}
|
||||
|
||||
let alt, ctrl, shift, cmd;
|
||||
for (let i = 0; i < parts.length - 1; i++) {
|
||||
const mod = parts[i];
|
||||
if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; } else if (/^a(lt)?$/i.test(mod)) { alt = true; } else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; } else if (/^s(hift)?$/i.test(mod)) { shift = true; } else { throw new Error(`Unrecognized modifier name: ${mod}`); }
|
||||
}
|
||||
if (alt) { name = `Alt-${name}`; }
|
||||
if (ctrl) { name = `Ctrl-${name}`; }
|
||||
if (cmd) { name = `Cmd-${name}`; }
|
||||
if (shift) { name = `Shift-${name}`; }
|
||||
return name;
|
||||
// End of code taken from codemirror/lib/codemirror.js
|
||||
};
|
||||
|
||||
export default normalizeAccelerator;
|
@ -9,3 +9,8 @@ export function defaultRenderedBody(): RenderedBody {
|
||||
pluginAssets: [],
|
||||
};
|
||||
}
|
||||
|
||||
export enum CodeMirrorVersion {
|
||||
CodeMirror5,
|
||||
CodeMirror6,
|
||||
}
|
||||
|
@ -12,15 +12,15 @@ import 'codemirror/addon/scroll/annotatescrollbar';
|
||||
import 'codemirror/addon/search/matchesonscrollbar';
|
||||
import 'codemirror/addon/search/searchcursor';
|
||||
|
||||
import useListIdent from '../utils/useListIdent';
|
||||
import useScrollUtils from '../utils/useScrollUtils';
|
||||
import useCursorUtils from '../utils/useCursorUtils';
|
||||
import useLineSorting from '../utils/useLineSorting';
|
||||
import useListIdent from './utils/useListIdent';
|
||||
import useScrollUtils from './utils/useScrollUtils';
|
||||
import useCursorUtils from './utils/useCursorUtils';
|
||||
import useLineSorting from './utils/useLineSorting';
|
||||
import useEditorSearch from '../utils/useEditorSearchExtension';
|
||||
import useJoplinMode from '../utils/useJoplinMode';
|
||||
import useKeymap from '../utils/useKeymap';
|
||||
import useExternalPlugins from '../utils/useExternalPlugins';
|
||||
import useJoplinCommands from '../utils/useJoplinCommands';
|
||||
import useJoplinMode from './utils/useJoplinMode';
|
||||
import useKeymap from './utils/useKeymap';
|
||||
import useExternalPlugins from './utils/useExternalPlugins';
|
||||
import useJoplinCommands from './utils/useJoplinCommands';
|
||||
|
||||
import 'codemirror/keymap/emacs';
|
||||
import 'codemirror/keymap/vim';
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { useEffect } from 'react';
|
||||
import CommandService from '@joplin/lib/services/CommandService';
|
||||
import KeymapService, { KeymapItem } from '@joplin/lib/services/KeymapService';
|
||||
import { EditorCommand } from '../../../utils/types';
|
||||
import { EditorCommand } from '../../../../utils/types';
|
||||
import shim from '@joplin/lib/shim';
|
||||
import { reg } from '@joplin/lib/registry';
|
||||
import setupVim from '@joplin/editor/CodeMirror/util/setupVim';
|
||||
import { EventName } from '@joplin/lib/eventManager';
|
||||
import normalizeAccelerator from '../../utils/normalizeAccelerator';
|
||||
import { CodeMirrorVersion } from '../../utils/types';
|
||||
|
||||
export default function useKeymap(CodeMirror: any) {
|
||||
|
||||
@ -28,29 +30,6 @@ export default function useKeymap(CodeMirror: any) {
|
||||
return command.slice(7); // 7 is the length of editor.
|
||||
}
|
||||
|
||||
// CodeMirror and Electron register accelerators slightly different
|
||||
// CodeMirror requires a - between keys while Electron want's a +
|
||||
// CodeMirror doesn't recognize Option (it uses Alt instead)
|
||||
// CodeMirror requires Shift to be first
|
||||
function normalizeAccelerator(accelerator: string) {
|
||||
const command = accelerator.replace(/\+/g, '-').replace('Option', 'Alt');
|
||||
// From here is taken out of codemirror/lib/codemirror.js
|
||||
const parts = command.split(/-(?!$)/);
|
||||
|
||||
let name = parts[parts.length - 1];
|
||||
let alt, ctrl, shift, cmd;
|
||||
for (let i = 0; i < parts.length - 1; i++) {
|
||||
const mod = parts[i];
|
||||
if (/^(cmd|meta|m)$/i.test(mod)) { cmd = true; } else if (/^a(lt)?$/i.test(mod)) { alt = true; } else if (/^(c|ctrl|control)$/i.test(mod)) { ctrl = true; } else if (/^s(hift)?$/i.test(mod)) { shift = true; } else { throw new Error(`Unrecognized modifier name: ${mod}`); }
|
||||
}
|
||||
if (alt) { name = `Alt-${name}`; }
|
||||
if (ctrl) { name = `Ctrl-${name}`; }
|
||||
if (cmd) { name = `Cmd-${name}`; }
|
||||
if (shift) { name = `Shift-${name}`; }
|
||||
return name;
|
||||
// End of code taken from codemirror/lib/codemirror.js
|
||||
}
|
||||
|
||||
// Because there is sometimes a clash between these keybindings and the Joplin window ones
|
||||
// (This specifically can happen with the Ctrl-B and Ctrl-I keybindings when
|
||||
// codemirror is in contenteditable mode)
|
||||
@ -74,7 +53,7 @@ export default function useKeymap(CodeMirror: any) {
|
||||
}
|
||||
|
||||
// CodeMirror and Electron have slightly different formats for defining accelerators
|
||||
const acc = normalizeAccelerator(key.accelerator);
|
||||
const acc = normalizeAccelerator(key.accelerator, CodeMirrorVersion.CodeMirror5);
|
||||
|
||||
CodeMirror.keyMap.default[acc] = command;
|
||||
}
|
@ -10,6 +10,7 @@ import shim from '@joplin/lib/shim';
|
||||
import PluginService from '@joplin/lib/services/plugins/PluginService';
|
||||
import setupVim from '@joplin/editor/CodeMirror/util/setupVim';
|
||||
import { dirname } from 'path';
|
||||
import useKeymap from './utils/useKeymap';
|
||||
import useEditorSearch from '../utils/useEditorSearchExtension';
|
||||
|
||||
interface Props extends EditorProps {
|
||||
@ -145,6 +146,8 @@ const Editor = (props: Props, ref: ForwardedRef<CodeMirrorControl>) => {
|
||||
setupVim(editor);
|
||||
}, [editor]);
|
||||
|
||||
useKeymap(editor);
|
||||
|
||||
return (
|
||||
<div
|
||||
style={props.style}
|
||||
|
@ -0,0 +1,49 @@
|
||||
import { useEffect } from 'react';
|
||||
import CommandService from '@joplin/lib/services/CommandService';
|
||||
import KeymapService, { KeymapItem } from '@joplin/lib/services/KeymapService';
|
||||
import CodeMirrorControl from '@joplin/editor/CodeMirror/CodeMirrorControl';
|
||||
import normalizeAccelerator from '../../utils/normalizeAccelerator';
|
||||
import { CodeMirrorVersion } from '../../utils/types';
|
||||
|
||||
const useKeymap = (editorControl: CodeMirrorControl) => {
|
||||
useEffect(() => {
|
||||
if (!editorControl) return () => {};
|
||||
|
||||
// Some commands aren't registered with the command service
|
||||
// (e.g. Quit). Don't have CodeMirror handle these.
|
||||
// See gui/KeymapConfig/getLabel.ts.
|
||||
const isCommandRegistered = (commandName: string) => {
|
||||
const commandNames = CommandService.instance().commandNames();
|
||||
return commandNames.includes(commandName);
|
||||
};
|
||||
|
||||
const keymapItemToCodeMirror = (binding: KeymapItem) => {
|
||||
if (!binding.accelerator || !isCommandRegistered(binding.command)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
key: normalizeAccelerator(
|
||||
binding.accelerator, CodeMirrorVersion.CodeMirror6,
|
||||
),
|
||||
run: () => {
|
||||
void CommandService.instance().execute(binding.command);
|
||||
return true;
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const keymapItems = KeymapService.instance().getKeymapItems();
|
||||
const addedKeymap = editorControl.prependKeymap(
|
||||
keymapItems
|
||||
.map(item => keymapItemToCodeMirror(item))
|
||||
.filter(item => !!item),
|
||||
);
|
||||
|
||||
return () => {
|
||||
addedKeymap.remove();
|
||||
};
|
||||
}, [editorControl]);
|
||||
};
|
||||
|
||||
export default useKeymap;
|
@ -1,5 +1,7 @@
|
||||
import { ViewPlugin } from '@codemirror/view';
|
||||
import createEditorControl from './testUtil/createEditorControl';
|
||||
import { EditorCommandType } from '../types';
|
||||
import pressReleaseKey from './testUtil/pressReleaseKey';
|
||||
|
||||
describe('CodeMirrorControl', () => {
|
||||
it('clearHistory should clear the undo/redo history', () => {
|
||||
@ -58,6 +60,31 @@ describe('CodeMirrorControl', () => {
|
||||
expect(command).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should support overriding default keybindings', () => {
|
||||
const control = createEditorControl('test');
|
||||
control.execCommand(EditorCommandType.SelectAll);
|
||||
|
||||
const testCommand = jest.fn(() => true);
|
||||
const keybindings = control.prependKeymap([
|
||||
// Override the default binding for ctrl-d (search)
|
||||
{ key: 'Ctrl-d', run: testCommand },
|
||||
]);
|
||||
|
||||
// Should call the override command rather than the default handler
|
||||
const keyData = {
|
||||
key: 'd',
|
||||
code: 'KeyD',
|
||||
ctrlKey: true,
|
||||
};
|
||||
pressReleaseKey(control.editor, keyData);
|
||||
expect(testCommand).toHaveBeenCalledTimes(1);
|
||||
|
||||
// Calling keybindings.remove should deregister the override.
|
||||
keybindings.remove();
|
||||
pressReleaseKey(control.editor, keyData);
|
||||
expect(testCommand).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('should toggle comments', () => {
|
||||
const control = createEditorControl('Hello\nWorld\n');
|
||||
control.select(1, 5);
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { EditorView } from '@codemirror/view';
|
||||
import { EditorView, KeyBinding, keymap } from '@codemirror/view';
|
||||
import { EditorCommandType, EditorControl, EditorSettings, LogMessageCallback, ContentScriptData, SearchState } from '../types';
|
||||
import CodeMirror5Emulation from './CodeMirror5Emulation/CodeMirror5Emulation';
|
||||
import editorCommands from './editorCommands/editorCommands';
|
||||
@ -166,6 +166,23 @@ export default class CodeMirrorControl extends CodeMirror5Emulation implements E
|
||||
// CodeMirror-specific methods
|
||||
//
|
||||
|
||||
public prependKeymap(bindings: readonly KeyBinding[]) {
|
||||
const compartment = new Compartment();
|
||||
this.editor.dispatch({
|
||||
effects: StateEffect.appendConfig.of([
|
||||
compartment.of(keymap.of(bindings)),
|
||||
]),
|
||||
});
|
||||
|
||||
return {
|
||||
remove: () => {
|
||||
this.editor.dispatch({
|
||||
effects: compartment.reconfigure([]),
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public joplinExtensions = {
|
||||
// Some plugins want to enable autocompletion from *just* that plugin, without also
|
||||
// enabling autocompletion for text within code blocks (and other built-in completion
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Compartment, EditorState } from '@codemirror/state';
|
||||
import { Compartment, EditorState, Prec } from '@codemirror/state';
|
||||
import { indentOnInput, syntaxHighlighting } from '@codemirror/language';
|
||||
import {
|
||||
openSearchPanel, closeSearchPanel, getSearchQuery, search,
|
||||
@ -238,7 +238,10 @@ const createEditor = (
|
||||
notifySelectionChange(viewUpdate);
|
||||
notifySelectionFormattingChange(viewUpdate);
|
||||
}),
|
||||
keymap.of([
|
||||
|
||||
// Give the default keymap low precedence so that it is overridden
|
||||
// by extensions with default precedence.
|
||||
Prec.low(keymap.of([
|
||||
// Custom mod-f binding: Toggle the external dialog implementation
|
||||
// (don't show/hide the Panel dialog).
|
||||
keyCommand('Mod-f', (_: EditorView) => {
|
||||
@ -268,7 +271,7 @@ const createEditor = (
|
||||
}, true),
|
||||
|
||||
...standardKeymap, ...historyKeymap, ...searchKeymap,
|
||||
]),
|
||||
])),
|
||||
],
|
||||
doc: initialText,
|
||||
}),
|
||||
|
20
packages/editor/CodeMirror/testUtil/pressReleaseKey.ts
Normal file
20
packages/editor/CodeMirror/testUtil/pressReleaseKey.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { EditorView } from '@codemirror/view';
|
||||
|
||||
interface KeyInfo {
|
||||
key: string;
|
||||
code: string;
|
||||
ctrlKey?: boolean;
|
||||
metaKey?: boolean;
|
||||
shiftKey?: boolean;
|
||||
}
|
||||
|
||||
const pressReleaseKey = (editor: EditorView, key: KeyInfo) => {
|
||||
editor.contentDOM.dispatchEvent(
|
||||
new KeyboardEvent('keydown', key),
|
||||
);
|
||||
editor.contentDOM.dispatchEvent(
|
||||
new KeyboardEvent('keyup', key),
|
||||
);
|
||||
};
|
||||
|
||||
export default pressReleaseKey;
|
@ -88,6 +88,7 @@ firstname
|
||||
lastname
|
||||
signup
|
||||
activatable
|
||||
Prec
|
||||
titlewrapper
|
||||
notyf
|
||||
Notyf
|
||||
|
Loading…
Reference in New Issue
Block a user