From 27778f0840895bf5e029d8c962e99890b8a0a8f6 Mon Sep 17 00:00:00 2001 From: Jamie Peabody Date: Mon, 23 Feb 2026 21:51:02 +0000 Subject: [PATCH] fix(#222): Fixed issue with poor rendering performance and marker misalignment * fix(#222): Fixed poor rendering performance in large files * fix(#222): Right-hand editor gutter marker was not aligned correctly (#227) --- src/diff-view.js | 8 ++++++-- src/vdoc.js | 23 +++++++++++++---------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/src/diff-view.js b/src/diff-view.js index 23fb782..5465317 100644 --- a/src/diff-view.js +++ b/src/diff-view.js @@ -740,6 +740,10 @@ CodeMirrorDiffView.prototype._isChangeInView = function(side, vp, change) { return true; } + // there are 3 conditions to test + // 1: the change "from" is within the viewport from/to + // 2: the change "to" is within the viewport from/to + // 3: the change is so big that the viewport is within return (change[`${side}-line-from`] >= vp.from && change[`${side}-line-from`] <= vp.to) || (change[`${side}-line-to`] >= vp.from && change[`${side}-line-to`] <= vp.to) || (vp.from >= change[`${side}-line-from`] && vp.to <= change[`${side}-line-to`]); @@ -1090,8 +1094,8 @@ CodeMirrorDiffView.prototype._renderDiff = function(changes) { ctx_lhs.strokeRect(1.5, mkr_lhs_y_start, 4.5, Math.max(mkr_lhs_y_end - mkr_lhs_y_start, 5)); ctx_lhs.stroke(); - const mkr_rhs_y_start = change['rhs-y-start'] * lratio; - const mkr_rhs_y_end = Math.max(change['rhs-y-end'] * lratio, 5); + const mkr_rhs_y_start = change['rhs-y-start'] * rratio; + const mkr_rhs_y_end = Math.max(change['rhs-y-end'] * rratio, 5); ctx_rhs.beginPath(); ctx_rhs.fillStyle = '#a3a3a3'; ctx_rhs.strokeStyle = '#000'; diff --git a/src/vdoc.js b/src/vdoc.js index ef82639..b2ec751 100644 --- a/src/vdoc.js +++ b/src/vdoc.js @@ -205,9 +205,13 @@ class VDoc { if (this.options._debug) { trace('vdoc#update', side, editor, viewport); } - const lines = Object.keys(this._lines[side]); - for (let i = 0; i < lines.length; ++i) { - const id = lines[i]; + const keys = Object.keys(this._lines[side]); + // while Mergely diffs unicode diacritic chars (letters+mark), + // CM is by character, so diffs need to be mapped. + const mappedChars = mapLettersToChars(editor.getValue()); + + for (const key of keys) { + const { id } = this._lines[side][key]; if (id < viewport.from || id > viewport.to) { continue; } @@ -216,7 +220,7 @@ class VDoc { if (vline.rendered) { continue; } - vline.update(editor); + vline.update(editor, mappedChars); } } @@ -257,7 +261,7 @@ class VLine { this.markup.push([ charFrom, charTo, className ]); } - update(editor) { + update(editor, mappedChars) { if (this.rendered) { // FIXME: probably do not need this now console.log('already rendered', this.id); @@ -279,18 +283,17 @@ class VLine { editor.setGutterMarker(this.id, name, item); } if (this.markup.length) { - // while Mergely diffs unicode chars (letters+mark), CM is by character, - // so diffs need to be mapped. - const mapped = mapLettersToChars(editor.getValue()); + // while Mergely diffs unicode diacritic chars (letters+mark), + // CM is by character, so diffs need to be mapped. for (const markup of this.markup) { const [ charFrom, charTo, className ] = markup; const fromPos = { line: this.id }; const toPos = { line: this.id }; if (charFrom >= 0) { - fromPos.ch = mapped[charFrom]; + fromPos.ch = mappedChars[charFrom]; } if (charTo >= 0) { - toPos.ch = mapped[charTo]; + toPos.ch = mappedChars[charTo]; } this._clearMarkup.push( editor.markText(fromPos, toPos, { className }));