summaryrefslogtreecommitdiff
path: root/src/Text/Pandoc/Filter
diff options
context:
space:
mode:
authorLaurentRDC <>2019-06-19 01:34:00 (GMT)
committerhdiff <hdiff@hdiff.luite.com>2019-06-19 01:34:00 (GMT)
commit3776ee96691a4874ed7a12fe6ab260983de62293 (patch)
treee99b6a517bf0d9970ff81c6e382c12c4993d3955 /src/Text/Pandoc/Filter
parent2a1b2400f81e0e8df8158eacbbd3e87520373f00 (diff)
version 2.1.4.02.1.4.0
Diffstat (limited to 'src/Text/Pandoc/Filter')
-rw-r--r--src/Text/Pandoc/Filter/Pyplot.hs120
-rw-r--r--src/Text/Pandoc/Filter/Pyplot/Configuration.hs2
-rw-r--r--src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs93
-rw-r--r--src/Text/Pandoc/Filter/Pyplot/Types.hs7
4 files changed, 81 insertions, 141 deletions
diff --git a/src/Text/Pandoc/Filter/Pyplot.hs b/src/Text/Pandoc/Filter/Pyplot.hs
index ced2a30..e74bb9c 100644
--- a/src/Text/Pandoc/Filter/Pyplot.hs
+++ b/src/Text/Pandoc/Filter/Pyplot.hs
@@ -10,8 +10,8 @@ Maintainer : laurent.decotret@outlook.com
Stability : stable
Portability : portable
-This module defines a Pandoc filter @makePlot@ that can be
-used to walk over a Pandoc document and generate figures from
+This module defines a Pandoc filter @makePlot@ and related functions
+that can be used to walk over a Pandoc document and generate figures from
Python code blocks.
The syntax for code blocks is simple, Code blocks with the @.pyplot@
@@ -30,68 +30,9 @@ Here are the possible attributes what pandoc-pyplot understands:
* @caption="..."@: Specify a plot caption (or alternate text). Captions support Markdown formatting and LaTeX math (@$...$@).
* @dpi=...@: Specify a value for figure resolution, or dots-per-inch. Default is 80DPI.
* @include=...@: Path to a Python script to include before the code block. Ideal to avoid repetition over many figures.
-
-Here are some example blocks in Markdown:
-
-@
-This is a paragraph
-
-```{.pyplot caption="This is a caption."}
-import matplotlib.pyplot as plt
-
-plt.figure()
-plt.plot([0,1,2,3,4], [1,2,3,4,5])
-plt.title('This is an example figure')
-```
-
-This is another paragraph
-
-```{.pyplot dpi=150 format=SVG}
-# This example was taken from the Matplotlib gallery
-# https://matplotlib.org/examples/pylab_examples/bar_stacked.html
-
-import numpy as np
-import matplotlib.pyplot as plt
-
-N = 5
-menMeans = (20, 35, 30, 35, 27)
-womenMeans = (25, 32, 34, 20, 25)
-menStd = (2, 3, 4, 1, 2)
-womenStd = (3, 5, 2, 3, 3)
-ind = np.arange(N) # the x locations for the groups
-width = 0.35 # the width of the bars: can also be len(x) sequence
-
-p1 = plt.bar(ind, menMeans, width, color='#d62728', yerr=menStd)
-p2 = plt.bar(ind, womenMeans, width,
- bottom=menMeans, yerr=womenStd)
-
-plt.ylabel('Scores')
-plt.title('Scores by group and gender')
-plt.xticks(ind, ('G1', 'G2', 'G3', 'G4', 'G5'))
-plt.yticks(np.arange(0, 81, 10))
-plt.legend((p1[0], p2[0]), ('Men', 'Women'))
-```
-@
-
-This filter was originally designed to be used with [Hakyll](https://jaspervdj.be/hakyll/).
-In case you want to use the filter with your own Hakyll setup, you can use a transform
-function that works on entire documents:
-
-@
-import Text.Pandoc.Filter.Pyplot (plotTransform)
-
-import Hakyll
-
--- Unsafe compiler is required because of the interaction
--- in IO (i.e. running an external Python script).
-makePlotPandocCompiler :: Compiler (Item String)
-makePlotPandocCompiler =
- pandocCompilerWithTransformM
- defaultHakyllReaderOptions
- defaultHakyllWriterOptions
- (unsafeCompiler . plotTransform)
-@
-
+ * @links=true|false@: Add links to source code and high-resolution version of this figure.
+ This is @true@ by default, but you may wish to disable this for PDF output.
+
Custom configurations are possible via the @Configuration@ type and the filter
functions @plotTransformWithConfig@ and @makePlotWithConfig@.
-}
@@ -112,64 +53,15 @@ module Text.Pandoc.Filter.Pyplot (
, makePlot'
) where
-import Control.Monad ((>=>), join)
-
-import Data.List (intersperse)
+import Control.Monad ((>=>))
import Data.Default.Class (def)
-import qualified Data.Map.Strict as Map
-import Data.Maybe (fromMaybe)
-import Data.Monoid ((<>))
-import qualified Data.Text as T
-import qualified Data.Text.IO as T
-import Data.Version (showVersion)
-
-import Paths_pandoc_pyplot (version)
-
-import System.FilePath (makeValid)
import Text.Pandoc.Definition
import Text.Pandoc.Walk (walkM)
import Text.Pandoc.Filter.Pyplot.Internal
--- | Code block class that will trigger the filter
-filterClass :: String
-filterClass = "pyplot"
-
-
--- | Flexible boolean parsing
-readBool :: String -> Bool
-readBool s | s `elem` ["True", "true", "'True'", "'true'", "1"] = True
- | s `elem` ["False", "false", "'False'", "'false'", "0"] = False
- | otherwise = error $ mconcat ["Could not parse '", s, "' into a boolean. Please use 'True' or 'False'"]
-
--- | Determine inclusion specifications from Block attributes.
--- Note that the @".pyplot"@ class is required, but all other parameters are optional
-parseFigureSpec :: Configuration -> Block -> IO (Maybe FigureSpec)
-parseFigureSpec config (CodeBlock (id', cls, attrs) content)
- | filterClass `elem` cls = Just <$> figureSpec
- | otherwise = return Nothing
- where
- attrs' = Map.fromList attrs
- filteredAttrs = filter (\(k, _) -> k `notElem` inclusionKeys) attrs
- includePath = Map.lookup includePathKey attrs'
-
- figureSpec :: IO FigureSpec
- figureSpec = do
- includeScript <- fromMaybe (return $ defaultIncludeScript config) $ T.readFile <$> includePath
- let header = "# Generated by pandoc-pyplot " <> ((T.pack . showVersion) version)
- fullScript = mconcat $ intersperse "\n" [header, includeScript, T.pack content]
- caption' = Map.findWithDefault mempty captionKey attrs'
- format = fromMaybe (defaultSaveFormat config) $ join $ saveFormatFromString <$> Map.lookup saveFormatKey attrs'
- dir = makeValid $ Map.findWithDefault (defaultDirectory config) directoryKey attrs'
- dpi' = fromMaybe (defaultDPI config) $ read <$> Map.lookup dpiKey attrs'
- withLinks' = fromMaybe (defaultWithLinks config) $ readBool <$> Map.lookup withLinksKey attrs'
- blockAttrs' = (id', filter (/= filterClass) cls, filteredAttrs)
- return $ FigureSpec caption' withLinks' fullScript format dir dpi' blockAttrs'
-
-parseFigureSpec _ _ = return Nothing
-
-- | Main routine to include Matplotlib plots.
-- Code blocks containing the attributes @.pyplot@ are considered
-- Python plotting scripts. All other possible blocks are ignored.
diff --git a/src/Text/Pandoc/Filter/Pyplot/Configuration.hs b/src/Text/Pandoc/Filter/Pyplot/Configuration.hs
index c2b4152..0bc924d 100644
--- a/src/Text/Pandoc/Filter/Pyplot/Configuration.hs
+++ b/src/Text/Pandoc/Filter/Pyplot/Configuration.hs
@@ -41,7 +41,7 @@ captionKey = "caption"
dpiKey = "dpi"
includePathKey = "include"
saveFormatKey = "format"
-withLinksKey = "with-links"
+withLinksKey = "links"
-- | list of all keys related to pandoc-pyplot.
inclusionKeys :: [String]
diff --git a/src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs b/src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs
index 64b1d02..357d5a4 100644
--- a/src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs
+++ b/src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs
@@ -19,53 +19,65 @@ module Text.Pandoc.Filter.Pyplot.FigureSpec
, sourceCodePath
, figurePath
, addPlotCapture
+ , parseFigureSpec
-- for testing purposes
, extension
) where
import Control.Monad (join)
+import Data.Default.Class (def)
import Data.Hashable (hash)
+import Data.List (intersperse)
+import qualified Data.Map.Strict as Map
import Data.Maybe (fromMaybe)
import Data.Monoid ((<>))
import qualified Data.Text as T
+import qualified Data.Text.IO as T
+import Data.Version (showVersion)
+
+import Paths_pandoc_pyplot (version)
import System.FilePath (FilePath, addExtension,
- replaceExtension, (</>))
+ replaceExtension, (</>), makeValid)
import Text.Pandoc.Definition
import Text.Pandoc.Builder (imageWith, link, para, fromList, toList)
import Text.Pandoc.Class (runPure)
import Text.Pandoc.Extensions (extensionsFromList, Extension(..))
-import Text.Pandoc.Options (def, ReaderOptions(..))
+import Text.Pandoc.Options (ReaderOptions(..))
import Text.Pandoc.Readers (readMarkdown)
import Text.Pandoc.Filter.Pyplot.Types
+import Text.Pandoc.Filter.Pyplot.Configuration
-readerOptions :: ReaderOptions
-readerOptions = def
- {readerExtensions =
- extensionsFromList
- [ Ext_tex_math_dollars
- , Ext_superscript
- , Ext_subscript
- ]
- }
--- | Read a figure caption in Markdown format. LaTeX math @$...$@ is supported,
--- as are Markdown subscripts and superscripts.
-captionReader :: String -> Maybe [Inline]
-captionReader t = either (const Nothing) (Just . extractFromBlocks) $ runPure $ readMarkdown' (T.pack t)
- where
- readMarkdown' = readMarkdown readerOptions
-
- extractFromBlocks (Pandoc _ blocks) = mconcat $ extractInlines <$> blocks
-
- extractInlines (Plain inlines) = inlines
- extractInlines (Para inlines) = inlines
- extractInlines (LineBlock multiinlines) = join multiinlines
- extractInlines _ = []
+-- | Determine inclusion specifications from Block attributes.
+-- Note that the @".pyplot"@ class is required, but all other parameters are optional
+parseFigureSpec :: Configuration -> Block -> IO (Maybe FigureSpec)
+parseFigureSpec config (CodeBlock (id', cls, attrs) content)
+ | "pyplot" `elem` cls = Just <$> figureSpec
+ | otherwise = return Nothing
+ where
+ attrs' = Map.fromList attrs
+ filteredAttrs = filter (\(k, _) -> k `notElem` inclusionKeys) attrs
+ includePath = Map.lookup includePathKey attrs'
+
+ figureSpec :: IO FigureSpec
+ figureSpec = do
+ includeScript <- fromMaybe (return $ defaultIncludeScript config) $ T.readFile <$> includePath
+ let header = "# Generated by pandoc-pyplot " <> ((T.pack . showVersion) version)
+ fullScript = mconcat $ intersperse "\n" [header, includeScript, T.pack content]
+ caption' = Map.findWithDefault mempty captionKey attrs'
+ format = fromMaybe (defaultSaveFormat config) $ join $ saveFormatFromString <$> Map.lookup saveFormatKey attrs'
+ dir = makeValid $ Map.findWithDefault (defaultDirectory config) directoryKey attrs'
+ dpi' = fromMaybe (defaultDPI config) $ read <$> Map.lookup dpiKey attrs'
+ withLinks' = fromMaybe (defaultWithLinks config) $ readBool <$> Map.lookup withLinksKey attrs'
+ blockAttrs' = (id', filter (/= "pyplot") cls, filteredAttrs)
+ return $ FigureSpec caption' withLinks' fullScript format dir dpi' blockAttrs'
+
+parseFigureSpec _ _ = return Nothing
-- | Convert a FigureSpec to a Pandoc block component
toImage :: FigureSpec -> Block
@@ -120,3 +132,36 @@ addPlotCapture spec =
, T.pack $ show dpi'
, ")"
]
+
+-- | Reader options for captions.
+readerOptions :: ReaderOptions
+readerOptions = def
+ {readerExtensions =
+ extensionsFromList
+ [ Ext_tex_math_dollars
+ , Ext_superscript
+ , Ext_subscript
+ , Ext_raw_tex
+ ]
+ }
+
+-- | Read a figure caption in Markdown format. LaTeX math @$...$@ is supported,
+-- as are Markdown subscripts and superscripts.
+captionReader :: String -> Maybe [Inline]
+captionReader t = either (const Nothing) (Just . extractFromBlocks) $ runPure $ readMarkdown' (T.pack t)
+ where
+ readMarkdown' = readMarkdown readerOptions
+
+ extractFromBlocks (Pandoc _ blocks) = mconcat $ extractInlines <$> blocks
+
+ extractInlines (Plain inlines) = inlines
+ extractInlines (Para inlines) = inlines
+ extractInlines (LineBlock multiinlines) = join multiinlines
+ extractInlines _ = []
+
+
+-- | Flexible boolean parsing
+readBool :: String -> Bool
+readBool s | s `elem` ["True", "true", "'True'", "'true'", "1"] = True
+ | s `elem` ["False", "false", "'False'", "'false'", "0"] = False
+ | otherwise = error $ mconcat ["Could not parse '", s, "' into a boolean. Please use 'True' or 'False'"] \ No newline at end of file
diff --git a/src/Text/Pandoc/Filter/Pyplot/Types.hs b/src/Text/Pandoc/Filter/Pyplot/Types.hs
index dd368d4..1f1caaf 100644
--- a/src/Text/Pandoc/Filter/Pyplot/Types.hs
+++ b/src/Text/Pandoc/Filter/Pyplot/Types.hs
@@ -147,7 +147,7 @@ instance ToJSON Configuration where
-- this is for a filepath
object [ "directory" .= dir'
, "include" .= ("example.py" :: FilePath)
- , "with-links" .= withLinks'
+ , "links" .= withLinks'
, "dpi" .= dpi'
, "format" .= (toLower <$> show savefmt')
, "interpreter" .= interp'
@@ -155,7 +155,10 @@ instance ToJSON Configuration where
]
--- | Datatype containing all parameters required to run pandoc-pyplot
+-- | Datatype containing all parameters required to run pandoc-pyplot.
+--
+-- It is assumed that once a @FigureSpec@ has been created, no configuration
+-- can overload it; hence, a @FigureSpec@ completely encodes a particular figure.
data FigureSpec = FigureSpec
{ caption :: String -- ^ Figure caption.
, withLinks :: Bool -- ^ Append links to source code and high-dpi figure to caption