Coverage for src/epublib/nav/resource.py: 96%
74 statements
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-18 16:07 -0300
« prev ^ index » next coverage.py v7.10.6, created at 2025-09-18 16:07 -0300
1from pathlib import Path
2from typing import IO, override
3from zipfile import ZipInfo
5from epublib.mediatype import MediaType
6from epublib.nav import LandmarksRoot, PageListRoot, TocRoot
7from epublib.nav.util import LandmarkEntryData, PageBreakData, TOCEntryData
8from epublib.resources import ContentDocument
9from epublib.util import get_relative_href
12class NavigationDocument(ContentDocument):
13 """
14 A specialization of the XHTML content document that contains human- and
15 machine-readable global navigation information.
16 """
18 def __init__(
19 self,
20 file: IO[bytes] | bytes,
21 info: ZipInfo | str | Path,
22 media_type: MediaType | str,
23 ) -> None:
24 super().__init__(file, info, media_type)
25 self._toc: TocRoot | None = None
26 self._page_list: PageListRoot | None = None
27 self._landmarks: LandmarksRoot | None = None
29 def add_to_toc(
30 self,
31 filename: str,
32 title: str,
33 position: int | None = None,
34 ):
35 href = get_relative_href(self.filename, filename)
37 if self.toc is None:
38 self._toc = TocRoot(self.soup, tag=None, base_filename=self.filename)
40 assert self.toc is not None
41 return self.toc.add_item(href=href, text=title, position=position)
43 @property
44 def toc(self):
45 if self._toc is None:
46 tag = self.soup.select_one('nav[epub|type="toc"]')
47 if tag:
48 self._toc = TocRoot(self.soup, tag, self.filename)
49 return self._toc
51 @property
52 def page_list(self):
53 if self._page_list is None:
54 tag = self.soup.select_one('nav[epub|type="page-list"]')
55 if tag:
56 self._page_list = PageListRoot(self.soup, tag, self.filename)
57 return self._page_list
59 @property
60 def landmarks(self):
61 if self._landmarks is None:
62 tag = self.soup.select_one('nav[epub|type="landmarks"]')
63 if tag:
64 self._landmarks = LandmarksRoot(self.soup, tag, self.filename)
65 return self._landmarks
67 def reset_page_list(self, pagebreaks: list[PageBreakData]):
68 if self.page_list is None:
69 self._page_list = PageListRoot(
70 self.soup,
71 tag=None,
72 base_filename=self.filename,
73 )
75 assert self.page_list
76 self.page_list.reset(pagebreaks)
78 def reset_toc(self, entries: list[TOCEntryData]):
79 if self.toc is None:
80 self._toc = TocRoot(self.soup, tag=None, base_filename=self.filename)
82 assert self.toc
83 self.toc.reset(entries)
85 def reset_landmarks(self, entries: list[LandmarkEntryData]):
86 if self.landmarks is None:
87 self._landmarks = LandmarksRoot(
88 self.soup,
89 tag=None,
90 base_filename=self.filename,
91 )
93 assert self.landmarks
94 self.landmarks.reset(entries)
96 def remove(self, filename: str):
97 if self.toc:
98 self.toc.remove(filename)
99 if self.landmarks:
100 self.landmarks.remove(filename)
101 if self.page_list:
102 self.page_list.remove(filename)
104 def on_soup_change(self):
105 del self._toc
106 del self._page_list
107 del self._landmarks
108 self._toc = None
109 self._page_list = None
110 self._landmarks = None
112 @override
113 def on_content_change(self):
114 super().on_content_change()
115 self.on_soup_change()