git.iko.soy/typeable/pandoc
on master help sign in
Changes to build with new doctemplates/doclayout.

The new version of doctemplates adds many features to pandoc's templating system, while remaining backwards-compatible. New features include partials and filters. Using template filters, one can lay out data in enumerated lists and tables. Templates are now layout-sensitive: so, for example, if a text with soft line breaks is interpolated near the end of a line, the text will break and wrap naturally. This makes the templating system much more suitable for programatically generating markdown or other plain-text files from metadata.

commit1fe97422630d4aa5644d55b0b3b41b0978b7fea0 authorJohn MacFarlane <jgm@berkeley.edu> dateSun 20 Oct 2019, 22:49 (7 years ago) parent4d5fd9e
27 files changed+120−97
cabal.project−4 data/templates/styles.html−1 pandoc.cabal+3−2 src/Text/Pandoc/App/Opt.hs+2−1 src/Text/Pandoc/Lua/Marshaling/Context.hs+6−4 src/Text/Pandoc/Options.hs+1−1 src/Text/Pandoc/PDF.hs+5−1 src/Text/Pandoc/Writers/CommonMark.hs+4−3 src/Text/Pandoc/Writers/Custom.hs+7−5 src/Text/Pandoc/Writers/DokuWiki.hs+6−5 src/Text/Pandoc/Writers/HTML.hs+4−3 src/Text/Pandoc/Writers/Ipynb.hs+3−2 src/Text/Pandoc/Writers/JATS.hs+2−2 src/Text/Pandoc/Writers/Jira.hs+8−4 src/Text/Pandoc/Writers/LaTeX.hs+2−2 src/Text/Pandoc/Writers/Markdown.hs+4−4 src/Text/Pandoc/Writers/MediaWiki.hs+6−6 src/Text/Pandoc/Writers/OPML.hs+6−4 src/Text/Pandoc/Writers/RTF.hs+11−9 src/Text/Pandoc/Writers/Roff.hs+2−2 src/Text/Pandoc/Writers/Shared.hs+11−9 src/Text/Pandoc/Writers/Textile.hs+7−6 src/Text/Pandoc/Writers/ZimWiki.hs+9−6 src/Text/Pandoc/XML.hs+8−5 stack.yaml+2−4 test/Tests/Writers/RST.hs+1−1 test/writer.textile−1
cabal.project−4
@@ -13,7 +13,3 @@ source-repository-package
1313 location: https://github.com/jgm/pandoc-citeproc
1414 tag: 0.16.3
1515
16−source-repository-package
17− type: git
18− location: https://github.com/jgm/doctemplates.git
19− tag: 0333142110e77408b8ee048064941884317aa757
data/templates/styles.html−1
@@ -9,4 +9,3 @@ $endif$
99$if(highlighting-css)$
1010$highlighting-css$
1111$endif$
12−
pandoc.cabal+3−2
@@ -417,9 +417,10 @@ library
417417 case-insensitive >= 1.2 && < 1.3,
418418 unicode-transforms >= 0.3 && < 0.4,
419419 HsYAML >= 0.2 && < 0.3,
420− doclayout >= 0.1 && < 0.2,
420+ doclayout >= 0.2 && < 0.3,
421421 ipynb >= 0.1 && < 0.2,
422− attoparsec >= 0.12 && < 0.14
422+ attoparsec >= 0.12 && < 0.14,
423+ text-conversions >= 0.3 && < 0.4
423424 if os(windows) && arch(i386)
424425 build-depends: basement >= 0.0.10,
425426 foundation >= 0.0.23
src/Text/Pandoc/App/Opt.hs+2−1
@@ -33,6 +33,7 @@ import Text.Pandoc.Options (TopLevelDivision (TopLevelDefault),
3333 ObfuscationMethod (NoObfuscation),
3434 CiteMethod (Citeproc))
3535import Text.Pandoc.Shared (camelCaseToHyphenated)
36+import Text.DocLayout (render)
3637import Text.DocTemplates (Context(..), Val(..))
3738import Data.Text (Text, unpack)
3839import qualified Data.Text as T
@@ -405,7 +406,7 @@ valToMetaVal :: Val Text -> MetaValue
405406valToMetaVal (MapVal (Context m)) =
406407 MetaMap . M.mapKeys unpack . M.map valToMetaVal $ m
407408valToMetaVal (ListVal xs) = MetaList $ map valToMetaVal xs
408−valToMetaVal (SimpleVal t) = MetaString (unpack t)
409+valToMetaVal (SimpleVal d) = MetaString (unpack $ render Nothing d)
409410valToMetaVal NullVal = MetaString ""
410411
411412-- see https://github.com/jgm/pandoc/pull/4083
src/Text/Pandoc/Lua/Marshaling/Context.hs+6−4
@@ -16,16 +16,18 @@ Marshaling instance for doctemplates Context and its components.
1616-}
1717module Text.Pandoc.Lua.Marshaling.Context () where
1818
19+import Prelude
1920import qualified Foreign.Lua as Lua
2021import Foreign.Lua (Pushable)
21−import Text.DocTemplates (Context(..), Val(..))
22+import Text.DocTemplates (Context(..), Val(..), TemplateTarget)
23+import Text.DocLayout (render)
2224
23−instance Pushable a => Pushable (Context a) where
25+instance (TemplateTarget a, Pushable a) => Pushable (Context a) where
2426 push (Context m) = Lua.push m
2527
26−instance Pushable a => Pushable (Val a) where
28+instance (TemplateTarget a, Pushable a) => Pushable (Val a) where
2729 push NullVal = Lua.push ()
2830 push (MapVal ctx) = Lua.push ctx
2931 push (ListVal xs) = Lua.push xs
30− push (SimpleVal x) = Lua.push x
32+ push (SimpleVal d) = Lua.push $ render Nothing d
3133
src/Text/Pandoc/Options.hs+1−1
@@ -231,7 +231,7 @@ instance FromYAML ReferenceLocation where
231231
232232-- | Options for writers
233233data WriterOptions = WriterOptions
234− { writerTemplate :: Maybe Template -- ^ Template to use
234+ { writerTemplate :: Maybe (Template Text) -- ^ Template to use
235235 , writerVariables :: Context Text -- ^ Variables to set in template
236236 , writerTabStop :: Int -- ^ Tabstop for conversion btw spaces and tabs
237237 , writerTableOfContents :: Bool -- ^ Include table of contents
src/Text/Pandoc/PDF.hs+5−1
@@ -37,6 +37,7 @@ import System.IO (stdout, hClose)
3737import System.IO.Temp (withSystemTempDirectory, withTempDirectory,
3838 withTempFile)
3939import qualified System.IO.Error as IE
40+import Text.DocLayout (literal)
4041import Text.Pandoc.Definition
4142import Text.Pandoc.Error (PandocError (PandocPDFProgramNotFoundError))
4243import Text.Pandoc.MIME (getMimeType)
@@ -134,7 +135,10 @@ makeWithWkhtmltopdf program pdfargs writer opts doc@(Pandoc meta _) = do
134135 MathJax _ -> ["--run-script", "MathJax.Hub.Register.StartupHook('End Typeset', function() { window.status = 'mathjax_loaded' });",
135136 "--window-status", "mathjax_loaded"]
136137 _ -> []
137− meta' <- metaToContext opts (return . stringify) (return . stringify) meta
138+ meta' <- metaToContext opts
139+ (return . literal . stringify)
140+ (return . literal . stringify)
141+ meta
138142 let toArgs (f, mbd) = maybe [] (\d -> ['-':'-':f, d]) mbd
139143 let args = pdfargs ++ mathArgs ++ concatMap toArgs
140144 [("page-size", getField "papersize" meta')
src/Text/Pandoc/Writers/CommonMark.hs+4−3
@@ -34,6 +34,7 @@ import Text.Pandoc.Walk (walk, walkM)
3434import Text.Pandoc.Writers.HTML (writeHtml5String, tagWithAttributes)
3535import Text.Pandoc.Writers.Shared
3636import Text.Pandoc.XML (toHtml5Entities)
37+import Text.DocLayout (literal, render)
3738
3839-- | Convert Pandoc to CommonMark.
3940writeCommonMark :: PandocMonad m => WriterOptions -> Pandoc -> m Text
@@ -50,8 +51,8 @@ writeCommonMark opts (Pandoc meta blocks) = do
5051 else [OrderedList (1, Decimal, Period) $ reverse notes]
5152 main <- blocksToCommonMark opts (blocks' ++ notes')
5253 metadata <- metaToContext opts
53− (fmap T.stripEnd . blocksToCommonMark opts)
54− (fmap T.stripEnd . inlinesToCommonMark opts)
54+ (fmap (literal . T.stripEnd) . blocksToCommonMark opts)
55+ (fmap (literal . T.stripEnd) . inlinesToCommonMark opts)
5556 meta
5657 let context =
5758 -- for backwards compatibility we populate toc
@@ -62,7 +63,7 @@ writeCommonMark opts (Pandoc meta blocks) = do
6263 return $
6364 case writerTemplate opts of
6465 Nothing -> main
65− Just tpl -> renderTemplate tpl context
66+ Just tpl -> render Nothing $ renderTemplate tpl context
6667
6768softBreakToSpace :: Inline -> Inline
6869softBreakToSpace SoftBreak = Space
src/Text/Pandoc/Writers/Custom.hs+7−5
@@ -23,6 +23,7 @@ import qualified Data.Map as M
2323import Data.Text (Text, pack)
2424import Data.Typeable
2525import Foreign.Lua (Lua, Pushable)
26+import Text.DocLayout (render, literal)
2627import Text.Pandoc.Class (PandocIO)
2728import Text.Pandoc.Definition
2829import Text.Pandoc.Lua (Global (..), LuaException (LuaException),
@@ -101,17 +102,18 @@ writeCustom luaFile opts doc@(Pandoc meta _) = do
101102 Lua.tostring' (-1) >>= throw . PandocLuaException . UTF8.toString
102103 rendered <- docToCustom opts doc
103104 context <- metaToContext opts
104− blockListToCustom
105− inlineListToCustom
105+ (fmap (literal . pack) . blockListToCustom)
106+ (fmap (literal . pack) . inlineListToCustom)
106107 meta
107− return (rendered, context)
108+ return (pack rendered, context)
108109 let (body, context) = case res of
109110 Left (LuaException msg) -> throw (PandocLuaException msg)
110111 Right x -> x
111− return $ pack $
112+ return $
112113 case writerTemplate opts of
113114 Nothing -> body
114− Just tpl -> renderTemplate tpl $ setField "body" body context
115+ Just tpl -> render Nothing $
116+ renderTemplate tpl $ setField "body" body context
115117
116118docToCustom :: WriterOptions -> Pandoc -> Lua String
117119docToCustom opts (Pandoc (Meta metamap) blocks) = do
src/Text/Pandoc/Writers/DokuWiki.hs+6−5
@@ -37,6 +37,7 @@ import Text.Pandoc.Options (WrapOption (..), WriterOptions (writerTableOfContent
3737import Text.Pandoc.Shared (camelCaseToHyphenated, escapeURI, isURI, linesToPara,
3838 removeFormatting, substitute, trimr)
3939import Text.Pandoc.Templates (renderTemplate)
40+import Text.DocLayout (render, literal)
4041import Text.Pandoc.Writers.Shared (defField, metaToContext)
4142
4243data WriterState = WriterState {
@@ -71,17 +72,17 @@ pandocToDokuWiki :: PandocMonad m
7172 => WriterOptions -> Pandoc -> DokuWiki m Text
7273pandocToDokuWiki opts (Pandoc meta blocks) = do
7374 metadata <- metaToContext opts
74− (fmap trimr . blockListToDokuWiki opts)
75− (fmap trimr . inlineListToDokuWiki opts)
75+ (fmap (literal . pack . trimr) . blockListToDokuWiki opts)
76+ (fmap (literal . pack . trimr) . inlineListToDokuWiki opts)
7677 meta
7778 body <- blockListToDokuWiki opts blocks
78− let main = body
79+ let main = pack body
7980 let context = defField "body" main
8081 $ defField "toc" (writerTableOfContents opts) metadata
81− return $ pack $
82+ return $
8283 case writerTemplate opts of
8384 Nothing -> main
84− Just tpl -> renderTemplate tpl context
85+ Just tpl -> render Nothing $ renderTemplate tpl context
8586
8687-- | Escape special characters for DokuWiki.
8788escapeString :: String -> String
src/Text/Pandoc/Writers/HTML.hs+4−3
@@ -42,6 +42,7 @@ import qualified Data.Text.Lazy as TL
4242import Network.HTTP (urlEncode)
4343import Network.URI (URI (..), parseURIReference)
4444import Numeric (showHex)
45+import Text.DocLayout (render, literal)
4546import Prelude
4647import Text.Blaze.Internal (MarkupM (Empty), customLeaf, customParent)
4748import Text.DocTemplates (FromContext (lookupContext))
@@ -226,7 +227,7 @@ writeHtmlString' st opts d = do
226227 lookupContext "sourcefile" (writerVariables opts)
227228 report $ NoTitleElement fallback
228229 return $ resetField "pagetitle" (T.pack fallback) context
229− return $ renderTemplate tpl
230+ return $ render Nothing $ renderTemplate tpl
230231 (defField "body" (renderHtml' body) context')
231232
232233writeHtml' :: PandocMonad m => WriterState -> WriterOptions -> Pandoc -> m Html
@@ -249,8 +250,8 @@ pandocToHtml opts (Pandoc meta blocks) = do
249250 let slideLevel = fromMaybe (getSlideLevel blocks) $ writerSlideLevel opts
250251 modify $ \st -> st{ stSlideLevel = slideLevel }
251252 metadata <- metaToContext opts
252− (fmap renderHtml' . blockListToHtml opts)
253− (fmap renderHtml' . inlineListToHtml opts)
253+ (fmap (literal . renderHtml') . blockListToHtml opts)
254+ (fmap (literal . renderHtml') . inlineListToHtml opts)
254255 meta
255256 let stringifyHTML = escapeStringForXML . stringify
256257 let authsMeta = map stringifyHTML $ docAuthors meta
src/Text/Pandoc/Writers/Ipynb.hs+3−2
@@ -39,6 +39,7 @@ import qualified Data.Text.Encoding as TE
3939import qualified Data.ByteString.Lazy as BL
4040import Data.Aeson.Encode.Pretty (Config(..), defConfig,
4141 encodePretty', keyOrder, Indent(Spaces))
42+import Text.DocLayout (literal)
4243
4344writeIpynb :: PandocMonad m => WriterOptions -> Pandoc -> m Text
4445writeIpynb opts d = do
@@ -57,9 +58,9 @@ writeIpynb opts d = do
5758pandocToNotebook :: PandocMonad m
5859 => WriterOptions -> Pandoc -> m (Notebook NbV4)
5960pandocToNotebook opts (Pandoc meta blocks) = do
60− let blockWriter bs = writeMarkdown
61+ let blockWriter bs = literal <$> writeMarkdown
6162 opts{ writerTemplate = Nothing } (Pandoc nullMeta bs)
62− let inlineWriter ils = T.stripEnd <$> writeMarkdown
63+ let inlineWriter ils = literal . T.stripEnd <$> writeMarkdown
6364 opts{ writerTemplate = Nothing } (Pandoc nullMeta [Plain ils])
6465 let jupyterMeta =
6566 case lookupMeta "jupyter" meta of
src/Text/Pandoc/Writers/JATS.hs+2−2
@@ -36,7 +36,7 @@ import Text.Pandoc.Options
3636import Text.DocLayout
3737import Text.Pandoc.Shared
3838import Text.Pandoc.Templates (renderTemplate)
39−import Text.DocTemplates (Context(..), Val(..), TemplateTarget(..))
39+import Text.DocTemplates (Context(..), Val(..))
4040import Text.Pandoc.Writers.Math
4141import Text.Pandoc.Writers.Shared
4242import Text.Pandoc.XML
@@ -88,7 +88,7 @@ docToJATS opts (Pandoc meta blocks) = do
8888 case getField "date" metadata of
8989 Nothing -> NullVal
9090 Just (SimpleVal (x :: Doc Text)) ->
91− case parseDate (T.unpack $ toText x) of
91+ case parseDate (T.unpack $ render Nothing x) of
9292 Nothing -> NullVal
9393 Just day ->
9494 let (y,m,d) = toGregorian day
src/Text/Pandoc/Writers/Jira.hs+8−4
@@ -29,6 +29,7 @@ import Text.Pandoc.Templates (renderTemplate)
2929import Text.Pandoc.Writers.Math (texMathToInlines)
3030import Text.Pandoc.Writers.Shared (metaToContext, defField)
3131import qualified Data.Text as T
32+import Text.DocLayout (literal, render)
3233
3334data WriterState = WriterState
3435 { stNotes :: [Text] -- Footnotes
@@ -53,16 +54,19 @@ writeJira opts document =
5354pandocToJira :: PandocMonad m
5455 => WriterOptions -> Pandoc -> JiraWriter m Text
5556pandocToJira opts (Pandoc meta blocks) = do
56− metadata <- metaToContext opts (blockListToJira opts)
57− (inlineListToJira opts) meta
57+ metadata <- metaToContext opts
58+ (fmap literal . blockListToJira opts)
59+ (fmap literal . inlineListToJira opts) meta
5860 body <- blockListToJira opts blocks
5961 notes <- gets $ T.intercalate "\n" . reverse . stNotes
60− let main = body <> if T.null notes then "" else "\n\n" <> notes
62+ let main = body <> if T.null notes
63+ then mempty
64+ else T.pack "\n\n" <> notes
6165 let context = defField "body" main metadata
6266 return $
6367 case writerTemplate opts of
6468 Nothing -> main
65− Just tpl -> renderTemplate tpl context
69+ Just tpl -> render Nothing $ renderTemplate tpl context
6670
6771-- | Escape one character as needed for Jira.
6872escapeCharForJira :: Char -> Text
src/Text/Pandoc/Writers/LaTeX.hs+2−2
@@ -186,7 +186,7 @@ pandocToLaTeX options (Pandoc meta blocks) = do
186186 ,("tmargin","margin-top")
187187 ,("bmargin","margin-bottom")
188188 ]
189− let toPolyObj :: Lang -> Val (Doc Text)
189+ let toPolyObj :: Lang -> Val Text
190190 toPolyObj lang = MapVal $ Context $
191191 M.fromList [ ("name" , SimpleVal $ text name)
192192 , ("options" , SimpleVal $ text opts) ]
@@ -289,7 +289,7 @@ pandocToLaTeX options (Pandoc meta blocks) = do
289289 )
290290 $ maybe id (defField "polyglossia-lang" . toPolyObj) mblang
291291 $ defField "polyglossia-otherlangs"
292− (ListVal (map toPolyObj docLangs :: [Val (Doc Text)]))
292+ (ListVal (map toPolyObj docLangs :: [Val Text]))
293293 $
294294 defField "latex-dir-rtl"
295295 ((render Nothing <$> getField "dir" context) ==
src/Text/Pandoc/Writers/Markdown.hs+4−4
@@ -112,7 +112,7 @@ pandocTitleBlock tit auths dat =
112112 hang 2 (text "% ") (vcat $ map nowrap auths) <> cr <>
113113 hang 2 (text "% ") dat <> cr
114114
115−mmdTitleBlock :: Context (Doc Text) -> Doc Text
115+mmdTitleBlock :: Context Text -> Doc Text
116116mmdTitleBlock (Context hashmap) =
117117 vcat $ map go $ sortBy (comparing fst) $ M.toList hashmap
118118 where go (k,v) =
@@ -138,10 +138,10 @@ plainTitleBlock tit auths dat =
138138 (hcat (intersperse (text "; ") auths)) <> cr <>
139139 dat <> cr
140140
141−yamlMetadataBlock :: Context (Doc Text) -> Doc Text
141+yamlMetadataBlock :: Context Text -> Doc Text
142142yamlMetadataBlock v = "---" $$ (contextToYaml v) $$ "---"
143143
144−contextToYaml :: Context (Doc Text) -> Doc Text
144+contextToYaml :: Context Text -> Doc Text
145145contextToYaml (Context o) =
146146 vcat $ map keyvalToYaml $ sortBy (comparing fst) $ M.toList o
147147 where
@@ -158,7 +158,7 @@ contextToYaml (Context o) =
158158 (_, NullVal) -> empty
159159 (k', _) -> k' <> ":" <+> hang 2 "" (valToYaml v)
160160
161−valToYaml :: Val (Doc Text) -> Doc Text
161+valToYaml :: Val Text -> Doc Text
162162valToYaml (ListVal xs) =
163163 vcat $ map (\v -> hang 2 "- " (valToYaml v)) xs
164164valToYaml (MapVal c) = contextToYaml c
src/Text/Pandoc/Writers/MediaWiki.hs+6−6
@@ -24,7 +24,7 @@ import Text.Pandoc.Definition
2424import Text.Pandoc.ImageSize
2525import Text.Pandoc.Logging
2626import Text.Pandoc.Options
27−import Text.DocLayout (render)
27+import Text.DocLayout (render, literal)
2828import Text.Pandoc.Shared
2929import Text.Pandoc.Templates (renderTemplate)
3030import Text.Pandoc.Writers.Shared
@@ -55,21 +55,21 @@ pandocToMediaWiki :: PandocMonad m => Pandoc -> MediaWikiWriter m Text
5555pandocToMediaWiki (Pandoc meta blocks) = do
5656 opts <- asks options
5757 metadata <- metaToContext opts
58− (fmap trimr . blockListToMediaWiki)
59− (fmap trimr . inlineListToMediaWiki)
58+ (fmap (literal . pack . trimr) . blockListToMediaWiki)
59+ (fmap (literal . pack . trimr) . inlineListToMediaWiki)
6060 meta
6161 body <- blockListToMediaWiki blocks
6262 notesExist <- gets stNotes
6363 let notes = if notesExist
6464 then "\n<references />"
6565 else ""
66− let main = body ++ notes
66+ let main = pack $ body ++ notes
6767 let context = defField "body" main
6868 $ defField "toc" (writerTableOfContents opts) metadata
69− return $ pack $
69+ return $
7070 case writerTemplate opts of
7171 Nothing -> main
72− Just tpl -> renderTemplate tpl context
72+ Just tpl -> render Nothing $ renderTemplate tpl context
7373
7474-- | Escape special characters for MediaWiki.
7575escapeString :: String -> String
src/Text/Pandoc/Writers/OPML.hs+6−4
@@ -36,17 +36,19 @@ writeOPML opts (Pandoc meta blocks) = do
3636 else Nothing
3737 meta' = B.setMeta "date" (B.str $ convertDate $ docDate meta) meta
3838 metadata <- metaToContext opts
39− (writeMarkdown def . Pandoc nullMeta)
40− (\ils -> T.stripEnd <$> writeMarkdown def (Pandoc nullMeta [Plain ils]))
39+ (fmap literal . writeMarkdown def . Pandoc nullMeta)
40+ (\ils -> literal . T.stripEnd <$>
41+ writeMarkdown def (Pandoc nullMeta [Plain ils]))
4142 meta'
4243 let blocks' = makeSections False (Just 1) blocks
43− main <- (render colwidth . vcat) <$> mapM (blockToOPML opts) blocks'
44+ main <- (render colwidth . vcat) <$>
45+ mapM (blockToOPML opts) blocks'
4446 let context = defField "body" main metadata
4547 return $
4648 (if writerPreferAscii opts then toEntities else id) $
4749 case writerTemplate opts of
4850 Nothing -> main
49− Just tpl -> renderTemplate tpl context
51+ Just tpl -> render colwidth $ renderTemplate tpl context
5052
5153
5254writeHtmlInlines :: PandocMonad m => [Inline] -> m Text
src/Text/Pandoc/Writers/RTF.hs+11−9
@@ -31,6 +31,7 @@ import Text.Pandoc.Logging
3131import Text.Pandoc.Options
3232import Text.Pandoc.Shared
3333import Text.Pandoc.Templates (renderTemplate)
34+import Text.DocLayout (render, literal)
3435import Text.Pandoc.Walk
3536import Text.Pandoc.Writers.Math
3637import Text.Pandoc.Writers.Shared
@@ -97,11 +98,12 @@ writeRTF options doc = do
9798 . M.adjust toPlain "date"
9899 $ metamap
99100 metadata <- metaToContext options
100− (fmap concat . mapM (blockToRTF 0 AlignDefault))
101− inlinesToRTF
101+ (fmap (literal . T.pack . concat) .
102+ mapM (blockToRTF 0 AlignDefault))
103+ (fmap (literal . T.pack) . inlinesToRTF)
102104 meta'
103− body <- blocksToRTF 0 AlignDefault blocks
104− toc <- blocksToRTF 0 AlignDefault
105+ body <- T.pack <$> blocksToRTF 0 AlignDefault blocks
106+ toc <- T.pack <$> blocksToRTF 0 AlignDefault
105107 [toTableOfContents options $ filter isHeaderBlock blocks]
106108 let context = defField "body" body
107109 $ defField "spacer" spacer
@@ -112,12 +114,12 @@ writeRTF options doc = do
112114 -- of the toc rather than a boolean:
113115 . defField "toc" toc
114116 else id) metadata
115− return $ T.pack $
117+ return $
116118 case writerTemplate options of
117− Just tpl -> renderTemplate tpl context
118− Nothing -> case reverse body of
119− ('\n':_) -> body
120− _ -> body ++ "\n"
119+ Just tpl -> render Nothing $ renderTemplate tpl context
120+ Nothing -> case T.unsnoc body of
121+ Just (_,'\n') -> body
122+ _ -> body <> T.singleton '\n'
121123
122124-- | Convert unicode characters (> 127) into rich text format representation.
123125handleUnicode :: String -> String
src/Text/Pandoc/Writers/Roff.hs+2−2
@@ -98,7 +98,7 @@ escapeString escapeMode (x:xs) =
9898characterCodeMap :: Map.Map Char String
9999characterCodeMap = Map.fromList characterCodes
100100
101−fontChange :: (IsString a, PandocMonad m) => MS m (Doc a)
101+fontChange :: (HasChars a, IsString a, PandocMonad m) => MS m (Doc a)
102102fontChange = do
103103 features <- gets stFontFeatures
104104 inHeader <- gets stInHeader
@@ -111,7 +111,7 @@ fontChange = do
111111 then text "\\f[R]"
112112 else text $ "\\f[" ++ filling ++ "]"
113113
114−withFontFeature :: (IsString a, PandocMonad m)
114+withFontFeature :: (HasChars a, IsString a, PandocMonad m)
115115 => Char -> MS m (Doc a) -> MS m (Doc a)
116116withFontFeature c action = do
117117 modify $ \st -> st{ stFontFeatures = Map.adjust not c $ stFontFeatures st }
src/Text/Pandoc/Writers/Shared.hs+11−9
@@ -45,6 +45,7 @@ import Control.Monad (zipWithM)
4545import Data.Aeson (ToJSON (..), encode)
4646import Data.Char (chr, ord, isSpace)
4747import Data.List (groupBy, intersperse, transpose, foldl')
48+import Data.Text.Conversions (FromText(..))
4849import qualified Data.Map as M
4950import qualified Data.Text as T
5051import qualified Text.Pandoc.Builder as Builder
@@ -55,7 +56,7 @@ import Text.Pandoc.Shared (stringify, makeSections, deNote, deLink)
5556import Text.Pandoc.Walk (walk)
5657import qualified Text.Pandoc.UTF8 as UTF8
5758import Text.Pandoc.XML (escapeStringForXML)
58−import Text.DocTemplates (Context(..), Val(..), TemplateTarget(..),
59+import Text.DocTemplates (Context(..), Val(..), TemplateTarget,
5960 ToContext(..), FromContext(..))
6061
6162-- | Create template Context from a 'Meta' and an association list
@@ -65,8 +66,8 @@ import Text.DocTemplates (Context(..), Val(..), TemplateTarget(..),
6566-- assigned. Does nothing if 'writerTemplate' is Nothing.
6667metaToContext :: (Monad m, TemplateTarget a)
6768 => WriterOptions
68− -> ([Block] -> m a)
69− -> ([Inline] -> m a)
69+ -> ([Block] -> m (Doc a))
70+ -> ([Inline] -> m (Doc a))
7071 -> Meta
7172 -> m (Context a)
7273metaToContext opts blockWriter inlineWriter meta =
@@ -78,8 +79,8 @@ metaToContext opts blockWriter inlineWriter meta =
7879-- | Like 'metaToContext, but does not include variables and is
7980-- not sensitive to 'writerTemplate'.
8081metaToContext' :: (Monad m, TemplateTarget a)
81− => ([Block] -> m a)
82− -> ([Inline] -> m a)
82+ => ([Block] -> m (Doc a))
83+ -> ([Inline] -> m (Doc a))
8384 -> Meta
8485 -> m (Context a)
8586metaToContext' blockWriter inlineWriter (Meta metamap) = do
@@ -97,13 +98,14 @@ addVariablesToContext opts (Context m1) =
9798 m2 = case traverse go (writerVariables opts) of
9899 Just (Context x) -> x
99100 Nothing -> mempty
100− m3 = M.insert "meta-json" (SimpleVal $ fromText jsonrep) mempty
101+ m3 = M.insert "meta-json" (SimpleVal $ literal $ fromText jsonrep)
102+ mempty
101103 go = Just . fromText
102104 jsonrep = UTF8.toText $ BL.toStrict $ encode $ toJSON m1
103105
104106metaValueToVal :: (Monad m, TemplateTarget a)
105− => ([Block] -> m a)
106− -> ([Inline] -> m a)
107+ => ([Block] -> m (Doc a))
108+ -> ([Inline] -> m (Doc a))
107109 -> MetaValue
108110 -> m (Val a)
109111metaValueToVal blockWriter inlineWriter (MetaMap metamap) =
@@ -111,7 +113,7 @@ metaValueToVal blockWriter inlineWriter (MetaMap metamap) =
111113 mapM (metaValueToVal blockWriter inlineWriter) metamap
112114metaValueToVal blockWriter inlineWriter (MetaList xs) = ListVal <$>
113115 mapM (metaValueToVal blockWriter inlineWriter) xs
114−metaValueToVal _ _ (MetaBool True) = return $ SimpleVal $ fromText "true"
116+metaValueToVal _ _ (MetaBool True) = return $ SimpleVal "true"
115117metaValueToVal _ _ (MetaBool False) = return NullVal
116118metaValueToVal _ inlineWriter (MetaString s) =
117119 SimpleVal <$> inlineWriter (Builder.toList (Builder.text s))
src/Text/Pandoc/Writers/Textile.hs+7−6
@@ -23,7 +23,7 @@ import Text.Pandoc.Definition
2323import Text.Pandoc.ImageSize
2424import Text.Pandoc.Logging
2525import Text.Pandoc.Options
26−import Text.DocLayout (render)
26+import Text.DocLayout (render, literal)
2727import Text.Pandoc.Shared
2828import Text.Pandoc.Templates (renderTemplate)
2929import Text.Pandoc.Writers.Shared
@@ -51,16 +51,17 @@ writeTextile opts document =
5151pandocToTextile :: PandocMonad m
5252 => WriterOptions -> Pandoc -> TW m Text
5353pandocToTextile opts (Pandoc meta blocks) = do
54− metadata <- metaToContext opts (blockListToTextile opts)
55− (inlineListToTextile opts) meta
54+ metadata <- metaToContext opts
55+ (fmap (literal . pack) . blockListToTextile opts)
56+ (fmap (literal . pack) . inlineListToTextile opts) meta
5657 body <- blockListToTextile opts blocks
5758 notes <- gets $ unlines . reverse . stNotes
58− let main = body ++ if null notes then "" else "\n\n" ++ notes
59+ let main = pack $ body ++ if null notes then "" else "\n\n" ++ notes
5960 let context = defField "body" main metadata
60− return $ pack $
61+ return $
6162 case writerTemplate opts of
6263 Nothing -> main
63− Just tpl -> renderTemplate tpl context
64+ Just tpl -> render Nothing $ renderTemplate tpl context
6465
6566withUseTags :: PandocMonad m => TW m a -> TW m a
6667withUseTags action = do
src/Text/Pandoc/Writers/ZimWiki.hs+9−6
@@ -20,13 +20,16 @@ import Control.Monad.State.Strict (StateT, evalStateT, gets, modify)
2020import Data.Default (Default (..))
2121import Data.List (intercalate, isInfixOf, isPrefixOf, transpose)
2222import qualified Data.Map as Map
23+import Text.DocLayout (render, literal)
2324import Data.Maybe (fromMaybe)
2425import Data.Text (Text, breakOnAll, pack)
2526import Text.Pandoc.Class (PandocMonad, report)
2627import Text.Pandoc.Definition
2728import Text.Pandoc.ImageSize
2829import Text.Pandoc.Logging
29−import Text.Pandoc.Options (WrapOption (..), WriterOptions (writerTableOfContents, writerTemplate, writerWrapText))
30+import Text.Pandoc.Options (WrapOption (..),
31+ WriterOptions (writerTableOfContents, writerTemplate,
32+ writerWrapText))
3033import Text.Pandoc.Shared (escapeURI, isURI, linesToPara, removeFormatting,
3134 substitute, trimr)
3235import Text.Pandoc.Templates (renderTemplate)
@@ -51,16 +54,16 @@ writeZimWiki opts document = evalStateT (pandocToZimWiki opts document) def
5154pandocToZimWiki :: PandocMonad m => WriterOptions -> Pandoc -> ZW m Text
5255pandocToZimWiki opts (Pandoc meta blocks) = do
5356 metadata <- metaToContext opts
54− (fmap trimr . blockListToZimWiki opts)
55− (fmap trimr . inlineListToZimWiki opts)
57+ (fmap (literal . pack . trimr) . blockListToZimWiki opts)
58+ (fmap (literal . pack . trimr) . inlineListToZimWiki opts)
5659 meta
57− main <- blockListToZimWiki opts blocks
60+ main <- pack <$> blockListToZimWiki opts blocks
5861 --let header = "Content-Type: text/x-zim-wiki\nWiki-Format: zim 0.4\n"
5962 let context = defField "body" main
6063 $ defField "toc" (writerTableOfContents opts) metadata
61− return $ pack $
64+ return $
6265 case writerTemplate opts of
63− Just tpl -> renderTemplate tpl context
66+ Just tpl -> render Nothing $ renderTemplate tpl context
6467 Nothing -> main
6568
6669-- | Escape special characters for ZimWiki.
src/Text/Pandoc/XML.hs+8−5
@@ -56,14 +56,14 @@ escapeNls (x:xs)
5656escapeNls [] = []
5757
5858-- | Return a text object with a string of formatted XML attributes.
59−attributeList :: IsString a => [(String, String)] -> Doc a
59+attributeList :: (HasChars a, IsString a) => [(String, String)] -> Doc a
6060attributeList = hcat . map
6161 (\(a, b) -> text (' ' : escapeStringForXML a ++ "=\"" ++
6262 escapeNls (escapeStringForXML b) ++ "\""))
6363
6464-- | Put the supplied contents between start and end tags of tagType,
6565-- with specified attributes and (if specified) indentation.
66−inTags:: IsString a
66+inTags:: (HasChars a, IsString a)
6767 => Bool -> String -> [(String, String)] -> Doc a -> Doc a
6868inTags isIndented tagType attribs contents =
6969 let openTag = char '<' <> text tagType <> attributeList attribs <>
@@ -74,16 +74,19 @@ inTags isIndented tagType attribs contents =
7474 else openTag <> contents <> closeTag
7575
7676-- | Return a self-closing tag of tagType with specified attributes
77−selfClosingTag :: IsString a => String -> [(String, String)] -> Doc a
77+selfClosingTag :: (HasChars a, IsString a)
78+ => String -> [(String, String)] -> Doc a
7879selfClosingTag tagType attribs =
7980 char '<' <> text tagType <> attributeList attribs <> text " />"
8081
8182-- | Put the supplied contents between start and end tags of tagType.
82−inTagsSimple :: IsString a => String -> Doc a -> Doc a
83+inTagsSimple :: (HasChars a, IsString a)
84+ => String -> Doc a -> Doc a
8385inTagsSimple tagType = inTags False tagType []
8486
8587-- | Put the supplied contents in indented block btw start and end tags.
86−inTagsIndented :: IsString a => String -> Doc a -> Doc a
88+inTagsIndented :: (HasChars a, IsString a)
89+ => String -> Doc a -> Doc a
8790inTagsIndented tagType = inTags True tagType []
8891
8992-- | Escape all non-ascii characters using numerical entities.
stack.yaml+2−4
@@ -19,12 +19,10 @@ extra-deps:
1919- skylighting-0.8.2.3
2020- skylighting-core-0.8.2.3
2121- regex-pcre-builtin-0.95.0.8.8.35
22−- doclayout-0.1
22+- doclayout-0.2
2323- HsYAML-0.2.0.0
2424- HsYAML-aeson-0.2.0.0
25−# - doctemplates-0.6.1
26−- git: https://github.com/jgm/doctemplates.git
27− commit: 0333142110e77408b8ee048064941884317aa757
25+- doctemplates-0.7
2826ghc-options:
2927 "$locals": -fhide-source-paths -Wno-missing-home-modules
3028resolver: lts-14.6
test/Tests/Writers/RST.hs+1−1
@@ -24,7 +24,7 @@ testTemplate t = case runIdentity (compileTemplate [] (T.pack t)) of
2424 Left e -> error $ "Could not compile RST template: " ++ e
2525 Right templ -> test (purely (writeRST def{ writerTemplate = Just templ }) . toPandoc)
2626
27−bodyTemplate :: Template
27+bodyTemplate :: Template T.Text
2828bodyTemplate = case runIdentity (compileTemplate [] "$body$\n") of
2929 Left e -> error $
3030 "Could not compile RST bodyTemplate" ++ e
test/writer.textile−1
@@ -717,4 +717,3 @@ fn4. In quote.
717717
718718
719719fn5. In list.
720−