pandoc-plot 0.2.2.0 → 0.3.0.0
raw patch · 9 files changed
+110/−43 lines, 9 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
+ Text.Pandoc.Filter.Plot: [captionFormat] :: Configuration -> Format
+ Text.Pandoc.Filter.Plot.Internal: CaptionFormatK :: InclusionKey
+ Text.Pandoc.Filter.Plot.Internal: [captionFormat] :: Configuration -> Format
- Text.Pandoc.Filter.Plot: Configuration :: !FilePath -> !Bool -> !Int -> !SaveFormat -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !Bool -> !Bool -> Configuration
+ Text.Pandoc.Filter.Plot: Configuration :: !FilePath -> !Bool -> !Int -> !SaveFormat -> Format -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !Bool -> !Bool -> Configuration
- Text.Pandoc.Filter.Plot: make :: Toolkit -> Configuration -> Format -> Block -> IO Block
+ Text.Pandoc.Filter.Plot: make :: Toolkit -> Configuration -> Block -> IO Block
- Text.Pandoc.Filter.Plot: makePlot :: Configuration -> Maybe Format -> Block -> IO Block
+ Text.Pandoc.Filter.Plot: makePlot :: Configuration -> Block -> IO Block
- Text.Pandoc.Filter.Plot: plotTransform :: Configuration -> Maybe Format -> Pandoc -> IO Pandoc
+ Text.Pandoc.Filter.Plot: plotTransform :: Configuration -> Pandoc -> IO Pandoc
- Text.Pandoc.Filter.Plot.Internal: Configuration :: !FilePath -> !Bool -> !Int -> !SaveFormat -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !Bool -> !Bool -> Configuration
+ Text.Pandoc.Filter.Plot.Internal: Configuration :: !FilePath -> !Bool -> !Int -> !SaveFormat -> Format -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !Script -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !FilePath -> !Bool -> !Bool -> Configuration
Files
- CHANGELOG.md +6/−0
- README.md +6/−6
- example-config.yml +15/−0
- pandoc-plot.cabal +1/−1
- src/Text/Pandoc/Filter/Plot.hs +11/−17
- src/Text/Pandoc/Filter/Plot/Configuration.hs +6/−0
- src/Text/Pandoc/Filter/Plot/Types.hs +5/−1
- tests/Common.hs +38/−16
- tests/Main.hs +22/−2
CHANGELOG.md view
@@ -2,6 +2,12 @@ pandoc-plot uses [Semantic Versioning](http://semver.org/spec/v2.0.0.html) +Release 0.3.0.0 +--------------- + +* Added more examples. +* Added MacOS binaries built via Azure pipelines. +* BREAKING CHANGE: Parsing captions based on source file was not working. Captions format can be specified in the configuration file. This unfortunately changes the type signature of a few high-level functions. Release 0.2.2.0 ---------------
README.md view
@@ -93,7 +93,7 @@ __LaTex__: ```latex -\begin{minted}[caption=This is a simple figure with a \LaTeX caption]{matlabplot} +\begin{minted}[caption=This is a simple figure with a caption]{matlabplot} x = 0: .1 : 2*pi; y1 = cos(x); y2 = sin(x); @@ -103,13 +103,13 @@ \end{minted} ``` -Caption formatting should match the document formatting. +Caption formatting unfortunately cannot be determined automatically. To specify a caption format (e.g. "markdown", "LaTeX", etc.), see [Configuration](#configuration). ### Link to source code In case of an output format that supports links (e.g. HTML), the embedded image generated by `pandoc-plot` can show a link to the source code which was used to generate the file. Therefore, other people can see what code was used to create your figures. -You can turn this off via the `source=true` key: +You can turn this on via the `source=true` key: __Markdown__: @@ -205,7 +205,7 @@ source: false dpi: 80 format: PNG -python_interpreter: python +caption_format: markdown+tex_math_dollars # The possible parameters for the Matplotlib toolkit matplotlib: @@ -302,9 +302,9 @@ ## Installation -### Binaries and Installers (Windows) +### Binaries and Installers -Windows binaries and installers are available on the [GitHub release page](https://github.com/LaurentRDC/pandoc-plot/releases). +Windows, Linux, and Mac OS binaries are available on the [GitHub release page](https://github.com/LaurentRDC/pandoc-plot/releases). There are also Windows installers. ### conda
example-config.yml view
@@ -13,10 +13,25 @@ # notices it. # The following parameters affect all toolkits +# Directory where to save the plots. The path can be relative to this file, or absolute. directory: plots/ + +# Whether or not to include a link to the source script in the caption. +# Particularly useful for HTML output. source: false + +# Default density of figures in dots per inches (DPI). +# This can be changed in the document specifically as well. dpi: 80 + +# Default format in which to save the figures. This can be specified individually as well. format: PNG + +# Text format for the captions. Unfortunately, there is no way to detect this automatically. +# You can use the same notation as Pandoc's --from parameter, specified here: +# https://pandoc.org/MANUAL.html#option--from +# Example: markdown, rst+raw_tex +caption_format: markdown+tex_math_dollars # The possible parameters for the Matplotlib toolkit matplotlib:
pandoc-plot.cabal view
@@ -1,5 +1,5 @@ name: pandoc-plot -version: 0.2.2.0 +version: 0.3.0.0 cabal-version: >= 1.12 synopsis: A Pandoc filter to include figures generated from code blocks using your plotting toolkit of choice. description: A Pandoc filter to include figures generated from code blocks. Keep the document and code in the same location. Output is captured and included as a figure.
src/Text/Pandoc/Filter/Plot.hs view
@@ -31,11 +31,12 @@ * @directory=...@ : Directory where to save the figure. * @source=true|false@ : Whether or not to link the source code of this figure in the caption. Ideal for web pages, for example. Default is false. * @format=...@: Format of the generated figure. This can be an extension or an acronym, e.g. @format=PNG@. - * @caption="..."@: Specify a plot caption (or alternate text). Captions should be formatted in the same format as the document (e.g. Markdown captions in Markdown documents). + * @caption="..."@: Specify a plot caption (or alternate text). Captions should be formatted in Markdown, with LaTeX math. * @dpi=...@: Specify a value for figure resolution, or dots-per-inch. Certain toolkits ignore this. * @preamble=...@: Path to a file to include before the code block. Ideal to avoid repetition over many figures. -Default values for the above attributes are stored in the @Configuration@ datatype. These can be specified in a YAML file. +Default values for the above attributes are stored in the @Configuration@ datatype. These can be specified in a +YAML file which must be named ".pandoc-plot.yml". Here is an example code block which will render a figure using gnuplot, in Markdown: @@ -67,8 +68,6 @@ import Control.Monad.IO.Class (liftIO) import Control.Monad.Reader (runReaderT) -import Data.Maybe (fromMaybe) - import System.IO (hPutStrLn, stderr) import Text.Pandoc.Definition @@ -84,21 +83,17 @@ -- The target document format determines how the figure captions should be parsed. -- By default (i.e. if Nothing), captions will be parsed as Markdown with LaTeX math @$...$@, makePlot :: Configuration -- ^ Configuration for default values - -> Maybe Format -- ^ Input document format -> Block -> IO Block -makePlot conf mfmt block = - let fmt = fromMaybe (Format "markdown+tex_math_dollars") mfmt - in maybe (return block) (\tk -> make tk conf fmt block) (plotToolkit block) +makePlot conf block = maybe (return block) (\tk -> make tk conf block) (plotToolkit block) -- | Walk over an entire Pandoc document, changing appropriate code blocks -- into figures. Default configuration is used. plotTransform :: Configuration -- ^ Configuration for default values - -> Maybe Format -- ^ Input document format - -> Pandoc + -> Pandoc -- ^ Input document -> IO Pandoc -plotTransform conf mfmt = walkM $ makePlot conf mfmt +plotTransform conf = walkM $ makePlot conf -- | Force to use a particular toolkit to render appropriate code blocks. @@ -106,12 +101,11 @@ -- Failing to render a figure does not stop the filter, so that you may run the filter -- on documents without having all necessary toolkits installed. In this case, error -- messages are printed to stderr, and blocks are left unchanged. -make :: Toolkit - -> Configuration -- ^ Configuration for default values - -> Format -- ^ Input document format +make :: Toolkit -- ^ Plotting toolkit. + -> Configuration -- ^ Configuration for default values. -> Block -> IO Block -make tk conf fmt block = runReaderT (makePlot' block) (PlotEnv tk conf) +make tk conf block = runReaderT (makePlot' block) (PlotEnv tk conf) where makePlot' :: Block -> PlotM Block makePlot' blk @@ -119,8 +113,8 @@ >>= maybe (return blk) (\s -> runScriptIfNecessary s >>= handleResult s) - where - handleResult spec ScriptSuccess = return $ toImage fmt spec + where + handleResult spec ScriptSuccess = return $ toImage (captionFormat conf) spec handleResult _ (ScriptChecksFailed msg) = do liftIO $ hPutStrLn stderr $ "pandoc-plot: The script check failed with message: " <> msg return blk
src/Text/Pandoc/Filter/Plot/Configuration.hs view
@@ -24,6 +24,8 @@ import Data.Yaml import Data.Yaml.Config (ignoreEnv, loadYamlSettings) +import Text.Pandoc.Definition (Format(..)) + import Text.Pandoc.Filter.Plot.Types -- | Read configuration from a YAML file. The @@ -43,6 +45,7 @@ , _defaultWithSource :: !Bool -- ^ The default behavior of whether or not to include links to source code and high-res , _defaultDPI :: !Int -- ^ The default dots-per-inch value for generated figures. Renderers might ignore this. , _defaultSaveFormat :: !SaveFormat -- ^ The default save format of generated figures. + , _captionFormat :: Format -- ^ Caption format in Pandoc notation, e.g. "markdown+tex_math_dollars". , _matplotlibPrec :: !MatplotlibPrecursor , _matlabPrec :: !MatlabPrecursor @@ -59,6 +62,7 @@ , _defaultWithSource = defaultWithSource def , _defaultDPI = defaultDPI def , _defaultSaveFormat = defaultSaveFormat def + , _captionFormat = captionFormat def , _matplotlibPrec = def , _matlabPrec = def @@ -137,6 +141,7 @@ _defaultWithSource <- v .:? (tshow WithSourceK) .!= (defaultWithSource def) _defaultDPI <- v .:? (tshow DpiK) .!= (defaultDPI def) _defaultSaveFormat <- v .:? (tshow SaveFormatK) .!= (_defaultSaveFormat def) + _captionFormat <- v .:? (tshow CaptionFormatK) .!= (_captionFormat def) _matplotlibPrec <- v .:? (cls Matplotlib) .!= def _matlabPrec <- v .:? (cls Matlab) .!= def @@ -156,6 +161,7 @@ defaultWithSource = _defaultWithSource defaultDPI = _defaultDPI defaultSaveFormat = _defaultSaveFormat + captionFormat = _captionFormat matplotlibTightBBox = _matplotlibTightBBox _matplotlibPrec matplotlibTransparent = _matplotlibTransparent _matplotlibPrec
src/Text/Pandoc/Filter/Plot/Types.hs view
@@ -45,7 +45,7 @@ import GHC.Generics (Generic) import System.Info (os) -import Text.Pandoc.Definition (Attr) +import Text.Pandoc.Definition (Attr, Format(..)) toolkits :: [Toolkit] toolkits = enumFromTo minBound maxBound @@ -96,6 +96,7 @@ , defaultWithSource :: !Bool -- ^ The default behavior of whether or not to include links to source code and high-res , defaultDPI :: !Int -- ^ The default dots-per-inch value for generated figures. Renderers might ignore this. , defaultSaveFormat :: !SaveFormat -- ^ The default save format of generated figures. + , captionFormat :: Format -- ^ Caption format, in the same notation as Pandoc format, e.g. "markdown+tex_math_dollars" , matplotlibPreamble :: !Script -- ^ The default preamble script for the matplotlib toolkit. , plotlyPythonPreamble :: !Script -- ^ The default preamble script for the Plotly/Python toolkit. @@ -123,6 +124,7 @@ , defaultWithSource = False , defaultDPI = 80 , defaultSaveFormat = PNG + , captionFormat = Format "markdown+tex_math_dollars" , matplotlibPreamble = mempty , plotlyPythonPreamble= mempty @@ -167,6 +169,7 @@ | CaptionK | SaveFormatK | WithSourceK + | CaptionFormatK | PreambleK | DpiK | ExecutableK @@ -181,6 +184,7 @@ show CaptionK = "caption" show SaveFormatK = "format" show WithSourceK = "source" + show CaptionFormatK = "caption_format" show PreambleK = "preamble" show DpiK = "dpi" show ExecutableK = "executable"
tests/Common.hs view
@@ -31,9 +31,6 @@ import System.FilePath (takeExtensions, (</>)) import System.IO.Temp (getCanonicalTemporaryDirectory) --- Default caption format -defFmt = B.Format "markdown+tex_math_dollars" - ------------------------------------------------------------------------------- -- Test that plot files and source files are created when the filter is run testFileCreation :: Toolkit -> TestTree @@ -44,7 +41,7 @@ ensureDirectoryExistsAndEmpty tempDir let cb = (addDirectory tempDir $ codeBlock tk (trivialContent tk)) - _ <- (make tk) def defFmt cb + _ <- (make tk) def cb filesCreated <- length <$> listDirectory tempDir assertEqual "" 2 filesCreated @@ -59,7 +56,7 @@ let cb = (addPreamble (include tk) $ addDirectory tempDir $ codeBlock tk (trivialContent tk)) - _ <- (make tk) def defFmt cb + _ <- (make tk) def cb inclusion <- readFile (include tk) sourcePath <- head . filter (isExtensionOf "txt") <$> listDirectory tempDir src <- readFile (tempDir </> sourcePath) @@ -84,7 +81,7 @@ let fmt = head (supportedSaveFormats tk) cb = (addSaveFormat fmt $ addDirectory tempDir $ codeBlock tk (trivialContent tk)) - _ <- (make tk) def defFmt cb + _ <- (make tk) def cb numberjpgFiles <- length <$> filter (isExtensionOf (extension fmt)) <$> listDirectory tempDir @@ -108,8 +105,8 @@ $ addDirectory tempDir $ addCaption expected $ codeBlock tk (trivialContent tk) - blockNoSource <- (make tk) def defFmt noSource - blockWithSource <- (make tk) def defFmt withSource + blockNoSource <- (make tk) def noSource + blockWithSource <- (make tk) def withSource -- In the case where source=false, the caption is used verbatim. -- Otherwise, links will be appended to the caption; hence, the caption @@ -148,7 +145,7 @@ let cb = addDirectory tempDir $ addSaveFormat PNG $ codeBlock tk (trivialContent tk) - _ <- (make tk) config defFmt cb + _ <- (make tk) config cb numberPngFiles <- length <$> filter (isExtensionOf (extension PNG)) <$> @@ -160,12 +157,12 @@ assertEqual "" numberJpgFiles 0 ------------------------------------------------------------------------------- --- Test that Markdown formatting in captions is correctly rendered -testMarkdownFormattingCaption :: Toolkit -> TestTree -testMarkdownFormattingCaption tk = - testCase "appropriately parses captions" $ do +-- Test that Markdown bold formatting in captions is correctly rendered +testMarkdownFormattingCaption1 :: Toolkit -> TestTree +testMarkdownFormattingCaption1 tk = + testCase "appropriately parses captions 1" $ do let postfix = unpack . cls $ tk - tempDir <- (</> "test-caption-parsing-" <> postfix) <$> getCanonicalTemporaryDirectory + tempDir <- (</> "test-caption-parsing1-" <> postfix) <$> getCanonicalTemporaryDirectory ensureDirectoryExistsAndEmpty tempDir -- Note that this test is fragile, in the sense that the expected result must be carefully @@ -174,8 +171,33 @@ cb = addDirectory tempDir $ addCaption "**caption**" $ codeBlock tk (trivialContent tk) - fmt = B.Format "markdown+tex_math_dollars" - result <- (make tk) def fmt cb + fmt = B.Format "markdown" + result <- (make tk) (def {captionFormat=fmt}) cb + assertIsInfix expected (extractCaption result) + where + extractCaption (B.Para blocks) = extractImageCaption . head $ blocks + extractCaption _ = mempty + + extractImageCaption (Image _ c _) = c + extractImageCaption _ = mempty + +------------------------------------------------------------------------------- +-- Test that Markdown bold formatting in captions is correctly rendered +testMarkdownFormattingCaption2 :: Toolkit -> TestTree +testMarkdownFormattingCaption2 tk = + testCase "appropriately parses captions 2" $ do + let postfix = unpack . cls $ tk + tempDir <- (</> "test-caption-parsing2-" <> postfix) <$> getCanonicalTemporaryDirectory + ensureDirectoryExistsAndEmpty tempDir + + -- Note that this test is fragile, in the sense that the expected result must be carefully + -- constructed + let expected = [Link ("",[],[]) [Str "title"] ("https://google.com","")] + cb = addDirectory tempDir + $ addCaption "[title](https://google.com)" + $ codeBlock tk (trivialContent tk) + fmt = B.Format "markdown" + result <- (make tk) (def {captionFormat=fmt}) cb assertIsInfix expected (extractCaption result) where extractCaption (B.Para blocks) = extractImageCaption . head $ blocks
tests/Main.hs view
@@ -9,6 +9,10 @@ import Test.Tasty import Test.Tasty.HUnit +import qualified Text.Pandoc.Builder as B +import qualified Text.Pandoc.Definition as B +import Text.Pandoc.JSON + import Common import Text.Pandoc.Filter.Plot.Internal @@ -26,6 +30,9 @@ , testExampleConfiguration ] , testGroup + "Parsing tests" + [ testCaptionReader ] + , testGroup "Toolkit tests" (toolkitSuite <$> available) ] @@ -40,7 +47,8 @@ , testSaveFormat , testWithSource , testOverrideConfiguration - , testMarkdownFormattingCaption + , testMarkdownFormattingCaption1 + , testMarkdownFormattingCaption2 ] <*> [tk] @@ -67,4 +75,16 @@ } parsedConfig <- configuration "example-config.yml" - assertEqual "" config parsedConfig+ assertEqual "" config parsedConfig + +testCaptionReader :: TestTree +testCaptionReader = + testCase "caption is parsed in the same way as input document format" $ do + -- Note that this test is fragile, in the sense that the expected result must be carefully + -- constructed + let caption="Here is a [link](https://www.google.com) in a caption." + expected = Just $ [Str "Here",Space,Str "is",Space,Str "a",Space,Link ("",[],[]) [Str "link"] ("https://www.google.com",""),Space,Str "in",Space,Str "a",Space,Str "caption."] + fmt = B.Format "markdown+tex_math_dollars" + parsed = captionReader fmt caption + + assertEqual "" expected parsed