aboutsummaryrefslogtreecommitdiff
path: root/src/Text/Pandoc/Writers
diff options
context:
space:
mode:
Diffstat (limited to 'src/Text/Pandoc/Writers')
-rw-r--r--src/Text/Pandoc/Writers/HTML.hs80
1 files changed, 57 insertions, 23 deletions
diff --git a/src/Text/Pandoc/Writers/HTML.hs b/src/Text/Pandoc/Writers/HTML.hs
index 15286b0ea..5dcca4825 100644
--- a/src/Text/Pandoc/Writers/HTML.hs
+++ b/src/Text/Pandoc/Writers/HTML.hs
@@ -40,8 +40,7 @@ import Text.XHtml.Strict
type Notes = [Html]
type Ids = [String]
-type Toc = Html
-type WriterState = (Notes, Ids, Toc)
+type WriterState = (Notes, Ids)
-- | Convert Pandoc document to Html string.
writeHtmlString :: WriterOptions -> Pandoc -> String
@@ -54,7 +53,7 @@ writeHtmlString opts =
writeHtml :: WriterOptions -> Pandoc -> Html
writeHtml opts (Pandoc (Meta tit authors date) blocks) =
let titlePrefix = writerTitlePrefix opts
- topTitle = evalState (inlineListToHtml opts tit) ([],[],noHtml)
+ topTitle = evalState (inlineListToHtml opts tit) ([],[])
topTitle' = if null titlePrefix
then topTitle
else titlePrefix +++ " - " +++ topTitle
@@ -74,13 +73,15 @@ writeHtml opts (Pandoc (Meta tit authors date) blocks) =
else noHtml
headerBlocks = filter isHeaderBlock blocks
ids = uniqueIdentifiers $ map (\(Header _ lst) -> lst) headerBlocks
- toc = noHtml -- for debugging: tableOfContents headerBlocks ids
- (blocks', (revnotes,_,_)) =
- runState (blockListToHtml opts blocks) ([],ids,toc)
+ toc = if writerTableOfContents opts
+ then tableOfContents opts headerBlocks ids
+ else noHtml
+ (blocks', (revnotes,_)) =
+ runState (blockListToHtml opts blocks) ([],ids)
notes = reverse revnotes
before = primHtml $ writerIncludeBefore opts
after = primHtml $ writerIncludeAfter opts
- thebody = before +++ titleHeader +++ blocks' +++
+ thebody = before +++ titleHeader +++ toc +++ blocks' +++
footnoteSection opts notes +++ after
in if writerStandalone opts
then head +++ (body thebody)
@@ -91,6 +92,33 @@ isHeaderBlock :: Block -> Bool
isHeaderBlock (Header _ _) = True
isHeaderBlock _ = False
+-- | Construct table of contents from list of header blocks and identifiers.
+-- Assumes there are as many identifiers as header blocks.
+tableOfContents :: WriterOptions -> [Block] -> Ids -> Html
+tableOfContents opts headers ids =
+ let opts' = opts { writerIgnoreNotes = True }
+ contentsTree = hierarchicalize headers
+ contents = evalState (mapM (elementToListItem opts') contentsTree)
+ ([],ids)
+ in unordList ! [identifier "toc"] $ 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 opts (Blk _) = return noHtml
+elementToListItem opts (Sec headerText subsecs) = do
+ (notes, ids) <- get
+ let (id, rest) = if null ids
+ then ("",[])
+ else (head ids, tail ids)
+ put (notes, rest)
+ txt <- inlineListToHtml opts headerText
+ subHeads <- mapM (elementToListItem opts) subsecs
+ let subList = if null subHeads
+ then noHtml
+ else unordList subHeads
+ return $ (anchor ! [href ("#" ++ id)] $ txt) +++ subList
+
-- | Convert list of Note blocks to a footnote <div>.
-- Assumes notes are sorted.
footnoteSection :: WriterOptions -> Notes -> Html
@@ -167,12 +195,12 @@ inlineListToIdentifier (x:xs) =
-- | Return unique identifiers for list of inline lists.
uniqueIdentifiers :: [[Inline]] -> [String]
uniqueIdentifiers ls =
- reverse (foldl addIdentifier [] ls) where
- addIdentifier ids l =
+ let addIdentifier (nonuniqueIds, uniqueIds) l =
let new = inlineListToIdentifier l
- matches = length $ filter (== new) ids
+ matches = length $ filter (== new) nonuniqueIds
new' = new ++ if matches > 0 then show matches else ""
- in new':ids
+ in (new:nonuniqueIds, new':uniqueIds)
+ in reverse $ snd (foldl addIdentifier ([],[]) $ ls)
-- | Convert Pandoc block element to HTML.
blockToHtml :: WriterOptions -> Block -> State WriterState Html
@@ -199,19 +227,25 @@ blockToHtml opts block =
(return . blockquote)
else blockListToHtml opts blocks >>= (return . blockquote)
(Header level lst) -> do contents <- inlineListToHtml opts lst
- (notes, ids, toc) <- get
+ (notes, ids) <- get
let (id, rest) = if null ids
then ("", [])
else (head ids, tail ids)
- put (notes, rest, toc)
- return $ case level of
- 1 -> h1 contents ! [identifier id]
- 2 -> h2 contents ! [identifier id]
- 3 -> h3 contents ! [identifier id]
- 4 -> h4 contents ! [identifier id]
- 5 -> h5 contents ! [identifier id]
- 6 -> h6 contents ! [identifier id]
- _ -> paragraph contents ! [identifier id]
+ put (notes, rest)
+ let attribs = [identifier id]
+ let headerHtml = 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
+ let headerHtml' = if writerTableOfContents opts
+ then anchor ! [href "#toc"] $
+ headerHtml
+ else headerHtml
+ return headerHtml'
(BulletList lst) -> do contents <- mapM (blockListToHtml opts) lst
let attribs = if writerIncremental opts
then [theclass "incremental"]
@@ -313,11 +347,11 @@ inlineToHtml opts inline =
if null txt then [] else [alt alternate']
return $ image ! attributes
-- note: null title included, as in Markdown.pl
- (Note contents) -> do (notes, ids, toc) <- get
+ (Note contents) -> do (notes, ids) <- get
let number = (length notes) + 1
let ref = show number
htmlContents <- blockListToNote opts ref contents
- put (htmlContents:notes, ids, toc) -- push contents onto front of notes
+ put (htmlContents:notes, ids) -- push contents onto front of notes
return $ anchor ! [href ("#fn" ++ ref),
theclass "footnoteRef",
identifier ("fnref" ++ ref)] << sup << ref