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
72.75k stars 6.64k forks source link

vdots hline array{c|c} (vertical lines) do not render #5424

Open FieryRMS opened 8 months ago

FieryRMS commented 8 months ago

Description

the \vdots \hline \array{c|c} from KaTeX does not render in mermaid.

Steps to reproduce

  1. add code to the editor
  2. output does not include horizontal lines, vertical lines or vdots.

Screenshots

working on KaTeX

Code Sample

flowchart TD
   A["$$\begin{array}{c|c} a & b \\ \hline c & d \\ \dots & \vdots \\ \end{array}$$"]

Setup

Suggested Solutions

No response

Additional Context

Output is different on Firefox. The vertical and horizontal lines show but the vdots is still missing

FieryRMS commented 8 months ago

One of the issues is caused by DOMPurify sanitizing the mi tags. Apparently, its removing everything inside the outer mi. In this example,

<mi><mi mathvariant="normal">⋮</mi><mpadded height="0em" voffset="0em"><mspace mathbackground="black" width="0em" height="1.5em"></mspace></mpadded></mi>

is reduced to just

<mi></mi>

So the vdots disappear.

Related https://github.com/cure53/DOMPurify/issues/847

I have not yet looked into the vertical and horizontal lines yet.

FieryRMS commented 8 months ago

https://github.com/cure53/DOMPurify/issues/673 It looks like a lot more tags are being removed by DOMPurify, although, I don't think there is much effect on the final render of it. I still couldn't figure out why the rendering of the lines are different for Chrome and Firefox, even though the html output is the same. My guess is that Chrome does not yet support it.

Solution

My suggestion would be to use config.legacyMathML instead of isMathMLSupported() for choosing rendering output.

https://github.com/mermaid-js/mermaid/blob/8e95c4db55c10b152e262d6fb271415f86f616d6/packages/mermaid/src/diagrams/common/common.ts#L356-L361

would become,

 katex 
   .renderToString(c, { 
     throwOnError: true, 
     displayMode: true, 
     output: !config.legacyMathML ? 'mathml' : 'htmlAndMathml', 
   }) 

After doing so, the rendering issues are fixed (after also including the KaTeX css as well)

Below picture is my testing on Chrome.

image

The drawback of this would be if the user instead wanted fallback to htmlAndMathml, it wouldn't work. Perhaps we can expose isMathMLSupported() to the user and let them decide?

Or maybe that's not necessary either, since if they wish to support legacy, they will include the css, and at that point its just better to use the legacy to maintain a consistent output on all the platforms.

Alternative (partial) solution

I tried to add a DOMPurify hook, and if an mi element had children, delete it and add it to the parent. It works, but not optimal.

DOMPurify.addHook('uponSanitizeElement', (node: Element) => {
    if (node.localName === 'mi' && node.childElementCount > 0) {
      const parent = node.parentElement;
      if (!parent) {
        return;
      }
      node.childNodes.forEach((child) => {
        parent.insertBefore(child, node);
      });
      parent.removeChild(node);
    }
  });

Chrome Chrome

Firefox Firefox

image

The dots are very obviously different and there is some weird spacing issues only on Chrome. This, however, does not address the issue of the invisible lines.

Let me know if you'd like me to make a PR.