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

+ 34 - 27
apps/app/src/components/Page/RevisionRenderer.tsx

@@ -3,10 +3,12 @@ import React, { useEffect, useState } 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';
@@ -36,7 +38,7 @@ const ErrorFallback: React.FC<FallbackProps> = React.memo(({ error, resetErrorBo
 });
 ErrorFallback.displayName = 'ErrorFallback';
 
-const RevisionSlidePreview = dynamic(() => import('./RevisionSlidePreview').then(mod => mod.RevisionSlidePreview), { ssr: false });
+const Slides = dynamic(() => import('@growi/presentation').then(mod => mod.Slides), { ssr: false });
 
 const RevisionRenderer = React.memo((props: Props): JSX.Element => {
 
@@ -52,42 +54,47 @@ const RevisionRenderer = React.memo((props: Props): JSX.Element => {
       .use(remarkParse)
       .use(remarkStringify)
       .use(remarkFrontmatter, ['yaml'])
-      .use(() => (obj) => {
+      .use(() => (tree) => {
         setSlideStyle(null);
-        if (obj.children[0]?.type === 'yaml') {
-          for (const line of obj.children[0]?.value.split('\n')) {
-            // obj.children[0].value is "presentation:true\ntitle: hoge\nclass: fuga" etc..
-            // applay last presentation style in frontmatter
-            const parts = line.split(':');
-            if (parts.length !== 2) {
-              continue;
-            }
-            const key = parts[0].trim();
-            const value = parts[1].trim();
-            if (key === 'presentation') {
-              setSlideStyle(
-                value === 'marp' || value === 'true' ? value : null,
-              );
-            }
-            else if (key === 'marp' && value === 'true') {
-              setSlideStyle('marp');
+        visit(tree, (node) => {
+          if (node.type === 'yaml') {
+            for (const line of node.value?.split('\n')) {
+            // node.value is "presentation:true\ntitle: hoge\nclass: fuga" etc..
+              const parts = line.split(':');
+              if (parts.length !== 2) {
+                continue;
+              }
+              const key = parts[0].trim();
+              const value = parts[1].trim();
+              if (key === 'presentation') {
+                setSlideStyle(
+                  value === 'marp' || value === 'true' ? value : null,
+                );
+              }
+              else if (key === 'marp' && value === 'true') {
+                setSlideStyle('marp');
+              }
             }
           }
-        }
+        });
       })
       .process(markdown);
   }, [markdown, setSlideStyle]);
 
-  //  if (isSlidesOverviewEnabled && marp) {
-  if (slideStyle === 'true' || slideStyle === 'marp') {
+  if (slideStyle != null) {
+    const options = {
+      rendererOptions: rendererOptions as ReactMarkdownOptions,
+      isDarkMode: false,
+      disableSeparationsByHeader: false,
+    };
     return (
-      <RevisionSlidePreview
-        rendererOptions = {rendererOptions}
-        markdown = {markdown}
-        slideStyle = {slideStyle}
-      />
+      <Slides
+        options={options}
+        slideStyle={slideStyle}
+      >{markdown}</Slides>
     );
   }
+
   return (
     <ErrorBoundary FallbackComponent={ErrorFallback}>
       <ReactMarkdown

+ 0 - 53
apps/app/src/components/Page/RevisionSlidePreview.tsx

@@ -1,53 +0,0 @@
-
-import React from 'react';
-
-import { MARP_CONTAINER_CLASS_NAME, Slides } from '@growi/presentation';
-import { Head } from 'next/head';
-import type { ReactMarkdownOptions } from 'react-markdown/lib/react-markdown';
-
-import type { RendererOptions } from '~/interfaces/renderer-options';
-import loggerFactory from '~/utils/logger';
-
-import 'katex/dist/katex.min.css';
-
-
-const logger = loggerFactory('components:Page:RevisionSlidePreview');
-
-
-type Props = {
-  rendererOptions: RendererOptions,
-  markdown: string,
-  slideStyle: string,
-}
-export const RevisionSlidePreview = React.memo((props: Props): JSX.Element => {
-
-  const {
-    rendererOptions, markdown, slideStyle,
-  } = props;
-
-  const options = {
-    rendererOptions: rendererOptions as ReactMarkdownOptions,
-    isDarkMode: false,
-    disableSeparationsByHeader: false,
-  };
-  if (slideStyle === 'true') {
-    return (
-      <div className={`${MARP_CONTAINER_CLASS_NAME}`}>
-        <div className = "slides">
-          <Slides options={options}>{markdown}</Slides>
-        </div>
-      </div>
-    );
-  }
-  if (slideStyle === 'marp') {
-    return (
-      <></>
-    );
-  }
-
-  return (
-    <></>
-  );
-
-});
-RevisionSlidePreview.displayName = 'RevisionSlidePreview';

+ 44 - 3
packages/presentation/src/components/Slides.tsx

@@ -9,6 +9,7 @@ import type { PresentationOptions } from '../consts';
 import * as extractSections from '../services/renderer/extract-sections';
 
 import './Slides.global.scss';
+import { string } from 'yargs';
 
 export const MARP_CONTAINER_CLASS_NAME = 'marpit';
 
@@ -24,15 +25,28 @@ const marp = new Marp({
   math: false,
 });
 
+const marpDefaultTheme = marp.themeSet.default;
+const marpSlideTheme = marp.themeSet.add(`
+    /*!
+     * @theme slide_preview
+     */
+    section {
+      max-width: 90%;
+    }
+`);
+
 
 type Props = {
   options: PresentationOptions,
   children?: string,
+  slideStyle?: 'true' | 'marp' | null,
 }
 
 export const Slides = (props: Props): JSX.Element => {
-  const { options, children } = props;
-  const { rendererOptions, isDarkMode, disableSeparationByHeader } = options;
+  const { options, children, slideStyle } = props;
+  const {
+    rendererOptions, isDarkMode, disableSeparationByHeader,
+  } = options;
 
   rendererOptions.remarkPlugins?.push([
     extractSections.remarkPlugin,
@@ -42,8 +56,35 @@ export const Slides = (props: Props): JSX.Element => {
     },
   ]);
 
-  const { css } = marp.render('', { htmlAsArray: true });
 
+  if (slideStyle === 'true') {
+    marp.themeSet.default = marpSlideTheme;
+    const { css } = marp.render('', { htmlAsArray: true });
+    return (
+      <>
+        <Head>
+          <style>{css}</style>
+        </Head>
+        <div className={`${MARP_CONTAINER_CLASS_NAME}`}>
+          <div className="slides">
+            <ReactMarkdown {...rendererOptions}>
+              { children ?? '## No Contents' }
+            </ReactMarkdown>
+          </div>
+        </div>
+      </>
+    );
+  }
+
+  if (slideStyle === 'marp') {
+    return (
+      <></>
+    );
+  }
+
+
+  marp.themeSet.default = marpDefaultTheme;
+  const { css } = marp.render('', { htmlAsArray: true });
   return (
     <>
       <Head>