table of contents integration

This commit is contained in:
Marko Andjelic 2026-02-08 03:02:54 +00:00
commit 4ddb090b2f
3 changed files with 17 additions and 14 deletions

View file

@ -14,6 +14,8 @@ import Codec.Archive.Zip (Archive, findEntryByPath, fromEntry, toArchive)
import qualified Codec.Epub.Data.Manifest as DMan
import qualified Codec.Epub.Data.Spine as DSpin
import Codec.Epub.Parse (getManifest, getMetadata, getSpine)
import Control.Applicative ((<|>))
import Control.Monad (guard)
import Control.Monad.Except (runExceptT)
import Control.Monad.Reader (MonadReader (ask), liftIO)
import qualified Data.ByteString.Base64 as B64
@ -24,9 +26,7 @@ import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import System.FilePath (normalise, takeDirectory, (</>))
import Text.HTML.Scalpel (Scraper, ScraperT, anySelector, attr, chroot, chroots, html, innerHTML, scrapeStringLike, text)
import Control.Applicative ((<|>))
import Types (EpubEnv(..), EpubAction, Chapter(..))
import Control.Monad (guard)
import Types (Chapter (..), EpubAction, EpubEnv (..))
openEpub :: FilePath -> IO (Either String EpubEnv)
openEpub path = do
@ -69,7 +69,7 @@ getRootPath :: T.Text -> Maybe String
getRootPath rawhtml =
scrapeStringLike rawhtml $ T.unpack <$> attr "full-path" "rootfile"
resolveSpine :: EpubAction [FilePath]
resolveSpine :: EpubAction [(FilePath, T.Text)]
resolveSpine = do
env <- ask
let xmlStr = opfXml env
@ -77,26 +77,30 @@ resolveSpine = do
let (DMan.Manifest items) = eManifest env
case spineResult of
Right (DSpin.Spine _ refs) -> do
Right (DSpin.Spine maybeTocId refs) -> do
let lookupHref ident = DMan.mfiHref <$> find (\mi -> DMan.mfiId mi == ident) items
pure [p | ref <- refs, let ident = DSpin.siIdRef ref, Just p <- [lookupHref ident]]
let maybeTocPath = lookupHref maybeTocId
liftIO $ putStrLn $ "Found TOC Path: " ++ show maybeTocPath
pure [(p, "Chapter " <> T.pack (show (i :: Int))) | (ref, i) <- zip refs [1 ..], let ident = DSpin.siIdRef ref, Just p <- [lookupHref ident]]
_ -> pure []
getChapter :: FilePath -> Int -> EpubAction Chapter
getChapter filename idx = do
getChapter :: (FilePath, T.Text) -> Int -> EpubAction Chapter
getChapter (filename, tocTitle) idx = do
env <- ask
let full = normalise (baseDir env </> filename)
case findEntryByPath full (archive env) of
Nothing -> pure $ Chapter "Missing" "" idx
Nothing -> pure $ Chapter tocTitle "" idx
Just e -> do
let rawText = TE.decodeUtf8 . B.toStrict $ fromEntry e
let withImages = embedImages env rawText
let (title, content) =
fromMaybe ("Chapter " <> T.pack (show idx), "") $
let (_, content) =
fromMaybe (tocTitle, "") $
scrapeStringLike withImages chapterScraper
pure $ Chapter title content idx
pure $ Chapter tocTitle content idx
getMimeFromManifest :: DMan.Manifest -> FilePath -> T.Text
getMimeFromManifest (DMan.Manifest items) relPath =

View file

@ -17,7 +17,6 @@ saveLastRead bPath chapterIdx = do
createDirectoryIfMissing True dataDir
let configFile = dataDir </> "last_read.txt"
-- Line 1 = Path, Line 2 = Index
let content = T.pack bPath <> T.pack "\n" <> T.pack (show chapterIdx)
TIO.writeFile configFile content

View file

@ -40,7 +40,7 @@ data AppState = AppState
{ cEnv :: EpubEnv,
cIdx :: Int,
zoomlvl :: Double,
cSpine :: [FilePath],
cSpine :: [(FilePath, T.Text)],
bTitle :: T.Text,
cAllChapters :: [Chapter],
activeTask :: Maybe (Async ()),