{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings #-}
module Text.Pandoc.Writers.RTF ( writeRTF
) where
import Control.Monad.Except (catchError, throwError)
import Control.Monad
import qualified Data.ByteString as B
import Data.Char (chr, isDigit, ord, isAlphaNum)
import qualified Data.Map as M
import Data.Text (Text)
import qualified Data.Text as T
import Text.Pandoc.Class.PandocMonad (PandocMonad, report)
import qualified Text.Pandoc.Class.PandocMonad as P
import Text.Pandoc.Definition
import Text.Pandoc.Error
import Text.Pandoc.ImageSize
import Text.Pandoc.Logging
import Text.Pandoc.Options
import Text.Pandoc.Shared
import Text.Pandoc.Templates (renderTemplate)
import Text.DocLayout (render, literal)
import Text.Pandoc.Walk
import Text.Pandoc.Writers.Math
import Text.Pandoc.Writers.Shared
import Text.Printf (printf)
rtfEmbedImage :: PandocMonad m => WriterOptions -> Inline -> m Inline
rtfEmbedImage :: forall (m :: * -> *).
PandocMonad m =>
WriterOptions -> Inline -> m Inline
rtfEmbedImage WriterOptions
opts x :: Inline
x@(Image Attr
attr [Inline]
_ (Text
src,Text
_)) = forall e (m :: * -> *) a.
MonadError e m =>
m a -> (e -> m a) -> m a
catchError
(do (ByteString, Maybe Text)
result <- forall (m :: * -> *).
PandocMonad m =>
Text -> m (ByteString, Maybe Text)
P.fetchItem Text
src
case (ByteString, Maybe Text)
result of
(ByteString
imgdata, Just Text
mime)
| Text
mime' <- (Char -> Bool) -> Text -> Text
T.takeWhile (forall a. Eq a => a -> a -> Bool
/=Char
';') Text
mime
, Text
mime' forall a. Eq a => a -> a -> Bool
== Text
"image/jpeg" Bool -> Bool -> Bool
|| Text
mime' forall a. Eq a => a -> a -> Bool
== Text
"image/png" -> do
let bytes :: [Text]
bytes = forall a b. (a -> b) -> [a] -> [b]
map (String -> Text
T.pack forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall r. PrintfType r => String -> r
printf String
"%02x") forall a b. (a -> b) -> a -> b
$ ByteString -> [Word8]
B.unpack ByteString
imgdata
Text
filetype <-
case Text
mime' of
Text
"image/jpeg" -> forall (m :: * -> *) a. Monad m => a -> m a
return Text
"\\jpegblip"
Text
"image/png" -> forall (m :: * -> *) a. Monad m => a -> m a
return Text
"\\pngblip"
Text
_ -> forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError forall a b. (a -> b) -> a -> b
$
Text -> PandocError
PandocShouldNeverHappenError forall a b. (a -> b) -> a -> b
$
Text
"Unknown file type " forall a. Semigroup a => a -> a -> a
<> Text
mime
Text
sizeSpec <-
case WriterOptions -> ByteString -> Either Text ImageSize
imageSize WriterOptions
opts ByteString
imgdata of
Left Text
msg -> do
forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
report forall a b. (a -> b) -> a -> b
$ Text -> Text -> LogMessage
CouldNotDetermineImageSize Text
src Text
msg
forall (m :: * -> *) a. Monad m => a -> m a
return Text
""
Right ImageSize
sz -> forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"\\picw" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow Integer
xpx forall a. Semigroup a => a -> a -> a
<>
Text
"\\pich" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow Integer
ypx forall a. Semigroup a => a -> a -> a
<>
Text
"\\picwgoal" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow (forall a b. (RealFrac a, Integral b) => a -> b
floor (Double
xpt forall a. Num a => a -> a -> a
* Double
20) :: Integer)
forall a. Semigroup a => a -> a -> a
<> Text
"\\pichgoal" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow (forall a b. (RealFrac a, Integral b) => a -> b
floor (Double
ypt forall a. Num a => a -> a -> a
* Double
20) :: Integer)
where (Integer
xpx, Integer
ypx) = ImageSize -> (Integer, Integer)
sizeInPixels ImageSize
sz
(Double
xpt, Double
ypt) = WriterOptions -> Attr -> ImageSize -> (Double, Double)
desiredSizeInPoints WriterOptions
opts Attr
attr ImageSize
sz
let raw :: Text
raw = Text
"{\\pict" forall a. Semigroup a => a -> a -> a
<> Text
filetype forall a. Semigroup a => a -> a -> a
<> Text
sizeSpec forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<>
[Text] -> Text
T.concat [Text]
bytes forall a. Semigroup a => a -> a -> a
<> Text
"}"
if ByteString -> Bool
B.null ByteString
imgdata
then do
forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
report forall a b. (a -> b) -> a -> b
$ Text -> Text -> LogMessage
CouldNotFetchResource Text
src Text
"image contained no data"
forall (m :: * -> *) a. Monad m => a -> m a
return Inline
x
else forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Format -> Text -> Inline
RawInline (Text -> Format
Format Text
"rtf") Text
raw
| Bool
otherwise -> do
forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
report forall a b. (a -> b) -> a -> b
$ Text -> Text -> LogMessage
CouldNotFetchResource Text
src Text
"image is not a jpeg or png"
forall (m :: * -> *) a. Monad m => a -> m a
return Inline
x
(ByteString
_, Maybe Text
Nothing) -> do
forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
report forall a b. (a -> b) -> a -> b
$ Text -> LogMessage
CouldNotDetermineMimeType Text
src
forall (m :: * -> *) a. Monad m => a -> m a
return Inline
x)
(\PandocError
e -> do
forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
report forall a b. (a -> b) -> a -> b
$ Text -> Text -> LogMessage
CouldNotFetchResource Text
src forall a b. (a -> b) -> a -> b
$ forall a. Show a => a -> Text
tshow PandocError
e
forall (m :: * -> *) a. Monad m => a -> m a
return Inline
x)
rtfEmbedImage WriterOptions
_ Inline
x = forall (m :: * -> *) a. Monad m => a -> m a
return Inline
x
writeRTF :: PandocMonad m => WriterOptions -> Pandoc -> m Text
writeRTF :: forall (m :: * -> *).
PandocMonad m =>
WriterOptions -> Pandoc -> m Text
writeRTF WriterOptions
options Pandoc
doc = do
Pandoc meta :: Meta
meta@(Meta Map Text MetaValue
metamap) [Block]
blocks <- forall a b (m :: * -> *).
(Walkable a b, Monad m, Applicative m, Functor m) =>
(a -> m a) -> b -> m b
walkM (forall (m :: * -> *).
PandocMonad m =>
WriterOptions -> Inline -> m Inline
rtfEmbedImage WriterOptions
options) Pandoc
doc
let spacer :: Bool
spacer = Bool -> Bool
not forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all forall (t :: * -> *) a. Foldable t => t a -> Bool
null forall a b. (a -> b) -> a -> b
$ Meta -> [Inline]
docTitle Meta
meta forall a. a -> [a] -> [a]
: Meta -> [Inline]
docDate Meta
meta forall a. a -> [a] -> [a]
: Meta -> [[Inline]]
docAuthors Meta
meta
let toPlain :: MetaValue -> MetaValue
toPlain (MetaBlocks [Para [Inline]
ils]) = [Inline] -> MetaValue
MetaInlines [Inline]
ils
toPlain MetaValue
x = MetaValue
x
let meta' :: Meta
meta' = Map Text MetaValue -> Meta
Meta forall a b. (a -> b) -> a -> b
$ forall k a. Ord k => (a -> a) -> k -> Map k a -> Map k a
M.adjust MetaValue -> MetaValue
toPlain Text
"title"
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Ord k => (a -> a) -> k -> Map k a -> Map k a
M.adjust MetaValue -> MetaValue
toPlain Text
"author"
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall k a. Ord k => (a -> a) -> k -> Map k a -> Map k a
M.adjust MetaValue -> MetaValue
toPlain Text
"date"
forall a b. (a -> b) -> a -> b
$ Map Text MetaValue
metamap
Context Text
metadata <- forall (m :: * -> *) a.
(Monad m, TemplateTarget a) =>
WriterOptions
-> ([Block] -> m (Doc a))
-> ([Inline] -> m (Doc a))
-> Meta
-> m (Context a)
metaToContext WriterOptions
options
(forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (forall a. HasChars a => a -> Doc a
literal forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
T.concat) forall b c a. (b -> c) -> (a -> b) -> a -> c
.
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> Block -> m Text
blockToRTF Int
0 Alignment
AlignDefault))
(forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. HasChars a => a -> Doc a
literal forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF)
Meta
meta'
Text
body <- forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> [Block] -> m Text
blocksToRTF Int
0 Alignment
AlignDefault [Block]
blocks
Text
toc <- forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> [Block] -> m Text
blocksToRTF Int
0 Alignment
AlignDefault [WriterOptions -> [Block] -> Block
toTableOfContents WriterOptions
options [Block]
blocks]
let context :: Context Text
context = forall a b. ToContext a b => Text -> b -> Context a -> Context a
defField Text
"body" Text
body
forall a b. (a -> b) -> a -> b
$ forall a b. ToContext a b => Text -> b -> Context a -> Context a
defField Text
"spacer" Bool
spacer
forall a b. (a -> b) -> a -> b
$ (if WriterOptions -> Bool
writerTableOfContents WriterOptions
options
then forall a b. ToContext a b => Text -> b -> Context a -> Context a
defField Text
"table-of-contents" Text
toc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall a b. ToContext a b => Text -> b -> Context a -> Context a
defField Text
"toc" Text
toc
else forall a. a -> a
id) Context Text
metadata
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$
case WriterOptions -> Maybe (Template Text)
writerTemplate WriterOptions
options of
Just Template Text
tpl -> forall a. HasChars a => Maybe Int -> Doc a -> a
render forall a. Maybe a
Nothing forall a b. (a -> b) -> a -> b
$ forall a b.
(TemplateTarget a, ToContext a b) =>
Template a -> b -> Doc a
renderTemplate Template Text
tpl Context Text
context
Maybe (Template Text)
Nothing -> case Text -> Maybe (Text, Char)
T.unsnoc Text
body of
Just (Text
_,Char
'\n') -> Text
body
Maybe (Text, Char)
_ -> Text
body forall a. Semigroup a => a -> a -> a
<> Char -> Text
T.singleton Char
'\n'
handleUnicode :: Text -> Text
handleUnicode :: Text -> Text
handleUnicode = (Char -> Text) -> Text -> Text
T.concatMap forall a b. (a -> b) -> a -> b
$ \Char
c ->
if Char -> Int
ord Char
c forall a. Ord a => a -> a -> Bool
> Int
127
then if Char -> Bool
surrogate Char
c
then let x :: Int
x = Char -> Int
ord Char
c forall a. Num a => a -> a -> a
- Int
0x10000
(Int
q, Int
r) = Int
x forall a. Integral a => a -> a -> (a, a)
`divMod` Int
0x400
upper :: Int
upper = Int
q forall a. Num a => a -> a -> a
+ Int
0xd800
lower :: Int
lower = Int
r forall a. Num a => a -> a -> a
+ Int
0xDC00
in Char -> Text
enc (Int -> Char
chr Int
upper) forall a. Semigroup a => a -> a -> a
<> Char -> Text
enc (Int -> Char
chr Int
lower)
else Char -> Text
enc Char
c
else Char -> Text
T.singleton Char
c
where
surrogate :: Char -> Bool
surrogate Char
x = Bool -> Bool
not ( (Int
0x0000 forall a. Ord a => a -> a -> Bool
<= Char -> Int
ord Char
x Bool -> Bool -> Bool
&& Char -> Int
ord Char
x forall a. Ord a => a -> a -> Bool
<= Int
0xd7ff)
Bool -> Bool -> Bool
|| (Int
0xe000 forall a. Ord a => a -> a -> Bool
<= Char -> Int
ord Char
x Bool -> Bool -> Bool
&& Char -> Int
ord Char
x forall a. Ord a => a -> a -> Bool
<= Int
0xffff) )
enc :: Char -> Text
enc Char
x = Text
"\\u" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow (Char -> Int
ord Char
x) forall a. Semigroup a => a -> a -> a
<> Text
" ?"
escapeSpecial :: Text -> Text
escapeSpecial :: Text -> Text
escapeSpecial Text
t
| (Char -> Bool) -> Text -> Bool
T.all Char -> Bool
isAlphaNum Text
t = Text
t
| Bool
otherwise = (Char -> Text) -> Text -> Text
T.concatMap Char -> Text
escChar Text
t
where
escChar :: Char -> Text
escChar Char
'\t' = Text
"\\tab "
escChar Char
'\8216' = Text
"\\u8216'"
escChar Char
'\8217' = Text
"\\u8217'"
escChar Char
'\8220' = Text
"\\u8220\""
escChar Char
'\8221' = Text
"\\u8221\""
escChar Char
'\8211' = Text
"\\u8211-"
escChar Char
'\8212' = Text
"\\u8212-"
escChar Char
'{' = Text
"\\{"
escChar Char
'}' = Text
"\\}"
escChar Char
'\\' = Text
"\\\\"
escChar Char
c = Char -> Text
T.singleton Char
c
stringToRTF :: Text -> Text
stringToRTF :: Text -> Text
stringToRTF = Text -> Text
handleUnicode forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
escapeSpecial
codeStringToRTF :: Text -> Text
codeStringToRTF :: Text -> Text
codeStringToRTF Text
str = Text -> [Text] -> Text
T.intercalate Text
"\\line\n" forall a b. (a -> b) -> a -> b
$ Text -> [Text]
T.lines (Text -> Text
stringToRTF Text
str)
rtfParSpaced :: Int
-> Int
-> Int
-> Alignment
-> Text
-> Text
rtfParSpaced :: Int -> Int -> Int -> Alignment -> Text -> Text
rtfParSpaced Int
spaceAfter Int
indent Int
firstLineIndent Alignment
alignment Text
content =
let alignString :: Text
alignString = case Alignment
alignment of
Alignment
AlignLeft -> Text
"\\ql "
Alignment
AlignRight -> Text
"\\qr "
Alignment
AlignCenter -> Text
"\\qc "
Alignment
AlignDefault -> Text
"\\ql "
in Text
"{\\pard " forall a. Semigroup a => a -> a -> a
<> Text
alignString forall a. Semigroup a => a -> a -> a
<>
Text
"\\f0 \\sa" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow Int
spaceAfter forall a. Semigroup a => a -> a -> a
<> Text
" \\li" forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (forall a. Show a => a -> String
show Int
indent) forall a. Semigroup a => a -> a -> a
<>
Text
" \\fi" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow Int
firstLineIndent forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<> Text
content forall a. Semigroup a => a -> a -> a
<> Text
"\\par}\n"
rtfPar :: Int
-> Int
-> Alignment
-> Text
-> Text
rtfPar :: Int -> Int -> Alignment -> Text -> Text
rtfPar = Int -> Int -> Int -> Alignment -> Text -> Text
rtfParSpaced Int
180
rtfCompact :: Int
-> Int
-> Alignment
-> Text
-> Text
rtfCompact :: Int -> Int -> Alignment -> Text -> Text
rtfCompact = Int -> Int -> Int -> Alignment -> Text -> Text
rtfParSpaced Int
0
indentIncrement :: Int
indentIncrement :: Int
indentIncrement = Int
720
listIncrement :: Int
listIncrement :: Int
listIncrement = Int
360
bulletMarker :: Int -> Text
bulletMarker :: Int -> Text
bulletMarker Int
indent = case Int
indent forall a. Integral a => a -> a -> a
`mod` Int
720 of
Int
0 -> Text
"\\bullet "
Int
_ -> Text
"\\endash "
orderedMarkers :: Int -> ListAttributes -> [Text]
orderedMarkers :: Int -> ListAttributes -> [Text]
orderedMarkers Int
indent (Int
start, ListNumberStyle
style, ListNumberDelim
delim) =
if ListNumberStyle
style forall a. Eq a => a -> a -> Bool
== ListNumberStyle
DefaultStyle Bool -> Bool -> Bool
&& ListNumberDelim
delim forall a. Eq a => a -> a -> Bool
== ListNumberDelim
DefaultDelim
then case Int
indent forall a. Integral a => a -> a -> a
`mod` Int
720 of
Int
0 -> ListAttributes -> [Text]
orderedListMarkers (Int
start, ListNumberStyle
Decimal, ListNumberDelim
Period)
Int
_ -> ListAttributes -> [Text]
orderedListMarkers (Int
start, ListNumberStyle
LowerAlpha, ListNumberDelim
Period)
else ListAttributes -> [Text]
orderedListMarkers (Int
start, ListNumberStyle
style, ListNumberDelim
delim)
blocksToRTF :: PandocMonad m
=> Int
-> Alignment
-> [Block]
-> m Text
blocksToRTF :: forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> [Block] -> m Text
blocksToRTF Int
indent Alignment
align = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Text] -> Text
T.concat forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> Block -> m Text
blockToRTF Int
indent Alignment
align)
blockToRTF :: PandocMonad m
=> Int
-> Alignment
-> Block
-> m Text
blockToRTF :: forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> Block -> m Text
blockToRTF Int
indent Alignment
alignment (Div Attr
_ [Block]
bs) =
forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> [Block] -> m Text
blocksToRTF Int
indent Alignment
alignment [Block]
bs
blockToRTF Int
indent Alignment
alignment (Plain [Inline]
lst) =
Int -> Int -> Alignment -> Text -> Text
rtfCompact Int
indent Int
0 Alignment
alignment forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
blockToRTF Int
indent Alignment
alignment (Para [Inline]
lst) =
Int -> Int -> Alignment -> Text -> Text
rtfPar Int
indent Int
0 Alignment
alignment forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
blockToRTF Int
indent Alignment
alignment (LineBlock [[Inline]]
lns) =
forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> Block -> m Text
blockToRTF Int
indent Alignment
alignment forall a b. (a -> b) -> a -> b
$ [[Inline]] -> Block
linesToPara [[Inline]]
lns
blockToRTF Int
indent Alignment
alignment (BlockQuote [Block]
lst) =
forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> [Block] -> m Text
blocksToRTF (Int
indent forall a. Num a => a -> a -> a
+ Int
indentIncrement) Alignment
alignment [Block]
lst
blockToRTF Int
indent Alignment
_ (CodeBlock Attr
_ Text
str) =
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Int -> Int -> Alignment -> Text -> Text
rtfPar Int
indent Int
0 Alignment
AlignLeft (Text
"\\f1 " forall a. Semigroup a => a -> a -> a
<> Text -> Text
codeStringToRTF Text
str)
blockToRTF Int
_ Alignment
_ b :: Block
b@(RawBlock Format
f Text
str)
| Format
f forall a. Eq a => a -> a -> Bool
== Text -> Format
Format Text
"rtf" = forall (m :: * -> *) a. Monad m => a -> m a
return Text
str
| Bool
otherwise = do
forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
report forall a b. (a -> b) -> a -> b
$ Block -> LogMessage
BlockNotRendered Block
b
forall (m :: * -> *) a. Monad m => a -> m a
return Text
""
blockToRTF Int
indent Alignment
alignment (BulletList [[Block]]
lst) = Text -> Text
spaceAtEnd forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
T.concat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall (m :: * -> *).
PandocMonad m =>
Alignment -> Int -> Text -> [Block] -> m Text
listItemToRTF Alignment
alignment Int
indent (Int -> Text
bulletMarker Int
indent)) [[Block]]
lst
blockToRTF Int
indent Alignment
alignment (OrderedList ListAttributes
attribs [[Block]]
lst) =
Text -> Text
spaceAtEnd forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
T.concat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM (forall (m :: * -> *).
PandocMonad m =>
Alignment -> Int -> Text -> [Block] -> m Text
listItemToRTF Alignment
alignment Int
indent) (Int -> ListAttributes -> [Text]
orderedMarkers Int
indent ListAttributes
attribs) [[Block]]
lst
blockToRTF Int
indent Alignment
alignment (DefinitionList [([Inline], [[Block]])]
lst) = Text -> Text
spaceAtEnd forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Text] -> Text
T.concat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall (m :: * -> *).
PandocMonad m =>
Alignment -> Int -> ([Inline], [[Block]]) -> m Text
definitionListItemToRTF Alignment
alignment Int
indent) [([Inline], [[Block]])]
lst
blockToRTF Int
indent Alignment
_ Block
HorizontalRule = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$
Int -> Int -> Alignment -> Text -> Text
rtfPar Int
indent Int
0 Alignment
AlignCenter Text
"\\emdash\\emdash\\emdash\\emdash\\emdash"
blockToRTF Int
indent Alignment
alignment (Header Int
level Attr
_ [Inline]
lst) = do
Text
contents <- forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Int -> Int -> Alignment -> Text -> Text
rtfPar Int
indent Int
0 Alignment
alignment forall a b. (a -> b) -> a -> b
$
Text
"\\outlinelevel" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow (Int
level forall a. Num a => a -> a -> a
- Int
1) forall a. Semigroup a => a -> a -> a
<>
Text
" \\b \\fs" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow (Int
40 forall a. Num a => a -> a -> a
- (Int
level forall a. Num a => a -> a -> a
* Int
4)) forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<> Text
contents
blockToRTF Int
indent Alignment
alignment (Table Attr
_ Caption
blkCapt [ColSpec]
specs TableHead
thead [TableBody]
tbody TableFoot
tfoot) = do
let ([Inline]
caption, [Alignment]
aligns, [Double]
sizes, [[Block]]
headers, [[[Block]]]
rows) = Caption
-> [ColSpec]
-> TableHead
-> [TableBody]
-> TableFoot
-> ([Inline], [Alignment], [Double], [[Block]], [[[Block]]])
toLegacyTable Caption
blkCapt [ColSpec]
specs TableHead
thead [TableBody]
tbody TableFoot
tfoot
Text
caption' <- forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
caption
Text
header' <- if forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all forall (t :: * -> *) a. Foldable t => t a -> Bool
null [[Block]]
headers
then forall (m :: * -> *) a. Monad m => a -> m a
return Text
""
else forall (m :: * -> *).
PandocMonad m =>
Bool -> Int -> [Alignment] -> [Double] -> [[Block]] -> m Text
tableRowToRTF Bool
True Int
indent [Alignment]
aligns [Double]
sizes [[Block]]
headers
Text
rows' <- [Text] -> Text
T.concat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall (m :: * -> *).
PandocMonad m =>
Bool -> Int -> [Alignment] -> [Double] -> [[Block]] -> m Text
tableRowToRTF Bool
False Int
indent [Alignment]
aligns [Double]
sizes) [[[Block]]]
rows
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
header' forall a. Semigroup a => a -> a -> a
<> Text
rows' forall a. Semigroup a => a -> a -> a
<> Int -> Int -> Alignment -> Text -> Text
rtfPar Int
indent Int
0 Alignment
alignment Text
caption'
blockToRTF Int
indent Alignment
alignment (Figure Attr
attr Caption
capt [Block]
body) =
forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> Block -> m Text
blockToRTF Int
indent Alignment
alignment forall a b. (a -> b) -> a -> b
$ Attr -> Caption -> [Block] -> Block
figureDiv Attr
attr Caption
capt [Block]
body
tableRowToRTF :: PandocMonad m
=> Bool -> Int -> [Alignment] -> [Double] -> [[Block]] -> m Text
tableRowToRTF :: forall (m :: * -> *).
PandocMonad m =>
Bool -> Int -> [Alignment] -> [Double] -> [[Block]] -> m Text
tableRowToRTF Bool
header Int
indent [Alignment]
aligns [Double]
sizes' [[Block]]
cols = do
let totalTwips :: Double
totalTwips = Double
6 forall a. Num a => a -> a -> a
* Double
1440
let sizes :: [Double]
sizes = if forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (forall a. Eq a => a -> a -> Bool
== Double
0) [Double]
sizes'
then forall a. Int -> a -> [a]
replicate (forall (t :: * -> *) a. Foldable t => t a -> Int
length [[Block]]
cols) (Double
1.0 forall a. Fractional a => a -> a -> a
/ forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall (t :: * -> *) a. Foldable t => t a -> Int
length [[Block]]
cols))
else [Double]
sizes'
Text
columns <- [Text] -> Text
T.concat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$>
forall (m :: * -> *) a b c.
Applicative m =>
(a -> b -> m c) -> [a] -> [b] -> m [c]
zipWithM (forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> [Block] -> m Text
tableItemToRTF Int
indent) [Alignment]
aligns [[Block]]
cols
let rightEdges :: [Integer]
rightEdges = forall a. [a] -> [a]
tail forall a b. (a -> b) -> a -> b
$ forall b a. (b -> a -> b) -> b -> [a] -> [b]
scanl (\Integer
sofar Double
new -> Integer
sofar forall a. Num a => a -> a -> a
+ forall a b. (RealFrac a, Integral b) => a -> b
floor (Double
new forall a. Num a => a -> a -> a
* Double
totalTwips))
(Integer
0 :: Integer) [Double]
sizes
let cellDefs :: [Text]
cellDefs = forall a b. (a -> b) -> [a] -> [b]
map (\Integer
edge -> (if Bool
header
then Text
"\\clbrdrb\\brdrs"
else Text
"") forall a. Semigroup a => a -> a -> a
<> Text
"\\cellx" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow Integer
edge)
[Integer]
rightEdges
let start :: Text
start = Text
"{\n\\trowd \\trgaph120\n" forall a. Semigroup a => a -> a -> a
<> [Text] -> Text
T.concat [Text]
cellDefs forall a. Semigroup a => a -> a -> a
<> Text
"\n" forall a. Semigroup a => a -> a -> a
<>
Text
"\\trkeep\\intbl\n{\n"
let end :: Text
end = Text
"}\n\\intbl\\row}\n"
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
start forall a. Semigroup a => a -> a -> a
<> Text
columns forall a. Semigroup a => a -> a -> a
<> Text
end
tableItemToRTF :: PandocMonad m => Int -> Alignment -> [Block] -> m Text
tableItemToRTF :: forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> [Block] -> m Text
tableItemToRTF Int
indent Alignment
alignment [Block]
item = do
Text
contents <- forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> [Block] -> m Text
blocksToRTF Int
indent Alignment
alignment [Block]
item
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"{" forall a. Semigroup a => a -> a -> a
<> Text -> Text -> Text -> Text
T.replace Text
"\\pard" Text
"\\pard\\intbl" Text
contents forall a. Semigroup a => a -> a -> a
<> Text
"\\cell}\n"
spaceAtEnd :: Text -> Text
spaceAtEnd :: Text -> Text
spaceAtEnd Text
str = forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
str (forall a. Semigroup a => a -> a -> a
<> Text
"\\sa180\\par}\n") forall a b. (a -> b) -> a -> b
$ Text -> Text -> Maybe Text
T.stripSuffix Text
"\\par}\n" Text
str
listItemToRTF :: PandocMonad m
=> Alignment
-> Int
-> Text
-> [Block]
-> m Text
listItemToRTF :: forall (m :: * -> *).
PandocMonad m =>
Alignment -> Int -> Text -> [Block] -> m Text
listItemToRTF Alignment
alignment Int
indent Text
marker [] = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$
Int -> Int -> Alignment -> Text -> Text
rtfCompact (Int
indent forall a. Num a => a -> a -> a
+ Int
listIncrement) (forall a. Num a => a -> a
negate Int
listIncrement) Alignment
alignment
(Text
marker forall a. Semigroup a => a -> a -> a
<> Text
"\\tx" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow Int
listIncrement forall a. Semigroup a => a -> a -> a
<> Text
"\\tab ")
listItemToRTF Alignment
alignment Int
indent Text
marker (Block
listFirst:[Block]
listRest) = do
let f :: Block -> m Text
f = forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> Block -> m Text
blockToRTF (Int
indent forall a. Num a => a -> a -> a
+ Int
listIncrement) Alignment
alignment
Text
first <- Block -> m Text
f Block
listFirst
[Text]
rest <- forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Block -> m Text
f [Block]
listRest
let listMarker :: Text
listMarker = Text
"\\fi" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow (forall a. Num a => a -> a
negate Int
listIncrement) forall a. Semigroup a => a -> a -> a
<> Text
" " forall a. Semigroup a => a -> a -> a
<> Text
marker forall a. Semigroup a => a -> a -> a
<>
Text
"\\tx" forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
tshow Int
listIncrement forall a. Semigroup a => a -> a -> a
<> Text
"\\tab"
let insertListMarker :: Text -> Text
insertListMarker Text
t = case Text -> Maybe Text
popDigit forall a b. (a -> b) -> a -> b
$ Text -> Text
optionDash forall a b. (a -> b) -> a -> b
$ Int -> Text -> Text
T.drop Int
3 Text
suff of
Just Text
suff' -> Text
pref forall a. Semigroup a => a -> a -> a
<> Text
listMarker forall a. Semigroup a => a -> a -> a
<> (Char -> Bool) -> Text -> Text
T.dropWhile Char -> Bool
isDigit Text
suff'
Maybe Text
Nothing -> Text
t
where
(Text
pref, Text
suff) = Text -> Text -> (Text, Text)
T.breakOn Text
"\\fi" Text
t
optionDash :: Text -> Text
optionDash Text
x = case Text -> Maybe (Char, Text)
T.uncons Text
x of
Just (Char
'-', Text
xs) -> Text
xs
Maybe (Char, Text)
_ -> Text
x
popDigit :: Text -> Maybe Text
popDigit Text
x
| Just (Char
d, Text
xs) <- Text -> Maybe (Char, Text)
T.uncons Text
x
, Char -> Bool
isDigit Char
d = forall a. a -> Maybe a
Just Text
xs
| Bool
otherwise = forall a. Maybe a
Nothing
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text -> Text
insertListMarker Text
first forall a. Semigroup a => a -> a -> a
<> [Text] -> Text
T.concat [Text]
rest
definitionListItemToRTF :: PandocMonad m
=> Alignment
-> Int
-> ([Inline],[[Block]])
-> m Text
definitionListItemToRTF :: forall (m :: * -> *).
PandocMonad m =>
Alignment -> Int -> ([Inline], [[Block]]) -> m Text
definitionListItemToRTF Alignment
alignment Int
indent ([Inline]
label, [[Block]]
defs) = do
Text
labelText <- forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> Block -> m Text
blockToRTF Int
indent Alignment
alignment ([Inline] -> Block
Plain [Inline]
label)
Text
itemsText <- forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> [Block] -> m Text
blocksToRTF (Int
indent forall a. Num a => a -> a -> a
+ Int
listIncrement) Alignment
alignment (forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Block]]
defs)
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
labelText forall a. Semigroup a => a -> a -> a
<> Text
itemsText
inlinesToRTF :: PandocMonad m
=> [Inline]
-> m Text
inlinesToRTF :: forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst = [Text] -> Text
T.concat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM forall (m :: * -> *). PandocMonad m => Inline -> m Text
inlineToRTF [Inline]
lst
inlineToRTF :: PandocMonad m
=> Inline
-> m Text
inlineToRTF :: forall (m :: * -> *). PandocMonad m => Inline -> m Text
inlineToRTF (Span Attr
_ [Inline]
lst) = forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
inlineToRTF (Emph [Inline]
lst) = do
Text
contents <- forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"{\\i " forall a. Semigroup a => a -> a -> a
<> Text
contents forall a. Semigroup a => a -> a -> a
<> Text
"}"
inlineToRTF (Underline [Inline]
lst) = do
Text
contents <- forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"{\\ul " forall a. Semigroup a => a -> a -> a
<> Text
contents forall a. Semigroup a => a -> a -> a
<> Text
"}"
inlineToRTF (Strong [Inline]
lst) = do
Text
contents <- forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"{\\b " forall a. Semigroup a => a -> a -> a
<> Text
contents forall a. Semigroup a => a -> a -> a
<> Text
"}"
inlineToRTF (Strikeout [Inline]
lst) = do
Text
contents <- forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"{\\strike " forall a. Semigroup a => a -> a -> a
<> Text
contents forall a. Semigroup a => a -> a -> a
<> Text
"}"
inlineToRTF (Superscript [Inline]
lst) = do
Text
contents <- forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"{\\super " forall a. Semigroup a => a -> a -> a
<> Text
contents forall a. Semigroup a => a -> a -> a
<> Text
"}"
inlineToRTF (Subscript [Inline]
lst) = do
Text
contents <- forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"{\\sub " forall a. Semigroup a => a -> a -> a
<> Text
contents forall a. Semigroup a => a -> a -> a
<> Text
"}"
inlineToRTF (SmallCaps [Inline]
lst) = do
Text
contents <- forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"{\\scaps " forall a. Semigroup a => a -> a -> a
<> Text
contents forall a. Semigroup a => a -> a -> a
<> Text
"}"
inlineToRTF (Quoted QuoteType
SingleQuote [Inline]
lst) = do
Text
contents <- forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"\\u8216'" forall a. Semigroup a => a -> a -> a
<> Text
contents forall a. Semigroup a => a -> a -> a
<> Text
"\\u8217'"
inlineToRTF (Quoted QuoteType
DoubleQuote [Inline]
lst) = do
Text
contents <- forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"\\u8220\"" forall a. Semigroup a => a -> a -> a
<> Text
contents forall a. Semigroup a => a -> a -> a
<> Text
"\\u8221\""
inlineToRTF (Code Attr
_ Text
str) = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"{\\f1 " forall a. Semigroup a => a -> a -> a
<> Text -> Text
codeStringToRTF Text
str forall a. Semigroup a => a -> a -> a
<> Text
"}"
inlineToRTF (Str Text
str) = forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text -> Text
stringToRTF Text
str
inlineToRTF (Math MathType
t Text
str) = forall (m :: * -> *).
PandocMonad m =>
MathType -> Text -> m [Inline]
texMathToInlines MathType
t Text
str forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF
inlineToRTF (Cite [Citation]
_ [Inline]
lst) = forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
lst
inlineToRTF il :: Inline
il@(RawInline Format
f Text
str)
| Format
f forall a. Eq a => a -> a -> Bool
== Text -> Format
Format Text
"rtf" = forall (m :: * -> *) a. Monad m => a -> m a
return Text
str
| Bool
otherwise = do
forall (m :: * -> *). PandocMonad m => LogMessage -> m ()
report forall a b. (a -> b) -> a -> b
$ Inline -> LogMessage
InlineNotRendered Inline
il
forall (m :: * -> *) a. Monad m => a -> m a
return Text
""
inlineToRTF Inline
LineBreak = forall (m :: * -> *) a. Monad m => a -> m a
return Text
"\\line "
inlineToRTF Inline
SoftBreak = forall (m :: * -> *) a. Monad m => a -> m a
return Text
" "
inlineToRTF Inline
Space = forall (m :: * -> *) a. Monad m => a -> m a
return Text
" "
inlineToRTF (Link Attr
_ [Inline]
text (Text
src, Text
_)) = do
Text
contents <- forall (m :: * -> *). PandocMonad m => [Inline] -> m Text
inlinesToRTF [Inline]
text
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"{\\field{\\*\\fldinst{HYPERLINK \"" forall a. Semigroup a => a -> a -> a
<> Text -> Text
codeStringToRTF Text
src forall a. Semigroup a => a -> a -> a
<>
Text
"\"}}{\\fldrslt{\\ul\n" forall a. Semigroup a => a -> a -> a
<> Text
contents forall a. Semigroup a => a -> a -> a
<> Text
"\n}}}\n"
inlineToRTF (Image Attr
_ [Inline]
_ (Text
source, Text
_)) =
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"{\\cf1 [image: " forall a. Semigroup a => a -> a -> a
<> Text
source forall a. Semigroup a => a -> a -> a
<> Text
"]\\cf0}"
inlineToRTF (Note [Block]
contents) = do
Text
body <- [Text] -> Text
T.concat forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (forall (m :: * -> *).
PandocMonad m =>
Int -> Alignment -> Block -> m Text
blockToRTF Int
0 Alignment
AlignDefault) [Block]
contents
forall (m :: * -> *) a. Monad m => a -> m a
return forall a b. (a -> b) -> a -> b
$ Text
"{\\super\\chftn}{\\*\\footnote\\chftn\\~\\plain\\pard " forall a. Semigroup a => a -> a -> a
<>
Text
body forall a. Semigroup a => a -> a -> a
<> Text
"}"