Three things that only showed on screen

Grey letters ran down the bar while dragging a column edge. The editor marks
the column under the pointer by putting a small div in each of its cells;
drawn along the cell's right edge, that absolutely positioned child sent
Chromium down another painting path and the cell's own text came out a second
time, squeezed into the two pixels under the bar, one letter to a line. It
appeared with the bar and went with it, which named the culprit -- measured,
there was no text there at all, only three empty markers, and a forced repaint
did not clear it. The marker is display:none now and only says which cells the
column is made of; the line is an inset shadow on those cells, matched with
:has(). Two suspects were tried and reverted first: the table as its own paint
region, and separate borders. Neither changed anything, so neither stayed.

Opening a note flashed a long narrow page. The drawing stage starts at the
canonical page, 1600px tall, and the measurement that fits it to the pane ran
as an ordinary effect -- a frame too late. useLayoutEffect runs between the DOM
being built and the browser painting it, which is exactly the gap that flash
lived in. The test samples the sheet's height every frame across a note switch,
because one frame is all it was.

The mark above a note did not stand in the same column as the tools below it.
Vertically it was already exact -- measured, symbol centre 20, cap centre 20 --
but it began six pixels right of the first tool, and the title thirty. The
mark's box is only as wide as the mark now, so the mark lands on that column,
and the title follows nine pixels closer.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
marcandClaude Opus 5 committed 2026-08-17 19:14:38 +02:00
1 parent 1c0f2184e6
commit 641acaae40
7 files changed
+154 -19

No files matched your search

+29
View File
@@ -131,6 +131,35 @@ try {
);
check((await p.locator(".ProseMirror").innerText()).includes("Grundtext"), "plain text survived a reload");
await p.screenshot({ path: `${OUT}/editor-after-reload.png` });
/* ── the sheet is the right size from the first frame ──
* It was not. The stage starts at the canonical page, 1600px tall, and the
* measurement that pulls it back to the pane ran an ordinary effect — a frame
* too late. Every note opened by flashing a long narrow sheet and then
* righting itself. Sampled every frame, because one frame is all it was. */
const settled = await p.locator("[data-page-sheet]").first().evaluate((el) => el.getBoundingClientRect().height);
await p.evaluate(() => {
window.__tall = 0;
const tick = () => {
const el = document.querySelector("[data-page-sheet]");
if (el) window.__tall = Math.max(window.__tall, el.getBoundingClientRect().height);
window.__raf = requestAnimationFrame(tick);
};
tick();
});
await p.locator("button").filter({ hasText: "Ziel" }).first().click();
await p.waitForSelector(".ProseMirror", { timeout: 15000 });
await p.waitForTimeout(1500);
const tallest = await p.evaluate(() => {
cancelAnimationFrame(window.__raf);
return window.__tall;
});
check(
tallest <= settled * 1.15,
"switching notes never draws the sheet at the wrong size, not even for a frame",
`settled ${Math.round(settled)}, tallest ${Math.round(tallest)}`
);
await reopenNote(p, "Quelle");
/* ── how many pages the writing fills ── */
// Pages are a reading aid, not a change to the document: the note stays one
// body, and Markdown has no page. The height of one is the same 3:4 the canvas
+32
View File
@@ -120,6 +120,38 @@ try {
});
check(!/ne-page-spacer/.test(body || ""), "and no page furniture reaches the stored note");
check(/table/.test(body || ""), "which does hold the table itself", String(body || "").slice(0, 60));
/* ── the edge being dragged is drawn on the cell, not in it ──
* The editor marks the column under the pointer with a small div in each of
* its cells. Positioned along the cell's right edge it painted the cell's own
* text a second time, squeezed into the two pixels under the bar, one letter
* to a line — an absolutely positioned child inside a collapsed-border table
* cell sends Chromium down another painting path. The div is never drawn now;
* it only says which cells the column is made of. */
const cell = await p.locator(".ProseMirror table th").first().boundingBox();
await p.mouse.move(cell.x + cell.width - 1, cell.y + cell.height / 2);
await p.waitForTimeout(500);
const edge = await p.evaluate(() => {
const marks = [...document.querySelectorAll(".column-resize-handle")];
const host = marks[0]?.parentElement;
return {
marks: marks.length,
drawn: marks.map((m) => getComputedStyle(m).display),
onCell: host ? getComputedStyle(host).boxShadow : "",
painted: marks.every((m) => m.getBoundingClientRect().width === 0),
};
});
check(edge.marks > 0, "holding over a column edge marks that column", JSON.stringify(edge.marks));
check(
edge.drawn.every((d) => d === "none") && edge.painted,
"the marker itself is never painted",
JSON.stringify(edge.drawn)
);
check(
/inset/.test(edge.onCell) && edge.onCell !== "none",
"and the line is drawn on the cell that carries it",
edge.onCell
);
} catch (e) {
check(false, "suite ran to the end", e.message);
} finally {