packages feed

pandoc-plot 1.0.2.1 → 1.1.0

raw patch · 15 files changed

+196/−40 lines, 15 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Text.Pandoc.Filter.Plot: PlantUML :: Toolkit
+ Text.Pandoc.Filter.Plot: [plantumlCmdArgs] :: Configuration -> !Text
+ Text.Pandoc.Filter.Plot: [plantumlExe] :: Configuration -> !FilePath
+ Text.Pandoc.Filter.Plot: [plantumlPreamble] :: Configuration -> !Script
+ Text.Pandoc.Filter.Plot.Internal: Figure :: FigureSpec -> ParseFigureResult
+ Text.Pandoc.Filter.Plot.Internal: MissingToolkit :: Toolkit -> ParseFigureResult
+ Text.Pandoc.Filter.Plot.Internal: NotAFigure :: ParseFigureResult
+ Text.Pandoc.Filter.Plot.Internal: PlantUML :: Toolkit
+ Text.Pandoc.Filter.Plot.Internal: [oCWD] :: OutputSpec -> FilePath
+ Text.Pandoc.Filter.Plot.Internal: [plantumlCmdArgs] :: Configuration -> !Text
+ Text.Pandoc.Filter.Plot.Internal: [plantumlExe] :: Configuration -> !FilePath
+ Text.Pandoc.Filter.Plot.Internal: [plantumlPreamble] :: Configuration -> !Script
+ Text.Pandoc.Filter.Plot.Internal: data ParseFigureResult
- Text.Pandoc.Filter.Plot: Configuration :: !FilePath -> !Bool -> !Int -> !SaveFormat -> ![FilePath] -> !Format -> !Text -> !Bool -> !Verbosity -> !LogSink -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Bool -> !Bool -> Configuration
+ Text.Pandoc.Filter.Plot: Configuration :: !FilePath -> !Bool -> !Int -> !SaveFormat -> ![FilePath] -> !Format -> !Text -> !Bool -> !Verbosity -> !LogSink -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Bool -> !Bool -> Configuration
- Text.Pandoc.Filter.Plot.Internal: Configuration :: !FilePath -> !Bool -> !Int -> !SaveFormat -> ![FilePath] -> !Format -> !Text -> !Bool -> !Verbosity -> !LogSink -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Bool -> !Bool -> Configuration
+ Text.Pandoc.Filter.Plot.Internal: Configuration :: !FilePath -> !Bool -> !Int -> !SaveFormat -> ![FilePath] -> !Format -> !Text -> !Bool -> !Verbosity -> !LogSink -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Text -> !Bool -> !Bool -> Configuration
- Text.Pandoc.Filter.Plot.Internal: OutputSpec :: FigureSpec -> FilePath -> FilePath -> OutputSpec
+ Text.Pandoc.Filter.Plot.Internal: OutputSpec :: FigureSpec -> FilePath -> FilePath -> FilePath -> OutputSpec
- Text.Pandoc.Filter.Plot.Internal: parseFigureSpec :: Block -> PlotM (Maybe FigureSpec)
+ Text.Pandoc.Filter.Plot.Internal: parseFigureSpec :: Block -> PlotM ParseFigureResult

Files

CHANGELOG.md view
@@ -2,6 +2,22 @@ 
 pandoc-plot uses [Semantic Versioning](http://semver.org/spec/v2.0.0.html)
 
+Release 1.1.0
+-------------
+
+* Added the [PlantUML](https://plantuml.com) toolkit (#18). Diagrams can be generated like so:
+
+  ````markdown
+
+  ```{.plantuml}
+  @startuml
+  Bob->Alice : hello
+  @enduml
+  ```
+
+  ````
+* Changed versioning scheme to match more common Major.Minor.Bugfix.
+
 Release 1.0.2.1
 ---------------
 
README.md view
@@ -2,7 +2,7 @@ 
 ## A Pandoc filter to generate figures from code blocks in documents
 
-[![Hackage version](https://img.shields.io/hackage/v/pandoc-plot.svg)](http://hackage.haskell.org/package/pandoc-plot) [![Stackage version (latest long-term service)](http://stackage.org/package/pandoc-plot/badge/lts)](http://stackage.org/lts/package/pandoc-plot) [![Conda Version](https://img.shields.io/conda/vn/conda-forge/pandoc-plot.svg)](https://anaconda.org/conda-forge/pandoc-plot) [![license](https://img.shields.io/badge/license-GPLv2+-lightgray.svg)](https://www.gnu.org/licenses/gpl.html) 
+[![Hackage version](https://img.shields.io/hackage/v/pandoc-plot.svg)](http://hackage.haskell.org/package/pandoc-plot) [![Conda Version](https://anaconda.org/conda-forge/pandoc-plot/badges/version.svg)](https://anaconda.org/conda-forge/pandoc-plot) [![license](https://img.shields.io/badge/license-GPLv2+-lightgray.svg)](https://www.gnu.org/licenses/gpl.html) 
 
 `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.
 
@@ -59,7 +59,8 @@   - `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`](https://docs.juliaplots.org/latest/) package.
+  - `plotsjl`: plots using the [Julia `Plots.jl`](https://docs.juliaplots.org/latest/) package;
+  - `plantuml`: diagrams using the [PlantUML](https://plantuml.com/) software suite.
 
 To know which toolkits are useable on *your machine* (and which ones are
 not available), you can check with the `toolkits` command:
example-config.yml view
@@ -123,4 +123,14 @@ plotsjl:
   # preamble: plotsjl.jl
   executable: julia
-  command_line_arguments:+  command_line_arguments:
+
+plantuml:
+  # preamble: plantuml.txt
+  executable: java
+  command_line_arguments: -jar plantuml.jar
+  # On Linux, it you have `plantuml.jar` as an executable, you can also
+  # use the following configuration instead:
+  # plantuml:
+  #   executable: plantuml
+  #   command_line_arguments:
pandoc-plot.cabal view
@@ -1,6 +1,6 @@ cabal-version:  2.2
 name:           pandoc-plot
-version:        1.0.2.1
+version:        1.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 
@@ -14,7 +14,7 @@ license:        GPL-2.0-or-later
 license-file:   LICENSE
 build-type:     Simple
-tested-with:    GHC == 8.10.3
+tested-with:    GHC == 8.10.4
 extra-source-files:
     CHANGELOG.md
     LICENSE
@@ -78,6 +78,7 @@         Text.Pandoc.Filter.Plot.Renderers.Graphviz
         Text.Pandoc.Filter.Plot.Renderers.Bokeh
         Text.Pandoc.Filter.Plot.Renderers.Plotsjl
+        Text.Pandoc.Filter.Plot.Renderers.PlantUML
         Text.Pandoc.Filter.Plot.Monad
         Text.Pandoc.Filter.Plot.Monad.Logging
         Text.Pandoc.Filter.Plot.Monad.Types
src/Text/Pandoc/Filter/Plot.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE LambdaCase #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 -- |
@@ -119,6 +120,7 @@   ( Configuration (..),
     FigureSpec,
     LogSink (..),
+    ParseFigureResult (..),
     PlotM,
     RuntimeEnv (envConfig),
     SaveFormat (..),
@@ -182,9 +184,10 @@ makeEither :: Block -> PlotM (Either PandocPlotError Block)
 makeEither block =
   parseFigureSpec block
-    >>= maybe
-      (return $ Right block)
-      (\s -> runScriptIfNecessary s >>= handleResult s)
+    >>= \case
+      NotAFigure -> return $ Right block
+      Figure fs -> runScriptIfNecessary fs >>= handleResult fs
+      MissingToolkit tk -> return $ Left $ ToolkitNotInstalledError tk
   where
     -- Logging of errors has been taken care of in @runScriptIfNecessary@
     handleResult :: FigureSpec -> ScriptResult -> PlotM (Either PandocPlotError Block)
src/Text/Pandoc/Filter/Plot/Clean.hs view
@@ -61,10 +61,11 @@   Walkable Block b =>
   b ->
   PlotM [FilePath]
-outputDirs =
-  fmap (nub . catMaybes)
-    . sequence
-    . query (\b -> [parseFigureSpec b >>= return . fmap directory])
+outputDirs = fmap (catMaybes . nub) . sequence . query (\b -> [hasDirectory <$> parseFigureSpec b])
+  where
+    hasDirectory :: ParseFigureResult -> Maybe FilePath
+    hasDirectory (Figure fs) = Just $ directory fs
+    hasDirectory _ = Nothing
 
 -- PlotM version of @cleanOutputDirs@
 cleanOutputDirsM ::
@@ -87,18 +88,19 @@ 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
-                fct readerOpts t
-              P.ByteStringReader bst -> do
-                b <- liftIO $ B.readFile fp
-                bst readerOpts b
-        )
+    =<< 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
+              b <- liftIO $ B.readFile fp
+              bst readerOpts b
+      )
 
 -- Determine format based on file extension
 -- Note : this is exactly the heuristic used by pandoc here:
@@ -126,6 +128,11 @@     ".lhs" -> Just "markdown+lhs"
     ".ltx" -> Just "latex"
     ".markdown" -> Just "markdown"
+    ".mkdn" -> Just "markdown"
+    ".mkd" -> Just "markdown"
+    ".mdwn" -> Just "markdown"
+    ".mdown" -> Just "markdown"
+    ".Rmd" -> Just "markdown"
     ".md" -> Just "markdown"
     ".ms" -> Just "ms"
     ".muse" -> Just "muse"
@@ -152,5 +159,6 @@     ".xhtml" -> Just "html"
     ".ipynb" -> Just "ipynb"
     ".csv" -> Just "csv"
+    ".bib" -> Just "biblatex"
     ['.', y] | y `elem` ['1' .. '9'] -> Just "man"
     _ -> Nothing
src/Text/Pandoc/Filter/Plot/Configuration.hs view
@@ -61,6 +61,7 @@       graphvizPreamble = mempty,
       bokehPreamble = mempty,
       plotsjlPreamble = mempty,
+      plantumlPreamble = mempty,
       -- Executables
       matplotlibExe = python,
       matlabExe = "matlab",
@@ -73,6 +74,7 @@       graphvizExe = "dot",
       bokehExe = python,
       plotsjlExe = "julia",
+      plantumlExe = "java",
       -- Command line arguments
       matplotlibCmdArgs = mempty,
       matlabCmdArgs = mempty,
@@ -85,6 +87,7 @@       graphvizCmdArgs = mempty,
       bokehCmdArgs = mempty,
       plotsjlCmdArgs = mempty,
+      plantumlCmdArgs = "-jar plantuml.jar",
       -- Extras
       matplotlibTightBBox = False,
       matplotlibTransparent = False
@@ -142,7 +145,8 @@     _gnuplotPrec :: !GNUPlotPrecursor,
     _graphvizPrec :: !GraphvizPrecursor,
     _bokehPrec :: !BokehPrecursor,
-    _plotsjlPrec :: !PlotsjlPrecursor
+    _plotsjlPrec :: !PlotsjlPrecursor,
+    _plantumlPrec :: !PlantUMLPrecursor
   }
 
 defaultConfigPrecursor :: ConfigPrecursor
@@ -167,7 +171,8 @@       _gnuplotPrec = GNUPlotPrecursor Nothing (gnuplotExe defaultConfiguration) (gnuplotCmdArgs defaultConfiguration),
       _graphvizPrec = GraphvizPrecursor Nothing (graphvizExe defaultConfiguration) (graphvizCmdArgs defaultConfiguration),
       _bokehPrec = BokehPrecursor Nothing (bokehExe defaultConfiguration) (bokehCmdArgs defaultConfiguration),
-      _plotsjlPrec = PlotsjlPrecursor Nothing (plotsjlExe defaultConfiguration) (plotsjlCmdArgs defaultConfiguration)
+      _plotsjlPrec = PlotsjlPrecursor Nothing (plotsjlExe defaultConfiguration) (plotsjlCmdArgs defaultConfiguration),
+      _plantumlPrec = PlantUMLPrecursor Nothing (plantumlExe defaultConfiguration) (plantumlCmdArgs defaultConfiguration)
     }
 
 data LoggingPrecursor = LoggingPrecursor
@@ -204,6 +209,8 @@ 
 data PlotsjlPrecursor = PlotsjlPrecursor {_plotsjlPreamble :: !(Maybe FilePath), _plotsjlExe :: !FilePath, _plotsjlCmdArgs :: !Text}
 
+data PlantUMLPrecursor = PlantUMLPrecursor {_plantumlPreamble :: !(Maybe FilePath), _plantumlExe :: !FilePath, _plantumlCmdArgs :: !Text}
+
 instance FromJSON LoggingPrecursor where
   parseJSON (Object v) =
     LoggingPrecursor <$> v .:? "verbosity" .!= (logVerbosity defaultConfiguration)
@@ -260,6 +267,10 @@   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 _ = fail $ mconcat ["Could not parse ", show PlantUML, " configuration."]
+
 instance FromJSON ConfigPrecursor where
   parseJSON (Null) = return defaultConfigPrecursor -- In case of empty file
   parseJSON (Object v) = do
@@ -284,6 +295,7 @@     _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."
@@ -316,6 +328,7 @@       graphvizExe = _graphvizExe _graphvizPrec
       bokehExe = _bokehExe _bokehPrec
       plotsjlExe = _plotsjlExe _plotsjlPrec
+      plantumlExe = _plantumlExe _plantumlPrec
 
       matplotlibCmdArgs = _matplotlibCmdArgs _matplotlibPrec
       matlabCmdArgs = _matlabCmdArgs _matlabPrec
@@ -328,6 +341,7 @@       graphvizCmdArgs = _graphvizCmdArgs _graphvizPrec
       bokehCmdArgs = _bokehCmdArgs _bokehPrec
       plotsjlCmdArgs = _plotsjlCmdArgs _plotsjlPrec
+      plantumlCmdArgs = _plantumlCmdArgs _plantumlPrec
 
   matplotlibPreamble <- readPreamble (_matplotlibPreamble _matplotlibPrec)
   matlabPreamble <- readPreamble (_matlabPreamble _matlabPrec)
@@ -340,6 +354,7 @@   graphvizPreamble <- readPreamble (_graphvizPreamble _graphvizPrec)
   bokehPreamble <- readPreamble (_bokehPreamble _bokehPrec)
   plotsjlPreamble <- readPreamble (_plotsjlPreamble _plotsjlPrec)
+  plantumlPreamble <- readPreamble (_plantumlPreamble _plantumlPrec)
 
   return Configuration {..}
   where
src/Text/Pandoc/Filter/Plot/Monad.hs view
@@ -290,6 +290,7 @@     exeSelector Graphviz = asksConfig graphvizExe
     exeSelector Bokeh = asksConfig bokehExe
     exeSelector Plotsjl = asksConfig plotsjlExe
+    exeSelector PlantUML = asksConfig plantumlExe
 
 -- | The @Configuration@ type holds the default values to use
 -- when running pandoc-plot. These values can be overridden in code blocks.
@@ -354,6 +355,8 @@     bokehPreamble :: !Script,
     -- | The default preamble script for the Julia/Plots.jl toolkit.
     plotsjlPreamble :: !Script,
+    -- | The default preamble script for the PlantUML toolkit.
+    plantumlPreamble :: !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.
@@ -376,6 +379,8 @@     bokehExe :: !FilePath,
     -- | The executable to use to generate figures using the Julia/Plots.jl toolkit.
     plotsjlExe :: !FilePath,
+    -- | The executable to use to generate figures using the PlantUML toolkit.
+    plantumlExe :: !FilePath,
     -- | Command-line arguments to pass to the Python interpreter for the Matplotlib toolkit
     matplotlibCmdArgs :: !Text,
     -- | Command-line arguments to pass to the interpreter for the MATLAB toolkit.
@@ -398,6 +403,8 @@     bokehCmdArgs :: !Text,
     -- | Command-line arguments to pass to the interpreter for the Julia/Plots.jl toolkit.
     plotsjlCmdArgs :: !Text,
+    -- | Command-line arguments to pass to the interpreter for the plantUML toolkit.
+    plantumlCmdArgs :: !Text,
     -- | Whether or not to make Matplotlib figures tight by default.
     matplotlibTightBBox :: !Bool,
     -- | Whether or not to make Matplotlib figures transparent by default.
src/Text/Pandoc/Filter/Plot/Monad/Types.hs view
@@ -58,6 +58,7 @@   | Graphviz
   | Bokeh
   | Plotsjl
+  | PlantUML
   deriving (Bounded, Eq, Enum, Generic, Ord)
 
 -- | This instance should only be used to display toolkit names
@@ -73,6 +74,7 @@   show Graphviz = "graphviz"
   show Bokeh = "Python/Bokeh"
   show Plotsjl = "Julia/Plots.jl"
+  show PlantUML = "PlantUML"
 
 -- | Class name which will trigger the filter
 cls :: Toolkit -> Text
@@ -87,6 +89,7 @@ cls Graphviz = "graphviz"
 cls Bokeh = "bokeh"
 cls Plotsjl = "plotsjl"
+cls PlantUML = "plantuml"
 
 -- | Executable program and directory where it can be found.
 data Executable = Executable FilePath Text
@@ -248,7 +251,9 @@     -- | Path to the script to render
     oScriptPath :: FilePath,
     -- | Figure output path
-    oFigurePath :: FilePath
+    oFigurePath :: FilePath,
+    -- | Current working directory (used for PlantUML)
+    oCWD :: FilePath
   }
 
 data Renderer = Renderer
src/Text/Pandoc/Filter/Plot/Parse.hs view
@@ -14,6 +14,7 @@ module Text.Pandoc.Filter.Plot.Parse
   ( plotToolkit,
     parseFigureSpec,
+    ParseFigureResult (..),
     captionReader,
   )
 where
@@ -46,26 +47,30 @@ tshow :: Show a => a -> Text
 tshow = pack . show
 
+data ParseFigureResult
+  = NotAFigure
+  | Figure FigureSpec
+  | MissingToolkit Toolkit
+
 -- | Determine inclusion specifications from @Block@ attributes.
 -- If an environment is detected, but the save format is incompatible,
 -- an error will be thrown.
-parseFigureSpec :: Block -> PlotM (Maybe FigureSpec)
+parseFigureSpec :: Block -> PlotM ParseFigureResult
 parseFigureSpec block@(CodeBlock (id', classes, attrs) _) = do
   -- The following would be a good case for the use of MaybeT
   -- but I don't want to bring in another dependency
   let mtk = plotToolkit block
   case mtk of
-    Nothing -> return Nothing
+    Nothing -> return NotAFigure
     Just tk -> do
       r <- renderer tk
       case r of
         Nothing -> do
           let msg = mconcat ["Renderer for ", tshow tk, " needed but is not installed"]
-          whenStrict $ throwStrictError msg
           warning msg
-          return Nothing
+          return $ MissingToolkit tk
         Just r' -> do
-          Just <$> figureSpec r'
+          Figure <$> figureSpec r'
   where
     attrs' = Map.fromList attrs
     preamblePath = unpack <$> Map.lookup (tshow PreambleK) attrs'
@@ -111,7 +116,7 @@           let msg = pack $ mconcat ["Save format ", show saveFormat, " not supported by ", show toolkit]
            in err msg
       return FigureSpec {..}
-parseFigureSpec _ = return Nothing
+parseFigureSpec _ = return NotAFigure
 
 -- | Parse script content from a block, if possible.
 -- The script content can either come from a file
src/Text/Pandoc/Filter/Plot/Renderers.hs view
@@ -44,6 +44,7 @@ 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.PlantUML
 import Text.Pandoc.Filter.Plot.Renderers.PlotlyPython
 import Text.Pandoc.Filter.Plot.Renderers.PlotlyR
 import Text.Pandoc.Filter.Plot.Renderers.Plotsjl
@@ -80,6 +81,7 @@     sel Graphviz = graphviz
     sel Bokeh = bokeh
     sel Plotsjl = plotsjl
+    sel PlantUML = plantuml
 
 -- | Save formats supported by this renderer.
 supportedSaveFormats :: Toolkit -> [SaveFormat]
@@ -94,6 +96,7 @@ supportedSaveFormats Graphviz = graphvizSupportedSaveFormats
 supportedSaveFormats Bokeh = bokehSupportedSaveFormats
 supportedSaveFormats Plotsjl = plotsjlSupportedSaveFormats
+supportedSaveFormats PlantUML = plantumlSupportedSaveFormats
 
 -- | The function that maps from configuration to the preamble.
 preambleSelector :: Toolkit -> (Configuration -> Script)
@@ -108,6 +111,7 @@ preambleSelector Graphviz = graphvizPreamble
 preambleSelector Bokeh = bokehPreamble
 preambleSelector Plotsjl = plotsjlPreamble
+preambleSelector PlantUML = plantumlPreamble
 
 -- | Parse code block headers for extra attributes that are specific
 -- to this renderer. By default, no extra attributes are parsed.
+ src/Text/Pandoc/Filter/Plot/Renderers/PlantUML.hs view
@@ -0,0 +1,76 @@+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE QuasiQuotes #-}
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+
+-- |
+-- Module      : $header$
+-- Copyright   : (c) Laurent P René de Cotret, 2019 - 2021
+-- License     : GNU GPL, version 2 or above
+-- Maintainer  : laurent.decotret@outlook.com
+-- Stability   : internal
+-- Portability : portable
+--
+-- Rendering PlantUML markup
+module Text.Pandoc.Filter.Plot.Renderers.PlantUML
+  ( plantuml,
+    plantumlSupportedSaveFormats,
+  )
+where
+
+import Data.Char
+import System.FilePath (takeDirectory, takeFileName, (</>))
+import Data.Text (replace, pack)
+import Text.Pandoc.Filter.Plot.Renderers.Prelude
+
+plantuml :: PlotM (Maybe Renderer)
+plantuml = do
+  avail <- plantumlAvailable
+  if not avail
+    then return Nothing
+    else do
+      cmdargs <- asksConfig plantumlCmdArgs
+      mexe <- executable PlantUML
+      return $
+        mexe >>= \exe@(Executable _ exename) ->
+          return
+            Renderer
+              { rendererToolkit = PlantUML,
+                rendererExe = exe,
+                rendererCapture = plantumlCapture,
+                rendererCommand = plantumlCommand cmdargs exename,
+                rendererSupportedSaveFormats = plantumlSupportedSaveFormats,
+                rendererChecks = mempty,
+                rendererLanguage = "plantuml",
+                rendererComment = mappend "' ",
+                rendererScriptExtension = ".txt"
+              }
+
+plantumlSupportedSaveFormats :: [SaveFormat]
+plantumlSupportedSaveFormats = [PNG, PDF, SVG]
+
+plantumlCommand :: Text -> Text -> OutputSpec -> Text
+plantumlCommand cmdargs exe OutputSpec {..} =
+  let fmt = fmap toLower . show . saveFormat $ oFigureSpec
+      dir = takeDirectory oFigurePath
+   in [st|#{exe} #{cmdargs} -t#{fmt} -output "#{oCWD </> dir}" "#{normalizePath oScriptPath}"|]
+
+normalizePath :: String -> String
+normalizePath = map f
+    where f '\\' = '/'
+          f x = x
+
+plantumlAvailable :: PlotM Bool
+plantumlAvailable = do
+  mexe <- executable PlantUML
+  case mexe of
+    Nothing -> return False
+    Just (Executable dir exe) -> do
+      cmdargs <- asksConfig plantumlCmdArgs
+      withPrependedPath dir $ asks envCWD >>= flip commandSuccess [st|#{exe} #{cmdargs} -h|]
+
+plantumlCapture :: FigureSpec -> FilePath -> Script
+plantumlCapture FigureSpec {..} fp = 
+    -- Only the filename is included in the script; we need to also pass the ABSOLUTE output directory 
+    -- to the executable.
+    replace "@startuml" ("@startuml " <> pack (takeFileName fp)) script
src/Text/Pandoc/Filter/Plot/Scripting.hs view
@@ -94,6 +94,7 @@     CheckPassed -> do
       scriptPath <- tempScriptPath spec
       target <- figurePath spec
+      cwd <- asks envCWD
 
       let scriptWithCapture = rendererCapture renderer_ spec target
 
@@ -102,7 +103,8 @@             OutputSpec
               { oFigureSpec = spec,
                 oScriptPath = scriptPath,
-                oFigurePath = target
+                oFigurePath = target,
+                oCWD = cwd
               }
       let command_ = rendererCommand renderer_ outputSpec
 
@@ -112,7 +114,6 @@       withPrependedPath exedir $ do
         -- 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
@@ -157,8 +158,8 @@           ( dpi,
             dependenciesHash,
             extraAttrs,
-            show version -- Included version because capture
-          ) -- scripts may change between releases
+            show version -- Included version because capture scripts may change between releases
+          ) 
         )
 
 -- | Determine the path a figure should have.
stack.yaml view
@@ -1,12 +1,14 @@ resolver: nightly-2021-01-05 # GHC 8.10.3
 
+compiler: ghc-8.10.4
+
 packages:
 - .
 
 extra-deps:
-- pandoc-2.11.3.2
-- citeproc-0.3.0.3@sha256:273b4935b18079fb666e53419dbf31e1edb7c7bdf7ea4295ff7ba6da22dc61b3,5590
-- commonmark-0.1.1.2@sha256:c06ab05f0f224ab7982502a96e17952823a9b6dae8505fb35194b0baa9e2a975,3278
+- pandoc-2.11.4
+- citeproc-0.3.0.5@sha256:c32a7676fe1b369f44b6601fdf926ca50a4f3c2768006e696bf624953b1ba2ca,5590 
+- commonmark-0.1.1.3@sha256:e3af411216448fe61cc36d2d5dbffd85c9f714761f1a47ae0a9c611babf72ea7,3278
 - commonmark-extensions-0.2.0.4@sha256:6a437bcfa3c757af4262b71336513619990eafb5cfdc33e57a499c93ad225608,3184
 - commonmark-pandoc-0.2.0.1@sha256:529c6e2c6cabf61558b66a28123eafc1d90d3324be29819f59f024e430312c1f,1105
 
tests/Common.hs view
@@ -94,6 +94,7 @@     include Graphviz = "tests/includes/graphviz.dot"
     include Bokeh = "tests/includes/bokeh.py"
     include Plotsjl = "tests/includes/plotsjl.jl"
+    include PlantUML = "tests/includes/plantuml.txt"
 
 -------------------------------------------------------------------------------
 -- Test that the files are saved in the appropriate format
@@ -333,6 +334,7 @@       "p.line([1,2,3,4], [5,6,7,8])"
     ]
 trivialContent Plotsjl = "using Plots; x = 1:10; y = rand(10); plot(x, y);"
+trivialContent PlantUML = "@startuml\nAlice -> Bob: test\n@enduml"
 
 addCaption :: String -> Block -> Block
 addCaption caption (CodeBlock (id', cls, attrs) script) =