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 +16/−0
- README.md +3/−2
- example-config.yml +11/−1
- pandoc-plot.cabal +3/−2
- src/Text/Pandoc/Filter/Plot.hs +6/−3
- src/Text/Pandoc/Filter/Plot/Clean.hs +24/−16
- src/Text/Pandoc/Filter/Plot/Configuration.hs +17/−2
- src/Text/Pandoc/Filter/Plot/Monad.hs +7/−0
- src/Text/Pandoc/Filter/Plot/Monad/Types.hs +6/−1
- src/Text/Pandoc/Filter/Plot/Parse.hs +11/−6
- src/Text/Pandoc/Filter/Plot/Renderers.hs +4/−0
- src/Text/Pandoc/Filter/Plot/Renderers/PlantUML.hs +76/−0
- src/Text/Pandoc/Filter/Plot/Scripting.hs +5/−4
- stack.yaml +5/−3
- tests/Common.hs +2/−0
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 -[](http://hackage.haskell.org/package/pandoc-plot) [](http://stackage.org/lts/package/pandoc-plot) [](https://anaconda.org/conda-forge/pandoc-plot) [](https://www.gnu.org/licenses/gpl.html) +[](http://hackage.haskell.org/package/pandoc-plot) [](https://anaconda.org/conda-forge/pandoc-plot) [](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) =