Skip to content

Commit 91327d1

Browse files
committed
feat(mdviewer): add persistent bidirectional cursor sync highlights
Show a subtle background highlight on the synced element/line when cursor is on the other side: CM cursor → viewer element highlight, viewer cursor → CM line highlight. Highlights clear when focus moves to the highlighted panel (no highlight on the active panel). Works in both light and dark themes.
1 parent 605c7fa commit 91327d1

4 files changed

Lines changed: 50 additions & 0 deletions

File tree

src-mdviewer/src/bridge.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,8 +836,23 @@ function handleScrollToLine(data) {
836836
if (!isVisible) {
837837
bestEl.scrollIntoView({ behavior: "instant", block: "center" });
838838
}
839+
840+
// Persistent highlight on the element corresponding to the CM cursor.
841+
// Only show when CM has focus (not when viewer has focus).
842+
const prev = viewer.querySelector(".cursor-sync-highlight");
843+
if (prev) { prev.classList.remove("cursor-sync-highlight"); }
844+
bestEl.classList.add("cursor-sync-highlight");
839845
}
840846

847+
// Clear viewer highlight when viewer gets focus (user is editing in viewer)
848+
document.addEventListener("focusin", (e) => {
849+
const viewer = document.getElementById("viewer-content");
850+
if (viewer && viewer.contains(e.target)) {
851+
const prev = viewer.querySelector(".cursor-sync-highlight");
852+
if (prev) { prev.classList.remove("cursor-sync-highlight"); }
853+
}
854+
});
855+
841856
// --- Selection sync ---
842857

843858
function _clearSelectionHighlight() {

src-mdviewer/src/styles/markdown.css

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,16 @@
474474
background-color: rgba(50, 100, 220, 0.1);
475475
}
476476

477+
/* Persistent cursor-sync highlight on the element corresponding to CM cursor */
478+
.cursor-sync-highlight {
479+
background-color: rgba(100, 150, 255, 0.18);
480+
border-radius: 2px;
481+
}
482+
483+
[data-theme="light"] .cursor-sync-highlight {
484+
background-color: rgba(50, 100, 220, 0.14);
485+
}
486+
477487
/* ===== Mermaid diagrams ===== */
478488

479489
.mermaid-diagram {

src/extensionsIntegrated/Phoenix-live-preview/MarkdownSync.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,13 @@ define(function (require, exports, module) {
206206
_activeCM = cm;
207207
if (cm) {
208208
cm.on("cursorActivity", _cursorHandler);
209+
// Clear sync highlight when CM gets focus (user is editing in CM)
210+
cm.on("focus", function () {
211+
if (_highlightLineHandle) {
212+
cm.removeLineClass(_highlightLineHandle, "background", "cm-cursor-sync-highlight");
213+
_highlightLineHandle = null;
214+
}
215+
});
209216
// Listen for change origin (undo/redo detection)
210217
cm.on("change", function (_cm, changeObj) {
211218
if (changeObj) {
@@ -622,6 +629,18 @@ define(function (require, exports, module) {
622629
const targetScrollTop = lineTop - (scrollInfo.clientHeight / 2);
623630
cm.scrollTo(null, targetScrollTop);
624631
}
632+
633+
// Brief flash on the CM line to show cursor sync feedback
634+
_flashCMLine(cm, cmLine);
635+
}
636+
637+
let _highlightLineHandle = null;
638+
639+
function _flashCMLine(cm, line) {
640+
if (_highlightLineHandle) {
641+
cm.removeLineClass(_highlightLineHandle, "background", "cm-cursor-sync-highlight");
642+
}
643+
_highlightLineHandle = cm.addLineClass(line, "background", "cm-cursor-sync-highlight");
625644
}
626645

627646
// --- Selection sync ---
@@ -690,6 +709,7 @@ define(function (require, exports, module) {
690709
if (!selectedText) {
691710
// No selection — just move cursor to clear any existing selection
692711
cm.setCursor({ line: cmLine, ch: 0 });
712+
_flashCMLine(cm, cmLine);
693713
_syncingFromIframe = false;
694714
return;
695715
}

src/extensionsIntegrated/Phoenix-live-preview/live-preview.css

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,3 +248,8 @@
248248
.live-preview-overlay-close:hover {
249249
color: #fff;
250250
}
251+
252+
/* Persistent cursor-sync highlight on CM line corresponding to md viewer cursor */
253+
.cm-cursor-sync-highlight {
254+
background-color: rgba(100, 150, 255, 0.18) !important;
255+
}

0 commit comments

Comments
 (0)