pandoc-pyplot-2.0.0.0: src/Text/Pandoc/Filter/FigureSpec.hs
{-# LANGUAGE OverloadedStrings #-}
{-|
Module : Text.Pandoc.Filter.FigureSpec
Copyright : (c) Laurent P René de Cotret, 2019
License : MIT
Maintainer : laurent.decotret@outlook.com
Stability : internal
Portability : portable
This module defines types and functions that help
with keeping track of figure specifications
-}
module Text.Pandoc.Filter.FigureSpec
( FigureSpec(..)
, SaveFormat(..)
, saveFormatFromString
, figurePath
, hiresFigurePath
, addPlotCapture
-- for testing purposes
, extension
) where
import Data.Hashable (Hashable, hash, hashWithSalt)
import qualified Data.Text as T
import System.FilePath (FilePath, addExtension,
replaceExtension, (</>))
import Text.Pandoc.Definition (Attr)
import Text.Pandoc.Filter.Scripting (PythonScript)
data SaveFormat
= PNG
| PDF
| SVG
| JPG
| EPS
-- | Parse an image save format string
saveFormatFromString :: String -> Maybe SaveFormat
saveFormatFromString s
| s `elem` ["png", "PNG", ".png"] = Just PNG
| s `elem` ["pdf", "PDF", ".pdf"] = Just PDF
| s `elem` ["svg", "SVG", ".svg"] = Just SVG
| s `elem` ["jpg", "jpeg", "JPG", "JPEG", ".jpg", ".jpeg"] = Just JPG
| s `elem` ["eps", "EPS", ".eps"] = Just EPS
| otherwise = Nothing
-- | Save format file extension
extension :: SaveFormat -> String
extension PNG = ".png"
extension PDF = ".pdf"
extension SVG = ".svg"
extension JPG = ".jpg"
extension EPS = ".eps"
-- | Datatype containing all parameters required
-- to run pandoc-pyplot
data FigureSpec = FigureSpec
{ caption :: String -- ^ Figure caption.
, script :: PythonScript -- ^ Source code for the figure.
, saveFormat :: SaveFormat -- ^ Save format of the figure
, directory :: FilePath -- ^ Directory where to save the file
, dpi :: Int -- ^ Dots-per-inch of figure
, blockAttrs :: Attr -- ^ Attributes not related to @pandoc-pyplot@ will be propagated.
}
instance Hashable FigureSpec where
hashWithSalt salt spec =
hashWithSalt salt (caption spec, script spec, directory spec, dpi spec, blockAttrs spec)
-- | Determine the path a figure should have.
figurePath :: FigureSpec -> FilePath
figurePath spec = (directory spec </> stem spec)
where
stem = flip addExtension ext . show . hash
ext = extension . saveFormat $ spec
-- | The path to the high-resolution figure.
hiresFigurePath :: FigureSpec -> FilePath
hiresFigurePath spec = flip replaceExtension (".hires" <> ext) . figurePath $ spec
where
ext = extension . saveFormat $ spec
-- | Modify a Python plotting script to save the figure to a filename.
-- An additional file (with extension PNG) will also be captured.
addPlotCapture ::
FigureSpec -- ^ Path where to save the figure
-> PythonScript -- ^ Code block with added capture
addPlotCapture spec =
mconcat
[ script spec
, "\nimport matplotlib.pyplot as plt" -- Just in case
, plotCapture (figurePath spec) (dpi spec)
, plotCapture (hiresFigurePath spec) (minimum [200, 2 * dpi spec])
]
where
plotCapture fname' dpi' =
mconcat
[ "\nplt.savefig("
, T.pack $ show fname' -- show is required for quotes
, ", dpi="
, T.pack $ show dpi'
, ")"
]