/
ellersseer
/
MyCheat
Обзор
Документация
Войти
/
ellersseer
/
MyCheat
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
2
CI/CD
Аналитика
Безопасность
master
scripts/embed_html.py
130 строк
4 KB
Dmitry Zhiltsov
feat(logs): Добавить логи в WEB
20 фев 2026, 20:39
20 фев 2026, 20:39
dae6bcf
Код
Авторство
О чём код?
""" PlatformIO pre-build script: converts data/*.html into include/web_html_*.h Each HTML file is wrapped in a PROGMEM C string using R"rawhtml(...)rawhtml" syntax. The generated headers are identical in format to what was previously hand-maintained. Mapping: data/index.html -> include/web_html_index.h (var: INDEX_HTML) data/settings.html -> include/web_html_settings.h (var: SETTINGS_HTML) ESPAsyncWebServer uses % for template placeholders (%WIFI_SSID%, etc.). JavaScript % operators must be escaped as %% in the final PROGMEM string. This script automatically escapes % while preserving template placeholders. """ import os import hashlib import re # Map: html filename (without .html) -> C variable name VAR_NAMES = { "index": "INDEX_HTML", "settings": "SETTINGS_HTML", "logs": "LOGS_HTML", } def escape_percent_for_esp_async(html_content): """ Escape % for ESPAsyncWebServer template processor. Converts % to %% except in template placeholders like %PLACEHOLDER_NAME%. This allows writing valid JavaScript (e.g., seconds % 60) in data/*.html while generating correct escaped output (%%) for ESPAsyncWebServer. """ # Find all template placeholders: %UPPERCASE_NAME% placeholders = re.findall(r'%[A-Z_]+%', html_content) temp_markers = {} # Temporarily replace placeholders with markers for i, placeholder in enumerate(placeholders): marker = f"___PLACEHOLDER_{i}___" temp_markers[marker] = placeholder html_content = html_content.replace(placeholder, marker, 1) # Escape all remaining % → %% html_content = html_content.replace('%', '%%') # Restore placeholders (now with single %) for marker, placeholder in temp_markers.items(): html_content = html_content.replace(marker, placeholder) return html_content def generate_header(name, var_name, html_content): """Generate a PROGMEM header file from HTML content.""" guard = f"WEB_HTML_{name.upper()}_H" return ( f"// Auto-generated by scripts/embed_html.py from data/{name}.html\n" f"// Do not edit this file directly — edit data/{name}.html instead.\n" f"#ifndef {guard}\n" f"#define {guard}\n" f"\n" f"#include <pgmspace.h>\n" f"\n" f"const char {var_name}[] PROGMEM = R\"rawhtml(\n" f"{html_content}" f")rawhtml\";\n" f"\n" f"#endif // {guard}\n" ) def file_hash(path): """Return MD5 hash of file contents, or None if file doesn't exist.""" if not os.path.exists(path): return None with open(path, "rb") as f: return hashlib.md5(f.read()).hexdigest() def main(project_dir=None): if project_dir is None: # Standalone mode: resolve relative to this script script_dir = os.path.dirname(os.path.abspath(__file__)) project_dir = os.path.dirname(script_dir) data_dir = os.path.join(project_dir, "data") include_dir = os.path.join(project_dir, "include") if not os.path.isdir(data_dir): print("[embed_html] No data/ directory found, skipping") return for name, var_name in VAR_NAMES.items(): html_path = os.path.join(data_dir, f"{name}.html") header_path = os.path.join(include_dir, f"web_html_{name}.h") if not os.path.exists(html_path): print(f"[embed_html] WARNING: {html_path} not found, skipping") continue with open(html_path, "r", encoding="utf-8") as f: html_content = f.read() # Ensure HTML ends with newline if not html_content.endswith("\n"): html_content += "\n" # Escape % for ESPAsyncWebServer (except template placeholders) html_content = escape_percent_for_esp_async(html_content) new_header = generate_header(name, var_name, html_content) # Only write if content changed (avoid unnecessary recompilation) old_hash = file_hash(header_path) new_hash = hashlib.md5(new_header.encode("utf-8")).hexdigest() if old_hash == new_hash: continue with open(header_path, "w", encoding="utf-8") as f: f.write(new_header) print(f"[embed_html] {html_path} -> {header_path}") # PlatformIO calls Import("env") in the script context # but we also support standalone execution for testing try: Import("env") main(env.subst("$PROJECT_DIR")) # noqa: F821 — SCons built-in except NameError: # Running standalone (python3 scripts/embed_html.py) main()