[web_server] Emit the resource tables with cg.extern_progmem_array (#20300)

This commit is contained in:
J. Nick Koston
2026-10-08 11:34:34 -04:00
committed by GitHub
parent f224cb37d6
commit 7910d02b71
5 changed files with 56 additions and 6 deletions
+8 -6
View File
@@ -364,12 +364,14 @@ def add_resource_as_progmem(
content_encoded = content.encode("utf-8")
if compress:
content_encoded = gzip.compress(content_encoded)
content_encoded_size = len(content_encoded)
bytes_as_int = ", ".join(str(x) for x in content_encoded)
uint8_t = f"constexpr uint8_t ESPHOME_WEBSERVER_{resource_name}[{content_encoded_size}] PROGMEM = {{{bytes_as_int}}}"
size_t = f"constexpr size_t ESPHOME_WEBSERVER_{resource_name}_SIZE = {content_encoded_size}"
cg.add_global(cg.RawExpression(uint8_t))
cg.add_global(cg.RawExpression(size_t))
cg.extern_progmem_array(
f"ESPHOME_WEBSERVER_{resource_name}", cg.uint8, list(content_encoded)
)
cg.add_global(
cg.RawExpression(
f"constexpr size_t ESPHOME_WEBSERVER_{resource_name}_SIZE = {len(content_encoded)}"
)
)
@coroutine_with_priority(CoroPriority.WEB)
@@ -0,0 +1 @@
body { color: red; }
@@ -0,0 +1 @@
console.log("hi");
@@ -0,0 +1,13 @@
esphome:
name: test
esp32:
board: esp32dev
wifi:
ssid: test
password: testtest
web_server:
css_include: include.css
js_include: include.js
@@ -0,0 +1,33 @@
"""Tests for the web_server resources emitted as flash tables."""
from collections.abc import Callable
import gzip
from pathlib import Path
import re
def _table(main_cpp: str, name: str) -> bytes:
# Anchored so a static table does not match
match = re.search(
rf"^const uint8_t ESPHOME_WEBSERVER_{name}\[\] PROGMEM = \{{([^}}]*)\}};",
main_cpp,
re.MULTILINE,
)
assert match is not None
return bytes(int(byte) for byte in match.group(1).split(","))
def test_resources_are_externally_linked_tables(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
"""web_server.cpp reads these through extern declarations, so they must not be static."""
main_cpp = generate_main(component_config_path("includes.yaml"))
assert b"<esp-app></esp-app>" in _table(main_cpp, "INDEX_HTML")
assert gzip.decompress(_table(main_cpp, "CSS_INCLUDE")) == b"body { color: red; }\n"
assert gzip.decompress(_table(main_cpp, "JS_INCLUDE")) == b'console.log("hi");\n'
css_size = len(_table(main_cpp, "CSS_INCLUDE"))
assert (
f"constexpr size_t ESPHOME_WEBSERVER_CSS_INCLUDE_SIZE = {css_size};" in main_cpp
)