diff options
Diffstat (limited to 'src/Text/Pandoc/Writers/Haddock.hs')
-rw-r--r-- | src/Text/Pandoc/Writers/Haddock.hs | 370 |
1 files changed, 0 insertions, 370 deletions
diff --git a/src/Text/Pandoc/Writers/Haddock.hs b/src/Text/Pandoc/Writers/Haddock.hs deleted file mode 100644 index 945e4a0f1..000000000 --- a/src/Text/Pandoc/Writers/Haddock.hs +++ /dev/null @@ -1,370 +0,0 @@ -{-# LANGUAGE OverloadedStrings, TupleSections, ScopedTypeVariables #-} -{- -Copyright (C) 2014 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.Haddock - Copyright : Copyright (C) 2014 John MacFarlane - License : GNU GPL, version 2 or above - - Maintainer : John MacFarlane <jgm@berkeley.edu> - Stability : alpha - Portability : portable - -Conversion of 'Pandoc' documents to haddock markup. - -Haddock: <http://www.haskell.org/haddock/doc/html/> --} -module Text.Pandoc.Writers.Haddock (writeHaddock) where -import Text.Pandoc.Definition -import Text.Pandoc.Templates (renderTemplate') -import Text.Pandoc.Shared -import Text.Pandoc.Writers.Shared -import Text.Pandoc.Options -import Data.List ( intersperse, transpose ) -import Text.Pandoc.Pretty -import Control.Monad.State -import Text.Pandoc.Writers.Math (texMathToInlines) -import Network.URI (isURI) -import Data.Default -import Text.Pandoc.Class (PandocMonad, report) -import Text.Pandoc.Logging - -type Notes = [[Block]] -data WriterState = WriterState { stNotes :: Notes } -instance Default WriterState - where def = WriterState{ stNotes = [] } - --- | Convert Pandoc to Haddock. -writeHaddock :: PandocMonad m => WriterOptions -> Pandoc -> m String -writeHaddock opts document = - evalStateT (pandocToHaddock opts{ - writerWrapText = writerWrapText opts } document) def - --- | Return haddock representation of document. -pandocToHaddock :: PandocMonad m - => WriterOptions -> Pandoc -> StateT WriterState m String -pandocToHaddock opts (Pandoc meta blocks) = do - let colwidth = if writerWrapText opts == WrapAuto - then Just $ writerColumns opts - else Nothing - body <- blockListToHaddock opts blocks - st <- get - notes' <- notesToHaddock opts (reverse $ stNotes st) - let render' :: Doc -> String - render' = render colwidth - let main = render' $ body <> - (if isEmpty notes' then empty else blankline <> notes') - metadata <- metaToJSON opts - (fmap (render colwidth) . blockListToHaddock opts) - (fmap (render colwidth) . inlineListToHaddock opts) - meta - let context = defField "body" main - $ metadata - case writerTemplate opts of - Nothing -> return main - Just tpl -> return $ renderTemplate' tpl context - --- | Return haddock representation of notes. -notesToHaddock :: PandocMonad m - => WriterOptions -> [[Block]] -> StateT WriterState m Doc -notesToHaddock opts notes = - if null notes - then return empty - else do - contents <- blockToHaddock opts $ OrderedList (1,DefaultStyle,DefaultDelim) notes - return $ text "#notes#" <> blankline <> contents - --- | Escape special characters for Haddock. -escapeString :: String -> String -escapeString = escapeStringUsing haddockEscapes - where haddockEscapes = backslashEscapes "\\/'`\"@<" - --- | Convert Pandoc block element to haddock. -blockToHaddock :: PandocMonad m - => WriterOptions -- ^ Options - -> Block -- ^ Block element - -> StateT WriterState m Doc -blockToHaddock _ Null = return empty -blockToHaddock opts (Div _ ils) = do - contents <- blockListToHaddock opts ils - return $ contents <> blankline -blockToHaddock opts (Plain inlines) = do - contents <- inlineListToHaddock opts inlines - return $ contents <> cr --- title beginning with fig: indicates figure -blockToHaddock opts (Para [Image attr alt (src,'f':'i':'g':':':tit)]) = - blockToHaddock opts (Para [Image attr alt (src,tit)]) -blockToHaddock opts (Para inlines) = - -- TODO: if it contains linebreaks, we need to use a @...@ block - (<> blankline) `fmap` blockToHaddock opts (Plain inlines) -blockToHaddock opts (LineBlock lns) = - blockToHaddock opts $ linesToPara lns -blockToHaddock _ b@(RawBlock f str) - | f == "haddock" = do - return $ text str <> text "\n" - | otherwise = do - report $ BlockNotRendered b - return empty -blockToHaddock opts HorizontalRule = - return $ blankline <> text (replicate (writerColumns opts) '_') <> blankline -blockToHaddock opts (Header level (ident,_,_) inlines) = do - contents <- inlineListToHaddock opts inlines - let attr' = if null ident - then empty - else cr <> text "#" <> text ident <> text "#" - return $ nowrap (text (replicate level '=') <> space <> contents) - <> attr' <> blankline -blockToHaddock _ (CodeBlock (_,_,_) str) = - return $ prefixed "> " (text str) <> blankline --- Nothing in haddock corresponds to block quotes: -blockToHaddock opts (BlockQuote blocks) = - blockListToHaddock opts blocks --- Haddock doesn't have tables. Use haddock tables in code. -blockToHaddock opts (Table caption aligns widths headers rows) = do - caption' <- inlineListToHaddock opts caption - let caption'' = if null caption - then empty - else blankline <> caption' <> blankline - rawHeaders <- mapM (blockListToHaddock opts) headers - rawRows <- mapM (mapM (blockListToHaddock opts)) rows - let isSimple = all (==0) widths - let isPlainBlock (Plain _) = True - isPlainBlock _ = False - let hasBlocks = not (all isPlainBlock $ concat . concat $ headers:rows) - (nst,tbl) <- case True of - _ | isSimple -> fmap (nest 2,) $ - pandocTable opts (all null headers) aligns widths - rawHeaders rawRows - | not hasBlocks -> fmap (nest 2,) $ - pandocTable opts (all null headers) aligns widths - rawHeaders rawRows - | otherwise -> fmap (id,) $ - gridTable opts (all null headers) aligns widths - rawHeaders rawRows - return $ (prefixed "> " $ nst $ tbl $$ blankline $$ caption'') $$ blankline -blockToHaddock opts (BulletList items) = do - contents <- mapM (bulletListItemToHaddock opts) items - return $ cat contents <> blankline -blockToHaddock opts (OrderedList (start,_,delim) items) = do - let attribs = (start, Decimal, delim) - 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) -> orderedListItemToHaddock opts item num) $ - zip markers' items - return $ cat contents <> blankline -blockToHaddock opts (DefinitionList items) = do - contents <- mapM (definitionListItemToHaddock opts) items - return $ cat contents <> blankline - -pandocTable :: PandocMonad m - => WriterOptions -> Bool -> [Alignment] -> [Double] - -> [Doc] -> [[Doc]] -> StateT WriterState m Doc -pandocTable opts headless aligns widths rawHeaders rawRows = do - let isSimple = all (==0) widths - let alignHeader alignment = case alignment of - AlignLeft -> lblock - AlignCenter -> cblock - AlignRight -> rblock - AlignDefault -> lblock - let numChars = maximum . map offset - let widthsInChars = if isSimple - then map ((+2) . numChars) - $ transpose (rawHeaders : rawRows) - else map - (floor . (fromIntegral (writerColumns opts) *)) - widths - let makeRow = hcat . intersperse (lblock 1 (text " ")) . - (zipWith3 alignHeader aligns widthsInChars) - let rows' = map makeRow rawRows - let head' = makeRow rawHeaders - let maxRowHeight = maximum $ map height (head':rows') - let underline = cat $ intersperse (text " ") $ - map (\width -> text (replicate width '-')) widthsInChars - let border = if maxRowHeight > 1 - then text (replicate (sum widthsInChars + - length widthsInChars - 1) '-') - else if headless - then underline - else empty - let head'' = if headless - then empty - else border <> cr <> head' - let body = if maxRowHeight > 1 - then vsep rows' - else vcat rows' - let bottom = if headless - then underline - else border - return $ head'' $$ underline $$ body $$ bottom - -gridTable :: PandocMonad m - => WriterOptions -> Bool -> [Alignment] -> [Double] - -> [Doc] -> [[Doc]] -> StateT WriterState m Doc -gridTable opts headless _aligns widths headers' rawRows = do - let numcols = length headers' - let widths' = if all (==0) widths - then replicate numcols (1.0 / fromIntegral numcols) - else widths - let widthsInChars = map (floor . (fromIntegral (writerColumns opts) *)) widths' - let hpipeBlocks blocks = hcat [beg, middle, end] - where h = maximum (map height blocks) - sep' = lblock 3 $ vcat (map text $ replicate h " | ") - beg = lblock 2 $ vcat (map text $ replicate h "| ") - end = lblock 2 $ vcat (map text $ replicate h " |") - middle = chomp $ hcat $ intersperse sep' blocks - let makeRow = hpipeBlocks . zipWith lblock widthsInChars - let head' = makeRow headers' - let rows' = map (makeRow . map chomp) rawRows - 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 '-') rows' - let head'' = if headless - then empty - else head' $$ border '=' - return $ border '-' $$ head'' $$ body $$ border '-' - --- | Convert bullet list item (list of blocks) to haddock -bulletListItemToHaddock :: PandocMonad m - => WriterOptions -> [Block] -> StateT WriterState m Doc -bulletListItemToHaddock opts items = do - contents <- blockListToHaddock opts items - let sps = replicate (writerTabStop opts - 2) ' ' - let start = text ('-' : ' ' : sps) - -- remove trailing blank line if it is a tight list - let contents' = case reverse items of - (BulletList xs:_) | isTightList xs -> - chomp contents <> cr - (OrderedList _ xs:_) | isTightList xs -> - chomp contents <> cr - _ -> contents - return $ hang (writerTabStop opts) start $ contents' <> cr - --- | Convert ordered list item (a list of blocks) to haddock -orderedListItemToHaddock :: PandocMonad m - => WriterOptions -- ^ options - -> String -- ^ list item marker - -> [Block] -- ^ list item (list of blocks) - -> StateT WriterState m Doc -orderedListItemToHaddock opts marker items = do - contents <- blockListToHaddock opts items - let sps = case length marker - writerTabStop opts of - n | n > 0 -> text $ replicate n ' ' - _ -> text " " - let start = text marker <> sps - return $ hang (writerTabStop opts) start $ contents <> cr - --- | Convert definition list item (label, list of blocks) to haddock -definitionListItemToHaddock :: PandocMonad m - => WriterOptions - -> ([Inline],[[Block]]) - -> StateT WriterState m Doc -definitionListItemToHaddock opts (label, defs) = do - labelText <- inlineListToHaddock opts label - defs' <- mapM (mapM (blockToHaddock opts)) defs - let contents = vcat $ map (\d -> hang 4 empty $ vcat d <> cr) defs' - return $ nowrap (brackets labelText) <> cr <> contents <> cr - --- | Convert list of Pandoc block elements to haddock -blockListToHaddock :: PandocMonad m - => WriterOptions -- ^ Options - -> [Block] -- ^ List of block elements - -> StateT WriterState m Doc -blockListToHaddock opts blocks = - mapM (blockToHaddock opts) blocks >>= return . cat - --- | Convert list of Pandoc inline elements to haddock. -inlineListToHaddock :: PandocMonad m - => WriterOptions -> [Inline] -> StateT WriterState m Doc -inlineListToHaddock opts lst = - mapM (inlineToHaddock opts) lst >>= return . cat - --- | Convert Pandoc inline element to haddock. -inlineToHaddock :: PandocMonad m - => WriterOptions -> Inline -> StateT WriterState m Doc -inlineToHaddock opts (Span (ident,_,_) ils) = do - contents <- inlineListToHaddock opts ils - if not (null ident) && null ils - then return $ "#" <> text ident <> "#" - else return contents -inlineToHaddock opts (Emph lst) = do - contents <- inlineListToHaddock opts lst - return $ "/" <> contents <> "/" -inlineToHaddock opts (Strong lst) = do - contents <- inlineListToHaddock opts lst - return $ "__" <> contents <> "__" -inlineToHaddock opts (Strikeout lst) = do - contents <- inlineListToHaddock opts lst - -- not supported in haddock, but we fake it: - return $ "~~" <> contents <> "~~" --- not supported in haddock: -inlineToHaddock opts (Superscript lst) = inlineListToHaddock opts lst --- not supported in haddock: -inlineToHaddock opts (Subscript lst) = inlineListToHaddock opts lst --- not supported in haddock: -inlineToHaddock opts (SmallCaps lst) = inlineListToHaddock opts lst -inlineToHaddock opts (Quoted SingleQuote lst) = do - contents <- inlineListToHaddock opts lst - return $ "‘" <> contents <> "’" -inlineToHaddock opts (Quoted DoubleQuote lst) = do - contents <- inlineListToHaddock opts lst - return $ "“" <> contents <> "”" -inlineToHaddock _ (Code _ str) = - return $ "@" <> text (escapeString str) <> "@" -inlineToHaddock _ (Str str) = do - return $ text $ escapeString str -inlineToHaddock opts (Math mt str) = do - let adjust x = case mt of - DisplayMath -> cr <> x <> cr - InlineMath -> x - adjust <$> (lift (texMathToInlines mt str) >>= inlineListToHaddock opts) -inlineToHaddock _ il@(RawInline f str) - | f == "haddock" = return $ text str - | otherwise = do - report $ InlineNotRendered il - return empty --- no line break in haddock (see above on CodeBlock) -inlineToHaddock _ LineBreak = return cr -inlineToHaddock opts SoftBreak = - case writerWrapText opts of - WrapAuto -> return space - WrapNone -> return space - WrapPreserve -> return cr -inlineToHaddock _ Space = return space -inlineToHaddock opts (Cite _ lst) = inlineListToHaddock opts lst -inlineToHaddock _ (Link _ txt (src, _)) = do - let linktext = text $ escapeString $ stringify txt - let useAuto = isURI src && - case txt of - [Str s] | escapeURI s == src -> True - _ -> False - return $ nowrap $ "<" <> text src <> - (if useAuto then empty else space <> linktext) <> ">" -inlineToHaddock opts (Image attr alternate (source, tit)) = do - linkhaddock <- inlineToHaddock opts (Link attr alternate (source, tit)) - return $ "<" <> linkhaddock <> ">" --- haddock doesn't have notes, but we can fake it: -inlineToHaddock opts (Note contents) = do - modify (\st -> st{ stNotes = contents : stNotes st }) - st <- get - let ref = text $ writerIdentifierPrefix opts ++ show (length $ stNotes st) - return $ "<#notes [" <> ref <> "]>" |