summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJohn MacFarlane <jgm@berkeley.edu>2022-11-06 14:11:32 -0800
committerJohn MacFarlane <jgm@berkeley.edu>2022-11-06 21:31:40 -0800
commit04973586eb36773c3a1d149019edf291b527a719 (patch)
tree144d761c0a029049968964a27bfc8ae226836ea2 /src
parent9e2df2a718a3e9d8ebe5fac6e2d98466a5e04fce (diff)
Move SecInfo, toTOCTree to T.P.Chunks.
Also add `secPath` to `SecInfo`.
Diffstat (limited to 'src')
-rw-r--r--src/Text/Pandoc/Chunks.hs46
-rw-r--r--src/Text/Pandoc/Writers/EPUB.hs33
-rw-r--r--src/Text/Pandoc/Writers/Shared.hs39
3 files changed, 68 insertions, 50 deletions
diff --git a/src/Text/Pandoc/Chunks.hs b/src/Text/Pandoc/Chunks.hs
index 9be710c63..c25ed50f9 100644
--- a/src/Text/Pandoc/Chunks.hs
+++ b/src/Text/Pandoc/Chunks.hs
@@ -21,21 +21,22 @@ module Text.Pandoc.Chunks
, ChunkedDoc(..)
, PathTemplate(..)
, splitIntoChunks
+ , toTOCTree
+ , SecInfo(..)
) where
import Text.Pandoc.Definition
import Text.Pandoc.Shared (makeSections, stringify)
import Text.Pandoc.Walk (Walkable(..))
import Data.Text (Text)
import Text.Printf (printf)
-import Data.Maybe (fromMaybe)
+import Data.Maybe (fromMaybe, isNothing)
import qualified Data.Map as M
import qualified Data.Text as T
import Data.List (find)
import Data.String (IsString)
import GHC.Generics (Generic)
import Text.HTML.TagSoup (Tag (TagOpen), fromAttrib, parseTags)
-import Text.Pandoc.Writers.Shared (toTOCTree, SecInfo(..))
-import Data.Tree (Tree)
+import Data.Tree (Tree(..))
-- | Split 'Pandoc' into 'Chunk's, e.g. for conversion into
-- a set of HTML pages or EPUB chapters.
@@ -324,3 +325,42 @@ instance Walkable Block ChunkedDoc where
return $ doc{ chunkedMeta = meta'
, chunkedChunks = chunks' }
+-- | Data for a section in a hierarchical document.
+data SecInfo =
+ SecInfo
+ { secTitle :: [Inline]
+ , secNumber :: Maybe Text
+ , secId :: Text
+ , secPath :: Text
+ , secLevel :: Int
+ } deriving (Show, Ord, Eq)
+
+instance Walkable Inline SecInfo where
+ query f sec = query f (secTitle sec)
+ walk f sec = sec{ secTitle = walk f (secTitle sec) }
+ walkM f sec = do
+ st <- walkM f (secTitle sec)
+ return sec{ secTitle = st }
+
+-- | Create tree of sections with titles, links, and numbers,
+-- in a form that can be turned into a table of contents.
+-- Presupposes that the '[Block]' is the output of 'makeSections'.
+toTOCTree :: [Block] -> Tree SecInfo
+toTOCTree bs =
+ Node SecInfo{ secTitle = []
+ , secNumber = Nothing
+ , secId = ""
+ , secPath = ""
+ , secLevel = 0 } $ foldr go [] bs
+ where
+ go :: Block -> [Tree SecInfo] -> [Tree SecInfo]
+ go (Div (ident,_,_) (Header lev (_,classes,kvs) ils : subsecs))
+ | not (isNothing (lookup "number" kvs) && "unlisted" `elem` classes)
+ = ((Node SecInfo{ secTitle = ils
+ , secNumber = lookup "number" kvs
+ , secId = ident
+ , secPath = ""
+ , secLevel = lev } (foldr go [] subsecs)) :)
+ go (Div _ [d@Div{}]) = go d -- #8402
+ go _ = id
+
diff --git a/src/Text/Pandoc/Writers/EPUB.hs b/src/Text/Pandoc/Writers/EPUB.hs
index f058e0a0a..0dffb9f51 100644
--- a/src/Text/Pandoc/Writers/EPUB.hs
+++ b/src/Text/Pandoc/Writers/EPUB.hs
@@ -36,6 +36,7 @@ import System.FilePath (takeExtension, takeFileName, makeRelative)
import Text.HTML.TagSoup (Tag (TagOpen), fromAttrib, parseTags)
import Text.Pandoc.Builder (fromList, setMeta)
import Text.Pandoc.Writers.Shared (ensureValidXmlIdentifiers)
+import Data.Tree (Tree(..))
import Text.Pandoc.Class (PandocMonad, report)
import qualified Text.Pandoc.Class.PandocPure as P
import Text.Pandoc.Data (readDataFile)
@@ -50,17 +51,19 @@ import Text.Pandoc.URI (urlEncode)
import Text.Pandoc.Options (EPUBVersion (..), HTMLMathMethod (..),
ObfuscationMethod (NoObfuscation), WrapOption (..),
WriterOptions (..))
-import Text.Pandoc.Shared (makeSections, normalizeDate, renderTags',
+import Text.Pandoc.Shared (normalizeDate, renderTags',
stringify, uniqueIdent, tshow)
import qualified Text.Pandoc.UTF8 as UTF8
import Text.Pandoc.UUID (getRandomUUID)
-import Text.Pandoc.Walk (query, walk, walkM)
+import Text.Pandoc.Walk (walk, walkM)
import Text.Pandoc.Writers.HTML (writeHtmlStringForEPUB)
import Text.Printf (printf)
import Text.Pandoc.XML.Light
import Text.Pandoc.XML (escapeStringForXML)
import Text.DocTemplates (FromContext(lookupContext), Context(..),
ToContext(toVal), Val(..))
+import Text.Pandoc.Chunks (splitIntoChunks, Chunk(..), ChunkedDoc(..),
+ SecInfo(..))
-- A Chapter includes a list of blocks.
newtype Chapter = Chapter [Block]
@@ -693,11 +696,14 @@ pandocToEPUB version opts doc = do
navPointNode _ _ = return []
-- Create the tocEntry from the metadata together with the sections and title.
- tocEntry <- createTocEntry meta metadata plainTitle secs navPointNode
+ tocEntry <- createTocEntry meta metadata plainTitle (chunkedTOC chunkedDoc)
+ navPointNode
-- Create the navEntry using the metadata, all of the various writer options,
-- the CSS and HTML helpers, the document and toc title as well as the epub version and all of the sections
- navEntry <- createNavEntry meta metadata opts' True vars cssvars writeHtml tocTitle version secs navPointNode
+ navEntry <- createNavEntry meta metadata opts' True vars cssvars
+ writeHtml tocTitle version (chunkedTOC chunkedDoc)
+ navPointNode
-- mimetype
mimetypeEntry <- mkEntry "mimetype" $
@@ -920,13 +926,14 @@ createChaptersAndReftable chapterHeaderLevel secs = (chapters, reftable)
chapters'
createTocEntry :: PandocMonad m =>
- Meta
- -> EPUBMetadata
- -> Text
- -> [Block]
- -> ((Int -> [Inline] -> T.Text -> [Element] -> Element) -> Block -> StateT Int m [Element])
- -> StateT EPUBState m Entry
-createTocEntry meta metadata plainTitle secs navPointNode = do
+ Meta
+ -> EPUBMetadata
+ -> Text
+ -> Tree SecInfo
+ -> ((Int -> [Inline] -> T.Text -> [Element] -> Element)
+ -> Block -> StateT Int m [Element])
+ -> StateT EPUBState m Entry
+createTocEntry meta metadata plainTitle toctree navPointNode = do
let navMapFormatter :: Int -> [Inline] -> T.Text -> [Element] -> Element
navMapFormatter n tit src subs = unode "navPoint" !
[("id", "navPoint-" <> tshow n)] $
@@ -978,11 +985,11 @@ createNavEntry :: PandocMonad m =>
-> (WriterOptions -> Pandoc -> m B8.ByteString)
-> Text
-> EPUBVersion
- -> [Block]
+ -> Tree SecInfo
-> ((Int -> [Inline] -> T.Text -> [Element] -> Element) -> Block -> StateT Int m [Element])
-> StateT EPUBState m Entry
createNavEntry meta metadata opts includeTitlePage
- vars cssvars writeHtml tocTitle version secs navPointNode = do
+ vars cssvars writeHtml tocTitle version toctree navPointNode = do
let navXhtmlFormatter :: Int -> [Inline] -> T.Text -> [Element] -> Element
navXhtmlFormatter n tit src subs = unode "li" !
[("id", "toc-li-" <> tshow n)] $
diff --git a/src/Text/Pandoc/Writers/Shared.hs b/src/Text/Pandoc/Writers/Shared.hs
index 362c4ac22..d56efe398 100644
--- a/src/Text/Pandoc/Writers/Shared.hs
+++ b/src/Text/Pandoc/Writers/Shared.hs
@@ -1,4 +1,5 @@
{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE OverloadedStrings #-}
{- |
@@ -34,8 +35,6 @@ module Text.Pandoc.Writers.Shared (
, toSubscript
, toSuperscript
, toTableOfContents
- , toTOCTree
- , SecInfo(..)
, endsWithPlain
, toLegacyTable
, splitSentences
@@ -44,7 +43,6 @@ module Text.Pandoc.Writers.Shared (
where
import Safe (lastMay)
import qualified Data.ByteString.Lazy as BL
-import Data.Maybe (isNothing)
import Control.Monad (zipWithM)
import Data.Aeson (ToJSON (..), encode)
import Data.Char (chr, ord, isSpace, isLetter)
@@ -59,11 +57,12 @@ import Text.Pandoc.Definition
import Text.Pandoc.Options
import Text.DocLayout
import Text.Pandoc.Shared (stringify, makeSections, blocksToInlines)
-import Text.Pandoc.Walk (walk)
+import Text.Pandoc.Walk (Walkable(..))
import qualified Text.Pandoc.UTF8 as UTF8
import Text.Pandoc.XML (escapeStringForXML)
import Text.DocTemplates (Context(..), Val(..), TemplateTarget,
ToContext(..), FromContext(..))
+import Text.Pandoc.Chunks (toTOCTree, SecInfo(..))
import Data.Tree
-- | Create template Context from a 'Meta' and an association list
@@ -435,34 +434,6 @@ toTableOfContents opts =
. toTOCTree
. makeSections (writerNumberSections opts) Nothing
-data SecInfo =
- SecInfo
- { secTitle :: [Inline]
- , secNumber :: Maybe Text
- , secIdent :: Text
- , secLevel :: Int
- } deriving (Show, Ord, Eq)
-
--- | Create tree of sections with titles, links, and numbers,
--- in a form that can be turned into a table of contents.
--- Presupposes that the '[Block]' is the output of 'makeSections'.
-toTOCTree :: [Block] -> Tree SecInfo
-toTOCTree bs =
- Node SecInfo{ secTitle = []
- , secNumber = Nothing
- , secIdent = ""
- , secLevel = 0 } $ foldr go [] bs
- where
- go :: Block -> [Tree SecInfo] -> [Tree SecInfo]
- go (Div (ident,_,_) (Header lev (_,classes,kvs) ils : subsecs))
- | not (isNothing (lookup "number" kvs) && "unlisted" `elem` classes)
- = ((Node SecInfo{ secTitle = ils
- , secNumber = lookup "number" kvs
- , secIdent = ident
- , secLevel = lev } (foldr go [] subsecs)) :)
- go (Div _ [d@Div{}]) = go d -- #8402
- go _ = id
-
tocEntryToLink :: SecInfo -> [Inline]
tocEntryToLink secinfo = headerLink
where
@@ -473,12 +444,12 @@ tocEntryToLink secinfo = headerLink
clean (Link _ xs _) = xs
clean (Note _) = []
clean x = [x]
- ident = secIdent secinfo
+ ident = secId secinfo
headerText = addNumber $ walk (concatMap clean) (secTitle secinfo)
headerLink = if T.null ident
then headerText
else [Link ("toc-" <> ident, [], [])
- headerText ("#" <> ident, "")]
+ headerText (secPath secinfo <> "#" <> ident, "")]
tocToList :: Int -> Tree SecInfo -> Block
tocToList tocDepth (Node _ subtrees)