Skip to content
Open
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
21 changes: 21 additions & 0 deletions src/common/uri.ts
Original file line number Diff line number Diff line change
Expand Up @@ -701,6 +701,27 @@ export function fromOpenIssueWebviewUri(uri: vscode.Uri): OpenIssueWebviewUriPar
return;
}
try {
// Check if the query uses the simplified format: uri=https://github.com/owner/repo/issues/number
const queryParams = new URLSearchParams(uri.query);
const uriParam = queryParams.get('uri');
if (uriParam) {
const issueUrlRegex = /^https?:\/\/github\.com\/(?<owner>[^\/]+)\/(?<repo>[^\/]+)\/issues\/(?<issueNumber>\d+)$/;
const match = issueUrlRegex.exec(uriParam);
if (match && match.groups) {
const { owner, repo, issueNumber } = match.groups;
const params = {
owner,
repo,
issueNumber: parseInt(issueNumber, 10)
};
if (!validateOpenWebviewParams(params.owner, params.repo, params.issueNumber.toString())) {
return;
}
return params;
}
}

// Fall back to the old JSON format for backward compatibility
const query = JSON.parse(uri.query.split('&')[0]);
if (!validateOpenWebviewParams(query.owner, query.repo, query.issueNumber)) {
return;
Expand Down
66 changes: 65 additions & 1 deletion src/test/common/uri.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import { default as assert } from 'assert';
import * as vscode from 'vscode';
import { fromOpenOrCheckoutPullRequestWebviewUri } from '../../common/uri';
import { fromOpenIssueWebviewUri, fromOpenOrCheckoutPullRequestWebviewUri } from '../../common/uri';

describe('uri', () => {
describe('fromOpenOrCheckoutPullRequestWebviewUri', () => {
Expand Down Expand Up @@ -128,4 +128,68 @@ describe('uri', () => {
assert.strictEqual(result?.pullRequestNumber, 123);
});
});

describe('fromOpenIssueWebviewUri', () => {
it('should parse the new simplified format with uri parameter', () => {
const uri = vscode.Uri.parse('vscode://github.vscode-pull-request-github/open-issue-webview?uri=https://github.com/microsoft/vscode-tools/issues/964');
const result = fromOpenIssueWebviewUri(uri);

assert.strictEqual(result?.owner, 'microsoft');
assert.strictEqual(result?.repo, 'vscode-tools');
assert.strictEqual(result?.issueNumber, 964);
});

it('should parse the new simplified format with http (not https)', () => {
const uri = vscode.Uri.parse('vscode://github.vscode-pull-request-github/open-issue-webview?uri=http://github.com/owner/repo/issues/123');
const result = fromOpenIssueWebviewUri(uri);

assert.strictEqual(result?.owner, 'owner');
assert.strictEqual(result?.repo, 'repo');
assert.strictEqual(result?.issueNumber, 123);
});

it('should parse the old JSON format for backward compatibility', () => {
const uri = vscode.Uri.parse('vscode://github.vscode-pull-request-github/open-issue-webview?%7B%22owner%22%3A%22microsoft%22%2C%22repo%22%3A%22vscode-tools%22%2C%22issueNumber%22%3A964%7D');
const result = fromOpenIssueWebviewUri(uri);

assert.strictEqual(result?.owner, 'microsoft');
assert.strictEqual(result?.repo, 'vscode-tools');
assert.strictEqual(result?.issueNumber, 964);
});

it('should return undefined for invalid authority', () => {
const uri = vscode.Uri.parse('vscode://invalid-authority/open-issue-webview?uri=https://github.com/owner/repo/issues/1');
const result = fromOpenIssueWebviewUri(uri);

assert.strictEqual(result, undefined);
});

it('should return undefined for invalid path', () => {
const uri = vscode.Uri.parse('vscode://github.vscode-pull-request-github/invalid-path?uri=https://github.com/owner/repo/issues/1');
const result = fromOpenIssueWebviewUri(uri);

assert.strictEqual(result, undefined);
});

it('should return undefined for non-github host', () => {
const uri = vscode.Uri.parse('vscode://github.vscode-pull-request-github/open-issue-webview?uri=https://example.com/owner/repo/issues/1');
const result = fromOpenIssueWebviewUri(uri);

assert.strictEqual(result, undefined);
});

it('should return undefined for non-numeric issue number', () => {
const uri = vscode.Uri.parse('vscode://github.vscode-pull-request-github/open-issue-webview?uri=https://github.com/owner/repo/issues/abc');
const result = fromOpenIssueWebviewUri(uri);

assert.strictEqual(result, undefined);
});

it('should reject URLs with extra path segments after issue number', () => {
const uri = vscode.Uri.parse('vscode://github.vscode-pull-request-github/open-issue-webview?uri=https://github.com/owner/repo/issues/123/something');
const result = fromOpenIssueWebviewUri(uri);

assert.strictEqual(result, undefined);
});
});
});