Coverage for src/epublib/nav/util.py: 97%

38 statements  

« prev     ^ index     » next       coverage.py v7.10.7, created at 2025-10-06 16:12 -0300

1from dataclasses import dataclass, field 

2 

3import bs4 

4from bs4.element import NamespacedAttribute 

5 

6from epublib.exceptions import warn 

7from epublib.util import attr_to_str, parse_int 

8 

9epub_type = NamespacedAttribute( 

10 prefix="epub", 

11 name="type", 

12 namespace="http://www.idpf.org/2007/ops", 

13) 

14 

15 

16def detect_page(tag: bs4.Tag): 

17 page = None 

18 if tag.string: 

19 page = parse_int(tag.string) 

20 if page is not None: 

21 return page 

22 

23 for attr in "title", "aria-label", "id", "class": 

24 if tag.get(attr): 

25 page = parse_int(attr_to_str(tag[attr])) 

26 

27 if page is not None: 

28 return page 

29 

30 warn(f"Can't determine page number of pagebreak element: {tag}") 

31 return None 

32 

33 

34@dataclass 

35class PageBreakData: 

36 """Data for a page break.""" 

37 

38 filename: str 

39 page: int 

40 label: str = "" 

41 

42 def __post_init__(self): 

43 if not self.label: 

44 self.label = str(self.page) 

45 

46 

47@dataclass 

48class TOCEntryData: 

49 """Data for a table of contents entry.""" 

50 

51 filename: str 

52 label: str 

53 id: str | None = None 

54 children: list["TOCEntryData"] = field(default_factory=list) 

55 

56 

57@dataclass 

58class LandmarkEntryData: 

59 """Represents a landmark, a special navigation point in an EPUB file.""" 

60 

61 filename: str 

62 label: str 

63 epub_type: str