Fix #167: renumber gutter to visual rows when line wrap is on
Split the paste codebody into per-line block spans (paste-lines.js) and rebuild the gutter from each line's wrapped height so numbers count visual rows, not logical lines. Pinned the gutter width (flex 0 0 auto, 3ch) so its row count no longer feeds back into the code column width. ResizeObserver renumbers on wrap toggle / resize; wrap-off behavior is unchanged (one number per newline).
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
// #167: with line wrapping on, a logical line can occupy several visual
|
||||
// lines; the gutter must show one number per VISUAL line. Per-line spans
|
||||
// give each logical line its own box so offsetTop order stays correct even
|
||||
// when highlighting spans cross no line boundaries.
|
||||
// give each logical line its own box so its height identifies the wrapped
|
||||
// row count; blank gutter rows keep numbers aligned with line starts.
|
||||
(function () {
|
||||
var body = document.getElementById('codebody');
|
||||
var gutter = document.getElementById('gutter');
|
||||
@@ -31,9 +31,9 @@
|
||||
// Each logical line block occupies rows = height / line-height when
|
||||
// wrapped; its number sits on the first row and the remaining rows get
|
||||
// blank gutter lines so numbers stay aligned with line starts.
|
||||
// The code column width must not change while measuring (the gutter is
|
||||
// flex-shrink:0 so its own row count never affects it), and renumber
|
||||
// must be idempotent to avoid a ResizeObserver feedback loop.
|
||||
// The gutter has a fixed CSS width now (.code .gutter), so its row
|
||||
// count never changes the code column width: measurement is stable
|
||||
// with no measurement/layout feedback.
|
||||
var lh = parseFloat(getComputedStyle(body).lineHeight) || 1;
|
||||
gutter.textContent = '';
|
||||
var frag = document.createDocumentFragment();
|
||||
@@ -61,19 +61,11 @@
|
||||
renumber();
|
||||
|
||||
// Re-renumber on toggle (theme.js toggles data-wrap on <html>) and on any
|
||||
// size change (paste of lots of text, window resize, zoom). Only width
|
||||
// changes of the code column affect wrapping, so observe width only —
|
||||
// height changes caused by our own renumbering must not re-trigger.
|
||||
// size change (paste of lots of text, window resize, zoom).
|
||||
var mo = new MutationObserver(renumber);
|
||||
mo.observe(document.documentElement, { attributes: true, attributeFilter: ['data-wrap'] });
|
||||
var lastW = body.getBoundingClientRect().width;
|
||||
if (window.ResizeObserver) {
|
||||
var ro = new ResizeObserver(function () {
|
||||
var w = body.getBoundingClientRect().width;
|
||||
if (Math.abs(w - lastW) < 0.5) return;
|
||||
lastW = w;
|
||||
renumber();
|
||||
});
|
||||
var ro = new ResizeObserver(function () { renumber(); });
|
||||
ro.observe(body);
|
||||
} else {
|
||||
window.addEventListener('resize', renumber);
|
||||
|
||||
Reference in New Issue
Block a user