Forráskód Böngészése

Merge pull request #7952 from weseek/imprv/115672-125680-beautiful-slidestyle-in-preview

imprv: Normal slide preview look like a Marp
Yuki Takei 2 éve
szülő
commit
774a8b6d5b

+ 6 - 11
apps/app/src/components/ReactMarkdownComponents/SlideViewer.tsx

@@ -1,6 +1,5 @@
 import React from 'react';
 
-import { MARP_CONTAINER_CLASS_NAME } from '@growi/presentation';
 import dynamic from 'next/dynamic';
 import { ReactMarkdownOptions } from 'react-markdown/lib/react-markdown';
 
@@ -22,16 +21,12 @@ export const SlideViewer: React.FC<SlideViewerProps> = React.memo((props: SlideV
   const { data: rendererOptions } = usePresentationViewOptions();
 
   return (
-    <div className={`${MARP_CONTAINER_CLASS_NAME}`}>
-      <div className="slides">
-        <Slides
-          hasMarpFlag={marp != null}
-          options={{ rendererOptions: rendererOptions as ReactMarkdownOptions }}
-        >
-          {children}
-        </Slides>
-      </div>
-    </div>
+    <Slides
+      hasMarpFlag={marp != null}
+      options={{ rendererOptions: rendererOptions as ReactMarkdownOptions }}
+    >
+      {children}
+    </Slides>
   );
 });
 

+ 20 - 33
packages/presentation/src/components/GrowiSlides.tsx

@@ -1,67 +1,54 @@
-import { Marp } from '@marp-team/marp-core';
-import { Element } from '@marp-team/marpit';
 import Head from 'next/head';
 import { ReactMarkdown } from 'react-markdown/lib/react-markdown';
 
 import type { PresentationOptions } from '../consts';
+import { MARP_CONTAINER_CLASS_NAME, presentationMarpit, slideMarpit } from '../services/growi-marpit';
 import * as extractSections from '../services/renderer/extract-sections';
 
-import './Slides.global.scss';
 
-const MARP_CONTAINER_CLASS_NAME = 'marpit';
+import './Slides.global.scss';
+import { PresentationRichSlideSection, RichSlideSection } from './RichSlideSection';
 
-// ----------------------------------------------------
-// TODO: to change better slide style
-// https://redmine.weseek.co.jp/issues/125680
-const marp = new Marp({
-  container: [
-    new Element('div', { class: MARP_CONTAINER_CLASS_NAME }),
-    new Element('div', { class: 'slides' }),
-  ],
-  inlineSVG: false,
-  emoji: undefined,
-  html: false,
-  math: false,
-});
-const marpSlideTheme = marp.themeSet.add(`
-    /*!
-     * @theme slide_preview
-     */
-    section {
-      max-width: 90%;
-    }
-`);
-marp.themeSet.default = marpSlideTheme;
-// ----------------------------------------------------
 
 type Props = {
   options: PresentationOptions,
   children?: string,
+  presentation?: boolean,
 }
 
 export const GrowiSlides = (props: Props): JSX.Element => {
-  const { options, children } = props;
+  const {
+    options, children, presentation,
+  } = props;
   const {
     rendererOptions, isDarkMode, disableSeparationByHeader,
   } = options;
 
-  rendererOptions.remarkPlugins?.push([
+  if (rendererOptions == null || rendererOptions.remarkPlugins == null || rendererOptions.components == null) {
+    return <></>;
+  }
+
+  rendererOptions.remarkPlugins.push([
     extractSections.remarkPlugin,
     {
       isDarkMode,
       disableSeparationByHeader,
     },
   ]);
+  rendererOptions.components.section = presentation ? PresentationRichSlideSection : RichSlideSection;
 
-  const { css } = marp.render('', { htmlAsArray: true });
+  const marpit = presentation ? presentationMarpit : slideMarpit;
+  const { css } = marpit.render('');
   return (
     <>
       <Head>
         <style>{css}</style>
       </Head>
-      <ReactMarkdown {...rendererOptions}>
-        { children ?? '## No Contents' }
-      </ReactMarkdown>
+      <div className={`slides ${MARP_CONTAINER_CLASS_NAME}`}>
+        <ReactMarkdown {...rendererOptions}>
+          { children ?? '## No Contents' }
+        </ReactMarkdown>
+      </div>
     </>
   );
 

+ 4 - 19
packages/presentation/src/components/MarpSlides.tsx

@@ -1,32 +1,17 @@
-import { Marp } from '@marp-team/marp-core';
-import { Element } from '@marp-team/marpit';
 import Head from 'next/head';
 
 import './Slides.global.scss';
-
-const MARP_CONTAINER_CLASS_NAME = 'marpit';
-
-const marpit = new Marp({
-  container: [
-    new Element('div', { class: MARP_CONTAINER_CLASS_NAME }),
-    new Element('div', { class: 'slides' }),
-  ],
-  slideContainer: [
-    new Element('div', { class: 'shadow rounded m-2' }),
-  ],
-  inlineSVG: true,
-  emoji: undefined,
-  html: false,
-  math: false,
-});
+import { presentationMarpit, slideMarpit } from '../services/growi-marpit';
 
 type Props = {
   children?: string,
+  presentation?: boolean,
 }
 
 export const MarpSlides = (props: Props): JSX.Element => {
-  const { children } = props;
+  const { children, presentation } = props;
 
+  const marpit = presentation ? presentationMarpit : slideMarpit;
   const { html, css } = marpit.render(children ?? '');
   return (
     <>

+ 4 - 6
packages/presentation/src/components/Presentation.tsx

@@ -5,12 +5,11 @@ import Reveal from 'reveal.js';
 import type { PresentationOptions } from '../consts';
 import { parseSlideFrontmatterInMarkdown } from '../services/parse-slide-frontmatter';
 
-import { MARP_CONTAINER_CLASS_NAME, Slides } from './Slides';
+import { Slides } from './Slides';
 
 import 'reveal.js/dist/reveal.css';
 import './Presentation.global.scss';
 
-
 import styles from './Presentation.module.scss';
 
 
@@ -20,6 +19,7 @@ const baseRevealOptions: Reveal.Options = {
   height: 720,
   maxScale: 1.2,
   slideNumber: 'c/t',
+  display: '',
 };
 
 /**
@@ -65,10 +65,8 @@ export const Presentation = (props: PresentationProps): JSX.Element => {
   }, [children, revealOptions]);
 
   return (
-    <div className={`grw-presentation ${styles['grw-presentation']} reveal ${MARP_CONTAINER_CLASS_NAME}`}>
-      <div className="slides">
-        <Slides options={options} hasMarpFlag={marp}>{children}</Slides>
-      </div>
+    <div className={`grw-presentation ${styles['grw-presentation']} reveal`}>
+      <Slides options={options} hasMarpFlag={marp} presentation>{children}</Slides>
     </div>
   );
 };

+ 43 - 0
packages/presentation/src/components/RichSlideSection.tsx

@@ -0,0 +1,43 @@
+import React, { ReactNode } from 'react';
+
+type RichSlideSectionProps = {
+  children: ReactNode,
+  presentation?: boolean,
+}
+
+const OriginalRichSlideSection = React.memo((props: RichSlideSectionProps): JSX.Element => {
+  const { children, presentation } = props;
+
+  return (
+    <section className={presentation ? 'm-2' : 'shadow rounded m-2'}>
+      <svg data-marpit-svg="" viewBox="0 0 1280 720">
+        <foreignObject width="1280" height="720">
+          <section>
+            {children}
+          </section>
+        </foreignObject>
+      </svg>
+    </section>
+  );
+});
+
+export const RichSlideSection = React.memo((props: RichSlideSectionProps): JSX.Element => {
+  const { children } = props;
+
+  return (
+    <OriginalRichSlideSection>
+      {children}
+    </OriginalRichSlideSection>
+  );
+});
+
+
+export const PresentationRichSlideSection = React.memo((props: RichSlideSectionProps): JSX.Element => {
+  const { children } = props;
+
+  return (
+    <OriginalRichSlideSection presentation>
+      {children}
+    </OriginalRichSlideSection>
+  );
+});

+ 1 - 1
packages/presentation/src/components/Slides.global.scss

@@ -1,4 +1,4 @@
-div.marpit > div.slides > section :is(pre, marp-pre) {
+div.slides.marpit > section :is(pre, marp-pre) {
   padding: 0;
   border: none;
 }

+ 11 - 12
packages/presentation/src/components/Slides.tsx

@@ -1,3 +1,4 @@
+
 import type { PresentationOptions } from '../consts';
 
 import { GrowiSlides } from './GrowiSlides';
@@ -5,23 +6,21 @@ import { MarpSlides } from './MarpSlides';
 
 import './Slides.global.scss';
 
-// TODO: to remove MARP_CONTAINER_CLASS_NAME
-// https://redmine.weseek.co.jp/issues/125680
-export const MARP_CONTAINER_CLASS_NAME = 'marpit';
-
 type Props = {
   options: PresentationOptions,
   children?: string,
   hasMarpFlag?: boolean,
+  presentation?: boolean,
 }
 
 export const Slides = (props: Props): JSX.Element => {
-  const { options, children, hasMarpFlag } = props;
-
-  if (hasMarpFlag) {
-    return <MarpSlides>{children}</MarpSlides>;
-  }
-
-  return <GrowiSlides options={options}>{children}</GrowiSlides>;
-
+  const {
+    options, children, hasMarpFlag, presentation,
+  } = props;
+
+  return (
+    hasMarpFlag
+      ? <MarpSlides presentation={presentation}>{children}</MarpSlides>
+      : <GrowiSlides options={options} presentation={presentation}>{children}</GrowiSlides>
+  );
 };

+ 30 - 0
packages/presentation/src/services/growi-marpit.ts

@@ -0,0 +1,30 @@
+import { Marp } from '@marp-team/marp-core';
+import { Element } from '@marp-team/marpit';
+
+export const MARP_CONTAINER_CLASS_NAME = 'marpit';
+
+export const slideMarpit = new Marp({
+  container: [
+    new Element('div', { class: `slides ${MARP_CONTAINER_CLASS_NAME}` }),
+  ],
+  slideContainer: [
+    new Element('section', { class: 'shadow rounded m-2' }),
+  ],
+  inlineSVG: true,
+  emoji: undefined,
+  html: false,
+  math: false,
+});
+
+export const presentationMarpit = new Marp({
+  container: [
+    new Element('div', { class: `slides ${MARP_CONTAINER_CLASS_NAME}` }),
+  ],
+  slideContainer: [
+    new Element('section', { class: 'm-2' }),
+  ],
+  inlineSVG: true,
+  emoji: undefined,
+  html: false,
+  math: false,
+});

+ 1 - 1
packages/presentation/src/services/renderer/extract-sections.ts

@@ -62,7 +62,7 @@ export const remarkPlugin: Plugin<[ExtractSectionsPluginParams]> = (options) =>
       tree,
       startCondition,
       (node, index, parent: Parent) => {
-        if (parent == null || parent.type !== 'root') {
+        if (parent == null || parent.type !== 'root' || node.type === 'yaml') {
           return;
         }