Coverage for src/mkdocs_iframe/plugin.py: 86.54%

78 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-06 09:32 -0400

1"""This module contains the `mkdocs_iframe` plugin.""" 

2 

3from __future__ import annotations 

4 

5import re 

6import shutil 

7import textwrap 

8from pathlib import Path 

9from tempfile import mkdtemp 

10from typing import TYPE_CHECKING, Any, Sequence 

11 

12from mkdocs.config.config_options import Type as MkType 

13from mkdocs.plugins import BasePlugin 

14from mkdocs.structure.files import File, Files 

15 

16from mkdocs_iframe.loggers import get_logger 

17 

18if TYPE_CHECKING: 

19 from mkdocs.config import Config 

20 

21log = get_logger(__name__) 

22 

23 

24class Report: 

25 """HTML Report.""" 

26 

27 def __init__( 

28 self, 

29 *, 

30 name: str, 

31 path: str | None = None, 

32 root: str = "index.html", 

33 page: str | None = None, 

34 use_directory_urls: bool = False, 

35 ): 

36 """Initialize Report.""" 

37 self.name = name 

38 self.path = path or f"html{name}" 

39 self.root = root 

40 self.page = page or f"{name}.md" 

41 self.id = f"{name}iframe" 

42 self.use_directory_urls = use_directory_urls 

43 

44 def root_file(self) -> str: 

45 """Return the root page of the report.""" 

46 report_index = self.root 

47 if report_index == "index.html": 47 ↛ 50line 47 didn't jump to line 50, because the condition on line 47 was never false

48 report_index = f"{self.name}index.html" 

49 

50 if self.use_directory_urls: 50 ↛ 52line 50 didn't jump to line 52, because the condition on line 50 was never false

51 return report_index 

52 return f"{self.name}/{report_index}" 

53 

54 def nav_page(self) -> str: 

55 """Generate the NAV page source.""" 

56 root = self.root_file() 

57 

58 style = textwrap.dedent( 

59 """ 

60 <style> 

61 article h1, article > a, .md-sidebar--secondary { 

62 display: none !important; 

63 } 

64 </style> 

65 """, 

66 ) 

67 

68 iframe = textwrap.dedent( 

69 f""" 

70 <iframe 

71 id="{self.id}" 

72 src="{root}" 

73 frameborder="0" 

74 scrolling="no" 

75 onload="resizeIframe();" 

76 width="100%"> 

77 </iframe> 

78 """, 

79 ) 

80 

81 script = textwrap.dedent( 

82 f""" 

83 <script> 

84 var {self.id} = document.getElementById("{self.id}"); 

85 

86 function resizeIframe() {{ 

87 {self.id}.style.height = {self.id}.contentWindow.document.documentElement.offsetHeight + 'px'; 

88 }} 

89 

90 testiframe.contentWindow.document.body.onclick = function() {{ 

91 {self.id}.contentWindow.location.reload(); 

92 }} 

93 </script> 

94 

95 """, 

96 ) 

97 return style + iframe + script 

98 

99 

100class MkDocsIframePlugin(BasePlugin): 

101 """The MkDocs plugin to integrate the HTML reports in the site.""" 

102 

103 config_scheme: Sequence[tuple[str, MkType]] = (("reports", MkType(list, default=[])),) 

104 

105 def reports(self, *, use_directory_urls: bool = False) -> list[Report]: 

106 """Convert config data to Reports.""" 

107 res = [] 

108 for report in self.config["reports"]: 

109 if isinstance(report, str): 109 ↛ 110line 109 didn't jump to line 110, because the condition on line 109 was never true

110 res.append(Report(use_directory_urls=use_directory_urls, name=report)) 

111 else: 

112 res.append(Report(use_directory_urls=use_directory_urls, **report)) 

113 return res 

114 

115 def on_files(self, files: Files, config: Config, **kwargs: Any) -> Files: # noqa: ARG002 

116 """Add the html report to the navigation. 

117 

118 Hook for the [`on_files` event](https://www.mkdocs.org/user-guide/plugins/#on_files). 

119 

120 Arguments: 

121 files: The files collection. 

122 config: The MkDocs config object. 

123 **kwargs: Additional arguments passed by MkDocs. 

124 

125 Returns: 

126 The modified files collection. 

127 

128 """ 

129 site_dir = Path(config["site_dir"]) 

130 use_directory_urls = config["use_directory_urls"] 

131 for report in self.reports(use_directory_urls=use_directory_urls): 

132 page_contents = report.nav_page() 

133 tmp_dir = mkdtemp() 

134 tmp_file = Path(tmp_dir) / report.page 

135 with tmp_file.open("w") as fp: 

136 fp.write(page_contents) 

137 

138 files.append( 

139 File( 

140 report.page, 

141 str(tmp_file.parent), 

142 str(site_dir), 

143 use_directory_urls, 

144 ), 

145 ) 

146 

147 return files 

148 

149 def on_post_build(self, config: Config, **kwargs: Any) -> None: # noqa: ARG002 

150 """Copy the HTML reports into the site directory. 

151 

152 Hook for the [`on_post_build` event](https://www.mkdocs.org/user-guide/plugins/#on_post_build). 

153 

154 Arguments: 

155 config: The MkDocs config object. 

156 **kwargs: Additional arguments passed by MkDocs. 

157 

158 """ 

159 site_dir = Path(config["site_dir"]) 

160 use_directory_urls = config["use_directory_urls"] 

161 

162 for report in self.reports(use_directory_urls=use_directory_urls): 

163 report_dir = site_dir / report.name 

164 tmp_index = site_dir / f".{report.name}-tmp.html" 

165 

166 if report.root == "index.html": 166 ↛ 172line 166 didn't jump to line 172, because the condition on line 166 was never false

167 if config["use_directory_urls"]: 167 ↛ 170line 167 didn't jump to line 170, because the condition on line 167 was never false

168 shutil.move(str(report_dir / "index.html"), tmp_index) 

169 else: 

170 shutil.move(str(report_dir.with_suffix(".html")), tmp_index) 

171 

172 shutil.rmtree(str(report_dir), ignore_errors=True) 

173 try: 

174 shutil.copytree(report.path, str(report_dir)) 

175 except FileNotFoundError: 

176 log.warning(f"No such HTML report directory: {report.path}") 

177 return 

178 

179 if report.root == "index.html": 179 ↛ 162line 179 didn't jump to line 162, because the condition on line 179 was never false

180 report_root = report.root_file() 

181 

182 shutil.move(str(report_dir / "index.html"), report_dir / report_root) 

183 if use_directory_urls: 183 ↛ 186line 183 didn't jump to line 186, because the condition on line 183 was never false

184 shutil.move(str(tmp_index), report_dir / "index.html") 

185 else: 

186 shutil.move(str(tmp_index), report_dir.with_suffix(".html")) 

187 

188 for html_file in report_dir.iterdir(): 

189 if html_file.suffix == ".html" and html_file.name != "index.html": 

190 html_file.write_text( 

191 re.sub(r'href="index\.html"', f'href="{report_root}"', html_file.read_text()), 

192 )