From 9a6cabf8846df01bd8b6bb17cee06bccc120daee Mon Sep 17 00:00:00 2001 From: Matt Bierner <12821956+mjbvz@users.noreply.github.com> Date: Tue, 5 May 2026 08:21:16 -0700 Subject: [PATCH] Fix some bugs around preserving location when switching current tab to md preview --- .../preview-src/index.ts | 8 ++++-- .../src/preview/preview.ts | 2 +- .../src/preview/previewManager.ts | 28 +++++++++++++------ .../src/preview/topmostLineMonitor.ts | 6 ---- 4 files changed, 26 insertions(+), 18 deletions(-) diff --git a/extensions/markdown-language-features/preview-src/index.ts b/extensions/markdown-language-features/preview-src/index.ts index 46363267631..9cfe14556f1 100644 --- a/extensions/markdown-language-features/preview-src/index.ts +++ b/extensions/markdown-language-features/preview-src/index.ts @@ -38,8 +38,10 @@ const state: State = { ...getData>('data-state') }; -if (typeof originalState.scrollProgress !== 'undefined' && originalState?.resource !== state.resource) { - state.scrollProgress = 0; +const hasStartingLine = typeof settings.settings.line === 'number' && !isNaN(settings.settings.line); +if (typeof originalState.scrollProgress !== 'undefined' + && (originalState?.resource !== state.resource || (hasStartingLine && originalState.line !== settings.settings.line))) { + state.scrollProgress = undefined; } // Make sure to sync VS Code state here @@ -419,6 +421,8 @@ window.addEventListener('scroll', throttle(() => { const line = getEditorLineNumberForPageOffset(window.scrollY, documentVersion); if (typeof line === 'number' && !isNaN(line)) { + state.line = line; + vscode.setState(state); messaging.postMessage('revealLine', { line }); } }, 50)); diff --git a/extensions/markdown-language-features/src/preview/preview.ts b/extensions/markdown-language-features/src/preview/preview.ts index 5a5649981d7..699237aa7b8 100644 --- a/extensions/markdown-language-features/src/preview/preview.ts +++ b/extensions/markdown-language-features/src/preview/preview.ts @@ -537,7 +537,7 @@ export class StaticMarkdownPreview extends Disposable implements IManagedMarkdow this.#webviewPanel = webviewPanel; this.#previewConfigurations = previewConfigurations; - const topScrollLocation = scrollLine ? new StartingScrollLine(scrollLine) : undefined; + const topScrollLocation = typeof scrollLine === 'number' ? new StartingScrollLine(scrollLine) : undefined; this.#preview = this._register(new MarkdownPreview(this.#webviewPanel, resource, topScrollLocation, { getAdditionalState: () => { return {}; }, getLineChanges, diff --git a/extensions/markdown-language-features/src/preview/previewManager.ts b/extensions/markdown-language-features/src/preview/previewManager.ts index cc6018b6d3b..f80e78214ab 100644 --- a/extensions/markdown-language-features/src/preview/previewManager.ts +++ b/extensions/markdown-language-features/src/preview/previewManager.ts @@ -13,8 +13,8 @@ import { MdDocumentRenderer } from './documentRenderer'; import { MarkdownPreviewLineDiffProvider } from './lineDiff'; import { DynamicMarkdownPreview, IManagedMarkdownPreview, StaticMarkdownPreview } from './preview'; import { MarkdownPreviewConfigurationManager } from './previewConfig'; -import { scrollEditorToLine, StartingScrollFragment } from './scrolling'; -import { TopmostLineMonitor } from './topmostLineMonitor'; +import { scrollEditorToLine, StartingScrollFragment, StartingScrollLine, StartingScrollLocation } from './scrolling'; +import { getVisibleLine, TopmostLineMonitor } from './topmostLineMonitor'; import type { MarkdownPreviewLineChanges } from '../../types/previewMessaging'; @@ -138,16 +138,17 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview resource: vscode.Uri, settings: DynamicPreviewSettings ): void { + const scrollLocation = resource.fragment ? new StartingScrollFragment(resource.fragment) : this.#getActiveTextEditorScrollLocation(resource); let preview = this.#dynamicPreviews.get(resource, settings); if (preview) { preview.reveal(settings.previewColumn); } else { - preview = this.#createNewDynamicPreview(resource, settings); + preview = this.#createNewDynamicPreview(resource, settings, scrollLocation); } preview.update( resource, - resource.fragment ? new StartingScrollFragment(resource.fragment) : undefined + scrollLocation ); } @@ -278,7 +279,7 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview webview: vscode.WebviewPanel, getLineChanges?: () => MarkdownPreviewLineChanges | Promise | undefined, ): StaticMarkdownPreview { - const lineNumber = this.#topmostLineMonitor.getPreviousStaticTextEditorLineByUri(document.uri); + const lineNumber = this.#topmostLineMonitor.getPreviousTextEditorLineByUri(document.uri); const preview = StaticMarkdownPreview.revive( document.uri, webview, @@ -383,16 +384,15 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview #createNewDynamicPreview( resource: vscode.Uri, - previewSettings: DynamicPreviewSettings + previewSettings: DynamicPreviewSettings, + scrollLocation: StartingScrollLocation | undefined, ): DynamicMarkdownPreview { - const activeTextEditorURI = vscode.window.activeTextEditor?.document.uri; - const scrollLine = (activeTextEditorURI?.toString() === resource.toString()) ? vscode.window.activeTextEditor?.visibleRanges[0].start.line : undefined; const preview = DynamicMarkdownPreview.create( { resource, resourceColumn: previewSettings.resourceColumn, locked: previewSettings.locked, - line: scrollLine, + line: scrollLocation?.type === 'line' ? scrollLocation.line : undefined, }, previewSettings.previewColumn, this.#contentProvider, @@ -406,6 +406,16 @@ export class MarkdownPreviewManager extends Disposable implements vscode.Webview return this.#registerDynamicPreview(preview); } + #getActiveTextEditorScrollLocation(resource: vscode.Uri): StartingScrollLine | undefined { + const editor = vscode.window.activeTextEditor; + if (editor?.document.uri.toString() !== resource.toString()) { + return undefined; + } + + const line = getVisibleLine(editor); + return typeof line === 'number' ? new StartingScrollLine(line) : undefined; + } + #registerDynamicPreview(preview: DynamicMarkdownPreview): DynamicMarkdownPreview { this.#dynamicPreviews.add(preview); diff --git a/extensions/markdown-language-features/src/preview/topmostLineMonitor.ts b/extensions/markdown-language-features/src/preview/topmostLineMonitor.ts index 59fdbb13cfd..7ddaa1ac74a 100644 --- a/extensions/markdown-language-features/src/preview/topmostLineMonitor.ts +++ b/extensions/markdown-language-features/src/preview/topmostLineMonitor.ts @@ -62,12 +62,6 @@ export class TopmostLineMonitor extends Disposable { this.#previousTextEditorInfo.delete(resource); return scrollLoc?.line; } - - public getPreviousStaticTextEditorLineByUri(resource: vscode.Uri): number | undefined { - const state = this.#previousStaticEditorInfo.get(resource); - return state?.line; - } - public updateLine( resource: vscode.Uri, line: number