@@ -31,7 +31,7 @@ TODO:
32[ ] warning for non-rendered raw content
32[ ] warning for non-rendered raw content
33[ ] is there a better way to do strikeout?
33[ ] is there a better way to do strikeout?
34−[ ] strong + em doesn't seem to work
34+[x] strong + em doesn't seem to work
35[ ] super + subscript don't seem to work
35[ ] super + subscript don't seem to work
36[ ] options for hyperlink rendering (currently footnote)
36[ ] options for hyperlink rendering (currently footnote)
37[ ] avoid note-in-note (which we currently get easily with
37[ ] avoid note-in-note (which we currently get easily with
@@ -43,10 +43,23 @@ TODO:
43 they exist in the groff manual PDF version)
43 they exist in the groff manual PDF version)
44[ ] use a custom macro for defn lists so they're configurable
44[ ] use a custom macro for defn lists so they're configurable
45[ ] better handling of accented characters and other non-ascii
45[ ] better handling of accented characters and other non-ascii
46− characters (e.g. curly quotes) -- we shouldn't rely on a
46+ characters (e.g. curly quotes).
47− utf8 compatible groff
47+ Note: recent versions of groff (more recent than standard
48+ on many systems) include a -k option which runs preconv.
49+ preconv basically converts non-ascii characters
50+ to \[uXXXX] entities. Since we can't assume that the local
51+ groff has the -k option, we could have any invocation of
52+ groff in Text.Pandoc.PDF filter the input through a Haskell
53+ function that does what preconv does.
54+ On the other hand: only recent groffs have -Tpdf. so
55+ if we want compatibility with older groffs, we need to to
56+ -Tps and pipe through ps2pdf (can we assume it's available?).
57+ A big advantage of gropdf: it supports the tag
58+ \X'pdf: pdfpic file alignment width height line-length'
59+ and also seems to support bookmarks.
48[ ] avoid blank line after footnote marker when footnote has a
60[ ] avoid blank line after footnote marker when footnote has a
62+[ ] better smallcaps support, see below...
50[ ] add via groff option to PDF module
63[ ] add via groff option to PDF module
51[ ] better handling of autolinks?
64[ ] better handling of autolinks?
52[ ] better handling of images, perhaps converting to eps when
65[ ] better handling of images, perhaps converting to eps when
@@ -63,7 +76,8 @@ import Text.Pandoc.Writers.Shared
63import Text.Pandoc.Options
76import Text.Pandoc.Options
64import Text.Pandoc.Writers.Math
77import Text.Pandoc.Writers.Math
65import Text.Printf ( printf )
78import Text.Printf ( printf )
79+import qualified Data.Map as Map
66−import Data.List ( stripPrefix, intersperse, intercalate )
80+import Data.List ( stripPrefix, intersperse, intercalate, sort )
67import Data.Maybe (fromMaybe)
81import Data.Maybe (fromMaybe)
68import Text.Pandoc.Pretty
82import Text.Pandoc.Pretty
69import Text.Pandoc.Builder (deleteMeta)
83import Text.Pandoc.Builder (deleteMeta)
@@ -73,7 +87,20 @@ import Data.Char ( isDigit )
73import Text.TeXMath (writeEqn)
87import Text.TeXMath (writeEqn)
75data WriterState = WriterState { stHasInlineMath :: Bool
89data WriterState = WriterState { stHasInlineMath :: Bool
76− , stNotes :: [Note] }
90+ , stNotes :: [Note]
91+ , stFontFeatures :: Map.Map Char Bool
94+defaultWriterState :: WriterState
95+defaultWriterState = WriterState{ stHasInlineMath = False
97+ , stFontFeatures = Map.fromList [
77type Note = [Block]
104type Note = [Block]
79type MS = StateT WriterState
106type MS = StateT WriterState
@@ -81,7 +108,7 @@ type MS = StateT WriterState
81-- | Convert Pandoc to Ms.
108-- | Convert Pandoc to Ms.
82writeMs :: PandocMonad m => WriterOptions -> Pandoc -> m String
109writeMs :: PandocMonad m => WriterOptions -> Pandoc -> m String
83writeMs opts document =
110writeMs opts document =
84− evalStateT (pandocToMs opts document) (WriterState False [])
111+ evalStateT (pandocToMs opts document) defaultWriterState
86-- | Return groff man representation of document.
113-- | Return groff man representation of document.
87pandocToMs :: PandocMonad m => WriterOptions -> Pandoc -> MS m String
114pandocToMs :: PandocMonad m => WriterOptions -> Pandoc -> MS m String
@@ -342,12 +369,10 @@ inlineListToMs' opts lst = do
342-- | Convert Pandoc inline element to man.
369-- | Convert Pandoc inline element to man.
343inlineToMs :: PandocMonad m => WriterOptions -> Inline -> MS m Doc
370inlineToMs :: PandocMonad m => WriterOptions -> Inline -> MS m Doc
344inlineToMs opts (Span _ ils) = inlineListToMs opts ils
371inlineToMs opts (Span _ ils) = inlineListToMs opts ils
345−inlineToMs opts (Emph lst) = do
372+inlineToMs opts (Emph lst) =
346− contents <- inlineListToMs opts lst
373+ withFontFeature 'I' (inlineListToMs opts lst)
347− return $ text "\\f[I]" <> contents <> text "\\f[]"
348−inlineToMs opts (Strong lst) = do
374+inlineToMs opts (Strong lst) =
349− contents <- inlineListToMs opts lst
375+ withFontFeature 'B' (inlineListToMs opts lst)
350− return $ text "\\f[B]" <> contents <> text "\\f[]"
351inlineToMs opts (Strikeout lst) = do
376inlineToMs opts (Strikeout lst) = do
352 contents <- inlineListToMs opts lst
377 contents <- inlineListToMs opts lst
353 return $ text "[STRIKEOUT:" <> contents <> char ']'
378 return $ text "[STRIKEOUT:" <> contents <> char ']'
@@ -358,6 +383,8 @@ inlineToMs opts (Subscript lst) = do
358 contents <- inlineListToMs opts lst
383 contents <- inlineListToMs opts lst
359 return $ char '~' <> contents <> char '~'
384 return $ char '~' <> contents <> char '~'
360inlineToMs opts (SmallCaps lst) = inlineListToMs opts lst -- not supported
385inlineToMs opts (SmallCaps lst) = inlineListToMs opts lst -- not supported
386+-- but see https://lists.gnu.org/archive/html/groff/2015-01/msg00016.html
387+-- for a way to fake them
361inlineToMs opts (Quoted SingleQuote lst) = do
388inlineToMs opts (Quoted SingleQuote lst) = do
362 contents <- inlineListToMs opts lst
389 contents <- inlineListToMs opts lst
363 return $ char '`' <> contents <> char '\''
390 return $ char '`' <> contents <> char '\''
@@ -367,7 +394,7 @@ inlineToMs opts (Quoted DoubleQuote lst) = do
367inlineToMs opts (Cite _ lst) =
394inlineToMs opts (Cite _ lst) =
368 inlineListToMs opts lst
395 inlineListToMs opts lst
369inlineToMs _ (Code _ str) =
396inlineToMs _ (Code _ str) =
370− return $ text $ "\\f[C]" ++ escapeCode str ++ "\\f[]"
397+ withFontFeature 'C' (return $ text $ escapeCode str)
371inlineToMs _ (Str str) = return $ text $ escapeString str
398inlineToMs _ (Str str) = return $ text $ escapeString str
372inlineToMs opts (Math InlineMath str) = do
399inlineToMs opts (Math InlineMath str) = do
373 modify $ \st -> st{ stHasInlineMath = True }
400 modify $ \st -> st{ stHasInlineMath = True }
@@ -424,3 +451,17 @@ handleNote opts bs = do
424 contents <- blockListToMs opts bs
451 contents <- blockListToMs opts bs
425 return $ cr <> text ".FS" $$ contents $$ text ".FE" <> cr
452 return $ cr <> text ".FS" $$ contents $$ text ".FE" <> cr
454+fontChange :: PandocMonad m => MS m Doc
456+ features <- gets stFontFeatures
457+ let filling = sort [c | (c,True) <- Map.toList features]
458+ return $ text $ "\\f[" ++ filling ++ "]"
460+withFontFeature :: PandocMonad m => Char -> MS m Doc -> MS m Doc
461+withFontFeature c action = do
462+ modify $ \st -> st{ stFontFeatures = Map.adjust not c $ stFontFeatures st }
465+ modify $ \st -> st{ stFontFeatures = Map.adjust not c $ stFontFeatures st }
467+ return $ begin <> d <> end