renderer.tsx 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. import { useCallback } from 'react';
  2. import type { HtmlElementNode } from 'rehype-toc';
  3. import useSWR, { type SWRResponse } from 'swr';
  4. import {
  5. type RendererOptions,
  6. generateSimpleViewOptions, generatePreviewOptions,
  7. generateViewOptions, generateTocOptions, generatePresentationViewOptions,
  8. } from '~/services/renderer/renderer';
  9. import { getGrowiFacade } from '~/utils/growi-facade';
  10. import {
  11. useRendererConfig,
  12. } from './context';
  13. import { useCurrentPagePath } from './page';
  14. import { useCurrentPageTocNode } from './ui';
  15. export const useViewOptions = (): SWRResponse<RendererOptions, Error> => {
  16. const { data: currentPagePath } = useCurrentPagePath();
  17. const { data: rendererConfig } = useRendererConfig();
  18. const { mutate: mutateCurrentPageTocNode } = useCurrentPageTocNode();
  19. const storeTocNodeHandler = useCallback((toc: HtmlElementNode) => {
  20. mutateCurrentPageTocNode(toc, { revalidate: false });
  21. }, [mutateCurrentPageTocNode]);
  22. const isAllDataValid = currentPagePath != null && rendererConfig != null;
  23. return useSWR(
  24. isAllDataValid
  25. ? ['viewOptions', currentPagePath, rendererConfig]
  26. : null,
  27. ([, currentPagePath, rendererConfig]) => {
  28. // determine options generator
  29. const optionsGenerator = getGrowiFacade().markdownRenderer?.optionsGenerators?.customGenerateViewOptions ?? generateViewOptions;
  30. return optionsGenerator(currentPagePath, rendererConfig, storeTocNodeHandler);
  31. },
  32. {
  33. keepPreviousData: true,
  34. fallbackData: isAllDataValid ? generateViewOptions(currentPagePath, rendererConfig, storeTocNodeHandler) : undefined,
  35. revalidateOnFocus: false,
  36. revalidateOnReconnect: false,
  37. },
  38. );
  39. };
  40. export const useTocOptions = (): SWRResponse<RendererOptions, Error> => {
  41. const { data: currentPagePath } = useCurrentPagePath();
  42. const { data: rendererConfig } = useRendererConfig();
  43. const { data: tocNode } = useCurrentPageTocNode();
  44. const isAllDataValid = currentPagePath != null && rendererConfig != null && tocNode != null;
  45. return useSWR(
  46. isAllDataValid
  47. ? ['tocOptions', currentPagePath, tocNode, rendererConfig]
  48. : null,
  49. ([, , tocNode, rendererConfig]) => generateTocOptions(rendererConfig, tocNode),
  50. {
  51. keepPreviousData: true,
  52. fallbackData: isAllDataValid ? generateTocOptions(rendererConfig, tocNode) : undefined,
  53. revalidateOnFocus: false,
  54. revalidateOnReconnect: false,
  55. },
  56. );
  57. };
  58. export const usePreviewOptions = (): SWRResponse<RendererOptions, Error> => {
  59. const { data: currentPagePath } = useCurrentPagePath();
  60. const { data: rendererConfig } = useRendererConfig();
  61. const isAllDataValid = currentPagePath != null && rendererConfig != null;
  62. return useSWR(
  63. isAllDataValid
  64. ? ['previewOptions', rendererConfig, currentPagePath]
  65. : null,
  66. ([, rendererConfig, pagePath]) => {
  67. // determine options generator
  68. const optionsGenerator = getGrowiFacade().markdownRenderer?.optionsGenerators?.customGeneratePreviewOptions ?? generatePreviewOptions;
  69. return optionsGenerator(rendererConfig, pagePath);
  70. },
  71. {
  72. keepPreviousData: true,
  73. fallbackData: isAllDataValid ? generatePreviewOptions(rendererConfig, currentPagePath) : undefined,
  74. revalidateOnFocus: false,
  75. revalidateOnReconnect: false,
  76. },
  77. );
  78. };
  79. export const useCommentForCurrentPageOptions = (): SWRResponse<RendererOptions, Error> => {
  80. const { data: currentPagePath } = useCurrentPagePath();
  81. const { data: rendererConfig } = useRendererConfig();
  82. const isAllDataValid = currentPagePath != null && rendererConfig != null;
  83. return useSWR(
  84. isAllDataValid
  85. ? ['commentPreviewOptions', rendererConfig, currentPagePath]
  86. : null,
  87. ([, rendererConfig, currentPagePath]) => generateSimpleViewOptions(
  88. rendererConfig,
  89. currentPagePath,
  90. undefined,
  91. rendererConfig.isEnabledLinebreaksInComments,
  92. ),
  93. {
  94. keepPreviousData: true,
  95. fallbackData: isAllDataValid ? generateSimpleViewOptions(
  96. rendererConfig,
  97. currentPagePath,
  98. undefined,
  99. rendererConfig.isEnabledLinebreaksInComments,
  100. ) : undefined,
  101. revalidateOnFocus: false,
  102. revalidateOnReconnect: false,
  103. },
  104. );
  105. };
  106. export const useCommentPreviewOptions = useCommentForCurrentPageOptions;
  107. export const useSelectedPagePreviewOptions = (pagePath: string, highlightKeywords?: string | string[]): SWRResponse<RendererOptions, Error> => {
  108. const { data: rendererConfig } = useRendererConfig();
  109. const isAllDataValid = rendererConfig != null;
  110. return useSWR(
  111. isAllDataValid
  112. ? ['selectedPagePreviewOptions', rendererConfig, pagePath, highlightKeywords]
  113. : null,
  114. ([, rendererConfig, pagePath, highlightKeywords]) => generateSimpleViewOptions(rendererConfig, pagePath, highlightKeywords),
  115. {
  116. fallbackData: isAllDataValid ? generateSimpleViewOptions(rendererConfig, pagePath, highlightKeywords) : undefined,
  117. revalidateOnFocus: false,
  118. revalidateOnReconnect: false,
  119. },
  120. );
  121. };
  122. export const useSearchResultOptions = useSelectedPagePreviewOptions;
  123. export const useTimelineOptions = useSelectedPagePreviewOptions;
  124. export const useCustomSidebarOptions = (): SWRResponse<RendererOptions, Error> => {
  125. const { data: rendererConfig } = useRendererConfig();
  126. const isAllDataValid = rendererConfig != null;
  127. return useSWR(
  128. isAllDataValid
  129. ? ['customSidebarOptions', rendererConfig]
  130. : null,
  131. ([, rendererConfig]) => generateSimpleViewOptions(rendererConfig, '/'),
  132. {
  133. keepPreviousData: true,
  134. fallbackData: isAllDataValid ? generateSimpleViewOptions(rendererConfig, '/') : undefined,
  135. revalidateOnFocus: false,
  136. revalidateOnReconnect: false,
  137. },
  138. );
  139. };
  140. export const usePresentationViewOptions = (): SWRResponse<RendererOptions, Error> => {
  141. const { data: currentPagePath } = useCurrentPagePath();
  142. const { data: rendererConfig } = useRendererConfig();
  143. const isAllDataValid = currentPagePath != null && rendererConfig != null;
  144. return useSWR(
  145. isAllDataValid
  146. ? ['presentationViewOptions', currentPagePath, rendererConfig]
  147. : null,
  148. ([, currentPagePath, rendererConfig]) => generatePresentationViewOptions(rendererConfig, currentPagePath),
  149. {
  150. fallbackData: isAllDataValid ? generatePresentationViewOptions(rendererConfig, currentPagePath) : undefined,
  151. revalidateOnFocus: false,
  152. revalidateOnReconnect: false,
  153. },
  154. );
  155. };