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

fix biome organizeImports settings

Yuki Takei 5 месяцев назад
Родитель
Сommit
0a79c151ff
100 измененных файлов с 1216 добавлено и 580 удалено
  1. 1 0
      apps/app/.eslintrc.js
  2. 2 2
      apps/app/src/components/Admin/Common/AdminNavigation.tsx
  3. 1 1
      apps/app/src/components/Common/PagePathHierarchicalLink/PagePathHierarchicalLink.tsx
  4. 3 2
      apps/app/src/components/Common/PagePathNav/PagePathNav.tsx
  5. 1 1
      apps/app/src/components/Common/PagePathNav/PagePathNavLayout.tsx
  6. 1 1
      apps/app/src/components/Common/PagePathNavTitle/PagePathNavTitle.tsx
  7. 5 3
      apps/app/src/components/Layout/AdminLayout.tsx
  8. 4 2
      apps/app/src/components/Layout/BasicLayout.tsx
  9. 3 2
      apps/app/src/components/Layout/NoLoginLayout.tsx
  10. 3 3
      apps/app/src/components/Layout/RawLayout.tsx
  11. 1 1
      apps/app/src/components/Layout/ShareLinkLayout.tsx
  12. 2 1
      apps/app/src/components/PageView/PageAlerts/FixPageGrantAlert.tsx
  13. 1 1
      apps/app/src/components/PageView/PageAlerts/FullTextSearchNotCoverAlert.tsx
  14. 2 2
      apps/app/src/components/PageView/PageAlerts/OldRevisionAlert.tsx
  15. 1 1
      apps/app/src/components/PageView/PageAlerts/PageAlerts.tsx
  16. 1 1
      apps/app/src/components/PageView/PageAlerts/PageGrantAlert.tsx
  17. 1 1
      apps/app/src/components/PageView/PageAlerts/PageRedirectedAlert.tsx
  18. 1 1
      apps/app/src/components/PageView/PageAlerts/PageStaleAlert.tsx
  19. 2 2
      apps/app/src/components/PageView/PageAlerts/TrashPageAlert.tsx
  20. 2 2
      apps/app/src/components/PageView/PageContentFooter.tsx
  21. 1 1
      apps/app/src/components/PageView/PageView.tsx
  22. 2 2
      apps/app/src/components/ReactMarkdownComponents/NextLink.tsx
  23. 2 2
      apps/app/src/components/Script/DrawioViewerScript/DrawioViewerScript.tsx
  24. 1 1
      apps/app/src/components/ShareLinkPageView/ShareLinkAlert.tsx
  25. 1 1
      apps/app/src/components/ShareLinkPageView/ShareLinkPageView.tsx
  26. 1 1
      apps/app/src/components/User/UserDate.jsx
  27. 1 1
      apps/app/src/components/User/UserInfo.tsx
  28. 3 3
      apps/app/src/components/User/Username.tsx
  29. 1 1
      apps/app/src/features/collaborative-editor/states/current-page-yjs-data.ts
  30. 2 2
      apps/app/src/features/external-user-group/client/components/ExternalUserGroup/ExternalUserGroupManagement.tsx
  31. 1 1
      apps/app/src/features/growi-plugin/client/Admin/components/PluginsExtensionPageContents/PluginCard.tsx
  32. 2 2
      apps/app/src/features/growi-plugin/client/Admin/components/PluginsExtensionPageContents/PluginDeleteModal.tsx
  33. 1 1
      apps/app/src/features/growi-plugin/client/Admin/components/PluginsExtensionPageContents/PluginInstallerForm.tsx
  34. 1 1
      apps/app/src/features/growi-plugin/client/Admin/components/PluginsExtensionPageContents/PluginsExtensionPageContents.tsx
  35. 1 1
      apps/app/src/features/growi-plugin/client/Admin/states/modal/plugin-delete.ts
  36. 1 1
      apps/app/src/features/mermaid/components/MermaidViewer.tsx
  37. 1 1
      apps/app/src/features/page-bulk-export/client/components/PageBulkExportSelectModal.tsx
  38. 2 2
      apps/app/src/features/search/client/components/PrivateLegacyPages.tsx
  39. 1 1
      apps/app/src/features/search/client/components/SearchHelp.tsx
  40. 1 1
      apps/app/src/features/search/client/components/SearchMethodMenuItem.tsx
  41. 2 2
      apps/app/src/features/search/client/components/SearchModal.tsx
  42. 4 2
      apps/app/src/features/search/client/components/SearchPage/SearchControl.tsx
  43. 1 1
      apps/app/src/features/search/client/components/SearchPage/SearchOptionModal.tsx
  44. 3 2
      apps/app/src/features/search/client/components/SearchPage/SearchPage.tsx
  45. 7 5
      apps/app/src/features/search/client/components/SearchPage/SearchPageBase.tsx
  46. 3 3
      apps/app/src/features/search/client/components/SearchPage/SearchResultContent.tsx
  47. 2 2
      apps/app/src/features/search/client/components/SearchPage/SearchResultList.tsx
  48. 1 1
      apps/app/src/features/search/client/components/SearchPage/SortControl.tsx
  49. 1 1
      apps/app/src/features/search/client/components/SearchResultMenuItem.tsx
  50. 1 1
      apps/app/src/features/search/client/states/modal/search.ts
  51. 1 1
      apps/app/src/interfaces/ui.ts
  52. 138 49
      apps/app/src/pages/[[...path]]/index.page.tsx
  53. 92 41
      apps/app/src/pages/[[...path]]/page-data-props.ts
  54. 30 15
      apps/app/src/pages/[[...path]]/server-side-props.ts
  55. 13 6
      apps/app/src/pages/[[...path]]/types.ts
  56. 18 10
      apps/app/src/pages/[[...path]]/use-same-route-navigation.spec.tsx
  57. 1 2
      apps/app/src/pages/[[...path]]/use-same-route-navigation.ts
  58. 4 3
      apps/app/src/pages/[[...path]]/use-shallow-routing.ts
  59. 34 21
      apps/app/src/pages/_app.page.tsx
  60. 47 28
      apps/app/src/pages/_document.page.tsx
  61. 2 4
      apps/app/src/pages/_error.page.tsx
  62. 20 11
      apps/app/src/pages/_private-legacy-pages/index.page.tsx
  63. 35 11
      apps/app/src/pages/_search/get-server-side-props/index.ts
  64. 24 11
      apps/app/src/pages/_search/index.page.tsx
  65. 2 2
      apps/app/src/pages/_search/types.ts
  66. 12 8
      apps/app/src/pages/_search/use-hydrate-server-configurations.ts
  67. 11 3
      apps/app/src/pages/admin/[...path].page.tsx
  68. 10 3
      apps/app/src/pages/admin/_shared/AdminPageFrame.tsx
  69. 24 13
      apps/app/src/pages/admin/_shared/get-server-side-common-props.ts
  70. 1 1
      apps/app/src/pages/admin/_shared/index.ts
  71. 17 7
      apps/app/src/pages/admin/_shared/layout.tsx
  72. 4 4
      apps/app/src/pages/admin/_shared/types.ts
  73. 8 4
      apps/app/src/pages/admin/_shared/use-unstated-container.ts
  74. 25 9
      apps/app/src/pages/admin/ai-integration.page.tsx
  75. 16 8
      apps/app/src/pages/admin/app.page.tsx
  76. 34 15
      apps/app/src/pages/admin/audit-log.page.tsx
  77. 33 18
      apps/app/src/pages/admin/customize.page.tsx
  78. 17 7
      apps/app/src/pages/admin/data-transfer.page.tsx
  79. 17 7
      apps/app/src/pages/admin/export.page.tsx
  80. 30 13
      apps/app/src/pages/admin/global-notification/[globalNotificationId].page.tsx
  81. 18 6
      apps/app/src/pages/admin/global-notification/new.page.tsx
  82. 17 7
      apps/app/src/pages/admin/importer.page.tsx
  83. 32 15
      apps/app/src/pages/admin/index.page.tsx
  84. 18 7
      apps/app/src/pages/admin/markdown.page.tsx
  85. 17 7
      apps/app/src/pages/admin/notification.page.tsx
  86. 17 7
      apps/app/src/pages/admin/plugins.page.tsx
  87. 40 14
      apps/app/src/pages/admin/search.page.tsx
  88. 62 18
      apps/app/src/pages/admin/security.page.tsx
  89. 19 7
      apps/app/src/pages/admin/slack-integration-legacy.page.tsx
  90. 20 9
      apps/app/src/pages/admin/slack-integration.page.tsx
  91. 19 9
      apps/app/src/pages/admin/user-group-detail/[userGroupId].page.tsx
  92. 22 10
      apps/app/src/pages/admin/user-groups.page.tsx
  93. 15 5
      apps/app/src/pages/admin/users/external-accounts.page.tsx
  94. 22 8
      apps/app/src/pages/admin/users/index.page.tsx
  95. 13 13
      apps/app/src/pages/basic-layout-page/get-server-side-props/index.ts
  96. 6 2
      apps/app/src/pages/basic-layout-page/get-server-side-props/search-configurations.ts
  97. 9 3
      apps/app/src/pages/basic-layout-page/get-server-side-props/sidebar-configurations.ts
  98. 9 6
      apps/app/src/pages/basic-layout-page/get-server-side-props/user-ui-settings.ts
  99. 23 9
      apps/app/src/pages/basic-layout-page/hydrate.ts
  100. 8 6
      apps/app/src/pages/basic-layout-page/types.ts

+ 1 - 0
apps/app/.eslintrc.js

@@ -52,6 +52,7 @@ module.exports = {
     'src/utils/**',
     'src/utils/**',
     'src/components/**',
     'src/components/**',
     'src/services/**',
     'src/services/**',
+    'src/pages/**',
     'src/states/**',
     'src/states/**',
   ],
   ],
   settings: {
   settings: {

+ 2 - 2
apps/app/src/components/Admin/Common/AdminNavigation.tsx

@@ -1,7 +1,7 @@
-import { pathUtils } from '@growi/core/dist/utils';
+import React, { type JSX, useCallback } from 'react';
 import Link from 'next/link';
 import Link from 'next/link';
+import { pathUtils } from '@growi/core/dist/utils';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
-import React, { type JSX, useCallback } from 'react';
 import urljoin from 'url-join';
 import urljoin from 'url-join';
 
 
 import { useGrowiAppIdForGrowiCloud, useGrowiCloudUri } from '~/states/global';
 import { useGrowiAppIdForGrowiCloud, useGrowiCloudUri } from '~/states/global';

+ 1 - 1
apps/app/src/components/Common/PagePathHierarchicalLink/PagePathHierarchicalLink.tsx

@@ -1,5 +1,5 @@
-import Link from 'next/link';
 import { type JSX, memo, useCallback } from 'react';
 import { type JSX, memo, useCallback } from 'react';
+import Link from 'next/link';
 import urljoin from 'url-join';
 import urljoin from 'url-join';
 
 
 import type LinkedPagePath from '~/models/linked-page-path';
 import type LinkedPagePath from '~/models/linked-page-path';

+ 3 - 2
apps/app/src/components/Common/PagePathNav/PagePathNav.tsx

@@ -1,14 +1,15 @@
+import { type JSX, useMemo } from 'react';
 import { DevidedPagePath } from '@growi/core/dist/models';
 import { DevidedPagePath } from '@growi/core/dist/models';
 import { pagePathUtils } from '@growi/core/dist/utils';
 import { pagePathUtils } from '@growi/core/dist/utils';
-import { type JSX, useMemo } from 'react';
 
 
 import LinkedPagePath from '~/models/linked-page-path';
 import LinkedPagePath from '~/models/linked-page-path';
 
 
 import { PagePathHierarchicalLink } from '../PagePathHierarchicalLink';
 import { PagePathHierarchicalLink } from '../PagePathHierarchicalLink';
-import styles from './PagePathNav.module.scss';
 import type { PagePathNavLayoutProps } from './PagePathNavLayout';
 import type { PagePathNavLayoutProps } from './PagePathNavLayout';
 import { PagePathNavLayout } from './PagePathNavLayout';
 import { PagePathNavLayout } from './PagePathNavLayout';
 
 
+import styles from './PagePathNav.module.scss';
+
 const { isTrashPage } = pagePathUtils;
 const { isTrashPage } = pagePathUtils;
 
 
 const Separator = ({ className }: { className?: string }): JSX.Element => {
 const Separator = ({ className }: { className?: string }): JSX.Element => {

+ 1 - 1
apps/app/src/components/Common/PagePathNav/PagePathNavLayout.tsx

@@ -1,5 +1,5 @@
-import dynamic from 'next/dynamic';
 import type { JSX, ReactNode } from 'react';
 import type { JSX, ReactNode } from 'react';
+import dynamic from 'next/dynamic';
 
 
 import { usePageNotFound } from '~/states/page';
 import { usePageNotFound } from '~/states/page';
 
 

+ 1 - 1
apps/app/src/components/Common/PagePathNavTitle/PagePathNavTitle.tsx

@@ -1,6 +1,6 @@
+import { type JSX, useState } from 'react';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 import withLoadingProps from 'next-dynamic-loading-props';
 import withLoadingProps from 'next-dynamic-loading-props';
-import { type JSX, useState } from 'react';
 import { useIsomorphicLayoutEffect } from 'usehooks-ts';
 import { useIsomorphicLayoutEffect } from 'usehooks-ts';
 
 
 import type { PagePathNavLayoutProps } from '../PagePathNav';
 import type { PagePathNavLayoutProps } from '../PagePathNav';

+ 5 - 3
apps/app/src/components/Layout/AdminLayout.tsx

@@ -1,12 +1,14 @@
-import dynamic from 'next/dynamic';
-import Link from 'next/link';
 import type { JSX, ReactNode } from 'react';
 import type { JSX, ReactNode } from 'react';
 import React from 'react';
 import React from 'react';
+import dynamic from 'next/dynamic';
+import Link from 'next/link';
 
 
 import GrowiLogo from '~/components/Common/GrowiLogo';
 import GrowiLogo from '~/components/Common/GrowiLogo';
-import styles from './Admin.module.scss';
+
 import { RawLayout } from './RawLayout';
 import { RawLayout } from './RawLayout';
 
 
+import styles from './Admin.module.scss';
+
 const AdminNavigation = dynamic(
 const AdminNavigation = dynamic(
   () =>
   () =>
     import('../Admin/Common/AdminNavigation').then(
     import('../Admin/Common/AdminNavigation').then(

+ 4 - 2
apps/app/src/components/Layout/BasicLayout.tsx

@@ -1,8 +1,10 @@
-import dynamic from 'next/dynamic';
 import type { JSX, ReactNode } from 'react';
 import type { JSX, ReactNode } from 'react';
-import styles from './BasicLayout.module.scss';
+import dynamic from 'next/dynamic';
+
 import { RawLayout } from './RawLayout';
 import { RawLayout } from './RawLayout';
 
 
+import styles from './BasicLayout.module.scss';
+
 const AiAssistantSidebar = dynamic(
 const AiAssistantSidebar = dynamic(
   () =>
   () =>
     import(
     import(

+ 3 - 2
apps/app/src/components/Layout/NoLoginLayout.tsx

@@ -1,12 +1,13 @@
-import Image from 'next/image';
 import type { JSX, ReactNode } from 'react';
 import type { JSX, ReactNode } from 'react';
+import Image from 'next/image';
 
 
 import { useAppTitle } from '~/states/global';
 import { useAppTitle } from '~/states/global';
 
 
 import GrowiLogo from '../Common/GrowiLogo';
 import GrowiLogo from '../Common/GrowiLogo';
-import commonStyles from './NoLoginLayout.module.scss';
 import { RawLayout } from './RawLayout';
 import { RawLayout } from './RawLayout';
 
 
+import commonStyles from './NoLoginLayout.module.scss';
+
 type Props = {
 type Props = {
   className?: string;
   className?: string;
   children?: ReactNode;
   children?: ReactNode;

+ 3 - 3
apps/app/src/components/Layout/RawLayout.tsx

@@ -1,8 +1,8 @@
-import type { ColorScheme } from '@growi/core';
-import dynamic from 'next/dynamic';
-import Head from 'next/head';
 import type { JSX, ReactNode } from 'react';
 import type { JSX, ReactNode } from 'react';
 import React, { useState } from 'react';
 import React, { useState } from 'react';
+import dynamic from 'next/dynamic';
+import Head from 'next/head';
+import type { ColorScheme } from '@growi/core';
 import { useIsomorphicLayoutEffect } from 'usehooks-ts';
 import { useIsomorphicLayoutEffect } from 'usehooks-ts';
 
 
 import {
 import {

+ 1 - 1
apps/app/src/components/Layout/ShareLinkLayout.tsx

@@ -1,6 +1,6 @@
-import dynamic from 'next/dynamic';
 import type { JSX, ReactNode } from 'react';
 import type { JSX, ReactNode } from 'react';
 import React from 'react';
 import React from 'react';
+import dynamic from 'next/dynamic';
 
 
 import { RawLayout } from './RawLayout';
 import { RawLayout } from './RawLayout';
 
 

+ 2 - 1
apps/app/src/components/PageView/PageAlerts/FixPageGrantAlert.tsx

@@ -1,7 +1,8 @@
-import { GroupType, PageGrant } from '@growi/core';
 import { type JSX, useCallback, useEffect, useState } from 'react';
 import { type JSX, useCallback, useEffect, useState } from 'react';
+import { GroupType, PageGrant } from '@growi/core';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
 import { Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
+
 import {
 import {
   type IPageGrantData,
   type IPageGrantData,
   UserGroupPageGrantStatus,
   UserGroupPageGrantStatus,

+ 1 - 1
apps/app/src/components/PageView/PageAlerts/FullTextSearchNotCoverAlert.tsx

@@ -1,5 +1,5 @@
-import { useAtomValue } from 'jotai';
 import type { JSX } from 'react';
 import type { JSX } from 'react';
+import { useAtomValue } from 'jotai';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 
 
 import { useCurrentPageData } from '~/states/page';
 import { useCurrentPageData } from '~/states/page';

+ 2 - 2
apps/app/src/components/PageView/PageAlerts/OldRevisionAlert.tsx

@@ -1,6 +1,6 @@
-import { returnPathForURL } from '@growi/core/dist/utils/path-utils';
-import { useRouter } from 'next/router';
 import { type JSX, useCallback } from 'react';
 import { type JSX, useCallback } from 'react';
+import { useRouter } from 'next/router';
+import { returnPathForURL } from '@growi/core/dist/utils/path-utils';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 
 
 import {
 import {

+ 1 - 1
apps/app/src/components/PageView/PageAlerts/PageAlerts.tsx

@@ -1,5 +1,5 @@
-import dynamic from 'next/dynamic';
 import type { JSX } from 'react';
 import type { JSX } from 'react';
+import dynamic from 'next/dynamic';
 
 
 import { usePageNotFound } from '~/states/page';
 import { usePageNotFound } from '~/states/page';
 
 

+ 1 - 1
apps/app/src/components/PageView/PageAlerts/PageGrantAlert.tsx

@@ -1,5 +1,5 @@
-import { isPopulated } from '@growi/core';
 import React, { type JSX } from 'react';
 import React, { type JSX } from 'react';
+import { isPopulated } from '@growi/core';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 
 
 import { useCurrentPageData } from '~/states/page';
 import { useCurrentPageData } from '~/states/page';

+ 1 - 1
apps/app/src/components/PageView/PageAlerts/PageRedirectedAlert.tsx

@@ -1,5 +1,5 @@
-import { useTranslation } from 'next-i18next';
 import React, { type JSX, useCallback, useState } from 'react';
 import React, { type JSX, useCallback, useState } from 'react';
+import { useTranslation } from 'next-i18next';
 
 
 import { useCurrentPagePath, useRedirectFrom } from '~/states/page';
 import { useCurrentPagePath, useRedirectFrom } from '~/states/page';
 
 

+ 1 - 1
apps/app/src/components/PageView/PageAlerts/PageStaleAlert.tsx

@@ -1,7 +1,7 @@
+import type { JSX } from 'react';
 import { isIPageInfoForEntity } from '@growi/core';
 import { isIPageInfoForEntity } from '@growi/core';
 import { useAtomValue } from 'jotai';
 import { useAtomValue } from 'jotai';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
-import type { JSX } from 'react';
 
 
 import { useCurrentPageData } from '~/states/page';
 import { useCurrentPageData } from '~/states/page';
 import { isEnabledStaleNotificationAtom } from '~/states/server-configurations';
 import { isEnabledStaleNotificationAtom } from '~/states/server-configurations';

+ 2 - 2
apps/app/src/components/PageView/PageAlerts/TrashPageAlert.tsx

@@ -1,7 +1,7 @@
+import { type JSX, useCallback } from 'react';
+import { useRouter } from 'next/router';
 import { UserPicture } from '@growi/ui/dist/components';
 import { UserPicture } from '@growi/ui/dist/components';
 import { format } from 'date-fns/format';
 import { format } from 'date-fns/format';
-import { useRouter } from 'next/router';
-import { type JSX, useCallback } from 'react';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 
 
 import {
 import {

+ 2 - 2
apps/app/src/components/PageView/PageContentFooter.tsx

@@ -1,6 +1,6 @@
-import type { IPage, IPagePopulatedToShowRevision } from '@growi/core';
-import dynamic from 'next/dynamic';
 import type { JSX } from 'react';
 import type { JSX } from 'react';
+import dynamic from 'next/dynamic';
+import type { IPage, IPagePopulatedToShowRevision } from '@growi/core';
 
 
 import styles from './PageContentFooter.module.scss';
 import styles from './PageContentFooter.module.scss';
 
 

+ 1 - 1
apps/app/src/components/PageView/PageView.tsx

@@ -1,6 +1,6 @@
+import { type JSX, useEffect, useMemo, useRef } from 'react';
 import { isUsersHomepage } from '@growi/core/dist/utils/page-path-utils';
 import { isUsersHomepage } from '@growi/core/dist/utils/page-path-utils';
 import { useSlidesByFrontmatter } from '@growi/presentation/dist/services';
 import { useSlidesByFrontmatter } from '@growi/presentation/dist/services';
-import { type JSX, useEffect, useMemo, useRef } from 'react';
 
 
 import { PagePathNavTitle } from '~/components/Common/PagePathNavTitle';
 import { PagePathNavTitle } from '~/components/Common/PagePathNavTitle';
 import type { RendererConfig } from '~/interfaces/services/renderer';
 import type { RendererConfig } from '~/interfaces/services/renderer';

+ 2 - 2
apps/app/src/components/ReactMarkdownComponents/NextLink.tsx

@@ -1,7 +1,7 @@
-import { pagePathUtils } from '@growi/core/dist/utils';
+import type { JSX } from 'react';
 import type { LinkProps } from 'next/link';
 import type { LinkProps } from 'next/link';
 import Link from 'next/link';
 import Link from 'next/link';
-import type { JSX } from 'react';
+import { pagePathUtils } from '@growi/core/dist/utils';
 
 
 import { useSiteUrl } from '~/states/global';
 import { useSiteUrl } from '~/states/global';
 import loggerFactory from '~/utils/logger';
 import loggerFactory from '~/utils/logger';

+ 2 - 2
apps/app/src/components/Script/DrawioViewerScript/DrawioViewerScript.tsx

@@ -1,6 +1,6 @@
-import type { IGraphViewerGlobal } from '@growi/remark-drawio';
-import Head from 'next/head';
 import { type JSX, useCallback } from 'react';
 import { type JSX, useCallback } from 'react';
+import Head from 'next/head';
+import type { IGraphViewerGlobal } from '@growi/remark-drawio';
 
 
 import { generateViewerMinJsUrl } from './use-viewer-min-js-url';
 import { generateViewerMinJsUrl } from './use-viewer-min-js-url';
 
 

+ 1 - 1
apps/app/src/components/ShareLinkPageView/ShareLinkAlert.tsx

@@ -1,6 +1,6 @@
-import { useTranslation } from 'next-i18next';
 import type { FC } from 'react';
 import type { FC } from 'react';
 import React from 'react';
 import React from 'react';
+import { useTranslation } from 'next-i18next';
 
 
 const generateRatio = (expiredAt: Date, createdAt: Date): number => {
 const generateRatio = (expiredAt: Date, createdAt: Date): number => {
   const wholeTime =
   const wholeTime =

+ 1 - 1
apps/app/src/components/ShareLinkPageView/ShareLinkPageView.tsx

@@ -1,5 +1,5 @@
-import { useSlidesByFrontmatter } from '@growi/presentation/dist/services';
 import { type JSX, memo, useMemo } from 'react';
 import { type JSX, memo, useMemo } from 'react';
+import { useSlidesByFrontmatter } from '@growi/presentation/dist/services';
 
 
 import { PagePathNavTitle } from '~/components/Common/PagePathNavTitle';
 import { PagePathNavTitle } from '~/components/Common/PagePathNavTitle';
 import type { RendererConfig } from '~/interfaces/services/renderer';
 import type { RendererConfig } from '~/interfaces/services/renderer';

+ 1 - 1
apps/app/src/components/User/UserDate.jsx

@@ -1,6 +1,6 @@
+import React from 'react';
 import { format } from 'date-fns/format';
 import { format } from 'date-fns/format';
 import PropTypes from 'prop-types';
 import PropTypes from 'prop-types';
-import React from 'react';
 
 
 /**
 /**
  * UserDate
  * UserDate

+ 1 - 1
apps/app/src/components/User/UserInfo.tsx

@@ -1,6 +1,6 @@
+import React, { type JSX } from 'react';
 import type { IUserHasId } from '@growi/core';
 import type { IUserHasId } from '@growi/core';
 import { UserPicture } from '@growi/ui/dist/components';
 import { UserPicture } from '@growi/ui/dist/components';
-import React, { type JSX } from 'react';
 
 
 import styles from './UserInfo.module.scss';
 import styles from './UserInfo.module.scss';
 
 

+ 3 - 3
apps/app/src/components/User/Username.tsx

@@ -1,9 +1,9 @@
+import type React from 'react';
+import type { JSX } from 'react';
+import Link from 'next/link';
 import type { IUserHasId } from '@growi/core';
 import type { IUserHasId } from '@growi/core';
 import { type IUser, isPopulated, type Ref } from '@growi/core';
 import { type IUser, isPopulated, type Ref } from '@growi/core';
 import { pagePathUtils } from '@growi/core/dist/utils';
 import { pagePathUtils } from '@growi/core/dist/utils';
-import Link from 'next/link';
-import type React from 'react';
-import type { JSX } from 'react';
 
 
 export const Username: React.FC<{ user?: IUserHasId | Ref<IUser> }> = ({
 export const Username: React.FC<{ user?: IUserHasId | Ref<IUser> }> = ({
   user,
   user,

+ 1 - 1
apps/app/src/features/collaborative-editor/states/current-page-yjs-data.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 
 import { apiv3Get } from '../../../client/util/apiv3-client';
 import { apiv3Get } from '../../../client/util/apiv3-client';
 import type { CurrentPageYjsData } from '../../../interfaces/yjs';
 import type { CurrentPageYjsData } from '../../../interfaces/yjs';

+ 2 - 2
apps/app/src/features/external-user-group/client/components/ExternalUserGroup/ExternalUserGroupManagement.tsx

@@ -1,8 +1,8 @@
+import type { FC } from 'react';
+import { useCallback, useMemo, useState } from 'react';
 import type { IGrantedGroup } from '@growi/core';
 import type { IGrantedGroup } from '@growi/core';
 import { GroupType, getIdForRef } from '@growi/core';
 import { GroupType, getIdForRef } from '@growi/core';
 import { useAtomValue } from 'jotai';
 import { useAtomValue } from 'jotai';
-import type { FC } from 'react';
-import { useCallback, useMemo, useState } from 'react';
 import { useTranslation } from 'react-i18next';
 import { useTranslation } from 'react-i18next';
 import { TabContent, TabPane } from 'reactstrap';
 import { TabContent, TabPane } from 'reactstrap';
 
 

+ 1 - 1
apps/app/src/features/growi-plugin/client/Admin/components/PluginsExtensionPageContents/PluginCard.tsx

@@ -1,6 +1,6 @@
+import { type JSX, useState } from 'react';
 import Link from 'next/link';
 import Link from 'next/link';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
-import { type JSX, useState } from 'react';
 
 
 import { apiv3Put } from '~/client/util/apiv3-client';
 import { apiv3Put } from '~/client/util/apiv3-client';
 import { toastError, toastSuccess } from '~/client/util/toastr';
 import { toastError, toastSuccess } from '~/client/util/toastr';

+ 2 - 2
apps/app/src/features/growi-plugin/client/Admin/components/PluginsExtensionPageContents/PluginDeleteModal.tsx

@@ -1,7 +1,7 @@
-import Link from 'next/link';
-import { useTranslation } from 'next-i18next';
 import type React from 'react';
 import type React from 'react';
 import { useCallback } from 'react';
 import { useCallback } from 'react';
+import Link from 'next/link';
+import { useTranslation } from 'next-i18next';
 import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
 import { Button, Modal, ModalBody, ModalFooter, ModalHeader } from 'reactstrap';
 
 
 import { apiv3Delete } from '~/client/util/apiv3-client';
 import { apiv3Delete } from '~/client/util/apiv3-client';

+ 1 - 1
apps/app/src/features/growi-plugin/client/Admin/components/PluginsExtensionPageContents/PluginInstallerForm.tsx

@@ -1,5 +1,5 @@
-import { useTranslation } from 'next-i18next';
 import { type JSX, useCallback } from 'react';
 import { type JSX, useCallback } from 'react';
+import { useTranslation } from 'next-i18next';
 
 
 import { apiv3Post } from '~/client/util/apiv3-client';
 import { apiv3Post } from '~/client/util/apiv3-client';
 import { toastError, toastSuccess } from '~/client/util/toastr';
 import { toastError, toastSuccess } from '~/client/util/toastr';

+ 1 - 1
apps/app/src/features/growi-plugin/client/Admin/components/PluginsExtensionPageContents/PluginsExtensionPageContents.tsx

@@ -1,6 +1,6 @@
+import type { JSX } from 'react';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
-import type { JSX } from 'react';
 import { Spinner } from 'reactstrap';
 import { Spinner } from 'reactstrap';
 
 
 import { usePluginDeleteModalActions } from '../../states/modal/plugin-delete';
 import { usePluginDeleteModalActions } from '../../states/modal/plugin-delete';

+ 1 - 1
apps/app/src/features/growi-plugin/client/Admin/states/modal/plugin-delete.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 
 import type { IGrowiPluginHasId } from '../../../../interfaces';
 import type { IGrowiPluginHasId } from '../../../../interfaces';
 
 

+ 1 - 1
apps/app/src/features/mermaid/components/MermaidViewer.tsx

@@ -1,5 +1,5 @@
-import mermaid from 'mermaid';
 import React, { type JSX, useEffect, useRef } from 'react';
 import React, { type JSX, useEffect, useRef } from 'react';
+import mermaid from 'mermaid';
 import { v7 as uuidV7 } from 'uuid';
 import { v7 as uuidV7 } from 'uuid';
 
 
 import { useNextThemes } from '~/stores-universal/use-next-themes';
 import { useNextThemes } from '~/stores-universal/use-next-themes';

+ 1 - 1
apps/app/src/features/page-bulk-export/client/components/PageBulkExportSelectModal.tsx

@@ -1,7 +1,7 @@
+import { type JSX, useCallback, useMemo, useState } from 'react';
 import { format } from 'date-fns/format';
 import { format } from 'date-fns/format';
 import { useAtomValue } from 'jotai';
 import { useAtomValue } from 'jotai';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
-import { type JSX, useCallback, useMemo, useState } from 'react';
 import { Modal, ModalBody, ModalHeader } from 'reactstrap';
 import { Modal, ModalBody, ModalHeader } from 'reactstrap';
 
 
 import { apiv3Post } from '~/client/util/apiv3-client';
 import { apiv3Post } from '~/client/util/apiv3-client';

+ 2 - 2
apps/app/src/features/search/client/components/PrivateLegacyPages.tsx

@@ -1,5 +1,3 @@
-import { LoadingSpinner } from '@growi/ui/dist/components';
-import { useTranslation } from 'next-i18next';
 import React, {
 import React, {
   type JSX,
   type JSX,
   useCallback,
   useCallback,
@@ -8,6 +6,8 @@ import React, {
   useRef,
   useRef,
   useState,
   useState,
 } from 'react';
 } from 'react';
+import { LoadingSpinner } from '@growi/ui/dist/components';
+import { useTranslation } from 'next-i18next';
 import {
 import {
   DropdownItem,
   DropdownItem,
   DropdownMenu,
   DropdownMenu,

+ 1 - 1
apps/app/src/features/search/client/components/SearchHelp.tsx

@@ -1,5 +1,5 @@
-import { useTranslation } from 'next-i18next';
 import { type JSX, useState } from 'react';
 import { type JSX, useState } from 'react';
+import { useTranslation } from 'next-i18next';
 import { Collapse } from 'reactstrap';
 import { Collapse } from 'reactstrap';
 
 
 export const SearchHelp = (): JSX.Element => {
 export const SearchHelp = (): JSX.Element => {

+ 1 - 1
apps/app/src/features/search/client/components/SearchMethodMenuItem.tsx

@@ -1,6 +1,6 @@
+import type { JSX } from 'react';
 import { DevidedPagePath } from '@growi/core/dist/models';
 import { DevidedPagePath } from '@growi/core/dist/models';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
-import type { JSX } from 'react';
 
 
 import { useCurrentPagePath } from '~/states/page';
 import { useCurrentPagePath } from '~/states/page';
 
 

+ 2 - 2
apps/app/src/features/search/client/components/SearchModal.tsx

@@ -1,9 +1,9 @@
+import { type JSX, useCallback, useEffect, useMemo, useState } from 'react';
+import { useRouter } from 'next/router';
 import Downshift, {
 import Downshift, {
   type DownshiftState,
   type DownshiftState,
   type StateChangeOptions,
   type StateChangeOptions,
 } from 'downshift';
 } from 'downshift';
-import { useRouter } from 'next/router';
-import { type JSX, useCallback, useEffect, useMemo, useState } from 'react';
 import { Modal, ModalBody } from 'reactstrap';
 import { Modal, ModalBody } from 'reactstrap';
 
 
 import { useSetSearchKeyword } from '~/states/search';
 import { useSetSearchKeyword } from '~/states/search';

+ 4 - 2
apps/app/src/features/search/client/components/SearchPage/SearchControl.tsx

@@ -1,14 +1,16 @@
-import { useTranslation } from 'next-i18next';
 import React, { type JSX, useCallback, useEffect, useState } from 'react';
 import React, { type JSX, useCallback, useEffect, useState } from 'react';
+import { useTranslation } from 'next-i18next';
 import { Collapse } from 'reactstrap';
 import { Collapse } from 'reactstrap';
 
 
 import { SORT_AXIS, SORT_ORDER } from '~/interfaces/search';
 import { SORT_AXIS, SORT_ORDER } from '~/interfaces/search';
 import type { ISearchConditions, ISearchConfigurations } from '~/stores/search';
 import type { ISearchConditions, ISearchConfigurations } from '~/stores/search';
-import styles from './SearchControl.module.scss';
+
 import { SearchModalTriggerinput } from './SearchModalTriggerinput';
 import { SearchModalTriggerinput } from './SearchModalTriggerinput';
 import SearchOptionModal from './SearchOptionModal';
 import SearchOptionModal from './SearchOptionModal';
 import SortControl from './SortControl';
 import SortControl from './SortControl';
 
 
+import styles from './SearchControl.module.scss';
+
 type Props = {
 type Props = {
   isEnableSort: boolean;
   isEnableSort: boolean;
   isEnableFilter: boolean;
   isEnableFilter: boolean;

+ 1 - 1
apps/app/src/features/search/client/components/SearchPage/SearchOptionModal.tsx

@@ -1,5 +1,5 @@
-import { useTranslation } from 'next-i18next';
 import { type FC, useCallback } from 'react';
 import { type FC, useCallback } from 'react';
+import { useTranslation } from 'next-i18next';
 import { Modal, ModalBody, ModalHeader } from 'reactstrap';
 import { Modal, ModalBody, ModalHeader } from 'reactstrap';
 
 
 type Props = {
 type Props = {

+ 3 - 2
apps/app/src/features/search/client/components/SearchPage/SearchPage.tsx

@@ -1,6 +1,6 @@
+import React, { type JSX, useCallback, useMemo, useRef, useState } from 'react';
 import { useAtomValue } from 'jotai';
 import { useAtomValue } from 'jotai';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
-import React, { type JSX, useCallback, useMemo, useRef, useState } from 'react';
 
 
 import { NotAvailableForGuest } from '~/client/components/NotAvailableForGuest';
 import { NotAvailableForGuest } from '~/client/components/NotAvailableForGuest';
 import { NotAvailableForReadOnlyUser } from '~/client/components/NotAvailableForReadOnlyUser';
 import { NotAvailableForReadOnlyUser } from '~/client/components/NotAvailableForReadOnlyUser';
@@ -20,13 +20,14 @@ import {
 
 
 import { OperateAllControl } from './OperateAllControl';
 import { OperateAllControl } from './OperateAllControl';
 import SearchControl from './SearchControl';
 import SearchControl from './SearchControl';
-import styles from './SearchPage.module.scss';
 import type { IReturnSelectedPageIds } from './SearchPageBase';
 import type { IReturnSelectedPageIds } from './SearchPageBase';
 import {
 import {
   SearchPageBase,
   SearchPageBase,
   usePageDeleteModalForBulkDeletion,
   usePageDeleteModalForBulkDeletion,
 } from './SearchPageBase';
 } from './SearchPageBase';
 
 
+import styles from './SearchPage.module.scss';
+
 // TODO: replace with "customize:showPageLimitationS"
 // TODO: replace with "customize:showPageLimitationS"
 const INITIAL_PAGIONG_SIZE = 20;
 const INITIAL_PAGIONG_SIZE = 20;
 
 

+ 7 - 5
apps/app/src/features/search/client/components/SearchPage/SearchPageBase.tsx

@@ -1,7 +1,3 @@
-import { LoadingSpinner } from '@growi/ui/dist/components';
-import { useAtomValue } from 'jotai';
-import dynamic from 'next/dynamic';
-import { useTranslation } from 'next-i18next';
 import type React from 'react';
 import type React from 'react';
 import type { ForwardRefRenderFunction, JSX } from 'react';
 import type { ForwardRefRenderFunction, JSX } from 'react';
 import {
 import {
@@ -11,6 +7,10 @@ import {
   useRef,
   useRef,
   useState,
   useState,
 } from 'react';
 } from 'react';
+import dynamic from 'next/dynamic';
+import { LoadingSpinner } from '@growi/ui/dist/components';
+import { useAtomValue } from 'jotai';
+import { useTranslation } from 'next-i18next';
 
 
 import type { ForceHideMenuItems } from '~/client/components/Common/Dropdown/PageItemControl';
 import type { ForceHideMenuItems } from '~/client/components/Common/Dropdown/PageItemControl';
 import type { ISelectableAll } from '~/client/interfaces/selectable-all';
 import type { ISelectableAll } from '~/client/interfaces/selectable-all';
@@ -28,11 +28,13 @@ import {
 } from '~/states/server-configurations';
 } from '~/states/server-configurations';
 import { usePageDeleteModalActions } from '~/states/ui/modal/page-delete';
 import { usePageDeleteModalActions } from '~/states/ui/modal/page-delete';
 import { mutatePageTree, mutateRecentlyUpdated } from '~/stores/page-listing';
 import { mutatePageTree, mutateRecentlyUpdated } from '~/stores/page-listing';
-import styles from './SearchPageBase.module.scss';
+
 // Do not import with next/dynamic
 // Do not import with next/dynamic
 // see: https://github.com/growilabs/growi/pull/7923
 // see: https://github.com/growilabs/growi/pull/7923
 import { SearchResultList } from './SearchResultList';
 import { SearchResultList } from './SearchResultList';
 
 
+import styles from './SearchPageBase.module.scss';
+
 // https://regex101.com/r/brrkBu/1
 // https://regex101.com/r/brrkBu/1
 const highlightKeywordsSplitter = /"[^"]+"|[^\u{20}\u{3000}]+/gu;
 const highlightKeywordsSplitter = /"[^"]+"|[^\u{20}\u{3000}]+/gu;
 
 

+ 3 - 3
apps/app/src/features/search/client/components/SearchPage/SearchResultContent.tsx

@@ -1,9 +1,9 @@
+import type { FC, JSX } from 'react';
+import { useCallback, useEffect, useRef } from 'react';
+import dynamic from 'next/dynamic';
 import type { IPageToDeleteWithMeta, IPageToRenameWithMeta } from '@growi/core';
 import type { IPageToDeleteWithMeta, IPageToRenameWithMeta } from '@growi/core';
 import { getIdStringForRef } from '@growi/core';
 import { getIdStringForRef } from '@growi/core';
-import dynamic from 'next/dynamic';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
-import type { FC, JSX } from 'react';
-import { useCallback, useEffect, useRef } from 'react';
 import { animateScroll } from 'react-scroll';
 import { animateScroll } from 'react-scroll';
 import { DropdownItem } from 'reactstrap';
 import { DropdownItem } from 'reactstrap';
 import { debounce } from 'throttle-debounce';
 import { debounce } from 'throttle-debounce';

+ 2 - 2
apps/app/src/features/search/client/components/SearchPage/SearchResultList.tsx

@@ -1,11 +1,11 @@
+import type { ForwardRefRenderFunction } from 'react';
+import { forwardRef, useCallback, useImperativeHandle, useRef } from 'react';
 import {
 import {
   type IPageInfoForListing,
   type IPageInfoForListing,
   type IPageWithMeta,
   type IPageWithMeta,
   isIPageInfoForListing,
   isIPageInfoForListing,
 } from '@growi/core/dist/interfaces';
 } from '@growi/core/dist/interfaces';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
-import type { ForwardRefRenderFunction } from 'react';
-import { forwardRef, useCallback, useImperativeHandle, useRef } from 'react';
 
 
 import type { ForceHideMenuItems } from '~/client/components/Common/Dropdown/PageItemControl';
 import type { ForceHideMenuItems } from '~/client/components/Common/Dropdown/PageItemControl';
 import { PageListItemL } from '~/client/components/PageList/PageListItemL';
 import { PageListItemL } from '~/client/components/PageList/PageListItemL';

+ 1 - 1
apps/app/src/features/search/client/components/SearchPage/SortControl.tsx

@@ -1,5 +1,5 @@
-import { useTranslation } from 'next-i18next';
 import type { FC } from 'react';
 import type { FC } from 'react';
+import { useTranslation } from 'next-i18next';
 
 
 import { SORT_AXIS, SORT_ORDER } from '~/interfaces/search';
 import { SORT_AXIS, SORT_ORDER } from '~/interfaces/search';
 
 

+ 1 - 1
apps/app/src/features/search/client/components/SearchResultMenuItem.tsx

@@ -1,5 +1,5 @@
-import { PagePathLabel, UserPicture } from '@growi/ui/dist/components';
 import { type JSX, useCallback } from 'react';
 import { type JSX, useCallback } from 'react';
+import { PagePathLabel, UserPicture } from '@growi/ui/dist/components';
 import { useDebounce } from 'usehooks-ts';
 import { useDebounce } from 'usehooks-ts';
 
 
 import { useSWRxSearch } from '~/stores/search';
 import { useSWRxSearch } from '~/stores/search';

+ 1 - 1
apps/app/src/features/search/client/states/modal/search.ts

@@ -1,5 +1,5 @@
-import { atom, useAtomValue, useSetAtom } from 'jotai';
 import { useCallback } from 'react';
 import { useCallback } from 'react';
+import { atom, useAtomValue, useSetAtom } from 'jotai';
 
 
 type OnSearch = (keyword: string) => void;
 type OnSearch = (keyword: string) => void;
 type OpenSearchModal = (
 type OpenSearchModal = (

+ 1 - 1
apps/app/src/interfaces/ui.ts

@@ -1,5 +1,5 @@
-import type { Nullable } from '@growi/core';
 import type { JSX } from 'react';
 import type { JSX } from 'react';
+import type { Nullable } from '@growi/core';
 
 
 import type { IPageForItem } from '~/interfaces/page';
 import type { IPageForItem } from '~/interfaces/page';
 
 

+ 138 - 49
apps/app/src/pages/[[...path]]/index.page.tsx

@@ -1,25 +1,23 @@
-import type { ReactNode, JSX } from 'react';
-import React, { useEffect } from 'react';
-
-import EventEmitter from 'events';
-
-import { isClient } from '@growi/core/dist/utils';
-import type {
-  GetServerSideProps, GetServerSidePropsContext,
-} from 'next';
+import type React from 'react';
+import type { JSX, ReactNode } from 'react';
+import { useEffect } from 'react';
+import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 import Head from 'next/head';
 import Head from 'next/head';
+import { isClient } from '@growi/core/dist/utils';
+import EventEmitter from 'events';
 
 
 import { BasicLayout } from '~/components/Layout/BasicLayout';
 import { BasicLayout } from '~/components/Layout/BasicLayout';
 import { PageView } from '~/components/PageView/PageView';
 import { PageView } from '~/components/PageView/PageView';
 import { DrawioViewerScript } from '~/components/Script/DrawioViewerScript';
 import { DrawioViewerScript } from '~/components/Script/DrawioViewerScript';
 import { useEditorModeClassName } from '~/services/layout/use-editor-mode-class-name';
 import { useEditorModeClassName } from '~/services/layout/use-editor-mode-class-name';
-import {
-  useCurrentPageData, useCurrentPagePath,
-} from '~/states/page';
+import { useCurrentPageData, useCurrentPagePath } from '~/states/page';
 import { useHydratePageAtoms } from '~/states/page/hydrate';
 import { useHydratePageAtoms } from '~/states/page/hydrate';
 import { useRendererConfig } from '~/states/server-configurations';
 import { useRendererConfig } from '~/states/server-configurations';
-import { useSetupGlobalSocket, useSetupGlobalSocketForPage } from '~/states/socket-io';
+import {
+  useSetupGlobalSocket,
+  useSetupGlobalSocketForPage,
+} from '~/states/socket-io';
 import { useSetEditingMarkdown } from '~/states/ui/editor';
 import { useSetEditingMarkdown } from '~/states/ui/editor';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
@@ -28,12 +26,17 @@ import { getServerSideCommonEachProps } from '../common-props';
 import { useInitialCSRFetch } from '../general-page';
 import { useInitialCSRFetch } from '../general-page';
 import { useHydrateGeneralPageConfigurationAtoms } from '../general-page/hydrate';
 import { useHydrateGeneralPageConfigurationAtoms } from '../general-page/hydrate';
 import { registerPageToShowRevisionWithMeta } from '../general-page/superjson';
 import { registerPageToShowRevisionWithMeta } from '../general-page/superjson';
-import { NextjsRoutingType, detectNextjsRoutingType } from '../utils/nextjs-routing-utils';
+import {
+  detectNextjsRoutingType,
+  NextjsRoutingType,
+} from '../utils/nextjs-routing-utils';
 import { useCustomTitleForPage } from '../utils/page-title-customization';
 import { useCustomTitleForPage } from '../utils/page-title-customization';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
-
 import { NEXT_JS_ROUTING_PAGE } from './consts';
 import { NEXT_JS_ROUTING_PAGE } from './consts';
-import { getServerSidePropsForInitial, getServerSidePropsForSameRoute } from './server-side-props';
+import {
+  getServerSidePropsForInitial,
+  getServerSidePropsForSameRoute,
+} from './server-side-props';
 import type { EachProps, InitialProps } from './types';
 import type { EachProps, InitialProps } from './types';
 import { useSameRouteNavigation } from './use-same-route-navigation';
 import { useSameRouteNavigation } from './use-same-route-navigation';
 import { useShallowRouting } from './use-shallow-routing';
 import { useShallowRouting } from './use-shallow-routing';
@@ -46,39 +49,105 @@ declare global {
   var globalEmitter: EventEmitter;
   var globalEmitter: EventEmitter;
 }
 }
 
 
-const GrowiContextualSubNavigation = dynamic(() => import('~/client/components/Navbar/GrowiContextualSubNavigation'), { ssr: false });
+const GrowiContextualSubNavigation = dynamic(
+  () => import('~/client/components/Navbar/GrowiContextualSubNavigation'),
+  { ssr: false },
+);
 
 
 const GrowiPluginsActivator = dynamic(
 const GrowiPluginsActivator = dynamic(
-  () => import('~/features/growi-plugin/client/components/GrowiPluginsActivator').then(mod => mod.GrowiPluginsActivator),
+  () =>
+    import(
+      '~/features/growi-plugin/client/components/GrowiPluginsActivator'
+    ).then((mod) => mod.GrowiPluginsActivator),
   { ssr: false },
   { ssr: false },
 );
 );
 
 
-const DisplaySwitcher = dynamic(() => import('~/client/components/Page/DisplaySwitcher').then(mod => mod.DisplaySwitcher), { ssr: false });
-const PageStatusAlert = dynamic(() => import('~/client/components/PageStatusAlert').then(mod => mod.PageStatusAlert), { ssr: false });
+const DisplaySwitcher = dynamic(
+  () =>
+    import('~/client/components/Page/DisplaySwitcher').then(
+      (mod) => mod.DisplaySwitcher,
+    ),
+  { ssr: false },
+);
+const PageStatusAlert = dynamic(
+  () =>
+    import('~/client/components/PageStatusAlert').then(
+      (mod) => mod.PageStatusAlert,
+    ),
+  { ssr: false },
+);
 
 
-const UnsavedAlertDialog = dynamic(() => import('~/client/components/UnsavedAlertDialog'), { ssr: false });
+const UnsavedAlertDialog = dynamic(
+  () => import('~/client/components/UnsavedAlertDialog'),
+  { ssr: false },
+);
 const DescendantsPageListModal = dynamic(
 const DescendantsPageListModal = dynamic(
-  () => import('~/client/components/DescendantsPageListModal').then(mod => mod.DescendantsPageListModal),
+  () =>
+    import('~/client/components/DescendantsPageListModal').then(
+      (mod) => mod.DescendantsPageListModal,
+    ),
+  { ssr: false },
+);
+const DrawioModal = dynamic(
+  () =>
+    import('~/client/components/PageEditor/DrawioModal').then(
+      (mod) => mod.DrawioModal,
+    ),
+  { ssr: false },
+);
+const HandsontableModal = dynamic(
+  () =>
+    import('~/client/components/PageEditor/HandsontableModal').then(
+      (mod) => mod.HandsontableModal,
+    ),
+  { ssr: false },
+);
+const TemplateModal = dynamic(
+  () =>
+    import('~/client/components/TemplateModal').then(
+      (mod) => mod.TemplateModal,
+    ),
+  { ssr: false },
+);
+const LinkEditModal = dynamic(
+  () =>
+    import('~/client/components/PageEditor/LinkEditModal').then(
+      (mod) => mod.LinkEditModal,
+    ),
+  { ssr: false },
+);
+const TagEditModal = dynamic(
+  () =>
+    import('~/client/components/PageTags/TagEditModal').then(
+      (mod) => mod.TagEditModal,
+    ),
+  { ssr: false },
+);
+const ConflictDiffModal = dynamic(
+  () =>
+    import('~/client/components/PageEditor/ConflictDiffModal').then(
+      (mod) => mod.ConflictDiffModal,
+    ),
   { ssr: false },
   { ssr: false },
 );
 );
-const DrawioModal = dynamic(() => import('~/client/components/PageEditor/DrawioModal').then(mod => mod.DrawioModal), { ssr: false });
-const HandsontableModal = dynamic(() => import('~/client/components/PageEditor/HandsontableModal').then(mod => mod.HandsontableModal), { ssr: false });
-const TemplateModal = dynamic(() => import('~/client/components/TemplateModal').then(mod => mod.TemplateModal), { ssr: false });
-const LinkEditModal = dynamic(() => import('~/client/components/PageEditor/LinkEditModal').then(mod => mod.LinkEditModal), { ssr: false });
-const TagEditModal = dynamic(() => import('~/client/components/PageTags/TagEditModal').then(mod => mod.TagEditModal), { ssr: false });
-const ConflictDiffModal = dynamic(() => import('~/client/components/PageEditor/ConflictDiffModal').then(mod => mod.ConflictDiffModal), { ssr: false });
 
 
-const EditablePageEffects = dynamic(() => import('~/client/components/Page/EditablePageEffects').then(mod => mod.EditablePageEffects), { ssr: false });
+const EditablePageEffects = dynamic(
+  () =>
+    import('~/client/components/Page/EditablePageEffects').then(
+      (mod) => mod.EditablePageEffects,
+    ),
+  { ssr: false },
+);
 
 
 type Props = EachProps | InitialProps;
 type Props = EachProps | InitialProps;
 
 
 const isInitialProps = (props: Props): props is InitialProps => {
 const isInitialProps = (props: Props): props is InitialProps => {
-  return 'isNextjsRoutingTypeInitial' in props && props.isNextjsRoutingTypeInitial;
+  return (
+    'isNextjsRoutingTypeInitial' in props && props.isNextjsRoutingTypeInitial
+  );
 };
 };
 
 
-
 const Page: NextPageWithLayout<Props> = (props: Props) => {
 const Page: NextPageWithLayout<Props> = (props: Props) => {
-
   // register global EventEmitter
   // register global EventEmitter
   if (isClient() && window.globalEmitter == null) {
   if (isClient() && window.globalEmitter == null) {
     window.globalEmitter = new EventEmitter();
     window.globalEmitter = new EventEmitter();
@@ -129,7 +198,6 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
         <title>{title}</title>
         <title>{title}</title>
       </Head>
       </Head>
       <div className="dynamic-layout-root justify-content-between">
       <div className="dynamic-layout-root justify-content-between">
-
         <GrowiContextualSubNavigation currentPage={currentPage} />
         <GrowiContextualSubNavigation currentPage={currentPage} />
 
 
         <PageView
         <PageView
@@ -147,20 +215,31 @@ const Page: NextPageWithLayout<Props> = (props: Props) => {
   );
   );
 };
 };
 
 
-const BasicLayoutWithEditor = ({ children }: { children?: ReactNode }): JSX.Element => {
+const BasicLayoutWithEditor = ({
+  children,
+}: {
+  children?: ReactNode;
+}): JSX.Element => {
   const editorModeClassName = useEditorModeClassName();
   const editorModeClassName = useEditorModeClassName();
   return <BasicLayout className={editorModeClassName}>{children}</BasicLayout>;
   return <BasicLayout className={editorModeClassName}>{children}</BasicLayout>;
 };
 };
 
 
 type LayoutProps = Props & {
 type LayoutProps = Props & {
-  children?: ReactNode
-}
+  children?: ReactNode;
+};
 
 
 const Layout = ({ children, ...props }: LayoutProps): JSX.Element => {
 const Layout = ({ children, ...props }: LayoutProps): JSX.Element => {
   // Hydrate sidebar atoms with server-side data - must be called unconditionally
   // Hydrate sidebar atoms with server-side data - must be called unconditionally
   const initialProps = isInitialProps(props) ? props : undefined;
   const initialProps = isInitialProps(props) ? props : undefined;
-  useHydrateBasicLayoutConfigurationAtoms(initialProps?.searchConfig, initialProps?.sidebarConfig, initialProps?.userUISettings);
-  useHydrateGeneralPageConfigurationAtoms(initialProps?.serverConfig, initialProps?.rendererConfig);
+  useHydrateBasicLayoutConfigurationAtoms(
+    initialProps?.searchConfig,
+    initialProps?.sidebarConfig,
+    initialProps?.userUISettings,
+  );
+  useHydrateGeneralPageConfigurationAtoms(
+    initialProps?.serverConfig,
+    initialProps?.rendererConfig,
+  );
 
 
   return <BasicLayoutWithEditor>{children}</BasicLayoutWithEditor>;
   return <BasicLayoutWithEditor>{children}</BasicLayoutWithEditor>;
 };
 };
@@ -177,9 +256,7 @@ Page.getLayout = function getLayout(page: React.ReactElement<Props>) {
       <GrowiPluginsActivator />
       <GrowiPluginsActivator />
       <DrawioViewerScriptWithAtom />
       <DrawioViewerScriptWithAtom />
 
 
-      <Layout {...page.props}>
-        {page}
-      </Layout>
+      <Layout {...page.props}>{page}</Layout>
       <UnsavedAlertDialog />
       <UnsavedAlertDialog />
       <DescendantsPageListModal />
       <DescendantsPageListModal />
       <DrawioModal />
       <DrawioModal />
@@ -192,14 +269,22 @@ Page.getLayout = function getLayout(page: React.ReactElement<Props>) {
   );
   );
 };
 };
 
 
-export const getServerSideProps: GetServerSideProps<Props> = async(context: GetServerSidePropsContext) => {
+export const getServerSideProps: GetServerSideProps<Props> = async (
+  context: GetServerSidePropsContext,
+) => {
   //
   //
   // STAGE 1
   // STAGE 1
   //
   //
 
 
-  const commonEachPropsResult = await getServerSideCommonEachProps(context, NEXT_JS_ROUTING_PAGE);
+  const commonEachPropsResult = await getServerSideCommonEachProps(
+    context,
+    NEXT_JS_ROUTING_PAGE,
+  );
   // Handle early return cases (redirect/notFound)
   // Handle early return cases (redirect/notFound)
-  if ('redirect' in commonEachPropsResult || 'notFound' in commonEachPropsResult) {
+  if (
+    'redirect' in commonEachPropsResult ||
+    'notFound' in commonEachPropsResult
+  ) {
     return commonEachPropsResult;
     return commonEachPropsResult;
   }
   }
   const commonEachProps = await commonEachPropsResult.props;
   const commonEachProps = await commonEachPropsResult.props;
@@ -219,14 +304,18 @@ export const getServerSideProps: GetServerSideProps<Props> = async(context: GetS
   //
   //
 
 
   // detect Next.js routing type
   // detect Next.js routing type
-  const nextjsRoutingType = detectNextjsRoutingType(context, NEXT_JS_ROUTING_PAGE);
+  const nextjsRoutingType = detectNextjsRoutingType(
+    context,
+    NEXT_JS_ROUTING_PAGE,
+  );
 
 
   // Merge all results in a type-safe manner (using sequential merging)
   // Merge all results in a type-safe manner (using sequential merging)
-  return mergeGetServerSidePropsResults(commonEachPropsResult, (
-    (nextjsRoutingType === NextjsRoutingType.INITIAL)
+  return mergeGetServerSidePropsResults(
+    commonEachPropsResult,
+    nextjsRoutingType === NextjsRoutingType.INITIAL
       ? await getServerSidePropsForInitial(context)
       ? await getServerSidePropsForInitial(context)
-      : await getServerSidePropsForSameRoute(context)
-  ));
+      : await getServerSidePropsForSameRoute(context),
+  );
 };
 };
 
 
 export default Page;
 export default Page;

+ 92 - 41
apps/app/src/pages/[[...path]]/page-data-props.ts

@@ -1,24 +1,31 @@
-import assert from 'assert';
-
+import type { GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
 import type {
 import type {
-  IDataWithRequiredMeta, IPage, IPageNotFoundInfo, IUser,
+  IDataWithRequiredMeta,
+  IPage,
+  IPageNotFoundInfo,
+  IUser,
 } from '@growi/core/dist/interfaces';
 } from '@growi/core/dist/interfaces';
+import { isIPageInfo, isIPageNotFoundInfo } from '@growi/core/dist/interfaces';
 import {
 import {
-  isIPageInfo,
-  isIPageNotFoundInfo,
-} from '@growi/core/dist/interfaces';
-import { isPermalink as _isPermalink, isTopPage } from '@growi/core/dist/utils/page-path-utils';
+  isPermalink as _isPermalink,
+  isTopPage,
+} from '@growi/core/dist/utils/page-path-utils';
 import { removeHeadingSlash } from '@growi/core/dist/utils/path-utils';
 import { removeHeadingSlash } from '@growi/core/dist/utils/path-utils';
-import type { model, HydratedDocument } from 'mongoose';
-import type { GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
+import assert from 'assert';
+import type { HydratedDocument, model } from 'mongoose';
 
 
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { PageModel } from '~/server/models/page';
 import type { PageModel } from '~/server/models/page';
-import type { IPageRedirect, PageRedirectModel } from '~/server/models/page-redirect';
+import type {
+  IPageRedirect,
+  PageRedirectModel,
+} from '~/server/models/page-redirect';
 
 
 import type { CommonEachProps } from '../common-props';
 import type { CommonEachProps } from '../common-props';
-import type { GeneralPageInitialProps, IPageToShowRevisionWithMeta } from '../general-page';
-
+import type {
+  GeneralPageInitialProps,
+  IPageToShowRevisionWithMeta,
+} from '../general-page';
 import type { EachProps } from './types';
 import type { EachProps } from './types';
 
 
 // Utility to resolve path, redirect, and identical path page check
 // Utility to resolve path, redirect, and identical path page check
@@ -40,13 +47,15 @@ async function initModels(): Promise<void> {
     Page = mongooseModel<IPage, PageModel>('Page');
     Page = mongooseModel<IPage, PageModel>('Page');
   }
   }
   if (PageRedirect == null) {
   if (PageRedirect == null) {
-    PageRedirect = mongooseModel<IPageRedirect, PageRedirectModel>('PageRedirect');
+    PageRedirect = mongooseModel<IPageRedirect, PageRedirectModel>(
+      'PageRedirect',
+    );
   }
   }
 }
 }
 
 
 async function resolvePathAndCheckIdentical(
 async function resolvePathAndCheckIdentical(
-    path: string,
-    user: IUser | undefined,
+  path: string,
+  user: IUser | undefined,
 ): Promise<PathResolutionResult> {
 ): Promise<PathResolutionResult> {
   await initModels();
   await initModels();
 
 
@@ -61,7 +70,12 @@ async function resolvePathAndCheckIdentical(
       resolvedPagePath = chains.end.toPath;
       resolvedPagePath = chains.end.toPath;
       redirectFrom = chains.start.fromPath;
       redirectFrom = chains.start.fromPath;
     }
     }
-    const multiplePagesCount = await Page.countByPathAndViewer(resolvedPagePath, user, null, true);
+    const multiplePagesCount = await Page.countByPathAndViewer(
+      resolvedPagePath,
+      user,
+      null,
+      true,
+    );
     isIdenticalPathPage = multiplePagesCount > 1;
     isIdenticalPathPage = multiplePagesCount > 1;
   }
   }
   return { resolvedPagePath, isIdenticalPathPage, redirectFrom };
   return { resolvedPagePath, isIdenticalPathPage, redirectFrom };
@@ -72,9 +86,9 @@ async function resolvePathAndCheckIdentical(
  * @returns Final pathname to be used in the URL
  * @returns Final pathname to be used in the URL
  */
  */
 function resolveFinalizedPathname(
 function resolveFinalizedPathname(
-    pagePath: string,
-    page: HydratedDocument<IPage> | null | undefined,
-    isPermalink: boolean,
+  pagePath: string,
+  page: HydratedDocument<IPage> | null | undefined,
+  isPermalink: boolean,
 ): string {
 ): string {
   let finalPathname = pagePath;
   let finalPathname = pagePath;
 
 
@@ -95,30 +109,37 @@ function resolveFinalizedPathname(
   return finalPathname;
   return finalPathname;
 }
 }
 
 
-
 // Page data retrieval for initial load - returns GetServerSidePropsResult
 // Page data retrieval for initial load - returns GetServerSidePropsResult
 export async function getPageDataForInitial(
 export async function getPageDataForInitial(
-    context: GetServerSidePropsContext,
-): Promise<GetServerSidePropsResult<
-  Pick<GeneralPageInitialProps, 'pageWithMeta' | 'skipSSR'> &
-  Pick<EachProps, 'currentPathname' | 'isIdenticalPathPage' | 'redirectFrom'>
->> {
+  context: GetServerSidePropsContext,
+): Promise<
+  GetServerSidePropsResult<
+    Pick<GeneralPageInitialProps, 'pageWithMeta' | 'skipSSR'> &
+      Pick<
+        EachProps,
+        'currentPathname' | 'isIdenticalPathPage' | 'redirectFrom'
+      >
+  >
+> {
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
   const { crowi, user } = req;
   const { crowi, user } = req;
   const { revisionId } = req.query;
   const { revisionId } = req.query;
 
 
   // Parse path from URL
   // Parse path from URL
   let { path: pathFromQuery } = context.query;
   let { path: pathFromQuery } = context.query;
-  pathFromQuery = pathFromQuery != null ? pathFromQuery as string[] : [];
+  pathFromQuery = pathFromQuery != null ? (pathFromQuery as string[]) : [];
   let pathFromUrl = `/${pathFromQuery.join('/')}`;
   let pathFromUrl = `/${pathFromQuery.join('/')}`;
   pathFromUrl = pathFromUrl === '//' ? '/' : pathFromUrl;
   pathFromUrl = pathFromUrl === '//' ? '/' : pathFromUrl;
 
 
   const { pageService, configManager } = crowi;
   const { pageService, configManager } = crowi;
 
 
-  const pageId = _isPermalink(pathFromUrl) ? removeHeadingSlash(pathFromUrl) : null;
+  const pageId = _isPermalink(pathFromUrl)
+    ? removeHeadingSlash(pathFromUrl)
+    : null;
   const isPermalink = _isPermalink(pathFromUrl);
   const isPermalink = _isPermalink(pathFromUrl);
 
 
-  const { resolvedPagePath, isIdenticalPathPage, redirectFrom } = await resolvePathAndCheckIdentical(pathFromUrl, user);
+  const { resolvedPagePath, isIdenticalPathPage, redirectFrom } =
+    await resolvePathAndCheckIdentical(pathFromUrl, user);
 
 
   if (isIdenticalPathPage) {
   if (isIdenticalPathPage) {
     return {
     return {
@@ -133,10 +154,18 @@ export async function getPageDataForInitial(
   }
   }
 
 
   // Get full page data
   // Get full page data
-  const pageWithMeta = await pageService.findPageAndMetaDataByViewer(pageId, resolvedPagePath, user);
+  const pageWithMeta = await pageService.findPageAndMetaDataByViewer(
+    pageId,
+    resolvedPagePath,
+    user,
+  );
 
 
   // Handle URL conversion
   // Handle URL conversion
-  const currentPathname = resolveFinalizedPathname(resolvedPagePath, pageWithMeta.data, isPermalink);
+  const currentPathname = resolveFinalizedPathname(
+    resolvedPagePath,
+    pageWithMeta.data,
+    isPermalink,
+  );
 
 
   // When the page exists
   // When the page exists
   if (pageWithMeta.data != null) {
   if (pageWithMeta.data != null) {
@@ -171,11 +200,15 @@ export async function getPageDataForInitial(
 
 
     // Handle existing page with valid meta that is not IPageNotFoundInfo
     // Handle existing page with valid meta that is not IPageNotFoundInfo
     page.initLatestRevisionField(revisionId);
     page.initLatestRevisionField(revisionId);
-    const ssrMaxRevisionBodyLength = configManager.getConfig('app:ssrMaxRevisionBodyLength');
+    const ssrMaxRevisionBodyLength = configManager.getConfig(
+      'app:ssrMaxRevisionBodyLength',
+    );
 
 
     // Check if SSR should be skipped
     // Check if SSR should be skipped
     const latestRevisionBodyLength = await page.getLatestRevisionBodyLength();
     const latestRevisionBodyLength = await page.getLatestRevisionBodyLength();
-    const skipSSR = latestRevisionBodyLength != null && ssrMaxRevisionBodyLength < latestRevisionBodyLength;
+    const skipSSR =
+      latestRevisionBodyLength != null &&
+      ssrMaxRevisionBodyLength < latestRevisionBodyLength;
 
 
     const populatedPage = await page.populateDataToShowRevision(skipSSR);
     const populatedPage = await page.populateDataToShowRevision(skipSSR);
 
 
@@ -194,14 +227,20 @@ export async function getPageDataForInitial(
   }
   }
 
 
   // type assertion
   // type assertion
-  assert(isIPageNotFoundInfo(pageWithMeta.meta), 'meta should be IPageNotFoundInfo when data is null');
+  assert(
+    isIPageNotFoundInfo(pageWithMeta.meta),
+    'meta should be IPageNotFoundInfo when data is null',
+  );
 
 
   // Handle the case where the page does not exist
   // Handle the case where the page does not exist
   return {
   return {
     props: {
     props: {
       currentPathname: resolvedPagePath,
       currentPathname: resolvedPagePath,
       isIdenticalPathPage: false,
       isIdenticalPathPage: false,
-      pageWithMeta: pageWithMeta satisfies IDataWithRequiredMeta<null, IPageNotFoundInfo>,
+      pageWithMeta: pageWithMeta satisfies IDataWithRequiredMeta<
+        null,
+        IPageNotFoundInfo
+      >,
       skipSSR: false,
       skipSSR: false,
       redirectFrom,
       redirectFrom,
     },
     },
@@ -210,19 +249,27 @@ export async function getPageDataForInitial(
 
 
 // Page data retrieval for same-route navigation
 // Page data retrieval for same-route navigation
 export async function getPageDataForSameRoute(
 export async function getPageDataForSameRoute(
-    context: GetServerSidePropsContext,
-): Promise<GetServerSidePropsResult<
+  context: GetServerSidePropsContext,
+): Promise<
+  GetServerSidePropsResult<
     Pick<CommonEachProps, 'currentPathname'> &
     Pick<CommonEachProps, 'currentPathname'> &
-    Pick<EachProps, 'currentPathname' | 'isIdenticalPathPage' | 'redirectFrom'>
->> {
+      Pick<
+        EachProps,
+        'currentPathname' | 'isIdenticalPathPage' | 'redirectFrom'
+      >
+  >
+> {
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
   const { user } = req;
   const { user } = req;
 
 
-  const pathname = decodeURIComponent(context.resolvedUrl?.split('?')[0] ?? '/');
+  const pathname = decodeURIComponent(
+    context.resolvedUrl?.split('?')[0] ?? '/',
+  );
   const pageId = _isPermalink(pathname) ? removeHeadingSlash(pathname) : null;
   const pageId = _isPermalink(pathname) ? removeHeadingSlash(pathname) : null;
   const isPermalink = _isPermalink(pathname);
   const isPermalink = _isPermalink(pathname);
 
 
-  const { resolvedPagePath, isIdenticalPathPage, redirectFrom } = await resolvePathAndCheckIdentical(pathname, user);
+  const { resolvedPagePath, isIdenticalPathPage, redirectFrom } =
+    await resolvePathAndCheckIdentical(pathname, user);
 
 
   if (isIdenticalPathPage) {
   if (isIdenticalPathPage) {
     return {
     return {
@@ -239,7 +286,11 @@ export async function getPageDataForSameRoute(
     isPermalink ? { _id: pageId } : { path: resolvedPagePath },
     isPermalink ? { _id: pageId } : { path: resolvedPagePath },
   ).exec();
   ).exec();
 
 
-  const currentPathname = resolveFinalizedPathname(resolvedPagePath, basicPageInfo, isPermalink);
+  const currentPathname = resolveFinalizedPathname(
+    resolvedPagePath,
+    basicPageInfo,
+    isPermalink,
+  );
 
 
   return {
   return {
     props: {
     props: {

+ 30 - 15
apps/app/src/pages/[[...path]]/server-side-props.ts

@@ -2,21 +2,23 @@ import type { GetServerSidePropsContext, GetServerSidePropsResult } from 'next';
 
 
 import { getServerSideBasicLayoutProps } from '../basic-layout-page';
 import { getServerSideBasicLayoutProps } from '../basic-layout-page';
 import {
 import {
-  getServerSideI18nProps, getServerSideCommonInitialProps,
+  getServerSideCommonInitialProps,
+  getServerSideI18nProps,
 } from '../common-props';
 } from '../common-props';
 import {
 import {
-  getServerSideRendererConfigProps,
   getActivityAction,
   getActivityAction,
   getServerSideGeneralPageProps,
   getServerSideGeneralPageProps,
+  getServerSideRendererConfigProps,
 } from '../general-page';
 } from '../general-page';
 import { isValidGeneralPageInitialProps } from '../general-page/type-guards';
 import { isValidGeneralPageInitialProps } from '../general-page/type-guards';
 import { addActivity } from '../utils/activity';
 import { addActivity } from '../utils/activity';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
-
 import { NEXT_JS_ROUTING_PAGE } from './consts';
 import { NEXT_JS_ROUTING_PAGE } from './consts';
-import { getPageDataForInitial, getPageDataForSameRoute } from './page-data-props';
-import type { Stage2InitialProps, Stage2EachProps } from './types';
-
+import {
+  getPageDataForInitial,
+  getPageDataForSameRoute,
+} from './page-data-props';
+import type { Stage2EachProps, Stage2InitialProps } from './types';
 
 
 const nextjsRoutingProps = {
 const nextjsRoutingProps = {
   props: {
   props: {
@@ -24,8 +26,9 @@ const nextjsRoutingProps = {
   },
   },
 };
 };
 
 
-export async function getServerSidePropsForInitial(context: GetServerSidePropsContext):
-    Promise<GetServerSidePropsResult<Stage2InitialProps>> {
+export async function getServerSidePropsForInitial(
+  context: GetServerSidePropsContext,
+): Promise<GetServerSidePropsResult<Stage2InitialProps>> {
   const [
   const [
     commonInitialResult,
     commonInitialResult,
     basicLayoutResult,
     basicLayoutResult,
@@ -43,12 +46,22 @@ export async function getServerSidePropsForInitial(context: GetServerSidePropsCo
   ]);
   ]);
 
 
   // Merge all results in a type-safe manner (using sequential merging)
   // Merge all results in a type-safe manner (using sequential merging)
-  const mergedResult = mergeGetServerSidePropsResults(commonInitialResult,
-    mergeGetServerSidePropsResults(basicLayoutResult,
-      mergeGetServerSidePropsResults(generalPageResult,
-        mergeGetServerSidePropsResults(rendererConfigResult,
-          mergeGetServerSidePropsResults(i18nPropsResult,
-            mergeGetServerSidePropsResults(pageDataResult, nextjsRoutingProps))))));
+  const mergedResult = mergeGetServerSidePropsResults(
+    commonInitialResult,
+    mergeGetServerSidePropsResults(
+      basicLayoutResult,
+      mergeGetServerSidePropsResults(
+        generalPageResult,
+        mergeGetServerSidePropsResults(
+          rendererConfigResult,
+          mergeGetServerSidePropsResults(
+            i18nPropsResult,
+            mergeGetServerSidePropsResults(pageDataResult, nextjsRoutingProps),
+          ),
+        ),
+      ),
+    ),
+  );
 
 
   // Check for early return (redirect/notFound)
   // Check for early return (redirect/notFound)
   if ('redirect' in mergedResult || 'notFound' in mergedResult) {
   if ('redirect' in mergedResult || 'notFound' in mergedResult) {
@@ -67,7 +80,9 @@ export async function getServerSidePropsForInitial(context: GetServerSidePropsCo
   return mergedResult;
   return mergedResult;
 }
 }
 
 
-export async function getServerSidePropsForSameRoute(context: GetServerSidePropsContext): Promise<GetServerSidePropsResult<Stage2EachProps>> {
+export async function getServerSidePropsForSameRoute(
+  context: GetServerSidePropsContext,
+): Promise<GetServerSidePropsResult<Stage2EachProps>> {
   // Get page data
   // Get page data
   const result = await getPageDataForSameRoute(context);
   const result = await getPageDataForSameRoute(context);
 
 

+ 13 - 6
apps/app/src/pages/[[...path]]/types.ts

@@ -1,18 +1,25 @@
 import type { BasicLayoutConfigurationProps } from '../basic-layout-page';
 import type { BasicLayoutConfigurationProps } from '../basic-layout-page';
 import type { CommonEachProps, CommonInitialProps } from '../common-props';
 import type { CommonEachProps, CommonInitialProps } from '../common-props';
-import type { GeneralPageEachProps, GeneralPageInitialProps } from '../general-page';
+import type {
+  GeneralPageEachProps,
+  GeneralPageInitialProps,
+} from '../general-page';
 
 
 type PageEachProps = {
 type PageEachProps = {
   redirectFrom?: string;
   redirectFrom?: string;
 
 
-  isIdenticalPathPage: boolean,
+  isIdenticalPathPage: boolean;
 
 
-  templateTagData?: string[],
-  templateBodyData?: string,
+  templateTagData?: string[];
+  templateBodyData?: string;
 };
 };
 
 
 export type Stage2EachProps = GeneralPageEachProps & PageEachProps;
 export type Stage2EachProps = GeneralPageEachProps & PageEachProps;
-export type Stage2InitialProps = Stage2EachProps & GeneralPageInitialProps & BasicLayoutConfigurationProps;
+export type Stage2InitialProps = Stage2EachProps &
+  GeneralPageInitialProps &
+  BasicLayoutConfigurationProps;
 
 
 export type EachProps = CommonEachProps & Stage2EachProps;
 export type EachProps = CommonEachProps & Stage2EachProps;
-export type InitialProps = CommonEachProps & CommonInitialProps & Stage2InitialProps;
+export type InitialProps = CommonEachProps &
+  CommonInitialProps &
+  Stage2InitialProps;

+ 18 - 10
apps/app/src/pages/[[...path]]/use-same-route-navigation.spec.tsx

@@ -1,7 +1,7 @@
-import type { IPagePopulatedToShowRevision } from '@growi/core';
-import { renderHook, waitFor } from '@testing-library/react';
 import type { NextRouter } from 'next/router';
 import type { NextRouter } from 'next/router';
 import { useRouter } from 'next/router';
 import { useRouter } from 'next/router';
+import type { IPagePopulatedToShowRevision } from '@growi/core';
+import { renderHook, waitFor } from '@testing-library/react';
 import { vi } from 'vitest';
 import { vi } from 'vitest';
 import { mock } from 'vitest-mock-extended';
 import { mock } from 'vitest-mock-extended';
 
 
@@ -41,18 +41,22 @@ describe('useSameRouteNavigation', () => {
     };
     };
 
 
     // Mock useRouter to return our mutable router object
     // Mock useRouter to return our mutable router object
-    (useRouter as ReturnType<typeof vi.fn>).mockReturnValue(mockRouter as NextRouter);
+    (useRouter as ReturnType<typeof vi.fn>).mockReturnValue(
+      mockRouter as NextRouter,
+    );
 
 
     (useFetchCurrentPage as ReturnType<typeof vi.fn>).mockReturnValue({
     (useFetchCurrentPage as ReturnType<typeof vi.fn>).mockReturnValue({
       fetchCurrentPage: mockFetchCurrentPage,
       fetchCurrentPage: mockFetchCurrentPage,
     });
     });
 
 
-    (useSetEditingMarkdown as ReturnType<typeof vi.fn>).mockReturnValue(mockSetEditingMarkdown);
+    (useSetEditingMarkdown as ReturnType<typeof vi.fn>).mockReturnValue(
+      mockSetEditingMarkdown,
+    );
 
 
     mockFetchCurrentPage.mockResolvedValue(pageDataMock);
     mockFetchCurrentPage.mockResolvedValue(pageDataMock);
   });
   });
 
 
-  it('should call fetchCurrentPage and mutateEditingMarkdown on path change', async() => {
+  it('should call fetchCurrentPage and mutateEditingMarkdown on path change', async () => {
     // Arrange
     // Arrange
     mockRouter.asPath = '/initial-path';
     mockRouter.asPath = '/initial-path';
     const { rerender } = renderHook(() => useSameRouteNavigation());
     const { rerender } = renderHook(() => useSameRouteNavigation());
@@ -67,11 +71,13 @@ describe('useSameRouteNavigation', () => {
       expect(mockFetchCurrentPage).toHaveBeenCalledWith({ path: '/new-path' });
       expect(mockFetchCurrentPage).toHaveBeenCalledWith({ path: '/new-path' });
 
 
       // 2. mutateEditingMarkdown is called with the content from the fetched page
       // 2. mutateEditingMarkdown is called with the content from the fetched page
-      expect(mockSetEditingMarkdown).toHaveBeenCalledWith(pageDataMock.revision?.body);
+      expect(mockSetEditingMarkdown).toHaveBeenCalledWith(
+        pageDataMock.revision?.body,
+      );
     });
     });
   });
   });
 
 
-  it('should not trigger effects if the path does not change', async() => {
+  it('should not trigger effects if the path does not change', async () => {
     // Arrange
     // Arrange
     mockRouter.asPath = '/same-path';
     mockRouter.asPath = '/same-path';
     const { rerender } = renderHook(() => useSameRouteNavigation());
     const { rerender } = renderHook(() => useSameRouteNavigation());
@@ -86,12 +92,12 @@ describe('useSameRouteNavigation', () => {
 
 
     // Assert
     // Assert
     // A short delay to ensure no async operations are triggered
     // A short delay to ensure no async operations are triggered
-    await new Promise(resolve => setTimeout(resolve, 100));
+    await new Promise((resolve) => setTimeout(resolve, 100));
     expect(mockFetchCurrentPage).toHaveBeenCalledTimes(1); // Should not be called again
     expect(mockFetchCurrentPage).toHaveBeenCalledTimes(1); // Should not be called again
     expect(mockSetEditingMarkdown).toHaveBeenCalledTimes(1);
     expect(mockSetEditingMarkdown).toHaveBeenCalledTimes(1);
   });
   });
 
 
-  it('should not call mutateEditingMarkdown if pageData or revision is null', async() => {
+  it('should not call mutateEditingMarkdown if pageData or revision is null', async () => {
     // Arrange: first, fetch successfully
     // Arrange: first, fetch successfully
     mockRouter.asPath = '/initial-path';
     mockRouter.asPath = '/initial-path';
     const { rerender } = renderHook(() => useSameRouteNavigation());
     const { rerender } = renderHook(() => useSameRouteNavigation());
@@ -110,7 +116,9 @@ describe('useSameRouteNavigation', () => {
     // Assert
     // Assert
     await waitFor(() => {
     await waitFor(() => {
       // fetch should be called again
       // fetch should be called again
-      expect(mockFetchCurrentPage).toHaveBeenCalledWith({ path: '/path-with-no-data' });
+      expect(mockFetchCurrentPage).toHaveBeenCalledWith({
+        path: '/path-with-no-data',
+      });
       // but mutate should not be called again
       // but mutate should not be called again
       expect(mockSetEditingMarkdown).toHaveBeenCalledTimes(1);
       expect(mockSetEditingMarkdown).toHaveBeenCalledTimes(1);
     });
     });

+ 1 - 2
apps/app/src/pages/[[...path]]/use-same-route-navigation.ts

@@ -1,5 +1,4 @@
 import { useEffect } from 'react';
 import { useEffect } from 'react';
-
 import { useRouter } from 'next/router';
 import { useRouter } from 'next/router';
 
 
 import { useFetchCurrentPage } from '~/states/page';
 import { useFetchCurrentPage } from '~/states/page';
@@ -18,7 +17,7 @@ export const useSameRouteNavigation = (): void => {
 
 
   // useEffect to trigger data fetching when the path changes
   // useEffect to trigger data fetching when the path changes
   useEffect(() => {
   useEffect(() => {
-    const fetch = async() => {
+    const fetch = async () => {
       const pageData = await fetchCurrentPage({ path: router.asPath });
       const pageData = await fetchCurrentPage({ path: router.asPath });
       if (pageData?.revision?.body != null) {
       if (pageData?.revision?.body != null) {
         setEditingMarkdown(pageData.revision.body);
         setEditingMarkdown(pageData.revision.body);

+ 4 - 3
apps/app/src/pages/[[...path]]/use-shallow-routing.ts

@@ -1,7 +1,6 @@
 import { useEffect, useRef } from 'react';
 import { useEffect, useRef } from 'react';
-
-import { isClient } from '@growi/core/dist/utils';
 import { useRouter } from 'next/router';
 import { useRouter } from 'next/router';
+import { isClient } from '@growi/core/dist/utils';
 
 
 import type { CommonEachProps } from '../common-props';
 import type { CommonEachProps } from '../common-props';
 
 
@@ -25,7 +24,9 @@ export const useShallowRouting = (props: CommonEachProps): void => {
     // Only update if URLs actually differ
     // Only update if URLs actually differ
     if (currentURL !== props.currentPathname) {
     if (currentURL !== props.currentPathname) {
       const { search, hash } = window.location;
       const { search, hash } = window.location;
-      router.replace(`${props.currentPathname}${search}${hash}`, undefined, { shallow: true });
+      router.replace(`${props.currentPathname}${search}${hash}`, undefined, {
+        shallow: true,
+      });
     }
     }
 
 
     // Update reference for next comparison
     // Update reference for next comparison

+ 34 - 21
apps/app/src/pages/_app.page.tsx

@@ -1,20 +1,22 @@
-import type { ReactNode, JSX } from 'react';
+import type { JSX, ReactNode } from 'react';
 import React, { useEffect } from 'react';
 import React, { useEffect } from 'react';
-
-import type { Locale } from '@growi/core/dist/interfaces';
-import { Provider } from 'jotai';
 import type { NextPage } from 'next';
 import type { NextPage } from 'next';
-import { appWithTranslation } from 'next-i18next';
 import type { AppContext, AppProps } from 'next/app';
 import type { AppContext, AppProps } from 'next/app';
 import App from 'next/app';
 import App from 'next/app';
 import { useRouter } from 'next/router';
 import { useRouter } from 'next/router';
+import type { Locale } from '@growi/core/dist/interfaces';
+import { Provider } from 'jotai';
+import { appWithTranslation } from 'next-i18next';
 import { SWRConfig } from 'swr';
 import { SWRConfig } from 'swr';
 
 
 import * as nextI18nConfig from '^/config/next-i18next.config';
 import * as nextI18nConfig from '^/config/next-i18next.config';
 
 
 import { GlobalFonts } from '~/components/FontFamily/GlobalFonts';
 import { GlobalFonts } from '~/components/FontFamily/GlobalFonts';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
-import { useHydrateGlobalEachAtoms, useHydrateGlobalInitialAtoms } from '~/states/global/hydrate';
+import {
+  useHydrateGlobalEachAtoms,
+  useHydrateGlobalInitialAtoms,
+} from '~/states/global/hydrate';
 import { swrGlobalConfiguration } from '~/utils/swr-utils';
 import { swrGlobalConfiguration } from '~/utils/swr-utils';
 
 
 import type { CommonEachProps, CommonInitialProps } from './common-props';
 import type { CommonEachProps, CommonInitialProps } from './common-props';
@@ -29,33 +31,42 @@ import '~/styles/style-app.scss';
 // register custom serializer
 // register custom serializer
 registerTransformerForObjectId();
 registerTransformerForObjectId();
 
 
-const StateManagementContainer = ({ children }: { children: ReactNode }): JSX.Element => {
+const StateManagementContainer = ({
+  children,
+}: {
+  children: ReactNode;
+}): JSX.Element => {
   return (
   return (
     <SWRConfig value={swrGlobalConfiguration}>
     <SWRConfig value={swrGlobalConfiguration}>
-      <Provider>
-        {children}
-      </Provider>
+      <Provider>{children}</Provider>
     </SWRConfig>
     </SWRConfig>
   );
   );
 };
 };
 
 
-
 // eslint-disable-next-line @typescript-eslint/ban-types
 // eslint-disable-next-line @typescript-eslint/ban-types
 export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
 export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
-  getLayout?: (page: JSX.Element) => ReactNode,
-}
+  getLayout?: (page: JSX.Element) => ReactNode;
+};
 
 
-type CombinedCommonProps = CommonEachProps | (CommonEachProps & CommonInitialProps);
+type CombinedCommonProps =
+  | CommonEachProps
+  | (CommonEachProps & CommonInitialProps);
 type GrowiAppProps = AppProps<CombinedCommonProps> & {
 type GrowiAppProps = AppProps<CombinedCommonProps> & {
-  Component: NextPageWithLayout<CombinedCommonProps>,
-  userLocale: Locale,
+  Component: NextPageWithLayout<CombinedCommonProps>;
+  userLocale: Locale;
 };
 };
 
 
-const GrowiAppSubstance = ({ Component, pageProps, userLocale }: GrowiAppProps): JSX.Element => {
+const GrowiAppSubstance = ({
+  Component,
+  pageProps,
+  userLocale,
+}: GrowiAppProps): JSX.Element => {
   const router = useRouter();
   const router = useRouter();
 
 
   // Hydrate global atoms with server-side data
   // Hydrate global atoms with server-side data
-  useHydrateGlobalInitialAtoms(isCommonInitialProps(pageProps) ? pageProps : undefined);
+  useHydrateGlobalInitialAtoms(
+    isCommonInitialProps(pageProps) ? pageProps : undefined,
+  );
   useHydrateGlobalEachAtoms(pageProps);
   useHydrateGlobalEachAtoms(pageProps);
 
 
   useNextjsRoutingPageRegister(pageProps.nextjsRoutingPage);
   useNextjsRoutingPageRegister(pageProps.nextjsRoutingPage);
@@ -77,7 +88,7 @@ const GrowiAppSubstance = ({ Component, pageProps, userLocale }: GrowiAppProps):
   }, []);
   }, []);
 
 
   // Use the layout defined at the page level, if available
   // Use the layout defined at the page level, if available
-  const getLayout = Component.getLayout ?? (page => page);
+  const getLayout = Component.getLayout ?? ((page) => page);
 
 
   return <>{getLayout(<Component {...pageProps} />)}</>;
   return <>{getLayout(<Component {...pageProps} />)}</>;
 };
 };
@@ -94,9 +105,11 @@ function GrowiApp(props: GrowiAppProps): JSX.Element {
 }
 }
 
 
 // inject userLocale by context
 // inject userLocale by context
-GrowiApp.getInitialProps = async(appContext: AppContext) => {
+GrowiApp.getInitialProps = async (appContext: AppContext) => {
   const appProps = App.getInitialProps(appContext);
   const appProps = App.getInitialProps(appContext);
-  const userLocale = getLocaleAtServerSide(appContext.ctx.req as unknown as CrowiRequest);
+  const userLocale = getLocaleAtServerSide(
+    appContext.ctx.req as unknown as CrowiRequest,
+  );
 
 
   return { ...appProps, userLocale };
   return { ...appProps, userLocale };
 };
 };

+ 47 - 28
apps/app/src/pages/_document.page.tsx

@@ -1,11 +1,8 @@
 /* eslint-disable @next/next/google-font-display */
 /* eslint-disable @next/next/google-font-display */
 import React, { type JSX } from 'react';
 import React, { type JSX } from 'react';
-
-import type { Locale } from '@growi/core/dist/interfaces';
 import type { DocumentContext, DocumentInitialProps } from 'next/document';
 import type { DocumentContext, DocumentInitialProps } from 'next/document';
-import Document, {
-  Html, Head, Main, NextScript,
-} from 'next/document';
+import Document, { Head, Html, Main, NextScript } from 'next/document';
+import type { Locale } from '@growi/core/dist/interfaces';
 
 
 import type { GrowiPluginResourceEntries } from '~/features/growi-plugin/server/services';
 import type { GrowiPluginResourceEntries } from '~/features/growi-plugin/server/services';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
@@ -13,47 +10,54 @@ import loggerFactory from '~/utils/logger';
 
 
 import { getLocaleAtServerSide } from './utils/locale';
 import { getLocaleAtServerSide } from './utils/locale';
 
 
-
 const logger = loggerFactory('growi:page:_document');
 const logger = loggerFactory('growi:page:_document');
 
 
 type HeadersForGrowiPluginProps = {
 type HeadersForGrowiPluginProps = {
   pluginResourceEntries: GrowiPluginResourceEntries;
   pluginResourceEntries: GrowiPluginResourceEntries;
-}
-const HeadersForGrowiPlugin = (props: HeadersForGrowiPluginProps): JSX.Element => {
+};
+const HeadersForGrowiPlugin = (
+  props: HeadersForGrowiPluginProps,
+): JSX.Element => {
   const { pluginResourceEntries } = props;
   const { pluginResourceEntries } = props;
 
 
   return (
   return (
     <>
     <>
-      { pluginResourceEntries.map(([installedPath, href]) => {
+      {pluginResourceEntries.map(([installedPath, href]) => {
         if (href.endsWith('.js')) {
         if (href.endsWith('.js')) {
           // eslint-disable-next-line @next/next/no-sync-scripts
           // eslint-disable-next-line @next/next/no-sync-scripts
-          return <script type="module" key={`script_${installedPath}`} src={href} />;
+          return (
+            <script type="module" key={`script_${installedPath}`} src={href} />
+          );
         }
         }
         if (href.endsWith('.css')) {
         if (href.endsWith('.css')) {
           // eslint-disable-next-line @next/next/no-sync-scripts
           // eslint-disable-next-line @next/next/no-sync-scripts
-          return <link rel="stylesheet" key={`link_${installedPath}`} href={href} />;
+          return (
+            <link rel="stylesheet" key={`link_${installedPath}`} href={href} />
+          );
         }
         }
         return <></>;
         return <></>;
-      }) }
+      })}
     </>
     </>
   );
   );
 };
 };
 
 
 interface GrowiDocumentProps {
 interface GrowiDocumentProps {
-  themeHref: string,
-  customScript: string | null,
-  customCss: string | null,
-  customNoscript: string | null,
+  themeHref: string;
+  customScript: string | null;
+  customCss: string | null;
+  customNoscript: string | null;
   pluginResourceEntries: GrowiPluginResourceEntries;
   pluginResourceEntries: GrowiPluginResourceEntries;
   locale: Locale;
   locale: Locale;
 }
 }
-declare type GrowiDocumentInitialProps = DocumentInitialProps & GrowiDocumentProps;
+declare type GrowiDocumentInitialProps = DocumentInitialProps &
+  GrowiDocumentProps;
 
 
 class GrowiDocument extends Document<GrowiDocumentInitialProps> {
 class GrowiDocument extends Document<GrowiDocumentInitialProps> {
-
-  static override async getInitialProps(ctx: DocumentContext): Promise<GrowiDocumentInitialProps> {
-
-    const initialProps: DocumentInitialProps = await Document.getInitialProps(ctx);
+  static override async getInitialProps(
+    ctx: DocumentContext,
+  ): Promise<GrowiDocumentInitialProps> {
+    const initialProps: DocumentInitialProps =
+      await Document.getInitialProps(ctx);
     const req = ctx.req as CrowiRequest;
     const req = ctx.req as CrowiRequest;
     const { crowi } = req;
     const { crowi } = req;
     const { customizeService } = crowi;
     const { customizeService } = crowi;
@@ -64,8 +68,11 @@ class GrowiDocument extends Document<GrowiDocumentInitialProps> {
     const customNoscript: string | null = customizeService.getCustomNoscript();
     const customNoscript: string | null = customizeService.getCustomNoscript();
 
 
     // retrieve plugin manifests
     // retrieve plugin manifests
-    const growiPluginService = await import('~/features/growi-plugin/server/services').then(mod => mod.growiPluginService);
-    const pluginResourceEntries = await growiPluginService.retrieveAllPluginResourceEntries();
+    const growiPluginService = await import(
+      '~/features/growi-plugin/server/services'
+    ).then((mod) => mod.growiPluginService);
+    const pluginResourceEntries =
+      await growiPluginService.retrieveAllPluginResourceEntries();
 
 
     const locale = getLocaleAtServerSide(req);
     const locale = getLocaleAtServerSide(req);
 
 
@@ -84,13 +91,20 @@ class GrowiDocument extends Document<GrowiDocumentInitialProps> {
     if (customScript == null || customScript.length === 0) {
     if (customScript == null || customScript.length === 0) {
       return <></>;
       return <></>;
     }
     }
-    return <script id="customScript" dangerouslySetInnerHTML={{ __html: customScript }} />;
+    return (
+      <script
+        id="customScript"
+        // biome-ignore lint/security/noDangerouslySetInnerHtml: ignore
+        dangerouslySetInnerHTML={{ __html: customScript }}
+      />
+    );
   }
   }
 
 
   renderCustomCss(customCss: string | null): JSX.Element {
   renderCustomCss(customCss: string | null): JSX.Element {
     if (customCss == null || customCss.length === 0) {
     if (customCss == null || customCss.length === 0) {
       return <></>;
       return <></>;
     }
     }
+    // biome-ignore lint/security/noDangerouslySetInnerHtml: ignore
     return <style dangerouslySetInnerHTML={{ __html: customCss }} />;
     return <style dangerouslySetInnerHTML={{ __html: customCss }} />;
   }
   }
 
 
@@ -98,13 +112,17 @@ class GrowiDocument extends Document<GrowiDocumentInitialProps> {
     if (customNoscript == null || customNoscript.length === 0) {
     if (customNoscript == null || customNoscript.length === 0) {
       return <></>;
       return <></>;
     }
     }
+    // biome-ignore lint/security/noDangerouslySetInnerHtml: ignore
     return <noscript dangerouslySetInnerHTML={{ __html: customNoscript }} />;
     return <noscript dangerouslySetInnerHTML={{ __html: customNoscript }} />;
   }
   }
 
 
   override render(): JSX.Element {
   override render(): JSX.Element {
     const {
     const {
-      customCss, customScript, customNoscript,
-      themeHref, pluginResourceEntries,
+      customCss,
+      customScript,
+      customNoscript,
+      themeHref,
+      pluginResourceEntries,
       locale,
       locale,
     } = this.props;
     } = this.props;
 
 
@@ -115,7 +133,9 @@ class GrowiDocument extends Document<GrowiDocumentInitialProps> {
           <link rel="stylesheet" key="link-theme" href={themeHref} />
           <link rel="stylesheet" key="link-theme" href={themeHref} />
           <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
           <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
           <link rel="alternate icon" href="/favicon.ico" />
           <link rel="alternate icon" href="/favicon.ico" />
-          <HeadersForGrowiPlugin pluginResourceEntries={pluginResourceEntries} />
+          <HeadersForGrowiPlugin
+            pluginResourceEntries={pluginResourceEntries}
+          />
           {this.renderCustomCss(customCss)}
           {this.renderCustomCss(customCss)}
         </Head>
         </Head>
         <body>
         <body>
@@ -126,7 +146,6 @@ class GrowiDocument extends Document<GrowiDocumentInitialProps> {
       </Html>
       </Html>
     );
     );
   }
   }
-
 }
 }
 
 
 export default GrowiDocument;
 export default GrowiDocument;

+ 2 - 4
apps/app/src/pages/_error.page.tsx

@@ -1,12 +1,10 @@
 import type { JSX } from 'react';
 import type { JSX } from 'react';
-
 import type { NextPageContext } from 'next';
 import type { NextPageContext } from 'next';
 import type { ErrorProps } from 'next/error';
 import type { ErrorProps } from 'next/error';
-import Error from 'next/error';
-
+import NextError from 'next/error';
 
 
 export default function ErrorPage(props: ErrorProps): JSX.Element {
 export default function ErrorPage(props: ErrorProps): JSX.Element {
-  return <Error {...props} />;
+  return <NextError {...props} />;
 }
 }
 
 
 // add getInitialProps to disable "https://nextjs.org/docs/messages/prerender-error"
 // add getInitialProps to disable "https://nextjs.org/docs/messages/prerender-error"

+ 20 - 11
apps/app/src/pages/_private-legacy-pages/index.page.tsx

@@ -1,10 +1,8 @@
 import { useEffect } from 'react';
 import { useEffect } from 'react';
-
 import type { NextPage } from 'next';
 import type { NextPage } from 'next';
-import { useTranslation } from 'next-i18next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 import Head from 'next/head';
 import Head from 'next/head';
-import { useRouter } from 'next/router';
+import { useTranslation } from 'next-i18next';
 
 
 import { DrawioViewerScript } from '~/components/Script/DrawioViewerScript';
 import { DrawioViewerScript } from '~/components/Script/DrawioViewerScript';
 import { useSetSearchPage } from '~/states/context';
 import { useSetSearchPage } from '~/states/context';
@@ -18,17 +16,24 @@ import type { CommonEachProps, CommonInitialProps } from '../common-props';
 import type { RendererConfigProps } from '../general-page';
 import type { RendererConfigProps } from '../general-page';
 import { useCustomTitle } from '../utils/page-title-customization';
 import { useCustomTitle } from '../utils/page-title-customization';
 
 
+const SearchResultLayout = dynamic(
+  () => import('~/components/Layout/SearchResultLayout'),
+  { ssr: false },
+);
 
 
-const SearchResultLayout = dynamic(() => import('~/components/Layout/SearchResultLayout'), { ssr: false });
-
-
-type Props = CommonInitialProps & CommonEachProps & BasicLayoutConfigurationProps & ServerConfigurationProps & RendererConfigProps;
+type Props = CommonInitialProps &
+  CommonEachProps &
+  BasicLayoutConfigurationProps &
+  ServerConfigurationProps &
+  RendererConfigProps;
 
 
 const PrivateLegacyPage: NextPage<Props> = (props: Props) => {
 const PrivateLegacyPage: NextPage<Props> = (props: Props) => {
-  const router = useRouter();
   const { t } = useTranslation();
   const { t } = useTranslation();
 
 
-  const PrivateLegacyPages = dynamic(() => import('~/features/search/client/components/PrivateLegacyPages'), { ssr: false });
+  const PrivateLegacyPages = dynamic(
+    () => import('~/features/search/client/components/PrivateLegacyPages'),
+    { ssr: false },
+  );
 
 
   // clear the cache for the current page
   // clear the cache for the current page
   //  in order to fix https://redmine.weseek.co.jp/issues/135811
   //  in order to fix https://redmine.weseek.co.jp/issues/135811
@@ -36,7 +41,11 @@ const PrivateLegacyPage: NextPage<Props> = (props: Props) => {
   // useCurrentPathname('/_private-legacy-pages');
   // useCurrentPathname('/_private-legacy-pages');
 
 
   // Hydrate server-side data
   // Hydrate server-side data
-  useHydrateBasicLayoutConfigurationAtoms(props.searchConfig, props.sidebarConfig, props.userUISettings);
+  useHydrateBasicLayoutConfigurationAtoms(
+    props.searchConfig,
+    props.sidebarConfig,
+    props.userUISettings,
+  );
   useHydrateServerConfigurationAtoms(props.serverConfig, props.rendererConfig);
   useHydrateServerConfigurationAtoms(props.serverConfig, props.rendererConfig);
 
 
   const setSearchPage = useSetSearchPage();
   const setSearchPage = useSetSearchPage();
@@ -46,7 +55,7 @@ const PrivateLegacyPage: NextPage<Props> = (props: Props) => {
     setSearchPage(true);
     setSearchPage(true);
     // cleanup
     // cleanup
     return () => setSearchPage(false);
     return () => setSearchPage(false);
-  }, [router, setSearchPage]);
+  }, [setSearchPage]);
 
 
   const title = useCustomTitle(t('private_legacy_pages.title'));
   const title = useCustomTitle(t('private_legacy_pages.title'));
 
 

+ 35 - 11
apps/app/src/pages/_search/get-server-side-props/index.ts

@@ -1,17 +1,25 @@
-import { isPermalink, isUserPage, isUsersTopPage } from '@growi/core/dist/utils/page-path-utils';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
+import {
+  isPermalink,
+  isUserPage,
+  isUsersTopPage,
+} from '@growi/core/dist/utils/page-path-utils';
 
 
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 
 
 import { getServerSideBasicLayoutProps } from '../../basic-layout-page';
 import { getServerSideBasicLayoutProps } from '../../basic-layout-page';
 import {
 import {
-  getServerSideCommonEachProps, getServerSideCommonInitialProps, getServerSideI18nProps,
+  getServerSideCommonEachProps,
+  getServerSideCommonInitialProps,
+  getServerSideI18nProps,
 } from '../../common-props';
 } from '../../common-props';
 import { getServerSideRendererConfigProps } from '../../general-page';
 import { getServerSideRendererConfigProps } from '../../general-page';
 import { mergeGetServerSidePropsResults } from '../../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../../utils/server-side-props';
 import type { ServerConfigurationProps } from '../types';
 import type { ServerConfigurationProps } from '../types';
 
 
-const getServerSideConfigurationProps: GetServerSideProps<ServerConfigurationProps> = async(context: GetServerSidePropsContext) => {
+const getServerSideConfigurationProps: GetServerSideProps<
+  ServerConfigurationProps
+> = async (context: GetServerSidePropsContext) => {
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
   const { crowi } = req;
   const { crowi } = req;
   const { configManager } = crowi;
   const { configManager } = crowi;
@@ -20,19 +28,27 @@ const getServerSideConfigurationProps: GetServerSideProps<ServerConfigurationPro
     props: {
     props: {
       serverConfig: {
       serverConfig: {
         isContainerFluid: configManager.getConfig('customize:isContainerFluid'),
         isContainerFluid: configManager.getConfig('customize:isContainerFluid'),
-        showPageLimitationL: configManager.getConfig('customize:showPageLimitationL'),
+        showPageLimitationL: configManager.getConfig(
+          'customize:showPageLimitationL',
+        ),
       },
       },
     },
     },
   };
   };
 };
 };
 
 
-export const getServerSideSearchPageProps: GetServerSideProps = async(context: GetServerSidePropsContext) => {
+export const getServerSideSearchPageProps: GetServerSideProps = async (
+  context: GetServerSidePropsContext,
+) => {
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
 
 
   // redirect to the page the user was on before moving to the Login Page
   // redirect to the page the user was on before moving to the Login Page
   if (req.headers.referer != null) {
   if (req.headers.referer != null) {
     const urlBeforeLogin = new URL(req.headers.referer);
     const urlBeforeLogin = new URL(req.headers.referer);
-    if (isPermalink(urlBeforeLogin.pathname) || isUserPage(urlBeforeLogin.pathname) || isUsersTopPage(urlBeforeLogin.pathname)) {
+    if (
+      isPermalink(urlBeforeLogin.pathname) ||
+      isUserPage(urlBeforeLogin.pathname) ||
+      isUsersTopPage(urlBeforeLogin.pathname)
+    ) {
       req.session.redirectTo = urlBeforeLogin.href;
       req.session.redirectTo = urlBeforeLogin.href;
     }
     }
   }
   }
@@ -53,9 +69,17 @@ export const getServerSideSearchPageProps: GetServerSideProps = async(context: G
     getServerSideI18nProps(context, ['translation']),
     getServerSideI18nProps(context, ['translation']),
   ]);
   ]);
 
 
-  return mergeGetServerSidePropsResults(commonInitialResult,
-    mergeGetServerSidePropsResults(commonEachResult,
-      mergeGetServerSidePropsResults(basicLayoutResult,
-        mergeGetServerSidePropsResults(rendererConfigResult,
-          mergeGetServerSidePropsResults(serverConfigResult, i18nPropsResult)))));
+  return mergeGetServerSidePropsResults(
+    commonInitialResult,
+    mergeGetServerSidePropsResults(
+      commonEachResult,
+      mergeGetServerSidePropsResults(
+        basicLayoutResult,
+        mergeGetServerSidePropsResults(
+          rendererConfigResult,
+          mergeGetServerSidePropsResults(serverConfigResult, i18nPropsResult),
+        ),
+      ),
+    ),
+  );
 };
 };

+ 24 - 11
apps/app/src/pages/_search/index.page.tsx

@@ -1,9 +1,8 @@
 import { useEffect } from 'react';
 import { useEffect } from 'react';
-
-import { useTranslation } from 'next-i18next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 import Head from 'next/head';
 import Head from 'next/head';
 import { useRouter } from 'next/router';
 import { useRouter } from 'next/router';
+import { useTranslation } from 'next-i18next';
 
 
 import { DrawioViewerScript } from '~/components/Script/DrawioViewerScript';
 import { DrawioViewerScript } from '~/components/Script/DrawioViewerScript';
 import { useSetSearchPage } from '~/states/context';
 import { useSetSearchPage } from '~/states/context';
@@ -14,19 +13,29 @@ import { useHydrateBasicLayoutConfigurationAtoms } from '../basic-layout-page/hy
 import type { CommonEachProps, CommonInitialProps } from '../common-props';
 import type { CommonEachProps, CommonInitialProps } from '../common-props';
 import type { RendererConfigProps } from '../general-page';
 import type { RendererConfigProps } from '../general-page';
 import { useCustomTitle } from '../utils/page-title-customization';
 import { useCustomTitle } from '../utils/page-title-customization';
-
 import { getServerSideSearchPageProps } from './get-server-side-props';
 import { getServerSideSearchPageProps } from './get-server-side-props';
 import type { ServerConfigurationProps } from './types';
 import type { ServerConfigurationProps } from './types';
 import { useHydrateServerConfigurationAtoms } from './use-hydrate-server-configurations';
 import { useHydrateServerConfigurationAtoms } from './use-hydrate-server-configurations';
 
 
-
-const SearchResultLayout = dynamic(() => import('~/components/Layout/SearchResultLayout'), { ssr: false });
-const SearchPage = dynamic(() => import('~/features/search/client/components/SearchPage').then(mod => mod.SearchPage), { ssr: false });
-
-type Props = CommonInitialProps & CommonEachProps & BasicLayoutConfigurationProps & ServerConfigurationProps & RendererConfigProps;
+const SearchResultLayout = dynamic(
+  () => import('~/components/Layout/SearchResultLayout'),
+  { ssr: false },
+);
+const SearchPage = dynamic(
+  () =>
+    import('~/features/search/client/components/SearchPage').then(
+      (mod) => mod.SearchPage,
+    ),
+  { ssr: false },
+);
+
+type Props = CommonInitialProps &
+  CommonEachProps &
+  BasicLayoutConfigurationProps &
+  ServerConfigurationProps &
+  RendererConfigProps;
 
 
 const SearchResultPage: NextPageWithLayout<Props> = (props: Props) => {
 const SearchResultPage: NextPageWithLayout<Props> = (props: Props) => {
-  const router = useRouter();
   const { t } = useTranslation();
   const { t } = useTranslation();
 
 
   // clear the cache for the current page
   // clear the cache for the current page
@@ -35,7 +44,11 @@ const SearchResultPage: NextPageWithLayout<Props> = (props: Props) => {
   // useCurrentPathname('/_search');
   // useCurrentPathname('/_search');
 
 
   // Hydrate server-side data
   // Hydrate server-side data
-  useHydrateBasicLayoutConfigurationAtoms(props.searchConfig, props.sidebarConfig, props.userUISettings);
+  useHydrateBasicLayoutConfigurationAtoms(
+    props.searchConfig,
+    props.sidebarConfig,
+    props.userUISettings,
+  );
   useHydrateServerConfigurationAtoms(props.serverConfig, props.rendererConfig);
   useHydrateServerConfigurationAtoms(props.serverConfig, props.rendererConfig);
 
 
   const setSearchPage = useSetSearchPage();
   const setSearchPage = useSetSearchPage();
@@ -45,7 +58,7 @@ const SearchResultPage: NextPageWithLayout<Props> = (props: Props) => {
     setSearchPage(true);
     setSearchPage(true);
     // cleanup
     // cleanup
     return () => setSearchPage(false);
     return () => setSearchPage(false);
-  }, [router, setSearchPage]);
+  }, [setSearchPage]);
 
 
   const title = useCustomTitle(t('search_result.title'));
   const title = useCustomTitle(t('search_result.title'));
 
 

+ 2 - 2
apps/app/src/pages/_search/types.ts

@@ -2,5 +2,5 @@ export type ServerConfigurationProps = {
   serverConfig: {
   serverConfig: {
     isContainerFluid: boolean;
     isContainerFluid: boolean;
     showPageLimitationL: number;
     showPageLimitationL: number;
-  },
-}
+  };
+};

+ 12 - 8
apps/app/src/pages/_search/use-hydrate-server-configurations.ts

@@ -3,8 +3,8 @@ import { useHydrateAtoms } from 'jotai/utils';
 import type { RendererConfig } from '~/interfaces/services/renderer';
 import type { RendererConfig } from '~/interfaces/services/renderer';
 import {
 import {
   isContainerFluidAtom,
   isContainerFluidAtom,
-  showPageLimitationLAtom,
   rendererConfigAtom,
   rendererConfigAtom,
+  showPageLimitationLAtom,
 } from '~/states/server-configurations';
 } from '~/states/server-configurations';
 
 
 import type { ServerConfigurationProps } from './types';
 import type { ServerConfigurationProps } from './types';
@@ -14,13 +14,17 @@ import type { ServerConfigurationProps } from './types';
  * This should be called early in the app component to ensure atoms are properly initialized before rendering
  * This should be called early in the app component to ensure atoms are properly initialized before rendering
  */
  */
 export const useHydrateServerConfigurationAtoms = (
 export const useHydrateServerConfigurationAtoms = (
-    serverConfig: ServerConfigurationProps['serverConfig'] | undefined,
-    rendererConfigs: RendererConfig | undefined,
+  serverConfig: ServerConfigurationProps['serverConfig'] | undefined,
+  rendererConfigs: RendererConfig | undefined,
 ): void => {
 ): void => {
   // Hydrate server configuration atoms with server-side data
   // Hydrate server configuration atoms with server-side data
-  useHydrateAtoms(serverConfig == null || rendererConfigs == null ? [] : [
-    [isContainerFluidAtom, serverConfig.isContainerFluid],
-    [showPageLimitationLAtom, serverConfig.showPageLimitationL],
-    [rendererConfigAtom, rendererConfigs],
-  ]);
+  useHydrateAtoms(
+    serverConfig == null || rendererConfigs == null
+      ? []
+      : [
+          [isContainerFluidAtom, serverConfig.isContainerFluid],
+          [showPageLimitationLAtom, serverConfig.showPageLimitationL],
+          [rendererConfigAtom, rendererConfigs],
+        ],
+  );
 };
 };

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

@@ -1,10 +1,18 @@
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
-
-const AdminNotFoundPage = dynamic(() => import('~/client/components/Admin/NotFoundPage').then(mod => mod.AdminNotFoundPage), { ssr: false });
+const AdminNotFoundPage = dynamic(
+  () =>
+    import('~/client/components/Admin/NotFoundPage').then(
+      (mod) => mod.AdminNotFoundPage,
+    ),
+  { ssr: false },
+);
 
 
 const AdminCatchAllPage: NextPageWithLayout = () => <AdminNotFoundPage />;
 const AdminCatchAllPage: NextPageWithLayout = () => <AdminNotFoundPage />;
 
 

+ 10 - 3
apps/app/src/pages/admin/_shared/AdminPageFrame.tsx

@@ -1,6 +1,5 @@
 import type { JSX } from 'react';
 import type { JSX } from 'react';
 import React from 'react';
 import React from 'react';
-
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 import Head from 'next/head';
 import Head from 'next/head';
 import { Provider } from 'unstated';
 import { Provider } from 'unstated';
@@ -8,8 +7,16 @@ import { Provider } from 'unstated';
 import type { AdminPageFrameProps } from './types';
 import type { AdminPageFrameProps } from './types';
 
 
 // Dynamic imports to avoid SSR issues with admin-only components
 // Dynamic imports to avoid SSR issues with admin-only components
-const AdminLayout = dynamic(() => import('~/components/Layout/AdminLayout'), { ssr: false });
-const ForbiddenPage = dynamic(() => import('~/client/components/Admin/ForbiddenPage').then(mod => mod.ForbiddenPage), { ssr: false });
+const AdminLayout = dynamic(() => import('~/components/Layout/AdminLayout'), {
+  ssr: false,
+});
+const ForbiddenPage = dynamic(
+  () =>
+    import('~/client/components/Admin/ForbiddenPage').then(
+      (mod) => mod.ForbiddenPage,
+    ),
+  { ssr: false },
+);
 
 
 /**
 /**
  * Admin page frame that centralizes:
  * Admin page frame that centralizes:

+ 24 - 13
apps/app/src/pages/admin/_shared/get-server-side-common-props.ts

@@ -2,17 +2,21 @@ import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 
 
 import type { GetServerSideI18nPropsOption } from '~/pages/common-props/i18n';
 import type { GetServerSideI18nPropsOption } from '~/pages/common-props/i18n';
 
 
-import { getServerSideCommonInitialProps, getServerSideCommonEachProps, getServerSideI18nProps } from '../../common-props';
+import {
+  getServerSideCommonEachProps,
+  getServerSideCommonInitialProps,
+  getServerSideI18nProps,
+} from '../../common-props';
 import { mergeGetServerSidePropsResults } from '../../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../../utils/server-side-props';
-
 import type { AdminCommonProps } from './types';
 import type { AdminCommonProps } from './types';
 
 
 /**
 /**
  * Build common admin SSR props (merges common initial/each/i18n and computes admin flag).
  * Build common admin SSR props (merges common initial/each/i18n and computes admin flag).
  * Returns redirect / notFound as-is.
  * Returns redirect / notFound as-is.
  */
  */
-export const getServerSideAdminCommonProps = async(
-    context: GetServerSidePropsContext, options?: GetServerSideI18nPropsOption,
+export const getServerSideAdminCommonProps = async (
+  context: GetServerSidePropsContext,
+  options?: GetServerSideI18nPropsOption,
 ): ReturnType<GetServerSideProps<AdminCommonProps>> => {
 ): ReturnType<GetServerSideProps<AdminCommonProps>> => {
   //
   //
   // STAGE 1
   // STAGE 1
@@ -20,26 +24,33 @@ export const getServerSideAdminCommonProps = async(
 
 
   const commonEachPropsResult = await getServerSideCommonEachProps(context);
   const commonEachPropsResult = await getServerSideCommonEachProps(context);
   // Handle early return cases (redirect/notFound)
   // Handle early return cases (redirect/notFound)
-  if ('redirect' in commonEachPropsResult || 'notFound' in commonEachPropsResult) {
+  if (
+    'redirect' in commonEachPropsResult ||
+    'notFound' in commonEachPropsResult
+  ) {
     return commonEachPropsResult;
     return commonEachPropsResult;
   }
   }
   const commonEachProps = await commonEachPropsResult.props;
   const commonEachProps = await commonEachPropsResult.props;
   const { currentUser } = commonEachProps;
   const { currentUser } = commonEachProps;
 
 
-  const isAccessDeniedForNonAdminUser = (currentUser == null || !currentUser.admin);
+  const isAccessDeniedForNonAdminUser =
+    currentUser == null || !currentUser.admin;
 
 
   //
   //
   // STAGE 2
   // STAGE 2
   //
   //
-  const [
-    commonInitialResult,
-    i18nResult,
-  ] = await Promise.all([
+  const [commonInitialResult, i18nResult] = await Promise.all([
     getServerSideCommonInitialProps(context),
     getServerSideCommonInitialProps(context),
     getServerSideI18nProps(context, ['admin'], options),
     getServerSideI18nProps(context, ['admin'], options),
   ]);
   ]);
 
 
-  return mergeGetServerSidePropsResults(commonInitialResult,
-    mergeGetServerSidePropsResults(commonEachPropsResult,
-      mergeGetServerSidePropsResults(i18nResult, { props: { isAccessDeniedForNonAdminUser } })));
+  return mergeGetServerSidePropsResults(
+    commonInitialResult,
+    mergeGetServerSidePropsResults(
+      commonEachPropsResult,
+      mergeGetServerSidePropsResults(i18nResult, {
+        props: { isAccessDeniedForNonAdminUser },
+      }),
+    ),
+  );
 };
 };

+ 1 - 1
apps/app/src/pages/admin/_shared/index.ts

@@ -1,4 +1,4 @@
-export type * from './types';
 export { getServerSideAdminCommonProps } from './get-server-side-common-props';
 export { getServerSideAdminCommonProps } from './get-server-side-common-props';
 export { createAdminPageLayout } from './layout';
 export { createAdminPageLayout } from './layout';
+export type * from './types';
 export { useUnstatedContainers } from './use-unstated-container';
 export { useUnstatedContainers } from './use-unstated-container';

+ 17 - 7
apps/app/src/pages/admin/_shared/layout.tsx

@@ -1,13 +1,13 @@
-import React, { useMemo } from 'react';
+import type React from 'react';
 import type { ReactElement, ReactNode } from 'react';
 import type { ReactElement, ReactNode } from 'react';
-
+import { useMemo } from 'react';
 import type { TFunction } from 'i18next';
 import type { TFunction } from 'i18next';
 import { useTranslation } from 'next-i18next';
 import { useTranslation } from 'next-i18next';
 
 
 import { useCustomTitle } from '~/pages/utils/page-title-customization';
 import { useCustomTitle } from '~/pages/utils/page-title-customization';
 
 
 import { AdminPageFrame } from './AdminPageFrame';
 import { AdminPageFrame } from './AdminPageFrame';
-import type { AnyUnstatedContainer, AdminCommonProps } from './types';
+import type { AdminCommonProps, AnyUnstatedContainer } from './types';
 import { useUnstatedContainers } from './use-unstated-container';
 import { useUnstatedContainers } from './use-unstated-container';
 
 
 export interface AdminLayoutOptions<P extends AdminCommonProps> {
 export interface AdminLayoutOptions<P extends AdminCommonProps> {
@@ -15,22 +15,32 @@ export interface AdminLayoutOptions<P extends AdminCommonProps> {
   containerFactories?: Array<() => Promise<AnyUnstatedContainer>>;
   containerFactories?: Array<() => Promise<AnyUnstatedContainer>>;
 }
 }
 
 
-export function createAdminPageLayout<P extends AdminCommonProps>(options: AdminLayoutOptions<P>) {
+export function createAdminPageLayout<P extends AdminCommonProps>(
+  options: AdminLayoutOptions<P>,
+) {
   return function getLayout(page: ReactElement<P>): ReactNode {
   return function getLayout(page: ReactElement<P>): ReactNode {
     const Wrapper: React.FC = () => {
     const Wrapper: React.FC = () => {
       const { t } = useTranslation('admin');
       const { t } = useTranslation('admin');
 
 
-      const rawTitle = typeof options.title === 'function' ? options.title(page.props, t) : options.title;
+      const rawTitle =
+        typeof options.title === 'function'
+          ? options.title(page.props, t)
+          : options.title;
       const title = useCustomTitle(rawTitle);
       const title = useCustomTitle(rawTitle);
 
 
-      const factories = useMemo(() => options.containerFactories ?? [], []);
+      const factories = useMemo(
+        () => options.containerFactories ?? [],
+        [options.containerFactories],
+      );
       const containers = useUnstatedContainers(factories);
       const containers = useUnstatedContainers(factories);
 
 
       return (
       return (
         <AdminPageFrame
         <AdminPageFrame
           title={title}
           title={title}
           componentTitle={rawTitle}
           componentTitle={rawTitle}
-          isAccessDeniedForNonAdminUser={page.props.isAccessDeniedForNonAdminUser}
+          isAccessDeniedForNonAdminUser={
+            page.props.isAccessDeniedForNonAdminUser
+          }
           containers={containers}
           containers={containers}
         >
         >
           {page}
           {page}

+ 4 - 4
apps/app/src/pages/admin/_shared/types.ts

@@ -1,12 +1,12 @@
 import type { ReactNode } from 'react';
 import type { ReactNode } from 'react';
-
 import type { Container } from 'unstated';
 import type { Container } from 'unstated';
 
 
 import type { CommonEachProps, CommonInitialProps } from '~/pages/common-props';
 import type { CommonEachProps, CommonInitialProps } from '~/pages/common-props';
 
 
-export type AdminCommonProps = CommonInitialProps & CommonEachProps & {
-  isAccessDeniedForNonAdminUser: boolean;
-};
+export type AdminCommonProps = CommonInitialProps &
+  CommonEachProps & {
+    isAccessDeniedForNonAdminUser: boolean;
+  };
 
 
 export type AnyUnstatedContainer = Container<Record<string, unknown>>;
 export type AnyUnstatedContainer = Container<Record<string, unknown>>;
 
 

+ 8 - 4
apps/app/src/pages/admin/_shared/use-unstated-container.ts

@@ -6,16 +6,20 @@ import type { AnyUnstatedContainer } from './types';
  * Helper hook to dynamically load and instantiate unstated containers for admin pages.
  * Helper hook to dynamically load and instantiate unstated containers for admin pages.
  * Pass an array of async factory functions returning container instances.
  * Pass an array of async factory functions returning container instances.
  */
  */
-export const useUnstatedContainers = (factories: Array<() => Promise<AnyUnstatedContainer>>): AnyUnstatedContainer[] => {
+export const useUnstatedContainers = (
+  factories: Array<() => Promise<AnyUnstatedContainer>>,
+): AnyUnstatedContainer[] => {
   const [containers, setContainers] = useState<AnyUnstatedContainer[]>([]);
   const [containers, setContainers] = useState<AnyUnstatedContainer[]>([]);
 
 
   useEffect(() => {
   useEffect(() => {
     let canceled = false;
     let canceled = false;
-    (async() => {
-      const resolved = await Promise.all(factories.map(f => f()));
+    (async () => {
+      const resolved = await Promise.all(factories.map((f) => f()));
       if (!canceled) setContainers(resolved);
       if (!canceled) setContainers(resolved);
     })();
     })();
-    return () => { canceled = true };
+    return () => {
+      canceled = true;
+    };
   }, [factories]);
   }, [factories]);
 
 
   return containers;
   return containers;

+ 25 - 9
apps/app/src/pages/admin/ai-integration.page.tsx

@@ -1,26 +1,42 @@
-import { useHydrateAtoms } from 'jotai/utils';
 import type { GetServerSideProps } from 'next';
 import type { GetServerSideProps } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
+import { useHydrateAtoms } from 'jotai/utils';
 
 
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import { aiEnabledAtom } from '~/states/server-configurations';
 import { aiEnabledAtom } from '~/states/server-configurations';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
-
-const AiIntegration = dynamic(() => import('~/features/openai/client/components/AiIntegration/AiIntegration').then(mod => mod.AiIntegration), { ssr: false });
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
+
+const AiIntegration = dynamic(
+  () =>
+    import(
+      '~/features/openai/client/components/AiIntegration/AiIntegration'
+    ).then((mod) => mod.AiIntegration),
+  { ssr: false },
+);
 const AiIntegrationDisableMode = dynamic(
 const AiIntegrationDisableMode = dynamic(
-  () => import('~/features/openai/client/components/AiIntegration/AiIntegrationDisableMode').then(mod => mod.AiIntegrationDisableMode), { ssr: false },
+  () =>
+    import(
+      '~/features/openai/client/components/AiIntegration/AiIntegrationDisableMode'
+    ).then((mod) => mod.AiIntegrationDisableMode),
+  { ssr: false },
 );
 );
 
 
 type Props = AdminCommonProps & { aiEnabled: boolean };
 type Props = AdminCommonProps & { aiEnabled: boolean };
 
 
-const AdminAiIntegrationPage: NextPageWithLayout<Props> = ({ aiEnabled }: Props) => {
+const AdminAiIntegrationPage: NextPageWithLayout<Props> = ({
+  aiEnabled,
+}: Props) => {
   // Hydrate server-provided prop into atom (runs only on mount / hydration)
   // Hydrate server-provided prop into atom (runs only on mount / hydration)
-  useHydrateAtoms([[aiEnabledAtom, aiEnabled]], { dangerouslyForceHydrate: true });
+  useHydrateAtoms([[aiEnabledAtom, aiEnabled]], {
+    dangerouslyForceHydrate: true,
+  });
   return aiEnabled ? <AiIntegration /> : <AiIntegrationDisableMode />;
   return aiEnabled ? <AiIntegration /> : <AiIntegrationDisableMode />;
 };
 };
 
 
@@ -28,7 +44,7 @@ AdminAiIntegrationPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('ai_integration.ai_integration'),
   title: (_p, t) => t('ai_integration.ai_integration'),
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps = async(context) => {
+export const getServerSideProps: GetServerSideProps = async (context) => {
   const baseResult = await getServerSideAdminCommonProps(context);
   const baseResult = await getServerSideAdminCommonProps(context);
   if (!('props' in baseResult)) return baseResult; // redirect / notFound pass-through
   if (!('props' in baseResult)) return baseResult; // redirect / notFound pass-through
 
 

+ 16 - 8
apps/app/src/pages/admin/app.page.tsx

@@ -2,28 +2,36 @@ import type { GetServerSideProps } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
-
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
-const AppSettingsPageContents = dynamic(() => import('~/client/components/Admin/App/AppSettingsPageContents'), { ssr: false });
+const AppSettingsPageContents = dynamic(
+  () => import('~/client/components/Admin/App/AppSettingsPageContents'),
+  { ssr: false },
+);
 
 
 type Props = AdminCommonProps;
 type Props = AdminCommonProps;
 
 
-const AdminAppPage: NextPageWithLayout<Props> = () => <AppSettingsPageContents />;
+const AdminAppPage: NextPageWithLayout<Props> = () => (
+  <AppSettingsPageContents />
+);
 
 
 AdminAppPage.getLayout = createAdminPageLayout<Props>({
 AdminAppPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('headers.app_settings', { ns: 'commons' }),
   title: (_p, t) => t('headers.app_settings', { ns: 'commons' }),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminAppContainer = (await import('~/client/services/AdminAppContainer')).default;
+    async () => {
+      const AdminAppContainer = (
+        await import('~/client/services/AdminAppContainer')
+      ).default;
       return new AdminAppContainer();
       return new AdminAppContainer();
     },
     },
   ],
   ],
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps = async(context) => {
+export const getServerSideProps: GetServerSideProps = async (context) => {
   return getServerSideAdminCommonProps(context, { preloadAllLang: true });
   return getServerSideAdminCommonProps(context, { preloadAllLang: true });
 };
 };
 
 

+ 34 - 15
apps/app/src/pages/admin/audit-log.page.tsx

@@ -1,34 +1,49 @@
-import { useHydrateAtoms } from 'jotai/utils';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
+import { useHydrateAtoms } from 'jotai/utils';
 
 
 import type { SupportedActionType } from '~/interfaces/activity';
 import type { SupportedActionType } from '~/interfaces/activity';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
-import { activityExpirationSecondsAtom, auditLogAvailableActionsAtom, auditLogEnabledAtom } from '~/states/server-configurations';
+import {
+  activityExpirationSecondsAtom,
+  auditLogAvailableActionsAtom,
+  auditLogEnabledAtom,
+} from '~/states/server-configurations';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
-const AuditLogManagement = dynamic(() => import('~/client/components/Admin/AuditLogManagement').then(mod => mod.AuditLogManagement), { ssr: false });
+const AuditLogManagement = dynamic(
+  () =>
+    import('~/client/components/Admin/AuditLogManagement').then(
+      (mod) => mod.AuditLogManagement,
+    ),
+  { ssr: false },
+);
 
 
 type PageProps = {
 type PageProps = {
-  auditLogEnabled: boolean,
-  activityExpirationSeconds: number,
-  auditLogAvailableActions: SupportedActionType[],
+  auditLogEnabled: boolean;
+  activityExpirationSeconds: number;
+  auditLogAvailableActions: SupportedActionType[];
 };
 };
 
 
 type Props = AdminCommonProps & PageProps;
 type Props = AdminCommonProps & PageProps;
 
 
 const AdminAuditLogPage: NextPageWithLayout<Props> = (props: Props) => {
 const AdminAuditLogPage: NextPageWithLayout<Props> = (props: Props) => {
   // hydrate
   // hydrate
-  useHydrateAtoms([
-    [auditLogEnabledAtom, props.auditLogEnabled],
-    [activityExpirationSecondsAtom, props.activityExpirationSeconds],
-    [auditLogAvailableActionsAtom, props.auditLogAvailableActions],
-  ], { dangerouslyForceHydrate: true });
+  useHydrateAtoms(
+    [
+      [auditLogEnabledAtom, props.auditLogEnabled],
+      [activityExpirationSecondsAtom, props.activityExpirationSeconds],
+      [auditLogAvailableActionsAtom, props.auditLogAvailableActions],
+    ],
+    { dangerouslyForceHydrate: true },
+  );
 
 
   return <AuditLogManagement />;
   return <AuditLogManagement />;
 };
 };
@@ -39,7 +54,9 @@ AdminAuditLogPage.getLayout = createAdminPageLayout<Props>({
 });
 });
 
 
 // Extend common SSR to inject audit log specific server configs
 // Extend common SSR to inject audit log specific server configs
-export const getServerSideProps: GetServerSideProps<Props> = async(context: GetServerSidePropsContext) => {
+export const getServerSideProps: GetServerSideProps<Props> = async (
+  context: GetServerSidePropsContext,
+) => {
   const baseResult = await getServerSideAdminCommonProps(context);
   const baseResult = await getServerSideAdminCommonProps(context);
 
 
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
@@ -50,7 +67,9 @@ export const getServerSideProps: GetServerSideProps<Props> = async(context: GetS
   const auditLogPropsFragment = {
   const auditLogPropsFragment = {
     props: {
     props: {
       auditLogEnabled: configManager.getConfig('app:auditLogEnabled'),
       auditLogEnabled: configManager.getConfig('app:auditLogEnabled'),
-      activityExpirationSeconds: configManager.getConfig('app:activityExpirationSeconds'),
+      activityExpirationSeconds: configManager.getConfig(
+        'app:activityExpirationSeconds',
+      ),
       auditLogAvailableActions: activityService.getAvailableActions(false),
       auditLogAvailableActions: activityService.getAvailableActions(false),
     },
     },
   } satisfies { props: PageProps };
   } satisfies { props: PageProps };

+ 33 - 18
apps/app/src/pages/admin/customize.page.tsx

@@ -1,6 +1,6 @@
-import { useHydrateAtoms } from 'jotai/utils';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
+import { useHydrateAtoms } from 'jotai/utils';
 
 
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import { _atomsForAdminPagesHydration as atoms } from '~/states/global';
 import { _atomsForAdminPagesHydration as atoms } from '~/states/global';
@@ -8,27 +8,37 @@ import { isCustomizedLogoUploadedAtom } from '~/states/server-configurations';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
-const CustomizeSettingContents = dynamic(() => import('~/client/components/Admin/Customize/Customize'), { ssr: false });
+const CustomizeSettingContents = dynamic(
+  () => import('~/client/components/Admin/Customize/Customize'),
+  { ssr: false },
+);
 
 
 type PageProps = {
 type PageProps = {
-  isDefaultBrandLogoUsed: boolean,
-  isCustomizedLogoUploaded: boolean,
-  customTitleTemplate?: string,
+  isDefaultBrandLogoUsed: boolean;
+  isCustomizedLogoUploaded: boolean;
+  customTitleTemplate?: string;
 };
 };
 
 
 type Props = AdminCommonProps & PageProps;
 type Props = AdminCommonProps & PageProps;
 
 
 // eslint-disable-next-line react/prop-types
 // eslint-disable-next-line react/prop-types
-const AdminCustomizeSettingsPage: NextPageWithLayout<Props> = (props: Props) => {
-  useHydrateAtoms([
-    [atoms.isDefaultLogoAtom, props.isDefaultBrandLogoUsed],
-    [atoms.customTitleTemplateAtom, props.customTitleTemplate],
-    [isCustomizedLogoUploadedAtom, props.isCustomizedLogoUploaded],
-  ], { dangerouslyForceHydrate: true });
+const AdminCustomizeSettingsPage: NextPageWithLayout<Props> = (
+  props: Props,
+) => {
+  useHydrateAtoms(
+    [
+      [atoms.isDefaultLogoAtom, props.isDefaultBrandLogoUsed],
+      [atoms.customTitleTemplateAtom, props.customTitleTemplate],
+      [isCustomizedLogoUploadedAtom, props.isCustomizedLogoUploaded],
+    ],
+    { dangerouslyForceHydrate: true },
+  );
 
 
   return <CustomizeSettingContents />;
   return <CustomizeSettingContents />;
 };
 };
@@ -36,14 +46,17 @@ const AdminCustomizeSettingsPage: NextPageWithLayout<Props> = (props: Props) =>
 AdminCustomizeSettingsPage.getLayout = createAdminPageLayout<Props>({
 AdminCustomizeSettingsPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('customize_settings.customize_settings'),
   title: (_p, t) => t('customize_settings.customize_settings'),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const C = (await import('~/client/services/AdminCustomizeContainer')).default;
+    async () => {
+      const C = (await import('~/client/services/AdminCustomizeContainer'))
+        .default;
       return new C();
       return new C();
     },
     },
   ],
   ],
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps<Props> = async(context: GetServerSidePropsContext) => {
+export const getServerSideProps: GetServerSideProps<Props> = async (
+  context: GetServerSidePropsContext,
+) => {
   const commonResult = await getServerSideAdminCommonProps(context);
   const commonResult = await getServerSideAdminCommonProps(context);
 
 
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
@@ -51,8 +64,10 @@ export const getServerSideProps: GetServerSideProps<Props> = async(context: GetS
 
 
   const customizePropsFragment = {
   const customizePropsFragment = {
     props: {
     props: {
-      isDefaultBrandLogoUsed: await crowi.attachmentService.isDefaultBrandLogoUsed(),
-      isCustomizedLogoUploaded: await crowi.attachmentService.isBrandLogoExist(),
+      isDefaultBrandLogoUsed:
+        await crowi.attachmentService.isDefaultBrandLogoUsed(),
+      isCustomizedLogoUploaded:
+        await crowi.attachmentService.isBrandLogoExist(),
       customTitleTemplate: crowi.configManager.getConfig('customize:title'),
       customTitleTemplate: crowi.configManager.getConfig('customize:title'),
     },
     },
   } satisfies { props: PageProps };
   } satisfies { props: PageProps };

+ 17 - 7
apps/app/src/pages/admin/data-transfer.page.tsx

@@ -2,26 +2,36 @@ import type { GetServerSideProps } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
-const G2GDataTransferPage = dynamic(() => import('~/client/components/Admin/G2GDataTransfer'), { ssr: false });
+const G2GDataTransferPage = dynamic(
+  () => import('~/client/components/Admin/G2GDataTransfer'),
+  { ssr: false },
+);
 
 
 type Props = AdminCommonProps;
 type Props = AdminCommonProps;
 
 
-const DataTransferPage: NextPageWithLayout<Props> = () => <G2GDataTransferPage />;
+const DataTransferPage: NextPageWithLayout<Props> = () => (
+  <G2GDataTransferPage />
+);
 
 
 DataTransferPage.getLayout = createAdminPageLayout<Props>({
 DataTransferPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('g2g_data_transfer.data_transfer', { ns: 'commons' }),
   title: (_p, t) => t('g2g_data_transfer.data_transfer', { ns: 'commons' }),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminAppContainer = (await import('~/client/services/AdminAppContainer')).default;
+    async () => {
+      const AdminAppContainer = (
+        await import('~/client/services/AdminAppContainer')
+      ).default;
       return new AdminAppContainer();
       return new AdminAppContainer();
     },
     },
   ],
   ],
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps<Props> = getServerSideAdminCommonProps;
+export const getServerSideProps: GetServerSideProps<Props> =
+  getServerSideAdminCommonProps;
 
 
 export default DataTransferPage;
 export default DataTransferPage;

+ 17 - 7
apps/app/src/pages/admin/export.page.tsx

@@ -2,26 +2,36 @@ import type { GetServerSideProps } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
-const ExportArchiveDataPage = dynamic(() => import('~/client/components/Admin/ExportArchiveDataPage'), { ssr: false });
+const ExportArchiveDataPage = dynamic(
+  () => import('~/client/components/Admin/ExportArchiveDataPage'),
+  { ssr: false },
+);
 
 
 type Props = AdminCommonProps;
 type Props = AdminCommonProps;
 
 
-const AdminExportDataArchivePage: NextPageWithLayout<Props> = () => <ExportArchiveDataPage />;
+const AdminExportDataArchivePage: NextPageWithLayout<Props> = () => (
+  <ExportArchiveDataPage />
+);
 
 
 AdminExportDataArchivePage.getLayout = createAdminPageLayout<Props>({
 AdminExportDataArchivePage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('export_management.export_archive_data'),
   title: (_p, t) => t('export_management.export_archive_data'),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminAppContainer = (await import('~/client/services/AdminAppContainer')).default;
+    async () => {
+      const AdminAppContainer = (
+        await import('~/client/services/AdminAppContainer')
+      ).default;
       return new AdminAppContainer();
       return new AdminAppContainer();
     },
     },
   ],
   ],
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps = getServerSideAdminCommonProps;
+export const getServerSideProps: GetServerSideProps =
+  getServerSideAdminCommonProps;
 
 
 export default AdminExportDataArchivePage;
 export default AdminExportDataArchivePage;

+ 30 - 13
apps/app/src/pages/admin/global-notification/[globalNotificationId].page.tsx

@@ -1,46 +1,63 @@
 import { useEffect } from 'react';
 import { useEffect } from 'react';
-
-import { objectIdUtils } from '@growi/core/dist/utils';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 import { useRouter } from 'next/router';
 import { useRouter } from 'next/router';
+import { objectIdUtils } from '@growi/core/dist/utils';
 
 
 import type { NextPageWithLayout } from '../../_app.page';
 import type { NextPageWithLayout } from '../../_app.page';
 import type { AdminCommonProps } from '../_shared';
 import type { AdminCommonProps } from '../_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from '../_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from '../_shared';
 
 
-const ManageGlobalNotification = dynamic(() => import('~/client/components/Admin/Notification/ManageGlobalNotification'), { ssr: false });
+const ManageGlobalNotification = dynamic(
+  () =>
+    import('~/client/components/Admin/Notification/ManageGlobalNotification'),
+  { ssr: false },
+);
 
 
 type Props = AdminCommonProps;
 type Props = AdminCommonProps;
 
 
 const AdminGlobalNotificationDetailPage: NextPageWithLayout<Props> = () => {
 const AdminGlobalNotificationDetailPage: NextPageWithLayout<Props> = () => {
   const router = useRouter();
   const router = useRouter();
   const { globalNotificationId } = router.query;
   const { globalNotificationId } = router.query;
-  const currentGlobalNotificationId = Array.isArray(globalNotificationId) ? globalNotificationId[0] : globalNotificationId;
+  const currentGlobalNotificationId = Array.isArray(globalNotificationId)
+    ? globalNotificationId[0]
+    : globalNotificationId;
 
 
   useEffect(() => {
   useEffect(() => {
-    const toastErrorPromise = import('~/client/util/toastr').then(mod => mod.toastError);
+    const toastErrorPromise = import('~/client/util/toastr').then(
+      (mod) => mod.toastError,
+    );
     if (globalNotificationId == null) {
     if (globalNotificationId == null) {
       router.push('/admin/notification');
       router.push('/admin/notification');
       return;
       return;
     }
     }
-    if (currentGlobalNotificationId != null && !objectIdUtils.isValidObjectId(currentGlobalNotificationId)) {
-      (async() => {
+    if (
+      currentGlobalNotificationId != null &&
+      !objectIdUtils.isValidObjectId(currentGlobalNotificationId)
+    ) {
+      (async () => {
         (await toastErrorPromise)('Invalid notification id');
         (await toastErrorPromise)('Invalid notification id');
         router.push('/admin/global-notification/new');
         router.push('/admin/global-notification/new');
       })();
       })();
     }
     }
   }, [currentGlobalNotificationId, globalNotificationId, router]);
   }, [currentGlobalNotificationId, globalNotificationId, router]);
 
 
-  return (currentGlobalNotificationId != null && router.isReady)
-    ? <ManageGlobalNotification globalNotificationId={currentGlobalNotificationId} />
-    : null;
+  return currentGlobalNotificationId != null && router.isReady ? (
+    <ManageGlobalNotification
+      globalNotificationId={currentGlobalNotificationId}
+    />
+  ) : null;
 };
 };
 
 
 AdminGlobalNotificationDetailPage.getLayout = createAdminPageLayout<Props>({
 AdminGlobalNotificationDetailPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('external_notification.external_notification'),
   title: (_p, t) => t('external_notification.external_notification'),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminNotificationContainer = (await import('~/client/services/AdminNotificationContainer')).default;
+    async () => {
+      const AdminNotificationContainer = (
+        await import('~/client/services/AdminNotificationContainer')
+      ).default;
       return new AdminNotificationContainer();
       return new AdminNotificationContainer();
     },
     },
   ],
   ],

+ 18 - 6
apps/app/src/pages/admin/global-notification/new.page.tsx

@@ -3,24 +3,36 @@ import dynamic from 'next/dynamic';
 
 
 import type { NextPageWithLayout } from '../../_app.page';
 import type { NextPageWithLayout } from '../../_app.page';
 import type { AdminCommonProps } from '../_shared';
 import type { AdminCommonProps } from '../_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from '../_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from '../_shared';
 
 
-const ManageGlobalNotification = dynamic(() => import('~/client/components/Admin/Notification/ManageGlobalNotification'), { ssr: false });
+const ManageGlobalNotification = dynamic(
+  () =>
+    import('~/client/components/Admin/Notification/ManageGlobalNotification'),
+  { ssr: false },
+);
 
 
 type Props = AdminCommonProps;
 type Props = AdminCommonProps;
 
 
-const AdminGlobalNotificationNewPage: NextPageWithLayout<Props> = () => <ManageGlobalNotification />;
+const AdminGlobalNotificationNewPage: NextPageWithLayout<Props> = () => (
+  <ManageGlobalNotification />
+);
 
 
 AdminGlobalNotificationNewPage.getLayout = createAdminPageLayout<Props>({
 AdminGlobalNotificationNewPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('external_notification.external_notification'),
   title: (_p, t) => t('external_notification.external_notification'),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminNotificationContainer = (await import('~/client/services/AdminNotificationContainer')).default;
+    async () => {
+      const AdminNotificationContainer = (
+        await import('~/client/services/AdminNotificationContainer')
+      ).default;
       return new AdminNotificationContainer();
       return new AdminNotificationContainer();
     },
     },
   ],
   ],
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps<Props> = getServerSideAdminCommonProps;
+export const getServerSideProps: GetServerSideProps<Props> =
+  getServerSideAdminCommonProps;
 
 
 export default AdminGlobalNotificationNewPage;
 export default AdminGlobalNotificationNewPage;

+ 17 - 7
apps/app/src/pages/admin/importer.page.tsx

@@ -2,26 +2,36 @@ import type { GetServerSideProps } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
-const DataImportPageContents = dynamic(() => import('~/client/components/Admin/ImportData/ImportDataPageContents'), { ssr: false });
+const DataImportPageContents = dynamic(
+  () => import('~/client/components/Admin/ImportData/ImportDataPageContents'),
+  { ssr: false },
+);
 
 
 type Props = AdminCommonProps;
 type Props = AdminCommonProps;
 
 
-const AdminDataImportPage: NextPageWithLayout<Props> = () => <DataImportPageContents />;
+const AdminDataImportPage: NextPageWithLayout<Props> = () => (
+  <DataImportPageContents />
+);
 
 
 AdminDataImportPage.getLayout = createAdminPageLayout<Props>({
 AdminDataImportPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('importer_management.import_data'),
   title: (_p, t) => t('importer_management.import_data'),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminImportContainer = (await import('~/client/services/AdminImportContainer')).default;
+    async () => {
+      const AdminImportContainer = (
+        await import('~/client/services/AdminImportContainer')
+      ).default;
       return new AdminImportContainer();
       return new AdminImportContainer();
     },
     },
   ],
   ],
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps = getServerSideAdminCommonProps;
+export const getServerSideProps: GetServerSideProps =
+  getServerSideAdminCommonProps;
 
 
 export default AdminDataImportPage;
 export default AdminDataImportPage;

+ 32 - 15
apps/app/src/pages/admin/index.page.tsx

@@ -1,31 +1,42 @@
-import { useHydrateAtoms } from 'jotai/utils';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
+import { useHydrateAtoms } from 'jotai/utils';
 
 
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import { _atomsForAdminPagesHydration as atoms } from '~/states/global';
 import { _atomsForAdminPagesHydration as atoms } from '~/states/global';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
-const AdminHome = dynamic(() => import('~/client/components/Admin/AdminHome/AdminHome'), { ssr: false });
+const AdminHome = dynamic(
+  () => import('~/client/components/Admin/AdminHome/AdminHome'),
+  { ssr: false },
+);
 
 
 type ExtraProps = {
 type ExtraProps = {
-  growiCloudUri?: string,
-  growiAppIdForGrowiCloud?: number,
+  growiCloudUri?: string;
+  growiAppIdForGrowiCloud?: number;
 };
 };
 type Props = AdminCommonProps & ExtraProps;
 type Props = AdminCommonProps & ExtraProps;
 
 
 // eslint-disable-next-line react/prop-types
 // eslint-disable-next-line react/prop-types
-const AdminHomepage: NextPageWithLayout<Props> = ({ growiCloudUri, growiAppIdForGrowiCloud }) => {
+const AdminHomepage: NextPageWithLayout<Props> = ({
+  growiCloudUri,
+  growiAppIdForGrowiCloud,
+}) => {
   // Hydrate atoms with fragment values (idempotent if already set by common props)
   // Hydrate atoms with fragment values (idempotent if already set by common props)
-  useHydrateAtoms([
-    [atoms.growiCloudUriAtom, growiCloudUri],
-    [atoms.growiAppIdForGrowiCloudAtom, growiAppIdForGrowiCloud],
-  ], { dangerouslyForceHydrate: true });
+  useHydrateAtoms(
+    [
+      [atoms.growiCloudUriAtom, growiCloudUri],
+      [atoms.growiAppIdForGrowiCloudAtom, growiAppIdForGrowiCloud],
+    ],
+    { dangerouslyForceHydrate: true },
+  );
 
 
   return <AdminHome />;
   return <AdminHome />;
 };
 };
@@ -33,14 +44,18 @@ const AdminHomepage: NextPageWithLayout<Props> = ({ growiCloudUri, growiAppIdFor
 AdminHomepage.getLayout = createAdminPageLayout<Props>({
 AdminHomepage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('wiki_management_homepage'),
   title: (_p, t) => t('wiki_management_homepage'),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminHomeContainer = (await import('~/client/services/AdminHomeContainer')).default;
+    async () => {
+      const AdminHomeContainer = (
+        await import('~/client/services/AdminHomeContainer')
+      ).default;
       return new AdminHomeContainer();
       return new AdminHomeContainer();
     },
     },
   ],
   ],
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps<Props> = async(context: GetServerSidePropsContext) => {
+export const getServerSideProps: GetServerSideProps<Props> = async (
+  context: GetServerSidePropsContext,
+) => {
   const baseResult = await getServerSideAdminCommonProps(context);
   const baseResult = await getServerSideAdminCommonProps(context);
 
 
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
@@ -48,7 +63,9 @@ export const getServerSideProps: GetServerSideProps<Props> = async(context: GetS
   const fragment = {
   const fragment = {
     props: {
     props: {
       growiCloudUri: crowi.configManager.getConfig('app:growiCloudUri'),
       growiCloudUri: crowi.configManager.getConfig('app:growiCloudUri'),
-      growiAppIdForGrowiCloud: crowi.configManager.getConfig('app:growiAppIdForCloud'),
+      growiAppIdForGrowiCloud: crowi.configManager.getConfig(
+        'app:growiAppIdForCloud',
+      ),
     },
     },
   } satisfies { props: ExtraProps };
   } satisfies { props: ExtraProps };
   return mergeGetServerSidePropsResults(baseResult, fragment);
   return mergeGetServerSidePropsResults(baseResult, fragment);

+ 18 - 7
apps/app/src/pages/admin/markdown.page.tsx

@@ -2,26 +2,37 @@ import type { GetServerSideProps } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
-const MarkDownSettingContents = dynamic(() => import('~/client/components/Admin/MarkdownSetting/MarkDownSettingContents'), { ssr: false });
+const MarkDownSettingContents = dynamic(
+  () =>
+    import('~/client/components/Admin/MarkdownSetting/MarkDownSettingContents'),
+  { ssr: false },
+);
 
 
 type Props = AdminCommonProps;
 type Props = AdminCommonProps;
 
 
-const AdminMarkdownPage: NextPageWithLayout<Props> = () => <MarkDownSettingContents />;
+const AdminMarkdownPage: NextPageWithLayout<Props> = () => (
+  <MarkDownSettingContents />
+);
 
 
 AdminMarkdownPage.getLayout = createAdminPageLayout<Props>({
 AdminMarkdownPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('markdown_settings.markdown_settings'),
   title: (_p, t) => t('markdown_settings.markdown_settings'),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminMarkDownContainer = (await import('~/client/services/AdminMarkDownContainer')).default;
+    async () => {
+      const AdminMarkDownContainer = (
+        await import('~/client/services/AdminMarkDownContainer')
+      ).default;
       return new AdminMarkDownContainer();
       return new AdminMarkDownContainer();
     },
     },
   ],
   ],
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps = getServerSideAdminCommonProps;
+export const getServerSideProps: GetServerSideProps =
+  getServerSideAdminCommonProps;
 
 
 export default AdminMarkdownPage;
 export default AdminMarkdownPage;

+ 17 - 7
apps/app/src/pages/admin/notification.page.tsx

@@ -2,26 +2,36 @@ import type { GetServerSideProps } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
-const NotificationSetting = dynamic(() => import('~/client/components/Admin/Notification/NotificationSetting'), { ssr: false });
+const NotificationSetting = dynamic(
+  () => import('~/client/components/Admin/Notification/NotificationSetting'),
+  { ssr: false },
+);
 
 
 type Props = AdminCommonProps;
 type Props = AdminCommonProps;
 
 
-const AdminExternalNotificationPage: NextPageWithLayout<Props> = () => <NotificationSetting />;
+const AdminExternalNotificationPage: NextPageWithLayout<Props> = () => (
+  <NotificationSetting />
+);
 
 
 AdminExternalNotificationPage.getLayout = createAdminPageLayout<Props>({
 AdminExternalNotificationPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('external_notification.external_notification'),
   title: (_p, t) => t('external_notification.external_notification'),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminNotificationContainer = (await import('~/client/services/AdminNotificationContainer')).default;
+    async () => {
+      const AdminNotificationContainer = (
+        await import('~/client/services/AdminNotificationContainer')
+      ).default;
       return new AdminNotificationContainer();
       return new AdminNotificationContainer();
     },
     },
   ],
   ],
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps = getServerSideAdminCommonProps;
+export const getServerSideProps: GetServerSideProps =
+  getServerSideAdminCommonProps;
 
 
 export default AdminExternalNotificationPage;
 export default AdminExternalNotificationPage;

+ 17 - 7
apps/app/src/pages/admin/plugins.page.tsx

@@ -2,29 +2,39 @@ import type { GetServerSideProps } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
 const PluginsExtensionPageContents = dynamic(
 const PluginsExtensionPageContents = dynamic(
-  () => import('~/features/growi-plugin/client/Admin/components').then(mod => mod.PluginsExtensionPageContents),
+  () =>
+    import('~/features/growi-plugin/client/Admin/components').then(
+      (mod) => mod.PluginsExtensionPageContents,
+    ),
   { ssr: false },
   { ssr: false },
 );
 );
 
 
 type Props = AdminCommonProps;
 type Props = AdminCommonProps;
 
 
-const AdminAppPage: NextPageWithLayout<Props> = () => <PluginsExtensionPageContents />;
+const AdminAppPage: NextPageWithLayout<Props> = () => (
+  <PluginsExtensionPageContents />
+);
 
 
 AdminAppPage.getLayout = createAdminPageLayout<Props>({
 AdminAppPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('plugins.plugins'),
   title: (_p, t) => t('plugins.plugins'),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminAppContainer = (await import('~/client/services/AdminAppContainer')).default;
+    async () => {
+      const AdminAppContainer = (
+        await import('~/client/services/AdminAppContainer')
+      ).default;
       return new AdminAppContainer();
       return new AdminAppContainer();
     },
     },
   ],
   ],
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps = getServerSideAdminCommonProps;
+export const getServerSideProps: GetServerSideProps =
+  getServerSideAdminCommonProps;
 
 
 export default AdminAppPage;
 export default AdminAppPage;

+ 40 - 14
apps/app/src/pages/admin/search.page.tsx

@@ -1,40 +1,66 @@
-import { useHydrateAtoms } from 'jotai/utils';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
+import { useHydrateAtoms } from 'jotai/utils';
 
 
-import { isSearchScopeChildrenAsDefaultAtom, isSearchServiceConfiguredAtom, isSearchServiceReachableAtom } from '~/states/server-configurations';
+import {
+  isSearchScopeChildrenAsDefaultAtom,
+  isSearchServiceConfiguredAtom,
+  isSearchServiceReachableAtom,
+} from '~/states/server-configurations';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
 import type { SearchConfigurationProps } from '../basic-layout-page';
 import type { SearchConfigurationProps } from '../basic-layout-page';
 import { getServerSideSearchConfigurationProps } from '../basic-layout-page/get-server-side-props/search-configurations';
 import { getServerSideSearchConfigurationProps } from '../basic-layout-page/get-server-side-props/search-configurations';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
-
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
 const FullTextSearchManagement = dynamic(
 const FullTextSearchManagement = dynamic(
-  () => import('~/client/components/Admin/FullTextSearchManagement').then(mod => mod.FullTextSearchManagement), { ssr: false },
+  () =>
+    import('~/client/components/Admin/FullTextSearchManagement').then(
+      (mod) => mod.FullTextSearchManagement,
+    ),
+  { ssr: false },
 );
 );
 
 
 type Props = AdminCommonProps & SearchConfigurationProps;
 type Props = AdminCommonProps & SearchConfigurationProps;
 
 
-const AdminFullTextSearchManagementPage: NextPageWithLayout<Props> = (props: Props) => {
+const AdminFullTextSearchManagementPage: NextPageWithLayout<Props> = (
+  props: Props,
+) => {
   // hydrate
   // hydrate
-  useHydrateAtoms([
-    [isSearchServiceConfiguredAtom, props.searchConfig.isSearchServiceConfigured],
-    [isSearchServiceReachableAtom, props.searchConfig.isSearchServiceReachable],
-    [isSearchScopeChildrenAsDefaultAtom, props.searchConfig.isSearchScopeChildrenAsDefault],
-  ], { dangerouslyForceHydrate: true });
+  useHydrateAtoms(
+    [
+      [
+        isSearchServiceConfiguredAtom,
+        props.searchConfig.isSearchServiceConfigured,
+      ],
+      [
+        isSearchServiceReachableAtom,
+        props.searchConfig.isSearchServiceReachable,
+      ],
+      [
+        isSearchScopeChildrenAsDefaultAtom,
+        props.searchConfig.isSearchScopeChildrenAsDefault,
+      ],
+    ],
+    { dangerouslyForceHydrate: true },
+  );
 
 
   return <FullTextSearchManagement />;
   return <FullTextSearchManagement />;
 };
 };
 
 
 AdminFullTextSearchManagementPage.getLayout = createAdminPageLayout<Props>({
 AdminFullTextSearchManagementPage.getLayout = createAdminPageLayout<Props>({
-  title: (_p, t) => t('full_text_search_management.full_text_search_management'),
+  title: (_p, t) =>
+    t('full_text_search_management.full_text_search_management'),
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps<Props> = async(context: GetServerSidePropsContext) => {
+export const getServerSideProps: GetServerSideProps<Props> = async (
+  context: GetServerSidePropsContext,
+) => {
   return mergeGetServerSidePropsResults(
   return mergeGetServerSidePropsResults(
     await getServerSideAdminCommonProps(context),
     await getServerSideAdminCommonProps(context),
     await getServerSideSearchConfigurationProps(context),
     await getServerSideSearchConfigurationProps(context),

+ 62 - 18
apps/app/src/pages/admin/security.page.tsx

@@ -1,6 +1,6 @@
-import { useHydrateAtoms } from 'jotai/utils';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
+import { useHydrateAtoms } from 'jotai/utils';
 
 
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import { _atomsForAdminPagesHydration as atoms } from '~/states/global';
 import { _atomsForAdminPagesHydration as atoms } from '~/states/global';
@@ -8,24 +8,31 @@ import { isMailerSetupAtom } from '~/states/server-configurations';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
 
 
-
-const SecurityManagement = dynamic(() => import('~/client/components/Admin/Security/SecurityManagement'), { ssr: false });
+const SecurityManagement = dynamic(
+  () => import('~/client/components/Admin/Security/SecurityManagement'),
+  { ssr: false },
+);
 
 
 type ExtraProps = {
 type ExtraProps = {
-  isMailerSetup: boolean,
+  isMailerSetup: boolean;
 };
 };
 type Props = AdminCommonProps & ExtraProps;
 type Props = AdminCommonProps & ExtraProps;
 
 
 const AdminSecuritySettingsPage: NextPageWithLayout<Props> = (props: Props) => {
 const AdminSecuritySettingsPage: NextPageWithLayout<Props> = (props: Props) => {
   // hydrate
   // hydrate
-  useHydrateAtoms([
-    [isMailerSetupAtom, props.isMailerSetup],
-    [atoms.siteUrlWithEmptyValueWarnAtom, props.siteUrlWithEmptyValueWarn],
-  ], { dangerouslyForceHydrate: true });
+  useHydrateAtoms(
+    [
+      [isMailerSetupAtom, props.isMailerSetup],
+      [atoms.siteUrlWithEmptyValueWarnAtom, props.siteUrlWithEmptyValueWarn],
+    ],
+    { dangerouslyForceHydrate: true },
+  );
 
 
   return <SecurityManagement />;
   return <SecurityManagement />;
 };
 };
@@ -33,17 +40,54 @@ const AdminSecuritySettingsPage: NextPageWithLayout<Props> = (props: Props) => {
 AdminSecuritySettingsPage.getLayout = createAdminPageLayout<Props>({
 AdminSecuritySettingsPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('security_settings.security_settings'),
   title: (_p, t) => t('security_settings.security_settings'),
   containerFactories: [
   containerFactories: [
-    async() => { const { default: C } = await import('~/client/services/AdminGeneralSecurityContainer'); return new C() },
-    async() => { const { default: C } = await import('~/client/services/AdminLocalSecurityContainer'); return new C() },
-    async() => { const { default: C } = await import('~/client/services/AdminLdapSecurityContainer'); return new C() },
-    async() => { const { default: C } = await import('~/client/services/AdminSamlSecurityContainer'); return new C() },
-    async() => { const { default: C } = await import('~/client/services/AdminOidcSecurityContainer'); return new C() },
-    async() => { const { default: C } = await import('~/client/services/AdminGoogleSecurityContainer'); return new C() },
-    async() => { const { default: C } = await import('~/client/services/AdminGitHubSecurityContainer'); return new C() },
+    async () => {
+      const { default: C } = await import(
+        '~/client/services/AdminGeneralSecurityContainer'
+      );
+      return new C();
+    },
+    async () => {
+      const { default: C } = await import(
+        '~/client/services/AdminLocalSecurityContainer'
+      );
+      return new C();
+    },
+    async () => {
+      const { default: C } = await import(
+        '~/client/services/AdminLdapSecurityContainer'
+      );
+      return new C();
+    },
+    async () => {
+      const { default: C } = await import(
+        '~/client/services/AdminSamlSecurityContainer'
+      );
+      return new C();
+    },
+    async () => {
+      const { default: C } = await import(
+        '~/client/services/AdminOidcSecurityContainer'
+      );
+      return new C();
+    },
+    async () => {
+      const { default: C } = await import(
+        '~/client/services/AdminGoogleSecurityContainer'
+      );
+      return new C();
+    },
+    async () => {
+      const { default: C } = await import(
+        '~/client/services/AdminGitHubSecurityContainer'
+      );
+      return new C();
+    },
   ],
   ],
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps<Props> = async(context: GetServerSidePropsContext) => {
+export const getServerSideProps: GetServerSideProps<Props> = async (
+  context: GetServerSidePropsContext,
+) => {
   const commonResult = await getServerSideAdminCommonProps(context);
   const commonResult = await getServerSideAdminCommonProps(context);
 
 
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;

+ 19 - 7
apps/app/src/pages/admin/slack-integration-legacy.page.tsx

@@ -1,21 +1,33 @@
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
-
-const LegacySlackIntegration = dynamic(() => import('~/client/components/Admin/LegacySlackIntegration/LegacySlackIntegration'), { ssr: false });
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
+
+const LegacySlackIntegration = dynamic(
+  () =>
+    import(
+      '~/client/components/Admin/LegacySlackIntegration/LegacySlackIntegration'
+    ),
+  { ssr: false },
+);
 
 
 type Props = AdminCommonProps;
 type Props = AdminCommonProps;
 
 
-const AdminLegacySlackIntegrationPage: NextPageWithLayout<Props> = () => <LegacySlackIntegration />;
+const AdminLegacySlackIntegrationPage: NextPageWithLayout<Props> = () => (
+  <LegacySlackIntegration />
+);
 
 
 AdminLegacySlackIntegrationPage.getLayout = createAdminPageLayout<Props>({
 AdminLegacySlackIntegrationPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('slack_integration_legacy.slack_integration_legacy'),
   title: (_p, t) => t('slack_integration_legacy.slack_integration_legacy'),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminSlackIntegrationLegacyContainer = (await import('~/client/services/AdminSlackIntegrationLegacyContainer')).default;
+    async () => {
+      const AdminSlackIntegrationLegacyContainer = (
+        await import('~/client/services/AdminSlackIntegrationLegacyContainer')
+      ).default;
       return new AdminSlackIntegrationLegacyContainer();
       return new AdminSlackIntegrationLegacyContainer();
     },
     },
   ],
   ],

+ 20 - 9
apps/app/src/pages/admin/slack-integration.page.tsx

@@ -1,23 +1,32 @@
-import { useHydrateAtoms } from 'jotai/utils';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
+import { useHydrateAtoms } from 'jotai/utils';
 
 
 import { _atomsForAdminPagesHydration as atoms } from '~/states/global';
 import { _atomsForAdminPagesHydration as atoms } from '~/states/global';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
-
-const SlackIntegration = dynamic(() => import('~/client/components/Admin/SlackIntegration/SlackIntegration').then(mod => mod.SlackIntegration), { ssr: false });
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
+
+const SlackIntegration = dynamic(
+  () =>
+    import('~/client/components/Admin/SlackIntegration/SlackIntegration').then(
+      (mod) => mod.SlackIntegration,
+    ),
+  { ssr: false },
+);
 
 
 type Props = AdminCommonProps;
 type Props = AdminCommonProps;
 
 
 const AdminSlackIntegrationPage: NextPageWithLayout<Props> = (props: Props) => {
 const AdminSlackIntegrationPage: NextPageWithLayout<Props> = (props: Props) => {
   // hydrate global state
   // hydrate global state
-  useHydrateAtoms([
-    [atoms.siteUrlWithEmptyValueWarnAtom, props.siteUrlWithEmptyValueWarn],
-  ], { dangerouslyForceHydrate: true });
+  useHydrateAtoms(
+    [[atoms.siteUrlWithEmptyValueWarnAtom, props.siteUrlWithEmptyValueWarn]],
+    { dangerouslyForceHydrate: true },
+  );
 
 
   return <SlackIntegration />;
   return <SlackIntegration />;
 };
 };
@@ -26,7 +35,9 @@ AdminSlackIntegrationPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('slack_integration.slack_integration'),
   title: (_p, t) => t('slack_integration.slack_integration'),
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps<Props> = async(context: GetServerSidePropsContext) => {
+export const getServerSideProps: GetServerSideProps<Props> = async (
+  context: GetServerSidePropsContext,
+) => {
   return getServerSideAdminCommonProps(context);
   return getServerSideAdminCommonProps(context);
 };
 };
 
 

+ 19 - 9
apps/app/src/pages/admin/user-group-detail/[userGroupId].page.tsx

@@ -1,16 +1,21 @@
 import { useMemo } from 'react';
 import { useMemo } from 'react';
-
-import { useHydrateAtoms } from 'jotai/utils';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
 import { useRouter } from 'next/router';
 import { useRouter } from 'next/router';
+import { useHydrateAtoms } from 'jotai/utils';
 
 
 import { isAclEnabledAtom } from '~/states/server-configurations';
 import { isAclEnabledAtom } from '~/states/server-configurations';
 
 
 import type { NextPageWithLayout } from '../../_app.page';
 import type { NextPageWithLayout } from '../../_app.page';
 import type { AdminCommonProps } from '../_shared';
 import type { AdminCommonProps } from '../_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from '../_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from '../_shared';
 
 
-const UserGroupDetailPage = dynamic(() => import('~/client/components/Admin/UserGroupDetail/UserGroupDetailPage'), { ssr: false });
+const UserGroupDetailPage = dynamic(
+  () => import('~/client/components/Admin/UserGroupDetail/UserGroupDetailPage'),
+  { ssr: false },
+);
 
 
 type PageProps = { isAclEnabled: boolean };
 type PageProps = { isAclEnabled: boolean };
 type Props = AdminCommonProps & PageProps;
 type Props = AdminCommonProps & PageProps;
@@ -19,15 +24,20 @@ const AdminUserGroupDetailPage: NextPageWithLayout<Props> = (props: Props) => {
   const router = useRouter();
   const router = useRouter();
 
 
   // hydrate
   // hydrate
-  useHydrateAtoms([[isAclEnabledAtom, props.isAclEnabled]], { dangerouslyForceHydrate: true });
+  useHydrateAtoms([[isAclEnabledAtom, props.isAclEnabled]], {
+    dangerouslyForceHydrate: true,
+  });
 
 
   const { userGroupId, isExternalGroup } = router.query;
   const { userGroupId, isExternalGroup } = router.query;
-  const id = useMemo(() => (Array.isArray(userGroupId) ? userGroupId[0] : userGroupId), [userGroupId]);
+  const id = useMemo(
+    () => (Array.isArray(userGroupId) ? userGroupId[0] : userGroupId),
+    [userGroupId],
+  );
   const isExternal = isExternalGroup === 'true';
   const isExternal = isExternalGroup === 'true';
 
 
-  return (id != null && router.isReady)
-    ? <UserGroupDetailPage userGroupId={id} isExternalGroup={isExternal} />
-    : null;
+  return id != null && router.isReady ? (
+    <UserGroupDetailPage userGroupId={id} isExternalGroup={isExternal} />
+  ) : null;
 };
 };
 
 
 AdminUserGroupDetailPage.getLayout = createAdminPageLayout<Props>({
 AdminUserGroupDetailPage.getLayout = createAdminPageLayout<Props>({

+ 22 - 10
apps/app/src/pages/admin/user-groups.page.tsx

@@ -1,26 +1,34 @@
-import { useHydrateAtoms } from 'jotai/utils';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
+import { useHydrateAtoms } from 'jotai/utils';
 
 
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import { isAclEnabledAtom } from '~/states/server-configurations';
 import { isAclEnabledAtom } from '~/states/server-configurations';
 
 
 import type { NextPageWithLayout } from '../_app.page';
 import type { NextPageWithLayout } from '../_app.page';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../utils/server-side-props';
-
 import type { AdminCommonProps } from './_shared';
 import type { AdminCommonProps } from './_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from './_shared';
-
-const UserGroupPage = dynamic(() => import('~/client/components/Admin/UserGroup/UserGroupPage').then(mod => mod.UserGroupPage), { ssr: false });
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from './_shared';
+
+const UserGroupPage = dynamic(
+  () =>
+    import('~/client/components/Admin/UserGroup/UserGroupPage').then(
+      (mod) => mod.UserGroupPage,
+    ),
+  { ssr: false },
+);
 
 
 type PageProps = { isAclEnabled: boolean };
 type PageProps = { isAclEnabled: boolean };
 type Props = AdminCommonProps & PageProps;
 type Props = AdminCommonProps & PageProps;
 
 
 const AdminUserGroupPage: NextPageWithLayout<Props> = (props: Props) => {
 const AdminUserGroupPage: NextPageWithLayout<Props> = (props: Props) => {
   // hydrate
   // hydrate
-  useHydrateAtoms([
-    [isAclEnabledAtom, props.isAclEnabled],
-  ], { dangerouslyForceHydrate: true });
+  useHydrateAtoms([[isAclEnabledAtom, props.isAclEnabled]], {
+    dangerouslyForceHydrate: true,
+  });
 
 
   return <UserGroupPage />;
   return <UserGroupPage />;
 };
 };
@@ -29,14 +37,18 @@ AdminUserGroupPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('user_group_management.user_group_management'),
   title: (_p, t) => t('user_group_management.user_group_management'),
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps<Props> = async(context: GetServerSidePropsContext) => {
+export const getServerSideProps: GetServerSideProps<Props> = async (
+  context: GetServerSidePropsContext,
+) => {
   const baseResult = await getServerSideAdminCommonProps(context);
   const baseResult = await getServerSideAdminCommonProps(context);
 
 
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
   const { crowi } = req;
   const { crowi } = req;
   const { aclService } = crowi;
   const { aclService } = crowi;
 
 
-  const fragment = { props: { isAclEnabled: aclService.isAclEnabled() } } satisfies { props: PageProps };
+  const fragment = {
+    props: { isAclEnabled: aclService.isAclEnabled() },
+  } satisfies { props: PageProps };
   return mergeGetServerSidePropsResults(baseResult, fragment);
   return mergeGetServerSidePropsResults(baseResult, fragment);
 };
 };
 
 

+ 15 - 5
apps/app/src/pages/admin/users/external-accounts.page.tsx

@@ -2,19 +2,29 @@ import dynamic from 'next/dynamic';
 
 
 import type { NextPageWithLayout } from '../../_app.page';
 import type { NextPageWithLayout } from '../../_app.page';
 import type { AdminCommonProps } from '../_shared';
 import type { AdminCommonProps } from '../_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from '../_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from '../_shared';
 
 
-const ManageExternalAccount = dynamic(() => import('~/client/components/Admin/ManageExternalAccount'), { ssr: false });
+const ManageExternalAccount = dynamic(
+  () => import('~/client/components/Admin/ManageExternalAccount'),
+  { ssr: false },
+);
 
 
 type Props = AdminCommonProps;
 type Props = AdminCommonProps;
 
 
-const AdminExternalAccountsPage: NextPageWithLayout<Props> = () => <ManageExternalAccount />;
+const AdminExternalAccountsPage: NextPageWithLayout<Props> = () => (
+  <ManageExternalAccount />
+);
 
 
 AdminExternalAccountsPage.getLayout = createAdminPageLayout<Props>({
 AdminExternalAccountsPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('user_management.external_account'),
   title: (_p, t) => t('user_management.external_account'),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminExternalAccountsContainer = (await import('~/client/services/AdminExternalAccountsContainer')).default;
+    async () => {
+      const AdminExternalAccountsContainer = (
+        await import('~/client/services/AdminExternalAccountsContainer')
+      ).default;
       return new AdminExternalAccountsContainer();
       return new AdminExternalAccountsContainer();
     },
     },
   ],
   ],

+ 22 - 8
apps/app/src/pages/admin/users/index.page.tsx

@@ -1,6 +1,6 @@
-import { useHydrateAtoms } from 'jotai/utils';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 import dynamic from 'next/dynamic';
 import dynamic from 'next/dynamic';
+import { useHydrateAtoms } from 'jotai/utils';
 
 
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import type { CrowiRequest } from '~/interfaces/crowi-request';
 import { isMailerSetupAtom } from '~/states/server-configurations';
 import { isMailerSetupAtom } from '~/states/server-configurations';
@@ -8,37 +8,51 @@ import { isMailerSetupAtom } from '~/states/server-configurations';
 import type { NextPageWithLayout } from '../../_app.page';
 import type { NextPageWithLayout } from '../../_app.page';
 import { mergeGetServerSidePropsResults } from '../../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../../utils/server-side-props';
 import type { AdminCommonProps } from '../_shared';
 import type { AdminCommonProps } from '../_shared';
-import { createAdminPageLayout, getServerSideAdminCommonProps } from '../_shared';
+import {
+  createAdminPageLayout,
+  getServerSideAdminCommonProps,
+} from '../_shared';
 
 
-const UserManagement = dynamic(() => import('~/client/components/Admin/UserManagement'), { ssr: false });
+const UserManagement = dynamic(
+  () => import('~/client/components/Admin/UserManagement'),
+  { ssr: false },
+);
 
 
 type PageProps = { isMailerSetup: boolean };
 type PageProps = { isMailerSetup: boolean };
 type Props = AdminCommonProps & PageProps;
 type Props = AdminCommonProps & PageProps;
 
 
 const AdminUserManagementPage: NextPageWithLayout<Props> = (props: Props) => {
 const AdminUserManagementPage: NextPageWithLayout<Props> = (props: Props) => {
   // hydrate
   // hydrate
-  useHydrateAtoms([[isMailerSetupAtom, props.isMailerSetup]], { dangerouslyForceHydrate: true });
+  useHydrateAtoms([[isMailerSetupAtom, props.isMailerSetup]], {
+    dangerouslyForceHydrate: true,
+  });
   return <UserManagement />;
   return <UserManagement />;
 };
 };
 
 
 AdminUserManagementPage.getLayout = createAdminPageLayout<Props>({
 AdminUserManagementPage.getLayout = createAdminPageLayout<Props>({
   title: (_p, t) => t('user_management.user_management'),
   title: (_p, t) => t('user_management.user_management'),
   containerFactories: [
   containerFactories: [
-    async() => {
-      const AdminUsersContainer = (await import('~/client/services/AdminUsersContainer')).default;
+    async () => {
+      const AdminUsersContainer = (
+        await import('~/client/services/AdminUsersContainer')
+      ).default;
       return new AdminUsersContainer();
       return new AdminUsersContainer();
     },
     },
   ],
   ],
 });
 });
 
 
-export const getServerSideProps: GetServerSideProps<Props> = async(context: GetServerSidePropsContext) => {
+export const getServerSideProps: GetServerSideProps<Props> = async (
+  context: GetServerSidePropsContext,
+) => {
   const baseResult = await getServerSideAdminCommonProps(context);
   const baseResult = await getServerSideAdminCommonProps(context);
 
 
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
   const { crowi } = req;
   const { crowi } = req;
   const { mailService } = crowi;
   const { mailService } = crowi;
 
 
-  const fragment = { props: { isMailerSetup: mailService.isMailerSetup } } satisfies { props: PageProps };
+  const fragment = {
+    props: { isMailerSetup: mailService.isMailerSetup },
+  } satisfies { props: PageProps };
   return mergeGetServerSidePropsResults(baseResult, fragment);
   return mergeGetServerSidePropsResults(baseResult, fragment);
 };
 };
 
 

+ 13 - 13
apps/app/src/pages/basic-layout-page/get-server-side-props/index.ts

@@ -2,22 +2,22 @@ import type { GetServerSideProps, GetServerSidePropsContext } from 'next';
 
 
 import { mergeGetServerSidePropsResults } from '../../utils/server-side-props';
 import { mergeGetServerSidePropsResults } from '../../utils/server-side-props';
 import type { BasicLayoutConfigurationProps } from '../types';
 import type { BasicLayoutConfigurationProps } from '../types';
-
 import { getServerSideSearchConfigurationProps } from './search-configurations';
 import { getServerSideSearchConfigurationProps } from './search-configurations';
 import { getServerSideSidebarConfigProps } from './sidebar-configurations';
 import { getServerSideSidebarConfigProps } from './sidebar-configurations';
 import { getServerSideUserUISettingsProps } from './user-ui-settings';
 import { getServerSideUserUISettingsProps } from './user-ui-settings';
 
 
-export const getServerSideBasicLayoutProps: GetServerSideProps<BasicLayoutConfigurationProps> = async(context: GetServerSidePropsContext) => {
-  const [
-    searchConfigResult,
-    sidebarConfigResult,
-    userUIResult,
-  ] = await Promise.all([
-    getServerSideSearchConfigurationProps(context),
-    getServerSideSidebarConfigProps(context),
-    getServerSideUserUISettingsProps(context),
-  ]);
+export const getServerSideBasicLayoutProps: GetServerSideProps<
+  BasicLayoutConfigurationProps
+> = async (context: GetServerSidePropsContext) => {
+  const [searchConfigResult, sidebarConfigResult, userUIResult] =
+    await Promise.all([
+      getServerSideSearchConfigurationProps(context),
+      getServerSideSidebarConfigProps(context),
+      getServerSideUserUISettingsProps(context),
+    ]);
 
 
-  return mergeGetServerSidePropsResults(searchConfigResult,
-    mergeGetServerSidePropsResults(sidebarConfigResult, userUIResult));
+  return mergeGetServerSidePropsResults(
+    searchConfigResult,
+    mergeGetServerSidePropsResults(sidebarConfigResult, userUIResult),
+  );
 };
 };

+ 6 - 2
apps/app/src/pages/basic-layout-page/get-server-side-props/search-configurations.ts

@@ -4,7 +4,9 @@ import type { CrowiRequest } from '~/interfaces/crowi-request';
 
 
 import type { SearchConfigurationProps } from '../types';
 import type { SearchConfigurationProps } from '../types';
 
 
-export const getServerSideSearchConfigurationProps: GetServerSideProps<SearchConfigurationProps> = async(context: GetServerSidePropsContext) => {
+export const getServerSideSearchConfigurationProps: GetServerSideProps<
+  SearchConfigurationProps
+> = async (context: GetServerSidePropsContext) => {
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
   const { crowi } = req;
   const { crowi } = req;
   const { configManager, searchService } = crowi;
   const { configManager, searchService } = crowi;
@@ -14,7 +16,9 @@ export const getServerSideSearchConfigurationProps: GetServerSideProps<SearchCon
       searchConfig: {
       searchConfig: {
         isSearchServiceConfigured: searchService.isConfigured,
         isSearchServiceConfigured: searchService.isConfigured,
         isSearchServiceReachable: searchService.isReachable,
         isSearchServiceReachable: searchService.isReachable,
-        isSearchScopeChildrenAsDefault: configManager.getConfig('customize:isSearchScopeChildrenAsDefault'),
+        isSearchScopeChildrenAsDefault: configManager.getConfig(
+          'customize:isSearchScopeChildrenAsDefault',
+        ),
       },
       },
     },
     },
   };
   };

+ 9 - 3
apps/app/src/pages/basic-layout-page/get-server-side-props/sidebar-configurations.ts

@@ -4,7 +4,9 @@ import type { CrowiRequest } from '~/interfaces/crowi-request';
 
 
 import type { SidebarConfigurationProps } from '../types';
 import type { SidebarConfigurationProps } from '../types';
 
 
-export const getServerSideSidebarConfigProps: GetServerSideProps<SidebarConfigurationProps> = async(context: GetServerSidePropsContext) => {
+export const getServerSideSidebarConfigProps: GetServerSideProps<
+  SidebarConfigurationProps
+> = async (context: GetServerSidePropsContext) => {
   const req: CrowiRequest = context.req as CrowiRequest;
   const req: CrowiRequest = context.req as CrowiRequest;
   const { crowi } = req;
   const { crowi } = req;
   const { configManager } = crowi;
   const { configManager } = crowi;
@@ -12,8 +14,12 @@ export const getServerSideSidebarConfigProps: GetServerSideProps<SidebarConfigur
   return {
   return {
     props: {
     props: {
       sidebarConfig: {
       sidebarConfig: {
-        isSidebarCollapsedMode: configManager.getConfig('customize:isSidebarCollapsedMode'),
-        isSidebarClosedAtDockMode: configManager.getConfig('customize:isSidebarClosedAtDockMode'),
+        isSidebarCollapsedMode: configManager.getConfig(
+          'customize:isSidebarCollapsedMode',
+        ),
+        isSidebarClosedAtDockMode: configManager.getConfig(
+          'customize:isSidebarClosedAtDockMode',
+        ),
       },
       },
     },
     },
   };
   };

+ 9 - 6
apps/app/src/pages/basic-layout-page/get-server-side-props/user-ui-settings.ts

@@ -7,16 +7,19 @@ import { getModelSafely } from '~/server/util/mongoose-utils';
 
 
 import type { UserUISettingsProps } from '../types';
 import type { UserUISettingsProps } from '../types';
 
 
-
-export const getServerSideUserUISettingsProps: GetServerSideProps<UserUISettingsProps> = async(context: GetServerSidePropsContext) => {
+export const getServerSideUserUISettingsProps: GetServerSideProps<
+  UserUISettingsProps
+> = async (context: GetServerSidePropsContext) => {
   const req = context.req as CrowiRequest;
   const req = context.req as CrowiRequest;
   const { user } = req;
   const { user } = req;
 
 
   // retrieve UserUISettings
   // retrieve UserUISettings
-  const UserUISettings = getModelSafely<UserUISettingsDocument>('UserUISettings');
-  const userUISettings = user != null && UserUISettings != null
-    ? await UserUISettings.findOne({ user: user._id }).lean() ?? undefined
-    : req.session.uiSettings as IUserUISettings; // for guests
+  const UserUISettings =
+    getModelSafely<UserUISettingsDocument>('UserUISettings');
+  const userUISettings =
+    user != null && UserUISettings != null
+      ? ((await UserUISettings.findOne({ user: user._id }).lean()) ?? undefined)
+      : (req.session.uiSettings as IUserUISettings); // for guests
 
 
   return {
   return {
     props: {
     props: {

+ 23 - 9
apps/app/src/pages/basic-layout-page/hydrate.ts

@@ -7,23 +7,37 @@ import {
 } from '~/states/server-configurations';
 } from '~/states/server-configurations';
 import { useHydrateSidebarAtoms } from '~/states/ui/sidebar/hydrate';
 import { useHydrateSidebarAtoms } from '~/states/ui/sidebar/hydrate';
 
 
-import type { SearchConfigurationProps, SidebarConfigurationProps, UserUISettingsProps } from './types';
+import type {
+  SearchConfigurationProps,
+  SidebarConfigurationProps,
+  UserUISettingsProps,
+} from './types';
 
 
 /**
 /**
  * Hook for hydrating server configuration atoms with server-side data
  * Hook for hydrating server configuration atoms with server-side data
  * This should be called early in the app component to ensure atoms are properly initialized before rendering
  * This should be called early in the app component to ensure atoms are properly initialized before rendering
  */
  */
 export const useHydrateBasicLayoutConfigurationAtoms = (
 export const useHydrateBasicLayoutConfigurationAtoms = (
-    searchConfig: SearchConfigurationProps['searchConfig'] | undefined,
-    sidebarConfig: SidebarConfigurationProps['sidebarConfig'] | undefined,
-    userUISettings: UserUISettingsProps['userUISettings'] | undefined,
+  searchConfig: SearchConfigurationProps['searchConfig'] | undefined,
+  sidebarConfig: SidebarConfigurationProps['sidebarConfig'] | undefined,
+  userUISettings: UserUISettingsProps['userUISettings'] | undefined,
 ): void => {
 ): void => {
   // Hydrate server configuration atoms with server-side data
   // Hydrate server configuration atoms with server-side data
-  useHydrateAtoms(searchConfig == null ? [] : [
-    [isSearchServiceConfiguredAtom, searchConfig.isSearchServiceConfigured],
-    [isSearchServiceReachableAtom, searchConfig.isSearchServiceReachable],
-    [isSearchScopeChildrenAsDefaultAtom, searchConfig.isSearchScopeChildrenAsDefault],
-  ]);
+  useHydrateAtoms(
+    searchConfig == null
+      ? []
+      : [
+          [
+            isSearchServiceConfiguredAtom,
+            searchConfig.isSearchServiceConfigured,
+          ],
+          [isSearchServiceReachableAtom, searchConfig.isSearchServiceReachable],
+          [
+            isSearchScopeChildrenAsDefaultAtom,
+            searchConfig.isSearchScopeChildrenAsDefault,
+          ],
+        ],
+  );
 
 
   useHydrateSidebarAtoms(sidebarConfig, userUISettings);
   useHydrateSidebarAtoms(sidebarConfig, userUISettings);
 };
 };

+ 8 - 6
apps/app/src/pages/basic-layout-page/types.ts

@@ -2,19 +2,21 @@ import type { ISidebarConfig } from '~/interfaces/sidebar-config';
 import type { IUserUISettings } from '~/interfaces/user-ui-settings';
 import type { IUserUISettings } from '~/interfaces/user-ui-settings';
 
 
 export type UserUISettingsProps = {
 export type UserUISettingsProps = {
-  userUISettings?: IUserUISettings,
+  userUISettings?: IUserUISettings;
 };
 };
 
 
 export type SidebarConfigurationProps = {
 export type SidebarConfigurationProps = {
-  sidebarConfig: ISidebarConfig,
-}
+  sidebarConfig: ISidebarConfig;
+};
 
 
 export type SearchConfigurationProps = {
 export type SearchConfigurationProps = {
   searchConfig: {
   searchConfig: {
     isSearchServiceConfigured: boolean;
     isSearchServiceConfigured: boolean;
     isSearchServiceReachable: boolean;
     isSearchServiceReachable: boolean;
     isSearchScopeChildrenAsDefault: boolean;
     isSearchScopeChildrenAsDefault: boolean;
-  },
-}
+  };
+};
 
 
-export type BasicLayoutConfigurationProps = UserUISettingsProps & SidebarConfigurationProps & SearchConfigurationProps;
+export type BasicLayoutConfigurationProps = UserUISettingsProps &
+  SidebarConfigurationProps &
+  SearchConfigurationProps;

Некоторые файлы не были показаны из-за большого количества измененных файлов