Links handling in commands (#15118)

* format

* update external options type

* add command flag for command

* Allow commands in Notebooks

Co-authored-by: chgagnon <chgagnon@microsoft.com>
This commit is contained in:
Aditya Bist
2021-04-14 13:06:45 -07:00
committed by GitHub
parent 842a33e318
commit e151668c81
20 changed files with 69 additions and 35 deletions

View File

@@ -58,7 +58,7 @@ export class MarkdownRenderer {
if (!markdown) {
element = document.createElement('span');
} else {
element = renderMarkdown(markdown, { ...this._getRenderOptions(disposeables), ...options }, markedOptions);
element = renderMarkdown(markdown, { ...this._getRenderOptions(markdown, disposeables), ...options }, markedOptions);
}
return {
@@ -67,7 +67,7 @@ export class MarkdownRenderer {
};
}
protected _getRenderOptions(disposeables: DisposableStore): MarkdownRenderOptions {
protected _getRenderOptions(markdown: IMarkdownString, disposeables: DisposableStore): MarkdownRenderOptions {
return {
baseUrl: this._options.baseUrl,
codeBlockRenderer: async (languageAlias, value) => {
@@ -105,7 +105,7 @@ export class MarkdownRenderer {
},
asyncRenderCallback: () => this._onDidRenderAsync.fire(),
actionHandler: {
callback: (content) => this._openerService.open(content, { fromUserGesture: true }).catch(onUnexpectedError),
callback: (content) => this._openerService.open(content, { fromUserGesture: true, allowContributedOpeners: true, allowCommands: markdown.isTrusted }).catch(onUnexpectedError),
disposeables
}
};

View File

@@ -21,10 +21,15 @@ class CommandOpener implements IOpener {
constructor(@ICommandService private readonly _commandService: ICommandService) { }
async open(target: URI | string) {
async open(target: URI | string, options?: OpenOptions): Promise<boolean> {
if (!matchesScheme(target, Schemas.command)) {
return false;
}
if (!options?.allowCommands) {
// silently ignore commands when command-links are disabled, also
// surpress other openers by returning TRUE
return true;
}
// run command or bail out if command isn't known
if (typeof target === 'string') {
target = URI.parse(target);

View File

@@ -143,7 +143,7 @@ class MessageWidget {
this._codeLink.setAttribute('href', `${code.target.toString()}`);
this._codeLink.onclick = (e) => {
this._openerService.open(code.target);
this._openerService.open(code.target, { allowCommands: true });
e.preventDefault();
e.stopPropagation();
};

View File

@@ -536,7 +536,7 @@ export class ModesContentHoverWidget extends ContentHoverWidget {
this._codeLink.setAttribute('href', code.target.toString());
this._codeLink.onclick = (e) => {
this._openerService.open(code.target);
this._openerService.open(code.target, { allowCommands: true });
e.preventDefault();
e.stopPropagation();
};

View File

@@ -327,7 +327,7 @@ export class LinkDetector implements IEditorContribution {
}
}
return this.openerService.open(uri, { openToSide, fromUserGesture });
return this.openerService.open(uri, { openToSide, fromUserGesture, allowContributedOpeners: true, allowCommands: true });
}, err => {
const messageOrError =

View File

@@ -81,20 +81,10 @@ suite('OpenerService', function () {
const id = `aCommand${Math.random()}`;
CommandsRegistry.registerCommand(id, function () { });
assert.strictEqual(lastCommand, undefined);
await openerService.open(URI.parse('command:' + id));
assert.equal(lastCommand!.id, id);
assert.equal(lastCommand!.args.length, 0);
await openerService.open(URI.parse('command:' + id).with({ query: '123' }));
assert.equal(lastCommand!.id, id);
assert.equal(lastCommand!.args.length, 1);
assert.equal(lastCommand!.args[0], '123');
await openerService.open(URI.parse('command:' + id).with({ query: JSON.stringify([12, true]) }));
assert.equal(lastCommand!.id, id);
assert.equal(lastCommand!.args.length, 2);
assert.equal(lastCommand!.args[0], 12);
assert.equal(lastCommand!.args[1], true);
assert.strictEqual(lastCommand, undefined);
});
test('links are protected by validators', async function () {
@@ -108,6 +98,33 @@ suite('OpenerService', function () {
assert.equal(httpsResult, false);
});
test('delegate to commandsService, command:someid', async function () {
const openerService = new OpenerService(editorService, commandService);
const id = `aCommand${Math.random()}`;
CommandsRegistry.registerCommand(id, function () { });
await openerService.open(URI.parse('command:' + id).with({ query: '\"123\"' }), { allowCommands: true });
assert.strictEqual(lastCommand!.id, id);
assert.strictEqual(lastCommand!.args.length, 1);
assert.strictEqual(lastCommand!.args[0], '123');
await openerService.open(URI.parse('command:' + id), { allowCommands: true });
assert.strictEqual(lastCommand!.id, id);
assert.strictEqual(lastCommand!.args.length, 0);
await openerService.open(URI.parse('command:' + id).with({ query: '123' }), { allowCommands: true });
assert.strictEqual(lastCommand!.id, id);
assert.strictEqual(lastCommand!.args.length, 1);
assert.strictEqual(lastCommand!.args[0], 123);
await openerService.open(URI.parse('command:' + id).with({ query: JSON.stringify([12, true]) }), { allowCommands: true });
assert.strictEqual(lastCommand!.id, id);
assert.strictEqual(lastCommand!.args.length, 2);
assert.strictEqual(lastCommand!.args[0], 12);
assert.strictEqual(lastCommand!.args[1], true);
});
test('links validated by validators go to openers', async function () {
const openerService = new OpenerService(editorService, commandService);