Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions apps/vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Fixed a bug where formatting a code cell stripped leading empty lines. Leading empty lines between option directives and code are now preserved, and two or more leading empty lines are collapsed to one (<https://github.com/quarto-dev/quarto/pull/953>).
- Fixed a bug where IPython magics (`%`, `%%`) and shell escapes (`!`) in Python code cells produced spurious diagnostics from language servers like Pyrefly and Ruff. These lines are now commented out in the virtual document handed to language servers (<https://github.com/quarto-dev/quarto/pull/1013>).
- The "Render Document" command is now available in the Positron Notebook Editor (<https://github.com/quarto-dev/quarto/pull/1002>).
- Fixed notebooks failing to render or preview when they were visible but not active, or while the Panel or Sidebar were open (<https://github.com/quarto-dev/quarto/pull/1007>).

## 1.133.0 (Release on 2026-06-03)

Expand Down
97 changes: 70 additions & 27 deletions apps/vscode/src/core/doc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ export function preserveEditorFocus(editor?: QuartoEditor) {
editor =
editor ||
(vscode.window.activeTextEditor
? quartoEditor(vscode.window.activeTextEditor)
? quartoTextEditor(vscode.window.activeTextEditor)
: undefined);
if (editor) {
if (!isNotebook(editor?.document)) {
Expand Down Expand Up @@ -217,47 +217,63 @@ export function findQuartoEditor(
| vscode.NotebookDocument
| undefined;
if (notebookDocument) {
const textEditor = vscode.window.visibleTextEditors.find((editor) => {
return editor.document.uri.fsPath.includes(notebookDocument.uri.fsPath);
});
if (textEditor && filter(textEditor.document)) {
return quartoEditor(textEditor, engine, context, notebookDocument);
const firstCellDocument = notebookDocument.cellAt(0)?.document;
if (firstCellDocument && filter(firstCellDocument)) {
return quartoNotebookEditor(notebookEditor, firstCellDocument);
}
}
}

// active text editor
const textEditor = vscode.window.activeTextEditor;
if (textEditor && filter(textEditor.document)) {
return quartoEditor(textEditor, engine, context);
// check visible text editors
} else if (includeVisible) {
// visible visual editor (sometime it loses track of 'active' so we need to use 'visible')
const visibleVisualEditor = VisualEditorProvider.activeEditor(true);
if (visibleVisualEditor && filter(visibleVisualEditor.document)) {
return visibleVisualEditor;
}
return quartoTextEditor(textEditor, engine, context);
}

// visible text editors
const visibleEditor = vscode.window.visibleTextEditors.find((editor) =>
filter(editor.document)
);
if (visibleEditor) {
return quartoEditor(visibleEditor, engine, context);
} else {
return undefined;
}
} else {
return undefined;
// check visible editors

// visible visual editor (sometime it loses track of 'active' so we need to use 'visible')
const visibleVisualEditor = VisualEditorProvider.activeEditor(true);
if (visibleVisualEditor && filter(visibleVisualEditor.document)) {
return visibleVisualEditor;
}

// visible notebook editors
const visibleNotebookEditor = vscode.window.visibleNotebookEditors.find((editor) =>
filter(editor.notebook.cellAt(0)?.document)
);
if (visibleNotebookEditor) {
// NOTE: We used to get the text document belonging to the first item in
// `vscode.window.visibleTextEditors` whose URI matched the notebook.
// However, there was a bug where cells would stop appearing in
// `visibleTextEditors` when the Panel or Sidebar were open. Now we
// arbitrarily use the first cell's document. This is ok because,
// for notebooks, the rest of this extension only requires that
// `QuartoEditor.document` belongs to any cell in the notebook.
// A better longer-term solution would be to *not* require a text
// document for notebook `QuartoEditor`s and expose the required
// information (e.g. `document.uri`) in another way.
const firstCellDocument = visibleNotebookEditor.notebook.cellAt(0).document;
return quartoNotebookEditor(visibleNotebookEditor, firstCellDocument);
Comment thread
seeM marked this conversation as resolved.
}

// visible text editors
const visibleEditor = vscode.window.visibleTextEditors.find((editor) =>
filter(editor.document)
);
if (visibleEditor) {
return quartoTextEditor(visibleEditor, engine, context);
}

return undefined;
}

export function quartoEditor(
function quartoTextEditor(
editor: vscode.TextEditor,
engine?: MarkdownEngine,
context?: QuartoContext,
notebook?: NotebookDocument
) {
): QuartoEditor {
return {
document: editor.document,
activate: async () => {
Expand Down Expand Up @@ -285,6 +301,33 @@ export function quartoEditor(
};
}

function quartoNotebookEditor(
editor: vscode.NotebookEditor,
firstCellDocument: vscode.TextDocument,
): QuartoEditor {
return {
document: firstCellDocument,
activate: async () => {
// TODO: This should probably use showNotebookDocument.
// And we could probably also activate() notebook editors
// in many places where we currently skip notebooks.
// We're leaving it as showTextDocument for now to minimize
// the number of changes in this PR focused on #1006.
await vscode.window.showTextDocument(
firstCellDocument,
editor.viewColumn,
false
);
},
slideIndex: async () => {
// Throwing is safe, since the only place slideIndex is called today
// skips notebooks.
throw new Error("slideIndex not supported for notebook editors");
},
notebook: editor.notebook,
};
}

async function tryResolveUriToQuartoDoc(
resource: vscode.Uri
): Promise<vscode.TextDocument | undefined> {
Expand Down
29 changes: 29 additions & 0 deletions apps/vscode/src/test/examples/hello.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "e4e2834b",
"metadata": {},
"source": [
"# Heading"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e1181b7a",
"metadata": {},
"outputs": [],
"source": [
"print(\"Hello, world!\")"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading
Loading