remcohaszing / rehype-mermaid

A rehype plugin to render mermaid diagrams
MIT License
68 stars 8 forks source link

Improvement: option to remove inline-svg style block #7

Closed Caellian closed 7 months ago

Caellian commented 7 months ago

Theme css is inserted in the diagram svg even after running the plugin with the following settings:

unified()
//...
.use(rehypeMermaid, {
        mermaidConfig: {
            theme: null,
        }
    })
//...

I'm getting around this by running the following transformer at the moment:

visit(tree, "element", (style, i, svg) => {
            if (style.tagName !== "style") {
                return SKIP;
            }
            if (svg.tagName !== "svg") {
                return SKIP;
            }
            let id = svg.properties?.id;
            if (id == null || !id.startsWith("mermaid-")) {
                return SKIP;
            }

            svg.splice(i, 1);
        });

It would be nice if the plugin detected null or "null" theme value and then ran that piece of code on the inserted children in order to allow processors to use their own styles.

remcohaszing commented 7 months ago

I don’t understand what you mean. Can you elaborate?

Caellian commented 7 months ago

I updated the initial comment.

stereobooster commented 7 months ago

@Caellian hey 👋 . I have a question - do you intend to inline SVGs in HTML and later style them with your own styles? And if yes, does it mean it would be possible to create styles for light and dark themes in CSS (without changing HTML contents)?

Caellian commented 7 months ago

@Caellian hey 👋 . I have a question - do you intend to inline SVGs in HTML and later style them with your own styles? And if yes, does it mean it would be possible to create styles for light and dark themes in CSS (without changing HTML contents)?

Yes, yes, depends.

Styles in mermaid are defined in /packages/mermaid/src/diagrams/class/styles.js files. I'm running a rehype from a static context in Node so I can (worst case) glob diagram types, append /styles.js and then use dynamic imports.

Diagram types can be detected using detectors in /packages/mermaid/src/diagrams/sankey/sankeyDetector.ts.

Now, it's questionable whether I'll be able to use mermaid directly or I'll have to handle these on a case-by-case basis (which is fine; 5min of work per diagram type).

I have a [data-scheme="dark"] on my document body so I can run all detectors until I find which diagram I'm visiting, replace the id with a class ("diagram flowchart-v2") and then generate selectors for each.

My use case can't break in "production" as the page won't get published if my logic fails because some diagram isn't properly handled (i.e. got updated), I don't suggest this approach to be used when running unified dynamically though because it will silently fail - in my case, all the content that's ever processed acts as a conformance test so I know about edge cases up front.

I'll mention you if I get it to work.

remcohaszing commented 7 months ago

There is no such thing as a null theme. The theme affects layout the generated diagram, including colors, font, borders, spacing, etc.

If I understand correctly, you are asking for an option that removes the <style> element in the diagram after processing. However, this relies on an implementation detail. Mermaid adds some styling via the <style> tag. Some style is inlined in style attributes. Other styling happens via attributes.

I don’t want to add an option to postprocess the SVG. It has proven to be fragile in the past. If you really need to, you can use a custom rehype plugin to do so.

If I don’t understand correctly and you want something else, please elaborate with an example showing input and output, for example based on one of the test fixtures in this repository.

Caellian commented 7 months ago

Inlined styles are only used by layouting and generator and shouldn't be changed, i.e. styling (as in colors, fonts, backgrounds, ...) is done entirely through the css. The only information that's inserted directly into attributes is stuff like "stroke-dasharray" where it's important for semantics of the drawn graph that the stroke is dashed (for instance). In other words, it's entirely possible to recolor the graph by replacing the old <style> with a new one.

If you run the graph through svgo (like you said you did), then svgo will likely break things, but generating a <style> should be lossless and work AFAICT.

It's possibly (probably) out of scope though and should be submitted to mermaid.js directly though.

remcohaszing commented 7 months ago

I appreciate the suggestion, but I’m not convinced this really adds value. Also it’s relatively simple to remove the <style> element using a custom rehype plugin that runs after this one.