add epub3 navigation parsing

This commit is contained in:
Marko Andjelic 2026-03-06 01:52:15 +00:00
commit ec47012b5f
Signed by: marko
GPG key ID: 9C5E99C8C682FB59

View file

@ -6,12 +6,16 @@ module Navigation
)
where
import Text.HTML.Scalpel (Scraper, attr, (@:), (@=), chroot, chroots, text, match)
import Types (NavItem(..), EpubType (..), InternalPath(..))
import Text.HTML.Scalpel (Scraper, attr, (@:), (@=), chroot, chroots, text, match, scrapeStringLike, scrape)
import Types (NavItem(..), EpubType (..), InternalPath(..), EpubEnv(..))
import Data.Maybe (fromMaybe)
import qualified Data.ByteString.Lazy as B
import Control.Applicative (optional)
import Control.Monad (guard)
import Codec.Archive.Zip
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import System.FilePath (normalise, takeDirectory, (</>))
-- ------------------------------------------------------------
-- EPub 3 navigation
@ -39,3 +43,24 @@ lndmkScraper labels =
where
navPredicate "epub:type" xs = EpubType (T.pack xs) `elem` labels
navPredicate _ _ = False
--------------------------------------------------------
-- dispatching --
--------------------------------------------------------
getLandmarks :: EpubEnv -> [NavItem]
getLandmarks env =
case eVersion env of
"2.0" -> []
"3.0" ->
case scrapeStringLike (opfXml env) navFinder of
Nothing -> []
Just relPath ->
let fullPath = normalise $ (baseDir env) </> relPath
in case findEntryByPath fullPath (archive env) of
Nothing -> []
Just entry ->
let content = TE.decodeUtf8 . B.toStrict $ fromEntry entry
types = map EpubType ["toc", "landmarks", "bodymatter"]
scrp = lndmkScraper types
in fromMaybe [] $ scrapeStringLike content scrp