Parcourir la source

Merge pull request #6365 from weseek/support/apply-nextjs-to-CommentEditor

support: Apply nextjs to CommentEditor
cao il y a 3 ans
Parent
commit
4af103b98b

+ 1 - 3
packages/app/src/components/PageComment.tsx

@@ -15,7 +15,7 @@ import { useSWRxPageComment } from '../stores/comment';
 
 
 
 
 import Comment from './PageComment/Comment';
 import Comment from './PageComment/Comment';
-import CommentEditor from './PageComment/CommentEditor';
+import { CommentEditor } from './PageComment/CommentEditor';
 import DeleteCommentModal from './PageComment/DeleteCommentModal';
 import DeleteCommentModal from './PageComment/DeleteCommentModal';
 import { ReplayComments } from './PageComment/ReplayComments';
 import { ReplayComments } from './PageComment/ReplayComments';
 
 
@@ -143,7 +143,6 @@ const PageComment:FC<Props> = memo((props:Props):JSX.Element => {
     <ReplayComments
     <ReplayComments
       replyList={replyComments}
       replyList={replyComments}
       deleteBtnClicked={onClickDeleteButton}
       deleteBtnClicked={onClickDeleteButton}
-      rendererOptions={rendererOptions}
       isReadOnly={isReadOnly}
       isReadOnly={isReadOnly}
       onComment={mutate}
       onComment={mutate}
     />
     />
@@ -192,7 +191,6 @@ const PageComment:FC<Props> = memo((props:Props):JSX.Element => {
                     {/* display reply editor */}
                     {/* display reply editor */}
                     {(!isReadOnly && showEditorIds.has(comment._id)) && (
                     {(!isReadOnly && showEditorIds.has(comment._id)) && (
                       <CommentEditor
                       <CommentEditor
-                        rendererOptions={rendererOptions}
                         replyTo={comment._id}
                         replyTo={comment._id}
                         onCancelButtonClicked={() => {
                         onCancelButtonClicked={() => {
                           removeShowEditorId(comment._id);
                           removeShowEditorId(comment._id);

+ 3 - 3
packages/app/src/components/PageComment/Comment.jsx

@@ -2,12 +2,13 @@ import React from 'react';
 
 
 import { UserPicture } from '@growi/ui';
 import { UserPicture } from '@growi/ui';
 import { format } from 'date-fns';
 import { format } from 'date-fns';
-import PropTypes from 'prop-types';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
+import PropTypes from 'prop-types';
 import { UncontrolledTooltip } from 'reactstrap';
 import { UncontrolledTooltip } from 'reactstrap';
 
 
 import AppContainer from '~/client/services/AppContainer';
 import AppContainer from '~/client/services/AppContainer';
 import PageContainer from '~/client/services/PageContainer';
 import PageContainer from '~/client/services/PageContainer';
+import { RendererOptions } from '~/services/renderer/renderer';
 import { useCurrentUser } from '~/stores/context';
 import { useCurrentUser } from '~/stores/context';
 
 
 import FormattedDistanceDate from '../FormattedDistanceDate';
 import FormattedDistanceDate from '../FormattedDistanceDate';
@@ -17,9 +18,8 @@ import { withUnstatedContainers } from '../UnstatedUtils';
 import Username from '../User/Username';
 import Username from '../User/Username';
 
 
 import CommentControl from './CommentControl';
 import CommentControl from './CommentControl';
-import CommentEditor from './CommentEditor';
+import { CommentEditor } from './CommentEditor';
 
 
-import { RendererOptions } from '~/services/renderer/renderer';
 
 
 /**
 /**
  *
  *

+ 30 - 72
packages/app/src/components/PageComment/CommentEditor.tsx

@@ -3,22 +3,17 @@ import React, {
 } from 'react';
 } from 'react';
 
 
 import { UserPicture } from '@growi/ui';
 import { UserPicture } from '@growi/ui';
+import dynamic from 'next/dynamic';
 import {
 import {
-  Button,
-  TabContent, TabPane,
+  Button, TabContent, TabPane,
 } from 'reactstrap';
 } from 'reactstrap';
 import * as toastr from 'toastr';
 import * as toastr from 'toastr';
 
 
-import AppContainer from '~/client/services/AppContainer';
-import EditorContainer from '~/client/services/EditorContainer';
-import PageContainer from '~/client/services/PageContainer';
 import { apiPostForm } from '~/client/util/apiv1-client';
 import { apiPostForm } from '~/client/util/apiv1-client';
-import { CustomWindow } from '~/interfaces/global';
-import { IInterceptorManager } from '~/interfaces/interceptor-manager';
-import { RendererOptions } from '~/services/renderer/renderer';
 import { useSWRxPageComment } from '~/stores/comment';
 import { useSWRxPageComment } from '~/stores/comment';
 import {
 import {
-  useCurrentPagePath, useCurrentPageId, useCurrentUser, useRevisionId,
+  useCurrentPagePath, useCurrentPageId, useCurrentUser, useRevisionId, useIsSlackConfigured,
+  useEditorConfig,
 } from '~/stores/context';
 } from '~/stores/context';
 import { useSWRxSlackChannels, useIsSlackEnabled } from '~/stores/editor';
 import { useSWRxSlackChannels, useIsSlackEnabled } from '~/stores/editor';
 import { useIsMobile } from '~/stores/ui';
 import { useIsMobile } from '~/stores/ui';
@@ -26,12 +21,9 @@ import { useIsMobile } from '~/stores/ui';
 
 
 import { CustomNavTab } from '../CustomNavigation/CustomNav';
 import { CustomNavTab } from '../CustomNavigation/CustomNav';
 import NotAvailableForGuest from '../NotAvailableForGuest';
 import NotAvailableForGuest from '../NotAvailableForGuest';
-import Editor from '../PageEditor/Editor';
 import { SlackNotification } from '../SlackNotification';
 import { SlackNotification } from '../SlackNotification';
-import { withUnstatedContainers } from '../UnstatedUtils';
-
-import CommentPreview from './CommentPreview';
 
 
+import { CommentPreview } from './CommentPreview';
 
 
 const navTabMapping = {
 const navTabMapping = {
   comment_editor: {
   comment_editor: {
@@ -47,14 +39,10 @@ const navTabMapping = {
 };
 };
 
 
 type PropsType = {
 type PropsType = {
-  appContainer: AppContainer,
-
-  rendererOptions: RendererOptions,
   isForNewComment?: boolean,
   isForNewComment?: boolean,
   replyTo?: string,
   replyTo?: string,
   currentCommentId?: string,
   currentCommentId?: string,
   commentBody?: string,
   commentBody?: string,
-  commentCreator?: string,
   onCancelButtonClicked?: () => void,
   onCancelButtonClicked?: () => void,
   onCommentButtonClicked?: () => void,
   onCommentButtonClicked?: () => void,
 }
 }
@@ -65,11 +53,11 @@ type EditorRef = {
   terminateUploadingState: () => void,
   terminateUploadingState: () => void,
 }
 }
 
 
-const CommentEditor = (props: PropsType): JSX.Element => {
+export const CommentEditor = (props: PropsType): JSX.Element => {
 
 
   const {
   const {
-    appContainer, rendererOptions, isForNewComment, replyTo,
-    currentCommentId, commentBody, commentCreator, onCancelButtonClicked, onCommentButtonClicked,
+    isForNewComment, replyTo,
+    currentCommentId, commentBody, onCancelButtonClicked, onCommentButtonClicked,
   } = props;
   } = props;
   const { data: currentUser } = useCurrentUser();
   const { data: currentUser } = useCurrentUser();
   const { data: currentPagePath } = useCurrentPagePath();
   const { data: currentPagePath } = useCurrentPagePath();
@@ -79,57 +67,23 @@ const CommentEditor = (props: PropsType): JSX.Element => {
   const { data: isMobile } = useIsMobile();
   const { data: isMobile } = useIsMobile();
   const { data: isSlackEnabled, mutate: mutateIsSlackEnabled } = useIsSlackEnabled();
   const { data: isSlackEnabled, mutate: mutateIsSlackEnabled } = useIsSlackEnabled();
   const { data: slackChannelsData } = useSWRxSlackChannels(currentPagePath);
   const { data: slackChannelsData } = useSWRxSlackChannels(currentPagePath);
-
-  const config = appContainer.getConfig();
-  const isUploadable = config.upload.image || config.upload.file;
-  const isUploadableFile = config.upload.file;
-  const isSlackConfigured = config.isSlackConfigured;
+  const { data: isSlackConfigured } = useIsSlackConfigured();
+  const { data: editorConfig } = useEditorConfig();
 
 
   const [isReadyToUse, setIsReadyToUse] = useState(!isForNewComment);
   const [isReadyToUse, setIsReadyToUse] = useState(!isForNewComment);
+  // TODO: Refactor comment and markdown variable names or logic after presentation
   const [comment, setComment] = useState(commentBody ?? '');
   const [comment, setComment] = useState(commentBody ?? '');
-  const [html, setHtml] = useState('');
+  const [markdown, setMarkdown] = useState('');
   const [activeTab, setActiveTab] = useState('comment_editor');
   const [activeTab, setActiveTab] = useState('comment_editor');
   const [error, setError] = useState();
   const [error, setError] = useState();
   const [slackChannels, setSlackChannels] = useState(slackChannelsData?.toString());
   const [slackChannels, setSlackChannels] = useState(slackChannelsData?.toString());
 
 
   const editorRef = useRef<EditorRef>(null);
   const editorRef = useRef<EditorRef>(null);
 
 
-  const renderHtml = useCallback((markdown: string) => {
-    const context = {
-      markdown,
-      parsedHTML: '',
-    };
-
-    // TODO: use ReactMarkdown
-
-    // const interceptorManager: IInterceptorManager = (window as CustomWindow).interceptorManager;
-    // interceptorManager.process('preRenderCommnetPreview', context)
-    //   .then(() => { return interceptorManager.process('prePreProcess', context) })
-    //   .then(() => {
-    //     context.markdown = rendererOptions.preProcess(context.markdown, context);
-    //   })
-    //   .then(() => { return interceptorManager.process('postPreProcess', context) })
-    //   .then(() => {
-    //     const parsedHTML = rendererOptions.process(context.markdown, context);
-    //     context.parsedHTML = parsedHTML;
-    //   })
-    //   .then(() => { return interceptorManager.process('prePostProcess', context) })
-    //   .then(() => {
-    //     context.parsedHTML = rendererOptions.postProcess(context.parsedHTML, context);
-    //   })
-    //   .then(() => { return interceptorManager.process('postPostProcess', context) })
-    //   .then(() => { return interceptorManager.process('preRenderCommentPreviewHtml', context) })
-    //   .then(() => {
-    //     setHtml(context.parsedHTML);
-    //   })
-    //   // process interceptors for post rendering
-    //   .then(() => { return interceptorManager.process('postRenderCommentPreviewHtml', context) });
-  }, [rendererOptions]);
-
   const handleSelect = useCallback((activeTab: string) => {
   const handleSelect = useCallback((activeTab: string) => {
     setActiveTab(activeTab);
     setActiveTab(activeTab);
-    renderHtml(comment);
-  }, [comment, renderHtml]);
+    setMarkdown(comment);
+  }, [comment, setMarkdown]);
 
 
   useEffect(() => {
   useEffect(() => {
     if (slackChannels === undefined) { return }
     if (slackChannels === undefined) { return }
@@ -138,7 +92,7 @@ const CommentEditor = (props: PropsType): JSX.Element => {
 
 
   const initializeEditor = useCallback(() => {
   const initializeEditor = useCallback(() => {
     setComment('');
     setComment('');
-    setHtml('');
+    setMarkdown('');
     setActiveTab('comment_editor');
     setActiveTab('comment_editor');
     setError(undefined);
     setError(undefined);
     // reset value
     // reset value
@@ -247,13 +201,19 @@ const CommentEditor = (props: PropsType): JSX.Element => {
     }
     }
   }, [apiErrorHandler, currentPageId, currentPagePath]);
   }, [apiErrorHandler, currentPageId, currentPagePath]);
 
 
+
   const getCommentHtml = useCallback(() => {
   const getCommentHtml = useCallback(() => {
+    if (currentPagePath == null) {
+      return <></>;
+    }
+
     return (
     return (
       <CommentPreview
       <CommentPreview
-        html={html}
+        markdown={markdown}
+        path={currentPagePath}
       />
       />
     );
     );
-  }, [html]);
+  }, [currentPagePath, markdown]);
 
 
   const renderBeforeReady = useCallback((): JSX.Element => {
   const renderBeforeReady = useCallback((): JSX.Element => {
     return (
     return (
@@ -292,9 +252,16 @@ const CommentEditor = (props: PropsType): JSX.Element => {
       </Button>
       </Button>
     );
     );
 
 
+    const Editor = dynamic(() => import('../PageEditor/Editor'), { ssr: false });
     // TODO: typescriptize Editor
     // TODO: typescriptize Editor
     const AnyEditor = Editor as any;
     const AnyEditor = Editor as any;
 
 
+    if (editorConfig === undefined) {
+      return <></>;
+    }
+    const isUploadable = editorConfig.upload.image || editorConfig.upload.file;
+    const isUploadableFile = editorConfig.upload.file;
+
     return (
     return (
       <>
       <>
         <div className="comment-write">
         <div className="comment-write">
@@ -376,12 +343,3 @@ const CommentEditor = (props: PropsType): JSX.Element => {
   );
   );
 
 
 };
 };
-
-/**
- * Wrapper component for using unstated
- */
-const CommentEditorWrapper = withUnstatedContainers<unknown, Partial<PropsType>>(
-  CommentEditor, [AppContainer, PageContainer, EditorContainer],
-);
-
-export default CommentEditorWrapper;

+ 1 - 14
packages/app/src/components/PageComment/CommentEditorLazyRenderer.tsx

@@ -2,13 +2,9 @@ import React, { FC } from 'react';
 
 
 import { useSWRxPageComment } from '../../stores/comment';
 import { useSWRxPageComment } from '../../stores/comment';
 
 
-import AppContainer from '~/client/services/AppContainer';
-
-import CommentEditor from './CommentEditor';
-import { useCommentPreviewOptions } from '~/stores/renderer';
+import { CommentEditor } from './CommentEditor';
 
 
 type Props = {
 type Props = {
-  appContainer: AppContainer,
   pageId: string,
   pageId: string,
 }
 }
 
 
@@ -16,18 +12,9 @@ const CommentEditorLazyRenderer:FC<Props> = (props:Props):JSX.Element => {
 
 
   const { pageId } = props;
   const { pageId } = props;
   const { mutate } = useSWRxPageComment(pageId);
   const { mutate } = useSWRxPageComment(pageId);
-  const { data: rendererOptions } = useCommentPreviewOptions();
-
-  if (rendererOptions == null) {
-    return <></>;
-  }
-
-  const { appContainer } = props;
 
 
   return (
   return (
     <CommentEditor
     <CommentEditor
-      appContainer={appContainer}
-      rendererOptions={rendererOptions}
       replyTo={undefined}
       replyTo={undefined}
       onCommentButtonClicked={mutate}
       onCommentButtonClicked={mutate}
       isForNewComment
       isForNewComment

+ 0 - 29
packages/app/src/components/PageComment/CommentPreview.jsx

@@ -1,29 +0,0 @@
-import React from 'react';
-
-import PropTypes from 'prop-types';
-
-import RevisionBody from '../Page/RevisionBody';
-
-/**
- * Wrapper component for Page/RevisionBody
- */
-const CommentPreview = (props) => {
-
-  return (
-    <div className="page-comment-preview-body">
-      <RevisionBody
-        html={props.html}
-        additionalClassName="comment"
-        isMathJaxEnabled
-        renderMathJaxInRealtime
-      />
-    </div>
-  );
-
-};
-
-CommentPreview.propTypes = {
-  html: PropTypes.string,
-};
-
-export default CommentPreview;

+ 30 - 0
packages/app/src/components/PageComment/CommentPreview.tsx

@@ -0,0 +1,30 @@
+import { useCommentPreviewOptions } from '~/stores/renderer';
+
+import RevisionRenderer from '../Page/RevisionRenderer';
+
+type CommentPreviewPorps = {
+  markdown: string,
+  path: string,
+}
+
+export const CommentPreview = (props: CommentPreviewPorps): JSX.Element => {
+  const { markdown, path } = props;
+
+  const { data: commentPreviewOptions } = useCommentPreviewOptions();
+
+  if (commentPreviewOptions == null) {
+    return <></>;
+  }
+
+  return (
+    <div className="page-comment-preview-body">
+      <RevisionRenderer
+        rendererOptions={commentPreviewOptions}
+        markdown={markdown}
+        additionalClassName="comment"
+        pagePath={path}
+      />
+    </div>
+  );
+
+};

+ 1 - 5
packages/app/src/components/PageComment/ReplayComments.tsx

@@ -3,8 +3,6 @@ import React, { useState } from 'react';
 
 
 import { Collapse } from 'reactstrap';
 import { Collapse } from 'reactstrap';
 
 
-import { RendererOptions } from '~/services/renderer/renderer';
-
 import { ICommentHasId, ICommentHasIdList } from '../../interfaces/comment';
 import { ICommentHasId, ICommentHasIdList } from '../../interfaces/comment';
 import { useRendererConfig, useIsAllReplyShown } from '../../stores/context';
 import { useRendererConfig, useIsAllReplyShown } from '../../stores/context';
 
 
@@ -12,7 +10,6 @@ import Comment from './Comment';
 
 
 type ReplaycommentsProps = {
 type ReplaycommentsProps = {
   deleteBtnClicked: (comment: ICommentHasId) => void,
   deleteBtnClicked: (comment: ICommentHasId) => void,
-  rendererOptions: RendererOptions,
   isReadOnly: boolean,
   isReadOnly: boolean,
   replyList: ICommentHasIdList,
   replyList: ICommentHasIdList,
   onComment: () => void,
   onComment: () => void,
@@ -20,7 +17,7 @@ type ReplaycommentsProps = {
 
 
 export const ReplayComments = (props: ReplaycommentsProps): JSX.Element => {
 export const ReplayComments = (props: ReplaycommentsProps): JSX.Element => {
   const {
   const {
-    deleteBtnClicked, rendererOptions, isReadOnly, replyList, onComment,
+    deleteBtnClicked, isReadOnly, replyList, onComment,
   } = props;
   } = props;
   const { data: rendererConfig } = useRendererConfig();
   const { data: rendererConfig } = useRendererConfig();
   const { data: isAllReplyShown } = useIsAllReplyShown();
   const { data: isAllReplyShown } = useIsAllReplyShown();
@@ -34,7 +31,6 @@ export const ReplayComments = (props: ReplaycommentsProps): JSX.Element => {
         <Comment
         <Comment
           comment={reply}
           comment={reply}
           deleteBtnClicked={deleteBtnClicked}
           deleteBtnClicked={deleteBtnClicked}
-          rendererOptions={rendererOptions}
           isReadOnly={isReadOnly}
           isReadOnly={isReadOnly}
           onComment={onComment}
           onComment={onComment}
         />
         />

+ 7 - 0
packages/app/src/interfaces/editor-settings.ts

@@ -29,3 +29,10 @@ export interface IEditorSettings {
   autoFormatMarkdownTable: boolean,
   autoFormatMarkdownTable: boolean,
   textlintSettings: undefined | ITextlintSettings;
   textlintSettings: undefined | ITextlintSettings;
 }
 }
+
+export type EditorConfig = {
+  upload: {
+    image: boolean,
+    file: boolean,
+  }
+}

+ 11 - 9
packages/app/src/pages/[[...path]].page.tsx

@@ -26,6 +26,7 @@ import { CrowiRequest } from '~/interfaces/crowi-request';
 // import { useIndentSize } from '~/stores/editor';
 // import { useIndentSize } from '~/stores/editor';
 // import { useRendererSettings } from '~/stores/renderer';
 // import { useRendererSettings } from '~/stores/renderer';
 // import { EditorMode, useEditorMode, useIsMobile } from '~/stores/ui';
 // import { EditorMode, useEditorMode, useIsMobile } from '~/stores/ui';
+import { EditorConfig } from '~/interfaces/editor-settings';
 import { CustomWindow } from '~/interfaces/global';
 import { CustomWindow } from '~/interfaces/global';
 import { RendererConfig } from '~/interfaces/services/renderer';
 import { RendererConfig } from '~/interfaces/services/renderer';
 import { ISidebarConfig } from '~/interfaces/sidebar-config';
 import { ISidebarConfig } from '~/interfaces/sidebar-config';
@@ -40,6 +41,7 @@ import {
 } from '~/stores/ui';
 } from '~/stores/ui';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';
 
 
+
 // import { isUserPage, isTrashPage, isSharedPage } from '~/utils/path-utils';
 // import { isUserPage, isTrashPage, isSharedPage } from '~/utils/path-utils';
 
 
 // import GrowiSubNavigation from '../client/js/components/Navbar/GrowiSubNavigation';
 // import GrowiSubNavigation from '../client/js/components/Navbar/GrowiSubNavigation';
@@ -64,7 +66,7 @@ import {
   useIsAclEnabled, useIsUserPage, useIsNotCreatable,
   useIsAclEnabled, useIsUserPage, useIsNotCreatable,
   useCsrfToken, useIsSearchScopeChildrenAsDefault, useCurrentPageId, useCurrentPathname,
   useCsrfToken, useIsSearchScopeChildrenAsDefault, useCurrentPageId, useCurrentPathname,
   useIsSlackConfigured, useIsBlinkedHeaderAtBoot, useRendererConfig, useEditingMarkdown,
   useIsSlackConfigured, useIsBlinkedHeaderAtBoot, useRendererConfig, useEditingMarkdown,
-  useIsAllReplyShown,
+  useEditorConfig, useIsAllReplyShown,
 } from '../stores/context';
 } from '../stores/context';
 import { useXss } from '../stores/xss';
 import { useXss } from '../stores/xss';
 
 
@@ -151,7 +153,7 @@ type Props = CommonProps & {
   // highlightJsStyle: string,
   // highlightJsStyle: string,
   isAllReplyShown: boolean,
   isAllReplyShown: boolean,
   // isContainerFluid: boolean,
   // isContainerFluid: boolean,
-  // editorConfig: any,
+  editorConfig: EditorConfig,
   isEnabledStaleNotification: boolean,
   isEnabledStaleNotification: boolean,
   // isEnabledLinebreaks: boolean,
   // isEnabledLinebreaks: boolean,
   // isEnabledLinebreaksInComments: boolean,
   // isEnabledLinebreaksInComments: boolean,
@@ -183,7 +185,7 @@ const GrowiPage: NextPage<Props> = (props: Props) => {
 
 
   // commons
   // commons
   useXss(new Xss());
   useXss(new Xss());
-  // useEditorConfig(props.editorConfig);
+  useEditorConfig(props.editorConfig);
   useCsrfToken(props.csrfToken);
   useCsrfToken(props.csrfToken);
 
 
   // UserUISettings
   // UserUISettings
@@ -487,12 +489,12 @@ function injectServerConfigurations(context: GetServerSidePropsContext, props: P
   // props.isEnabledLinebreaks = configManager.getConfig('markdown', 'markdown:isEnabledLinebreaks');
   // props.isEnabledLinebreaks = configManager.getConfig('markdown', 'markdown:isEnabledLinebreaks');
   // props.isEnabledLinebreaksInComments = configManager.getConfig('markdown', 'markdown:isEnabledLinebreaksInComments');
   // props.isEnabledLinebreaksInComments = configManager.getConfig('markdown', 'markdown:isEnabledLinebreaksInComments');
   props.disableLinkSharing = configManager.getConfig('crowi', 'security:disableLinkSharing');
   props.disableLinkSharing = configManager.getConfig('crowi', 'security:disableLinkSharing');
-  // props.editorConfig = {
-  //   upload: {
-  //     image: crowi.fileUploadService.getIsUploadable(),
-  //     file: crowi.fileUploadService.getFileUploadEnabled(),
-  //   },
-  // };
+  props.editorConfig = {
+    upload: {
+      image: crowi.fileUploadService.getIsUploadable(),
+      file: crowi.fileUploadService.getFileUploadEnabled(),
+    },
+  };
   // props.adminPreferredIndentSize = configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize');
   // props.adminPreferredIndentSize = configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize');
   // props.isIndentSizeForced = configManager.getConfig('markdown', 'markdown:isIndentSizeForced');
   // props.isIndentSizeForced = configManager.getConfig('markdown', 'markdown:isIndentSizeForced');
 
 

+ 5 - 0
packages/app/src/stores/context.tsx

@@ -6,6 +6,7 @@ import useSWRImmutable from 'swr/immutable';
 
 
 
 
 import { SupportedActionType } from '~/interfaces/activity';
 import { SupportedActionType } from '~/interfaces/activity';
+import { EditorConfig } from '~/interfaces/editor-settings';
 // import { CustomWindow } from '~/interfaces/global';
 // import { CustomWindow } from '~/interfaces/global';
 import { RendererConfig } from '~/interfaces/services/renderer';
 import { RendererConfig } from '~/interfaces/services/renderer';
 import { GrowiThemes } from '~/interfaces/theme';
 import { GrowiThemes } from '~/interfaces/theme';
@@ -224,6 +225,10 @@ export const useIsLatestRevision = (initialData?: boolean): SWRResponse<boolean,
   return useStaticSWR('isLatestRevision', initialData);
   return useStaticSWR('isLatestRevision', initialData);
 };
 };
 
 
+export const useEditorConfig = (initialData?: EditorConfig): SWRResponse<EditorConfig, Error> => {
+  return useStaticSWR<EditorConfig, Error>('editorConfig', initialData);
+};
+
 export const useRendererConfig = (initialData?: RendererConfig): SWRResponse<RendererConfig, any> => {
 export const useRendererConfig = (initialData?: RendererConfig): SWRResponse<RendererConfig, any> => {
   return useStaticSWR('growiRendererConfig', initialData);
   return useStaticSWR('growiRendererConfig', initialData);
 };
 };