Release v0.4.0: dev -> main #251
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user