Rand Stats

WWW::MermaidInk

zef:antononcube

WWW::MermaidInk Raku package

The function mermaid-ink of the Raku package "WWW::MermaidInk" gets images corresponding to Mermaid-js specifications via the web Mermaid-ink interface of Mermaid-js.

For a "full set" of examples see the file MermaidInk_woven.html.


Usage

use WWW::MermaidInk
loads the package.

mermaid-ink($spec)
retrieves an image defined by the spec $spec from Mermaid's Ink Web interface.

mermaid-ink($spec format => 'md-image')
returns a string that is a Markdown image specification in Base64 format.

mermaid-ink($spec format => 'md-url')
returns a string that is a Markdown image link specification.

mermaid-ink($spec format => 'svg')
returns a string that is a Scalable Vector Graphics (SVG) code.

mermaid-ink($spec format => 'hash')
returns a Hash object (the result of HTTP::Tiny.get.)

mermaid-ink($spec file => fileName)
exports the retrieved image into a specified PNG file.

mermaid-ink($spec file => Whatever)
exports the retrieved image into the file $*CMD ~ /out.png.

Details & Options


Examples

Basic Examples

Generate a flowchart from a Mermaid specification:

use WWW::MermaidInk;

'graph TD 
   WL --> |ZMQ|Python --> |ZMQ|WL' 
 ==> mermaid-ink(format=>'md-url')

Create a Markdown image expression from a class diagram:

my $spec = q:to/END/;
classDiagram
    Animal <|-- Duck
    Animal <|-- Fish
    Animal <|-- Zebra
    Animal : +int age
    Animal : +String gender
    Animal: +isMammal()
    Animal: +mate()
    class Duck{
        +String beakColor
        +swim()
        +quack()
    }
    class Fish{
        -int sizeInFeet
        -canEat()
    }
    class Zebra{
        +bool is_wild
        +run()
    }
END

mermaid-ink($spec, format=>'md-url')    

Scope

The first argument can be a list of pairs -- the corresponding Mermaid-js graph is produced. Here are the edges of directed graph:

my @edges = ['1' => '3', '3' => '1', '1' => '4', '2' => '3', '2' => '4', '3' => '4'];

[1 => 3 3 => 1 1 => 4 2 => 3 2 => 4 3 => 4]

Here is the corresponding mermaid-js image:

mermaid-ink(@edges, format=>'md-url')

Scalable Vector Graphics (SVG) code can be generated with format => 'svg':

mermaid-ink(@edges, format=>'svg')
# <svg id="mermaid-svg" width="100%" xmlns="http://www.w3.org/2000/svg" style="max-width: 124.205px; background-color: rgb(255, 255, 255);" viewBox="-9.423566102981567 -8 124.20481872558594 218" role="graphics-document document" aria-roledescription="flowchart-v2" xmlns:xlink="http://www.w3.org/1999/xlink"><style>#mermaid-svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg .error-icon{fill:#552222;}#mermaid-svg .error-text{fill:#552222;stroke:#552222;}#mermaid-svg .edge-thickness-normal{stroke-width:2px;}#mermaid-svg .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg .marker{fill:#333333;stroke:#333333;}#mermaid-svg .marker.cross{stroke:#333333;}#mermaid-svg svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg .cluster-label text{fill:#333;}#mermaid-svg .cluster-label span,#mermaid-svg p{color:#333;}#mermaid-svg .label text,#mermaid-svg span,#mermaid-svg p{fill:#333;color:#333;}#mermaid-svg .node rect,#mermaid-svg .node circle,#mermaid-svg .node ellipse,#mermaid-svg .node polygon,#mermaid-svg .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg .flowchart-label text{text-anchor:middle;}#mermaid-svg .node .label{text-align:center;}#mermaid-svg .node.clickable{cursor:pointer;}#mermaid-svg .arrowheadPath{fill:#333333;}#mermaid-svg .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg .cluster text{fill:#333;}#mermaid-svg .cluster span,#mermaid-svg p{color:#333;}#mermaid-svg div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}</style><g><marker id="mermaid-svg_flowchart-pointEnd" class="marker flowchart" viewBox="0 0 10 10" refX="6" refY="5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"></path></marker><marker id="mermaid-svg_flowchart-pointStart" class="marker flowchart" viewBox="0 0 10 10" refX="4.5" refY="5" markerUnits="userSpaceOnUse" markerWidth="12" markerHeight="12" orient="auto"><path d="M 0 5 L 10 10 L 10 0 z" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"></path></marker><marker id="mermaid-svg_flowchart-circleEnd" class="marker flowchart" viewBox="0 0 10 10" refX="11" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"></circle></marker><marker id="mermaid-svg_flowchart-circleStart" class="marker flowchart" viewBox="0 0 10 10" refX="-1" refY="5" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><circle cx="5" cy="5" r="5" class="arrowMarkerPath" style="stroke-width: 1; stroke-dasharray: 1, 0;"></circle></marker><marker id="mermaid-svg_flowchart-crossEnd" class="marker cross flowchart" viewBox="0 0 11 11" refX="12" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"></path></marker><marker id="mermaid-svg_flowchart-crossStart" class="marker cross flowchart" viewBox="0 0 11 11" refX="-1" refY="5.2" markerUnits="userSpaceOnUse" markerWidth="11" markerHeight="11" orient="auto"><path d="M 1,1 l 9,9 M 10,1 l -9,9" class="arrowMarkerPath" style="stroke-width: 2; stroke-dasharray: 1, 0;"></path></marker><g class="root"><g class="clusters"></g><g class="edgePaths"><path d="M3.6,34L1.616,38.167C-0.368,42.333,-4.336,50.667,2.099,60.135C8.534,69.604,25.372,80.207,33.791,85.509L42.21,90.811" id="L-1-3-0" class=" edge-thickness-normal edge-pattern-solid flowchart-link LS-1 LE-3" style="fill:none;" marker-end="url(#mermaid-svg_flowchart-pointEnd)"></path><path d="M52.988,84L51.664,79.833C50.34,75.667,47.691,67.333,43.308,59.313C38.924,51.294,32.805,43.587,29.746,39.734L26.686,35.881" id="L-3-1-0" class=" edge-thickness-normal edge-pattern-solid flowchart-link LS-3 LE-1" style="fill:none;" marker-end="url(#mermaid-svg_flowchart-pointEnd)"></path><path d="M11.695,34L11.695,38.167C11.695,42.333,11.695,50.667,11.695,61.833C11.695,73,11.695,87,11.695,101C11.695,115,11.695,129,14.755,139.853C17.814,150.706,23.933,158.413,26.993,162.266L30.052,166.119" id="L-1-4-0" class=" edge-thickness-normal edge-pattern-solid flowchart-link LS-1 LE-4" style="fill:none;" marker-end="url(#mermaid-svg_flowchart-pointEnd)"></path><path d="M85.636,34L83.319,38.167C81.003,42.333,76.371,50.667,72.998,58.158C69.625,65.65,67.512,72.299,66.455,75.624L65.398,78.949" id="L-2-3-0" class=" edge-thickness-normal edge-pattern-solid flowchart-link LS-2 LE-3" style="fill:none;" marker-end="url(#mermaid-svg_flowchart-pointEnd)"></path><path d="M99.134,34L100.126,38.167C101.118,42.333,103.102,50.667,104.094,61.833C105.086,73,105.086,87,105.086,101C105.086,115,105.086,129,97.752,141.13C90.418,153.26,75.749,163.521,68.415,168.651L61.081,173.781" id="L-2-4-0" class=" edge-thickness-normal edge-pattern-solid flowchart-link LS-2 LE-4" style="fill:none;" marker-end="url(#mermaid-svg_flowchart-pointEnd)"></path><path d="M58.391,118L58.391,122.167C58.391,126.333,58.391,134.667,57.334,142.158C56.277,149.65,54.164,156.299,53.107,159.624L52.051,162.949" id="L-3-4-0" class=" edge-thickness-normal edge-pattern-solid flowchart-link LS-3 LE-4" style="fill:none;" marker-end="url(#mermaid-svg_flowchart-pointEnd)"></path></g><g class="edgeLabels"><g class="edgeLabel"><g class="label" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g><g class="edgeLabel"><g class="label" transform="translate(0, 0)"><foreignObject width="0" height="0"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="edgeLabel"></span></div></foreignObject></g></g></g><g class="nodes"><g class="node default default flowchart-label" id="flowchart-1-0" transform="translate(11.6953125, 17)"><rect class="basic label-container" style="" rx="0" ry="0" x="-11.6953125" y="-17" width="23.390625" height="34"></rect><g class="label" style="" transform="translate(-4.1953125, -9.5)"><rect></rect><foreignObject width="8.390625" height="19"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">1</span></div></foreignObject></g></g><g class="node default default flowchart-label" id="flowchart-2-6" transform="translate(95.0859375, 17)"><rect class="basic label-container" style="" rx="0" ry="0" x="-11.6953125" y="-17" width="23.390625" height="34"></rect><g class="label" style="" transform="translate(-4.1953125, -9.5)"><rect></rect><foreignObject width="8.390625" height="19"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">2</span></div></foreignObject></g></g><g class="node default default flowchart-label" id="flowchart-3-1" transform="translate(58.390625, 101)"><rect class="basic label-container" style="" rx="0" ry="0" x="-11.6953125" y="-17" width="23.390625" height="34"></rect><g class="label" style="" transform="translate(-4.1953125, -9.5)"><rect></rect><foreignObject width="8.390625" height="19"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">3</span></div></foreignObject></g></g><g class="node default default flowchart-label" id="flowchart-4-5" transform="translate(45.04296875, 185)"><rect class="basic label-container" style="" rx="0" ry="0" x="-11.6953125" y="-17" width="23.390625" height="34"></rect><g class="label" style="" transform="translate(-4.1953125, -9.5)"><rect></rect><foreignObject width="8.390625" height="19"><div xmlns="http://www.w3.org/1999/xhtml" style="display: inline-block; white-space: nowrap;"><span class="nodeLabel">4</span></div></foreignObject></g></g></g></g></g><style>@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css");</style></svg>

Options

When format => 'svg' and subdomain => Whatever, then subdomain is automatically determined to be "svg". The argument subdomain can take the values "base64", "hash", "md-image", "md-url", "svg", Whatever.

Background color can be specified with the optional argument background.

Here is an example of using "md-url" as a format and background "Cornsilk":

'graph LR
   CompSci[Computational Science] --> Physics
   CompSci --> Math[Mathematics]
   Physics --> Philosophy 
   Math --> Philosophy'
 ==> mermaid-ink(format=>'md-url', background=>'Cornsilk') 


Command Line Interface (CLI)

The package provides the CLI script mermaid-ink. Here is its help message:

mermaid-ink --help
# Usage:
#   mermaid-ink <spec> [-o|--file=<Str>] [--format=<Str>] -- Diagram image for Mermaid-JS spec (via mermaid.ink).
#   mermaid-ink [<words> ...] [-o|--file=<Str>] [--format=<Str>] -- Command given as a sequence of words.
#   
#     <spec>             Mermaid-JS spec.
#     -o|--file=<Str>    File to export the image to. [default: '']
#     --format=<Str>     Format of the result; one of "asis", "base64", "md-image", or "none". [default: 'md-image']

Flowchart

This flowchart summarizes the execution path of obtaining Mermaid images in a Markdown document:

graph TD
    UI[/User input/]
    MS{{Mermaid-ink server}}
    Raku{{Raku}}
    MDnb>Markdown document]
    MDIC[[Input cell]]
    MDOC[[Output cell]]
    MI[mermaid-ink]
    TCP[[Text::CodeProcessing]]
    UI --> MDIC -.- MDnb
    MDIC --> MI -.- TCP
    MI --> |spec|MS
    MS --> |image|MI
    MI --> MDOC -.- MDnb
    MDnb -.- TCP -.- Raku

References

Articles

[AA1] Anton Antonov, "Interactive Mermaid diagrams generation via Markdown evaluation", (2022), RakuForPrediction at WordPress.

Functions and packages

[AAf1] Anton Antonov, MermaidInk Mathematica resource function, (2022-2023), Wolfram Function Repository.

Mermaid resources