Redocly / redoc

📘 OpenAPI/Swagger-generated API Reference Documentation
https://redocly.github.io/redoc/
MIT License
22.91k stars 2.27k forks source link

Draw diagrams from markdown within ReDoc page #266

Open avkonst opened 7 years ago

avkonst commented 7 years ago

I have discovered needs to embed various diagrams within the documentation page rendered by the ReDoc. Currently I generate pictures from PlantUML text and hope to refer to these pictures from the markdown text embedded within the swagger specification, provided to the ReDoc. The problem is that the pictures need to be saved and served from somewhere and could get dis-synchronized with the documentation eventually, because the documentation content ends up in different places.

Instead, it would be great to have a way to render diagrams within the ReDoc page from markdown text embedded within the swagger specification. Something similar to this: http://support.typora.io/Draw-Diagrams-With-Markdown/

Is it valid idea? or I am taking some non-advised approach? If valid, would this feature be possible for implementation?

avkonst commented 7 years ago

The last diagram example on this page http://jumly.tmtk.net/ is sort of what diagrams I am trying to draw..

RomanHotsiy commented 7 years ago

@avkonst thanks for this feature request. But I'm not sure if this should be the part of ReDoc core. My concerns are following:

But I see your use case and I have an idea of how we can cover it: ReDoc can have an option called markdownCompiler or a set of hooks before/afterMarkdownRender so you can add any diagram rendering engine you want + it won't be limited to diagram generation. It can be even packed in something like ReDoc plugin 🎁 😀

What do you think?

avkonst commented 7 years ago

Hi,

Thanks for the proposal. Maybe hooks/plugins is good feature to have, keep this in mind, but I am not very much dependent on this now. I have solved the problem by inserting a picture link into markdown, and the picture link points out to my backend which generates pictures from text. It allowed me to write documentation in separate markdown editor and still have pictures in preview in the editor. I have not tried it yet to deploy to ReDoc, but as long as the markdown renderer you use in ReDoc can insert SVG and PNG pictures, it should be all good as it is now.

Thanks

webwurst commented 7 years ago

Sounds good, I would vote for a plugin for mermaid :)

foriequal0 commented 4 years ago

For those who want mermaid anyway, I've made a hacky way to render it.

    mermaid.initialize({startOnLoad: false});
    let id = 0;
    Redoc.init(url, {
        ...configs,
        theme: {
            extensionsHook: (name, props) => {
                if (name !== "Markdown" || props.html === undefined) return "";
                var markdown = document.createElement("div");
                markdown.innerHTML = props.html;
                var mermaidNodes = markdown.querySelectorAll("pre > code.language-mermaid");
                for (const mermaidNode of mermaidNodes) {
                    mermaid.render(`mermaid-${id++}`, mermaidNode.textContent, svg => {
                        mermaidNode.parentNode.outerHTML = svg;
                    });
                }
                props.dangerouslySetInnerHTML.__html = markdown.innerHTML;

                return "";
            }
        }
    }, container);
dcopso commented 2 years ago

If you're generating static docs using redoc-cli build, here are the changes to the template file that must be made for mermaid diagrams to be rendered (tested with OpenAPI 3.0.3 spec on redoc-cli 0.13.13):

  1. Add the following code snippet to <head>:
    <script src="https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.min.js"></script>
    <script>
        mermaid.initialize({startOnLoad: true});
    </script>
  2. Add the following snippet between {{redocHTML}} and </body>:
    <script>
    let renderedMermaidId = 0;
    const nextId = () => {
        renderedMermaidId++;
        return renderedMermaidId;
    };
    const renderMermaidDiagrams = () => {
        let mermaidNodes = document.querySelectorAll("pre > code.language-mermaid");
        for (const nv of mermaidNodes) {
            let nextIdz = `mermaid-${nextId()}`;
            let codz = nv.textContent;
            mermaid.render(nextIdz, codz, svg => nv.parentNode.outerHTML = svg)
        }
    };
    renderMermaidDiagrams();
    </script>
  3. Invoke build:
    npx redoc-cli build -t template.hbs myapi.yaml
Gyunikuchan commented 10 months ago

With Mermaid v10's breaking change and its dependence on async/await, I've only been able to get it to work by waiting for Redoc to finish rendering. https://github.com/mermaid-js/mermaid/releases/tag/v10.0.0 Does anyone know of a better way to implement this?

<body>
<div id="redoc"></div>

<script src="https://cdn.jsdelivr.net/npm/redoc@next/bundles/redoc.standalone.js"></script>
<script type="module">
    import mermaid from "https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs";
    mermaid.initialize({ startOnLoad: true });

    Redoc.init("./docs/swagger.json", {}, document.getElementById("redoc"), async () => {
        let id = 0;
        const mermaidNodes = document.getElementById("redoc").querySelectorAll("pre > code.language-mermaid");
        for (const mermaidNode of mermaidNodes) {
            const { svg } = await mermaid.render(`mermaid-${id++}`, mermaidNode.textContent);
            mermaidNode.parentNode.outerHTML = svg;
        }
    });
</script>
</body>