Release v0.4.0: dev -> main #251
@@ -42,28 +42,22 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Measure each logical line's offsetTop (viewport-relative for
|
// Measure each logical line's geometry. Reading all rects first avoids
|
||||||
// comparison with gutter rows rendered in the same scroll flow).
|
// interleaved layout reads/writes. A line's number goes on the visual row
|
||||||
// Reading all rects first avoids interleaved layout reads/writes.
|
// whose top matches the line's top; the gutter is sized to cover the
|
||||||
var tops = [];
|
// deepest row any line STARTS on (a trailing empty logical line renders
|
||||||
for (var i = 0; i < lines.length; i++) {
|
// with zero height but still needs its number row).
|
||||||
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.
|
|
||||||
var bodyTop = body.getBoundingClientRect().top;
|
var bodyTop = body.getBoundingClientRect().top;
|
||||||
var lh = parseFloat(getComputedStyle(body).lineHeight) || 1;
|
var lh = parseFloat(getComputedStyle(body).lineHeight) || 1;
|
||||||
var maxBottom = 0;
|
var rowIdx = [];
|
||||||
for (var j = 0; j < lines.length; j++) {
|
var totalRows = 1;
|
||||||
var btm = lines[j].getBoundingClientRect().bottom - bodyTop;
|
for (var i = 0; i < lines.length; i++) {
|
||||||
if (btm > maxBottom) maxBottom = btm;
|
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
|
if (totalRows < lines.length) totalRows = lines.length;
|
||||||
// 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);
|
|
||||||
gutter.textContent = '';
|
gutter.textContent = '';
|
||||||
var frag = document.createDocumentFragment();
|
var frag = document.createDocumentFragment();
|
||||||
var spans = [];
|
var spans = [];
|
||||||
@@ -75,11 +69,8 @@
|
|||||||
frag.appendChild(cell);
|
frag.appendChild(cell);
|
||||||
}
|
}
|
||||||
gutter.appendChild(frag);
|
gutter.appendChild(frag);
|
||||||
for (var j = 0; j < tops.length; j++) {
|
for (var j = 0; j < rowIdx.length; j++) {
|
||||||
var row = Math.round((tops[j] - bodyTop) / lh);
|
spans[rowIdx[j]].textContent = String(j + 1);
|
||||||
if (row < 0) row = 0;
|
|
||||||
if (row > totalRows - 1) row = totalRows - 1;
|
|
||||||
spans[row].textContent = String(j + 1);
|
|
||||||
}
|
}
|
||||||
// A wrapped line whose last visual row is only partially filled can
|
// 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
|
// settle a hair under N * line-height after the gutter is rebuilt; a
|
||||||
|
|||||||
Reference in New Issue
Block a user