diff options
| author | John MacFarlane <jgm@berkeley.edu> | 2022-11-06 14:11:32 -0800 |
|---|---|---|
| committer | John MacFarlane <jgm@berkeley.edu> | 2022-11-06 21:31:40 -0800 |
| commit | 04973586eb36773c3a1d149019edf291b527a719 (patch) | |
| tree | 144d761c0a029049968964a27bfc8ae226836ea2 /src | |
| parent | 9e2df2a718a3e9d8ebe5fac6e2d98466a5e04fce (diff) | |
Move SecInfo, toTOCTree to T.P.Chunks.
Also add `secPath` to `SecInfo`.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Text/Pandoc/Chunks.hs | 46 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/EPUB.hs | 33 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/Shared.hs | 39 |
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) |
