An admin area a phone could reach and not navigate
Administration has a nav of its own rather than the chat sidebar, and 1.1.0 gave every `.sidebar` the drawer behaviour -- starts closed, slides in -- without giving that one any of the drawer's furniture. No id for the toggle to resolve, no toggle, no close, no scrim: it sat at left:-280 with nothing in the application able to open it. The close button and the scrim are partials now, used by both, and the test that guards it *finds* sidebars by scanning the templates rather than working from a list, which is exactly why this one was missed. The chat, measured at 390px, spent forty pixels of side padding and a forty-four pixel avatar column before drawing a word -- close to a quarter of the screen on margin, so anything that could not wrap had to be reached sideways. Padding halved and the avatar moved above the turn; a code block gained about sixty pixels. Worse in the same row: `.topbar__actions` asked for 317px of a 390px bar, because the control that used to give in that row is display:none below a tablet width, so the group went rigid and the title -- flex: 1 -- was squeezed to exactly zero. And `.btn--icon` sets a width with no `flex: none`, so the row shrank the button instead of the text: the sidebar toggle measured eighteen pixels across. The picker gives now, and shows its avatar rather than its name on a phone. Also the instrument, which lied twice more: it could not see horizontal overflow at all, because `.shell` is overflow:hidden and its "is this contained" test therefore answered yes for everything on the page; and run from a copy it resolved `STATIC` to a directory that did not exist, rewrote every asset URL to a dead file:// path and reported the whole application overflowing by thirty thousand pixels. It resolves from the imported package now and asserts that what it rewrote to is really there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+35
-5
@@ -29,10 +29,19 @@ import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
REPO = Path(__file__).resolve().parent.parent
|
||||
SRC = REPO / "src"
|
||||
sys.path.insert(0, str(SRC))
|
||||
sys.path.insert(0, str(REPO / "src"))
|
||||
|
||||
STATIC = SRC / "lembas/web/static"
|
||||
# Resolved from the package that actually got imported, not from where this
|
||||
# file happens to sit. A copy of this script run from somewhere else silently
|
||||
# pointed STATIC at a directory that did not exist, every asset URL was
|
||||
# rewritten to a file:// path with nothing behind it, and the run measured an
|
||||
# unstyled document -- reporting that every page in the application overflowed
|
||||
# by thirty thousand pixels. The guard below only asked whether the URLs had
|
||||
# been rewritten, which they had.
|
||||
import lembas # noqa: E402
|
||||
|
||||
SRC = Path(lembas.__file__).resolve().parent.parent
|
||||
STATIC = Path(lembas.__file__).resolve().parent / "web/static"
|
||||
CHROMIUM = shutil.which("chromium") or shutil.which("chromium-browser")
|
||||
|
||||
# Routes that are served by the app rather than mounted, so the rewrite has to
|
||||
@@ -131,8 +140,17 @@ window.__measure = function () {
|
||||
tallCulprits: culprits('y'),
|
||||
wideCulprits: culprits('x'),
|
||||
/* The invariant: the application shell fills the window and the DOCUMENT
|
||||
never scrolls. A document taller than the window is the /settings bug. */
|
||||
documentScrolls: de.scrollHeight > window.innerHeight + 1,
|
||||
never scrolls *for the reader*. A document taller than the window is the
|
||||
/settings bug -- but only when the reader can actually move it. `overflow:
|
||||
hidden` blocks a wheel and a finger while still permitting an assignment
|
||||
to scrollTop, so a page whose shell clips a tall descendant reports a
|
||||
scrollHeight of thousands and scrolls for nobody. /admin/prompts does
|
||||
exactly that, and reading the raw height called it a bug four times. */
|
||||
documentScrolls:
|
||||
de.scrollHeight > window.innerHeight + 1 &&
|
||||
["visible", "auto", "scroll"].indexOf(
|
||||
getComputedStyle(document.documentElement).overflowY
|
||||
) !== -1,
|
||||
scrollsSideways: de.scrollWidth > window.innerWidth + 1,
|
||||
smallTargets: small.slice(0, 40),
|
||||
smallCount: small.length,
|
||||
@@ -219,6 +237,18 @@ def rewrite(html: str, client, assets: Path) -> str:
|
||||
f"{sorted(set(blocking))[:8]}"
|
||||
)
|
||||
|
||||
# And that what they were rewritten *to* is really there. A rewrite that
|
||||
# matches and produces a dead path is indistinguishable, from inside the
|
||||
# browser, from no stylesheet at all -- and it is the failure that actually
|
||||
# happened, twice.
|
||||
missing = [
|
||||
url
|
||||
for url in re.findall(r'(?:href|src)="file://([^"?]+)"', html)
|
||||
if not Path(url).exists()
|
||||
]
|
||||
if missing:
|
||||
raise SystemExit(f"REWRITTEN TO NOTHING -- still an unstyled document: {missing[:5]}")
|
||||
|
||||
# The one-time notifications offer is a modal over the very page we came
|
||||
# to measure, and it is gated on a localStorage key. Set it in the head, so
|
||||
# it runs before the deferred script that reads it.
|
||||
|
||||
Reference in New Issue
Block a user