studio: version text in the status bar, favicon
Deploy web Studio / deploy (push) Successful in 3m15s
Deploy web Studio / deploy (push) Successful in 3m15s
The status bar ends with "isokit <engine version>"; the web build adds the commit (linked on Gitea), its date as a tooltip and a "+" when built from a tree with uncommitted changes (build_web.py writes a <meta name="isokit-build"> from GITHUB_SHA or git). /api/meta now carries "engine". studio/favicon.svg (isometric cube in the accent green) is served by `isokit studio` (also on /view) and copied into the web build. check_web.py and check_studio.py check both.
This commit is contained in:
1 parent
c1d01331ac
commit
c647f39059
11 files changed
+66
-4
No files matched your search
+24
-3
@@ -81,6 +81,24 @@ def demo_files():
|
||||
return out
|
||||
|
||||
|
||||
def build_info():
|
||||
"""'<commit> <commit date> [dirty]' for the version text in the Studio's
|
||||
status bar; GITHUB_SHA (CI) wins over git. Empty when git is missing."""
|
||||
def git(*args):
|
||||
r = subprocess.run(["git", *args], capture_output=True, text=True, cwd=ROOT)
|
||||
return r.stdout.strip() if r.returncode == 0 else ""
|
||||
try:
|
||||
sha = os.environ.get("GITHUB_SHA") or git("rev-parse", "HEAD")
|
||||
if not sha:
|
||||
return ""
|
||||
parts = [sha, git("log", "-1", "--format=%cs", sha) or "-"]
|
||||
if git("status", "--porcelain", "--untracked-files=no"):
|
||||
parts.append("dirty")
|
||||
return " ".join(parts)
|
||||
except OSError:
|
||||
return ""
|
||||
|
||||
|
||||
def replace_once(s, old, new):
|
||||
n = s.count(old)
|
||||
assert n == 1, f"studio/index.html: expected {old!r} once, found {n}"
|
||||
@@ -116,7 +134,7 @@ def main():
|
||||
print(" (wasm-opt not found: the .wasm stays unoptimised by binaryen, about 15% larger)")
|
||||
|
||||
for src, dst in [("viewer/isokit-view.js", "viewer"), ("viewer/isokit-view.css", "viewer"),
|
||||
("studio/studio.js", "studio"), ("studio/studio.css", "studio"),
|
||||
("studio/studio.js", "studio"), ("studio/studio.css", "studio"), ("studio/favicon.svg", "studio"),
|
||||
("web/web.js", "web"), ("web/web.css", "web")]:
|
||||
(out / "assets" / dst).mkdir(parents=True, exist_ok=True)
|
||||
shutil.copy2(ROOT / src, out / "assets" / dst / Path(src).name)
|
||||
@@ -129,8 +147,11 @@ def main():
|
||||
v = "v=" + h.hexdigest()[:10]
|
||||
|
||||
html = (ROOT / "studio" / "index.html").read_text(encoding="utf-8")
|
||||
build = build_info()
|
||||
html = replace_once(html, '<title>isokit Studio</title>',
|
||||
'<title>isokit Studio</title>\n<meta name="description" content="isokit Studio: edit isometric site plans in the browser.">')
|
||||
'<title>isokit Studio</title>\n<meta name="description" content="isokit Studio: edit isometric site plans in the browser.">'
|
||||
+ (f'\n<meta name="isokit-build" content="{build}">' if build else ""))
|
||||
html = replace_once(html, 'href="/assets/studio/favicon.svg"', f'href="assets/studio/favicon.svg?{v}"')
|
||||
html = replace_once(html, 'href="/assets/viewer/isokit-view.css"', f'href="assets/viewer/isokit-view.css?{v}"')
|
||||
html = replace_once(html, '<link rel="stylesheet" href="/assets/theme.css">', '<style id="iso-theme"></style>')
|
||||
html = replace_once(html, '<link rel="stylesheet" href="/assets/studio/studio.css">',
|
||||
@@ -148,7 +169,7 @@ def main():
|
||||
if p.is_file():
|
||||
total += p.stat().st_size
|
||||
print(f" {p.relative_to(out).as_posix():40} {p.stat().st_size / 1024:8.1f} kB")
|
||||
print(f"{out} ({total / 1024 / 1024:.1f} MB, {v})")
|
||||
print(f"{out} ({total / 1024 / 1024:.1f} MB, {v}, build {build or 'unknown'})")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -48,6 +48,10 @@ with sync_playwright() as p:
|
||||
n0 = len(doc()["objects"])
|
||||
check(pg.locator("#objects li").count() == n0, f"object list shows {n0} objects")
|
||||
check(pg.locator(".st-tile").count() >= 20, "palette lists the prefabs")
|
||||
ver = pg.locator("#ver").inner_text()
|
||||
check(ver == "isokit " + get("/api/meta")["engine"], "status bar shows the engine version: " + ver)
|
||||
icon = urllib.request.urlopen(BASE + "/assets/studio/favicon.svg")
|
||||
check(icon.headers.get_content_type() == "image/svg+xml" and b"<svg" in icon.read(), "favicon served as SVG")
|
||||
pg.screenshot(path=str(OUT / "studio-start.jpg"), type="jpeg", quality=80)
|
||||
|
||||
# place a tree: pick it in the palette, click an empty spot of the map
|
||||
|
||||
@@ -89,6 +89,11 @@ try:
|
||||
check(pg.evaluate("() => getComputedStyle(document.querySelector('.iso-svg .iso-t')).fill") not in ("", "rgb(0, 0, 0)"),
|
||||
"theme CSS styles the scene")
|
||||
check(pg.evaluate("() => isokit.webmcp") == 15, "15 MCP tools registered with WebMCP")
|
||||
ver = pg.locator("#ver").inner_text()
|
||||
check(ver.startswith("isokit " + pg.evaluate("() => isokit.engine") + " · "), "status bar shows version and build: " + ver)
|
||||
icon = pg.evaluate("""async () => { const l = document.querySelector('link[rel=icon]');
|
||||
const r = await fetch(l.href); return r.ok && (await r.text()).includes('<svg'); }""")
|
||||
check(icon, "favicon link loads an SVG")
|
||||
shot(pg, "web-start.jpg")
|
||||
|
||||
# ---------------------------------------------------------------- edit: place, drag, props, undo
|
||||
|
||||
Reference in new issue
Block a user