Skip to content

Conversation

@mjbvz
Copy link
Collaborator

@mjbvz mjbvz commented Jan 29, 2026

Provides a better editor title when the diagram is opened

@mjbvz mjbvz self-assigned this Jan 29, 2026
Copilot AI review requested due to automatic review settings January 29, 2026 00:11
@vs-code-engineering vs-code-engineering bot added this to the January 2026 milestone Jan 29, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for optional titles for Mermaid diagrams generated through the language model tool. The title is provided by the LM when calling the renderMermaidDiagram tool and flows through the chat output renderer to be displayed as the editor title when the diagram is opened in a dedicated editor panel.

Changes:

  • Added optional title parameter to the renderMermaidDiagram LM tool schema
  • Updated data encoding/decoding to support title in JSON format with backward compatibility for legacy plain-text format
  • Modified webview manager to track title information for each webview
  • Enhanced editor manager to accept and display custom titles when opening diagram previews

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
package.json Added optional title field to the renderMermaidDiagram tool input schema
chatOutputRenderer.ts Updated tool output encoding to include title in JSON format, added backward-compatible decoder, and created fence generation utility
webviewManager.ts Extended MermaidWebviewInfo interface and registerWebview method to include title parameter
editorManager.ts Modified openPreview and MermaidPreview.create to accept and use title parameter for panel titles


// Register with the webview manager
this._register(this._webviewManager.registerWebview(this.diagramId, this._webviewPanel.webview, this._mermaidSource, 'editor'));
this._register(this._webviewManager.registerWebview(this.diagramId, this._webviewPanel.webview, this._mermaidSource, undefined, 'editor'));
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The title parameter is not being passed through to the webview registration. The title is received in the create method and used to set the panel title, but it's then discarded. At line 178, undefined is hardcoded as the title parameter when registering the webview. This means the title won't be available in the MermaidWebviewInfo, and won't be passed when opening the diagram in an editor from the revive path.

To fix this, the title should be stored in the MermaidPreview class (e.g., as a private readonly field) and passed to registerWebview instead of undefined.

Suggested change
this._register(this._webviewManager.registerWebview(this.diagramId, this._webviewPanel.webview, this._mermaidSource, undefined, 'editor'));
this._register(this._webviewManager.registerWebview(this.diagramId, this._webviewPanel.webview, this._mermaidSource, this._webviewPanel.title, 'editor'));

Copilot uses AI. Check for mistakes.
Comment on lines +185 to +190
const backtickMatch = content.matchAll(/`+/g);
if (!backtickMatch) {
return '```';
}

const maxBackticks = Math.max(...Array.from(backtickMatch, s => s[0].length));
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic for checking if backtickMatch is falsy is incorrect. The matchAll() method always returns an iterator object, never null or undefined, so the condition on line 186 will never be true. Additionally, if there are no backticks in the content, the Array.from() call on line 190 will create an empty array, and Math.max() with an empty array returns -Infinity, which will cause Math.max(3, -Infinity + 1) to return 3 but only by accident.

The correct approach would be to convert the iterator to an array first, check if the array is empty, and handle that case explicitly.

Suggested change
const backtickMatch = content.matchAll(/`+/g);
if (!backtickMatch) {
return '```';
}
const maxBackticks = Math.max(...Array.from(backtickMatch, s => s[0].length));
const backtickMatches = Array.from(content.matchAll(/`+/g));
if (backtickMatches.length === 0) {
return '```';
}
const maxBackticks = Math.max(...backtickMatches.map(s => s[0].length));

Copilot uses AI. Check for mistakes.
Comment on lines +205 to +206
if (typeof parsed === 'object' && typeof parsed.source === 'string') {
return { title: parsed.title, source: parsed.source };
Copy link

Copilot AI Jan 29, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The type validation for the title field is incomplete. While the code checks that parsed.source is a string (line 205), it doesn't validate that parsed.title is either undefined or a string. If the parsed JSON contains a title field with an invalid type (e.g., number, object, array), it will be assigned to the title field without validation, potentially causing type safety issues downstream.

Add a check to ensure that if title exists, it must be a string: (parsed.title === undefined || typeof parsed.title === 'string')

Suggested change
if (typeof parsed === 'object' && typeof parsed.source === 'string') {
return { title: parsed.title, source: parsed.source };
if (typeof parsed === 'object'
&& parsed !== null
&& typeof (parsed as { source?: unknown }).source === 'string'
&& ((parsed as { title?: unknown }).title === undefined || typeof (parsed as { title?: unknown }).title === 'string')) {
return { title: (parsed as { title?: string }).title, source: (parsed as { source: string }).source };

Copilot uses AI. Check for mistakes.
@mjbvz mjbvz enabled auto-merge January 29, 2026 00:29
@mjbvz mjbvz merged commit a5cfde1 into microsoft:main Jan 30, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants