diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,11 @@
 
 pandoc-pyplot uses [Semantic Versioning](http://semver.org/spec/v2.0.0.html)
 
+Release 2.2.0.0
+---------------
+
+* Added support for rendering figures via the Plotly library
+
 Release 2.1.5.1
 ---------------
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,9 +1,9 @@
-# pandoc-pyplot - A Pandoc filter to generate Matplotlib figures directly in documents
+# pandoc-pyplot - A Pandoc filter to generate Matplotlib/Plotly figures directly in documents
 
-[![Hackage version](https://img.shields.io/hackage/v/pandoc-pyplot.svg)](http://hackage.haskell.org/package/pandoc-pyplot) [![Stackage version (LTS)](http://stackage.org/package/pandoc-pyplot/badge/lts)](http://stackage.org/nightly/package/pandoc-pyplot) [![Stackage version (nightly)](http://stackage.org/package/pandoc-pyplot/badge/nightly)](http://stackage.org/nightly/package/pandoc-pyplot) [![Windows Build status](https://ci.appveyor.com/api/projects/status/qbmq9cyks5jup48e?svg=true)](https://ci.appveyor.com/project/LaurentRDC/pandoc-pyplot) [![macOS and Linux Build Status](https://dev.azure.com/laurentdecotret/pandoc-pyplot/_apis/build/status/LaurentRDC.pandoc-pyplot?branchName=master)](https://dev.azure.com/laurentdecotret/pandoc-pyplot/_build/latest?definitionId=2&branchName=master) 
+[![Hackage version](https://img.shields.io/hackage/v/pandoc-pyplot.svg)](http://hackage.haskell.org/package/pandoc-pyplot) [![Stackage version (LTS)](http://stackage.org/package/pandoc-pyplot/badge/lts)](http://stackage.org/nightly/package/pandoc-pyplot) [![Windows Build status](https://ci.appveyor.com/api/projects/status/qbmq9cyks5jup48e?svg=true)](https://ci.appveyor.com/project/LaurentRDC/pandoc-pyplot) [![macOS and Linux Build Status](https://dev.azure.com/laurentdecotret/pandoc-pyplot/_apis/build/status/LaurentRDC.pandoc-pyplot?branchName=master)](https://dev.azure.com/laurentdecotret/pandoc-pyplot/_build/latest?definitionId=2&branchName=master) 
 ![GitHub](https://img.shields.io/github/license/LaurentRDC/pandoc-pyplot.svg)
 
-`pandoc-pyplot` turns Python code present in your documents into embedded Matplotlib figures.
+`pandoc-pyplot` turns Python code present in your documents into embedded figures via Matplotlib or Plotly.
 
 * [Usage](#usage)
     * [Markdown](#markdown)
@@ -14,6 +14,7 @@
     * [Link to source code and high-resolution
       figure](#link-to-source-code-and-high-resolution-figure)
     * [Including scripts](#including-scripts)
+    * [Multiple backends](#multiple-backends)
     * [No wasted work](#no-wasted-work)
     * [Compatibility with
       pandoc-crossref](#compatibility-with-pandoc-crossref)
@@ -29,7 +30,7 @@
 
 ### Markdown
 
-The filter recognizes code blocks with the `.pyplot` class present in Markdown documents. It will run the script in the associated code block in a Python interpreter and capture the generated Matplotlib figure.
+The filter recognizes code blocks with the `.pyplot` or `.plotly`  classes present in Markdown documents. It will run the script in the associated code block in a Python interpreter and capture the generated Matplotlib/Plotly figure.
 
 Here is a basic example using the scripting `matplotlib.pyplot` API:
 
@@ -175,18 +176,45 @@
 
 This `include` parameter is perfect for longer documents with many plots. Simply define the style you want in a separate script! You can also import packages this way, or define functions you often use.
 
-Customization of figures beyond what is available in `pandoc-pyplot` can also be done through the `include` script. For example, if you wanted to have transparent figures, you can do so via `matplotlib.pyplot.rcParams`:
+Customization of figures beyond what is available in `pandoc-pyplot` can also be done through the `include` script. For example, if you wanted to figures with a black background, you can do so via `matplotlib.pyplot.rcParams`:
 ```python
 import matplotlib.pyplot as plt
 
-plt.rcParams['savefig.transparent'] = True
+plt.rcParams['savefig.facecolor'] = 'k'
 ...
 ```
 You can take a look at all available `matplotlib` parameters [here](https://matplotlib.org/users/customizing.html).
 
+### Multiple backends
+
+(*new in version 2.2.0.0*) Both Matplotlib and Plotly are supported!
+
+To render Plotly figures in Markdown:
+
+~~~markdown
+```{.plotly caption="This is a Plotly figure"}
+import plotly.graph_objects as go
+figure = go.Figure(
+    data=[go.Bar(y=[2, 1, 3])],
+)
+~~~
+
+Here is the LaTeX equivalent:
+
+```latex
+\begin{minted}[caption=This is a Plotly figure]{plotly}
+import plotly.graph_objects as go
+figure = go.Figure(
+    data=[go.Bar(y=[2, 1, 3])],
+)
+\end{minted}
+```
+
+`pandoc-pyplot` will render and capture your figure automagically. 
+
 ### No wasted work
 
-`pandoc-pyplot` minimizes work, only generating figures if it absolutely must. Therefore, you can confidently run the filter on very large documents containing dozens of figures --- like a book or a thesis --- and only the figures which have recently changed will be re-generated.
+`pandoc-pyplot` minimizes work, only generating figures if it absolutely must. Therefore, you can confidently run the filter on very large documents containing dozens of figures --- like a book or a thesis --- and only the figures which have changed will be re-generated.
 
 ### Compatibility with pandoc-crossref
 
@@ -219,9 +247,9 @@
 include: mystyle.py
 format: jpeg
 links: false
-dpi: 150
-tight_bbox: true
-transparent: false
+dpi: 150            # Matplotlib only
+tight_bbox: true    # Matplotlib only
+transparent: false  # Matplotlib only
 flags: [-O, -Wignore]
 ```
 
@@ -250,8 +278,8 @@
 
 * `interpreter` is the name of the interpreter to use. For example, `interpreter: python36`;
 * `flags` is a list of strings, which are flags that are passed to the python interpreter. For example, `flags: [-O, -Wignore]`;
-* (*New in version 2.1.5.0*) `tight_bbox` is a boolean that determines whether to use `bbox_inches="tight"` or not when saving Matplotlib figures. For example, `tight_bbox: true`. See [here](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.savefig.html) for details;
-* (*New in version 2.1.5.0*) `transparent` is a boolean that determines whether to make figure background transparent or not. This is useful, for example, for displaying a plot on top of a colored background on a web page. High-resolution figures are not affected. For example, `transparent: true`.
+* (*New in version 2.1.5.0*) `tight_bbox` is a boolean that determines whether to use `bbox_inches="tight"` or not when saving Matplotlib figures. For example, `tight_bbox: true`. See [here](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.savefig.html) for details. This is ignored for Plotly figures.
+* (*New in version 2.1.5.0*) `transparent` is a boolean that determines whether to make Matplotlib figure background transparent or not. This is useful, for example, for displaying a plot on top of a colored background on a web page. High-resolution figures are not affected. For example, `transparent: true`. This is ignored for Plotly figures.
 
 ## Installation
 
@@ -295,15 +323,15 @@
 
 ### Requirements
 
-This filter only works with the Matplotlib plotting library. Therefore, you a Python interpreter and at least [Matplotlib](https://matplotlib.org/) installed. The name of the Python interpreter to use can be specified in a `.pandoc-pyplot.yml` file; by default, `pandoc-pyplot` will use the `"python"` name on Windows, and `"python3"` otherwise.
+This filter requires a Python interpreter and at least [Matplotlib](https://matplotlib.org/) or [Plotly](https://plot.ly/python/) installed. The name of the Python interpreter to use can be specified in a `.pandoc-pyplot.yml` file; by default, `pandoc-pyplot` will use the `"python"` name on Windows, and `"python3"` otherwise.
 
-You can use the filter with Pandoc as follows:
+Use the filter with Pandoc as follows:
 
 ```bash
 pandoc --filter pandoc-pyplot input.md --output output.html
 ```
 
-In which case, the output is HTML. Another example with PDF output:
+in which case, the output is HTML. Another example with PDF output:
 
 ```bash
 pandoc --filter pandoc-pyplot input.md --output output.pdf
@@ -319,7 +347,7 @@
 
 ## Usage as a Haskell library
 
-To include the functionality of `pandoc-pyplot` in a Haskell package, you can use the `makePlot :: Block -> IO Block` function (for single blocks) or `plotTransform :: Pandoc -> IO Pandoc` function (for entire documents).
+To include the functionality of `pandoc-pyplot` in a Haskell package, you can use the `makePlot :: Block -> IO Block` function (for single blocks) or `plotTransform :: Pandoc -> IO Pandoc` function (for entire documents). Variations of these functions exist for more advanced configurations. [Take a look at the documentation on Hackage](https://hackage.haskell.org/package/pandoc-pyplot).
 
 ### Usage with Hakyll
 
diff --git a/executable/Main.hs b/executable/Main.hs
--- a/executable/Main.hs
+++ b/executable/Main.hs
@@ -1,33 +1,35 @@
+{-# LANGUAGE ApplicativeDo   #-}
 {-# LANGUAGE LambdaCase      #-}
 {-# LANGUAGE TemplateHaskell #-}
-{-# LANGUAGE ApplicativeDo   #-}
 
 module Main where
 
-import           Control.Applicative       ((<|>))
-import           Control.Monad             (join)
+import           Control.Applicative                ((<|>))
+import           Control.Monad                      (join)
 
-import           Data.Default.Class        (def)
-import           Data.List                 (intersperse)
-import           Data.Monoid               ((<>))
-import qualified Data.Text                 as T
+import           Data.Default.Class                 (def)
+import           Data.List                          (intersperse)
+import           Data.Monoid                        ((<>))
+import qualified Data.Text                          as T
 
 import           Options.Applicative
-import qualified Options.Applicative.Help.Pretty as P
+import qualified Options.Applicative.Help.Pretty    as P
 
-import           System.Directory          (doesFileExist)
-import           System.IO.Temp            (writeSystemTempFile)
+import           System.Directory                   (doesFileExist)
+import           System.IO.Temp                     (writeSystemTempFile)
 
-import           Text.Pandoc.Filter.Pyplot (plotTransformWithConfig, configuration, SaveFormat(..))
+import           Text.Pandoc.Filter.Pyplot          (SaveFormat (..),
+                                                     configuration,
+                                                     plotTransformWithConfig)
 import           Text.Pandoc.Filter.Pyplot.Internal (writeConfig)
-import           Text.Pandoc.JSON          (toJSONFilter)
+import           Text.Pandoc.JSON                   (toJSONFilter)
 
-import           Web.Browser               (openBrowser)
+import           Web.Browser                        (openBrowser)
 
-import qualified Data.Version              as V
-import           Paths_pandoc_pyplot       (version)
+import qualified Data.Version                       as V
+import           Paths_pandoc_pyplot                (version)
 
-import           ManPage                   (embedManualHtml)
+import           ManPage                            (embedManualHtml)
 
 main :: IO ()
 main = join $ execParser opts
@@ -38,8 +40,8 @@
             <> header "pandoc-pyplot - generate Matplotlib figures directly in documents."
             <> footerDoc (Just footer')
             )
-    
 
+
 toJSONFilterWithConfig :: IO ()
 toJSONFilterWithConfig = do
     configExists <- doesFileExist ".pandoc-pyplot.yml"
@@ -58,28 +60,28 @@
 
 run :: Parser (IO ())
 run = do
-    versionP <- flag Nothing (Just Version) (long "version" <> short 'v' 
+    versionP <- flag Nothing (Just Version) (long "version" <> short 'v'
                     <> help "Show version number and exit.")
 
-    formatsP <- flag Nothing (Just Formats) (long "formats" <> short 'f' 
+    formatsP <- flag Nothing (Just Formats) (long "formats" <> short 'f'
                     <> help "Show supported output figure formats and exit.")
 
-    manualP  <- flag Nothing (Just Manual)  (long "manual"  <> short 'm' 
+    manualP  <- flag Nothing (Just Manual)  (long "manual"  <> short 'm'
                     <> help "Open the manual page in the default web browser and exit.")
 
-    configP  <- flag Nothing (Just Config)  (long "write-example-config" 
+    configP  <- flag Nothing (Just Config)  (long "write-example-config"
                     <> help "Write the default configuration in '.pandoc-pyplot.yml', \
                             \which you can subsequently customize, and exit. If '.pandoc-pyplot.yml' \
                             \already exists, an error will be thrown. ")
-                            
+
     input    <- optional $ strArgument (metavar "AST")
     return $ go (versionP <|> formatsP <|> manualP <|> configP) input
     where
         go :: Maybe Flag -> Maybe String -> IO ()
         go (Just Version) _ = putStrLn (V.showVersion version)
         go (Just Formats) _ = putStrLn . mconcat . intersperse ", " . fmap show $ supportedSaveFormats
-        go (Just Manual)  _ = writeSystemTempFile "pandoc-pyplot-manual.html" (T.unpack manualHtml) 
-                                >>= \fp -> openBrowser ("file:///" <> fp) 
+        go (Just Manual)  _ = writeSystemTempFile "pandoc-pyplot-manual.html" (T.unpack manualHtml)
+                                >>= \fp -> openBrowser ("file:///" <> fp)
                                 >> return ()
         go (Just Config) _  = writeConfig ".pandoc-pyplot.yml" def
         go Nothing _ = toJSONFilterWithConfig
@@ -108,4 +110,4 @@
     , P.line
     , P.indent 4 $ P.text "https://github.com/LaurentRDC/pandoc-pyplot"
     , P.line
-    ]
+    ]
diff --git a/pandoc-pyplot.cabal b/pandoc-pyplot.cabal
--- a/pandoc-pyplot.cabal
+++ b/pandoc-pyplot.cabal
@@ -1,8 +1,8 @@
 name:           pandoc-pyplot
-version:        2.1.5.1
+version:        2.2.0.0
 cabal-version:  >= 1.12
 synopsis:       A Pandoc filter to include figures generated from Python code blocks
-description:    A Pandoc filter to include figures generated from Python code blocks. Keep the document and Python code in the same location. Output from Matplotlib is captured and included as a figure.
+description:    A Pandoc filter to include figures generated from Python code blocks. Keep the document and Python code in the same location. Output is captured and included as a figure.
 category:       Documentation
 homepage:       https://github.com/LaurentRDC/pandoc-pyplot#readme
 bug-reports:    https://github.com/LaurentRDC/pandoc-pyplot/issues
@@ -44,10 +44,12 @@
         , hashable           >= 1     && < 2
         , pandoc             >= 2     && < 3
         , pandoc-types       >=1.12   && < 2
+        , shakespeare        >= 2.0   && < 3
         , temporary
         , text               >= 1     && < 2
         , typed-process      >= 0.2.1 && < 1
-        , yaml >= 0.8.16
+        , yaml               >= 0.8   && < 1
+        , mtl                >= 2.2   && < 2.3
     default-language: Haskell2010
 
 executable pandoc-pyplot
@@ -91,5 +93,6 @@
                    , tasty-hspec
                    , temporary
                    , text
+                   , mtl                >= 2.2   && < 2.3
     default-language: Haskell2010
   
diff --git a/src/Text/Pandoc/Filter/Pyplot.hs b/src/Text/Pandoc/Filter/Pyplot.hs
--- a/src/Text/Pandoc/Filter/Pyplot.hs
+++ b/src/Text/Pandoc/Filter/Pyplot.hs
@@ -2,42 +2,43 @@
 {-# LANGUAGE OverloadedStrings #-}
 
 {-|
-Module      : Text.Pandoc.Filter.Pyplot
-Description : Pandoc filter to create Matplotlib figures from code blocks
+Module      : $header$
+Description : Pandoc filter to create Matplotlib/Plotly figures from code blocks
 Copyright   : (c) Laurent P René de Cotret, 2019
 License     : MIT
 Maintainer  : laurent.decotret@outlook.com
 Stability   : stable
 Portability : portable
 
-This module defines a Pandoc filter @makePlot@ and related functions 
+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@
+The syntax for code blocks is simple, Code blocks with the @.pyplot@ or @.plotly@
 attribute will trigger the filter. The code block will be reworked into a Python
 script and the output figure will be captured, along with a high-resolution version
 of the figure and the source code used to generate the figure.
 
-To trigger pandoc-pyplot, the following is __required__:
+To trigger pandoc-pyplot, one of the following is __required__:
 
-    * @.pyplot@: Trigger pandoc-pyplot but let it decide on a filename
+    * @.pyplot@: Trigger pandoc-pyplot, rendering via the Matplotlib library
+    * @.plotly@: Trigger pandoc-pyplot, rendering via the Plotly library
 
 Here are the possible attributes what pandoc-pyplot understands:
 
     * @directory=...@ : Directory where to save the figure.
     * @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 support Markdown formatting and LaTeX math (@$...$@).
-    * @dpi=...@: Specify a value for figure resolution, or dots-per-inch. Default is 80DPI.
+    * @dpi=...@: Specify a value for figure resolution, or dots-per-inch. Default is 80DPI. (Matplotlib only, ignored otherwise)
     * @include=...@: Path to a Python script to include before the code block. Ideal to avoid repetition over many figures.
-    * @links=true|false@: Add links to source code and high-resolution version of this figure. 
+    * @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@. 
+
+Custom configurations are possible via the @Configuration@ type and the filter
+functions @plotTransformWithConfig@ and @makePlotWithConfig@.
 -}
 module Text.Pandoc.Filter.Pyplot (
-    -- * Operating on single Pandoc blocks 
+    -- * Operating on single Pandoc blocks
       makePlot
     , makePlotWithConfig
     -- * Operating on whole Pandoc documents
@@ -53,25 +54,25 @@
     , makePlot'
     ) where
 
-import           Control.Monad                 ((>=>))
+import           Control.Monad.Reader
 
-import           Data.Default.Class            (def)
+import           Data.Default.Class                 (def)
 
 import           Text.Pandoc.Definition
-import           Text.Pandoc.Walk              (walkM)
+import           Text.Pandoc.Walk                   (walkM)
 
 import           Text.Pandoc.Filter.Pyplot.Internal
 
 -- | Main routine to include Matplotlib plots.
 -- Code blocks containing the attributes @.pyplot@ are considered
 -- Python plotting scripts. All other possible blocks are ignored.
-makePlot' :: Configuration -> Block -> IO (Either PandocPyplotError Block)
-makePlot' config block = do
-    parsed <- parseFigureSpec config block  
-    case parsed of
-        Nothing   -> return $ Right block
-        Just spec -> handleResult spec <$> runScriptIfNecessary config spec
-
+makePlot' :: Block -> PyplotM (Either PandocPyplotError Block)
+makePlot' block = do
+    parsed <- parseFigureSpec block
+    maybe
+        (return $ Right block)
+        (\s -> handleResult s <$> runScriptIfNecessary s)
+        parsed
     where
         handleResult _ (ScriptChecksFailed msg) = Left  $ ScriptChecksFailedError msg
         handleResult _ (ScriptFailure code)     = Left  $ ScriptError code
@@ -87,7 +88,8 @@
 --
 -- @since 2.1.0.0
 makePlotWithConfig :: Configuration -> Block -> IO Block
-makePlotWithConfig config = makePlot' config >=> either (fail . show) return
+makePlotWithConfig config block =
+    runReaderT (makePlot' block >>= either (fail . show) return) config
 
 -- | Walk over an entire Pandoc document, changing appropriate code blocks
 -- into figures. Default configuration is used.
diff --git a/src/Text/Pandoc/Filter/Pyplot/Configuration.hs b/src/Text/Pandoc/Filter/Pyplot/Configuration.hs
--- a/src/Text/Pandoc/Filter/Pyplot/Configuration.hs
+++ b/src/Text/Pandoc/Filter/Pyplot/Configuration.hs
@@ -1,6 +1,6 @@
 {-# LANGUAGE OverloadedStrings #-}
 {-|
-Module      : Text.Pandoc.Filter.Pyplot.Configuration
+Module      : $header$
 Copyright   : (c) Laurent P René de Cotret, 2019
 License     : MIT
 Maintainer  : laurent.decotret@outlook.com
@@ -25,23 +25,23 @@
     , isTransparentKey
 ) where
 
-import           Data.Maybe                    (fromMaybe)
-import           Data.Default.Class            (def)
-import qualified Data.Text                     as T
-import qualified Data.Text.IO                  as T
-import           Data.Yaml         
-import           Data.Yaml.Config              (loadYamlSettings, ignoreEnv)
+import           Data.Default.Class              (def)
+import           Data.Maybe                      (fromMaybe)
+import qualified Data.Text                       as T
+import qualified Data.Text.IO                    as T
+import           Data.Yaml
+import           Data.Yaml.Config                (ignoreEnv, loadYamlSettings)
 
-import           System.Directory              (doesFileExist)
+import           System.Directory                (doesFileExist)
 
-import Text.Pandoc.Filter.Pyplot.Types
+import           Text.Pandoc.Filter.Pyplot.Types
 
--- A @Configuration@ cannot be directly created from a YAML file
+-- | A @Configuration@ cannot be directly created from a YAML file
 -- for two reasons:
 --
---     * we want to store an include script. However, it makes more sense to 
+--     * we want to store an include script. However, it makes more sense to
 --       specify the script path in a YAML file.
---     * Save format is best specified by a string, and this must be parsed later 
+--     * Save format is best specified by a string, and this must be parsed later
 --
 -- Therefore, we have another type, ConfigPrecursor, which CAN be created directly from
 -- a YAML file.
@@ -56,36 +56,39 @@
         , transparent_        :: Bool
         , interpreter_        :: String
         , flags_              :: [String]
-        } 
+        }
 
 instance FromJSON ConfigPrecursor where
-    parseJSON (Object v) = ConfigPrecursor
-        <$> v .:? (T.pack directoryKey)     .!= (defaultDirectory def)
-        <*> v .:? (T.pack includePathKey)
-        <*> v .:? (T.pack withLinksKey)     .!= (defaultWithLinks def)
-        <*> v .:? (T.pack saveFormatKey)    .!= (extension $ defaultSaveFormat def)
-        <*> v .:? (T.pack dpiKey)           .!= (defaultDPI def)
-        <*> v .:? (T.pack isTightBboxKey)   .!= (isTightBbox def)
-        <*> v .:? (T.pack isTransparentKey) .!= (isTransparent def)
-        <*> v .:? "interpreter"             .!= (interpreter def)
-        <*> v .:? "flags"                   .!= (flags def)
-    
+    parseJSON (Object v) =
+        ConfigPrecursor
+            <$> v .:? (T.pack directoryKey)     .!= (defaultDirectory def)
+            <*> v .:? (T.pack includePathKey)
+            <*> v .:? (T.pack withLinksKey)     .!= (defaultWithLinks def)
+            <*> v .:? (T.pack saveFormatKey)    .!= (extension $ defaultSaveFormat def)
+            <*> v .:? (T.pack dpiKey)           .!= (defaultDPI def)
+            <*> v .:? (T.pack isTightBboxKey)   .!= (isTightBbox def)
+            <*> v .:? (T.pack isTransparentKey) .!= (isTransparent def)
+            <*> v .:? "interpreter"             .!= (interpreter def)
+            <*> v .:? "flags"                   .!= (flags def)
+
     parseJSON _ = fail "Could not parse the configuration"
 
+    
 renderConfiguration :: ConfigPrecursor -> IO Configuration
 renderConfiguration prec = do
     includeScript <- fromMaybe mempty $ T.readFile <$> defaultIncludePath_ prec
     let saveFormat' = fromMaybe (defaultSaveFormat def) $ saveFormatFromString $ defaultSaveFormat_ prec
-    return $ Configuration { defaultDirectory     = defaultDirectory_ prec
-                           , defaultIncludeScript = includeScript
-                           , defaultSaveFormat    = saveFormat'
-                           , defaultWithLinks     = defaultWithLinks_ prec
-                           , defaultDPI           = defaultDPI_ prec
-                           , isTightBbox          = tightBbox_ prec
-                           , isTransparent        = transparent_ prec
-                           , interpreter          = interpreter_ prec
-                           , flags                = flags_ prec
-                           }
+    return $ Configuration
+        { defaultDirectory     = defaultDirectory_ prec
+        , defaultIncludeScript = includeScript
+        , defaultSaveFormat    = saveFormat'
+        , defaultWithLinks     = defaultWithLinks_ prec
+        , defaultDPI           = defaultDPI_ prec
+        , isTightBbox          = tightBbox_ prec
+        , isTransparent        = transparent_ prec
+        , interpreter          = interpreter_ prec
+        , flags                = flags_ prec
+        }
 
 
 -- | Building configuration from a YAML file. The
@@ -107,4 +110,4 @@
     fileExists <- doesFileExist fp
     if fileExists
         then error $ mconcat ["File ", fp, " already exists."]
-        else encodeFile fp config
+        else encodeFile fp config
diff --git a/src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs b/src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs
--- a/src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs
+++ b/src/Text/Pandoc/Filter/Pyplot/FigureSpec.hs
@@ -1,7 +1,10 @@
-{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE OverloadedStrings    #-}
+{-# LANGUAGE QuasiQuotes          #-}
+{-# LANGUAGE TemplateHaskell      #-}
+{-# LANGUAGE TypeSynonymInstances #-}
 
 {-|
-Module      : Text.Pandoc.Filter.Pyplot.FigureSpec
+Module      : $header$
 Copyright   : (c) Laurent P René de Cotret, 2019
 License     : MIT
 Maintainer  : laurent.decotret@outlook.com
@@ -24,48 +27,59 @@
     , extension
     ) where
 
-import           Control.Monad                (join)
+import           Control.Monad                   (join)
+import           Control.Monad.IO.Class          (liftIO)
+import           Control.Monad.Reader
 
-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           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           Paths_pandoc_pyplot             (version)
 
-import           System.FilePath              (FilePath, addExtension,
-                                               replaceExtension, (</>), makeValid)
+import           System.FilePath                 (FilePath, addExtension,
+                                                  makeValid, normalise,
+                                                  replaceExtension, (</>))
 
-import           Text.Pandoc.Definition       
-import           Text.Pandoc.Builder          (imageWith, link, para, fromList, toList)
+import           Text.Pandoc.Builder             (fromList, imageWith, link,
+                                                  para, toList)
+import           Text.Pandoc.Definition
+import           Text.Shakespeare.Text           (st)
 
-import           Text.Pandoc.Class            (runPure)
-import           Text.Pandoc.Extensions       (extensionsFromList, Extension(..))
-import           Text.Pandoc.Options          (ReaderOptions(..))
-import           Text.Pandoc.Readers          (readMarkdown)
+import           Text.Pandoc.Class               (runPure)
+import           Text.Pandoc.Extensions          (Extension (..),
+                                                  extensionsFromList)
+import           Text.Pandoc.Options             (ReaderOptions (..))
+import           Text.Pandoc.Readers             (readMarkdown)
 
-import Text.Pandoc.Filter.Pyplot.Types
+import           Text.Pandoc.Filter.Pyplot.Types
 
 
 -- | 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
+-- Note that the @".pyplot"@ OR @.plotly@ class is required, but all other
+-- parameters are optional.
+parseFigureSpec :: Block -> PyplotM (Maybe FigureSpec)
+parseFigureSpec (CodeBlock (id', cls, attrs) content)
+    | "pyplot" `elem` cls = Just <$> figureSpec Matplotlib
+    | "plotly" `elem` cls = Just <$> figureSpec Plotly
     | 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
+    figureSpec :: RenderingLibrary -> PyplotM FigureSpec
+    figureSpec lib = do
+        config <- ask
+        includeScript <- fromMaybe
+                            (return $ defaultIncludeScript config)
+                            ((liftIO . 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'
@@ -75,12 +89,22 @@
             withLinks'   = fromMaybe (defaultWithLinks config) $ readBool <$> Map.lookup withLinksKey attrs'
             tightBbox'   = isTightBbox config
             transparent' = isTransparent config
-            blockAttrs'  = (id', filter (/= "pyplot") cls, filteredAttrs)
-        return $ FigureSpec caption' withLinks' fullScript format dir dpi' tightBbox' transparent' blockAttrs'
-    
-parseFigureSpec _ _ = return Nothing
+            blockAttrs'  = (id', filter (\c -> c `notElem` ["pyplot", "plotly"]) cls, filteredAttrs)
+        return $ FigureSpec
+                    caption'
+                    withLinks'
+                    fullScript
+                    format
+                    dir
+                    dpi'
+                    lib
+                    tightBbox'
+                    transparent'
+                    blockAttrs'
 
+parseFigureSpec _ = return Nothing
 
+
 -- | Convert a FigureSpec to a Pandoc block component
 toImage :: FigureSpec -> Block
 toImage spec = head . toList $ para $ imageWith attrs' target' "fig:" caption'
@@ -91,7 +115,7 @@
         attrs'       = blockAttrs spec
         target'      = figurePath spec
         withLinks'   = withLinks spec
-        srcLink      = link (replaceExtension target' ".txt") mempty "Source code" 
+        srcLink      = link (replaceExtension target' ".txt") mempty "Source code"
         hiresLink    = link (hiresFigurePath spec) mempty "high res."
         captionText  = fromList $ fromMaybe mempty (captionReader $ caption spec)
         captionLinks = mconcat [" (", srcLink, ", ", hiresLink, ")"]
@@ -100,7 +124,7 @@
 
 -- | Determine the path a figure should have.
 figurePath :: FigureSpec -> FilePath
-figurePath spec = directory spec </> stem spec
+figurePath spec = normalise $ directory spec </> stem spec
   where
     stem = flip addExtension ext . show . hash
     ext  = extension . saveFormat $ spec
@@ -108,12 +132,12 @@
 
 -- | Determine the path to the source code that generated the figure.
 sourceCodePath :: FigureSpec -> FilePath
-sourceCodePath = flip replaceExtension ".txt" . figurePath
+sourceCodePath = normalise . flip replaceExtension ".txt" . figurePath
 
 
 -- | The path to the high-resolution figure.
 hiresFigurePath :: FigureSpec -> FilePath
-hiresFigurePath spec = flip replaceExtension (".hires" <> ext) . figurePath $ spec
+hiresFigurePath spec = normalise $ flip replaceExtension (".hires" <> ext) . figurePath $ spec
   where
     ext = extension . saveFormat $ spec
 
@@ -122,41 +146,62 @@
 -- An additional file 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
+addPlotCapture spec = mconcat
+        [ script spec <> "\n"
         -- Note that the high-resolution figure always has non-transparent background
-        -- because it is difficult to see the image when opened directly 
+        -- because it is difficult to see the image when opened directly
         -- in Chrome, for example.
-        , plotCapture (figurePath spec) (dpi spec) (transparent spec)
-        , plotCapture (hiresFigurePath spec) (minimum [200, 2 * dpi spec]) False
+        , plotCapture (renderingLib spec) (figurePath spec) (dpi spec) (transparent spec) (tight')
+        , plotCapture (renderingLib spec) (hiresFigurePath spec) (minimum [200, 2 * dpi spec]) False (tight')
         ]
   where
-    tight' = tightBbox spec
-    plotCapture fname' dpi' transparent' = mconcat $ 
-        [ "\nplt.savefig("
-        , T.pack $ show fname' -- show is required for quotes
-        , ", dpi="
-        , T.pack $ show dpi'
-        , ", transparent="
-        , T.pack $ show transparent'
-        , if tight' 
-            then ", bbox_inches=\"tight\")"
-            else ")"
-        ]
+    tight' = if tightBbox spec then ("'tight'" :: T.Text) else ("None" :: T.Text)
+    -- Note that, especially for Windows, raw strings (r"...") must be used because path separators might
+    -- be interpreted as escape characters
+    plotCapture Matplotlib = captureMatplotlib
+    plotCapture Plotly     = capturePlotly
 
 
+type Tight = T.Text
+type IsTransparent = Bool
+type RenderingFunc = (FilePath -> Int -> IsTransparent -> Tight -> PythonScript)
+
+
+-- | Capture plot from Matplotlib
+-- Note that, especially for Windows, raw strings (r"...") must be used because path separators might
+-- be interpreted as escape characters
+captureMatplotlib :: RenderingFunc
+captureMatplotlib fname' dpi' transparent' tight' = [st|
+import matplotlib.pyplot as plt
+plt.savefig(r"#{fname'}", dpi=#{dpi'}, transparent=#{transparent''}, bbox_inches=#{tight'})
+|]
+    where
+        transparent'' :: T.Text
+        transparent'' = if transparent' then "True" else "False"
+
+-- | Capture Plotly figure
+--
+-- We are trying to emulate the behavior of "matplotlib.pyplot.savefig" which
+-- knows the "current figure". This saves us from contraining users to always
+-- have the same Plotly figure name, e.g. "fig" in all examples
+capturePlotly :: RenderingFunc
+capturePlotly fname' _ _ _ = [st|
+import plotly.graph_objects as go
+__current_plotly_figure = next(obj for obj in globals().values() if type(obj) == go.Figure)
+__current_plotly_figure.write_image("#{fname'}")
+|]
+
+
 -- | Reader options for captions.
 readerOptions :: ReaderOptions
-readerOptions = def 
-    {readerExtensions = 
-        extensionsFromList 
+readerOptions = def
+    {readerExtensions =
+        extensionsFromList
             [ Ext_tex_math_dollars
-            , Ext_superscript 
+            , Ext_superscript
             , Ext_subscript
             , Ext_raw_tex
-            ] 
+            ]
     }
 
 
@@ -169,14 +214,14 @@
 
         extractFromBlocks (Pandoc _ blocks) = mconcat $ extractInlines <$> blocks
 
-        extractInlines (Plain inlines) = inlines
-        extractInlines (Para inlines) = inlines
+        extractInlines (Plain inlines)          = inlines
+        extractInlines (Para inlines)           = inlines
         extractInlines (LineBlock multiinlines) = join multiinlines
-        extractInlines _ = []
+        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'"] 
+           | otherwise = error $ mconcat ["Could not parse '", s, "' into a boolean. Please use 'True' or 'False'"]
diff --git a/src/Text/Pandoc/Filter/Pyplot/Internal.hs b/src/Text/Pandoc/Filter/Pyplot/Internal.hs
--- a/src/Text/Pandoc/Filter/Pyplot/Internal.hs
+++ b/src/Text/Pandoc/Filter/Pyplot/Internal.hs
@@ -1,6 +1,6 @@
 
 {-|
-Module      : Text.Pandoc.Filter.Internal
+Module      : $header$
 Copyright   : (c) Laurent P René de Cotret, 2019
 License     : MIT
 Maintainer  : laurent.decotret@outlook.com
@@ -17,7 +17,7 @@
     , module Text.Pandoc.Filter.Pyplot.Types
  ) where
 
-import Text.Pandoc.Filter.Pyplot.Configuration
-import Text.Pandoc.Filter.Pyplot.FigureSpec
-import Text.Pandoc.Filter.Pyplot.Scripting
-import Text.Pandoc.Filter.Pyplot.Types
+import           Text.Pandoc.Filter.Pyplot.Configuration
+import           Text.Pandoc.Filter.Pyplot.FigureSpec
+import           Text.Pandoc.Filter.Pyplot.Scripting
+import           Text.Pandoc.Filter.Pyplot.Types
diff --git a/src/Text/Pandoc/Filter/Pyplot/Scripting.hs b/src/Text/Pandoc/Filter/Pyplot/Scripting.hs
--- a/src/Text/Pandoc/Filter/Pyplot/Scripting.hs
+++ b/src/Text/Pandoc/Filter/Pyplot/Scripting.hs
@@ -1,7 +1,7 @@
 {-# LANGUAGE OverloadedStrings #-}
 
 {-|
-Module      : Text.Pandoc.Filter.Pyplot.Scripting
+Module      : $header$
 Copyright   : (c) Laurent P René de Cotret, 2019
 License     : MIT
 Maintainer  : laurent.decotret@outlook.com
@@ -16,58 +16,63 @@
     , runScriptIfNecessary
     ) where
 
-import           Data.Hashable        (hash)
-import           Data.List            (intersperse)
-import           Data.Monoid          (Any(..), (<>))
-import qualified Data.Text            as T
-import qualified Data.Text.IO         as T
+import           Control.Monad.IO.Class
+import           Control.Monad.Reader.Class
 
-import           System.Directory     (createDirectoryIfMissing,
-                                      doesFileExist)
-import           System.Exit          (ExitCode (..))
-import           System.FilePath      ((</>), takeDirectory)
-import           System.IO.Temp       (getCanonicalTemporaryDirectory)
-import           System.Process.Typed (runProcess, shell)
+import           Data.Hashable                        (hash)
+import           Data.List                            (intersperse)
+import           Data.Monoid                          (Any (..), (<>))
+import qualified Data.Text                            as T
+import qualified Data.Text.IO                         as T
 
-import           Text.Pandoc.Filter.Pyplot.Types
+import           System.Directory                     (createDirectoryIfMissing,
+                                                       doesFileExist)
+import           System.Exit                          (ExitCode (..))
+import           System.FilePath                      (takeDirectory, (</>))
+import           System.IO.Temp                       (getCanonicalTemporaryDirectory)
+import           System.Process.Typed                 (runProcess, shell)
+
 import           Text.Pandoc.Filter.Pyplot.FigureSpec
+import           Text.Pandoc.Filter.Pyplot.Types
 
 -- | Detect the presence of a blocking show call, for example "plt.show()"
 checkBlockingShowCall :: PythonScript -> CheckResult
-checkBlockingShowCall script' = 
-    if hasShowCall 
+checkBlockingShowCall script' =
+    if hasShowCall
         then CheckFailed "The script has a blocking call to `matplotlib.pyplot.show`. "
-        else CheckPassed 
+        else CheckPassed
     where
         scriptLines = T.lines script'
         hasShowCall = getAny $ mconcat $ Any <$>
             [ "plt.show()" `elem` scriptLines
             , "pyplot.show()" `elem` scriptLines
             , "matplotlib.pyplot.show()" `elem` scriptLines
+            , "fig.show()" `elem` scriptLines
             ]
 
+
 -- | List of all script checks
 -- This might be overkill right now but extension to other languages will be easier
 scriptChecks :: [PythonScript -> CheckResult]
 scriptChecks = [checkBlockingShowCall]
 
+
 -- | Take a python script in string form, write it in a temporary directory,
 -- then execute it.
-runTempPythonScript :: String          -- ^ Interpreter (e.g. "python" or "python35")
-                    -> [String]        -- ^ Command-line flags
-                    -> PythonScript    -- ^ Content of the script
-                    -> IO ScriptResult -- ^ Result.
-runTempPythonScript interpreter' flags' script' =  case checkResult of
+runTempPythonScript :: PythonScript         -- ^ Content of the script
+                    -> PyplotM ScriptResult -- ^ Result.
+runTempPythonScript script' =  case checkResult of
     CheckFailed msg -> return $ ScriptChecksFailed msg
     CheckPassed -> do
         -- We involve the script hash as a temporary filename
         -- so that there is never any collision
-        scriptPath <- (</> hashedPath) <$> getCanonicalTemporaryDirectory
-        T.writeFile scriptPath script'
-
+        scriptPath <- liftIO $ (</> hashedPath) <$> getCanonicalTemporaryDirectory
+        liftIO $ T.writeFile scriptPath script'
+        interpreter' <- asks interpreter
+        flags' <- asks flags
         let command = mconcat . intersperse " " $ [interpreter'] <> flags' <> [show scriptPath]
 
-        ec <- runProcess . shell $ command
+        ec <- liftIO $ runProcess . shell $ command
         case ec of
             ExitSuccess      -> return   ScriptSuccess
             ExitFailure code -> return $ ScriptFailure code
@@ -75,21 +80,25 @@
         checkResult = mconcat $ scriptChecks <*> [script']
         hashedPath = show . hash $ script'
 
+        
 -- | Run the Python script. In case the file already exists, we can safely assume
 -- there is no need to re-run it.
-runScriptIfNecessary :: Configuration -> FigureSpec -> IO ScriptResult
-runScriptIfNecessary config spec = do
-    createDirectoryIfMissing True . takeDirectory $ figurePath spec
+runScriptIfNecessary :: FigureSpec
+                     -> PyplotM ScriptResult
+runScriptIfNecessary spec = do
+    liftIO $ createDirectoryIfMissing True . takeDirectory $ figurePath spec
 
-    fileAlreadyExists <- doesFileExist $ figurePath spec
+    fileAlreadyExists <- liftIO . doesFileExist $ figurePath spec
     result <- if fileAlreadyExists
                 then return ScriptSuccess
-                else runTempPythonScript (interpreter config) (flags config) scriptWithCapture
-    
+                else runTempPythonScript scriptWithCapture
+
     case result of
-        ScriptSuccess      -> T.writeFile (sourceCodePath spec) (script spec) >> return ScriptSuccess
+        ScriptSuccess      -> liftIO $ T.writeFile (sourceCodePath spec) (script spec) >> return ScriptSuccess
         ScriptFailure code -> return $ ScriptFailure code
         ScriptChecksFailed msg -> return $ ScriptChecksFailed msg
 
     where
-        scriptWithCapture = addPlotCapture spec
+        scriptWithCapture = addPlotCapture spec
+
+
diff --git a/src/Text/Pandoc/Filter/Pyplot/Types.hs b/src/Text/Pandoc/Filter/Pyplot/Types.hs
--- a/src/Text/Pandoc/Filter/Pyplot/Types.hs
+++ b/src/Text/Pandoc/Filter/Pyplot/Types.hs
@@ -1,8 +1,8 @@
 {-# LANGUAGE CPP               #-}
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE DeriveGeneric     #-}
+{-# LANGUAGE OverloadedStrings #-}
 {-|
-Module      : Text.Pandoc.Filter.Pyplot.Types
+Module      : $header$
 Copyright   : (c) Laurent P René de Cotret, 2019
 License     : MIT
 Maintainer  : laurent.decotret@outlook.com
@@ -14,18 +14,20 @@
 
 module Text.Pandoc.Filter.Pyplot.Types where
 
-import Data.Char              (toLower)
-import Data.Default.Class     (Default, def)
-import Data.Hashable          (Hashable)
-import Data.Semigroup         as Sem
-import Data.Text              (Text, pack)
-import Data.Yaml
+import           Control.Monad.Reader
 
-import GHC.Generics           (Generic)
+import           Data.Char              (toLower)
+import           Data.Default.Class     (Default, def)
+import           Data.Hashable          (Hashable)
+import           Data.Semigroup         as Sem
+import           Data.Text              (Text, pack)
+import           Data.Yaml
 
-import Text.Pandoc.Definition (Attr)   
+import           GHC.Generics           (Generic)
 
+import           Text.Pandoc.Definition (Attr)
 
+
 -- | Keys that pandoc-pyplot will look for in code blocks. These are only exported for testing purposes.
 directoryKey, captionKey, dpiKey, includePathKey, saveFormatKey, withLinksKey, isTightBboxKey, isTransparentKey :: String
 directoryKey     = "directory"
@@ -37,7 +39,8 @@
 isTightBboxKey   = "tight_bbox"
 isTransparentKey = "transparent"
 
--- | list of all keys related to pandoc-pyplot that 
+
+-- | list of all keys related to pandoc-pyplot that
 -- can be specified in source material.
 inclusionKeys :: [String]
 inclusionKeys = [ directoryKey
@@ -51,10 +54,25 @@
                 ]
 
 
+-- | Monad in which to run pandoc-pyplot computations
+type PyplotM a = ReaderT Configuration IO a
+
+
 -- | String representation of a Python script
 type PythonScript = Text
 
 
+-- | Rendering library
+--
+-- @since 2.2.0.0
+data RenderingLibrary
+    = Matplotlib -- ^ Rendering via the Matplotlib library. This library has the most features.
+    | Plotly     -- ^ Rendering via the Plotly library.
+    deriving (Show, Eq, Generic)
+
+instance Hashable RenderingLibrary
+
+
 -- | Possible result of running a Python script
 data ScriptResult
     = ScriptSuccess
@@ -63,19 +81,19 @@
 
 
 -- | Result of checking scripts for problems
-data CheckResult 
+data CheckResult
     = CheckPassed
     | CheckFailed String
     deriving (Eq)
 
 instance Sem.Semigroup CheckResult where
-    (<>) CheckPassed a = a
-    (<>) a CheckPassed = a
+    (<>) CheckPassed a                         = a
+    (<>) a CheckPassed                         = a
     (<>) (CheckFailed msg1) (CheckFailed msg2) = CheckFailed (msg1 <> msg2)
 
 instance Monoid CheckResult where
     mempty = CheckPassed
-    
+
 #if !(MIN_VERSION_base(4,11,0))
     mappend = (<>)
 #endif
@@ -86,13 +104,15 @@
     = ScriptError Int                 -- ^ Running Python script has yielded an error
     | ScriptChecksFailedError String  -- ^ Python script did not pass all checks
     deriving (Eq)
-    
+
 instance Show PandocPyplotError where
     show (ScriptError exitcode)        = "Script error: plot could not be generated. Exit code " <> (show exitcode)
     show (ScriptChecksFailedError msg) = "Script did not pass all checks: " <> msg
 
 
--- | Generated figure file format supported by pandoc-pyplot. 
+-- | Generated figure file format supported by pandoc-pyplot.
+-- Note: all formats are supported by Matplotlib, but not all
+-- formats are supported by Plotly
 data SaveFormat
     = PNG
     | PDF
@@ -130,7 +150,7 @@
 extension :: SaveFormat -> String
 extension fmt = mconcat [".", fmap toLower . show $ fmt]
 
--- | Default interpreter should be Python 3, which has a different 
+-- | Default interpreter should be Python 3, which has a different
 -- name on Windows ("python") vs Unix ("python3")
 --
 -- @since 2.1.2.0
@@ -142,21 +162,21 @@
 #endif
 
 -- | Configuration of pandoc-pyplot, describing the default behavior
--- of the filter. 
+-- of the filter.
 --
 -- A Configuration is useful when dealing with lots of figures; it avoids
 -- repeating the same values.sta
--- 
+--
 -- @since 2.1.0.0
-data Configuration 
-    = Configuration 
+data Configuration
+    = Configuration
         { defaultDirectory     :: FilePath     -- ^ The default directory where figures will be saved.
         , defaultIncludeScript :: PythonScript -- ^ The default script to run before other instructions.
         , defaultWithLinks     :: Bool         -- ^ The default behavior of whether or not to include links to source code and high-res
         , defaultSaveFormat    :: SaveFormat   -- ^ The default save format of generated figures.
-        , defaultDPI           :: Int          -- ^ The default dots-per-inch value for generated figures.
-        , isTightBbox          :: Bool         -- ^ Whether the figures should be saved with @bbox_inches="tight"@ or not. Useful for larger figures with subplots.
-        , isTransparent        :: Bool         -- ^ If True, figures will be saved with transparent background rather than solid color.
+        , defaultDPI           :: Int          -- ^ The default dots-per-inch value for generated figures. Matplotlib only, ignored otherwise.
+        , isTightBbox          :: Bool         -- ^ Whether the figures should be saved with @bbox_inches="tight"@ or not. Useful for larger figures with subplots. Matplotlib only, ignored otherwise.
+        , isTransparent        :: Bool         -- ^ If True, figures will be saved with transparent background rather than solid color. .Matplotlib only, ignored otherwise.
         , interpreter          :: String       -- ^ The name of the interpreter to use to render figures.
         , flags                :: [String]     -- ^ Command-line flags to be passed to the Python interpreger, e.g. ["-O", "-Wignore"]
         }
@@ -176,35 +196,36 @@
     }
 
 instance ToJSON Configuration where
-    toJSON (Configuration dir' _ withLinks' savefmt' dpi' tightbbox' transparent' interp' flags') = 
+    toJSON (Configuration dir' _ withLinks' savefmt' dpi' tightbbox' transparent' interp' flags') =
         -- We ignore the include script as we want to examplify that
         -- this is for a filepath
-            object [ pack directoryKey      .= dir'
+            object [ pack directoryKey     .= dir'
                    , pack includePathKey   .= ("example.py" :: FilePath)
                    , pack withLinksKey     .= withLinks'
                    , pack dpiKey           .= dpi'
                    , pack saveFormatKey    .= (toLower <$> show savefmt')
                    , pack isTightBboxKey   .= tightbbox'
                    , pack isTransparentKey .= transparent'
-                   , "interpreter" .= interp'
-                   , "flags"       .= flags'
+                   , "interpreter"         .= interp'
+                   , "flags"               .= flags'
                    ]
 
-    
--- | 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.
-    , 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.
-    , tightBbox   :: Bool         -- ^ Enforce tight bounding-box with @bbox_inches="tight"@.
-    , transparent :: Bool         -- ^ Make figure background transparent.
-    , blockAttrs  :: Attr         -- ^ Attributes not related to @pandoc-pyplot@ will be propagated.
+    { caption      :: String           -- ^ Figure caption.
+    , withLinks    :: Bool             -- ^ Append links to source code and high-dpi figure to 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. This option only affects the Matplotlib backend.
+    , renderingLib :: RenderingLibrary -- ^ Rendering library.
+    , tightBbox    :: Bool             -- ^ Enforce tight bounding-box with @bbox_inches="tight"@. This option only affects the Matplotlib backend.
+    , transparent  :: Bool             -- ^ Make figure background transparent. This option only affects the Matplotlib backend.
+    , blockAttrs   :: Attr             -- ^ Attributes not related to @pandoc-pyplot@ will be propagated.
     } deriving Generic
 
 instance Hashable FigureSpec -- From Generic
diff --git a/stack.yaml b/stack.yaml
--- a/stack.yaml
+++ b/stack.yaml
@@ -17,7 +17,7 @@
 #
 # resolver: ./custom-snapshot.yaml
 # resolver: https://example.com/snapshots/2018-01-01.yaml
-resolver: lts-13.16
+resolver: lts-14.1
 
 # User packages to be built.
 # Various formats can be used as shown in the example below.
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -3,12 +3,13 @@
 
 module Main where
 
-import           Control.Monad                 (unless)
+import           Control.Monad                      (unless)
+import           Control.Monad.Reader
 
-import           Data.Default.Class            (def)
-import           Data.List                     (isInfixOf, isSuffixOf)
-import           Data.Monoid                   ((<>))
-import           Data.Text                     (unpack)
+import           Data.Default.Class                 (def)
+import           Data.List                          (isInfixOf, isSuffixOf)
+import           Data.Monoid                        ((<>))
+import           Data.Text                          (unpack)
 
 import           Test.Tasty
 import           Test.Tasty.HUnit
@@ -16,18 +17,19 @@
 import           Text.Pandoc.Filter.Pyplot
 import           Text.Pandoc.Filter.Pyplot.Internal
 
+import qualified Text.Pandoc.Builder                as B
+import qualified Text.Pandoc.Definition             as B
 import           Text.Pandoc.JSON
-import qualified Text.Pandoc.Builder           as B
-import qualified Text.Pandoc.Definition        as B
 
-import           System.Directory              (createDirectory,
-                                                createDirectoryIfMissing,
-                                                doesDirectoryExist,
-                                                doesFileExist, listDirectory,
-                                                removeDirectoryRecursive,
-                                                removePathForcibly)
-import           System.FilePath               ((</>), takeExtensions)
-import           System.IO.Temp                (getCanonicalTemporaryDirectory)
+import           System.Directory                   (createDirectory,
+                                                     createDirectoryIfMissing,
+                                                     doesDirectoryExist,
+                                                     doesFileExist,
+                                                     listDirectory,
+                                                     removeDirectoryRecursive,
+                                                     removePathForcibly)
+import           System.FilePath                    (takeExtensions, (</>))
+import           System.IO.Temp                     (getCanonicalTemporaryDirectory)
 
 main :: IO ()
 main =
@@ -87,8 +89,8 @@
 isExtensionOf :: String -> FilePath -> Bool
 isExtensionOf ext@('.':_) = isSuffixOf ext . takeExtensions
 isExtensionOf ext         = isSuffixOf ('.':ext) . takeExtensions
-    
 
+
 -- | Assert that the first list is contained,
 -- wholly and intact, anywhere within the second.
 assertIsInfix :: (Eq a, Show a, HasCallStack) => [a] -> [a] -> Assertion
@@ -114,7 +116,7 @@
         ensureDirectoryExistsAndEmpty tempDir
 
         let codeBlock = (addDirectory tempDir $ plotCodeBlock "import matplotlib.pyplot as plt\n")
-        _ <- makePlot' def codeBlock
+        _ <- runReaderT (makePlot' codeBlock) def
         filesCreated <- length <$> listDirectory tempDir
         assertEqual "" filesCreated 3
 
@@ -129,7 +131,7 @@
         let codeBlock =
                 (addInclusion "test/fixtures/include.py" $
                  addDirectory tempDir $ plotCodeBlock "import matplotlib.pyplot as plt\n")
-        _ <- makePlot' def codeBlock
+        _ <- runReaderT (makePlot' codeBlock) def
         inclusion <- readFile "test/fixtures/include.py"
         sourcePath <- head . filter (isExtensionOf "txt") <$> listDirectory tempDir
         src <- readFile (tempDir </> sourcePath)
@@ -148,7 +150,7 @@
                  addDirectory tempDir $
                  plotCodeBlock
                      "import matplotlib.pyplot as plt\nplt.figure()\nplt.plot([1,2], [1,2])")
-        _ <- makePlot' def codeBlock
+        _ <- runReaderT (makePlot' codeBlock) def
         numberjpgFiles <-
             length <$> filter (isExtensionOf (extension JPG)) <$>
             listDirectory tempDir
@@ -164,7 +166,7 @@
         ensureDirectoryExistsAndEmpty tempDir
 
         let codeBlock = addDirectory tempDir $ plotCodeBlock "import matplotlib.pyplot as plt\nplt.show()"
-        result <- makePlot' def codeBlock
+        result <- runReaderT (makePlot' codeBlock) def
         case result of
             Right block -> assertFailure "did not catch the expected blocking call"
             Left error ->
@@ -173,7 +175,7 @@
                     else assertFailure "An error was caught but not the expected blocking call"
     where
         isCheckError (ScriptChecksFailedError msg) = True
-        isCheckError _ = False
+        isCheckError _                             = False
 -------------------------------------------------------------------------------
 
 -------------------------------------------------------------------------------
@@ -188,16 +190,16 @@
         -- constructed
         let expected = [B.Strong [B.Str "caption"]]
             codeBlock = addDirectory tempDir $ addCaption "**caption**" $ plotCodeBlock "import matplotlib.pyplot as plt"
-        result <- makePlot' def codeBlock
+        result <- runReaderT (makePlot' codeBlock) def
         case result of
-            Left error -> assertFailure $ "an error occured: " <> show error
+            Left error  -> assertFailure $ "an error occured: " <> show error
             Right block -> assertIsInfix expected (extractCaption block)
     where
         extractCaption (B.Para blocks) = extractImageCaption . head $ blocks
-        extractCaption _ = mempty
+        extractCaption _               = mempty
 
         extractImageCaption (Image _ c _) = c
-        extractImageCaption _ = mempty
+        extractImageCaption _             = mempty
 -------------------------------------------------------------------------------
 
 -------------------------------------------------------------------------------
@@ -212,16 +214,16 @@
         -- constructed
         let expected = mempty
             codeBlock = addWithLinks False $ addDirectory tempDir $ addCaption mempty $ plotCodeBlock "import matplotlib.pyplot as plt"
-        result <- makePlot' def codeBlock
+        result <- runReaderT (makePlot' codeBlock) def
         case result of
-            Left error -> assertFailure $ "an error occured: " <> show error
+            Left error  -> assertFailure $ "an error occured: " <> show error
             Right block -> assertIsInfix expected (extractCaption block)
     where
         extractCaption (B.Para blocks) = extractImageCaption . head $ blocks
-        extractCaption _ = mempty
+        extractCaption _               = mempty
 
         extractImageCaption (Image _ c _) = c
-        extractImageCaption _ = mempty
+        extractImageCaption _             = mempty
 -------------------------------------------------------------------------------
 
 
@@ -241,10 +243,10 @@
 
         -- The default from config says the save format should be JPG
         -- but the code block save format="png"
-        let codeBlock = (addSaveFormat PNG $ 
-                         plotCodeBlock 
+        let codeBlock = (addSaveFormat PNG $
+                         plotCodeBlock
                             "import matplotlib.pyplot as plt\nplt.figure()\nplt.plot([1,2], [1,2])")
-        _ <- makePlot' config codeBlock
+        _ <- runReaderT (makePlot' codeBlock) config
 
         numberjpgFiles <-
             length <$> filter (isExtensionOf (extension JPG)) <$>
@@ -264,7 +266,7 @@
         config <- testConfig
 
         let codeBlock = plotCodeBlock "import matplotlib.pyplot as plt\nplt.figure()\nplt.plot([1,2], [1,2])"
-        _ <- makePlot' config codeBlock
+        _ <- runReaderT (makePlot' codeBlock) config
 
         numberjpgFiles <-
             length <$> filter (isExtensionOf (extension JPG)) <$>
@@ -273,7 +275,7 @@
 -------------------------------------------------------------------------------
 
 testBuildConfiguration :: TestTree
-testBuildConfiguration = 
+testBuildConfiguration =
     testCase "configuration is correctly parsed" $ do
         let config = def { defaultDirectory = "generated/other"
                          , defaultSaveFormat = JPG
@@ -283,4 +285,4 @@
                          , isTransparent = True
                          }
         parsedConfig <- configuration "test/fixtures/.pandoc-pyplot.yml"
-        assertEqual "" config parsedConfig
+        assertEqual "" config parsedConfig
