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
55 changes: 50 additions & 5 deletions src/@types/vscode.proposed.shareProvider.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,72 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

// https://github.com/microsoft/vscode/issues/176316
// https://github.com/microsoft/vscode/issues/176316 @joyceerhl

declare module 'vscode' {
export interface TreeItem {
shareableItem?: ShareableItem;
}

/**
* Data about an item which can be shared.
*/
export interface ShareableItem {
/**
* A resource in the workspace that can be shared.
*/
resourceUri: Uri;

/**
* If present, a selection within the `resourceUri`.
*/
selection?: Range;
}

/**
* A provider which generates share links for resources in the editor.
*/
export interface ShareProvider {

/**
* A unique ID for the provider.
* This will be used to activate specific extensions contributing share providers if necessary.
*/
readonly id: string;

/**
* A label which will be used to present this provider's options in the UI.
*/
readonly label: string;

/**
* The order in which the provider should be listed in the UI when there are multiple providers.
*/
readonly priority: number;

provideShare(item: ShareableItem, token: CancellationToken): ProviderResult<Uri>;
/**
*
* @param item Data about an item which can be shared.
* @param token A cancellation token.
* @returns A {@link Uri} representing an external link or sharing text. The provider result
* will be copied to the user's clipboard and presented in a confirmation dialog.
*/
provideShare(item: ShareableItem, token: CancellationToken): ProviderResult<Uri | string>;
}

export namespace window {

/**
* Register a share provider. An extension may register multiple share providers.
* There may be multiple share providers for the same {@link ShareableItem}.
* @param selector A document selector to filter whether the provider should be shown for a {@link ShareableItem}.
* @param provider A share provider.
*/
export function registerShareProvider(selector: DocumentSelector, provider: ShareProvider): Disposable;
}

export interface TreeItem {

/**
* An optional property which, when set, inlines a `Share` option in the context menu for this tree item.
*/
shareableItem?: ShareableItem;
}
}
56 changes: 52 additions & 4 deletions src/issues/shareProviders.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import * as pathLib from 'path';
import * as vscode from 'vscode';
import { Commit, Remote, Repository } from '../api/api';
import { GitApiImpl } from '../api/api1';
Expand All @@ -22,6 +23,7 @@ export class ShareProviderManager implements vscode.Disposable {
this.disposables.push(
new GitHubDevShareProvider(repositoryManager, gitAPI),
new GitHubPermalinkShareProvider(repositoryManager, gitAPI),
new GitHubPermalinkAsMarkdownShareProvider(repositoryManager, gitAPI),
new GitHubHeadLinkShareProvider(repositoryManager, gitAPI)
);
}
Expand Down Expand Up @@ -97,7 +99,7 @@ abstract class AbstractShareProvider implements vscode.Disposable, vscode.ShareP
protected abstract getBlob(folderManager: FolderRepositoryManager, uri: vscode.Uri): Promise<string>;
protected abstract getUpstream(repository: Repository, commit: string): Promise<Remote | undefined>;

public async provideShare(item: vscode.ShareableItem): Promise<vscode.Uri | undefined> {
public async provideShare(item: vscode.ShareableItem): Promise<vscode.Uri | string | undefined> {
// Get the blob
const folderManager = this.repositoryManager.getManagerForFile(item.resourceUri);
if (!folderManager) {
Expand Down Expand Up @@ -147,8 +149,14 @@ export class GitHubDevShareProvider extends AbstractShareProvider implements vsc
}

export class GitHubPermalinkShareProvider extends AbstractShareProvider implements vscode.ShareProvider {
constructor(repositoryManager: RepositoriesManager, gitApi: GitApiImpl) {
super(repositoryManager, gitApi, 'githubComPermalink', vscode.l10n.t('Copy GitHub Permalink'), 11);
constructor(
repositoryManager: RepositoriesManager,
gitApi: GitApiImpl,
id: string = 'githubComPermalink',
label: string = vscode.l10n.t('Copy GitHub Permalink'),
priority: number = 11
) {
super(repositoryManager, gitApi, id, label, priority);
}

protected shouldRegister() {
Expand Down Expand Up @@ -194,9 +202,49 @@ export class GitHubPermalinkShareProvider extends AbstractShareProvider implemen
}
}

export class GitHubPermalinkAsMarkdownShareProvider extends GitHubPermalinkShareProvider {

constructor(repositoryManager: RepositoriesManager, gitApi: GitApiImpl) {
super(repositoryManager, gitApi, 'githubComPermalinkAsMarkdown', vscode.l10n.t('Copy GitHub Permalink as Markdown'), 12);
}

async provideShare(item: vscode.ShareableItem): Promise<vscode.Uri | string | undefined> {
const link = await super.provideShare(item);

const text = await this.getMarkdownLinkText(item);
if (link) {
return `[${text?.trim() ?? ''}](${link.toString()})`;
}
}

private async getMarkdownLinkText(item: vscode.ShareableItem): Promise<string | undefined> {
const fileName = pathLib.basename(item.resourceUri.path);

if (item.selection) {
const document = await vscode.workspace.openTextDocument(item.resourceUri);

const editorSelection = item.selection.start === item.selection.end
? item.selection
: new vscode.Range(item.selection.start, new vscode.Position(item.selection.start.line + 1, 0));

const selectedText = document.getText(editorSelection);
if (selectedText) {
return selectedText;
}

const wordRange = document.getWordRangeAtPosition(item.selection.start);
if (wordRange) {
return document.getText(wordRange);
}
}

return fileName;
Comment thread
joyceerhl marked this conversation as resolved.
}
}

export class GitHubHeadLinkShareProvider extends AbstractShareProvider implements vscode.ShareProvider {
constructor(repositoryManager: RepositoriesManager, gitApi: GitApiImpl) {
super(repositoryManager, gitApi, 'githubComHeadLink', vscode.l10n.t('Copy GitHub HEAD Link'), 12);
super(repositoryManager, gitApi, 'githubComHeadLink', vscode.l10n.t('Copy GitHub HEAD Link'), 13);
}

protected shouldRegister() {
Expand Down