Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
3-manifolds
GitHub Repository: 3-manifolds/Sage_macOS
Path: blob/main/bin/compress_site.py
170 views
1
#!/usr/bin/env python3
2
import sys
3
import os
4
import shutil
5
import subprocess
6
7
class SiteCompressor:
8
"""
9
Compresses a static web site generated by Sphinx by:
10
(1) Merging all _static directories into a single _static directory at the
11
top level.
12
(2) Using gzip to compress the file types below, adding a .gz suffix to
13
the filename.
14
"""
15
# Filename extensions for files that we want to compress
16
gzip_extensions = ['.html', '.css', '.js', '.woff', '.svg']
17
image_extensions = ['.png', '.pdf', '.svg',]
18
19
def __init__(self, site):
20
if not os.path.isdir(site):
21
raise RuntimeError(
22
'A Brotlifier must be instantiated with a directory')
23
self.site = os.path.abspath(site)
24
25
def merge_static_dirs(self):
26
static_dirs = []
27
for dirpath, dirnames, filenames in os.walk(self.site):
28
if dirpath.endswith('_static') and not os.path.islink(dirpath):
29
static_dirs.append(dirpath)
30
main_static_dir = os.path.join(self.site, '_static')
31
try:
32
static_dirs.remove(main_static_dir)
33
except ValueError:
34
pass
35
# Copy the contents of each subsidiary static dir into the main one
36
# then replace the subsidiary with a symlink.
37
for dirpath in static_dirs:
38
# This assumes that all symlinks point inside the static dir.
39
shutil.copytree(dirpath, main_static_dir, symlinks=True,
40
dirs_exist_ok=True)
41
relpath = os.path.relpath(main_static_dir, os.path.dirname(dirpath))
42
shutil.rmtree(dirpath)
43
os.symlink(relpath, dirpath)
44
45
def clean_images(self):
46
"""All images should be in _static or _images."""
47
# I have no idea why these get copied rather than moved.
48
# Apparently this does not happen with a standard build.
49
to_delete = []
50
for dirpath, dirnames, filenames in os.walk(self.site):
51
if dirpath.find('_static') >= 0 or dirpath.find('_images') >= 0:
52
continue
53
for filename in filenames:
54
base, ext = os.path.splitext(filename)
55
if ext in self.image_extensions:
56
print('deleting', os.path.join(dirpath, filename))
57
to_delete.append(os.path.join(dirpath, filename))
58
for path in to_delete:
59
os.unlink(path)
60
61
def compress_files(self):
62
"""Compress compressible files."""
63
compressible = []
64
for dirpath, dirnames, filenames in os.walk(self.site):
65
for filename in filenames:
66
base, ext = os.path.splitext(filename)
67
if ext in self.gzip_extensions:
68
compressible.append(os.path.join(dirpath, filename))
69
for path in compressible:
70
subprocess.run(['gzip', '--best', path])
71
72
if __name__ == '__main__':
73
try:
74
site = sys.argv[1]
75
except IndexError:
76
print('Please provide the site root directory as an argument.')
77
sys.exit(1)
78
if not os.path.isdir(site):
79
print('The site root must be a directory.')
80
sys.exit(1)
81
compressor = SiteCompressor(site)
82
print('Merging _static directories ..')
83
compressor.merge_static_dirs()
84
print("Deleting extraneous images ...")
85
compressor.clean_images()
86
print('Compressing files ...')
87
compressor.compress_files()
88
89
90
91
92