    {-# LANGUAGE OverloadedStrings   #-}
    {-# LANGUAGE CPP                 #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {- |
       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 (
                convertWithOpts
              , Opt(..)
              , LineEnding(..)
              , Filter(..)
              , defaultOpts
              , parseOptions
              , options
              , applyFilters
              ) where
    import qualified Control.Exception as E
    import Control.Monad
    import Control.Monad.Trans
    import Control.Monad.Except (throwError)
    import qualified Data.ByteString as BS
    import qualified Data.ByteString.Lazy as BL
    import Data.Char (toLower)
    import Data.Maybe (fromMaybe, isJust, isNothing)
    import qualified Data.Set as Set
    import Data.Text (Text)
    import qualified Data.Text as T
    import qualified Data.Text.Lazy as TL
    import qualified Data.Text.Lazy.Encoding as TE
    import qualified Data.Text.Encoding.Error as TE
    import qualified Data.Text.Encoding.Error as TSE
    import Network.URI (URI (..), parseURI)
    import System.Directory (doesDirectoryExist)
    import System.Exit (exitSuccess)
    import System.FilePath
    import System.IO (nativeNewline, stdout)
    import qualified System.IO as IO (Newline (..))
    import Text.Pandoc
    import Text.Pandoc.App.FormatHeuristics (formatFromFilePaths)
    import Text.Pandoc.App.Opt (Opt (..), LineEnding (..), defaultOpts,
                                IpynbOutput (..) )
    import Text.Pandoc.App.CommandLineOptions (parseOptions, options)
    import Text.Pandoc.App.OutputSettings (OutputSettings (..), optToOutputSettings)
    import Text.Pandoc.BCP47 (Lang (..), parseBCP47)
    import Text.Pandoc.Builder (setMeta)
    import Text.Pandoc.Filter (Filter (JSONFilter, LuaFilter), applyFilters)
    import Text.Pandoc.PDF (makePDF)
    import Text.Pandoc.SelfContained (makeDataURI, makeSelfContained)
    import Text.Pandoc.Shared (eastAsianLineBreakFilter, stripEmptyParagraphs,
             headerShift, isURI, tabFilter, uriPathToPath, filterIpynbOutput,
             defaultUserDataDirs, tshow, findM)
    import Text.Pandoc.Writers.Shared (lookupMetaString)
    import Text.Pandoc.Readers.Markdown (yamlToMeta)
    import qualified Text.Pandoc.UTF8 as UTF8
    #ifndef _WINDOWS
    import System.Posix.IO (stdOutput)
    import System.Posix.Terminal (queryTerminal)
    #endif

    convertWithOpts :: Opt -> IO ()
    convertWithOpts :: Opt -> IO ()
    convertWithOpts 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)
      let filters :: [Filter]
    filters = Opt -> [Filter]
    optFilters Opt
    opts
      let verbosity :: Verbosity
    verbosity = Opt -> Verbosity
    optVerbosity Opt
    opts

      Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Opt -> Bool
    optDumpArgs Opt
    opts) (IO () -> IO ()) -> IO () -> IO ()
    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

      let isPandocCiteproc :: Filter -> Bool
    isPandocCiteproc (JSONFilter f :: FilePath
    f) = FilePath -> FilePath
    takeBaseName FilePath
    f FilePath -> FilePath -> Bool
    forall a. Eq a => a -> a -> Bool
    == "pandoc-citeproc"
          isPandocCiteproc _              = Bool
    False
      -- --bibliography implies -F pandoc-citeproc for backwards compatibility:
      let needsCiteproc :: Bool
    needsCiteproc = Maybe MetaValue -> Bool
    forall a. Maybe a -> Bool
    isJust (Text -> Meta -> Maybe MetaValue
    lookupMeta "bibliography"
                                    (Opt -> Meta
    optMetadata Opt
    opts)) Bool -> Bool -> Bool
    &&
                          Opt -> CiteMethod
    optCiteMethod Opt
    opts CiteMethod -> [CiteMethod] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `notElem` [CiteMethod
    Natbib, CiteMethod
    Biblatex] Bool -> Bool -> Bool
    &&
                          Bool -> Bool
    not ((Filter -> Bool) -> [Filter] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any Filter -> Bool
    isPandocCiteproc [Filter]
    filters)
      let filters' :: [Filter]
    filters' = [Filter]
    filters [Filter] -> [Filter] -> [Filter]
    forall a. [a] -> [a] -> [a]
    ++ [ FilePath -> Filter
    JSONFilter "pandoc-citeproc" | Bool
    needsCiteproc ]

      let sources :: [FilePath]
    sources = case Opt -> Maybe [FilePath]
    optInputFiles Opt
    opts of
                         Just xs :: [FilePath]
    xs | Bool -> Bool
    not (Opt -> Bool
    optIgnoreArgs Opt
    opts) -> [FilePath]
    xs
                         _ -> ["-"]

      Maybe FilePath
    datadir <- case Opt -> Maybe FilePath
    optDataDir Opt
    opts of
                      Nothing   -> do
                        [FilePath]
    ds <- IO [FilePath]
    defaultUserDataDirs
                        (FilePath -> IO Bool) -> [FilePath] -> IO (Maybe FilePath)
    forall (m :: * -> *) (t :: * -> *) a.
    (Monad m, Foldable t) =>
    (a -> m Bool) -> t a -> m (Maybe a)
    findM FilePath -> IO Bool
    doesDirectoryExist [FilePath]
    ds
                      Just _    -> Maybe FilePath -> IO (Maybe FilePath)
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe FilePath -> IO (Maybe FilePath))
    -> Maybe FilePath -> IO (Maybe FilePath)
    forall a b. (a -> b) -> a -> b
    $ Opt -> Maybe FilePath
    optDataDir Opt
    opts

      let runIO' :: PandocIO a -> IO a
          runIO' :: PandocIO a -> IO a
    runIO' f :: PandocIO a
    f = do
            (res :: a
    res, reports :: [LogMessage]
    reports) <- PandocIO (a, [LogMessage]) -> IO (a, [LogMessage])
    forall a. PandocIO a -> IO a
    runIOorExplode (PandocIO (a, [LogMessage]) -> IO (a, [LogMessage]))
    -> PandocIO (a, [LogMessage]) -> IO (a, [LogMessage])
    forall a b. (a -> b) -> a -> b
    $ do
                                 Bool -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => Bool -> m ()
    setTrace (Opt -> Bool
    optTrace Opt
    opts)
                                 Verbosity -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => Verbosity -> m ()
    setVerbosity Verbosity
    verbosity
                                 a
    x <- PandocIO a
    f
                                 [LogMessage]
    rs <- PandocIO [LogMessage]
    forall (m :: * -> *). PandocMonad m => m [LogMessage]
    getLog
                                 (a, [LogMessage]) -> PandocIO (a, [LogMessage])
    forall (m :: * -> *) a. Monad m => a -> m a
    return (a
    x, [LogMessage]
    rs)
            case Opt -> Maybe FilePath
    optLogFile Opt
    opts of
                 Nothing      -> () -> IO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                 Just logfile :: FilePath
    logfile -> FilePath -> ByteString -> IO ()
    BL.writeFile FilePath
    logfile ([LogMessage] -> ByteString
    encodeLogMessages [LogMessage]
    reports)
            let isWarning :: LogMessage -> Bool
    isWarning msg :: LogMessage
    msg = LogMessage -> Verbosity
    messageVerbosity LogMessage
    msg Verbosity -> Verbosity -> Bool
    forall a. Eq a => a -> a -> Bool
    == Verbosity
    WARNING
            Bool -> IO () -> IO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Opt -> Bool
    optFailIfWarnings Opt
    opts Bool -> Bool -> Bool
    && (LogMessage -> Bool) -> [LogMessage] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any LogMessage -> Bool
    isWarning [LogMessage]
    reports) (IO () -> IO ()) -> IO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $
                PandocError -> IO ()
    forall e a. Exception e => e -> IO a
    E.throwIO PandocError
    PandocFailOnWarningError
            a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return a
    res

      let eol :: Newline
    eol = case Opt -> LineEnding
    optEol Opt
    opts of
                     CRLF   -> Newline
    IO.CRLF
                     LF     -> Newline
    IO.LF
                     Native -> Newline
    nativeNewline
    #ifdef _WINDOWS
      let istty = True
    #else
      Bool
    istty <- IO Bool -> IO Bool
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Bool -> IO Bool) -> IO Bool -> IO Bool
    forall a b. (a -> b) -> a -> b
    $ Fd -> IO Bool
    queryTerminal Fd
    stdOutput
    #endif

      PandocIO () -> IO ()
    forall a. PandocIO a -> IO a
    runIO' (PandocIO () -> IO ()) -> PandocIO () -> IO ()
    forall a b. (a -> b) -> a -> b
    $ do
        Maybe FilePath -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => Maybe FilePath -> m ()
    setUserDataDir Maybe FilePath
    datadir
        [FilePath] -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => [FilePath] -> m ()
    setResourcePath (Opt -> [FilePath]
    optResourcePath Opt
    opts)

        [FilePath] -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => [FilePath] -> m ()
    setInputFiles ([FilePath] -> Maybe [FilePath] -> [FilePath]
    forall a. a -> Maybe a -> a
    fromMaybe ["-"] (Opt -> Maybe [FilePath]
    optInputFiles Opt
    opts))
        Maybe FilePath -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => Maybe FilePath -> m ()
    setOutputFile (Opt -> Maybe FilePath
    optOutputFile Opt
    opts)

        -- assign reader and writer based on options and filenames
        Text
    readerName <- case Opt -> Maybe Text
    optFrom Opt
    opts of
                           Just f :: Text
    f  -> Text -> PandocIO Text
    forall (m :: * -> *) a. Monad m => a -> m a
    return Text
    f
                           Nothing -> case [FilePath] -> Maybe Text
    formatFromFilePaths [FilePath]
    sources of
                               Just f' :: Text
    f' -> Text -> PandocIO Text
    forall (m :: * -> *) a. Monad m => a -> m a
    return Text
    f'
                               Nothing | [FilePath]
    sources [FilePath] -> [FilePath] -> Bool
    forall a. Eq a => a -> a -> Bool
    == ["-"] -> Text -> PandocIO Text
    forall (m :: * -> *) a. Monad m => a -> m a
    return "markdown"
                                       | (FilePath -> Bool) -> [FilePath] -> Bool
    forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
    any (Text -> Bool
    isURI (Text -> Bool) -> (FilePath -> Text) -> FilePath -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> Text
    T.pack) [FilePath]
    sources -> Text -> PandocIO Text
    forall (m :: * -> *) a. Monad m => a -> m a
    return "html"
                                       | Bool
    otherwise -> 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) -> [FilePath] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (FilePath -> Text
    T.pack (FilePath -> Text) -> (FilePath -> FilePath) -> FilePath -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> FilePath
    takeExtension) [FilePath]
    sources) "markdown"
                                 Text -> PandocIO Text
    forall (m :: * -> *) a. Monad m => a -> m a
    return "markdown"

        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 -> PandocIO () -> PandocIO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Bool
    pdfOutput Bool -> Bool -> Bool
    && Text
    readerName Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == "latex") (PandocIO () -> PandocIO ()) -> PandocIO () -> PandocIO ()
    forall a b. (a -> b) -> a -> b
    $
          case Opt -> Maybe [FilePath]
    optInputFiles Opt
    opts of
            Just (inputFile :: FilePath
    inputFile:_) -> LogMessage -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
    report (LogMessage -> PandocIO ()) -> LogMessage -> PandocIO ()
    forall a b. (a -> b) -> a -> b
    $ Text -> LogMessage
    UnusualConversion (Text -> LogMessage) -> Text -> LogMessage
    forall a b. (a -> b) -> a -> b
    $ FilePath -> Text
    T.pack (FilePath -> Text) -> FilePath -> Text
    forall a b. (a -> b) -> a -> b
    $
              "to convert a .tex file to PDF, you get better results by using pdflatex "
                FilePath -> FilePath -> FilePath
    forall a. Semigroup a => a -> a -> a
    <> "(or lualatex or xelatex) directly, try `pdflatex " FilePath -> FilePath -> FilePath
    forall a. Semigroup a => a -> a -> a
    <> FilePath
    inputFile
                FilePath -> FilePath -> FilePath
    forall a. Semigroup a => a -> a -> a
    <> "` instead of `pandoc " FilePath -> FilePath -> FilePath
    forall a. Semigroup a => a -> a -> a
    <> FilePath
    inputFile FilePath -> FilePath -> FilePath
    forall a. Semigroup a => a -> a -> a
    <> " -o " FilePath -> FilePath -> FilePath
    forall a. Semigroup a => a -> a -> a
    <> FilePath
    outputFile FilePath -> FilePath -> FilePath
    forall a. Semigroup a => a -> a -> a
    <> "`."
            _ -> () -> PandocIO ()
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()

        (Reader PandocIO
    reader :: Reader PandocIO, readerExts :: Extensions
    readerExts) <- Text -> PandocIO (Reader PandocIO, Extensions)
    forall (m :: * -> *).
    PandocMonad m =>
    Text -> m (Reader m, Extensions)
    getReader Text
    readerName

        let convertTabs :: Text -> Text
    convertTabs = Int -> Text -> Text
    tabFilter (if Opt -> Bool
    optPreserveTabs Opt
    opts Bool -> Bool -> Bool
    ||
                                          Text
    readerName Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == "t2t" Bool -> Bool -> Bool
    ||
                                          Text
    readerName Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == "man"
                                        then 0
                                        else Opt -> Int
    optTabStop Opt
    opts)

        let readSources :: [FilePath] -> PandocIO Text
            readSources :: [FilePath] -> PandocIO Text
    readSources srcs :: [FilePath]
    srcs = Text -> Text
    convertTabs (Text -> Text) -> ([Text] -> Text) -> [Text] -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> [Text] -> Text
    T.intercalate (FilePath -> Text
    T.pack "\n") ([Text] -> Text) -> PandocIO [Text] -> PandocIO Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
                                  (FilePath -> PandocIO Text) -> [FilePath] -> PandocIO [Text]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM FilePath -> PandocIO Text
    readSource [FilePath]
    srcs

        OutputSettings
    outputSettings <- Opt -> PandocIO OutputSettings
    optToOutputSettings Opt
    opts
        let format :: Text
    format = OutputSettings -> Text
    outputFormat OutputSettings
    outputSettings
        let writer :: Writer PandocIO
    writer = OutputSettings -> Writer PandocIO
    outputWriter OutputSettings
    outputSettings
        let writerName :: Text
    writerName = OutputSettings -> Text
    outputWriterName OutputSettings
    outputSettings
        let writerOptions :: WriterOptions
    writerOptions = OutputSettings -> WriterOptions
    outputWriterOptions OutputSettings
    outputSettings

        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

        -- We don't want to send output to the terminal if the user
        -- does 'pandoc -t docx input.txt'; though we allow them to
        -- force this with '-o -'.  On posix systems, we detect
        -- when stdout is being piped and allow output to stdout
        -- in that case, but on Windows we can't.
        Bool -> PandocIO () -> PandocIO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when ((Bool
    pdfOutput Bool -> Bool -> Bool
    || Bool -> Bool
    not (Text -> Bool
    isTextFormat Text
    format)) Bool -> Bool -> Bool
    &&
                 Bool
    istty Bool -> Bool -> Bool
    && Maybe FilePath -> Bool
    forall a. Maybe a -> Bool
    isNothing ( Opt -> Maybe FilePath
    optOutputFile Opt
    opts)) (PandocIO () -> PandocIO ()) -> PandocIO () -> PandocIO ()
    forall a b. (a -> b) -> a -> b
    $
          PandocError -> PandocIO ()
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError (PandocError -> PandocIO ()) -> PandocError -> PandocIO ()
    forall a b. (a -> b) -> a -> b
    $ Text -> PandocError
    PandocAppError (Text -> PandocError) -> Text -> PandocError
    forall a b. (a -> b) -> a -> b
    $
                  "Cannot write " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    format Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> " output to terminal.\n" Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <>
                  "Specify an output file using the -o option, or " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <>
                  "use '-o -' to force output to stdout."

        Set Text
    abbrevs <- [Text] -> Set Text
    forall a. Ord a => [a] -> Set a
    Set.fromList ([Text] -> Set Text)
    -> (ByteString -> [Text]) -> ByteString -> Set Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Text -> Bool) -> [Text] -> [Text]
    forall a. (a -> Bool) -> [a] -> [a]
    filter (Bool -> Bool
    not (Bool -> Bool) -> (Text -> Bool) -> Text -> Bool
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Bool
    T.null) ([Text] -> [Text])
    -> (ByteString -> [Text]) -> ByteString -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> [Text]
    T.lines (Text -> [Text]) -> (ByteString -> Text) -> ByteString -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> Text
    UTF8.toText (ByteString -> Set Text)
    -> PandocIO ByteString -> PandocIO (Set Text)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$>
                   case Opt -> Maybe FilePath
    optAbbreviations Opt
    opts of
                        Nothing -> FilePath -> PandocIO ByteString
    forall (m :: * -> *). PandocMonad m => FilePath -> m ByteString
    readDataFile "abbreviations"
                        Just f :: FilePath
    f  -> FilePath -> PandocIO ByteString
    forall (m :: * -> *). PandocMonad m => FilePath -> m ByteString
    readFileStrict FilePath
    f

        Meta
    metadata <- if Text
    format Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == "jats" Bool -> Bool -> Bool
    &&
                       Maybe MetaValue -> Bool
    forall a. Maybe a -> Bool
    isNothing (Text -> Meta -> Maybe MetaValue
    lookupMeta "csl" (Opt -> Meta
    optMetadata Opt
    opts)) Bool -> Bool -> Bool
    &&
                       Maybe MetaValue -> Bool
    forall a. Maybe a -> Bool
    isNothing (Text -> Meta -> Maybe MetaValue
    lookupMeta "citation-style"
                                                   (Opt -> Meta
    optMetadata Opt
    opts))
                       then do
                         ByteString
    jatsCSL <- FilePath -> PandocIO ByteString
    forall (m :: * -> *). PandocMonad m => FilePath -> m ByteString
    readDataFile "jats.csl"
                         let jatsEncoded :: Text
    jatsEncoded = (Text, ByteString) -> Text
    makeDataURI
                                             ("application/xml", ByteString
    jatsCSL)
                         Meta -> PandocIO Meta
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Meta -> PandocIO Meta) -> Meta -> PandocIO Meta
    forall a b. (a -> b) -> a -> b
    $ Text -> Text -> Meta -> Meta
    forall a b. (HasMeta a, ToMetaValue b) => Text -> b -> a -> a
    setMeta "csl" Text
    jatsEncoded (Meta -> Meta) -> Meta -> Meta
    forall a b. (a -> b) -> a -> b
    $ Opt -> Meta
    optMetadata Opt
    opts
                       else Meta -> PandocIO Meta
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Meta -> PandocIO Meta) -> Meta -> PandocIO Meta
    forall a b. (a -> b) -> a -> b
    $ Opt -> Meta
    optMetadata Opt
    opts

        case Text -> Meta -> Text
    lookupMetaString "lang" (Opt -> Meta
    optMetadata Opt
    opts) of
               ""      -> Lang -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => Lang -> m ()
    setTranslations (Lang -> PandocIO ()) -> Lang -> PandocIO ()
    forall a b. (a -> b) -> a -> b
    $ Text -> Text -> Text -> [Text] -> Lang
    Lang "en" "" "US" []
               l :: Text
    l       -> case Text -> Either Text Lang
    parseBCP47 Text
    l of
                               Left _   -> LogMessage -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
    report (LogMessage -> PandocIO ()) -> LogMessage -> PandocIO ()
    forall a b. (a -> b) -> a -> b
    $ Text -> LogMessage
    InvalidLang Text
    l
                               Right l' :: Lang
    l' -> Lang -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => Lang -> m ()
    setTranslations Lang
    l'

        let readerOpts :: ReaderOptions
    readerOpts = ReaderOptions
    forall a. Default a => a
    def{
                readerStandalone :: Bool
    readerStandalone = Bool
    standalone
              , readerColumns :: Int
    readerColumns = Opt -> Int
    optColumns Opt
    opts
              , readerTabStop :: Int
    readerTabStop = Opt -> Int
    optTabStop Opt
    opts
              , readerIndentedCodeClasses :: [Text]
    readerIndentedCodeClasses = Opt -> [Text]
    optIndentedCodeClasses Opt
    opts
              , readerDefaultImageExtension :: Text
    readerDefaultImageExtension =
                 Opt -> Text
    optDefaultImageExtension Opt
    opts
              , readerTrackChanges :: TrackChanges
    readerTrackChanges = Opt -> TrackChanges
    optTrackChanges Opt
    opts
              , readerAbbreviations :: Set Text
    readerAbbreviations = Set Text
    abbrevs
              , readerExtensions :: Extensions
    readerExtensions = Extensions
    readerExts
              , readerStripComments :: Bool
    readerStripComments = Opt -> Bool
    optStripComments Opt
    opts
              }

        Meta
    metadataFromFile <-
          case Opt -> [FilePath]
    optMetadataFiles Opt
    opts of
            []    -> Meta -> PandocIO Meta
    forall (m :: * -> *) a. Monad m => a -> m a
    return Meta
    forall a. Monoid a => a
    mempty
            paths :: [FilePath]
    paths -> (FilePath -> PandocIO ByteString)
    -> [FilePath] -> PandocIO [ByteString]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM FilePath -> PandocIO ByteString
    forall (m :: * -> *). PandocMonad m => FilePath -> m ByteString
    readFileLazy [FilePath]
    paths PandocIO [ByteString]
    -> ([ByteString] -> PandocIO Meta) -> PandocIO Meta
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
                        ([Meta] -> Meta) -> PandocIO [Meta] -> PandocIO Meta
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap [Meta] -> Meta
    forall a. Monoid a => [a] -> a
    mconcat (PandocIO [Meta] -> PandocIO Meta)
    -> ([ByteString] -> PandocIO [Meta])
    -> [ByteString]
    -> PandocIO Meta
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (ByteString -> PandocIO Meta) -> [ByteString] -> PandocIO [Meta]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM (ReaderOptions -> ByteString -> PandocIO Meta
    forall (m :: * -> *).
    PandocMonad m =>
    ReaderOptions -> ByteString -> m Meta
    yamlToMeta ReaderOptions
    readerOpts)

        let transforms :: [Pandoc -> Pandoc]
    transforms = (case Opt -> Int
    optShiftHeadingLevelBy Opt
    opts of
                              0             -> [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
    forall a. a -> a
    id
                              x :: Int
    x             -> (Int -> Pandoc -> Pandoc
    headerShift Int
    x (Pandoc -> Pandoc) -> [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
    forall a. a -> [a] -> [a]
    :)) ([Pandoc -> Pandoc] -> [Pandoc -> Pandoc])
    -> ([Pandoc -> Pandoc] -> [Pandoc -> Pandoc])
    -> [Pandoc -> Pandoc]
    -> [Pandoc -> Pandoc]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                         (if Opt -> Bool
    optStripEmptyParagraphs Opt
    opts
                             then (Pandoc -> Pandoc
    stripEmptyParagraphs (Pandoc -> Pandoc) -> [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
    forall a. a -> [a] -> [a]
    :)
                             else [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
    forall a. a -> a
    id) ([Pandoc -> Pandoc] -> [Pandoc -> Pandoc])
    -> ([Pandoc -> Pandoc] -> [Pandoc -> Pandoc])
    -> [Pandoc -> Pandoc]
    -> [Pandoc -> Pandoc]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                         (if Extension -> Extensions -> Bool
    extensionEnabled Extension
    Ext_east_asian_line_breaks
                                Extensions
    readerExts Bool -> Bool -> Bool
    &&
                             Bool -> Bool
    not (Extension -> Extensions -> Bool
    extensionEnabled Extension
    Ext_east_asian_line_breaks
                                  (WriterOptions -> Extensions
    writerExtensions WriterOptions
    writerOptions) Bool -> Bool -> Bool
    &&
                                  WriterOptions -> WrapOption
    writerWrapText WriterOptions
    writerOptions WrapOption -> WrapOption -> Bool
    forall a. Eq a => a -> a -> Bool
    == WrapOption
    WrapPreserve)
                             then (Pandoc -> Pandoc
    eastAsianLineBreakFilter (Pandoc -> Pandoc) -> [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
    forall a. a -> [a] -> [a]
    :)
                             else [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
    forall a. a -> a
    id) ([Pandoc -> Pandoc] -> [Pandoc -> Pandoc])
    -> ([Pandoc -> Pandoc] -> [Pandoc -> Pandoc])
    -> [Pandoc -> Pandoc]
    -> [Pandoc -> Pandoc]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    .
                         (case Opt -> IpynbOutput
    optIpynbOutput Opt
    opts of
                           IpynbOutputAll  -> [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
    forall a. a -> a
    id
                           IpynbOutputNone -> (Maybe Format -> Pandoc -> Pandoc
    filterIpynbOutput Maybe Format
    forall a. Maybe a
    Nothing (Pandoc -> Pandoc) -> [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
    forall a. a -> [a] -> [a]
    :)
                           IpynbOutputBest -> (Maybe Format -> Pandoc -> Pandoc
    filterIpynbOutput (Format -> Maybe Format
    forall a. a -> Maybe a
    Just (Format -> Maybe Format) -> Format -> Maybe Format
    forall a b. (a -> b) -> a -> b
    $
                                         if Text -> Bool
    htmlFormat Text
    format
                                            then Text -> Format
    Format "html"
                                            else
                                              case Text
    format of
                                                "latex"  -> Text -> Format
    Format "latex"
                                                "beamer" -> Text -> Format
    Format "latex"
                                                _        -> Text -> Format
    Format Text
    format) (Pandoc -> Pandoc) -> [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
    forall a. a -> [a] -> [a]
    :))
                         ([Pandoc -> Pandoc] -> [Pandoc -> Pandoc])
    -> [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
    forall a b. (a -> b) -> a -> b
    $ []

        let sourceToDoc :: [FilePath] -> PandocIO Pandoc
            sourceToDoc :: [FilePath] -> PandocIO Pandoc
    sourceToDoc sources' :: [FilePath]
    sources' =
               case Reader PandocIO
    reader of
                    TextReader r :: ReaderOptions -> Text -> PandocIO Pandoc
    r
                      | Opt -> Bool
    optFileScope Opt
    opts Bool -> Bool -> Bool
    || Text
    readerName Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == "json" ->
                          [Pandoc] -> Pandoc
    forall a. Monoid a => [a] -> a
    mconcat ([Pandoc] -> Pandoc) -> PandocIO [Pandoc] -> PandocIO Pandoc
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (FilePath -> PandocIO Pandoc) -> [FilePath] -> PandocIO [Pandoc]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM (FilePath -> PandocIO Text
    readSource (FilePath -> PandocIO Text)
    -> (Text -> PandocIO Pandoc) -> FilePath -> PandocIO Pandoc
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> ReaderOptions -> Text -> PandocIO Pandoc
    r ReaderOptions
    readerOpts) [FilePath]
    sources'
                      | Bool
    otherwise ->
                          [FilePath] -> PandocIO Text
    readSources [FilePath]
    sources' PandocIO Text -> (Text -> PandocIO Pandoc) -> PandocIO Pandoc
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= ReaderOptions -> Text -> PandocIO Pandoc
    r ReaderOptions
    readerOpts
                    ByteStringReader r :: ReaderOptions -> ByteString -> PandocIO Pandoc
    r ->
                      [Pandoc] -> Pandoc
    forall a. Monoid a => [a] -> a
    mconcat ([Pandoc] -> Pandoc) -> PandocIO [Pandoc] -> PandocIO Pandoc
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> (FilePath -> PandocIO Pandoc) -> [FilePath] -> PandocIO [Pandoc]
    forall (t :: * -> *) (m :: * -> *) a b.
    (Traversable t, Monad m) =>
    (a -> m b) -> t a -> m (t b)
    mapM (FilePath -> PandocIO ByteString
    forall (m :: * -> *). MonadIO m => FilePath -> m ByteString
    readFile' (FilePath -> PandocIO ByteString)
    -> (ByteString -> PandocIO Pandoc) -> FilePath -> PandocIO Pandoc
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> ReaderOptions -> ByteString -> PandocIO Pandoc
    r ReaderOptions
    readerOpts) [FilePath]
    sources'

        Bool -> PandocIO () -> PandocIO ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Text
    readerName Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == "markdown_github" Bool -> Bool -> Bool
    ||
              Text
    writerName Text -> Text -> Bool
    forall a. Eq a => a -> a -> Bool
    == "markdown_github") (PandocIO () -> PandocIO ()) -> PandocIO () -> PandocIO ()
    forall a b. (a -> b) -> a -> b
    $
          LogMessage -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
    report (LogMessage -> PandocIO ()) -> LogMessage -> PandocIO ()
    forall a b. (a -> b) -> a -> b
    $ Text -> Text -> LogMessage
    Deprecated "markdown_github" "Use gfm instead."

        ((Text, Text) -> PandocIO ()) -> [(Text, Text)] -> PandocIO ()
    forall (t :: * -> *) (m :: * -> *) a b.
    (Foldable t, Monad m) =>
    (a -> m b) -> t a -> m ()
    mapM_ ((Text -> Text -> PandocIO ()) -> (Text, Text) -> PandocIO ()
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry Text -> Text -> PandocIO ()
    forall (m :: * -> *). PandocMonad m => Text -> Text -> m ()
    setRequestHeader) (Opt -> [(Text, Text)]
    optRequestHeaders Opt
    opts)

        Pandoc
    doc <- [FilePath] -> PandocIO Pandoc
    sourceToDoc [FilePath]
    sources PandocIO Pandoc -> (Pandoc -> PandocIO Pandoc) -> PandocIO Pandoc
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>=
                  (   (if Maybe FilePath -> Bool
    forall a. Maybe a -> Bool
    isJust (Opt -> Maybe FilePath
    optExtractMedia Opt
    opts)
                          then Pandoc -> PandocIO Pandoc
    forall (m :: * -> *). PandocMonad m => Pandoc -> m Pandoc
    fillMediaBag
                          else Pandoc -> PandocIO Pandoc
    forall (m :: * -> *) a. Monad m => a -> m a
    return)
                  (Pandoc -> PandocIO Pandoc)
    -> (Pandoc -> PandocIO Pandoc) -> Pandoc -> PandocIO Pandoc
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> Pandoc -> PandocIO Pandoc
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Pandoc -> PandocIO Pandoc)
    -> (Pandoc -> Pandoc) -> Pandoc -> PandocIO Pandoc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Meta -> Meta) -> Pandoc -> Pandoc
    adjustMetadata (Meta
    metadataFromFile Meta -> Meta -> Meta
    forall a. Semigroup a => a -> a -> a
    <>)
                  (Pandoc -> PandocIO Pandoc)
    -> (Pandoc -> PandocIO Pandoc) -> Pandoc -> PandocIO Pandoc
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> Pandoc -> PandocIO Pandoc
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Pandoc -> PandocIO Pandoc)
    -> (Pandoc -> Pandoc) -> Pandoc -> PandocIO Pandoc
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Meta -> Meta) -> Pandoc -> Pandoc
    adjustMetadata (Meta -> Meta -> Meta
    forall a. Semigroup a => a -> a -> a
    <> Meta
    metadata)
                  (Pandoc -> PandocIO Pandoc)
    -> (Pandoc -> PandocIO Pandoc) -> Pandoc -> PandocIO Pandoc
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> [Pandoc -> Pandoc] -> Pandoc -> PandocIO Pandoc
    forall (m :: * -> *).
    Monad m =>
    [Pandoc -> Pandoc] -> Pandoc -> m Pandoc
    applyTransforms [Pandoc -> Pandoc]
    transforms
                  (Pandoc -> PandocIO Pandoc)
    -> (Pandoc -> PandocIO Pandoc) -> Pandoc -> PandocIO Pandoc
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> ReaderOptions
    -> [Filter] -> [FilePath] -> Pandoc -> PandocIO Pandoc
    applyFilters ReaderOptions
    readerOpts [Filter]
    filters' [Text -> FilePath
    T.unpack Text
    format]
                  (Pandoc -> PandocIO Pandoc)
    -> (Pandoc -> PandocIO Pandoc) -> Pandoc -> PandocIO Pandoc
    forall (m :: * -> *) a b c.
    Monad m =>
    (a -> m b) -> (b -> m c) -> a -> m c
    >=> (Pandoc -> PandocIO Pandoc)
    -> (FilePath -> Pandoc -> PandocIO Pandoc)
    -> Maybe FilePath
    -> Pandoc
    -> PandocIO Pandoc
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe Pandoc -> PandocIO Pandoc
    forall (m :: * -> *) a. Monad m => a -> m a
    return FilePath -> Pandoc -> PandocIO Pandoc
    extractMedia (Opt -> Maybe FilePath
    optExtractMedia Opt
    opts)
                  )

        case Writer PandocIO
    writer of
          ByteStringWriter f :: WriterOptions -> Pandoc -> PandocIO ByteString
    f -> WriterOptions -> Pandoc -> PandocIO ByteString
    f WriterOptions
    writerOptions Pandoc
    doc PandocIO ByteString -> (ByteString -> PandocIO ()) -> PandocIO ()
    forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
    >>= FilePath -> ByteString -> PandocIO ()
    forall (m :: * -> *). MonadIO m => FilePath -> ByteString -> m ()
    writeFnBinary FilePath
    outputFile
          TextWriter f :: WriterOptions -> Pandoc -> PandocIO Text
    f -> case OutputSettings -> Maybe FilePath
    outputPdfProgram OutputSettings
    outputSettings of
            Just pdfProg :: FilePath
    pdfProg -> do
                    Either ByteString ByteString
    res <- FilePath
    -> [FilePath]
    -> (WriterOptions -> Pandoc -> PandocIO Text)
    -> WriterOptions
    -> Pandoc
    -> PandocIO (Either ByteString ByteString)
    makePDF FilePath
    pdfProg (Opt -> [FilePath]
    optPdfEngineOpts Opt
    opts) WriterOptions -> Pandoc -> PandocIO Text
    f
                            WriterOptions
    writerOptions Pandoc
    doc
                    case Either ByteString ByteString
    res of
                         Right pdf :: ByteString
    pdf -> FilePath -> ByteString -> PandocIO ()
    forall (m :: * -> *). MonadIO m => FilePath -> ByteString -> m ()
    writeFnBinary FilePath
    outputFile ByteString
    pdf
                         Left err' :: ByteString
    err' -> PandocError -> PandocIO ()
    forall e (m :: * -> *) a. MonadError e m => e -> m a
    throwError (PandocError -> PandocIO ()) -> PandocError -> PandocIO ()
    forall a b. (a -> b) -> a -> b
    $ Text -> PandocError
    PandocPDFError (Text -> PandocError) -> Text -> PandocError
    forall a b. (a -> b) -> a -> b
    $
                                         Text -> Text
    TL.toStrict (OnDecodeError -> ByteString -> Text
    TE.decodeUtf8With OnDecodeError
    TE.lenientDecode ByteString
    err')

            Nothing -> do
                    let ensureNl :: Text -> Text
    ensureNl t :: Text
    t
                          | Bool
    standalone = Text
    t
                          | Text -> Bool
    T.null Text
    t Bool -> Bool -> Bool
    || Text -> Char
    T.last Text
    t Char -> Char -> Bool
    forall a. Eq a => a -> a -> Bool
    /= '\n' = Text
    t Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Char -> Text
    T.singleton '\n'
                          | Bool
    otherwise = Text
    t
                    Text
    output <- Text -> Text
    ensureNl (Text -> Text) -> PandocIO Text -> PandocIO Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> WriterOptions -> Pandoc -> PandocIO Text
    f WriterOptions
    writerOptions Pandoc
    doc
                    Newline -> FilePath -> Text -> PandocIO ()
    forall (m :: * -> *).
    MonadIO m =>
    Newline -> FilePath -> Text -> m ()
    writerFn Newline
    eol FilePath
    outputFile (Text -> PandocIO ()) -> PandocIO Text -> PandocIO ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<<
                      if Opt -> Bool
    optSelfContained Opt
    opts Bool -> Bool -> Bool
    && Text -> Bool
    htmlFormat Text
    format
                         then Text -> PandocIO Text
    forall (m :: * -> *). PandocMonad m => Text -> m Text
    makeSelfContained Text
    output
                         else Text -> PandocIO Text
    forall (m :: * -> *) a. Monad m => a -> m a
    return Text
    output

    type Transform = Pandoc -> Pandoc

    htmlFormat :: Text -> Bool
    htmlFormat :: Text -> Bool
    htmlFormat = (Text -> [Text] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` ["html","html4","html5","s5","slidy",
                          "slideous","dzslides","revealjs"])

    isTextFormat :: 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"]

    adjustMetadata :: (Meta -> Meta) -> Pandoc -> Pandoc
    adjustMetadata :: (Meta -> Meta) -> Pandoc -> Pandoc
    adjustMetadata f :: Meta -> Meta
    f (Pandoc meta :: Meta
    meta bs :: [Block]
    bs) = Meta -> [Block] -> Pandoc
    Pandoc (Meta -> Meta
    f Meta
    meta) [Block]
    bs

    -- Transformations of a Pandoc document post-parsing:

    applyTransforms :: Monad m => [Transform] -> Pandoc -> m Pandoc
    applyTransforms :: [Pandoc -> Pandoc] -> Pandoc -> m Pandoc
    applyTransforms transforms :: [Pandoc -> Pandoc]
    transforms d :: Pandoc
    d = Pandoc -> m Pandoc
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Pandoc -> m Pandoc) -> Pandoc -> m Pandoc
    forall a b. (a -> b) -> a -> b
    $ ((Pandoc -> Pandoc) -> Pandoc -> Pandoc)
    -> Pandoc -> [Pandoc -> Pandoc] -> Pandoc
    forall (t :: * -> *) a b.
    Foldable t =>
    (a -> b -> b) -> b -> t a -> b
    foldr (Pandoc -> Pandoc) -> Pandoc -> Pandoc
    forall a b. (a -> b) -> a -> b
    ($) Pandoc
    d [Pandoc -> Pandoc]
    transforms

    readSource :: FilePath -> PandocIO Text
    readSource :: FilePath -> PandocIO Text
    readSource src :: FilePath
    src = case FilePath -> Maybe URI
    parseURI FilePath
    src of
                          Just u :: URI
    u | URI -> FilePath
    uriScheme URI
    u FilePath -> [FilePath] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` ["http:","https:"] ->
                                     FilePath -> PandocIO Text
    readURI FilePath
    src
                                 | URI -> FilePath
    uriScheme URI
    u FilePath -> FilePath -> Bool
    forall a. Eq a => a -> a -> Bool
    == "file:" -> IO Text -> PandocIO Text
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Text -> PandocIO Text) -> IO Text -> PandocIO Text
    forall a b. (a -> b) -> a -> b
    $
                                     FilePath -> IO Text
    readTextFile (Text -> FilePath
    uriPathToPath (Text -> FilePath) -> Text -> FilePath
    forall a b. (a -> b) -> a -> b
    $ FilePath -> Text
    T.pack (FilePath -> Text) -> FilePath -> Text
    forall a b. (a -> b) -> a -> b
    $ URI -> FilePath
    uriPath URI
    u)
                          _       -> IO Text -> PandocIO Text
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO Text -> PandocIO Text) -> IO Text -> PandocIO Text
    forall a b. (a -> b) -> a -> b
    $ FilePath -> IO Text
    readTextFile FilePath
    src
      where readTextFile :: FilePath -> IO Text
            readTextFile :: FilePath -> IO Text
    readTextFile fp :: FilePath
    fp = do
              ByteString
    bs <- if FilePath
    src FilePath -> FilePath -> Bool
    forall a. Eq a => a -> a -> Bool
    == "-"
                       then IO ByteString
    BS.getContents
                       else FilePath -> IO ByteString
    BS.readFile FilePath
    fp
              IO Text -> (UnicodeException -> IO Text) -> IO Text
    forall e a. Exception e => IO a -> (e -> IO a) -> IO a
    E.catch (Text -> IO Text
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Text -> IO Text) -> Text -> IO Text
    forall a b. (a -> b) -> a -> b
    $! ByteString -> Text
    UTF8.toText ByteString
    bs)
                 (\e :: UnicodeException
    e -> PandocError -> IO Text
    forall e a. Exception e => e -> IO a
    E.throwIO (PandocError -> IO Text) -> PandocError -> IO Text
    forall a b. (a -> b) -> a -> b
    $ case UnicodeException
    e of
                             TSE.DecodeError _ (Just w :: Word8
    w) ->
                               case Word8 -> ByteString -> Maybe Int
    BS.elemIndex Word8
    w ByteString
    bs of
                                 Just offset :: Int
    offset ->
                                      Text -> Int -> Word8 -> PandocError
    PandocUTF8DecodingError (FilePath -> Text
    T.pack FilePath
    fp) Int
    offset Word8
    w
                                 _ -> Text -> Int -> Word8 -> PandocError
    PandocUTF8DecodingError (FilePath -> Text
    T.pack FilePath
    fp) 0 Word8
    w
                             _ -> Text -> PandocError
    PandocAppError (UnicodeException -> Text
    forall a. Show a => a -> Text
    tshow UnicodeException
    e))

    readURI :: FilePath -> PandocIO Text
    readURI :: FilePath -> PandocIO Text
    readURI src :: FilePath
    src = 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)
    -> PandocIO (ByteString, Maybe Text) -> PandocIO Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> Text -> PandocIO (ByteString, Maybe Text)
    forall (m :: * -> *).
    PandocMonad m =>
    Text -> m (ByteString, Maybe Text)
    openURL (FilePath -> Text
    T.pack FilePath
    src)

    readFile' :: MonadIO m => FilePath -> m BL.ByteString
    readFile' :: FilePath -> m ByteString
    readFile' "-" = IO ByteString -> m ByteString
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO IO ByteString
    BL.getContents
    readFile' f :: FilePath
    f   = IO ByteString -> m ByteString
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO ByteString -> m ByteString) -> IO ByteString -> m ByteString
    forall a b. (a -> b) -> a -> b
    $ FilePath -> IO ByteString
    BL.readFile FilePath
    f

    writeFnBinary :: MonadIO m => FilePath -> BL.ByteString -> m ()
    writeFnBinary :: FilePath -> ByteString -> m ()
    writeFnBinary "-" = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (ByteString -> IO ()) -> ByteString -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ByteString -> IO ()
    BL.putStr
    writeFnBinary f :: FilePath
    f   = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (ByteString -> IO ()) -> ByteString -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> ByteString -> IO ()
    BL.writeFile (FilePath -> FilePath
    UTF8.encodePath FilePath
    f)

    writerFn :: MonadIO m => IO.Newline -> FilePath -> Text -> m ()
    -- TODO this implementation isn't maximally efficient:
    writerFn :: Newline -> FilePath -> Text -> m ()
    writerFn eol :: Newline
    eol "-" = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (Text -> IO ()) -> Text -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Newline -> FilePath -> IO ()
    UTF8.putStrWith Newline
    eol (FilePath -> IO ()) -> (Text -> FilePath) -> Text -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> FilePath
    T.unpack
    writerFn eol :: Newline
    eol f :: FilePath
    f   = IO () -> m ()
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO () -> m ()) -> (Text -> IO ()) -> Text -> m ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Newline -> FilePath -> FilePath -> IO ()
    UTF8.writeFileWith Newline
    eol FilePath
    f (FilePath -> IO ()) -> (Text -> FilePath) -> Text -> IO ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> FilePath
    T.unpack