#!/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 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') # Read noise.png and inline as base64 data URI with open(os.path.join(ROOT, 'noise.png'), 'rb') as f: noise_b64 = base64.b64encode(f.read()).decode('ascii') # Replace noiseDataUri placeholder with the actual data URI html = html.replace( "'data:image/png;base64,PLACEHOLDER'", "'data:image/png;base64," + noise_b64 + "'" ) # Resolve active theme css theme_css = read(theme + '.css') # Inline the active theme stylesheet at the end of html = html.replace('', '\n', 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('', '', 1) 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()