Skip to content

Commit 1aeb8fb

Browse files
New: include .py code and all downloads in jb Download menu
1 parent 309cdc8 commit 1aeb8fb

File tree

2 files changed

+140
-1
lines changed

2 files changed

+140
-1
lines changed

notebooks/shared/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,7 @@ $(PDF_TARGET)%.tex: $(RENDERED_NOTEBOOKS)/%.ipynb $(BIB) $(PUBLISH_PLUGINS) $(SH
507507
@-$(RM) -fr $(TMPDIR)
508508
@cd $(PDF_TARGET) && $(RM) $*.nbpub.log
509509

510-
# The psot-html.py script
510+
# The post-html.py script
511511
POST_HTML ?= $(SHARED)utils/post_html.py
512512

513513
# Its options
@@ -781,6 +781,8 @@ endif
781781
JUPYTER_BOOK = jupyter-book
782782
jb jupyter-book: $(JB_LINKS) _build/index.html
783783
jb-links: $(JB_LINKS)
784+
785+
PATCH_JB ?= $(SHARED)utils/patch_jb.py
784786

785787
JB_LINKS = $(FULL_NOTEBOOKS)/_config.yml $(FULL_NOTEBOOKS)/_toc.yml $(FULL_NOTEBOOKS)/_build
786788

@@ -795,6 +797,7 @@ $(FULL_NOTEBOOKS)/_build: _build
795797

796798
_build/index.html: $(FULLS)
797799
cd $(FULL_NOTEBOOKS); $(JUPYTER_BOOK) build .
800+
$(PYTHON) $(PATCH_JB) _build/html/*.html
798801

799802

800803
## Some checks

notebooks/shared/utils/patch_jb.py

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#!/usr/bin/env python3
2+
# Patch Jupyter Book HTML
3+
4+
import argparse
5+
import os.path
6+
import sys
7+
8+
example_content = """
9+
<div class="dropdown dropdown-download-buttons">
10+
<button class="btn dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false" aria-label="Download this page">
11+
<i class="fas fa-download"></i>
12+
</button>
13+
<ul class="dropdown-menu">
14+
15+
16+
17+
<li><a href="../_sources/sphinx/index.md" target="_blank"
18+
class="btn btn-sm btn-download-source-button dropdown-item"
19+
title="Download source file"
20+
data-bs-placement="left" data-bs-toggle="tooltip"
21+
>
22+
23+
24+
<span class="btn__icon-container">
25+
<i class="fas fa-file"></i>
26+
</span>
27+
<span class="btn__text-container">.md</span>
28+
</a>
29+
</li>
30+
31+
32+
33+
34+
<li>
35+
<button onclick="window.print()"
36+
class="btn btn-sm btn-download-pdf-button dropdown-item"
37+
title="Print to PDF"
38+
data-bs-placement="left" data-bs-toggle="tooltip"
39+
>
40+
41+
42+
<span class="btn__icon-container">
43+
<i class="fas fa-file-pdf"></i>
44+
</span>
45+
<span class="btn__text-container">.pdf</span>
46+
</button>
47+
</li>
48+
49+
</ul>
50+
</div>
51+
"""
52+
53+
# We are at
54+
# https://www.fuzzingbook.org/html/Fuzzer.html
55+
# We refer to
56+
# https://www.fuzzingbook.org/code/Fuzzer.py
57+
58+
def convert(content, basename="index"):
59+
# Replace "Download source file"
60+
content = content.replace('title="Download source file"', 'title="Download notebook"')
61+
62+
# Add .py download button at top
63+
start = content.find('dropdown-download-buttons')
64+
start = content.find('<ul class="dropdown-menu">', start)
65+
start = content.find('\n', start)
66+
67+
py_ref = f"../code/{basename}.py"
68+
69+
py_button_html = f'''
70+
<li><a href="{py_ref}" target="_blank"
71+
class="btn btn-sm btn-download-source-button dropdown-item"
72+
title="Download Python code"
73+
data-bs-placement="left" data-bs-toggle="tooltip"
74+
>
75+
76+
77+
<span class="btn__icon-container">
78+
<i class="fas fa-file"></i>
79+
</span>
80+
<span class="btn__text-container">.py</span>
81+
</a>
82+
</li>
83+
'''
84+
85+
content = content[:start] + py_button_html + content[start:]
86+
87+
# Add "all downloads" download button at end of menu
88+
start = content.find('</ul>', start)
89+
90+
importing_ref = "Importing.html"
91+
py_downloads_html = f'''
92+
<li><a href="{importing_ref}" target="_blank"
93+
class="btn btn-sm btn-download-source-button dropdown-item"
94+
title="All downloads"
95+
data-bs-placement="left" data-bs-toggle="tooltip"
96+
>
97+
98+
99+
<span class="btn__icon-container">
100+
<i class="fas fa-file"></i>
101+
</span>
102+
<span class="btn__text-container">All downloads</span>
103+
</a>
104+
</li>
105+
'''
106+
107+
content = content[:start] + py_downloads_html + content[start:]
108+
109+
return content
110+
111+
if __name__ == "__main__":
112+
parser = argparse.ArgumentParser()
113+
parser.add_argument("files", nargs='*', help="jupyter-book HTML files")
114+
115+
args = parser.parse_args()
116+
117+
if len(args.files) == 0:
118+
print(convert(example_content))
119+
sys.exit(0)
120+
121+
for html_file in args.files:
122+
content = open(html_file).read()
123+
if 'title="All downloads"' in content:
124+
print(f'{html_file}: already patched')
125+
continue
126+
127+
basename = os.path.splitext(os.path.basename(html_file))[0]
128+
new_content = convert(content, basename=basename)
129+
open(html_file + '~', 'w').write(content)
130+
open(html_file, 'w').write(new_content)
131+
print(f'{html_file}: patched')
132+
133+
134+
135+
136+

0 commit comments

Comments
 (0)