yuzutech / kroki

Creates diagrams from textual descriptions!
https://kroki.io
MIT License
2.79k stars 206 forks source link

MermaidJS: Suppress using HTML tags in SVG documents #1410

Open ghost opened 1 year ago

ghost commented 1 year ago

MermaidJS, by default, uses tags that only render inside of web browsers (foreignObject and div). A number of issues have been logged against MermaidJS to address this problem:

Issue 2688 recommends:

{
    "flowchart": {
        "htmlLabels": "false"
    }
}

What would be involved in revising Kroki to configure MermaidJS to avoid using HTML tags for all diagrams so as to generate more conformant SVG documents?

KeenWrite invokes Kroki using an HTTP GET request, so ideally the server could be configured to set htmlLabels to false, which would then allow KeenWrite to display the SVG files without modification:

https://github.com/DaveJarvis/keenwrite/blob/6fa925d27bbec807fc4419454aa81941524f889f/src/main/java/com/keenwrite/preview/DiagramUrlGenerator.java#L26

Alternatively, it looks like Kroki supports HTTP GET URL parameters for setting options:

https://docs.kroki.io/kroki/setup/usage/#_options

See also:

ggrossetie commented 1 year ago

Kroki supports diagram options: https://docs.kroki.io/kroki/setup/usage/#_options

Currently, the gateway server calls the mermaid companion container with the diagram options but the mermaid service does not use them.

We are using the following default Mermaid configuration: https://github.com/yuzutech/kroki/blob/main/mermaid/src/task.js

So what we need to do is:

  1. establish a naming convention for Mermaid configuration (since they are using nested name)
  2. establish a convention to infer the type of the value (array, boolean, number...)
  3. get the diagram options from the query parameters in: https://github.com/yuzutech/kroki/blob/main/mermaid/src/index.js#L12
  4. merge the configuration with the default configuration: https://github.com/yuzutech/kroki/blob/main/mermaid/src/task.js

As a workaround, I think you can use a directive:

%%{ init: { "flowchart": { "htmlLabels": false } }%%

https://mermaid-js.github.io/mermaid/#/./directives?id=declaring-directives

As a side note, I'm leaning toward HTTP headers (rather than query parameters) to send diagram options to a companion container:

https://github.com/yuzutech/kroki/blob/f953fcf117053ea00c47d45caec5bb3b5ad897d4/server/src/main/java/io/kroki/server/action/Delegator.java#L33-L37

ghost commented 1 year ago

As a side note, I'm leaning toward HTTP headers (rather than query parameters) to send diagram options to a companion container:

Would those get censored by aggressive (corporate) network filters, or possibly trip security traps?

ZScaler can be configured to be pretty restrictive for what it accepts over HTTP(s).

ghost commented 1 year ago

As a workaround, I think you can use a directive: %%{ init: { "flowchart": { "htmlLabels": false } }%%

KeenWrite generates diagrams dynamically. Users can write the following in their documents:

``` diagram-blockdiag
...
```

As well as:

``` diagram-graphviz
...
```

And:

``` diagram-mermaid
...
```

What's great about Kroki's API at the moment is that KeenWrite doesn't have to care about parsing and identifying the type of diagram to send to Kroki. By introducing %%{ init: { "flowchart": { "htmlLabels": false } }%%, does that mean KeenWrite not only has to detect the diagram type (mermaid) but also try to identify the type of MermaidJS diagram being used?

Is there any way we can keep the API simple and have diagrams "just work"? (I'm rather loathe to add diagram-specific parsing and configuration on the client side of Kroki.)

ggrossetie commented 1 year ago

I was referring to the "internal" requests between Kroki containers. We will still support all the options when sending a request to the gateway server.

ghost commented 1 year ago

Here's a sreenshot showing the issue:

https://user-images.githubusercontent.com/2131950/141664461-033423b6-e9ae-4c23-8828-f760b9dde5f6.png

The Preview panel has missing text. A server-side fix would also mean users wouldn't have to upgrade to get the text fixes, which would be pretty cool for a desktop app.

ggrossetie commented 1 year ago

The Preview panel has missing text. A server-side fix would also mean users wouldn't have to upgrade to get the text fixes, which would be pretty cool for a desktop app.

I'm not really sure why Mermaid chose to use htmlLabels to true by default but if you strongly believe it should be false by default then you should make your case upstream.

What we can do in Kroki is allow to pass options to change this default configuration. It means that you will need to pass a query parameter (or an HTTP header) to your GET request. Something like:

GET https://kroki.io/mermaid/svg/abcd1234?flowchart-html-labels=false

Since some configurations seem to be global we could use:

GET https://kroki.io/mermaid/svg/abcd1234?global-html-labels=false
ghost commented 1 year ago

Since some configurations seem to be global we could use:

Does that option get silently ignored for non-Mermaid diagrams? That is, would the following still generate a valid SVG file:

final var server = "kroki.io";
final var diagram = "graphviz";
final var encoded = "...";
final var options = "global-html-labels=false";

http.get( format( "https://%s/%s/svg/%s?%s", server, diagram, encoded, options ) );

If so, then that'd work out quite well. If not, could we add an option to ignore irrelevant/unknown/invalid options? Perhaps:

final var options = "accept-non-applicable=true&global-html-labels=false";