Skip to content

Commit 46c5512

Browse files
Merge branch 'microsoft:main' into dev/fix-test-exporer-filter-ui-margin
2 parents 51e9002 + 91070de commit 46c5512

File tree

54 files changed

+916
-144
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+916
-144
lines changed

build/lib/i18n.resources.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,10 @@
510510
"name": "vs/workbench/services/localization",
511511
"project": "vscode-workbench"
512512
},
513+
{
514+
"name": "vs/workbench/contrib/share",
515+
"project": "vscode-workbench"
516+
},
513517
{
514518
"name": "vs/workbench/contrib/accessibility",
515519
"project": "vscode-workbench"

build/lib/stylelint/vscode-known-variables.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@
457457
"--vscode-problemsErrorIcon-foreground",
458458
"--vscode-problemsInfoIcon-foreground",
459459
"--vscode-problemsWarningIcon-foreground",
460+
"--vscode-problemsSuccessIcon-foreground",
460461
"--vscode-profileBadge-background",
461462
"--vscode-profileBadge-foreground",
462463
"--vscode-progressBar-background",

extensions/github/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
"enabledApiProposals": [
2929
"contribShareMenu",
3030
"contribEditSessions",
31-
"canonicalUriProvider"
31+
"canonicalUriProvider",
32+
"shareProvider"
3233
],
3334
"contributes": {
3435
"commands": [

extensions/github/src/extension.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { GitBaseExtension } from './typings/git-base';
1414
import { GithubRemoteSourcePublisher } from './remoteSourcePublisher';
1515
import { GithubBranchProtectionProviderManager } from './branchProtection';
1616
import { GitHubCanonicalUriProvider } from './canonicalUriProvider';
17+
import { VscodeDevShareProvider } from './shareProviders';
1718

1819
export function activate(context: ExtensionContext): void {
1920
const disposables: Disposable[] = [];
@@ -95,6 +96,7 @@ function initializeGitExtension(context: ExtensionContext, logger: LogOutputChan
9596
disposables.add(gitAPI.registerPushErrorHandler(new GithubPushErrorHandler()));
9697
disposables.add(gitAPI.registerRemoteSourcePublisher(new GithubRemoteSourcePublisher(gitAPI)));
9798
disposables.add(new GitHubCanonicalUriProvider(gitAPI));
99+
disposables.add(new VscodeDevShareProvider(gitAPI));
98100
setGitHubContext(gitAPI, disposables);
99101

100102
commands.executeCommand('setContext', 'git-base.gitEnabled', true);

extensions/github/src/links.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ function getRangeOrSelection(lineNumber: number | undefined) {
9292
: vscode.window.activeTextEditor?.selection;
9393
}
9494

95-
function rangeString(range: vscode.Range | undefined) {
95+
export function rangeString(range: vscode.Range | undefined) {
9696
if (!range) {
9797
return '';
9898
}
@@ -119,7 +119,7 @@ export function notebookCellRangeString(index: number | undefined, range: vscode
119119
return hash;
120120
}
121121

122-
function encodeURIComponentExceptSlashes(path: string) {
122+
export function encodeURIComponentExceptSlashes(path: string) {
123123
// There may be special characters like # and whitespace in the path.
124124
// These characters are not escaped by encodeURI(), so it is not sufficient to
125125
// feed the full URI to encodeURI().
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
import * as vscode from 'vscode';
7+
import { API } from './typings/git';
8+
import { getRepositoryFromUrl, repositoryHasGitHubRemote } from './util';
9+
import { encodeURIComponentExceptSlashes, getRepositoryForFile, notebookCellRangeString, rangeString } from './links';
10+
11+
export class VscodeDevShareProvider implements vscode.ShareProvider, vscode.Disposable {
12+
readonly id: string = 'copyVscodeDevLink';
13+
readonly label: string = vscode.l10n.t('Copy vscode.dev Link');
14+
readonly priority: number = 10;
15+
16+
17+
private _hasGitHubRepositories: boolean = false;
18+
private set hasGitHubRepositories(value: boolean) {
19+
vscode.commands.executeCommand('setContext', 'github.hasGitHubRepo', value);
20+
this._hasGitHubRepositories = value;
21+
this.ensureShareProviderRegistration();
22+
}
23+
24+
private shareProviderRegistration: vscode.Disposable | undefined;
25+
private disposables: vscode.Disposable[] = [];
26+
27+
constructor(private readonly gitAPI: API) {
28+
this.initializeGitHubRepoContext();
29+
}
30+
31+
dispose() {
32+
this.disposables.forEach(d => d.dispose());
33+
}
34+
35+
private initializeGitHubRepoContext() {
36+
if (this.gitAPI.repositories.find(repo => repositoryHasGitHubRemote(repo))) {
37+
this.hasGitHubRepositories = true;
38+
vscode.commands.executeCommand('setContext', 'github.hasGitHubRepo', true);
39+
} else {
40+
this.disposables.push(this.gitAPI.onDidOpenRepository(async e => {
41+
await e.status();
42+
if (repositoryHasGitHubRemote(e)) {
43+
vscode.commands.executeCommand('setContext', 'github.hasGitHubRepo', true);
44+
this.hasGitHubRepositories = true;
45+
}
46+
}));
47+
}
48+
this.disposables.push(this.gitAPI.onDidCloseRepository(() => {
49+
if (!this.gitAPI.repositories.find(repo => repositoryHasGitHubRemote(repo))) {
50+
this.hasGitHubRepositories = false;
51+
}
52+
}));
53+
}
54+
55+
private ensureShareProviderRegistration() {
56+
if (vscode.env.appHost !== 'codespaces' && !this.shareProviderRegistration && this._hasGitHubRepositories) {
57+
const shareProviderRegistration = vscode.window.registerShareProvider({ scheme: 'file' }, this);
58+
this.shareProviderRegistration = shareProviderRegistration;
59+
this.disposables.push(shareProviderRegistration);
60+
} else if (this.shareProviderRegistration && !this._hasGitHubRepositories) {
61+
this.shareProviderRegistration.dispose();
62+
this.shareProviderRegistration = undefined;
63+
}
64+
}
65+
66+
provideShare(item: vscode.ShareableItem, _token: vscode.CancellationToken): vscode.ProviderResult<vscode.Uri> {
67+
const repository = getRepositoryForFile(this.gitAPI, item.resourceUri);
68+
if (!repository) {
69+
return;
70+
}
71+
72+
let repo: { owner: string; repo: string } | undefined;
73+
repository.state.remotes.find(remote => {
74+
if (remote.fetchUrl) {
75+
const foundRepo = getRepositoryFromUrl(remote.fetchUrl);
76+
if (foundRepo && (remote.name === repository.state.HEAD?.upstream?.remote)) {
77+
repo = foundRepo;
78+
return;
79+
} else if (foundRepo && !repo) {
80+
repo = foundRepo;
81+
}
82+
}
83+
return;
84+
});
85+
86+
if (!repo) {
87+
return;
88+
}
89+
90+
const blobSegment = repository?.state.HEAD?.name ? encodeURIComponentExceptSlashes(repository.state.HEAD?.name) : repository?.state.HEAD?.commit;
91+
const filepathSegment = encodeURIComponentExceptSlashes(item.resourceUri.path.substring(repository?.rootUri.path.length));
92+
const rangeSegment = getRangeSegment(item);
93+
return vscode.Uri.parse(`${this.getVscodeDevHost()}/${repo.owner}/${repo.repo}/blob/${blobSegment}${filepathSegment}${rangeSegment}${rangeSegment}`);
94+
95+
}
96+
97+
private getVscodeDevHost(): string {
98+
return `https://${vscode.env.appName.toLowerCase().includes('insiders') ? 'insiders.' : ''}vscode.dev/github`;
99+
}
100+
}
101+
102+
function getRangeSegment(item: vscode.ShareableItem) {
103+
if (item.resourceUri.scheme === 'vscode-notebook-cell') {
104+
const notebookEditor = vscode.window.visibleNotebookEditors.find(editor => editor.notebook.uri.fsPath === item.resourceUri.fsPath);
105+
const cell = notebookEditor?.notebook.getCells().find(cell => cell.document.uri.fragment === item.resourceUri?.fragment);
106+
const cellIndex = cell?.index ?? notebookEditor?.selection.start;
107+
return notebookCellRangeString(cellIndex, item.selection);
108+
}
109+
110+
return rangeString(item.selection);
111+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*---------------------------------------------------------------------------------------------
2+
* Copyright (c) Microsoft Corporation. All rights reserved.
3+
* Licensed under the MIT License. See License.txt in the project root for license information.
4+
*--------------------------------------------------------------------------------------------*/
5+
6+
// https://github.com/microsoft/vscode/issues/176316
7+
8+
declare module 'vscode' {
9+
export interface TreeItem {
10+
shareableItem?: ShareableItem;
11+
}
12+
13+
export interface ShareableItem {
14+
resourceUri: Uri;
15+
selection?: Range;
16+
}
17+
18+
export interface ShareProvider {
19+
readonly id: string;
20+
readonly label: string;
21+
readonly priority: number;
22+
23+
provideShare(item: ShareableItem, token: CancellationToken): ProviderResult<Uri>;
24+
}
25+
26+
export namespace window {
27+
export function registerShareProvider(selector: DocumentSelector, provider: ShareProvider): Disposable;
28+
}
29+
}

extensions/notebook-renderers/src/index.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ function renderImage(outputInfo: OutputItem, element: HTMLElement): IDisposable
3333

3434
const image = document.createElement('img');
3535
image.src = src;
36+
const alt = getAltText(outputInfo);
37+
if (alt) {
38+
image.alt = alt;
39+
}
3640
const display = document.createElement('div');
3741
display.classList.add('display');
3842
display.appendChild(image);
@@ -64,12 +68,33 @@ const domEval = (container: Element) => {
6468
}
6569
};
6670

71+
function getAltText(outputInfo: OutputItem) {
72+
const metadata = outputInfo.metadata;
73+
if (typeof metadata === 'object' && metadata && 'vscode_altText' in metadata && typeof metadata.vscode_altText === 'string') {
74+
return metadata.vscode_altText;
75+
}
76+
return undefined;
77+
}
78+
79+
function injectTitleForSvg(outputInfo: OutputItem, element: HTMLElement) {
80+
if (outputInfo.mime.indexOf('svg') > -1) {
81+
const svgElement = element.querySelector('svg');
82+
const altText = getAltText(outputInfo);
83+
if (svgElement && altText) {
84+
const title = document.createElement('title');
85+
title.innerText = altText;
86+
svgElement.prepend(title);
87+
}
88+
}
89+
}
90+
6791
async function renderHTML(outputInfo: OutputItem, container: HTMLElement, signal: AbortSignal, hooks: Iterable<HtmlRenderingHook>): Promise<void> {
6892
clearContainer(container);
6993
let element: HTMLElement = document.createElement('div');
7094
const htmlContent = outputInfo.text();
7195
const trustedHtml = ttPolicy?.createHTML(htmlContent) ?? htmlContent;
7296
element.innerHTML = trustedHtml as string;
97+
injectTitleForSvg(outputInfo, element);
7398

7499
for (const hook of hooks) {
75100
element = (await hook.postRender(outputInfo, element, signal)) ?? element;

extensions/theme-defaults/themes/light_modern.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@
137137
"terminal.tab.activeBorder": "#005fb8",
138138
"textBlockQuote.background": "#f8f8f8",
139139
"textBlockQuote.border": "#0000001a",
140-
"textCodeBlock.background": "#6e768166",
140+
"textCodeBlock.background": "#f2f2f2",
141141
"textLink.activeForeground": "#005FB8",
142142
"textLink.foreground": "#005FB8",
143143
"textSeparator.foreground": "#21262d",

extensions/vscode-api-tests/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@
4545
"treeViewReveal",
4646
"workspaceTrust",
4747
"telemetry",
48-
"windowActivity"
48+
"windowActivity",
49+
"interactiveUserActions"
4950
],
5051
"private": true,
5152
"activationEvents": [],

0 commit comments

Comments
 (0)