Fix Monaco Peek References preview collapse (#7662)

Co-authored-by: Orca <help@stably.ai>
This commit is contained in:
Brennan Benson
2026-07-07 12:55:41 -07:00
committed by GitHub
co-authored by Orca
parent fed545d330
commit 0fe20ddff9
4 changed files with 177 additions and 0 deletions
+10
View File
@@ -1971,6 +1971,16 @@
pointer-events: auto;
}
/* Why: Monaco leaves the peek preview container `inline-block` and only sizes the
editor child, so the container shrink-wraps the child in BOTH axes while the
inherited automaticLayout ResizeObserver measures the container — a feedback
loop that ratchets the preview to blank at fractional zoom/DPI (issue #7405).
Pinning both dimensions to the splitview slot severs the loop. */
.monaco-editor .reference-zone-widget .preview.inline {
height: 100%;
width: 100%;
}
/* ── Git conflict decorations ───────────────────────────────────── */
.monaco-editor .orca-conflict-marker-line {
@@ -0,0 +1,98 @@
// @vitest-environment happy-dom
import { describe, expect, it, vi } from 'vitest'
import type * as Monaco from 'monaco-editor'
import { installMonacoPeekReferencesPreviewOptions } from './monaco-peek-preview-options'
type FakePreviewEditor = Pick<Monaco.editor.ICodeEditor, 'updateOptions'>
type FakeReferenceWidgetInstance = {
_preview?: FakePreviewEditor
_fillBody?: (containerElement: HTMLElement) => void
_revealReference?: (...args: unknown[]) => Promise<unknown>
}
function createReferenceWidgetConstructor(hooks: {
fillBody?: (instance: FakeReferenceWidgetInstance) => void
revealReference?: (instance: FakeReferenceWidgetInstance) => Promise<unknown>
}): {
prototype: FakeReferenceWidgetInstance &
Required<Pick<FakeReferenceWidgetInstance, '_fillBody' | '_revealReference'>>
} {
return {
prototype: {
_fillBody(this: FakeReferenceWidgetInstance): void {
hooks.fillBody?.(this)
},
async _revealReference(this: FakeReferenceWidgetInstance): Promise<unknown> {
return hooks.revealReference?.(this)
}
}
}
}
function createPreviewEditor(): FakePreviewEditor {
return { updateOptions: vi.fn() }
}
const peekPreviewOptions = {
smoothScrolling: false,
stickyScroll: { enabled: false },
wordWrap: 'off'
}
describe('installMonacoPeekReferencesPreviewOptions', () => {
it('updates the embedded preview after ReferenceWidget creates it', () => {
const preview = createPreviewEditor()
const referenceWidget = createReferenceWidgetConstructor({
fillBody(instance) {
instance._preview = preview
}
})
installMonacoPeekReferencesPreviewOptions(referenceWidget)
referenceWidget.prototype._fillBody(document.createElement('div'))
expect(preview.updateOptions).toHaveBeenCalledWith(peekPreviewOptions)
})
it('updates the embedded preview before revealing a reference', async () => {
const calls: string[] = []
const preview: FakePreviewEditor = {
updateOptions: vi.fn(() => calls.push('updateOptions'))
}
const referenceWidget = createReferenceWidgetConstructor({
revealReference: async () => {
calls.push('revealReference')
}
})
referenceWidget.prototype._preview = preview
installMonacoPeekReferencesPreviewOptions(referenceWidget)
await referenceWidget.prototype._revealReference('reference')
expect(calls).toEqual(['updateOptions', 'revealReference', 'updateOptions'])
expect(preview.updateOptions).toHaveBeenCalledWith(peekPreviewOptions)
})
it('skips patching when the private Monaco hooks are missing', () => {
const referenceWidget: { prototype: FakeReferenceWidgetInstance } = { prototype: {} }
installMonacoPeekReferencesPreviewOptions(referenceWidget)
expect(referenceWidget.prototype._fillBody).toBeUndefined()
expect(referenceWidget.prototype._revealReference).toBeUndefined()
})
it('does not wrap ReferenceWidget more than once', async () => {
const preview = createPreviewEditor()
const referenceWidget = createReferenceWidgetConstructor({})
referenceWidget.prototype._preview = preview
installMonacoPeekReferencesPreviewOptions(referenceWidget)
installMonacoPeekReferencesPreviewOptions(referenceWidget)
await referenceWidget.prototype._revealReference('reference')
expect(preview.updateOptions).toHaveBeenCalledTimes(2)
})
})
@@ -0,0 +1,67 @@
import type * as Monaco from 'monaco-editor'
import { ReferenceWidget as MonacoReferenceWidget } from 'monaco-editor/esm/vs/editor/contrib/gotoSymbol/browser/peek/referencesWidget.js'
type PeekPreviewEditor = Pick<Monaco.editor.ICodeEditor, 'updateOptions'>
const PEEK_REFERENCES_PREVIEW_OPTIONS: Monaco.editor.IEditorOptions = {
smoothScrolling: false,
stickyScroll: { enabled: false },
wordWrap: 'off'
}
type ReferenceWidgetInstance = {
_preview?: PeekPreviewEditor
_fillBody?: (containerElement: HTMLElement) => void
_revealReference?: (...args: unknown[]) => Promise<unknown>
}
type ReferenceWidgetConstructor = {
prototype: ReferenceWidgetInstance & {
__orcaPeekPreviewOptionsInstalled?: true
}
}
function applyPeekReferencesPreviewOptions(editor: PeekPreviewEditor | undefined): void {
// Why: Monaco embedded editors inherit Orca's full-editor options first.
// Peek previews are transient readers, so keep scroll/wrap widgets out of them.
editor?.updateOptions(PEEK_REFERENCES_PREVIEW_OPTIONS)
}
export function installMonacoPeekReferencesPreviewOptions(
referenceWidget: ReferenceWidgetConstructor = MonacoReferenceWidget as unknown as ReferenceWidgetConstructor
): void {
const prototype = referenceWidget.prototype
if (prototype.__orcaPeekPreviewOptionsInstalled) {
return
}
const originalFillBody = prototype._fillBody
const originalRevealReference = prototype._revealReference
// Why: these are private Monaco members with no stability guarantee; if an
// upgrade removes either, skip patching so Peek keeps Monaco's defaults.
if (typeof originalFillBody !== 'function' || typeof originalRevealReference !== 'function') {
return
}
prototype._fillBody = function fillBodyWithPeekPreviewOptions(
this: ReferenceWidgetInstance,
containerElement: HTMLElement
): void {
originalFillBody.call(this, containerElement)
applyPeekReferencesPreviewOptions(this._preview)
}
prototype._revealReference = async function revealReferenceWithPeekPreviewOptions(
this: ReferenceWidgetInstance,
...args: unknown[]
): Promise<unknown> {
applyPeekReferencesPreviewOptions(this._preview)
try {
return await originalRevealReference.apply(this, args)
} finally {
applyPeekReferencesPreviewOptions(this._preview)
}
}
prototype.__orcaPeekPreviewOptionsInstalled = true
}
+2
View File
@@ -13,6 +13,7 @@ import { registerSvelteLanguage } from './monaco-languages/register-svelte'
import { registerVueLanguage } from './monaco-languages/register-vue'
import { installMonacoDelayerCancellationGuard } from './monaco-delayer-cancellation-guard'
import { installMonacoDiffEditorDisposalGuard } from './monaco-diff-editor-disposal'
import { installMonacoPeekReferencesPreviewOptions } from './monaco-peek-preview-options'
import { installMonacoContextMenuPaste } from '@/components/editor/install-monaco-context-menu-paste'
globalThis.MonacoEnvironment = {
@@ -78,6 +79,7 @@ registerAstroLanguage(monaco)
registerNimLanguage(monaco)
installMonacoDelayerCancellationGuard()
installMonacoDiffEditorDisposalGuard(monaco)
installMonacoPeekReferencesPreviewOptions()
// Why: Monaco's built-in context-menu Paste reads navigator.clipboard, which is
// blocked in Orca's sandboxed renderer. Route it through the trusted IPC bridge
// so right-click Paste works like Cmd+V (which already works via native events).