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

73 statements  

« prev     ^ index     » next       coverage.py v7.2.7, created at 2023-06-05 09:22 -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 def __init__(self, name: str, path: str | None = None, index: str = "index.html"): 

26 self.name = name 

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

28 self.index = index 

29 self.page_name = f"{name}.md" 

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

31 

32 def index_file(self, use_directory_urls: bool) -> str: 

33 report_index = self.index 

34 if report_index == "index.html": 

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

36 

37 if use_directory_urls: 

38 return report_index 

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

40 

41 def index_page(self, use_directory_urls: bool) -> str: 

42 index = self.index_file(use_directory_urls) 

43 

44 style = textwrap.dedent( 

45 """ 

46 <style> 

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

48 display: none !important; 

49 } 

50 </style> 

51 """, 

52 ) 

53 

54 iframe = textwrap.dedent( 

55 f""" 

56 <iframe 

57 id="{self.id}" 

58 src="{index}" 

59 frameborder="0" 

60 scrolling="no" 

61 onload="resizeIframe();" 

62 width="100%"> 

63 </iframe> 

64 """, 

65 ) 

66 

67 script = textwrap.dedent( 

68 f""" 

69 <script> 

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

71 

72 function resizeIframe() {{ 

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

74 }} 

75 

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

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

78 }} 

79 </script> 

80 

81 """, 

82 ) 

83 page_contents = style + iframe + script 

84 return page_contents 

85 

86 

87class MkDocsIframePlugin(BasePlugin): 

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

89 

90 config_scheme: Sequence[tuple[str, MkType]] = ( 

91 ("reports", MkType(list, default=[])), 

92 ) 

93 

94 def reports(self) -> list[Report]: 

95 return [Report(**report) for report in self.config.reports] 

96 

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

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

99 

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

101 

102 Arguments: 

103 files: The files collection. 

104 config: The MkDocs config object. 

105 **kwargs: Additional arguments passed by MkDocs. 

106 

107 Returns: 

108 The modified files collection. 

109 

110 """ 

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

112 use_directory_urls = config["use_directory_urls"] 

113 for report in self.reports(): 

114 page_contents = report.index_page(use_directory_urls) 

115 tempdir = mkdtemp() 

116 tempfile = Path(tempdir) / report.page_name 

117 with tempfile.open("w") as fp: 

118 fp.write(page_contents) 

119 

120 files.append( 

121 File( 

122 report.page_name, 

123 str(tempfile.parent), 

124 str(site_dir), 

125 use_directory_urls, 

126 ) 

127 ) 

128 

129 return files 

130 

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

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

133 

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

135 

136 Arguments: 

137 config: The MkDocs config object. 

138 **kwargs: Additional arguments passed by MkDocs. 

139 

140 """ 

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

142 use_directory_urls = config["use_directory_urls"] 

143 

144 for report in self.reports(): 

145 report_dir = site_dir / report.name 

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

147 

148 if report.index == "index.html": 

149 if config["use_directory_urls"]: 

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

151 else: 

152 shutil.move(report_dir.with_suffix(".html"), tmp_index) 

153 

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

155 try: 

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

157 except FileNotFoundError: 

158 log.warning(f"No such HTML report directory: {report_dir}") 

159 return 

160 

161 if report.index == "index.html": 

162 report_index = report.index_file(use_directory_urls) 

163 

164 shutil.move(report_dir / "index.html", report_dir / report_index) 

165 if use_directory_urls: 

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

167 else: 

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

169 

170 for html_file in report_dir.iterdir(): 

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

172 html_file.write_text(re.sub(r'href="index\.html"', f'href="{report_index}"', html_file.read_text()))