Add build.py: bundles all assets into a single standalone HTML
This commit is contained in:
1 parent
3ccc3e4be7
commit
8e05444cfb
2 files changed
+2610
No files matched your search
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,94 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Build a single self-contained HTML file from the source files.
|
||||
|
||||
Usage:
|
||||
python3 build.py [output.html]
|
||||
|
||||
If output is not given, defaults to 'background-final.html'.
|
||||
|
||||
This reads config.js to pick the active theme and inlines all CSS,
|
||||
JS, and the noise.png texture into a single HTML document. After
|
||||
building, the resulting double-standalone HTML can be opened directly in
|
||||
a browser (file://) because all external resources are inlined.
|
||||
"""
|
||||
|
||||
import base64
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
|
||||
ROOT = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
def read(path):
|
||||
with open(os.path.join(ROOT, path), 'r', encoding='utf-8') as f:
|
||||
return f.read()
|
||||
|
||||
|
||||
def parse_config():
|
||||
"""Extract window.CONFIG values from config.js."""
|
||||
src = read('config.js')
|
||||
out = {}
|
||||
for key in ['debug', 'theme', 'units', 'language', 'timeFormat']:
|
||||
m = re.search(r"\b%s\s*:\s*'([^']*)'" % key, src) or re.search(r'\b%s\s*:\s*(\d+)' % key, src)
|
||||
if m:
|
||||
out[key] = m.group(1)
|
||||
m = re.search(r'lat\s*:\s*([\d.]+)', src)
|
||||
if m:
|
||||
out['lat'] = m.group(1)
|
||||
m = re.search(r'lon\s*:\s*([-\d.]+)', src)
|
||||
if m:
|
||||
out['lon'] = m.group(1)
|
||||
return out
|
||||
|
||||
|
||||
def main():
|
||||
out = sys.argv[1] if len(sys.argv) > 1 else 'background-final.html'
|
||||
|
||||
cfg = parse_config()
|
||||
theme = cfg.get('theme', 'ash')
|
||||
|
||||
html = read('background.html')
|
||||
|
||||
# Resolve active theme css
|
||||
theme_css = read(theme + '.css')
|
||||
# Inline the active theme stylesheet at the end of <head>
|
||||
html = html.replace('</head>',
|
||||
'<style>\n' + theme_css + '\n</style>\n</head>',
|
||||
1)
|
||||
|
||||
# Inline vendor scripts in the body, before the main script block
|
||||
for _, path in [
|
||||
('three', 'vendor/three.min.js'),
|
||||
('suncalc', 'vendor/suncalc.js'),
|
||||
('vanta2', 'vendor/vanta.clouds2.min.js'),
|
||||
('i18n', 'i18n.js'),
|
||||
('config', 'config.js'),
|
||||
]:
|
||||
body = read(path)
|
||||
html = html.replace('<script src="' + path + '"></script>',
|
||||
'<script>\n' + body + '\n</script>',
|
||||
1)
|
||||
|
||||
# Inline noise.png as data URI in the Vanta init script.
|
||||
with open(os.path.join(ROOT, 'noise.png'), 'rb') as f:
|
||||
noise_b64 = base64.b64encode(f.read()).decode('ascii')
|
||||
noise_uri = 'data:image/png;base64,' + noise_b64
|
||||
html = re.sub(
|
||||
r"texturePath:\s*'[^']*'",
|
||||
"texturePath: '" + noise_uri + "'",
|
||||
html)
|
||||
|
||||
with open(os.path.join(ROOT, out), 'w', encoding='utf-8') as f:
|
||||
f.write(html)
|
||||
|
||||
print('Wrote ' + out + ' (' + str(len(html)) + ' bytes)')
|
||||
print('Config used:')
|
||||
for k in ('debug', 'theme', 'units', 'language', 'timeFormat', 'lat', 'lon'):
|
||||
if k in cfg:
|
||||
print(' ' + k + ' = ' + cfg[k])
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in new issue
Block a user