aboutsummaryrefslogtreecommitdiff
path: root/Text/Pandoc/Writers
diff options
context:
space:
mode:
authorfiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b>2009-01-24 20:00:26 +0000
committerfiddlosopher <fiddlosopher@788f1e2b-df1e-0410-8736-df70ead52e1b>2009-01-24 20:00:26 +0000
commit42aca57dee8d88afa5fac512aeb1198102908865 (patch)
tree1c6a98bd226f4fffde6768010715bc1d80e5d168 /Text/Pandoc/Writers
parent39e8d8486693029abfef84c45e85416f7c775280 (diff)
downloadpandoc-42aca57dee8d88afa5fac512aeb1198102908865.tar.gz
Moved all haskell source to src subdirectory.
git-svn-id: https://pandoc.googlecode.com/svn/trunk@1528 788f1e2b-df1e-0410-8736-df70ead52e1b
Diffstat (limited to 'Text/Pandoc/Writers')
-rw-r--r--Text/Pandoc/Writers/ConTeXt.hs302
-rw-r--r--Text/Pandoc/Writers/Docbook.hs262
-rw-r--r--Text/Pandoc/Writers/HTML.hs557
-rw-r--r--Text/Pandoc/Writers/LaTeX.hs331
-rw-r--r--Text/Pandoc/Writers/Man.hs301
-rw-r--r--Text/Pandoc/Writers/Markdown.hs396
-rw-r--r--Text/Pandoc/Writers/MediaWiki.hs396
-rw-r--r--Text/Pandoc/Writers/OpenDocument.hs568
-rw-r--r--Text/Pandoc/Writers/RST.hs346
-rw-r--r--Text/Pandoc/Writers/RTF.hs291
-rw-r--r--Text/Pandoc/Writers/S5.hs157
-rw-r--r--Text/Pandoc/Writers/Texinfo.hs474
12 files changed, 0 insertions, 4381 deletions
diff --git a/Text/Pandoc/Writers/ConTeXt.hs b/Text/Pandoc/Writers/ConTeXt.hs
deleted file mode 100644
index 014751968..000000000
--- a/Text/Pandoc/Writers/ConTeXt.hs
+++ /dev/null
@@ -1,302 +0,0 @@
-{-
-Copyright (C) 2007-8 John MacFarlane <jgm@berkeley.edu>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.ConTeXt
- Copyright : Copyright (C) 2007-8 John MacFarlane
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Conversion of 'Pandoc' format into ConTeXt.
--}
-module Text.Pandoc.Writers.ConTeXt ( writeConTeXt ) where
-import Text.Pandoc.Definition
-import Text.Pandoc.Shared
-import Text.Printf ( printf )
-import Data.List ( isSuffixOf, intercalate )
-import Control.Monad.State
-import Text.PrettyPrint.HughesPJ hiding ( Str )
-
-data WriterState =
- WriterState { stNextRef :: Int -- number of next URL reference
- , stOrderedListLevel :: Int -- level of ordered list
- , stOptions :: WriterOptions -- writer options
- }
-
-orderedListStyles :: [[Char]]
-orderedListStyles = cycle ["[n]","[a]", "[r]", "[g]"]
-
--- | Convert Pandoc to ConTeXt.
-writeConTeXt :: WriterOptions -> Pandoc -> String
-writeConTeXt options document =
- let defaultWriterState = WriterState { stNextRef = 1
- , stOrderedListLevel = 0
- , stOptions = options
- }
- in render $
- evalState (pandocToConTeXt options document) defaultWriterState
-
-pandocToConTeXt :: WriterOptions -> Pandoc -> State WriterState Doc
-pandocToConTeXt options (Pandoc meta blocks) = do
- main <- blockListToConTeXt blocks
- let before = if null (writerIncludeBefore options)
- then empty
- else text $ writerIncludeBefore options
- let after = if null (writerIncludeAfter options)
- then empty
- else text $ writerIncludeAfter options
- let body = before $$ main $$ after
- head' <- if writerStandalone options
- then contextHeader options meta
- else return empty
- let toc = if writerTableOfContents options
- then text "\\placecontent\n"
- else empty
- let foot = if writerStandalone options
- then text "\\stoptext\n"
- else empty
- return $ head' $$ toc $$ body $$ foot
-
--- | Insert bibliographic information into ConTeXt header.
-contextHeader :: WriterOptions -- ^ Options, including ConTeXt header
- -> Meta -- ^ Meta with bibliographic information
- -> State WriterState Doc
-contextHeader options (Meta title authors date) = do
- titletext <- if null title
- then return empty
- else inlineListToConTeXt title
- let authorstext = if null authors
- then ""
- else if length authors == 1
- then stringToConTeXt $ head authors
- else stringToConTeXt $ (intercalate ", " $
- init authors) ++ " & " ++ last authors
- let datetext = if date == ""
- then ""
- else stringToConTeXt date
- let titleblock = text "\\doctitle{" <> titletext <> char '}' $$
- text ("\\author{" ++ authorstext ++ "}") $$
- text ("\\date{" ++ datetext ++ "}")
- let header = text $ writerHeader options
- return $ header $$ titleblock $$ text "\\starttext\n\\maketitle\n"
-
--- escape things as needed for ConTeXt
-
-escapeCharForConTeXt :: Char -> String
-escapeCharForConTeXt ch =
- case ch of
- '{' -> "\\letteropenbrace{}"
- '}' -> "\\letterclosebrace{}"
- '\\' -> "\\letterbackslash{}"
- '$' -> "\\$"
- '|' -> "\\letterbar{}"
- '^' -> "\\letterhat{}"
- '%' -> "\\%"
- '~' -> "\\lettertilde{}"
- '&' -> "\\&"
- '#' -> "\\#"
- '<' -> "\\letterless{}"
- '>' -> "\\lettermore{}"
- '_' -> "\\letterunderscore{}"
- '\160' -> "~"
- x -> [x]
-
--- | Escape string for ConTeXt
-stringToConTeXt :: String -> String
-stringToConTeXt = concatMap escapeCharForConTeXt
-
--- | Convert Pandoc block element to ConTeXt.
-blockToConTeXt :: Block
- -> State WriterState BlockWrapper
-blockToConTeXt Null = return $ Reg empty
-blockToConTeXt (Plain lst) = do
- st <- get
- let options = stOptions st
- contents <- wrapTeXIfNeeded options False inlineListToConTeXt lst
- return $ Reg contents
-blockToConTeXt (Para lst) = do
- st <- get
- let options = stOptions st
- contents <- wrapTeXIfNeeded options False inlineListToConTeXt lst
- return $ Pad contents
-blockToConTeXt (BlockQuote lst) = do
- contents <- blockListToConTeXt lst
- return $ Pad $ text "\\startblockquote" $$ contents $$ text "\\stopblockquote"
-blockToConTeXt (CodeBlock _ str) =
- return $ Reg $ text $ "\\starttyping\n" ++ str ++ "\n\\stoptyping\n"
- -- \n because \stoptyping can't have anything after it, inc. }
-blockToConTeXt (RawHtml _) = return $ Reg empty
-blockToConTeXt (BulletList lst) = do
- contents <- mapM listItemToConTeXt lst
- return $ Pad $ text "\\startitemize" $$ vcat contents $$ text "\\stopitemize"
-blockToConTeXt (OrderedList (start, style', delim) lst) = do
- st <- get
- let level = stOrderedListLevel st
- put $ st {stOrderedListLevel = level + 1}
- contents <- mapM listItemToConTeXt lst
- put $ st {stOrderedListLevel = level}
- let start' = if start == 1 then "" else "start=" ++ show start
- let delim' = case delim of
- DefaultDelim -> ""
- Period -> "stopper=."
- OneParen -> "stopper=)"
- TwoParens -> "left=(,stopper=)"
- let width = maximum $ map length $ take (length contents)
- (orderedListMarkers (start, style', delim))
- let width' = (toEnum width + 1) / 2
- let width'' = if width' > (1.5 :: Double)
- then "width=" ++ show width' ++ "em"
- else ""
- let specs2Items = filter (not . null) [start', delim', width'']
- let specs2 = if null specs2Items
- then ""
- else "[" ++ intercalate "," specs2Items ++ "]"
- let style'' = case style' of
- DefaultStyle -> orderedListStyles !! level
- Decimal -> "[n]"
- LowerRoman -> "[r]"
- UpperRoman -> "[R]"
- LowerAlpha -> "[a]"
- UpperAlpha -> "[A]"
- let specs = style'' ++ specs2
- return $ Pad $ text ("\\startitemize" ++ specs) $$ vcat contents $$
- text "\\stopitemize"
-blockToConTeXt (DefinitionList lst) =
- mapM defListItemToConTeXt lst >>= return . Pad . wrappedBlocksToDoc
-blockToConTeXt HorizontalRule = return $ Pad $ text "\\thinrule"
-blockToConTeXt (Header level lst) = do
- contents <- inlineListToConTeXt lst
- st <- get
- let opts = stOptions st
- let base = if writerNumberSections opts then "section" else "subject"
- return $ Pad $ if level >= 1 && level <= 5
- then char '\\' <> text (concat (replicate (level - 1) "sub")) <>
- text base <> char '{' <> contents <> char '}'
- else contents
-blockToConTeXt (Table caption aligns widths heads rows) = do
- let colWidths = map printDecimal widths
- let colDescriptor colWidth alignment = (case alignment of
- AlignLeft -> 'l'
- AlignRight -> 'r'
- AlignCenter -> 'c'
- AlignDefault -> 'l'):
- "p(" ++ colWidth ++ "\\textwidth)|"
- let colDescriptors = "|" ++ (concat $
- zipWith colDescriptor colWidths aligns)
- headers <- tableRowToConTeXt heads
- captionText <- inlineListToConTeXt caption
- let captionText' = if null caption then text "none" else captionText
- rows' <- mapM tableRowToConTeXt rows
- return $ Pad $ text "\\placetable[here]{" <> captionText' <> char '}' $$
- text "\\starttable[" <> text colDescriptors <> char ']' $$
- text "\\HL" $$ headers $$ text "\\HL" $$
- vcat rows' $$ text "\\HL\n\\stoptable"
-
-printDecimal :: Double -> String
-printDecimal = printf "%.2f"
-
-tableRowToConTeXt :: [[Block]] -> State WriterState Doc
-tableRowToConTeXt cols = do
- cols' <- mapM blockListToConTeXt cols
- return $ (vcat (map (text "\\NC " <>) cols')) $$
- text "\\NC\\AR"
-
-listItemToConTeXt :: [Block] -> State WriterState Doc
-listItemToConTeXt list = blockListToConTeXt list >>=
- return . (text "\\item" $$) . (nest 2)
-
-defListItemToConTeXt :: ([Inline], [Block]) -> State WriterState BlockWrapper
-defListItemToConTeXt (term, def) = do
- term' <- inlineListToConTeXt term
- def' <- blockListToConTeXt def
- return $ Pad $ text "\\startdescr{" <> term' <> char '}' $$ def' $$ text "\\stopdescr"
-
--- | Convert list of block elements to ConTeXt.
-blockListToConTeXt :: [Block] -> State WriterState Doc
-blockListToConTeXt lst = mapM blockToConTeXt lst >>= return . wrappedBlocksToDoc
-
--- | Convert list of inline elements to ConTeXt.
-inlineListToConTeXt :: [Inline] -- ^ Inlines to convert
- -> State WriterState Doc
-inlineListToConTeXt lst = mapM inlineToConTeXt lst >>= return . hcat
-
--- | Convert inline element to ConTeXt
-inlineToConTeXt :: Inline -- ^ Inline to convert
- -> State WriterState Doc
-inlineToConTeXt (Emph lst) = do
- contents <- inlineListToConTeXt lst
- return $ text "{\\em " <> contents <> char '}'
-inlineToConTeXt (Strong lst) = do
- contents <- inlineListToConTeXt lst
- return $ text "{\\bf " <> contents <> char '}'
-inlineToConTeXt (Strikeout lst) = do
- contents <- inlineListToConTeXt lst
- return $ text "\\overstrikes{" <> contents <> char '}'
-inlineToConTeXt (Superscript lst) = do
- contents <- inlineListToConTeXt lst
- return $ text "\\high{" <> contents <> char '}'
-inlineToConTeXt (Subscript lst) = do
- contents <- inlineListToConTeXt lst
- return $ text "\\low{" <> contents <> char '}'
-inlineToConTeXt (SmallCaps lst) = do
- contents <- inlineListToConTeXt lst
- return $ text "{\\sc " <> contents <> char '}'
-inlineToConTeXt (Code str) = return $ text $ "\\type{" ++ str ++ "}"
-inlineToConTeXt (Quoted SingleQuote lst) = do
- contents <- inlineListToConTeXt lst
- return $ text "\\quote{" <> contents <> char '}'
-inlineToConTeXt (Quoted DoubleQuote lst) = do
- contents <- inlineListToConTeXt lst
- return $ text "\\quotation{" <> contents <> char '}'
-inlineToConTeXt (Cite _ lst) = inlineListToConTeXt lst
-inlineToConTeXt Apostrophe = return $ char '\''
-inlineToConTeXt EmDash = return $ text "---"
-inlineToConTeXt EnDash = return $ text "--"
-inlineToConTeXt Ellipses = return $ text "\\ldots{}"
-inlineToConTeXt (Str str) = return $ text $ stringToConTeXt str
-inlineToConTeXt (Math InlineMath str) = return $ char '$' <> text str <> char '$'
-inlineToConTeXt (Math DisplayMath str) = return $ text "\\startformula " <> text str <> text " \\stopformula"
-inlineToConTeXt (TeX str) = return $ text str
-inlineToConTeXt (HtmlInline _) = return empty
-inlineToConTeXt (LineBreak) = return $ text "\\crlf\n"
-inlineToConTeXt Space = return $ char ' '
-inlineToConTeXt (Link [Code str] (src, tit)) = -- since ConTeXt has its own
- inlineToConTeXt (Link [Str str] (src, tit)) -- way of printing links...
-inlineToConTeXt (Link txt (src, _)) = do
- st <- get
- let next = stNextRef st
- put $ st {stNextRef = next + 1}
- let ref = show next
- label <- inlineListToConTeXt txt
- return $ text "\\useURL[" <> text ref <> text "][" <> text src <>
- text "][][" <> label <> text "]\\from[" <> text ref <> char ']'
-inlineToConTeXt (Image alternate (src, tit)) = do
- alt <- inlineListToConTeXt alternate
- return $ text "\\placefigure\n[]\n[fig:" <> alt <> text "]\n{" <>
- text tit <> text "}\n{\\externalfigure[" <> text src <> text "]}"
-inlineToConTeXt (Note contents) = do
- contents' <- blockListToConTeXt contents
- let rawnote = stripTrailingNewlines $ render contents'
- -- note: a \n before } is needed when note ends with a \stoptyping
- let optNewline = "\\stoptyping" `isSuffixOf` rawnote
- return $ text "\\footnote{" <>
- text rawnote <> (if optNewline then char '\n' else empty) <> char '}'
-
diff --git a/Text/Pandoc/Writers/Docbook.hs b/Text/Pandoc/Writers/Docbook.hs
deleted file mode 100644
index 3e535a87e..000000000
--- a/Text/Pandoc/Writers/Docbook.hs
+++ /dev/null
@@ -1,262 +0,0 @@
-{-
-Copyright (C) 2006-7 John MacFarlane <jgm@berkeley.edu>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.Docbook
- Copyright : Copyright (C) 2006-7 John MacFarlane
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Conversion of 'Pandoc' documents to Docbook XML.
--}
-module Text.Pandoc.Writers.Docbook ( writeDocbook) where
-import Text.Pandoc.Definition
-import Text.Pandoc.XML
-import Text.Pandoc.Shared
-import Text.Pandoc.Readers.TeXMath
-import Data.List ( isPrefixOf, drop, intercalate )
-import Text.PrettyPrint.HughesPJ hiding ( Str )
-
--- | Convert list of authors to a docbook <author> section
-authorToDocbook :: [Char] -> Doc
-authorToDocbook name = inTagsIndented "author" $
- if ',' `elem` name
- then -- last name first
- let (lastname, rest) = break (==',') name
- firstname = removeLeadingSpace rest in
- inTagsSimple "firstname" (text $ escapeStringForXML firstname) <>
- inTagsSimple "surname" (text $ escapeStringForXML lastname)
- else -- last name last
- let namewords = words name
- lengthname = length namewords
- (firstname, lastname) = case lengthname of
- 0 -> ("","")
- 1 -> ("", name)
- n -> (intercalate " " (take (n-1) namewords), last namewords)
- in inTagsSimple "firstname" (text $ escapeStringForXML firstname) $$
- inTagsSimple "surname" (text $ escapeStringForXML lastname)
-
--- | Convert Pandoc document to string in Docbook format.
-writeDocbook :: WriterOptions -> Pandoc -> String
-writeDocbook opts (Pandoc (Meta title authors date) blocks) =
- let head' = if writerStandalone opts
- then text (writerHeader opts)
- else empty
- meta = if writerStandalone opts
- then inTagsIndented "articleinfo" $
- (inTagsSimple "title" (wrap opts title)) $$
- (vcat (map authorToDocbook authors)) $$
- (inTagsSimple "date" (text $ escapeStringForXML date))
- else empty
- elements = hierarchicalize blocks
- before = writerIncludeBefore opts
- after = writerIncludeAfter opts
- body = (if null before then empty else text before) $$
- vcat (map (elementToDocbook opts) elements) $$
- (if null after then empty else text after)
- body' = if writerStandalone opts
- then inTagsIndented "article" (meta $$ body)
- else body
- in render $ head' $$ body' $$ text ""
-
--- | Convert an Element to Docbook.
-elementToDocbook :: WriterOptions -> Element -> Doc
-elementToDocbook opts (Blk block) = blockToDocbook opts block
-elementToDocbook opts (Sec title elements) =
- -- Docbook doesn't allow sections with no content, so insert some if needed
- let elements' = if null elements
- then [Blk (Para [])]
- else elements
- in inTagsIndented "section" $
- inTagsSimple "title" (wrap opts title) $$
- vcat (map (elementToDocbook opts) elements')
-
--- | Convert a list of Pandoc blocks to Docbook.
-blocksToDocbook :: WriterOptions -> [Block] -> Doc
-blocksToDocbook opts = vcat . map (blockToDocbook opts)
-
--- | Auxiliary function to convert Plain block to Para.
-plainToPara :: Block -> Block
-plainToPara (Plain x) = Para x
-plainToPara x = x
-
--- | Convert a list of pairs of terms and definitions into a list of
--- Docbook varlistentrys.
-deflistItemsToDocbook :: WriterOptions -> [([Inline],[Block])] -> Doc
-deflistItemsToDocbook opts items =
- vcat $ map (\(term, def) -> deflistItemToDocbook opts term def) items
-
--- | Convert a term and a list of blocks into a Docbook varlistentry.
-deflistItemToDocbook :: WriterOptions -> [Inline] -> [Block] -> Doc
-deflistItemToDocbook opts term def =
- let def' = map plainToPara def
- in inTagsIndented "varlistentry" $
- inTagsIndented "term" (inlinesToDocbook opts term) $$
- inTagsIndented "listitem" (blocksToDocbook opts def')
-
--- | Convert a list of lists of blocks to a list of Docbook list items.
-listItemsToDocbook :: WriterOptions -> [[Block]] -> Doc
-listItemsToDocbook opts items = vcat $ map (listItemToDocbook opts) items
-
--- | Convert a list of blocks into a Docbook list item.
-listItemToDocbook :: WriterOptions -> [Block] -> Doc
-listItemToDocbook opts item =
- inTagsIndented "listitem" $ blocksToDocbook opts $ map plainToPara item
-
--- | Convert a Pandoc block element to Docbook.
-blockToDocbook :: WriterOptions -> Block -> Doc
-blockToDocbook _ Null = empty
-blockToDocbook _ (Header _ _) = empty -- should not occur after hierarchicalize
-blockToDocbook opts (Plain lst) = wrap opts lst
-blockToDocbook opts (Para lst) = inTagsIndented "para" $ wrap opts lst
-blockToDocbook opts (BlockQuote blocks) =
- inTagsIndented "blockquote" $ blocksToDocbook opts blocks
-blockToDocbook _ (CodeBlock _ str) =
- text "<screen>\n" <> text (escapeStringForXML str) <> text "\n</screen>"
-blockToDocbook opts (BulletList lst) =
- inTagsIndented "itemizedlist" $ listItemsToDocbook opts lst
-blockToDocbook _ (OrderedList _ []) = empty
-blockToDocbook opts (OrderedList (start, numstyle, _) (first:rest)) =
- let attribs = case numstyle of
- DefaultStyle -> []
- Decimal -> [("numeration", "arabic")]
- UpperAlpha -> [("numeration", "upperalpha")]
- LowerAlpha -> [("numeration", "loweralpha")]
- UpperRoman -> [("numeration", "upperroman")]
- LowerRoman -> [("numeration", "lowerroman")]
- items = if start == 1
- then listItemsToDocbook opts (first:rest)
- else (inTags True "listitem" [("override",show start)]
- (blocksToDocbook opts $ map plainToPara first)) $$
- listItemsToDocbook opts rest
- in inTags True "orderedlist" attribs items
-blockToDocbook opts (DefinitionList lst) =
- inTagsIndented "variablelist" $ deflistItemsToDocbook opts lst
-blockToDocbook _ (RawHtml str) = text str -- raw XML block
-blockToDocbook _ HorizontalRule = empty -- not semantic
-blockToDocbook opts (Table caption aligns widths headers rows) =
- let alignStrings = map alignmentToString aligns
- captionDoc = if null caption
- then empty
- else inTagsIndented "caption"
- (inlinesToDocbook opts caption)
- tableType = if isEmpty captionDoc then "informaltable" else "table"
- in inTagsIndented tableType $ captionDoc $$
- (colHeadsToDocbook opts alignStrings widths headers) $$
- (vcat $ map (tableRowToDocbook opts alignStrings) rows)
-
-colHeadsToDocbook :: WriterOptions
- -> [[Char]]
- -> [Double]
- -> [[Block]]
- -> Doc
-colHeadsToDocbook opts alignStrings widths headers =
- let heads = zipWith3 (\align width item ->
- tableItemToDocbook opts "th" align width item)
- alignStrings widths headers
- in inTagsIndented "tr" $ vcat heads
-
-alignmentToString :: Alignment -> [Char]
-alignmentToString alignment = case alignment of
- AlignLeft -> "left"
- AlignRight -> "right"
- AlignCenter -> "center"
- AlignDefault -> "left"
-
-tableRowToDocbook :: WriterOptions -> [[Char]] -> [[Block]] -> Doc
-tableRowToDocbook opts aligns cols = inTagsIndented "tr" $
- vcat $ zipWith3 (tableItemToDocbook opts "td") aligns (repeat 0) cols
-
-tableItemToDocbook :: WriterOptions
- -> [Char]
- -> [Char]
- -> Double
- -> [Block]
- -> Doc
-tableItemToDocbook opts tag align width item =
- let attrib = [("align", align)] ++
- if width /= 0
- then [("style", "{width: " ++
- show (truncate (100*width) :: Integer) ++ "%;}")]
- else []
- in inTags True tag attrib $ vcat $ map (blockToDocbook opts) item
-
--- | Take list of inline elements and return wrapped doc.
-wrap :: WriterOptions -> [Inline] -> Doc
-wrap opts lst = if writerWrapText opts
- then fsep $ map (inlinesToDocbook opts) (splitBy Space lst)
- else inlinesToDocbook opts lst
-
--- | Convert a list of inline elements to Docbook.
-inlinesToDocbook :: WriterOptions -> [Inline] -> Doc
-inlinesToDocbook opts lst = hcat $ map (inlineToDocbook opts) lst
-
--- | Convert an inline element to Docbook.
-inlineToDocbook :: WriterOptions -> Inline -> Doc
-inlineToDocbook _ (Str str) = text $ escapeStringForXML str
-inlineToDocbook opts (Emph lst) =
- inTagsSimple "emphasis" $ inlinesToDocbook opts lst
-inlineToDocbook opts (Strong lst) =
- inTags False "emphasis" [("role", "strong")] $ inlinesToDocbook opts lst
-inlineToDocbook opts (Strikeout lst) =
- inTags False "emphasis" [("role", "strikethrough")] $
- inlinesToDocbook opts lst
-inlineToDocbook opts (Superscript lst) =
- inTagsSimple "superscript" $ inlinesToDocbook opts lst
-inlineToDocbook opts (Subscript lst) =
- inTagsSimple "subscript" $ inlinesToDocbook opts lst
-inlineToDocbook opts (SmallCaps lst) =
- inTags False "emphasis" [("role", "smallcaps")] $
- inlinesToDocbook opts lst
-inlineToDocbook opts (Quoted _ lst) =
- inTagsSimple "quote" $ inlinesToDocbook opts lst
-inlineToDocbook opts (Cite _ lst) =
- inlinesToDocbook opts lst
-inlineToDocbook _ Apostrophe = char '\''
-inlineToDocbook _ Ellipses = text "&#8230;"
-inlineToDocbook _ EmDash = text "&#8212;"
-inlineToDocbook _ EnDash = text "&#8211;"
-inlineToDocbook _ (Code str) =
- inTagsSimple "literal" $ text (escapeStringForXML str)
-inlineToDocbook opts (Math _ str) = inlinesToDocbook opts $ readTeXMath str
-inlineToDocbook _ (TeX _) = empty
-inlineToDocbook _ (HtmlInline _) = empty
-inlineToDocbook _ LineBreak = text $ "<literallayout></literallayout>"
-inlineToDocbook _ Space = char ' '
-inlineToDocbook opts (Link txt (src, _)) =
- if isPrefixOf "mailto:" src
- then let src' = drop 7 src
- emailLink = inTagsSimple "email" $ text $
- escapeStringForXML $ src'
- in if txt == [Code src']
- then emailLink
- else inlinesToDocbook opts txt <+> char '(' <> emailLink <>
- char ')'
- else inTags False "ulink" [("url", src)] $ inlinesToDocbook opts txt
-inlineToDocbook _ (Image _ (src, tit)) =
- let titleDoc = if null tit
- then empty
- else inTagsIndented "objectinfo" $
- inTagsIndented "title" (text $ escapeStringForXML tit)
- in inTagsIndented "inlinemediaobject" $ inTagsIndented "imageobject" $
- titleDoc $$ selfClosingTag "imagedata" [("fileref", src)]
-inlineToDocbook opts (Note contents) =
- inTagsIndented "footnote" $ blocksToDocbook opts contents
diff --git a/Text/Pandoc/Writers/HTML.hs b/Text/Pandoc/Writers/HTML.hs
deleted file mode 100644
index fb7320e92..000000000
--- a/Text/Pandoc/Writers/HTML.hs
+++ /dev/null
@@ -1,557 +0,0 @@
-{-# OPTIONS_GHC -fno-warn-deprecations #-}
-{-
-Copyright (C) 2006-8 John MacFarlane <jgm@berkeley.edu>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.HTML
- Copyright : Copyright (C) 2006-8 John MacFarlane
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Conversion of 'Pandoc' documents to HTML.
--}
-module Text.Pandoc.Writers.HTML ( writeHtml , writeHtmlString ) where
-import Text.Pandoc.Definition
-import Text.Pandoc.LaTeXMathML
-import Text.Pandoc.CharacterReferences ( decodeCharacterReferences )
-import Text.Pandoc.Shared
-import Text.Pandoc.Readers.TeXMath
-import Text.Pandoc.Highlighting ( highlightHtml, defaultHighlightingCss )
-import Numeric ( showHex )
-import Data.Char ( ord, toLower, isAlpha )
-import Data.List ( isPrefixOf, intercalate )
-import qualified Data.Set as S
-import Control.Monad.State
-import Text.XHtml.Transitional hiding ( stringToHtml )
-
-data WriterState = WriterState
- { stNotes :: [Html] -- ^ List of notes
- , stIds :: [String] -- ^ List of header identifiers
- , stMath :: Bool -- ^ Math is used in document
- , stCSS :: S.Set String -- ^ CSS to include in header
- } deriving Show
-
-defaultWriterState :: WriterState
-defaultWriterState = WriterState {stNotes= [], stIds = [],
- stMath = False, stCSS = S.empty}
-
--- Helpers to render HTML with the appropriate function.
-
-render :: (HTML html) => WriterOptions -> html -> String
-render opts = if writerWrapText opts then renderHtml else showHtml
-
-renderFragment :: (HTML html) => WriterOptions -> html -> String
-renderFragment opts = if writerWrapText opts
- then renderHtmlFragment
- else showHtmlFragment
-
--- | Slightly modified version of Text.XHtml's stringToHtml.
--- Only uses numerical entities for 0xff and greater.
--- Adds &nbsp;.
-stringToHtml :: String -> Html
-stringToHtml = primHtml . concatMap fixChar
- where
- fixChar '<' = "&lt;"
- fixChar '>' = "&gt;"
- fixChar '&' = "&amp;"
- fixChar '"' = "&quot;"
- fixChar '\160' = "&nbsp;"
- fixChar c | ord c < 0xff = [c]
- fixChar c = "&#" ++ show (ord c) ++ ";"
-
--- | Convert Pandoc document to Html string.
-writeHtmlString :: WriterOptions -> Pandoc -> String
-writeHtmlString opts =
- if writerStandalone opts
- then render opts . writeHtml opts
- else renderFragment opts . writeHtml opts
-
--- | Convert Pandoc document to Html structure.
-writeHtml :: WriterOptions -> Pandoc -> Html
-writeHtml opts (Pandoc (Meta tit authors date) blocks) =
- let titlePrefix = writerTitlePrefix opts
- topTitle = evalState (inlineListToHtml opts tit) defaultWriterState
- topTitle' = if null titlePrefix
- then topTitle
- else if null tit
- then stringToHtml titlePrefix
- else titlePrefix +++ " - " +++ topTitle
- metadata = thetitle topTitle' +++
- meta ! [httpequiv "Content-Type",
- content "text/html; charset=UTF-8"] +++
- meta ! [name "generator", content "pandoc"] +++
- (toHtmlFromList $
- map (\a -> meta ! [name "author", content a]) authors) +++
- (if null date
- then noHtml
- else meta ! [name "date", content date])
- titleHeader = if writerStandalone opts && not (null tit) &&
- not (writerS5 opts)
- then h1 ! [theclass "title"] $ topTitle
- else noHtml
- headerBlocks = filter isHeaderBlock blocks
- ids = uniqueIdentifiers $
- map (\(Header _ lst) -> lst) headerBlocks
- toc = if writerTableOfContents opts
- then tableOfContents opts headerBlocks ids
- else noHtml
- (blocks', newstate) =
- runState (blockListToHtml opts blocks)
- (defaultWriterState {stIds = ids})
- cssLines = stCSS newstate
- css = if S.null cssLines
- then noHtml
- else style ! [thetype "text/css"] $ primHtml $
- '\n':(unlines $ S.toList cssLines)
- math = if stMath newstate
- then case writerHTMLMathMethod opts of
- LaTeXMathML Nothing ->
- primHtml latexMathMLScript
- LaTeXMathML (Just url) ->
- script !
- [src url, thetype "text/javascript"] $
- noHtml
- JsMath (Just url) ->
- script !
- [src url, thetype "text/javascript"] $
- noHtml
- _ -> noHtml
- else noHtml
- head' = header $ metadata +++ math +++ css +++
- primHtml (writerHeader opts)
- notes = reverse (stNotes newstate)
- before = primHtml $ writerIncludeBefore opts
- after = primHtml $ writerIncludeAfter opts
- thebody = before +++ titleHeader +++ toc +++ blocks' +++
- footnoteSection notes +++ after
- in if writerStandalone opts
- then head' +++ body thebody
- else thebody
-
--- | Construct table of contents from list of header blocks and identifiers.
--- Assumes there are as many identifiers as header blocks.
-tableOfContents :: WriterOptions -> [Block] -> [String] -> Html
-tableOfContents _ [] _ = noHtml
-tableOfContents opts headers ids =
- let opts' = opts { writerIgnoreNotes = True }
- contentsTree = hierarchicalize headers
- contents = evalState (mapM (elementToListItem opts') contentsTree)
- (defaultWriterState {stIds = ids})
- in thediv ! [identifier "toc"] $ unordList contents
-
--- | Converts an Element to a list item for a table of contents,
--- retrieving the appropriate identifier from state.
-elementToListItem :: WriterOptions -> Element -> State WriterState Html
-elementToListItem _ (Blk _) = return noHtml
-elementToListItem opts (Sec headerText subsecs) = do
- st <- get
- let ids = stIds st
- let (id', rest) = if null ids
- then ("", [])
- else (head ids, tail ids)
- put $ st {stIds = rest}
- txt <- inlineListToHtml opts headerText
- subHeads <- mapM (elementToListItem opts) subsecs
- let subList = if null subHeads
- then noHtml
- else unordList subHeads
- return $ (anchor ! [href ("#" ++ id'), identifier ("TOC-" ++ id')] $ txt) +++
- subList
-
--- | Convert list of Note blocks to a footnote <div>.
--- Assumes notes are sorted.
-footnoteSection :: [Html] -> Html
-footnoteSection notes =
- if null notes
- then noHtml
- else thediv ! [theclass "footnotes"] $ hr +++ (olist << notes)
-
-
--- | Parse a mailto link; return Just (name, domain) or Nothing.
-parseMailto :: String -> Maybe (String, String)
-parseMailto ('m':'a':'i':'l':'t':'o':':':addr) =
- let (name', rest) = span (/='@') addr
- domain = drop 1 rest
- in Just (name', domain)
-parseMailto _ = Nothing
-
--- | Obfuscate a "mailto:" link.
-obfuscateLink :: WriterOptions -> String -> String -> Html
-obfuscateLink opts txt s | writerEmailObfuscation opts == NoObfuscation =
- anchor ! [href s] << txt
-obfuscateLink opts txt s =
- let meth = writerEmailObfuscation opts
- s' = map toLower s
- in case parseMailto s' of
- (Just (name', domain)) ->
- let domain' = substitute "." " dot " domain
- at' = obfuscateChar '@'
- (linkText, altText) =
- if txt == drop 7 s' -- autolink
- then ("'<code>'+e+'</code>'", name' ++ " at " ++ domain')
- else ("'" ++ txt ++ "'", txt ++ " (" ++ name' ++ " at " ++
- domain' ++ ")")
- in case meth of
- ReferenceObfuscation ->
- -- need to use primHtml or &'s are escaped to &amp; in URL
- primHtml $ "<a href=\"" ++ (obfuscateString s')
- ++ "\">" ++ (obfuscateString txt) ++ "</a>"
- JavascriptObfuscation ->
- (script ! [thetype "text/javascript"] $
- primHtml ("\n<!--\nh='" ++
- obfuscateString domain ++ "';a='" ++ at' ++ "';n='" ++
- obfuscateString name' ++ "';e=n+a+h;\n" ++
- "document.write('<a h'+'ref'+'=\"ma'+'ilto'+':'+e+'\">'+" ++
- linkText ++ "+'<\\/'+'a'+'>');\n// -->\n")) +++
- noscript (primHtml $ obfuscateString altText)
- _ -> error $ "Unknown obfuscation method: " ++ show meth
- _ -> anchor ! [href s] $ primHtml txt -- malformed email
-
--- | Obfuscate character as entity.
-obfuscateChar :: Char -> String
-obfuscateChar char =
- let num = ord char
- numstr = if even num then show num else "x" ++ showHex num ""
- in "&#" ++ numstr ++ ";"
-
--- | Obfuscate string using entities.
-obfuscateString :: String -> String
-obfuscateString = concatMap obfuscateChar . decodeCharacterReferences
-
--- | True if character is a punctuation character (unicode).
-isPunctuation :: Char -> Bool
-isPunctuation c =
- let c' = ord c
- in if c `elem` "!\"'()*,-./:;<>?[\\]`{|}~" || c' >= 0x2000 && c' <= 0x206F ||
- c' >= 0xE000 && c' <= 0xE0FF
- then True
- else False
-
--- | Add CSS for document header.
-addToCSS :: String -> State WriterState ()
-addToCSS item = do
- st <- get
- let current = stCSS st
- put $ st {stCSS = S.insert item current}
-
--- | Convert Pandoc inline list to plain text identifier.
-inlineListToIdentifier :: [Inline] -> String
-inlineListToIdentifier = dropWhile (not . isAlpha) . inlineListToIdentifier'
-
-inlineListToIdentifier' :: [Inline] -> [Char]
-inlineListToIdentifier' [] = ""
-inlineListToIdentifier' (x:xs) =
- xAsText ++ inlineListToIdentifier' xs
- where xAsText = case x of
- Str s -> filter (\c -> c == '-' || not (isPunctuation c)) $
- intercalate "-" $ words $ map toLower s
- Emph lst -> inlineListToIdentifier' lst
- Strikeout lst -> inlineListToIdentifier' lst
- Superscript lst -> inlineListToIdentifier' lst
- SmallCaps lst -> inlineListToIdentifier' lst
- Subscript lst -> inlineListToIdentifier' lst
- Strong lst -> inlineListToIdentifier' lst
- Quoted _ lst -> inlineListToIdentifier' lst
- Cite _ lst -> inlineListToIdentifier' lst
- Code s -> s
- Space -> "-"
- EmDash -> "-"
- EnDash -> "-"
- Apostrophe -> ""
- Ellipses -> ""
- LineBreak -> "-"
- Math _ _ -> ""
- TeX _ -> ""
- HtmlInline _ -> ""
- Link lst _ -> inlineListToIdentifier' lst
- Image lst _ -> inlineListToIdentifier' lst
- Note _ -> ""
-
--- | Return unique identifiers for list of inline lists.
-uniqueIdentifiers :: [[Inline]] -> [String]
-uniqueIdentifiers ls =
- let addIdentifier (nonuniqueIds, uniqueIds) l =
- let new = inlineListToIdentifier l
- matches = length $ filter (== new) nonuniqueIds
- new' = (if null new then "section" else new) ++
- if matches > 0 then ("-" ++ show matches) else ""
- in (new:nonuniqueIds, new':uniqueIds)
- in reverse $ snd $ foldl addIdentifier ([],[]) ls
-
--- | Convert Pandoc block element to HTML.
-blockToHtml :: WriterOptions -> Block -> State WriterState Html
-blockToHtml _ Null = return $ noHtml
-blockToHtml opts (Plain lst) = inlineListToHtml opts lst
-blockToHtml opts (Para lst) = inlineListToHtml opts lst >>= (return . paragraph)
-blockToHtml _ (RawHtml str) = return $ primHtml str
-blockToHtml _ (HorizontalRule) = return $ hr
-blockToHtml opts (CodeBlock (_,classes,_) rawCode) | "haskell" `elem` classes &&
- writerLiterateHaskell opts =
- let classes' = map (\c -> if c == "haskell" then "literatehaskell" else c) classes
- in blockToHtml opts $ CodeBlock ("",classes',[]) $ intercalate "\n" $ map ("> " ++) $ lines rawCode
-blockToHtml _ (CodeBlock attr@(_,classes,_) rawCode) = do
- case highlightHtml attr rawCode of
- Left _ -> -- change leading newlines into <br /> tags, because some
- -- browsers ignore leading newlines in pre blocks
- let (leadingBreaks, rawCode') = span (=='\n') rawCode
- in return $ pre ! (if null classes
- then []
- else [theclass $ unwords classes]) $ thecode <<
- (replicate (length leadingBreaks) br +++
- [stringToHtml $ rawCode' ++ "\n"])
- Right h -> addToCSS defaultHighlightingCss >> return h
-blockToHtml opts (BlockQuote blocks) =
- -- in S5, treat list in blockquote specially
- -- if default is incremental, make it nonincremental;
- -- otherwise incremental
- if writerS5 opts
- then let inc = not (writerIncremental opts) in
- case blocks of
- [BulletList lst] -> blockToHtml (opts {writerIncremental = inc})
- (BulletList lst)
- [OrderedList attribs lst] ->
- blockToHtml (opts {writerIncremental = inc})
- (OrderedList attribs lst)
- _ -> blockListToHtml opts blocks >>=
- (return . blockquote)
- else blockListToHtml opts blocks >>= (return . blockquote)
-blockToHtml opts (Header level lst) = do
- contents <- inlineListToHtml opts lst
- st <- get
- let ids = stIds st
- let (id', rest) = if null ids
- then ("", [])
- else (head ids, tail ids)
- put $ st {stIds = rest}
- let attribs = if writerStrictMarkdown opts && not (writerTableOfContents opts)
- then []
- else [identifier id']
- let contents' = if writerTableOfContents opts
- then anchor ! [href ("#TOC-" ++ id')] $ contents
- else contents
- return $ case level of
- 1 -> h1 contents' ! attribs
- 2 -> h2 contents' ! attribs
- 3 -> h3 contents' ! attribs
- 4 -> h4 contents' ! attribs
- 5 -> h5 contents' ! attribs
- 6 -> h6 contents' ! attribs
- _ -> paragraph contents' ! attribs
-blockToHtml opts (BulletList lst) = do
- contents <- mapM (blockListToHtml opts) lst
- let attribs = if writerIncremental opts
- then [theclass "incremental"]
- else []
- return $ unordList ! attribs $ contents
-blockToHtml opts (OrderedList (startnum, numstyle, _) lst) = do
- contents <- mapM (blockListToHtml opts) lst
- let numstyle' = camelCaseToHyphenated $ show numstyle
- let attribs = (if writerIncremental opts
- then [theclass "incremental"]
- else []) ++
- (if startnum /= 1
- then [start startnum]
- else []) ++
- (if numstyle /= DefaultStyle
- then [thestyle $ "list-style-type: " ++ numstyle' ++ ";"]
- else [])
- return $ ordList ! attribs $ contents
-blockToHtml opts (DefinitionList lst) = do
- contents <- mapM (\(term, def) -> do term' <- inlineListToHtml opts term
- def' <- blockListToHtml opts def
- return $ (term', def')) lst
- let attribs = if writerIncremental opts
- then [theclass "incremental"]
- else []
- return $ defList ! attribs $ contents
-blockToHtml opts (Table capt aligns widths headers rows') = do
- let alignStrings = map alignmentToString aligns
- captionDoc <- if null capt
- then return noHtml
- else inlineListToHtml opts capt >>= return . caption
- colHeads <- colHeadsToHtml opts alignStrings
- widths headers
- rows'' <- zipWithM (tableRowToHtml opts alignStrings) (cycle ["odd", "even"]) rows'
- return $ table $ captionDoc +++ colHeads +++ rows''
-
-colHeadsToHtml :: WriterOptions
- -> [[Char]]
- -> [Double]
- -> [[Block]]
- -> State WriterState Html
-colHeadsToHtml opts alignStrings widths headers = do
- heads <- sequence $ zipWith3
- (\alignment columnwidth item -> tableItemToHtml opts th alignment columnwidth item)
- alignStrings widths headers
- return $ tr ! [theclass "header"] $ toHtmlFromList heads
-
-alignmentToString :: Alignment -> [Char]
-alignmentToString alignment = case alignment of
- AlignLeft -> "left"
- AlignRight -> "right"
- AlignCenter -> "center"
- AlignDefault -> "left"
-
-tableRowToHtml :: WriterOptions
- -> [[Char]]
- -> String
- -> [[Block]]
- -> State WriterState Html
-tableRowToHtml opts aligns rowclass columns =
- (sequence $ zipWith3 (tableItemToHtml opts td) aligns (repeat 0) columns) >>=
- return . (tr ! [theclass rowclass]) . toHtmlFromList
-
-tableItemToHtml :: WriterOptions
- -> (Html -> Html)
- -> [Char]
- -> Double
- -> [Block]
- -> State WriterState Html
-tableItemToHtml opts tag' align' width' item = do
- contents <- blockListToHtml opts item
- let attrib = [align align'] ++
- if width' /= 0
- then [thestyle ("width: " ++ (show (truncate (100 * width') :: Integer)) ++ "%;")]
- else []
- return $ tag' ! attrib $ contents
-
-blockListToHtml :: WriterOptions -> [Block] -> State WriterState Html
-blockListToHtml opts lst =
- mapM (blockToHtml opts) lst >>= return . toHtmlFromList
-
--- | Convert list of Pandoc inline elements to HTML.
-inlineListToHtml :: WriterOptions -> [Inline] -> State WriterState Html
-inlineListToHtml opts lst =
- mapM (inlineToHtml opts) lst >>= return . toHtmlFromList
-
--- | Convert Pandoc inline element to HTML.
-inlineToHtml :: WriterOptions -> Inline -> State WriterState Html
-inlineToHtml opts inline =
- case inline of
- (Str str) -> return $ stringToHtml str
- (Space) -> return $ stringToHtml " "
- (LineBreak) -> return $ br
- (EmDash) -> return $ primHtmlChar "mdash"
- (EnDash) -> return $ primHtmlChar "ndash"
- (Ellipses) -> return $ primHtmlChar "hellip"
- (Apostrophe) -> return $ primHtmlChar "rsquo"
- (Emph lst) -> inlineListToHtml opts lst >>= return . emphasize
- (Strong lst) -> inlineListToHtml opts lst >>= return . strong
- (Code str) -> return $ thecode << str
- (Strikeout lst) -> inlineListToHtml opts lst >>=
- return . (thespan ! [thestyle "text-decoration: line-through;"])
- (SmallCaps lst) -> inlineListToHtml opts lst >>=
- return . (thespan ! [thestyle "font-variant: small-caps;"])
- (Superscript lst) -> inlineListToHtml opts lst >>= return . sup
- (Subscript lst) -> inlineListToHtml opts lst >>= return . sub
- (Quoted quoteType lst) ->
- let (leftQuote, rightQuote) = case quoteType of
- SingleQuote -> (primHtmlChar "lsquo",
- primHtmlChar "rsquo")
- DoubleQuote -> (primHtmlChar "ldquo",
- primHtmlChar "rdquo")
- in do contents <- inlineListToHtml opts lst
- return $ leftQuote +++ contents +++ rightQuote
- (Math t str) ->
- modify (\st -> st {stMath = True}) >>
- (case writerHTMLMathMethod opts of
- LaTeXMathML _ ->
- -- putting LaTeXMathML in container with class "LaTeX" prevents
- -- non-math elements on the page from being treated as math by
- -- the javascript
- return $ thespan ! [theclass "LaTeX"] $
- if t == InlineMath
- then primHtml ("$" ++ str ++ "$")
- else primHtml ("$$" ++ str ++ "$$")
- JsMath _ ->
- return $ if t == InlineMath
- then thespan ! [theclass "math"] $ primHtml str
- else thediv ! [theclass "math"] $ primHtml str
- MimeTeX url ->
- return $ image ! [src (url ++ "?" ++ str),
- alt str, title str]
- GladTeX ->
- return $ primHtml $ "<EQ>" ++ str ++ "</EQ>"
- PlainMath ->
- inlineListToHtml opts (readTeXMath str) >>=
- return . (thespan ! [theclass "math"]))
- (TeX str) -> case writerHTMLMathMethod opts of
- LaTeXMathML _ -> do modify (\st -> st {stMath = True})
- return $ primHtml str
- _ -> return noHtml
- (HtmlInline str) -> return $ primHtml str
- (Link [Code str] (s,_)) | "mailto:" `isPrefixOf` s ->
- return $ obfuscateLink opts str s
- (Link txt (s,_)) | "mailto:" `isPrefixOf` s -> do
- linkText <- inlineListToHtml opts txt
- return $ obfuscateLink opts (show linkText) s
- (Link txt (s,tit)) -> do
- linkText <- inlineListToHtml opts txt
- return $ anchor ! ([href s] ++
- if null tit then [] else [title tit]) $
- linkText
- (Image txt (s,tit)) -> do
- alternate <- inlineListToHtml opts txt
- let alternate' = renderFragment opts alternate
- let attributes = [src s] ++
- (if null tit
- then []
- else [title tit]) ++
- if null txt
- then []
- else [alt alternate']
- return $ image ! attributes
- -- note: null title included, as in Markdown.pl
- (Note contents) -> do
- st <- get
- let notes = stNotes st
- let number = (length notes) + 1
- let ref = show number
- htmlContents <- blockListToNote opts ref contents
- -- push contents onto front of notes
- put $ st {stNotes = (htmlContents:notes)}
- return $ anchor ! [href ("#fn" ++ ref),
- theclass "footnoteRef",
- identifier ("fnref" ++ ref)] <<
- sup << ref
- (Cite _ il) -> inlineListToHtml opts il
-
-blockListToNote :: WriterOptions -> String -> [Block] -> State WriterState Html
-blockListToNote opts ref blocks =
- -- If last block is Para or Plain, include the backlink at the end of
- -- that block. Otherwise, insert a new Plain block with the backlink.
- let backlink = [HtmlInline $ " <a href=\"#fnref" ++ ref ++
- "\" class=\"footnoteBackLink\"" ++
- " title=\"Jump back to footnote " ++ ref ++ "\">&#8617;</a>"]
- blocks' = if null blocks
- then []
- else let lastBlock = last blocks
- otherBlocks = init blocks
- in case lastBlock of
- (Para lst) -> otherBlocks ++
- [Para (lst ++ backlink)]
- (Plain lst) -> otherBlocks ++
- [Plain (lst ++ backlink)]
- _ -> otherBlocks ++ [lastBlock,
- Plain backlink]
- in do contents <- blockListToHtml opts blocks'
- return $ li ! [identifier ("fn" ++ ref)] $ contents
-
diff --git a/Text/Pandoc/Writers/LaTeX.hs b/Text/Pandoc/Writers/LaTeX.hs
deleted file mode 100644
index f3cbf1acb..000000000
--- a/Text/Pandoc/Writers/LaTeX.hs
+++ /dev/null
@@ -1,331 +0,0 @@
-{-
-Copyright (C) 2006-8 John MacFarlane <jgm@berkeley.edu>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.LaTeX
- Copyright : Copyright (C) 2006-8 John MacFarlane
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Conversion of 'Pandoc' format into LaTeX.
--}
-module Text.Pandoc.Writers.LaTeX ( writeLaTeX ) where
-import Text.Pandoc.Definition
-import Text.Pandoc.Shared
-import Text.Printf ( printf )
-import Data.List ( (\\), isSuffixOf, intercalate )
-import Data.Char ( toLower )
-import qualified Data.Set as S
-import Control.Monad.State
-import Text.PrettyPrint.HughesPJ hiding ( Str )
-
-data WriterState =
- WriterState { stIncludes :: S.Set String -- strings to include in header
- , stInNote :: Bool -- @True@ if we're in a note
- , stOLLevel :: Int -- level of ordered list nesting
- , stOptions :: WriterOptions -- writer options, so they don't have to be parameter
- }
-
--- | Add line to header.
-addToHeader :: String -> State WriterState ()
-addToHeader str = do
- st <- get
- let includes = stIncludes st
- put st {stIncludes = S.insert str includes}
-
--- | Convert Pandoc to LaTeX.
-writeLaTeX :: WriterOptions -> Pandoc -> String
-writeLaTeX options document =
- render $ evalState (pandocToLaTeX options document) $
- WriterState { stIncludes = S.empty, stInNote = False, stOLLevel = 1, stOptions = options }
-
-pandocToLaTeX :: WriterOptions -> Pandoc -> State WriterState Doc
-pandocToLaTeX options (Pandoc meta blocks) = do
- main <- blockListToLaTeX blocks
- head' <- if writerStandalone options
- then latexHeader options meta
- else return empty
- let before = if null (writerIncludeBefore options)
- then empty
- else text (writerIncludeBefore options)
- let after = if null (writerIncludeAfter options)
- then empty
- else text (writerIncludeAfter options)
- let body = before $$ main $$ after
- let toc = if writerTableOfContents options
- then text "\\tableofcontents\n"
- else empty
- let foot = if writerStandalone options
- then text "\\end{document}"
- else empty
- return $ head' $$ toc $$ body $$ foot
-
--- | Insert bibliographic information into LaTeX header.
-latexHeader :: WriterOptions -- ^ Options, including LaTeX header
- -> Meta -- ^ Meta with bibliographic information
- -> State WriterState Doc
-latexHeader options (Meta title authors date) = do
- titletext <- if null title
- then return empty
- else inlineListToLaTeX title >>= return . inCmd "title"
- headerIncludes <- get >>= return . S.toList . stIncludes
- let extras = text $ unlines headerIncludes
- let verbatim = if "\\usepackage{fancyvrb}" `elem` headerIncludes
- then text "\\VerbatimFootnotes % allows verbatim text in footnotes"
- else empty
- let authorstext = text $ "\\author{" ++
- intercalate "\\\\" (map stringToLaTeX authors) ++ "}"
- let datetext = if date == ""
- then empty
- else text $ "\\date{" ++ stringToLaTeX date ++ "}"
- let maketitle = if null title then empty else text "\\maketitle"
- let secnumline = if (writerNumberSections options)
- then empty
- else text "\\setcounter{secnumdepth}{0}"
- let baseHeader = text $ writerHeader options
- let header = baseHeader $$ extras
- return $ header $$ secnumline $$ verbatim $$ titletext $$ authorstext $$
- datetext $$ text "\\begin{document}" $$ maketitle $$ text ""
-
--- escape things as needed for LaTeX
-
-stringToLaTeX :: String -> String
-stringToLaTeX = escapeStringUsing latexEscapes
- where latexEscapes = backslashEscapes "{}$%&_#" ++
- [ ('^', "\\^{}")
- , ('\\', "\\textbackslash{}")
- , ('~', "\\ensuremath{\\sim}")
- , ('|', "\\textbar{}")
- , ('<', "\\textless{}")
- , ('>', "\\textgreater{}")
- , ('\160', "~")
- ]
-
--- | Puts contents into LaTeX command.
-inCmd :: String -> Doc -> Doc
-inCmd cmd contents = char '\\' <> text cmd <> braces contents
-
--- | Remove all code elements from list of inline elements
--- (because it's illegal to have verbatim inside some command arguments)
-deVerb :: [Inline] -> [Inline]
-deVerb [] = []
-deVerb ((Code str):rest) =
- (TeX $ "\\texttt{" ++ stringToLaTeX str ++ "}"):(deVerb rest)
-deVerb (other:rest) = other:(deVerb rest)
-
--- | Convert Pandoc block element to LaTeX.
-blockToLaTeX :: Block -- ^ Block to convert
- -> State WriterState Doc
-blockToLaTeX Null = return empty
-blockToLaTeX (Plain lst) = do
- st <- get
- let opts = stOptions st
- wrapTeXIfNeeded opts True inlineListToLaTeX lst
-blockToLaTeX (Para lst) = do
- st <- get
- let opts = stOptions st
- result <- wrapTeXIfNeeded opts True inlineListToLaTeX lst
- return $ result <> char '\n'
-blockToLaTeX (BlockQuote lst) = do
- contents <- blockListToLaTeX lst
- return $ text "\\begin{quote}" $$ contents $$ text "\\end{quote}"
-blockToLaTeX (CodeBlock (_,classes,_) str) = do
- st <- get
- env <- if writerLiterateHaskell (stOptions st) && "haskell" `elem` classes
- then return "code"
- else if stInNote st
- then do addToHeader "\\usepackage{fancyvrb}"
- return "Verbatim"
- else return "verbatim"
- return $ text ("\\begin{" ++ env ++ "}\n") <> text str <>
- text ("\n\\end{" ++ env ++ "}")
-blockToLaTeX (RawHtml _) = return empty
-blockToLaTeX (BulletList lst) = do
- items <- mapM listItemToLaTeX lst
- return $ text "\\begin{itemize}" $$ vcat items $$ text "\\end{itemize}"
-blockToLaTeX (OrderedList (start, numstyle, numdelim) lst) = do
- st <- get
- let oldlevel = stOLLevel st
- put $ st {stOLLevel = oldlevel + 1}
- items <- mapM listItemToLaTeX lst
- modify (\s -> s {stOLLevel = oldlevel})
- exemplar <- if numstyle /= DefaultStyle || numdelim /= DefaultDelim
- then do addToHeader "\\usepackage{enumerate}"
- return $ char '[' <>
- text (head (orderedListMarkers (1, numstyle,
- numdelim))) <> char ']'
- else return empty
- let resetcounter = if start /= 1 && oldlevel <= 4
- then text $ "\\setcounter{enum" ++
- map toLower (toRomanNumeral oldlevel) ++
- "}{" ++ show (start - 1) ++ "}"
- else empty
- return $ text "\\begin{enumerate}" <> exemplar $$ resetcounter $$
- vcat items $$ text "\\end{enumerate}"
-blockToLaTeX (DefinitionList lst) = do
- items <- mapM defListItemToLaTeX lst
- return $ text "\\begin{description}" $$ vcat items $$
- text "\\end{description}"
-blockToLaTeX HorizontalRule = return $ text $
- "\\begin{center}\\rule{3in}{0.4pt}\\end{center}\n"
-blockToLaTeX (Header level lst) = do
- txt <- inlineListToLaTeX (deVerb lst)
- return $ if (level > 0) && (level <= 3)
- then text ("\\" ++ (concat (replicate (level - 1) "sub")) ++
- "section{") <> txt <> text "}\n"
- else txt <> char '\n'
-blockToLaTeX (Table caption aligns widths heads rows) = do
- headers <- tableRowToLaTeX heads
- captionText <- inlineListToLaTeX caption
- rows' <- mapM tableRowToLaTeX rows
- let colWidths = map (printf "%.2f") widths
- let colDescriptors = concat $ zipWith
- (\width align -> ">{\\PBS" ++
- (case align of
- AlignLeft -> "\\raggedright"
- AlignRight -> "\\raggedleft"
- AlignCenter -> "\\centering"
- AlignDefault -> "\\raggedright") ++
- "\\hspace{0pt}}p{" ++ width ++
- "\\columnwidth}")
- colWidths aligns
- let tableBody = text ("\\begin{tabular}{" ++ colDescriptors ++ "}") $$
- headers $$ text "\\hline" $$ vcat rows' $$
- text "\\end{tabular}"
- let centered txt = text "\\begin{center}" $$ txt $$ text "\\end{center}"
- addToHeader $ "\\usepackage{array}\n" ++
- "% This is needed because raggedright in table elements redefines \\\\:\n" ++
- "\\newcommand{\\PreserveBackslash}[1]{\\let\\temp=\\\\#1\\let\\\\=\\temp}\n" ++
- "\\let\\PBS=\\PreserveBackslash"
- return $ if isEmpty captionText
- then centered tableBody <> char '\n'
- else text "\\begin{table}[h]" $$ centered tableBody $$
- inCmd "caption" captionText $$ text "\\end{table}\n"
-
-blockListToLaTeX :: [Block] -> State WriterState Doc
-blockListToLaTeX lst = mapM blockToLaTeX lst >>= return . vcat
-
-tableRowToLaTeX :: [[Block]] -> State WriterState Doc
-tableRowToLaTeX cols = mapM blockListToLaTeX cols >>=
- return . ($$ text "\\\\") . foldl (\row item -> row $$
- (if isEmpty row then text "" else text " & ") <> item) empty
-
-listItemToLaTeX :: [Block] -> State WriterState Doc
-listItemToLaTeX lst = blockListToLaTeX lst >>= return . (text "\\item" $$) .
- (nest 2)
-
-defListItemToLaTeX :: ([Inline], [Block]) -> State WriterState Doc
-defListItemToLaTeX (term, def) = do
- term' <- inlineListToLaTeX $ deVerb term
- def' <- blockListToLaTeX def
- return $ text "\\item[" <> term' <> text "]" $$ def'
-
--- | Convert list of inline elements to LaTeX.
-inlineListToLaTeX :: [Inline] -- ^ Inlines to convert
- -> State WriterState Doc
-inlineListToLaTeX lst = mapM inlineToLaTeX lst >>= return . hcat
-
-isQuoted :: Inline -> Bool
-isQuoted (Quoted _ _) = True
-isQuoted Apostrophe = True
-isQuoted _ = False
-
--- | Convert inline element to LaTeX
-inlineToLaTeX :: Inline -- ^ Inline to convert
- -> State WriterState Doc
-inlineToLaTeX (Emph lst) =
- inlineListToLaTeX (deVerb lst) >>= return . inCmd "emph"
-inlineToLaTeX (Strong lst) =
- inlineListToLaTeX (deVerb lst) >>= return . inCmd "textbf"
-inlineToLaTeX (Strikeout lst) = do
- contents <- inlineListToLaTeX $ deVerb lst
- addToHeader "\\usepackage[normalem]{ulem}"
- return $ inCmd "sout" contents
-inlineToLaTeX (Superscript lst) =
- inlineListToLaTeX (deVerb lst) >>= return . inCmd "textsuperscript"
-inlineToLaTeX (Subscript lst) = do
- contents <- inlineListToLaTeX $ deVerb lst
- -- oddly, latex includes \textsuperscript but not \textsubscript
- -- so we have to define it (using a different name so as not to conflict with memoir class):
- addToHeader "\\newcommand{\\textsubscr}[1]{\\ensuremath{_{\\scriptsize\\textrm{#1}}}}"
- return $ inCmd "textsubscr" contents
-inlineToLaTeX (SmallCaps lst) =
- inlineListToLaTeX (deVerb lst) >>= return . inCmd "textsc"
-inlineToLaTeX (Cite _ lst) =
- inlineListToLaTeX lst
-inlineToLaTeX (Code str) = do
- st <- get
- if stInNote st
- then do addToHeader "\\usepackage{fancyvrb}"
- else return ()
- let chr = ((enumFromTo '!' '~') \\ str) !! 0
- return $ text $ "\\verb" ++ [chr] ++ str ++ [chr]
-inlineToLaTeX (Quoted SingleQuote lst) = do
- contents <- inlineListToLaTeX lst
- let s1 = if (not (null lst)) && (isQuoted (head lst))
- then text "\\,"
- else empty
- let s2 = if (not (null lst)) && (isQuoted (last lst))
- then text "\\,"
- else empty
- return $ char '`' <> s1 <> contents <> s2 <> char '\''
-inlineToLaTeX (Quoted DoubleQuote lst) = do
- contents <- inlineListToLaTeX lst
- let s1 = if (not (null lst)) && (isQuoted (head lst))
- then text "\\,"
- else empty
- let s2 = if (not (null lst)) && (isQuoted (last lst))
- then text "\\,"
- else empty
- return $ text "``" <> s1 <> contents <> s2 <> text "''"
-inlineToLaTeX Apostrophe = return $ char '\''
-inlineToLaTeX EmDash = return $ text "---"
-inlineToLaTeX EnDash = return $ text "--"
-inlineToLaTeX Ellipses = return $ text "\\ldots{}"
-inlineToLaTeX (Str str) = return $ text $ stringToLaTeX str
-inlineToLaTeX (Math InlineMath str) = return $ char '$' <> text str <> char '$'
-inlineToLaTeX (Math DisplayMath str) = return $ text "\\[" <> text str <> text "\\]"
-inlineToLaTeX (TeX str) = return $ text str
-inlineToLaTeX (HtmlInline _) = return empty
-inlineToLaTeX (LineBreak) = return $ text "\\\\"
-inlineToLaTeX Space = return $ char ' '
-inlineToLaTeX (Link txt (src, _)) = do
- addToHeader "\\usepackage[breaklinks=true]{hyperref}"
- case txt of
- [Code x] | x == src -> -- autolink
- do addToHeader "\\usepackage{url}"
- return $ text $ "\\url{" ++ x ++ "}"
- _ -> do contents <- inlineListToLaTeX $ deVerb txt
- return $ text ("\\href{" ++ src ++ "}{") <> contents <>
- char '}'
-inlineToLaTeX (Image _ (source, _)) = do
- addToHeader "\\usepackage{graphicx}"
- return $ text $ "\\includegraphics{" ++ source ++ "}"
-inlineToLaTeX (Note contents) = do
- st <- get
- put (st {stInNote = True})
- contents' <- blockListToLaTeX contents
- modify (\s -> s {stInNote = False})
- let rawnote = stripTrailingNewlines $ render contents'
- -- note: a \n before } is needed when note ends with a Verbatim environment
- let optNewline = "\\end{Verbatim}" `isSuffixOf` rawnote
- return $ text "\\footnote{" <>
- text rawnote <> (if optNewline then char '\n' else empty) <> char '}'
diff --git a/Text/Pandoc/Writers/Man.hs b/Text/Pandoc/Writers/Man.hs
deleted file mode 100644
index 210c7ed07..000000000
--- a/Text/Pandoc/Writers/Man.hs
+++ /dev/null
@@ -1,301 +0,0 @@
-{-
-Copyright (C) 2007 John MacFarlane <jgm@berkeley.edu>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.Man
- Copyright : Copyright (C) 2007 John MacFarlane
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Conversion of 'Pandoc' documents to groff man page format.
-
--}
-module Text.Pandoc.Writers.Man ( writeMan) where
-import Text.Pandoc.Definition
-import Text.Pandoc.Shared
-import Text.Printf ( printf )
-import Data.List ( isPrefixOf, drop, nub, intersperse, intercalate )
-import Text.PrettyPrint.HughesPJ hiding ( Str )
-import Control.Monad.State
-
-type Notes = [[Block]]
-type Preprocessors = [String] -- e.g. "t" for tbl
-type WriterState = (Notes, Preprocessors)
-
--- | Convert Pandoc to Man.
-writeMan :: WriterOptions -> Pandoc -> String
-writeMan opts document = render $ evalState (pandocToMan opts document) ([],[])
-
--- | Return groff man representation of document.
-pandocToMan :: WriterOptions -> Pandoc -> State WriterState Doc
-pandocToMan opts (Pandoc meta blocks) = do
- let before = writerIncludeBefore opts
- let after = writerIncludeAfter opts
- let before' = if null before then empty else text before
- let after' = if null after then empty else text after
- (head', foot) <- metaToMan opts meta
- body <- blockListToMan opts blocks
- (notes, preprocessors) <- get
- let preamble = if null preprocessors || not (writerStandalone opts)
- then empty
- else text $ ".\\\" " ++ concat (nub preprocessors)
- notes' <- notesToMan opts (reverse notes)
- return $ preamble $$ head' $$ before' $$ body $$ notes' $$ foot $$ after'
-
--- | Insert bibliographic information into Man header and footer.
-metaToMan :: WriterOptions -- ^ Options, including Man header
- -> Meta -- ^ Meta with bibliographic information
- -> State WriterState (Doc, Doc)
-metaToMan options (Meta title authors date) = do
- titleText <- inlineListToMan options title
- let (cmdName, rest) = break (== ' ') $ render titleText
- let (title', section) = case reverse cmdName of
- (')':d:'(':xs) | d `elem` ['0'..'9'] ->
- (text (reverse xs), char d)
- xs -> (text (reverse xs), doubleQuotes empty)
- let extras = map (doubleQuotes . text . removeLeadingTrailingSpace) $
- splitBy '|' rest
- let head' = (text ".TH") <+> title' <+> section <+>
- doubleQuotes (text date) <+> hsep extras
- let foot = case length authors of
- 0 -> empty
- 1 -> text ".SH AUTHOR" $$ (text $ intercalate ", " authors)
- _ -> text ".SH AUTHORS" $$ (text $ intercalate ", " authors)
- return $ if writerStandalone options
- then (head', foot)
- else (empty, empty)
-
--- | Return man representation of notes.
-notesToMan :: WriterOptions -> [[Block]] -> State WriterState Doc
-notesToMan opts notes =
- if null notes
- then return empty
- else mapM (\(num, note) -> noteToMan opts num note) (zip [1..] notes) >>=
- return . (text ".SH NOTES" $$) . vcat
-
--- | Return man representation of a note.
-noteToMan :: WriterOptions -> Int -> [Block] -> State WriterState Doc
-noteToMan opts num note = do
- contents <- blockListToMan opts note
- let marker = text "\n.SS [" <> text (show num) <> char ']'
- return $ marker $$ contents
-
--- | Association list of characters to escape.
-manEscapes :: [(Char, String)]
-manEscapes = [('\160', "\\ "), ('\'', "\\[aq]")] ++ backslashEscapes ".@\\"
-
--- | Escape special characters for Man.
-escapeString :: String -> String
-escapeString = escapeStringUsing manEscapes
-
--- | Escape a literal (code) section for Man.
-escapeCode :: String -> String
-escapeCode = escapeStringUsing (manEscapes ++ backslashEscapes "\t ")
-
--- | Convert Pandoc block element to man.
-blockToMan :: WriterOptions -- ^ Options
- -> Block -- ^ Block element
- -> State WriterState Doc
-blockToMan _ Null = return empty
-blockToMan opts (Plain inlines) =
- wrapIfNeeded opts (inlineListToMan opts) inlines
-blockToMan opts (Para inlines) = do
- contents <- wrapIfNeeded opts (inlineListToMan opts) inlines
- return $ text ".PP" $$ contents
-blockToMan _ (RawHtml str) = return $ text str
-blockToMan _ HorizontalRule = return $ text $ ".PP\n * * * * *"
-blockToMan opts (Header level inlines) = do
- contents <- inlineListToMan opts inlines
- let heading = case level of
- 1 -> ".SH "
- _ -> ".SS "
- return $ text heading <> contents
-blockToMan _ (CodeBlock _ str) = return $
- text ".PP" $$ text "\\f[CR]" $$
- text ((unlines . map (" " ++) . lines) (escapeCode str)) <> text "\\f[]"
-blockToMan opts (BlockQuote blocks) = do
- contents <- blockListToMan opts blocks
- return $ text ".RS" $$ contents $$ text ".RE"
-blockToMan opts (Table caption alignments widths headers rows) =
- let aligncode AlignLeft = "l"
- aligncode AlignRight = "r"
- aligncode AlignCenter = "c"
- aligncode AlignDefault = "l"
- in do
- caption' <- inlineListToMan opts caption
- modify (\(notes, preprocessors) -> (notes, "t":preprocessors))
- let iwidths = map (printf "w(%0.2fn)" . (70 *)) widths
- -- 78n default width - 8n indent = 70n
- let coldescriptions = text $ intercalate " "
- (zipWith (\align width -> aligncode align ++ width)
- alignments iwidths) ++ "."
- colheadings <- mapM (blockListToMan opts) headers
- let makeRow cols = text "T{" $$
- (vcat $ intersperse (text "T}@T{") cols) $$
- text "T}"
- let colheadings' = makeRow colheadings
- body <- mapM (\row -> do
- cols <- mapM (blockListToMan opts) row
- return $ makeRow cols) rows
- return $ text ".PP" $$ caption' $$
- text ".TS" $$ text "tab(@);" $$ coldescriptions $$
- colheadings' $$ char '_' $$ vcat body $$ text ".TE"
-
-blockToMan opts (BulletList items) = do
- contents <- mapM (bulletListItemToMan opts) items
- return (vcat contents)
-blockToMan opts (OrderedList attribs items) = do
- let markers = take (length items) $ orderedListMarkers attribs
- let indent = 1 + (maximum $ map length markers)
- contents <- mapM (\(num, item) -> orderedListItemToMan opts num indent item) $
- zip markers items
- return (vcat contents)
-blockToMan opts (DefinitionList items) = do
- contents <- mapM (definitionListItemToMan opts) items
- return (vcat contents)
-
--- | Convert bullet list item (list of blocks) to man.
-bulletListItemToMan :: WriterOptions -> [Block] -> State WriterState Doc
-bulletListItemToMan _ [] = return empty
-bulletListItemToMan opts ((Para first):rest) =
- bulletListItemToMan opts ((Plain first):rest)
-bulletListItemToMan opts ((Plain first):rest) = do
- first' <- blockToMan opts (Plain first)
- rest' <- blockListToMan opts rest
- let first'' = text ".IP \\[bu] 2" $$ first'
- let rest'' = if null rest
- then empty
- else text ".RS 2" $$ rest' $$ text ".RE"
- return (first'' $$ rest'')
-bulletListItemToMan opts (first:rest) = do
- first' <- blockToMan opts first
- rest' <- blockListToMan opts rest
- return $ text "\\[bu] .RS 2" $$ first' $$ rest' $$ text ".RE"
-
--- | Convert ordered list item (a list of blocks) to man.
-orderedListItemToMan :: WriterOptions -- ^ options
- -> String -- ^ order marker for list item
- -> Int -- ^ number of spaces to indent
- -> [Block] -- ^ list item (list of blocks)
- -> State WriterState Doc
-orderedListItemToMan _ _ _ [] = return empty
-orderedListItemToMan opts num indent ((Para first):rest) =
- orderedListItemToMan opts num indent ((Plain first):rest)
-orderedListItemToMan opts num indent (first:rest) = do
- first' <- blockToMan opts first
- rest' <- blockListToMan opts rest
- let num' = printf ("%" ++ show (indent - 1) ++ "s") num
- let first'' = text (".IP \"" ++ num' ++ "\" " ++ show indent) $$ first'
- let rest'' = if null rest
- then empty
- else text ".RS 4" $$ rest' $$ text ".RE"
- return $ first'' $$ rest''
-
--- | Convert definition list item (label, list of blocks) to man.
-definitionListItemToMan :: WriterOptions
- -> ([Inline],[Block])
- -> State WriterState Doc
-definitionListItemToMan opts (label, items) = do
- labelText <- inlineListToMan opts label
- contents <- if null items
- then return empty
- else do
- let (first, rest) = case items of
- ((Para x):y) -> (Plain x,y)
- (x:y) -> (x,y)
- [] -> error "items is null"
- rest' <- mapM (\item -> blockToMan opts item)
- rest >>= (return . vcat)
- first' <- blockToMan opts first
- return $ first' $$ text ".RS" $$ rest' $$ text ".RE"
- return $ text ".TP\n.B " <> labelText $+$ contents
-
--- | Convert list of Pandoc block elements to man.
-blockListToMan :: WriterOptions -- ^ Options
- -> [Block] -- ^ List of block elements
- -> State WriterState Doc
-blockListToMan opts blocks =
- mapM (blockToMan opts) blocks >>= (return . vcat)
-
--- | Convert list of Pandoc inline elements to man.
-inlineListToMan :: WriterOptions -> [Inline] -> State WriterState Doc
-inlineListToMan opts lst = mapM (inlineToMan opts) lst >>= (return . hcat)
-
--- | Convert Pandoc inline element to man.
-inlineToMan :: WriterOptions -> Inline -> State WriterState Doc
-inlineToMan opts (Emph lst) = do
- contents <- inlineListToMan opts lst
- return $ text "\\f[I]" <> contents <> text "\\f[]"
-inlineToMan opts (Strong lst) = do
- contents <- inlineListToMan opts lst
- return $ text "\\f[B]" <> contents <> text "\\f[]"
-inlineToMan opts (Strikeout lst) = do
- contents <- inlineListToMan opts lst
- return $ text "[STRIKEOUT:" <> contents <> char ']'
-inlineToMan opts (Superscript lst) = do
- contents <- inlineListToMan opts lst
- return $ char '^' <> contents <> char '^'
-inlineToMan opts (Subscript lst) = do
- contents <- inlineListToMan opts lst
- return $ char '~' <> contents <> char '~'
-inlineToMan opts (SmallCaps lst) = inlineListToMan opts lst -- not supported
-inlineToMan opts (Quoted SingleQuote lst) = do
- contents <- inlineListToMan opts lst
- return $ char '`' <> contents <> char '\''
-inlineToMan opts (Quoted DoubleQuote lst) = do
- contents <- inlineListToMan opts lst
- return $ text "\\[lq]" <> contents <> text "\\[rq]"
-inlineToMan opts (Cite _ lst) =
- inlineListToMan opts lst
-inlineToMan _ EmDash = return $ text "\\[em]"
-inlineToMan _ EnDash = return $ text "\\[en]"
-inlineToMan _ Apostrophe = return $ char '\''
-inlineToMan _ Ellipses = return $ text "\\&..."
-inlineToMan _ (Code str) =
- return $ text $ "\\f[B]" ++ escapeCode str ++ "\\f[]"
-inlineToMan _ (Str str) = return $ text $ escapeString str
-inlineToMan opts (Math InlineMath str) = inlineToMan opts (Code str)
-inlineToMan opts (Math DisplayMath str) = do
- contents <- inlineToMan opts (Code str)
- return $ text ".RS" $$ contents $$ text ".RE"
-inlineToMan _ (TeX _) = return empty
-inlineToMan _ (HtmlInline str) = return $ text $ escapeCode str
-inlineToMan _ (LineBreak) = return $ text "\n.PD 0\n.P\n.PD\n"
-inlineToMan _ Space = return $ char ' '
-inlineToMan opts (Link txt (src, _)) = do
- linktext <- inlineListToMan opts txt
- let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src
- return $ if txt == [Code srcSuffix]
- then char '<' <> text srcSuffix <> char '>'
- else linktext <> text " (" <> text src <> char ')'
-inlineToMan opts (Image alternate (source, tit)) = do
- let txt = if (null alternate) || (alternate == [Str ""]) ||
- (alternate == [Str source]) -- to prevent autolinks
- then [Str "image"]
- else alternate
- linkPart <- inlineToMan opts (Link txt (source, tit))
- return $ char '[' <> text "IMAGE: " <> linkPart <> char ']'
-inlineToMan _ (Note contents) = do
- modify (\(notes, prep) -> (contents:notes, prep)) -- add to notes in state
- (notes, _) <- get
- let ref = show $ (length notes)
- return $ char '[' <> text ref <> char ']'
-
diff --git a/Text/Pandoc/Writers/Markdown.hs b/Text/Pandoc/Writers/Markdown.hs
deleted file mode 100644
index 70d1f0c91..000000000
--- a/Text/Pandoc/Writers/Markdown.hs
+++ /dev/null
@@ -1,396 +0,0 @@
-{-
-Copyright (C) 2006-7 John MacFarlane <jgm@berkeley.edu>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.Markdown
- Copyright : Copyright (C) 2006-7 John MacFarlane
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Conversion of 'Pandoc' documents to markdown-formatted plain text.
-
-Markdown: <http://daringfireball.net/projects/markdown/>
--}
-module Text.Pandoc.Writers.Markdown ( writeMarkdown) where
-import Text.Pandoc.Definition
-import Text.Pandoc.Shared
-import Text.Pandoc.Blocks
-import Text.ParserCombinators.Parsec ( parse, GenParser )
-import Data.List ( group, isPrefixOf, drop, find, intersperse, intercalate )
-import Text.PrettyPrint.HughesPJ hiding ( Str )
-import Control.Monad.State
-
-type Notes = [[Block]]
-type Refs = KeyTable
-type WriterState = (Notes, Refs)
-
--- | Convert Pandoc to Markdown.
-writeMarkdown :: WriterOptions -> Pandoc -> String
-writeMarkdown opts document =
- render $ evalState (pandocToMarkdown opts document) ([],[])
-
--- | Return markdown representation of document.
-pandocToMarkdown :: WriterOptions -> Pandoc -> State WriterState Doc
-pandocToMarkdown opts (Pandoc meta blocks) = do
- let before = writerIncludeBefore opts
- let after = writerIncludeAfter opts
- let before' = if null before then empty else text before
- let after' = if null after then empty else text after
- metaBlock <- metaToMarkdown opts meta
- let head' = if writerStandalone opts
- then metaBlock $+$ text (writerHeader opts)
- else empty
- let headerBlocks = filter isHeaderBlock blocks
- let toc = if writerTableOfContents opts
- then tableOfContents opts headerBlocks
- else empty
- body <- blockListToMarkdown opts blocks
- (notes, _) <- get
- notes' <- notesToMarkdown opts (reverse notes)
- (_, refs) <- get -- note that the notes may contain refs
- refs' <- keyTableToMarkdown opts (reverse refs)
- return $ head' $+$ before' $+$ toc $+$ body $+$ text "" $+$
- notes' $+$ text "" $+$ refs' $+$ after'
-
--- | Return markdown representation of reference key table.
-keyTableToMarkdown :: WriterOptions -> KeyTable -> State WriterState Doc
-keyTableToMarkdown opts refs = mapM (keyToMarkdown opts) refs >>= return . vcat
-
--- | Return markdown representation of a reference key.
-keyToMarkdown :: WriterOptions
- -> ([Inline], (String, String))
- -> State WriterState Doc
-keyToMarkdown opts (label, (src, tit)) = do
- label' <- inlineListToMarkdown opts label
- let tit' = if null tit then empty else text $ " \"" ++ tit ++ "\""
- return $ text " " <> char '[' <> label' <> char ']' <> text ": " <>
- text src <> tit'
-
--- | Return markdown representation of notes.
-notesToMarkdown :: WriterOptions -> [[Block]] -> State WriterState Doc
-notesToMarkdown opts notes =
- mapM (\(num, note) -> noteToMarkdown opts num note) (zip [1..] notes) >>=
- return . vcat
-
--- | Return markdown representation of a note.
-noteToMarkdown :: WriterOptions -> Int -> [Block] -> State WriterState Doc
-noteToMarkdown opts num blocks = do
- contents <- blockListToMarkdown opts blocks
- let marker = text "[^" <> text (show num) <> text "]:"
- return $ hang' marker (writerTabStop opts) contents
-
--- | Escape special characters for Markdown.
-escapeString :: String -> String
-escapeString = escapeStringUsing markdownEscapes
- where markdownEscapes = backslashEscapes "`<\\*_^~"
-
--- | Convert bibliographic information into Markdown header.
-metaToMarkdown :: WriterOptions -> Meta -> State WriterState Doc
-metaToMarkdown opts (Meta title authors date) = do
- title' <- titleToMarkdown opts title
- authors' <- authorsToMarkdown authors
- date' <- dateToMarkdown date
- return $ title' $+$ authors' $+$ date'
-
-titleToMarkdown :: WriterOptions -> [Inline] -> State WriterState Doc
-titleToMarkdown _ [] = return empty
-titleToMarkdown opts lst = do
- contents <- inlineListToMarkdown opts lst
- return $ text "% " <> contents
-
-authorsToMarkdown :: [String] -> State WriterState Doc
-authorsToMarkdown [] = return empty
-authorsToMarkdown lst = return $
- text "% " <> text (intercalate ", " (map escapeString lst))
-
-dateToMarkdown :: String -> State WriterState Doc
-dateToMarkdown [] = return empty
-dateToMarkdown str = return $ text "% " <> text (escapeString str)
-
--- | Construct table of contents from list of header blocks.
-tableOfContents :: WriterOptions -> [Block] -> Doc
-tableOfContents opts headers =
- let opts' = opts { writerIgnoreNotes = True }
- contents = BulletList $ map elementToListItem $ hierarchicalize headers
- in evalState (blockToMarkdown opts' contents) ([],[])
-
--- | Converts an Element to a list item for a table of contents,
-elementToListItem :: Element -> [Block]
-elementToListItem (Blk _) = []
-elementToListItem (Sec headerText subsecs) = [Plain headerText] ++
- if null subsecs
- then []
- else [BulletList $ map elementToListItem subsecs]
-
--- | Ordered list start parser for use in Para below.
-olMarker :: GenParser Char st Char
-olMarker = do (start, style', delim) <- anyOrderedListMarker
- if delim == Period &&
- (style' == UpperAlpha || (style' == UpperRoman &&
- start `elem` [1, 5, 10, 50, 100, 500, 1000]))
- then spaceChar >> spaceChar
- else spaceChar
-
--- | True if string begins with an ordered list marker
-beginsWithOrderedListMarker :: String -> Bool
-beginsWithOrderedListMarker str =
- case parse olMarker "para start" str of
- Left _ -> False
- Right _ -> True
-
-wrappedMarkdown :: WriterOptions -> [Inline] -> State WriterState Doc
-wrappedMarkdown opts inlines = do
- let chunks = splitBy LineBreak inlines
- let chunks' = if null chunks
- then []
- else (map (++ [Str " "]) $ init chunks) ++ [last chunks]
- lns <- mapM (wrapIfNeeded opts (inlineListToMarkdown opts)) chunks'
- return $ vcat lns
-
--- | Convert Pandoc block element to markdown.
-blockToMarkdown :: WriterOptions -- ^ Options
- -> Block -- ^ Block element
- -> State WriterState Doc
-blockToMarkdown _ Null = return empty
-blockToMarkdown opts (Plain inlines) =
- wrappedMarkdown opts inlines
-blockToMarkdown opts (Para inlines) = do
- contents <- wrappedMarkdown opts inlines
- -- escape if para starts with ordered list marker
- let esc = if (not (writerStrictMarkdown opts)) &&
- beginsWithOrderedListMarker (render contents)
- then char '\\'
- else empty
- return $ esc <> contents <> text "\n"
-blockToMarkdown _ (RawHtml str) = return $ text str
-blockToMarkdown _ HorizontalRule = return $ text "\n* * * * *\n"
-blockToMarkdown opts (Header level inlines) = do
- contents <- inlineListToMarkdown opts inlines
- -- use setext style headers if in literate haskell mode.
- -- ghc interprets '#' characters in column 1 as line number specifiers.
- if writerLiterateHaskell opts
- then let len = length $ render contents
- in return $ contents <> text "\n" <>
- case level of
- 1 -> text $ replicate len '=' ++ "\n"
- 2 -> text $ replicate len '-' ++ "\n"
- _ -> empty
- else return $ text ((replicate level '#') ++ " ") <> contents <> text "\n"
-blockToMarkdown opts (CodeBlock (_,classes,_) str) | "haskell" `elem` classes &&
- writerLiterateHaskell opts =
- return $ (vcat $ map (text "> " <>) $ map text (lines str)) <> text "\n"
-blockToMarkdown opts (CodeBlock _ str) = return $
- (nest (writerTabStop opts) $ vcat $ map text (lines str)) <> text "\n"
-blockToMarkdown opts (BlockQuote blocks) = do
- -- if we're writing literate haskell, put a space before the bird tracks
- -- so they won't be interpreted as lhs...
- let leader = if writerLiterateHaskell opts
- then text . (" > " ++)
- else text . ("> " ++)
- contents <- blockListToMarkdown opts blocks
- return $ (vcat $ map leader $ lines $ render contents) <>
- text "\n"
-blockToMarkdown opts (Table caption aligns widths headers rows) = do
- caption' <- inlineListToMarkdown opts caption
- let caption'' = if null caption
- then empty
- else text "" $+$ (text "Table: " <> caption')
- headers' <- mapM (blockListToMarkdown opts) headers
- let widthsInChars = map (floor . (78 *)) widths
- let alignHeader alignment = case alignment of
- AlignLeft -> leftAlignBlock
- AlignCenter -> centerAlignBlock
- AlignRight -> rightAlignBlock
- AlignDefault -> leftAlignBlock
- let makeRow = hsepBlocks . (zipWith alignHeader aligns) .
- (zipWith docToBlock widthsInChars)
- let head' = makeRow headers'
- rows' <- mapM (\row -> do cols <- mapM (blockListToMarkdown opts) row
- return $ makeRow cols) rows
- let maxRowHeight = maximum $ map heightOfBlock (head':rows')
- let isMultilineTable = maxRowHeight > 1
- let underline = hsep $
- map (\width -> text $ replicate width '-') widthsInChars
- let border = if isMultilineTable
- then text $ replicate (sum widthsInChars + (length widthsInChars - 1)) '-'
- else empty
- let spacer = if isMultilineTable
- then text ""
- else empty
- let body = vcat $ intersperse spacer $ map blockToDoc rows'
- return $ (nest 2 $ border $+$ (blockToDoc head') $+$ underline $+$ body $+$
- border $+$ caption'') <> text "\n"
-blockToMarkdown opts (BulletList items) = do
- contents <- mapM (bulletListItemToMarkdown opts) items
- return $ (vcat contents) <> text "\n"
-blockToMarkdown opts (OrderedList attribs items) = do
- let markers = orderedListMarkers attribs
- let markers' = map (\m -> if length m < 3
- then m ++ replicate (3 - length m) ' '
- else m) markers
- contents <- mapM (\(item, num) -> orderedListItemToMarkdown opts item num) $
- zip markers' items
- return $ (vcat contents) <> text "\n"
-blockToMarkdown opts (DefinitionList items) = do
- contents <- mapM (definitionListItemToMarkdown opts) items
- return $ (vcat contents) <> text "\n"
-
--- | Convert bullet list item (list of blocks) to markdown.
-bulletListItemToMarkdown :: WriterOptions -> [Block] -> State WriterState Doc
-bulletListItemToMarkdown opts items = do
- contents <- blockListToMarkdown opts items
- return $ hang' (text "- ") (writerTabStop opts) contents
-
--- | Convert ordered list item (a list of blocks) to markdown.
-orderedListItemToMarkdown :: WriterOptions -- ^ options
- -> String -- ^ list item marker
- -> [Block] -- ^ list item (list of blocks)
- -> State WriterState Doc
-orderedListItemToMarkdown opts marker items = do
- contents <- blockListToMarkdown opts items
- return $ hsep [nest (min (3 - length marker) 0) (text marker),
- nest (writerTabStop opts) contents]
-
--- | Convert definition list item (label, list of blocks) to markdown.
-definitionListItemToMarkdown :: WriterOptions
- -> ([Inline],[Block])
- -> State WriterState Doc
-definitionListItemToMarkdown opts (label, items) = do
- labelText <- inlineListToMarkdown opts label
- let tabStop = writerTabStop opts
- let leader = char ':'
- contents <- mapM (\item -> blockToMarkdown opts item >>=
- (\txt -> return (leader $$ nest tabStop txt)))
- items >>= return . vcat
- return $ labelText $+$ contents
-
--- | Convert list of Pandoc block elements to markdown.
-blockListToMarkdown :: WriterOptions -- ^ Options
- -> [Block] -- ^ List of block elements
- -> State WriterState Doc
-blockListToMarkdown opts blocks =
- mapM (blockToMarkdown opts) blocks >>= return . vcat
-
--- | Get reference for target; if none exists, create unique one and return.
--- Prefer label if possible; otherwise, generate a unique key.
-getReference :: [Inline] -> Target -> State WriterState [Inline]
-getReference label (src, tit) = do
- (_,refs) <- get
- case find ((== (src, tit)) . snd) refs of
- Just (ref, _) -> return ref
- Nothing -> do
- let label' = case find ((== label) . fst) refs of
- Just _ -> -- label is used; generate numerical label
- case find (\n -> not (any (== [Str (show n)])
- (map fst refs))) [1..(10000 :: Integer)] of
- Just x -> [Str (show x)]
- Nothing -> error "no unique label"
- Nothing -> label
- modify (\(notes, refs') -> (notes, (label', (src,tit)):refs'))
- return label'
-
--- | Convert list of Pandoc inline elements to markdown.
-inlineListToMarkdown :: WriterOptions -> [Inline] -> State WriterState Doc
-inlineListToMarkdown opts lst =
- mapM (inlineToMarkdown opts) lst >>= return . hcat
-
--- | Convert Pandoc inline element to markdown.
-inlineToMarkdown :: WriterOptions -> Inline -> State WriterState Doc
-inlineToMarkdown opts (Emph lst) = do
- contents <- inlineListToMarkdown opts lst
- return $ char '*' <> contents <> char '*'
-inlineToMarkdown opts (Strong lst) = do
- contents <- inlineListToMarkdown opts lst
- return $ text "**" <> contents <> text "**"
-inlineToMarkdown opts (Strikeout lst) = do
- contents <- inlineListToMarkdown opts lst
- return $ text "~~" <> contents <> text "~~"
-inlineToMarkdown opts (Superscript lst) = do
- contents <- inlineListToMarkdown opts lst
- let contents' = text $ substitute " " "\\ " $ render contents
- return $ char '^' <> contents' <> char '^'
-inlineToMarkdown opts (Subscript lst) = do
- contents <- inlineListToMarkdown opts lst
- let contents' = text $ substitute " " "\\ " $ render contents
- return $ char '~' <> contents' <> char '~'
-inlineToMarkdown opts (SmallCaps lst) = inlineListToMarkdown opts lst
-inlineToMarkdown opts (Quoted SingleQuote lst) = do
- contents <- inlineListToMarkdown opts lst
- return $ char '\'' <> contents <> char '\''
-inlineToMarkdown opts (Quoted DoubleQuote lst) = do
- contents <- inlineListToMarkdown opts lst
- return $ char '"' <> contents <> char '"'
-inlineToMarkdown _ EmDash = return $ text "--"
-inlineToMarkdown _ EnDash = return $ char '-'
-inlineToMarkdown _ Apostrophe = return $ char '\''
-inlineToMarkdown _ Ellipses = return $ text "..."
-inlineToMarkdown _ (Code str) =
- let tickGroups = filter (\s -> '`' `elem` s) $ group str
- longest = if null tickGroups
- then 0
- else maximum $ map length tickGroups
- marker = replicate (longest + 1) '`'
- spacer = if (longest == 0) then "" else " " in
- return $ text (marker ++ spacer ++ str ++ spacer ++ marker)
-inlineToMarkdown _ (Str str) = return $ text $ escapeString str
-inlineToMarkdown _ (Math InlineMath str) = return $ char '$' <> text str <> char '$'
-inlineToMarkdown _ (Math DisplayMath str) = return $ text "$$" <> text str <> text "$$"
-inlineToMarkdown _ (TeX str) = return $ text str
-inlineToMarkdown _ (HtmlInline str) = return $ text str
-inlineToMarkdown _ (LineBreak) = return $ text " \n"
-inlineToMarkdown _ Space = return $ char ' '
-inlineToMarkdown _ (Cite cits _ ) = do
- let format (a,b) xs = text a <>
- (if b /= [] then char '@' else empty) <>
- text b <>
- (if isEmpty xs then empty else text "; ") <>
- xs
- return $ char '[' <> foldr format empty cits <> char ']'
-inlineToMarkdown opts (Link txt (src, tit)) = do
- linktext <- inlineListToMarkdown opts txt
- let linktitle = if null tit then empty else text $ " \"" ++ tit ++ "\""
- let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src
- let useRefLinks = writerReferenceLinks opts
- let useAuto = null tit && txt == [Code srcSuffix]
- ref <- if useRefLinks then getReference txt (src, tit) else return []
- reftext <- inlineListToMarkdown opts ref
- return $ if useAuto
- then char '<' <> text srcSuffix <> char '>'
- else if useRefLinks
- then let first = char '[' <> linktext <> char ']'
- second = if txt == ref
- then text "[]"
- else char '[' <> reftext <> char ']'
- in first <> second
- else char '[' <> linktext <> char ']' <>
- char '(' <> text src <> linktitle <> char ')'
-inlineToMarkdown opts (Image alternate (source, tit)) = do
- let txt = if (null alternate) || (alternate == [Str ""]) ||
- (alternate == [Str source]) -- to prevent autolinks
- then [Str "image"]
- else alternate
- linkPart <- inlineToMarkdown opts (Link txt (source, tit))
- return $ char '!' <> linkPart
-inlineToMarkdown _ (Note contents) = do
- modify (\(notes, refs) -> (contents:notes, refs)) -- add to notes in state
- (notes, _) <- get
- let ref = show $ (length notes)
- return $ text "[^" <> text ref <> char ']'
diff --git a/Text/Pandoc/Writers/MediaWiki.hs b/Text/Pandoc/Writers/MediaWiki.hs
deleted file mode 100644
index c5f6b3bf1..000000000
--- a/Text/Pandoc/Writers/MediaWiki.hs
+++ /dev/null
@@ -1,396 +0,0 @@
-{-
-Copyright (C) 2008 John MacFarlane <jgm@berkeley.edu>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.MediaWiki
- Copyright : Copyright (C) 2006-7 John MacFarlane
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Conversion of 'Pandoc' documents to MediaWiki markup.
-
-MediaWiki: <http://www.mediawiki.org/wiki/MediaWiki>
--}
-module Text.Pandoc.Writers.MediaWiki ( writeMediaWiki ) where
-import Text.Pandoc.Definition
-import Text.Pandoc.Shared
-import Text.Pandoc.XML ( escapeStringForXML )
-import Data.List ( intersect )
-import Network.URI ( isURI )
-import Control.Monad.State
-
-data WriterState = WriterState {
- stNotes :: Bool -- True if there are notes
- , stListLevel :: [Char] -- String at beginning of list items, e.g. "**"
- , stUseTags :: Bool -- True if we should use HTML tags because we're in a complex list
- }
-
--- | Convert Pandoc to MediaWiki.
-writeMediaWiki :: WriterOptions -> Pandoc -> String
-writeMediaWiki opts document =
- evalState (pandocToMediaWiki opts document)
- (WriterState { stNotes = False, stListLevel = [], stUseTags = False })
-
--- | Return MediaWiki representation of document.
-pandocToMediaWiki :: WriterOptions -> Pandoc -> State WriterState String
-pandocToMediaWiki opts (Pandoc _ blocks) = do
- let before = writerIncludeBefore opts
- let after = writerIncludeAfter opts
- let head' = if writerStandalone opts
- then writerHeader opts
- else ""
- let toc = if writerTableOfContents opts
- then "__TOC__\n"
- else ""
- body <- blockListToMediaWiki opts blocks
- notesExist <- get >>= return . stNotes
- let notes = if notesExist
- then "\n== Notes ==\n<references />"
- else ""
- return $ head' ++ before ++ toc ++ body ++ after ++ notes
-
--- | Escape special characters for MediaWiki.
-escapeString :: String -> String
-escapeString = escapeStringForXML
-
--- | Convert Pandoc block element to MediaWiki.
-blockToMediaWiki :: WriterOptions -- ^ Options
- -> Block -- ^ Block element
- -> State WriterState String
-
-blockToMediaWiki _ Null = return ""
-
-blockToMediaWiki opts (Plain inlines) =
- inlineListToMediaWiki opts inlines
-
-blockToMediaWiki opts (Para inlines) = do
- useTags <- get >>= return . stUseTags
- listLevel <- get >>= return . stListLevel
- contents <- inlineListToMediaWiki opts inlines
- return $ if useTags
- then "<p>" ++ contents ++ "</p>"
- else contents ++ if null listLevel then "\n" else ""
-
-blockToMediaWiki _ (RawHtml str) = return str
-
-blockToMediaWiki _ HorizontalRule = return "\n-----\n"
-
-blockToMediaWiki opts (Header level inlines) = do
- contents <- inlineListToMediaWiki opts inlines
- let eqs = replicate (level + 1) '='
- return $ eqs ++ " " ++ contents ++ " " ++ eqs ++ "\n"
-
-blockToMediaWiki _ (CodeBlock (_,classes,_) str) = do
- let at = classes `intersect` ["actionscript", "ada", "apache", "applescript", "asm", "asp",
- "autoit", "bash", "blitzbasic", "bnf", "c", "c_mac", "caddcl", "cadlisp", "cfdg", "cfm",
- "cpp", "cpp-qt", "csharp", "css", "d", "delphi", "diff", "div", "dos", "eiffel", "fortran",
- "freebasic", "gml", "groovy", "html4strict", "idl", "ini", "inno", "io", "java", "java5",
- "javascript", "latex", "lisp", "lua", "matlab", "mirc", "mpasm", "mysql", "nsis", "objc",
- "ocaml", "ocaml-brief", "oobas", "oracle8", "pascal", "perl", "php", "php-brief", "plsql",
- "python", "qbasic", "rails", "reg", "robots", "ruby", "sas", "scheme", "sdlbasic",
- "smalltalk", "smarty", "sql", "tcl", "", "thinbasic", "tsql", "vb", "vbnet", "vhdl",
- "visualfoxpro", "winbatch", "xml", "xpp", "z80"]
- let (beg, end) = if null at
- then ("<pre" ++ if null classes then ">" else " class=\"" ++ unwords classes ++ "\">", "</pre>")
- else ("<source lang=\"" ++ head at ++ "\">", "</source>")
- return $ beg ++ escapeString str ++ end
-
-blockToMediaWiki opts (BlockQuote blocks) = do
- contents <- blockListToMediaWiki opts blocks
- return $ "<blockquote>" ++ contents ++ "</blockquote>"
-
-blockToMediaWiki opts (Table caption aligns widths headers rows) = do
- let alignStrings = map alignmentToString aligns
- captionDoc <- if null caption
- then return ""
- else do
- c <- inlineListToMediaWiki opts caption
- return $ "<caption>" ++ c ++ "</caption>"
- colHeads <- colHeadsToMediaWiki opts alignStrings widths headers
- rows' <- mapM (tableRowToMediaWiki opts alignStrings) rows
- return $ "<table>\n" ++ captionDoc ++ colHeads ++ vcat rows' ++ "\n</table>"
-
-blockToMediaWiki opts x@(BulletList items) = do
- oldUseTags <- get >>= return . stUseTags
- let useTags = oldUseTags || not (isSimpleList x)
- if useTags
- then do
- modify $ \s -> s { stUseTags = True }
- contents <- mapM (listItemToMediaWiki opts) items
- modify $ \s -> s { stUseTags = oldUseTags }
- return $ "<ul>\n" ++ vcat contents ++ "</ul>\n"
- else do
- modify $ \s -> s { stListLevel = stListLevel s ++ "*" }
- contents <- mapM (listItemToMediaWiki opts) items
- modify $ \s -> s { stListLevel = init (stListLevel s) }
- return $ vcat contents
-
-blockToMediaWiki opts x@(OrderedList attribs items) = do
- oldUseTags <- get >>= return . stUseTags
- let useTags = oldUseTags || not (isSimpleList x)
- if useTags
- then do
- modify $ \s -> s { stUseTags = True }
- contents <- mapM (listItemToMediaWiki opts) items
- modify $ \s -> s { stUseTags = oldUseTags }
- return $ "<ol" ++ listAttribsToString attribs ++ ">\n" ++ vcat contents ++ "</ol>\n"
- else do
- modify $ \s -> s { stListLevel = stListLevel s ++ "#" }
- contents <- mapM (listItemToMediaWiki opts) items
- modify $ \s -> s { stListLevel = init (stListLevel s) }
- return $ vcat contents
-
-blockToMediaWiki opts x@(DefinitionList items) = do
- oldUseTags <- get >>= return . stUseTags
- let useTags = oldUseTags || not (isSimpleList x)
- if useTags
- then do
- modify $ \s -> s { stUseTags = True }
- contents <- mapM (definitionListItemToMediaWiki opts) items
- modify $ \s -> s { stUseTags = oldUseTags }
- return $ "<dl>\n" ++ vcat contents ++ "</dl>\n"
- else do
- modify $ \s -> s { stListLevel = stListLevel s ++ ";" }
- contents <- mapM (definitionListItemToMediaWiki opts) items
- modify $ \s -> s { stListLevel = init (stListLevel s) }
- return $ vcat contents
-
--- Auxiliary functions for lists:
-
--- | Convert ordered list attributes to HTML attribute string
-listAttribsToString :: ListAttributes -> String
-listAttribsToString (startnum, numstyle, _) =
- let numstyle' = camelCaseToHyphenated $ show numstyle
- in (if startnum /= 1
- then " start=\"" ++ show startnum ++ "\""
- else "") ++
- (if numstyle /= DefaultStyle
- then " style=\"list-style-type: " ++ numstyle' ++ ";\""
- else "")
-
--- | Convert bullet or ordered list item (list of blocks) to MediaWiki.
-listItemToMediaWiki :: WriterOptions -> [Block] -> State WriterState String
-listItemToMediaWiki opts items = do
- contents <- blockListToMediaWiki opts items
- useTags <- get >>= return . stUseTags
- if useTags
- then return $ "<li>" ++ contents ++ "</li>"
- else do
- marker <- get >>= return . stListLevel
- return $ marker ++ " " ++ contents
-
--- | Convert definition list item (label, list of blocks) to MediaWiki.
-definitionListItemToMediaWiki :: WriterOptions
- -> ([Inline],[Block])
- -> State WriterState String
-definitionListItemToMediaWiki opts (label, items) = do
- labelText <- inlineListToMediaWiki opts label
- contents <- blockListToMediaWiki opts items
- useTags <- get >>= return . stUseTags
- if useTags
- then return $ "<dt>" ++ labelText ++ "</dt>\n<dd>" ++ contents ++ "</dd>"
- else do
- marker <- get >>= return . stListLevel
- return $ marker ++ " " ++ labelText ++ "\n" ++ (init marker ++ ": ") ++ contents
-
--- | True if the list can be handled by simple wiki markup, False if HTML tags will be needed.
-isSimpleList :: Block -> Bool
-isSimpleList x =
- case x of
- BulletList items -> all isSimpleListItem items
- OrderedList (num, sty, _) items -> all isSimpleListItem items &&
- num == 1 && sty `elem` [DefaultStyle, Decimal]
- DefinitionList items -> all isSimpleListItem $ map snd items
- _ -> False
-
--- | True if list item can be handled with the simple wiki syntax. False if
--- HTML tags will be needed.
-isSimpleListItem :: [Block] -> Bool
-isSimpleListItem [] = True
-isSimpleListItem [x] =
- case x of
- Plain _ -> True
- Para _ -> True
- BulletList _ -> isSimpleList x
- OrderedList _ _ -> isSimpleList x
- DefinitionList _ -> isSimpleList x
- _ -> False
-isSimpleListItem [x, y] | isPlainOrPara x =
- case y of
- BulletList _ -> isSimpleList y
- OrderedList _ _ -> isSimpleList y
- DefinitionList _ -> isSimpleList y
- _ -> False
-isSimpleListItem _ = False
-
-isPlainOrPara :: Block -> Bool
-isPlainOrPara (Plain _) = True
-isPlainOrPara (Para _) = True
-isPlainOrPara _ = False
-
-tr :: String -> String
-tr x = "<tr>\n" ++ x ++ "\n</tr>"
-
--- | Concatenates strings with line breaks between them.
-vcat :: [String] -> String
-vcat [] = ""
-vcat [x] = x
-vcat (x:xs) = x ++ "\n" ++ vcat xs
-
--- Auxiliary functions for tables:
-
-colHeadsToMediaWiki :: WriterOptions
- -> [[Char]]
- -> [Double]
- -> [[Block]]
- -> State WriterState String
-colHeadsToMediaWiki opts alignStrings widths headers = do
- heads <- sequence $ zipWith3
- (\alignment columnwidth item -> tableItemToMediaWiki opts "th" alignment columnwidth item)
- alignStrings widths headers
- return $ tr $ vcat heads
-
-alignmentToString :: Alignment -> [Char]
-alignmentToString alignment = case alignment of
- AlignLeft -> "left"
- AlignRight -> "right"
- AlignCenter -> "center"
- AlignDefault -> "left"
-
-tableRowToMediaWiki :: WriterOptions
- -> [[Char]]
- -> [[Block]]
- -> State WriterState String
-tableRowToMediaWiki opts aligns columns =
- (sequence $ zipWith3 (tableItemToMediaWiki opts "td") aligns (repeat 0) columns) >>=
- return . tr . vcat
-
-tableItemToMediaWiki :: WriterOptions
- -> [Char]
- -> [Char]
- -> Double
- -> [Block]
- -> State WriterState String
-tableItemToMediaWiki opts tag' align' width' item = do
- contents <- blockListToMediaWiki opts item
- let attrib = " align=\"" ++ align' ++ "\"" ++
- if width' /= 0
- then " style=\"width: " ++ (show (truncate (100 * width') :: Integer)) ++ "%;\""
- else ""
- return $ "<" ++ tag' ++ attrib ++ ">" ++ contents ++ "</" ++ tag' ++ ">"
-
--- | Convert list of Pandoc block elements to MediaWiki.
-blockListToMediaWiki :: WriterOptions -- ^ Options
- -> [Block] -- ^ List of block elements
- -> State WriterState String
-blockListToMediaWiki opts blocks =
- mapM (blockToMediaWiki opts) blocks >>= return . vcat
-
--- | Convert list of Pandoc inline elements to MediaWiki.
-inlineListToMediaWiki :: WriterOptions -> [Inline] -> State WriterState String
-inlineListToMediaWiki opts lst =
- mapM (inlineToMediaWiki opts) lst >>= return . concat
-
--- | Convert Pandoc inline element to MediaWiki.
-inlineToMediaWiki :: WriterOptions -> Inline -> State WriterState String
-
-inlineToMediaWiki opts (Emph lst) = do
- contents <- inlineListToMediaWiki opts lst
- return $ "''" ++ contents ++ "''"
-
-inlineToMediaWiki opts (Strong lst) = do
- contents <- inlineListToMediaWiki opts lst
- return $ "'''" ++ contents ++ "'''"
-
-inlineToMediaWiki opts (Strikeout lst) = do
- contents <- inlineListToMediaWiki opts lst
- return $ "<s>" ++ contents ++ "</s>"
-
-inlineToMediaWiki opts (Superscript lst) = do
- contents <- inlineListToMediaWiki opts lst
- return $ "<sup>" ++ contents ++ "</sup>"
-
-inlineToMediaWiki opts (Subscript lst) = do
- contents <- inlineListToMediaWiki opts lst
- return $ "<sub>" ++ contents ++ "</sub>"
-
-inlineToMediaWiki opts (SmallCaps lst) = inlineListToMediaWiki opts lst
-
-inlineToMediaWiki opts (Quoted SingleQuote lst) = do
- contents <- inlineListToMediaWiki opts lst
- return $ "&lsquo;" ++ contents ++ "&rsquo;"
-
-inlineToMediaWiki opts (Quoted DoubleQuote lst) = do
- contents <- inlineListToMediaWiki opts lst
- return $ "&ldquo;" ++ contents ++ "&rdquo;"
-
-inlineToMediaWiki opts (Cite _ lst) = inlineListToMediaWiki opts lst
-
-inlineToMediaWiki _ EmDash = return "&mdash;"
-
-inlineToMediaWiki _ EnDash = return "&ndash;"
-
-inlineToMediaWiki _ Apostrophe = return "&rsquo;"
-
-inlineToMediaWiki _ Ellipses = return "&hellip;"
-
-inlineToMediaWiki _ (Code str) =
- return $ "<tt>" ++ (escapeString str) ++ "</tt>"
-
-inlineToMediaWiki _ (Str str) = return $ escapeString str
-
-inlineToMediaWiki _ (Math _ str) = return $ "<math>" ++ str ++ "</math>"
- -- note: str should NOT be escaped
-
-inlineToMediaWiki _ (TeX _) = return ""
-
-inlineToMediaWiki _ (HtmlInline str) = return str
-
-inlineToMediaWiki _ (LineBreak) = return "<br />\n"
-
-inlineToMediaWiki _ Space = return " "
-
-inlineToMediaWiki opts (Link txt (src, _)) = do
- link <- inlineListToMediaWiki opts txt
- let useAuto = txt == [Code src]
- let src' = if isURI src
- then src
- else if take 1 src == "/"
- then "http://{{SERVERNAME}}" ++ src
- else "http://{{SERVERNAME}}/" ++ src
- return $ if useAuto
- then src'
- else "[" ++ src' ++ " " ++ link ++ "]"
-
-inlineToMediaWiki opts (Image alt (source, tit)) = do
- alt' <- inlineListToMediaWiki opts alt
- let txt = if (null tit)
- then if null alt
- then ""
- else "|" ++ alt'
- else "|" ++ tit
- return $ "[[Image:" ++ source ++ txt ++ "]]"
-
-inlineToMediaWiki opts (Note contents) = do
- contents' <- blockListToMediaWiki opts contents
- modify (\s -> s { stNotes = True })
- return $ "<ref>" ++ contents' ++ "</ref>"
- -- note - may not work for notes with multiple blocks
diff --git a/Text/Pandoc/Writers/OpenDocument.hs b/Text/Pandoc/Writers/OpenDocument.hs
deleted file mode 100644
index 52438f81e..000000000
--- a/Text/Pandoc/Writers/OpenDocument.hs
+++ /dev/null
@@ -1,568 +0,0 @@
-{-# LANGUAGE PatternGuards #-}
-{-
-Copyright (C) 2008 Andrea Rossato <andrea.rossato@ing.unitn.it>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.OpenDocument
- Copyright : Copyright (C) 2008 Andrea Rossato
- License : GNU GPL, version 2 or above
-
- Maintainer : Andrea Rossato <andrea.rossato@ing.unitn.it>
- Stability : alpha
- Portability : portable
-
-Conversion of 'Pandoc' documents to OpenDocument XML.
--}
-module Text.Pandoc.Writers.OpenDocument ( writeOpenDocument ) where
-import Text.Pandoc.Definition
-import Text.Pandoc.Shared
-import Text.Pandoc.XML
-import Text.Pandoc.Readers.TeXMath
-import Text.PrettyPrint.HughesPJ hiding ( Str )
-import Text.Printf ( printf )
-import Control.Applicative ( (<$>) )
-import Control.Arrow ( (***), (>>>) )
-import Control.Monad.State hiding ( when )
-import Data.Char (chr)
-import Data.List (intercalate)
-
--- | Auxiliary function to convert Plain block to Para.
-plainToPara :: Block -> Block
-plainToPara (Plain x) = Para x
-plainToPara x = x
-
---
--- OpenDocument writer
---
-
-data WriterState =
- WriterState { stNotes :: [Doc]
- , stTableStyles :: [Doc]
- , stParaStyles :: [Doc]
- , stListStyles :: [(Int, [Doc])]
- , stTextStyles :: [Doc]
- , stTextStyleAttr :: [(TextStyle,[(String,String)])]
- , stIndentPara :: Int
- , stInDefinition :: Bool
- , stTight :: Bool
- }
-
-defaultWriterState :: WriterState
-defaultWriterState =
- WriterState { stNotes = []
- , stTableStyles = []
- , stParaStyles = []
- , stListStyles = []
- , stTextStyles = []
- , stTextStyleAttr = []
- , stIndentPara = 0
- , stInDefinition = False
- , stTight = False
- }
-
-when :: Bool -> Doc -> Doc
-when p a = if p then a else empty
-
-addTableStyle :: Doc -> State WriterState ()
-addTableStyle i = modify $ \s -> s { stTableStyles = i : stTableStyles s }
-
-addNote :: Doc -> State WriterState ()
-addNote i = modify $ \s -> s { stNotes = i : stNotes s }
-
-addParaStyle :: Doc -> State WriterState ()
-addParaStyle i = modify $ \s -> s { stParaStyles = i : stParaStyles s }
-
-addTextStyle :: Doc -> State WriterState ()
-addTextStyle i = modify $ \s -> s { stTextStyles = i : stTextStyles s }
-
-addTextStyleAttr :: (TextStyle, [(String,String)]) -> State WriterState ()
-addTextStyleAttr i = modify $ \s -> s { stTextStyleAttr = i : stTextStyleAttr s }
-
-rmTextStyleAttr :: State WriterState ()
-rmTextStyleAttr = modify $ \s -> s { stTextStyleAttr = rmHead (stTextStyleAttr s) }
- where rmHead l = if l /= [] then tail l else []
-
-increaseIndent :: State WriterState ()
-increaseIndent = modify $ \s -> s { stIndentPara = 1 + stIndentPara s }
-
-resetIndent :: State WriterState ()
-resetIndent = modify $ \s -> s { stIndentPara = (stIndentPara s) - 1 }
-
-inTightList :: State WriterState a -> State WriterState a
-inTightList f = modify (\s -> s { stTight = True }) >> f >>= \r ->
- modify (\s -> s { stTight = False }) >> return r
-
-setInDefinitionList :: Bool -> State WriterState ()
-setInDefinitionList b = modify $ \s -> s { stInDefinition = b }
-
-inParagraphTags :: Doc -> Doc
-inParagraphTags = inTags False "text:p" [("text:style-name", "Text_20_body")]
-
-inParagraphTagsWithStyle :: String -> Doc -> Doc
-inParagraphTagsWithStyle sty = inTags False "text:p" [("text:style-name", sty)]
-
-inSpanTags :: String -> Doc -> Doc
-inSpanTags s = inTags False "text:span" [("text:style-name",s)]
-
-withTextStyle :: TextStyle -> State WriterState a -> State WriterState a
-withTextStyle s f = addTextStyleAttr (s,textStyleAttr s) >>
- f >>= \r -> rmTextStyleAttr >> return r
-
-inTextStyle :: Doc -> State WriterState Doc
-inTextStyle d = do
- at <- gets stTextStyleAttr
- if at == []
- then return d
- else do
- tn <- (+) 1 . length <$> gets stTextStyles
- addTextStyle $ inTags False "style:style" [("style:name" , "T" ++ show tn)
- ,("style:family", "text" )]
- $ selfClosingTag "style:text-properties" (concatMap snd at)
- return $ inTags False "text:span" [("text:style-name","T" ++ show tn)] d
-
-inHeaderTags :: Int -> Doc -> Doc
-inHeaderTags i = inTags False "text:h" [ ("text:style-name", "Heading_20_" ++ show i)
- , ("text:outline-level", show i)]
-
-inQuotes :: QuoteType -> Doc -> Doc
-inQuotes SingleQuote s = text "&#8216;" <> s <> text "&#8217;"
-inQuotes DoubleQuote s = text "&#8220;" <> s <> text "&#8221;"
-
-handleSpaces :: String -> Doc
-handleSpaces s
- | ( ' ':_) <- s = genTag s
- | ('\t':x) <- s = selfClosingTag "text:tab" [] <> rm x
- | otherwise = rm s
- where
- genTag = span (==' ') >>> tag . length *** rm >>> uncurry (<>)
- tag n = when (n /= 0) $ selfClosingTag "text:s" [("text:c", show n)]
- rm ( ' ':xs) = char ' ' <> genTag xs
- rm ('\t':xs) = selfClosingTag "text:tab" [] <> genTag xs
- rm ( x:xs) = char x <> rm xs
- rm [] = empty
-
--- | Convert list of authors to a docbook <author> section
-authorToOpenDocument :: [Char] -> Doc
-authorToOpenDocument name =
- if ',' `elem` name
- then -- last name first
- let (lastname, rest) = break (==',') name
- firstname = removeLeadingSpace rest
- in inParagraphTagsWithStyle "Author" $
- (text $ escapeStringForXML firstname) <+>
- (text $ escapeStringForXML lastname)
- else -- last name last
- let namewords = words name
- lengthname = length namewords
- (firstname, lastname) = case lengthname of
- 0 -> ("","")
- 1 -> ("", name)
- n -> (intercalate " " (take (n-1) namewords), last namewords)
- in inParagraphTagsWithStyle "Author" $
- (text $ escapeStringForXML firstname) <+>
- (text $ escapeStringForXML lastname)
-
--- | Convert Pandoc document to string in OpenDocument format.
-writeOpenDocument :: WriterOptions -> Pandoc -> String
-writeOpenDocument opts (Pandoc (Meta title authors date) blocks) =
- let root = inTags True "office:document-content" openDocumentNameSpaces
- header = when (writerStandalone opts) $ text (writerHeader opts)
- title' = case runState (wrap opts title) defaultWriterState of
- (t,_) -> if isEmpty t then empty else inHeaderTags 1 t
- authors' = when (authors /= []) $ vcat (map authorToOpenDocument authors)
- date' = when (date /= []) $
- inParagraphTagsWithStyle "Date" (text $ escapeStringForXML date)
- meta = when (writerStandalone opts) $ title' $$ authors' $$ date'
- before = writerIncludeBefore opts
- after = writerIncludeAfter opts
- (doc, s) = runState (blocksToOpenDocument opts blocks) defaultWriterState
- body = (if null before then empty else text before) $$
- doc $$
- (if null after then empty else text after)
- body' = if writerStandalone opts
- then inTagsIndented "office:body" $
- inTagsIndented "office:text" (meta $$ body)
- else body
- styles = stTableStyles s ++ stParaStyles s ++ stTextStyles s
- listStyle (n,l) = inTags True "text:list-style" [("style:name", "L" ++ show n)] (vcat l)
- listStyles = map listStyle (stListStyles s)
- in render $ header $$ root (generateStyles (styles ++ listStyles) $$ body' $$ text "")
-
-withParagraphStyle :: WriterOptions -> String -> [Block] -> State WriterState Doc
-withParagraphStyle o s (b:bs)
- | Para l <- b = go =<< inParagraphTagsWithStyle s <$> inlinesToOpenDocument o l
- | otherwise = go =<< blockToOpenDocument o b
- where go i = ($$) i <$> withParagraphStyle o s bs
-withParagraphStyle _ _ [] = return empty
-
-inPreformattedTags :: String -> State WriterState Doc
-inPreformattedTags s = do
- n <- paraStyle "Preformatted_20_Text" []
- return . inParagraphTagsWithStyle ("P" ++ show n) . handleSpaces $ s
-
-orderedListToOpenDocument :: WriterOptions -> Int -> [[Block]] -> State WriterState Doc
-orderedListToOpenDocument o pn bs =
- vcat . map (inTagsIndented "text:list-item") <$>
- mapM (orderedItemToOpenDocument o pn . map plainToPara) bs
-
-orderedItemToOpenDocument :: WriterOptions -> Int -> [Block] -> State WriterState Doc
-orderedItemToOpenDocument o n (b:bs)
- | OrderedList a l <- b = newLevel a l
- | Para l <- b = go =<< inParagraphTagsWithStyle ("P" ++ show n) <$> inlinesToOpenDocument o l
- | otherwise = go =<< blockToOpenDocument o b
- where
- go i = ($$) i <$> orderedItemToOpenDocument o n bs
- newLevel a l = do
- nn <- length <$> gets stParaStyles
- ls <- head <$> gets stListStyles
- modify $ \s -> s { stListStyles = orderedListLevelStyle a ls : tail (stListStyles s) }
- inTagsIndented "text:list" <$> orderedListToOpenDocument o nn l
-orderedItemToOpenDocument _ _ [] = return empty
-
-isTightList :: [[Block]] -> Bool
-isTightList [] = False
-isTightList (b:_)
- | Plain {} : _ <- b = True
- | otherwise = False
-
-newOrderedListStyle :: Bool -> ListAttributes -> State WriterState (Int,Int)
-newOrderedListStyle b a = do
- ln <- (+) 1 . length <$> gets stListStyles
- let nbs = orderedListLevelStyle a (ln, [])
- pn <- if b then inTightList (paraListStyle ln) else paraListStyle ln
- modify $ \s -> s { stListStyles = nbs : stListStyles s }
- return (ln,pn)
-
-bulletListToOpenDocument :: WriterOptions -> [[Block]] -> State WriterState Doc
-bulletListToOpenDocument o b = do
- ln <- (+) 1 . length <$> gets stListStyles
- (pn,ns) <- if isTightList b then inTightList (bulletListStyle ln) else bulletListStyle ln
- modify $ \s -> s { stListStyles = ns : stListStyles s }
- is <- listItemsToOpenDocument ("P" ++ show pn) o b
- return $ inTags True "text:list" [("text:style-name", "L" ++ show ln)] is
-
-listItemsToOpenDocument :: String -> WriterOptions -> [[Block]] -> State WriterState Doc
-listItemsToOpenDocument s o is =
- vcat . map (inTagsIndented "text:list-item") <$> mapM (withParagraphStyle o s . map plainToPara) is
-
-deflistItemToOpenDocument :: WriterOptions -> ([Inline],[Block]) -> State WriterState Doc
-deflistItemToOpenDocument o (t,d) = do
- let ts = if isTightList [d]
- then "Definition_20_Term_20_Tight" else "Definition_20_Term"
- ds = if isTightList [d]
- then "Definition_20_Definition_20_Tight" else "Definition_20_Definition"
- t' <- withParagraphStyle o ts [Para t]
- d' <- withParagraphStyle o ds (map plainToPara d)
- return $ t' $$ d'
-
-inBlockQuote :: WriterOptions -> Int -> [Block] -> State WriterState Doc
-inBlockQuote o i (b:bs)
- | BlockQuote l <- b = do increaseIndent
- ni <- paraStyle "Quotations" []
- go =<< inBlockQuote o ni (map plainToPara l)
- | Para l <- b = do go =<< inParagraphTagsWithStyle ("P" ++ show i) <$> inlinesToOpenDocument o l
- | otherwise = do go =<< blockToOpenDocument o b
- where go block = ($$) block <$> inBlockQuote o i bs
-inBlockQuote _ _ [] = resetIndent >> return empty
-
--- | Convert a list of Pandoc blocks to OpenDocument.
-blocksToOpenDocument :: WriterOptions -> [Block] -> State WriterState Doc
-blocksToOpenDocument o b = vcat <$> mapM (blockToOpenDocument o) b
-
--- | Convert a Pandoc block element to OpenDocument.
-blockToOpenDocument :: WriterOptions -> Block -> State WriterState Doc
-blockToOpenDocument o bs
- | Plain b <- bs = inParagraphTags <$> wrap o b
- | Para b <- bs = inParagraphTags <$> wrap o b
- | Header i b <- bs = inHeaderTags i <$> wrap o b
- | BlockQuote b <- bs = mkBlockQuote b
- | CodeBlock _ s <- bs = preformatted s
- | RawHtml _ <- bs = return empty
- | DefinitionList b <- bs = defList b
- | BulletList b <- bs = bulletListToOpenDocument o b
- | OrderedList a b <- bs = orderedList a b
- | Table c a w h r <- bs = table c a w h r
- | Null <- bs = return empty
- | HorizontalRule <- bs = return $ selfClosingTag "text:p" [ ("text:style-name", "Horizontal_20_Line") ]
- | otherwise = return empty
- where
- defList b = do setInDefinitionList True
- r <- vcat <$> mapM (deflistItemToOpenDocument o) b
- setInDefinitionList False
- return r
- preformatted s = vcat <$> mapM (inPreformattedTags . escapeStringForXML) (lines s)
- mkBlockQuote b = do increaseIndent
- i <- paraStyle "Quotations" []
- inBlockQuote o i (map plainToPara b)
- orderedList a b = do (ln,pn) <- newOrderedListStyle (isTightList b) a
- inTags True "text:list" [ ("text:style-name", "L" ++ show ln)]
- <$> orderedListToOpenDocument o pn b
- table c a w h r = do
- tn <- length <$> gets stTableStyles
- pn <- length <$> gets stParaStyles
- let genIds = map chr [65..]
- name = "Table" ++ show (tn + 1)
- columnIds = zip genIds w
- mkColumn n = selfClosingTag "table:table-column" [("table:style-name", name ++ "." ++ [fst n])]
- columns = map mkColumn columnIds
- paraHStyles = paraTableStyles "Heading" pn a
- paraStyles = paraTableStyles "Contents" (pn + length (newPara paraHStyles)) a
- newPara = map snd . filter (not . isEmpty . snd)
- addTableStyle $ tableStyle tn columnIds
- mapM_ addParaStyle . newPara $ paraHStyles ++ paraStyles
- captionDoc <- if null c
- then return empty
- else withParagraphStyle o "Caption" [Para c]
- th <- colHeadsToOpenDocument o name (map fst paraHStyles) h
- tr <- mapM (tableRowToOpenDocument o name (map fst paraStyles)) r
- return $ inTags True "table:table" [ ("table:name" , name)
- , ("table:style-name", name)
- ] (vcat columns $$ th $$ vcat tr) $$ captionDoc
-
-colHeadsToOpenDocument :: WriterOptions -> String -> [String] -> [[Block]] -> State WriterState Doc
-colHeadsToOpenDocument o tn ns hs =
- inTagsIndented "table:table-header-rows" . inTagsIndented "table:table-row" . vcat <$>
- mapM (tableItemToOpenDocument o tn) (zip ns hs)
-
-tableRowToOpenDocument :: WriterOptions -> String -> [String] -> [[Block]] -> State WriterState Doc
-tableRowToOpenDocument o tn ns cs =
- inTagsIndented "table:table-row" . vcat <$>
- mapM (tableItemToOpenDocument o tn) (zip ns cs)
-
-tableItemToOpenDocument :: WriterOptions -> String -> (String,[Block])-> State WriterState Doc
-tableItemToOpenDocument o tn (n,i) =
- let a = [ ("table:style-name" , tn ++ ".A1" )
- , ("office:value-type", "string" )
- ]
- in inTags True "table:table-cell" a <$>
- withParagraphStyle o n (map plainToPara i)
-
--- | Take list of inline elements and return wrapped doc.
-wrap :: WriterOptions -> [Inline] -> State WriterState Doc
-wrap o l = if writerWrapText o
- then fsep <$> mapM (inlinesToOpenDocument o) (splitBy Space l)
- else inlinesToOpenDocument o l
-
--- | Convert a list of inline elements to OpenDocument.
-inlinesToOpenDocument :: WriterOptions -> [Inline] -> State WriterState Doc
-inlinesToOpenDocument o l = hcat <$> mapM (inlineToOpenDocument o) l
-
--- | Convert an inline element to OpenDocument.
-inlineToOpenDocument :: WriterOptions -> Inline -> State WriterState Doc
-inlineToOpenDocument o ils
- | Ellipses <- ils = inTextStyle $ text "&#8230;"
- | EmDash <- ils = inTextStyle $ text "&#8212;"
- | EnDash <- ils = inTextStyle $ text "&#8211;"
- | Apostrophe <- ils = inTextStyle $ text "&#8217;"
- | Space <- ils = inTextStyle $ char ' '
- | LineBreak <- ils = return $ selfClosingTag "text:line-break" []
- | Str s <- ils = inTextStyle $ handleSpaces $ escapeStringForXML s
- | Emph l <- ils = withTextStyle Italic $ inlinesToOpenDocument o l
- | Strong l <- ils = withTextStyle Bold $ inlinesToOpenDocument o l
- | Strikeout l <- ils = withTextStyle Strike $ inlinesToOpenDocument o l
- | Superscript l <- ils = withTextStyle Sup $ inlinesToOpenDocument o l
- | Subscript l <- ils = withTextStyle Sub $ inlinesToOpenDocument o l
- | SmallCaps l <- ils = withTextStyle SmallC $ inlinesToOpenDocument o l
- | Quoted t l <- ils = inQuotes t <$> inlinesToOpenDocument o l
- | Code s <- ils = preformatted s
- | Math _ s <- ils = inlinesToOpenDocument o (readTeXMath s)
- | Cite _ l <- ils = inlinesToOpenDocument o l
- | TeX s <- ils = preformatted s
- | HtmlInline s <- ils = preformatted s
- | Link l (s,t) <- ils = mkLink s t <$> inlinesToOpenDocument o l
- | Image _ (s,_) <- ils = return $ mkImg s
- | Note l <- ils = mkNote l
- | otherwise = return empty
- where
- preformatted = return . inSpanTags "Teletype" . handleSpaces . escapeStringForXML
- mkLink s t = inTags False "text:a" [ ("xlink:type" , "simple")
- , ("xlink:href" , s )
- , ("office:name", t )
- ] . inSpanTags "Definition"
- mkImg s = inTags False "draw:frame" [] $
- selfClosingTag "draw:image" [ ("xlink:href" , s )
- , ("xlink:type" , "simple")
- , (" xlink:show" , "embed" )
- , ("xlink:actuate", "onLoad")]
- mkNote l = do
- n <- length <$> gets stNotes
- let footNote t = inTags False "text:note"
- [ ("text:id" , "ftn" ++ show n)
- , ("text:note-class", "footnote" )] $
- inTagsSimple "text:note-citation" (text . show $ n + 1) $$
- inTagsSimple "text:note-body" t
- nn <- footNote <$> withParagraphStyle o "Footnote" l
- addNote nn
- return nn
-
-generateStyles :: [Doc] -> Doc
-generateStyles acc =
- let scripts = selfClosingTag "office:scripts" []
- fonts = inTagsIndented "office:font-face-decls"
- (vcat $ map font ["Lucida Sans Unicode", "Tahoma", "Times New Roman"])
- font fn = selfClosingTag "style:font-face"
- [ ("style:name" , "&apos;" ++ fn ++ "&apos;")
- , ("svg:font-family", fn )]
- in scripts $$ fonts $$ inTagsIndented "office:automatic-styles" (vcat $ reverse acc)
-
-bulletListStyle :: Int -> State WriterState (Int,(Int,[Doc]))
-bulletListStyle l =
- let doStyles i = inTags True "text:list-level-style-bullet"
- [ ("text:level" , show (i + 1) )
- , ("text:style-name" , "Bullet_20_Symbols")
- , ("style:num-suffix", "." )
- , ("text:bullet-char", [bulletList !! i] )
- ] (listLevelStyle (1 + i))
- bulletList = map chr $ cycle [8226,8227,8259]
- listElStyle = map doStyles [0..9]
- in do pn <- paraListStyle l
- return (pn, (l, listElStyle))
-
-orderedListLevelStyle :: ListAttributes -> (Int, [Doc]) -> (Int,[Doc])
-orderedListLevelStyle (s,n, d) (l,ls) =
- let suffix = case d of
- OneParen -> [("style:num-suffix", ")")]
- TwoParens -> [("style:num-prefix", "(")
- ,("style:num-suffix", ")")]
- _ -> [("style:num-suffix", ".")]
- format = case n of
- UpperAlpha -> "A"
- LowerAlpha -> "a"
- UpperRoman -> "I"
- LowerRoman -> "i"
- _ -> "1"
- listStyle = inTags True "text:list-level-style-number"
- ([ ("text:level" , show $ 1 + length ls )
- , ("text:style-name" , "Numbering_20_Symbols")
- , ("style:num-format", format )
- , ("text:start-value", show s )
- ] ++ suffix) (listLevelStyle (1 + length ls))
- in (l, ls ++ [listStyle])
-
-listLevelStyle :: Int -> Doc
-listLevelStyle i =
- let indent = show (0.25 * fromIntegral i :: Double) in
- selfClosingTag "style:list-level-properties"
- [ ("text:space-before" , indent ++ "in")
- , ("text:min-label-width", "0.25in")]
-
-tableStyle :: Int -> [(Char,Double)] -> Doc
-tableStyle num wcs =
- let tableId = "Table" ++ show (num + 1)
- table = inTags True "style:style"
- [("style:name", tableId)] $
- selfClosingTag "style:table-properties"
- [ ("style:rel-width", "100%" )
- , ("table:align" , "center")]
- colStyle (c,w) = inTags True "style:style"
- [ ("style:name" , tableId ++ "." ++ [c])
- , ("style:family", "table-column" )] $
- selfClosingTag "style:table-column-properties"
- [("style:column-width", printf "%.2f" (7 * w) ++ "in")]
- cellStyle = inTags True "style:style"
- [ ("style:name" , tableId ++ ".A1")
- , ("style:family", "table-cell" )] $
- selfClosingTag "style:table-cell-properties"
- [ ("fo:border", "none")]
- columnStyles = map colStyle wcs
- in table $$ vcat columnStyles $$ cellStyle
-
-paraStyle :: String -> [(String,String)] -> State WriterState Int
-paraStyle parent attrs = do
- pn <- (+) 1 . length <$> gets stParaStyles
- i <- (*) 0.5 . fromIntegral <$> gets stIndentPara :: State WriterState Double
- b <- gets stInDefinition
- t <- gets stTight
- let styleAttr = [ ("style:name" , "P" ++ show pn)
- , ("style:family" , "paragraph" )
- , ("style:parent-style-name", parent )]
- indentVal = flip (++) "in" . show $ if b then (max 0.5 i) else i
- tight = if t then [ ("fo:margin-top" , "0in" )
- , ("fo:margin-bottom" , "0in" )]
- else []
- indent = when (i /= 0 || b || t) $
- selfClosingTag "style:paragraph-properties" $
- [ ("fo:margin-left" , indentVal)
- , ("fo:margin-right" , "0in" )
- , ("fo:text-indent" , "0in" )
- , ("style:auto-text-indent" , "false" )]
- ++ tight
- addParaStyle $ inTags True "style:style" (styleAttr ++ attrs) indent
- return pn
-
-paraListStyle :: Int -> State WriterState Int
-paraListStyle l = paraStyle "Text_20_body" [("style:list-style-name", "L" ++ show l )]
-
-paraTableStyles :: String -> Int -> [Alignment] -> [(String, Doc)]
-paraTableStyles _ _ [] = []
-paraTableStyles t s (a:xs)
- | AlignRight <- a = ( pName s, res s "end" ) : paraTableStyles t (s + 1) xs
- | AlignCenter <- a = ( pName s, res s "center") : paraTableStyles t (s + 1) xs
- | otherwise = ("Table_20_" ++ t, empty ) : paraTableStyles t s xs
- where pName sn = "P" ++ show (sn + 1)
- res sn x = inTags True "style:style"
- [ ("style:name" , pName sn )
- , ("style:family" , "paragraph" )
- , ("style:parent-style-name", "Table_20_" ++ t)] $
- selfClosingTag "style:paragraph-properties"
- [ ("fo:text-align", x)
- , ("style:justify-single-word", "false")]
-
-data TextStyle = Italic | Bold | Strike | Sub | Sup | SmallC deriving ( Eq )
-
-textStyleAttr :: TextStyle -> [(String,String)]
-textStyleAttr s
- | Italic <- s = [("fo:font-style" ,"italic" )
- ,("style:font-style-asian" ,"italic" )
- ,("style:font-style-complex" ,"italic" )]
- | Bold <- s = [("fo:font-weight" ,"bold" )
- ,("style:font-weight-asian" ,"bold" )
- ,("style:font-weight-complex" ,"bold" )]
- | Strike <- s = [("style:text-line-through-style", "solid" )]
- | Sub <- s = [("style:text-position" ,"sub 58%" )]
- | Sup <- s = [("style:text-position" ,"super 58%" )]
- | SmallC <- s = [("fo:font-variant" ,"small-caps")]
- | otherwise = []
-
-openDocumentNameSpaces :: [(String, String)]
-openDocumentNameSpaces =
- [ ("xmlns:office" , "urn:oasis:names:tc:opendocument:xmlns:office:1.0" )
- , ("xmlns:style" , "urn:oasis:names:tc:opendocument:xmlns:style:1.0" )
- , ("xmlns:text" , "urn:oasis:names:tc:opendocument:xmlns:text:1.0" )
- , ("xmlns:table" , "urn:oasis:names:tc:opendocument:xmlns:table:1.0" )
- , ("xmlns:draw" , "urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" )
- , ("xmlns:fo" , "urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0")
- , ("xmlns:xlink" , "http://www.w3.org/1999/xlink" )
- , ("xmlns:dc" , "http://purl.org/dc/elements/1.1/" )
- , ("xmlns:meta" , "urn:oasis:names:tc:opendocument:xmlns:meta:1.0" )
- , ("xmlns:number" , "urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" )
- , ("xmlns:svg" , "urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" )
- , ("xmlns:chart" , "urn:oasis:names:tc:opendocument:xmlns:chart:1.0" )
- , ("xmlns:dr3d" , "urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" )
- , ("xmlns:math" , "http://www.w3.org/1998/Math/MathML" )
- , ("xmlns:form" , "urn:oasis:names:tc:opendocument:xmlns:form:1.0" )
- , ("xmlns:script" , "urn:oasis:names:tc:opendocument:xmlns:script:1.0" )
- , ("xmlns:ooo" , "http://openoffice.org/2004/office" )
- , ("xmlns:ooow" , "http://openoffice.org/2004/writer" )
- , ("xmlns:oooc" , "http://openoffice.org/2004/calc" )
- , ("xmlns:dom" , "http://www.w3.org/2001/xml-events" )
- , ("xmlns:xforms" , "http://www.w3.org/2002/xforms" )
- , ("xmlns:xsd" , "http://www.w3.org/2001/XMLSchema" )
- , ("xmlns:xsi" , "http://www.w3.org/2001/XMLSchema-instance" )
- , ("office:version", "1.0" )
- ]
diff --git a/Text/Pandoc/Writers/RST.hs b/Text/Pandoc/Writers/RST.hs
deleted file mode 100644
index 91826cbcd..000000000
--- a/Text/Pandoc/Writers/RST.hs
+++ /dev/null
@@ -1,346 +0,0 @@
-{-
-Copyright (C) 2006-7 John MacFarlane <jgm@berkeley.edu>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.RST
- Copyright : Copyright (C) 2006-7 John MacFarlane
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Conversion of 'Pandoc' documents to reStructuredText.
-
-reStructuredText: <http://docutils.sourceforge.net/rst.html>
--}
-module Text.Pandoc.Writers.RST ( writeRST) where
-import Text.Pandoc.Definition
-import Text.Pandoc.Shared
-import Text.Pandoc.Blocks
-import Data.List ( isPrefixOf, isSuffixOf, drop, intersperse )
-import Text.PrettyPrint.HughesPJ hiding ( Str )
-import Control.Monad.State
-import Control.Applicative ( (<$>) )
-
-data WriterState =
- WriterState { stNotes :: [[Block]]
- , stLinks :: KeyTable
- , stImages :: KeyTable
- , stIncludes :: [String]
- , stOptions :: WriterOptions
- }
-
--- | Convert Pandoc to RST.
-writeRST :: WriterOptions -> Pandoc -> String
-writeRST opts document =
- let st = WriterState { stNotes = [], stLinks = [],
- stImages = [], stIncludes = [],
- stOptions = opts }
- in render $ evalState (pandocToRST document) st
-
--- | Return RST representation of document.
-pandocToRST :: Pandoc -> State WriterState Doc
-pandocToRST (Pandoc meta blocks) = do
- opts <- get >>= (return . stOptions)
- let before = writerIncludeBefore opts
- let after = writerIncludeAfter opts
- before' = if null before then empty else text before
- after' = if null after then empty else text after
- metaBlock <- metaToRST opts meta
- let head' = if (writerStandalone opts)
- then metaBlock $+$ text (writerHeader opts)
- else empty
- body <- blockListToRST blocks
- includes <- get >>= (return . concat . stIncludes)
- let includes' = if null includes then empty else text includes
- notes <- get >>= (notesToRST . reverse . stNotes)
- -- note that the notes may contain refs, so we do them first
- refs <- get >>= (keyTableToRST . reverse . stLinks)
- pics <- get >>= (pictTableToRST . reverse . stImages)
- return $ head' $+$ before' $+$ includes' $+$ body $+$ notes $+$ text "" $+$
- refs $+$ pics $+$ after'
-
--- | Return RST representation of reference key table.
-keyTableToRST :: KeyTable -> State WriterState Doc
-keyTableToRST refs = mapM keyToRST refs >>= return . vcat
-
--- | Return RST representation of a reference key.
-keyToRST :: ([Inline], (String, String))
- -> State WriterState Doc
-keyToRST (label, (src, _)) = do
- label' <- inlineListToRST label
- let label'' = if ':' `elem` (render label')
- then char '`' <> label' <> char '`'
- else label'
- return $ text ".. _" <> label'' <> text ": " <> text src
-
--- | Return RST representation of notes.
-notesToRST :: [[Block]] -> State WriterState Doc
-notesToRST notes =
- mapM (\(num, note) -> noteToRST num note) (zip [1..] notes) >>=
- return . vcat
-
--- | Return RST representation of a note.
-noteToRST :: Int -> [Block] -> State WriterState Doc
-noteToRST num note = do
- contents <- blockListToRST note
- let marker = text ".. [" <> text (show num) <> text "]"
- return $ marker $$ nest 3 contents
-
--- | Return RST representation of picture reference table.
-pictTableToRST :: KeyTable -> State WriterState Doc
-pictTableToRST refs = mapM pictToRST refs >>= return . vcat
-
--- | Return RST representation of a picture substitution reference.
-pictToRST :: ([Inline], (String, String))
- -> State WriterState Doc
-pictToRST (label, (src, _)) = do
- label' <- inlineListToRST label
- return $ text ".. " <> char '|' <> label' <> char '|' <> text " image:: " <>
- text src
-
--- | Take list of inline elements and return wrapped doc.
-wrappedRST :: WriterOptions -> [Inline] -> State WriterState Doc
-wrappedRST opts inlines = do
- lineBreakDoc <- inlineToRST LineBreak
- chunks <- mapM (wrapIfNeeded opts inlineListToRST)
- (splitBy LineBreak inlines)
- return $ vcat $ intersperse lineBreakDoc chunks
-
--- | Escape special characters for RST.
-escapeString :: String -> String
-escapeString = escapeStringUsing (backslashEscapes "`\\|*_")
-
--- | Convert bibliographic information into RST header.
-metaToRST :: WriterOptions -> Meta -> State WriterState Doc
-metaToRST opts (Meta title authors date) = do
- title' <- titleToRST title
- authors' <- authorsToRST authors
- date' <- dateToRST date
- let toc = if writerTableOfContents opts
- then text "" $+$ text ".. contents::"
- else empty
- return $ title' $+$ authors' $+$ date' $+$ toc
-
-titleToRST :: [Inline] -> State WriterState Doc
-titleToRST [] = return empty
-titleToRST lst = do
- contents <- inlineListToRST lst
- let titleLength = length $ render contents
- let border = text (replicate titleLength '=')
- return $ border $+$ contents $+$ border <> text "\n"
-
-authorsToRST :: [String] -> State WriterState Doc
-authorsToRST [] = return empty
-authorsToRST (first:rest) = do
- rest' <- authorsToRST rest
- return $ (text ":Author: " <> text first) $+$ rest'
-
-dateToRST :: String -> State WriterState Doc
-dateToRST [] = return empty
-dateToRST str = return $ text ":Date: " <> text (escapeString str)
-
--- | Convert Pandoc block element to RST.
-blockToRST :: Block -- ^ Block element
- -> State WriterState Doc
-blockToRST Null = return empty
-blockToRST (Plain inlines) = do
- opts <- get >>= (return . stOptions)
- wrappedRST opts inlines
-blockToRST (Para inlines) = do
- opts <- get >>= (return . stOptions)
- contents <- wrappedRST opts inlines
- return $ contents <> text "\n"
-blockToRST (RawHtml str) =
- let str' = if "\n" `isSuffixOf` str then str ++ "\n" else str ++ "\n\n" in
- return $ (text "\n.. raw:: html\n") $$ (nest 3 $ vcat $ map text (lines str'))
-blockToRST HorizontalRule = return $ text "--------------\n"
-blockToRST (Header level inlines) = do
- contents <- inlineListToRST inlines
- let headerLength = length $ render contents
- let headerChar = if level > 5 then ' ' else "=-~^'" !! (level - 1)
- let border = text $ replicate headerLength headerChar
- return $ contents $+$ border <> text "\n"
-blockToRST (CodeBlock (_,classes,_) str) = do
- opts <- stOptions <$> get
- let tabstop = writerTabStop opts
- if "haskell" `elem` classes && writerLiterateHaskell opts
- then return $ (vcat $ map (text "> " <>) $ map text (lines str)) <> text "\n"
- else return $ (text "::\n") $+$
- (nest tabstop $ vcat $ map text (lines str)) <> text "\n"
-blockToRST (BlockQuote blocks) = do
- tabstop <- get >>= (return . writerTabStop . stOptions)
- contents <- blockListToRST blocks
- return $ (nest tabstop contents) <> text "\n"
-blockToRST (Table caption _ widths headers rows) = do
- caption' <- inlineListToRST caption
- let caption'' = if null caption
- then empty
- else text "" $+$ (text "Table: " <> caption')
- headers' <- mapM blockListToRST headers
- let widthsInChars = map (floor . (78 *)) widths
- let hpipeBlocks blocks = hcatBlocks [beg, middle, end]
- where height = maximum (map heightOfBlock blocks)
- sep' = TextBlock 3 height (replicate height " | ")
- beg = TextBlock 2 height (replicate height "| ")
- end = TextBlock 2 height (replicate height " |")
- middle = hcatBlocks $ intersperse sep' blocks
- let makeRow = hpipeBlocks . zipWith docToBlock widthsInChars
- let head' = makeRow headers'
- rows' <- mapM (\row -> do cols <- mapM blockListToRST row
- return $ makeRow cols) rows
- let border ch = char '+' <> char ch <>
- (hcat $ intersperse (char ch <> char '+' <> char ch) $
- map (\l -> text $ replicate l ch) widthsInChars) <>
- char ch <> char '+'
- let body = vcat $ intersperse (border '-') $ map blockToDoc rows'
- return $ border '-' $+$ blockToDoc head' $+$ border '=' $+$ body $+$
- border '-' $$ caption'' $$ text ""
-blockToRST (BulletList items) = do
- contents <- mapM bulletListItemToRST items
- -- ensure that sublists have preceding blank line
- return $ text "" $+$ vcat contents <> text "\n"
-blockToRST (OrderedList (start, style', delim) items) = do
- let markers = if start == 1 && style' == DefaultStyle && delim == DefaultDelim
- then take (length items) $ repeat "#."
- else take (length items) $ orderedListMarkers
- (start, style', delim)
- let maxMarkerLength = maximum $ map length markers
- let markers' = map (\m -> let s = maxMarkerLength - length m
- in m ++ replicate s ' ') markers
- contents <- mapM (\(item, num) -> orderedListItemToRST item num) $
- zip markers' items
- -- ensure that sublists have preceding blank line
- return $ text "" $+$ vcat contents <> text "\n"
-blockToRST (DefinitionList items) = do
- contents <- mapM definitionListItemToRST items
- return $ (vcat contents) <> text "\n"
-
--- | Convert bullet list item (list of blocks) to RST.
-bulletListItemToRST :: [Block] -> State WriterState Doc
-bulletListItemToRST items = do
- contents <- blockListToRST items
- return $ (text "- ") <> contents
-
--- | Convert ordered list item (a list of blocks) to RST.
-orderedListItemToRST :: String -- ^ marker for list item
- -> [Block] -- ^ list item (list of blocks)
- -> State WriterState Doc
-orderedListItemToRST marker items = do
- contents <- blockListToRST items
- return $ (text marker <> char ' ') <> contents
-
--- | Convert defintion list item (label, list of blocks) to RST.
-definitionListItemToRST :: ([Inline], [Block]) -> State WriterState Doc
-definitionListItemToRST (label, items) = do
- label' <- inlineListToRST label
- contents <- blockListToRST items
- tabstop <- get >>= (return . writerTabStop . stOptions)
- return $ label' $+$ nest tabstop contents
-
--- | Convert list of Pandoc block elements to RST.
-blockListToRST :: [Block] -- ^ List of block elements
- -> State WriterState Doc
-blockListToRST blocks = mapM blockToRST blocks >>= return . vcat
-
--- | Convert list of Pandoc inline elements to RST.
-inlineListToRST :: [Inline] -> State WriterState Doc
-inlineListToRST lst = mapM inlineToRST lst >>= return . hcat
-
--- | Convert Pandoc inline element to RST.
-inlineToRST :: Inline -> State WriterState Doc
-inlineToRST (Emph lst) = do
- contents <- inlineListToRST lst
- return $ char '*' <> contents <> char '*'
-inlineToRST (Strong lst) = do
- contents <- inlineListToRST lst
- return $ text "**" <> contents <> text "**"
-inlineToRST (Strikeout lst) = do
- contents <- inlineListToRST lst
- return $ text "[STRIKEOUT:" <> contents <> char ']'
-inlineToRST (Superscript lst) = do
- contents <- inlineListToRST lst
- return $ text "\\ :sup:`" <> contents <> text "`\\ "
-inlineToRST (Subscript lst) = do
- contents <- inlineListToRST lst
- return $ text "\\ :sub:`" <> contents <> text "`\\ "
-inlineToRST (SmallCaps lst) = inlineListToRST lst
-inlineToRST (Quoted SingleQuote lst) = do
- contents <- inlineListToRST lst
- return $ char '\'' <> contents <> char '\''
-inlineToRST (Quoted DoubleQuote lst) = do
- contents <- inlineListToRST lst
- return $ char '"' <> contents <> char '"'
-inlineToRST (Cite _ lst) =
- inlineListToRST lst
-inlineToRST EmDash = return $ text "--"
-inlineToRST EnDash = return $ char '-'
-inlineToRST Apostrophe = return $ char '\''
-inlineToRST Ellipses = return $ text "..."
-inlineToRST (Code str) = return $ text $ "``" ++ str ++ "``"
-inlineToRST (Str str) = return $ text $ escapeString str
-inlineToRST (Math t str) = do
- includes <- get >>= (return . stIncludes)
- let rawMathRole = ".. role:: math(raw)\n" ++
- " :format: html latex\n"
- if not (rawMathRole `elem` includes)
- then modify $ \st -> st { stIncludes = rawMathRole : includes }
- else return ()
- return $ if t == InlineMath
- then text $ ":math:`$" ++ str ++ "$`"
- else text $ ":math:`$$" ++ str ++ "$$`"
-inlineToRST (TeX _) = return empty
-inlineToRST (HtmlInline _) = return empty
-inlineToRST (LineBreak) = do
- return $ empty -- there's no line break in RST
-inlineToRST Space = return $ char ' '
-inlineToRST (Link [Code str] (src, _)) | src == str ||
- src == "mailto:" ++ str = do
- let srcSuffix = if isPrefixOf "mailto:" src then drop 7 src else src
- return $ text srcSuffix
-inlineToRST (Link txt (src, tit)) = do
- useReferenceLinks <- get >>= (return . writerReferenceLinks . stOptions)
- linktext <- inlineListToRST $ normalizeSpaces txt
- if useReferenceLinks
- then do refs <- get >>= (return . stLinks)
- let refs' = if (txt, (src, tit)) `elem` refs
- then refs
- else (txt, (src, tit)):refs
- modify $ \st -> st { stLinks = refs' }
- return $ char '`' <> linktext <> text "`_"
- else return $ char '`' <> linktext <> text " <" <> text src <> text ">`_"
-inlineToRST (Image alternate (source, tit)) = do
- pics <- get >>= (return . stImages)
- let labelsUsed = map fst pics
- let txt = if null alternate || alternate == [Str ""] ||
- alternate `elem` labelsUsed
- then [Str $ "image" ++ show (length pics)]
- else alternate
- let pics' = if (txt, (source, tit)) `elem` pics
- then pics
- else (txt, (source, tit)):pics
- modify $ \st -> st { stImages = pics' }
- label <- inlineListToRST txt
- return $ char '|' <> label <> char '|'
-inlineToRST (Note contents) = do
- -- add to notes in state
- notes <- get >>= (return . stNotes)
- modify $ \st -> st { stNotes = contents:notes }
- let ref = show $ (length notes) + 1
- return $ text " [" <> text ref <> text "]_"
diff --git a/Text/Pandoc/Writers/RTF.hs b/Text/Pandoc/Writers/RTF.hs
deleted file mode 100644
index fc6cd1bf0..000000000
--- a/Text/Pandoc/Writers/RTF.hs
+++ /dev/null
@@ -1,291 +0,0 @@
-{-
-Copyright (C) 2006-7 John MacFarlane <jgm@berkeley.edu>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.RTF
- Copyright : Copyright (C) 2006-7 John MacFarlane
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Conversion of 'Pandoc' documents to RTF (rich text format).
--}
-module Text.Pandoc.Writers.RTF ( writeRTF ) where
-import Text.Pandoc.Definition
-import Text.Pandoc.Shared
-import Text.Pandoc.Readers.TeXMath
-import Data.List ( isSuffixOf, intercalate )
-import Data.Char ( ord, isDigit )
-
--- | Convert Pandoc to a string in rich text format.
-writeRTF :: WriterOptions -> Pandoc -> String
-writeRTF options (Pandoc meta blocks) =
- let head' = if writerStandalone options
- then rtfHeader (writerHeader options) meta
- else ""
- toc = if writerTableOfContents options
- then tableOfContents $ filter isHeaderBlock blocks
- else ""
- foot = if writerStandalone options then "\n}\n" else ""
- body = writerIncludeBefore options ++
- concatMap (blockToRTF 0 AlignDefault) blocks ++
- writerIncludeAfter options
- in head' ++ toc ++ body ++ foot
-
--- | Construct table of contents from list of header blocks.
-tableOfContents :: [Block] -> String
-tableOfContents headers =
- let contentsTree = hierarchicalize headers
- in concatMap (blockToRTF 0 AlignDefault) $
- [Header 1 [Str "Contents"],
- BulletList (map elementToListItem contentsTree)]
-
-elementToListItem :: Element -> [Block]
-elementToListItem (Blk _) = []
-elementToListItem (Sec sectext subsecs) = [Plain sectext] ++
- if null subsecs
- then []
- else [BulletList (map elementToListItem subsecs)]
-
--- | Convert unicode characters (> 127) into rich text format representation.
-handleUnicode :: String -> String
-handleUnicode [] = []
-handleUnicode (c:cs) =
- if ord c > 127
- then '\\':'u':(show (ord c)) ++ "?" ++ handleUnicode cs
- else c:(handleUnicode cs)
-
--- | Escape special characters.
-escapeSpecial :: String -> String
-escapeSpecial = escapeStringUsing (('\t',"\\tab "):(backslashEscapes "{\\}"))
-
--- | Escape strings as needed for rich text format.
-stringToRTF :: String -> String
-stringToRTF = handleUnicode . escapeSpecial
-
--- | Escape things as needed for code block in RTF.
-codeStringToRTF :: String -> String
-codeStringToRTF str = intercalate "\\line\n" $ lines (stringToRTF str)
-
--- | Make a paragraph with first-line indent, block indent, and space after.
-rtfParSpaced :: Int -- ^ space after (in twips)
- -> Int -- ^ block indent (in twips)
- -> Int -- ^ first line indent (relative to block) (in twips)
- -> Alignment -- ^ alignment
- -> String -- ^ string with content
- -> String
-rtfParSpaced spaceAfter indent firstLineIndent alignment content =
- let alignString = case alignment of
- AlignLeft -> "\\ql "
- AlignRight -> "\\qr "
- AlignCenter -> "\\qc "
- AlignDefault -> "\\ql "
- in "{\\pard " ++ alignString ++
- "\\f0 \\sa" ++ (show spaceAfter) ++ " \\li" ++ (show indent) ++
- " \\fi" ++ (show firstLineIndent) ++ " " ++ content ++ "\\par}\n"
-
--- | Default paragraph.
-rtfPar :: Int -- ^ block indent (in twips)
- -> Int -- ^ first line indent (relative to block) (in twips)
- -> Alignment -- ^ alignment
- -> String -- ^ string with content
- -> String
-rtfPar = rtfParSpaced 180
-
--- | Compact paragraph (e.g. for compact list items).
-rtfCompact :: Int -- ^ block indent (in twips)
- -> Int -- ^ first line indent (relative to block) (in twips)
- -> Alignment -- ^ alignment
- -> String -- ^ string with content
- -> String
-rtfCompact = rtfParSpaced 0
-
--- number of twips to indent
-indentIncrement :: Int
-indentIncrement = 720
-
-listIncrement :: Int
-listIncrement = 360
-
--- | Returns appropriate bullet list marker for indent level.
-bulletMarker :: Int -> String
-bulletMarker indent = case indent `mod` 720 of
- 0 -> "\\bullet "
- _ -> "\\endash "
-
--- | Returns appropriate (list of) ordered list markers for indent level.
-orderedMarkers :: Int -> ListAttributes -> [String]
-orderedMarkers indent (start, style, delim) =
- if style == DefaultStyle && delim == DefaultDelim
- then case indent `mod` 720 of
- 0 -> orderedListMarkers (start, Decimal, Period)
- _ -> orderedListMarkers (start, LowerAlpha, Period)
- else orderedListMarkers (start, style, delim)
-
--- | Returns RTF header.
-rtfHeader :: String -- ^ header text
- -> Meta -- ^ bibliographic information
- -> String
-rtfHeader headerText (Meta title authors date) =
- let titletext = if null title
- then ""
- else rtfPar 0 0 AlignCenter $
- "\\b \\fs36 " ++ inlineListToRTF title
- authorstext = if null authors
- then ""
- else rtfPar 0 0 AlignCenter (" " ++ (intercalate "\\" $
- map stringToRTF authors))
- datetext = if date == ""
- then ""
- else rtfPar 0 0 AlignCenter (" " ++ stringToRTF date) in
- let spacer = if null (titletext ++ authorstext ++ datetext)
- then ""
- else rtfPar 0 0 AlignDefault "" in
- headerText ++ titletext ++ authorstext ++ datetext ++ spacer
-
--- | Convert Pandoc block element to RTF.
-blockToRTF :: Int -- ^ indent level
- -> Alignment -- ^ alignment
- -> Block -- ^ block to convert
- -> String
-blockToRTF _ _ Null = ""
-blockToRTF indent alignment (Plain lst) =
- rtfCompact indent 0 alignment $ inlineListToRTF lst
-blockToRTF indent alignment (Para lst) =
- rtfPar indent 0 alignment $ inlineListToRTF lst
-blockToRTF indent alignment (BlockQuote lst) =
- concatMap (blockToRTF (indent + indentIncrement) alignment) lst
-blockToRTF indent _ (CodeBlock _ str) =
- rtfPar indent 0 AlignLeft ("\\f1 " ++ (codeStringToRTF str))
-blockToRTF _ _ (RawHtml _) = ""
-blockToRTF indent alignment (BulletList lst) = spaceAtEnd $
- concatMap (listItemToRTF alignment indent (bulletMarker indent)) lst
-blockToRTF indent alignment (OrderedList attribs lst) = spaceAtEnd $ concat $
- zipWith (listItemToRTF alignment indent) (orderedMarkers indent attribs) lst
-blockToRTF indent alignment (DefinitionList lst) = spaceAtEnd $
- concatMap (definitionListItemToRTF alignment indent) lst
-blockToRTF indent _ HorizontalRule =
- rtfPar indent 0 AlignCenter "\\emdash\\emdash\\emdash\\emdash\\emdash"
-blockToRTF indent alignment (Header level lst) = rtfPar indent 0 alignment $
- "\\b \\fs" ++ (show (40 - (level * 4))) ++ " " ++ inlineListToRTF lst
-blockToRTF indent alignment (Table caption aligns sizes headers rows) =
- tableRowToRTF True indent aligns sizes headers ++
- concatMap (tableRowToRTF False indent aligns sizes) rows ++
- rtfPar indent 0 alignment (inlineListToRTF caption)
-
-tableRowToRTF :: Bool -> Int -> [Alignment] -> [Double] -> [[Block]] -> String
-tableRowToRTF header indent aligns sizes cols =
- let columns = concat $ zipWith (tableItemToRTF indent) aligns cols
- totalTwips = 6 * 1440 -- 6 inches
- rightEdges = tail $ scanl (\sofar new -> sofar + floor (new * totalTwips))
- (0 :: Integer) sizes
- cellDefs = map (\edge -> (if header
- then "\\clbrdrb\\brdrs"
- else "") ++ "\\cellx" ++ show edge)
- rightEdges
- start = "{\n\\trowd \\trgaph120\n" ++ concat cellDefs ++ "\n" ++
- "\\trkeep\\intbl\n{\n"
- end = "}\n\\intbl\\row}\n"
- in start ++ columns ++ end
-
-tableItemToRTF :: Int -> Alignment -> [Block] -> String
-tableItemToRTF indent alignment item =
- let contents = concatMap (blockToRTF indent alignment) item
- in "{\\intbl " ++ contents ++ "\\cell}\n"
-
--- | Ensure that there's the same amount of space after compact
--- lists as after regular lists.
-spaceAtEnd :: String -> String
-spaceAtEnd str =
- if isSuffixOf "\\par}\n" str
- then (take ((length str) - 6) str) ++ "\\sa180\\par}\n"
- else str
-
--- | Convert list item (list of blocks) to RTF.
-listItemToRTF :: Alignment -- ^ alignment
- -> Int -- ^ indent level
- -> String -- ^ list start marker
- -> [Block] -- ^ list item (list of blocks)
- -> [Char]
-listItemToRTF alignment indent marker [] =
- rtfCompact (indent + listIncrement) (0 - listIncrement) alignment
- (marker ++ "\\tx" ++ (show listIncrement) ++ "\\tab ")
-listItemToRTF alignment indent marker list =
- let (first:rest) = map (blockToRTF (indent + listIncrement) alignment) list
- listMarker = "\\fi" ++ show (0 - listIncrement) ++ " " ++ marker ++ "\\tx" ++
- show listIncrement ++ "\\tab"
- insertListMarker ('\\':'f':'i':'-':d:xs) | isDigit d =
- listMarker ++ dropWhile isDigit xs
- insertListMarker ('\\':'f':'i':d:xs) | isDigit d =
- listMarker ++ dropWhile isDigit xs
- insertListMarker (x:xs) =
- x : insertListMarker xs
- insertListMarker [] = []
- -- insert the list marker into the (processed) first block
- in insertListMarker first ++ concat rest
-
--- | Convert definition list item (label, list of blocks) to RTF.
-definitionListItemToRTF :: Alignment -- ^ alignment
- -> Int -- ^ indent level
- -> ([Inline],[Block]) -- ^ list item (list of blocks)
- -> [Char]
-definitionListItemToRTF alignment indent (label, items) =
- let labelText = blockToRTF indent alignment (Plain label)
- itemsText = concatMap (blockToRTF (indent + listIncrement) alignment) items
- in labelText ++ itemsText
-
--- | Convert list of inline items to RTF.
-inlineListToRTF :: [Inline] -- ^ list of inlines to convert
- -> String
-inlineListToRTF lst = concatMap inlineToRTF lst
-
--- | Convert inline item to RTF.
-inlineToRTF :: Inline -- ^ inline to convert
- -> String
-inlineToRTF (Emph lst) = "{\\i " ++ (inlineListToRTF lst) ++ "}"
-inlineToRTF (Strong lst) = "{\\b " ++ (inlineListToRTF lst) ++ "}"
-inlineToRTF (Strikeout lst) = "{\\strike " ++ (inlineListToRTF lst) ++ "}"
-inlineToRTF (Superscript lst) = "{\\super " ++ (inlineListToRTF lst) ++ "}"
-inlineToRTF (Subscript lst) = "{\\sub " ++ (inlineListToRTF lst) ++ "}"
-inlineToRTF (SmallCaps lst) = "{\\scaps " ++ (inlineListToRTF lst) ++ "}"
-inlineToRTF (Quoted SingleQuote lst) =
- "\\u8216'" ++ (inlineListToRTF lst) ++ "\\u8217'"
-inlineToRTF (Quoted DoubleQuote lst) =
- "\\u8220\"" ++ (inlineListToRTF lst) ++ "\\u8221\""
-inlineToRTF Apostrophe = "\\u8217'"
-inlineToRTF Ellipses = "\\u8230?"
-inlineToRTF EmDash = "\\u8212-"
-inlineToRTF EnDash = "\\u8211-"
-inlineToRTF (Code str) = "{\\f1 " ++ (codeStringToRTF str) ++ "}"
-inlineToRTF (Str str) = stringToRTF str
-inlineToRTF (Math _ str) = inlineListToRTF $ readTeXMath str
-inlineToRTF (Cite _ lst) = inlineListToRTF lst
-inlineToRTF (TeX _) = ""
-inlineToRTF (HtmlInline _) = ""
-inlineToRTF (LineBreak) = "\\line "
-inlineToRTF Space = " "
-inlineToRTF (Link text (src, _)) =
- "{\\field{\\*\\fldinst{HYPERLINK \"" ++ (codeStringToRTF src) ++
- "\"}}{\\fldrslt{\\ul\n" ++ (inlineListToRTF text) ++ "\n}}}\n"
-inlineToRTF (Image _ (source, _)) =
- "{\\cf1 [image: " ++ source ++ "]\\cf0}"
-inlineToRTF (Note contents) =
- "{\\super\\chftn}{\\*\\footnote\\chftn\\~\\plain\\pard " ++
- (concatMap (blockToRTF 0 AlignDefault) contents) ++ "}"
diff --git a/Text/Pandoc/Writers/S5.hs b/Text/Pandoc/Writers/S5.hs
deleted file mode 100644
index 6f528503a..000000000
--- a/Text/Pandoc/Writers/S5.hs
+++ /dev/null
@@ -1,157 +0,0 @@
-{-# LANGUAGE CPP, TemplateHaskell #-}
-{-
-Copyright (C) 2006-7 John MacFarlane <jgm@berkeley.edu>
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.S5
- Copyright : Copyright (C) 2006-7 John MacFarlane
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Definitions for creation of S5 powerpoint-like HTML.
-(See <http://meyerweb.com/eric/tools/s5/>.)
--}
-module Text.Pandoc.Writers.S5 (
- -- * Strings
- s5Meta,
- s5Javascript,
- s5CSS,
- s5Links,
- -- * Functions
- writeS5,
- writeS5String,
- insertS5Structure
- ) where
-import Text.Pandoc.Shared ( WriterOptions )
-import Text.Pandoc.TH ( contentsOf )
-import Text.Pandoc.Writers.HTML ( writeHtml, writeHtmlString )
-import Text.Pandoc.Definition
-import Text.XHtml.Strict
-import System.FilePath ( (</>) )
-import Data.List ( intercalate )
-
-s5Meta :: String
-s5Meta = "<!-- configuration parameters -->\n<meta name=\"defaultView\" content=\"slideshow\" />\n<meta name=\"controlVis\" content=\"hidden\" />\n"
-
-s5Javascript :: String
-#ifndef __HADDOCK__
-s5Javascript = "<script type=\"text/javascript\">\n" ++
- $(contentsOf $ "data" </> "ui" </> "default" </> "slides.js.comment") ++
- $(contentsOf $ "data" </> "ui" </> "default" </> "slides.js.packed") ++ "</script>\n"
-#endif
-
-s5CoreCSS :: String
-#ifndef __HADDOCK__
-s5CoreCSS = $(contentsOf $ "data" </> "ui" </> "default" </> "s5-core.css")
-#endif
-
-s5FramingCSS :: String
-#ifndef __HADDOCK__
-s5FramingCSS = $(contentsOf $ "data" </> "ui" </> "default" </> "framing.css")
-#endif
-
-s5PrettyCSS :: String
-#ifndef __HADDOCK__
-s5PrettyCSS = $(contentsOf $ "data" </> "ui" </> "default" </> "pretty.css")
-#endif
-
-s5OperaCSS :: String
-#ifndef __HADDOCK__
-s5OperaCSS = $(contentsOf $ "data" </> "ui" </> "default" </> "opera.css")
-#endif
-
-s5OutlineCSS :: String
-#ifndef __HADDOCK__
-s5OutlineCSS = $(contentsOf $ "data" </> "ui" </> "default" </> "outline.css")
-#endif
-
-s5PrintCSS :: String
-#ifndef __HADDOCK__
-s5PrintCSS = $(contentsOf $ "data" </> "ui" </> "default" </> "print.css")
-#endif
-
-s5CSS :: String
-s5CSS = "<style type=\"text/css\" media=\"projection\" id=\"slideProj\">\n" ++ s5CoreCSS ++ "\n" ++ s5FramingCSS ++ "\n" ++ s5PrettyCSS ++ "\n</style>\n<style type=\"text/css\" media=\"projection\" id=\"operaFix\">\n" ++ s5OperaCSS ++ "\n</style>\n<style type=\"text/css\" media=\"screen\" id=\"outlineStyle\">\n" ++ s5OutlineCSS ++ "\n</style>\n<style type=\"text/css\" media=\"print\" id=\"slidePrint\">\n" ++ s5PrintCSS ++ "\n</style>\n"
-
-s5Links :: String
-s5Links = "<!-- style sheet links -->\n<link rel=\"stylesheet\" href=\"ui/default/slides.css\" type=\"text/css\" media=\"projection\" id=\"slideProj\" />\n<link rel=\"stylesheet\" href=\"ui/default/outline.css\" type=\"text/css\" media=\"screen\" id=\"outlineStyle\" />\n<link rel=\"stylesheet\" href=\"ui/default/print.css\" type=\"text/css\" media=\"print\" id=\"slidePrint\" />\n<link rel=\"stylesheet\" href=\"ui/default/opera.css\" type=\"text/css\" media=\"projection\" id=\"operaFix\" />\n<!-- S5 JS -->\n<script src=\"ui/default/slides.js\" type=\"text/javascript\"></script>\n"
-
--- | Converts Pandoc document to an S5 HTML presentation (Html structure).
-writeS5 :: WriterOptions -> Pandoc -> Html
-writeS5 options = (writeHtml options) . insertS5Structure
-
--- | Converts Pandoc document to an S5 HTML presentation (string).
-writeS5String :: WriterOptions -> Pandoc -> String
-writeS5String options = (writeHtmlString options) . insertS5Structure
-
--- | Inserts HTML needed for an S5 presentation (e.g. around slides).
-layoutDiv :: [Inline] -- ^ Title of document (for header or footer)
- -> String -- ^ Date of document (for header or footer)
- -> [Block] -- ^ List of block elements returned
-layoutDiv title' date = [(RawHtml "<div class=\"layout\">\n<div id=\"controls\"></div>\n<div id=\"currentSlide\"></div>\n<div id=\"header\"></div>\n<div id=\"footer\">\n"), (Header 1 [Str date]), (Header 2 title'), (RawHtml "</div>\n</div>\n")]
-
-presentationStart :: Block
-presentationStart = RawHtml "<div class=\"presentation\">\n\n"
-
-presentationEnd :: Block
-presentationEnd = RawHtml "</div>\n"
-
-slideStart :: Block
-slideStart = RawHtml "<div class=\"slide\">\n"
-
-slideEnd :: Block
-slideEnd = RawHtml "</div>\n"
-
--- | Returns 'True' if block is a Header 1.
-isH1 :: Block -> Bool
-isH1 (Header 1 _) = True
-isH1 _ = False
-
--- | Insert HTML around sections to make individual slides.
-insertSlides :: Bool -> [Block] -> [Block]
-insertSlides beginning blocks =
- let (beforeHead, rest) = break isH1 blocks in
- if (null rest) then
- if beginning then
- beforeHead
- else
- beforeHead ++ [slideEnd]
- else
- if beginning then
- beforeHead ++
- slideStart:(head rest):(insertSlides False (tail rest))
- else
- beforeHead ++
- slideEnd:slideStart:(head rest):(insertSlides False (tail rest))
-
--- | Insert blocks into 'Pandoc' for slide structure.
-insertS5Structure :: Pandoc -> Pandoc
-insertS5Structure (Pandoc meta' []) = Pandoc meta' []
-insertS5Structure (Pandoc (Meta title' authors date) blocks) =
- let slides = insertSlides True blocks
- firstSlide = if not (null title')
- then [slideStart, (Header 1 title'),
- (Header 3 [Str (intercalate ", " authors)]),
- (Header 4 [Str date]), slideEnd]
- else []
- newBlocks = (layoutDiv title' date) ++ presentationStart:firstSlide ++
- slides ++ [presentationEnd]
- in Pandoc (Meta title' authors date) newBlocks
diff --git a/Text/Pandoc/Writers/Texinfo.hs b/Text/Pandoc/Writers/Texinfo.hs
deleted file mode 100644
index 305a1a8d0..000000000
--- a/Text/Pandoc/Writers/Texinfo.hs
+++ /dev/null
@@ -1,474 +0,0 @@
-{-
-Copyright (C) 2008 John MacFarlane and Peter Wang
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
--}
-
-{- |
- Module : Text.Pandoc.Writers.Texinfo
- Copyright : Copyright (C) 2008 John MacFarlane and Peter Wang
- License : GNU GPL, version 2 or above
-
- Maintainer : John MacFarlane <jgm@berkeley.edu>
- Stability : alpha
- Portability : portable
-
-Conversion of 'Pandoc' format into Texinfo.
--}
-module Text.Pandoc.Writers.Texinfo ( writeTexinfo ) where
-import Text.Pandoc.Definition
-import Text.Pandoc.Shared
-import Text.Pandoc.Readers.TeXMath
-import Text.Printf ( printf )
-import Data.List ( isSuffixOf )
-import Data.Char ( chr, ord )
-import qualified Data.Set as S
-import Control.Monad.State
-import Text.PrettyPrint.HughesPJ hiding ( Str )
-
-data WriterState =
- WriterState { stIncludes :: S.Set String -- strings to include in header
- }
-
-{- TODO:
- - internal cross references a la HTML
- - generated .texi files don't work when run through texi2dvi
- -}
-
--- | Add line to header.
-addToHeader :: String -> State WriterState ()
-addToHeader str = do
- st <- get
- let includes = stIncludes st
- put st {stIncludes = S.insert str includes}
-
--- | Convert Pandoc to Texinfo.
-writeTexinfo :: WriterOptions -> Pandoc -> String
-writeTexinfo options document =
- render $ evalState (pandocToTexinfo options $ wrapTop document) $
- WriterState { stIncludes = S.empty }
-
--- | Add a "Top" node around the document, needed by Texinfo.
-wrapTop :: Pandoc -> Pandoc
-wrapTop (Pandoc (Meta title authors date) blocks) =
- Pandoc (Meta title authors date) (Header 0 title : blocks)
-
-pandocToTexinfo :: WriterOptions -> Pandoc -> State WriterState Doc
-pandocToTexinfo options (Pandoc meta blocks) = do
- main <- blockListToTexinfo blocks
- head' <- if writerStandalone options
- then texinfoHeader options meta
- else return empty
- let before = if null (writerIncludeBefore options)
- then empty
- else text (writerIncludeBefore options)
- let after = if null (writerIncludeAfter options)
- then empty
- else text (writerIncludeAfter options)
- let body = before $$ main $$ after
- -- XXX toc untested
- let toc = if writerTableOfContents options
- then text "@contents"
- else empty
- let foot = if writerStandalone options
- then text "@bye"
- else empty
- return $ head' $$ toc $$ body $$ foot
-
--- | Insert bibliographic information into Texinfo header.
-texinfoHeader :: WriterOptions -- ^ Options, including Texinfo header
- -> Meta -- ^ Meta with bibliographic information
- -> State WriterState Doc
-texinfoHeader options (Meta title authors date) = do
- titletext <- if null title
- then return empty
- else do
- t <- inlineListToTexinfo title
- return $ text "@title " <> t
- headerIncludes <- get >>= return . S.toList . stIncludes
- let extras = text $ unlines headerIncludes
- let authorstext = map makeAuthor authors
- let datetext = if date == ""
- then empty
- else text $ stringToTexinfo date
-
- let baseHeader = text $ writerHeader options
- let header = baseHeader $$ extras
- return $ text "\\input texinfo" $$
- header $$
- text "@ifnottex" $$
- text "@paragraphindent 0" $$
- text "@end ifnottex" $$
- text "@titlepage" $$
- titletext $$ vcat authorstext $$
- datetext $$
- text "@end titlepage"
-
-makeAuthor :: String -> Doc
-makeAuthor author = text $ "@author " ++ (stringToTexinfo author)
-
--- | Escape things as needed for Texinfo.
-stringToTexinfo :: String -> String
-stringToTexinfo = escapeStringUsing texinfoEscapes
- where texinfoEscapes = [ ('{', "@{")
- , ('}', "@}")
- , ('@', "@@")
- , (',', "@comma{}") -- only needed in argument lists
- , ('\160', "@ ")
- ]
-
--- | Puts contents into Texinfo command.
-inCmd :: String -> Doc -> Doc
-inCmd cmd contents = char '@' <> text cmd <> braces contents
-
--- | Convert Pandoc block element to Texinfo.
-blockToTexinfo :: Block -- ^ Block to convert
- -> State WriterState Doc
-
-blockToTexinfo Null = return empty
-
-blockToTexinfo (Plain lst) =
- inlineListToTexinfo lst
-
-blockToTexinfo (Para lst) =
- inlineListToTexinfo lst -- this is handled differently from Plain in blockListToTexinfo
-
-blockToTexinfo (BlockQuote lst) = do
- contents <- blockListToTexinfo lst
- return $ text "@quotation" $$
- contents $$
- text "@end quotation"
-
-blockToTexinfo (CodeBlock _ str) = do
- return $ text "@verbatim" $$
- vcat (map text (lines str)) $$
- text "@end verbatim\n"
-
-blockToTexinfo (RawHtml _) = return empty
-
-blockToTexinfo (BulletList lst) = do
- items <- mapM listItemToTexinfo lst
- return $ text "@itemize" $$
- vcat items $$
- text "@end itemize\n"
-
-blockToTexinfo (OrderedList (start, numstyle, _) lst) = do
- items <- mapM listItemToTexinfo lst
- return $ text "@enumerate " <> exemplar $$
- vcat items $$
- text "@end enumerate\n"
- where
- exemplar = case numstyle of
- DefaultStyle -> decimal
- Decimal -> decimal
- UpperRoman -> decimal -- Roman numerals not supported
- LowerRoman -> decimal
- UpperAlpha -> upperAlpha
- LowerAlpha -> lowerAlpha
- decimal = if start == 1
- then empty
- else text (show start)
- upperAlpha = text [chr $ ord 'A' + start - 1]
- lowerAlpha = text [chr $ ord 'a' + start - 1]
-
-blockToTexinfo (DefinitionList lst) = do
- items <- mapM defListItemToTexinfo lst
- return $ text "@table @asis" $$
- vcat items $$
- text "@end table\n"
-
-blockToTexinfo HorizontalRule =
- -- XXX can't get the equivalent from LaTeX.hs to work
- return $ text "@iftex" $$
- text "@bigskip@hrule@bigskip" $$
- text "@end iftex" $$
- text "@ifnottex" $$
- text (take 72 $ repeat '-') $$
- text "@end ifnottex"
-
-blockToTexinfo (Header 0 lst) = do
- txt <- if null lst
- then return $ text "Top"
- else inlineListToTexinfo lst
- return $ text "@node Top" $$
- text "@top " <> txt <> char '\n'
-
-blockToTexinfo (Header level lst) = do
- node <- inlineListForNode lst
- txt <- inlineListToTexinfo lst
- return $ if (level > 0) && (level <= 4)
- then text "\n@node " <> node <> char '\n' <>
- text (seccmd level) <> txt
- else txt
- where
- seccmd 1 = "@chapter "
- seccmd 2 = "@section "
- seccmd 3 = "@subsection "
- seccmd 4 = "@subsubsection "
- seccmd _ = error "illegal seccmd level"
-
-blockToTexinfo (Table caption aligns widths heads rows) = do
- headers <- tableHeadToTexinfo aligns heads
- captionText <- inlineListToTexinfo caption
- rowsText <- mapM (tableRowToTexinfo aligns) rows
- let colWidths = map (printf "%.2f ") widths
- let colDescriptors = concat colWidths
- let tableBody = text ("@multitable @columnfractions " ++ colDescriptors) $$
- headers $$
- vcat rowsText $$
- text "@end multitable"
- return $ if isEmpty captionText
- then tableBody <> char '\n'
- else text "@float" $$
- tableBody $$
- inCmd "caption" captionText $$
- text "@end float"
-
-tableHeadToTexinfo :: [Alignment]
- -> [[Block]]
- -> State WriterState Doc
-tableHeadToTexinfo = tableAnyRowToTexinfo "@headitem "
-
-tableRowToTexinfo :: [Alignment]
- -> [[Block]]
- -> State WriterState Doc
-tableRowToTexinfo = tableAnyRowToTexinfo "@item "
-
-tableAnyRowToTexinfo :: String
- -> [Alignment]
- -> [[Block]]
- -> State WriterState Doc
-tableAnyRowToTexinfo itemtype aligns cols =
- zipWithM alignedBlock aligns cols >>=
- return . (text itemtype $$) . foldl (\row item -> row $$
- (if isEmpty row then empty else text " @tab ") <> item) empty
-
-alignedBlock :: Alignment
- -> [Block]
- -> State WriterState Doc
--- XXX @flushleft and @flushright text won't get word wrapped. Since word
--- wrapping is more important than alignment, we ignore the alignment.
-alignedBlock _ = blockListToTexinfo
-{-
-alignedBlock AlignLeft col = do
- b <- blockListToTexinfo col
- return $ text "@flushleft" $$ b $$ text "@end flushleft"
-alignedBlock AlignRight col = do
- b <- blockListToTexinfo col
- return $ text "@flushright" $$ b $$ text "@end flushright"
-alignedBlock _ col = blockListToTexinfo col
--}
-
--- | Convert Pandoc block elements to Texinfo.
-blockListToTexinfo :: [Block]
- -> State WriterState Doc
-blockListToTexinfo [] = return $ empty
-blockListToTexinfo (x:xs) = do
- x' <- blockToTexinfo x
- case x of
- Header level _ -> do
- -- We need need to insert a menu for this node.
- let (before, after) = break isHeader xs
- before' <- blockListToTexinfo before
- let menu = if level < 4
- then collectNodes (level + 1) after
- else []
- lines' <- mapM makeMenuLine menu
- let menu' = if null lines'
- then empty
- else text "@menu" $$
- vcat lines' $$
- text "@end menu"
- after' <- blockListToTexinfo after
- return $ x' $$ before' $$ menu' $$ after'
- Para _ -> do
- xs' <- blockListToTexinfo xs
- case xs of
- ((CodeBlock _ _):_) -> return $ x' $$ xs'
- _ -> return $ x' $$ text "" $$ xs'
- _ -> do
- xs' <- blockListToTexinfo xs
- return $ x' $$ xs'
-
-isHeader :: Block -> Bool
-isHeader (Header _ _) = True
-isHeader _ = False
-
-collectNodes :: Int -> [Block] -> [Block]
-collectNodes _ [] = []
-collectNodes level (x:xs) =
- case x of
- (Header hl _) ->
- if hl < level
- then []
- else if hl == level
- then x : collectNodes level xs
- else collectNodes level xs
- _ ->
- collectNodes level xs
-
-makeMenuLine :: Block
- -> State WriterState Doc
-makeMenuLine (Header _ lst) = do
- txt <- inlineListForNode lst
- return $ text "* " <> txt <> text "::"
-makeMenuLine _ = error "makeMenuLine called with non-Header block"
-
-listItemToTexinfo :: [Block]
- -> State WriterState Doc
-listItemToTexinfo lst = blockListToTexinfo lst >>=
- return . (text "@item" $$)
-
-defListItemToTexinfo :: ([Inline], [Block])
- -> State WriterState Doc
-defListItemToTexinfo (term, def) = do
- term' <- inlineListToTexinfo term
- def' <- blockListToTexinfo def
- return $ text "@item " <> term' <> text "\n" $$ def'
-
--- | Convert list of inline elements to Texinfo.
-inlineListToTexinfo :: [Inline] -- ^ Inlines to convert
- -> State WriterState Doc
-inlineListToTexinfo lst = mapM inlineToTexinfo lst >>= return . hcat
-
--- | Convert list of inline elements to Texinfo acceptable for a node name.
-inlineListForNode :: [Inline] -- ^ Inlines to convert
- -> State WriterState Doc
-inlineListForNode lst = mapM inlineForNode lst >>= return . hcat
-
-inlineForNode :: Inline -> State WriterState Doc
-inlineForNode (Str str) = return $ text $ filter (not.disallowedInNode) str
-inlineForNode (Emph lst) = inlineListForNode lst
-inlineForNode (Strong lst) = inlineListForNode lst
-inlineForNode (Strikeout lst) = inlineListForNode lst
-inlineForNode (Superscript lst) = inlineListForNode lst
-inlineForNode (Subscript lst) = inlineListForNode lst
-inlineForNode (SmallCaps lst) = inlineListForNode lst
-inlineForNode (Quoted _ lst) = inlineListForNode lst
-inlineForNode (Cite _ lst) = inlineListForNode lst
-inlineForNode (Code str) = inlineForNode (Str str)
-inlineForNode Space = return $ char ' '
-inlineForNode EmDash = return $ text "---"
-inlineForNode EnDash = return $ text "--"
-inlineForNode Apostrophe = return $ char '\''
-inlineForNode Ellipses = return $ text "..."
-inlineForNode LineBreak = return empty
-inlineForNode (Math _ str) = inlineListForNode $ readTeXMath str
-inlineForNode (TeX _) = return empty
-inlineForNode (HtmlInline _) = return empty
-inlineForNode (Link lst _) = inlineListForNode lst
-inlineForNode (Image lst _) = inlineListForNode lst
-inlineForNode (Note _) = return empty
-
--- periods, commas, colons, and parentheses are disallowed in node names
-disallowedInNode :: Char -> Bool
-disallowedInNode c = c `elem` ".,:()"
-
--- | Convert inline element to Texinfo
-inlineToTexinfo :: Inline -- ^ Inline to convert
- -> State WriterState Doc
-
-inlineToTexinfo (Emph lst) =
- inlineListToTexinfo lst >>= return . inCmd "emph"
-
-inlineToTexinfo (Strong lst) =
- inlineListToTexinfo lst >>= return . inCmd "strong"
-
-inlineToTexinfo (Strikeout lst) = do
- addToHeader $ "@macro textstrikeout{text}\n" ++
- "~~\\text\\~~\n" ++
- "@end macro\n"
- contents <- inlineListToTexinfo lst
- return $ text "@textstrikeout{" <> contents <> text "}"
-
-inlineToTexinfo (Superscript lst) = do
- addToHeader $ "@macro textsuperscript{text}\n" ++
- "@iftex\n" ++
- "@textsuperscript{\\text\\}\n" ++
- "@end iftex\n" ++
- "@ifnottex\n" ++
- "^@{\\text\\@}\n" ++
- "@end ifnottex\n" ++
- "@end macro\n"
- contents <- inlineListToTexinfo lst
- return $ text "@textsuperscript{" <> contents <> char '}'
-
-inlineToTexinfo (Subscript lst) = do
- addToHeader $ "@macro textsubscript{text}\n" ++
- "@iftex\n" ++
- "@textsubscript{\\text\\}\n" ++
- "@end iftex\n" ++
- "@ifnottex\n" ++
- "_@{\\text\\@}\n" ++
- "@end ifnottex\n" ++
- "@end macro\n"
- contents <- inlineListToTexinfo lst
- return $ text "@textsubscript{" <> contents <> char '}'
-
-inlineToTexinfo (SmallCaps lst) =
- inlineListToTexinfo lst >>= return . inCmd "sc"
-
-inlineToTexinfo (Code str) = do
- return $ text $ "@code{" ++ stringToTexinfo str ++ "}"
-
-inlineToTexinfo (Quoted SingleQuote lst) = do
- contents <- inlineListToTexinfo lst
- return $ char '`' <> contents <> char '\''
-
-inlineToTexinfo (Quoted DoubleQuote lst) = do
- contents <- inlineListToTexinfo lst
- return $ text "``" <> contents <> text "''"
-
-inlineToTexinfo (Cite _ lst) =
- inlineListToTexinfo lst
-inlineToTexinfo Apostrophe = return $ char '\''
-inlineToTexinfo EmDash = return $ text "---"
-inlineToTexinfo EnDash = return $ text "--"
-inlineToTexinfo Ellipses = return $ text "@dots{}"
-inlineToTexinfo (Str str) = return $ text (stringToTexinfo str)
-inlineToTexinfo (Math _ str) = return $ inCmd "math" $ text str
-inlineToTexinfo (TeX str) = return $ text "@tex" $$ text str $$ text "@end tex"
-inlineToTexinfo (HtmlInline _) = return empty
-inlineToTexinfo (LineBreak) = return $ text "@*"
-inlineToTexinfo Space = return $ char ' '
-
-inlineToTexinfo (Link txt (src, _)) = do
- case txt of
- [Code x] | x == src -> -- autolink
- do return $ text $ "@url{" ++ x ++ "}"
- _ -> do contents <- inlineListToTexinfo txt
- let src1 = stringToTexinfo src
- return $ text ("@uref{" ++ src1 ++ ",") <> contents <>
- char '}'
-
-inlineToTexinfo (Image alternate (source, _)) = do
- content <- inlineListToTexinfo alternate
- return $ text ("@image{" ++ base ++ ",,,") <> content <> text "," <>
- text (ext ++ "}")
- where
- (revext, revbase) = break (=='.') (reverse source)
- ext = reverse revext
- base = case revbase of
- ('.' : rest) -> reverse rest
- _ -> reverse revbase
-
-inlineToTexinfo (Note contents) = do
- contents' <- blockListToTexinfo contents
- let rawnote = stripTrailingNewlines $ render contents'
- let optNewline = "@end verbatim" `isSuffixOf` rawnote
- return $ text "@footnote{" <>
- text rawnote <>
- (if optNewline then char '\n' else empty) <>
- char '}'