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 e1056df747 - Show all commits
+15 -24
View File
@@ -42,28 +42,22 @@
return;
}
// Measure each logical line's offsetTop (viewport-relative for
// comparison with gutter rows rendered in the same scroll flow).
// Reading all rects first avoids interleaved layout reads/writes.
var tops = [];
for (var i = 0; i < lines.length; i++) {
tops.push(lines[i].getBoundingClientRect().top);
}
// Build one gutline per visual row of the tallest column (the code
// body itself); each number is assigned to the visual row whose top
// is closest to its line's top.
// 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).
var bodyTop = body.getBoundingClientRect().top;
var lh = parseFloat(getComputedStyle(body).lineHeight) || 1;
var maxBottom = 0;
for (var j = 0; j < lines.length; j++) {
var btm = lines[j].getBoundingClientRect().bottom - bodyTop;
if (btm > maxBottom) maxBottom = btm;
var rowIdx = [];
var totalRows = 1;
for (var i = 0; i < lines.length; i++) {
var row = Math.round((lines[i].getBoundingClientRect().top - bodyTop) / lh);
if (row < 0) row = 0;
rowIdx.push(row);
if (row + 1 > totalRows) totalRows = row + 1;
}
// Rows needed through the last visual row of the deepest line (ceil, so a
// partially-filled last row still gets its gutter span).
// Rows needed: floor(last line bottom / lh) + 1 — the row a line STARTS on
// must exist even when its bottom lands exactly on the body's edge.
var totalRows = Math.max(lines.length, Math.floor(maxBottom / lh) + 1);
if (totalRows < lines.length) totalRows = lines.length;
gutter.textContent = '';
var frag = document.createDocumentFragment();
var spans = [];
@@ -75,11 +69,8 @@
frag.appendChild(cell);
}
gutter.appendChild(frag);
for (var j = 0; j < tops.length; j++) {
var row = Math.round((tops[j] - bodyTop) / lh);
if (row < 0) row = 0;
if (row > totalRows - 1) row = totalRows - 1;
spans[row].textContent = String(j + 1);
for (var j = 0; j < rowIdx.length; j++) {
spans[rowIdx[j]].textContent = String(j + 1);
}
// A wrapped line whose last visual row is only partially filled can
// settle a hair under N * line-height after the gutter is rebuilt; a