{-# LANGUAGE OverloadedStrings #-} -- | Scrapers that turn a table-of-contents document into a /tree/ of raw -- entries. Two formats are supported: -- -- * EPUB 2 — an NCX file with nested @\@s. -- * EPUB 3 — a nav document with nested @\@\/@\@ lists. -- -- Hrefs are left relative here; 'EpubParser' resolves them against the TOC -- document's location. We use 'atDepth' so each recursion level only picks up -- its /direct/ children (otherwise scalpel's descendant matching would flatten -- the hierarchy and duplicate nested nodes). module Navigation ( RawToc (..), navDocHref, ncxToc, navToc, guideToc, ) where import Control.Applicative ((<|>)) import qualified Data.Text as T import Text.HTML.Scalpel (Scraper, atDepth, attr, chroot, chroots, scrapeStringLike, text, (@:), (@=)) -- | A TOC node with an as-yet-unresolved (document-relative) href. data RawToc = RawToc { rawLabel :: T.Text, rawHref :: FilePath, rawChildren :: [RawToc] } deriving (Show) -- | The EPUB 3 navigation document's href, declared in the OPF manifest as the -- item carrying @properties="nav"@. navDocHref :: String -> Maybe FilePath navDocHref opf = scrapeStringLike opf (attr "href" ("item" @: ["properties" @= "nav"])) -- | EPUB 2: walk the @\@ of nested @\@s. ncxToc :: Scraper T.Text [RawToc] ncxToc = chroot "navMap" points where points = chroots ("navPoint" `atDepth` 1) node node = RawToc <$> (T.strip <$> text ("navLabel" `atDepth` 1)) <*> (T.unpack <$> attr "src" ("content" `atDepth` 1)) <*> points -- | EPUB 3: walk @\