mermaid-js / mermaid

Generation of diagrams like flowcharts or sequence diagrams from text in a similar manner as markdown
https://mermaid.js.org
MIT License
70.49k stars 6.3k forks source link

Proposal: a diagram registration system #1385

Closed hikerpig closed 11 months ago

hikerpig commented 4 years ago

This is a feature request and discussion of mermaid's project structure.

As mermaid is growing to be more and more versatile, and there are various diagram type requests coming up, I think a plugin-like API for diagram registration system would be helpful.

Why would we need it

Currently if I want to add a new type of diagram to mermaid, I will have to add some switch cases (e.g. to render function) to existing code, and compiles the whole library (which is version 8.5, is 824.7 kB minified, according to bundlephobia) all over again.

But based on the fact that different types of diagrams:

  1. have no shared state
  2. can be detected easily by starting string, as in detectType(text) function

A separation of mermaid core and various diagrams would make it easier to add customized diagrams. Developers can develop them in separate projects, and users can import them as plugins. For example:

<script src="//cdn.jsdelivr.net/npm/mermaid@8.5.0/dist/mermaid.min.js"></script>
<script src="path/to/mermaid-diagram-mindmap.js"></script>

API draft

From what I saw in the codebase, I think a simple and rough example below is good to start with:

mermaid.registerDiagram('sequenceDiagram', {
  pattern: /^\s*sequenceDiagram/
  parser: sequenceParser,
  renderer: sequenceRenderer,
  db: sequenceDb,
  configKey: 'sequenceDiagram',
  setConfig,
  ...
})

And the detectType function should be converted to something like:

function detectDiagram(text) {
  let diagram = registeredDiagrams['flowchart'] // default
  for (const d of Object.values(registeredDiagrams) {
    if (d.pattern.test(text)) {
      diagram = d
      break
    }
  }
  return diagram
}
spopida commented 4 years ago

I can see the motivation for this...updating case statements is usually an indication that something more elegant is possible. Some brief thoughts:

knsv commented 4 years ago

I agree with the gist of this. The root problem is the bundle size, diagram registration is one way of mitigating this.

Currently 80% of the bundle size is made up of lodash and d3. lodash is easy to remove, we should do that, d3 not so easy. But we can minimize d3 use by removing statements like this

import * as d3 from 'd3';

I think these two first steps should be made before the plugin architecture. However, a suspicion of mine is that most diagrams hardly use d3 much but the gantt chart for instance does. Meaning the size cost for gantt is high and if you are not at all interested in gantts yo could save space with this plugin architecture.

One feature and possible success factor of mermaid has been that is easy to get going. Pop in the mermaid.min.js bundle and start putting in divs with diagrams. It would be important to try to keep a really simple option.

(See issues #1389 and #1390)

hikerpig commented 4 years ago

It would be important to try to keep a really simple option.

@knsv We should definitely keep the change transparent to end users.

My proposal is initially more about developing experience.

One even further and wilder thought, If mermaid would export a generalized graph-layouter/renderer, which accepts data that accord with a specification (maybe something like Vega marks, but without all the reactive and interaction related features), new diagram implementions would be even ligther and easier.

sidharthv96 commented 11 months ago

We now support external diagram registration. 🚀

https://mermaid.js.org/syntax/zenuml.html#integrating-with-your-library-website

import mermaid from 'url/mermaid';
import diagram from 'url/diagram';

mermaid.registerExternalDiagrams([diagram]);