Răsfoiți Sursa

Merge branch 'master' into feat/112904-120355-enable-attachment-refs

Futa Arai 3 ani în urmă
părinte
comite
4e3af3c209
29 a modificat fișierele cu 210 adăugiri și 228 ștergeri
  1. 9 0
      .github/workflows/cache-clear.yml
  2. 7 1
      .github/workflows/reusable-app-prod.yml
  3. 0 3
      apps/app/jest.config.js
  4. 1 2
      apps/app/package.json
  5. 0 1
      apps/app/src/client/services/renderer/renderer.tsx
  6. 11 3
      apps/app/src/components/PageEditor.tsx
  7. 8 8
      apps/app/src/components/PageEditor/DrawioModal.tsx
  8. 24 3
      apps/app/src/components/PageEditorByHackmd.tsx
  9. 14 2
      apps/app/src/components/SavePageControls.tsx
  10. 14 8
      apps/app/src/components/Script/DrawioViewerScript.tsx
  11. 2 2
      apps/app/src/interfaces/services/renderer.ts
  12. 3 4
      apps/app/src/pages/[[...path]].page.tsx
  13. 3 9
      apps/app/src/pages/_private-legacy-pages.page.tsx
  14. 3 9
      apps/app/src/pages/_search.page.tsx
  15. 2 2
      apps/app/src/pages/me/[[...path]].page.tsx
  16. 3 4
      apps/app/src/pages/share/[[...path]].page.tsx
  17. 1 19
      apps/app/src/pages/tags.page.tsx
  18. 1 19
      apps/app/src/pages/trash.page.tsx
  19. 7 7
      apps/app/src/server/service/config-loader.ts
  20. 0 18
      apps/app/src/services/renderer/markdown-it/blockdiag.ts
  21. 2 2
      apps/app/src/services/renderer/remark-plugins/plantuml.ts
  22. 0 1
      apps/app/src/services/renderer/renderer.tsx
  23. 0 4
      apps/app/src/stores/context.tsx
  24. 5 0
      apps/app/src/stores/editor.tsx
  25. 13 6
      apps/app/test/cypress/integration/20-basic-features/20-basic-features--use-tools.spec.ts
  26. 1 1
      packages/presentation/package.json
  27. 1 1
      packages/remark-lsx/package.json
  28. 0 3
      packages/remark-lsx/src/server/routes/lsx.ts
  29. 75 86
      yarn.lock

+ 9 - 0
.github/workflows/cache-clear.yml

@@ -0,0 +1,9 @@
+name: Cache Clear
+
+on: workflow_dispatch
+
+jobs:
+  clear:
+    runs-on: ubuntu-latest
+    steps:
+      - uses: snnaplab/delete-branch-cache-action@v1

+ 7 - 1
.github/workflows/reusable-app-prod.yml

@@ -272,6 +272,11 @@ jobs:
         restore-keys: |
           deps-for-cypress-${{ runner.OS }}-node${{ inputs.node-version }}-
 
+    - name: Install dependencies
+      run: |
+        yarn --frozen-lockfile
+        yarn cypress install
+
     - name: Download production files artifact
       uses: actions/download-artifact@v3
       with:
@@ -305,11 +310,12 @@ jobs:
         cat config/ci/.env.local.for-auto-install-with-allowing-guest >> .env.production.local
 
     - name: Cypress Run
-      uses: cypress-io/github-action@v3
+      uses: cypress-io/github-action@v5
       with:
         browser: chrome
         working-directory: ./apps/app
         spec: '${{ steps.determine-spec-exp.outputs.value }}'
+        install: false
         start: yarn server
         wait-on: 'http://localhost:3000'
         config: video=${{ inputs.cypress-config-video }}

+ 0 - 3
apps/app/jest.config.js

@@ -4,9 +4,6 @@
 const MODULE_NAME_MAPPING = {
   '^\\^/(.+)$': '<rootDir>/$1',
   '^~/(.+)$': '<rootDir>/src/$1',
-  '^@growi/codemirror-textlint$': '<rootDir>/../../packages/codemirror-textlint/src',
-  '^@growi/remark-drawio$': '<rootDir>/../../packages/remark-drawio/src',
-  '^@growi/remark-growi-directive$': '<rootDir>/../../packages/remark-growi-directive/src',
 };
 
 module.exports = {

+ 1 - 2
apps/app/package.json

@@ -47,7 +47,6 @@
   },
   "// comments for dependencies": {
     "escape-string-regexp": "5.0.0 or above exports only ESM",
-    "next": ">=13.1.2 with Node v14 have the problem => https://github.com/vercel/next.js/issues/45052",
     "string-width": "5.0.0 or above exports only ESM.",
     "prom-client": "!!DO NOT REMOVE!! A peer dependency of @promster.",
     "remark-wiki-link": "!!DO NOT REMOVE!! including 'mdast-util-wiki-link' and 'micromark-extension-wiki-link' required by pukiwiki-like-linker"
@@ -131,7 +130,7 @@
     "mongoose-unique-validator": "^2.0.3",
     "multer": "~1.4.0",
     "multer-autoreap": "^1.0.3",
-    "next": "=13.1.1",
+    "next": "^13.3.0",
     "next-i18next": "^13.2.1",
     "next-superjson": "^0.0.4",
     "next-themes": "^0.2.1",

+ 0 - 1
apps/app/src/client/services/renderer/renderer.tsx

@@ -31,7 +31,6 @@ import {
 import loggerFactory from '~/utils/logger';
 
 // import EasyGrid from './PreProcessor/EasyGrid';
-// import BlockdiagConfigurer from './markdown-it/blockdiag';
 
 import '@growi/remark-lsx/dist/client/style.css';
 

+ 11 - 3
apps/app/src/components/PageEditor.tsx

@@ -29,6 +29,7 @@ import {
   useIsEnabledUnsavedWarning,
   useIsConflict,
   useEditingMarkdown,
+  useWaitingSaveProcessing,
 } from '~/stores/editor';
 import { useConflictDiffModal } from '~/stores/modal';
 import {
@@ -76,7 +77,7 @@ const PageEditor = React.memo((): JSX.Element => {
   const { t } = useTranslation();
   const router = useRouter();
 
-  const { data: isNotFound, mutate: mutateIsNotFound } = useIsNotFound();
+  const { data: isNotFound } = useIsNotFound();
   const { data: pageId, mutate: mutateCurrentPageId } = useCurrentPageId();
   const { data: currentPagePath } = useCurrentPagePath();
   const { data: currentPathname } = useCurrentPathname();
@@ -89,6 +90,7 @@ const PageEditor = React.memo((): JSX.Element => {
   const { data: isEnabledAttachTitleHeader } = useIsEnabledAttachTitleHeader();
   const { data: templateBodyData } = useTemplateBodyData();
   const { data: isEditable } = useIsEditable();
+  const { mutate: mutateWaitingSaveProcessing } = useWaitingSaveProcessing();
   const { data: editorMode, mutate: mutateEditorMode } = useEditorMode();
   const { data: isSlackEnabled } = useIsSlackEnabled();
   const { data: isTextlintEnabled } = useIsTextlintEnabled();
@@ -201,6 +203,8 @@ const PageEditor = React.memo((): JSX.Element => {
     const options = Object.assign(optionsToSave, opts);
 
     try {
+      mutateWaitingSaveProcessing(true);
+
       const { page } = await saveOrUpdate(
         markdownToSave.current,
         { pageId, path: currentPagePath || currentPathname, revisionId: currentRevisionId },
@@ -223,10 +227,14 @@ const PageEditor = React.memo((): JSX.Element => {
       }
       return null;
     }
+    finally {
+      mutateWaitingSaveProcessing(false);
+    }
 
   }, [
     currentPathname, optionsToSave, grantData, isSlackEnabled, saveOrUpdate, pageId,
-    currentPagePath, currentRevisionId, mutateRemotePageId, mutateRemoteRevisionId, mutateRemoteRevisionLastUpdatedAt, mutateRemoteRevisionLastUpdateUser,
+    currentPagePath, currentRevisionId,
+    mutateWaitingSaveProcessing, mutateRemotePageId, mutateRemoteRevisionId, mutateRemoteRevisionLastUpdatedAt, mutateRemoteRevisionLastUpdateUser,
   ]);
 
   const saveAndReturnToViewHandler = useCallback(async(opts: {slackChannels: string, overwriteScopesOfDescendants?: boolean}) => {
@@ -331,7 +339,7 @@ const PageEditor = React.memo((): JSX.Element => {
     finally {
       editorRef.current.terminateUploadingState();
     }
-  }, [currentPagePath, mutateCurrentPage, mutateCurrentPageId, mutateGrant, mutateIsLatestRevision, mutateIsNotFound, pageId]);
+  }, [currentPagePath, mutateCurrentPage, mutateCurrentPageId, mutateGrant, mutateIsLatestRevision, pageId]);
 
 
   const scrollPreviewByEditorLine = useCallback((line: number) => {

+ 8 - 8
apps/app/src/components/PageEditor/DrawioModal.tsx

@@ -10,7 +10,7 @@ import {
 } from 'reactstrap';
 
 import { getDiagramsNetLangCode } from '~/client/util/locale-utils';
-import { useDrawioUri } from '~/stores/context';
+import { useRendererConfig } from '~/stores/context';
 import { useDrawioModal } from '~/stores/modal';
 import { usePersonalSettings } from '~/stores/personal-settings';
 import loggerFactory from '~/utils/logger';
@@ -38,7 +38,7 @@ const drawioConfig: DrawioConfig = {
 
 
 export const DrawioModal = (): JSX.Element => {
-  const { data: drawioUri } = useDrawioUri();
+  const { data: rendererConfig } = useRendererConfig();
   const { data: personalSettingsInfo } = usePersonalSettings({
     // make immutable
     revalidateIfStale: false,
@@ -50,13 +50,13 @@ export const DrawioModal = (): JSX.Element => {
   const isOpened = drawioModalData?.isOpened ?? false;
 
   const drawioUriWithParams = useMemo(() => {
-    if (drawioUri == null) {
+    if (rendererConfig == null) {
       return undefined;
     }
 
     let url;
     try {
-      url = new URL(drawioUri);
+      url = new URL(rendererConfig.drawioUri);
     }
     catch (err) {
       logger.debug(err);
@@ -71,19 +71,19 @@ export const DrawioModal = (): JSX.Element => {
     url.searchParams.append('configure', '1');
 
     return url;
-  }, [drawioUri, personalSettingsInfo?.lang]);
+  }, [rendererConfig, personalSettingsInfo?.lang]);
 
   const drawioCommunicationHelper = useMemo(() => {
-    if (drawioUri == null) {
+    if (rendererConfig == null) {
       return undefined;
     }
 
     return new DrawioCommunicationHelper(
-      drawioUri,
+      rendererConfig.drawioUri,
       drawioConfig,
       { onClose: closeDrawioModal, onSave: drawioModalData?.onSave },
     );
-  }, [closeDrawioModal, drawioModalData?.onSave, drawioUri]);
+  }, [closeDrawioModal, drawioModalData?.onSave, rendererConfig]);
 
   const receiveMessageHandler = useCallback((event: MessageEvent) => {
     if (drawioModalData == null) {

+ 24 - 3
apps/app/src/components/PageEditorByHackmd.tsx

@@ -19,7 +19,7 @@ import {
   useCurrentPathname, useHackmdUri,
 } from '~/stores/context';
 import {
-  useIsSlackEnabled, usePageTagsForEditors, useIsEnabledUnsavedWarning,
+  useIsSlackEnabled, usePageTagsForEditors, useIsEnabledUnsavedWarning, useWaitingSaveProcessing,
 } from '~/stores/editor';
 import {
   usePageIdOnHackmd, useHasDraftOnHackmd, useRevisionIdHackmdSynced, useIsHackmdDraftUpdatingInRealtime,
@@ -56,6 +56,7 @@ export const PageEditorByHackmd = (): JSX.Element => {
   const router = useRouter();
 
   const { data: isNotFound } = useIsNotFound();
+  const { mutate: mutateWaitingSaveProcessing } = useWaitingSaveProcessing();
   const { data: editorMode, mutate: mutateEditorMode } = useEditorMode();
   const { data: currentPagePath } = useCurrentPagePath();
   const { data: currentPathname } = useCurrentPathname();
@@ -116,6 +117,8 @@ export const PageEditorByHackmd = (): JSX.Element => {
         throw new Error('Some materials to save are invalid');
       }
 
+      mutateWaitingSaveProcessing(true);
+
       const options = Object.assign(optionsToSave, opts, { isSyncRevisionToHackmd: true });
 
       const markdown = await hackmdEditorRef.current.getValue();
@@ -142,8 +145,16 @@ export const PageEditorByHackmd = (): JSX.Element => {
       logger.error('failed to save', error);
       toastError(error.message);
     }
+    finally {
+      mutateWaitingSaveProcessing(false);
+    }
+
   // eslint-disable-next-line max-len
-  }, [editorMode, currentPathname, revision, revisionIdHackmdSynced, optionsToSave, saveOrUpdate, pageId, currentPagePath, isNotFound, mutateEditorMode, router, updateStateAfterSave, mutateIsHackmdDraftUpdatingInRealtime]);
+  }, [
+    pageId, currentPagePath, isNotFound, router,
+    editorMode, currentPathname, revision, revisionIdHackmdSynced, optionsToSave,
+    saveOrUpdate, mutateEditorMode, updateStateAfterSave, mutateIsHackmdDraftUpdatingInRealtime, mutateWaitingSaveProcessing,
+  ]);
 
   // set handler to save and reload Page
   useEffect(() => {
@@ -249,6 +260,8 @@ export const PageEditorByHackmd = (): JSX.Element => {
    */
   const onSaveWithShortcut = useCallback(async(markdown) => {
     try {
+      mutateWaitingSaveProcessing(true);
+
       const currentPagePathOrPathname = currentPagePath || currentPathname;
       if (
         pageId == null || revisionIdHackmdSynced == null || currentPagePathOrPathname == null || optionsToSave == null
@@ -278,8 +291,16 @@ export const PageEditorByHackmd = (): JSX.Element => {
       logger.error('failed to save', error);
       toastError(error.message);
     }
+    finally {
+      mutateWaitingSaveProcessing(false);
+    }
+
   // eslint-disable-next-line max-len
-  }, [currentPagePath, currentPathname, pageId, revisionIdHackmdSynced, optionsToSave, saveOrUpdate, mutatePageData, updateStateAfterSave, mutateTagsInfo, mutateIsEnabledUnsavedWarning, t]);
+  }, [
+    currentPagePath, currentPathname, pageId, revisionIdHackmdSynced, optionsToSave,
+    saveOrUpdate,
+    mutateWaitingSaveProcessing, mutatePageData, updateStateAfterSave, mutateTagsInfo, mutateIsEnabledUnsavedWarning, t,
+  ]);
 
   /**
    * onChange event of HackmdEditor handler

+ 14 - 2
apps/app/src/components/SavePageControls.tsx

@@ -13,6 +13,7 @@ import { IPageGrantData } from '~/interfaces/page';
 import {
   useIsEditable, useIsAclEnabled,
 } from '~/stores/context';
+import { useWaitingSaveProcessing } from '~/stores/editor';
 import { useCurrentPagePath, useCurrentPageId } from '~/stores/page';
 import { useSelectedGrant } from '~/stores/ui';
 import loggerFactory from '~/utils/logger';
@@ -42,7 +43,9 @@ export const SavePageControls = (props: SavePageControlsProps): JSX.Element | nu
   const { data: isAclEnabled } = useIsAclEnabled();
   const { data: grantData, mutate: mutateGrant } = useSelectedGrant();
   const { data: pageId } = useCurrentPageId();
+  const { data: _isWaitingSaveProcessing } = useWaitingSaveProcessing();
 
+  const isWaitingSaveProcessing = _isWaitingSaveProcessing === true; // ignore undefined
 
   const updateGrantHandler = useCallback((grantData: IPageGrantData): void => {
     mutateGrant(grantData);
@@ -91,10 +94,19 @@ export const SavePageControls = (props: SavePageControlsProps): JSX.Element | nu
       }
 
       <UncontrolledButtonDropdown direction="up">
-        <Button data-testid="save-page-btn" id="caret" color="primary" className="btn-submit" onClick={save}>
+        <Button
+          id="caret" data-testid="save-page-btn"
+          color="primary"
+          className="btn-submit"
+          onClick={save}
+          disabled={isWaitingSaveProcessing}
+        >
+          { isWaitingSaveProcessing && (
+            <i className="fa fa-spinner fa-pulse mr-1"></i>
+          ) }
           {labelSubmitButton}
         </Button>
-        <DropdownToggle caret color="primary" />
+        <DropdownToggle caret color="primary" disabled={isWaitingSaveProcessing} />
         <DropdownMenu right>
           <DropdownItem onClick={saveAndOverwriteScopesOfDescendants}>
             {labelOverwriteScopes}

+ 14 - 8
apps/app/src/components/Script/DrawioViewerScript.tsx

@@ -1,9 +1,9 @@
 import { useCallback } from 'react';
 
 import type { IGraphViewerGlobal } from '@growi/remark-drawio';
-import Script from 'next/script';
+import Head from 'next/head';
 
-import { useDrawioUri } from '~/stores/context';
+import { useRendererConfig } from '~/stores/context';
 
 declare global {
   // eslint-disable-next-line vars-on-top, no-var
@@ -11,7 +11,7 @@ declare global {
 }
 
 export const DrawioViewerScript = (): JSX.Element => {
-  const { data: drawioUri } = useDrawioUri();
+  const { data: rendererConfig } = useRendererConfig();
 
   const loadedHandler = useCallback(() => {
     // disable useResizeSensor and checkVisibleState
@@ -32,11 +32,17 @@ export const DrawioViewerScript = (): JSX.Element => {
     GraphViewer.processElements();
   }, []);
 
+  if (rendererConfig == null) {
+    return <></>;
+  }
+
   return (
-    <Script
-      type="text/javascript"
-      src={(new URL('/js/viewer.min.js', drawioUri)).toString()}
-      onLoad={loadedHandler}
-    />
+    <Head>
+      <script
+        type="text/javascript" async
+        src={(new URL('/js/viewer.min.js', rendererConfig.drawioUri)).toString()}
+        onLoad={loadedHandler}
+      />
+    </Head>
   );
 };

+ 2 - 2
apps/app/src/interfaces/services/renderer.ts

@@ -8,6 +8,6 @@ export type RendererConfig = {
   isIndentSizeForced: boolean,
   highlightJsStyleBorder: boolean,
 
-  plantumlUri: string | null,
-  blockdiagUri: string | null,
+  drawioUri: string,
+  plantumlUri: string,
 } & XssOptionConfig;

+ 3 - 4
apps/app/src/pages/[[...path]].page.tsx

@@ -33,7 +33,7 @@ import {
   useIsForbidden, useIsSharedUser,
   useIsEnabledStaleNotification, useIsIdenticalPath,
   useIsSearchServiceConfigured, useIsSearchServiceReachable, useDisableLinkSharing,
-  useDrawioUri, useHackmdUri, useDefaultIndentSize, useIsIndentSizeForced,
+  useHackmdUri, useDefaultIndentSize, useIsIndentSizeForced,
   useIsAclEnabled, useIsSearchPage, useIsEnabledAttachTitleHeader,
   useCsrfToken, useIsSearchScopeChildrenAsDefault, useCurrentPathname,
   useIsSlackConfigured, useRendererConfig,
@@ -211,7 +211,6 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
   // useIsMailerSetup(props.isMailerSetup);
   useIsAclEnabled(props.isAclEnabled);
   // useHasSlackConfig(props.hasSlackConfig);
-  useDrawioUri(props.drawioUri);
   useHackmdUri(props.hackmdUri);
   // useNoCdn(props.noCdn);
   useDefaultIndentSize(props.adminPreferredIndentSize);
@@ -577,8 +576,8 @@ function injectServerConfigurations(context: GetServerSidePropsContext, props: P
     adminPreferredIndentSize: configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize'),
     isIndentSizeForced: configManager.getConfig('markdown', 'markdown:isIndentSizeForced'),
 
-    plantumlUri: process.env.PLANTUML_URI ?? null,
-    blockdiagUri: process.env.BLOCKDIAG_URI ?? null,
+    drawioUri: configManager.getConfig('crowi', 'app:drawioUri'),
+    plantumlUri: configManager.getConfig('crowi', 'app:plantumlUri'),
 
     // XSS Options
     isEnabledXssPrevention: configManager.getConfig('markdown', 'markdown:rehypeSanitize:isEnabledPrevention'),

+ 3 - 9
apps/app/src/pages/_private-legacy-pages.page.tsx

@@ -11,7 +11,7 @@ import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { RendererConfig } from '~/interfaces/services/renderer';
 import type { IUser, IUserHasId } from '~/interfaces/user';
 import {
-  useCsrfToken, useCurrentUser, useDrawioUri, useIsSearchPage, useIsSearchScopeChildrenAsDefault,
+  useCsrfToken, useCurrentUser, useIsSearchPage, useIsSearchScopeChildrenAsDefault,
   useIsSearchServiceConfigured, useIsSearchServiceReachable, useRendererConfig,
 } from '~/stores/context';
 
@@ -29,8 +29,6 @@ type Props = CommonProps & {
   isSearchServiceReachable: boolean,
   isSearchScopeChildrenAsDefault: boolean,
 
-  drawioUri: string | null,
-
   // Render config
   rendererConfig: RendererConfig,
 
@@ -52,8 +50,6 @@ const PrivateLegacyPage: NextPage<Props> = (props: Props) => {
   useIsSearchServiceReachable(props.isSearchServiceReachable);
   useIsSearchScopeChildrenAsDefault(props.isSearchScopeChildrenAsDefault);
 
-  useDrawioUri(props.drawioUri);
-
   // init sidebar config with UserUISettings and sidebarConfig
   useInitSidebarConfig(props.sidebarConfig, props.userUISettings);
 
@@ -88,8 +84,6 @@ async function injectServerConfigurations(context: GetServerSidePropsContext, pr
   props.isSearchServiceReachable = searchService.isReachable;
   props.isSearchScopeChildrenAsDefault = configManager.getConfig('crowi', 'customize:isSearchScopeChildrenAsDefault');
 
-  props.drawioUri = configManager.getConfig('crowi', 'app:drawioUri');
-
   props.sidebarConfig = {
     isSidebarDrawerMode: configManager.getConfig('crowi', 'customize:isSidebarDrawerMode'),
     isSidebarClosedAtDockMode: configManager.getConfig('crowi', 'customize:isSidebarClosedAtDockMode'),
@@ -101,8 +95,8 @@ async function injectServerConfigurations(context: GetServerSidePropsContext, pr
     adminPreferredIndentSize: configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize'),
     isIndentSizeForced: configManager.getConfig('markdown', 'markdown:isIndentSizeForced'),
 
-    plantumlUri: process.env.PLANTUML_URI ?? null,
-    blockdiagUri: process.env.BLOCKDIAG_URI ?? null,
+    drawioUri: configManager.getConfig('crowi', 'app:drawioUri'),
+    plantumlUri: configManager.getConfig('crowi', 'app:plantumlUri'),
 
     // XSS Options
     isEnabledXssPrevention: configManager.getConfig('markdown', 'markdown:rehypeSanitize:isEnabledPrevention'),

+ 3 - 9
apps/app/src/pages/_search.page.tsx

@@ -12,7 +12,7 @@ import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { RendererConfig } from '~/interfaces/services/renderer';
 import type { IUser, IUserHasId } from '~/interfaces/user';
 import {
-  useCsrfToken, useCurrentUser, useDrawioUri, useIsContainerFluid, useIsSearchPage, useIsSearchScopeChildrenAsDefault,
+  useCsrfToken, useCurrentUser, useIsContainerFluid, useIsSearchPage, useIsSearchScopeChildrenAsDefault,
   useIsSearchServiceConfigured, useIsSearchServiceReachable, useRendererConfig, useShowPageLimitationL,
 } from '~/stores/context';
 
@@ -32,8 +32,6 @@ type Props = CommonProps & {
   isSearchServiceReachable: boolean,
   isSearchScopeChildrenAsDefault: boolean,
 
-  drawioUri: string | null,
-
   // Render config
   rendererConfig: RendererConfig,
 
@@ -58,8 +56,6 @@ const SearchResultPage: NextPageWithLayout<Props> = (props: Props) => {
   useIsSearchServiceReachable(props.isSearchServiceReachable);
   useIsSearchScopeChildrenAsDefault(props.isSearchScopeChildrenAsDefault);
 
-  useDrawioUri(props.drawioUri);
-
   // init sidebar config with UserUISettings and sidebarConfig
   useInitSidebarConfig(props.sidebarConfig, props.userUISettings);
 
@@ -125,8 +121,6 @@ function injectServerConfigurations(context: GetServerSidePropsContext, props: P
   props.isSearchScopeChildrenAsDefault = configManager.getConfig('crowi', 'customize:isSearchScopeChildrenAsDefault');
   props.isContainerFluid = configManager.getConfig('crowi', 'customize:isContainerFluid');
 
-  props.drawioUri = configManager.getConfig('crowi', 'app:drawioUri');
-
   props.sidebarConfig = {
     isSidebarDrawerMode: configManager.getConfig('crowi', 'customize:isSidebarDrawerMode'),
     isSidebarClosedAtDockMode: configManager.getConfig('crowi', 'customize:isSidebarClosedAtDockMode'),
@@ -138,8 +132,8 @@ function injectServerConfigurations(context: GetServerSidePropsContext, props: P
     adminPreferredIndentSize: configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize'),
     isIndentSizeForced: configManager.getConfig('markdown', 'markdown:isIndentSizeForced'),
 
-    plantumlUri: process.env.PLANTUML_URI ?? null,
-    blockdiagUri: process.env.BLOCKDIAG_URI ?? null,
+    drawioUri: configManager.getConfig('crowi', 'app:drawioUri'),
+    plantumlUri: configManager.getConfig('crowi', 'app:plantumlUri'),
 
     // XSS Options
     isEnabledXssPrevention: configManager.getConfig('markdown', 'markdown:rehypeSanitize:isEnabledPrevention'),

+ 2 - 2
apps/app/src/pages/me/[[...path]].page.tsx

@@ -158,8 +158,8 @@ async function injectServerConfigurations(context: GetServerSidePropsContext, pr
     adminPreferredIndentSize: configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize'),
     isIndentSizeForced: configManager.getConfig('markdown', 'markdown:isIndentSizeForced'),
 
-    plantumlUri: process.env.PLANTUML_URI ?? null,
-    blockdiagUri: process.env.BLOCKDIAG_URI ?? null,
+    drawioUri: configManager.getConfig('crowi', 'app:drawioUri'),
+    plantumlUri: configManager.getConfig('crowi', 'app:plantumlUri'),
 
     // XSS Options
     isEnabledXssPrevention: configManager.getConfig('markdown', 'markdown:rehypeSanitize:isEnabledPrevention'),

+ 3 - 4
apps/app/src/pages/share/[[...path]].page.tsx

@@ -20,7 +20,7 @@ import type { IShareLinkHasId } from '~/interfaces/share-link';
 import type { PageDocument } from '~/server/models/page';
 import {
   useCurrentUser, useRendererConfig, useIsSearchPage, useCurrentPathname,
-  useShareLinkId, useIsSearchServiceConfigured, useIsSearchServiceReachable, useIsSearchScopeChildrenAsDefault, useDrawioUri, useIsContainerFluid,
+  useShareLinkId, useIsSearchServiceConfigured, useIsSearchServiceReachable, useIsSearchScopeChildrenAsDefault, useIsContainerFluid,
 } from '~/stores/context';
 import { useCurrentPageId, useIsNotFound } from '~/stores/page';
 import loggerFactory from '~/utils/logger';
@@ -90,7 +90,6 @@ const SharedPage: NextPageWithLayout<Props> = (props: Props) => {
   useIsSearchServiceConfigured(props.isSearchServiceConfigured);
   useIsSearchServiceReachable(props.isSearchServiceReachable);
   useIsSearchScopeChildrenAsDefault(props.isSearchScopeChildrenAsDefault);
-  useDrawioUri(props.drawioUri);
   useIsContainerFluid(props.isContainerFluid);
 
 
@@ -156,8 +155,8 @@ function injectServerConfigurations(context: GetServerSidePropsContext, props: P
     adminPreferredIndentSize: configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize'),
     isIndentSizeForced: configManager.getConfig('markdown', 'markdown:isIndentSizeForced'),
 
-    plantumlUri: process.env.PLANTUML_URI ?? null,
-    blockdiagUri: process.env.BLOCKDIAG_URI ?? null,
+    drawioUri: configManager.getConfig('crowi', 'app:drawioUri'),
+    plantumlUri: configManager.getConfig('crowi', 'app:plantumlUri'),
 
     // XSS Options
     isEnabledXssPrevention: configManager.getConfig('markdown', 'markdown:rehypeSanitize:isEnabledPrevention'),

+ 1 - 19
apps/app/src/pages/tags.page.tsx

@@ -16,7 +16,7 @@ import { BasicLayout } from '../components/Layout/BasicLayout';
 import {
   useCurrentUser, useIsSearchPage,
   useIsSearchServiceConfigured, useIsSearchServiceReachable,
-  useIsSearchScopeChildrenAsDefault, useRendererConfig,
+  useIsSearchScopeChildrenAsDefault,
 } from '../stores/context';
 
 import { NextPageWithLayout } from './_app.page';
@@ -64,8 +64,6 @@ const TagPage: NextPageWithLayout<CommonProps> = (props: Props) => {
   // init sidebar config with UserUISettings and sidebarConfig
   useInitSidebarConfig(props.sidebarConfig, props.userUISettings);
 
-  useRendererConfig(props.rendererConfig);
-
   const title = generateCustomTitle(props, t('Tags'));
 
   return (
@@ -139,22 +137,6 @@ function injectServerConfigurations(context: GetServerSidePropsContext, props: P
     isSidebarClosedAtDockMode: configManager.getConfig('crowi', 'customize:isSidebarClosedAtDockMode'),
   };
 
-  props.rendererConfig = {
-    isEnabledLinebreaks: configManager.getConfig('markdown', 'markdown:isEnabledLinebreaks'),
-    isEnabledLinebreaksInComments: configManager.getConfig('markdown', 'markdown:isEnabledLinebreaksInComments'),
-    adminPreferredIndentSize: configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize'),
-    isIndentSizeForced: configManager.getConfig('markdown', 'markdown:isIndentSizeForced'),
-
-    plantumlUri: process.env.PLANTUML_URI ?? null,
-    blockdiagUri: process.env.BLOCKDIAG_URI ?? null,
-
-    // XSS Options
-    isEnabledXssPrevention: configManager.getConfig('markdown', 'markdown:rehypeSanitize:isEnabledPrevention'),
-    xssOption: configManager.getConfig('markdown', 'markdown:rehypeSanitize:option'),
-    attrWhiteList: JSON.parse(crowi.configManager.getConfig('markdown', 'markdown:rehypeSanitize:attributes')),
-    tagWhiteList: crowi.configManager.getConfig('markdown', 'markdown:rehypeSanitize:tagNames'),
-    highlightJsStyleBorder: crowi.configManager.getConfig('crowi', 'customize:highlightJsStyleBorder'),
-  };
 }
 
 /**

+ 1 - 19
apps/app/src/pages/trash.page.tsx

@@ -16,7 +16,7 @@ import { BasicLayout } from '../components/Layout/BasicLayout';
 import {
   useCurrentUser, useCurrentPathname,
   useIsSearchServiceConfigured, useIsSearchServiceReachable,
-  useIsSearchScopeChildrenAsDefault, useIsSearchPage, useShowPageLimitationXL, useIsGuestUser, useRendererConfig,
+  useIsSearchScopeChildrenAsDefault, useIsSearchPage, useShowPageLimitationXL, useIsGuestUser,
 } from '../stores/context';
 
 import type { NextPageWithLayout } from './_app.page';
@@ -55,8 +55,6 @@ const TrashPage: NextPageWithLayout<CommonProps> = (props: Props) => {
 
   useShowPageLimitationXL(props.showPageLimitationXL);
 
-  useRendererConfig(props.rendererConfig);
-
   const { data: isDrawerMode } = useDrawerMode();
   const { data: isGuestUser } = useIsGuestUser();
 
@@ -128,22 +126,6 @@ function injectServerConfigurations(context: GetServerSidePropsContext, props: P
     isSidebarClosedAtDockMode: configManager.getConfig('crowi', 'customize:isSidebarClosedAtDockMode'),
   };
 
-  props.rendererConfig = {
-    isEnabledLinebreaks: configManager.getConfig('markdown', 'markdown:isEnabledLinebreaks'),
-    isEnabledLinebreaksInComments: configManager.getConfig('markdown', 'markdown:isEnabledLinebreaksInComments'),
-    adminPreferredIndentSize: configManager.getConfig('markdown', 'markdown:adminPreferredIndentSize'),
-    isIndentSizeForced: configManager.getConfig('markdown', 'markdown:isIndentSizeForced'),
-
-    plantumlUri: process.env.PLANTUML_URI ?? null,
-    blockdiagUri: process.env.BLOCKDIAG_URI ?? null,
-
-    // XSS Options
-    isEnabledXssPrevention: configManager.getConfig('markdown', 'markdown:rehypeSanitize:isEnabledPrevention'),
-    xssOption: configManager.getConfig('markdown', 'markdown:rehypeSanitize:option'),
-    attrWhiteList: JSON.parse(crowi.configManager.getConfig('markdown', 'markdown:rehypeSanitize:attributes')),
-    tagWhiteList: crowi.configManager.getConfig('markdown', 'markdown:rehypeSanitize:tagNames'),
-    highlightJsStyleBorder: crowi.configManager.getConfig('crowi', 'customize:highlightJsStyleBorder'),
-  };
 }
 
 /**

+ 7 - 7
apps/app/src/server/service/config-loader.ts

@@ -73,12 +73,6 @@ const ENV_VAR_NAME_TO_CONFIG_INFO = {
     type:    ValueType.STRING,
     default: null,
   },
-  // PLANTUML_URI: {
-  //   ns:      ,
-  //   key:     ,
-  //   type:    ,
-  //   default:
-  // },
   // BLOCKDIAG_URI: {
   //   ns:      ,
   //   key:     ,
@@ -121,11 +115,17 @@ const ENV_VAR_NAME_TO_CONFIG_INFO = {
   //   type:    ,
   //   default:
   // },
+  PLANTUML_URI: {
+    ns:      'crowi',
+    key:     'app:plantumlUri',
+    type:    ValueType.STRING,
+    default: 'https://www.plantuml.com/plantuml',
+  },
   DRAWIO_URI: {
     ns:      'crowi',
     key:     'app:drawioUri',
     type:    ValueType.STRING,
-    default: null,
+    default: 'https://embed.diagrams.net/',
   },
   NCHAN_URI: {
     ns:      'crowi',

+ 0 - 18
apps/app/src/services/renderer/markdown-it/blockdiag.ts

@@ -1,18 +0,0 @@
-import { RendererConfig } from '~/interfaces/services/renderer';
-
-export default class BlockdiagConfigurer {
-
-  generateSourceUrl: string;
-
-  constructor(config: RendererConfig) {
-    this.generateSourceUrl = config.blockdiagUri || 'https://blockdiag-api.com/';
-  }
-
-  configure(md) {
-    // md.use(require('markdown-it-blockdiag'), {
-    //   generateSourceUrl: this.generateSourceUrl,
-    //   marker: ':::',
-    // });
-  }
-
-}

+ 2 - 2
apps/app/src/services/renderer/remark-plugins/plantuml.ts

@@ -3,11 +3,11 @@ import { Plugin } from 'unified';
 import urljoin from 'url-join';
 
 type PlantUMLPluginParams = {
-  plantumlUri?: string,
+  plantumlUri: string,
 }
 
 export const remarkPlugin: Plugin<[PlantUMLPluginParams]> = (options) => {
-  const plantumlUri = options.plantumlUri ?? 'https://www.plantuml.com/plantuml';
+  const plantumlUri = options.plantumlUri;
 
   const baseUrl = urljoin(plantumlUri, '/svg');
 

+ 0 - 1
apps/app/src/services/renderer/renderer.tsx

@@ -27,7 +27,6 @@ import { pukiwikiLikeLinker } from './remark-plugins/pukiwiki-like-linker';
 import * as xsvToTable from './remark-plugins/xsv-to-table';
 
 // import EasyGrid from './PreProcessor/EasyGrid';
-// import BlockdiagConfigurer from './markdown-it/blockdiag';
 
 
 const logger = loggerFactory('growi:services:renderer');

+ 0 - 4
apps/app/src/stores/context.tsx

@@ -72,10 +72,6 @@ export const useRegistrationWhiteList = (initialData?: Nullable<string[]>): SWRR
   return useContextSWR<Nullable<string[]>, Error>('registrationWhiteList', initialData);
 };
 
-export const useDrawioUri = (initialData?: Nullable<string>): SWRResponse<string, Error> => {
-  return useContextSWR('drawioUri', initialData ?? undefined, { fallbackData: 'https://embed.diagrams.net/' });
-};
-
 export const useHackmdUri = (initialData?: Nullable<string>): SWRResponse<Nullable<string>, Error> => {
   return useContextSWR<Nullable<string>, Error>('hackmdUri', initialData);
 };

+ 5 - 0
apps/app/src/stores/editor.tsx

@@ -17,6 +17,11 @@ import { useSWRxTagsInfo } from './page';
 import { useStaticSWR } from './use-static-swr';
 
 
+export const useWaitingSaveProcessing = (): SWRResponse<boolean, Error> => {
+  return useStaticSWR('waitingSaveProcessing', undefined, { fallbackData: false });
+};
+
+
 export const useEditingMarkdown = (initialData?: string): SWRResponse<string, Error> => {
   return useStaticSWR('editingMarkdown', initialData);
 };

+ 13 - 6
apps/app/test/cypress/integration/20-basic-features/20-basic-features--use-tools.spec.ts

@@ -44,16 +44,16 @@ context('Modal for page operation', () => {
       cy.screenshot(`${ssPrefix}today-add-page-name`);
       cy.getByTestid('btn-create-memo').click();
     });
-    cy.getByTestid('page-editor').should('be.visible');
 
+    cy.getByTestid('page-editor').should('be.visible');
+    cy.getByTestid('save-page-btn').as('save-page-btn').should('be.visible');
     cy.waitUntil(() => {
       // do
-      cy.getByTestid('save-page-btn').should('be.visible').click();
+      cy.get('@save-page-btn').click();
       // wait until
-      return cy.get('.layout-root').then($elem => $elem.hasClass('editing'));
+      return cy.get('@save-page-btn').then($elem => $elem.is(':disabled'));
     });
-
-    cy.getByTestid('grw-contextual-sub-nav').should('be.visible');
+    cy.get('.layout-root').should('not.have.class', 'editing');
 
     cy.collapseSidebar(true);
     cy.waitUntilSkeletonDisappear();
@@ -80,8 +80,15 @@ context('Modal for page operation', () => {
       cy.screenshot(`${ssPrefix}under-path-add-page-name`);
       cy.getByTestid('btn-create-page-under-below').click();
     });
+
     cy.getByTestid('page-editor').should('be.visible');
-    cy.getByTestid('save-page-btn').click();
+    cy.getByTestid('save-page-btn').as('save-page-btn').should('be.visible');
+    cy.waitUntil(() => {
+      // do
+      cy.get('@save-page-btn').click();
+      // wait until
+      return cy.get('@save-page-btn').then($elem => $elem.is(':disabled'));
+    });
     cy.get('.layout-root').should('not.have.class', 'editing');
 
     cy.getByTestid('grw-contextual-sub-nav').should('be.visible');

+ 1 - 1
packages/presentation/package.json

@@ -27,7 +27,7 @@
     "reveal.js": "^4.4.0"
   },
   "peerDependencies": {
-    "next": "~12.2",
+    "next": "^13",
     "react": "^18.2.0",
     "react-dom": "^18.2.0",
     "react-markdown": "^8.0.7"

+ 1 - 1
packages/remark-lsx/package.json

@@ -31,7 +31,7 @@
     "eslint-plugin-regex": "^1.8.0"
   },
   "peerDependencies": {
-    "next": "~12.2",
+    "next": "^13",
     "react": "^18.2.0",
     "react-dom": "^18.2.0",
     "react-markdown": "^8.0.3"

+ 0 - 3
packages/remark-lsx/src/server/routes/lsx.ts

@@ -194,9 +194,6 @@ export const routesFactory = (crowi): any => {
     const builder = new Page.PageQueryBuilder(baseQuery);
     builder.addConditionToListOnlyDescendants(pagePath);
 
-    builder
-      .addConditionToExcludeTrashed();
-
     return Page.addConditionToFilteringByViewerForList(builder, user);
   }
 

+ 75 - 86
yarn.lock

@@ -2584,10 +2584,10 @@
   dependencies:
     webpack-bundle-analyzer "4.7.0"
 
-"@next/env@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/env/-/env-13.1.1.tgz#6ff26488dc7674ef2bfdd1ca28fe43eed1113bea"
-  integrity sha512-vFMyXtPjSAiOXOywMojxfKIqE3VWN5RCAx+tT3AS3pcKjMLFTCJFUWsKv8hC+87Z1F4W3r68qTwDFZIFmd5Xkw==
+"@next/env@13.3.0":
+  version "13.3.0"
+  resolved "https://registry.yarnpkg.com/@next/env/-/env-13.3.0.tgz#cc2e49f03060a4684ce7ec7fd617a21bc5b9edba"
+  integrity sha512-AjppRV4uG3No7L1plinoTQETH+j2F10TEnrMfzbTUYwze5sBUPveeeBAPZPm8OkJZ1epq9OyYKhZrvbD6/9HCQ==
 
 "@next/eslint-plugin-next@12.1.6":
   version "12.1.6"
@@ -2596,70 +2596,50 @@
   dependencies:
     glob "7.1.7"
 
-"@next/swc-android-arm-eabi@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-13.1.1.tgz#b5c3cd1f79d5c7e6a3b3562785d4e5ac3555b9e1"
-  integrity sha512-qnFCx1kT3JTWhWve4VkeWuZiyjG0b5T6J2iWuin74lORCupdrNukxkq9Pm+Z7PsatxuwVJMhjUoYz7H4cWzx2A==
-
-"@next/swc-android-arm64@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-13.1.1.tgz#e2ca9ccbba9ef770cb19fbe96d1ac00fe4cb330d"
-  integrity sha512-eCiZhTzjySubNqUnNkQCjU3Fh+ep3C6b5DCM5FKzsTH/3Gr/4Y7EiaPZKILbvnXmhWtKPIdcY6Zjx51t4VeTfA==
-
-"@next/swc-darwin-arm64@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.1.1.tgz#4af00877332231bbd5a3703435fdd0b011e74767"
-  integrity sha512-9zRJSSIwER5tu9ADDkPw5rIZ+Np44HTXpYMr0rkM656IvssowPxmhK0rTreC1gpUCYwFsRbxarUJnJsTWiutPg==
-
-"@next/swc-darwin-x64@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.1.1.tgz#bf4cb09e7e6ec6d91e031118dde2dd17078bcbbc"
-  integrity sha512-qWr9qEn5nrnlhB0rtjSdR00RRZEtxg4EGvicIipqZWEyayPxhUu6NwKiG8wZiYZCLfJ5KWr66PGSNeDMGlNaiA==
-
-"@next/swc-freebsd-x64@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-13.1.1.tgz#6933ea1264328e8523e28818f912cd53824382d4"
-  integrity sha512-UwP4w/NcQ7V/VJEj3tGVszgb4pyUCt3lzJfUhjDMUmQbzG9LDvgiZgAGMYH6L21MoyAATJQPDGiAMWAPKsmumA==
-
-"@next/swc-linux-arm-gnueabihf@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-13.1.1.tgz#b5896967aaba3873d809c3ad2e2039e89acde419"
-  integrity sha512-CnsxmKHco9sosBs1XcvCXP845Db+Wx1G0qouV5+Gr+HT/ZlDYEWKoHVDgnJXLVEQzq4FmHddBNGbXvgqM1Gfkg==
-
-"@next/swc-linux-arm64-gnu@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.1.1.tgz#91b3e9ea8575b1ded421c0ea0739b7bccf228469"
-  integrity sha512-JfDq1eri5Dif+VDpTkONRd083780nsMCOKoFG87wA0sa4xL8LGcXIBAkUGIC1uVy9SMsr2scA9CySLD/i+Oqiw==
-
-"@next/swc-linux-arm64-musl@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.1.1.tgz#83149ea05d7d55f3664d608dbe004c0d125f9147"
-  integrity sha512-GA67ZbDq2AW0CY07zzGt07M5b5Yaq5qUpFIoW3UFfjOPgb0Sqf3DAW7GtFMK1sF4ROHsRDMGQ9rnT0VM2dVfKA==
-
-"@next/swc-linux-x64-gnu@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.1.1.tgz#d7d0777b56de0dd82b78055772e13e18594a15ca"
-  integrity sha512-nnjuBrbzvqaOJaV+XgT8/+lmXrSCOt1YYZn/irbDb2fR2QprL6Q7WJNgwsZNxiLSfLdv+2RJGGegBx9sLBEzGA==
-
-"@next/swc-linux-x64-musl@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.1.1.tgz#41655722b127133cd95ab5bc8ca1473e9ab6876f"
-  integrity sha512-CM9xnAQNIZ8zf/igbIT/i3xWbQZYaF397H+JroF5VMOCUleElaMdQLL5riJml8wUfPoN3dtfn2s4peSr3azz/g==
-
-"@next/swc-win32-arm64-msvc@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.1.1.tgz#f10da3dfc9b3c2bbd202f5d449a9b807af062292"
-  integrity sha512-pzUHOGrbgfGgPlOMx9xk3QdPJoRPU+om84hqVoe6u+E0RdwOG0Ho/2UxCgDqmvpUrMab1Deltlt6RqcXFpnigQ==
-
-"@next/swc-win32-ia32-msvc@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.1.1.tgz#4c0102b9b18ece15c818056d07e3917ee9dade78"
-  integrity sha512-WeX8kVS46aobM9a7Xr/kEPcrTyiwJqQv/tbw6nhJ4fH9xNZ+cEcyPoQkwPo570dCOLz3Zo9S2q0E6lJ/EAUOBg==
-
-"@next/swc-win32-x64-msvc@13.1.1":
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.1.1.tgz#c209a37da13be27b722f9c40c40ab4b094866244"
-  integrity sha512-mVF0/3/5QAc5EGVnb8ll31nNvf3BWpPY4pBb84tk+BfQglWLqc5AC9q1Ht/YMWiEgs8ALNKEQ3GQnbY0bJF2Gg==
+"@next/swc-darwin-arm64@13.3.0":
+  version "13.3.0"
+  resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.3.0.tgz#38f18e0639cd4c7edc6a38d4b83fe00f38eea4f2"
+  integrity sha512-DmIQCNq6JtccLPPBzf0dgh2vzMWt5wjxbP71pCi5EWpWYE3MsP6FcRXi4MlAmFNDQOfcFXR2r7kBeG1LpZUh1w==
+
+"@next/swc-darwin-x64@13.3.0":
+  version "13.3.0"
+  resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.3.0.tgz#b670ed1fd1d231aa21279173ec52e3ad56dc6aeb"
+  integrity sha512-oQoqFa88OGgwnYlnAGHVct618FRI/749se0N3S8t9Bzdv5CRbscnO0RcX901+YnNK4Q6yeiizfgO3b7kogtsZg==
+
+"@next/swc-linux-arm64-gnu@13.3.0":
+  version "13.3.0"
+  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.3.0.tgz#b114935f6b4c94c123f6cac55a4823d483209ba5"
+  integrity sha512-Wzz2p/WqAJUqTVoLo6H18WMeAXo3i+9DkPDae4oQG8LMloJ3if4NEZTnOnTUlro6cq+S/W4pTGa97nWTrOjbGw==
+
+"@next/swc-linux-arm64-musl@13.3.0":
+  version "13.3.0"
+  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.3.0.tgz#67a57309f8761c7d00d629d6785d56ed0567a0d2"
+  integrity sha512-xPVrIQOQo9WXJYgmoTlMnAD/HlR/1e1ZIWGbwIzEirXBVBqMARUulBEIKdC19zuvoJ477qZJgBDCKtKEykCpyQ==
+
+"@next/swc-linux-x64-gnu@13.3.0":
+  version "13.3.0"
+  resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.3.0.tgz#11bd2bea7c00b40be111c0dd16e71171f3792086"
+  integrity sha512-jOFlpGuPD7W2tuXVJP4wt9a3cpNxWAPcloq5EfMJRiXsBBOjLVFZA7boXYxEBzSVgUiVVr1V9T0HFM7pULJ1qA==
+
+"@next/swc-linux-x64-musl@13.3.0":
+  version "13.3.0"
+  resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.3.0.tgz#d57e99f85890799b78719c3ea32a4624de8d701b"
+  integrity sha512-2OwKlzaBgmuet9XYHc3KwsEilzb04F540rlRXkAcjMHL7eCxB7uZIGtsVvKOnQLvC/elrUegwSw1+5f7WmfyOw==
+
+"@next/swc-win32-arm64-msvc@13.3.0":
+  version "13.3.0"
+  resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.3.0.tgz#0c209aa35d1c88b01e78259a89cd68f4139b5093"
+  integrity sha512-OeHiA6YEvndxT46g+rzFK/MQTfftKxJmzslERMu9LDdC6Kez0bdrgEYed5eXFK2Z1viKZJCGRlhd06rBusyztA==
+
+"@next/swc-win32-ia32-msvc@13.3.0":
+  version "13.3.0"
+  resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.3.0.tgz#52ae74da1dd6d840c3743923367d27ed013803dd"
+  integrity sha512-4aB7K9mcVK1lYEzpOpqWrXHEZympU3oK65fnNcY1Qc4HLJFLJj8AViuqQd4jjjPNuV4sl8jAwTz3gN5VNGWB7w==
+
+"@next/swc-win32-x64-msvc@13.3.0":
+  version "13.3.0"
+  resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.3.0.tgz#db7b55fee834dc8c2c484c696469e65bae2ee770"
+  integrity sha512-Reer6rkLLcoOvB0dd66+Y7WrWVFH7sEEkF/4bJCIfsSKnTStTYaHtwIJAwbqnt9I392Tqvku0KkoqZOryWV9LQ==
 
 "@node-rs/xxhash-android-arm-eabi@1.3.0":
   version "1.3.0"
@@ -5623,6 +5603,13 @@ bunyan@^1.8.15:
     mv "~2"
     safe-json-stringify "~1"
 
+busboy@1.6.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
+  integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
+  dependencies:
+    streamsearch "^1.1.0"
+
 busboy@^0.2.11:
   version "0.2.14"
   resolved "https://registry.yarnpkg.com/busboy/-/busboy-0.2.14.tgz#6c2a622efcf47c57bbbe1e2a9c37ad36c7925453"
@@ -14240,30 +14227,27 @@ next-themes@^0.2.1:
   resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.2.1.tgz#0c9f128e847979daf6c67f70b38e6b6567856e45"
   integrity sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==
 
-next@=13.1.1:
-  version "13.1.1"
-  resolved "https://registry.yarnpkg.com/next/-/next-13.1.1.tgz#42b825f650410649aff1017d203a088d77c80b5b"
-  integrity sha512-R5eBAaIa3X7LJeYvv1bMdGnAVF4fVToEjim7MkflceFPuANY3YyvFxXee/A+acrSYwYPvOvf7f6v/BM/48ea5w==
+next@^13.3.0:
+  version "13.3.0"
+  resolved "https://registry.yarnpkg.com/next/-/next-13.3.0.tgz#40632d303d74fc8521faa0a5bf4a033a392749b1"
+  integrity sha512-OVTw8MpIPa12+DCUkPqRGPS3thlJPcwae2ZL4xti3iBff27goH024xy4q2lhlsdoYiKOi8Kz6uJoLW/GXwgfOA==
   dependencies:
-    "@next/env" "13.1.1"
+    "@next/env" "13.3.0"
     "@swc/helpers" "0.4.14"
+    busboy "1.6.0"
     caniuse-lite "^1.0.30001406"
     postcss "8.4.14"
     styled-jsx "5.1.1"
   optionalDependencies:
-    "@next/swc-android-arm-eabi" "13.1.1"
-    "@next/swc-android-arm64" "13.1.1"
-    "@next/swc-darwin-arm64" "13.1.1"
-    "@next/swc-darwin-x64" "13.1.1"
-    "@next/swc-freebsd-x64" "13.1.1"
-    "@next/swc-linux-arm-gnueabihf" "13.1.1"
-    "@next/swc-linux-arm64-gnu" "13.1.1"
-    "@next/swc-linux-arm64-musl" "13.1.1"
-    "@next/swc-linux-x64-gnu" "13.1.1"
-    "@next/swc-linux-x64-musl" "13.1.1"
-    "@next/swc-win32-arm64-msvc" "13.1.1"
-    "@next/swc-win32-ia32-msvc" "13.1.1"
-    "@next/swc-win32-x64-msvc" "13.1.1"
+    "@next/swc-darwin-arm64" "13.3.0"
+    "@next/swc-darwin-x64" "13.3.0"
+    "@next/swc-linux-arm64-gnu" "13.3.0"
+    "@next/swc-linux-arm64-musl" "13.3.0"
+    "@next/swc-linux-x64-gnu" "13.3.0"
+    "@next/swc-linux-x64-musl" "13.3.0"
+    "@next/swc-win32-arm64-msvc" "13.3.0"
+    "@next/swc-win32-ia32-msvc" "13.3.0"
+    "@next/swc-win32-x64-msvc" "13.3.0"
 
 nice-try@^1.0.4:
   version "1.0.4"
@@ -18199,6 +18183,11 @@ streamsearch@0.1.2:
   version "0.1.2"
   resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a"
 
+streamsearch@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764"
+  integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
+
 string-argv@~0.3.1:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da"