Skip to content

Pandoc filter that enables usage of Pandoc's Markdown in SVG text elements.

License

Notifications You must be signed in to change notification settings

rnwst/pandoc-svg

Repository files navigation

A Pandoc filter that enables usage of Pandoc's Markdown in SVG <text> elements (see demos below). This is particularly useful for SVGs containing math.

Currently, only HTML output is supported, but PDF/LaTeX support is in the works. Other output formats (such as DOCX) could be supported by converting the SVG to a raster graphics format. If you have a need for this, please open an issue!

For HTML output, pandoc-svg optimizes SVGs (using SVGO as well as some custom algorithms) and inlines SVGs in the HTML output for greater page load speed. Furthermore, pandoc-svg converts some elements of the SVG 2 specification to their SVG 1.1 equivalents so that they can be rendered correctly by browsers. This allows inclusion of SVGs generated by Inkscape (which makes use of SVG 2 features) without post-processing.

If you have an intriguing example SVG that you would like to share, please open an issue, and I'll add it here.

Known limitations

All known current limitations are listed below:

  • For the time being, only HTML output is supported.

  • Currently, if the file path of the SVGs is relative, it must be specified relative to the directory from which Pandoc is executed. This limitation is due to this issue and will hopefully soon be removed.

  • At the moment, pandoc-svg has no way of knowing what options Pandoc was executed with. Therefore, no other math output option apart from MathJax is available (such as KaTeX). This limitation can be removed once the above issue is resolved.

  • For HTML output, conversion from SVG 2 to SVG 1.1 is very crude at the moment. All it currently does is replace the marker style attributes fill:context-stroke and stroke:context-stroke with fill:#000 and stroke:#000 respectively. This results in incorrect marker/arrow colors, unless they are meant to be black. If an element of your SVG displays incorrectly in the browser, please open an issue and I will try to fix it.

Installation

pandoc-svg requires Node.js.

npm install pandoc-svg --global

I don't like to install npm packages system-wide, since this requires superuser privileges. To install the package user-wide instead, configure npm (before running the installation command) to use the directory ~/.local/ for global installation of npm packages (this adds the line prefix=~/.local/ to your ~/.npmrc):

npm config set prefix '~/.local/'

Make sure that ~/.local/bin exists and add it to the PATH (replace ~/.shellrc with the configuration file of the shell you are using, such as ~/.bashrc):

mkdir -p ~/.local/bin
echo 'export PATH=~/.local/bin/:$PATH' >> ~/.shellrc

Usage

The filter can be invoked as follows:

pandoc input-file.pdc -o output-file.html -f markdown -t html --filter pandoc-svg

If an SVG contains math, the defaults file below needs to be provided to Pandoc by appending --defaults=defaults.yaml to the above command (alternatively, the math variable can also be set in the document's metadata or via the command line).

defaults.yaml:

variables:
  math: |
    <script>
      MathJax = {
        startup: {
          ready() {
            MathJax._.core.MmlTree.MmlNodes.math.MmlMath.defaults.scriptminsize = '6pt';
            MathJax.startup.defaultReady();
          }
        }
      }
    </script>
    <script
     async
     src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg-full.js">
    </script>

The math variable needs to be set if your document contains no math other than inside SVGs. Furthermore, MathJax's scriptminsize value needs to be set to avoid this sizing issue.

Positioning of Markdown

SVG <text> elements are positioned via an anchor whose position is either start-, middle-, or end-of-baseline (shown by a small hollow square in Inkscape). To change the anchor position from start-of-baseline to one of the two other possible values, use the text-alignment tool:   .

Inlining SVGs in HTML

By default, for HTML output, pandoc-svg inlines SVGs to increase page load speed (since no separate requests need to be made to retrieve the SVGs). If an SVG is particularly large, it may be undesirable to inline it, since it would increase the time to load the HTML file (even though the total load time would be slightly reduced). In that case, pandoc-svg can be disabled for an individual SVG by adding the class ignore to it:

![Caption](file.svg){.ignore}

Note that this will disable all of pandoc-svg's functionality for this SVG, i.e. resizing and MathJax formulas won't work.

Controlling SVG dimensions

TLDR: pandoc-svg scales SVGs so that elements of size 12 pt/16 px become the same size as the font size of the text that surrounds the SVG. This behavior can be disabled.

When creating the SVG (using an editor such as Inkscape), care must be taken to size elements appropriately for the context the SVG is going to appear in (i.e. the rest of the HTML page). pandoc-svg simplifies this process by automatically scaling the SVG so that elements of size 12 pt/16 px (as set in the SVG editor) become the same size as the font size of the surrounding text. pandoc-svg does this by scaling the SVG from the absolute units the editor usually dimensions it in to the appropriate relative size in em units, where 12 pt equals 1 em. This has the advantage that the size of the SVG is always adjusted to the size of the surrounding text it appears in.

This behavior can be disabled by adding the class keep-size to the SVG:

![Caption](file.svg){.keep-size}

In addition, a custom scale factor can be supplied for the SVG. This can be used to change the SVG's size without modifying it. The SVG is still dimensioned in relative units, thus it will change size if the font-size of its parent element changes.

![Caption](file.svg){scale-factor=1.5}

To maintain compatibility with pandoc, pandoc-svg also allows sizing of SVGs using the width and height attributes:

![Caption](file.svg){width=2in}

As for Pandoc, the unit identifiers px, cm, mm, in, inch, and % can be used. Specifying either width or height overrides scale-factor or keep-size.

Miscellaneous

Understanding SVG sizing

Below follows a brief explanation of how SVG sizing works, for those who are interested. You do not need to understand this to be able to use pandoc-svg.

Dimensions inside of an SVG are specified using user units, which are dimensionless. If a style attribute is used inside the SVG, the unit identifier is 'px', since CSS requires the presence of a unit identifier. The 'SVG style attribute px' is defined to be equal to one user unit. It is important to note that the user unit (or 'SVG style attribute px') does not correspond to a 'px' in your HTML file! The relation beteween the SVG user unit and units in the HTML file is set using the <width>, <height>, and <viewBox> attributes. The <width> and <height> attributes are in CSS units (when no unit identifier is present, the unit is CSS px), and the <viewBox> attribute is in user units. In the following example, one user unit equals 2mm:

<svg
 xmlns="http://www.w3.org/2000/svg"
 width="30mm"
 height="20mm"
 viewBox="0 0 15 10">  <!-- `width` and `height` are in 'real units'
                                whereas `viewBox` is in *user units* -->
  <!--
     Pretty shapes go here, which are dimensioned in user units.
     If a style tag is used, the CSS unit identifier must be 'px'.
  -->
</svg>

License

© 2022 R. N. West. Released under the GPL version 2 or greater. This software carries no warranty of any kind.

About

Pandoc filter that enables usage of Pandoc's Markdown in SVG text elements.

Resources

License

Stars

Watchers

Forks

Packages

No packages published