From fc3e9d52cc682e83a3eab1c84dd9be910d2f5857 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Guillaume=20Perr=C3=A9al?= <guillaume.perreal@inrae.fr>
Date: Sun, 10 May 2020 01:51:22 +0200
Subject: [PATCH] Termine le plugin "mermaid".

---
 gulpfile.esm.js               | 26 ++++++++++--
 lib/rollup.js                 | 77 +++++++++++++++++++----------------
 package.json                  | 12 +++++-
 src/plugin/mermaid/index.js   | 63 +++++++++++++++++++++++++++-
 src/plugin/mermaid/theme.scss | 11 +++++
 5 files changed, 149 insertions(+), 40 deletions(-)
 create mode 100644 src/plugin/mermaid/theme.scss

diff --git a/gulpfile.esm.js b/gulpfile.esm.js
index 8f3c7af..bdc6a1b 100644
--- a/gulpfile.esm.js
+++ b/gulpfile.esm.js
@@ -1,4 +1,4 @@
-import { dest as _dest, src as _src, parallel, series } from "gulp";
+import { dest as _dest, src as _src, parallel, series, watch } from "gulp";
 import csso from "gulp-csso";
 import del from "del";
 import doZip from "gulp-zip";
@@ -102,14 +102,27 @@ export const code = () =>
     .pipe(sourcemaps.write("."))
     .pipe(dest(DEST));
 
-export const plugins = () =>
+const plugin_code = () =>
   src(`${SRC}/plugin/*/index.js`)
     .pipe(sourcemaps.init())
-    .pipe(rollup())
-    //.pipe(terser())
+    .pipe(rollup({}, { globals: { "reveal.js": "Reveal" } }))
+    .pipe(terser())
     .pipe(sourcemaps.write("."))
     .pipe(dest(DEST));
 
+const plugin_stylesheets = () =>
+  src(`${SRC}/plugin/*/*.{css,scss}`)
+    .pipe(sourcemaps.init())
+    .pipe(
+      sass({
+        outputStyle: "compressed",
+      })
+    )
+    .pipe(sourcemaps.write("."))
+    .pipe(dest(DEST));
+
+export const plugins = parallel(plugin_code, plugin_stylesheets);
+
 export const build = series(
   clean,
   parallel(misc, images, code, plugins, stylesheets, themes, highlightjs_themes)
@@ -122,4 +135,9 @@ const archive = () =>
 
 export const zip = series(build, archive);
 
+const watch_themes = () => watch(`${SRC}/css/theme/source/**/*.scss`, themes);
+const watch_plugins = () => watch(`${SRC}/plugin/**`, plugins);
+
+export const dev = parallel(watch_themes, watch_plugins);
+
 export default build;
diff --git a/lib/rollup.js b/lib/rollup.js
index 4a729ac..1884ed3 100644
--- a/lib/rollup.js
+++ b/lib/rollup.js
@@ -15,7 +15,7 @@ const DEFAULT_INPUT_OPTIONS = {
 };
 
 const DEFAULT_OUTPUT_OPTIONS = {
-  format: "umd",
+  format: "iife",
 };
 
 const onwarn = (input) => {
@@ -35,43 +35,52 @@ export default function (inputOptions = {}, outputOptions) {
   const outOpts = { ...DEFAULT_OUTPUT_OPTIONS, ...outputOptions };
 
   return obj(
-    callbackify(async function (input) {
-      try {
-        const bundle = await rollup({
-          ...inOpts,
-          input: input.path,
-          onwarn: onwarn(input),
-        });
-
-        const { output } = await bundle.generate({
-          ...outOpts,
-          sourcemap: !!input.sourceMap,
-        });
+    callbackify(
+      /**
+       * @param {File} input
+       */
+      async function (input) {
+        if (input.extname !== ".js") {
+          this.push(input);
+          return;
+        }
+        try {
+          const bundle = await rollup({
+            ...inOpts,
+            input: input.path,
+            onwarn: onwarn(input),
+          });
 
-        for (const chunk of output) {
-          const fileChunk = new File({
-            base: input.base,
-            path: input.path,
-            history: input.history,
+          const { output } = await bundle.generate({
+            ...outOpts,
+            sourcemap: !!input.sourceMap,
           });
-          fileChunk.sourceMap = input.sourceMap;
-          fileChunk.basename = chunk.fileName;
-          if (input.sourceMap && chunk.map) {
-            applySourceMap(fileChunk, chunk.map);
-          }
-          switch (chunk.type) {
-            case "chunk":
-              fileChunk.contents = Buffer.from(chunk.code);
-              break;
-            case "asset":
-              fileChunk.contents = Buffer.from(chunk.source);
-              break;
+
+          for (const chunk of output) {
+            const fileChunk = new File({
+              base: input.base,
+              path: input.path,
+              history: input.history,
+            });
+            fileChunk.sourceMap = input.sourceMap;
+            fileChunk.basename = chunk.fileName;
+            if (input.sourceMap && chunk.map) {
+              applySourceMap(fileChunk, chunk.map);
+            }
+            switch (chunk.type) {
+              case "chunk":
+                fileChunk.contents = Buffer.from(chunk.code);
+                break;
+              case "asset":
+                fileChunk.contents = Buffer.from(chunk.source);
+                break;
+            }
+            this.push(fileChunk);
           }
-          this.push(fileChunk);
+        } catch (error) {
+          throw new PluginError(PLUGIN_NAME, error);
         }
-      } catch (error) {
-        throw new PluginError(PLUGIN_NAME, error);
       }
-    })
+    )
   );
 }
diff --git a/package.json b/package.json
index 48fd582..c2e35ac 100644
--- a/package.json
+++ b/package.json
@@ -83,7 +83,17 @@
           "ignoreCase": true
         }
       ]
-    }
+    },
+    "overrides": [
+      {
+        "files": [
+          "src/plugin/**/*.js"
+        ],
+        "globals": {
+          "Reveal": "readonly"
+        }
+      }
+    ]
   },
   "pretiter:": {
     "printWidth": 80
diff --git a/src/plugin/mermaid/index.js b/src/plugin/mermaid/index.js
index 5e0de04..34baa12 100644
--- a/src/plugin/mermaid/index.js
+++ b/src/plugin/mermaid/index.js
@@ -1,3 +1,64 @@
 import mermaid from "mermaid/dist/mermaid";
 
-mermaid;
+class MermaidPlugin {
+  init() {
+    Reveal.addEventListener("slidechanged", (event) =>
+      this.onSlideChanged(event)
+    );
+    this.serial = 0;
+    mermaid.initialize({ startOnLoad: false, theme: "neutral" });
+
+    this.processSlide(Reveal.getCurrentSlide());
+  }
+
+  /**
+   *
+   * @param {{ currentSlide: HTMLElement }} param0
+   */
+  onSlideChanged({ currentSlide }) {
+    this.processSlide(currentSlide);
+  }
+
+  /**
+   *
+   * @param {HTMLElement} slide
+   */
+  async processSlide(slide) {
+    const graphs = [];
+    for (const graph of slide.querySelectorAll("pre.mermaid")) {
+      const prom = this.renderGraph(graph);
+      if (prom) {
+        graphs.push(prom);
+      }
+    }
+    await Promise.all(graphs);
+    Reveal.layout();
+  }
+
+  /**
+   * @param {HTMLElement} element
+   * @return {Promise<boolean>|null}
+   */
+  renderGraph(element) {
+    if (element.hasAttribute("data-processed")) {
+      return null;
+    }
+    return new Promise((resolve, reject) => {
+      try {
+        mermaid.render(
+          `__mermaid${+this.serial}`,
+          element.textContent,
+          (svgCode) => {
+            element.innerHTML = svgCode;
+            element.setAttribute("data-processed", true);
+            resolve(true);
+          }
+        );
+      } catch (error) {
+        reject(error);
+      }
+    });
+  }
+}
+
+Reveal.registerPlugin("mermaid", new MermaidPlugin());
diff --git a/src/plugin/mermaid/theme.scss b/src/plugin/mermaid/theme.scss
new file mode 100644
index 0000000..9073a15
--- /dev/null
+++ b/src/plugin/mermaid/theme.scss
@@ -0,0 +1,11 @@
+
+pre.mermaid {
+  background: none;
+  border: none;
+
+  * {
+    font-family: "Avenir Next LT Pro Condensed", Helvetica, sans-serif;
+    font-size: 13pt;
+    line-height: 1em;
+  }
+}
-- 
GitLab