    {-# LANGUAGE CPP                 #-}
    {-# LANGUAGE FlexibleContexts    #-}
    {-# LANGUAGE OverloadedStrings   #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE TupleSections       #-}
    {- |
       Module      : Text.Pandoc.App
       Copyright   : Copyright (C) 2006-2020 John MacFarlane
       License     : GNU GPL, version 2 or above

       Maintainer  : John MacFarlane <jgm@berkeley@edu>
       Stability   : alpha
       Portability : portable

    Does a pandoc conversion based on command-line options.
    -}
    module Text.Pandoc.App.OutputSettings
      ( OutputSettings (..)
      , optToOutputSettings
      ) where
    import qualified Data.Map as M
    import qualified Data.Text as T
    import Text.DocTemplates (toVal, Context(..), Val(..))
    import qualified Control.Exception as E
    import Control.Monad
    import Control.Monad.Except (throwError)
    import Control.Monad.Trans
    import Data.Char (toLower)
    import Data.List (find)
    import Data.Maybe (fromMaybe)
    import Skylighting (defaultSyntaxMap)
    import Skylighting.Parser (addSyntaxDefinition, parseSyntaxDefinition)
    import System.Directory (getCurrentDirectory)
    import System.Exit (exitSuccess)
    import System.FilePath
    import System.IO (stdout)
    import Text.Pandoc
    import Text.Pandoc.App.FormatHeuristics (formatFromFilePaths)
    import Text.Pandoc.App.Opt (Opt (..))
    import Text.Pandoc.App.CommandLineOptions (engines, lookupHighlightStyle,
                                              setVariable)
    import qualified Text.Pandoc.UTF8 as UTF8

    readUtf8File :: PandocMonad m => FilePath -> m T.Text
    readUtf8File :: FilePath -> m Text
    readUtf8File = (ByteString -> Text) -> m ByteString -> m Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ByteString -> Text
    UTF8.toText (m ByteString -> m Text)
    -> (FilePath -> m ByteString) -> FilePath -> m Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> m ByteString
    forall (m :: * -> *). PandocMonad m => FilePath -> m ByteString
    readFileStrict

    -- | Settings specifying how document output should be produced.
    data OutputSettings = OutputSettings
      { OutputSettings -> Text
    outputFormat :: T.Text
      , OutputSettings -> Writer PandocIO
    outputWriter :: Writer PandocIO
      , OutputSettings -> Text
    outputWriterName :: T.Text
      , OutputSettings -> WriterOptions
    outputWriterOptions :: WriterOptions
      , OutputSettings -> Maybe FilePath
    outputPdfProgram :: Maybe String
      }

    -- | Get output settings from command line options.
    optToOutputSettings :: Opt -> PandocIO OutputSettings
    optToOutputSettings :: Opt -> PandocIO OutputSettings
    optToOutputSettings opts :: Opt
    opts = do
      let outputFile :: FilePath
    outputFile = FilePath -> Maybe FilePath -> FilePath
    forall a. a -> Maybe a -> a
    fromMaybe "-" (Opt -> Maybe FilePath
    optOutputFile Opt
    opts)

      Bool -> PandocIO () -> PandocIO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Opt -> Bool
    optDumpArgs Opt
    opts) (PandocIO () -> PandocIO ())
    -> (IO () -> PandocIO ()) -> IO () -> PandocIO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . IO () -> PandocIO ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> PandocIO ()) -> IO () -> PandocIO ()
    forall a b. (a -> b) -> a -> b
    $ do
        Handle -> FilePath -> IO ()
    UTF8.hPutStrLn Handle
    stdout FilePath
    outputFile
        (FilePath -> IO ()) -> [FilePath] -> IO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ (Handle -> FilePath -> IO ()
    UTF8.hPutStrLn Handle
    stdout) ([FilePath] -> Maybe [FilePath] -> [FilePath]
    forall a. a -> Maybe a -> a
    fromMaybe [] (Maybe [FilePath] -> [FilePath]) -> Maybe [FilePath] -> [FilePath]
    forall a b. (a -> b) -> a -> b
    $ Opt -> Maybe [FilePath]
    optInputFiles Opt
    opts)
        IO ()
    forall a. IO a
    exitSuccess

      Maybe Text
    epubMetadata <- (FilePath -> PandocIO Text)
    -> Maybe FilePath -> PandocIO (Maybe Text)
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    traverse FilePath -> PandocIO Text
    forall (m :: * -> *). PandocMonad m => FilePath -> m Text
    readUtf8File (Maybe FilePath -> PandocIO (Maybe Text))
    -> Maybe FilePath -> PandocIO (Maybe Text)
    forall a b. (a -> b) -> a -> b
    $ Opt -> Maybe FilePath
    optEpubMetadata Opt
    opts

      let pdfOutput :: Bool
    pdfOutput = (Char -> Char) -> FilePath -> FilePath
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Char
    toLower (FilePath -> FilePath
    takeExtension FilePath
    outputFile) FilePath -> FilePath -> Bool
    forall a. Eq a => a -> a -> Bool
    == ".pdf" Bool -> Bool -> Bool
    ||
                      Opt -> Maybe Text
    optTo Opt
    opts Maybe Text -> Maybe Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text -> Maybe Text
    forall a. a -> Maybe a
    Just "pdf"
      (writerName :: Text
    writerName, maybePdfProg :: Maybe FilePath
    maybePdfProg) <-
        if Bool
    pdfOutput
           then IO (Text, Maybe FilePath) -> PandocIO (Text, Maybe FilePath)
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Text, Maybe FilePath) -> PandocIO (Text, Maybe FilePath))
    -> IO (Text, Maybe FilePath) -> PandocIO (Text, Maybe FilePath)
    forall a b. (a -> b) -> a -> b
    $ Maybe Text -> Maybe FilePath -> IO (Text, Maybe FilePath)
    pdfWriterAndProg
                   (case Opt -> Maybe Text
    optTo Opt
    opts of
                      Just "pdf" -> Maybe Text
    forall a. Maybe a
    Nothing
                      x :: Maybe Text
    x          -> Maybe Text
    x)
                   (Opt -> Maybe FilePath
    optPdfEngine Opt
    opts)
           else case Opt -> Maybe Text
    optTo Opt
    opts of
                  Just f :: Text
    f -> (Text, Maybe FilePath) -> PandocIO (Text, Maybe FilePath)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Text
    f, Maybe FilePath
    forall a. Maybe a
    Nothing)
                  Nothing
                   | FilePath
    outputFile FilePath -> FilePath -> Bool
    forall a. Eq a => a -> a -> Bool
    == "-" -> (Text, Maybe FilePath) -> PandocIO (Text, Maybe FilePath)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ("html", Maybe FilePath
    forall a. Maybe a
    Nothing)
                   | Bool
    otherwise ->
                         case [FilePath] -> Maybe Text
    formatFromFilePaths [FilePath
    outputFile] of
                               Nothing -> do
                                 LogMessage -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
    report (LogMessage -> PandocIO ()) -> LogMessage -> PandocIO ()
    forall a b. (a -> b) -> a -> b
    $ [Text] -> Text -> LogMessage
    CouldNotDeduceFormat
                                    [FilePath -> Text
    T.pack (FilePath -> Text) -> FilePath -> Text
    forall a b. (a -> b) -> a -> b
    $ FilePath -> FilePath
    takeExtension FilePath
    outputFile] "html"
                                 (Text, Maybe FilePath) -> PandocIO (Text, Maybe FilePath)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ("html", Maybe FilePath
    forall a. Maybe a
    Nothing)
                               Just f :: Text
    f  -> (Text, Maybe FilePath) -> PandocIO (Text, Maybe FilePath)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Text
    f, Maybe FilePath
    forall a. Maybe a
    Nothing)

      let format :: Text
    format = if ".lua" Text -> Text -> Bool
    `T.isSuffixOf` Text
    writerName
                      then Text
    writerName
                      else Text -> Text
    T.toLower (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ Text -> Text
    baseWriterName Text
    writerName

      (Writer PandocIO
    writer :: Writer PandocIO, writerExts :: Extensions
    writerExts) <-
                if ".lua" Text -> Text -> Bool
    `T.isSuffixOf` Text
    format
                   then (Writer PandocIO, Extensions)
    -> PandocIO (Writer PandocIO, Extensions)
    forall (m :: * -> *) a. Monad m => a -> m a
    return ((WriterOptions -> Pandoc -> PandocIO Text) -> Writer PandocIO
    forall (m :: * -> *).
    (WriterOptions -> Pandoc -> m Text) -> Writer m
    TextWriter
                           (\o :: WriterOptions
    o d :: Pandoc
    d -> FilePath -> WriterOptions -> Pandoc -> PandocIO Text
    writeCustom (Text -> FilePath
    T.unpack Text
    writerName) WriterOptions
    o Pandoc
    d)
                                   :: Writer PandocIO, Extensions
    forall a. Monoid a => a
    mempty)
                   else Text -> PandocIO (Writer PandocIO, Extensions)
    forall (m :: * -> *).
    PandocMonad m =>
    Text -> m (Writer m, Extensions)
    getWriter (Text -> Text
    T.toLower Text
    writerName)

      let standalone :: Bool
    standalone = Opt -> Bool
    optStandalone Opt
    opts Bool -> Bool -> Bool
    || Bool -> Bool
    not (Text -> Bool
    isTextFormat Text
    format) Bool -> Bool -> Bool
    || Bool
    pdfOutput

      let addSyntaxMap :: SyntaxMap -> FilePath -> m SyntaxMap
    addSyntaxMap existingmap :: SyntaxMap
    existingmap f :: FilePath
    f = do
            Either FilePath Syntax
    res <- IO (Either FilePath Syntax) -> m (Either FilePath Syntax)
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (FilePath -> IO (Either FilePath Syntax)
    parseSyntaxDefinition FilePath
    f)
            case Either FilePath Syntax
    res of
                  Left errstr :: FilePath
    errstr -> PandocError -> m SyntaxMap
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError (PandocError -> m SyntaxMap) -> PandocError -> m SyntaxMap
    forall a b. (a -> b) -> a -> b
    $ Text -> PandocError
    PandocSyntaxMapError (Text -> PandocError) -> Text -> PandocError
    forall a b. (a -> b) -> a -> b
    $ FilePath -> Text
    T.pack FilePath
    errstr
                  Right syn :: Syntax
    syn   -> SyntaxMap -> m SyntaxMap
    forall (m :: * -> *) a. Monad m => a -> m a
    return (SyntaxMap -> m SyntaxMap) -> SyntaxMap -> m SyntaxMap
    forall a b. (a -> b) -> a -> b
    $ Syntax -> SyntaxMap -> SyntaxMap
    addSyntaxDefinition Syntax
    syn SyntaxMap
    existingmap

      SyntaxMap
    syntaxMap <- (SyntaxMap -> FilePath -> PandocIO SyntaxMap)
    -> SyntaxMap -> [FilePath] -> PandocIO SyntaxMap
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldM SyntaxMap -> FilePath -> PandocIO SyntaxMap
    forall (m :: * -> *).
    (MonadIO m, MonadError PandocError m) =>
    SyntaxMap -> FilePath -> m SyntaxMap
    addSyntaxMap SyntaxMap
    defaultSyntaxMap
                         (Opt -> [FilePath]
    optSyntaxDefinitions Opt
    opts)

      Maybe Style
    hlStyle <- (Text -> PandocIO Style) -> Maybe Text -> PandocIO (Maybe Style)
    forall (t :: * -> *) (f :: * -> *) a b.
    (Traversable t, Applicative f) =>
    (a -> f b) -> t a -> f (t b)
    traverse (FilePath -> PandocIO Style
    forall (m :: * -> *). PandocMonad m => FilePath -> m Style
    lookupHighlightStyle (FilePath -> PandocIO Style)
    -> (Text -> FilePath) -> Text -> PandocIO Style
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> FilePath
    T.unpack) (Maybe Text -> PandocIO (Maybe Style))
    -> Maybe Text -> PandocIO (Maybe Style)
    forall a b. (a -> b) -> a -> b
    $ Opt -> Maybe Text
    optHighlightStyle Opt
    opts

      let setVariableM :: Text -> Text -> Context Text -> m (Context Text)
    setVariableM k :: Text
    k v :: Text
    v = Context Text -> m (Context Text)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Context Text -> m (Context Text))
    -> (Context Text -> Context Text)
    -> Context Text
    -> m (Context Text)
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text -> Context Text -> Context Text
    setVariable Text
    k Text
    v

      let setListVariableM :: Text -> [b] -> Context a -> m (Context a)
    setListVariableM _ [] ctx :: Context a
    ctx = Context a -> m (Context a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return Context a
    ctx
          setListVariableM k :: Text
    k vs :: [b]
    vs ctx :: Context a
    ctx = do
            let ctxMap :: Map Text (Val a)
    ctxMap = Context a -> Map Text (Val a)
    forall a. Context a -> Map Text (Val a)
    unContext Context a
    ctx
            Context a -> m (Context a)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Context a -> m (Context a)) -> Context a -> m (Context a)
    forall a b. (a -> b) -> a -> b
    $ Map Text (Val a) -> Context a
    forall a. Map Text (Val a) -> Context a
    Context (Map Text (Val a) -> Context a) -> Map Text (Val a) -> Context a
    forall a b. (a -> b) -> a -> b
    $
              case Text -> Map Text (Val a) -> Maybe (Val a)
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup Text
    k Map Text (Val a)
    ctxMap of
                  Just (ListVal xs :: [Val a]
    xs) -> Text -> Val a -> Map Text (Val a) -> Map Text (Val a)
    forall k a. Ord k => k -> a -> Map k a -> Map k a
    M.insert Text
    k
                                      ([Val a] -> Val a
    forall a. [Val a] -> Val a
    ListVal ([Val a] -> Val a) -> [Val a] -> Val a
    forall a b. (a -> b) -> a -> b
    $ [Val a]
    xs [Val a] -> [Val a] -> [Val a]
    forall a. [a] -> [a] -> [a]
    ++ (b -> Val a) -> [b] -> [Val a]
    forall a b. (a -> b) -> [a] -> [b]
    map b -> Val a
    forall a b. ToContext a b => b -> Val a
    toVal [b]
    vs) Map Text (Val a)
    ctxMap
                  Just v :: Val a
    v -> Text -> Val a -> Map Text (Val a) -> Map Text (Val a)
    forall k a. Ord k => k -> a -> Map k a -> Map k a
    M.insert Text
    k
                             ([Val a] -> Val a
    forall a. [Val a] -> Val a
    ListVal ([Val a] -> Val a) -> [Val a] -> Val a
    forall a b. (a -> b) -> a -> b
    $ Val a
    v Val a -> [Val a] -> [Val a]
    forall a. a -> [a] -> [a]
    : (b -> Val a) -> [b] -> [Val a]
    forall a b. (a -> b) -> [a] -> [b]
    map b -> Val a
    forall a b. ToContext a b => b -> Val a
    toVal [b]
    vs) Map Text (Val a)
    ctxMap
                  Nothing -> Text -> Val a -> Map Text (Val a) -> Map Text (Val a)
    forall k a. Ord k => k -> a -> Map k a -> Map k a
    M.insert Text
    k ([b] -> Val a
    forall a b. ToContext a b => b -> Val a
    toVal [b]
    vs) Map Text (Val a)
    ctxMap

      let getTextContents :: FilePath -> f Text
    getTextContents fp :: FilePath
    fp = ByteString -> Text
    UTF8.toText (ByteString -> Text)
    -> ((ByteString, Maybe Text) -> ByteString)
    -> (ByteString, Maybe Text)
    -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ByteString, Maybe Text) -> ByteString
    forall a b. (a, b) -> a
    fst ((ByteString, Maybe Text) -> Text)
    -> f (ByteString, Maybe Text) -> f Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Text -> f (ByteString, Maybe Text)
    forall (m :: * -> *).
    PandocMonad m =>
    Text -> m (ByteString, Maybe Text)
    fetchItem (FilePath -> Text
    T.pack FilePath
    fp)

      let setFilesVariableM :: Text -> [FilePath] -> Context a -> m (Context a)
    setFilesVariableM k :: Text
    k fps :: [FilePath]
    fps ctx :: Context a
    ctx = do
            [Text]
    xs <- (FilePath -> m Text) -> [FilePath] -> m [Text]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM FilePath -> m Text
    forall (m :: * -> *). PandocMonad m => FilePath -> m Text
    getTextContents [FilePath]
    fps
            Text -> [Text] -> Context a -> m (Context a)
    forall (m :: * -> *) a b.
    (Monad m, ToContext a b, ToContext a [b]) =>
    Text -> [b] -> Context a -> m (Context a)
    setListVariableM Text
    k [Text]
    xs Context a
    ctx

      FilePath
    curdir <- IO FilePath -> PandocIO FilePath
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO FilePath
    getCurrentDirectory

      Context Text
    variables <-
        Context Text -> PandocIO (Context Text)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Opt -> Context Text
    optVariables Opt
    opts)
        PandocIO (Context Text)
    -> (Context Text -> PandocIO (Context Text))
    -> PandocIO (Context Text)
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
        Text -> [Text] -> Context Text -> PandocIO (Context Text)
    forall (m :: * -> *) a b.
    (Monad m, ToContext a b, ToContext a [b]) =>
    Text -> [b] -> Context a -> m (Context a)
    setListVariableM "sourcefile"
          ([Text] -> ([FilePath] -> [Text]) -> Maybe [FilePath] -> [Text]
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe ["-"] ((FilePath -> Text) -> [FilePath] -> [Text]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap FilePath -> Text
    T.pack) (Opt -> Maybe [FilePath]
    optInputFiles Opt
    opts))
        PandocIO (Context Text)
    -> (Context Text -> PandocIO (Context Text))
    -> PandocIO (Context Text)
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
        Text -> Text -> Context Text -> PandocIO (Context Text)
    forall (m :: * -> *).
    Monad m =>
    Text -> Text -> Context Text -> m (Context Text)
    setVariableM "outputfile" (FilePath -> Text
    T.pack FilePath
    outputFile)
        PandocIO (Context Text)
    -> (Context Text -> PandocIO (Context Text))
    -> PandocIO (Context Text)
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
        Text -> [FilePath] -> Context Text -> PandocIO (Context Text)
    forall (m :: * -> *) a.
    (PandocMonad m, ToContext a [Text], ToContext a Text) =>
    Text -> [FilePath] -> Context a -> m (Context a)
    setFilesVariableM "include-before" (Opt -> [FilePath]
    optIncludeBeforeBody Opt
    opts)
        PandocIO (Context Text)
    -> (Context Text -> PandocIO (Context Text))
    -> PandocIO (Context Text)
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
        Text -> [FilePath] -> Context Text -> PandocIO (Context Text)
    forall (m :: * -> *) a.
    (PandocMonad m, ToContext a [Text], ToContext a Text) =>
    Text -> [FilePath] -> Context a -> m (Context a)
    setFilesVariableM "include-after" (Opt -> [FilePath]
    optIncludeAfterBody Opt
    opts)
        PandocIO (Context Text)
    -> (Context Text -> PandocIO (Context Text))
    -> PandocIO (Context Text)
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
        Text -> [FilePath] -> Context Text -> PandocIO (Context Text)
    forall (m :: * -> *) a.
    (PandocMonad m, ToContext a [Text], ToContext a Text) =>
    Text -> [FilePath] -> Context a -> m (Context a)
    setFilesVariableM "header-includes" (Opt -> [FilePath]
    optIncludeInHeader Opt
    opts)
        PandocIO (Context Text)
    -> (Context Text -> PandocIO (Context Text))
    -> PandocIO (Context Text)
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
        Text -> [Text] -> Context Text -> PandocIO (Context Text)
    forall (m :: * -> *) a b.
    (Monad m, ToContext a b, ToContext a [b]) =>
    Text -> [b] -> Context a -> m (Context a)
    setListVariableM "css" ((FilePath -> Text) -> [FilePath] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map FilePath -> Text
    T.pack ([FilePath] -> [Text]) -> [FilePath] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ Opt -> [FilePath]
    optCss Opt
    opts)
        PandocIO (Context Text)
    -> (Context Text -> PandocIO (Context Text))
    -> PandocIO (Context Text)
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
        (Context Text -> PandocIO (Context Text))
    -> (Text -> Context Text -> PandocIO (Context Text))
    -> Maybe Text
    -> Context Text
    -> PandocIO (Context Text)
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Context Text -> PandocIO (Context Text)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Text -> Text -> Context Text -> PandocIO (Context Text)
    forall (m :: * -> *).
    Monad m =>
    Text -> Text -> Context Text -> m (Context Text)
    setVariableM "title-prefix") (Opt -> Maybe Text
    optTitlePrefix Opt
    opts)
        PandocIO (Context Text)
    -> (Context Text -> PandocIO (Context Text))
    -> PandocIO (Context Text)
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
        (Context Text -> PandocIO (Context Text))
    -> (Text -> Context Text -> PandocIO (Context Text))
    -> Maybe Text
    -> Context Text
    -> PandocIO (Context Text)
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Context Text -> PandocIO (Context Text)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Text -> Text -> Context Text -> PandocIO (Context Text)
    forall (m :: * -> *).
    Monad m =>
    Text -> Text -> Context Text -> m (Context Text)
    setVariableM "epub-cover-image")
                     (FilePath -> Text
    T.pack (FilePath -> Text) -> Maybe FilePath -> Maybe Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Opt -> Maybe FilePath
    optEpubCoverImage Opt
    opts)
        PandocIO (Context Text)
    -> (Context Text -> PandocIO (Context Text))
    -> PandocIO (Context Text)
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
        Text -> Text -> Context Text -> PandocIO (Context Text)
    forall (m :: * -> *).
    Monad m =>
    Text -> Text -> Context Text -> m (Context Text)
    setVariableM "curdir" (FilePath -> Text
    T.pack FilePath
    curdir)
        PandocIO (Context Text)
    -> (Context Text -> PandocIO (Context Text))
    -> PandocIO (Context Text)
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
        (\vars :: Context Text
    vars ->  if Text
    format Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == "dzslides"
                      then do
                          Text
    dztempl <- ByteString -> Text
    UTF8.toText (ByteString -> Text) -> PandocIO ByteString -> PandocIO Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> FilePath -> PandocIO ByteString
    forall (m :: * -> *). PandocMonad m => FilePath -> m ByteString
    readDataFile
                                       ("dzslides" FilePath -> FilePath -> FilePath
    </> "template.html")
                          let dzline :: Text
    dzline = "<!-- {{{{ dzslides core"
                          let dzcore :: Text
    dzcore = [Text] -> Text
    T.unlines
                                     ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ (Text -> Bool) -> [Text] -> [Text]
    forall a. (a -> Bool) -> [a] -> [a]
    dropWhile (Bool -> Bool
    not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Text
    dzline Text -> Text -> Bool
    `T.isPrefixOf`))
                                     ([Text] -> [Text]) -> [Text] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ Text -> [Text]
    T.lines Text
    dztempl
                          Text -> Text -> Context Text -> PandocIO (Context Text)
    forall (m :: * -> *).
    Monad m =>
    Text -> Text -> Context Text -> m (Context Text)
    setVariableM "dzslides-core" Text
    dzcore Context Text
    vars
                      else Context Text -> PandocIO (Context Text)
    forall (m :: * -> *) a. Monad m => a -> m a
    return Context Text
    vars)

      Maybe (Template Text)
    templ <- case Opt -> Maybe FilePath
    optTemplate Opt
    opts of
                      _ | Bool -> Bool
    not Bool
    standalone -> Maybe (Template Text) -> PandocIO (Maybe (Template Text))
    forall (m :: * -> *) a. Monad m => a -> m a
    return Maybe (Template Text)
    forall a. Maybe a
    Nothing
                      Nothing -> Template Text -> Maybe (Template Text)
    forall a. a -> Maybe a
    Just (Template Text -> Maybe (Template Text))
    -> PandocIO (Template Text) -> PandocIO (Maybe (Template Text))
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Text -> PandocIO (Template Text)
    forall (m :: * -> *). PandocMonad m => Text -> m (Template Text)
    compileDefaultTemplate Text
    format
                      Just tp :: FilePath
    tp -> do
                        -- strip off extensions
                        let tp' :: FilePath
    tp' = case FilePath -> FilePath
    takeExtension FilePath
    tp of
                                       "" -> FilePath
    tp FilePath -> FilePath -> FilePath
    <.> Text -> FilePath
    T.unpack Text
    format
                                       _  -> FilePath
    tp
                        Either FilePath (Template Text)
    res <- FilePath -> PandocIO Text
    forall (m :: * -> *). PandocMonad m => FilePath -> m Text
    getTemplate FilePath
    tp' PandocIO Text
    -> (Text -> PandocIO (Either FilePath (Template Text)))
    -> PandocIO (Either FilePath (Template Text))
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= WithPartials PandocIO (Either FilePath (Template Text))
    -> PandocIO (Either FilePath (Template Text))
    forall (m :: * -> *) a. WithPartials m a -> m a
    runWithPartials (WithPartials PandocIO (Either FilePath (Template Text))
     -> PandocIO (Either FilePath (Template Text)))
    -> (Text
        -> WithPartials PandocIO (Either FilePath (Template Text)))
    -> Text
    -> PandocIO (Either FilePath (Template Text))
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath
    -> Text -> WithPartials PandocIO (Either FilePath (Template Text))
    forall (m :: * -> *) a.
    (TemplateMonad m, TemplateTarget a) =>
    FilePath -> Text -> m (Either FilePath (Template a))
    compileTemplate FilePath
    tp'
                        case Either FilePath (Template Text)
    res of
                          Left  e :: FilePath
    e -> PandocError -> PandocIO (Maybe (Template Text))
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError (PandocError -> PandocIO (Maybe (Template Text)))
    -> PandocError -> PandocIO (Maybe (Template Text))
    forall a b. (a -> b) -> a -> b
    $ Text -> PandocError
    PandocTemplateError (Text -> PandocError) -> Text -> PandocError
    forall a b. (a -> b) -> a -> b
    $ FilePath -> Text
    T.pack FilePath
    e
                          Right t :: Template Text
    t -> Maybe (Template Text) -> PandocIO (Maybe (Template Text))
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe (Template Text) -> PandocIO (Maybe (Template Text)))
    -> Maybe (Template Text) -> PandocIO (Maybe (Template Text))
    forall a b. (a -> b) -> a -> b
    $ Template Text -> Maybe (Template Text)
    forall a. a -> Maybe a
    Just Template Text
    t

      let writerOpts :: WriterOptions
    writerOpts = WriterOptions
    forall a. Default a => a
    def {
              writerTemplate :: Maybe (Template Text)
    writerTemplate         = Maybe (Template Text)
    templ
            , writerVariables :: Context Text
    writerVariables        = Context Text
    variables
            , writerTabStop :: Int
    writerTabStop          = Opt -> Int
    optTabStop Opt
    opts
            , writerTableOfContents :: Bool
    writerTableOfContents  = Opt -> Bool
    optTableOfContents Opt
    opts
            , writerHTMLMathMethod :: HTMLMathMethod
    writerHTMLMathMethod   = Opt -> HTMLMathMethod
    optHTMLMathMethod Opt
    opts
            , writerIncremental :: Bool
    writerIncremental      = Opt -> Bool
    optIncremental Opt
    opts
            , writerCiteMethod :: CiteMethod
    writerCiteMethod       = Opt -> CiteMethod
    optCiteMethod Opt
    opts
            , writerNumberSections :: Bool
    writerNumberSections   = Opt -> Bool
    optNumberSections Opt
    opts
            , writerNumberOffset :: [Int]
    writerNumberOffset     = Opt -> [Int]
    optNumberOffset Opt
    opts
            , writerSectionDivs :: Bool
    writerSectionDivs      = Opt -> Bool
    optSectionDivs Opt
    opts
            , writerExtensions :: Extensions
    writerExtensions       = Extensions
    writerExts
            , writerReferenceLinks :: Bool
    writerReferenceLinks   = Opt -> Bool
    optReferenceLinks Opt
    opts
            , writerReferenceLocation :: ReferenceLocation
    writerReferenceLocation = Opt -> ReferenceLocation
    optReferenceLocation Opt
    opts
            , writerDpi :: Int
    writerDpi              = Opt -> Int
    optDpi Opt
    opts
            , writerWrapText :: WrapOption
    writerWrapText         = Opt -> WrapOption
    optWrap Opt
    opts
            , writerColumns :: Int
    writerColumns          = Opt -> Int
    optColumns Opt
    opts
            , writerEmailObfuscation :: ObfuscationMethod
    writerEmailObfuscation = Opt -> ObfuscationMethod
    optEmailObfuscation Opt
    opts
            , writerIdentifierPrefix :: Text
    writerIdentifierPrefix = Opt -> Text
    optIdentifierPrefix Opt
    opts
            , writerHtmlQTags :: Bool
    writerHtmlQTags        = Opt -> Bool
    optHtmlQTags Opt
    opts
            , writerTopLevelDivision :: TopLevelDivision
    writerTopLevelDivision = Opt -> TopLevelDivision
    optTopLevelDivision Opt
    opts
            , writerListings :: Bool
    writerListings         = Opt -> Bool
    optListings Opt
    opts
            , writerSlideLevel :: Maybe Int
    writerSlideLevel       = Opt -> Maybe Int
    optSlideLevel Opt
    opts
            , writerHighlightStyle :: Maybe Style
    writerHighlightStyle   = Maybe Style
    hlStyle
            , writerSetextHeaders :: Bool
    writerSetextHeaders    = Opt -> Bool
    optSetextHeaders Opt
    opts
            , writerEpubSubdirectory :: Text
    writerEpubSubdirectory = FilePath -> Text
    T.pack (FilePath -> Text) -> FilePath -> Text
    forall a b. (a -> b) -> a -> b
    $ Opt -> FilePath
    optEpubSubdirectory Opt
    opts
            , writerEpubMetadata :: Maybe Text
    writerEpubMetadata     = Maybe Text
    epubMetadata
            , writerEpubFonts :: [FilePath]
    writerEpubFonts        = Opt -> [FilePath]
    optEpubFonts Opt
    opts
            , writerEpubChapterLevel :: Int
    writerEpubChapterLevel = Opt -> Int
    optEpubChapterLevel Opt
    opts
            , writerTOCDepth :: Int
    writerTOCDepth         = Opt -> Int
    optTOCDepth Opt
    opts
            , writerReferenceDoc :: Maybe FilePath
    writerReferenceDoc     = Opt -> Maybe FilePath
    optReferenceDoc Opt
    opts
            , writerSyntaxMap :: SyntaxMap
    writerSyntaxMap        = SyntaxMap
    syntaxMap
            , writerPreferAscii :: Bool
    writerPreferAscii      = Opt -> Bool
    optAscii Opt
    opts
            }
      OutputSettings -> PandocIO OutputSettings
    forall (m :: * -> *) a. Monad m => a -> m a
    return (OutputSettings -> PandocIO OutputSettings)
    -> OutputSettings -> PandocIO OutputSettings
    forall a b. (a -> b) -> a -> b
    $ OutputSettings :: Text
    -> Writer PandocIO
    -> Text
    -> WriterOptions
    -> Maybe FilePath
    -> OutputSettings
    OutputSettings
        { outputFormat :: Text
    outputFormat = Text
    format
        , outputWriter :: Writer PandocIO
    outputWriter = Writer PandocIO
    writer
        , outputWriterName :: Text
    outputWriterName = Text
    writerName
        , outputWriterOptions :: WriterOptions
    outputWriterOptions = WriterOptions
    writerOpts
        , outputPdfProgram :: Maybe FilePath
    outputPdfProgram = Maybe FilePath
    maybePdfProg
        }

    baseWriterName :: T.Text -> T.Text
    baseWriterName :: Text -> Text
    baseWriterName = (Char -> Bool) -> Text -> Text
    T.takeWhile (\c :: Char
    c -> Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /= '+' Bool -> Bool -> Bool
    && Char
    c Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /= '-')

    pdfWriterAndProg :: Maybe T.Text              -- ^ user-specified writer name
                     -> Maybe String              -- ^ user-specified pdf-engine
                     -> IO (T.Text, Maybe String) -- ^ IO (writerName, maybePdfEngineProg)
    pdfWriterAndProg :: Maybe Text -> Maybe FilePath -> IO (Text, Maybe FilePath)
    pdfWriterAndProg mWriter :: Maybe Text
    mWriter mEngine :: Maybe FilePath
    mEngine =
      case Maybe Text -> Maybe FilePath -> Either Text (Text, FilePath)
    go Maybe Text
    mWriter Maybe FilePath
    mEngine of
          Right (writ :: Text
    writ, prog :: FilePath
    prog) -> (Text, Maybe FilePath) -> IO (Text, Maybe FilePath)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Text
    writ, FilePath -> Maybe FilePath
    forall a. a -> Maybe a
    Just FilePath
    prog)
          Left err :: Text
    err           -> IO (Text, Maybe FilePath) -> IO (Text, Maybe FilePath)
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Text, Maybe FilePath) -> IO (Text, Maybe FilePath))
    -> IO (Text, Maybe FilePath) -> IO (Text, Maybe FilePath)
    forall a b. (a -> b) -> a -> b
    $ PandocError -> IO (Text, Maybe FilePath)
    forall e a. Exception e => e -> IO a
    E.throwIO (PandocError -> IO (Text, Maybe FilePath))
    -> PandocError -> IO (Text, Maybe FilePath)
    forall a b. (a -> b) -> a -> b
    $ Text -> PandocError
    PandocAppError Text
    err
        where
          go :: Maybe Text -> Maybe FilePath -> Either Text (Text, FilePath)
    go Nothing Nothing       = (Text, FilePath) -> Either Text (Text, FilePath)
    forall a b. b -> Either a b
    Right ("latex", "pdflatex")
          go (Just writer :: Text
    writer) Nothing = (Text
    writer,) (FilePath -> (Text, FilePath))
    -> Either Text FilePath -> Either Text (Text, FilePath)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Text -> Either Text FilePath
    engineForWriter Text
    writer
          go Nothing (Just engine :: FilePath
    engine) = (,FilePath
    engine) (Text -> (Text, FilePath))
    -> Either Text Text -> Either Text (Text, FilePath)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> FilePath -> Either Text Text
    writerForEngine (FilePath -> FilePath
    takeBaseName FilePath
    engine)
          go (Just writer :: Text
    writer) (Just engine :: FilePath
    engine) =
               case ((Text, FilePath) -> Bool)
    -> [(Text, FilePath)] -> Maybe (Text, FilePath)
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Maybe a
    find ((Text, FilePath) -> (Text, FilePath) -> Bool
    forall a. Eq a => a -> a -> Bool
    == (Text -> Text
    baseWriterName Text
    writer, FilePath -> FilePath
    takeBaseName FilePath
    engine)) [(Text, FilePath)]
    engines of
                    Just _  -> (Text, FilePath) -> Either Text (Text, FilePath)
    forall a b. b -> Either a b
    Right (Text
    writer, FilePath
    engine)
                    Nothing -> Text -> Either Text (Text, FilePath)
    forall a b. a -> Either a b
    Left (Text -> Either Text (Text, FilePath))
    -> Text -> Either Text (Text, FilePath)
    forall a b. (a -> b) -> a -> b
    $ "pdf-engine " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> FilePath -> Text
    T.pack FilePath
    engine Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <>
                               " is not compatible with output format " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    writer

          writerForEngine :: FilePath -> Either Text Text
    writerForEngine eng :: FilePath
    eng = case [Text
    f | (f :: Text
    f,e :: FilePath
    e) <- [(Text, FilePath)]
    engines, FilePath
    e FilePath -> FilePath -> Bool
    forall a. Eq a => a -> a -> Bool
    == FilePath
    eng] of
                                     fmt :: Text
    fmt : _ -> Text -> Either Text Text
    forall a b. b -> Either a b
    Right Text
    fmt
                                     []      -> Text -> Either Text Text
    forall a b. a -> Either a b
    Left (Text -> Either Text Text) -> Text -> Either Text Text
    forall a b. (a -> b) -> a -> b
    $
                                       "pdf-engine " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> FilePath -> Text
    T.pack FilePath
    eng Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> " not known"

          engineForWriter :: Text -> Either Text FilePath
    engineForWriter "pdf" = Text -> Either Text FilePath
    forall a b. a -> Either a b
    Left "pdf writer"
          engineForWriter w :: Text
    w = case [FilePath
    e |  (f :: Text
    f,e :: FilePath
    e) <- [(Text, FilePath)]
    engines, Text
    f Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == Text -> Text
    baseWriterName Text
    w] of
                                    eng :: FilePath
    eng : _ -> FilePath -> Either Text FilePath
    forall a b. b -> Either a b
    Right FilePath
    eng
                                    []      -> Text -> Either Text FilePath
    forall a b. a -> Either a b
    Left (Text -> Either Text FilePath) -> Text -> Either Text FilePath
    forall a b. (a -> b) -> a -> b
    $
                                       "cannot produce pdf output from " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    w

    isTextFormat :: T.Text -> Bool
    isTextFormat :: Text -> Bool
    isTextFormat s :: Text
    s =
      Text
    s Text -> [Text] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `notElem` ["odt","docx","epub2","epub3","epub","pptx","pdf"]