Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server-side rendering #7

Open
connelhooley opened this issue Jun 2, 2024 · 1 comment
Open

Server-side rendering #7

connelhooley opened this issue Jun 2, 2024 · 1 comment
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@connelhooley
Copy link

Hi

I noticed in the future ideas section of the readme it mentioned "generate SVG server-side during build". I've been playing around with 11ty and I'm not sure if I'm going to continue with it but thought I'd share how I got server side rendering working in a prototype.

It uses the mermaid-cli. The CLI in turn uses a puppeteer instance as mermaid requires a browser to render.

import { renderMermaid } from "@mermaid-js/mermaid-cli";
import puppeteer from "puppeteer";

export const mermaidPlugin = (eleventyConfig, options) => {
  let browser;
  eleventyConfig.on("eleventy.before", async () => {
    if (!browser) {
      browser = await puppeteer.launch({headless: "new"});
    };
  });
  eleventyConfig.on("eleventy.after", async () => {
    if (browser) {
      browser.close();
      browser = undefined;
    }
  });

  eleventyConfig.htmlTransformer.addPosthtmlPlugin("html", () => {
    return async (tree) => {
      const transformTag = async (node) => {
        let content;
        if (Array.isArray(node.content)) {
          content = node.content.join("");
        } else {
          content = node.content;
        }
        const { data } = await renderMermaid(browser, content, "svg", {
          mermaidConfig: options.mermaidConfig,
        });
        const htmlString = data.toString();
        node.tag = false;
        node.content = tree.parser(htmlString);
      };  
      const promises = [];
      tree.match({ tag: "pre", attrs: { class: "mermaid" } }, node => {
        promises.push(transformTag(node));
        return node;
      });  
      await Promise.all(promises);
      return tree;
    };
  });
};

It's probably very unperformant but appears to work. Usage would be like this:

eleventyConfig.addPlugin(mermaidPlugin, {
  mermaidConfig: {
    theme: "base",
    themeVariables: {
      primaryColor: "#BB2528",
      primaryTextColor: "#fff",
      primaryBorderColor: "#7C0000",
      lineColor: "#F8B229",
      secondaryColor: "#006100",
      tertiaryColor: "#fff",
    }
  },
});

It asumes/requires you have set up the syntax highlighter to ignore mermaid code blocks and instead return a <pre class="mermaid"> tag, like you already do here.

@KevinGimbel
Copy link
Owner

Wow, thanks a lot!
This is a great starting point to get this feature going, if I find the time I'll give it a try!

Some questions I have (for myself):

Can puppeteer and mermaid-cli be hidden behind a feature flag?
Don't want to pull in big dependencies unless people wanna use them.

Split plugin into browser and ssr?
Maybe it makes sense to create a new plugin which implements the SSR. This plugin could re-use the existing plugin as dependency, people who want SSR can then use the SSR plugin.

@KevinGimbel KevinGimbel added enhancement New feature or request help wanted Extra attention is needed labels Jun 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

No branches or pull requests

2 participants