packages feed

pandoc-plot 1.0.0.0 → 1.0.1.0

raw patch · 40 files changed

+3234/−2818 lines, 40 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Text.Pandoc.Filter.Plot: [sourceCodeLabel] :: Configuration -> !Text
+ Text.Pandoc.Filter.Plot.Internal: SourceCodeLabelK :: InclusionKey
+ Text.Pandoc.Filter.Plot.Internal: [sourceCodeLabel] :: Configuration -> !Text
+ Text.Pandoc.Filter.Plot.Internal: language :: Toolkit -> Text
+ Text.Pandoc.Filter.Plot.Internal: sourceCodePath :: FigureSpec -> PlotM FilePath
- Text.Pandoc.Filter.Plot: Configuration :: !FilePath -> !Bool -> !Int -> !SaveFormat -> ![FilePath] -> !Format -> !Verbosity -> !LogSink -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !Bool -> !Bool -> Configuration
+ Text.Pandoc.Filter.Plot: Configuration :: !FilePath -> !Bool -> !Int -> !SaveFormat -> ![FilePath] -> !Format -> !Text -> !Verbosity -> !LogSink -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !Bool -> !Bool -> Configuration
- Text.Pandoc.Filter.Plot.Internal: Configuration :: !FilePath -> !Bool -> !Int -> !SaveFormat -> ![FilePath] -> !Format -> !Verbosity -> !LogSink -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !Bool -> !Bool -> Configuration
+ Text.Pandoc.Filter.Plot.Internal: Configuration :: !FilePath -> !Bool -> !Int -> !SaveFormat -> ![FilePath] -> !Format -> !Text -> !Verbosity -> !LogSink -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !Bool -> !Bool -> Configuration

Files

CHANGELOG.md view
@@ -2,6 +2,13 @@ 
 pandoc-plot uses [Semantic Versioning](http://semver.org/spec/v2.0.0.html)
 
+Release 1.0.1.0
+---------------
+
+* Added the ability to change the "Source code" label to other languages via configuration.
+* Added syntax highlighting to the linked source code.
+* Fixed an issue where code blocks with unicode symbols (e.g. greek letters) would trip up pandoc-plot (#16).
+
 Release 1.0.0.0
 ---------------
 
MANUAL.md view
@@ -6,21 +6,21 @@ 
 `pandoc-plot` turns code blocks present in your documents (Markdown, LaTeX, etc.) into embedded figures, using your plotting toolkit of choice, including Matplotlib, ggplot2, MATLAB, Mathematica, and more.
 
-  - [Features Overview](#features-overview)
-      - [Captions](#captions)
-      - [Link to source code](#link-to-source-code)
-      - [Preamble scripts](#preamble-scripts)
-      - [Support for interactive plots](#support-for-interactive-plots)
-      - [Performance](#performance)
-      - [Compatibility with pandoc-crossref](#compatibility-with-pandoc-crossref)
-  - [Detailed usage](#detailed-usage)
-      - [As a filter](#as-a-filter)
-      - [Syntax](#syntax)
-      - [Parameters and options](#parameters-and-options)
-      - [Interactive HTML figures](#interactive-html-figures)
-      - [Configuration](#configuration)
-      - [Other commands](#other-commands)
-  - [Warning](#warning)
+-   [Features Overview](#features-overview)
+    -   [Captions](#captions)
+    -   [Link to source code](#link-to-source-code)
+    -   [Preamble scripts](#preamble-scripts)
+    -   [Support for interactive plots](#support-for-interactive-plots)
+    -   [Performance](#performance)
+    -   [Compatibility with pandoc-crossref](#compatibility-with-pandoc-crossref)
+-   [Detailed usage](#detailed-usage)
+    -   [As a filter](#as-a-filter)
+    -   [Syntax](#syntax)
+    -   [Parameters and options](#parameters-and-options)
+    -   [Interactive HTML figures](#interactive-html-figures)
+    -   [Configuration](#configuration)
+    -   [Other commands](#other-commands)
+-   [Warning](#warning)
 
 ## Features Overview
 
@@ -120,7 +120,7 @@ \end{minted}
 ```
 
-This `preamble` parameter is perfect for longer documents with many plots. Simply define the style you want in a separate script\! You can also import packages this way, or define functions you often use.
+This `preamble` parameter is perfect for longer documents with many plots. Simply define the style you want in a separate script! You can also import packages this way, or define functions you often use.
 
 ### Support for interactive plots
 
@@ -128,7 +128,7 @@ 
 ### Performance
 
-`pandoc-plot` minimizes work, only generating figures if it absolutely must, i.e. if the content has changed. `pandoc-plot` will save the hash of the source code used to generate a figure in its filename. Before generating a figure, `pandoc-plot` will check it this figure already exists based on the hash of its source\! This also means that there is no way to directly name figures.
+`pandoc-plot` minimizes work, only generating figures if it absolutely must, i.e. if the content has changed. `pandoc-plot` will save the hash of the source code used to generate a figure in its filename. Before generating a figure, `pandoc-plot` will check it this figure already exists based on the hash of its source! This also means that there is no way to directly name figures.
 
 Moreover, starting with version 0.5.0.0, `pandoc-plot` takes advantage of multicore CPUs, rendering figures **in parallel**.
 
@@ -159,7 +159,7 @@ `pandoc-plot` is a command line executable with a few functions. You can take a look at the help using the `-h`/`--help` flag:
 
 ``` bash
-pandoc-plot 0.9.4.0 - generate figures directly in documents
+pandoc-plot 1.0.1.0 - generate figures directly in documents
 
 Usage: pandoc-plot.EXE [(-v|--version) | --full-version | (-m|--manual)] 
                        [COMMAND] [AST]
@@ -235,7 +235,8 @@       directory=(path) 
       caption=(text) 
       format=(PNG|PDF|SVG|JPG|EPS|GIF|TIF|WEBP|HTML) 
-      source=(true|false) 
+      source=(true|True|false|False) 
+      source_label=(text)
       preamble=(path) 
       dpi=(integer)
       dependencies=[...]
@@ -247,21 +248,22 @@   ```
 ````
 
-  - `cls` must be one of the following: `matplotlib`, `matlabplot`, `plotly_python`, `plotly_r`, `mathplot`, `octaveplot`, `ggplot2`, `gnuplot`, `graphviz`, `bokeh`, `plotsjl`.
+-   `cls` must be one of the following: `matplotlib`, `matlabplot`, `plotly_python`, `plotly_r`, `mathplot`, `octaveplot`, `ggplot2`, `gnuplot`, `graphviz`, `bokeh`, `plotsjl`.
 
-All following parameters are optional, with their default values controlled by the [configuration](#configuration)
+All following parameters are optional, with their default values controlled by the [configuration](#configuration).
 
-  - `language` specifies the programming language used in this block. This parameter is ignored by `pandoc-plot`, but your text editor may use it to highlight code. See [Code highlighting](#code-highlighting) below.
-  - `directory` is a path to the directory where the figure and source code will be saved. You cannot control the file name. This path is either absolute, or relative from the working directory where you call `pandoc-plot`.
-  - `caption` is the caption text. The format of the caption is specified in the `caption_format` parameter, described below.
-  - `format` is the desired filetype for the resulting figure. Possible values for `format` are \[`PNG`, `PDF`, `SVG`, `JPG`, `EPS`, `GIF`, `TIF`, `WEBP`, `HTML`\]. Not all toolkits support all formats. See `pandoc-plot toolkits` for toolkit-specific information regarding save formats. The `HTML` format is special; it can produce standalone, offline, interactive plots. As such, it only makes sense to use this format when creating HTML documents.
-  - `source` is a boolean toggle that determines whether the source code should be linked in the caption or not. Possible values are \[`true`, `True`, `false`, `False`\].
-  - `preamble` is a path to a script that will be included as a preamble to the content of the code block. This path is either absolute, or relative from the working directory where you call `pandoc-plot`.
-  - `dpi` is the pixel density of the figure in dots-per-inch. Possible values are positive integers. Not all toolkits respect this.
-  - `dependencies` is a list of files/directories that affect the figure, for example data files. If one of those files/directories changes, `pandoc-plot` will re-render the associated figure. Format is a comma-separated list, e.g. `dependencies=[data.txt, foo.bar, ~/wtv]`. Values for `dependencies` in the configuration file will be appended to the values in a code block.
-  - `file` is a path to a file from which to read the figure content. If this parameter is used, the content of the code block is ignored. By using this parameter, you can use all the standard tooling of your plotting toolkit of choice, which is especially useful for complex figures.
-  - `executable` is a path to the executable to use (e.g. `C:\\python3.exe`) or the name of the executable (e.g. `python3`).
-  - `caption_format` is the text format of the caption. Possible values are exactly the same as `pandoc`’s format specification, usually `FORMAT+EXTENSION-EXTENSION`. For example, captions in Markdown with raw LaTeX would be parsed correctly provided that `caption_format=markdown+raw_tex`. See Pandoc’s guide on [Specifying formats](https://pandoc.org/MANUAL.html#specifying-formats).
+-   `language` specifies the programming language used in this block. This parameter is ignored by `pandoc-plot`, but your text editor may use it to highlight code. See [Code highlighting](#code-highlighting) below.
+-   `directory` is a path to the directory where the figure and source code will be saved. You cannot control the file name. This path is either absolute, or relative from the working directory where you call `pandoc-plot`.
+-   `caption` is the caption text. The format of the caption is specified in the `caption_format` parameter, described below.
+-   `format` is the desired filetype for the resulting figure. Possible values for `format` are \[`PNG`, `PDF`, `SVG`, `JPG`, `EPS`, `GIF`, `TIF`, `WEBP`, `HTML`\]. Not all toolkits support all formats. See `pandoc-plot toolkits` for toolkit-specific information regarding save formats. The `HTML` format is special; it can produce standalone, offline, interactive plots. As such, it only makes sense to use this format when creating HTML documents.
+-   `source` is a boolean toggle that determines whether the source code should be linked in the caption or not. Possible values are \[`true`, `True`, `false`, `False`\].
+-   `source_label` is the text that links to source code (if `source=true`). This is useful if you are writing text in a different language. The default is `source_label="Source Code"`. You might want to set this via the [configuration](#configuration) instead.
+-   `preamble` is a path to a script that will be included as a preamble to the content of the code block. This path is either absolute, or relative from the working directory where you call `pandoc-plot`.
+-   `dpi` is the pixel density of the figure in dots-per-inch. Possible values are positive integers. Not all toolkits respect this.
+-   `dependencies` is a list of files/directories that affect the figure, for example data files. If one of those files/directories changes, `pandoc-plot` will re-render the associated figure. Format is a comma-separated list, e.g. `dependencies=[data.txt, foo.bar, ~/wtv]`. Values for `dependencies` in the configuration file will be appended to the values in a code block.
+-   `file` is a path to a file from which to read the figure content. If this parameter is used, the content of the code block is ignored. By using this parameter, you can use all the standard tooling of your plotting toolkit of choice, which is especially useful for complex figures.
+-   `executable` is a path to the executable to use (e.g. `C:\\python3.exe`) or the name of the executable (e.g. `python3`).
+-   `caption_format` is the text format of the caption. Possible values are exactly the same as `pandoc`’s format specification, usually `FORMAT+EXTENSION-EXTENSION`. For example, captions in Markdown with raw LaTeX would be parsed correctly provided that `caption_format=markdown+raw_tex`. See Pandoc’s guide on [Specifying formats](https://pandoc.org/MANUAL.html#specifying-formats).
 
 #### Code highlighting
 
@@ -319,7 +321,6 @@ files. Here are **all** the possible parameters:
 
 ``` yaml
-
 # This is an example configuration. Everything in this file is optional.
 # Please refer to the documentation to know about the parameters herein.
 #
@@ -339,6 +340,11 @@ # Particularly useful for HTML output.
 source: false
 
+# Text label for links to source code.
+# You can change this label if you are writing a document in a non-English language. 
+# This only matters if `source` is set to `true`.
+source_label: Source code
+
 # Default density of figures in dots per inches (DPI). 
 # This can be changed in the document specifically as well.
 dpi: 80
@@ -361,6 +367,7 @@ # Example: markdown, rst+raw_tex
 caption_format: markdown+tex_math_dollars
 
+
 # Logging configuration
 logging:
   # Possible verbosity values: debug, error, warning, info, silent
@@ -469,8 +476,8 @@ 
 ##### Matplotlib
 
-  - `tight_bbox` is a boolean that determines whether to use `bbox_inches="tight"` or not when saving Matplotlib figures. For example, `tight_bbox: true`. See [here](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.savefig.html) for details.
-  - `transparent` is a boolean that determines whether to make Matplotlib figure background transparent or not. This is useful, for example, for displaying a plot on top of a colored background on a web page. High-resolution figures are not affected. For example, `transparent: true`.
+-   `tight_bbox` is a boolean that determines whether to use `bbox_inches="tight"` or not when saving Matplotlib figures. For example, `tight_bbox: true`. See [here](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.savefig.html) for details.
+-   `transparent` is a boolean that determines whether to make Matplotlib figure background transparent or not. This is useful, for example, for displaying a plot on top of a colored background on a web page. High-resolution figures are not affected. For example, `transparent: true`.
 
 #### Logging
 
@@ -529,7 +536,7 @@ 
 #### Configuration template
 
-Because `pandoc-plot` supports a few toolkits, there are a lot of configuration options. Don’t start from scratch\! The `write-example-config` command will create a file for you, which you can then modify:
+Because `pandoc-plot` supports a few toolkits, there are a lot of configuration options. Don’t start from scratch! The `write-example-config` command will create a file for you, which you can then modify:
 
 ``` bash
 pandoc-plot write-example-config
@@ -552,4 +559,4 @@ ## Warning
 
 Do not run this filter on unknown documents. There is nothing in
-`pandoc-plot` that can stop a script from performing **evil actions**.+`pandoc-plot` that can stop a script from performing **evil actions**.
README.md view
@@ -59,7 +59,7 @@   - `gnuplot`: plots using [gnuplot](http://www.gnuplot.info/);
   - `graphviz`: graphs using [Graphviz](http://graphviz.org/);
   - `bokeh`: plots using the [Bokeh](https://bokeh.org/) visualization library;
-  - `plotsjl`: plots using the [Julia `Plots.jl`](http://docs.plotsjl.org/latest/) package.
+  - `plotsjl`: plots using the [Julia `Plots.jl`](https://docs.juliaplots.org/latest/) package.
 
 To know which toolkits are useable on *your machine* (and which ones are
 not available), you can check with the `toolkits` command:
benchmark/MatplotlibGallery.hs view
@@ -2,25 +2,22 @@ 
 module MatplotlibGallery where
 
-import           Data.String                (fromString)
-
-import qualified Data.Text                  as T
-import qualified Data.Text.IO               as T
-
-import           Language.Haskell.TH.Syntax
-
+import Data.String (fromString)
+import qualified Data.Text as T
+import qualified Data.Text.IO as T
+import Language.Haskell.TH.Syntax
 
 galleryItem :: FilePath -> Q Exp
 galleryItem fp = do
-    qAddDependentFile fp
-    txt <- runIO $ T.readFile fp
-    strToExp $ T.unpack txt
-    where
-        strToExp :: String -> Q Exp
-        strToExp s = return $ VarE 'fromString `AppE` LitE (StringL s)
+  qAddDependentFile fp
+  txt <- runIO $ T.readFile fp
+  strToExp $ T.unpack txt
+  where
+    strToExp :: String -> Q Exp
+    strToExp s = return $ VarE 'fromString `AppE` LitE (StringL s)
 
 galleryItem1, galleryItem2, galleryItem3, galleryItem4 :: Q Exp
 galleryItem1 = galleryItem "benchmark/gallery_item_1.py"
 galleryItem2 = galleryItem "benchmark/gallery_item_2.py"
 galleryItem3 = galleryItem "benchmark/gallery_item_3.py"
-galleryItem4 = galleryItem "benchmark/gallery_item_4.py"+galleryItem4 = galleryItem "benchmark/gallery_item_4.py"
benchmark/bench.hs view
@@ -1,39 +1,56 @@ {-# LANGUAGE TemplateHaskell #-}
 
 import Criterion.Main
-
-import Text.Pandoc.Definition
+  ( bench,
+    bgroup,
+    defaultMain,
+    envWithCleanup,
+    nfIO,
+  )
+import MatplotlibGallery
+  ( galleryItem1,
+    galleryItem2,
+    galleryItem3,
+    galleryItem4,
+  )
+import Text.Pandoc.Definition (Block (CodeBlock), Pandoc (..))
 import Text.Pandoc.Filter.Plot
-import Text.Pandoc.Filter.Plot.Internal
-
-import MatplotlibGallery ( galleryItem1, galleryItem2
-                         , galleryItem3, galleryItem4
-                         )
+  ( Configuration (logSink, logVerbosity),
+    LogSink (StdErr),
+    Script,
+    Toolkit (Matplotlib),
+    Verbosity (Silent),
+    cleanOutputDirs,
+    defaultConfiguration,
+    plotTransform,
+  )
+import Text.Pandoc.Filter.Plot.Internal (cls)
 
 main :: IO ()
-main = 
-    defaultMain [
-        envWithCleanup (return ()) (\_ -> cleanupEnv) $ \_ -> 
-            bgroup "main" [
-                    bench "filter-async" $ nfIO (plotTransform plotConfig benchDoc)
-                  , bench "filter"       $ nfIO (makePlot plotConfig benchDoc)
-                ]
+main =
+  defaultMain
+    [ envWithCleanup (return ()) (\_ -> cleanupEnv) $ \_ ->
+        bgroup
+          "main"
+          [ bench "filter" $ nfIO (plotTransform plotConfig benchDoc)
+          ]
     ]
 
 plotConfig :: Configuration
-plotConfig = defaultConfiguration {logVerbosity=Silent, logSink =StdErr}
+plotConfig = defaultConfiguration {logVerbosity = Silent, logSink = StdErr}
 
 cleanupEnv :: IO ()
 cleanupEnv = cleanOutputDirs plotConfig benchDoc >> return ()
 
-
 codeBlock :: Script -> Block
 codeBlock = CodeBlock (mempty, [cls Matplotlib], mempty)
 
-
 benchDoc :: Pandoc
-benchDoc = Pandoc mempty [ codeBlock $(galleryItem1)
-                         , codeBlock $(galleryItem2)
-                         , codeBlock $(galleryItem3)
-                         , codeBlock $(galleryItem4)
-                         ]+benchDoc =
+  Pandoc
+    mempty
+    [ codeBlock $(galleryItem1),
+      codeBlock $(galleryItem2),
+      codeBlock $(galleryItem3),
+      codeBlock $(galleryItem4)
+    ]
+ data/srctemplate.html view
@@ -0,0 +1,241 @@+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" lang="$lang$" xml:lang="$lang$"$if(dir)$ dir="$dir$"$endif$>
+<head>
+  <meta charset="utf-8" />
+  <meta name="generator" content="pandoc-plot" />
+  <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
+$for(author-meta)$
+  <meta name="author" content="$author-meta$" />
+$endfor$
+$if(date-meta)$
+  <meta name="dcterms.date" content="$date-meta$" />
+$endif$
+$if(keywords)$
+  <meta name="keywords" content="$for(keywords)$$keywords$$sep$, $endfor$" />
+$endif$
+  <title>Generated figure</title>
+  <style>
+$if(document-css)$
+html {
+  line-height: $if(linestretch)$$linestretch$$else$1.5$endif$;
+  font-family: $if(mainfont)$$mainfont$$else$Georgia, serif$endif$;
+  font-size: $if(fontsize)$$fontsize$$else$20px$endif$;
+  color: $if(fontcolor)$$fontcolor$$else$#1a1a1a$endif$;
+  background-color: $if(backgroundcolor)$$backgroundcolor$$else$#fdfdfd$endif$;
+}
+body {
+  margin: 0 auto;
+  max-width: 36em;
+  padding-left: $if(margin-left)$$margin-left$$else$50px$endif$;
+  padding-right: $if(margin-right)$$margin-right$$else$50px$endif$;
+  padding-top: $if(margin-top)$$margin-top$$else$50px$endif$;
+  padding-bottom: $if(margin-bottom)$$margin-bottom$$else$50px$endif$;
+  hyphens: auto;
+  word-wrap: break-word;
+  text-rendering: optimizeLegibility;
+  font-kerning: normal;
+}
+@media (max-width: 600px) {
+  body {
+    font-size: 0.9em;
+    padding: 1em;
+  }
+}
+@media print {
+  body {
+    background-color: transparent;
+    color: black;
+    font-size: 12pt;
+  }
+  p, h2, h3 {
+    orphans: 3;
+    widows: 3;
+  }
+  h2, h3, h4 {
+    page-break-after: avoid;
+  }
+}
+p {
+  margin: 1em 0;
+}
+a {
+  color: $if(linkcolor)$$linkcolor$$else$#1a1a1a$endif$;
+}
+a:visited {
+  color: $if(linkcolor)$$linkcolor$$else$#1a1a1a$endif$;
+}
+img {
+  max-width: 100%;
+}
+h1, h2, h3, h4, h5, h6 {
+  margin-top: 1.4em;
+}
+h5, h6 {
+  font-size: 1em;
+  font-style: italic;
+}
+h6 {
+  font-weight: normal;
+}
+ol, ul {
+  padding-left: 1.7em;
+  margin-top: 1em;
+}
+li > ol, li > ul {
+  margin-top: 0;
+}
+blockquote {
+  margin: 1em 0 1em 1.7em;
+  padding-left: 1em;
+  border-left: 2px solid #e6e6e6;
+  color: #606060;
+}
+code {
+  font-family: $if(monofont)$$monofont$$else$Menlo, Monaco, 'Lucida Console', Consolas, monospace$endif$;
+$if(monobackgroundcolor)$
+  background-color: $monobackgroundcolor$;
+  padding: .2em .4em;
+$endif$
+  font-size: 85%;
+  margin: 0;
+}
+pre {
+  margin: 1em 0;
+$if(monobackgroundcolor)$
+  background-color: $monobackgroundcolor$;
+  padding: 1em;
+$endif$
+  overflow: auto;
+}
+pre code {
+  padding: 0;
+  overflow: visible;
+}
+.sourceCode {
+ background-color: transparent;
+ overflow: visible;
+}
+hr {
+  background-color: #1a1a1a;
+  border: none;
+  height: 1px;
+  margin: 1em 0;
+}
+table {
+  margin: 1em 0;
+  border-collapse: collapse;
+  width: 100%;
+  overflow-x: auto;
+  display: block;
+  font-variant-numeric: lining-nums tabular-nums;
+}
+table caption {
+  margin-bottom: 0.75em;
+}
+tbody {
+  margin-top: 0.5em;
+  border-top: 1px solid $if(fontcolor)$$fontcolor$$else$#1a1a1a$endif$;
+  border-bottom: 1px solid $if(fontcolor)$$fontcolor$$else$#1a1a1a$endif$;
+}
+th {
+  border-top: 1px solid $if(fontcolor)$$fontcolor$$else$#1a1a1a$endif$;
+  padding: 0.25em 0.5em 0.25em 0.5em;
+}
+td {
+  padding: 0.125em 0.5em 0.25em 0.5em;
+}
+header {
+  margin-bottom: 4em;
+  text-align: center;
+}
+#TOC li {
+  list-style: none;
+}
+#TOC a:not(:hover) {
+  text-decoration: none;
+}
+$endif$
+code{white-space: pre-wrap;}
+span.smallcaps{font-variant: small-caps;}
+span.underline{text-decoration: underline;}
+div.column{display: inline-block; vertical-align: top; width: 50%;}
+div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
+ul.task-list{list-style: none;}
+$if(quotes)$
+q { quotes: "“" "”" "‘" "’"; }
+$endif$
+$if(highlighting-css)$
+$highlighting-css$
+$endif$
+$if(displaymath-css)$
+.display.math{display: block; text-align: center; margin: 0.5rem auto;}
+$endif$
+$if(csl-css)$
+div.csl-bib-body { }
+div.csl-entry {
+  clear: both;
+$if(csl-entry-spacing)$
+  margin-bottom: $csl-entry-spacing$;
+$endif$
+}
+.hanging div.csl-entry {
+  margin-left:2em;
+  text-indent:-2em;
+}
+div.csl-left-margin {
+  min-width:2em;
+  float:left;
+}
+div.csl-right-inline {
+  margin-left:2em;
+  padding-left:1em;
+}
+div.csl-indent {
+  margin-left: 2em;
+}
+$endif$
+  </style>
+$for(css)$
+  <link rel="stylesheet" href="$css$" />
+$endfor$
+$if(math)$
+  $math$
+$endif$
+
+$for(header-includes)$
+  $header-includes$
+$endfor$
+</head>
+<body>
+$for(include-before)$
+$include-before$
+$endfor$
+$if(title)$
+<header id="title-block-header">
+<h1 class="title">$title$</h1>
+$if(subtitle)$
+<p class="subtitle">$subtitle$</p>
+$endif$
+$for(author)$
+<p class="author">$author$</p>
+$endfor$
+$if(date)$
+<p class="date">$date$</p>
+$endif$
+</header>
+$endif$
+$if(toc)$
+<nav id="$idprefix$TOC" role="doc-toc">
+$if(toc-title)$
+<h2 id="$idprefix$toc-title">$toc-title$</h2>
+$endif$
+$table-of-contents$
+</nav>
+$endif$
+$body$
+$for(include-after)$
+$include-after$
+$endfor$
+<a href="https://github.com/LaurentRDC/pandoc-plot">Click here to see how this plot was generated.</a>
+</body>
+</html>
docs/MANUAL.html view
@@ -4,7 +4,7 @@   <meta charset="utf-8" />
   <meta name="generator" content="pandoc" />
   <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
-  <title>pandoc-plot 1.0.0.0 manual</title>
+  <title>pandoc-plot 1.0.1.0 manual</title>
   <style>
     code{white-space: pre-wrap;}
     span.smallcaps{font-variant: small-caps;}
@@ -15,6 +15,7 @@     pre > code.sourceCode { white-space: pre; position: relative; }
     pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
     pre > code.sourceCode > span:empty { height: 1.2em; }
+    .sourceCode { overflow: visible; }
     code.sourceCode > span { color: inherit; text-decoration: inherit; }
     div.sourceCode { margin: 1em 0; }
     pre.sourceCode { margin: 0; }
@@ -76,14 +77,14 @@     code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
     .display.math{display: block; text-align: center; margin: 0.5rem auto;}
   </style>
-  <style type="text/css">html { font-size: 100%; overflow-y: scroll; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }body{color:#444;font-family:Georgia, Palatino, 'Palatino Linotype', Times, 'Times New Roman', serif;font-size:12px;line-height:1.5em;padding:1em;margin:auto;max-width:42em;background:#fefefe;}a{ color: #0645ad; text-decoration:none;}a:visited{ color: #0b0080; }a:hover{ color: #06e; }a:active{ color:#faa700; }a:focus{ outline: thin dotted; }a:hover, a:active{ outline: 0; }::-moz-selection{background:rgba(255,255,0,0.3);color:#000}::selection{background:rgba(255,255,0,0.3);color:#000}a::-moz-selection{background:rgba(255,255,0,0.3);color:#0645ad}a::selection{background:rgba(255,255,0,0.3);color:#0645ad}p{margin:1em 0;}img{max-width:100%;}h1,h2,h3,h4,h5,h6{font-weight:normal;color:#111;line-height:1em;}h4,h5,h6{ font-weight: bold; }h1{ font-size:2.5em; }h2{ font-size:2em; }h3{ font-size:1.5em; }h4{ font-size:1.2em; }h5{ font-size:1em; }h6{ font-size:0.9em; }blockquote{color:#666666;margin:0;padding-left: 3em;border-left: 0.5em #EEE solid;}hr { display: block; height: 2px; border: 0; border-top: 1px solid #aaa;border-bottom: 1px solid #eee; margin: 1em 0; padding: 0; }pre, code, kbd, samp { color: #000; font-family: monospace, monospace; _font-family: 'courier new', monospace; font-size: 0.98em; }pre { white-space: pre; white-space: pre-wrap; word-wrap: break-word; }b, strong { font-weight: bold; }dfn { font-style: italic; }ins { background: #ff9; color: #000; text-decoration: none; }mark { background: #ff0; color: #000; font-style: italic; font-weight: bold; }sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; }sup { top: -0.5em; }sub { bottom: -0.25em; }ul, ol { margin: 1em 0; padding: 0 0 0 2em; }li p:last-child { margin:0 }dd { margin: 0 0 0 2em; }img { border: 0; -ms-interpolation-mode: bicubic; vertical-align: middle; }table {border-collapse: collapse;border-spacing: 0;width: 100%;}th { border-bottom: 1px solid black; }td { vertical-align: top; }@media only screen and (min-width: 480px) {body{font-size:14px;}}@media only screen and (min-width: 768px) {body{font-size:16px;}}@media print {* { background: transparent !important; color: black !important; filter:none !important; -ms-filter: none !important; }body{font-size:12pt; max-width:100%;}a, a:visited { text-decoration: underline; }hr { height: 1px; border:0; border-bottom:1px solid black; }a[href]:after { content: " (" attr(href) ")"; }abbr[title]:after { content: " (" attr(title) ")"; }.ir a:after, a[href^="javascript:"]:after, a[href^="#"]:after { content: ""; }pre, blockquote { border: 1px solid #999; padding-right: 1em; page-break-inside: avoid; }tr, img { page-break-inside: avoid; }img { max-width: 100% !important; }@page :left { margin: 15mm 20mm 15mm 10mm; }@page :right { margin: 15mm 10mm 15mm 20mm; }p, h2, h3 { orphans: 3; widows: 3; }h2, h3 { page-break-after: avoid; }}</style>
+  <link rel="stylesheet" href="data:text/css,html%20%7B%20font%2Dsize%3A%20100%25%3B%20overflow%2Dy%3A%20scroll%3B%20%2Dwebkit%2Dtext%2Dsize%2Dadjust%3A%20100%25%3B%20%2Dms%2Dtext%2Dsize%2Dadjust%3A%20100%25%3B%20%7Dbody%7Bcolor%3A%23444%3Bfont%2Dfamily%3AGeorgia%2C%20Palatino%2C%20%27Palatino%20Linotype%27%2C%20Times%2C%20%27Times%20New%20Roman%27%2C%20serif%3Bfont%2Dsize%3A12px%3Bline%2Dheight%3A1%2E5em%3Bpadding%3A1em%3Bmargin%3Aauto%3Bmax%2Dwidth%3A42em%3Bbackground%3A%23fefefe%3B%7Da%7B%20color%3A%20%230645ad%3B%20text%2Ddecoration%3Anone%3B%7Da%3Avisited%7B%20color%3A%20%230b0080%3B%20%7Da%3Ahover%7B%20color%3A%20%2306e%3B%20%7Da%3Aactive%7B%20color%3A%23faa700%3B%20%7Da%3Afocus%7B%20outline%3A%20thin%20dotted%3B%20%7Da%3Ahover%2C%20a%3Aactive%7B%20outline%3A%200%3B%20%7D%3A%3A%2Dmoz%2Dselection%7Bbackground%3Argba%28255%2C255%2C0%2C0%2E3%29%3Bcolor%3A%23000%7D%3A%3Aselection%7Bbackground%3Argba%28255%2C255%2C0%2C0%2E3%29%3Bcolor%3A%23000%7Da%3A%3A%2Dmoz%2Dselection%7Bbackground%3Argba%28255%2C255%2C0%2C0%2E3%29%3Bcolor%3A%230645ad%7Da%3A%3Aselection%7Bbackground%3Argba%28255%2C255%2C0%2C0%2E3%29%3Bcolor%3A%230645ad%7Dp%7Bmargin%3A1em%200%3B%7Dimg%7Bmax%2Dwidth%3A100%25%3B%7Dh1%2Ch2%2Ch3%2Ch4%2Ch5%2Ch6%7Bfont%2Dweight%3Anormal%3Bcolor%3A%23111%3Bline%2Dheight%3A1em%3B%7Dh4%2Ch5%2Ch6%7B%20font%2Dweight%3A%20bold%3B%20%7Dh1%7B%20font%2Dsize%3A2%2E5em%3B%20%7Dh2%7B%20font%2Dsize%3A2em%3B%20%7Dh3%7B%20font%2Dsize%3A1%2E5em%3B%20%7Dh4%7B%20font%2Dsize%3A1%2E2em%3B%20%7Dh5%7B%20font%2Dsize%3A1em%3B%20%7Dh6%7B%20font%2Dsize%3A0%2E9em%3B%20%7Dblockquote%7Bcolor%3A%23666666%3Bmargin%3A0%3Bpadding%2Dleft%3A%203em%3Bborder%2Dleft%3A%200%2E5em%20%23EEE%20solid%3B%7Dhr%20%7B%20display%3A%20block%3B%20height%3A%202px%3B%20border%3A%200%3B%20border%2Dtop%3A%201px%20solid%20%23aaa%3Bborder%2Dbottom%3A%201px%20solid%20%23eee%3B%20margin%3A%201em%200%3B%20padding%3A%200%3B%20%7Dpre%2C%20code%2C%20kbd%2C%20samp%20%7B%20color%3A%20%23000%3B%20font%2Dfamily%3A%20monospace%2C%20monospace%3B%20%5Ffont%2Dfamily%3A%20%27courier%20new%27%2C%20monospace%3B%20font%2Dsize%3A%200%2E98em%3B%20%7Dpre%20%7B%20white%2Dspace%3A%20pre%3B%20white%2Dspace%3A%20pre%2Dwrap%3B%20word%2Dwrap%3A%20break%2Dword%3B%20%7Db%2C%20strong%20%7B%20font%2Dweight%3A%20bold%3B%20%7Ddfn%20%7B%20font%2Dstyle%3A%20italic%3B%20%7Dins%20%7B%20background%3A%20%23ff9%3B%20color%3A%20%23000%3B%20text%2Ddecoration%3A%20none%3B%20%7Dmark%20%7B%20background%3A%20%23ff0%3B%20color%3A%20%23000%3B%20font%2Dstyle%3A%20italic%3B%20font%2Dweight%3A%20bold%3B%20%7Dsub%2C%20sup%20%7B%20font%2Dsize%3A%2075%25%3B%20line%2Dheight%3A%200%3B%20position%3A%20relative%3B%20vertical%2Dalign%3A%20baseline%3B%20%7Dsup%20%7B%20top%3A%20%2D0%2E5em%3B%20%7Dsub%20%7B%20bottom%3A%20%2D0%2E25em%3B%20%7Dul%2C%20ol%20%7B%20margin%3A%201em%200%3B%20padding%3A%200%200%200%202em%3B%20%7Dli%20p%3Alast%2Dchild%20%7B%20margin%3A0%20%7Ddd%20%7B%20margin%3A%200%200%200%202em%3B%20%7Dimg%20%7B%20border%3A%200%3B%20%2Dms%2Dinterpolation%2Dmode%3A%20bicubic%3B%20vertical%2Dalign%3A%20middle%3B%20%7Dtable%20%7Bborder%2Dcollapse%3A%20collapse%3Bborder%2Dspacing%3A%200%3Bwidth%3A%20100%25%3B%7Dth%20%7B%20border%2Dbottom%3A%201px%20solid%20black%3B%20%7Dtd%20%7B%20vertical%2Dalign%3A%20top%3B%20%7D%40media%20only%20screen%20and%20%28min%2Dwidth%3A%20480px%29%20%7Bbody%7Bfont%2Dsize%3A14px%3B%7D%7D%40media%20only%20screen%20and%20%28min%2Dwidth%3A%20768px%29%20%7Bbody%7Bfont%2Dsize%3A16px%3B%7D%7D%40media%20print%20%7B%2A%20%7B%20background%3A%20transparent%20%21important%3B%20color%3A%20black%20%21important%3B%20filter%3Anone%20%21important%3B%20%2Dms%2Dfilter%3A%20none%20%21important%3B%20%7Dbody%7Bfont%2Dsize%3A12pt%3B%20max%2Dwidth%3A100%25%3B%7Da%2C%20a%3Avisited%20%7B%20text%2Ddecoration%3A%20underline%3B%20%7Dhr%20%7B%20height%3A%201px%3B%20border%3A0%3B%20border%2Dbottom%3A1px%20solid%20black%3B%20%7Da%5Bhref%5D%3Aafter%20%7B%20content%3A%20%22%20%28%22%20attr%28href%29%20%22%29%22%3B%20%7Dabbr%5Btitle%5D%3Aafter%20%7B%20content%3A%20%22%20%28%22%20attr%28title%29%20%22%29%22%3B%20%7D%2Eir%20a%3Aafter%2C%20a%5Bhref%5E%3D%22javascript%3A%22%5D%3Aafter%2C%20a%5Bhref%5E%3D%22%23%22%5D%3Aafter%20%7B%20content%3A%20%22%22%3B%20%7Dpre%2C%20blockquote%20%7B%20border%3A%201px%20solid%20%23999%3B%20padding%2Dright%3A%201em%3B%20page%2Dbreak%2Dinside%3A%20avoid%3B%20%7Dtr%2C%20img%20%7B%20page%2Dbreak%2Dinside%3A%20avoid%3B%20%7Dimg%20%7B%20max%2Dwidth%3A%20100%25%20%21important%3B%20%7D%40page%20%3Aleft%20%7B%20margin%3A%2015mm%2020mm%2015mm%2010mm%3B%20%7D%40page%20%3Aright%20%7B%20margin%3A%2015mm%2010mm%2015mm%2020mm%3B%20%7Dp%2C%20h2%2C%20h3%20%7B%20orphans%3A%203%3B%20widows%3A%203%3B%20%7Dh2%2C%20h3%20%7B%20page%2Dbreak%2Dafter%3A%20avoid%3B%20%7D%7D" />
   <!--[if lt IE 9]>
     <script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
   <![endif]-->
 </head>
 <body>
 <header id="title-block-header">
-<h1 class="title">pandoc-plot 1.0.0.0 manual</h1>
+<h1 class="title">pandoc-plot 1.0.1.0 manual</h1>
 </header>
 <!--
 The file MANUAL.md is automatically generated by the tools/mkmanual.ps1 script. Do not edit manually.
@@ -184,23 +185,23 @@ <span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a></span>
 <span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a>As you can see in @fig:myexample, ...</span></code></pre></div>
 <p>If the above source is located in file <code>myfile.md</code>, you can render the figure and references by applying <code>pandoc-plot</code> <strong>first</strong>, and then <code>pandoc-crossref</code>. For example:</p>
-<div class="sourceCode" id="cb10"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc</span> --filter pandoc-plot --filter pandoc-crossref -i myfile.md -o myfile.html</span></code></pre></div>
+<div class="sourceCode" id="cb10"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc</span> <span class="at">--filter</span> pandoc-plot <span class="at">--filter</span> pandoc-crossref <span class="at">-i</span> myfile.md <span class="at">-o</span> myfile.html</span></code></pre></div>
 <h2 id="detailed-usage">Detailed usage</h2>
 <p><code>pandoc-plot</code> is a command line executable with a few functions. You can take a look at the help using the <code>-h</code>/<code>--help</code> flag:</p>
-<div class="sourceCode" id="cb11"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc-plot</span> 0.9.4.0 - generate figures directly in documents</span>
+<div class="sourceCode" id="cb11"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc-plot</span> 1.0.1.0 <span class="at">-</span> generate figures directly in documents</span>
 <span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="ex">Usage</span>: pandoc-plot.EXE [(-v<span class="kw">|</span><span class="ex">--version</span>) <span class="kw">|</span> <span class="ex">--full-version</span> <span class="kw">|</span> <span class="kw">(</span><span class="ex">-m</span><span class="kw">|</span><span class="ex">--manual</span><span class="kw">)</span>] </span>
-<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>                       [<span class="ex">COMMAND</span>] [AST]</span>
+<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a><span class="ex">Usage:</span> pandoc-plot.EXE [<span class="er">(</span><span class="ex">-v</span><span class="kw">|</span><span class="ex">--version</span><span class="kw">)</span> <span class="kw">|</span> <span class="ex">--full-version</span> <span class="kw">|</span> <span class="kw">(</span><span class="ex">-m</span><span class="kw">|</span><span class="ex">--manual</span><span class="kw">)</span><span class="ex">]</span> </span>
+<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a>                       <span class="ex">[COMMAND]</span> [AST]</span>
 <span id="cb11-5"><a href="#cb11-5" aria-hidden="true" tabindex="-1"></a>  <span class="ex">This</span> pandoc filter generates plots from code blocks using a multitude of</span>
 <span id="cb11-6"><a href="#cb11-6" aria-hidden="true" tabindex="-1"></a>  <span class="ex">possible</span> renderers. This allows to keep documentation and figures in perfect</span>
 <span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a>  <span class="ex">synchronicity.</span></span>
 <span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a></span>
 <span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="ex">Available</span> options:</span>
-<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>  <span class="ex">-v</span>,--version             Show version number and exit.</span>
+<span id="cb11-10"><a href="#cb11-10" aria-hidden="true" tabindex="-1"></a>  <span class="ex">-v,--version</span>             Show version number and exit.</span>
 <span id="cb11-11"><a href="#cb11-11" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--full-version</span>           Show full version information and exit.</span>
-<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>  <span class="ex">-m</span>,--manual              Open the manual page in the default web browser and</span>
+<span id="cb11-12"><a href="#cb11-12" aria-hidden="true" tabindex="-1"></a>  <span class="ex">-m,--manual</span>              Open the manual page in the default web browser and</span>
 <span id="cb11-13"><a href="#cb11-13" aria-hidden="true" tabindex="-1"></a>                           <span class="ex">exit.</span></span>
-<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>  <span class="ex">-h</span>,--help                Show this help text</span>
+<span id="cb11-14"><a href="#cb11-14" aria-hidden="true" tabindex="-1"></a>  <span class="ex">-h,--help</span>                Show this help text</span>
 <span id="cb11-15"><a href="#cb11-15" aria-hidden="true" tabindex="-1"></a></span>
 <span id="cb11-16"><a href="#cb11-16" aria-hidden="true" tabindex="-1"></a><span class="ex">Available</span> commands:</span>
 <span id="cb11-17"><a href="#cb11-17" aria-hidden="true" tabindex="-1"></a>  <span class="ex">toolkits</span>                 Show information on toolkits and exit.</span>
@@ -209,14 +210,14 @@ <span id="cb11-20"><a href="#cb11-20" aria-hidden="true" tabindex="-1"></a>                           <span class="ex">those</span> directories will be deleted.</span>
 <span id="cb11-21"><a href="#cb11-21" aria-hidden="true" tabindex="-1"></a>  <span class="ex">write-example-config</span>     Write example configuration to a file and exit.</span>
 <span id="cb11-22"><a href="#cb11-22" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a><span class="ex">More</span> information can be found via the manual (pandoc-plot --manual) <span class="ex">or</span> the</span>
+<span id="cb11-23"><a href="#cb11-23" aria-hidden="true" tabindex="-1"></a><span class="ex">More</span> information can be found via the manual <span class="er">(</span><span class="ex">pandoc-plot</span> <span class="at">--manual</span><span class="kw">)</span> <span class="ex">or</span> the</span>
 <span id="cb11-24"><a href="#cb11-24" aria-hidden="true" tabindex="-1"></a><span class="ex">repository</span> README, located at https://github.com/LaurentRDC/pandoc-plot</span></code></pre></div>
 <h3 id="as-a-filter">As a filter</h3>
 <p>The most common use for <code>pandoc-plot</code> is as a pandoc filter, in which case it should be called without arguments. For example:</p>
-<div class="sourceCode" id="cb12"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc</span> --filter pandoc-plot -i input.md -o output.html</span></code></pre></div>
+<div class="sourceCode" id="cb12"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc</span> <span class="at">--filter</span> pandoc-plot <span class="at">-i</span> input.md <span class="at">-o</span> output.html</span></code></pre></div>
 <p>If <code>pandoc-plot</code> fails to render a code block into a figure, the filtering will not stop. Your code blocks will stay unchanged.</p>
 <p>You can chain other filters with it (e.g., <a href="https://github.com/lierdakil/pandoc-crossref"><code>pandoc-crossref</code></a>) like so:</p>
-<div class="sourceCode" id="cb13"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc</span> --filter pandoc-plot --filter pandoc-crossref -i input.md -o output.html</span></code></pre></div>
+<div class="sourceCode" id="cb13"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc</span> <span class="at">--filter</span> pandoc-plot <span class="at">--filter</span> pandoc-crossref <span class="at">-i</span> input.md <span class="at">-o</span> output.html</span></code></pre></div>
 <h3 id="syntax">Syntax</h3>
 <p>The syntax for code blocks in documents is shown below. <code>pandoc-plot</code> looks for code blocks with a specific class, depending on the toolkit you want to use. <code>pandoc-plot</code> will run the code and capture the figure output. There can only be <strong>one</strong> figure per code block.</p>
 <p>The possible parameters and options are described in <a href="#parameters-and-options">further below</a>.</p>
@@ -236,26 +237,28 @@ <span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="in">      directory=(path) </span></span>
 <span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a><span class="in">      caption=(text) </span></span>
 <span id="cb16-5"><a href="#cb16-5" aria-hidden="true" tabindex="-1"></a><span class="in">      format=(PNG|PDF|SVG|JPG|EPS|GIF|TIF|WEBP|HTML) </span></span>
-<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="in">      source=(true|false) </span></span>
-<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="in">      preamble=(path) </span></span>
-<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a><span class="in">      dpi=(integer)</span></span>
-<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a><span class="in">      dependencies=[...]</span></span>
-<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a><span class="in">      file=(path)</span></span>
-<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a><span class="in">      executable=(path) </span></span>
-<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a><span class="in">      caption_format=(text)</span></span>
-<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a><span class="in">      }</span></span>
-<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a><span class="in">  # script content</span></span>
-<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a><span class="in">  ```</span></span></code></pre></div>
+<span id="cb16-6"><a href="#cb16-6" aria-hidden="true" tabindex="-1"></a><span class="in">      source=(true|True|false|False) </span></span>
+<span id="cb16-7"><a href="#cb16-7" aria-hidden="true" tabindex="-1"></a><span class="in">      source_label=(text)</span></span>
+<span id="cb16-8"><a href="#cb16-8" aria-hidden="true" tabindex="-1"></a><span class="in">      preamble=(path) </span></span>
+<span id="cb16-9"><a href="#cb16-9" aria-hidden="true" tabindex="-1"></a><span class="in">      dpi=(integer)</span></span>
+<span id="cb16-10"><a href="#cb16-10" aria-hidden="true" tabindex="-1"></a><span class="in">      dependencies=[...]</span></span>
+<span id="cb16-11"><a href="#cb16-11" aria-hidden="true" tabindex="-1"></a><span class="in">      file=(path)</span></span>
+<span id="cb16-12"><a href="#cb16-12" aria-hidden="true" tabindex="-1"></a><span class="in">      executable=(path) </span></span>
+<span id="cb16-13"><a href="#cb16-13" aria-hidden="true" tabindex="-1"></a><span class="in">      caption_format=(text)</span></span>
+<span id="cb16-14"><a href="#cb16-14" aria-hidden="true" tabindex="-1"></a><span class="in">      }</span></span>
+<span id="cb16-15"><a href="#cb16-15" aria-hidden="true" tabindex="-1"></a><span class="in">  # script content</span></span>
+<span id="cb16-16"><a href="#cb16-16" aria-hidden="true" tabindex="-1"></a><span class="in">  ```</span></span></code></pre></div>
 <ul>
 <li><code>cls</code> must be one of the following: <code>matplotlib</code>, <code>matlabplot</code>, <code>plotly_python</code>, <code>plotly_r</code>, <code>mathplot</code>, <code>octaveplot</code>, <code>ggplot2</code>, <code>gnuplot</code>, <code>graphviz</code>, <code>bokeh</code>, <code>plotsjl</code>.</li>
 </ul>
-<p>All following parameters are optional, with their default values controlled by the <a href="#configuration">configuration</a></p>
+<p>All following parameters are optional, with their default values controlled by the <a href="#configuration">configuration</a>.</p>
 <ul>
 <li><code>language</code> specifies the programming language used in this block. This parameter is ignored by <code>pandoc-plot</code>, but your text editor may use it to highlight code. See <a href="#code-highlighting">Code highlighting</a> below.</li>
 <li><code>directory</code> is a path to the directory where the figure and source code will be saved. You cannot control the file name. This path is either absolute, or relative from the working directory where you call <code>pandoc-plot</code>.</li>
 <li><code>caption</code> is the caption text. The format of the caption is specified in the <code>caption_format</code> parameter, described below.</li>
 <li><code>format</code> is the desired filetype for the resulting figure. Possible values for <code>format</code> are [<code>PNG</code>, <code>PDF</code>, <code>SVG</code>, <code>JPG</code>, <code>EPS</code>, <code>GIF</code>, <code>TIF</code>, <code>WEBP</code>, <code>HTML</code>]. Not all toolkits support all formats. See <code>pandoc-plot toolkits</code> for toolkit-specific information regarding save formats. The <code>HTML</code> format is special; it can produce standalone, offline, interactive plots. As such, it only makes sense to use this format when creating HTML documents.</li>
 <li><code>source</code> is a boolean toggle that determines whether the source code should be linked in the caption or not. Possible values are [<code>true</code>, <code>True</code>, <code>false</code>, <code>False</code>].</li>
+<li><code>source_label</code> is the text that links to source code (if <code>source=true</code>). This is useful if you are writing text in a different language. The default is <code>source_label=&quot;Source Code&quot;</code>. You might want to set this via the <a href="#configuration">configuration</a> instead.</li>
 <li><code>preamble</code> is a path to a script that will be included as a preamble to the content of the code block. This path is either absolute, or relative from the working directory where you call <code>pandoc-plot</code>.</li>
 <li><code>dpi</code> is the pixel density of the figure in dots-per-inch. Possible values are positive integers. Not all toolkits respect this.</li>
 <li><code>dependencies</code> is a list of files/directories that affect the figure, for example data files. If one of those files/directories changes, <code>pandoc-plot</code> will re-render the associated figure. Format is a comma-separated list, e.g. <code>dependencies=[data.txt, foo.bar, ~/wtv]</code>. Values for <code>dependencies</code> in the configuration file will be appended to the values in a code block.</li>
@@ -285,115 +288,120 @@ <p>Interactive HTML figures are available for a few toolkits, e.g. <code>bokeh</code>. To make a figure interactive, use the output format <code>format=html</code>. This only makes sense if your output file is also HTML.</p>
 <p>You can take a look at the <a href="https://laurentrdc.github.io/pandoc-plot/">demonstration page</a> for an example result.</p>
 <p>Many interactive plots rely on javascript scripts stored on the internet. If you want to have a self-contained document that can be viewed offline – or you want your document to work for the next 10 years –, you can use pandoc’s <code>--self-contained</code> flag:</p>
-<div class="sourceCode" id="cb21"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc</span> --self-contained --filter pandoc-plot -i mydoc.md -o webpage.html </span></code></pre></div>
+<div class="sourceCode" id="cb21"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc</span> <span class="at">--self-contained</span> <span class="at">--filter</span> pandoc-plot <span class="at">-i</span> mydoc.md <span class="at">-o</span> webpage.html </span></code></pre></div>
 <p>The resulting output <code>webpage.html</code> will contain everything, at the cost of size.</p>
 <h3 id="configuration">Configuration</h3>
 <p>To avoid repetition, <code>pandoc-plot</code> can be configured using simple YAML
 files. Here are <strong>all</strong> the possible parameters:</p>
-<div class="sourceCode" id="cb22"><pre class="sourceCode yaml"><code class="sourceCode yaml"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="co"># This is an example configuration. Everything in this file is optional.</span></span>
-<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="co"># Please refer to the documentation to know about the parameters herein.</span></span>
-<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a><span class="co">#</span></span>
-<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a><span class="co"># The `executable` parameter for all toolkits can be either the</span></span>
-<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a><span class="co"># executable name (if it is present on the PATH), or</span></span>
-<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a><span class="co"># the full path to the executable.</span></span>
-<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a><span class="co"># E.g.:</span></span>
-<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a><span class="co">#  executable: python3</span></span>
-<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a><span class="co">#  executable: &quot;C:\Python37\Scripts\python.exe&quot;</span></span>
-<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a><span class="co"># The following parameters affect all toolkits</span></span>
-<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a><span class="co"># Directory where to save the plots. The path can be relative to pandoc-plot&#39;s</span></span>
-<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a><span class="co"># current working directory, or absolute.</span></span>
-<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a><span class="fu">directory</span><span class="kw">:</span><span class="at"> plots/</span></span>
-<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a><span class="co"># Whether or not to include a link to the source script in the caption. </span></span>
-<span id="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a><span class="co"># Particularly useful for HTML output.</span></span>
-<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a><span class="fu">source</span><span class="kw">:</span><span class="at"> </span><span class="ch">false</span></span>
-<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a><span class="co"># Default density of figures in dots per inches (DPI). </span></span>
-<span id="cb22-22"><a href="#cb22-22" aria-hidden="true" tabindex="-1"></a><span class="co"># This can be changed in the document specifically as well.</span></span>
-<span id="cb22-23"><a href="#cb22-23" aria-hidden="true" tabindex="-1"></a><span class="fu">dpi</span><span class="kw">:</span><span class="at"> </span><span class="dv">80</span></span>
+<div class="sourceCode" id="cb22"><pre class="sourceCode yaml"><code class="sourceCode yaml"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="co"># This is an example configuration. Everything in this file is optional.</span></span>
+<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a><span class="co"># Please refer to the documentation to know about the parameters herein.</span></span>
+<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="co">#</span></span>
+<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a><span class="co"># The `executable` parameter for all toolkits can be either the</span></span>
+<span id="cb22-5"><a href="#cb22-5" aria-hidden="true" tabindex="-1"></a><span class="co"># executable name (if it is present on the PATH), or</span></span>
+<span id="cb22-6"><a href="#cb22-6" aria-hidden="true" tabindex="-1"></a><span class="co"># the full path to the executable.</span></span>
+<span id="cb22-7"><a href="#cb22-7" aria-hidden="true" tabindex="-1"></a><span class="co"># E.g.:</span></span>
+<span id="cb22-8"><a href="#cb22-8" aria-hidden="true" tabindex="-1"></a><span class="co">#  executable: python3</span></span>
+<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a><span class="co">#  executable: &quot;C:\Python37\Scripts\python.exe&quot;</span></span>
+<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a><span class="co"># The following parameters affect all toolkits</span></span>
+<span id="cb22-12"><a href="#cb22-12" aria-hidden="true" tabindex="-1"></a><span class="co"># Directory where to save the plots. The path can be relative to pandoc-plot&#39;s</span></span>
+<span id="cb22-13"><a href="#cb22-13" aria-hidden="true" tabindex="-1"></a><span class="co"># current working directory, or absolute.</span></span>
+<span id="cb22-14"><a href="#cb22-14" aria-hidden="true" tabindex="-1"></a><span class="fu">directory</span><span class="kw">:</span><span class="at"> plots/</span></span>
+<span id="cb22-15"><a href="#cb22-15" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb22-16"><a href="#cb22-16" aria-hidden="true" tabindex="-1"></a><span class="co"># Whether or not to include a link to the source script in the caption. </span></span>
+<span id="cb22-17"><a href="#cb22-17" aria-hidden="true" tabindex="-1"></a><span class="co"># Particularly useful for HTML output.</span></span>
+<span id="cb22-18"><a href="#cb22-18" aria-hidden="true" tabindex="-1"></a><span class="fu">source</span><span class="kw">:</span><span class="at"> </span><span class="ch">false</span></span>
+<span id="cb22-19"><a href="#cb22-19" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb22-20"><a href="#cb22-20" aria-hidden="true" tabindex="-1"></a><span class="co"># Text label for links to source code.</span></span>
+<span id="cb22-21"><a href="#cb22-21" aria-hidden="true" tabindex="-1"></a><span class="co"># You can change this label if you are writing a document in a non-English language. </span></span>
+<span id="cb22-22"><a href="#cb22-22" aria-hidden="true" tabindex="-1"></a><span class="co"># This only matters if `source` is set to `true`.</span></span>
+<span id="cb22-23"><a href="#cb22-23" aria-hidden="true" tabindex="-1"></a><span class="fu">source_label</span><span class="kw">:</span><span class="at"> Source code</span></span>
 <span id="cb22-24"><a href="#cb22-24" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-25"><a href="#cb22-25" aria-hidden="true" tabindex="-1"></a><span class="co"># Default format in which to save the figures. This can be specified </span></span>
-<span id="cb22-26"><a href="#cb22-26" aria-hidden="true" tabindex="-1"></a><span class="co"># individually as well.</span></span>
-<span id="cb22-27"><a href="#cb22-27" aria-hidden="true" tabindex="-1"></a><span class="fu">format</span><span class="kw">:</span><span class="at"> PNG</span></span>
+<span id="cb22-25"><a href="#cb22-25" aria-hidden="true" tabindex="-1"></a><span class="co"># Default density of figures in dots per inches (DPI). </span></span>
+<span id="cb22-26"><a href="#cb22-26" aria-hidden="true" tabindex="-1"></a><span class="co"># This can be changed in the document specifically as well.</span></span>
+<span id="cb22-27"><a href="#cb22-27" aria-hidden="true" tabindex="-1"></a><span class="fu">dpi</span><span class="kw">:</span><span class="at"> </span><span class="dv">80</span></span>
 <span id="cb22-28"><a href="#cb22-28" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-29"><a href="#cb22-29" aria-hidden="true" tabindex="-1"></a><span class="co"># Default files/directories on which all figures depend. If any of these files/directories</span></span>
-<span id="cb22-30"><a href="#cb22-30" aria-hidden="true" tabindex="-1"></a><span class="co"># changes, all figures will be re-rendered.</span></span>
-<span id="cb22-31"><a href="#cb22-31" aria-hidden="true" tabindex="-1"></a><span class="co"># Dependencies specified in code blocks will be appended to this list.</span></span>
-<span id="cb22-32"><a href="#cb22-32" aria-hidden="true" tabindex="-1"></a><span class="fu">dependencies</span><span class="kw">:</span></span>
-<span id="cb22-33"><a href="#cb22-33" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="kw">-</span><span class="at"> file1.txt</span></span>
-<span id="cb22-34"><a href="#cb22-34" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="kw">-</span><span class="at"> file2.txt</span></span>
-<span id="cb22-35"><a href="#cb22-35" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-36"><a href="#cb22-36" aria-hidden="true" tabindex="-1"></a><span class="co"># Text format for the captions. Unfortunately, there is no way to detect</span></span>
-<span id="cb22-37"><a href="#cb22-37" aria-hidden="true" tabindex="-1"></a><span class="co"># this automatically. You can use the same notation as Pandoc&#39;s --from </span></span>
-<span id="cb22-38"><a href="#cb22-38" aria-hidden="true" tabindex="-1"></a><span class="co"># parameter, specified here: </span></span>
-<span id="cb22-39"><a href="#cb22-39" aria-hidden="true" tabindex="-1"></a><span class="co">#     https://pandoc.org/MANUAL.html#option--from</span></span>
-<span id="cb22-40"><a href="#cb22-40" aria-hidden="true" tabindex="-1"></a><span class="co"># Example: markdown, rst+raw_tex</span></span>
-<span id="cb22-41"><a href="#cb22-41" aria-hidden="true" tabindex="-1"></a><span class="fu">caption_format</span><span class="kw">:</span><span class="at"> markdown+tex_math_dollars</span></span>
-<span id="cb22-42"><a href="#cb22-42" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-43"><a href="#cb22-43" aria-hidden="true" tabindex="-1"></a><span class="co"># Logging configuration</span></span>
-<span id="cb22-44"><a href="#cb22-44" aria-hidden="true" tabindex="-1"></a><span class="fu">logging</span><span class="kw">:</span></span>
-<span id="cb22-45"><a href="#cb22-45" aria-hidden="true" tabindex="-1"></a><span class="co">  # Possible verbosity values: debug, error, warning, info, silent</span></span>
-<span id="cb22-46"><a href="#cb22-46" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">verbosity</span><span class="kw">:</span><span class="at"> warning</span></span>
-<span id="cb22-47"><a href="#cb22-47" aria-hidden="true" tabindex="-1"></a><span class="co">  # If the filepath below is not present, then pandoc-plot will log to stderr</span></span>
-<span id="cb22-48"><a href="#cb22-48" aria-hidden="true" tabindex="-1"></a><span class="co">  # Otherwise, log messages will be appended to the filepath.</span></span>
-<span id="cb22-49"><a href="#cb22-49" aria-hidden="true" tabindex="-1"></a><span class="co">  # filepath: path/to/file.txt</span></span>
-<span id="cb22-50"><a href="#cb22-50" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-51"><a href="#cb22-51" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the Matplotlib toolkit</span></span>
-<span id="cb22-52"><a href="#cb22-52" aria-hidden="true" tabindex="-1"></a><span class="fu">matplotlib</span><span class="kw">:</span></span>
-<span id="cb22-53"><a href="#cb22-53" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: matplotlib.py</span></span>
-<span id="cb22-54"><a href="#cb22-54" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">tight_bbox</span><span class="kw">:</span><span class="at"> </span><span class="ch">false</span></span>
-<span id="cb22-55"><a href="#cb22-55" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">transparent</span><span class="kw">:</span><span class="at"> </span><span class="ch">false</span></span>
-<span id="cb22-56"><a href="#cb22-56" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> python</span></span>
-<span id="cb22-57"><a href="#cb22-57" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-58"><a href="#cb22-58" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the MATLAB toolkit</span></span>
-<span id="cb22-59"><a href="#cb22-59" aria-hidden="true" tabindex="-1"></a><span class="fu">matlabplot</span><span class="kw">:</span></span>
-<span id="cb22-60"><a href="#cb22-60" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: matlab.m</span></span>
-<span id="cb22-61"><a href="#cb22-61" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> matlab</span></span>
+<span id="cb22-29"><a href="#cb22-29" aria-hidden="true" tabindex="-1"></a><span class="co"># Default format in which to save the figures. This can be specified </span></span>
+<span id="cb22-30"><a href="#cb22-30" aria-hidden="true" tabindex="-1"></a><span class="co"># individually as well.</span></span>
+<span id="cb22-31"><a href="#cb22-31" aria-hidden="true" tabindex="-1"></a><span class="fu">format</span><span class="kw">:</span><span class="at"> PNG</span></span>
+<span id="cb22-32"><a href="#cb22-32" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb22-33"><a href="#cb22-33" aria-hidden="true" tabindex="-1"></a><span class="co"># Default files/directories on which all figures depend. If any of these files/directories</span></span>
+<span id="cb22-34"><a href="#cb22-34" aria-hidden="true" tabindex="-1"></a><span class="co"># changes, all figures will be re-rendered.</span></span>
+<span id="cb22-35"><a href="#cb22-35" aria-hidden="true" tabindex="-1"></a><span class="co"># Dependencies specified in code blocks will be appended to this list.</span></span>
+<span id="cb22-36"><a href="#cb22-36" aria-hidden="true" tabindex="-1"></a><span class="fu">dependencies</span><span class="kw">:</span></span>
+<span id="cb22-37"><a href="#cb22-37" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="kw">-</span><span class="at"> file1.txt</span></span>
+<span id="cb22-38"><a href="#cb22-38" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="kw">-</span><span class="at"> file2.txt</span></span>
+<span id="cb22-39"><a href="#cb22-39" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb22-40"><a href="#cb22-40" aria-hidden="true" tabindex="-1"></a><span class="co"># Text format for the captions. Unfortunately, there is no way to detect</span></span>
+<span id="cb22-41"><a href="#cb22-41" aria-hidden="true" tabindex="-1"></a><span class="co"># this automatically. You can use the same notation as Pandoc&#39;s --from </span></span>
+<span id="cb22-42"><a href="#cb22-42" aria-hidden="true" tabindex="-1"></a><span class="co"># parameter, specified here: </span></span>
+<span id="cb22-43"><a href="#cb22-43" aria-hidden="true" tabindex="-1"></a><span class="co">#     https://pandoc.org/MANUAL.html#option--from</span></span>
+<span id="cb22-44"><a href="#cb22-44" aria-hidden="true" tabindex="-1"></a><span class="co"># Example: markdown, rst+raw_tex</span></span>
+<span id="cb22-45"><a href="#cb22-45" aria-hidden="true" tabindex="-1"></a><span class="fu">caption_format</span><span class="kw">:</span><span class="at"> markdown+tex_math_dollars</span></span>
+<span id="cb22-46"><a href="#cb22-46" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb22-47"><a href="#cb22-47" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb22-48"><a href="#cb22-48" aria-hidden="true" tabindex="-1"></a><span class="co"># Logging configuration</span></span>
+<span id="cb22-49"><a href="#cb22-49" aria-hidden="true" tabindex="-1"></a><span class="fu">logging</span><span class="kw">:</span></span>
+<span id="cb22-50"><a href="#cb22-50" aria-hidden="true" tabindex="-1"></a><span class="co">  # Possible verbosity values: debug, error, warning, info, silent</span></span>
+<span id="cb22-51"><a href="#cb22-51" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">verbosity</span><span class="kw">:</span><span class="at"> warning</span></span>
+<span id="cb22-52"><a href="#cb22-52" aria-hidden="true" tabindex="-1"></a><span class="co">  # If the filepath below is not present, then pandoc-plot will log to stderr</span></span>
+<span id="cb22-53"><a href="#cb22-53" aria-hidden="true" tabindex="-1"></a><span class="co">  # Otherwise, log messages will be appended to the filepath.</span></span>
+<span id="cb22-54"><a href="#cb22-54" aria-hidden="true" tabindex="-1"></a><span class="co">  # filepath: path/to/file.txt</span></span>
+<span id="cb22-55"><a href="#cb22-55" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb22-56"><a href="#cb22-56" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the Matplotlib toolkit</span></span>
+<span id="cb22-57"><a href="#cb22-57" aria-hidden="true" tabindex="-1"></a><span class="fu">matplotlib</span><span class="kw">:</span></span>
+<span id="cb22-58"><a href="#cb22-58" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: matplotlib.py</span></span>
+<span id="cb22-59"><a href="#cb22-59" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">tight_bbox</span><span class="kw">:</span><span class="at"> </span><span class="ch">false</span></span>
+<span id="cb22-60"><a href="#cb22-60" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">transparent</span><span class="kw">:</span><span class="at"> </span><span class="ch">false</span></span>
+<span id="cb22-61"><a href="#cb22-61" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> python</span></span>
 <span id="cb22-62"><a href="#cb22-62" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-63"><a href="#cb22-63" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the Plotly/Python toolkit</span></span>
-<span id="cb22-64"><a href="#cb22-64" aria-hidden="true" tabindex="-1"></a><span class="fu">plotly_python</span><span class="kw">:</span></span>
-<span id="cb22-65"><a href="#cb22-65" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: plotly-python.py</span></span>
-<span id="cb22-66"><a href="#cb22-66" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> python</span></span>
+<span id="cb22-63"><a href="#cb22-63" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the MATLAB toolkit</span></span>
+<span id="cb22-64"><a href="#cb22-64" aria-hidden="true" tabindex="-1"></a><span class="fu">matlabplot</span><span class="kw">:</span></span>
+<span id="cb22-65"><a href="#cb22-65" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: matlab.m</span></span>
+<span id="cb22-66"><a href="#cb22-66" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> matlab</span></span>
 <span id="cb22-67"><a href="#cb22-67" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-68"><a href="#cb22-68" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the Plotly/R toolkit</span></span>
-<span id="cb22-69"><a href="#cb22-69" aria-hidden="true" tabindex="-1"></a><span class="fu">plotly_r</span><span class="kw">:</span></span>
-<span id="cb22-70"><a href="#cb22-70" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: plotly-r.r</span></span>
-<span id="cb22-71"><a href="#cb22-71" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> Rscript</span></span>
+<span id="cb22-68"><a href="#cb22-68" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the Plotly/Python toolkit</span></span>
+<span id="cb22-69"><a href="#cb22-69" aria-hidden="true" tabindex="-1"></a><span class="fu">plotly_python</span><span class="kw">:</span></span>
+<span id="cb22-70"><a href="#cb22-70" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: plotly-python.py</span></span>
+<span id="cb22-71"><a href="#cb22-71" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> python</span></span>
 <span id="cb22-72"><a href="#cb22-72" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-73"><a href="#cb22-73" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the Mathematica toolkit</span></span>
-<span id="cb22-74"><a href="#cb22-74" aria-hidden="true" tabindex="-1"></a><span class="fu">mathplot</span><span class="kw">:</span></span>
-<span id="cb22-75"><a href="#cb22-75" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: mathematica.m</span></span>
-<span id="cb22-76"><a href="#cb22-76" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> math</span></span>
+<span id="cb22-73"><a href="#cb22-73" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the Plotly/R toolkit</span></span>
+<span id="cb22-74"><a href="#cb22-74" aria-hidden="true" tabindex="-1"></a><span class="fu">plotly_r</span><span class="kw">:</span></span>
+<span id="cb22-75"><a href="#cb22-75" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: plotly-r.r</span></span>
+<span id="cb22-76"><a href="#cb22-76" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> Rscript</span></span>
 <span id="cb22-77"><a href="#cb22-77" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-78"><a href="#cb22-78" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the GNU Octave toolkit</span></span>
-<span id="cb22-79"><a href="#cb22-79" aria-hidden="true" tabindex="-1"></a><span class="fu">octaveplot</span><span class="kw">:</span></span>
-<span id="cb22-80"><a href="#cb22-80" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: octave.m</span></span>
-<span id="cb22-81"><a href="#cb22-81" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> octave</span></span>
+<span id="cb22-78"><a href="#cb22-78" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the Mathematica toolkit</span></span>
+<span id="cb22-79"><a href="#cb22-79" aria-hidden="true" tabindex="-1"></a><span class="fu">mathplot</span><span class="kw">:</span></span>
+<span id="cb22-80"><a href="#cb22-80" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: mathematica.m</span></span>
+<span id="cb22-81"><a href="#cb22-81" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> math</span></span>
 <span id="cb22-82"><a href="#cb22-82" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-83"><a href="#cb22-83" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the ggplot2 toolkit</span></span>
-<span id="cb22-84"><a href="#cb22-84" aria-hidden="true" tabindex="-1"></a><span class="fu">ggplot2</span><span class="kw">:</span></span>
-<span id="cb22-85"><a href="#cb22-85" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: ggplot2.r</span></span>
-<span id="cb22-86"><a href="#cb22-86" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> Rscript</span></span>
+<span id="cb22-83"><a href="#cb22-83" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the GNU Octave toolkit</span></span>
+<span id="cb22-84"><a href="#cb22-84" aria-hidden="true" tabindex="-1"></a><span class="fu">octaveplot</span><span class="kw">:</span></span>
+<span id="cb22-85"><a href="#cb22-85" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: octave.m</span></span>
+<span id="cb22-86"><a href="#cb22-86" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> octave</span></span>
 <span id="cb22-87"><a href="#cb22-87" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-88"><a href="#cb22-88" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the gnuplot toolkit</span></span>
-<span id="cb22-89"><a href="#cb22-89" aria-hidden="true" tabindex="-1"></a><span class="fu">gnuplot</span><span class="kw">:</span></span>
-<span id="cb22-90"><a href="#cb22-90" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: gnuplot.gp</span></span>
-<span id="cb22-91"><a href="#cb22-91" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> gnuplot</span></span>
+<span id="cb22-88"><a href="#cb22-88" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the ggplot2 toolkit</span></span>
+<span id="cb22-89"><a href="#cb22-89" aria-hidden="true" tabindex="-1"></a><span class="fu">ggplot2</span><span class="kw">:</span></span>
+<span id="cb22-90"><a href="#cb22-90" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: ggplot2.r</span></span>
+<span id="cb22-91"><a href="#cb22-91" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> Rscript</span></span>
 <span id="cb22-92"><a href="#cb22-92" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-93"><a href="#cb22-93" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the graphviz toolkit</span></span>
-<span id="cb22-94"><a href="#cb22-94" aria-hidden="true" tabindex="-1"></a><span class="fu">graphviz</span><span class="kw">:</span></span>
-<span id="cb22-95"><a href="#cb22-95" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: graphviz.dot</span></span>
-<span id="cb22-96"><a href="#cb22-96" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> dot</span></span>
+<span id="cb22-93"><a href="#cb22-93" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the gnuplot toolkit</span></span>
+<span id="cb22-94"><a href="#cb22-94" aria-hidden="true" tabindex="-1"></a><span class="fu">gnuplot</span><span class="kw">:</span></span>
+<span id="cb22-95"><a href="#cb22-95" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: gnuplot.gp</span></span>
+<span id="cb22-96"><a href="#cb22-96" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> gnuplot</span></span>
 <span id="cb22-97"><a href="#cb22-97" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-98"><a href="#cb22-98" aria-hidden="true" tabindex="-1"></a><span class="fu">bokeh</span><span class="kw">:</span></span>
-<span id="cb22-99"><a href="#cb22-99" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: bokeh.py</span></span>
-<span id="cb22-100"><a href="#cb22-100" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> python</span></span>
-<span id="cb22-101"><a href="#cb22-101" aria-hidden="true" tabindex="-1"></a></span>
-<span id="cb22-102"><a href="#cb22-102" aria-hidden="true" tabindex="-1"></a><span class="fu">plotsjl</span><span class="kw">:</span></span>
-<span id="cb22-103"><a href="#cb22-103" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: plotsjl.jl</span></span>
-<span id="cb22-104"><a href="#cb22-104" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> julia</span></span></code></pre></div>
+<span id="cb22-98"><a href="#cb22-98" aria-hidden="true" tabindex="-1"></a><span class="co"># The possible parameters for the graphviz toolkit</span></span>
+<span id="cb22-99"><a href="#cb22-99" aria-hidden="true" tabindex="-1"></a><span class="fu">graphviz</span><span class="kw">:</span></span>
+<span id="cb22-100"><a href="#cb22-100" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: graphviz.dot</span></span>
+<span id="cb22-101"><a href="#cb22-101" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> dot</span></span>
+<span id="cb22-102"><a href="#cb22-102" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb22-103"><a href="#cb22-103" aria-hidden="true" tabindex="-1"></a><span class="fu">bokeh</span><span class="kw">:</span></span>
+<span id="cb22-104"><a href="#cb22-104" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: bokeh.py</span></span>
+<span id="cb22-105"><a href="#cb22-105" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> python</span></span>
+<span id="cb22-106"><a href="#cb22-106" aria-hidden="true" tabindex="-1"></a></span>
+<span id="cb22-107"><a href="#cb22-107" aria-hidden="true" tabindex="-1"></a><span class="fu">plotsjl</span><span class="kw">:</span></span>
+<span id="cb22-108"><a href="#cb22-108" aria-hidden="true" tabindex="-1"></a><span class="co">  # preamble: plotsjl.jl</span></span>
+<span id="cb22-109"><a href="#cb22-109" aria-hidden="true" tabindex="-1"></a><span class="at">  </span><span class="fu">executable</span><span class="kw">:</span><span class="at"> julia</span></span></code></pre></div>
 <p>A file like the above sets the <strong>default</strong> values; you can still override them in documents directly.</p>
 <p>The easiest way to specify configuration for <code>pandoc-plot</code> is to place a <code>.pandoc-plot.yml</code> file in the current working directory. You can also specify a configuration file in document metadata, under the <code>plot-configuration</code> key. For example, in Markdown:</p>
 <div class="sourceCode" id="cb23"><pre class="sourceCode markdown"><code class="sourceCode markdown"><span id="cb23-1"><a href="#cb23-1" aria-hidden="true" tabindex="-1"></a><span class="co">---</span></span>
@@ -402,7 +410,7 @@ <span id="cb23-4"><a href="#cb23-4" aria-hidden="true" tabindex="-1"></a><span class="an">plot-configuration:</span><span class="co"> /path/to/file.yml</span></span>
 <span id="cb23-5"><a href="#cb23-5" aria-hidden="true" tabindex="-1"></a><span class="co">---</span></span></code></pre></div>
 <p>or on the command line, using the pandoc <code>-M/--metadata</code> flag:</p>
-<div class="sourceCode" id="cb24"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc</span> --filter pandoc-plot -M plot-configuration=/path/to/file.yml ...</span></code></pre></div>
+<div class="sourceCode" id="cb24"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc</span> <span class="at">--filter</span> pandoc-plot <span class="at">-M</span> plot-configuration=/path/to/file.yml ...</span></code></pre></div>
 <p>The hierarchy of configuration files is as follows:</p>
 <ol type="1">
 <li>A configuration file specified in the metadata under the <code>plot-configuration</code> key;</li>
@@ -437,36 +445,36 @@ <h3 id="other-commands">Other commands</h3>
 <h4 id="finding-installed-toolkits">Finding installed toolkits</h4>
 <p>You can determine which toolkits are available on your current machine using the <code>pandoc-plot toolkits</code> command. Here is the full help text:</p>
-<div class="sourceCode" id="cb28"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="ex">Usage</span>: pandoc-plot.EXE toolkits [--config PATH]</span>
+<div class="sourceCode" id="cb28"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="ex">Usage:</span> pandoc-plot.EXE toolkits [--config PATH]</span>
 <span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a>  <span class="ex">Show</span> information on toolkits and exit.</span>
 <span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a></span>
 <span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a><span class="ex">Available</span> options:</span>
 <span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--config</span> PATH            Path to optional configuration file.</span>
-<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>  <span class="ex">-h</span>,--help                Show this help text</span></code></pre></div>
+<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a>  <span class="ex">-h,--help</span>                Show this help text</span></code></pre></div>
 <h4 id="cleaning-output">Cleaning output</h4>
 <p>Figures produced by <code>pandoc-plot</code> can be placed in a few different locations. You can set a default location in the <a href="#configuration">Configuration</a>, but you can also re-direct specific figures in other directories if you use the <code>directory=...</code> argument in code blocks. These figures will build up over time. You can use the <code>clean</code> command to scan documents and delete the associated <code>pandoc-plot</code> output files. For example, to delete the figures generated from the <code>input.md</code> file:</p>
 <div class="sourceCode" id="cb29"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc-plot</span> clean input.md</span></code></pre></div>
 <p>This sill remove all directories where a figure <em>could</em> have been placed. <strong>WARNING</strong>: all files will be removed.</p>
 <p>Here is the full help text for the <code>clean</code> command:</p>
-<div class="sourceCode" id="cb30"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="ex">Usage</span>: pandoc-plot.EXE clean [--config PATH] FILE</span>
+<div class="sourceCode" id="cb30"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="ex">Usage:</span> pandoc-plot.EXE clean [--config PATH] FILE</span>
 <span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a>  <span class="ex">Clean</span> output directories where figures from FILE and log files might be</span>
 <span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a>  <span class="ex">stored.</span> WARNING: All files in those directories will be deleted.</span>
 <span id="cb30-4"><a href="#cb30-4" aria-hidden="true" tabindex="-1"></a></span>
 <span id="cb30-5"><a href="#cb30-5" aria-hidden="true" tabindex="-1"></a><span class="ex">Available</span> options:</span>
 <span id="cb30-6"><a href="#cb30-6" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--config</span> PATH            Path to optional configuration file.</span>
-<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a>  <span class="ex">-h</span>,--help                Show this help text</span></code></pre></div>
+<span id="cb30-7"><a href="#cb30-7" aria-hidden="true" tabindex="-1"></a>  <span class="ex">-h,--help</span>                Show this help text</span></code></pre></div>
 <h4 id="configuration-template">Configuration template</h4>
 <p>Because <code>pandoc-plot</code> supports a few toolkits, there are a lot of configuration options. Don’t start from scratch! The <code>write-example-config</code> command will create a file for you, which you can then modify:</p>
 <div class="sourceCode" id="cb31"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="ex">pandoc-plot</span> write-example-config</span></code></pre></div>
 <p>You will need to re-name the file to <code>.pandoc-ploy.yml</code> to be able to use it, so don’t worry about overwriting your own configuration.</p>
 <p>Here is the full help text for the <code>write-example-config</code> command:</p>
-<div class="sourceCode" id="cb32"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="ex">Usage</span>: pandoc-plot.EXE write-example-config [--path FILE]</span>
+<div class="sourceCode" id="cb32"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="ex">Usage:</span> pandoc-plot.EXE write-example-config [--path FILE]</span>
 <span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a>  <span class="ex">Write</span> example configuration to a file and exit.</span>
 <span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a></span>
 <span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a><span class="ex">Available</span> options:</span>
 <span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a>  <span class="ex">--path</span> FILE              Target location of the configuration file. Default is</span>
 <span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a>                           <span class="st">&quot;.example-pandoc-plot.yml&quot;</span></span>
-<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>  <span class="ex">-h</span>,--help                Show this help text</span></code></pre></div>
+<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a>  <span class="ex">-h,--help</span>                Show this help text</span></code></pre></div>
 <h2 id="warning">Warning</h2>
 <p>Do not run this filter on unknown documents. There is nothing in
 <code>pandoc-plot</code> that can stop a script from performing <strong>evil actions</strong>.</p>
example-config.yml view
@@ -18,6 +18,11 @@ # Particularly useful for HTML output.
 source: false
 
+# Text label for links to source code.
+# You can change this label if you are writing a document in a non-English language. 
+# This only matters if `source` is set to `true`.
+source_label: Source code
+
 # Default density of figures in dots per inches (DPI). 
 # This can be changed in the document specifically as well.
 dpi: 80
@@ -39,6 +44,7 @@ #     https://pandoc.org/MANUAL.html#option--from
 # Example: markdown, rst+raw_tex
 caption_format: markdown+tex_math_dollars
+
 
 # Logging configuration
 logging:
executable/ExampleConfig.hs view
@@ -1,13 +1,11 @@ {-# LANGUAGE TemplateHaskellQuotes #-}
 
-module ExampleConfig ( embedExampleConfig ) where
-
-
-import           Data.String
-import           Data.Text                  (unpack)
-import qualified Data.Text.IO               as TIO
+module ExampleConfig (embedExampleConfig) where
 
-import           Language.Haskell.TH.Syntax
+import Data.String
+import Data.Text (unpack)
+import qualified Data.Text.IO as TIO
+import Language.Haskell.TH.Syntax
 
 docFile :: FilePath
 docFile = "example-config.yml"
@@ -17,9 +15,9 @@ 
 embedExampleConfig :: Q Exp
 embedExampleConfig = do
-    qAddDependentFile docFile
-    s <- runIO readDocFile
-    strToExp s
-    where
-        strToExp :: String -> Q Exp
-        strToExp s = return $ VarE 'fromString `AppE` LitE (StringL s)+  qAddDependentFile docFile
+  s <- runIO readDocFile
+  strToExp s
+  where
+    strToExp :: String -> Q Exp
+    strToExp s = return $ VarE 'fromString `AppE` LitE (StringL s)
executable/Main.hs view
@@ -1,282 +1,312 @@-{-# LANGUAGE ApplicativeDo     #-}
-{-# LANGUAGE LambdaCase        #-}
-{-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE TemplateHaskell   #-}
-{-# LANGUAGE RecordWildCards   #-}
+{-# LANGUAGE ApplicativeDo #-}
 {-# LANGUAGE CPP #-}
+{-# LANGUAGE LambdaCase #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TemplateHaskell #-}
 
 module Main where
 
-import           Control.Monad                    (join, when, msum)
-
-import           Data.List                        (intersperse, (\\))
-import           Data.Maybe                       (fromJust)
-import           Data.Text                        (unpack)
-import qualified Data.Text.IO                     as TIO
-import           Data.Version                     (parseVersion, showVersion)
-
-import           GHC.IO.Encoding                  (setLocaleEncoding, utf8)
-import           GitHash                          as Git
-
-import           Options.Applicative
-import qualified Options.Applicative.Help.Pretty  as P
-
-import           System.Directory                 (doesFileExist, getTemporaryDirectory)
-import           System.Environment               (lookupEnv)
-import           System.FilePath                  ((</>))
-import           System.IO                        (hPutStrLn, stderr)
-
-import           Text.Pandoc.Filter.Plot          (availableToolkits,
-                                                   plotTransform,
-                                                   defaultConfiguration, 
-                                                   configuration, Configuration(..),
-                                                   pandocPlotVersion, )
-import           Text.Pandoc.Filter.Plot.Internal (cls, 
-                                                   supportedSaveFormats, 
-                                                   toolkits, readDoc, 
-                                                   cleanOutputDirs, 
-                                                   configurationPathMeta,
-                                                   executable, runPlotM, Executable(..))
-
-import           Text.Pandoc                      (pandocVersion)
-import           Text.Pandoc.Definition           (pandocTypesVersion)
-import           Text.Pandoc.JSON                 (toJSONFilter)
-
-import           Text.ParserCombinators.ReadP     (readP_to_S)
-
-import           OpenFile                         (openFile)
-
-import qualified Data.Version                     as V
-
-import           ManPage                          (embedManualHtml)
-import           ExampleConfig                    (embedExampleConfig)
+import Control.Monad (join, msum, when)
+import Data.List (intersperse, (\\))
+import Data.Maybe (fromJust)
+import Data.Text (unpack)
+import qualified Data.Text.IO as TIO
+import Data.Version (parseVersion, showVersion)
+import qualified Data.Version as V
+import ExampleConfig (embedExampleConfig)
+import GHC.IO.Encoding (setLocaleEncoding, utf8)
+import GitHash as Git
+import ManPage (embedManualHtml)
+import OpenFile (openFile)
+import Options.Applicative
+import qualified Options.Applicative.Help.Pretty as P
+import System.Directory (doesFileExist, getTemporaryDirectory)
+import System.Environment (lookupEnv)
+import System.FilePath ((</>))
+import System.IO (hPutStrLn, stderr)
+import Text.Pandoc (pandocVersion)
+import Text.Pandoc.Definition (pandocTypesVersion)
+import Text.Pandoc.Filter.Plot
+  ( Configuration (..),
+    availableToolkits,
+    configuration,
+    defaultConfiguration,
+    pandocPlotVersion,
+    plotTransform,
+  )
+import Text.Pandoc.Filter.Plot.Internal
+  ( Executable (..),
+    cleanOutputDirs,
+    cls,
+    configurationPathMeta,
+    executable,
+    readDoc,
+    runPlotM,
+    supportedSaveFormats,
+    toolkits,
+  )
+import Text.Pandoc.JSON (toJSONFilter)
+import Text.ParserCombinators.ReadP (readP_to_S)
 
 -- The difference between commands and flags is that commands require knowledge of
 -- the configuration, while flags only display static information.
 
-data Command = Clean (Maybe FilePath) FilePath
-             | WriteConfig FilePath
-             | Toolkits (Maybe FilePath)
-
-data Flag = Version
-          | FullVersion
-          | Manual
-    deriving (Eq)
+data Command
+  = Clean (Maybe FilePath) FilePath
+  | WriteConfig FilePath
+  | Toolkits (Maybe FilePath)
 
+data Flag
+  = Version
+  | FullVersion
+  | Manual
+  deriving (Eq)
 
 main :: IO ()
-main = join $ execParser opts
-    where 
-        opts = info (optparse <**> helper)
-            (fullDesc
-            <> progDesc (unlines 
-                ["This pandoc filter generates plots from code blocks using a multitude of "
-                , "possible renderers. This allows to keep documentation and figures in"
-                , "perfect synchronicity."
-                ]
-            )
+main = do
+  setLocaleEncoding utf8
+  join $ execParser opts
+  where
+    opts =
+      info
+        (optparse <**> helper)
+        ( fullDesc
+            <> progDesc
+              ( unlines
+                  [ "This pandoc filter generates plots from code blocks using a multitude of ",
+                    "possible renderers. This allows to keep documentation and figures in",
+                    "perfect synchronicity."
+                  ]
+              )
             <> header (mconcat ["pandoc-plot ", V.showVersion pandocPlotVersion, " - generate figures directly in documents"])
             <> footerDoc (Just footer')
-            )
-        
-        optparse = do
-            flag_ <- flagParser
-            command_ <- commandParser
-            -- The extra optional input below only serves to show
-            -- to the user that the last argument is the AST from pandoc
-            -- The parsed input is never used
-            input <- optional $ strArgument (metavar "AST")
-            return $ go flag_ command_ input
-        
-        go :: Maybe Flag -> Maybe Command -> Maybe String -> IO ()
-        go (Just Version)          _ _ = putStrLn (V.showVersion pandocPlotVersion)
-        go (Just FullVersion)      _ _ = showFullVersion
-        go (Just Manual)           _ _ = showManPage
-        go _ (Just (Toolkits mfp))   _ = showAvailableToolkits mfp
-        go _ (Just (Clean mfp fp))   _ = clean mfp fp
-        go _ (Just (WriteConfig fp)) _ = writeFile fp $(embedExampleConfig)
-        go Nothing Nothing           _ = toJSONFilterWithConfig
+        )
 
+    optparse = do
+      flag_ <- flagParser
+      command_ <- commandParser
+      -- The extra optional input below only serves to show
+      -- to the user that the last argument is the AST from pandoc
+      -- The parsed input is never used
+      input <- optional $ strArgument (metavar "AST")
+      return $ go flag_ command_ input
+
+    go :: Maybe Flag -> Maybe Command -> Maybe String -> IO ()
+    go (Just Version) _ _ = putStrLn (V.showVersion pandocPlotVersion)
+    go (Just FullVersion) _ _ = showFullVersion
+    go (Just Manual) _ _ = showManPage
+    go _ (Just (Toolkits mfp)) _ = showAvailableToolkits mfp
+    go _ (Just (Clean mfp fp)) _ = clean mfp fp
+    go _ (Just (WriteConfig fp)) _ = writeFile fp $(embedExampleConfig)
+    go Nothing Nothing _ = toJSONFilterWithConfig
+
 flagParser :: Parser (Maybe Flag)
 flagParser = versionP <|> fullVersionP <|> manualP
-    where
-        versionP = flag Nothing (Just Version) (mconcat
-            [ long "version"
-            , short 'v'
-            , help "Show version number and exit."
-            ])
-        
-        fullVersionP = flag Nothing (Just FullVersion) (mconcat
-            [ long "full-version"
-            , help "Show full version information and exit."
-            ])
+  where
+    versionP =
+      flag
+        Nothing
+        (Just Version)
+        ( mconcat
+            [ long "version",
+              short 'v',
+              help "Show version number and exit."
+            ]
+        )
 
-        manualP  = flag Nothing (Just Manual) (mconcat
-            [ long "manual"
-            , short 'm'
-            , help "Open the manual page in the default web browser and exit."
-            ])
+    fullVersionP =
+      flag
+        Nothing
+        (Just FullVersion)
+        ( mconcat
+            [ long "full-version",
+              help "Show full version information and exit."
+            ]
+        )
 
+    manualP =
+      flag
+        Nothing
+        (Just Manual)
+        ( mconcat
+            [ long "manual",
+              short 'm',
+              help "Open the manual page in the default web browser and exit."
+            ]
+        )
+
 commandParser :: Parser (Maybe Command)
-commandParser = optional $ subparser $ mconcat
-            [ command "toolkits" ( 
-                info (toolkitsP <**> helper) (progDesc "Show information on toolkits and exit.")
-                )  
-            , command "clean" (
-                info (cleanP <**> helper) ( 
-                    progDesc (unlines 
-                        [ "Clean output directories where figures from FILE and log files might be stored."
-                        , "WARNING: All files in those directories will be deleted."
+commandParser =
+  optional $
+    subparser $
+      mconcat
+        [ command
+            "toolkits"
+            ( info (toolkitsP <**> helper) (progDesc "Show information on toolkits and exit.")
+            ),
+          command
+            "clean"
+            ( info
+                (cleanP <**> helper)
+                ( progDesc
+                    ( unlines
+                        [ "Clean output directories where figures from FILE and log files might be stored.",
+                          "WARNING: All files in those directories will be deleted."
                         ]
-                    ) 
+                    )
                 )
+            ),
+          command
+            "write-example-config"
+            ( info (writeConfigP <**> helper) (progDesc "Write example configuration to a file and exit.")
             )
-            , command "write-example-config" (
-                info (writeConfigP <**> helper) (progDesc "Write example configuration to a file and exit.")
-                )
-            ]
-    where
-        configP = optional $ strOption (mconcat [long "config", metavar "PATH", help "Path to optional configuration file."])
-        toolkitsP = Toolkits <$> configP
-        cleanP = Clean <$> configP <*> strArgument (metavar "FILE")
-        writeConfigP = WriteConfig <$> 
-                strOption ( 
-                    mconcat [ long "path"
-                            , metavar "FILE"
-                            , value ".example-pandoc-plot.yml"
-                            , help "Target location of the configuration file. Default is \".example-pandoc-plot.yml\""
-                            ] 
-                          )
+        ]
+  where
+    configP = optional $ strOption (mconcat [long "config", metavar "PATH", help "Path to optional configuration file."])
+    toolkitsP = Toolkits <$> configP
+    cleanP = Clean <$> configP <*> strArgument (metavar "FILE")
+    writeConfigP =
+      WriteConfig
+        <$> strOption
+          ( mconcat
+              [ long "path",
+                metavar "FILE",
+                value ".example-pandoc-plot.yml",
+                help "Target location of the configuration file. Default is \".example-pandoc-plot.yml\""
+              ]
+          )
 
 -- | Determine configuration and run filter.
 --
 -- Priority for configuration:
--- 
+--
 --     (1) Loaded from filepath stored in document metadata, under the key @plot-configuration@;
 --
 --     (2) Loaded from file @.pandoc-plot.yml@ in current work directory;
 --
 --     (3) Default configuration
---
 toJSONFilterWithConfig :: IO ()
 toJSONFilterWithConfig = do
-    upToDatePandoc <- checkRuntimePandocVersion 
-    when upToDatePandoc $ toJSONFilter $ \doc -> do
-        c <- maybe localConfig configuration (configurationPathMeta doc)
-        plotTransform c doc
-
+  upToDatePandoc <- checkRuntimePandocVersion
+  when upToDatePandoc $
+    toJSONFilter $ \doc -> do
+      c <- maybe localConfig configuration (configurationPathMeta doc)
+      plotTransform c doc
 
 -- | Check that the runtime version of Pandoc is at least 2.11. The return value
 -- indicates whether the Pandoc version is new enough or not.
 checkRuntimePandocVersion :: IO Bool
 checkRuntimePandocVersion = do
-    -- Please note that for some reason, makeVersion [2, 11, 0, 0] > makeVersion [2, 11]
-    let minimumPandocVersion = V.makeVersion [2, 11]
-    
-    -- Pandoc runs filters in an environment with two variables:
-    -- PANDOV_VERSION and PANDOC_READER_OPTS
-    -- We can use the former to ensure that people are not using pandoc < 2.11
-    pandocV <- lookupEnv "PANDOC_VERSION"
-    case pandocV >>= readVersion of
-        Nothing -> return True
-        Just v -> if (v < minimumPandocVersion)
-            then do
-                hPutStrLn stderr $ mconcat 
-                    [ "ERROR (pandoc-plot) The pandoc-plot filter only "
-                    , "supports Pandoc 2.11 and newer. "
-                    , "but you are using Pandoc "
-                    , showVersion v
-                    ] 
-                return False 
-            else return True
-    where
-        readVersion = fmap fst . lastMaybe . readP_to_S parseVersion
-        lastMaybe xs = if length xs > 1 then Just (last xs) else Nothing
+  -- Please note that for some reason, makeVersion [2, 11, 0, 0] > makeVersion [2, 11]
+  let minimumPandocVersion = V.makeVersion [2, 11]
 
+  -- Pandoc runs filters in an environment with two variables:
+  -- PANDOV_VERSION and PANDOC_READER_OPTS
+  -- We can use the former to ensure that people are not using pandoc < 2.11
+  pandocV <- lookupEnv "PANDOC_VERSION"
+  case pandocV >>= readVersion of
+    Nothing -> return True
+    Just v ->
+      if (v < minimumPandocVersion)
+        then do
+          hPutStrLn stderr $
+            mconcat
+              [ "ERROR (pandoc-plot) The pandoc-plot filter only ",
+                "supports Pandoc 2.11 and newer. ",
+                "but you are using Pandoc ",
+                showVersion v
+              ]
+          return False
+        else return True
+  where
+    readVersion = fmap fst . lastMaybe . readP_to_S parseVersion
+    lastMaybe xs = if length xs > 1 then Just (last xs) else Nothing
 
--- | Load configuration from local file @.pandoc-plot.yml@. 
+-- | Load configuration from local file @.pandoc-plot.yml@.
 -- If the file does not exist, the default configuration will be used.
 localConfig :: IO Configuration
-localConfig = do 
-    configExists <- doesFileExist ".pandoc-plot.yml"
-    if configExists
-        then configuration ".pandoc-plot.yml"
-        else return defaultConfiguration
-
+localConfig = do
+  configExists <- doesFileExist ".pandoc-plot.yml"
+  if configExists
+    then configuration ".pandoc-plot.yml"
+    else return defaultConfiguration
 
 showFullVersion :: IO ()
 showFullVersion = do
-    putStrLn $ "pandoc-plot " <> (V.showVersion pandocPlotVersion)
-    putStrLn $ "Git revision " <> gitrev
-    putStrLn $ mconcat 
-        [ "Compiled with pandoc " , (unpack pandocVersion)
-        , " and pandoc-types " , V.showVersion pandocTypesVersion
-        , " using GHC ", TOOL_VERSION_ghc -- Constant defined by CPP
-        ]
-    where
-        -- In certain environments (e.g. Hackage when building documentation),
-        -- there is no git information. 
-        gitrev = either (const "unknown") Git.giHash ($$tGitInfoCwdTry)
-
+  putStrLn $ "pandoc-plot " <> (V.showVersion pandocPlotVersion)
+  putStrLn $ "Git revision " <> gitrev
+  putStrLn $
+    mconcat
+      [ "Compiled with pandoc ",
+        (unpack pandocVersion),
+        " and pandoc-types ",
+        V.showVersion pandocTypesVersion,
+        " using GHC ",
+        TOOL_VERSION_ghc -- Constant defined by CPP
+      ]
+  where
+    -- In certain environments (e.g. Hackage when building documentation),
+    -- there is no git information.
+    gitrev = either (const "unknown") Git.giHash ($$tGitInfoCwdTry)
 
 showAvailableToolkits :: Maybe FilePath -> IO ()
 showAvailableToolkits mfp = do
-    c <- case mfp of
-        Nothing -> localConfig
-        Just fp -> configuration fp
-
-    putStrLn "\nAVAILABLE TOOLKITS\n"
-    available <- availableToolkits c
-    return available >>= mapM_ (availToolkitInfo c)
-    putStrLn "\nUNAVAILABLE TOOLKITS\n"
-    -- We don't use unavailableToolkits because this would force
-    -- more IO actions
-    let unavailable = toolkits \\ available
-    return unavailable >>= mapM_ (unavailToolkitInfo c)
-    where
-        toolkitInfo avail conf tk = do
-            putStrLn $ "Toolkit: " <> show tk
-            when avail $ do
-                Executable dir exe <- fmap fromJust $ runPlotM conf $ executable tk
-                putStrLn $ "    Executable: " <> (dir </> unpack exe)
-            putStrLn $ "    Code block trigger: " <> (unpack . cls $ tk)
-            putStrLn $ "    Supported save formats: " <> (mconcat . intersperse ", " . fmap show $ supportedSaveFormats tk)
-            putStrLn mempty
-        availToolkitInfo = toolkitInfo True
-        unavailToolkitInfo = toolkitInfo False
+  c <- case mfp of
+    Nothing -> localConfig
+    Just fp -> configuration fp
 
+  putStrLn "\nAVAILABLE TOOLKITS\n"
+  available <- availableToolkits c
+  return available >>= mapM_ (availToolkitInfo c)
+  putStrLn "\nUNAVAILABLE TOOLKITS\n"
+  -- We don't use unavailableToolkits because this would force
+  -- more IO actions
+  let unavailable = toolkits \\ available
+  return unavailable >>= mapM_ (unavailToolkitInfo c)
+  where
+    toolkitInfo avail conf tk = do
+      putStrLn $ "Toolkit: " <> show tk
+      when avail $ do
+        Executable dir exe <- fmap fromJust $ runPlotM conf $ executable tk
+        putStrLn $ "    Executable: " <> (dir </> unpack exe)
+      putStrLn $ "    Code block trigger: " <> (unpack . cls $ tk)
+      putStrLn $ "    Supported save formats: " <> (mconcat . intersperse ", " . fmap show $ supportedSaveFormats tk)
+      putStrLn mempty
+    availToolkitInfo = toolkitInfo True
+    unavailToolkitInfo = toolkitInfo False
 
 -- | Clean output directories associated with a file
--- 
+--
 -- Priority for configuration are the same as @toJSONFilterWithConfig@.
-clean :: Maybe FilePath -- Use configuration file?
-      -> FilePath       -- Document to clean
-      -> IO ()
+clean ::
+  Maybe FilePath -> -- Use configuration file?
+  FilePath -> -- Document to clean
+  IO ()
 clean mfp fp = do
-    doc <- readDoc fp
-    -- Note the priority for configuration:
-    --   (1) path of argument --config 
-    --   (2) document metadata 
-    --   (3) local .pandoc-plot.yml 
-    --   (4) default config
-    conf <- maybe localConfig configuration $ firstJusts [configurationPathMeta doc, mfp]
-    cleanOutputDirs conf doc >> return ()
-    where
-        firstJusts :: [Maybe a] -> Maybe a
-        firstJusts = msum
-
+  doc <- readDoc fp
+  -- Note the priority for configuration:
+  --   (1) path of argument --config
+  --   (2) document metadata
+  --   (3) local .pandoc-plot.yml
+  --   (4) default config
+  conf <- maybe localConfig configuration $ firstJusts [configurationPathMeta doc, mfp]
+  cleanOutputDirs conf doc >> return ()
+  where
+    firstJusts :: [Maybe a] -> Maybe a
+    firstJusts = msum
 
 showManPage :: IO ()
 showManPage = do
-    setLocaleEncoding utf8 -- This is required to write the manual file, for some reason.
-    manualPath <- (</> "pandoc-plot-manual.html") <$> getTemporaryDirectory
-    TIO.writeFile manualPath $(embedManualHtml)
-    openFile ("file:///" <> manualPath)
+  manualPath <- (</> "pandoc-plot-manual.html") <$> getTemporaryDirectory
+  TIO.writeFile manualPath $(embedManualHtml)
+  openFile ("file:///" <> manualPath)
 
 -- | Use Doc type directly because of newline formatting
 footer' :: P.Doc
-footer' = mconcat 
-    [ P.text "More information can be found via the manual (pandoc-plot --manual) or the"
-    , P.line 
-    , P.text "repository README, located at https://github.com/LaurentRDC/pandoc-plot"
-    ]+footer' =
+  mconcat
+    [ P.text "More information can be found via the manual (pandoc-plot --manual) or the",
+      P.line,
+      P.text "repository README, located at https://github.com/LaurentRDC/pandoc-plot"
+    ]
executable/ManPage.hs view
@@ -1,30 +1,35 @@-{-# LANGUAGE TemplateHaskell   #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-|
-This module was inspired by pandoc-crossref
-|-}
-
-module ManPage ( embedManualHtml ) where
-
-import           Data.String                (fromString)
-import           Data.Text                  (unpack)
-import qualified Data.Text.IO               as TIO
+{-# LANGUAGE TemplateHaskell #-}
 
-import           System.FilePath            ((</>))
+-- |
+-- This module was inspired by pandoc-crossref
+-- |
+module ManPage (embedManualHtml) where
 
-import           Language.Haskell.TH.Syntax
+import Control.Monad (unless)
+import Data.String (fromString)
+import Data.Text (unpack)
+import qualified Data.Text.IO as TIO
+import Language.Haskell.TH.Syntax
+import System.Directory (doesFileExist)
+import System.FilePath ((</>))
 
 docFile :: FilePath
 docFile = "docs" </> "MANUAL.html"
 
 readDocFile :: IO String
-readDocFile = TIO.readFile docFile >>= return . unpack 
+readDocFile = TIO.readFile docFile >>= return . unpack
 
 embedManualHtml :: Q Exp
 embedManualHtml = do
-    qAddDependentFile docFile
-    d <- runIO readDocFile
-    strToExp d
-    where
-        strToExp :: String -> Q Exp
-        strToExp s = return $ VarE 'fromString `AppE` LitE (StringL s)
+  -- Ensure that the manual file exists
+  -- even if it is empty
+  manualExists <- runIO $ doesFileExist docFile
+  unless manualExists (runIO $ TIO.writeFile docFile mempty)
+
+  qAddDependentFile docFile
+  d <- runIO readDocFile
+  strToExp d
+  where
+    strToExp :: String -> Q Exp
+    strToExp s = return $ VarE 'fromString `AppE` LitE (StringL s)
executable/OpenFile.hs view
@@ -1,43 +1,37 @@-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Open a file in its default program.
--}
-
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Open a file in its default program.
 module OpenFile (openFile) where
 
-import Data.List            (isInfixOf)
-import System.Info          (os)
-import System.Process.Typed (runProcess_, shell, proc)
-
+import Data.List (isInfixOf)
+import System.Info (os)
+import System.Process.Typed (proc, runProcess_, shell)
 
 openFile :: FilePath -> IO ()
 openFile
-    -- Aliases taken from cabal's Distribution.System module
-    | os `elem` ["mingw32", "win32", "cygwin32"] = openFileWindows
-    | any (`isInfixOf` os) ["linux", "bsd"]      = openFileLinux
-    | os `elem` ["darwin"]                       = openFileMacOS
-    | otherwise                                  = error $ "Unsupported OS: " <> os
-
+  -- Aliases taken from cabal's Distribution.System module
+  | os `elem` ["mingw32", "win32", "cygwin32"] = openFileWindows
+  | any (`isInfixOf` os) ["linux", "bsd"] = openFileLinux
+  | os `elem` ["darwin"] = openFileMacOS
+  | otherwise = error $ "Unsupported OS: " <> os
 
 openFileWindows :: FilePath -> IO ()
-openFileWindows fp = 
-    -- Call looks like: cmd /c 'start "" "my_filepath.html"'
-    runProcess_ $ shell $ mconcat ["cmd /c start ", quoted mempty, " ", quoted fp]
-    where
-        quoted f = mconcat ["\"", f, "\""]
-
+openFileWindows fp =
+  -- Call looks like: cmd /c 'start "" "my_filepath.html"'
+  runProcess_ $ shell $ mconcat ["cmd /c start ", quoted mempty, " ", quoted fp]
+  where
+    quoted f = mconcat ["\"", f, "\""]
 
 openFileLinux :: FilePath -> IO ()
 openFileLinux fp =
-    runProcess_ (proc "sh" ["-c", "xdg-open \"$0\" 2>&1 > /dev/null", fp])
-
+  runProcess_ (proc "sh" ["-c", "xdg-open \"$0\" 2>&1 > /dev/null", fp])
 
 openFileMacOS :: FilePath -> IO ()
 openFileMacOS fp =
-    runProcess_ (proc "open" [fp])+  runProcess_ (proc "open" [fp])
pandoc-plot.cabal view
@@ -1,8 +1,10 @@ cabal-version:  2.2
 name:           pandoc-plot
-version:        1.0.0.0
+version:        1.0.1.0
 synopsis:       A Pandoc filter to include figures generated from code blocks using your plotting toolkit of choice.
-description:    A Pandoc filter to include figures generated from code blocks. Keep the document and code in the same location. Output is captured and included as a figure.
+description:    A Pandoc filter to include figures generated from code blocks. 
+                Keep the document and code in the same location. Output is 
+                captured and included as a figure.
 category:       Text
 copyright:      (c) 2019-2020 Laurent P. René de Cotret
 homepage:       https://github.com/LaurentRDC/pandoc-plot#readme
@@ -12,7 +14,7 @@ license:        GPL-2.0-or-later
 license-file:   LICENSE
 build-type:     Simple
-tested-with:    GHC == 8.6.5, GHC == 8.8.3, GHC == 8.10.1
+tested-with:    GHC == 8.10.1
 extra-source-files:
     CHANGELOG.md
     LICENSE
@@ -21,11 +23,15 @@     docs/MANUAL.html
     stack.yaml
     example-config.yml
+
+    data/srctemplate.html
+
     tests/fixtures/.config-meta.yml
     tests/fixtures/.empty-config.yml
     tests/fixtures/.verbose-config.yml
     tests/fixtures/plotfile.py
     tests/fixtures/data.csv
+    
     tests/includes/bokeh.py
     tests/includes/ggplot2.r
     tests/includes/gnuplot.gp
@@ -58,6 +64,7 @@         Text.Pandoc.Filter.Plot.Configuration
         Text.Pandoc.Filter.Plot.Parse
         Text.Pandoc.Filter.Plot.Scripting
+        Text.Pandoc.Filter.Plot.Scripting.Template
         Text.Pandoc.Filter.Plot.Renderers
         Text.Pandoc.Filter.Plot.Renderers.Prelude
         Text.Pandoc.Filter.Plot.Renderers.Matplotlib
@@ -96,6 +103,7 @@         , lifted-base        >= 0.2   && < 1
         , shakespeare        >= 2.0   && < 3
         , tagsoup            >= 0.14  && < 1
+        , template-haskell   >  2.7   && < 3
         , text               >= 1     && < 2
         , typed-process      >= 0.2.1 && < 1
         , yaml               >= 0.8   && < 1
src/Text/Pandoc/Filter/Plot.hs view
@@ -1,117 +1,143 @@+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE FlexibleContexts  #-}
-{-|
-Module      : $header$
-Description : Pandoc filter to create figures from code blocks using your plotting toolkit of choice
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : unstable
-Portability : portable
 
-This module defines a Pandoc filter @plotTransform@ and related functions
-that can be used to walk over a Pandoc document and generate figures from
-code blocks, using a multitude of plotting toolkits.
-
-The syntax for code blocks is simple. Code blocks with the appropriate class
-attribute will trigger the filter:
-
-*   @matplotlib@ for matplotlib-based Python plots;
-*   @plotly_python@ for Plotly-based Python plots;
-*   @plotly_r@ for Plotly-based R plots;
-*   @matlabplot@ for MATLAB plots;
-*   @mathplot@ for Mathematica plots;
-*   @octaveplot@ for GNU Octave plots;
-*   @ggplot2@ for ggplot2-based R plots;
-*   @gnuplot@ for gnuplot plots;
-*   @graphviz@ for Graphviz graphs;
-*   @bokeh@ for Bokeh-based Python plots;
-*   @plotsjl@ for Plots.jl-based Julia plots;
-
-For example, in Markdown:
-
-@
-    This is a paragraph.
-
-    ```{.matlabplot}
-    figure()
-    plot([1,2,3,4,5], [1,2,3,4,5], '-k')
-    ```
-@
-
-The code block will be reworked into a script and the output figure will be captured. Optionally, the source code
- used to generate the figure will be linked in the caption.
-
-Here are the possible attributes what pandoc-plot understands for ALL toolkits:
-
-    * @directory=...@ : Directory where to save the figure. This path should be specified with 
-      respect to the current working directory, and not with respect to the document.
-    * @source=true|false@ : Whether or not to link the source code of this figure in the caption. 
-      Ideal for web pages, for example. Default is false.
-    * @format=...@: Format of the generated figure. This can be an extension or an acronym, 
-      e.g. @format=PNG@.
-    * @caption="..."@: Specify a plot caption (or alternate text). Format 
-      for captions is specified in the documentation for the @Configuration@ type.
-    * @dpi=...@: Specify a value for figure resolution, or dots-per-inch. Certain toolkits ignore this.
-    * @dependencies=[...]@: Specify files/directories on which a figure depends, e.g. data file. 
-      Figures will be re-rendered if one of those file/directory changes. These paths should 
-      be specified with respect to the current working directory, and not with respect to the document.
-    * @preamble=...@: Path to a file to include before the code block. Ideal to avoid repetition over 
-      many figures.
-    * @file=...@: Path to a file from which to read the content of the figure. The content of the 
-      code block will be ignored. This path should be specified with respect to the current working 
-      directory, and not with respect to the document.
-
-Default values for the above attributes are stored in the @Configuration@ datatype. These can be specified in a 
-YAML file. 
-
-Here is an example code block which will render a figure using gnuplot, in Markdown:
-
-@
-    ```{.gnuplot format=png caption="Sinusoidal function" source=true}
-    sin(x)
+-- |
+-- Module      : $header$
+-- Description : Pandoc filter to create figures from code blocks using your plotting toolkit of choice
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : unstable
+-- Portability : portable
+--
+-- This module defines a Pandoc filter @plotTransform@ and related functions
+-- that can be used to walk over a Pandoc document and generate figures from
+-- code blocks, using a multitude of plotting toolkits.
+--
+-- The syntax for code blocks is simple. Code blocks with the appropriate class
+-- attribute will trigger the filter:
+--
+-- *   @matplotlib@ for matplotlib-based Python plots;
+-- *   @plotly_python@ for Plotly-based Python plots;
+-- *   @plotly_r@ for Plotly-based R plots;
+-- *   @matlabplot@ for MATLAB plots;
+-- *   @mathplot@ for Mathematica plots;
+-- *   @octaveplot@ for GNU Octave plots;
+-- *   @ggplot2@ for ggplot2-based R plots;
+-- *   @gnuplot@ for gnuplot plots;
+-- *   @graphviz@ for Graphviz graphs;
+-- *   @bokeh@ for Bokeh-based Python plots;
+-- *   @plotsjl@ for Plots.jl-based Julia plots;
+--
+-- For example, in Markdown:
+--
+-- @
+--     This is a paragraph.
+--
+--     ```{.matlabplot}
+--     figure()
+--     plot([1,2,3,4,5], [1,2,3,4,5], '-k')
+--     ```
+-- @
+--
+-- The code block will be reworked into a script and the output figure will be captured. Optionally, the source code
+--  used to generate the figure will be linked in the caption.
+--
+-- Here are the possible attributes what pandoc-plot understands for ALL toolkits:
+--
+--     * @directory=...@ : Directory where to save the figure. This path should be specified with
+--       respect to the current working directory, and not with respect to the document.
+--     * @source=true|false@ : Whether or not to link the source code of this figure in the caption.
+--       Ideal for web pages, for example. Default is false.
+--     * @format=...@: Format of the generated figure. This can be an extension or an acronym,
+--       e.g. @format=PNG@.
+--     * @caption="..."@: Specify a plot caption (or alternate text). Format
+--       for captions is specified in the documentation for the @Configuration@ type.
+--     * @dpi=...@: Specify a value for figure resolution, or dots-per-inch. Certain toolkits ignore this.
+--     * @dependencies=[...]@: Specify files/directories on which a figure depends, e.g. data file.
+--       Figures will be re-rendered if one of those file/directory changes. These paths should
+--       be specified with respect to the current working directory, and not with respect to the document.
+--     * @preamble=...@: Path to a file to include before the code block. Ideal to avoid repetition over
+--       many figures.
+--     * @file=...@: Path to a file from which to read the content of the figure. The content of the
+--       code block will be ignored. This path should be specified with respect to the current working
+--       directory, and not with respect to the document.
+--
+-- Default values for the above attributes are stored in the @Configuration@ datatype. These can be specified in a
+-- YAML file.
+--
+-- Here is an example code block which will render a figure using gnuplot, in Markdown:
+--
+-- @
+--     ```{.gnuplot format=png caption="Sinusoidal function" source=true}
+--     sin(x)
+--
+--     set xlabel "x"
+--     set ylabel "y"
+--     ```
+-- @
+module Text.Pandoc.Filter.Plot
+  ( -- * Operating on whole Pandoc documents
+    plotTransform,
 
-    set xlabel "x"
-    set ylabel "y"
-    ```
-@
--}
-module Text.Pandoc.Filter.Plot (
-    -- * Operating on whole Pandoc documents
-      plotTransform
     -- * Cleaning output directories
-    , cleanOutputDirs
+    cleanOutputDirs,
+
     -- * Runtime configuration
-    , configuration
-    , defaultConfiguration
-    , Configuration(..)
-    , Verbosity(..)
-    , LogSink(..)
-    , SaveFormat(..)
-    , Script
-    -- * Determining available plotting toolkits
-    , Toolkit(..)
-    , availableToolkits
-    , unavailableToolkits
-    , toolkits
-    , supportedSaveFormats
-    -- * Version information
-    , pandocPlotVersion
-    -- * For embedding, testing and internal purposes ONLY. Might change without notice.
-    , make
-    , makeEither
-    , PandocPlotError(..)
-    ) where
+    configuration,
+    defaultConfiguration,
+    Configuration (..),
+    Verbosity (..),
+    LogSink (..),
+    SaveFormat (..),
+    Script,
 
-import Control.Concurrent.Async.Lifted   (mapConcurrently)
-import Data.Text                         (Text, unpack)
-import Data.Version                      (Version)
+    -- * Determining available plotting toolkits
+    Toolkit (..),
+    availableToolkits,
+    unavailableToolkits,
+    toolkits,
+    supportedSaveFormats,
 
-import Paths_pandoc_plot                 (version)
+    -- * Version information
+    pandocPlotVersion,
 
-import Text.Pandoc.Definition            (Pandoc(..), Block)
+    -- * For embedding, testing and internal purposes ONLY. Might change without notice.
+    make,
+    makeEither,
+    PandocPlotError (..),
+  )
+where
 
+import Control.Concurrent.Async.Lifted (mapConcurrently)
+import Data.Text (Text, unpack)
+import Data.Version (Version)
+import Paths_pandoc_plot (version)
+import Text.Pandoc.Definition (Block, Pandoc (..))
 import Text.Pandoc.Filter.Plot.Internal
+  ( Configuration (..),
+    FigureSpec,
+    LogSink (..),
+    PlotM,
+    RuntimeEnv (envConfig),
+    SaveFormat (..),
+    Script,
+    ScriptResult (..),
+    Toolkit (..),
+    Verbosity (..),
+    asks,
+    availableToolkits,
+    cleanOutputDirs,
+    configuration,
+    defaultConfiguration,
+    parseFigureSpec,
+    runPlotM,
+    runScriptIfNecessary,
+    supportedSaveFormats,
+    toFigure,
+    toolkits,
+    unavailableToolkits,
+  )
 
 -- | Walk over an entire Pandoc document, transforming appropriate code blocks
 -- into figures. This function will operate on blocks in parallel if possible.
@@ -119,12 +145,14 @@ -- Failing to render a figure does not stop the filter, so that you may run the filter
 -- on documents without having all necessary toolkits installed. In this case, error
 -- messages are printed to stderr, and blocks are left unchanged.
-plotTransform :: Configuration -- ^ Configuration for default values
-              -> Pandoc        -- ^ Input document
-              -> IO Pandoc
-plotTransform conf (Pandoc meta blocks) = 
-    runPlotM conf $ mapConcurrently make blocks >>= return . Pandoc meta
-
+plotTransform ::
+  -- | Configuration for default values
+  Configuration ->
+  -- | Input document
+  Pandoc ->
+  IO Pandoc
+plotTransform conf (Pandoc meta blocks) =
+  runPlotM conf $ mapConcurrently make blocks >>= return . Pandoc meta
 
 -- | The version of the pandoc-plot package.
 --
@@ -132,35 +160,32 @@ pandocPlotVersion :: Version
 pandocPlotVersion = version
 
-
 -- | Try to process the block with `pandoc-plot`. If a failure happens (or the block)
 -- was not meant to become a figure, return the block as-is.
 make :: Block -> PlotM Block
-make blk = either (const (return blk) ) return =<< makeEither blk
-
+make blk = either (const (return blk)) return =<< makeEither blk
 
 -- | Try to process the block with `pandoc-plot`, documenting the error.
 makeEither :: Block -> PlotM (Either PandocPlotError Block)
-makeEither block = 
-    parseFigureSpec block 
-        >>= maybe 
-                (return $ Right block)
-                (\s -> runScriptIfNecessary s >>= handleResult s)
-    where
-        -- Logging of errors has been taken care of in @runScriptIfNecessary@ 
-        handleResult :: FigureSpec -> ScriptResult -> PlotM (Either PandocPlotError Block)
-        handleResult _ (ScriptFailure msg code)       = return $ Left (ScriptRuntimeError msg code) 
-        handleResult _ (ScriptChecksFailed msg)       = return $ Left (ScriptChecksFailedError msg)
-        handleResult _ (ToolkitNotInstalled tk')      = return $ Left (ToolkitNotInstalledError tk') 
-        handleResult spec ScriptSuccess = asks envConfig >>= \c -> Right <$> toFigure (captionFormat c) spec
-
+makeEither block =
+  parseFigureSpec block
+    >>= maybe
+      (return $ Right block)
+      (\s -> runScriptIfNecessary s >>= handleResult s)
+  where
+    -- Logging of errors has been taken care of in @runScriptIfNecessary@
+    handleResult :: FigureSpec -> ScriptResult -> PlotM (Either PandocPlotError Block)
+    handleResult _ (ScriptFailure msg code) = return $ Left (ScriptRuntimeError msg code)
+    handleResult _ (ScriptChecksFailed msg) = return $ Left (ScriptChecksFailedError msg)
+    handleResult _ (ToolkitNotInstalled tk') = return $ Left (ToolkitNotInstalledError tk')
+    handleResult spec ScriptSuccess = asks envConfig >>= \c -> Right <$> toFigure (captionFormat c) spec
 
 data PandocPlotError
-    = ScriptRuntimeError Text Int
-    | ScriptChecksFailedError Text
-    | ToolkitNotInstalledError Toolkit
+  = ScriptRuntimeError Text Int
+  | ScriptChecksFailedError Text
+  | ToolkitNotInstalledError Toolkit
 
 instance Show PandocPlotError where
-    show (ScriptRuntimeError _ exitcode) = "ERROR (pandoc-plot) The script failed with exit code " <> show exitcode <> "."
-    show (ScriptChecksFailedError msg)   = "ERROR (pandoc-plot) A script check failed with message: " <> unpack msg <> "."
-    show (ToolkitNotInstalledError tk)   = "ERROR (pandoc-plot) The " <> show tk <> " toolkit is required but not installed."+  show (ScriptRuntimeError _ exitcode) = "ERROR (pandoc-plot) The script failed with exit code " <> show exitcode <> "."
+  show (ScriptChecksFailedError msg) = "ERROR (pandoc-plot) A script check failed with message: " <> unpack msg <> "."
+  show (ToolkitNotInstalledError tk) = "ERROR (pandoc-plot) The " <> show tk <> " toolkit is required but not installed."
src/Text/Pandoc/Filter/Plot/Clean.hs view
@@ -1,105 +1,104 @@+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE FlexibleContexts  #-}
 
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Utilities to clean pandoc-plot output directories.
--}
-
-module Text.Pandoc.Filter.Plot.Clean (
-      cleanOutputDirs
-    , outputDirs
-    , readDoc
-) where
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Utilities to clean pandoc-plot output directories.
+module Text.Pandoc.Filter.Plot.Clean
+  ( cleanOutputDirs,
+    outputDirs,
+    readDoc,
+  )
+where
 
 -- TODO: forConcurrently
-import           Control.Monad.Reader             (forM)
-
-import qualified Data.ByteString.Lazy             as B
-import           Data.Char                        (toLower)
-import           Data.Default                     (def)
-import           Data.List                        (nub)
-import           Data.Maybe                       (fromMaybe, catMaybes)
-
-import           Data.Text                        (Text, pack)
-import qualified Data.Text.IO                     as Text
-
-import           System.Directory                 (removePathForcibly)
-
-import           System.FilePath                  (takeExtension) 
-
-import           Text.Pandoc.Class                (runIO)
-import           Text.Pandoc.Definition
-import           Text.Pandoc.Error                (handleError)
-import qualified Text.Pandoc.Readers              as P
-import qualified Text.Pandoc.Options              as P
-import           Text.Pandoc.Walk                 (query, Walkable)
-
-import Text.Pandoc.Filter.Plot.Parse
+import Control.Monad.Reader (forM)
+import qualified Data.ByteString.Lazy as B
+import Data.Char (toLower)
+import Data.Default (def)
+import Data.List (nub)
+import Data.Maybe (catMaybes, fromMaybe)
+import Data.Text (Text, pack)
+import qualified Data.Text.IO as Text
+import System.Directory (removePathForcibly)
+import System.FilePath (takeExtension)
+import Text.Pandoc.Class (runIO)
+import Text.Pandoc.Definition
+import Text.Pandoc.Error (handleError)
 import Text.Pandoc.Filter.Plot.Monad
-
+import Text.Pandoc.Filter.Plot.Parse
+import qualified Text.Pandoc.Options as P
+import qualified Text.Pandoc.Readers as P
+import Text.Pandoc.Walk (Walkable, query)
 
--- | Clean all output related to pandoc-plot. This includes output directories specified 
--- in the configuration and in the document/block, as well as log files. 
+-- | Clean all output related to pandoc-plot. This includes output directories specified
+-- in the configuration and in the document/block, as well as log files.
 -- Note that *all* files in pandoc-plot output directories will be removed.
 --
 -- The cleaned directories are returned.
-cleanOutputDirs :: Walkable Block b 
-                => Configuration -> b -> IO [FilePath]
+cleanOutputDirs ::
+  Walkable Block b =>
+  Configuration ->
+  b ->
+  IO [FilePath]
 cleanOutputDirs conf doc = do
-    dirs <- runPlotM conf . cleanOutputDirsM $ doc
-    -- Deletion of the log file must be done outside of PlotM
-    -- to ensure the log file has been closed.
-    case logSink conf of 
-        LogFile path -> removePathForcibly path
-        _            -> return ()
-    return dirs
-
+  dirs <- runPlotM conf . cleanOutputDirsM $ doc
+  -- Deletion of the log file must be done outside of PlotM
+  -- to ensure the log file has been closed.
+  case logSink conf of
+    LogFile path -> removePathForcibly path
+    _ -> return ()
+  return dirs
 
 -- | Analyze a document to determine where would the pandoc-plot output directories be.
-outputDirs :: Walkable Block b 
-           => b -> PlotM [FilePath]
-outputDirs = fmap (nub . catMaybes) 
-           . sequence 
-           . query (\b -> [parseFigureSpec b >>= return . fmap directory])
-
+outputDirs ::
+  Walkable Block b =>
+  b ->
+  PlotM [FilePath]
+outputDirs =
+  fmap (nub . catMaybes)
+    . sequence
+    . query (\b -> [parseFigureSpec b >>= return . fmap directory])
 
 -- PlotM version of @cleanOutputDirs@
-cleanOutputDirsM :: Walkable Block b 
-                 => b -> PlotM [FilePath]
+cleanOutputDirsM ::
+  Walkable Block b =>
+  b ->
+  PlotM [FilePath]
 cleanOutputDirsM doc = do
-    directories <- outputDirs doc
-    forM directories $ \fp -> do
-        info $ "Removing directory " <> pack fp
-        -- It is important to use `removePathForcibly` here, because it does 
-        -- not throw exceptions if the directory doesn't exist. This means
-        -- we do not have to check in advance if directories are nested in our 
-        -- list of directories.
-        liftIO $ removePathForcibly fp
-        return fp
-
+  directories <- outputDirs doc
+  forM directories $ \fp -> do
+    info $ "Removing directory " <> pack fp
+    -- It is important to use `removePathForcibly` here, because it does
+    -- not throw exceptions if the directory doesn't exist. This means
+    -- we do not have to check in advance if directories are nested in our
+    -- list of directories.
+    liftIO $ removePathForcibly fp
+    return fp
 
 -- | Read a document, guessing what extensions and reader options are appropriate. If
 -- the file cannot be read for any reason, an error is thrown.
 readDoc :: FilePath -> IO Pandoc
-readDoc fp = handleError =<< (runIO $ do
-        let fmt = fromMaybe mempty (formatFromFilePath fp)
-        (reader, exts) <- P.getReader fmt
-        let readerOpts = def {P.readerExtensions = exts}
-        case reader of 
-            P.TextReader fct -> do
-                t <- liftIO $ Text.readFile fp 
+readDoc fp =
+  handleError
+    =<< ( runIO $ do
+            let fmt = fromMaybe mempty (formatFromFilePath fp)
+            (reader, exts) <- P.getReader fmt
+            let readerOpts = def {P.readerExtensions = exts}
+            case reader of
+              P.TextReader fct -> do
+                t <- liftIO $ Text.readFile fp
                 fct readerOpts t
-            P.ByteStringReader bst -> do
+              P.ByteStringReader bst -> do
                 b <- liftIO $ B.readFile fp
-                bst readerOpts b)
-
+                bst readerOpts b
+        )
 
 -- Determine format based on file extension
 -- Note : this is exactly the heuristic used by pandoc here:
@@ -109,49 +108,49 @@ formatFromFilePath :: FilePath -> Maybe Text
 formatFromFilePath x =
   case takeExtension (map toLower x) of
-    ".adoc"     -> Just "asciidoc"
+    ".adoc" -> Just "asciidoc"
     ".asciidoc" -> Just "asciidoc"
-    ".context"  -> Just "context"
-    ".ctx"      -> Just "context"
-    ".db"       -> Just "docbook"
-    ".doc"      -> Just "doc"  -- so we get an "unknown reader" error
-    ".docx"     -> Just "docx"
+    ".context" -> Just "context"
+    ".ctx" -> Just "context"
+    ".db" -> Just "docbook"
+    ".doc" -> Just "doc" -- so we get an "unknown reader" error
+    ".docx" -> Just "docx"
     ".dokuwiki" -> Just "dokuwiki"
-    ".epub"     -> Just "epub"
-    ".fb2"      -> Just "fb2"
-    ".htm"      -> Just "html"
-    ".html"     -> Just "html"
-    ".icml"     -> Just "icml"
-    ".json"     -> Just "json"
-    ".latex"    -> Just "latex"
-    ".lhs"      -> Just "markdown+lhs"
-    ".ltx"      -> Just "latex"
+    ".epub" -> Just "epub"
+    ".fb2" -> Just "fb2"
+    ".htm" -> Just "html"
+    ".html" -> Just "html"
+    ".icml" -> Just "icml"
+    ".json" -> Just "json"
+    ".latex" -> Just "latex"
+    ".lhs" -> Just "markdown+lhs"
+    ".ltx" -> Just "latex"
     ".markdown" -> Just "markdown"
-    ".md"       -> Just "markdown"
-    ".ms"       -> Just "ms"
-    ".muse"     -> Just "muse"
-    ".native"   -> Just "native"
-    ".odt"      -> Just "odt"
-    ".opml"     -> Just "opml"
-    ".org"      -> Just "org"
-    ".pdf"      -> Just "pdf"  -- so we get an "unknown reader" error
-    ".pptx"     -> Just "pptx"
-    ".roff"     -> Just "ms"
-    ".rst"      -> Just "rst"
-    ".rtf"      -> Just "rtf"
-    ".s5"       -> Just "s5"
-    ".t2t"      -> Just "t2t"
-    ".tei"      -> Just "tei"
-    ".tei.xml"  -> Just "tei"
-    ".tex"      -> Just "latex"
-    ".texi"     -> Just "texinfo"
-    ".texinfo"  -> Just "texinfo"
-    ".text"     -> Just "markdown"
-    ".textile"  -> Just "textile"
-    ".txt"      -> Just "markdown"
-    ".wiki"     -> Just "mediawiki"
-    ".xhtml"    -> Just "html"
-    ".ipynb"    -> Just "ipynb"
-    ".csv"      -> Just "csv"
-    ['.',y]     | y `elem` ['1'..'9'] -> Just "man"
-    _           -> Nothing+    ".md" -> Just "markdown"
+    ".ms" -> Just "ms"
+    ".muse" -> Just "muse"
+    ".native" -> Just "native"
+    ".odt" -> Just "odt"
+    ".opml" -> Just "opml"
+    ".org" -> Just "org"
+    ".pdf" -> Just "pdf" -- so we get an "unknown reader" error
+    ".pptx" -> Just "pptx"
+    ".roff" -> Just "ms"
+    ".rst" -> Just "rst"
+    ".rtf" -> Just "rtf"
+    ".s5" -> Just "s5"
+    ".t2t" -> Just "t2t"
+    ".tei" -> Just "tei"
+    ".tei.xml" -> Just "tei"
+    ".tex" -> Just "latex"
+    ".texi" -> Just "texinfo"
+    ".texinfo" -> Just "texinfo"
+    ".text" -> Just "markdown"
+    ".textile" -> Just "textile"
+    ".txt" -> Just "markdown"
+    ".wiki" -> Just "mediawiki"
+    ".xhtml" -> Just "html"
+    ".ipynb" -> Just "ipynb"
+    ".csv" -> Just "csv"
+    ['.', y] | y `elem` ['1' .. '9'] -> Just "man"
+    _ -> Nothing
src/Text/Pandoc/Filter/Plot/Configuration.hs view
@@ -1,33 +1,30 @@ {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Reading configuration from file
--}
-
-module Text.Pandoc.Filter.Plot.Configuration (
-      configuration
-    , configurationPathMeta
-    , defaultConfiguration
-) where
-
-import           Data.Maybe             (fromMaybe)
-import           Data.Text              (Text, pack, unpack)
-import qualified Data.Text.IO           as TIO
-import           Data.Yaml              ((.!=), (.:?), FromJSON(parseJSON), Value(Object, Null))
-import           Data.Yaml.Config       (ignoreEnv, loadYamlSettings)
-
-import           System.FilePath        (normalise)
+{-# LANGUAGE RecordWildCards #-}
 
-import           Text.Pandoc.Definition (Format(..), Pandoc(..), MetaValue(..), Inline(..), lookupMeta)
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Reading configuration from file
+module Text.Pandoc.Filter.Plot.Configuration
+  ( configuration,
+    configurationPathMeta,
+    defaultConfiguration,
+  )
+where
 
-import Text.Pandoc.Filter.Plot.Monad   
+import Data.Maybe (fromMaybe)
+import Data.Text (Text, pack, unpack)
+import qualified Data.Text.IO as TIO
+import Data.Yaml (FromJSON (parseJSON), Value (Null, Object), (.!=), (.:?))
+import Data.Yaml.Config (ignoreEnv, loadYamlSettings)
+import System.FilePath (normalise)
+import Text.Pandoc.Definition (Format (..), Inline (..), MetaValue (..), Pandoc (..), lookupMeta)
+import Text.Pandoc.Filter.Plot.Monad
 
 -- | Read configuration from a YAML file. The
 -- keys are exactly the same as for code blocks.
@@ -37,52 +34,48 @@ configuration :: FilePath -> IO Configuration
 configuration fp = (loadYamlSettings [normalise fp] [] ignoreEnv) >>= renderConfig
 
-
 -- | Default configuration values.
 --
 -- @since 0.5.0.0
 defaultConfiguration :: Configuration
-defaultConfiguration = 
-    Configuration
-        { defaultDirectory    = "plots/"
-        , defaultWithSource   = False
-        , defaultDPI          = 80
-        , defaultSaveFormat   = PNG
-        , defaultDependencies = mempty
-        , captionFormat       = Format "markdown+tex_math_dollars"
-
-        , logVerbosity        = Warning
-        , logSink             = StdErr
-        
-        , matplotlibPreamble  = mempty
-        , plotlyPythonPreamble= mempty
-        , plotlyRPreamble     = mempty
-        , matlabPreamble      = mempty
-        , mathematicaPreamble = mempty
-        , octavePreamble      = mempty
-        , ggplot2Preamble     = mempty
-        , gnuplotPreamble     = mempty
-        , graphvizPreamble    = mempty
-        , bokehPreamble       = mempty
-        , plotsjlPreamble     = mempty
-
-        , matplotlibExe       = python
-        , matlabExe           = "matlab"
-        , plotlyPythonExe     = python
-        , plotlyRExe          = "Rscript"
-        , mathematicaExe      = "math"
-        , octaveExe           = "octave"
-        , ggplot2Exe          = "Rscript"
-        , gnuplotExe          = "gnuplot"
-        , graphvizExe         = "dot"
-        , bokehExe            = python
-        , plotsjlExe          = "julia"
-        
-        , matplotlibTightBBox   = False
-        , matplotlibTransparent = False
-        }
-        where
-            python = if isWindows then "python" else "python3"
+defaultConfiguration =
+  Configuration
+    { defaultDirectory = "plots/",
+      defaultWithSource = False,
+      defaultDPI = 80,
+      defaultSaveFormat = PNG,
+      defaultDependencies = mempty,
+      captionFormat = Format "markdown+tex_math_dollars",
+      sourceCodeLabel = "Source code",
+      logVerbosity = Warning,
+      logSink = StdErr,
+      matplotlibPreamble = mempty,
+      plotlyPythonPreamble = mempty,
+      plotlyRPreamble = mempty,
+      matlabPreamble = mempty,
+      mathematicaPreamble = mempty,
+      octavePreamble = mempty,
+      ggplot2Preamble = mempty,
+      gnuplotPreamble = mempty,
+      graphvizPreamble = mempty,
+      bokehPreamble = mempty,
+      plotsjlPreamble = mempty,
+      matplotlibExe = python,
+      matlabExe = "matlab",
+      plotlyPythonExe = python,
+      plotlyRExe = "Rscript",
+      mathematicaExe = "math",
+      octaveExe = "octave",
+      ggplot2Exe = "Rscript",
+      gnuplotExe = "gnuplot",
+      graphvizExe = "dot",
+      bokehExe = python,
+      plotsjlExe = "julia",
+      matplotlibTightBBox = False,
+      matplotlibTransparent = False
+    }
+  where
+    python = if isWindows then "python" else "python3"
 
 -- | Extact path to configuration from the metadata in a Pandoc document.
 -- The path to the configuration file should be under the @plot-configuration@ key.
@@ -95,7 +88,7 @@ --     title: My document
 --     author: John Doe
 --     plot-configuration: /path/to/file.yml
---     ---     
+--     ---
 -- @
 --
 -- The same can be specified via the command line using Pandoc's @-M@ flag:
@@ -104,216 +97,221 @@ --
 -- @since 0.6.0.0
 configurationPathMeta :: Pandoc -> Maybe FilePath
-configurationPathMeta (Pandoc meta _) = 
-        lookupMeta "plot-configuration" meta >>= getPath
-    where
-        getPath (MetaString t)        = Just (unpack t)
-        getPath (MetaInlines [Str s]) = Just (unpack s)
-        getPath _                     = Nothing
-
+configurationPathMeta (Pandoc meta _) =
+  lookupMeta "plot-configuration" meta >>= getPath
+  where
+    getPath (MetaString t) = Just (unpack t)
+    getPath (MetaInlines [Str s]) = Just (unpack s)
+    getPath _ = Nothing
 
 -- We define a precursor type because preambles are best specified as file paths,
 -- but we want to read those files before building a full
 -- @Configuration@ value.
 data ConfigPrecursor = ConfigPrecursor
-    { _defaultDirectory    :: !FilePath    
-    , _defaultWithSource   :: !Bool        
-    , _defaultDPI          :: !Int         
-    , _defaultSaveFormat   :: !SaveFormat  
-    , _defaultDependencies :: ![FilePath]  
-    , _captionFormat       :: !Format
-    
-    , _logPrec             :: !LoggingPrecursor
+  { _defaultDirectory :: !FilePath,
+    _defaultWithSource :: !Bool,
+    _defaultDPI :: !Int,
+    _defaultSaveFormat :: !SaveFormat,
+    _defaultDependencies :: ![FilePath],
+    _captionFormat :: !Format,
+    _sourceCodeLabel :: !Text,
+    _logPrec :: !LoggingPrecursor,
+    _matplotlibPrec :: !MatplotlibPrecursor,
+    _matlabPrec :: !MatlabPrecursor,
+    _plotlyPythonPrec :: !PlotlyPythonPrecursor,
+    _plotlyRPrec :: !PlotlyRPrecursor,
+    _mathematicaPrec :: !MathematicaPrecursor,
+    _octavePrec :: !OctavePrecursor,
+    _ggplot2Prec :: !GGPlot2Precursor,
+    _gnuplotPrec :: !GNUPlotPrecursor,
+    _graphvizPrec :: !GraphvizPrecursor,
+    _bokehPrec :: !BokehPrecursor,
+    _plotsjlPrec :: !PlotsjlPrecursor
+  }
 
-    , _matplotlibPrec      :: !MatplotlibPrecursor
-    , _matlabPrec          :: !MatlabPrecursor
-    , _plotlyPythonPrec    :: !PlotlyPythonPrecursor
-    , _plotlyRPrec         :: !PlotlyRPrecursor
-    , _mathematicaPrec     :: !MathematicaPrecursor
-    , _octavePrec          :: !OctavePrecursor
-    , _ggplot2Prec         :: !GGPlot2Precursor
-    , _gnuplotPrec         :: !GNUPlotPrecursor
-    , _graphvizPrec        :: !GraphvizPrecursor
-    , _bokehPrec           :: !BokehPrecursor
-    , _plotsjlPrec         :: !PlotsjlPrecursor
+defaultConfigPrecursor :: ConfigPrecursor
+defaultConfigPrecursor =
+  ConfigPrecursor
+    { _defaultDirectory = defaultDirectory defaultConfiguration,
+      _defaultWithSource = defaultWithSource defaultConfiguration,
+      _defaultDPI = defaultDPI defaultConfiguration,
+      _defaultSaveFormat = defaultSaveFormat defaultConfiguration,
+      _defaultDependencies = defaultDependencies defaultConfiguration,
+      _captionFormat = captionFormat defaultConfiguration,
+      _sourceCodeLabel = sourceCodeLabel defaultConfiguration,
+      _logPrec = LoggingPrecursor (logVerbosity defaultConfiguration) Nothing, -- _logFilePath=Nothing implies log to stderr
+      _matplotlibPrec = MatplotlibPrecursor Nothing (matplotlibTightBBox defaultConfiguration) (matplotlibTransparent defaultConfiguration) (matplotlibExe defaultConfiguration),
+      _matlabPrec = MatlabPrecursor Nothing (matlabExe defaultConfiguration),
+      _plotlyPythonPrec = PlotlyPythonPrecursor Nothing (plotlyPythonExe defaultConfiguration),
+      _plotlyRPrec = PlotlyRPrecursor Nothing (plotlyRExe defaultConfiguration),
+      _mathematicaPrec = MathematicaPrecursor Nothing (mathematicaExe defaultConfiguration),
+      _octavePrec = OctavePrecursor Nothing (octaveExe defaultConfiguration),
+      _ggplot2Prec = GGPlot2Precursor Nothing (ggplot2Exe defaultConfiguration),
+      _gnuplotPrec = GNUPlotPrecursor Nothing (gnuplotExe defaultConfiguration),
+      _graphvizPrec = GraphvizPrecursor Nothing (graphvizExe defaultConfiguration),
+      _bokehPrec = BokehPrecursor Nothing (bokehExe defaultConfiguration),
+      _plotsjlPrec = PlotsjlPrecursor Nothing (plotsjlExe defaultConfiguration)
     }
 
-defaultConfigPrecursor :: ConfigPrecursor
-defaultConfigPrecursor =  
-    ConfigPrecursor
-        { _defaultDirectory    = defaultDirectory defaultConfiguration
-        , _defaultWithSource   = defaultWithSource defaultConfiguration
-        , _defaultDPI          = defaultDPI defaultConfiguration
-        , _defaultSaveFormat   = defaultSaveFormat defaultConfiguration
-        , _defaultDependencies = defaultDependencies defaultConfiguration
-        , _captionFormat       = captionFormat defaultConfiguration
+data LoggingPrecursor = LoggingPrecursor
+  { _logVerbosity :: !Verbosity,
+    _logFilePath :: !(Maybe FilePath)
+  }
 
-        , _logPrec             = LoggingPrecursor (logVerbosity defaultConfiguration) Nothing -- _logFilePath=Nothing implies log to stderr
-        
-        , _matplotlibPrec      = MatplotlibPrecursor   Nothing (matplotlibTightBBox defaultConfiguration) (matplotlibTransparent defaultConfiguration) (matplotlibExe defaultConfiguration)
-        , _matlabPrec          = MatlabPrecursor       Nothing (matlabExe defaultConfiguration)
-        , _plotlyPythonPrec    = PlotlyPythonPrecursor Nothing (plotlyPythonExe defaultConfiguration)
-        , _plotlyRPrec         = PlotlyRPrecursor      Nothing (plotlyRExe defaultConfiguration)
-        , _mathematicaPrec     = MathematicaPrecursor  Nothing (mathematicaExe defaultConfiguration)
-        , _octavePrec          = OctavePrecursor       Nothing (octaveExe defaultConfiguration)
-        , _ggplot2Prec         = GGPlot2Precursor      Nothing (ggplot2Exe defaultConfiguration)
-        , _gnuplotPrec         = GNUPlotPrecursor      Nothing (gnuplotExe defaultConfiguration)
-        , _graphvizPrec        = GraphvizPrecursor     Nothing (graphvizExe defaultConfiguration)
-        , _bokehPrec           = BokehPrecursor        Nothing (bokehExe defaultConfiguration)
-        , _plotsjlPrec         = PlotsjlPrecursor      Nothing (plotsjlExe defaultConfiguration)
-        }
+-- Separate YAML clauses have their own types.
+data MatplotlibPrecursor = MatplotlibPrecursor
+  { _matplotlibPreamble :: !(Maybe FilePath),
+    _matplotlibTightBBox :: !Bool,
+    _matplotlibTransparent :: !Bool,
+    _matplotlibExe :: !FilePath
+  }
 
+data MatlabPrecursor = MatlabPrecursor {_matlabPreamble :: !(Maybe FilePath), _matlabExe :: !FilePath}
 
-data LoggingPrecursor = LoggingPrecursor { _logVerbosity :: !Verbosity
-                                         , _logFilePath  :: !(Maybe FilePath)
-                                         }
+data PlotlyPythonPrecursor = PlotlyPythonPrecursor {_plotlyPythonPreamble :: !(Maybe FilePath), _plotlyPythonExe :: !FilePath}
 
--- Separate YAML clauses have their own types.
-data MatplotlibPrecursor = MatplotlibPrecursor
-        { _matplotlibPreamble    :: !(Maybe FilePath)
-        , _matplotlibTightBBox   :: !Bool
-        , _matplotlibTransparent :: !Bool
-        , _matplotlibExe         :: !FilePath
-        }
-data MatlabPrecursor        = MatlabPrecursor       {_matlabPreamble       :: !(Maybe FilePath), _matlabExe       :: !FilePath}
-data PlotlyPythonPrecursor  = PlotlyPythonPrecursor {_plotlyPythonPreamble :: !(Maybe FilePath), _plotlyPythonExe :: !FilePath}
-data PlotlyRPrecursor       = PlotlyRPrecursor      {_plotlyRPreamble      :: !(Maybe FilePath), _plotlyRExe      :: !FilePath}
-data MathematicaPrecursor   = MathematicaPrecursor  {_mathematicaPreamble  :: !(Maybe FilePath), _mathematicaExe  :: !FilePath}
-data OctavePrecursor        = OctavePrecursor       {_octavePreamble       :: !(Maybe FilePath), _octaveExe       :: !FilePath}
-data GGPlot2Precursor       = GGPlot2Precursor      {_ggplot2Preamble      :: !(Maybe FilePath), _ggplot2Exe      :: !FilePath}
-data GNUPlotPrecursor       = GNUPlotPrecursor      {_gnuplotPreamble      :: !(Maybe FilePath), _gnuplotExe      :: !FilePath}
-data GraphvizPrecursor      = GraphvizPrecursor     {_graphvizPreamble     :: !(Maybe FilePath), _graphvizExe     :: !FilePath}
-data BokehPrecursor         = BokehPrecursor        {_bokehPreamble        :: !(Maybe FilePath), _bokehExe        :: !FilePath}
-data PlotsjlPrecursor       = PlotsjlPrecursor      {_plotsjlPreamble      :: !(Maybe FilePath), _plotsjlExe      :: !FilePath}
+data PlotlyRPrecursor = PlotlyRPrecursor {_plotlyRPreamble :: !(Maybe FilePath), _plotlyRExe :: !FilePath}
 
+data MathematicaPrecursor = MathematicaPrecursor {_mathematicaPreamble :: !(Maybe FilePath), _mathematicaExe :: !FilePath}
+
+data OctavePrecursor = OctavePrecursor {_octavePreamble :: !(Maybe FilePath), _octaveExe :: !FilePath}
+
+data GGPlot2Precursor = GGPlot2Precursor {_ggplot2Preamble :: !(Maybe FilePath), _ggplot2Exe :: !FilePath}
+
+data GNUPlotPrecursor = GNUPlotPrecursor {_gnuplotPreamble :: !(Maybe FilePath), _gnuplotExe :: !FilePath}
+
+data GraphvizPrecursor = GraphvizPrecursor {_graphvizPreamble :: !(Maybe FilePath), _graphvizExe :: !FilePath}
+
+data BokehPrecursor = BokehPrecursor {_bokehPreamble :: !(Maybe FilePath), _bokehExe :: !FilePath}
+
+data PlotsjlPrecursor = PlotsjlPrecursor {_plotsjlPreamble :: !(Maybe FilePath), _plotsjlExe :: !FilePath}
+
 instance FromJSON LoggingPrecursor where
-    parseJSON (Object v) = 
-        LoggingPrecursor <$> v .:? "verbosity" .!= (logVerbosity defaultConfiguration)
-                         <*> v .:? "filepath"
-    parseJSON _ = fail $ mconcat ["Could not parse logging configuration. "]
+  parseJSON (Object v) =
+    LoggingPrecursor <$> v .:? "verbosity" .!= (logVerbosity defaultConfiguration)
+      <*> v .:? "filepath"
+  parseJSON _ = fail $ mconcat ["Could not parse logging configuration. "]
 
 instance FromJSON MatplotlibPrecursor where
-    parseJSON (Object v) = 
-        MatplotlibPrecursor
-            <$> v .:? (tshow PreambleK)
-            <*> v .:? (tshow MatplotlibTightBBoxK)   .!= (matplotlibTightBBox defaultConfiguration) 
-            <*> v .:? (tshow MatplotlibTransparentK) .!= (matplotlibTransparent defaultConfiguration)
-            <*> v .:? (tshow ExecutableK)  .!= (matplotlibExe defaultConfiguration)
-    parseJSON _ = fail $ mconcat ["Could not parse ", show Matplotlib, " configuration."]
+  parseJSON (Object v) =
+    MatplotlibPrecursor
+      <$> v .:? (tshow PreambleK)
+      <*> v .:? (tshow MatplotlibTightBBoxK) .!= (matplotlibTightBBox defaultConfiguration)
+      <*> v .:? (tshow MatplotlibTransparentK) .!= (matplotlibTransparent defaultConfiguration)
+      <*> v .:? (tshow ExecutableK) .!= (matplotlibExe defaultConfiguration)
+  parseJSON _ = fail $ mconcat ["Could not parse ", show Matplotlib, " configuration."]
 
 instance FromJSON MatlabPrecursor where
-    parseJSON (Object v) = MatlabPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (matlabExe defaultConfiguration)
-    parseJSON _ = fail $ mconcat ["Could not parse ", show Matlab, " configuration."]
+  parseJSON (Object v) = MatlabPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (matlabExe defaultConfiguration)
+  parseJSON _ = fail $ mconcat ["Could not parse ", show Matlab, " configuration."]
 
 instance FromJSON PlotlyPythonPrecursor where
-    parseJSON (Object v) = PlotlyPythonPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (plotlyPythonExe defaultConfiguration)
-    parseJSON _ = fail $ mconcat ["Could not parse ", show PlotlyPython, " configuration."]
+  parseJSON (Object v) = PlotlyPythonPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (plotlyPythonExe defaultConfiguration)
+  parseJSON _ = fail $ mconcat ["Could not parse ", show PlotlyPython, " configuration."]
 
 instance FromJSON PlotlyRPrecursor where
-    parseJSON (Object v) = PlotlyRPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (plotlyRExe defaultConfiguration)
-    parseJSON _ = fail $ mconcat ["Could not parse ", show PlotlyR, " configuration."]
+  parseJSON (Object v) = PlotlyRPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (plotlyRExe defaultConfiguration)
+  parseJSON _ = fail $ mconcat ["Could not parse ", show PlotlyR, " configuration."]
 
 instance FromJSON MathematicaPrecursor where
-    parseJSON (Object v) = MathematicaPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (mathematicaExe defaultConfiguration)
-    parseJSON _ = fail $ mconcat ["Could not parse ", show Mathematica, " configuration."]
+  parseJSON (Object v) = MathematicaPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (mathematicaExe defaultConfiguration)
+  parseJSON _ = fail $ mconcat ["Could not parse ", show Mathematica, " configuration."]
 
 instance FromJSON OctavePrecursor where
-    parseJSON (Object v) = OctavePrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (octaveExe defaultConfiguration)
-    parseJSON _ = fail $ mconcat ["Could not parse ", show Octave, " configuration."]
+  parseJSON (Object v) = OctavePrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (octaveExe defaultConfiguration)
+  parseJSON _ = fail $ mconcat ["Could not parse ", show Octave, " configuration."]
 
 instance FromJSON GGPlot2Precursor where
-    parseJSON (Object v) = GGPlot2Precursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (ggplot2Exe defaultConfiguration)
-    parseJSON _ = fail $ mconcat ["Could not parse ", show GGPlot2, " configuration."]
+  parseJSON (Object v) = GGPlot2Precursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (ggplot2Exe defaultConfiguration)
+  parseJSON _ = fail $ mconcat ["Could not parse ", show GGPlot2, " configuration."]
 
 instance FromJSON GNUPlotPrecursor where
-    parseJSON (Object v) = GNUPlotPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (gnuplotExe defaultConfiguration)
-    parseJSON _ = fail $ mconcat ["Could not parse ", show GNUPlot, " configuration."]
+  parseJSON (Object v) = GNUPlotPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (gnuplotExe defaultConfiguration)
+  parseJSON _ = fail $ mconcat ["Could not parse ", show GNUPlot, " configuration."]
 
 instance FromJSON GraphvizPrecursor where
-    parseJSON (Object v) = GraphvizPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (graphvizExe defaultConfiguration)
-    parseJSON _ = fail $ mconcat ["Could not parse ", show Graphviz, " configuration."]
+  parseJSON (Object v) = GraphvizPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (graphvizExe defaultConfiguration)
+  parseJSON _ = fail $ mconcat ["Could not parse ", show Graphviz, " configuration."]
 
 instance FromJSON BokehPrecursor where
-    parseJSON (Object v) = BokehPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (bokehExe defaultConfiguration)
-    parseJSON _ = fail $ mconcat ["Could not parse ", show Bokeh, " configuration."]
+  parseJSON (Object v) = BokehPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (bokehExe defaultConfiguration)
+  parseJSON _ = fail $ mconcat ["Could not parse ", show Bokeh, " configuration."]
 
 instance FromJSON PlotsjlPrecursor where
-    parseJSON (Object v) = PlotsjlPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (plotsjlExe defaultConfiguration)
-    parseJSON _ = fail $ mconcat ["Could not parse ", show Plotsjl, " configuration."]
-
+  parseJSON (Object v) = PlotsjlPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (plotsjlExe defaultConfiguration)
+  parseJSON _ = fail $ mconcat ["Could not parse ", show Plotsjl, " configuration."]
 
 instance FromJSON ConfigPrecursor where
-    parseJSON (Null) = return defaultConfigPrecursor -- In case of empty file
-    parseJSON (Object v) = do
-        
-        _defaultDirectory    <- v .:? (tshow DirectoryK)     .!= (_defaultDirectory defaultConfigPrecursor)
-        _defaultWithSource   <- v .:? (tshow WithSourceK)    .!= (_defaultWithSource defaultConfigPrecursor)
-        _defaultDPI          <- v .:? (tshow DpiK)           .!= (_defaultDPI defaultConfigPrecursor)
-        _defaultSaveFormat   <- v .:? (tshow SaveFormatK)    .!= (_defaultSaveFormat defaultConfigPrecursor)
-        _defaultDependencies <- v .:? (tshow DependenciesK)  .!= (_defaultDependencies defaultConfigPrecursor)
-        _captionFormat       <- v .:? (tshow CaptionFormatK) .!= (_captionFormat defaultConfigPrecursor)
-
-        _logPrec             <- v .:? "logging"              .!= _logPrec defaultConfigPrecursor
+  parseJSON (Null) = return defaultConfigPrecursor -- In case of empty file
+  parseJSON (Object v) = do
+    _defaultDirectory <- v .:? (tshow DirectoryK) .!= (_defaultDirectory defaultConfigPrecursor)
+    _defaultWithSource <- v .:? (tshow WithSourceK) .!= (_defaultWithSource defaultConfigPrecursor)
+    _defaultDPI <- v .:? (tshow DpiK) .!= (_defaultDPI defaultConfigPrecursor)
+    _defaultSaveFormat <- v .:? (tshow SaveFormatK) .!= (_defaultSaveFormat defaultConfigPrecursor)
+    _defaultDependencies <- v .:? (tshow DependenciesK) .!= (_defaultDependencies defaultConfigPrecursor)
+    _captionFormat <- v .:? (tshow CaptionFormatK) .!= (_captionFormat defaultConfigPrecursor)
+    _sourceCodeLabel <- v .:? (tshow SourceCodeLabelK) .!= (_sourceCodeLabel defaultConfigPrecursor)
 
-        _matplotlibPrec      <- v .:? (cls Matplotlib)       .!= _matplotlibPrec defaultConfigPrecursor
-        _matlabPrec          <- v .:? (cls Matlab)           .!= _matlabPrec defaultConfigPrecursor
-        _plotlyPythonPrec    <- v .:? (cls PlotlyPython)     .!= _plotlyPythonPrec defaultConfigPrecursor
-        _plotlyRPrec         <- v .:? (cls PlotlyR)          .!= _plotlyRPrec defaultConfigPrecursor
-        _mathematicaPrec     <- v .:? (cls Mathematica)      .!= _mathematicaPrec defaultConfigPrecursor
-        _octavePrec          <- v .:? (cls Octave)           .!= _octavePrec defaultConfigPrecursor
-        _ggplot2Prec         <- v .:? (cls GGPlot2)          .!= _ggplot2Prec defaultConfigPrecursor
-        _gnuplotPrec         <- v .:? (cls GNUPlot)          .!= _gnuplotPrec defaultConfigPrecursor
-        _graphvizPrec        <- v .:? (cls Graphviz)         .!= _graphvizPrec defaultConfigPrecursor
-        _bokehPrec           <- v .:? (cls Bokeh)            .!= _bokehPrec defaultConfigPrecursor 
-        _plotsjlPrec         <- v .:? (cls Plotsjl)          .!= _plotsjlPrec defaultConfigPrecursor
+    _logPrec <- v .:? "logging" .!= _logPrec defaultConfigPrecursor
 
-        return $ ConfigPrecursor{..}
-    parseJSON _          = fail "Could not parse configuration."
+    _matplotlibPrec <- v .:? (cls Matplotlib) .!= _matplotlibPrec defaultConfigPrecursor
+    _matlabPrec <- v .:? (cls Matlab) .!= _matlabPrec defaultConfigPrecursor
+    _plotlyPythonPrec <- v .:? (cls PlotlyPython) .!= _plotlyPythonPrec defaultConfigPrecursor
+    _plotlyRPrec <- v .:? (cls PlotlyR) .!= _plotlyRPrec defaultConfigPrecursor
+    _mathematicaPrec <- v .:? (cls Mathematica) .!= _mathematicaPrec defaultConfigPrecursor
+    _octavePrec <- v .:? (cls Octave) .!= _octavePrec defaultConfigPrecursor
+    _ggplot2Prec <- v .:? (cls GGPlot2) .!= _ggplot2Prec defaultConfigPrecursor
+    _gnuplotPrec <- v .:? (cls GNUPlot) .!= _gnuplotPrec defaultConfigPrecursor
+    _graphvizPrec <- v .:? (cls Graphviz) .!= _graphvizPrec defaultConfigPrecursor
+    _bokehPrec <- v .:? (cls Bokeh) .!= _bokehPrec defaultConfigPrecursor
+    _plotsjlPrec <- v .:? (cls Plotsjl) .!= _plotsjlPrec defaultConfigPrecursor
 
+    return $ ConfigPrecursor {..}
+  parseJSON _ = fail "Could not parse configuration."
 
 renderConfig :: ConfigPrecursor -> IO Configuration
-renderConfig ConfigPrecursor{..} = do
-    let defaultDirectory    = _defaultDirectory
-        defaultWithSource   = _defaultWithSource
-        defaultDPI          = _defaultDPI
-        defaultSaveFormat   = _defaultSaveFormat
-        defaultDependencies = _defaultDependencies
-        captionFormat       = _captionFormat
+renderConfig ConfigPrecursor {..} = do
+  let defaultDirectory = _defaultDirectory
+      defaultWithSource = _defaultWithSource
+      defaultDPI = _defaultDPI
+      defaultSaveFormat = _defaultSaveFormat
+      defaultDependencies = _defaultDependencies
+      captionFormat = _captionFormat
+      sourceCodeLabel = _sourceCodeLabel
 
-        logVerbosity        = _logVerbosity _logPrec
-        logSink             = maybe StdErr LogFile (_logFilePath _logPrec)
+      logVerbosity = _logVerbosity _logPrec
+      logSink = maybe StdErr LogFile (_logFilePath _logPrec)
 
-        matplotlibTightBBox   = _matplotlibTightBBox _matplotlibPrec
-        matplotlibTransparent = _matplotlibTransparent _matplotlibPrec
+      matplotlibTightBBox = _matplotlibTightBBox _matplotlibPrec
+      matplotlibTransparent = _matplotlibTransparent _matplotlibPrec
 
-        matplotlibExe   = _matplotlibExe _matplotlibPrec
-        matlabExe       = _matlabExe _matlabPrec
-        plotlyPythonExe = _plotlyPythonExe _plotlyPythonPrec
-        plotlyRExe      = _plotlyRExe _plotlyRPrec
-        mathematicaExe  = _mathematicaExe _mathematicaPrec
-        octaveExe       = _octaveExe _octavePrec
-        ggplot2Exe      = _ggplot2Exe _ggplot2Prec
-        gnuplotExe      = _gnuplotExe _gnuplotPrec
-        graphvizExe     = _graphvizExe _graphvizPrec
-        bokehExe        = _bokehExe _bokehPrec
-        plotsjlExe      = _plotsjlExe _plotsjlPrec
-    
-    matplotlibPreamble   <- readPreamble (_matplotlibPreamble _matplotlibPrec)
-    matlabPreamble       <- readPreamble (_matlabPreamble _matlabPrec)
-    plotlyPythonPreamble <- readPreamble (_plotlyPythonPreamble _plotlyPythonPrec)
-    plotlyRPreamble      <- readPreamble (_plotlyRPreamble _plotlyRPrec)
-    mathematicaPreamble  <- readPreamble (_mathematicaPreamble _mathematicaPrec)
-    octavePreamble       <- readPreamble (_octavePreamble _octavePrec)
-    ggplot2Preamble      <- readPreamble (_ggplot2Preamble _ggplot2Prec)
-    gnuplotPreamble      <- readPreamble (_gnuplotPreamble _gnuplotPrec)
-    graphvizPreamble     <- readPreamble (_graphvizPreamble _graphvizPrec)
-    bokehPreamble        <- readPreamble (_bokehPreamble _bokehPrec)
-    plotsjlPreamble      <- readPreamble (_plotsjlPreamble _plotsjlPrec)
+      matplotlibExe = _matplotlibExe _matplotlibPrec
+      matlabExe = _matlabExe _matlabPrec
+      plotlyPythonExe = _plotlyPythonExe _plotlyPythonPrec
+      plotlyRExe = _plotlyRExe _plotlyRPrec
+      mathematicaExe = _mathematicaExe _mathematicaPrec
+      octaveExe = _octaveExe _octavePrec
+      ggplot2Exe = _ggplot2Exe _ggplot2Prec
+      gnuplotExe = _gnuplotExe _gnuplotPrec
+      graphvizExe = _graphvizExe _graphvizPrec
+      bokehExe = _bokehExe _bokehPrec
+      plotsjlExe = _plotsjlExe _plotsjlPrec
 
-    return Configuration{..}
-    where
-        readPreamble fp = fromMaybe mempty $ TIO.readFile <$> fp
+  matplotlibPreamble <- readPreamble (_matplotlibPreamble _matplotlibPrec)
+  matlabPreamble <- readPreamble (_matlabPreamble _matlabPrec)
+  plotlyPythonPreamble <- readPreamble (_plotlyPythonPreamble _plotlyPythonPrec)
+  plotlyRPreamble <- readPreamble (_plotlyRPreamble _plotlyRPrec)
+  mathematicaPreamble <- readPreamble (_mathematicaPreamble _mathematicaPrec)
+  octavePreamble <- readPreamble (_octavePreamble _octavePrec)
+  ggplot2Preamble <- readPreamble (_ggplot2Preamble _ggplot2Prec)
+  gnuplotPreamble <- readPreamble (_gnuplotPreamble _gnuplotPrec)
+  graphvizPreamble <- readPreamble (_graphvizPreamble _graphvizPrec)
+  bokehPreamble <- readPreamble (_bokehPreamble _bokehPrec)
+  plotsjlPreamble <- readPreamble (_plotsjlPreamble _plotsjlPrec)
 
+  return Configuration {..}
+  where
+    readPreamble fp = fromMaybe mempty $ TIO.readFile <$> fp
 
 tshow :: Show a => a -> Text
-tshow = pack . show+tshow = pack . show
src/Text/Pandoc/Filter/Plot/Embed.hs view
@@ -1,88 +1,97 @@ {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Embedding HTML content
--}
-
-module Text.Pandoc.Filter.Plot.Embed (
-      extractPlot
-    , toFigure
-) where
-
-import           Data.Default                      (def)
-import           Data.List                         (nub)
-import           Data.Maybe                        (fromMaybe)
-import           Data.Text                         (Text, pack)
-import qualified Data.Text.IO                      as T
-
-import           System.FilePath                   (replaceExtension)
-
-import           Text.HTML.TagSoup
-
-import           Text.Pandoc.Builder               (fromList, imageWith, link,
-                                                    para, toList, Inlines)
-import           Text.Pandoc.Class                 (runPure)
-import           Text.Pandoc.Definition            (Pandoc(..), Block (..), Format, Attr)
-import           Text.Pandoc.Error                 (handleError)
-import           Text.Pandoc.Writers.HTML          (writeHtml5String)
-
-import           Text.Pandoc.Filter.Plot.Parse     (captionReader)
-import           Text.Pandoc.Filter.Plot.Monad
-import           Text.Pandoc.Filter.Plot.Scripting (figurePath)
+{-# LANGUAGE QuasiQuotes #-}
 
-import           Text.Shakespeare.Text             (st)
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Embedding HTML content
+module Text.Pandoc.Filter.Plot.Embed
+  ( extractPlot,
+    toFigure,
+  )
+where
 
+import Data.Default (def)
+import Data.List (nub)
+import Data.Maybe (fromMaybe)
+import Data.Text (Text, pack)
+import qualified Data.Text.IO as T
+import Text.HTML.TagSoup
+import Text.Pandoc.Builder
+  ( Inlines,
+    fromList,
+    imageWith,
+    link,
+    para,
+    str,
+    toList,
+  )
+import Text.Pandoc.Class (runPure)
+import Text.Pandoc.Definition (Attr, Block (..), Format, Pandoc (..))
+import Text.Pandoc.Error (handleError)
+import Text.Pandoc.Filter.Plot.Monad
+import Text.Pandoc.Filter.Plot.Parse (captionReader)
+import Text.Pandoc.Filter.Plot.Scripting (figurePath, sourceCodePath)
+import Text.Pandoc.Writers.HTML (writeHtml5String)
+import Text.Shakespeare.Text (st)
 
 -- | Convert a @FigureSpec@ to a Pandoc figure component.
 -- Note that the script to generate figure files must still
 -- be run in another function.
-toFigure :: Format       -- ^ text format of the caption
-         -> FigureSpec 
-         -> PlotM Block
+toFigure ::
+  -- | text format of the caption
+  Format ->
+  FigureSpec ->
+  PlotM Block
 toFigure fmt spec = do
-    target <- figurePath spec
-    let srcLink = link (pack $ replaceExtension target ".txt") mempty "Source code"
-        attrs'       = blockAttrs spec
-        withSource'  = withSource spec
-        captionText  = fromList $ fromMaybe mempty (captionReader fmt $ caption spec)
-        captionLinks = mconcat [" (", srcLink, ")"]
-        caption'     = if withSource' then captionText <> captionLinks else captionText
-    builder attrs' target caption'
-    where
-        builder      = if saveFormat spec == HTML
-                        then interactiveBlock
-                        else figure
-
+  target <- figurePath spec
+  scp <- pack <$> sourceCodePath spec
+  sourceLabel <- asksConfig sourceCodeLabel -- Allow the possibility for non-english labels
+  let srcLink = link scp mempty (str sourceLabel)
+      attrs' = blockAttrs spec
+      withSource' = withSource spec
+      captionText = fromList $ fromMaybe mempty (captionReader fmt $ caption spec)
+      captionLinks = mconcat [" (", srcLink, ")"]
+      caption' = if withSource' then captionText <> captionLinks else captionText
+  builder attrs' target caption'
+  where
+    builder =
+      if saveFormat spec == HTML
+        then interactiveBlock
+        else figure
 
-figure :: Attr
-       -> FilePath
-       -> Inlines
-       -> PlotM Block
+figure ::
+  Attr ->
+  FilePath ->
+  Inlines ->
+  PlotM Block
 -- To render images as figures with captions, the target title
 -- must be "fig:"
 -- Janky? yes
-figure as fp caption' = return . head . toList . para $ 
-                        imageWith as (pack fp) "fig:" caption'
-
+figure as fp caption' =
+  return . head . toList . para $
+    imageWith as (pack fp) "fig:" caption'
 
-interactiveBlock :: Attr
-                 -> FilePath
-                 -> Inlines
-                 -> PlotM Block
+interactiveBlock ::
+  Attr ->
+  FilePath ->
+  Inlines ->
+  PlotM Block
 interactiveBlock _ fp caption' = do
-    -- TODO: should we instead include the scripts in the "include-after"
-    --       template variable?
-    --       See https://github.com/jgm/pandoc/issues/6582
-    htmlpage <- liftIO $ T.readFile fp
-    renderedCaption <- writeHtml caption'
-    return $ RawBlock "html5" [st|
+  -- TODO: should we instead include the scripts in the "include-after"
+  --       template variable?
+  --       See https://github.com/jgm/pandoc/issues/6582
+  htmlpage <- liftIO $ T.readFile fp
+  renderedCaption <- writeHtml caption'
+  return $
+    RawBlock
+      "html5"
+      [st|
 <figure>
     <div>
     #{extractPlot htmlpage}
@@ -91,57 +100,52 @@ </figure>
     |]
 
-
 -- | Convert Pandoc inlines to html
 writeHtml :: Inlines -> PlotM Text
 writeHtml is = liftIO $ handleError $ runPure $ writeHtml5String def document
-    where
-        document = Pandoc mempty [Para . toList $ is]
-
+  where
+    document = Pandoc mempty [Para . toList $ is]
 
 -- | Extract the plot-relevant content from inside of a full HTML document.
 -- Scripts contained in the <head> tag are extracted, as well as the entirety of the
 -- <body> tag.
 extractPlot :: Text -> Text
-extractPlot t = let tags = canonicalizeTags $ parseTagsOptions parseOptionsFast t  
-                    extracted = headScripts tags <> [inside "body" $ tags]
-                in mconcat $ renderTags <$> (deferScripts <$> extracted)
-    where
-        headScripts = partitions (~== ("<script>"::String)) . inside "head"
-
+extractPlot t =
+  let tags = canonicalizeTags $ parseTagsOptions parseOptionsFast t
+      extracted = headScripts tags <> [inside "body" $ tags]
+   in mconcat $ renderTags <$> (deferScripts <$> extracted)
+  where
+    headScripts = partitions (~== ("<script>" :: String)) . inside "head"
 
 -- | Get content inside a tag, e.g. /inside "body"/ returns all tags
 -- between /<body>/ and /</body>/
 inside :: Text -> [Tag Text] -> [Tag Text]
 inside t = init . tail . tgs
-    where
-        tgs = takeWhile (~/= TagClose t) . dropWhile (~/= TagOpen t [])
-
-
-data ScriptTag = InlineScript [Attribute Text]
-               | ExternalScript [Attribute Text]
+  where
+    tgs = takeWhile (~/= TagClose t) . dropWhile (~/= TagOpen t [])
 
+data ScriptTag
+  = InlineScript [Attribute Text]
+  | ExternalScript [Attribute Text]
 
 fromTag :: Tag Text -> Maybe ScriptTag
-fromTag (TagOpen "script" attrs) = 
-    Just $ if "src" `elem` (fst . unzip $ attrs) 
-        then ExternalScript attrs
-        else InlineScript attrs
+fromTag (TagOpen "script" attrs) =
+  Just $
+    if "src" `elem` (fst . unzip $ attrs)
+      then ExternalScript attrs
+      else InlineScript attrs
 fromTag _ = Nothing
 
-
 toTag :: ScriptTag -> Tag Text
-toTag (InlineScript t)   = TagOpen "script" t
+toTag (InlineScript t) = TagOpen "script" t
 toTag (ExternalScript t) = TagOpen "script" t
 
-
 deferScript :: ScriptTag -> ScriptTag
-deferScript (InlineScript   attrs) = InlineScript   $ nub $ attrs <> [("type", "module")]
+deferScript (InlineScript attrs) = InlineScript $ nub $ attrs <> [("type", "module")]
 deferScript (ExternalScript attrs) = ExternalScript $ nub $ attrs <> [("defer", mempty)]
 
-
 -- | Replace /<script src=...>/ tags with /<script src=... defer>/,
 -- and inline scripts as /<script type="module">/.
 -- This makes scripts execute only after HTML parsing has finished.
 deferScripts :: [Tag Text] -> [Tag Text]
-deferScripts = fmap (\t -> maybe t (toTag . deferScript) (fromTag t))+deferScripts = fmap (\t -> maybe t (toTag . deferScript) (fromTag t))
src/Text/Pandoc/Filter/Plot/Internal.hs view
@@ -1,29 +1,28 @@-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-This module re-exports internal pandoc-plot functionality.
-The external use of content from this module is discouraged.
--}
-
-module Text.Pandoc.Filter.Plot.Internal (
-      module Text.Pandoc.Filter.Plot.Renderers
-    , module Text.Pandoc.Filter.Plot.Scripting
-    , module Text.Pandoc.Filter.Plot.Parse
-    , module Text.Pandoc.Filter.Plot.Configuration
-    , module Text.Pandoc.Filter.Plot.Clean
-    , module Text.Pandoc.Filter.Plot.Monad
-    , module Text.Pandoc.Filter.Plot.Embed
- ) where
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- This module re-exports internal pandoc-plot functionality.
+-- The external use of content from this module is discouraged.
+module Text.Pandoc.Filter.Plot.Internal
+  ( module Text.Pandoc.Filter.Plot.Renderers,
+    module Text.Pandoc.Filter.Plot.Scripting,
+    module Text.Pandoc.Filter.Plot.Parse,
+    module Text.Pandoc.Filter.Plot.Configuration,
+    module Text.Pandoc.Filter.Plot.Clean,
+    module Text.Pandoc.Filter.Plot.Monad,
+    module Text.Pandoc.Filter.Plot.Embed,
+  )
+where
 
+import Text.Pandoc.Filter.Plot.Clean
+import Text.Pandoc.Filter.Plot.Configuration
+import Text.Pandoc.Filter.Plot.Embed
+import Text.Pandoc.Filter.Plot.Monad
 import Text.Pandoc.Filter.Plot.Parse
 import Text.Pandoc.Filter.Plot.Renderers
 import Text.Pandoc.Filter.Plot.Scripting
-import Text.Pandoc.Filter.Plot.Configuration
-import Text.Pandoc.Filter.Plot.Clean
-import Text.Pandoc.Filter.Plot.Monad
-import Text.Pandoc.Filter.Plot.Embed
src/Text/Pandoc/Filter/Plot/Monad.hs view
@@ -1,237 +1,247 @@ {-# LANGUAGE OverloadedStrings #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
 
-This module defines the @PlotM@ monad and related capabilities.
--}
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- This module defines the @PlotM@ monad and related capabilities.
+module Text.Pandoc.Filter.Plot.Monad
+  ( Configuration (..),
+    PlotM,
+    RuntimeEnv (..),
+    runPlotM,
 
-module Text.Pandoc.Filter.Plot.Monad (
-      Configuration(..)
-    , PlotM
-    , RuntimeEnv(..)
-    , runPlotM
     -- * Running external commands
-    , runCommand
-    -- * Getting file hashes
-    , fileHash
-    -- * Getting executables
-    , executable
-    -- * Logging
-    , Verbosity(..)
-    , LogSink(..)
-    , debug
-    , err
-    , warning
-    , info
-    -- * Lifting and other monadic operations
-    , liftIO
-    , ask
-    , asks
-    , asksConfig
-    , silence
-    -- * Base types
-    , module Text.Pandoc.Filter.Plot.Monad.Types
-) where
-
-
-import           Control.Concurrent.Chan     (writeChan)
-import           Control.Concurrent.MVar
+    runCommand,
 
-import           Control.Monad.Reader
-import           Control.Monad.State.Strict
+    -- * Getting file hashes
+    fileHash,
 
-import           Data.ByteString.Lazy        (toStrict)
-import           Data.Hashable               (hash)
-import           Data.Map.Strict             (Map)
-import qualified Data.Map.Strict             as M
+    -- * Getting executables
+    executable,
 
-import           Data.Text                   (Text, pack, unpack)
-import qualified Data.Text                   as T
-import           Data.Text.Encoding          (decodeUtf8With)
-import           Data.Text.Encoding.Error    (lenientDecode)
+    -- * Logging
+    Verbosity (..),
+    LogSink (..),
+    debug,
+    err,
+    warning,
+    info,
 
-import           System.Directory            ( doesFileExist, getModificationTime
-                                             , findExecutable, getCurrentDirectory
-                                             )
-import           System.Exit                 (ExitCode (..))
-import           System.Process.Typed        ( readProcessStderr, shell, nullStream
-                                             , setStdout, setStderr, byteStringOutput
-                                             , setWorkingDir
-                                             )
-import           Text.Pandoc.Definition      (Format(..))
+    -- * Lifting and other monadic operations
+    liftIO,
+    ask,
+    asks,
+    asksConfig,
+    silence,
 
-import           Prelude                     hiding (log, fst, snd)
+    -- * Base types
+    module Text.Pandoc.Filter.Plot.Monad.Types,
+  )
+where
 
+import Control.Concurrent.Chan (writeChan)
+import Control.Concurrent.MVar
+import Control.Monad.Reader
+import Control.Monad.State.Strict
+import Data.ByteString.Lazy (toStrict)
+import Data.Hashable (hash)
+import Data.Map.Strict (Map)
+import qualified Data.Map.Strict as M
+import Data.Text (Text, pack, unpack)
+import qualified Data.Text as T
+import Data.Text.Encoding (decodeUtf8With)
+import Data.Text.Encoding.Error (lenientDecode)
+import System.Directory
+  ( doesFileExist,
+    findExecutable,
+    getCurrentDirectory,
+    getModificationTime,
+  )
+import System.Exit (ExitCode (..))
+import System.Process.Typed
+  ( byteStringOutput,
+    nullStream,
+    readProcessStderr,
+    setStderr,
+    setStdout,
+    setWorkingDir,
+    shell,
+  )
+import Text.Pandoc.Definition (Format (..))
 import Text.Pandoc.Filter.Plot.Monad.Logging as Log
 import Text.Pandoc.Filter.Plot.Monad.Types
-
+import Prelude hiding (fst, log, snd)
 
 -- | pandoc-plot monad
 type PlotM a = StateT PlotState (ReaderT RuntimeEnv IO) a
 
-
-data RuntimeEnv = 
-    RuntimeEnv { envConfig    :: Configuration
-               , envLogger    :: Logger
-               , envCWD       :: FilePath
-               }
-
+data RuntimeEnv = RuntimeEnv
+  { envConfig :: Configuration,
+    envLogger :: Logger,
+    envCWD :: FilePath
+  }
 
 -- | Modify the runtime environment to be silent.
 silence :: PlotM a -> PlotM a
-silence = local (\(RuntimeEnv c l d) -> RuntimeEnv c l{lVerbosity = Silent} d)
-
+silence = local (\(RuntimeEnv c l d) -> RuntimeEnv c l {lVerbosity = Silent} d)
 
 -- | Get access to configuration within the @PlotM@ monad.
 asksConfig :: (Configuration -> a) -> PlotM a
 asksConfig f = asks (f . envConfig)
 
-
 -- | Evaluate a @PlotM@ action.
 runPlotM :: Configuration -> PlotM a -> IO a
 runPlotM conf v = do
-    cwd <- getCurrentDirectory
-    st <- PlotState <$> newMVar mempty
-                    <*> newMVar mempty
-    let verbosity = logVerbosity conf
-        sink      = logSink conf 
-    withLogger verbosity sink $ 
-        \logger -> runReaderT (evalStateT v st) (RuntimeEnv conf logger cwd)
-
+  cwd <- getCurrentDirectory
+  st <-
+    PlotState <$> newMVar mempty
+      <*> newMVar mempty
+  let verbosity = logVerbosity conf
+      sink = logSink conf
+  withLogger verbosity sink $
+    \logger -> runReaderT (evalStateT v st) (RuntimeEnv conf logger cwd)
 
 debug, err, warning, info :: Text -> PlotM ()
-debug     = log "DEBUG | " Debug 
-err       = log "ERROR | " Error 
-warning   = log "WARN  | " Warning 
-info      = log "INFO  | " Info 
-
+debug = log "DEBUG | " Debug
+err = log "ERROR | " Error
+warning = log "WARN  | " Warning
+info = log "INFO  | " Info
 
--- | General purpose logging. 
-log :: Text      -- ^ Header.
-    -> Verbosity -- ^ Verbosity of the message.
-    -> Text      -- ^ Message (can be multiple lines).
-    -> PlotM ()
+-- | General purpose logging.
+log ::
+  -- | Header.
+  Text ->
+  -- | Verbosity of the message.
+  Verbosity ->
+  -- | Message (can be multiple lines).
+  Text ->
+  PlotM ()
 log h v t = do
-    logger <- asks envLogger
-    when (v >= lVerbosity logger) $ 
-        liftIO $ do
-            forM_ ( T.lines t) $ \l -> writeChan (lChannel logger) (Just (h <> l <> "\n"))
-
+  logger <- asks envLogger
+  when (v >= lVerbosity logger) $
+    liftIO $ do
+      forM_ (T.lines t) $ \l -> writeChan (lChannel logger) (Just (h <> l <> "\n"))
 
 -- | Run a command within the @PlotM@ monad. Stderr stream
--- is read and decoded, while Stdout is ignored. 
+-- is read and decoded, while Stdout is ignored.
 -- Logging happens at the debug level if the command succeeds, or at
 -- the error level if it does not succeed.
-runCommand :: FilePath  -- Directory from which to run the command
-           -> Text      -- Command to run, including executable
-           -> PlotM (ExitCode, Text)
+runCommand ::
+  FilePath -> -- Directory from which to run the command
+  Text -> -- Command to run, including executable
+  PlotM (ExitCode, Text)
 runCommand wordir command = do
-    (ec, processOutput') <- liftIO 
-                        $ readProcessStderr 
-                        $ setStdout nullStream
-                        $ setStderr byteStringOutput 
-                        $ setWorkingDir wordir
-                        $ shell (unpack command)
-    let processOutput = decodeUtf8With lenientDecode $ toStrict processOutput'
-        logFunc = if ec == ExitSuccess
-                    then debug
-                    else err
-        message = T.unlines [ "Running command"
-                            , "    " <> command
-                            , "ended with exit code " <> (pack . show $ ec)
-                            ] 
-        errorMessage = if processOutput == mempty 
-            then mempty 
-            else T.unlines [ "*******"
-                           , processOutput
-                           , "*******"
-                           ]
-    
-    logFunc $ message <> errorMessage
-    return (ec, processOutput)
+  (ec, processOutput') <-
+    liftIO $
+      readProcessStderr $
+        setStdout nullStream $
+          setStderr byteStringOutput $
+            setWorkingDir wordir $
+              shell (unpack command)
+  let processOutput = decodeUtf8With lenientDecode $ toStrict processOutput'
+      logFunc =
+        if ec == ExitSuccess
+          then debug
+          else err
+      message =
+        T.unlines
+          [ "Running command",
+            "    " <> command,
+            "ended with exit code " <> (pack . show $ ec)
+          ]
+      errorMessage =
+        if processOutput == mempty
+          then mempty
+          else
+            T.unlines
+              [ "*******",
+                processOutput,
+                "*******"
+              ]
 
+  logFunc $ message <> errorMessage
+  return (ec, processOutput)
 
 -- Plot state is used for caching.
 -- One part consists of a map of filepaths to hashes
 -- This allows multiple plots to depend on the same file/directory, and the file hashes
 -- will only be calculated once. This is OK because pandoc-plot will not run for long.
--- We note that because figures are rendered possibly in parallel, access to 
+-- We note that because figures are rendered possibly in parallel, access to
 -- the state must be synchronized; otherwise, each thread might compute its own
 -- hashes.
 -- The other part is comprised of a map of toolkits to executables (possibly missing)
 -- This means that executable will be search for only once.
-type FileHash  = Word
-data PlotState = 
-    PlotState (MVar (Map FilePath FileHash))
-              (MVar (Map Toolkit (Maybe Executable)))
+type FileHash = Word
 
+data PlotState
+  = PlotState
+      (MVar (Map FilePath FileHash))
+      (MVar (Map Toolkit (Maybe Executable)))
 
 -- | Get a filehash. If the file hash has been computed before,
 -- it is reused. Otherwise, the filehash is calculated and stored.
 fileHash :: FilePath -> PlotM FileHash
 fileHash path = do
-    PlotState varHashes varExes <- get
-    hashes <- liftIO $ takeMVar varHashes
-    (fh, hashes') <- case M.lookup path hashes of
-        Nothing -> do
-            debug $ mconcat ["Calculating hash of dependency ", pack path]
-            fh <- fileHash' path
-            let hashes' = M.insert path fh hashes
-            return (fh, hashes')
-        Just h -> do
-            debug $ mconcat ["Hash of dependency ", pack path, " already calculated."]
-            return (h, hashes)
-    liftIO $ putMVar varHashes hashes'
-    put $ PlotState varHashes varExes
-    return fh
-    where
+  PlotState varHashes varExes <- get
+  hashes <- liftIO $ takeMVar varHashes
+  (fh, hashes') <- case M.lookup path hashes of
+    Nothing -> do
+      debug $ mconcat ["Calculating hash of dependency ", pack path]
+      fh <- fileHash' path
+      let hashes' = M.insert path fh hashes
+      return (fh, hashes')
+    Just h -> do
+      debug $ mconcat ["Hash of dependency ", pack path, " already calculated."]
+      return (h, hashes)
+  liftIO $ putMVar varHashes hashes'
+  put $ PlotState varHashes varExes
+  return fh
+  where
     -- As a proxy for the state of a file dependency, we use the modification time
     -- This is much faster than actual file hashing
     fileHash' :: FilePath -> PlotM FileHash
     fileHash' fp = do
-        fileExists <- liftIO $ doesFileExist fp
-        if fileExists
-            then liftIO . fmap (fromIntegral . hash . show) . getModificationTime $ fp
-            else err (mconcat ["Dependency ", pack fp, " does not exist."]) >> return 0 
-
+      fileExists <- liftIO $ doesFileExist fp
+      if fileExists
+        then liftIO . fmap (fromIntegral . hash . show) . getModificationTime $ fp
+        else err (mconcat ["Dependency ", pack fp, " does not exist."]) >> return 0
 
--- | Get an executable. If the executable has not been used before, 
+-- | Get an executable. If the executable has not been used before,
 -- find it and store where it is. It will be re-used.
 executable :: Toolkit -> PlotM (Maybe Executable)
 executable tk = do
-    name <- exeSelector tk
-    PlotState varHashes varExes <- get
-    exes <- liftIO $ takeMVar varExes
-    (exe', exes') <- case M.lookup tk exes of
-        Nothing -> do
-            debug $ mconcat ["Looking for executable \"", pack name, "\" for ", pack $ show tk]
-            exe' <- liftIO $ findExecutable name >>= return . fmap exeFromPath
-            let exes' = M.insert tk exe' exes
-            return (exe', exes')
-        Just e -> do
-            debug $ mconcat ["Executable \"", pack name, "\" already found."]
-            return (e, exes)
-    liftIO $ putMVar varExes exes'
-    put $ PlotState varHashes varExes
-    return exe'
-    where
-        exeSelector Matplotlib   = asksConfig matplotlibExe  
-        exeSelector PlotlyPython = asksConfig plotlyPythonExe 
-        exeSelector PlotlyR      = asksConfig plotlyRExe      
-        exeSelector Matlab       = asksConfig matlabExe       
-        exeSelector Mathematica  = asksConfig mathematicaExe  
-        exeSelector Octave       = asksConfig octaveExe       
-        exeSelector GGPlot2      = asksConfig ggplot2Exe      
-        exeSelector GNUPlot      = asksConfig gnuplotExe      
-        exeSelector Graphviz     = asksConfig graphvizExe     
-        exeSelector Bokeh        = asksConfig bokehExe         
-        exeSelector Plotsjl      = asksConfig plotsjlExe 
-
+  name <- exeSelector tk
+  PlotState varHashes varExes <- get
+  exes <- liftIO $ takeMVar varExes
+  (exe', exes') <- case M.lookup tk exes of
+    Nothing -> do
+      debug $ mconcat ["Looking for executable \"", pack name, "\" for ", pack $ show tk]
+      exe' <- liftIO $ findExecutable name >>= return . fmap exeFromPath
+      let exes' = M.insert tk exe' exes
+      return (exe', exes')
+    Just e -> do
+      debug $ mconcat ["Executable \"", pack name, "\" already found."]
+      return (e, exes)
+  liftIO $ putMVar varExes exes'
+  put $ PlotState varHashes varExes
+  return exe'
+  where
+    exeSelector Matplotlib = asksConfig matplotlibExe
+    exeSelector PlotlyPython = asksConfig plotlyPythonExe
+    exeSelector PlotlyR = asksConfig plotlyRExe
+    exeSelector Matlab = asksConfig matlabExe
+    exeSelector Mathematica = asksConfig mathematicaExe
+    exeSelector Octave = asksConfig octaveExe
+    exeSelector GGPlot2 = asksConfig ggplot2Exe
+    exeSelector GNUPlot = asksConfig gnuplotExe
+    exeSelector Graphviz = asksConfig graphvizExe
+    exeSelector Bokeh = asksConfig bokehExe
+    exeSelector Plotsjl = asksConfig plotsjlExe
 
 -- | The @Configuration@ type holds the default values to use
 -- when running pandoc-plot. These values can be overridden in code blocks.
@@ -245,7 +255,7 @@ --     title: My document
 --     author: John Doe
 --     plot-configuration: path\to\file.yml
---     ---     
+--     ---
 -- @
 --
 -- The same can be specified via the command line using Pandoc's @-M@ flag:
@@ -254,40 +264,71 @@ --
 -- In this case, use @configurationPathMeta@ to extact the path from @Pandoc@ documents.
 data Configuration = Configuration
-    { defaultDirectory      :: !FilePath   -- ^ The default directory where figures will be saved.
-    , defaultWithSource     :: !Bool       -- ^ The default behavior of whether or not to include links to source code and high-res
-    , defaultDPI            :: !Int        -- ^ The default dots-per-inch value for generated figures. Renderers might ignore this.
-    , defaultSaveFormat     :: !SaveFormat -- ^ The default save format of generated figures.
-    , defaultDependencies   :: ![FilePath] -- ^ List of files/directories on which all figures depend.
-    , captionFormat         :: !Format     -- ^ Caption format, in the same notation as Pandoc format, e.g. "markdown+tex_math_dollars"
-
-    , logVerbosity          :: !Verbosity  -- ^ Level of logging verbosity.
-    , logSink               :: !LogSink    -- ^ Method of logging, i.e. printing to stderr or file.
-
-    , matplotlibPreamble    :: !Script     -- ^ The default preamble script for the matplotlib toolkit.
-    , plotlyPythonPreamble  :: !Script     -- ^ The default preamble script for the Plotly/Python toolkit.
-    , plotlyRPreamble       :: !Script     -- ^ The default preamble script for the Plotly/R toolkit.
-    , matlabPreamble        :: !Script     -- ^ The default preamble script for the MATLAB toolkit.
-    , mathematicaPreamble   :: !Script     -- ^ The default preamble script for the Mathematica toolkit.
-    , octavePreamble        :: !Script     -- ^ The default preamble script for the GNU Octave toolkit.
-    , ggplot2Preamble       :: !Script     -- ^ The default preamble script for the GGPlot2 toolkit.
-    , gnuplotPreamble       :: !Script     -- ^ The default preamble script for the gnuplot toolkit.
-    , graphvizPreamble      :: !Script     -- ^ The default preamble script for the Graphviz toolkit.
-    , bokehPreamble         :: !Script     -- ^ The default preamble script for the Python/Bokeh toolkit.
-    , plotsjlPreamble       :: !Script     -- ^ The default preamble script for the Julia/Plots.jl toolkit.
-    
-    , matplotlibExe         :: !FilePath   -- ^ The executable to use to generate figures using the matplotlib toolkit.
-    , matlabExe             :: !FilePath   -- ^ The executable to use to generate figures using the MATLAB toolkit.
-    , plotlyPythonExe       :: !FilePath   -- ^ The executable to use to generate figures using the Plotly/Python toolkit.
-    , plotlyRExe            :: !FilePath   -- ^ The executable to use to generate figures using the Plotly/R toolkit.
-    , mathematicaExe        :: !FilePath   -- ^ The executable to use to generate figures using the Mathematica toolkit.
-    , octaveExe             :: !FilePath   -- ^ The executable to use to generate figures using the GNU Octave toolkit.
-    , ggplot2Exe            :: !FilePath   -- ^ The executable to use to generate figures using the GGPlot2 toolkit.
-    , gnuplotExe            :: !FilePath   -- ^ The executable to use to generate figures using the gnuplot toolkit.
-    , graphvizExe           :: !FilePath   -- ^ The executable to use to generate figures using the Graphviz toolkit.
-    , bokehExe              :: !FilePath   -- ^ The executable to use to generate figures using the Python/Bokeh toolkit.
-    , plotsjlExe            :: !FilePath   -- ^ The executable to use to generate figures using the Julia/Plots.jl toolkit.
-    
-    , matplotlibTightBBox   :: !Bool       -- ^ Whether or not to make Matplotlib figures tight by default.
-    , matplotlibTransparent :: !Bool       -- ^ Whether or not to make Matplotlib figures transparent by default.
-    } deriving (Eq, Show)+  { -- | The default directory where figures will be saved.
+    defaultDirectory :: !FilePath,
+    -- | The default behavior of whether or not to include links to source code and high-res
+    defaultWithSource :: !Bool,
+    -- | The default dots-per-inch value for generated figures. Renderers might ignore this.
+    defaultDPI :: !Int,
+    -- | The default save format of generated figures.
+    defaultSaveFormat :: !SaveFormat,
+    -- | List of files/directories on which all figures depend.
+    defaultDependencies :: ![FilePath],
+    -- | Caption format, in the same notation as Pandoc format, e.g. "markdown+tex_math_dollars"
+    captionFormat :: !Format,
+    -- | The text label to which the source code is linked. Change this if you are writing non-english documents.
+    sourceCodeLabel :: !Text,
+    -- | Level of logging verbosity.
+    logVerbosity :: !Verbosity,
+    -- | Method of logging, i.e. printing to stderr or file.
+    logSink :: !LogSink,
+    -- | The default preamble script for the matplotlib toolkit.
+    matplotlibPreamble :: !Script,
+    -- | The default preamble script for the Plotly/Python toolkit.
+    plotlyPythonPreamble :: !Script,
+    -- | The default preamble script for the Plotly/R toolkit.
+    plotlyRPreamble :: !Script,
+    -- | The default preamble script for the MATLAB toolkit.
+    matlabPreamble :: !Script,
+    -- | The default preamble script for the Mathematica toolkit.
+    mathematicaPreamble :: !Script,
+    -- | The default preamble script for the GNU Octave toolkit.
+    octavePreamble :: !Script,
+    -- | The default preamble script for the GGPlot2 toolkit.
+    ggplot2Preamble :: !Script,
+    -- | The default preamble script for the gnuplot toolkit.
+    gnuplotPreamble :: !Script,
+    -- | The default preamble script for the Graphviz toolkit.
+    graphvizPreamble :: !Script,
+    -- | The default preamble script for the Python/Bokeh toolkit.
+    bokehPreamble :: !Script,
+    -- | The default preamble script for the Julia/Plots.jl toolkit.
+    plotsjlPreamble :: !Script,
+    -- | The executable to use to generate figures using the matplotlib toolkit.
+    matplotlibExe :: !FilePath,
+    -- | The executable to use to generate figures using the MATLAB toolkit.
+    matlabExe :: !FilePath,
+    -- | The executable to use to generate figures using the Plotly/Python toolkit.
+    plotlyPythonExe :: !FilePath,
+    -- | The executable to use to generate figures using the Plotly/R toolkit.
+    plotlyRExe :: !FilePath,
+    -- | The executable to use to generate figures using the Mathematica toolkit.
+    mathematicaExe :: !FilePath,
+    -- | The executable to use to generate figures using the GNU Octave toolkit.
+    octaveExe :: !FilePath,
+    -- | The executable to use to generate figures using the GGPlot2 toolkit.
+    ggplot2Exe :: !FilePath,
+    -- | The executable to use to generate figures using the gnuplot toolkit.
+    gnuplotExe :: !FilePath,
+    -- | The executable to use to generate figures using the Graphviz toolkit.
+    graphvizExe :: !FilePath,
+    -- | The executable to use to generate figures using the Python/Bokeh toolkit.
+    bokehExe :: !FilePath,
+    -- | The executable to use to generate figures using the Julia/Plots.jl toolkit.
+    plotsjlExe :: !FilePath,
+    -- | Whether or not to make Matplotlib figures tight by default.
+    matplotlibTightBBox :: !Bool,
+    -- | Whether or not to make Matplotlib figures transparent by default.
+    matplotlibTransparent :: !Bool
+  }
+  deriving (Eq, Show)
src/Text/Pandoc/Filter/Plot/Monad/Logging.hs view
@@ -1,111 +1,112 @@ {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards   #-}
-
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Logging primitives.
--}
-
-module Text.Pandoc.Filter.Plot.Monad.Logging 
-    ( Verbosity(..)
-    , LogSink(..)
-    , Logger(..)
-    , withLogger
-    ) where
-
-
-import           Control.Concurrent           (forkIO)
-import           Control.Concurrent.Chan      (Chan, newChan, readChan, writeChan)
-import           Control.Concurrent.MVar      (MVar, newEmptyMVar, putMVar, takeMVar)
-
-import           Control.Monad                (forever)
-
-import           Data.Char                    (toLower)
-import           Data.List                    (intercalate)
-import           Data.String                  (IsString(..))
-import           Data.Text                    (Text, unpack)
-import           Data.Text.IO                 (hPutStr)
-import           Data.Yaml                    (FromJSON(parseJSON), Value(String))
-
-import           System.IO                    (stderr, withFile, IOMode (AppendMode) )
+{-# LANGUAGE RecordWildCards #-}
 
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Logging primitives.
+module Text.Pandoc.Filter.Plot.Monad.Logging
+  ( Verbosity (..),
+    LogSink (..),
+    Logger (..),
+    withLogger,
+  )
+where
 
+import Control.Concurrent (forkIO)
+import Control.Concurrent.Chan (Chan, newChan, readChan, writeChan)
+import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, takeMVar)
+import Control.Monad (forever)
+import Data.Char (toLower)
+import Data.List (intercalate)
+import Data.String (IsString (..))
+import Data.Text (Text, unpack)
+import Data.Text.IO (hPutStr)
+import Data.Yaml (FromJSON (parseJSON), Value (String))
+import System.IO (IOMode (AppendMode), stderr, withFile)
 
 -- | Verbosity of the logger.
-data Verbosity = Debug    -- ^ Log all messages, including debug messages.
-               | Info     -- ^ Log information, warning, and error messages.
-               | Warning  -- ^ Log warning and error messages.
-               | Error    -- ^ Only log errors.
-               | Silent   -- ^ Don't log anything. 
-               deriving (Eq, Ord, Show, Enum, Bounded)
-
+data Verbosity
+  = -- | Log all messages, including debug messages.
+    Debug
+  | -- | Log information, warning, and error messages.
+    Info
+  | -- | Log warning and error messages.
+    Warning
+  | -- | Only log errors.
+    Error
+  | -- | Don't log anything.
+    Silent
+  deriving (Eq, Ord, Show, Enum, Bounded)
 
 -- | Description of the possible ways to sink log messages.
-data LogSink = StdErr           -- ^ Standard error stream.
-             | LogFile FilePath -- ^ Appended to file.
-             deriving (Eq, Show)
-
+data LogSink
+  = -- | Standard error stream.
+    StdErr
+  | -- | Appended to file.
+    LogFile FilePath
+  deriving (Eq, Show)
 
 -- | The logging implementation is very similar to Hakyll's.
 data Logger = Logger
-    { lVerbosity :: Verbosity
-    , lChannel   :: Chan (Maybe Text)
-    , lSink      :: Text -> IO ()
-    , lSync      :: MVar ()
-    }
-
+  { lVerbosity :: Verbosity,
+    lChannel :: Chan (Maybe Text),
+    lSink :: Text -> IO (),
+    lSync :: MVar ()
+  }
 
 -- | Perform an IO action with a logger. Using this function
 -- ensures that logging will be gracefully shut down.
 withLogger :: Verbosity -> LogSink -> (Logger -> IO a) -> IO a
 withLogger v s f = do
-    logger <- Logger <$> pure v
-                     <*> newChan
-                     <*> pure (sink s)
-                     <*> newEmptyMVar 
-
-    -- The logger either logs messages (if Just "message"),
-    -- or stops working on Nothing.
-    _ <- forkIO $ forever $ 
-            readChan (lChannel logger) 
-                >>= maybe (putMVar (lSync logger) ()) (lSink logger)
+  logger <-
+    Logger <$> pure v
+      <*> newChan
+      <*> pure (sink s)
+      <*> newEmptyMVar
 
-    result <- f logger
-    
-    -- Flushing the logger
-    -- To signal to the logger that logging duties are over,
-    -- we append Nothing to the channel, and wait for it to finish
-    -- dealing with all items in the channel.
-    writeChan (lChannel logger) Nothing
-    () <- takeMVar (lSync logger)
+  -- The logger either logs messages (if Just "message"),
+  -- or stops working on Nothing.
+  _ <-
+    forkIO $
+      forever $
+        readChan (lChannel logger)
+          >>= maybe (putMVar (lSync logger) ()) (lSink logger)
 
-    return result
+  result <- f logger
 
-    where
-        sink StdErr       = hPutStr stderr
-        sink (LogFile fp) = \t -> withFile fp AppendMode $ \h -> hPutStr h t
+  -- Flushing the logger
+  -- To signal to the logger that logging duties are over,
+  -- we append Nothing to the channel, and wait for it to finish
+  -- dealing with all items in the channel.
+  writeChan (lChannel logger) Nothing
+  () <- takeMVar (lSync logger)
 
+  return result
+  where
+    sink StdErr = hPutStr stderr
+    sink (LogFile fp) = \t -> withFile fp AppendMode $ \h -> hPutStr h t
 
 instance IsString Verbosity where
-    fromString s
-        | ls == "silent"  = Silent
-        | ls == "info"    = Info
-        | ls == "warning" = Warning
-        | ls == "error"   = Error
-        | ls == "debug"   = Debug
-        | otherwise = errorWithoutStackTrace $ mconcat ["Unrecognized verbosity '", s, "'. Valid choices are: " ] <> choices
-        where
-            ls = toLower <$> s
-            choices = intercalate ", " 
-                    $ fmap (fmap toLower . show) 
-                    $ enumFromTo minBound (maxBound::Verbosity)
+  fromString s
+    | ls == "silent" = Silent
+    | ls == "info" = Info
+    | ls == "warning" = Warning
+    | ls == "error" = Error
+    | ls == "debug" = Debug
+    | otherwise = errorWithoutStackTrace $ mconcat ["Unrecognized verbosity '", s, "'. Valid choices are: "] <> choices
+    where
+      ls = toLower <$> s
+      choices =
+        intercalate ", " $
+          fmap (fmap toLower . show) $
+            enumFromTo minBound (maxBound :: Verbosity)
 
 instance FromJSON Verbosity where
-    parseJSON (String t) = pure $ fromString . unpack $ t
-    parseJSON _ = fail $ "Could not parse the logging verbosity."+  parseJSON (String t) = pure $ fromString . unpack $ t
+  parseJSON _ = fail $ "Could not parse the logging verbosity."
src/Text/Pandoc/Filter/Plot/Monad/Types.hs view
@@ -1,231 +1,235 @@-{-# LANGUAGE DeriveGeneric     #-}
+{-# LANGUAGE DeriveGeneric #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards   #-}
-
-
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-This module defines base types in use in pandoc-plot
--}
+{-# LANGUAGE RecordWildCards #-}
 
-module Text.Pandoc.Filter.Plot.Monad.Types (
-      Toolkit(..)
-    , Script
-    , CheckResult(..)
-    , InclusionKey(..)
-    , FigureSpec(..)
-    , SaveFormat(..)
-    , cls
-    , extension
-    , toolkits
-    , inclusionKeys
-    , Executable(..)
-    , exeFromPath
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- This module defines base types in use in pandoc-plot
+module Text.Pandoc.Filter.Plot.Monad.Types
+  ( Toolkit (..),
+    Script,
+    CheckResult (..),
+    InclusionKey (..),
+    FigureSpec (..),
+    SaveFormat (..),
+    cls,
+    extension,
+    toolkits,
+    inclusionKeys,
+    Executable (..),
+    exeFromPath,
     -- Utilities
-    , isWindows
-) where
-
-import           Data.Char              (toLower)
-import           Data.List              (intersperse)
-import           Data.String            (IsString (..))
-import           Data.Text              (Text, pack)
-import           Data.Yaml              (FromJSON, ToJSON(toJSON))
-
-import           GHC.Generics           (Generic)
-import           System.FilePath        (splitFileName)
-import           System.Info            (os)
+    isWindows,
+  )
+where
 
-import           Text.Pandoc.Definition (Attr)
+import Data.Char (toLower)
+import Data.List (intersperse)
+import Data.String (IsString (..))
+import Data.Text (Text, pack)
+import Data.Yaml (FromJSON, ToJSON (toJSON))
+import GHC.Generics (Generic)
+import System.FilePath (splitFileName)
+import System.Info (os)
+import Text.Pandoc.Definition (Attr)
 
 -- | List of supported toolkits.
 toolkits :: [Toolkit]
 toolkits = enumFromTo minBound maxBound
 
-
 -- | Enumeration of supported toolkits
 data Toolkit
-    = Matplotlib
-    | Matlab
-    | PlotlyPython
-    | PlotlyR
-    | Mathematica
-    | Octave
-    | GGPlot2
-    | GNUPlot
-    | Graphviz
-    | Bokeh
-    | Plotsjl
-    deriving (Bounded, Eq, Enum, Generic, Ord)
-
+  = Matplotlib
+  | Matlab
+  | PlotlyPython
+  | PlotlyR
+  | Mathematica
+  | Octave
+  | GGPlot2
+  | GNUPlot
+  | Graphviz
+  | Bokeh
+  | Plotsjl
+  deriving (Bounded, Eq, Enum, Generic, Ord)
 
 -- | This instance should only be used to display toolkit names
 instance Show Toolkit where
-    show Matplotlib   = "Python/Matplotlib"
-    show Matlab       = "MATLAB"
-    show PlotlyPython = "Python/Plotly"
-    show PlotlyR      = "R/Plotly"
-    show Mathematica  = "Mathematica"
-    show Octave       = "GNU Octave"
-    show GGPlot2      = "ggplot2"
-    show GNUPlot      = "gnuplot"
-    show Graphviz     = "graphviz"
-    show Bokeh        = "Python/Bokeh"
-    show Plotsjl      = "Julia/Plots.jl"
-
+  show Matplotlib = "Python/Matplotlib"
+  show Matlab = "MATLAB"
+  show PlotlyPython = "Python/Plotly"
+  show PlotlyR = "R/Plotly"
+  show Mathematica = "Mathematica"
+  show Octave = "GNU Octave"
+  show GGPlot2 = "ggplot2"
+  show GNUPlot = "gnuplot"
+  show Graphviz = "graphviz"
+  show Bokeh = "Python/Bokeh"
+  show Plotsjl = "Julia/Plots.jl"
 
 -- | Class name which will trigger the filter
 cls :: Toolkit -> Text
-cls Matplotlib   = "matplotlib"
-cls Matlab       = "matlabplot"
+cls Matplotlib = "matplotlib"
+cls Matlab = "matlabplot"
 cls PlotlyPython = "plotly_python"
-cls PlotlyR      = "plotly_r"
-cls Mathematica  = "mathplot"
-cls Octave       = "octaveplot"
-cls GGPlot2      = "ggplot2"
-cls GNUPlot      = "gnuplot"
-cls Graphviz     = "graphviz"
-cls Bokeh        = "bokeh"
-cls Plotsjl      = "plotsjl"
-
+cls PlotlyR = "plotly_r"
+cls Mathematica = "mathplot"
+cls Octave = "octaveplot"
+cls GGPlot2 = "ggplot2"
+cls GNUPlot = "gnuplot"
+cls Graphviz = "graphviz"
+cls Bokeh = "bokeh"
+cls Plotsjl = "plotsjl"
 
 -- | Executable program and directory where it can be found.
 data Executable = Executable FilePath Text
 
-
 exeFromPath :: FilePath -> Executable
-exeFromPath fp = let (dir, name) = splitFileName fp
-                 in Executable dir (pack name)
-
+exeFromPath fp =
+  let (dir, name) = splitFileName fp
+   in Executable dir (pack name)
 
 -- | Source context for plotting scripts
 type Script = Text
 
-
 -- | Result of checking scripts for problems
 data CheckResult
-    = CheckPassed
-    | CheckFailed Text
-    deriving (Eq)
+  = CheckPassed
+  | CheckFailed Text
+  deriving (Eq)
 
 instance Semigroup CheckResult where
-    (<>) CheckPassed a                         = a
-    (<>) a CheckPassed                         = a
-    (<>) (CheckFailed msg1) (CheckFailed msg2) = CheckFailed (msg1 <> msg2)
+  (<>) CheckPassed a = a
+  (<>) a CheckPassed = a
+  (<>) (CheckFailed msg1) (CheckFailed msg2) = CheckFailed (msg1 <> msg2)
 
 instance Monoid CheckResult where
-    mempty = CheckPassed
-
+  mempty = CheckPassed
 
 -- | Description of any possible inclusion key, both in documents
 -- and in configuration files.
 data InclusionKey
-    = DirectoryK
-    | CaptionK
-    | SaveFormatK
-    | WithSourceK
-    | CaptionFormatK
-    | PreambleK
-    | DpiK
-    | ExecutableK
-    | DependenciesK
-    | FileK
-    | MatplotlibTightBBoxK
-    | MatplotlibTransparentK
-    deriving (Bounded, Eq, Enum)
+  = DirectoryK
+  | CaptionK
+  | SaveFormatK
+  | WithSourceK
+  | CaptionFormatK
+  | PreambleK
+  | DpiK
+  | SourceCodeLabelK
+  | ExecutableK
+  | DependenciesK
+  | FileK
+  | MatplotlibTightBBoxK
+  | MatplotlibTransparentK
+  deriving (Bounded, Eq, Enum)
 
 -- | Keys that pandoc-plot will look for in code blocks.
 -- These are only exported for testing purposes.
 instance Show InclusionKey where
-    show DirectoryK             = "directory"
-    show CaptionK               = "caption"
-    show SaveFormatK            = "format"
-    show WithSourceK            = "source"
-    show CaptionFormatK         = "caption_format"
-    show PreambleK              = "preamble"
-    show DpiK                   = "dpi"
-    show ExecutableK            = "executable"
-    show DependenciesK          = "dependencies"
-    show FileK                  = "file"
-    show MatplotlibTightBBoxK   = "tight_bbox"
-    show MatplotlibTransparentK = "transparent"
-
+  show DirectoryK = "directory"
+  show CaptionK = "caption"
+  show SaveFormatK = "format"
+  show WithSourceK = "source"
+  show CaptionFormatK = "caption_format"
+  show PreambleK = "preamble"
+  show DpiK = "dpi"
+  show SourceCodeLabelK = "source_label"
+  show ExecutableK = "executable"
+  show DependenciesK = "dependencies"
+  show FileK = "file"
+  show MatplotlibTightBBoxK = "tight_bbox"
+  show MatplotlibTransparentK = "transparent"
 
 -- | List of all keys related to pandoc-plot that
 -- can be specified in source material.
 inclusionKeys :: [InclusionKey]
-inclusionKeys = enumFromTo (minBound::InclusionKey) maxBound
-
+inclusionKeys = enumFromTo (minBound :: InclusionKey) maxBound
 
 -- | Datatype containing all parameters required to run pandoc-plot.
 --
 -- It is assumed that once a @FigureSpec@ has been created, no configuration
 -- can overload it; hence, a @FigureSpec@ completely encodes a particular figure.
 data FigureSpec = FigureSpec
-    { toolkit      :: !Toolkit        -- ^ Plotting toolkit to use for this figure.
-    , caption      :: !Text           -- ^ Figure caption.
-    , withSource   :: !Bool           -- ^ Append link to source code in caption.
-    , script       :: !Script         -- ^ Source code for the figure.
-    , saveFormat   :: !SaveFormat     -- ^ Save format of the figure.
-    , directory    :: !FilePath       -- ^ Directory where to save the file.
-    , dpi          :: !Int            -- ^ Dots-per-inch of figure.
-    , dependencies :: ![FilePath]     -- ^ Files/directories on which this figure depends, e.g. data files.
-    , extraAttrs   :: ![(Text, Text)] -- ^ Renderer-specific extra attributes.
-    , blockAttrs   :: !Attr           -- ^ Attributes not related to @pandoc-plot@ will be propagated.
-    }
-
+  { -- | Plotting toolkit to use for this figure.
+    toolkit :: !Toolkit,
+    -- | Figure caption.
+    caption :: !Text,
+    -- | Append link to source code in caption.
+    withSource :: !Bool,
+    -- | Source code for the figure.
+    script :: !Script,
+    -- | Save format of the figure.
+    saveFormat :: !SaveFormat,
+    -- | Directory where to save the file.
+    directory :: !FilePath,
+    -- | Dots-per-inch of figure.
+    dpi :: !Int,
+    -- | Files/directories on which this figure depends, e.g. data files.
+    dependencies :: ![FilePath],
+    -- | Renderer-specific extra attributes.
+    extraAttrs :: ![(Text, Text)],
+    -- | Attributes not related to @pandoc-plot@ will be propagated.
+    blockAttrs :: !Attr
+  }
 
 -- | Generated figure file format supported by pandoc-plot.
 -- Note that not all formats are supported by all toolkits.
 data SaveFormat
-    = PNG   -- ^ Portable network graphics
-    | PDF   -- ^ Portable document format
-    | SVG   -- ^ Scalable vector graphics
-    | JPG   -- ^ JPEG/JPG compressed image
-    | EPS   -- ^ Encapsulated postscript
-    | GIF   -- ^ GIF format
-    | TIF   -- ^ Tagged image format
-    | WEBP  -- ^ WebP image format
-    | HTML  -- ^ HTML for interactive plots.
-    deriving (Bounded, Enum, Eq, Show, Generic)
+  = -- | Portable network graphics
+    PNG
+  | -- | Portable document format
+    PDF
+  | -- | Scalable vector graphics
+    SVG
+  | -- | JPEG/JPG compressed image
+    JPG
+  | -- | Encapsulated postscript
+    EPS
+  | -- | GIF format
+    GIF
+  | -- | Tagged image format
+    TIF
+  | -- | WebP image format
+    WEBP
+  | -- | HTML for interactive plots.
+    HTML
+  deriving (Bounded, Enum, Eq, Show, Generic)
 
 instance IsString SaveFormat where
-    -- | An error is thrown if the save format cannot be parsed. That's OK
-    -- since pandoc-plot is a command-line tool and isn't expected to run
-    -- long.
-    fromString s
-        | s `elem` ["png", "PNG", ".png"] = PNG
-        | s `elem` ["pdf", "PDF", ".pdf"] = PDF
-        | s `elem` ["svg", "SVG", ".svg"] = SVG
-        | s `elem` ["eps", "EPS", ".eps"] = EPS
-        | s `elem` ["gif", "GIF", ".gif"] = GIF
-        | s `elem` ["jpg", "jpeg", "JPG", "JPEG", ".jpg", ".jpeg"] = JPG
-        | s `elem` ["tif", "tiff", "TIF", "TIFF", ".tif", ".tiff"] = TIF
-        | s `elem` ["webp", "WEBP", ".webp"] = WEBP
-        | s `elem` ["html", "HTML", ".html"] = HTML
-        | otherwise = errorWithoutStackTrace $
-                mconcat [ s
-                        , " is not one of valid save format : "
-                        , mconcat $ intersperse ", " $ show <$> saveFormats
-                        ]
-        where
-            saveFormats =  (enumFromTo minBound maxBound) :: [SaveFormat]
+  fromString s
+    | s `elem` ["png", "PNG", ".png"] = PNG
+    | s `elem` ["pdf", "PDF", ".pdf"] = PDF
+    | s `elem` ["svg", "SVG", ".svg"] = SVG
+    | s `elem` ["eps", "EPS", ".eps"] = EPS
+    | s `elem` ["gif", "GIF", ".gif"] = GIF
+    | s `elem` ["jpg", "jpeg", "JPG", "JPEG", ".jpg", ".jpeg"] = JPG
+    | s `elem` ["tif", "tiff", "TIF", "TIFF", ".tif", ".tiff"] = TIF
+    | s `elem` ["webp", "WEBP", ".webp"] = WEBP
+    | s `elem` ["html", "HTML", ".html"] = HTML
+    | otherwise =
+      errorWithoutStackTrace $
+        mconcat
+          [ s,
+            " is not one of valid save format : ",
+            mconcat $ intersperse ", " $ show <$> saveFormats
+          ]
+    where
+      saveFormats = (enumFromTo minBound maxBound) :: [SaveFormat]
 
 instance FromJSON SaveFormat -- TODO: test this parsing
 
 instance ToJSON SaveFormat where
-    toJSON = toJSON . extension
-
+  toJSON = toJSON . extension
 
 -- | Save format file extension
 extension :: SaveFormat -> String
 extension fmt = mconcat [".", fmap toLower . show $ fmt]
 
-
 isWindows :: Bool
-isWindows = os `elem` ["mingw32", "win32", "cygwin32"] -- Aliases taken from cabal's Distribution.System module+isWindows = os `elem` ["mingw32", "win32", "cygwin32"] -- Aliases taken from cabal's Distribution.System module
src/Text/Pandoc/Filter/Plot/Parse.hs view
@@ -1,49 +1,47 @@-{-# LANGUAGE OverloadedStrings     #-}
-{-# LANGUAGE RecordWildCards       #-}
-
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-This module defines types and functions that help
-with keeping track of figure specifications
--}
-module Text.Pandoc.Filter.Plot.Parse (
-      plotToolkit
-    , parseFigureSpec
-    , captionReader
-) where
-
-import           Control.Monad                     (join, when)
-
-import           Data.Char                         (isSpace)
-import           Data.Default                      (def)
-import           Data.List                         (intersperse)
-import qualified Data.Map.Strict                   as Map
-import           Data.Maybe                        (fromMaybe, listToMaybe, isJust, fromJust)
-import           Data.String                       (fromString)
-import           Data.Text                         (Text, pack, unpack)
-import qualified Data.Text                         as T
-import qualified Data.Text.IO                      as TIO
-import           Data.Version                      (showVersion)
-
-import           Paths_pandoc_plot                 (version)
-
-import           System.FilePath                   (makeValid, normalise)
-
-import           Text.Pandoc.Definition            (Block (..), Inline,
-                                                    Pandoc (..), Format(..))
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
 
-import           Text.Pandoc.Class                 (runPure)
-import           Text.Pandoc.Options               (ReaderOptions (..))
-import           Text.Pandoc.Readers               (getReader, Reader(..))
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- This module defines types and functions that help
+-- with keeping track of figure specifications
+module Text.Pandoc.Filter.Plot.Parse
+  ( plotToolkit,
+    parseFigureSpec,
+    captionReader,
+  )
+where
 
-import           Text.Pandoc.Filter.Plot.Renderers
-import           Text.Pandoc.Filter.Plot.Monad
+import Control.Monad (join, when)
+import Data.Char (isSpace)
+import Data.Default (def)
+import Data.List (intersperse)
+import qualified Data.Map.Strict as Map
+import Data.Maybe (fromJust, fromMaybe, isJust, listToMaybe)
+import Data.String (fromString)
+import Data.Text (Text, pack, unpack)
+import qualified Data.Text as T
+import qualified Data.Text.IO as TIO
+import Data.Version (showVersion)
+import Paths_pandoc_plot (version)
+import System.FilePath (makeValid, normalise)
+import Text.Pandoc.Class (runPure)
+import Text.Pandoc.Definition
+  ( Block (..),
+    Format (..),
+    Inline,
+    Pandoc (..),
+  )
+import Text.Pandoc.Filter.Plot.Monad
+import Text.Pandoc.Filter.Plot.Renderers
+import Text.Pandoc.Options (ReaderOptions (..))
+import Text.Pandoc.Readers (Reader (..), getReader)
 
 tshow :: Show a => a -> Text
 tshow = pack . show
@@ -52,115 +50,117 @@ -- If an environment is detected, but the save format is incompatible,
 -- an error will be thrown.
 parseFigureSpec :: Block -> PlotM (Maybe FigureSpec)
-parseFigureSpec block@(CodeBlock (id', classes, attrs) _) = 
-    sequence $ fmap figureSpec 
-             $ plotToolkit block >>= hasToolkit
-    where
-        hasToolkit    = \tk -> if cls tk `elem` classes then return tk else Nothing
-        attrs'        = Map.fromList attrs
-        preamblePath  = unpack <$> Map.lookup (tshow PreambleK) attrs'
+parseFigureSpec block@(CodeBlock (id', classes, attrs) _) =
+  sequence $
+    fmap figureSpec $
+      plotToolkit block >>= hasToolkit
+  where
+    hasToolkit = \tk -> if cls tk `elem` classes then return tk else Nothing
+    attrs' = Map.fromList attrs
+    preamblePath = unpack <$> Map.lookup (tshow PreambleK) attrs'
 
-        figureSpec :: Toolkit -> PlotM FigureSpec
-        figureSpec toolkit = do
-            conf <- asks envConfig
-            let extraAttrs' = parseExtraAttrs toolkit attrs'
-                header = comment toolkit $ "Generated by pandoc-plot " <> ((pack . showVersion) version)
-                defaultPreamble = preambleSelector toolkit conf
+    figureSpec :: Toolkit -> PlotM FigureSpec
+    figureSpec toolkit = do
+      conf <- asks envConfig
+      let extraAttrs' = parseExtraAttrs toolkit attrs'
+          header = comment toolkit $ "Generated by pandoc-plot " <> ((pack . showVersion) version)
+          defaultPreamble = preambleSelector toolkit conf
 
-            includeScript <- fromMaybe
-                                (return defaultPreamble)
-                                ((liftIO . TIO.readFile) <$> preamblePath)
-            let -- Filtered attributes that are not relevant to pandoc-plot
-                -- This presumes that inclusionKeys includes ALL possible keys, for all toolkits
-                filteredAttrs = filter (\(k, _) -> k `notElem` (tshow <$> inclusionKeys)) attrs
-                defWithSource = defaultWithSource conf
-                defSaveFmt = defaultSaveFormat conf
-                defDPI = defaultDPI conf
+      includeScript <-
+        fromMaybe
+          (return defaultPreamble)
+          ((liftIO . TIO.readFile) <$> preamblePath)
+      let -- Filtered attributes that are not relevant to pandoc-plot
+          -- This presumes that inclusionKeys includes ALL possible keys, for all toolkits
+          filteredAttrs = filter (\(k, _) -> k `notElem` (tshow <$> inclusionKeys)) attrs
+          defWithSource = defaultWithSource conf
+          defSaveFmt = defaultSaveFormat conf
+          defDPI = defaultDPI conf
 
-            -- Decide between reading from file or using document content
-            content <- parseContent block
+      -- Decide between reading from file or using document content
+      content <- parseContent block
 
-            let caption        = Map.findWithDefault mempty (tshow CaptionK) attrs'
-                withSource     = fromMaybe defWithSource $ readBool <$> Map.lookup (tshow WithSourceK) attrs'
-                script         = mconcat $ intersperse "\n" [header, includeScript, content]
-                saveFormat     = fromMaybe defSaveFmt $ (fromString . unpack) <$> Map.lookup (tshow SaveFormatK) attrs'
-                directory      = makeValid $ unpack $ Map.findWithDefault (pack $ defaultDirectory conf) (tshow DirectoryK) attrs'
-                dpi            = fromMaybe defDPI $ (read . unpack) <$> Map.lookup (tshow DpiK) attrs'
-                extraAttrs     = Map.toList extraAttrs'
-                blockAttrs     = (id', filter (/= cls toolkit) classes, filteredAttrs)
+      let caption = Map.findWithDefault mempty (tshow CaptionK) attrs'
+          withSource = fromMaybe defWithSource $ readBool <$> Map.lookup (tshow WithSourceK) attrs'
+          script = mconcat $ intersperse "\n" [header, includeScript, content]
+          saveFormat = fromMaybe defSaveFmt $ (fromString . unpack) <$> Map.lookup (tshow SaveFormatK) attrs'
+          directory = makeValid $ unpack $ Map.findWithDefault (pack $ defaultDirectory conf) (tshow DirectoryK) attrs'
+          dpi = fromMaybe defDPI $ (read . unpack) <$> Map.lookup (tshow DpiK) attrs'
+          extraAttrs = Map.toList extraAttrs'
+          blockAttrs = (id', filter (/= cls toolkit) classes, filteredAttrs)
 
-            let blockDependencies = parseFileDependencies $ fromMaybe mempty $ Map.lookup (tshow DependenciesK) attrs'
-                dependencies = (defaultDependencies conf) <> blockDependencies
-            
-            -- This is the first opportunity to check save format compatibility
-            let saveFormatSupported = saveFormat `elem` (supportedSaveFormats toolkit)
-            when (not saveFormatSupported) $ do
-                let msg = pack $ mconcat ["Save format ", show saveFormat, " not supported by ", show toolkit ]
-                err msg
-            return FigureSpec{..}
+      let blockDependencies = parseFileDependencies $ fromMaybe mempty $ Map.lookup (tshow DependenciesK) attrs'
+          dependencies = (defaultDependencies conf) <> blockDependencies
 
+      -- This is the first opportunity to check save format compatibility
+      let saveFormatSupported = saveFormat `elem` (supportedSaveFormats toolkit)
+      when (not saveFormatSupported) $ do
+        let msg = pack $ mconcat ["Save format ", show saveFormat, " not supported by ", show toolkit]
+        err msg
+      return FigureSpec {..}
 parseFigureSpec _ = return Nothing
 
-
 -- | Parse script content from a block, if possible.
 -- The script content can either come from a file
 -- or from the code block itself. If both are present,
 -- the file is preferred.
 parseContent :: Block -> PlotM Script
 parseContent (CodeBlock (_, _, attrs) content) = do
-    let attrs' = Map.fromList attrs
-        mfile  = normalise . unpack <$> Map.lookup (tshow FileK) attrs'
-    when (content /= mempty && isJust mfile) $ do
-        err $ mconcat [ 
-            "Figure refers to a file (", pack $ fromJust mfile
-            , ") but also has content in the document.\nThe file content will be preferred."
-            ]
-    let loadFromFile fp = do
-            info $ "Loading figure content from " <> pack fp
-            liftIO $ TIO.readFile fp
-    maybe (return content) loadFromFile mfile
+  let attrs' = Map.fromList attrs
+      mfile = normalise . unpack <$> Map.lookup (tshow FileK) attrs'
+  when (content /= mempty && isJust mfile) $ do
+    err $
+      mconcat
+        [ "Figure refers to a file (",
+          pack $ fromJust mfile,
+          ") but also has content in the document.\nThe file content will be preferred."
+        ]
+  let loadFromFile fp = do
+        info $ "Loading figure content from " <> pack fp
+        liftIO $ TIO.readFile fp
+  maybe (return content) loadFromFile mfile
 parseContent _ = return mempty
 
-
 -- | Determine which toolkit should be used to render the plot
 -- from a code block, if any.
 plotToolkit :: Block -> Maybe Toolkit
 plotToolkit (CodeBlock (_, classes, _) _) =
-    listToMaybe $ filter (\tk->cls tk `elem` classes) toolkits
+  listToMaybe $ filter (\tk -> cls tk `elem` classes) toolkits
 plotToolkit _ = Nothing
 
-
 -- | Reader a caption, based on input document format
 captionReader :: Format -> Text -> Maybe [Inline]
-captionReader (Format f) t = either (const Nothing) (Just . extractFromBlocks) $ runPure $ do
+captionReader (Format f) t = either (const Nothing) (Just . extractFromBlocks) $
+  runPure $ do
     (reader, exts) <- getReader f
     let readerOpts = def {readerExtensions = exts}
     -- Assuming no ByteString readers...
     case reader of
-        TextReader fct -> fct readerOpts t
-        _              -> return mempty
-    where
-        extractFromBlocks (Pandoc _ blocks) = mconcat $ extractInlines <$> blocks
-
-        extractInlines (Plain inlines)          = inlines
-        extractInlines (Para inlines)           = inlines
-        extractInlines (LineBlock multiinlines) = join multiinlines
-        extractInlines _                        = []
+      TextReader fct -> fct readerOpts t
+      _ -> return mempty
+  where
+    extractFromBlocks (Pandoc _ blocks) = mconcat $ extractInlines <$> blocks
 
+    extractInlines (Plain inlines) = inlines
+    extractInlines (Para inlines) = inlines
+    extractInlines (LineBlock multiinlines) = join multiinlines
+    extractInlines _ = []
 
 -- | Flexible boolean parsing
 readBool :: Text -> Bool
-readBool s | s `elem` ["True",  "true",  "'True'",  "'true'",  "1"] = True
-           | s `elem` ["False", "false", "'False'", "'false'", "0"] = False
-           | otherwise = errorWithoutStackTrace $ unpack $ mconcat ["Could not parse '", s, "' into a boolean. Please use 'True' or 'False'"]
-
+readBool s
+  | s `elem` ["True", "true", "'True'", "'true'", "1"] = True
+  | s `elem` ["False", "false", "'False'", "'false'", "0"] = False
+  | otherwise = errorWithoutStackTrace $ unpack $ mconcat ["Could not parse '", s, "' into a boolean. Please use 'True' or 'False'"]
 
 -- | Parse a list of file dependencies such as /[foo.bar, hello.txt]/.
 parseFileDependencies :: Text -> [FilePath]
 parseFileDependencies t
-    | t == mempty = mempty
-    | otherwise   = fmap normalise 
-                      . fmap unpack 
-                      . fmap (T.dropAround isSpace) -- Remove leading/trailing whitespace on filenames
-                      . T.splitOn "," 
-                      . T.dropAround (\c -> c `elem` ['[', ']']) $ t+  | t == mempty = mempty
+  | otherwise =
+    fmap normalise
+      . fmap unpack
+      . fmap (T.dropAround isSpace) -- Remove leading/trailing whitespace on filenames
+      . T.splitOn ","
+      . T.dropAround (\c -> c `elem` ['[', ']'])
+      $ t
src/Text/Pandoc/Filter/Plot/Renderers.hs view
@@ -1,208 +1,209 @@ {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Specification of renderers.
--}
-
-module Text.Pandoc.Filter.Plot.Renderers (
-      scriptExtension
-    , comment
-    , preambleSelector
-    , supportedSaveFormats
-    , scriptChecks
-    , parseExtraAttrs
-    , command
-    , capture
-    , executable
-    , toolkitAvailable
-    , availableToolkits
-    , availableToolkitsM
-    , unavailableToolkits
-    , unavailableToolkitsM
-    , OutputSpec(..)
-    , Executable(..)
-) where
-
-import Control.Concurrent.Async.Lifted               (forConcurrently)
+{-# LANGUAGE RecordWildCards #-}
 
-import Data.List                                     ((\\))
-import Data.Map.Strict                               (Map)
-import Data.Maybe                                    (catMaybes)
-import Data.Text                                     (Text)
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Specification of renderers.
+module Text.Pandoc.Filter.Plot.Renderers
+  ( scriptExtension,
+    comment,
+    language,
+    preambleSelector,
+    supportedSaveFormats,
+    scriptChecks,
+    parseExtraAttrs,
+    command,
+    capture,
+    executable,
+    toolkitAvailable,
+    availableToolkits,
+    availableToolkitsM,
+    unavailableToolkits,
+    unavailableToolkitsM,
+    OutputSpec (..),
+    Executable (..),
+  )
+where
 
+import Control.Concurrent.Async.Lifted (forConcurrently)
+import Data.List ((\\))
+import Data.Map.Strict (Map)
+import Data.Maybe (catMaybes)
+import Data.Text (Text)
+import Text.Pandoc.Filter.Plot.Monad
+import Text.Pandoc.Filter.Plot.Renderers.Bokeh
+import Text.Pandoc.Filter.Plot.Renderers.GGPlot2
+import Text.Pandoc.Filter.Plot.Renderers.GNUPlot
+import Text.Pandoc.Filter.Plot.Renderers.Graphviz
 import Text.Pandoc.Filter.Plot.Renderers.Mathematica
 import Text.Pandoc.Filter.Plot.Renderers.Matlab
 import Text.Pandoc.Filter.Plot.Renderers.Matplotlib
 import Text.Pandoc.Filter.Plot.Renderers.Octave
 import Text.Pandoc.Filter.Plot.Renderers.PlotlyPython
 import Text.Pandoc.Filter.Plot.Renderers.PlotlyR
-import Text.Pandoc.Filter.Plot.Renderers.GGPlot2
-import Text.Pandoc.Filter.Plot.Renderers.GNUPlot
-import Text.Pandoc.Filter.Plot.Renderers.Graphviz
-import Text.Pandoc.Filter.Plot.Renderers.Bokeh
 import Text.Pandoc.Filter.Plot.Renderers.Plotsjl
-import Text.Pandoc.Filter.Plot.Renderers.Prelude     (OutputSpec(..))
-
-import Text.Pandoc.Filter.Plot.Monad
-
+import Text.Pandoc.Filter.Plot.Renderers.Prelude (OutputSpec (..))
 
 -- Extension for script files, e.g. ".py", or ".m".
 scriptExtension :: Toolkit -> String
-scriptExtension Matplotlib   = ".py"
+scriptExtension Matplotlib = ".py"
 scriptExtension PlotlyPython = ".py"
-scriptExtension PlotlyR      = ".r"
-scriptExtension Matlab       = ".m"
-scriptExtension Mathematica  = ".m"
-scriptExtension Octave       = ".m"
-scriptExtension GGPlot2      = ".r"
-scriptExtension GNUPlot      = ".gp"
-scriptExtension Graphviz     = ".dot"
-scriptExtension Bokeh        = ".py"
-scriptExtension Plotsjl      = ".jl"
+scriptExtension PlotlyR = ".r"
+scriptExtension Matlab = ".m"
+scriptExtension Mathematica = ".m"
+scriptExtension Octave = ".m"
+scriptExtension GGPlot2 = ".r"
+scriptExtension GNUPlot = ".gp"
+scriptExtension Graphviz = ".dot"
+scriptExtension Bokeh = ".py"
+scriptExtension Plotsjl = ".jl"
 
+-- | Language that is used by a toolkit. Specifically used
+-- to highlight the appropriate language in the external source code.
+language :: Toolkit -> Text
+language Matplotlib = "python"
+language PlotlyPython = "python"
+language PlotlyR = "r"
+language Matlab = "matlab"
+language Mathematica = "mathematica"
+language Octave = "matlab"
+language GGPlot2 = "r"
+language GNUPlot = "gnuplot"
+language Graphviz = "dot"
+language Bokeh = "python"
+language Plotsjl = "julia"
 
 -- Make a string into a comment
 comment :: Toolkit -> (Text -> Text)
-comment Matplotlib   = mappend "# "
+comment Matplotlib = mappend "# "
 comment PlotlyPython = mappend "# "
-comment PlotlyR      = mappend "# "
-comment Matlab       = mappend "% "
-comment Mathematica  = \t -> mconcat ["(*", t, "*)"]
-comment Octave       = mappend "% "
-comment GGPlot2      = mappend "# "
-comment GNUPlot      = mappend "# "
-comment Graphviz     = mappend "// "
-comment Bokeh        = mappend "# "
-comment Plotsjl      = mappend "# "
-
+comment PlotlyR = mappend "# "
+comment Matlab = mappend "% "
+comment Mathematica = \t -> mconcat ["(*", t, "*)"]
+comment Octave = mappend "% "
+comment GGPlot2 = mappend "# "
+comment GNUPlot = mappend "# "
+comment Graphviz = mappend "// "
+comment Bokeh = mappend "# "
+comment Plotsjl = mappend "# "
 
 -- | The function that maps from configuration to the preamble.
 preambleSelector :: Toolkit -> (Configuration -> Script)
-preambleSelector Matplotlib   = matplotlibPreamble
+preambleSelector Matplotlib = matplotlibPreamble
 preambleSelector PlotlyPython = plotlyPythonPreamble
-preambleSelector PlotlyR      = plotlyRPreamble
-preambleSelector Matlab       = matlabPreamble
-preambleSelector Mathematica  = mathematicaPreamble
-preambleSelector Octave       = octavePreamble
-preambleSelector GGPlot2      = ggplot2Preamble
-preambleSelector GNUPlot      = gnuplotPreamble
-preambleSelector Graphviz     = graphvizPreamble
-preambleSelector Bokeh        = bokehPreamble
-preambleSelector Plotsjl      = plotsjlPreamble
-
+preambleSelector PlotlyR = plotlyRPreamble
+preambleSelector Matlab = matlabPreamble
+preambleSelector Mathematica = mathematicaPreamble
+preambleSelector Octave = octavePreamble
+preambleSelector GGPlot2 = ggplot2Preamble
+preambleSelector GNUPlot = gnuplotPreamble
+preambleSelector Graphviz = graphvizPreamble
+preambleSelector Bokeh = bokehPreamble
+preambleSelector Plotsjl = plotsjlPreamble
 
 -- | Save formats supported by this renderer.
 supportedSaveFormats :: Toolkit -> [SaveFormat]
-supportedSaveFormats Matplotlib   = matplotlibSupportedSaveFormats
+supportedSaveFormats Matplotlib = matplotlibSupportedSaveFormats
 supportedSaveFormats PlotlyPython = plotlyPythonSupportedSaveFormats
-supportedSaveFormats PlotlyR      = plotlyRSupportedSaveFormats
-supportedSaveFormats Matlab       = matlabSupportedSaveFormats
-supportedSaveFormats Mathematica  = mathematicaSupportedSaveFormats
-supportedSaveFormats Octave       = octaveSupportedSaveFormats
-supportedSaveFormats GGPlot2      = ggplot2SupportedSaveFormats
-supportedSaveFormats GNUPlot      = gnuplotSupportedSaveFormats
-supportedSaveFormats Graphviz     = graphvizSupportedSaveFormats
-supportedSaveFormats Bokeh        = bokehSupportedSaveFormats
-supportedSaveFormats Plotsjl      = plotsjlSupportedSaveFormats
-
+supportedSaveFormats PlotlyR = plotlyRSupportedSaveFormats
+supportedSaveFormats Matlab = matlabSupportedSaveFormats
+supportedSaveFormats Mathematica = mathematicaSupportedSaveFormats
+supportedSaveFormats Octave = octaveSupportedSaveFormats
+supportedSaveFormats GGPlot2 = ggplot2SupportedSaveFormats
+supportedSaveFormats GNUPlot = gnuplotSupportedSaveFormats
+supportedSaveFormats Graphviz = graphvizSupportedSaveFormats
+supportedSaveFormats Bokeh = bokehSupportedSaveFormats
+supportedSaveFormats Plotsjl = plotsjlSupportedSaveFormats
 
 -- Checks to perform before running a script. If ANY check fails,
 -- the figure is not rendered. This is to prevent, for example,
 -- blocking operations to occur.
 scriptChecks :: Toolkit -> [Script -> CheckResult]
 scriptChecks Matplotlib = [matplotlibCheckIfShow]
-scriptChecks Bokeh      = [bokehCheckIfShow]
+scriptChecks Bokeh = [bokehCheckIfShow]
 scriptChecks _ = mempty
 
-
 -- | Parse code block headers for extra attributes that are specific
 -- to this renderer. By default, no extra attributes are parsed.
 parseExtraAttrs :: Toolkit -> Map Text Text -> Map Text Text
 parseExtraAttrs Matplotlib = matplotlibExtraAttrs
-parseExtraAttrs _          = return mempty
-
+parseExtraAttrs _ = return mempty
 
 -- | Generate the appropriate command-line command to generate a figure.
 -- The executable will need to be found first, hence the IO monad.
-command :: Toolkit 
-        -> OutputSpec
-        -> Text                -- Executable name (e.g. "python3")
-        -> Text
-command Matplotlib   = matplotlibCommand
+command ::
+  Toolkit ->
+  OutputSpec ->
+  Text -> -- Executable name (e.g. "python3")
+  Text
+command Matplotlib = matplotlibCommand
 command PlotlyPython = plotlyPythonCommand
-command PlotlyR      = plotlyRCommand
-command Matlab       = matlabCommand
-command Mathematica  = mathematicaCommand
-command Octave       = octaveCommand
-command GGPlot2      = ggplot2Command
-command GNUPlot      = gnuplotCommand
-command Graphviz     = graphvizCommand
-command Bokeh        = bokehCommand
-command Plotsjl      = plotsjlCommand
-
+command PlotlyR = plotlyRCommand
+command Matlab = matlabCommand
+command Mathematica = mathematicaCommand
+command Octave = octaveCommand
+command GGPlot2 = ggplot2Command
+command GNUPlot = gnuplotCommand
+command Graphviz = graphvizCommand
+command Bokeh = bokehCommand
+command Plotsjl = plotsjlCommand
 
 -- | Script fragment required to capture a figure.
 capture :: Toolkit -> (FigureSpec -> FilePath -> Script)
-capture Matplotlib   = matplotlibCapture
+capture Matplotlib = matplotlibCapture
 capture PlotlyPython = plotlyPythonCapture
-capture PlotlyR      = plotlyRCapture
-capture Matlab       = matlabCapture
-capture Mathematica  = mathematicaCapture
-capture Octave       = octaveCapture
-capture GGPlot2      = ggplot2Capture
-capture GNUPlot      = gnuplotCapture
-capture Graphviz     = graphvizCapture 
-capture Bokeh        = bokehCapture
-capture Plotsjl      = plotsjlCapture
-
+capture PlotlyR = plotlyRCapture
+capture Matlab = matlabCapture
+capture Mathematica = mathematicaCapture
+capture Octave = octaveCapture
+capture GGPlot2 = ggplot2Capture
+capture GNUPlot = gnuplotCapture
+capture Graphviz = graphvizCapture
+capture Bokeh = bokehCapture
+capture Plotsjl = plotsjlCapture
 
 -- | Check if a toolkit is available, based on the current configuration
 toolkitAvailable :: Toolkit -> PlotM Bool
-toolkitAvailable Matplotlib   = matplotlibAvailable
+toolkitAvailable Matplotlib = matplotlibAvailable
 toolkitAvailable PlotlyPython = plotlyPythonAvailable
-toolkitAvailable PlotlyR      = plotlyRAvailable
-toolkitAvailable Matlab       = matlabAvailable
-toolkitAvailable Mathematica  = mathematicaAvailable
-toolkitAvailable Octave       = octaveAvailable
-toolkitAvailable GGPlot2      = ggplot2Available
-toolkitAvailable GNUPlot      = gnuplotAvailable
-toolkitAvailable Graphviz     = graphvizAvailable
-toolkitAvailable Bokeh        = bokehAvailable
-toolkitAvailable Plotsjl      = plotsjlAvailable
-
+toolkitAvailable PlotlyR = plotlyRAvailable
+toolkitAvailable Matlab = matlabAvailable
+toolkitAvailable Mathematica = mathematicaAvailable
+toolkitAvailable Octave = octaveAvailable
+toolkitAvailable GGPlot2 = ggplot2Available
+toolkitAvailable GNUPlot = gnuplotAvailable
+toolkitAvailable Graphviz = graphvizAvailable
+toolkitAvailable Bokeh = bokehAvailable
+toolkitAvailable Plotsjl = plotsjlAvailable
 
 -- | List of toolkits available on this machine.
 -- The executables to look for are taken from the configuration.
 availableToolkits :: Configuration -> IO [Toolkit]
 availableToolkits conf = runPlotM conf availableToolkitsM
 
-
 -- | List of toolkits not available on this machine.
 -- The executables to look for are taken from the configur
 unavailableToolkits :: Configuration -> IO [Toolkit]
 unavailableToolkits conf = runPlotM conf unavailableToolkitsM
 
-
 -- | Monadic version of @availableToolkits@.
 --
 -- Note that logging is disabled
 availableToolkitsM :: PlotM [Toolkit]
 availableToolkitsM = silence $ do
-    mtks <- forConcurrently toolkits $  \tk -> do
-        available <- toolkitAvailable tk
-        if available
-            then return $ Just tk
-            else return Nothing
-    return $ catMaybes mtks
+  mtks <- forConcurrently toolkits $ \tk -> do
+    available <- toolkitAvailable tk
+    if available
+      then return $ Just tk
+      else return Nothing
+  return $ catMaybes mtks
 
-    
 -- | Monadic version of @unavailableToolkits@
 unavailableToolkitsM :: PlotM [Toolkit]
 unavailableToolkitsM = (\\) toolkits <$> availableToolkitsM
src/Text/Pandoc/Filter/Plot/Renderers/Bokeh.hs view
@@ -1,67 +1,63 @@-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Rendering Bokeh code blocks
--}
-
-module Text.Pandoc.Filter.Plot.Renderers.Bokeh (
-      bokehSupportedSaveFormats
-    , bokehCommand
-    , bokehCapture
-    , bokehAvailable
-    , bokehCheckIfShow
-) where
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
-import           Data.Monoid                               (Any(..))
-import qualified Data.Text                                 as T
-import           Text.Pandoc.Filter.Plot.Renderers.Prelude
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Rendering Bokeh code blocks
+module Text.Pandoc.Filter.Plot.Renderers.Bokeh
+  ( bokehSupportedSaveFormats,
+    bokehCommand,
+    bokehCapture,
+    bokehAvailable,
+    bokehCheckIfShow,
+  )
+where
 
+import Data.Monoid (Any (..))
+import qualified Data.Text as T
+import Text.Pandoc.Filter.Plot.Renderers.Prelude
 
 bokehSupportedSaveFormats :: [SaveFormat]
 bokehSupportedSaveFormats = [PNG, SVG, HTML]
 
-
 bokehCommand :: OutputSpec -> Text -> Text
-bokehCommand OutputSpec{..} exe = [st|#{exe} "#{oScriptPath}"|]
-
+bokehCommand OutputSpec {..} exe = [st|#{exe} "#{oScriptPath}"|]
 
 bokehAvailable :: PlotM Bool
 bokehAvailable = do
-    mexe <- executable Bokeh
-    case mexe of 
-        Nothing -> return False
-        Just (Executable dir exe) -> commandSuccess dir [st|#{exe} -c "import bokeh; import selenium"|]
-
+  mexe <- executable Bokeh
+  case mexe of
+    Nothing -> return False
+    Just (Executable dir exe) -> commandSuccess dir [st|#{exe} -c "import bokeh; import selenium"|]
 
 -- | Check if `matplotlib.pyplot.show()` calls are present in the script,
 -- which would halt pandoc-plot
 bokehCheckIfShow :: Script -> CheckResult
-bokehCheckIfShow s = 
-    if getAny $ mconcat showPresent
-        then CheckFailed "encountered a call to `bokeh.io.show`."
-        else CheckPassed
-    where
-        showPresent = (\n -> Any (T.isInfixOf n s)) <$> [
-                  "bokeh.io.show("
-                , "show("
+bokehCheckIfShow s =
+  if getAny $ mconcat showPresent
+    then CheckFailed "encountered a call to `bokeh.io.show`."
+    else CheckPassed
+  where
+    showPresent =
+      (\n -> Any (T.isInfixOf n s))
+        <$> [ "bokeh.io.show(",
+              "show("
             ]
 
-
 bokehCapture :: FigureSpec -> FilePath -> Script
 bokehCapture = appendCapture bokehCaptureFragment
 
-
 bokehCaptureFragment :: FigureSpec -> FilePath -> Script
-bokehCaptureFragment FigureSpec{..} fname = [st|
+bokehCaptureFragment FigureSpec {..} fname =
+  [st|
 from bokeh.io import export_png, export_svgs, save
 from bokeh.models import Model
 from bokeh.resources import CDN
@@ -73,9 +69,9 @@ __current_model = [obj for obj in globals().values() if isinstance(obj, Model)][-1]
 #{write}
 |]
-    where  
-        write = case saveFormat of
-            HTML -> [st|save(__current_model, filename=r"#{fname}", resources=CDN)|]
-            SVG  -> [st|__current_model.output_backend="svg"; export_svgs(__current_model, filename=r"#{fname}")|]
-            PNG  -> [st|export_png(obj = __current_model, filename=r"#{fname}")|]
-            fmt  -> errorWithoutStackTrace $ "Save format not supported: " <> show fmt
+  where
+    write = case saveFormat of
+      HTML -> [st|save(__current_model, filename=r"#{fname}", resources=CDN)|]
+      SVG -> [st|__current_model.output_backend="svg"; export_svgs(__current_model, filename=r"#{fname}")|]
+      PNG -> [st|export_png(obj = __current_model, filename=r"#{fname}")|]
+      fmt -> errorWithoutStackTrace $ "Save format not supported: " <> show fmt
src/Text/Pandoc/Filter/Plot/Renderers/GGPlot2.hs view
@@ -1,56 +1,53 @@-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Rendering GGPlot2 plots code blocks
--}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
-module Text.Pandoc.Filter.Plot.Renderers.GGPlot2 (
-      ggplot2SupportedSaveFormats
-    , ggplot2Command
-    , ggplot2Capture
-    , ggplot2Available
-) where
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Rendering GGPlot2 plots code blocks
+module Text.Pandoc.Filter.Plot.Renderers.GGPlot2
+  ( ggplot2SupportedSaveFormats,
+    ggplot2Command,
+    ggplot2Capture,
+    ggplot2Available,
+  )
+where
 
 import qualified Data.Text as T
-import           Text.Pandoc.Filter.Plot.Renderers.Prelude
-
+import Text.Pandoc.Filter.Plot.Renderers.Prelude
 
 ggplot2SupportedSaveFormats :: [SaveFormat]
 ggplot2SupportedSaveFormats = [PNG, PDF, SVG, JPG, EPS, TIF]
 
-
 ggplot2Command :: OutputSpec -> Text -> Text
-ggplot2Command OutputSpec{..} exe = [st|#{exe} "#{oScriptPath}"|]
-
+ggplot2Command OutputSpec {..} exe = [st|#{exe} "#{oScriptPath}"|]
 
 ggplot2Available :: PlotM Bool
 ggplot2Available = do
-    mexe <- executable GGPlot2
-    case mexe of 
-        Nothing -> return False
-        Just (Executable dir exe) -> 
-            commandSuccess dir [st|#{exe} -e 'if(!require("ggplot2")) {quit(status=1)}'|]
-
+  mexe <- executable GGPlot2
+  case mexe of
+    Nothing -> return False
+    Just (Executable dir exe) ->
+      commandSuccess dir [st|#{exe} -e 'if(!require("ggplot2")) {quit(status=1)}'|]
 
 ggplot2Capture :: FigureSpec -> FilePath -> Script
-ggplot2Capture fs fp = 
-    T.unlines [ "pdf(NULL)" -- Prevent the creation of empty Rplots.pdf
-              , script fs
-              , ggplot2CaptureFragment fs fp
-              ]
-
+ggplot2Capture fs fp =
+  T.unlines
+    [ "pdf(NULL)", -- Prevent the creation of empty Rplots.pdf
+      script fs,
+      ggplot2CaptureFragment fs fp
+    ]
 
 ggplot2CaptureFragment :: FigureSpec -> FilePath -> Script
-ggplot2CaptureFragment FigureSpec{..} fname = [st|
+ggplot2CaptureFragment FigureSpec {..} fname =
+  [st|
 library(ggplot2) # just in case
 ggsave("#{toRPath fname}", plot = last_plot(), dpi = #{dpi})
 |]
src/Text/Pandoc/Filter/Plot/Renderers/GNUPlot.hs view
@@ -1,56 +1,52 @@-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Rendering gnuplot plots code blocks
--}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
-module Text.Pandoc.Filter.Plot.Renderers.GNUPlot (
-      gnuplotSupportedSaveFormats
-    , gnuplotCommand
-    , gnuplotCapture
-    , gnuplotAvailable
-) where
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Rendering gnuplot plots code blocks
+module Text.Pandoc.Filter.Plot.Renderers.GNUPlot
+  ( gnuplotSupportedSaveFormats,
+    gnuplotCommand,
+    gnuplotCapture,
+    gnuplotAvailable,
+  )
+where
 
-import           Text.Pandoc.Filter.Plot.Renderers.Prelude
+import Text.Pandoc.Filter.Plot.Renderers.Prelude
 
 gnuplotSupportedSaveFormats :: [SaveFormat]
 gnuplotSupportedSaveFormats = [PNG, SVG, EPS, GIF, JPG, PDF]
 
-
 gnuplotCommand :: OutputSpec -> Text -> Text
-gnuplotCommand OutputSpec{..} exe = [st|#{exe} -c "#{oScriptPath}"|]
-
+gnuplotCommand OutputSpec {..} exe = [st|#{exe} -c "#{oScriptPath}"|]
 
 gnuplotAvailable :: PlotM Bool
 gnuplotAvailable = do
-    mexe <- executable GNUPlot
-    case mexe of 
-        Nothing -> return False
-        Just (Executable dir exe) -> 
-            commandSuccess dir [st|"#{exe}" -h|]
-
+  mexe <- executable GNUPlot
+  case mexe of
+    Nothing -> return False
+    Just (Executable dir exe) ->
+      commandSuccess dir [st|"#{exe}" -h|]
 
 gnuplotCapture :: FigureSpec -> FilePath -> Script
 gnuplotCapture = prependCapture gnuplotCaptureFragment
-    where
-        prependCapture f s fp = mconcat [f s fp, "\n", script s]
-
+  where
+    prependCapture f s fp = mconcat [f s fp, "\n", script s]
 
 gnuplotCaptureFragment :: FigureSpec -> FilePath -> Script
-gnuplotCaptureFragment FigureSpec{..} fname = [st|
+gnuplotCaptureFragment FigureSpec {..} fname =
+  [st|
 set terminal #{terminalString saveFormat}
 set output '#{fname}'
 |]
-
 
 -- | Terminal name for supported save formats
 terminalString :: SaveFormat -> Text
src/Text/Pandoc/Filter/Plot/Renderers/Graphviz.hs view
@@ -1,50 +1,46 @@-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Rendering Graphviz plots code blocks
--}
-
-module Text.Pandoc.Filter.Plot.Renderers.Graphviz (
-      graphvizSupportedSaveFormats
-    , graphvizCommand
-    , graphvizCapture
-    , graphvizAvailable
-) where
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
-import           Data.Char
-import           Text.Pandoc.Filter.Plot.Renderers.Prelude
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Rendering Graphviz plots code blocks
+module Text.Pandoc.Filter.Plot.Renderers.Graphviz
+  ( graphvizSupportedSaveFormats,
+    graphvizCommand,
+    graphvizCapture,
+    graphvizAvailable,
+  )
+where
 
+import Data.Char
+import Text.Pandoc.Filter.Plot.Renderers.Prelude
 
 graphvizSupportedSaveFormats :: [SaveFormat]
 graphvizSupportedSaveFormats = [PNG, PDF, SVG, JPG, EPS, WEBP, GIF]
 
-
 graphvizCommand :: OutputSpec -> Text -> Text
-graphvizCommand OutputSpec{..} exe = 
-    let fmt = fmap toLower . show . saveFormat $ oFigureSpec
-        dpi' = dpi oFigureSpec
-    in [st|#{exe} -T#{fmt} -Gdpi=#{dpi'} -o "#{oFigurePath}" "#{oScriptPath}"|]
-
+graphvizCommand OutputSpec {..} exe =
+  let fmt = fmap toLower . show . saveFormat $ oFigureSpec
+      dpi' = dpi oFigureSpec
+   in [st|#{exe} -T#{fmt} -Gdpi=#{dpi'} -o "#{oFigurePath}" "#{oScriptPath}"|]
 
 graphvizAvailable :: PlotM Bool
 graphvizAvailable = do
-    mexe <- executable Graphviz
-    case mexe of 
-        Nothing -> return False
-        Just (Executable dir exe) -> 
-            commandSuccess dir [st|#{exe} -?|]
-
+  mexe <- executable Graphviz
+  case mexe of
+    Nothing -> return False
+    Just (Executable dir exe) ->
+      commandSuccess dir [st|#{exe} -?|]
 
 -- Graphviz export is entirely based on command-line arguments
 -- so there is no need to modify the script itself.
 graphvizCapture :: FigureSpec -> FilePath -> Script
-graphvizCapture FigureSpec{..} _ = script
+graphvizCapture FigureSpec {..} _ = script
src/Text/Pandoc/Filter/Plot/Renderers/Mathematica.hs view
@@ -1,49 +1,46 @@-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Rendering Mathematica plots code blocks
--}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
-module Text.Pandoc.Filter.Plot.Renderers.Mathematica (
-      mathematicaSupportedSaveFormats
-    , mathematicaCommand
-    , mathematicaCapture
-    , mathematicaAvailable
-) where
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Rendering Mathematica plots code blocks
+module Text.Pandoc.Filter.Plot.Renderers.Mathematica
+  ( mathematicaSupportedSaveFormats,
+    mathematicaCommand,
+    mathematicaCapture,
+    mathematicaAvailable,
+  )
+where
 
-import           Text.Pandoc.Filter.Plot.Renderers.Prelude
+import Text.Pandoc.Filter.Plot.Renderers.Prelude
 
 mathematicaSupportedSaveFormats :: [SaveFormat]
 mathematicaSupportedSaveFormats = [PNG, PDF, SVG, JPG, EPS, GIF, TIF]
 
-
 mathematicaCommand :: OutputSpec -> Text -> Text
-mathematicaCommand OutputSpec{..} exe = [st|#{exe} -script "#{oScriptPath}"|]
-
+mathematicaCommand OutputSpec {..} exe = [st|#{exe} -script "#{oScriptPath}"|]
 
 mathematicaAvailable :: PlotM Bool
 mathematicaAvailable = do
-    mexe <- executable Mathematica
-    case mexe of 
-        Nothing -> return False
-        Just (Executable dir exe) -> 
-            commandSuccess dir [st|#{exe} -h|] -- TODO: test this
-
+  mexe <- executable Mathematica
+  case mexe of
+    Nothing -> return False
+    Just (Executable dir exe) ->
+      commandSuccess dir [st|#{exe} -h|] -- TODO: test this
 
 mathematicaCapture :: FigureSpec -> FilePath -> Script
 mathematicaCapture = appendCapture mathematicaCaptureFragment
 
-
 mathematicaCaptureFragment :: FigureSpec -> FilePath -> Script
-mathematicaCaptureFragment FigureSpec{..} fname = [st|
+mathematicaCaptureFragment FigureSpec {..} fname =
+  [st|
 Export["#{fname}", %, #{show saveFormat}, ImageResolution -> #{dpi}]
 |]
src/Text/Pandoc/Filter/Plot/Renderers/Matlab.hs view
@@ -1,52 +1,47 @@-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Rendering Matlab code blocks
--}
-
-module Text.Pandoc.Filter.Plot.Renderers.Matlab (
-      matlabSupportedSaveFormats
-    , matlabCommand
-    , matlabCapture
-    , matlabAvailable
-) where
-
-import           System.Directory                            (exeExtension)
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
-import           Text.Pandoc.Filter.Plot.Renderers.Prelude
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Rendering Matlab code blocks
+module Text.Pandoc.Filter.Plot.Renderers.Matlab
+  ( matlabSupportedSaveFormats,
+    matlabCommand,
+    matlabCapture,
+    matlabAvailable,
+  )
+where
 
+import System.Directory (exeExtension)
+import Text.Pandoc.Filter.Plot.Renderers.Prelude
 
 matlabSupportedSaveFormats :: [SaveFormat]
 matlabSupportedSaveFormats = [PNG, PDF, SVG, JPG, EPS, GIF, TIF]
 
-
 matlabCommand :: OutputSpec -> Text -> Text
-matlabCommand OutputSpec{..} exe = [st|#{exe} -batch "run('#{oScriptPath}')"|]
-
+matlabCommand OutputSpec {..} exe = [st|#{exe} -batch "run('#{oScriptPath}')"|]
 
 -- On Windows at least, "matlab -help"  actually returns -1, even though the
 -- help text is shown successfully!
--- Therefore, we cannot rely on this behavior to know if matlab is present, 
+-- Therefore, we cannot rely on this behavior to know if matlab is present,
 -- like other toolkits.
 matlabAvailable :: PlotM Bool
 matlabAvailable = asksConfig matlabExe >>= (\exe -> liftIO $ existsOnPath (exe <> exeExtension))
 
-
 matlabCapture :: FigureSpec -> FilePath -> Script
 matlabCapture = appendCapture matlabCaptureFragment
 
-
 matlabCaptureFragment :: FigureSpec -> FilePath -> Script
-matlabCaptureFragment FigureSpec{..} fname = [st|
+matlabCaptureFragment FigureSpec {..} fname =
+  [st|
 if exist("exportgraphics")>0
     exportgraphics(gcf, '#{fname}', 'Resolution', #{dpi});
 else
src/Text/Pandoc/Filter/Plot/Renderers/Matplotlib.hs view
@@ -1,92 +1,87 @@-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Rendering Matplotlib code blocks.
-
-Note that the MatplotlibM renderer supports two extra arguments:
-    * @tight_bbox=True|False@ : Make plot bounding box tight. Default is False
-    * @transparent=True|False@ : Make plot background transparent (perfect for web pages). Default is False.
--}
-
-module Text.Pandoc.Filter.Plot.Renderers.Matplotlib (
-      matplotlibSupportedSaveFormats
-    , matplotlibCommand
-    , matplotlibCapture
-    , matplotlibExtraAttrs
-    , matplotlibAvailable
-    , matplotlibCheckIfShow
-) where
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
-import           Text.Pandoc.Filter.Plot.Renderers.Prelude
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Rendering Matplotlib code blocks.
+--
+-- Note that the MatplotlibM renderer supports two extra arguments:
+--     * @tight_bbox=True|False@ : Make plot bounding box tight. Default is False
+--     * @transparent=True|False@ : Make plot background transparent (perfect for web pages). Default is False.
+module Text.Pandoc.Filter.Plot.Renderers.Matplotlib
+  ( matplotlibSupportedSaveFormats,
+    matplotlibCommand,
+    matplotlibCapture,
+    matplotlibExtraAttrs,
+    matplotlibAvailable,
+    matplotlibCheckIfShow,
+  )
+where
 
-import qualified Data.Map.Strict                           as M
-import           Data.Monoid                               (Any(..))
-import qualified Data.Text                                 as T
+import qualified Data.Map.Strict as M
+import Data.Monoid (Any (..))
+import qualified Data.Text as T
+import Text.Pandoc.Filter.Plot.Renderers.Prelude
 
 matplotlibSupportedSaveFormats :: [SaveFormat]
 matplotlibSupportedSaveFormats = [PNG, PDF, SVG, JPG, EPS, GIF, TIF]
 
-
 matplotlibCommand :: OutputSpec -> Text -> Text
-matplotlibCommand OutputSpec{..} exe = [st|#{exe} "#{oScriptPath}"|]
-
+matplotlibCommand OutputSpec {..} exe = [st|#{exe} "#{oScriptPath}"|]
 
 matplotlibCapture :: FigureSpec -> FilePath -> Script
 matplotlibCapture = appendCapture matplotlibCaptureFragment
 
-
 matplotlibCaptureFragment :: FigureSpec -> FilePath -> Script
-matplotlibCaptureFragment FigureSpec{..} fname = [st|
+matplotlibCaptureFragment FigureSpec {..} fname =
+  [st|
 import matplotlib.pyplot as plt
 plt.savefig(r"#{fname}", dpi=#{dpi}, transparent=#{transparent}, bbox_inches=#{tightBox})
 |]
-    where attrs        = M.fromList extraAttrs
-          tight_       = readBool $ M.findWithDefault "False" "tight"  attrs
-          transparent_ = readBool $ M.findWithDefault "False" "transparent" attrs
-          tightBox     = if tight_ then ("'tight'"::Text) else ("None"::Text)
-          transparent  = if transparent_ then ("True"::Text) else ("False"::Text)
-
+  where
+    attrs = M.fromList extraAttrs
+    tight_ = readBool $ M.findWithDefault "False" "tight" attrs
+    transparent_ = readBool $ M.findWithDefault "False" "transparent" attrs
+    tightBox = if tight_ then ("'tight'" :: Text) else ("None" :: Text)
+    transparent = if transparent_ then ("True" :: Text) else ("False" :: Text)
 
 matplotlibExtraAttrs :: M.Map Text Text -> (M.Map Text Text)
 matplotlibExtraAttrs kv = M.filterWithKey (\k _ -> k `elem` ["tight_bbox", "transparent"]) kv
 
-
 matplotlibAvailable :: PlotM Bool
 matplotlibAvailable = do
-    mexe <- executable Matplotlib
-    case mexe of 
-        Nothing -> return False
-        Just (Executable dir exe) -> 
-            commandSuccess dir [st|#{exe} -c "import matplotlib"|]
-
+  mexe <- executable Matplotlib
+  case mexe of
+    Nothing -> return False
+    Just (Executable dir exe) ->
+      commandSuccess dir [st|#{exe} -c "import matplotlib"|]
 
 -- | Check if `matplotlib.pyplot.show()` calls are present in the script,
 -- which would halt pandoc-plot
 matplotlibCheckIfShow :: Script -> CheckResult
-matplotlibCheckIfShow s = 
-    if getAny $ mconcat showPresent
-        then CheckFailed "encountered a call to `matplotlib.pyplot.show`."
-        else CheckPassed
-    where
-        showPresent = (\n -> Any (T.isInfixOf n s)) <$> [
-                  "matplotlib.pyplot.show()"
-                , "pyplot.show()"
-                , "plt.show()"
+matplotlibCheckIfShow s =
+  if getAny $ mconcat showPresent
+    then CheckFailed "encountered a call to `matplotlib.pyplot.show`."
+    else CheckPassed
+  where
+    showPresent =
+      (\n -> Any (T.isInfixOf n s))
+        <$> [ "matplotlib.pyplot.show()",
+              "pyplot.show()",
+              "plt.show()"
             ]
-        
 
-
 -- | Flexible boolean parsing
 readBool :: Text -> Bool
-readBool s | s `elem` ["True",  "true",  "'True'",  "'true'",  "1"] = True
-           | s `elem` ["False", "false", "'False'", "'false'", "0"] = False
-           | otherwise = errorWithoutStackTrace $ unpack $ mconcat ["Could not parse '", s, "' into a boolean. Please use 'True' or 'False'"]
+readBool s
+  | s `elem` ["True", "true", "'True'", "'true'", "1"] = True
+  | s `elem` ["False", "false", "'False'", "'false'", "0"] = False
+  | otherwise = errorWithoutStackTrace $ unpack $ mconcat ["Could not parse '", s, "' into a boolean. Please use 'True' or 'False'"]
src/Text/Pandoc/Filter/Plot/Renderers/Octave.hs view
@@ -1,50 +1,46 @@-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Rendering Octave plots code blocks
--}
-
-module Text.Pandoc.Filter.Plot.Renderers.Octave (
-      octaveSupportedSaveFormats
-    , octaveCommand
-    , octaveCapture
-    , octaveAvailable
-) where
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
-import           Text.Pandoc.Filter.Plot.Renderers.Prelude
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Rendering Octave plots code blocks
+module Text.Pandoc.Filter.Plot.Renderers.Octave
+  ( octaveSupportedSaveFormats,
+    octaveCommand,
+    octaveCapture,
+    octaveAvailable,
+  )
+where
 
+import Text.Pandoc.Filter.Plot.Renderers.Prelude
 
 octaveSupportedSaveFormats :: [SaveFormat]
 octaveSupportedSaveFormats = [PNG, PDF, SVG, JPG, EPS, GIF, TIF]
 
-
 octaveCommand :: OutputSpec -> Text -> Text
-octaveCommand OutputSpec{..} exe = [st|#{exe} --no-gui --no-window-system "#{oScriptPath}"|]
-
+octaveCommand OutputSpec {..} exe = [st|#{exe} --no-gui --no-window-system "#{oScriptPath}"|]
 
 octaveAvailable :: PlotM Bool
 octaveAvailable = do
-    mexe <- executable Octave
-    case mexe of 
-        Nothing -> return False
-        Just (Executable dir exe) -> 
-            commandSuccess dir [st|#{exe} -h|]
-
+  mexe <- executable Octave
+  case mexe of
+    Nothing -> return False
+    Just (Executable dir exe) ->
+      commandSuccess dir [st|#{exe} -h|]
 
 octaveCapture :: FigureSpec -> FilePath -> Script
 octaveCapture = appendCapture octaveCaptureFragment
 
-
 octaveCaptureFragment :: FigureSpec -> FilePath -> Script
-octaveCaptureFragment _ fname = [st|
+octaveCaptureFragment _ fname =
+  [st|
 saveas(gcf, '#{fname}')
 |]
src/Text/Pandoc/Filter/Plot/Renderers/PlotlyPython.hs view
@@ -1,62 +1,58 @@-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Rendering Plotly-python code blocks
--}
-
-module Text.Pandoc.Filter.Plot.Renderers.PlotlyPython (
-      plotlyPythonSupportedSaveFormats
-    , plotlyPythonCommand
-    , plotlyPythonCapture
-    , plotlyPythonAvailable
-) where
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
-import           Text.Pandoc.Filter.Plot.Renderers.Prelude
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Rendering Plotly-python code blocks
+module Text.Pandoc.Filter.Plot.Renderers.PlotlyPython
+  ( plotlyPythonSupportedSaveFormats,
+    plotlyPythonCommand,
+    plotlyPythonCapture,
+    plotlyPythonAvailable,
+  )
+where
 
+import Text.Pandoc.Filter.Plot.Renderers.Prelude
 
 plotlyPythonSupportedSaveFormats :: [SaveFormat]
 plotlyPythonSupportedSaveFormats = [PNG, JPG, WEBP, PDF, SVG, EPS, HTML]
 
-
 plotlyPythonCommand :: OutputSpec -> Text -> Text
-plotlyPythonCommand OutputSpec{..} exe = [st|#{exe} "#{oScriptPath}"|]
-
+plotlyPythonCommand OutputSpec {..} exe = [st|#{exe} "#{oScriptPath}"|]
 
 plotlyPythonAvailable :: PlotM Bool
 plotlyPythonAvailable = do
-    mexe <- executable Matplotlib
-    case mexe of 
-        Nothing -> return False
-        Just (Executable dir exe) -> 
-            commandSuccess dir [st|#{exe} -c "import plotly.graph_objects"|]
-
+  mexe <- executable Matplotlib
+  case mexe of
+    Nothing -> return False
+    Just (Executable dir exe) ->
+      commandSuccess dir [st|#{exe} -c "import plotly.graph_objects"|]
 
 plotlyPythonCapture :: FigureSpec -> FilePath -> Script
 plotlyPythonCapture = appendCapture plotlyPythonCaptureFragment
 
-
 plotlyPythonCaptureFragment :: FigureSpec -> FilePath -> Script
-plotlyPythonCaptureFragment FigureSpec{..} fname = [st|
+plotlyPythonCaptureFragment FigureSpec {..} fname =
+  [st|
 import plotly.graph_objects as go
 __current_plotly_figure = next(obj for obj in globals().values() if type(obj) == go.Figure)
 __current_plotly_figure.#{write_method}(r"#{fname}"#{extra_args})
 |]
-    where
-        -- Note: the default behaviour for HTML export is
-        --       to embed the entire Plotly.js content. This means
-        --       that the resulting file can be used completely offline   
-        write_method = case saveFormat of
-            HTML -> "write_html"::Text
-            _    -> "write_image"
-        extra_args = case saveFormat of
-            HTML -> ", include_plotlyjs='cdn'"::Text
-            _    -> mempty
+  where
+    -- Note: the default behaviour for HTML export is
+    --       to embed the entire Plotly.js content. This means
+    --       that the resulting file can be used completely offline
+    write_method = case saveFormat of
+      HTML -> "write_html" :: Text
+      _ -> "write_image"
+    extra_args = case saveFormat of
+      HTML -> ", include_plotlyjs='cdn'" :: Text
+      _ -> mempty
src/Text/Pandoc/Filter/Plot/Renderers/PlotlyR.hs view
@@ -1,75 +1,71 @@-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Rendering Plotly/R plots code blocks
--}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
-module Text.Pandoc.Filter.Plot.Renderers.PlotlyR (
-      plotlyRSupportedSaveFormats
-    , plotlyRCommand
-    , plotlyRCapture
-    , plotlyRAvailable
-) where
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Rendering Plotly/R plots code blocks
+module Text.Pandoc.Filter.Plot.Renderers.PlotlyR
+  ( plotlyRSupportedSaveFormats,
+    plotlyRCommand,
+    plotlyRCapture,
+    plotlyRAvailable,
+  )
+where
 
 import qualified Data.Text as T
-import           Text.Pandoc.Filter.Plot.Renderers.Prelude
-
+import Text.Pandoc.Filter.Plot.Renderers.Prelude
 
 plotlyRSupportedSaveFormats :: [SaveFormat]
 plotlyRSupportedSaveFormats = [PNG, PDF, SVG, JPG, EPS, HTML]
 
-
 plotlyRCommand :: OutputSpec -> Text -> Text
-plotlyRCommand OutputSpec{..} exe = [st|#{exe} "#{oScriptPath}"|]
-
+plotlyRCommand OutputSpec {..} exe = [st|#{exe} "#{oScriptPath}"|]
 
 plotlyRAvailable :: PlotM Bool
 plotlyRAvailable = do
-    mexe <- executable PlotlyR
-    case mexe of 
-        Nothing -> return False
-        Just (Executable dir exe) -> 
-            commandSuccess dir [st|#{exe} -e 'if(!require("plotly")) {quit(status=1)}'|]
-
+  mexe <- executable PlotlyR
+  case mexe of
+    Nothing -> return False
+    Just (Executable dir exe) ->
+      commandSuccess dir [st|#{exe} -e 'if(!require("plotly")) {quit(status=1)}'|]
 
 plotlyRCapture :: FigureSpec -> FilePath -> Script
-plotlyRCapture fs fp = 
-    T.unlines [ "pdf(NULL)" -- Prevent the creation of empty Rplots.pdf
-              , script fs
-              , plotlyRCaptureFragment fs fp
-              ]
-
+plotlyRCapture fs fp =
+  T.unlines
+    [ "pdf(NULL)", -- Prevent the creation of empty Rplots.pdf
+      script fs,
+      plotlyRCaptureFragment fs fp
+    ]
 
 plotlyRCaptureFragment :: FigureSpec -> FilePath -> Script
-plotlyRCaptureFragment spec@FigureSpec{..} fname = case saveFormat of
-    HTML -> plotlyRCaptureHtml spec fname
-    _    -> plotlyRCaptureStatic spec fname
-
+plotlyRCaptureFragment spec@FigureSpec {..} fname = case saveFormat of
+  HTML -> plotlyRCaptureHtml spec fname
+  _ -> plotlyRCaptureStatic spec fname
 
 -- Based on the following discussion:
 --    https://stackoverflow.com/q/34580095
 plotlyRCaptureHtml :: FigureSpec -> FilePath -> Script
-plotlyRCaptureHtml _ fname = [st|
+plotlyRCaptureHtml _ fname =
+  [st|
 library(plotly) # just in case
 library(htmlwidgets)
 p <- last_plot()
 htmlwidgets::saveWidget(as_widget(p), "#{toRPath fname}")
 |]
 
-
 -- Based on the following documentation:
 --    https://plotly.com/r/static-image-export/
 plotlyRCaptureStatic :: FigureSpec -> FilePath -> Script
-plotlyRCaptureStatic _ fname = [st|
+plotlyRCaptureStatic _ fname =
+  [st|
 library(plotly) # just in case
 if (!require("processx")) install.packages("processx")
 pdf(NULL)
src/Text/Pandoc/Filter/Plot/Renderers/Plotsjl.hs view
@@ -1,52 +1,48 @@-{-# LANGUAGE NoImplicitPrelude #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE QuasiQuotes       #-}
-{-# LANGUAGE RecordWildCards   #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Rendering Julia/Plots.jl code blocks
--}
-
-module Text.Pandoc.Filter.Plot.Renderers.Plotsjl (
-      plotsjlSupportedSaveFormats
-    , plotsjlCommand
-    , plotsjlCapture
-    , plotsjlAvailable
-) where
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
 
-import           Text.Pandoc.Filter.Plot.Renderers.Prelude
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Rendering Julia/Plots.jl code blocks
+module Text.Pandoc.Filter.Plot.Renderers.Plotsjl
+  ( plotsjlSupportedSaveFormats,
+    plotsjlCommand,
+    plotsjlCapture,
+    plotsjlAvailable,
+  )
+where
 
+import Text.Pandoc.Filter.Plot.Renderers.Prelude
 
 -- Save formats support by most backends
 -- https://docs.plotsjl.org/latest/output/#Supported-output-file-formats-1
 plotsjlSupportedSaveFormats :: [SaveFormat]
 plotsjlSupportedSaveFormats = [PNG, SVG, PDF]
 
-
 plotsjlCommand :: OutputSpec -> Text -> Text
-plotsjlCommand OutputSpec{..} exe = [st|#{exe} "#{oScriptPath}"|]
-
+plotsjlCommand OutputSpec {..} exe = [st|#{exe} "#{oScriptPath}"|]
 
 plotsjlAvailable :: PlotM Bool
 plotsjlAvailable = do
-    mexe <- executable Plotsjl
-    case mexe of 
-        Nothing -> return False
-        Just (Executable dir exe) -> 
-            commandSuccess dir [st|#{exe} -e "using Plots"|]
-
+  mexe <- executable Plotsjl
+  case mexe of
+    Nothing -> return False
+    Just (Executable dir exe) ->
+      commandSuccess dir [st|#{exe} -e "using Plots"|]
 
 plotsjlCapture :: FigureSpec -> FilePath -> Script
 plotsjlCapture = appendCapture plotsjlCaptureFragment
 
-
 plotsjlCaptureFragment :: FigureSpec -> FilePath -> Script
-plotsjlCaptureFragment _ fname = [st|
+plotsjlCaptureFragment _ fname =
+  [st|
 savefig(raw"#{fname}")
 |]
src/Text/Pandoc/Filter/Plot/Renderers/Prelude.hs view
@@ -1,70 +1,69 @@ {-# LANGUAGE OverloadedStrings #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
 
-Prelude for renderers, containing some helpful utilities.
--}
-module Text.Pandoc.Filter.Plot.Renderers.Prelude (
-
-      module Prelude
-    , module Text.Pandoc.Filter.Plot.Monad
-    , Text
-    , st
-    , unpack
-    , commandSuccess
-    , existsOnPath
-    , OutputSpec(..)
-    , appendCapture
-    , toRPath
-) where
-
-import           Data.Maybe                    (isJust)
-import           Data.Text                     (Text, unpack)
-
-import           System.Directory              (findExecutable)
-import           System.FilePath               (isPathSeparator)
-import           System.Exit                   (ExitCode(..))
-
-import           Text.Shakespeare.Text         (st)
-
-import           Text.Pandoc.Filter.Plot.Monad
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Prelude for renderers, containing some helpful utilities.
+module Text.Pandoc.Filter.Plot.Renderers.Prelude
+  ( module Prelude,
+    module Text.Pandoc.Filter.Plot.Monad,
+    Text,
+    st,
+    unpack,
+    commandSuccess,
+    existsOnPath,
+    OutputSpec (..),
+    appendCapture,
+    toRPath,
+  )
+where
 
+import Data.Maybe (isJust)
+import Data.Text (Text, unpack)
+import System.Directory (findExecutable)
+import System.Exit (ExitCode (..))
+import System.FilePath (isPathSeparator)
+import Text.Pandoc.Filter.Plot.Monad
+import Text.Shakespeare.Text (st)
 
 -- | Check that the supplied command results in
 -- an exit code of 0 (i.e. no errors)
-commandSuccess :: FilePath -- Directory from which to run the command
-               -> Text     -- Command to run, including the executable
-               -> PlotM Bool
+commandSuccess ::
+  FilePath -> -- Directory from which to run the command
+  Text -> -- Command to run, including the executable
+  PlotM Bool
 commandSuccess fp s = do
-    (ec, _) <- runCommand fp s
-    return $ ec == ExitSuccess
-
+  (ec, _) <- runCommand fp s
+  return $ ec == ExitSuccess
 
 -- | Checks that an executable is available on path, at all.
 existsOnPath :: FilePath -> IO Bool
 existsOnPath fp = findExecutable fp >>= fmap isJust . return
 
-
 -- | A shortcut to append capture script fragments to scripts
-appendCapture :: (FigureSpec -> FilePath -> Script) 
-              ->  FigureSpec -> FilePath -> Script
+appendCapture ::
+  (FigureSpec -> FilePath -> Script) ->
+  FigureSpec ->
+  FilePath ->
+  Script
 appendCapture f s fp = mconcat [script s, "\n", f s fp]
 
-
--- | Internal description of all information 
+-- | Internal description of all information
 -- needed to output a figure.
-data OutputSpec = OutputSpec 
-    { oFigureSpec    :: FigureSpec    -- ^ Figure spec
-    , oScriptPath    :: FilePath      -- ^ Path to the script to render
-    , oFigurePath    :: FilePath      -- ^ Figure output path
-    } 
-
+data OutputSpec = OutputSpec
+  { -- | Figure spec
+    oFigureSpec :: FigureSpec,
+    -- | Path to the script to render
+    oScriptPath :: FilePath,
+    -- | Figure output path
+    oFigurePath :: FilePath
+  }
 
 -- | R paths use the '/' path separator
 toRPath :: FilePath -> FilePath
-toRPath = fmap (\c -> if isPathSeparator c then '/' else c)+toRPath = fmap (\c -> if isPathSeparator c then '/' else c)
src/Text/Pandoc/Filter/Plot/Scripting.hs view
@@ -1,151 +1,160 @@-{-# LANGUAGE OverloadedStrings     #-}
-{-# LANGUAGE RecordWildCards       #-}
-{-|
-Module      : $header$
-Copyright   : (c) Laurent P René de Cotret, 2020
-License     : GNU GPL, version 2 or above
-Maintainer  : laurent.decotret@outlook.com
-Stability   : internal
-Portability : portable
-
-Scripting
--}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE TemplateHaskell #-}
 
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2020
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Scripting
 module Text.Pandoc.Filter.Plot.Scripting
-    ( ScriptResult(..)
-    , runTempScript
-    , runScriptIfNecessary
-    , figurePath
-    ) where
-
-import           Control.Exception.Lifted          (bracket)
-import           Control.Monad.Reader
-
-import           Data.Hashable                     (hash)
-import           Data.Text                         (Text, pack, unpack)
-import qualified Data.Text.IO                      as T
-
-import           Paths_pandoc_plot                 (version)
-
-import           System.Directory                  (createDirectoryIfMissing,
-                                                    doesFileExist, getTemporaryDirectory)
-import           System.Environment                (getEnv, setEnv)
-import           System.Exit                       (ExitCode (..))
-import           System.FilePath                   (addExtension,
-                                                    normalise, replaceExtension,
-                                                    takeDirectory, (</>))
-
-import           Text.Pandoc.Filter.Plot.Renderers
-import           Text.Pandoc.Filter.Plot.Monad
+  ( ScriptResult (..),
+    runTempScript,
+    runScriptIfNecessary,
+    figurePath,
+    sourceCodePath,
+  )
+where
 
+import Control.Exception.Lifted (bracket)
+import Control.Monad.Reader
+import Data.Default (def)
+import Data.Functor.Identity (Identity (..))
+import Data.Hashable (hash)
+import Data.Text (Text, pack, unpack)
+import qualified Data.Text.IO as T
+import Paths_pandoc_plot (version)
+import System.Directory
+  ( createDirectoryIfMissing,
+    doesFileExist,
+    getTemporaryDirectory,
+  )
+import System.Environment (getEnv, setEnv)
+import System.Exit (ExitCode (..))
+import System.FilePath
+  ( addExtension,
+    normalise,
+    replaceExtension,
+    takeDirectory,
+    (</>),
+  )
+import Text.Pandoc.Class (runPure)
+import Text.Pandoc.Definition
+import Text.Pandoc.Filter.Plot.Monad
+import Text.Pandoc.Filter.Plot.Renderers
+import Text.Pandoc.Filter.Plot.Scripting.Template
+import Text.Pandoc.Options (WriterOptions (..))
+import Text.Pandoc.SelfContained (makeSelfContained)
+import Text.Pandoc.Templates
+import Text.Pandoc.Writers (writeHtml5String)
 
 -- Run script as described by the spec, only if necessary
 runScriptIfNecessary :: FigureSpec -> PlotM ScriptResult
 runScriptIfNecessary spec = do
-    target <- figurePath spec
-    liftIO $ createDirectoryIfMissing True . takeDirectory $ target
-
-    fileAlreadyExists <- liftIO . doesFileExist $ target
-    result <- if fileAlreadyExists
-                then return ScriptSuccess
-                else runTempScript spec
-
-    logScriptResult result
+  target <- figurePath spec
+  liftIO $ createDirectoryIfMissing True . takeDirectory $ target
 
-    case result of
-        ScriptSuccess -> do
-            scp <- sourceCodePath spec
-            liftIO $ T.writeFile scp (script spec) >> return ScriptSuccess
-        other         -> return other
+  fileAlreadyExists <- liftIO . doesFileExist $ target
+  result <-
+    if fileAlreadyExists
+      then return ScriptSuccess
+      else runTempScript spec
 
-    where
-        logScriptResult ScriptSuccess = return () 
-        logScriptResult r             = err   . pack . show $ r
+  logScriptResult result
 
+  case result of
+    ScriptSuccess -> writeSource spec >> return ScriptSuccess
+    other -> return other
+  where
+    logScriptResult ScriptSuccess = return ()
+    logScriptResult r = err . pack . show $ r
 
 -- | Possible result of running a script
 data ScriptResult
-    = ScriptSuccess
-    | ScriptChecksFailed Text     -- Message
-    | ScriptFailure Text Int      -- Command and exit code
-    | ToolkitNotInstalled Toolkit -- Script failed because toolkit is not installed
+  = ScriptSuccess
+  | ScriptChecksFailed Text -- Message
+  | ScriptFailure Text Int -- Command and exit code
+  | ToolkitNotInstalled Toolkit -- Script failed because toolkit is not installed
 
 instance Show ScriptResult where
-    show ScriptSuccess            = "Script success."
-    show (ScriptChecksFailed msg) = unpack $ "Script checks failed: " <> msg
-    show (ScriptFailure msg ec)   = mconcat ["Script failed with exit code ", show ec, " and the following message: ", unpack msg]
-    show (ToolkitNotInstalled tk) = (show tk) <> " toolkit not installed."
-
+  show ScriptSuccess = "Script success."
+  show (ScriptChecksFailed msg) = unpack $ "Script checks failed: " <> msg
+  show (ScriptFailure msg ec) = mconcat ["Script failed with exit code ", show ec, " and the following message: ", unpack msg]
+  show (ToolkitNotInstalled tk) = (show tk) <> " toolkit not installed."
 
 -- Run script as described by the spec
 -- Checks are performed, according to the renderer
 -- Note that stdout from the script is suppressed, but not
 -- stderr.
 runTempScript :: FigureSpec -> PlotM ScriptResult
-runTempScript spec@FigureSpec{..} = do
-    let checks = scriptChecks toolkit
-        checkResult = mconcat $ checks <*> [script]
-    case checkResult of
-        CheckFailed msg -> return $ ScriptChecksFailed msg
-        CheckPassed -> do
-            scriptPath <- tempScriptPath spec
-            target <- figurePath spec
-
-            -- Check if executable is present
-            -- Note that checking if the toolkit if fully configured is much more involved,
-            -- and so we only check if the toolkit is appropriately installed if there is
-            -- an error.
-            exe <- executable toolkit
-            case exe of
-                Nothing -> error $ "Toolkit " <> show toolkit <> " is not installed."
-                Just (Executable exedir exename) ->
-                    -- Change the PATH environment variable so the appropriate executable is 
-                    -- found first 
-                    withPrependedPath exedir $ do
-                        let scriptWithCapture = (capture toolkit) spec target
+runTempScript spec@FigureSpec {..} = do
+  let checks = scriptChecks toolkit
+      checkResult = mconcat $ checks <*> [script]
+  case checkResult of
+    CheckFailed msg -> return $ ScriptChecksFailed msg
+    CheckPassed -> do
+      scriptPath <- tempScriptPath spec
+      target <- figurePath spec
 
-                        liftIO $ T.writeFile scriptPath scriptWithCapture
-                        let outputSpec = OutputSpec { oFigureSpec = spec
-                                                    , oScriptPath = scriptPath
-                                                    , oFigurePath = target
-                                                    }
+      -- Check if executable is present
+      -- Note that checking if the toolkit if fully configured is much more involved,
+      -- and so we only check if the toolkit is appropriately installed if there is
+      -- an error.
+      exe <- executable toolkit
+      case exe of
+        Nothing -> error $ "Toolkit " <> show toolkit <> " is not installed."
+        Just (Executable exedir exename) ->
+          -- Change the PATH environment variable so the appropriate executable is
+          -- found first
+          withPrependedPath exedir $ do
+            let scriptWithCapture = (capture toolkit) spec target
 
-                        let command_ = command toolkit outputSpec exename
-                        -- It is important that the CWD be inherited from the 
-                        -- parent process. See #2.
-                        cwd <- asks envCWD
-                        (ec, _) <- runCommand cwd command_
-                        case ec of
-                            ExitSuccess      -> return   ScriptSuccess
-                            ExitFailure code -> do
-                                -- Two possible types of failures: either the script
-                                -- failed because the toolkit was not available, or
-                                -- because of a genuine error
-                                toolkitInstalled <- toolkitAvailable toolkit 
-                                if toolkitInstalled
-                                    then return $ ScriptFailure command_ code
-                                    else return $ ToolkitNotInstalled toolkit
+            liftIO $ T.writeFile scriptPath scriptWithCapture
+            let outputSpec =
+                  OutputSpec
+                    { oFigureSpec = spec,
+                      oScriptPath = scriptPath,
+                      oFigurePath = target
+                    }
 
+            let command_ = command toolkit outputSpec exename
+            -- It is important that the CWD be inherited from the
+            -- parent process. See #2.
+            cwd <- asks envCWD
+            (ec, _) <- runCommand cwd command_
+            case ec of
+              ExitSuccess -> return ScriptSuccess
+              ExitFailure code -> do
+                -- Two possible types of failures: either the script
+                -- failed because the toolkit was not available, or
+                -- because of a genuine error
+                toolkitInstalled <- toolkitAvailable toolkit
+                if toolkitInstalled
+                  then return $ ScriptFailure command_ code
+                  else return $ ToolkitNotInstalled toolkit
 
 -- | Determine the temp script path from Figure specifications
 -- Note that for certain renderers, the appropriate file extension
 -- is important.
 tempScriptPath :: FigureSpec -> PlotM FilePath
-tempScriptPath FigureSpec{..} = do
-    let ext = scriptExtension toolkit
-    -- MATLAB will refuse to process files that don't start with
-    -- a letter
-    -- Note that this hash is only so that we are running scripts from unique
-    -- file names; it does NOT determine whether this figure should
-    -- be rendered or not.
-    let hashedPath = "pandocplot" <> (show . abs . hash $ script) <> ext
-    liftIO $ (</> hashedPath) <$> getTemporaryDirectory
-
+tempScriptPath FigureSpec {..} = do
+  let ext = scriptExtension toolkit
+  -- MATLAB will refuse to process files that don't start with
+  -- a letter
+  -- Note that this hash is only so that we are running scripts from unique
+  -- file names; it does NOT determine whether this figure should
+  -- be rendered or not.
+  let hashedPath = "pandocplot" <> (show . abs . hash $ script) <> ext
+  liftIO $ (</> hashedPath) <$> getTemporaryDirectory
 
 -- | Determine the path to the source code that generated the figure.
+-- To ensure that the source code path is distinguished from HTML figures, we use the extension .src.html.
 sourceCodePath :: FigureSpec -> PlotM FilePath
-sourceCodePath = fmap normalise . fmap (flip replaceExtension ".txt") . figurePath
-
+sourceCodePath = fmap normalise . fmap (flip replaceExtension ".src.html") . figurePath
 
 -- | Hash of the content of a @FigureSpec@. Note that unlike usual hashes,
 -- two @FigureSpec@ with the same @figureContentHash@ does not mean that they are equal!
@@ -153,21 +162,23 @@ -- Not all parts of a FigureSpec are related to running code.
 -- For example, changing the caption should not require running the figure again.
 figureContentHash :: FigureSpec -> PlotM Word
-figureContentHash FigureSpec{..} = do
-    dependenciesHash <- sequence $ fileHash <$> dependencies
-    -- hash looks strange because instances only exist for 7-tuples or less
-    return $ fromIntegral 
-           $ hash ( (fromEnum toolkit
-                    , script
-                    , fromEnum saveFormat
-                    , directory)
-                  , ( dpi
-                    , dependenciesHash
-                    , extraAttrs
-                    , show version -- Included version because capture
-                    )              -- scripts may change between releases
-                  )
-
+figureContentHash FigureSpec {..} = do
+  dependenciesHash <- sequence $ fileHash <$> dependencies
+  -- hash looks strange because instances only exist for 7-tuples or less
+  return $
+    fromIntegral $
+      hash
+        ( ( fromEnum toolkit,
+            script,
+            fromEnum saveFormat,
+            directory
+          ),
+          ( dpi,
+            dependenciesHash,
+            extraAttrs,
+            show version -- Included version because capture
+          ) -- scripts may change between releases
+        )
 
 -- | Determine the path a figure should have.
 -- The path for this file is unique to the content of the figure,
@@ -175,11 +186,10 @@ -- be rendered again or not.
 figurePath :: FigureSpec -> PlotM FilePath
 figurePath spec = do
-    fh <- figureContentHash spec
-    let    ext  = extension . saveFormat $ spec
-           stem = flip addExtension ext . show $ fh
-    return $ normalise $ directory spec </> stem
-
+  fh <- figureContentHash spec
+  let ext = extension . saveFormat $ spec
+      stem = flip addExtension ext . show $ fh
+  return $ normalise $ directory spec </> stem
 
 -- | Prepend a directory to the PATH environment variable for the duration
 -- of a computation.
@@ -188,12 +198,27 @@ -- computation, the PATH environment variable will be reverted back to
 -- its initial value.
 withPrependedPath :: FilePath -> PlotM a -> PlotM a
-withPrependedPath dir f = do 
-    pathVar <- liftIO $ getEnv "PATH"
-    let pathVarPrepended = mconcat [dir, ";", pathVar]
-    bracket 
-        (      liftIO $ setEnv "PATH" pathVarPrepended)
-        (\_ -> liftIO $ setEnv "PATH" pathVar)
-        (\_ -> f)
+withPrependedPath dir f = do
+  pathVar <- liftIO $ getEnv "PATH"
+  let pathVarPrepended = mconcat [dir, ";", pathVar]
+  bracket
+    (liftIO $ setEnv "PATH" pathVarPrepended)
+    (\_ -> liftIO $ setEnv "PATH" pathVar)
+    (\_ -> f)
 
+-- | Write the source code of a figure to an HTML file with appropriate syntax highlighting.
+writeSource :: FigureSpec -> PlotM ()
+writeSource spec = do
+  scp <- sourceCodePath spec
+  let doc = Pandoc mempty [CodeBlock (mempty, [language (toolkit spec)], mempty) (script spec)]
+      renderSource = \template -> do
+        let opts = def {writerTemplate = Just template}
+            -- Note that making the document self-contained is absolutely required so that the CSS for
+            -- syntax highlighting is included directly in the document.
+            t = either (const mempty) id $ runPure $ (writeHtml5String opts doc >>= makeSelfContained)
+        liftIO $ T.writeFile scp t
 
+  either (err . pack) (renderSource) $ runIdentity $ compileTemplate mempty sourceTemplate
+
+sourceTemplate :: Text
+sourceTemplate = pack $(sourceTemplate_)
+ src/Text/Pandoc/Filter/Plot/Scripting/Template.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE TemplateHaskell #-}
+
+module Text.Pandoc.Filter.Plot.Scripting.Template (sourceTemplate_) where
+
+import Data.String (fromString)
+import Language.Haskell.TH.Syntax
+import System.FilePath ((</>))
+
+sourceTemplate_ :: Q Exp
+sourceTemplate_ = do
+  let fp = ("data" </> "srctemplate.html")
+  qAddDependentFile fp
+  d <- runIO $ readFile fp
+  strToExp d
+  where
+    strToExp :: String -> Q Exp
+    strToExp s = return $ VarE 'fromString `AppE` LitE (StringL s)
stack.yaml view
@@ -1,4 +1,4 @@-resolver: nightly-2020-10-11 # GHC 8.10.2
+resolver: nightly-2020-12-14 # GHC 8.10.2
 
 packages:
 - .
@@ -8,15 +8,18 @@ compiler: ghc-8.10.1
 
 extra-deps:
-- pandoc-2.11
-- citeproc-0.1@sha256:0c82d6cf5be3d82d4f755e6a2075ce224b9f2bdb891f1417ca49f5e78ac4e26a,5355
-- commonmark-0.1.0.2@sha256:fbff7a2ade0ce7d699964a87f765e503a3a9e22542c05f0f02ba7aad64e38af4,3278
-- commonmark-extensions-0.2.0.1@sha256:647aa8dba5fd46984ddedc15c3693c9c4d9655503d42006576bd8f0dadf8cd39,3176
+- pandoc-2.11.3.1
+- citeproc-0.3.0.1@sha256:1860a6757d5bc3ec149a434ed4011edb30155cb6ae92a1d83ccf3bd163bca0f1,5590
+- commonmark-0.1.1.2@sha256:c06ab05f0f224ab7982502a96e17952823a9b6dae8505fb35194b0baa9e2a975,3278
+- commonmark-extensions-0.2.0.4@sha256:6a437bcfa3c757af4262b71336513619990eafb5cfdc33e57a499c93ad225608,3184
 - commonmark-pandoc-0.2.0.1@sha256:529c6e2c6cabf61558b66a28123eafc1d90d3324be29819f59f024e430312c1f,1105
+- doctemplates-0.9@sha256:eb0bf957ba8571746f36f07ceca43d311a0e390a9fdcfde6909f9f9be85b3b28,3125
+- skylighting-0.10.2@sha256:9c395703ca61752f4491044443e87d5b87ed94bca78c0a00b5ebf4e4b8e59904,10031
+- skylighting-core-0.10.2@sha256:5070d9f08135cdb7c935c5936a4a76a9e1922ec846cd40d6e2837f42e7a9f29f,8159
 
 # For development
 - git: https://github.com/owickstrom/pandoc-include-code.git
-  commit: d5cbdc86eb1abcd9561c0965ac423d7011378ddb
+  commit: 89c8465549960872257da993a399d978a269d6a6
 - ghc-check-0.3.0.1@sha256:651d9b2b75a5cbdb3c942117801bfa566079bcaf20360e4d0959f9e575c30b39,1070
   
 # Faster compilation.
tests/Common.hs view
@@ -1,355 +1,384 @@-{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Common where
 
-import           Control.Monad                    (unless, when)
-
-import           Data.List                        (isInfixOf, isSuffixOf)
-import           Data.Monoid                      ((<>))
-import           Data.String                      (fromString)
-import           Data.Text                        (Text, pack, unpack)
-import qualified Data.Text                        as T
-
-import           Test.Tasty
-import           Test.Tasty.HUnit
-
-import           Text.Pandoc.Filter.Plot
-import           Text.Pandoc.Filter.Plot.Internal
-
-import qualified Text.Pandoc.Builder              as B
-import qualified Text.Pandoc.Definition           as B
-import           Text.Pandoc.JSON
-
-import           System.Directory                 (createDirectory,
-                                                   createDirectoryIfMissing,
-                                                   doesDirectoryExist,
-                                                   doesFileExist, listDirectory,
-                                                   removeDirectoryRecursive,
-                                                   removePathForcibly, 
-                                                   getTemporaryDirectory)
-import           System.FilePath                  (takeExtensions, (</>))
-
+import Control.Monad (unless, when)
+import Data.List (isInfixOf, isSuffixOf, (!!))
+import Data.Monoid ((<>))
+import Data.String (fromString)
+import Data.Text (Text, pack, unpack)
+import qualified Data.Text as T
+import System.Directory
+  ( createDirectory,
+    createDirectoryIfMissing,
+    doesDirectoryExist,
+    doesFileExist,
+    getTemporaryDirectory,
+    listDirectory,
+    removeDirectoryRecursive,
+    removePathForcibly,
+  )
+import System.FilePath (takeExtensions, (</>))
+import Test.Tasty
+import Test.Tasty.HUnit
+import qualified Text.Pandoc.Builder as B
+import qualified Text.Pandoc.Definition as B
+import Text.Pandoc.Filter.Plot
+import Text.Pandoc.Filter.Plot.Internal
+import Text.Pandoc.JSON
 
 defaultTestConfig :: Configuration
-defaultTestConfig = defaultConfiguration { logVerbosity = Silent
-                                         , logSink = StdErr
-                                         }
+defaultTestConfig =
+  defaultConfiguration
+    { logVerbosity = Silent,
+      logSink = StdErr
+    }
 
 -------------------------------------------------------------------------------
 -- Test that plot files and source files are created when the filter is run
 testFileCreation :: Toolkit -> TestTree
 testFileCreation tk =
-    testCase "writes output files in appropriate directory" $ do
-        let postfix = unpack . cls $ tk
-        tempDir <- (</> "test-file-creation-" <> postfix) <$> getTemporaryDirectory
-        ensureDirectoryExistsAndEmpty tempDir
-
-        let cb = (addDirectory tempDir $ codeBlock tk (trivialContent tk))
-        _ <- runPlotM defaultTestConfig $ make cb
-        filesCreated <- length <$> listDirectory tempDir
-        assertEqual "" 2 filesCreated
+  testCase "writes output files in appropriate directory" $ do
+    let postfix = unpack . cls $ tk
+    tempDir <- (</> "test-file-creation-" <> postfix) <$> getTemporaryDirectory
+    ensureDirectoryExistsAndEmpty tempDir
 
+    let cb = (addDirectory tempDir $ codeBlock tk (trivialContent tk))
+    _ <- runPlotM defaultTestConfig $ make cb
+    filesCreated <- length <$> listDirectory tempDir
+    assertEqual "" 2 filesCreated
 
 -------------------------------------------------------------------------------
 -- Test that plot files and source files are created when the filter is run
 -- and the path of the files involves spaces. See Issue #2
 testFileCreationPathWithSpaces :: Toolkit -> TestTree
 testFileCreationPathWithSpaces tk =
-    testCase "writes output files in appropriate directory (with spaces)" $ do
-        let postfix = unpack . cls $ tk
-        tempDir <- (</> "test-file-creation-with-spaces-   -" <> postfix) <$> getTemporaryDirectory
-        ensureDirectoryExistsAndEmpty tempDir
-
-        let cb = (addDirectory tempDir $ codeBlock tk (trivialContent tk))
-        _ <- runPlotM defaultTestConfig $ make cb
-        filesCreated <- length <$> listDirectory tempDir
-        assertEqual "" 2 filesCreated
+  testCase "writes output files in appropriate directory (with spaces)" $ do
+    let postfix = unpack . cls $ tk
+    tempDir <- (</> "test-file-creation-with-spaces-   -" <> postfix) <$> getTemporaryDirectory
+    ensureDirectoryExistsAndEmpty tempDir
 
+    let cb = (addDirectory tempDir $ codeBlock tk (trivialContent tk))
+    _ <- runPlotM defaultTestConfig $ make cb
+    filesCreated <- length <$> listDirectory tempDir
+    assertEqual "" 2 filesCreated
 
 -------------------------------------------------------------------------------
 -- Test that included files are found within the source
 testFileInclusion :: Toolkit -> TestTree
 testFileInclusion tk =
-    testCase "includes plot inclusions" $ do
-        let postfix = unpack . cls $ tk
-        tempDir <- (</> "test-file-inclusion-" <> postfix) <$> getTemporaryDirectory
-        ensureDirectoryExistsAndEmpty tempDir
+  testCase "includes plot inclusions" $ do
+    let postfix = unpack . cls $ tk
+    tempDir <- (</> "test-file-inclusion-" <> postfix) <$> getTemporaryDirectory
+    ensureDirectoryExistsAndEmpty tempDir
 
-        let cb = (addPreamble (include tk) $
-                    addDirectory tempDir $ codeBlock tk (trivialContent tk))
-        _ <- runPlotM defaultTestConfig $ make cb
-        inclusion <- readFile (include tk)
-        sourcePath <- head . filter (isExtensionOf "txt") <$> listDirectory tempDir
-        src <- readFile (tempDir </> sourcePath)
-        assertIsInfix inclusion src
-    where
-        include Matplotlib   = "tests/includes/matplotlib.py"
-        include PlotlyPython = "tests/includes/plotly-python.py"
-        include PlotlyR      = "tests/includes/plotly-r.r"
-        include Matlab       = "tests/includes/matlabplot.m"
-        include Mathematica  = "tests/includes/mathplot.m"
-        include Octave       = "tests/includes/octave.m"
-        include GGPlot2      = "tests/includes/ggplot2.r"
-        include GNUPlot      = "tests/includes/gnuplot.gp"
-        include Graphviz     = "tests/includes/graphviz.dot"
-        include Bokeh        = "tests/includes/bokeh.py"
-        include Plotsjl      = "tests/includes/plotsjl.jl"
+    let cb =
+          ( addPreamble (include tk) $
+              addDirectory tempDir $ codeBlock tk (trivialContent tk)
+          )
+    _ <- runPlotM defaultTestConfig $ make cb
+    inclusion <- readFile (include tk)
+    sourcePath <- head . filter (isExtensionOf ".src.html") <$> listDirectory tempDir
+    src <- readFile (tempDir </> sourcePath)
+    assertIsInfix inclusion src
+  where
+    include Matplotlib = "tests/includes/matplotlib.py"
+    include PlotlyPython = "tests/includes/plotly-python.py"
+    include PlotlyR = "tests/includes/plotly-r.r"
+    include Matlab = "tests/includes/matlabplot.m"
+    include Mathematica = "tests/includes/mathplot.m"
+    include Octave = "tests/includes/octave.m"
+    include GGPlot2 = "tests/includes/ggplot2.r"
+    include GNUPlot = "tests/includes/gnuplot.gp"
+    include Graphviz = "tests/includes/graphviz.dot"
+    include Bokeh = "tests/includes/bokeh.py"
+    include Plotsjl = "tests/includes/plotsjl.jl"
 
 -------------------------------------------------------------------------------
 -- Test that the files are saved in the appropriate format
 testSaveFormat :: Toolkit -> TestTree
 testSaveFormat tk =
-    testCase "saves in the appropriate format" $ do
-        let postfix = unpack . cls $ tk
-        tempDir <- (</> "test-safe-format-" <> postfix) <$> getTemporaryDirectory
-        ensureDirectoryExistsAndEmpty tempDir
-        let fmt = head (supportedSaveFormats tk)
-            cb = (addSaveFormat fmt $
-                 addDirectory tempDir $ codeBlock tk (trivialContent tk))
-        _ <- runPlotM defaultTestConfig $ make cb
-        numberjpgFiles <-
-            length <$> filter (isExtensionOf (extension fmt)) <$>
-            listDirectory tempDir
-        assertEqual "" numberjpgFiles 1
+  testCase "saves in the appropriate format" $ do
+    let postfix = unpack . cls $ tk
+    tempDir <- (</> "test-safe-format-" <> postfix) <$> getTemporaryDirectory
+    ensureDirectoryExistsAndEmpty tempDir
+    let fmt = head (supportedSaveFormats tk)
+        cb =
+          ( addSaveFormat fmt $
+              addDirectory tempDir $ codeBlock tk (trivialContent tk)
+          )
+    _ <- runPlotM defaultTestConfig $ make cb
+    numberjpgFiles <-
+      length <$> filter (isExtensionOf (extension fmt))
+        <$> listDirectory tempDir
+    assertEqual "" numberjpgFiles 1
 
 -------------------------------------------------------------------------------
 -- Test that it is possible to not render source links in captions
 testWithSource :: Toolkit -> TestTree
 testWithSource tk =
-    testCase "appropriately omits links to source code" $ do
-        let postfix = unpack . cls $ tk
-        tempDir <- (</> "test-caption-links-" <> postfix) <$> getTemporaryDirectory
-        ensureDirectoryExistsAndEmpty tempDir
+  testCase "appropriately omits links to source code" $ do
+    let postfix = unpack . cls $ tk
+    tempDir <- (</> "test-caption-links-" <> postfix) <$> getTemporaryDirectory
+    ensureDirectoryExistsAndEmpty tempDir
 
-        let expected = "caption content"
-            noSource = addWithSource False 
-                      $ addDirectory tempDir 
-                      $ addCaption expected 
-                      $ codeBlock tk (trivialContent tk)
-            withSource = addWithSource True 
-                      $ addDirectory tempDir 
-                      $ addCaption expected 
-                      $ codeBlock tk (trivialContent tk)
-        blockNoSource   <- runPlotM defaultTestConfig $ make noSource
-        blockWithSource <- runPlotM defaultTestConfig $ make withSource
+    let expected = "caption content"
+        noSource =
+          addWithSource False $
+            addDirectory tempDir $
+              addCaption expected $
+                codeBlock tk (trivialContent tk)
+        withSource =
+          addWithSource True $
+            addDirectory tempDir $
+              addCaption expected $
+                codeBlock tk (trivialContent tk)
+    blockNoSource <- runPlotM defaultTestConfig $ make noSource
+    blockWithSource <- runPlotM defaultTestConfig $ make withSource
 
-        -- In the case where source=false, the caption is used verbatim.
-        -- Otherwise, links will be appended to the caption; hence, the caption
-        -- is no longer equal to the initial value
-        assertEqual    "" (B.toList $ fromString expected) (extractCaption blockNoSource)
-        assertNotEqual "" (B.toList $ fromString expected) (extractCaption blockWithSource)
+    -- In the case where source=false, the caption is used verbatim.
+    -- Otherwise, links will be appended to the caption; hence, the caption
+    -- is no longer equal to the initial value
+    assertEqual "" (B.toList $ fromString expected) (extractCaption blockNoSource)
+    assertNotEqual "" (B.toList $ fromString expected) (extractCaption blockWithSource)
+  where
+    extractCaption (B.Para blocks) = extractImageCaption . head $ blocks
+    extractCaption _ = mempty
 
-    where
-        extractCaption (B.Para blocks) = extractImageCaption . head $ blocks
-        extractCaption _               = mempty
+    extractImageCaption (Image _ c _) = c
+    extractImageCaption _ = mempty
 
-        extractImageCaption (Image _ c _) = c
-        extractImageCaption _             = mempty
+-------------------------------------------------------------------------------
+-- Test that it is possible to change the source code label in captions
+testSourceLabel :: Toolkit -> TestTree
+testSourceLabel tk =
+  testCase "appropriately changes the source code label" $ do
+    let postfix = unpack . cls $ tk
+    tempDir <- (</> "test-source-label-" <> postfix) <$> getTemporaryDirectory
+    ensureDirectoryExistsAndEmpty tempDir
 
+    -- Note that this test requires that the actual caption be empty
+    -- so that the caption is only the source code label
+    let withSource =
+          addWithSource True $
+            addDirectory tempDir $
+              addCaption mempty $ -- This test requires that the actual caption be empty
+                codeBlock tk (trivialContent tk)
+    blockWithSource <- runPlotM defaultTestConfig {sourceCodeLabel = "Test label"} $ make withSource
+
+    -- The caption will look like [Space, Str "(", Link ... ]. Hence, we skip the first elements with (!!)
+    let resultCaption = linkLabel $ (!! 2) . B.toList $ extractCaption blockWithSource
+    assertEqual "" (B.str "Test label") resultCaption
+  where
+    extractCaption (B.Para blocks) = extractImageCaption . head $ blocks
+    extractCaption _ = mempty
+
+    extractImageCaption (Image _ c _) = B.fromList c
+    extractImageCaption _ = mempty
+
+    linkLabel (B.Link _ ils _) = B.fromList ils
+    linkLabel _ = mempty
+
 -------------------------------------------------------------------------------
 -- Test that parameters in code blocks will override the defaults in configuration
 testOverrideConfiguration :: Toolkit -> TestTree
-testOverrideConfiguration tk = 
-    -- We set the default save format to JPG via the configuration, 
-    -- but set the code block parameter to PNG.
-    -- Therefore, after the filter has been used, there should be one PNG file and
-    -- no JPG files.
-    testCase "code block attributes override configuration defaults" $ do
-        let postfix = unpack . cls $ tk
-        tempDir <- (</> "test-caption-links-" <> postfix) <$> getTemporaryDirectory
-        ensureDirectoryExistsAndEmpty tempDir
-
-        let config = defaultTestConfig { defaultDirectory = tempDir
-                                       , defaultSaveFormat = JPG}
+testOverrideConfiguration tk =
+  -- We set the default save format to JPG via the configuration,
+  -- but set the code block parameter to PNG.
+  -- Therefore, after the filter has been used, there should be one PNG file and
+  -- no JPG files.
+  testCase "code block attributes override configuration defaults" $ do
+    let postfix = unpack . cls $ tk
+    tempDir <- (</> "test-caption-links-" <> postfix) <$> getTemporaryDirectory
+    ensureDirectoryExistsAndEmpty tempDir
 
-        -- Not all toolkits support both save formats
-        when (  JPG `elem` supportedSaveFormats tk 
-             && PNG `elem` supportedSaveFormats tk
-             ) $ do
+    let config =
+          defaultTestConfig
+            { defaultDirectory = tempDir,
+              defaultSaveFormat = JPG
+            }
 
-            let cb = addDirectory tempDir 
-                        $ addSaveFormat PNG
-                        $ codeBlock tk (trivialContent tk)
-            _ <- runPlotM config $ make cb
+    -- Not all toolkits support both save formats
+    when
+      ( JPG `elem` supportedSaveFormats tk
+          && PNG `elem` supportedSaveFormats tk
+      )
+      $ do
+        let cb =
+              addDirectory tempDir $
+                addSaveFormat PNG $
+                  codeBlock tk (trivialContent tk)
+        _ <- runPlotM config $ make cb
 
-            numberPngFiles <-
-                length <$> filter (isExtensionOf (extension PNG)) <$>
-                listDirectory (defaultDirectory config)
-            numberJpgFiles <-
-                length <$> filter (isExtensionOf (extension JPG)) <$>
-                listDirectory (defaultDirectory config)
-            assertEqual "" numberPngFiles 1
-            assertEqual "" numberJpgFiles 0
+        numberPngFiles <-
+          length <$> filter (isExtensionOf (extension PNG))
+            <$> listDirectory (defaultDirectory config)
+        numberJpgFiles <-
+          length <$> filter (isExtensionOf (extension JPG))
+            <$> listDirectory (defaultDirectory config)
+        assertEqual "" numberPngFiles 1
+        assertEqual "" numberJpgFiles 0
 
 -------------------------------------------------------------------------------
 -- Test that Markdown bold formatting in captions is correctly rendered
 testMarkdownFormattingCaption1 :: Toolkit -> TestTree
 testMarkdownFormattingCaption1 tk =
-    testCase "appropriately parses captions 1" $ do
-        let postfix = unpack . cls $ tk
-        tempDir <- (</> "test-caption-parsing1-" <> postfix) <$> getTemporaryDirectory
-        ensureDirectoryExistsAndEmpty tempDir
+  testCase "appropriately parses captions 1" $ do
+    let postfix = unpack . cls $ tk
+    tempDir <- (</> "test-caption-parsing1-" <> postfix) <$> getTemporaryDirectory
+    ensureDirectoryExistsAndEmpty tempDir
 
-        -- Note that this test is fragile, in the sense that the expected result must be carefully
-        -- constructed
-        let expected = [B.Strong [B.Str "caption"]]
-            cb = addDirectory tempDir 
-                    $ addCaption "**caption**" 
-                    $ codeBlock tk (trivialContent tk)
-            fmt = B.Format "markdown"
-        result <- runPlotM (defaultTestConfig {captionFormat=fmt}) $ make cb
-        assertIsInfix expected (extractCaption result)
-    where
-        extractCaption (B.Para blocks) = extractImageCaption . head $ blocks
-        extractCaption _               = mempty
+    -- Note that this test is fragile, in the sense that the expected result must be carefully
+    -- constructed
+    let expected = [B.Strong [B.Str "caption"]]
+        cb =
+          addDirectory tempDir $
+            addCaption "**caption**" $
+              codeBlock tk (trivialContent tk)
+        fmt = B.Format "markdown"
+    result <- runPlotM (defaultTestConfig {captionFormat = fmt}) $ make cb
+    assertIsInfix expected (extractCaption result)
+  where
+    extractCaption (B.Para blocks) = extractImageCaption . head $ blocks
+    extractCaption _ = mempty
 
-        extractImageCaption (Image _ c _) = c
-        extractImageCaption _             = mempty
+    extractImageCaption (Image _ c _) = c
+    extractImageCaption _ = mempty
 
 -------------------------------------------------------------------------------
 -- Test that Markdown bold formatting in captions is correctly rendered
 testMarkdownFormattingCaption2 :: Toolkit -> TestTree
 testMarkdownFormattingCaption2 tk =
-    testCase "appropriately parses captions 2" $ do
-        let postfix = unpack . cls $ tk
-        tempDir <- (</> "test-caption-parsing2-" <> postfix) <$> getTemporaryDirectory
-        ensureDirectoryExistsAndEmpty tempDir
-
-        -- Note that this test is fragile, in the sense that the expected result must be carefully
-        -- constructed
-        let expected =  [Link ("",[],[]) [Str "title"] ("https://google.com","")]
-            cb = addDirectory tempDir 
-                    $ addCaption "[title](https://google.com)" 
-                    $ codeBlock tk (trivialContent tk)
-            fmt = B.Format "markdown"
-        result <- runPlotM (defaultTestConfig {captionFormat=fmt}) $ make cb
-        assertIsInfix expected (extractCaption result)
-    where
-        extractCaption (B.Para blocks) = extractImageCaption . head $ blocks
-        extractCaption _               = mempty
+  testCase "appropriately parses captions 2" $ do
+    let postfix = unpack . cls $ tk
+    tempDir <- (</> "test-caption-parsing2-" <> postfix) <$> getTemporaryDirectory
+    ensureDirectoryExistsAndEmpty tempDir
 
-        extractImageCaption (Image _ c _) = c
-        extractImageCaption _             = mempty
+    -- Note that this test is fragile, in the sense that the expected result must be carefully
+    -- constructed
+    let expected = [Link ("", [], []) [Str "title"] ("https://google.com", "")]
+        cb =
+          addDirectory tempDir $
+            addCaption "[title](https://google.com)" $
+              codeBlock tk (trivialContent tk)
+        fmt = B.Format "markdown"
+    result <- runPlotM (defaultTestConfig {captionFormat = fmt}) $ make cb
+    assertIsInfix expected (extractCaption result)
+  where
+    extractCaption (B.Para blocks) = extractImageCaption . head $ blocks
+    extractCaption _ = mempty
 
+    extractImageCaption (Image _ c _) = c
+    extractImageCaption _ = mempty
 
 -------------------------------------------------------------------------------
 -- Test that cleanOutpuDirs correctly cleans the output directory specified in a block.
 testCleanOutputDirs :: Toolkit -> TestTree
-testCleanOutputDirs tk = 
-    testCase "correctly cleans output directories" $ do
-        let postfix = unpack . cls $ tk
-        tempDir <- (</> "test-clean-output-dir" <> postfix) <$> getTemporaryDirectory
-        ensureDirectoryExistsAndEmpty tempDir
+testCleanOutputDirs tk =
+  testCase "correctly cleans output directories" $ do
+    let postfix = unpack . cls $ tk
+    tempDir <- (</> "test-clean-output-dir" <> postfix) <$> getTemporaryDirectory
+    ensureDirectoryExistsAndEmpty tempDir
 
-        let cb = addDirectory tempDir
-                    $ codeBlock tk (trivialContent tk)
-        
-        result <- runPlotM defaultTestConfig $ make cb
-        cleanedDirs <- cleanOutputDirs defaultTestConfig cb
+    let cb =
+          addDirectory tempDir $
+            codeBlock tk (trivialContent tk)
 
-        assertEqual "" [tempDir] cleanedDirs
+    result <- runPlotM defaultTestConfig $ make cb
+    cleanedDirs <- cleanOutputDirs defaultTestConfig cb
 
-        outputDirExists <- doesDirectoryExist tempDir
-        assertEqual "" outputDirExists False
+    assertEqual "" [tempDir] cleanedDirs
 
+    outputDirExists <- doesDirectoryExist tempDir
+    assertEqual "" outputDirExists False
 
 -------------------------------------------------------------------------------
 -- Test that toolkit checks failed when appropriate.
 testChecksFail :: Toolkit -> TestTree
-testChecksFail tk = 
-    testCase "script checks fail when appropriate" $ do
-        assertChecksFail tk
-    where
-        assertChecksFail Matplotlib = do
-            let postfix = unpack . cls $ tk
-            tempDir <- (</> "test-checks" <> postfix) <$> getTemporaryDirectory
-            ensureDirectoryExistsAndEmpty tempDir
-
-            let cb = addDirectory tempDir $ codeBlock Matplotlib "plt.show()"
-            result <- runPlotM defaultTestConfig $ makeEither cb
-            let expectedCheck :: Either PandocPlotError a -> Bool
-                expectedCheck (Left (ScriptChecksFailedError _)) = True
-                expectedCheck _ = False
-            assertBool "" (expectedCheck result)
-
-        assertChecksFail _          = assertEqual "Test skipped" True True
+testChecksFail tk =
+  testCase "script checks fail when appropriate" $ do
+    assertChecksFail tk
+  where
+    assertChecksFail Matplotlib = do
+      let postfix = unpack . cls $ tk
+      tempDir <- (</> "test-checks" <> postfix) <$> getTemporaryDirectory
+      ensureDirectoryExistsAndEmpty tempDir
 
+      let cb = addDirectory tempDir $ codeBlock Matplotlib "plt.show()"
+      result <- runPlotM defaultTestConfig $ makeEither cb
+      let expectedCheck :: Either PandocPlotError a -> Bool
+          expectedCheck (Left (ScriptChecksFailedError _)) = True
+          expectedCheck _ = False
+      assertBool "" (expectedCheck result)
+    assertChecksFail _ = assertEqual "Test skipped" True True
 
 codeBlock :: Toolkit -> Script -> Block
 codeBlock tk script = CodeBlock (mempty, [cls tk], mempty) script
 
-
 trivialContent :: Toolkit -> Script
-trivialContent Matplotlib   = "import matplotlib.pyplot as plt\n"
+trivialContent Matplotlib = "import matplotlib.pyplot as plt\n"
 trivialContent PlotlyPython = "import plotly.graph_objects as go; fit = go.Figure()\n"
-trivialContent PlotlyR      = "library(plotly)\nfig <- plot_ly(midwest, x = ~percollege, color = ~state, type = \"box\")"
-trivialContent Matlab       = "figure('visible', 'off')\n"
-trivialContent Mathematica  = "\n"
-trivialContent Octave       = "figure('visible', 'off')\nplot (-10:0.1:10);"
-trivialContent GGPlot2      = "library(ggplot2)\nggplot()\n"
-trivialContent GNUPlot      = "plot sin(x)"
-trivialContent Graphviz     = "digraph {A -> B [label=\"test\"];}"
-trivialContent Bokeh        = T.unlines [ "from bokeh.plotting import figure"
-                                        , "p = figure(title='simple line example')"
-                                        , "p.line([1,2,3,4], [5,6,7,8])"
-                                        ]
-trivialContent Plotsjl   = "using Plots; x = 1:10; y = rand(10); plot(x, y);"
-
+trivialContent PlotlyR = "library(plotly)\nfig <- plot_ly(midwest, x = ~percollege, color = ~state, type = \"box\")"
+trivialContent Matlab = "figure('visible', 'off')\n"
+trivialContent Mathematica = "\n"
+trivialContent Octave = "figure('visible', 'off')\nplot (-10:0.1:10);"
+trivialContent GGPlot2 = "library(ggplot2)\nggplot()\n"
+trivialContent GNUPlot = "plot sin(x)"
+trivialContent Graphviz = "digraph {A -> B [label=\"test\"];}"
+trivialContent Bokeh =
+  T.unlines
+    [ "from bokeh.plotting import figure",
+      "p = figure(title='simple line example')",
+      "p.line([1,2,3,4], [5,6,7,8])"
+    ]
+trivialContent Plotsjl = "using Plots; x = 1:10; y = rand(10); plot(x, y);"
 
 addCaption :: String -> Block -> Block
 addCaption caption (CodeBlock (id', cls, attrs) script) =
-    CodeBlock (id', cls, attrs ++ [(tshow CaptionK, pack caption)]) script
-
+  CodeBlock (id', cls, attrs ++ [(tshow CaptionK, pack caption)]) script
 
 addDirectory :: FilePath -> Block -> Block
 addDirectory dir (CodeBlock (id', cls, attrs) script) =
-    CodeBlock (id', cls, attrs ++ [(tshow DirectoryK, pack dir)]) script
-
+  CodeBlock (id', cls, attrs ++ [(tshow DirectoryK, pack dir)]) script
 
 addPreamble :: FilePath -> Block -> Block
 addPreamble inclusionPath (CodeBlock (id', cls, attrs) script) =
-    CodeBlock (id', cls, attrs ++ [(tshow PreambleK, pack inclusionPath)]) script
-
+  CodeBlock (id', cls, attrs ++ [(tshow PreambleK, pack inclusionPath)]) script
 
 addSaveFormat :: SaveFormat -> Block -> Block
 addSaveFormat saveFormat (CodeBlock (id', cls, attrs) script) =
-    CodeBlock (id', cls, attrs ++ [(tshow SaveFormatK, pack . extension $ saveFormat)]) script
-
+  CodeBlock (id', cls, attrs ++ [(tshow SaveFormatK, pack . extension $ saveFormat)]) script
 
 addDPI :: Int -> Block -> Block
 addDPI dpi (CodeBlock (id', cls, attrs) script) =
-    CodeBlock (id', cls, attrs ++ [(tshow DpiK, pack . show $ dpi)]) script
-
+  CodeBlock (id', cls, attrs ++ [(tshow DpiK, pack . show $ dpi)]) script
 
 addWithSource :: Bool -> Block -> Block
 addWithSource yn (CodeBlock (id', cls, attrs) script) =
-    CodeBlock (id', cls, attrs ++ [(tshow WithSourceK, pack . show $ yn)]) script
-
+  CodeBlock (id', cls, attrs ++ [(tshow WithSourceK, pack . show $ yn)]) script
 
 -- | Assert that a file exists
 assertFileExists :: HasCallStack => FilePath -> Assertion
 assertFileExists filepath = do
-    fileExists <- doesFileExist filepath
-    unless fileExists (assertFailure msg)
+  fileExists <- doesFileExist filepath
+  unless fileExists (assertFailure msg)
   where
     msg = mconcat ["File ", filepath, " does not exist."]
 
-
 -- | Assert not equal
 assertNotEqual :: (HasCallStack, Eq a, Show a) => String -> a -> a -> Assertion
-assertNotEqual msg expected actual = 
-    unless (expected /= actual) 
-        (assertFailure $ mconcat [msg, ": expected ", show expected, " but got ", show actual])
-
+assertNotEqual msg expected actual =
+  unless
+    (expected /= actual)
+    (assertFailure $ mconcat [msg, ": expected ", show expected, " but got ", show actual])
 
 -- | Not available with GHC < 8.4
 -- since this function was added in filepath-1.4.2
 -- but GHC 8.2.2 comes with filepath-1.4.1.2
 isExtensionOf :: String -> FilePath -> Bool
-isExtensionOf ext@('.':_) = isSuffixOf ext . takeExtensions
-isExtensionOf ext         = isSuffixOf ('.':ext) . takeExtensions
-
+isExtensionOf ext@('.' : _) = isSuffixOf ext . takeExtensions
+isExtensionOf ext = isSuffixOf ('.' : ext) . takeExtensions
 
 -- | Assert that the first list is contained,
 -- wholly and intact, anywhere within the second.
@@ -358,16 +387,14 @@   where
     msg = mconcat ["Expected ", show xs, " to be an infix of ", show ys]
 
-
 -- Ensure a directory is empty but exists.
 ensureDirectoryExistsAndEmpty :: FilePath -> IO ()
 ensureDirectoryExistsAndEmpty dir = do
-    exists <- doesDirectoryExist dir
-    if exists
-        then removePathForcibly dir
-        else return ()
-    createDirectory dir
-
+  exists <- doesDirectoryExist dir
+  if exists
+    then removePathForcibly dir
+    else return ()
+  createDirectory dir
 
 tshow :: Show a => a -> Text
 tshow = pack . show
tests/Main.hs view
@@ -1,100 +1,98 @@-{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE FlexibleContexts #-}
 {-# LANGUAGE OverloadedStrings #-}
 
-import           Control.Monad                    (forM_)
-
-import qualified Data.Map.Strict                  as Map
-import           Data.Text                        (Text, unpack)
-import qualified Data.Text                        as T
-
-import           Test.Tasty
-import           Test.Tasty.HUnit
-
-import qualified Text.Pandoc.Builder              as B
-import qualified Text.Pandoc.Definition           as B
-import           Text.Pandoc.JSON
-
-import           Common
-import           Text.Pandoc.Filter.Plot
-import           Text.Pandoc.Filter.Plot.Internal
+import Common
+import Control.Monad (forM_)
+import qualified Data.Map.Strict as Map
+import Data.Text (Text, unpack)
+import qualified Data.Text as T
+import Test.Tasty
+import Test.Tasty.HUnit
+import qualified Text.Pandoc.Builder as B
+import qualified Text.Pandoc.Definition as B
+import Text.Pandoc.Filter.Plot
+import Text.Pandoc.Filter.Plot.Internal
+import Text.Pandoc.JSON
 
 main :: IO ()
 main = do
-    available <- availableToolkits defaultTestConfig
-    unavailable <- unavailableToolkits defaultTestConfig
-    forM_ unavailable $ \tk -> do
-        putStrLn $ show tk <> " is not available. Its tests will be skipped."
-
-    defaultMain $ testGroup "All tests"
-        [ testGroup
-            "Configuration tests"
-            [ testEmptyConfiguration
-            , testExampleConfiguration
-            , testConfigurationPathMeta
-            ]        
-        , testGroup
-            "Parsing tests"
-            [ testCaptionReader ]
-        , testGroup
-            "HTML embedding tests"
-            [ testHtmlBodyEmbedding
-            , testHtmlEmbedding 
-            ]
-        , testGroup
-            "Toolkit tests"
-            (toolkitSuite <$> available)
-        ]
+  available <- availableToolkits defaultTestConfig
+  unavailable <- unavailableToolkits defaultTestConfig
+  forM_ unavailable $ \tk -> do
+    putStrLn $ show tk <> " is not available. Its tests will be skipped."
 
+  defaultMain $
+    testGroup
+      "All tests"
+      [ testGroup
+          "Configuration tests"
+          [ testEmptyConfiguration,
+            testExampleConfiguration,
+            testConfigurationPathMeta
+          ],
+        testGroup
+          "Parsing tests"
+          [testCaptionReader],
+        testGroup
+          "HTML embedding tests"
+          [ testHtmlBodyEmbedding,
+            testHtmlEmbedding
+          ],
+        testGroup
+          "Toolkit tests"
+          (toolkitSuite <$> available)
+      ]
 
 -- | Suite of tests that every renderer should pass
 toolkitSuite :: Toolkit -> TestTree
 toolkitSuite tk =
-    testGroup (show tk) $
-        [ testFileCreation
-        , testFileCreationPathWithSpaces
-        , testFileInclusion
-        , testSaveFormat
-        , testWithSource
-        , testOverrideConfiguration
-        , testMarkdownFormattingCaption1
-        , testMarkdownFormattingCaption2
-        , testCleanOutputDirs
-        , testChecksFail
-        ] <*> [tk]
-
+  testGroup (show tk) $
+    [ testFileCreation,
+      testFileCreationPathWithSpaces,
+      testFileInclusion,
+      testSaveFormat,
+      testWithSource,
+      testSourceLabel,
+      testOverrideConfiguration,
+      testMarkdownFormattingCaption1,
+      testMarkdownFormattingCaption2,
+      testCleanOutputDirs,
+      testChecksFail
+    ]
+      <*> [tk]
 
 testEmptyConfiguration :: TestTree
-testEmptyConfiguration = 
-    testCase "empty configuration is correctly parsed to default values" $ do
-        let config = defaultConfiguration
-
-        parsedConfig <- configuration "tests/fixtures/.empty-config.yml"
-        assertEqual "" config parsedConfig
+testEmptyConfiguration =
+  testCase "empty configuration is correctly parsed to default values" $ do
+    let config = defaultConfiguration
 
+    parsedConfig <- configuration "tests/fixtures/.empty-config.yml"
+    assertEqual "" config parsedConfig
 
 -- The example configuration is build by hand (to add comments)
--- and it is embedded into the executable. Therefore, we must make sure it 
+-- and it is embedded into the executable. Therefore, we must make sure it
 -- is correctly parsed (and is therefore valid.)
 testExampleConfiguration :: TestTree
-testExampleConfiguration = 
-    testCase "example configuration is correctly parsed" $ do
-        -- The example config reflects the Windows default
-        -- Therefore, we need to test against the Windows default,
-        -- even on other OSes
-        let config = defaultConfiguration { matplotlibExe = "python"
-                                          , plotlyPythonExe = "python"
-                                          , bokehExe = "python"
-                                          , defaultDependencies = ["file1.txt", "file2.txt"]
-                                          }
-
-        parsedConfig <- configuration "example-config.yml"
-        assertEqual "" config parsedConfig
+testExampleConfiguration =
+  testCase "example configuration is correctly parsed" $ do
+    -- The example config reflects the Windows default
+    -- Therefore, we need to test against the Windows default,
+    -- even on other OSes
+    let config =
+          defaultConfiguration
+            { matplotlibExe = "python",
+              plotlyPythonExe = "python",
+              bokehExe = "python",
+              defaultDependencies = ["file1.txt", "file2.txt"]
+            }
 
+    parsedConfig <- configuration "example-config.yml"
+    assertEqual "" config parsedConfig
 
 -- Test that the path to configuration in metadata is found correctly
 testConfigurationPathMeta :: TestTree
-testConfigurationPathMeta = 
-    testCase "Configuration path stored in metadata is correctly parsed" $ do
+testConfigurationPathMeta =
+  testCase "Configuration path stored in metadata is correctly parsed" $ do
     let configPath = "tests/fixtures/.config-meta.yml"
         meta = B.Meta $ Map.fromList [("plot-configuration", B.MetaString configPath)]
 
@@ -102,58 +100,59 @@     expected <- configuration (unpack configPath)
     assertEqual "" expected parsedConfig
 
-
 testCaptionReader :: TestTree
-testCaptionReader = 
-    testCase "caption is parsed in the same way as input document format" $ do
-        -- Note that this test is fragile, in the sense that the expected result must be carefully
-        -- constructed
-        let caption="Here is a [link](https://www.google.com) in a caption."
-            expected = Just $ [Str "Here",Space,Str "is",Space,Str "a",Space,Link ("",[],[]) [Str "link"] ("https://www.google.com",""),Space,Str "in",Space,Str "a",Space,Str "caption."]
-            fmt = B.Format "markdown+tex_math_dollars"
-            parsed = captionReader fmt caption
-
-        assertEqual "" expected parsed
+testCaptionReader =
+  testCase "caption is parsed in the same way as input document format" $ do
+    -- Note that this test is fragile, in the sense that the expected result must be carefully
+    -- constructed
+    let caption = "Here is a [link](https://www.google.com) in a caption."
+        expected = Just $ [Str "Here", Space, Str "is", Space, Str "a", Space, Link ("", [], []) [Str "link"] ("https://www.google.com", ""), Space, Str "in", Space, Str "a", Space, Str "caption."]
+        fmt = B.Format "markdown+tex_math_dollars"
+        parsed = captionReader fmt caption
 
+    assertEqual "" expected parsed
 
 testHtmlBodyEmbedding :: TestTree
-testHtmlBodyEmbedding = 
-    testCase "HTML body can be extracted from file" $ do
-        let html=T.unlines ["<!DOCTYPE html>"
-                           ,"<html lang=\"en\">"
-                           ,"  <head>"
-                           ,"    <meta charset=\"utf-8\">"
-                           ,"    <title>title</title>"
-                           ,"    <link rel=\"stylesheet\" href=\"style.css\">"
-                           ,"  </head>"
-                           ,"  <body>"
-                           ,"    <p>Hello</p>"
-                           ,"  </body>"
-                           ,"</html>"
-                           ]
-            extracted = extractPlot html
-            expected = "\n    <p>Hello</p>"
-
-        assertEqual "" expected extracted 
+testHtmlBodyEmbedding =
+  testCase "HTML body can be extracted from file" $ do
+    let html =
+          T.unlines
+            [ "<!DOCTYPE html>",
+              "<html lang=\"en\">",
+              "  <head>",
+              "    <meta charset=\"utf-8\">",
+              "    <title>title</title>",
+              "    <link rel=\"stylesheet\" href=\"style.css\">",
+              "  </head>",
+              "  <body>",
+              "    <p>Hello</p>",
+              "  </body>",
+              "</html>"
+            ]
+        extracted = extractPlot html
+        expected = "\n    <p>Hello</p>"
 
+    assertEqual "" expected extracted
 
 testHtmlEmbedding :: TestTree
-testHtmlEmbedding = 
-    testCase "HTML body and head scripts can be extracted from file" $ do
-        let html=T.unlines ["<!DOCTYPE html>"
-                           ,"<html lang=\"en\">"
-                           ,"  <head>"
-                           ,"    <meta charset=\"utf-8\">"
-                           ,"    <title>title</title>"
-                           ,"    <link rel=\"stylesheet\" href=\"style.css\">"
-                           ,"    <script src=\"script.js\"></script>"
-                           ,"  </head>"
-                           ,"  <body>"
-                           ,"    <p>Hello</p>"
-                           ,"  </body>"
-                           ,"</html>"
-                           ]
-            extracted = extractPlot html
-            expected = "<script src=\"script.js\" defer></script>\n    <p>Hello</p>"
+testHtmlEmbedding =
+  testCase "HTML body and head scripts can be extracted from file" $ do
+    let html =
+          T.unlines
+            [ "<!DOCTYPE html>",
+              "<html lang=\"en\">",
+              "  <head>",
+              "    <meta charset=\"utf-8\">",
+              "    <title>title</title>",
+              "    <link rel=\"stylesheet\" href=\"style.css\">",
+              "    <script src=\"script.js\"></script>",
+              "  </head>",
+              "  <body>",
+              "    <p>Hello</p>",
+              "  </body>",
+              "</html>"
+            ]
+        extracted = extractPlot html
+        expected = "<script src=\"script.js\" defer></script>\n    <p>Hello</p>"
 
-        assertEqual "" expected extracted+    assertEqual "" expected extracted