| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101 |
- import React, {
- useCallback, useRef, MutableRefObject,
- } from 'react';
- import codemirror, { commands, Editor } from 'codemirror';
- import { type ICodeMirror, UnControlled as CodeMirror } from 'react-codemirror2';
- declare global {
- // eslint-disable-next-line vars-on-top, no-var
- var CodeMirror: ICodeMirror;
- }
- // set save handler
- // CommandActions in @types/codemirror does not include 'save' but actualy exists
- // https://codemirror.net/5/doc/manual.html#commands
- (commands as any).save = (instance) => {
- if (instance.codeMirrorEditor != null) {
- instance.codeMirrorEditor.dispatchSave();
- }
- };
- window.CodeMirror = codemirror;
- require('codemirror/addon/display/placeholder');
- require('~/client/util/codemirror/gfm-growi.mode');
- export interface UncontrolledCodeMirrorProps extends ICodeMirror {
- value: string;
- isGfmMode?: boolean;
- lineNumbers?: boolean;
- onSave?: () => Promise<void>;
- onCtrlEnter?: (event: Event) => void;
- onPasteFiles?: (editor: any, event: Event) => void;
- onScrollCursorIntoView?: (editor: any, event: Event) => void;
- }
- export const UncontrolledCodeMirror = React.forwardRef<CodeMirror|null, UncontrolledCodeMirrorProps>((props, forwardedRef): JSX.Element => {
- const {
- value, lineNumbers, options,
- onPasteFiles, onScrollCursorIntoView,
- ...rest
- } = props;
- const editorRef = useRef<Editor>();
- const wrapperRef = useRef<CodeMirror|null>();
- const editorDidMountHandler = useCallback((editor: Editor): void => {
- editorRef.current = editor;
- if (onPasteFiles != null) {
- editor.on('paste', onPasteFiles);
- }
- if (onScrollCursorIntoView != null) {
- editor.on('scrollCursorIntoView', onScrollCursorIntoView);
- }
- }, [onPasteFiles, onScrollCursorIntoView]);
- const editorWillUnmountHandler = useCallback((): void => {
- // workaround to fix editor duplicating by https://github.com/scniro/react-codemirror2/issues/284#issuecomment-1155928554
- if (editorRef.current != null) {
- (editorRef.current as any).display.wrapper.remove();
- }
- if (wrapperRef.current != null) {
- (wrapperRef.current as any).hydrated = false;
- }
- }, []);
- // default true
- const isGfmMode = rest.isGfmMode ?? true;
- return (
- <CodeMirror
- ref={(elem) => {
- // register to wrapperRef
- wrapperRef.current = elem;
- // register to forwardedRef
- if (forwardedRef != null) {
- if (typeof forwardedRef === 'function') {
- forwardedRef(elem);
- }
- else {
- (forwardedRef as MutableRefObject<CodeMirror|null>).current = elem;
- }
- }
- }}
- value={value}
- options={{
- lineNumbers: lineNumbers ?? true,
- mode: isGfmMode ? 'gfm-growi' : undefined,
- tabSize: 4,
- ...options,
- }}
- editorDidMount={editorDidMountHandler}
- editorWillUnmount={editorWillUnmountHandler}
- {...rest}
- />
- );
- });
- UncontrolledCodeMirror.displayName = 'UncontrolledCodeMirror';
|