Просмотр исходного кода

Merge branch 'master' into fix/react-dom-internal-server-error

ryoji-s 3 лет назад
Родитель
Сommit
86754a5b1f
43 измененных файлов с 386 добавлено и 354 удалено
  1. 14 12
      packages/app/next.config.js
  2. 7 7
      packages/app/package.json
  3. 7 0
      packages/app/src/@types/i18next.d.ts
  4. 5 7
      packages/app/src/components/Admin/Common/AdminNavigation.jsx
  5. 23 23
      packages/app/src/components/Admin/ManageExternalAccount.tsx
  6. 1 1
      packages/app/src/components/Admin/PluginsExtension/PluginCard.tsx
  7. 5 4
      packages/app/src/components/Admin/Security/SecurityManagementContents.jsx
  8. 2 2
      packages/app/src/components/Admin/UserGroupDetail/UserGroupDetailPage.tsx
  9. 7 5
      packages/app/src/components/Admin/UserManagement.tsx
  10. 2 2
      packages/app/src/components/CustomNavigation/CustomNav.jsx
  11. 1 1
      packages/app/src/components/CustomNavigation/CustomTabContent.tsx
  12. 13 6
      packages/app/src/components/LoginForm.tsx
  13. 1 1
      packages/app/src/components/Navbar/AuthorInfo.tsx
  14. 2 4
      packages/app/src/components/Navbar/GrowiNavbar.tsx
  15. 12 8
      packages/app/src/components/Navbar/PersonalDropdown.jsx
  16. 9 22
      packages/app/src/components/PageAccessoriesModal.tsx
  17. 1 1
      packages/app/src/components/PageAlert/OldRevisionAlert.tsx
  18. 8 7
      packages/app/src/components/PageComment/Comment.tsx
  19. 1 1
      packages/app/src/components/PageEditorByHackmd.tsx
  20. 7 4
      packages/app/src/components/PageHistory/Revision.tsx
  21. 14 8
      packages/app/src/components/PageHistory/RevisionDiff.tsx
  22. 4 1
      packages/app/src/components/PageList/PageListItemL.tsx
  23. 4 6
      packages/app/src/components/PagePathHierarchicalLink.tsx
  24. 1 1
      packages/app/src/components/PageTimeline.tsx
  25. 1 3
      packages/app/src/components/PasswordResetExecutionForm.tsx
  26. 1 3
      packages/app/src/components/PasswordResetRequestForm.tsx
  27. 1 1
      packages/app/src/components/ReactMarkdownComponents/NextLink.tsx
  28. 3 1
      packages/app/src/components/SearchPage/SearchPageBase.tsx
  29. 2 2
      packages/app/src/components/Sidebar/CustomSidebar.tsx
  30. 6 4
      packages/app/src/components/Sidebar/PageTree/Item.tsx
  31. 7 5
      packages/app/src/components/Sidebar/PageTree/PrivateLegacyPagesLink.tsx
  32. 7 4
      packages/app/src/components/Sidebar/RecentChanges.tsx
  33. 7 4
      packages/app/src/components/Sidebar/SidebarNav.tsx
  34. 5 4
      packages/app/src/components/TagCloudBox.tsx
  35. 4 6
      packages/app/src/components/TagList.tsx
  36. 1 1
      packages/app/src/components/User/Username.tsx
  37. 2 4
      packages/app/src/pages/forgot-password-errors.page.tsx
  38. 5 3
      packages/app/src/server/models/page.ts
  39. 15 2
      packages/app/src/server/routes/apiv3/pages.js
  40. 3 0
      packages/app/src/services/renderer/renderer.tsx
  41. 5 6
      packages/app/src/stores/modal.tsx
  42. 2 2
      packages/remark-lsx/src/components/LsxPageList/LsxPage.tsx
  43. 158 165
      yarn.lock

+ 14 - 12
packages/app/next.config.js

@@ -9,7 +9,7 @@ const { withSuperjson } = require('next-superjson');
 const { PHASE_PRODUCTION_BUILD, PHASE_PRODUCTION_SERVER } = require('next/constants');
 
 
-const setupTranspileModules = () => {
+const getTranspilePackages = () => {
   const eazyLogger = require('eazy-logger');
   const { listScopedPackages, listPrefixedPackages } = require('./src/utils/next.config.utils');
 
@@ -40,6 +40,8 @@ const setupTranspileModules = () => {
     'trough',
     'web-namespaces',
     'vfile',
+    'vfile-location',
+    'vfile-message',
     'zwitch',
     'emoticon',
     'direction', // for hast-util-select
@@ -50,7 +52,7 @@ const setupTranspileModules = () => {
   // logger.info('{bold:Listing scoped packages for transpiling:}');
   // logger.unprefixed('info', `{grey:${JSON.stringify(packages, null, 2)}}`);
 
-  return require('next-transpile-modules')(packages);
+  return packages;
 };
 
 
@@ -60,21 +62,22 @@ module.exports = async(phase, { defaultConfig }) => {
 
   /** @type {import('next').NextConfig} */
   const nextConfig = {
-    // == DOES NOT WORK
-    // see: https://github.com/vercel/next.js/discussions/27876
-    // experimental: { esmExternals: true }, // Prefer loading of ES Modules over CommonJS
 
+    reactStrictMode: true,
+    poweredByHeader: false,
+    pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js'],
+    i18n,
+
+    // for build
     eslint: {
       ignoreDuringBuilds: true,
     },
-    reactStrictMode: true,
-    swcMinify: true,
     typescript: {
       tsconfigPath: 'tsconfig.build.client.json',
     },
-    pageExtensions: ['page.tsx', 'page.ts', 'page.jsx', 'page.js'],
-
-    i18n,
+    transpilePackages: phase !== PHASE_PRODUCTION_SERVER
+      ? getTranspilePackages()
+      : undefined,
 
     /** @param config {import('next').NextConfig} */
     webpack(config, options) {
@@ -105,10 +108,9 @@ module.exports = async(phase, { defaultConfig }) => {
     return withSuperjson()(nextConfig);
   }
 
-  const withTM = setupTranspileModules();
   const withBundleAnalyzer = require('@next/bundle-analyzer')({
     enabled: phase === PHASE_PRODUCTION_BUILD || process.env.ANALYZE === 'true',
   });
 
-  return withBundleAnalyzer(withTM(withSuperjson()(nextConfig)));
+  return withBundleAnalyzer(withSuperjson()(nextConfig));
 };

+ 7 - 7
packages/app/package.json

@@ -51,9 +51,8 @@
     "ts-node": "node -r ts-node/register -r tsconfig-paths/register -r dotenv-flow/config"
   },
   "// comments for dependencies": {
-    "openid-client": "Node.js 12 or higher is required for openid-client@3 and above.",
     "escape-string-regexp": "5.0.0 or above exports only ESM",
-    "next": "/Sandbox rendering is crashed with v12.3 or above ",
+    "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"
@@ -118,6 +117,7 @@
     "hast-util-select": "^5.0.2",
     "helmet": "^4.6.0",
     "http-errors": "^2.0.0",
+    "i18next": "^22.4.10",
     "i18next-chained-backend": "^4.0.0",
     "i18next-http-backend": "^2.0.0",
     "i18next-localstorage-backend": "^4.0.0",
@@ -135,10 +135,10 @@
     "mongoose-unique-validator": "^2.0.3",
     "multer": "~1.4.0",
     "multer-autoreap": "^1.0.3",
-    "next": "~12.2",
-    "next-i18next": "^12.1.0",
+    "next": "=13.1.1",
+    "next-i18next": "^13.2.1",
     "next-superjson": "^0.0.4",
-    "next-themes": "^0.2.0",
+    "next-themes": "^0.2.1",
     "nocache": "^3.0.1",
     "nodemailer": "^6.6.2",
     "nodemailer-ses-transport": "~1.5.0",
@@ -160,6 +160,7 @@
     "react-dnd": "^14.0.5",
     "react-dnd-html5-backend": "^14.1.0",
     "react-dom": "^18.2.0",
+    "react-i18next": "^12.2.0",
     "react-image-crop": "^8.3.0",
     "react-markdown": "^8.0.3",
     "react-multiline-clamp": "^2.0.0",
@@ -207,7 +208,7 @@
     "@growi/ui": "^6.0.9-RC.0",
     "@handsontable/react": "=2.1.0",
     "@icon/themify-icons": "1.0.1-alpha.3",
-    "@next/bundle-analyzer": "^12.2.3",
+    "@next/bundle-analyzer": "^13.2.3",
     "@types/express": "^4.17.11",
     "@types/react-scroll": "^1.8.4",
     "autoprefixer": "^9.0.0",
@@ -230,7 +231,6 @@
     "load-css-file": "^1.0.0",
     "material-icons": "^1.11.3",
     "morgan": "^1.10.0",
-    "next-transpile-modules": "^9.0.0",
     "penpal": "^4.0.0",
     "plantuml-encoder": "^1.2.5",
     "prettier": "^1.19.1",

+ 7 - 0
packages/app/src/@types/i18next.d.ts

@@ -0,0 +1,7 @@
+import 'i18next';
+
+declare module 'i18next' {
+  interface CustomTypeOptions {
+    returnNull: false;
+  }
+}

+ 5 - 7
packages/app/src/components/Admin/Common/AdminNavigation.jsx

@@ -55,13 +55,11 @@ const AdminNavigation = (props) => {
     const href = isRoot ? '/admin' : urljoin('/admin', menu);
 
     return (
-      <Link href={href}>
-        <a
-          href={href}
-          className={`${pageTransitionClassName} ${isActive ? 'active' : ''}`}
-        >
-          <MenuLabel menu={menu} />
-        </a>
+      <Link
+        href={href}
+        className={`${pageTransitionClassName} ${isActive ? 'active' : ''}`}
+      >
+        <MenuLabel menu={menu} />
       </Link>
     );
   };

+ 23 - 23
packages/app/src/components/Admin/ManageExternalAccount.tsx

@@ -46,32 +46,32 @@ const ManageExternalAccount = (props: ManageExternalAccountProps): JSX.Element =
     />
   );
 
-  return (
-    <>
-      <p>
-        <Link href="/admin/users" prefetch={false}>
-          <a className="btn btn-outline-secondary">
-            <i className="icon-fw ti ti-arrow-left" aria-hidden="true"></i>
-            {t('admin:user_management.back_to_user_management')}
-          </a>
-        </Link>
-      </p>
-      <h2>{t('admin:user_management.external_account_list')}</h2>
-      {(totalAccounts !== 0) ? (
+  return <>
+    <p>
+      <Link
+        href="/admin/users"
+        prefetch={false}
+        className="btn btn-outline-secondary"
+      >
+        <i className="icon-fw ti ti-arrow-left" aria-hidden="true"></i>
+        {t('admin:user_management.back_to_user_management')}
+      </Link>
+    </p>
+    <h2>{t('admin:user_management.external_account_list')}</h2>
+    {(totalAccounts !== 0) ? (
+      <>
+        {pager}
+        <ExternalAccountTable />
+        {pager}
+      </>
+    )
+      : (
         <>
-          {pager}
-          <ExternalAccountTable />
-          {pager}
+          { t('admin:user_management.external_account_none') }
         </>
       )
-        : (
-          <>
-            { t('admin:user_management.external_account_none') }
-          </>
-        )
-      }
-    </>
-  );
+    }
+  </>;
 };
 
 const ManageExternalAccountWrapper = withUnstatedContainers(ManageExternalAccount, [AdminExternalAccountsContainer]);

+ 1 - 1
packages/app/src/components/Admin/PluginsExtension/PluginCard.tsx

@@ -105,7 +105,7 @@ export const PluginCard = (props: Props): JSX.Element => {
         <div className="row mb-3">
           <div className="col-9">
             <h2 className="card-title h3 border-bottom pb-2 mb-3">
-              <Link href={`${url}`}>{name}</Link>
+              <Link href={`${url}`} legacyBehavior>{name}</Link>
             </h2>
             <p className="card-text text-muted">{desc}</p>
           </div>

+ 5 - 4
packages/app/src/components/Admin/Security/SecurityManagementContents.jsx

@@ -84,10 +84,11 @@ const SecurityManagementContents = () => {
       <div className="mb-5">
         <h2 className="border-bottom">{t('security_settings.xss_prevent_setting')}</h2>
         <div className="text-center">
-          <Link href="/admin/markdown/#preventXSS" prefetch={false}>
-            <a style={{ fontSize: 'large' }}>
-              <i className="fa-fw icon-login"></i> {t('security_settings.xss_prevent_setting_link')}
-            </a>
+          <Link
+            href="/admin/markdown/#preventXSS"
+            style={{ fontSize: 'large' }}
+          >
+            <i className="fa-fw icon-login"></i> {t('security_settings.xss_prevent_setting_link')}
           </Link>
         </div>
       </div>

+ 2 - 2
packages/app/src/components/Admin/UserGroupDetail/UserGroupDetailPage.tsx

@@ -329,7 +329,7 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
         <ol className="breadcrumb">
           <li className="breadcrumb-item">
             <Link href="/admin/user-groups" prefetch={false}>
-              <a >{t('user_group_management.group_list')}</a>
+              {t('user_group_management.group_list')}
             </Link>
           </li>
           {
@@ -343,7 +343,7 @@ const UserGroupDetailPage = (props: Props): JSX.Element => {
                   <span>{ancestorUserGroup.name}</span>
                 ) : (
                   <Link href={`/admin/user-group-detail/${ancestorUserGroup._id}`} prefetch={false}>
-                    <a href={`/admin/user-group-detail/${ancestorUserGroup._id}`}>{ancestorUserGroup.name}</a>
+                    {ancestorUserGroup.name}
                   </Link>
                 ) }
               </li>

+ 7 - 5
packages/app/src/components/Admin/UserManagement.tsx

@@ -123,11 +123,13 @@ const UserManagement = (props: UserManagementProps) => {
       ) }
       <p>
         <InviteUserControl />
-        <Link href="/admin/users/external-accounts" prefetch={false}>
-          <a className="btn btn-outline-secondary ml-2" role="button">
-            <i className="icon-user-follow mr-1" aria-hidden="true"></i>
-            {t('admin:user_management.external_account')}
-          </a>
+        <Link
+          href="/admin/users/external-accounts"
+          className="btn btn-outline-secondary ml-2"
+          role="button"
+        >
+          <i className="icon-user-follow mr-1" aria-hidden="true"></i>
+          {t('admin:user_management.external_account')}
         </Link>
       </p>
 

+ 2 - 2
packages/app/src/components/CustomNavigation/CustomNav.jsx

@@ -78,8 +78,8 @@ export const CustomNavDropdown = (props) => {
 };
 
 CustomNavDropdown.propTypes = {
-  activeTab: PropTypes.string.isRequired,
   navTabMapping: PropTypes.object.isRequired,
+  activeTab: PropTypes.string,
   onNavSelected: PropTypes.func,
 };
 
@@ -119,7 +119,7 @@ export const CustomNavTab = (props) => {
   }
 
   useEffect(() => {
-    if (activeTab === '') {
+    if (activeTab == null || activeTab === '') {
       return;
     }
 

+ 1 - 1
packages/app/src/components/CustomNavigation/CustomTabContent.tsx

@@ -10,8 +10,8 @@ import { LazyRenderer } from '../Common/LazyRenderer';
 
 
 type Props = {
-  activeTab: string,
   navTabMapping: ICustomNavTabMappings,
+  activeTab?: string,
   additionalClassNames?: string[],
 }
 

+ 13 - 6
packages/app/src/components/LoginForm.tsx

@@ -36,6 +36,7 @@ type LoginFormProps = {
 }
 export const LoginForm = (props: LoginFormProps): JSX.Element => {
   const { t } = useTranslation();
+
   const router = useRouter();
 
   const {
@@ -71,7 +72,13 @@ export const LoginForm = (props: LoginFormProps): JSX.Element => {
     }
   }, []);
 
-  // functions
+  const tWithOpt = useCallback((key: string, opt?: any): string => {
+    if (typeof opt === 'object') {
+      return t(key, opt as object);
+    }
+    return t(key);
+  }, [t]);
+
   const handleLoginWithExternalAuth = useCallback((e) => {
     const auth = e.currentTarget.id;
 
@@ -133,11 +140,11 @@ export const LoginForm = (props: LoginFormProps): JSX.Element => {
     return (
       <div className="alert alert-danger">
         {errors.map((err, index) => {
-          return <small key={index} dangerouslySetInnerHTML={{ __html: t(err.message, err.args) }}></small>;
+          return <small key={index} dangerouslySetInnerHTML={{ __html: tWithOpt(err.message, err.args) }}></small>;
         })}
       </div>
     );
-  }, [t]);
+  }, [tWithOpt]);
 
   // wrap error elements which do not use dangerouslySetInnerHtml
   const generateSafelySetErrors = useCallback((errors: (IErrorV3 | IExternalAccountLoginError)[]): JSX.Element => {
@@ -146,13 +153,13 @@ export const LoginForm = (props: LoginFormProps): JSX.Element => {
       <ul className="alert alert-danger">
         {errors.map((err, index) => {
           return (
-            <li key={index}>
-              {t(err.message, err.args)}<br/>
+            <li key={index} className={index > 0 ? 'mt-1' : ''}>
+              {tWithOpt(err.message, err.args)}
             </li>);
         })}
       </ul>
     );
-  }, [t]);
+  }, [tWithOpt]);
 
   const renderLocalOrLdapLoginForm = useCallback(() => {
     const { isLdapStrategySetup } = props;

+ 1 - 1
packages/app/src/components/Navbar/AuthorInfo.tsx

@@ -33,7 +33,7 @@ export const AuthorInfo = (props: AuthorInfoProps): JSX.Element => {
   const userLabel = user != null
     ? (
       <Link href={userPageRoot(user)} prefetch={false}>
-        <a>{user.name}</a>
+        {user.name}
       </Link>
     )
     : <i>Unknown</i>;

+ 2 - 4
packages/app/src/components/Navbar/GrowiNavbar.tsx

@@ -154,10 +154,8 @@ export const GrowiNavbar = (props: Props): JSX.Element => {
     <nav id="grw-navbar" className={`navbar grw-navbar ${styles['grw-navbar']} navbar-expand navbar-dark sticky-top mb-0 px-0`}>
       {/* Brand Logo  */}
       <div className="navbar-brand mr-0">
-        <Link href="/" prefetch={false}>
-          <a className="grw-logo d-block">
-            <GrowiNavbarLogo isDefaultLogo={isDefaultLogo} />
-          </a>
+        <Link href="/" className="grw-logo d-block">
+          <GrowiNavbarLogo isDefaultLogo={isDefaultLogo} />
         </Link>
       </div>
 

+ 12 - 8
packages/app/src/components/Navbar/PersonalDropdown.jsx

@@ -54,15 +54,19 @@ const PersonalDropdown = () => {
           </div>
 
           <div className="btn-group btn-block mt-2" role="group">
-            <Link href={`/user/${user.username}`}>
-              <a className="btn btn-sm btn-outline-secondary col" data-testid="grw-personal-dropdown-menu-user-home">
-                <i className="icon-fw icon-home"></i>{t('personal_dropdown.home')}
-              </a>
+            <Link
+              href={`/user/${user.username}`}
+              className="btn btn-sm btn-outline-secondary col"
+              data-testid="grw-personal-dropdown-menu-user-home"
+            >
+              <i className="icon-fw icon-home"></i>{t('personal_dropdown.home')}
             </Link>
-            <Link href="/me">
-              <a className="btn btn-sm btn-outline-secondary col" data-testid="grw-personal-dropdown-menu-user-settings">
-                <i className="icon-fw icon-wrench"></i>{t('personal_dropdown.settings')}
-              </a>
+            <Link
+              href="/me"
+              className="btn btn-sm btn-outline-secondary col"
+              data-testid="grw-personal-dropdown-menu-user-settings"
+            >
+              <i className="icon-fw icon-wrench"></i>{t('personal_dropdown.settings')}
             </Link>
           </div>
         </div>

+ 9 - 22
packages/app/src/components/PageAccessoriesModal.tsx

@@ -26,7 +26,7 @@ const PageAccessoriesModal = (): JSX.Element => {
 
   const { t } = useTranslation();
 
-  const [activeTab, setActiveTab] = useState<PageAccessoriesModalContents>(PageAccessoriesModalContents.PageHistory);
+  const [activeTab, setActiveTab] = useState<PageAccessoriesModalContents>();
   const [sourceRevisionId, setSourceRevisionId] = useState<string>();
   const [targetRevisionId, setTargetRevisionId] = useState<string>();
 
@@ -38,18 +38,15 @@ const PageAccessoriesModal = (): JSX.Element => {
 
   const { data: status, mutate, close } = usePageAccessoriesModal();
 
-  // add event handler when opened
+  // activate tab when open
   useEffect(() => {
-    if (status == null || status.onOpened != null) {
-      return;
+    if (status == null) return;
+
+    const { isOpened, activatedContents } = status;
+    if (isOpened && activatedContents != null) {
+      setActiveTab(activatedContents);
     }
-    mutate({
-      ...status,
-      onOpened: (activatedContents) => {
-        setActiveTab(activatedContents);
-      },
-    }, false);
-  }, [mutate, status]);
+  }, [status]);
 
   // Set sourceRevisionId and targetRevisionId as state with valid object id string
   useEffect(() => {
@@ -74,14 +71,10 @@ const PageAccessoriesModal = (): JSX.Element => {
   }, [mutate]);
 
   const navTabMapping = useMemo(() => {
-    const isOpened = status == null ? false : status.isOpened;
     return {
       [PageAccessoriesModalContents.PageHistory]: {
         Icon: HistoryIcon,
         Content: () => {
-          if (!isOpened) {
-            return <></>;
-          }
           return <PageHistory onClose={close} sourceRevisionId={sourceRevisionId} targetRevisionId={targetRevisionId}/>;
         },
         i18n: t('History'),
@@ -91,9 +84,6 @@ const PageAccessoriesModal = (): JSX.Element => {
       [PageAccessoriesModalContents.Attachment]: {
         Icon: AttachmentIcon,
         Content: () => {
-          if (!isOpened) {
-            return <></>;
-          }
           return <PageAttachment />;
         },
         i18n: t('attachment_data'),
@@ -102,9 +92,6 @@ const PageAccessoriesModal = (): JSX.Element => {
       [PageAccessoriesModalContents.ShareLink]: {
         Icon: ShareLinkIcon,
         Content: () => {
-          if (!isOpened) {
-            return <></>;
-          }
           return <ShareLink />;
         },
         i18n: t('share_links.share_link_management'),
@@ -112,7 +99,7 @@ const PageAccessoriesModal = (): JSX.Element => {
         isLinkEnabled: () => !isGuestUser && !isSharedUser && !isLinkSharingDisabled,
       },
     };
-  }, [status, t, close, sourceRevisionId, targetRevisionId, isGuestUser, isSharedUser, isLinkSharingDisabled]);
+  }, [t, close, sourceRevisionId, targetRevisionId, isGuestUser, isSharedUser, isLinkSharingDisabled]);
 
   const buttons = useMemo(() => (
     <div className="d-flex flex-nowrap">

+ 1 - 1
packages/app/src/components/PageAlert/OldRevisionAlert.tsx

@@ -22,7 +22,7 @@ export const OldRevisionAlert = (): JSX.Element => {
     <div className="alert alert-warning">
       <strong>{t('Warning')}: </strong> {t('page_page.notice.version')}
       <Link href={returnPathForURL(page.path, page._id)}>
-        <a><i className="icon-fw icon-arrow-right-circle"></i>{t('Show latest')}</a>
+        <i className="icon-fw icon-arrow-right-circle"></i>{t('Show latest')}
       </Link>
     </div>
   );

+ 8 - 7
packages/app/src/components/PageComment/Comment.tsx

@@ -163,9 +163,7 @@ export const Comment = (props: CommentProps): JSX.Element => {
             <div className="page-comment-body">{commentBody}</div>
             <div className="page-comment-meta">
               <Link href={`#${commentId}`} prefetch={false}>
-                <a>
-                  <FormattedDistanceDate id={commentId} date={comment.createdAt} />
-                </a>
+                <FormattedDistanceDate id={commentId} date={comment.createdAt} />
               </Link>
               { isEdited && (
                 <>
@@ -174,10 +172,13 @@ export const Comment = (props: CommentProps): JSX.Element => {
                 </>
               ) }
               <span className="ml-2">
-                <Link href={urljoin(returnPathForURL(pagePath, pageId), revHref)} prefetch={false}>
-                  <a id={`page-comment-revision-${commentId}`} className="page-comment-revision">
-                    <HistoryIcon />
-                  </a>
+                <Link
+                  id={`page-comment-revision-${commentId}`}
+                  href={urljoin(returnPathForURL(pagePath, pageId), revHref)}
+                  className="page-comment-revision"
+                  prefetch={false}
+                >
+                  <HistoryIcon />
                 </Link>
                 <UncontrolledTooltip placement="bottom" fade={false} target={`page-comment-revision-${commentId}`}>
                   {t('page_comment.display_the_page_when_posting_this_comment')}

+ 1 - 1
packages/app/src/components/PageEditorByHackmd.tsx

@@ -364,7 +364,7 @@ export const PageEditorByHackmd = (): JSX.Element => {
                 {t('hackmd.based_on_revision')}&nbsp;
                 { pageData != null && (
                   <Link href={urljoin(returnPathForURL(pageData.path, pageData._id), `?revisionId=${revisionIdHackmdSynced}`)} prefetch={false}>
-                    <a><span className="badge badge-secondary">{revisionIdHackmdSynced?.substr(-8)}</span></a>
+                    <span className="badge badge-secondary">{revisionIdHackmdSynced?.substr(-8)}</span>
                   </Link>
                 )}
                 <div className="text-center mt-3">

+ 7 - 4
packages/app/src/components/PageHistory/Revision.tsx

@@ -69,10 +69,13 @@ export const Revision = (props: RevisionProps): JSX.Element => {
           <div className="mb-1">
             <UserDate dateTime={revision.createdAt} />
             <br className="d-xl-none d-block" />
-            <Link href={urljoin(returnPathForURL(currentPagePath, currentPageId), `?revisionId=${revision._id}`)} prefetch={false}>
-              <a className="ml-xl-3" onClick={onClose}>
-                <i className="icon-login"></i> {t('Go to this version')}
-              </a>
+            <Link
+              href={urljoin(returnPathForURL(currentPagePath, currentPageId), `?revisionId=${revision._id}`)}
+              className="ml-xl-3"
+              onClick={onClose}
+              prefetch={false}
+            >
+              <i className="icon-login"></i> {t('Go to this version')}
             </Link>
           </div>
         </div>

+ 14 - 8
packages/app/src/components/PageHistory/RevisionDiff.tsx

@@ -55,18 +55,24 @@ export const RevisionDiff = (props: RevisioinDiffProps): JSX.Element => {
           <div className="row">
             <div className="col comparison-source-wrapper pt-1 px-0">
               <span className="comparison-source pr-3">{t('page_history.comparing_source')}</span><UserDate dateTime={previousRevision.createdAt} />
-              <Link href={urljoin(returnPathForURL(currentPagePath, currentPageId), `?revisionId=${previousRevision._id}`)}>
-                <a className="ml-3" onClick={onClose}>
-                  <i className="icon-login"></i>
-                </a>
+              <Link
+                href={urljoin(returnPathForURL(currentPagePath, currentPageId), `?revisionId=${previousRevision._id}`)}
+                className="ml-3"
+                onClick={onClose}
+                prefetch={false}
+              >
+                <i className="icon-login"></i>
               </Link>
             </div>
             <div className="col comparison-target-wrapper pt-1">
               <span className="comparison-target pr-3">{t('page_history.comparing_target')}</span><UserDate dateTime={currentRevision.createdAt} />
-              <Link href={urljoin(returnPathForURL(currentPagePath, currentPageId), `?revisionId=${currentRevision._id}`)}>
-                <a className="ml-3" onClick={onClose}>
-                  <i className="icon-login"></i>
-                </a>
+              <Link
+                href={urljoin(returnPathForURL(currentPagePath, currentPageId), `?revisionId=${currentRevision._id}`)}
+                className="ml-3"
+                onClick={onClose}
+                prefetch={false}
+              >
+                <i className="icon-login"></i>
               </Link>
             </div>
           </div>

+ 4 - 1
packages/app/src/components/PageList/PageListItemL.tsx

@@ -221,7 +221,10 @@ const PageListItemLSubstance: ForwardRefRenderFunction<ISelectable, Props> = (pr
                 <span className="h5 mb-0">
                   {/* Use permanent links to care for pages with the same name (Cannot use page path url) */}
                   <span className="grw-page-path-hierarchical-link text-break">
-                    <Link href={returnPathForURL(pageData.path, pageData._id)} prefetch={false}>
+                    <Link legacyBehavior
+                      href={returnPathForURL(pageData.path, pageData._id)}
+                      prefetch={false}
+                    >
                       {shouldDangerouslySetInnerHTMLForPaths
                         ? (
                           <a

+ 4 - 6
packages/app/src/components/PagePathHierarchicalLink.tsx

@@ -40,7 +40,7 @@ const PagePathHierarchicalLink = memo((props: PagePathHierarchicalLinkProps): JS
         <RootElm>
           <span className="path-segment">
             <Link href="/trash" prefetch={false}>
-              <a ><i className="icon-trash"></i></a>
+              <i className="icon-trash"></i>
             </Link>
           </span>
           <span className="separator"><a href="/">/</a></span>
@@ -50,10 +50,8 @@ const PagePathHierarchicalLink = memo((props: PagePathHierarchicalLinkProps): JS
         <RootElm>
           <span className="path-segment">
             <Link href="/" prefetch={false}>
-              <a >
-                <i className="icon-home"></i>
-                <span className="separator">/</span>
-              </a>
+              <i className="icon-home"></i>
+              <span className="separator">/</span>
             </Link>
           </span>
         </RootElm>
@@ -83,7 +81,7 @@ const PagePathHierarchicalLink = memo((props: PagePathHierarchicalLinkProps): JS
         <span className="separator">/</span>
       ) }
 
-      <Link href={href} prefetch={false}>
+      <Link href={href} prefetch={false} legacyBehavior>
         {
           shouldDangerouslySetInnerHTML
             // eslint-disable-next-line react/no-danger

+ 1 - 1
packages/app/src/components/PageTimeline.tsx

@@ -26,7 +26,7 @@ const TimelineCard = ({ page }: TimelineCardProps): JSX.Element => {
     <div className={`card card-timeline ${styles['card-timeline']}`}>
       <div className="card-header h4 p-3">
         <Link href={page.path} prefetch={false}>
-          <a>{page.path}</a>
+          {page.path}
         </Link>
       </div>
       <div className="card-body">

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

@@ -81,9 +81,7 @@ const PasswordResetExecutionForm: FC = () => {
         <input name="reset-password-btn" className="btn btn-lg btn-primary btn-block" value={t('forgot_password.reset_password')} type="submit" />
       </div>
       <Link href="/login" prefetch={false}>
-        <a>
-          <i className="icon-login mr-1"></i>{t('forgot_password.sign_in_instead')}
-        </a>
+        <i className="icon-login mr-1"></i>{t('forgot_password.sign_in_instead')}
       </Link>
     </form>
   );

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

@@ -48,9 +48,7 @@ const PasswordResetRequestForm: FC = () => {
         </button>
       </div>
       <Link href='/login' prefetch={false}>
-        <a>
-          <i className="icon-login mr-1" />{t('forgot_password.return_to_login')}
-        </a>
+        <i className="icon-login mr-1" />{t('forgot_password.return_to_login')}
       </Link>
     </form>
   );

+ 1 - 1
packages/app/src/components/ReactMarkdownComponents/NextLink.tsx

@@ -60,7 +60,7 @@ export const NextLink = (props: Props): JSX.Element => {
   }
 
   return (
-    <Link {...rest} href={href} prefetch={false}>
+    <Link {...rest} href={href} prefetch={false} legacyBehavior>
       <a href={href} className={className} {...dataAttributes}>{children}</a>
     </Link>
   );

+ 3 - 1
packages/app/src/components/SearchPage/SearchPageBase.tsx

@@ -150,7 +150,9 @@ const SearchPageBaseSubstance: ForwardRefRenderFunction<ISelectableAll & IReturn
   }
 
   const highlightKeywords = searchingKeyword != null
-    ? searchingKeyword.match(highlightKeywordsSplitter) ?? undefined
+    // Remove double quotation marks before and after a keyword if present
+    // https://regex101.com/r/4QKBwg/1
+    ? searchingKeyword.match(highlightKeywordsSplitter)?.map(keyword => keyword.replace(/^"(.*)"$/, '$1')) ?? undefined
     : undefined;
 
   return (

+ 2 - 2
packages/app/src/components/Sidebar/CustomSidebar.tsx

@@ -23,7 +23,7 @@ const SidebarNotFound = () => {
   return (
     <div className="grw-sidebar-content-header h5 text-center py-3">
       <Link href="/Sidebar#edit">
-        <a><i className="icon-magic-wand"></i> Create <strong>/Sidebar</strong> page</a>
+        <i className="icon-magic-wand"></i>Create<strong>/Sidebar</strong>page
       </Link>
     </div>
   );
@@ -47,7 +47,7 @@ const CustomSidebar: FC = () => {
       <div className="grw-sidebar-content-header py-3 d-flex">
         <h3 className="mb-0">
           {t('CustomSidebar')}
-          <Link href="/Sidebar#edit"><a className="h6 ml-2"><i className="icon-pencil"></i></a></Link>
+          <Link href="/Sidebar#edit" className="h6 ml-2"><i className="icon-pencil"></i></Link>
         </h3>
         <SidebarHeaderReloadButton onClick={() => mutate()} />
       </div>

+ 6 - 4
packages/app/src/components/Sidebar/PageTree/Item.tsx

@@ -472,10 +472,12 @@ const Item: FC<ItemProps> = (props: ItemProps) => {
                 </>
               )}
               { page != null && page.path != null && page._id != null && (
-                <Link href={pathUtils.returnPathForURL(page.path, page._id)} prefetch={false}>
-                  <a className="grw-pagetree-title-anchor flex-grow-1">
-                    <p className={`text-truncate m-auto ${page.isEmpty && 'grw-sidebar-text-muted'}`}>{nodePath.basename(page.path ?? '') || '/'}</p>
-                  </a>
+                <Link
+                  href={pathUtils.returnPathForURL(page.path, page._id)}
+                  className="grw-pagetree-title-anchor flex-grow-1"
+                  prefetch={false}
+                >
+                  <p className={`text-truncate m-auto ${page.isEmpty && 'grw-sidebar-text-muted'}`}>{nodePath.basename(page.path ?? '') || '/'}</p>
                 </Link>
               )}
             </>

+ 7 - 5
packages/app/src/components/Sidebar/PageTree/PrivateLegacyPagesLink.tsx

@@ -1,17 +1,19 @@
 import React, { FC, memo } from 'react';
 
+import { useTranslation } from 'next-i18next';
 import Link from 'next/link';
 
-import { useTranslation } from 'next-i18next';
 
 export const PrivateLegacyPagesLink: FC = memo(() => {
   const { t } = useTranslation();
 
   return (
-    <Link href="/_private-legacy-pages" prefetch={false}>
-      <a className="h5 grw-private-legacy-pages-anchor text-decoration-none">
-        <i className="icon-drawer mr-2"></i> {t('private_legacy_pages.title')}
-      </a>
+    <Link
+      href="/_private-legacy-pages"
+      className="h5 grw-private-legacy-pages-anchor text-decoration-none"
+      prefetch={false}
+    >
+      <i className="icon-drawer mr-2"></i> {t('private_legacy_pages.title')}
     </Link>
   );
 });

+ 7 - 4
packages/app/src/components/Sidebar/RecentChanges.tsx

@@ -70,10 +70,13 @@ const PageItem = memo(({ page, isSmall }: PageItemProps): JSX.Element => {
       return <></>;
     }
     return (
-      <Link key={tag.name} href={`/_search?q=tag:${tag.name}`} prefetch={false}>
-        <a className="grw-tag-label badge badge-secondary mr-2 small">
-          {tag.name}
-        </a>
+      <Link
+        key={tag.name}
+        href={`/_search?q=tag:${tag.name}`}
+        className="grw-tag-label badge badge-secondary mr-2 small"
+        prefetch={false}
+      >
+        {tag.name}
       </Link>
     );
   });

+ 7 - 4
packages/app/src/components/Sidebar/SidebarNav.tsx

@@ -64,10 +64,13 @@ const SecondaryItem: FC<SecondaryItemProps> = memo((props: SecondaryItemProps) =
   const { iconName, href, isBlank } = props;
 
   return (
-    <Link href={href} prefetch={false}>
-      <a className="d-block btn btn-primary" target={`${isBlank ? '_blank' : ''}`}>
-        <i className="material-icons">{iconName}</i>
-      </a>
+    <Link
+      href={href}
+      className="d-block btn btn-primary"
+      target={`${isBlank ? '_blank' : ''}`}
+      prefetch={false}
+    >
+      <i className="material-icons">{iconName}</i>
     </Link>
   );
 });

+ 5 - 4
packages/app/src/components/TagCloudBox.tsx

@@ -31,11 +31,12 @@ const TagCloudBox: FC<Props> = memo((props:(Props & typeof defaultProps)) => {
 
     return (
       <Link
-        key={tag.name} href={`${url.pathname}${url.search}`}
+        key={tag.name}
+        href={`${url.pathname}${url.search}`}
+        className="grw-tag-label badge badge-secondary mr-2"
+        prefetch={false}
       >
-        <a className="grw-tag-label badge badge-secondary mr-2">
-          {tagNameFormat}
-        </a>
+        {tagNameFormat}
       </Link>
     );
   });

+ 4 - 6
packages/app/src/components/TagList.tsx

@@ -40,13 +40,11 @@ const TagList: FC<TagListProps> = (props:(TagListProps & typeof defaultProps)) =
         <Link
           key={tag._id}
           href={`${url.pathname}${url.search}`}
+          className={tagListClasses}
+          prefetch={false}
         >
-          <a
-            className={tagListClasses}
-          >
-            <div className="text-truncate list-tag-name">{tag.name}</div>
-            <div className="ml-4 my-auto py-1 px-2 list-tag-count badge badge-secondary text-white">{tag.count}</div>
-          </a>
+          <div className="text-truncate list-tag-name">{tag.name}</div>
+          <div className="ml-4 my-auto py-1 px-2 list-tag-count badge badge-secondary text-white">{tag.count}</div>
         </Link>
       );
     });

+ 1 - 1
packages/app/src/components/User/Username.tsx

@@ -20,7 +20,7 @@ export const Username = (props: UsernameProps): JSX.Element => {
 
   return (
     <Link href={href} prefetch={false}>
-      <a>{name} (@{username})</a>
+      {name}(@{username})
     </Link>
   );
 };

+ 2 - 4
packages/app/src/pages/forgot-password-errors.page.tsx

@@ -42,10 +42,8 @@ const ForgotPasswordErrorsPage: NextPage<Props> = (props: Props) => {
                     <div className="alert alert-warning mb-3">
                       <h2>{ t('forgot_password.incorrect_token_or_expired_url') }</h2>
                     </div>
-                    <Link href="/forgot-password" prefetch={false}>
-                      <a className="link-switch">
-                        <i className="icon-key"></i> { t('forgot_password.forgot_password') }
-                      </a>
+                    <Link href="/forgot-password" className="link-switch" prefetch={false}>
+                      <i className="icon-key"></i> { t('forgot_password.forgot_password') }
                     </Link>
                   </div>
                 ) }

+ 5 - 3
packages/app/src/server/models/page.ts

@@ -57,7 +57,7 @@ type PaginatedPages = {
 export type CreateMethod = (path: string, body: string, user, options: PageCreateOptions) => Promise<PageDocument & { _id: any }>
 export interface PageModel extends Model<PageDocument> {
   [x: string]: any; // for obsolete static methods
-  findByIdsAndViewer(pageIds: ObjectIdLike[], user, userGroups?, includeEmpty?: boolean): Promise<PageDocument[]>
+  findByIdsAndViewer(pageIds: ObjectIdLike[], user, userGroups?, includeEmpty?: boolean, includeAnyoneWithTheLink?: boolean): Promise<PageDocument[]>
   findByPathAndViewer(path: string | null, user, userGroups?, useFindOne?: true, includeEmpty?: boolean): Promise<PageDocument & HasObjectId | null>
   findByPathAndViewer(path: string | null, user, userGroups?, useFindOne?: false, includeEmpty?: boolean): Promise<(PageDocument & HasObjectId)[]>
   countByPathAndViewer(path: string | null, user, userGroups?, includeEmpty?:boolean): Promise<number>
@@ -553,11 +553,13 @@ schema.statics.replaceTargetWithPage = async function(exPage, pageToReplaceWith?
 /*
  * Find pages by ID and viewer.
  */
-schema.statics.findByIdsAndViewer = async function(pageIds: string[], user, userGroups?, includeEmpty?: boolean): Promise<PageDocument[]> {
+schema.statics.findByIdsAndViewer = async function(
+    pageIds: string[], user, userGroups?, includeEmpty?: boolean, includeAnyoneWithTheLink?: boolean,
+): Promise<PageDocument[]> {
   const baseQuery = this.find({ _id: { $in: pageIds } });
   const queryBuilder = new PageQueryBuilder(baseQuery, includeEmpty);
 
-  await queryBuilder.addViewerCondition(user, userGroups);
+  await queryBuilder.addViewerCondition(user, userGroups, includeAnyoneWithTheLink);
 
   return queryBuilder.query.exec();
 };

+ 15 - 2
packages/app/src/server/routes/apiv3/pages.js

@@ -1,6 +1,7 @@
 
 import { SupportedTargetModel, SupportedAction } from '~/interfaces/activity';
 import { subscribeRuleNames } from '~/interfaces/in-app-notification';
+import { PageGrant } from '~/interfaces/page';
 import loggerFactory from '~/utils/logger';
 
 import { generateAddActivityMiddleware } from '../../middlewares/add-activity';
@@ -202,6 +203,9 @@ module.exports = (crowi) => {
       body('isRecursively')
         .custom(v => v === 'true' || v === true || v == null)
         .withMessage('The body property "isRecursively" must be "true" or true. (Omit param for false)'),
+      body('isAnyoneWithTheLink')
+        .custom(v => v === 'true' || v === true || v == null)
+        .withMessage('The body property "isAnyoneWithTheLink" must be "true" or true. (Omit param for false)'),
     ],
     legacyPagesMigration: [
       body('convertPath').optional().isString().withMessage('convertPath must be a string'),
@@ -831,24 +835,33 @@ module.exports = (crowi) => {
   });
 
   router.post('/delete', accessTokenParser, loginRequiredStrictly, validator.deletePages, apiV3FormValidator, async(req, res) => {
-    const { pageIdToRevisionIdMap, isCompletely, isRecursively } = req.body;
+    const {
+      pageIdToRevisionIdMap, isCompletely, isRecursively, isAnyoneWithTheLink,
+    } = req.body;
+
     const pageIds = Object.keys(pageIdToRevisionIdMap);
 
     if (pageIds.length === 0) {
       return res.apiv3Err(new ErrorV3('Select pages to delete.', 'no_page_selected'), 400);
     }
+    if (isAnyoneWithTheLink && pageIds.length !== 1) {
+      return res.apiv3Err(new ErrorV3('Only one restricted page can be selected', 'not_single_page'), 400);
+    }
     if (pageIds.length > LIMIT_FOR_MULTIPLE_PAGE_OP) {
       return res.apiv3Err(new ErrorV3(`The maximum number of pages you can select is ${LIMIT_FOR_MULTIPLE_PAGE_OP}.`, 'exceeded_maximum_number'), 400);
     }
 
     let pagesToDelete;
     try {
-      pagesToDelete = await Page.findByIdsAndViewer(pageIds, req.user, null, true);
+      pagesToDelete = await Page.findByIdsAndViewer(pageIds, req.user, null, true, isAnyoneWithTheLink);
     }
     catch (err) {
       logger.error('Failed to find pages to delete.', err);
       return res.apiv3Err(new ErrorV3('Failed to find pages to delete.'));
     }
+    if (isAnyoneWithTheLink && pagesToDelete[0].grant !== PageGrant.GRANT_RESTRICTED) {
+      return res.apiv3Err(new ErrorV3('The grant of the retrieved page is not restricted'), 500);
+    }
 
     let pagesCanBeDeleted;
     /*

+ 3 - 0
packages/app/src/services/renderer/renderer.tsx

@@ -197,6 +197,9 @@ export const generateViewOptions = (
     components.h1 = Header;
     components.h2 = Header;
     components.h3 = Header;
+    components.h4 = Header;
+    components.h5 = Header;
+    components.h6 = Header;
     components.lsx = Lsx;
     components.drawio = DrawioViewerWithEditButton;
     components.table = TableWithEditButton;

+ 5 - 6
packages/app/src/stores/modal.tsx

@@ -345,7 +345,7 @@ export type PageAccessoriesModalContents = typeof PageAccessoriesModalContents[k
 
 type PageAccessoriesModalStatus = {
   isOpened: boolean,
-  onOpened?: (initialActivatedContents: PageAccessoriesModalContents) => void,
+  activatedContents?: PageAccessoriesModalContents,
 }
 
 type PageAccessoriesModalUtils = {
@@ -364,11 +364,10 @@ export const usePageAccessoriesModal = (): SWRResponse<PageAccessoriesModalStatu
       if (swrResponse.data == null) {
         return;
       }
-      swrResponse.mutate({ isOpened: true });
-
-      if (swrResponse.data.onOpened != null) {
-        swrResponse.data.onOpened(activatedContents);
-      }
+      swrResponse.mutate({
+        isOpened: true,
+        activatedContents,
+      });
     },
     close: () => {
       if (swrResponse.data == null) {

+ 2 - 2
packages/remark-lsx/src/components/LsxPageList/LsxPage.tsx

@@ -82,8 +82,8 @@ export const LsxPage = React.memo((props: Props): JSX.Element => {
         : encodeURI(pathUtils.removeTrailingSlash(pagePath));
 
       pagePathNode = (
-        <Link href={href} prefetch={false}>
-          <a className="page-list-link" href={href}>{pagePathNode}</a>
+        <Link href={href} prefetch={false} className="page-list-link">
+          {pagePathNode}
         </Link>
       );
     }

+ 158 - 165
yarn.lock

@@ -1438,13 +1438,6 @@
   dependencies:
     regenerator-runtime "^0.13.4"
 
-"@babel/runtime@^7.14.5", "@babel/runtime@^7.17.2":
-  version "7.18.6"
-  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.6.tgz#6a1ef59f838debd670421f8c7f2cbb8da9751580"
-  integrity sha512-t9wi7/AW6XtKahAe20Yw0/mMljKq0B1r2fPdvaAdV/KPDZewFXdaaa6K7lxmZBZ8FBNpCiAT6iHPmd6QO9bKfQ==
-  dependencies:
-    regenerator-runtime "^0.13.4"
-
 "@babel/runtime@^7.14.6", "@babel/runtime@^7.15.4", "@babel/runtime@^7.9.2":
   version "7.16.7"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.7.tgz#03ff99f64106588c9c403c6ecb8c3bafbbdff1fa"
@@ -1452,13 +1445,20 @@
   dependencies:
     regenerator-runtime "^0.13.4"
 
-"@babel/runtime@^7.18.9", "@babel/runtime@^7.19.4":
+"@babel/runtime@^7.19.4":
   version "7.19.4"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.19.4.tgz#a42f814502ee467d55b38dd1c256f53a7b885c78"
   integrity sha512-EXpLCrk55f+cYqmHsSR+yD/0gAIMxxA9QK9lnQWzhMCvt+YmoBN7Zx94s++Kv0+unHk39vxNO8t+CMA2WSS3wA==
   dependencies:
     regenerator-runtime "^0.13.4"
 
+"@babel/runtime@^7.20.13", "@babel/runtime@^7.20.6":
+  version "7.21.0"
+  resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.21.0.tgz#5b55c9d394e5fcf304909a8b00c07dc217b56673"
+  integrity sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==
+  dependencies:
+    regenerator-runtime "^0.13.11"
+
 "@babel/runtime@^7.3.1":
   version "7.18.9"
   resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.18.9.tgz#b4fcfce55db3d2e5e080d2490f608a3b9f407f4a"
@@ -2954,17 +2954,17 @@
     markdown-it-front-matter "^0.2.3"
     postcss "^8.4.19"
 
-"@next/bundle-analyzer@^12.2.3":
-  version "12.2.3"
-  resolved "https://registry.yarnpkg.com/@next/bundle-analyzer/-/bundle-analyzer-12.2.3.tgz#8b4b934d28c09b9c11c4a074fbcc444402c8e017"
-  integrity sha512-tRgyo5afC02eofvnN9IerUvTJpxV+eQH4S02hc1U4oJJOhpHbwRinFUE3u4SNWbT5wSFofv1tnw5rYhyX7W8wQ==
+"@next/bundle-analyzer@^13.2.3":
+  version "13.2.3"
+  resolved "https://registry.yarnpkg.com/@next/bundle-analyzer/-/bundle-analyzer-13.2.3.tgz#8a34f595f9d213b39fc68f5246f59d5043f8c6f4"
+  integrity sha512-hPAT0ja6zHmEIrLYAWmdtpS07FCuUL8TxKP5ekzel+NoP4cNOykBS2Y265ciJwurpisd8Ux29g3QgeyBBSBnLA==
   dependencies:
-    webpack-bundle-analyzer "4.3.0"
+    webpack-bundle-analyzer "4.7.0"
 
-"@next/env@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/env/-/env-12.2.6.tgz#5903853efa7e44e6280f4e805d07499b99f4b240"
-  integrity sha512-THKlM+l5a2JUKEC3/X+qZ74gACapD/OQ1dz9p2hi504FB3vdgUgh2lswkWvjLZssxBdHW0FJiWoUYf8z19vxuw==
+"@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/eslint-plugin-next@12.1.6":
   version "12.1.6"
@@ -2973,70 +2973,70 @@
   dependencies:
     glob "7.1.7"
 
-"@next/swc-android-arm-eabi@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-android-arm-eabi/-/swc-android-arm-eabi-12.2.6.tgz#6ca64fc3e3b37b55e61bc294adf17fc523167200"
-  integrity sha512-dDo8Dxz/+v7gM7y0GwKunl4iMyoXDJV4xhH3zsO2yYReK+WL/KTJxRMzxtRJIiH9XFHHzdxnL935067r4hs1+A==
-
-"@next/swc-android-arm64@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-android-arm64/-/swc-android-arm64-12.2.6.tgz#5a36130c2aee1f10f97a1b6f113f3132b1da80e6"
-  integrity sha512-l547hA/ddEnqCEhJgZ7exnTAvLdw6kcDmO/C+S0C6Pg63doNO/OwOD9tNqX7yU8EhJLOYFG07Ei3hPMeOGiEDw==
-
-"@next/swc-darwin-arm64@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-12.2.6.tgz#01aa6eeb457fbec3fd8775db6c37c87ef3233b8b"
-  integrity sha512-3HnlL7l/0S5YR4Wvi8BDWvqwbr0V/D034/pcaRlRK/bNWUA7PzjI6RuJ2HFdNVl9W/bUD6i5EoE7xQpRa8AFRA==
-
-"@next/swc-darwin-x64@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-12.2.6.tgz#ecef189e380b1212b6fdd409813b6e9bbfa2e593"
-  integrity sha512-praySt/hINjb8vI2J67sNvHGTvTmAVZqw8XewTWL7krj4MoiX2lTY+SsIKdfWkkYaae0OqufoPeOqXk3R7xE3g==
-
-"@next/swc-freebsd-x64@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-freebsd-x64/-/swc-freebsd-x64-12.2.6.tgz#611db3160d4c8ef0cf66ecd340ce1f05d2e1bb39"
-  integrity sha512-p8TU7HCNjFEf7pLrKG0fAtuHKbIk8XWLCFvn0n54RvGAnQmwo0kzghU0I8RFzcl/XFbVhxg5oX9Npx/GBlPgcw==
-
-"@next/swc-linux-arm-gnueabihf@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm-gnueabihf/-/swc-linux-arm-gnueabihf-12.2.6.tgz#27e977c115d495721434976435e7673718596ef1"
-  integrity sha512-l7yqnAVjYKECDytU6LBLqVYex473fp/e5xb/4wHIxSoAWH7OCfCH1UT+TdKXZBfeupBKlUhin7Rw//lWuq2qew==
-
-"@next/swc-linux-arm64-gnu@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-12.2.6.tgz#db353803c25bee7eb27af0640069901b634f22cf"
-  integrity sha512-UDy+1ynNSW27KJBj7mZSOopc9uavPQP31ywwVhcOVtTKMdEzZ5z3ZKsPUTsuJuihN/J5BGQke5PIh9KwMSEvkA==
-
-"@next/swc-linux-arm64-musl@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-12.2.6.tgz#8e45531b5fa08917f1ad63f628c3d67fbae6d1f8"
-  integrity sha512-6AVgmBi5gMZIdXh8GIrbW8Bf21wO993TZ5eeuIFXgKW7j30Xt+NnYxfq6ElilQnyrxdmhan8Efovx2pb5fWjMQ==
-
-"@next/swc-linux-x64-gnu@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-12.2.6.tgz#262680e69274cdffd8a57a178e35f7af846a46cf"
-  integrity sha512-JjixyBnwsdbdQedku8cWAeJ+E562TE3WsjYcFCaCrASa4hW8SrJsqm2fTe6Q0Tu5bCy4TwCNjo9Tjwgp88pCeg==
-
-"@next/swc-linux-x64-musl@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-12.2.6.tgz#1b754b404ed9ca80407a63ce04c096776d5b77f3"
-  integrity sha512-EQGRzdJKIrWVsn2/B7k0BdJ7N4yOYhR+6pr7DuIGnzJRo4CIZRMKs7dOvvnxtgHky3Swu5vIFOPp+qSdYmck8A==
-
-"@next/swc-win32-arm64-msvc@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-12.2.6.tgz#457c955b3787a7d00abc241415889e1cadc491cc"
-  integrity sha512-87jDRqWPH5J7HrLKSmVjnC+FGAPWvUhQUe1p5dROawsDrCJtNFPuxmOifDid9saW99CDpcOxu3xZ7HWbp9XO7A==
-
-"@next/swc-win32-ia32-msvc@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-12.2.6.tgz#6f6acae984e7ae08b9c4959e0b91752babb29f6e"
-  integrity sha512-IjAuEVybts1pguSHbPvk+KQEMnyyQnrhn7yaxphYfIh8wPhsxwKXJY+AN4WrxqA4gbO+sgpMxZW3bhqJmYKWGw==
-
-"@next/swc-win32-x64-msvc@12.2.6":
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-12.2.6.tgz#7ca74a12b2f46d8cbaca18de11547797db7a86b1"
-  integrity sha512-AQ1QbiJ13I+47wXRjJuOUmBp9tmEqEhhqFoaKrFvbj6v4ekZS5/2tlybaZxrVB5mF5Tqu/OcLp5fCqXrDxHbXw==
+"@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==
 
 "@nodelib/fs.scandir@2.1.3":
   version "2.1.3"
@@ -3636,10 +3636,10 @@
     "@swc/core-win32-ia32-msvc" "1.2.239"
     "@swc/core-win32-x64-msvc" "1.2.239"
 
-"@swc/helpers@0.4.3":
-  version "0.4.3"
-  resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.3.tgz#16593dfc248c53b699d4b5026040f88ddb497012"
-  integrity sha512-6JrF+fdUK2zbGpJIlN7G3v966PQjyx/dPt1T9km2wj+EUBqgrxCk3uX4Kct16MIm9gGxfKRcfax2hVf5jvlTzA==
+"@swc/helpers@0.4.14":
+  version "0.4.14"
+  resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.4.14.tgz#1352ac6d95e3617ccb7c1498ff019654f1e12a74"
+  integrity sha512-4C7nX/dvpzB7za4Ql9K81xK3HPxCpHMgwTZVyf+9JQ6VUbn9jjZVN7/Nkdz/Ugzs2CSjqnL/UPXroiVBVHUWUw==
   dependencies:
     tslib "^2.4.0"
 
@@ -6380,16 +6380,16 @@ caniuse-lite@^1.0.30001219:
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001248.tgz#26ab45e340f155ea5da2920dadb76a533cb8ebce"
   integrity sha512-NwlQbJkxUFJ8nMErnGtT0QTM2TJ33xgz4KXJSMIrjXIbDVdaYueGyjOrLKRtJC+rTiWfi6j5cnZN1NBiSBJGNw==
 
-caniuse-lite@^1.0.30001332:
-  version "1.0.30001441"
-  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001441.tgz#987437b266260b640a23cd18fbddb509d7f69f3e"
-  integrity sha512-OyxRR4Vof59I3yGWXws6i908EtGbMzVUi3ganaZQHmydk1iwDhRnvaPG2WaR0KcqrDFKrxVZHULT396LEPhXfg==
-
 caniuse-lite@^1.0.30001366:
   version "1.0.30001367"
   resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001367.tgz#2b97fe472e8fa29c78c5970615d7cd2ee414108a"
   integrity sha512-XDgbeOHfifWV3GEES2B8rtsrADx4Jf+juKX2SICJcaUhjYBO3bR96kvEIHa15VU6ohtOhBZuPGGYGbXMRn0NCw==
 
+caniuse-lite@^1.0.30001406:
+  version "1.0.30001460"
+  resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001460.tgz#31d2e26f0a2309860ed3eff154e03890d9d851a7"
+  integrity sha512-Bud7abqjvEjipUkpLs4D7gR0l8hBYBHoa+tGtKJHvT2AYzLp1z7EmVkUT4ERpVUfca8S2HGIVs883D8pUH1ZzQ==
+
 capital-case@^1.0.3, capital-case@^1.0.4:
   version "1.0.4"
   resolved "https://registry.yarnpkg.com/capital-case/-/capital-case-1.0.4.tgz#9d130292353c9249f6b00fa5852bee38a717e669"
@@ -6769,6 +6769,11 @@ cli@~1.0.0:
     exit "0.1.2"
     glob "^7.1.1"
 
+client-only@0.0.1:
+  version "0.0.1"
+  resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1"
+  integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==
+
 cliui@^4.0.0:
   version "4.1.0"
   resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49"
@@ -6977,11 +6982,16 @@ commander@^5.1.0:
   resolved "https://registry.yarnpkg.com/commander/-/commander-5.1.0.tgz#46abbd1652f8e059bddaef99bbdcb2ad9cf179ae"
   integrity sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==
 
-commander@^6.2.0, commander@^6.2.1:
+commander@^6.2.1:
   version "6.2.1"
   resolved "https://registry.yarnpkg.com/commander/-/commander-6.2.1.tgz#0792eb682dfbc325999bb2b84fddddba110ac73c"
   integrity sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==
 
+commander@^7.2.0:
+  version "7.2.0"
+  resolved "https://registry.yarnpkg.com/commander/-/commander-7.2.0.tgz#a36cb57d0b501ce108e4d20559a150a391d97ab7"
+  integrity sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==
+
 commander@^8.0.0, commander@^8.1.0:
   version "8.3.0"
   resolved "https://registry.yarnpkg.com/commander/-/commander-8.3.0.tgz#4837ea1b2da67b9c616a67afbb0fafee567bca66"
@@ -8475,14 +8485,6 @@ enhanced-resolve@^5.10.0:
     graceful-fs "^4.2.4"
     tapable "^2.2.0"
 
-enhanced-resolve@^5.7.0:
-  version "5.8.2"
-  resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.8.2.tgz#15ddc779345cbb73e97c611cd00c01c1e7bf4d8b"
-  integrity sha512-F27oB3WuHDzvR2DOGNTaYy0D5o0cnrv8TeI482VM4kYgQd/FT9lUQwuNsJ0oOHtBUq7eiW5ytqzp7nBFknL+GA==
-  dependencies:
-    graceful-fs "^4.2.4"
-    tapable "^2.2.0"
-
 enquirer@^2.3.6:
   version "2.3.6"
   resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d"
@@ -11622,10 +11624,10 @@ i18next-chained-backend@^4.0.0:
   dependencies:
     "@babel/runtime" "^7.19.4"
 
-i18next-fs-backend@^1.1.5:
-  version "1.2.0"
-  resolved "https://registry.yarnpkg.com/i18next-fs-backend/-/i18next-fs-backend-1.2.0.tgz#c498c68c8e6a8ae5ed59bea5e5392a11991de696"
-  integrity sha512-pUx3AcgXCbur0jpFA7U67Z2RJflAcIi698Y8VL+phdOqUchahxriV3Cs+M6UkPNQSS/zPEzWLfdJ8EgjB7HVxg==
+i18next-fs-backend@^2.1.1:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/i18next-fs-backend/-/i18next-fs-backend-2.1.1.tgz#07c6393be856c5a398e3dfc1257bf8439841cd89"
+  integrity sha512-FTnj+UmNgT3YRml5ruRv0jMZDG7odOL/OP5PF5mOqvXud2vHrPOOs68Zdk6iqzL47cnnM0ZVkK2BAvpFeDJToA==
 
 i18next-hmr@^1.11.0:
   version "1.11.0"
@@ -11646,12 +11648,12 @@ i18next-localstorage-backend@^4.0.0:
   dependencies:
     "@babel/runtime" "^7.19.4"
 
-i18next@^21.9.1:
-  version "21.10.0"
-  resolved "https://registry.yarnpkg.com/i18next/-/i18next-21.10.0.tgz#85429af55fdca4858345d0e16b584ec29520197d"
-  integrity sha512-YeuIBmFsGjUfO3qBmMOc0rQaun4mIpGKET5WDwvu8lU7gvwpcariZLNtL0Fzj+zazcHUrlXHiptcFhBMFaxzfg==
+i18next@^22.4.10:
+  version "22.4.10"
+  resolved "https://registry.yarnpkg.com/i18next/-/i18next-22.4.10.tgz#cfbfc412c6bc83e3c16564f47e6a5c145255960e"
+  integrity sha512-3EqgGK6fAJRjnGgfkNSStl4mYLCjUoJID338yVyLMj5APT67HUtWoqSayZewiiC5elzMUB1VEUwcmSCoeQcNEA==
   dependencies:
-    "@babel/runtime" "^7.17.2"
+    "@babel/runtime" "^7.20.6"
 
 iconv-lite@0.4.19, iconv-lite@~0.4.13:
   version "0.4.19"
@@ -15914,18 +15916,16 @@ nested-error-stacks@^2.0.0:
   resolved "https://registry.yarnpkg.com/nested-error-stacks/-/nested-error-stacks-2.1.0.tgz#0fbdcf3e13fe4994781280524f8b96b0cdff9c61"
   integrity sha512-AO81vsIO1k1sM4Zrd6Hu7regmJN1NSiAja10gc4bX3F0wd+9rQmcuHQaHVQCYIEC8iFXnE+mavh23GOt7wBgug==
 
-next-i18next@^12.1.0:
-  version "12.1.0"
-  resolved "https://registry.yarnpkg.com/next-i18next/-/next-i18next-12.1.0.tgz#70926fbe966bc4750d2f68573307bfe36eadba46"
-  integrity sha512-rhos/PVULmZPdC0jpec2MDBQMXdGZ3+Mbh/tZfrDtjgnVN3ucdq7k8BlwsJNww6FnqC8AC31n6dSYuqVzYsGsw==
+next-i18next@^13.2.1:
+  version "13.2.1"
+  resolved "https://registry.yarnpkg.com/next-i18next/-/next-i18next-13.2.1.tgz#6d578bbd7fc39daaaf3a1022a6902a1952ce0f0e"
+  integrity sha512-5JYAWHedbbgIZbGBtxjTMC4M1scvkJq6Wif5kiijXzs4L0CRMpnXtAG9mWOp2N0z2znhr/RtsK3nwVgPt54PNw==
   dependencies:
-    "@babel/runtime" "^7.18.9"
+    "@babel/runtime" "^7.20.13"
     "@types/hoist-non-react-statics" "^3.3.1"
     core-js "^3"
     hoist-non-react-statics "^3.3.2"
-    i18next "^21.9.1"
-    i18next-fs-backend "^1.1.5"
-    react-i18next "^11.18.4"
+    i18next-fs-backend "^2.1.1"
 
 next-superjson@^0.0.4:
   version "0.0.4"
@@ -15938,44 +15938,35 @@ next-superjson@^0.0.4:
     babel-loader "^8.2.2"
     babel-plugin-superjson-next "^0.4.2"
 
-next-themes@^0.2.0:
-  version "0.2.0"
-  resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.2.0.tgz#fdc507f61e95b3ae513dee8d4783bcec8c02e3a3"
-  integrity sha512-myhpDL4vadBD9YDSHiewqvzorGzB03N84e+3LxCwHRlM/hiBOaW+UsKsQojQAzC7fdcJA0l2ppveXcYaVV+hxQ==
-
-next-transpile-modules@^9.0.0:
-  version "9.0.0"
-  resolved "https://registry.yarnpkg.com/next-transpile-modules/-/next-transpile-modules-9.0.0.tgz#133b1742af082e61cc76b02a0f12ffd40ce2bf90"
-  integrity sha512-VCNFOazIAnXn1hvgYYSTYMnoWgKgwlYh4lm1pKbSfiB3kj5ZYLcKVhfh3jkPOg1cnd9DP+pte9yCUocdPEUBTQ==
-  dependencies:
-    enhanced-resolve "^5.7.0"
-    escalade "^3.1.1"
+next-themes@^0.2.1:
+  version "0.2.1"
+  resolved "https://registry.yarnpkg.com/next-themes/-/next-themes-0.2.1.tgz#0c9f128e847979daf6c67f70b38e6b6567856e45"
+  integrity sha512-B+AKNfYNIzh0vqQQKqQItTS8evEouKD7H5Hj3kmuPERwddR2TxvDSFZuTj6T7Jfn1oyeUyJMydPl1Bkxkh0W7A==
 
-next@~12.2:
-  version "12.2.6"
-  resolved "https://registry.yarnpkg.com/next/-/next-12.2.6.tgz#105383333c8de542a8c28db9246bd9f2d62f73d3"
-  integrity sha512-Wlln0vp91NVj4f2Tr5c1e7ZXPiwZ+XEefPiuoTnt/VopOh5xK7//KCl1pCicYZP3P2mRbpuKs5PvcVQG/+EC7w==
+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==
   dependencies:
-    "@next/env" "12.2.6"
-    "@swc/helpers" "0.4.3"
-    caniuse-lite "^1.0.30001332"
+    "@next/env" "13.1.1"
+    "@swc/helpers" "0.4.14"
+    caniuse-lite "^1.0.30001406"
     postcss "8.4.14"
-    styled-jsx "5.0.4"
-    use-sync-external-store "1.2.0"
+    styled-jsx "5.1.1"
   optionalDependencies:
-    "@next/swc-android-arm-eabi" "12.2.6"
-    "@next/swc-android-arm64" "12.2.6"
-    "@next/swc-darwin-arm64" "12.2.6"
-    "@next/swc-darwin-x64" "12.2.6"
-    "@next/swc-freebsd-x64" "12.2.6"
-    "@next/swc-linux-arm-gnueabihf" "12.2.6"
-    "@next/swc-linux-arm64-gnu" "12.2.6"
-    "@next/swc-linux-arm64-musl" "12.2.6"
-    "@next/swc-linux-x64-gnu" "12.2.6"
-    "@next/swc-linux-x64-musl" "12.2.6"
-    "@next/swc-win32-arm64-msvc" "12.2.6"
-    "@next/swc-win32-ia32-msvc" "12.2.6"
-    "@next/swc-win32-x64-msvc" "12.2.6"
+    "@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"
 
 nice-try@^1.0.4:
   version "1.0.4"
@@ -18167,12 +18158,12 @@ react-hotkeys@^2.0.0:
   dependencies:
     prop-types "^15.6.1"
 
-react-i18next@^11.18.4:
-  version "11.18.6"
-  resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.18.6.tgz#e159c2960c718c1314f1e8fcaa282d1c8b167887"
-  integrity sha512-yHb2F9BiT0lqoQDt8loZ5gWP331GwctHz9tYQ8A2EIEUu+CcEdjBLQWli1USG3RdWQt3W+jqQLg/d4rrQR96LA==
+react-i18next@^12.2.0:
+  version "12.2.0"
+  resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-12.2.0.tgz#010e3f6070b8d700442947233352ebe4b252d7a1"
+  integrity sha512-5XeVgSygaGfyFmDd2WcXvINRw2WEC1XviW1LXY/xLOEMzsCFRwKqfnHN+hUjla8ZipbVJR27GCMSuTr0BhBBBQ==
   dependencies:
-    "@babel/runtime" "^7.14.5"
+    "@babel/runtime" "^7.20.6"
     html-parse-stringify "^3.0.1"
 
 react-image-crop@^8.3.0:
@@ -21734,10 +21725,12 @@ style-to-object@^0.4.0:
   dependencies:
     inline-style-parser "0.1.1"
 
-styled-jsx@5.0.4:
-  version "5.0.4"
-  resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.0.4.tgz#5b1bd0b9ab44caae3dd1361295559706e044aa53"
-  integrity sha512-sDFWLbg4zR+UkNzfk5lPilyIgtpddfxXEULxhujorr5jtePTUqiPDc5BC0v1NRqTr/WaFBGQQUoYToGlF4B2KQ==
+styled-jsx@5.1.1:
+  version "5.1.1"
+  resolved "https://registry.yarnpkg.com/styled-jsx/-/styled-jsx-5.1.1.tgz#839a1c3aaacc4e735fed0781b8619ea5d0009d1f"
+  integrity sha512-pW7uC1l4mBZ8ugbiZrcIsiIvVx1UmTfw7UkC3Um2tmfUq9Bhk8IiyEIPl6F8agHgjzku6j0xQEZbfA5uSgSaCw==
+  dependencies:
+    client-only "0.0.1"
 
 stylelint-config-recess-order@^3.0.0:
   version "3.0.0"
@@ -23536,7 +23529,7 @@ url@0.10.3:
     punycode "1.3.2"
     querystring "0.2.0"
 
-use-sync-external-store@1.2.0, use-sync-external-store@^1.2.0:
+use-sync-external-store@^1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a"
   integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==
@@ -23837,15 +23830,15 @@ webidl-conversions@^7.0.0:
   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-7.0.0.tgz#256b4e1882be7debbf01d05f0aa2039778ea080a"
   integrity sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==
 
-webpack-bundle-analyzer@4.3.0:
-  version "4.3.0"
-  resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.3.0.tgz#2f3c0ca9041d5ee47fa418693cf56b4a518b578b"
-  integrity sha512-J3TPm54bPARx6QG8z4cKBszahnUglcv70+N+8gUqv2I5KOFHJbzBiLx+pAp606so0X004fxM7hqRu10MLjJifA==
+webpack-bundle-analyzer@4.7.0:
+  version "4.7.0"
+  resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.7.0.tgz#33c1c485a7fcae8627c547b5c3328b46de733c66"
+  integrity sha512-j9b8ynpJS4K+zfO5GGwsAcQX4ZHpWV+yRiHDiL+bE0XHJ8NiPYLTNVQdlFYWxtpg9lfAQNlwJg16J9AJtFSXRg==
   dependencies:
     acorn "^8.0.4"
     acorn-walk "^8.0.0"
     chalk "^4.1.0"
-    commander "^6.2.0"
+    commander "^7.2.0"
     gzip-size "^6.0.0"
     lodash "^4.17.20"
     opener "^1.5.2"