reiji-h 2 лет назад
Родитель
Сommit
15a0de8a6a

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

@@ -1,6 +1,7 @@
 import assert from 'assert';
 
 import { isClient } from '@growi/core/dist/utils/browser-utils';
+import * as slides from '@growi/presentation';
 import * as refsGrowiDirective from '@growi/remark-attachment-refs/dist/client/index.mjs';
 import * as drawio from '@growi/remark-drawio';
 // eslint-disable-next-line import/extensions
@@ -63,6 +64,7 @@ export const generateViewOptions = (
     mermaid.remarkPlugin,
     xsvToTable.remarkPlugin,
     attachment.remarkPlugin,
+    slides.remarkPlugin,
     lsxGrowiDirective.remarkPlugin,
     refsGrowiDirective.remarkPlugin,
   );
@@ -80,6 +82,7 @@ export const generateViewOptions = (
       drawio.sanitizeOption,
       mermaid.sanitizeOption,
       attachment.sanitizeOption,
+      slides.sanitizeOption,
       lsxGrowiDirective.sanitizeOption,
       refsGrowiDirective.sanitizeOption,
     )]
@@ -254,6 +257,7 @@ export const generatePreviewOptions = (config: RendererConfig, pagePath: string)
     attachment.remarkPlugin,
     lsxGrowiDirective.remarkPlugin,
     refsGrowiDirective.remarkPlugin,
+    slides.remarkPlugin,
   );
   if (config.isEnabledLinebreaks) {
     remarkPlugins.push(breaks);
@@ -272,6 +276,7 @@ export const generatePreviewOptions = (config: RendererConfig, pagePath: string)
       lsxGrowiDirective.sanitizeOption,
       refsGrowiDirective.sanitizeOption,
       addLineNumberAttribute.sanitizeOption,
+      slides.sanitizeOption,
     )]
     : () => {};
 

+ 1 - 62
apps/app/src/components/Page/RevisionRenderer.tsx

@@ -1,15 +1,7 @@
-import React, { useEffect, useState } from 'react';
+import React from 'react';
 
-import dynamic from 'next/dynamic';
 import { ErrorBoundary, FallbackProps } from 'react-error-boundary';
 import ReactMarkdown from 'react-markdown';
-import { ReactMarkdownOptions } from 'react-markdown/lib/react-markdown';
-import remarkFrontmatter from 'remark-frontmatter';
-import remarkParse from 'remark-parse';
-import remarkStringify from 'remark-stringify';
-import { unified } from 'unified';
-import { visit } from 'unist-util-visit';
-
 
 import type { RendererOptions } from '~/interfaces/renderer-options';
 import loggerFactory from '~/utils/logger';
@@ -38,65 +30,12 @@ const ErrorFallback: React.FC<FallbackProps> = React.memo(({ error, resetErrorBo
 });
 ErrorFallback.displayName = 'ErrorFallback';
 
-const Slides = dynamic(() => import('@growi/presentation').then(mod => mod.Slides), { ssr: false });
-
 const RevisionRenderer = React.memo((props: Props): JSX.Element => {
 
   const {
     rendererOptions, markdown, additionalClassName, isSlidesOverviewEnabled,
   } = props;
 
-  const [hasSlideFlag, setHasSlideFlag] = useState<boolean>();
-  const [hasMarpFlag, setHasMarpFlag] = useState<boolean>();
-
-  // use useEffect to avoid ssr
-  useEffect(() => {
-    if (isSlidesOverviewEnabled) {
-      const processMarkdown = () => (tree) => {
-        setHasSlideFlag(false);
-        setHasMarpFlag(false);
-        visit(tree, 'yaml', (node) => {
-          if (node.value != null) {
-            const lines = node.value.split('\n');
-
-            lines.forEach((line) => {
-              const [key, value] = line.split(':').map(part => part.trim());
-
-              if (key === 'slide' && value === 'true') {
-                setHasSlideFlag(true);
-              }
-              else if (key === 'marp' && value === 'true') {
-                setHasMarpFlag(true);
-              }
-            });
-          }
-        });
-      };
-
-      unified()
-        .use(remarkParse)
-        .use(remarkStringify)
-        .use(remarkFrontmatter, ['yaml'])
-        .use(processMarkdown)
-        .process(markdown);
-    }
-  }, [markdown, setHasSlideFlag, setHasMarpFlag, isSlidesOverviewEnabled]);
-
-  if (isSlidesOverviewEnabled && (hasSlideFlag || hasMarpFlag)) {
-    const options = {
-      rendererOptions: rendererOptions as ReactMarkdownOptions,
-      isDarkMode: false,
-      disableSeparationsByHeader: false,
-      hasMarpFlag,
-    };
-    return (
-      <Slides
-        options={options}
-        hasMarpFlag={hasMarpFlag}
-      >{markdown}</Slides>
-    );
-  }
-
   return (
     <ErrorBoundary FallbackComponent={ErrorFallback}>
       <ReactMarkdown

+ 46 - 0
packages/presentation/src/services/renderer/remark-slides.ts

@@ -0,0 +1,46 @@
+import type { Schema as SanitizeOption } from 'hast-util-sanitize';
+import type { Plugin } from 'unified';
+import type { Node } from 'unist';
+import { visit } from 'unist-util-visit';
+
+function rewriteNode(node: Node) {
+
+  node.type = 'paragraph';
+  node.children = [{ type: 'text', value: node.value }];
+
+  let slide = false;
+  let marp = false;
+
+  const lines = (node.value as string).split('\n');
+
+  lines.forEach((line) => {
+    const [key, value] = line.split(':').map(part => part.trim());
+
+    if (key === 'slide' && value === 'true') {
+      slide = true;
+    }
+    else if (key === 'marp' && value === 'true') {
+      marp = true;
+    }
+  });
+  if (marp) {
+    node.type = 'marp';
+  }
+  else if (slide) {
+    node.type = 'slide';
+  }
+}
+
+export const remarkPlugin: Plugin = function() {
+  return (tree) => {
+    visit(tree, (node) => {
+      if (node.type === 'yaml' && node.value != null) {
+        rewriteNode(node);
+      }
+    });
+  };
+};
+
+export const sanitizeOption: SanitizeOption = {
+  tagNames: ['slides'],
+};