2022-03-03

D3-Graphviz Remark presentations

D3-graphviz is a Javascript library for visualising dot graphs. I have a new theme for my Windows app Remarkpy that allows for displaying these kinds of graphs in a Remark-based presentation.

As an example, I can add to the presentation markdown file a dot diagrams with the following syntax:

    .d3graphviz[
    digraph  {a -> b}
    ]
    

Remarkpy theme

A Remarkpy theme has a well-defined structure, a directory with three files:

  • base.html, which normally doesn't have to be modified.
  • slideshow.html, where most of the customisations are included.
  • theme.md, a default presentation file.

Inside the slideshow.html file I have the following script tags:


    <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.3.0/d3.min.js"></script>
    <script src="https://unpkg.com/@hpcc-js/wasm@0.3.11/dist/index.min.js"></script>
    <script src="https://unpkg.com/d3-graphviz@3.0.5/build/d3-graphviz.js"></script>

    

The @hpcc-js/wasm script provides a compiled WASM version of Graphviz, while the D3 script will load the D3 JavaScript library.

Integrating another Javascript library to a Remark presentation is notoriously tricky and, in this case, it requires some Javascript/jQuery code.

The function below allows more than one dot graph inside a single slide.


    ...
    function D3graphviz(s) {
        const elements = document.querySelectorAll(".remark-slide")[s.getSlideIndex()]
            ?.querySelectorAll('.d3graphviz p:not([data-processed="true"])');
            if (elements) {
                for (let i = 0; i < elements.length; i++) {
                 elements[i].setAttribute("id","graphviz"+s.getSlideIndex()+i)
                 let id = d3.select("#graphviz"+s.getSlideIndex()+i).graphviz();
                 id.zoom(false)
                 id.renderDot(elements[i].textContent);
                 $('p#graphviz'+s.getSlideIndex()+i).contents().filter(function(){
                    return this.nodeType === 3;
                 }).remove();
                }
        }
    }

    // Render D3graphviz diagrams 
    D3graphviz(slideshow.getSlides()[slideshow.getCurrentSlideIndex()]);

   // Render diagrams in the next slide
   slideshow.on("afterShowSlide", D3graphviz);
    ...
    

This theme requires an active internet connection.