packages feed

pandoc-plot 1.1.1 → 1.2.0

raw patch · 20 files changed

+321/−152 lines, 20 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Text.Pandoc.Filter.Plot.Internal: [envFormat] :: RuntimeEnv -> Maybe Format
- Text.Pandoc.Filter.Plot.Internal: RuntimeEnv :: Configuration -> Logger -> FilePath -> RuntimeEnv
+ Text.Pandoc.Filter.Plot.Internal: RuntimeEnv :: Maybe Format -> Configuration -> Logger -> FilePath -> RuntimeEnv
- Text.Pandoc.Filter.Plot.Internal: debug :: Text -> PlotM ()
+ Text.Pandoc.Filter.Plot.Internal: debug :: (MonadLogger m, MonadIO m) => Text -> m ()
- Text.Pandoc.Filter.Plot.Internal: err :: Text -> PlotM ()
+ Text.Pandoc.Filter.Plot.Internal: err :: (MonadLogger m, MonadIO m) => Text -> m ()
- Text.Pandoc.Filter.Plot.Internal: info :: Text -> PlotM ()
+ Text.Pandoc.Filter.Plot.Internal: info :: (MonadLogger m, MonadIO m) => Text -> m ()
- Text.Pandoc.Filter.Plot.Internal: runPlotM :: Configuration -> PlotM a -> IO a
+ Text.Pandoc.Filter.Plot.Internal: runPlotM :: Maybe Format -> Configuration -> PlotM a -> IO a
- Text.Pandoc.Filter.Plot.Internal: type PlotM a = StateT PlotState (ReaderT RuntimeEnv IO) a
+ Text.Pandoc.Filter.Plot.Internal: type PlotM = StateT PlotState (ReaderT RuntimeEnv IO)
- Text.Pandoc.Filter.Plot.Internal: warning :: Text -> PlotM ()
+ Text.Pandoc.Filter.Plot.Internal: warning :: (MonadLogger m, MonadIO m) => Text -> m ()

Files

CHANGELOG.md view
@@ -2,6 +2,21 @@ 
 pandoc-plot uses [Semantic Versioning](http://semver.org/spec/v2.0.0.html)
 
+Release 1.2.0
+-------------
+
+* Fixed an issue where code blocks nested in other structures were detected properly. For example, in the following LaTeX snippet, plots would not be detected properly:
+```latex
+\begin{column}
+  \begin{minted}[]{matplotlib}
+  ...
+  \end{minted}
+\end{column}
+```
+Nested figures are not correctly identified.
+
+* The executables are now built with Pandoc 2.13. Pandoc 2.11 and Pandoc 2.12 are still supported.
+
 Release 1.1.1
 -------------
 
README.md view
@@ -97,6 +97,16 @@ conda install -c conda-forge pandoc-plot
 ```
 
+### Homebrew
+
+`pandoc-plot` is available as a package via [`Homebrew`](https://brew.sh/). [Click here to see the package page](https://formulae.brew.sh/formula/pandoc-plot#default). 
+
+To install:
+
+```sh
+brew install pandoc-plot
+```
+
 ### winget
 
 You can install `pandoc-plot` from the [Windows Package
executable/ExampleConfig.hs view
@@ -2,16 +2,23 @@ 
 module ExampleConfig (embedExampleConfig) where
 
-import Data.String
+import Data.Functor ((<&>))
+import Data.String (IsString (fromString))
 import Data.Text (unpack)
 import qualified Data.Text.IO as TIO
 import Language.Haskell.TH.Syntax
+  ( Exp (AppE, LitE, VarE),
+    Lit (StringL),
+    Q,
+    Quasi (qAddDependentFile),
+    runIO,
+  )
 
 docFile :: FilePath
 docFile = "example-config.yml"
 
 readDocFile :: IO String
-readDocFile = TIO.readFile docFile >>= return . unpack
+readDocFile = TIO.readFile docFile <&> unpack
 
 embedExampleConfig :: Q Exp
 embedExampleConfig = do
executable/Main.hs view
@@ -7,7 +7,7 @@ 
 module Main where
 
-import Control.Monad (join, msum, when)
+import Control.Monad (join, msum, void, when)
 import Data.List (intersperse, (\\))
 import Data.Maybe (fromJust)
 import Data.Text (unpack)
@@ -16,10 +16,32 @@ import qualified Data.Version as V
 import ExampleConfig (embedExampleConfig)
 import GHC.IO.Encoding (setLocaleEncoding, utf8)
-import GitHash as Git
+import GitHash as Git (giHash, tGitInfoCwdTry)
 import ManPage (embedManualHtml)
 import OpenFile (openFile)
 import Options.Applicative
+  ( Alternative ((<|>)),
+    Parser,
+    command,
+    execParser,
+    flag,
+    footerDoc,
+    fullDesc,
+    header,
+    help,
+    helper,
+    info,
+    long,
+    metavar,
+    optional,
+    progDesc,
+    short,
+    strArgument,
+    strOption,
+    subparser,
+    value,
+    (<**>),
+  )
 import qualified Options.Applicative.Help.Pretty as P
 import System.Directory (doesFileExist, getTemporaryDirectory)
 import System.Environment (lookupEnv)
@@ -52,6 +74,10 @@ -- The difference between commands and flags is that commands require knowledge of
 -- the configuration, while flags only display static information.
 
+-- Please note that for some reason, makeVersion [2, 11, 0, 0] > makeVersion [2, 11]
+minimumPandocVersion :: V.Version
+minimumPandocVersion = V.makeVersion [2, 11]
+
 data Command
   = Clean (Maybe FilePath) FilePath
   | WriteConfig FilePath
@@ -198,17 +224,15 @@ -- 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
+  -- We can use the former to ensure that people are not
+  -- using an old version of pandoc
   pandocV <- lookupEnv "PANDOC_VERSION"
   case pandocV >>= readVersion of
     Nothing -> return True
     Just v ->
-      if (v < minimumPandocVersion)
+      if v < minimumPandocVersion
         then do
           hPutStrLn stderr $
             mconcat
@@ -234,12 +258,12 @@ 
 showFullVersion :: IO ()
 showFullVersion = do
-  putStrLn $ "pandoc-plot " <> (V.showVersion pandocPlotVersion)
+  putStrLn $ "pandoc-plot " <> V.showVersion pandocPlotVersion
   putStrLn $ "Git revision " <> gitrev
   putStrLn $
     mconcat
       [ "Compiled with pandoc ",
-        (unpack pandocVersion),
+        unpack pandocVersion,
         " and pandoc-types ",
         V.showVersion pandocTypesVersion,
         " using GHC ",
@@ -252,23 +276,21 @@ 
 showAvailableToolkits :: Maybe FilePath -> IO ()
 showAvailableToolkits mfp = do
-  c <- case mfp of
-    Nothing -> localConfig
-    Just fp -> configuration fp
+  c <- maybe localConfig configuration mfp
 
   putStrLn "\nAVAILABLE TOOLKITS\n"
   available <- availableToolkits c
-  return available >>= mapM_ (availToolkitInfo c)
+  mapM_ (availToolkitInfo c) available
   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)
+  mapM_ (unavailToolkitInfo c) unavailable
   where
     toolkitInfo avail conf tk = do
       putStrLn $ "Toolkit: " <> show tk
       when avail $ do
-        Executable dir exe <- fmap fromJust $ runPlotM conf $ executable tk
+        Executable dir exe <- fmap fromJust $ runPlotM Nothing 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)
@@ -291,7 +313,7 @@   --   (3) local .pandoc-plot.yml
   --   (4) default config
   conf <- maybe localConfig configuration $ firstJusts [configurationPathMeta doc, mfp]
-  cleanOutputDirs conf doc >> return ()
+  void (cleanOutputDirs conf doc)
   where
     firstJusts :: [Maybe a] -> Maybe a
     firstJusts = msum
executable/ManPage.hs view
@@ -11,6 +11,12 @@ import Data.Text (unpack)
 import qualified Data.Text.IO as TIO
 import Language.Haskell.TH.Syntax
+  ( Exp (AppE, LitE, VarE),
+    Lit (StringL),
+    Q,
+    Quasi (qAddDependentFile),
+    runIO,
+  )
 import System.Directory (doesFileExist)
 import System.FilePath ((</>))
 
pandoc-plot.cabal view
@@ -1,6 +1,6 @@ cabal-version:  2.2
 name:           pandoc-plot
-version:        1.1.1
+version:        1.2.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 
src/Text/Pandoc/Filter/Plot.hs view
@@ -16,21 +16,9 @@ -- 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;
+-- attribute will trigger the filter, e.g. @matplotlib@ for matplotlib-based Python plots.
 --
--- For example, in Markdown:
+-- Here is an example, in Markdown, for a plot in MATLAB:
 --
 -- @
 --     This is a paragraph.
@@ -145,6 +133,7 @@     unavailableToolkits,
     whenStrict,
   )
+import Text.Pandoc.Walk (walkM)
 
 -- | Walk over an entire Pandoc document, transforming appropriate code blocks
 -- into figures. This function will operate on blocks in parallel if possible.
@@ -160,7 +149,8 @@   IO Pandoc
 plotTransform conf (Pandoc meta blocks) = do
   maxproc <- getNumCapabilities
-  runPlotM conf $ do
+  -- TODO: make filter aware of target format
+  runPlotM Nothing conf $ do
     debug $ mconcat ["Starting a new run, utilizing at most ", pack . show $ maxproc, " processes."]
     mapConcurrentlyN maxproc make blocks <&> Pandoc meta
 
@@ -172,8 +162,10 @@ 
 -- | 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 unless running in strict mode.
+--
+-- New in version 1.2.0: this function will detect nested code blocks, for example in @Div@ blocks.
 make :: Block -> PlotM Block
-make blk = either (onError blk) return =<< makeEither blk
+make = walkM $ \blk -> either (onError blk) return =<< makeEither blk
   where
     onError :: Block -> PandocPlotError -> PlotM Block
     onError b e = do
@@ -181,6 +173,8 @@       return b
 
 -- | Try to process the block with `pandoc-plot`, documenting the error.
+-- This function does not transform code blocks nested in
+-- other blocks (e.g. @Divs@)
 makeEither :: Block -> PlotM (Either PandocPlotError Block)
 makeEither block =
   parseFigureSpec block
src/Text/Pandoc/Filter/Plot/Clean.hs view
@@ -29,7 +29,7 @@ import System.Directory (removePathForcibly)
 import System.FilePath (takeExtension)
 import Text.Pandoc.Class (runIO)
-import Text.Pandoc.Definition
+import Text.Pandoc.Definition (Block, Pandoc)
 import Text.Pandoc.Error (handleError)
 import Text.Pandoc.Filter.Plot.Monad
 import Text.Pandoc.Filter.Plot.Parse
@@ -48,7 +48,7 @@   b ->
   IO [FilePath]
 cleanOutputDirs conf doc = do
-  dirs <- runPlotM conf . cleanOutputDirsM $ doc
+  dirs <- runPlotM Nothing 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
src/Text/Pandoc/Filter/Plot/Configuration.hs view
@@ -213,89 +213,89 @@ 
 instance FromJSON LoggingPrecursor where
   parseJSON (Object v) =
-    LoggingPrecursor <$> v .:? "verbosity" .!= (logVerbosity defaultConfiguration)
+    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)
-      <*> v .:? (tshow CommandLineArgsK) .!= (matplotlibCmdArgs defaultConfiguration)
+      <$> v .:? tshow PreambleK
+      <*> v .:? tshow MatplotlibTightBBoxK .!= matplotlibTightBBox defaultConfiguration
+      <*> v .:? tshow MatplotlibTransparentK .!= matplotlibTransparent defaultConfiguration
+      <*> v .:? tshow ExecutableK .!= matplotlibExe defaultConfiguration
+      <*> v .:? tshow CommandLineArgsK .!= matplotlibCmdArgs 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) <*> v .:? (tshow CommandLineArgsK) .!= (matlabCmdArgs defaultConfiguration)
+  parseJSON (Object v) = MatlabPrecursor <$> v .:? tshow PreambleK <*> v .:? tshow ExecutableK .!= matlabExe defaultConfiguration <*> v .:? tshow CommandLineArgsK .!= matlabCmdArgs 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) <*> v .:? (tshow CommandLineArgsK) .!= (plotlyPythonCmdArgs defaultConfiguration)
+  parseJSON (Object v) = PlotlyPythonPrecursor <$> v .:? tshow PreambleK <*> v .:? tshow ExecutableK .!= plotlyPythonExe defaultConfiguration <*> v .:? tshow CommandLineArgsK .!= plotlyPythonCmdArgs 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) <*> v .:? (tshow CommandLineArgsK) .!= (plotlyRCmdArgs defaultConfiguration)
+  parseJSON (Object v) = PlotlyRPrecursor <$> v .:? tshow PreambleK <*> v .:? tshow ExecutableK .!= plotlyRExe defaultConfiguration <*> v .:? tshow CommandLineArgsK .!= plotlyRCmdArgs 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) <*> v .:? (tshow CommandLineArgsK) .!= (mathematicaCmdArgs defaultConfiguration)
+  parseJSON (Object v) = MathematicaPrecursor <$> v .:? tshow PreambleK <*> v .:? tshow ExecutableK .!= mathematicaExe defaultConfiguration <*> v .:? tshow CommandLineArgsK .!= mathematicaCmdArgs 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) <*> v .:? (tshow CommandLineArgsK) .!= (octaveCmdArgs defaultConfiguration)
+  parseJSON (Object v) = OctavePrecursor <$> v .:? tshow PreambleK <*> v .:? tshow ExecutableK .!= octaveExe defaultConfiguration <*> v .:? tshow CommandLineArgsK .!= octaveCmdArgs 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) <*> v .:? (tshow CommandLineArgsK) .!= (ggplot2CmdArgs defaultConfiguration)
+  parseJSON (Object v) = GGPlot2Precursor <$> v .:? tshow PreambleK <*> v .:? tshow ExecutableK .!= ggplot2Exe defaultConfiguration <*> v .:? tshow CommandLineArgsK .!= ggplot2CmdArgs 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) <*> v .:? (tshow CommandLineArgsK) .!= (gnuplotCmdArgs defaultConfiguration)
+  parseJSON (Object v) = GNUPlotPrecursor <$> v .:? tshow PreambleK <*> v .:? tshow ExecutableK .!= gnuplotExe defaultConfiguration <*> v .:? tshow CommandLineArgsK .!= gnuplotCmdArgs 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) <*> v .:? (tshow CommandLineArgsK) .!= (graphvizCmdArgs defaultConfiguration)
+  parseJSON (Object v) = GraphvizPrecursor <$> v .:? tshow PreambleK <*> v .:? tshow ExecutableK .!= graphvizExe defaultConfiguration <*> v .:? tshow CommandLineArgsK .!= graphvizCmdArgs 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) <*> v .:? (tshow CommandLineArgsK) .!= (bokehCmdArgs defaultConfiguration)
+  parseJSON (Object v) = BokehPrecursor <$> v .:? tshow PreambleK <*> v .:? tshow ExecutableK .!= bokehExe defaultConfiguration <*> v .:? tshow CommandLineArgsK .!= bokehCmdArgs 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) <*> v .:? (tshow CommandLineArgsK) .!= (plotsjlCmdArgs defaultConfiguration)
+  parseJSON (Object v) = PlotsjlPrecursor <$> v .:? tshow PreambleK <*> v .:? tshow ExecutableK .!= plotsjlExe defaultConfiguration <*> v .:? tshow CommandLineArgsK .!= plotsjlCmdArgs defaultConfiguration
   parseJSON _ = fail $ mconcat ["Could not parse ", show Plotsjl, " configuration."]
 
 instance FromJSON PlantUMLPrecursor where
-  parseJSON (Object v) = PlantUMLPrecursor <$> v .:? (tshow PreambleK) <*> v .:? (tshow ExecutableK) .!= (plantumlExe defaultConfiguration) <*> v .:? (tshow CommandLineArgsK) .!= (plantumlCmdArgs defaultConfiguration)
+  parseJSON (Object v) = PlantUMLPrecursor <$> v .:? tshow PreambleK <*> v .:? tshow ExecutableK .!= plantumlExe defaultConfiguration <*> v .:? tshow CommandLineArgsK .!= plantumlCmdArgs defaultConfiguration
   parseJSON _ = fail $ mconcat ["Could not parse ", show PlantUML, " configuration."]
 
 instance FromJSON ConfigPrecursor where
-  parseJSON (Null) = return defaultConfigPrecursor -- In case of empty file
+  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)
-    _strictMode <- v .:? tshow StrictModeK .!= (_strictMode defaultConfigPrecursor)
+    _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
+    _strictMode <- v .:? tshow StrictModeK .!= _strictMode defaultConfigPrecursor
     _logPrec <- v .:? "logging" .!= _logPrec 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
-    _plantumlPrec <- v .:? (cls PlantUML) .!= _plantumlPrec 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
+    _plantumlPrec <- v .:? cls PlantUML .!= _plantumlPrec defaultConfigPrecursor
 
     return $ ConfigPrecursor {..}
   parseJSON _ = fail "Could not parse configuration."
src/Text/Pandoc/Filter/Plot/Embed.hs view
@@ -22,6 +22,16 @@ import Data.Text (Text, pack)
 import qualified Data.Text.IO as T
 import Text.HTML.TagSoup
+  ( Attribute,
+    Tag (TagClose, TagOpen),
+    canonicalizeTags,
+    parseOptionsFast,
+    parseTagsOptions,
+    partitions,
+    renderTags,
+    (~/=),
+    (~==),
+  )
 import Text.Pandoc.Builder
   ( Inlines,
     fromList,
@@ -77,6 +87,28 @@   return . head . toList . para $
     imageWith as (pack fp) "fig:" caption'
 
+-- TODO: also add the case where SVG plots can be
+--       embedded in HTML output
+-- embeddedSVGBlock ::
+--   Attr ->
+--   FilePath ->
+--   Inlines ->
+--   PlotM Block
+-- embeddedSVGBlock _ fp caption' = do
+--   svgsource <- liftIO $ T.readFile fp
+--   renderedCaption <- writeHtml caption'
+--   return $
+--     RawBlock
+--       "html5"
+--       [st|
+-- <figure>
+--     <svg>
+--     #{svgsource}
+--     </svg>
+--     <figcaption>#{renderedCaption}</figcaption>
+-- </figure>
+--     |]
+
 interactiveBlock ::
   Attr ->
   FilePath ->
@@ -112,7 +144,7 @@ extractPlot :: Text -> Text
 extractPlot t =
   let tags = canonicalizeTags $ parseTagsOptions parseOptionsFast t
-      extracted = headScripts tags <> [inside "body" $ tags]
+      extracted = headScripts tags <> [inside "body" tags]
    in mconcat $ renderTags <$> (deferScripts <$> extracted)
   where
     headScripts = partitions (~== ("<script>" :: String)) . inside "head"
@@ -131,7 +163,7 @@ fromTag :: Tag Text -> Maybe ScriptTag
 fromTag (TagOpen "script" attrs) =
   Just $
-    if "src" `elem` (fst . unzip $ attrs)
+    if "src" `elem` map fst attrs
       then ExternalScript attrs
       else InlineScript attrs
 fromTag _ = Nothing
src/Text/Pandoc/Filter/Plot/Monad.hs view
@@ -1,4 +1,6 @@+{-# LANGUAGE FlexibleInstances #-}
 {-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE TypeSynonymInstances #-}
 
 -- |
 -- Module      : $header$
@@ -54,12 +56,26 @@ where
 
 import Control.Concurrent.Async.Lifted (mapConcurrently)
-import Control.Concurrent.Chan (writeChan)
-import Control.Concurrent.MVar
+import Control.Concurrent.MVar (MVar, newMVar, putMVar, takeMVar)
 import Control.Concurrent.QSemN
+  ( QSemN,
+    newQSemN,
+    signalQSemN,
+    waitQSemN,
+  )
 import Control.Exception.Lifted (bracket, bracket_)
 import Control.Monad.Reader
+  ( MonadIO (liftIO),
+    MonadReader (ask, local),
+    ReaderT (runReaderT),
+    asks,
+    when,
+  )
 import Control.Monad.State.Strict
+  ( MonadState (get, put),
+    StateT,
+    evalStateT,
+  )
 import Data.ByteString.Lazy (toStrict)
 import Data.Functor ((<&>))
 import Data.Hashable (hash)
@@ -89,30 +105,46 @@     shell,
   )
 import Text.Pandoc.Definition (Format (..))
-import Text.Pandoc.Filter.Plot.Monad.Logging as Log
+import Text.Pandoc.Filter.Plot.Monad.Logging
+  ( LogSink (..),
+    Logger (lVerbosity),
+    MonadLogger (..),
+    Verbosity (..),
+    debug,
+    err,
+    info,
+    strict,
+    terminateLogging,
+    warning,
+    withLogger,
+  )
 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
+type PlotM = StateT PlotState (ReaderT RuntimeEnv IO)
 
+instance MonadLogger PlotM where
+  askLogger = asks envLogger
+
 data RuntimeEnv = RuntimeEnv
-  { envConfig :: Configuration,
+  { envFormat :: Maybe Format, -- pandoc output format
+    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 f c l d) -> RuntimeEnv f 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
+runPlotM :: Maybe Format -> Configuration -> PlotM a -> IO a
+runPlotM fmt conf v = do
   cwd <- getCurrentDirectory
   st <-
     PlotState <$> newMVar mempty
@@ -120,7 +152,7 @@   let verbosity = logVerbosity conf
       sink = logSink conf
   withLogger verbosity sink $
-    \logger -> runReaderT (evalStateT v st) (RuntimeEnv conf logger cwd)
+    \logger -> runReaderT (evalStateT v st) (RuntimeEnv fmt conf logger cwd)
 
 -- | maps a function, performing at most @N@ actions concurrently.
 mapConcurrentlyN :: Traversable t => Int -> (a -> PlotM b) -> t a -> PlotM (t b)
@@ -132,27 +164,6 @@     with :: QSemN -> PlotM a -> PlotM a
     with s = bracket_ (liftIO $ waitQSemN s 1) (liftIO $ signalQSemN s 1)
 
-debug, err, warning, info :: Text -> PlotM ()
-debug = log "[pandoc-plot] DEBUG | " Debug
-err = log "[pandoc-plot] ERROR | " Error
-warning = log "[pandoc-plot] WARN  | " Warning
-info = log "[pandoc-plot] INFO  | " Info
-
--- | 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"))
-
 -- | Run a command within the @PlotM@ monad. Stderr stream
 -- is read and decoded, while Stdout is ignored.
 -- Logging happens at the debug level if the command succeeds, or at
@@ -216,11 +227,9 @@ -- | Throw an error that halts the execution of pandoc-plot due to a strict-mode.
 throwStrictError :: Text -> PlotM ()
 throwStrictError msg = do
-  logger <- asks envLogger
-  log "[pandoc-plot] STRICT MODE | " Error msg
-  liftIO $ do
-    terminateLogging logger
-    exitFailure
+  strict msg
+  logger <- askLogger
+  liftIO $ terminateLogging logger >> exitFailure
 
 -- | Conditional execution of a PlotM action if pandoc-plot is
 -- run in strict mode.
src/Text/Pandoc/Filter/Plot/Monad/Logging.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
 
@@ -11,25 +12,36 @@ --
 -- Logging primitives.
 module Text.Pandoc.Filter.Plot.Monad.Logging
-  ( Verbosity (..),
+  ( MonadLogger (..),
+    Verbosity (..),
     LogSink (..),
     Logger (..),
     withLogger,
     terminateLogging,
+
+    -- * Logging messages
+    debug,
+    err,
+    warning,
+    info,
+    strict,
   )
 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, void)
+import Control.Monad (forM_, forever, void, when)
+import Control.Monad.IO.Class (MonadIO (..))
 import Data.Char (toLower)
 import Data.List (intercalate)
 import Data.String (IsString (..))
 import Data.Text (Text, unpack)
-import Data.Text.IO as TIO
+import qualified Data.Text as T
+import Data.Text.IO as TIO (appendFile, hPutStr)
 import Data.Yaml (FromJSON (parseJSON), Value (String))
 import System.IO (stderr)
+import Prelude hiding (log)
 
 -- | Verbosity of the logger.
 data Verbosity
@@ -55,12 +67,19 @@ 
 -- | 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, -- Verbosity level below which to ignore messages
+    lChannel :: Chan Command, -- Queue of logging commands
+    lSink :: Text -> IO (), -- Action to perform with log messages
+    lSync :: MVar () -- Synchronization variable
   }
 
+data Command
+  = LogMessage Text
+  | EndLogging
+
+class Monad m => MonadLogger m where
+  askLogger :: m Logger
+
 -- | Ensure that all log messages are flushed, and stop logging
 terminateLogging :: Logger -> IO ()
 terminateLogging logger = do
@@ -68,7 +87,7 @@   -- 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
+  writeChan (lChannel logger) EndLogging
   void $ takeMVar (lSync logger)
 
 -- | Perform an IO action with a logger. Using this function
@@ -76,8 +95,8 @@ withLogger :: Verbosity -> LogSink -> (Logger -> IO a) -> IO a
 withLogger v s f = do
   logger <-
-    Logger <$> pure v
-      <*> newChan
+    Logger v
+      <$> newChan
       <*> pure (sink s)
       <*> newEmptyMVar
 
@@ -87,7 +106,9 @@     forkIO $
       forever $
         readChan (lChannel logger)
-          >>= maybe (putMVar (lSync logger) ()) (lSink logger)
+          >>= \case
+            EndLogging -> putMVar (lSync logger) ()
+            LogMessage t -> lSink logger t
 
   result <- f logger
 
@@ -99,6 +120,26 @@     sink StdErr = TIO.hPutStr stderr
     sink (LogFile fp) = TIO.appendFile fp
 
+-- | General purpose logging function.
+log ::
+  (MonadLogger m, MonadIO m) =>
+  Text -> -- Header
+  Verbosity ->
+  Text ->
+  m ()
+log h v t = do
+  logger <- askLogger
+  when (v >= lVerbosity logger) $
+    liftIO $ do
+      forM_ (T.lines t) $ \l -> writeChan (lChannel logger) (LogMessage (h <> l <> "\n"))
+
+debug, err, strict, warning, info :: (MonadLogger m, MonadIO m) => Text -> m ()
+debug = log "[pandoc-plot] DEBUG | " Debug
+err = log "[pandoc-plot] ERROR | " Error
+strict = log "[pandoc-plot] STRICT MODE | " Error
+warning = log "[pandoc-plot] WARN  | " Warning
+info = log "[pandoc-plot] INFO  | " Info
+
 instance IsString Verbosity where
   fromString s
     | ls == "silent" = Silent
@@ -110,9 +151,11 @@     where
       ls = toLower <$> s
       choices =
-        intercalate ", " $
-          fmap (fmap toLower . show) $
-            enumFromTo minBound (maxBound :: Verbosity)
+        intercalate
+          ", "
+          ( fmap toLower . show
+              <$> enumFromTo minBound (maxBound :: Verbosity)
+          )
 
 instance FromJSON Verbosity where
   parseJSON (String t) = pure $ fromString . unpack $ t
src/Text/Pandoc/Filter/Plot/Monad/Types.hs view
@@ -225,13 +225,13 @@       errorWithoutStackTrace $
         mconcat
           [ s,
-            " is not one of valid save format : ",
+            " is not one of the valid save formats : ",
             mconcat $ intersperse ", " $ show <$> saveFormats
           ]
     where
       saveFormats = enumFromTo minBound maxBound :: [SaveFormat]
 
-instance FromJSON SaveFormat -- TODO: test this parsing
+instance FromJSON SaveFormat
 
 instance ToJSON SaveFormat where
   toJSON = toJSON . extension
src/Text/Pandoc/Filter/Plot/Renderers.hs view
@@ -27,9 +27,11 @@ where
 
 import Control.Concurrent.Async.Lifted (forConcurrently)
-import Control.Concurrent.MVar
+import Control.Concurrent.MVar (putMVar, takeMVar)
 import Control.Monad.Reader (local)
 import Control.Monad.State.Strict
+  ( MonadState (get, put),
+  )
 import Data.List ((\\))
 import Data.Map.Strict (Map)
 import qualified Data.Map.Strict as M
@@ -122,12 +124,12 @@ -- | 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
+availableToolkits conf = runPlotM Nothing 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
+unavailableToolkits conf = runPlotM Nothing conf unavailableToolkitsM
 
 -- | Monadic version of @availableToolkits@.
 --
@@ -142,7 +144,7 @@         else return Nothing
     return $ catMaybes mtks
   where
-    asNonStrict = local (\(RuntimeEnv c l d) -> RuntimeEnv c {strictMode = False} l d)
+    asNonStrict = local (\(RuntimeEnv f c l d) -> RuntimeEnv f c {strictMode = False} l d)
 
 -- | Monadic version of @unavailableToolkits@
 unavailableToolkitsM :: PlotM [Toolkit]
src/Text/Pandoc/Filter/Plot/Renderers/Prelude.hs view
@@ -22,6 +22,7 @@   )
 where
 
+import Data.Functor ((<&>))
 import Data.Maybe (isJust)
 import Data.Text (Text, unpack)
 import System.Directory (findExecutable)
@@ -42,7 +43,7 @@ 
 -- | Checks that an executable is available on path, at all.
 existsOnPath :: FilePath -> IO Bool
-existsOnPath fp = findExecutable fp >>= fmap isJust . return
+existsOnPath fp = findExecutable fp <&> isJust
 
 -- | A shortcut to append capture script fragments to scripts
 appendCapture ::
src/Text/Pandoc/Filter/Plot/Scripting.hs view
@@ -20,7 +20,6 @@   )
 where
 
-import Control.Monad.Reader
 import Data.Default (def)
 import Data.Functor.Identity (Identity (..))
 import Data.Hashable (hash)
@@ -42,7 +41,7 @@     (</>),
   )
 import Text.Pandoc.Class (runPure)
-import Text.Pandoc.Definition
+import Text.Pandoc.Definition (Block (CodeBlock), Pandoc (Pandoc))
 import Text.Pandoc.Filter.Plot.Monad
 import Text.Pandoc.Filter.Plot.Scripting.Template
 import Text.Pandoc.Options (WriterOptions (..))
@@ -85,7 +84,7 @@ 
 -- | Format a script to show in error messages
 formatScript :: Script -> Text
-formatScript s = T.unlines . fmap (\(n, l) -> formatLine n l) $ zip linenos (T.lines s)
+formatScript s = T.unlines . fmap (uncurry formatLine) $ zip linenos (T.lines s)
   where
     nlines = length (T.lines s)
     linenos = [1 .. nlines]
src/Text/Pandoc/Filter/Plot/Scripting/Template.hs view
@@ -4,11 +4,17 @@ 
 import Data.String (fromString)
 import Language.Haskell.TH.Syntax
+  ( Exp (AppE, LitE, VarE),
+    Lit (StringL),
+    Q,
+    Quasi (qAddDependentFile),
+    runIO,
+  )
 import System.FilePath ((</>))
 
 sourceTemplate_ :: Q Exp
 sourceTemplate_ = do
-  let fp = ("data" </> "srctemplate.html")
+  let fp = "data" </> "srctemplate.html"
   qAddDependentFile fp
   d <- runIO $ readFile fp
   strToExp d
stack.yaml view
@@ -1,11 +1,11 @@-resolver: lts-17.5 # GHC 8.10.4
+resolver: lts-17.9 # GHC 8.10.4
 
 packages:
 - .
 
 extra-deps:
-- pandoc-2.12
-- hslua-module-path-0.1.0.1
+- pandoc-2.13
+- hslua-module-path-0.1.0.1@sha256:1fe319f18315618491260c912e85b6f73e406499c8fe2fa505e59036a4ff78fd,2502
 
 # For development
 - git: https://github.com/owickstrom/pandoc-include-code.git
tests/Common.hs view
@@ -45,7 +45,7 @@     ensureDirectoryExistsAndEmpty tempDir
 
     let cb = (addDirectory tempDir $ codeBlock tk (trivialContent tk))
-    _ <- runPlotM defaultTestConfig $ make cb
+    _ <- runPlotM Nothing defaultTestConfig $ make cb
     filesCreated <- length <$> listDirectory tempDir
     assertEqual "" 2 filesCreated
 
@@ -60,11 +60,33 @@     ensureDirectoryExistsAndEmpty tempDir
 
     let cb = (addDirectory tempDir $ codeBlock tk (trivialContent tk))
-    _ <- runPlotM defaultTestConfig $ make cb
+    _ <- runPlotM Nothing defaultTestConfig $ make cb
     filesCreated <- length <$> listDirectory tempDir
     assertEqual "" 2 filesCreated
 
 -------------------------------------------------------------------------------
+-- Test that pandoc-plot appropriately transforms code blocks that are
+-- nested in other blocks (e.g. Divs)
+testNestedCodeBlocks :: Toolkit -> TestTree
+testNestedCodeBlocks tk =
+  testCase "transforms code blocks nested in other blocks" $ do
+    let postfix = unpack . cls $ tk
+    tempDir <- (</> "test-nester-blocks-" <> postfix) <$> getTemporaryDirectory
+    ensureDirectoryExistsAndEmpty tempDir
+
+    let block =
+          Div mempty $
+            singleton $
+              addDirectory tempDir $
+                codeBlock tk (trivialContent tk)
+    _ <- runPlotM Nothing defaultTestConfig $ make block
+    filesCreated <- length <$> listDirectory tempDir
+    assertEqual "" 2 filesCreated
+  where
+    singleton :: a -> [a]
+    singleton = return
+
+-------------------------------------------------------------------------------
 -- Test that included files are found within the source
 testFileInclusion :: Toolkit -> TestTree
 testFileInclusion tk =
@@ -77,7 +99,7 @@           ( addPreamble (include tk) $
               addDirectory tempDir $ codeBlock tk (trivialContent tk)
           )
-    _ <- runPlotM defaultTestConfig $ make cb
+    _ <- runPlotM Nothing defaultTestConfig $ make cb
     inclusion <- readFile (include tk)
     sourcePath <- head . filter (isExtensionOf ".src.html") <$> listDirectory tempDir
     src <- readFile (tempDir </> sourcePath)
@@ -109,7 +131,7 @@           ( addSaveFormat fmt $
               addDirectory tempDir $ codeBlock tk (trivialContent tk)
           )
-    _ <- runPlotM defaultTestConfig $ make cb
+    _ <- runPlotM Nothing defaultTestConfig $ make cb
     numberjpgFiles <-
       length <$> filter (isExtensionOf (extension fmt))
         <$> listDirectory tempDir
@@ -135,8 +157,8 @@             addDirectory tempDir $
               addCaption expected $
                 codeBlock tk (trivialContent tk)
-    blockNoSource <- runPlotM defaultTestConfig $ make noSource
-    blockWithSource <- runPlotM defaultTestConfig $ make withSource
+    blockNoSource <- runPlotM Nothing defaultTestConfig $ make noSource
+    blockWithSource <- runPlotM Nothing 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
@@ -166,7 +188,7 @@             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
+    blockWithSource <- runPlotM Nothing 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
@@ -210,7 +232,7 @@               addDirectory tempDir $
                 addSaveFormat PNG $
                   codeBlock tk (trivialContent tk)
-        _ <- runPlotM config $ make cb
+        _ <- runPlotM Nothing config $ make cb
 
         numberPngFiles <-
           length <$> filter (isExtensionOf (extension PNG))
@@ -238,7 +260,7 @@             addCaption "**caption**" $
               codeBlock tk (trivialContent tk)
         fmt = B.Format "markdown"
-    result <- runPlotM (defaultTestConfig {captionFormat = fmt}) $ make cb
+    result <- runPlotM Nothing (defaultTestConfig {captionFormat = fmt}) $ make cb
     assertIsInfix expected (extractCaption result)
   where
     extractCaption (B.Para blocks) = extractImageCaption . head $ blocks
@@ -264,7 +286,7 @@             addCaption "[title](https://google.com)" $
               codeBlock tk (trivialContent tk)
         fmt = B.Format "markdown"
-    result <- runPlotM (defaultTestConfig {captionFormat = fmt}) $ make cb
+    result <- runPlotM Nothing (defaultTestConfig {captionFormat = fmt}) $ make cb
     assertIsInfix expected (extractCaption result)
   where
     extractCaption (B.Para blocks) = extractImageCaption . head $ blocks
@@ -286,7 +308,7 @@           addDirectory tempDir $
             codeBlock tk (trivialContent tk)
 
-    result <- runPlotM defaultTestConfig $ make cb
+    result <- runPlotM Nothing defaultTestConfig $ make cb
     cleanedDirs <- cleanOutputDirs defaultTestConfig cb
 
     assertEqual "" [tempDir] cleanedDirs
@@ -307,7 +329,7 @@       ensureDirectoryExistsAndEmpty tempDir
 
       let cb = addDirectory tempDir $ codeBlock Matplotlib "plt.show()"
-      result <- runPlotM defaultTestConfig $ makeEither cb
+      result <- runPlotM Nothing defaultTestConfig $ makeEither cb
       let expectedCheck :: Either PandocPlotError a -> Bool
           expectedCheck (Left (ScriptChecksFailedError _)) = True
           expectedCheck _ = False
tests/Main.hs view
@@ -49,6 +49,7 @@   testGroup (show tk) $
     [ testFileCreation,
       testFileCreationPathWithSpaces,
+      testNestedCodeBlocks,
       testFileInclusion,
       testSaveFormat,
       testWithSource,