94 lines
2.7 KiB
Python
Executable File
94 lines
2.7 KiB
Python
Executable File
#!/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() |