Skip to content

Commit 2c8892f

Browse files
committed
better make-html.py script with dark default background
1 parent e84f186 commit 2c8892f

File tree

3 files changed

+96
-29
lines changed

3 files changed

+96
-29
lines changed

common.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import contextlib
3535
import itertools
3636
import os
37+
import posixpath
3738
import re
3839
import shutil
3940

@@ -73,9 +74,9 @@ def get_markdown_files():
7374
yield 'README.md'
7475
with open('README.md', 'r') as f:
7576
for match, lineno in find_links(f):
76-
target = match.group(2)
77-
# Currently the README doesn't link to itself, but I don't
78-
# want to break things if it will in the future.
77+
target = posixpath.normpath(match.group(2))
78+
# Currently he README links to itself, but we don't want to
79+
# break things if it will be modified not to link in the future.
7980
if target.endswith('.md') and target != 'README.md':
8081
yield target
8182

@@ -92,6 +93,7 @@ def askyesno(question, default=True):
9293
else:
9394
# no by default
9495
question += ' [y/N] '
96+
9597
while True:
9698
result = input(question).upper().strip()
9799
if result == 'Y':
@@ -100,6 +102,7 @@ def askyesno(question, default=True):
100102
return False
101103
if not result:
102104
return default
105+
print("Please type y, n or nothing at all.")
103106

104107

105108
def slashfix(path):

html-style.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
/* This file is used by the HTML files that make-html.py creates.
2+
Customize this if you want to create HTML files with different
3+
colors. See also make-html.py's --pygments-theme option. */
4+
body {
5+
color: white;
6+
background-color: #333333;
7+
}
8+
a {
9+
color: orange;
10+
}

make-html.py

Lines changed: 80 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -28,19 +28,20 @@
2828

2929
"""Create HTML files of the tutorial."""
3030

31+
import argparse
3132
import os
3233
import posixpath
3334
import shutil
3435
import string
3536
import sys
37+
import textwrap
3638
import webbrowser
3739

38-
import common
39-
4040
try:
4141
import mistune
4242
except ImportError:
43-
print("mistune isn't installed. You can install it like this:")
43+
print("mistune isn't installed.", file=sys.stderr)
44+
print("You can install it like this:")
4445
print()
4546
print(">>> import pip")
4647
print(">>> pip.main(['install', '--user', 'mistune'])")
@@ -49,17 +50,21 @@
4950
try:
5051
import pygments.formatters
5152
import pygments.lexers
53+
import pygments.styles
5254
except ImportError:
5355
# we can work without pygments, but we won't get colors
5456
pygments = None
5557

58+
import common
59+
5660

5761
HTML_TEMPLATE = """\
5862
<!DOCTYPE html>
5963
<html>
6064
<head>
6165
<meta charset="UTF-8">
6266
<title>{title}</title>
67+
<link rel="stylesheet" type="text/css" href="{stylefile}">
6368
</head>
6469
<body>
6570
{body}
@@ -77,19 +82,23 @@ def mkdir_slashfix_open(filename, mode):
7782

7883

7984
def fix_filename(filename):
80-
if posixpath.basename(filename) == 'README.md':
81-
# 'README.md' -> 'index.html'
82-
# 'some/place/README.md' -> 'some/place/index.html'
83-
return filename[:-9] + 'index.html'
85+
renames = [('README.md', 'index.html'),
86+
('LICENSE', 'LICENSE.txt')]
87+
for before, after in renames:
88+
if posixpath.basename(filename) == before:
89+
# BEFORE -> AFTER
90+
# some/place/BEFORE -> some/place/AFTER
91+
return filename[:-len(before)] + after
8492
if filename.endswith('.md'):
85-
return filename[:-3] + '.html'
93+
filename = filename[:-3] + '.html'
8694
return filename
8795

8896

8997
class TutorialRenderer(mistune.Renderer):
9098

91-
def __init__(self):
99+
def __init__(self, pygments_style):
92100
super().__init__()
101+
self.pygments_style = pygments_style
93102
self.title = None # will be set by header()
94103
self._headercounts = {}
95104

@@ -157,7 +166,7 @@ def block_code(self, code, lang=None):
157166
else:
158167
lexer = pygments.lexers.PythonLexer()
159168
formatter = pygments.formatters.HtmlFormatter(
160-
style='tango', noclasses=True)
169+
style=self.pygments_style, noclasses=True)
161170
return pygments.highlight(code, lexer, formatter)
162171
# we can't highlight it
163172
return super().block_code(code, lang)
@@ -173,51 +182,96 @@ def table(self, header, body):
173182
return result.replace('<table>', '<table border="1">', 1)
174183

175184

185+
def wrap_text(text):
186+
"""Like textwrap.fill, but respects newlines."""
187+
result = []
188+
for part in text.split('\n'):
189+
result.append(textwrap.fill(part))
190+
return '\n'.join(result)
191+
192+
176193
def main():
194+
desc = ("Create HTML files of the tutorial.\n\n"
195+
"The files have light text on a dark background by "
196+
"default, and you can edit html-style.css to change that.")
197+
if pygments is not None:
198+
desc += (
199+
" Editing the style file doesn't change the colors of the "
200+
"code examples, but you can use the --pygments-style "
201+
"option. Search for 'pygments style gallery' online or see "
202+
"https://help.farbox.com/pygments.html to get an idea of "
203+
"what different styles look like.")
204+
205+
parser = argparse.ArgumentParser(
206+
description=wrap_text(desc),
207+
formatter_class=argparse.RawDescriptionHelpFormatter)
208+
parser.add_argument(
209+
'-o', '--outdir', default='html',
210+
help="write the HTML files here, defaults to %(default)r")
211+
if pygments is not None:
212+
parser.add_argument(
213+
'--pygments-style', metavar='STYLE', default='native',
214+
choices=list(pygments.styles.get_all_styles()),
215+
help=("the Pygments color style (see above), "
216+
"%(default)r by default"))
217+
args = parser.parse_args()
218+
177219
if pygments is None:
178220
print("Pygments isn't installed. You can install it like this:")
179221
print()
180222
print(">>> import pip")
181-
print(">>> pip.main(['install', '--user', 'Pygments'])")
223+
print(">>> pip.main(['install', '--user', 'pygments'])")
182224
print()
183225
print("You can also continue without Pygments, but the code examples")
184-
print("will not be in color.")
226+
print("will not be colored.")
185227
if not common.askyesno("Continue without pygments?"):
186228
print("Interrupt.")
187229
return
188230

189-
if os.path.exists('html'):
190-
if not common.askyesno("html exists. Do you want to remove it?"):
231+
if os.path.exists(args.outdir):
232+
if not common.askyesno("%s exists. Do you want to remove it?"
233+
% args.outdir):
191234
print("Interrupt.")
192235
return
193-
if os.path.isdir('html'):
194-
shutil.rmtree('html')
236+
if os.path.isdir(args.outdir):
237+
shutil.rmtree(args.outdir)
195238
else:
196-
os.remove('html')
239+
os.remove(args.outdir)
197240

198241
print("Generating HTML files...")
199242
for markdownfile in common.get_markdown_files():
200-
htmlfile = posixpath.join('html', fix_filename(markdownfile))
201-
print(' ', markdownfile, '->', htmlfile)
243+
fixed_markdownfile = fix_filename(markdownfile)
244+
htmlfile = posixpath.join(args.outdir, fixed_markdownfile)
245+
print(' %-30.30s --> %-30.30s' % (markdownfile, htmlfile), end='\r')
246+
202247
with common.slashfix_open(markdownfile, 'r') as f:
203248
markdown = f.read()
204-
renderer = TutorialRenderer()
249+
renderer = TutorialRenderer(args.pygments_style)
205250
body = mistune.markdown(markdown, renderer=renderer)
206-
html = HTML_TEMPLATE.format(title=renderer.title, body=body)
251+
stylefile = posixpath.relpath(
252+
'style.css', posixpath.dirname(fixed_markdownfile))
253+
254+
html = HTML_TEMPLATE.format(
255+
title=renderer.title,
256+
body=body,
257+
stylefile=stylefile,
258+
)
207259
with mkdir_slashfix_open(htmlfile, 'w') as f:
208260
print(html, file=f)
261+
print()
209262

210263
print("Copying other files...")
211-
shutil.copytree('images', os.path.join('html', 'images'))
212-
shutil.copy('LICENSE', os.path.join('html', 'LICENSE'))
264+
shutil.copytree('images', os.path.join(args.outdir, 'images'))
265+
shutil.copy('LICENSE', os.path.join(args.outdir, 'LICENSE.txt'))
266+
shutil.copy('html-style.css', os.path.join(args.outdir, 'style.css'))
213267

214268
print("\n*********************\n")
215-
print("Ready! The files are in the html directory.")
216-
print("Go to html and double-click index.html to read the tutorial.")
269+
print("Ready! The files are in %r." % args.outdir)
270+
print("You can go there and double-click index.html to read the tutorial.")
217271
print()
218272
if common.askyesno("Do you want to view the tutorial now?", default=False):
219273
print("Opening the tutorial...")
220-
webbrowser.open(os.path.join('html', 'index.html'))
274+
webbrowser.open(os.path.join(args.outdir, 'index.html'))
221275

222276

223277
if __name__ == '__main__':

0 commit comments

Comments
 (0)