Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
55 commits
Select commit Hold shift + click to select a range
ef748e3
Add definition support for nls strings in package.json
mjbvz Feb 24, 2026
88f25bc
Add reference support too
mjbvz Feb 24, 2026
13a6803
style(quick-input): replace fixed border-radius with variable for con…
mrleemurray Feb 19, 2026
ef7a51a
style(suggest-widget): replace fixed border-radius with variable for …
mrleemurray Feb 19, 2026
b923a7a
style(quick-input): replace fixed border-radius with variable for con…
mrleemurray Feb 19, 2026
3d0e5d5
feat: add support for Copilot user agents and related functionality (…
DonJayamanne Mar 2, 2026
7b9ab03
Sessions - fix tree rendering in the changes view (#298663)
lszomoru Mar 2, 2026
a176e75
style(chat-input): replace fixed border-radius with variable for cons…
mrleemurray Feb 19, 2026
1dc1271
style(notifications): update border and border-radius for consistency…
mrleemurray Feb 19, 2026
b3bcabf
style(menu): replace fixed border-radius with CSS variable for consis…
mrleemurray Feb 19, 2026
75b588a
style(dialog): replace fixed border-radius with CSS variable for cons…
mrleemurray Feb 23, 2026
37e10e5
style(dialog): remove fixed border-radius for consistency with theme …
mrleemurray Feb 26, 2026
f51a4c9
style(hover): update border-radius to use theme variable for consistency
mrleemurray Feb 26, 2026
1ac1b46
style(keybindings): restore border-radius for defineKeybindingWidget …
mrleemurray Feb 26, 2026
b134226
style(dropdown, debug-toolbar): update border-radius to use theme var…
mrleemurray Feb 26, 2026
d36272a
style(action-widget): remove border-radius for consistency with theme…
mrleemurray Feb 26, 2026
c95a898
style(parameter-hints): update border-radius to use theme variable fo…
mrleemurray Feb 26, 2026
62adc94
style(notebook): update border-radius to use theme variable for consi…
mrleemurray Feb 26, 2026
7a54887
style(notebook): update action-item border-radius for consistency wit…
mrleemurray Feb 26, 2026
695348b
style(notebook): add border-radius to cell title toolbar for consiste…
mrleemurray Feb 26, 2026
af114f4
style(inline-chat): update border-radius to use theme variable for co…
mrleemurray Feb 26, 2026
30c9312
style(titlebar): update border-radius to use theme variable for consi…
mrleemurray Feb 26, 2026
154634f
style(dialog): update border-radius for modal block shadow to use the…
mrleemurray Feb 26, 2026
701d343
style(debug-hover): add border-radius to debug hover widget for consi…
mrleemurray Feb 26, 2026
4a38deb
Fix macOS sidebar traffic light spacer rendering with custom titlebar…
benibenj Mar 2, 2026
9d61d19
Add more logging to sanity test runner (#298664)
dmitrivMS Mar 2, 2026
062b8a4
style(chat): remove unnecessary border-radius from chat editor and no…
mrleemurray Mar 2, 2026
1cdf38f
style(dropdown): remove unnecessary whitespace for cleaner code
mrleemurray Mar 2, 2026
12d5932
style(defineKeybindingWidget): remove border-radius for consistency w…
mrleemurray Mar 2, 2026
0914e0c
style(notifications): update border-radius for last notification item…
mrleemurray Mar 2, 2026
9596633
style(notifications): update box-shadow to use theme variable for con…
mrleemurray Mar 2, 2026
2385bef
fix(terminal): update background color handling in terminal editor
mrleemurray Mar 2, 2026
2160dc5
make sure action are disabled when cloud is picked
benibenj Mar 2, 2026
f94268c
sessions - allow to run sub-app when using cli (#298685)
bpasero Mar 2, 2026
a6ac46b
sessions - resolve items again when trust changes (#298687)
bpasero Mar 2, 2026
9eb1d23
Merge pull request #298688 from microsoft/mrleemurray/experienced-jad…
mrleemurray Mar 2, 2026
df5e653
fix continuous auth dialogs in cloud session (#298689)
sandy081 Mar 2, 2026
03f25ca
Merge pull request #298684 from microsoft/mrleemurray/port-2026-borde…
mrleemurray Mar 2, 2026
a2dfaa0
make it more stable (#298691)
sandy081 Mar 2, 2026
5e4c0d5
Fix typos in user-facing localized strings (#297892)
kbhujbal Mar 2, 2026
543e520
Sessions - resize body when collapse/expand the tree (#298698)
lszomoru Mar 2, 2026
53f6dae
update hover and background colors in quick input for dark and light …
mrleemurray Mar 2, 2026
76944e5
update breadcrumbPicker and notificationCenterHeader background color…
mrleemurray Mar 2, 2026
cfc50ba
update quick input title background color for improved theme aesthetics
mrleemurray Mar 2, 2026
16869c2
remove background color mixing for suggest widget and title bar hover…
mrleemurray Mar 2, 2026
967655a
:lipstick:
benibenj Mar 2, 2026
f80e83b
Merge pull request #298702 from microsoft/mrleemurray/2026-themes-rem…
mrleemurray Mar 2, 2026
cb9e116
chat - confirm from toast should not force reveal session (#298693)
bpasero Mar 2, 2026
610ebdc
sessions - when applying changes, offer action to open (#298718)
bpasero Mar 2, 2026
61e42ed
remove test
benibenj Mar 2, 2026
41d6266
Enhance sync functionality with loading state and improved UI feedbac…
benibenj Mar 2, 2026
b9b33d2
include debug extension host env in shell env (#241078) (#298276)
eliericha Mar 2, 2026
318314b
Merge pull request #298692 from microsoft/benibenj/rival-snake
benibenj Mar 2, 2026
952b809
Add chat tip for /fork conversation feature (#298084)
Copilot Mar 2, 2026
68f4b3a
Merge pull request #297500 from microsoft/dev/mjbvz/youthful-whale
mjbvz Mar 2, 2026
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@

import * as vscode from 'vscode';
import { PackageDocument } from './packageDocumentHelper';
import { PackageDocumentL10nSupport } from './packageDocumentL10nSupport';

export function activate(context: vscode.ExtensionContext) {
//package.json suggestions
context.subscriptions.push(registerPackageDocumentCompletions());

//package.json go to definition for NLS strings
context.subscriptions.push(new PackageDocumentL10nSupport());
}

function registerPackageDocumentCompletions(): vscode.Disposable {
Expand All @@ -18,5 +21,4 @@ function registerPackageDocumentCompletions(): vscode.Disposable {
return new PackageDocument(document).provideCompletionItems(position, token);
}
});

}
4 changes: 4 additions & 0 deletions extensions/extension-editing/src/extensionEditingMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import * as vscode from 'vscode';
import { PackageDocument } from './packageDocumentHelper';
import { PackageDocumentL10nSupport } from './packageDocumentL10nSupport';
import { ExtensionLinter } from './extensionLinter';

export function activate(context: vscode.ExtensionContext) {
Expand All @@ -15,6 +16,9 @@ export function activate(context: vscode.ExtensionContext) {
//package.json code actions for lint warnings
context.subscriptions.push(registerCodeActionsProvider());

// package.json l10n support
context.subscriptions.push(new PackageDocumentL10nSupport());

context.subscriptions.push(new ExtensionLinter());
}

Expand Down
204 changes: 204 additions & 0 deletions extensions/extension-editing/src/packageDocumentL10nSupport.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as vscode from 'vscode';
import { getLocation, getNodeValue, parseTree, findNodeAtLocation, visit } from 'jsonc-parser';


const packageJsonSelector: vscode.DocumentSelector = { language: 'json', pattern: '**/package.json' };
const packageNlsJsonSelector: vscode.DocumentSelector = { language: 'json', pattern: '**/package.nls.json' };

export class PackageDocumentL10nSupport implements vscode.DefinitionProvider, vscode.ReferenceProvider, vscode.Disposable {

private readonly _disposables: vscode.Disposable[] = [];

constructor() {
this._disposables.push(vscode.languages.registerDefinitionProvider(packageJsonSelector, this));
this._disposables.push(vscode.languages.registerDefinitionProvider(packageNlsJsonSelector, this));

this._disposables.push(vscode.languages.registerReferenceProvider(packageNlsJsonSelector, this));
this._disposables.push(vscode.languages.registerReferenceProvider(packageJsonSelector, this));
}

dispose(): void {
for (const d of this._disposables) {
d.dispose();
}
}

public async provideDefinition(document: vscode.TextDocument, position: vscode.Position, _token: vscode.CancellationToken): Promise<vscode.DefinitionLink[] | undefined> {
const basename = document.uri.path.split('/').pop()?.toLowerCase();
if (basename === 'package.json') {
return this.provideNlsValueDefinition(document, position);
}

if (basename === 'package.nls.json') {
return this.provideNlsKeyDefinition(document, position);
}

return undefined;
}

private async provideNlsValueDefinition(packageJsonDoc: vscode.TextDocument, position: vscode.Position): Promise<vscode.DefinitionLink[] | undefined> {
const nlsRef = this.getNlsReferenceAtPosition(packageJsonDoc, position);
if (!nlsRef) {
return undefined;
}

const nlsUri = vscode.Uri.joinPath(packageJsonDoc.uri, '..', 'package.nls.json');
return this.resolveNlsDefinition(nlsRef, nlsUri);
}

private async provideNlsKeyDefinition(nlsDoc: vscode.TextDocument, position: vscode.Position): Promise<vscode.DefinitionLink[] | undefined> {
const nlsKey = this.getNlsKeyDefinitionAtPosition(nlsDoc, position);
if (!nlsKey) {
return undefined;
}
return this.resolveNlsDefinition(nlsKey, nlsDoc.uri);
}

private async resolveNlsDefinition(origin: { key: string; range: vscode.Range }, nlsUri: vscode.Uri): Promise<vscode.DefinitionLink[] | undefined> {
const target = await this.findNlsKeyDeclaration(origin.key, nlsUri);
if (!target) {
return undefined;
}

return [{
originSelectionRange: origin.range,
targetUri: target.uri,
targetRange: target.range,
}];
}

private getNlsReferenceAtPosition(packageJsonDoc: vscode.TextDocument, position: vscode.Position): { key: string; range: vscode.Range } | undefined {
const location = getLocation(packageJsonDoc.getText(), packageJsonDoc.offsetAt(position));
if (!location.previousNode || location.previousNode.type !== 'string') {
return undefined;
}

const value = getNodeValue(location.previousNode);
if (typeof value !== 'string') {
return undefined;
}

const match = value.match(/^%(.+)%$/);
if (!match) {
return undefined;
}

const nodeStart = packageJsonDoc.positionAt(location.previousNode.offset);
const nodeEnd = packageJsonDoc.positionAt(location.previousNode.offset + location.previousNode.length);
return { key: match[1], range: new vscode.Range(nodeStart, nodeEnd) };
}

public async provideReferences(document: vscode.TextDocument, position: vscode.Position, context: vscode.ReferenceContext, _token: vscode.CancellationToken): Promise<vscode.Location[] | undefined> {
const basename = document.uri.path.split('/').pop()?.toLowerCase();
if (basename === 'package.nls.json') {
return this.provideNlsKeyReferences(document, position, context);
}
if (basename === 'package.json') {
return this.provideNlsValueReferences(document, position, context);
}
return undefined;
}

private async provideNlsKeyReferences(nlsDoc: vscode.TextDocument, position: vscode.Position, context: vscode.ReferenceContext): Promise<vscode.Location[] | undefined> {
const nlsKey = this.getNlsKeyDefinitionAtPosition(nlsDoc, position);
if (!nlsKey) {
return undefined;
}

const packageJsonUri = vscode.Uri.joinPath(nlsDoc.uri, '..', 'package.json');
return this.findAllNlsReferences(nlsKey.key, packageJsonUri, nlsDoc.uri, context);
}

private async provideNlsValueReferences(packageJsonDoc: vscode.TextDocument, position: vscode.Position, context: vscode.ReferenceContext): Promise<vscode.Location[] | undefined> {
const nlsRef = this.getNlsReferenceAtPosition(packageJsonDoc, position);
if (!nlsRef) {
return undefined;
}

const nlsUri = vscode.Uri.joinPath(packageJsonDoc.uri, '..', 'package.nls.json');
return this.findAllNlsReferences(nlsRef.key, packageJsonDoc.uri, nlsUri, context);
}

private async findAllNlsReferences(nlsKey: string, packageJsonUri: vscode.Uri, nlsUri: vscode.Uri, context: vscode.ReferenceContext): Promise<vscode.Location[]> {
const locations = await this.findNlsReferencesInPackageJson(nlsKey, packageJsonUri);

if (context.includeDeclaration) {
const decl = await this.findNlsKeyDeclaration(nlsKey, nlsUri);
if (decl) {
locations.push(decl);
}
}

return locations;
}

private async findNlsKeyDeclaration(nlsKey: string, nlsUri: vscode.Uri): Promise<vscode.Location | undefined> {
try {
const nlsDoc = await vscode.workspace.openTextDocument(nlsUri);
const nlsTree = parseTree(nlsDoc.getText());
if (!nlsTree) {
return undefined;
}

const node = findNodeAtLocation(nlsTree, [nlsKey]);
if (!node?.parent) {
return undefined;
}

const keyNode = node.parent.children?.[0];
if (!keyNode) {
return undefined;
}

const start = nlsDoc.positionAt(keyNode.offset);
const end = nlsDoc.positionAt(keyNode.offset + keyNode.length);
return new vscode.Location(nlsUri, new vscode.Range(start, end));
} catch {
return undefined;
}
}

private async findNlsReferencesInPackageJson(nlsKey: string, packageJsonUri: vscode.Uri): Promise<vscode.Location[]> {
let packageJsonDoc: vscode.TextDocument;
try {
packageJsonDoc = await vscode.workspace.openTextDocument(packageJsonUri);
} catch {
return [];
}

const text = packageJsonDoc.getText();
const needle = `%${nlsKey}%`;
const locations: vscode.Location[] = [];

visit(text, {
onLiteralValue(value, offset, length) {
if (value === needle) {
const start = packageJsonDoc.positionAt(offset);
const end = packageJsonDoc.positionAt(offset + length);
locations.push(new vscode.Location(packageJsonUri, new vscode.Range(start, end)));
}
}
});

return locations;
}

private getNlsKeyDefinitionAtPosition(nlsDoc: vscode.TextDocument, position: vscode.Position): { key: string; range: vscode.Range } | undefined {
const location = getLocation(nlsDoc.getText(), nlsDoc.offsetAt(position));

// Must be on a top-level property key
if (location.path.length !== 1 || !location.isAtPropertyKey || !location.previousNode) {
return undefined;
}

const key = location.path[0] as string;
const start = nlsDoc.positionAt(location.previousNode.offset);
const end = nlsDoc.positionAt(location.previousNode.offset + location.previousNode.length);
return { key, range: new vscode.Range(start, end) };
}
}
2 changes: 1 addition & 1 deletion extensions/theme-2026/themes/2026-dark.json
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@
"quickInputList.focusBackground": "#3994BC26",
"quickInputList.focusForeground": "#bfbfbf",
"quickInputList.focusIconForeground": "#bfbfbf",
"quickInputList.hoverBackground": "#515253",
"quickInputList.hoverBackground": "#262728",
"terminal.selectionBackground": "#3994BC33",
"terminal.background": "#191A1B",
"terminal.border": "#2A2B2CFF",
Expand Down
6 changes: 3 additions & 3 deletions extensions/theme-2026/themes/2026-light.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@
"breadcrumb.background": "#FFFFFF",
"breadcrumb.focusForeground": "#202020",
"breadcrumb.activeSelectionForeground": "#202020",
"breadcrumbPicker.background": "#F0F0F3",
"breadcrumbPicker.background": "#FAFAFD",
"notificationCenter.border": "#F0F1F2FF",
"notificationCenterHeader.foreground": "#202020",
"notificationCenterHeader.background": "#FAFAFD",
Expand All @@ -229,7 +229,7 @@
"extensionButton.prominentHoverBackground": "#0064CC",
"pickerGroup.border": "#EEEEF1",
"pickerGroup.foreground": "#202020",
"quickInput.background": "#F0F0F3",
"quickInput.background": "#FAFAFD",
"quickInput.foreground": "#202020",
"quickInputList.focusBackground": "#0069CC1A",
"quickInputList.focusForeground": "#202020",
Expand All @@ -256,7 +256,7 @@
"gauge.errorForeground": "#ad0707",
"gauge.errorBackground": "#ad070740",
"statusBarItem.prominentHoverForeground": "#FFFFFF",
"quickInputTitle.background": "#F0F0F3",
"quickInputTitle.background": "#FAFAFD",
"chat.requestBubbleBackground": "#EEF4FB",
"chat.requestBubbleHoverBackground": "#E6EDFA",
"chat.thinkingShimmer": "#999999",
Expand Down
Loading
Loading