Release v0.4.0: dev -> main #251

Merged
fen merged 138 commits from dev into main 2026-09-17 15:35:21 +00:00
Showing only changes of commit 5c6cd40539 - Show all commits
+12 -12
View File
@@ -28,9 +28,11 @@
body.innerHTML = out.join('');
}
// One .gutline block per visual row. Numbers are placed at the gutter row
// whose top matches their .codeline's top; filler rows pad the gaps so
// alignment is driven by measured geometry, not by uniform row counts.
// One .gutline block per visual row. The gutter must reproduce the code
// column's REAL rendered rows: each number goes on the visual row whose top
// matches its .codeline's top (a line wrapping to N rows gets its number on
// the FIRST of those rows), and filler rows pad the gaps. Geometry is
// measured, not derived from span counts or heights.
function renumber() {
var lines = body.querySelectorAll('.codeline');
if (!wrapOn() || !lines.length) {
@@ -42,11 +44,8 @@
return;
}
// Measure each logical line's geometry. Reading all rects first avoids
// interleaved layout reads/writes. A line's number goes on the visual row
// whose top matches the line's top; the gutter is sized to cover the
// deepest row any line STARTS on (a trailing empty logical line renders
// with zero height but still needs its number row).
// Read all rects first: batching layout reads before the writes below
// avoids interleaved read/write reflows.
var bodyTop = body.getBoundingClientRect().top;
var lh = parseFloat(getComputedStyle(body).lineHeight) || 1;
var rowIdx = [];
@@ -76,15 +75,16 @@
// settle a hair under N * line-height after the gutter is rebuilt; a
// gutter pass that changes the code column width reflows it. Verify the
// placement one frame later and re-run if any line's row moved (#167).
var placed = {};
for (var q = 0; q < tops.length; q++) placed[q] = Math.round((tops[q] - bodyTop) / lh);
var placed = [];
for (var p = 0; p < rowIdx.length; p++) placed.push(rowIdx[p]);
requestAnimationFrame(function () {
var moved = false;
var bodyTop2 = body.getBoundingClientRect().top;
var lh2 = parseFloat(getComputedStyle(body).lineHeight) || lh;
var tops2 = [];
for (var q2 = 0; q2 < lines.length; q2++) tops2.push(lines[q2].getBoundingClientRect().top);
var bodyTop2 = body.getBoundingClientRect().top;
for (var q3 = 0; q3 < tops2.length; q3++) {
if (Math.round((tops2[q3] - bodyTop2) / lh) !== placed[q3]) { moved = true; break; }
if (Math.round((tops2[q3] - bodyTop2) / lh2) !== placed[q3]) { moved = true; break; }
}
if (moved) renumber();
});