make injection script template a data file

This commit is contained in:
Daniel Fichtinger 2025-07-13 16:54:04 -04:00
parent 585a987c3f
commit 1c64d1f431
3 changed files with 49 additions and 15 deletions

View file

@ -0,0 +1,6 @@
const ws = new WebSocket("__SOCKET_ADDRESS_");
ws.onmessage = event => {
if (event.data === "reload") {
location.reload();
}
};

View file

@ -13,6 +13,7 @@ from rich import print
from watchdog.events import FileSystemEvent, FileSystemEventHandler from watchdog.events import FileSystemEvent, FileSystemEventHandler
from watchdog.observers import Observer from watchdog.observers import Observer
from zona import util
from zona.builder import ZonaBuilder from zona.builder import ZonaBuilder
from zona.log import get_logger from zona.log import get_logger
from zona.websockets import WebSocketServer from zona.websockets import WebSocketServer
@ -22,16 +23,16 @@ logger = get_logger()
def make_reload_script(host: str, port: int) -> str: def make_reload_script(host: str, port: int) -> str:
"""Generates the JavaScript that must be injected into HTML pages for the live reloading to work.""" """Generates the JavaScript that must be injected into HTML pages for the live reloading to work."""
return f""" js = util.get_resource("server/inject.js").contents
<script> js = util.minify_js(js)
const ws = new WebSocket("ws://{host}:{port}"); address = f"ws://{host}:{port}"
ws.onmessage = event => {{ for placeholder, value in (("__SOCKET_ADDRESS_", address),):
if (event.data === "reload") {{ if placeholder not in js:
location.reload(); raise ValueError(
}} f"{placeholder} missing from reload script template!"
}}; )
</script> js = js.replace(placeholder, value)
""" return f"<script>{js}</script>"
def make_handler_class(script: str): def make_handler_class(script: str):

View file

@ -1,4 +1,5 @@
import fnmatch import fnmatch
import re
import string import string
from importlib import resources from importlib import resources
from importlib.resources.abc import Traversable from importlib.resources.abc import Traversable
@ -12,6 +13,15 @@ class ZonaResource(NamedTuple):
contents: str contents: str
def get_resource(path: str) -> ZonaResource:
"""Load the packaged resource in data/path"""
file = resources.files("zona").joinpath("data", path)
if file.is_file():
return ZonaResource(name=path, contents=file.read_text())
else:
raise FileNotFoundError(f"{path} is not a valid Zona resource!")
def get_resources(subdir: str) -> list[ZonaResource]: def get_resources(subdir: str) -> list[ZonaResource]:
"""Load the packaged resources in data/subdir""" """Load the packaged resources in data/subdir"""
out: list[ZonaResource] = [] out: list[ZonaResource] = []
@ -65,11 +75,28 @@ def normalize_url(url: str) -> str:
return url return url
def should_ignore( def should_ignore(path: Path, patterns: list[str], base: Path) -> bool:
path: Path, patterns: list[str], base: Path
) -> bool:
rel_path = path.relative_to(base) rel_path = path.relative_to(base)
return any( return any(
fnmatch.fnmatch(str(rel_path), pattern) fnmatch.fnmatch(str(rel_path), pattern) for pattern in patterns
for pattern in patterns
) )
MINIFY_JS_PATTERN = re.compile(
r"""
//.*?$ |
/\*.*?\*/ |
\s+
""",
re.MULTILINE | re.DOTALL | re.VERBOSE,
)
def minify_js(js: str) -> str:
"""Naively minifies JavaScript by stripping comments and whitespace."""
return MINIFY_JS_PATTERN.sub(
# replace whitespace with single space,
# strip comments
lambda m: " " if m.group(0).isspace() else "",
js,
).strip()