codemirror-editor.ts 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. import { useMemo, useRef } from 'react';
  2. import { type Extension } from '@codemirror/state';
  3. import { scrollPastEnd } from '@codemirror/view';
  4. import { useSWRStatic } from '@growi/core/dist/swr';
  5. import type { ReactCodeMirrorProps, UseCodeMirror } from '@uiw/react-codemirror';
  6. import type { SWRResponse } from 'swr';
  7. import deepmerge from 'ts-deepmerge';
  8. import type { UseCodeMirrorEditor } from '../services';
  9. import { useCodeMirrorEditor } from '../services';
  10. const isValid = (u: UseCodeMirrorEditor) => {
  11. return u.state != null && u.view != null;
  12. };
  13. const isDeepEquals = <T extends object>(obj1: T, obj2: T): boolean => {
  14. const typedKeys = Object.keys(obj1) as (keyof typeof obj1)[];
  15. return typedKeys.every(key => obj1[key] === obj2[key]);
  16. };
  17. const defaultExtensionsMain: Extension[] = [
  18. scrollPastEnd(),
  19. ];
  20. export const useCodeMirrorEditorIsolated = (
  21. key?: string, container?: HTMLDivElement | null, props?: ReactCodeMirrorProps,
  22. ): SWRResponse<UseCodeMirrorEditor> => {
  23. const ref = useRef<UseCodeMirrorEditor>();
  24. const currentData = ref.current;
  25. const swrKey = key != null ? `codeMirrorEditor_${key}` : null;
  26. const mergedProps = useMemo<UseCodeMirror>(() => {
  27. return deepmerge(
  28. props ?? {},
  29. {
  30. container,
  31. extensions: defaultExtensionsMain,
  32. },
  33. );
  34. }, [container, props]);
  35. const newData = useCodeMirrorEditor(mergedProps);
  36. const shouldUpdate = swrKey != null && container != null && props != null && (
  37. currentData == null
  38. || (isValid(newData) && !isDeepEquals(currentData, newData))
  39. );
  40. if (shouldUpdate) {
  41. ref.current = newData;
  42. // eslint-disable-next-line no-console
  43. console.info('Initializing codemirror for main');
  44. }
  45. return useSWRStatic(swrKey, shouldUpdate ? newData : undefined);
  46. };