{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Text.Pandoc.App (
convertWithOpts
, Opt(..)
, LineEnding(..)
, Filter(..)
, defaultOpts
, parseOptions
, parseOptionsFromArgs
, options
, applyFilters
) where
import qualified Control.Exception as E
import Control.Monad ( (>=>), when )
import Control.Monad.Trans ( MonadIO(..) )
import Control.Monad.Except (throwError)
import qualified Data.ByteString as BS
import qualified Data.ByteString.Char8 as B8
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 ( takeBaseName, takeExtension )
import System.IO (nativeNewline, stdout)
import qualified System.IO as IO (Newline (..))
import Text.Pandoc
import Text.Pandoc.Builder (setMeta)
import Text.Pandoc.MIME (getCharset)
import Text.Pandoc.App.FormatHeuristics (formatFromFilePaths)
import Text.Pandoc.App.Opt (Opt (..), LineEnding (..), defaultOpts,
IpynbOutput (..))
import Text.Pandoc.App.CommandLineOptions (parseOptions, parseOptionsFromArgs,
options)
import Text.Pandoc.App.OutputSettings (OutputSettings (..), optToOutputSettings)
import Text.Collate.Lang (Lang (..), parseLang)
import Text.Pandoc.Filter (Filter (JSONFilter, LuaFilter), applyFilters)
import Text.Pandoc.PDF (makePDF)
import Text.Pandoc.SelfContained (makeSelfContained)
import Text.Pandoc.Shared (eastAsianLineBreakFilter, stripEmptyParagraphs,
headerShift, isURI, tabFilter, uriPathToPath, filterIpynbOutput,
defaultUserDataDir, tshow)
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 Opt
opts = do
Maybe FilePath
datadir <- case Opt -> Maybe FilePath
optDataDir Opt
opts of
Maybe FilePath
Nothing -> do
FilePath
d <- IO FilePath
defaultUserDataDir
Bool
exists <- FilePath -> IO Bool
doesDirectoryExist FilePath
d
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
$ if Bool
exists
then FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
d
else Maybe FilePath
forall a. Maybe a
Nothing
Just FilePath
_ -> 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 outputFile :: FilePath
outputFile = FilePath -> Maybe FilePath -> FilePath
forall a. a -> Maybe a -> a
fromMaybe FilePath
"-" (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 -> Text -> IO ()
UTF8.hPutStrLn Handle
stdout (FilePath -> Text
T.pack FilePath
outputFile)
(FilePath -> IO ()) -> [FilePath] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (Handle -> Text -> IO ()
UTF8.hPutStrLn Handle
stdout (Text -> IO ()) -> (FilePath -> Text) -> FilePath -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Text
T.pack)
([FilePath] -> Maybe [FilePath] -> [FilePath]
forall a. a -> Maybe a -> a
fromMaybe [FilePath
"-"] (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 sources :: [FilePath]
sources = case Opt -> Maybe [FilePath]
optInputFiles Opt
opts of
Just [FilePath]
xs | Bool -> Bool
not (Opt -> Bool
optIgnoreArgs Opt
opts) -> [FilePath]
xs
Maybe [FilePath]
_ -> [FilePath
"-"]
let runIO' :: PandocIO a -> IO a
runIO' :: PandocIO a -> IO a
runIO' PandocIO a
f = do
(a
res, [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
Maybe FilePath
Nothing -> () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just FilePath
logfile -> FilePath -> ByteString -> IO ()
BL.writeFile FilePath
logfile ([LogMessage] -> ByteString
encodeLogMessages [LogMessage]
reports)
let isWarning :: LogMessage -> Bool
isWarning 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
LineEnding
CRLF -> Newline
IO.CRLF
LineEnding
LF -> Newline
IO.LF
LineEnding
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 [FilePath
"-"] (Opt -> Maybe [FilePath]
optInputFiles Opt
opts))
Maybe FilePath -> PandocIO ()
forall (m :: * -> *). PandocMonad m => Maybe FilePath -> m ()
setOutputFile (Opt -> Maybe FilePath
optOutputFile Opt
opts)
Text
readerName <- case Opt -> Maybe Text
optFrom Opt
opts of
Just Text
f -> Text -> PandocIO Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
f
Maybe Text
Nothing -> case [FilePath] -> Maybe Text
formatFromFilePaths [FilePath]
sources of
Just Text
f' -> Text -> PandocIO Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
f'
Maybe Text
Nothing | [FilePath]
sources [FilePath] -> [FilePath] -> Bool
forall a. Eq a => a -> a -> Bool
== [FilePath
"-"] -> Text -> PandocIO Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
"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 Text
"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) Text
"markdown"
Text -> PandocIO Text
forall (m :: * -> *) a. Monad m => a -> m a
return Text
"markdown"
let readerNameBase :: Text
readerNameBase = (Char -> Bool) -> Text -> Text
T.takeWhile (\Char
c -> Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'+' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'-') Text
readerName
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
== FilePath
".pdf"
Bool -> PandocIO () -> PandocIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
pdfOutput Bool -> Bool -> Bool
&& Text
readerNameBase Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"latex") (PandocIO () -> PandocIO ()) -> PandocIO () -> PandocIO ()
forall a b. (a -> b) -> a -> b
$
case Opt -> Maybe [FilePath]
optInputFiles Opt
opts of
Just (FilePath
inputFile:[FilePath]
_) -> 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
$
FilePath
"to convert a .tex file to PDF, you get better results by using pdflatex "
FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
"(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
<> FilePath
"` 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
<> FilePath
" -o " FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
outputFile FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
"`."
Maybe [FilePath]
_ -> () -> PandocIO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
(Reader PandocIO
reader :: Reader PandocIO, 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
readerNameBase Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"t2t" Bool -> Bool -> Bool
||
Text
readerNameBase Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"man"
then Int
0
else Opt -> Int
optTabStop Opt
opts)
let readSources :: [FilePath] -> PandocIO [(FilePath, Text)]
readSources :: [FilePath] -> PandocIO [(FilePath, Text)]
readSources [FilePath]
srcs =
(FilePath -> PandocIO (FilePath, Text))
-> [FilePath] -> PandocIO [(FilePath, Text)]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (\FilePath
fp -> do
Text
t <- FilePath -> PandocIO Text
readSource FilePath
fp
(FilePath, Text) -> PandocIO (FilePath, Text)
forall (m :: * -> *) a. Monad m => a -> m a
return (if FilePath
fp FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
"-" then FilePath
"" else FilePath
fp, Text -> Text
convertTabs Text
t)) [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 writerNameBase :: Text
writerNameBase = (Char -> Bool) -> Text -> Text
T.takeWhile (\Char
c -> Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'+' Bool -> Bool -> Bool
&& Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'-') Text
writerName
let writerOptions :: WriterOptions
writerOptions = OutputSettings -> WriterOptions
outputWriterOptions OutputSettings
outputSettings
let bibOutput :: Bool
bibOutput = Text
writerNameBase Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"bibtex" Bool -> Bool -> Bool
||
Text
writerNameBase Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"biblatex" Bool -> Bool -> Bool
||
Text
writerNameBase Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"csljson"
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 Bool -> Bool -> Bool
||
Bool
bibOutput
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
$
Text
"Cannot write " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
format Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" output to terminal.\n" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
"Specify an output file using the -o option, or " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>
Text
"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
Maybe FilePath
Nothing -> FilePath -> PandocIO ByteString
forall (m :: * -> *). PandocMonad m => FilePath -> m ByteString
readDataFile FilePath
"abbreviations"
Just FilePath
f -> FilePath -> PandocIO ByteString
forall (m :: * -> *). PandocMonad m => FilePath -> m ByteString
readFileStrict FilePath
f
case Text -> Meta -> Text
lookupMetaString Text
"lang" (Opt -> Meta
optMetadata Opt
opts) of
Text
"" -> Lang -> PandocIO ()
forall (m :: * -> *). PandocMonad m => Lang -> m ()
setTranslations (Lang -> PandocIO ()) -> Lang -> PandocIO ()
forall a b. (a -> b) -> a -> b
$ Text
-> Maybe Text
-> Maybe Text
-> [Text]
-> [(Text, [(Text, Text)])]
-> [Text]
-> Lang
Lang Text
"en" Maybe Text
forall a. Maybe a
Nothing (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"US") [] [] []
Text
l -> case Text -> Either FilePath Lang
parseLang Text
l of
Left FilePath
_ -> 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 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
[FilePath]
paths -> [Meta] -> Meta
forall a. Monoid a => [a] -> a
mconcat ([Meta] -> Meta) -> PandocIO [Meta] -> PandocIO Meta
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
(FilePath -> PandocIO Meta) -> [FilePath] -> PandocIO [Meta]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (\FilePath
path -> do ByteString
raw <- FilePath -> PandocIO ByteString
forall (m :: * -> *). PandocMonad m => FilePath -> m ByteString
readFileLazy FilePath
path
ReaderOptions -> Maybe FilePath -> ByteString -> PandocIO Meta
forall (m :: * -> *).
PandocMonad m =>
ReaderOptions -> Maybe FilePath -> ByteString -> m Meta
yamlToMeta ReaderOptions
readerOpts (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
path) ByteString
raw) [FilePath]
paths
let transforms :: [Pandoc -> Pandoc]
transforms = (case Opt -> Int
optShiftHeadingLevelBy Opt
opts of
Int
0 -> [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
forall a. a -> a
id
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
IpynbOutput
_ | Text
readerNameBase Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
/= Text
"ipynb" -> [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
forall a. a -> a
id
IpynbOutput
IpynbOutputAll -> [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
forall a. a -> a
id
IpynbOutput
IpynbOutputNone -> (Maybe Format -> Pandoc -> Pandoc
filterIpynbOutput Maybe Format
forall a. Maybe a
Nothing (Pandoc -> Pandoc) -> [Pandoc -> Pandoc] -> [Pandoc -> Pandoc]
forall a. a -> [a] -> [a]
:)
IpynbOutput
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 Text
"html"
else
case Text
format of
Text
"latex" -> Text -> Format
Format Text
"latex"
Text
"beamer" -> Text -> Format
Format Text
"latex"
Text
_ -> 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 [FilePath]
sources' =
case Reader PandocIO
reader of
TextReader forall a. ToSources a => ReaderOptions -> a -> PandocIO Pandoc
r
| Text
readerNameBase Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"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
forall a. ToSources a => ReaderOptions -> a -> PandocIO Pandoc
r ReaderOptions
readerOpts) [FilePath]
sources'
| Opt -> Bool
optFileScope Opt
opts ->
let readSource' :: FilePath -> PandocIO Text
readSource' = (Text -> Text) -> PandocIO Text -> PandocIO Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Text -> Text
convertTabs (PandocIO Text -> PandocIO Text)
-> (FilePath -> PandocIO Text) -> FilePath -> PandocIO Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> PandocIO Text
readSource
in [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
forall a. ToSources a => ReaderOptions -> a -> PandocIO Pandoc
r ReaderOptions
readerOpts) [FilePath]
sources'
| Bool
otherwise ->
[FilePath] -> PandocIO [(FilePath, Text)]
readSources [FilePath]
sources' PandocIO [(FilePath, Text)]
-> ([(FilePath, Text)] -> PandocIO Pandoc) -> PandocIO Pandoc
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ReaderOptions -> [(FilePath, Text)] -> PandocIO Pandoc
forall a. ToSources a => ReaderOptions -> a -> PandocIO Pandoc
r ReaderOptions
readerOpts
ByteStringReader 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
readerNameBase Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"markdown_github" Bool -> Bool -> Bool
||
Text
writerNameBase Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
"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 Text
"markdown_github" Text
"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)
Bool -> PandocIO ()
forall (m :: * -> *). PandocMonad m => Bool -> m ()
setNoCheckCertificate (Opt -> Bool
optNoCheckCertificate Opt
opts)
let isPandocCiteproc :: Filter -> Bool
isPandocCiteproc (JSONFilter FilePath
f) = FilePath -> FilePath
takeBaseName FilePath
f FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
"pandoc-citeproc"
isPandocCiteproc Filter
_ = Bool
False
Bool -> PandocIO () -> PandocIO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ((Filter -> Bool) -> [Filter] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any Filter -> Bool
isPandocCiteproc [Filter]
filters) (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 Text
"pandoc-citeproc filter"
Text
"Use --citeproc instead."
let cslMetadata :: Meta
cslMetadata =
(Meta -> Meta)
-> (FilePath -> Meta -> Meta) -> Maybe FilePath -> Meta -> Meta
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Meta -> Meta
forall a. a -> a
id (Text -> FilePath -> Meta -> Meta
forall a b. (HasMeta a, ToMetaValue b) => Text -> b -> a -> a
setMeta Text
"csl") (Opt -> Maybe FilePath
optCSL Opt
opts) (Meta -> Meta) -> (Meta -> Meta) -> Meta -> Meta
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(case Opt -> [FilePath]
optBibliography Opt
opts of
[] -> Meta -> Meta
forall a. a -> a
id
[FilePath]
xs -> Text -> [FilePath] -> Meta -> Meta
forall a b. (HasMeta a, ToMetaValue b) => Text -> b -> a -> a
setMeta Text
"bibliography" [FilePath]
xs) (Meta -> Meta) -> (Meta -> Meta) -> Meta -> Meta
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
(Meta -> Meta)
-> (FilePath -> Meta -> Meta) -> Maybe FilePath -> Meta -> Meta
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Meta -> Meta
forall a. a -> a
id (Text -> FilePath -> Meta -> Meta
forall a b. (HasMeta a, ToMetaValue b) => Text -> b -> a -> a
setMeta Text
"citation-abbreviations")
(Opt -> Maybe FilePath
optCitationAbbreviations Opt
opts) (Meta -> Meta) -> Meta -> Meta
forall a b. (a -> b) -> a -> b
$ Meta
forall a. Monoid a => a
mempty
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
<> Opt -> Meta
optMetadata Opt
opts)
(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
cslMetadata)
(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 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 WriterOptions -> Pandoc -> PandocIO Text
f -> case OutputSettings -> Maybe FilePath
outputPdfProgram OutputSettings
outputSettings of
Just 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 ByteString
pdf -> FilePath -> ByteString -> PandocIO ()
forall (m :: * -> *). MonadIO m => FilePath -> ByteString -> m ()
writeFnBinary FilePath
outputFile ByteString
pdf
Left 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')
Maybe FilePath
Nothing -> do
let ensureNl :: Text -> Text
ensureNl 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
/= Char
'\n' = Text
t Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Char -> Text
T.singleton Char
'\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` [Text
"html",Text
"html4",Text
"html5",Text
"s5",Text
"slidy",
Text
"slideous",Text
"dzslides",Text
"revealjs"])
isTextFormat :: Text -> Bool
isTextFormat :: Text -> Bool
isTextFormat Text
s = Text
s Text -> [Text] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [Text
"odt",Text
"docx",Text
"epub2",Text
"epub3",Text
"epub",Text
"pptx"]
adjustMetadata :: (Meta -> Meta) -> Pandoc -> Pandoc
adjustMetadata :: (Meta -> Meta) -> Pandoc -> Pandoc
adjustMetadata Meta -> Meta
f (Pandoc Meta
meta [Block]
bs) = Meta -> [Block] -> Pandoc
Pandoc (Meta -> Meta
f Meta
meta) [Block]
bs
applyTransforms :: Monad m => [Transform] -> Pandoc -> m Pandoc
applyTransforms :: [Pandoc -> Pandoc] -> Pandoc -> m Pandoc
applyTransforms [Pandoc -> Pandoc]
transforms 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 FilePath
src = case FilePath -> Maybe URI
parseURI FilePath
src of
Just URI
u | URI -> FilePath
uriScheme URI
u FilePath -> [FilePath] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath
"http:",FilePath
"https:"] ->
FilePath -> PandocIO Text
readURI FilePath
src
| URI -> FilePath
uriScheme URI
u FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
"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)
Maybe URI
_ -> 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 FilePath
fp = do
ByteString
bs <- if FilePath
src FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
"-"
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)
(\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 FilePath
_ (Just Word8
w) ->
case Word8 -> ByteString -> Maybe Int
BS.elemIndex Word8
w ByteString
bs of
Just Int
offset ->
Text -> Int -> Word8 -> PandocError
PandocUTF8DecodingError (FilePath -> Text
T.pack FilePath
fp) Int
offset Word8
w
Maybe Int
_ -> Text -> Int -> Word8 -> PandocError
PandocUTF8DecodingError (FilePath -> Text
T.pack FilePath
fp) Int
0 Word8
w
UnicodeException
_ -> Text -> PandocError
PandocAppError (UnicodeException -> Text
forall a. Show a => a -> Text
tshow UnicodeException
e))
readURI :: FilePath -> PandocIO Text
readURI :: FilePath -> PandocIO Text
readURI FilePath
src = do
(ByteString
bs, Maybe Text
mt) <- Text -> PandocIO (ByteString, Maybe Text)
forall (m :: * -> *).
PandocMonad m =>
Text -> m (ByteString, Maybe Text)
openURL (FilePath -> Text
T.pack FilePath
src)
case Maybe Text
mt Maybe Text -> (Text -> Maybe Text) -> Maybe Text
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text -> Maybe Text
getCharset of
Just Text
"UTF-8" -> Text -> PandocIO Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> PandocIO Text) -> Text -> PandocIO Text
forall a b. (a -> b) -> a -> b
$ ByteString -> Text
UTF8.toText ByteString
bs
Just Text
"ISO-8859-1" -> Text -> PandocIO Text
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> PandocIO Text) -> Text -> PandocIO Text
forall a b. (a -> b) -> a -> b
$ FilePath -> Text
T.pack (FilePath -> Text) -> FilePath -> Text
forall a b. (a -> b) -> a -> b
$ ByteString -> FilePath
B8.unpack ByteString
bs
Just Text
charset -> PandocError -> PandocIO Text
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (PandocError -> PandocIO Text) -> PandocError -> PandocIO Text
forall a b. (a -> b) -> a -> b
$ Text -> PandocError
PandocUnsupportedCharsetError Text
charset
Maybe Text
Nothing -> 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
$
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)
(\case
TSE.DecodeError{} ->
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
$ FilePath -> Text
T.pack (FilePath -> Text) -> FilePath -> Text
forall a b. (a -> b) -> a -> b
$ ByteString -> FilePath
B8.unpack ByteString
bs
UnicodeException
e -> UnicodeException -> IO Text
forall e a. Exception e => e -> IO a
E.throwIO UnicodeException
e)
readFile' :: MonadIO m => FilePath -> m BL.ByteString
readFile' :: FilePath -> m ByteString
readFile' FilePath
"-" = IO ByteString -> m ByteString
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO IO ByteString
BL.getContents
readFile' 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 FilePath
"-" = 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 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 ()
writerFn :: Newline -> FilePath -> Text -> m ()
writerFn Newline
eol FilePath
"-" = 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 -> Text -> IO ()
UTF8.putStrWith Newline
eol
writerFn Newline
eol 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 -> Text -> IO ()
UTF8.writeFileWith Newline
eol FilePath
f