use-editor-settings.ts 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. import { useEffect, useCallback, useState } from 'react';
  2. import { Prec, Extension } from '@codemirror/state';
  3. import {
  4. keymap, type Command, highlightActiveLine, highlightActiveLineGutter,
  5. } from '@codemirror/view';
  6. import type { EditorSettings } from '../consts';
  7. import type { UseCodeMirrorEditor, EditorTheme, KeyMapMode } from '../services';
  8. import { getEditorTheme, getKeymap } from '../services';
  9. import { insertNewlineContinueMarkup } from '../services/list-util/insert-newline-continue-markup';
  10. import { insertNewRowToMarkdownTable, isInTable } from '../services/table-util/insert-new-row-to-table-markdown';
  11. export const useEditorSettings = (
  12. codeMirrorEditor?: UseCodeMirrorEditor,
  13. editorSetings?: EditorSettings,
  14. onSave?: () => void,
  15. ): void => {
  16. useEffect(() => {
  17. if (editorSetings?.styleActiveLine == null) {
  18. return;
  19. }
  20. const extensions = (editorSetings?.styleActiveLine) ? [[highlightActiveLine(), highlightActiveLineGutter()]] : [[]];
  21. const cleanupFunction = codeMirrorEditor?.appendExtensions?.(extensions);
  22. return cleanupFunction;
  23. }, [codeMirrorEditor, editorSetings?.styleActiveLine]);
  24. const onPressEnter: Command = useCallback((editor) => {
  25. if (isInTable(editor) && editorSetings?.autoFormatMarkdownTable) {
  26. insertNewRowToMarkdownTable(editor);
  27. return true;
  28. }
  29. insertNewlineContinueMarkup(editor);
  30. return true;
  31. }, [editorSetings?.autoFormatMarkdownTable]);
  32. useEffect(() => {
  33. const extension = keymap.of([
  34. { key: 'Enter', run: onPressEnter },
  35. ]);
  36. const cleanupFunction = codeMirrorEditor?.appendExtensions?.(extension);
  37. return cleanupFunction;
  38. }, [codeMirrorEditor, onPressEnter]);
  39. const [themeExtension, setThemeExtension] = useState<Extension | undefined>(undefined);
  40. useEffect(() => {
  41. const settingTheme = async(name?: EditorTheme) => {
  42. setThemeExtension(await getEditorTheme(name));
  43. };
  44. settingTheme(editorSetings?.theme);
  45. }, [codeMirrorEditor, editorSetings?.theme, setThemeExtension]);
  46. useEffect(() => {
  47. if (themeExtension == null) {
  48. return;
  49. }
  50. // React CodeMirror has default theme which is default prec
  51. // and extension have to be higher prec here than default theme.
  52. const cleanupFunction = codeMirrorEditor?.appendExtensions(Prec.high(themeExtension));
  53. return cleanupFunction;
  54. }, [codeMirrorEditor, themeExtension]);
  55. const [keymapExtension, setKeymapExtension] = useState<Extension | undefined>(undefined);
  56. useEffect(() => {
  57. const settingKeyMap = async(name?: KeyMapMode) => {
  58. setKeymapExtension(await getKeymap(name, onSave));
  59. };
  60. settingKeyMap(editorSetings?.keymapMode);
  61. }, [codeMirrorEditor, editorSetings?.keymapMode, setKeymapExtension, onSave]);
  62. useEffect(() => {
  63. if (keymapExtension == null) {
  64. return;
  65. }
  66. // Prevent these Keybind from overwriting the originally defined keymap.
  67. const cleanupFunction = codeMirrorEditor?.appendExtensions(Prec.low(keymapExtension));
  68. return cleanupFunction;
  69. }, [codeMirrorEditor, keymapExtension]);
  70. };