diff --git a/src/sql/workbench/contrib/notebook/browser/calloutDialog/common/utils.ts b/src/sql/workbench/contrib/notebook/browser/calloutDialog/common/utils.ts index b602365945..6917ad449e 100644 --- a/src/sql/workbench/contrib/notebook/browser/calloutDialog/common/utils.ts +++ b/src/sql/workbench/contrib/notebook/browser/calloutDialog/common/utils.ts @@ -34,3 +34,16 @@ export function escapeUrl(unescapedUrl: string): string { } }); } + +/** + * Removes single or double quotes that enclose another string. + * @param quotedText The text to unquote + */ +export function unquoteText(quotedText: string): string { + let doubleQuotesRegex = /^[\"\'](.*)[\"\']$/; + let matches = doubleQuotesRegex.exec(quotedText); + if (matches && matches[1]) { + quotedText = matches[1]; + } + return quotedText; +} diff --git a/src/sql/workbench/contrib/notebook/browser/calloutDialog/imageCalloutDialog.ts b/src/sql/workbench/contrib/notebook/browser/calloutDialog/imageCalloutDialog.ts index 235a977082..f2bc34ad66 100644 --- a/src/sql/workbench/contrib/notebook/browser/calloutDialog/imageCalloutDialog.ts +++ b/src/sql/workbench/contrib/notebook/browser/calloutDialog/imageCalloutDialog.ts @@ -26,6 +26,7 @@ import { Checkbox } from 'sql/base/browser/ui/checkbox/checkbox'; import { RadioButton } from 'sql/base/browser/ui/radioButton/radioButton'; import { attachCalloutDialogStyler } from 'sql/workbench/common/styler'; import * as path from 'vs/base/common/path'; +import { unquoteText } from 'sql/workbench/contrib/notebook/browser/calloutDialog/common/utils'; export interface IImageCalloutDialogOptions { insertTitle?: string, @@ -199,7 +200,7 @@ export class ImageCalloutDialog extends Modal { public insert(): void { this.hide('ok'); - let imgPath = this._imageUrlInputBox.value; + let imgPath = unquoteText(this._imageUrlInputBox.value); let imageName = path.basename(imgPath); this._selectionComplete.resolve({ embedImage: this._imageEmbedCheckbox.checked, diff --git a/src/sql/workbench/contrib/notebook/browser/calloutDialog/linkCalloutDialog.ts b/src/sql/workbench/contrib/notebook/browser/calloutDialog/linkCalloutDialog.ts index 2ee080cc3f..f5b7e2bdb3 100644 --- a/src/sql/workbench/contrib/notebook/browser/calloutDialog/linkCalloutDialog.ts +++ b/src/sql/workbench/contrib/notebook/browser/calloutDialog/linkCalloutDialog.ts @@ -21,7 +21,7 @@ import { Deferred } from 'sql/base/common/promise'; import { InputBox } from 'sql/base/browser/ui/inputBox/inputBox'; import { attachCalloutDialogStyler } from 'sql/workbench/common/styler'; import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent'; -import { escapeLabel, escapeUrl } from 'sql/workbench/contrib/notebook/browser/calloutDialog/common/utils'; +import { escapeLabel, escapeUrl, unquoteText } from 'sql/workbench/contrib/notebook/browser/calloutDialog/common/utils'; export interface ILinkCalloutDialogOptions { insertTitle?: string, @@ -158,7 +158,7 @@ export class LinkCalloutDialog extends Modal { public insert(): void { this.hide('ok'); let escapedLabel = escapeLabel(this._linkTextInputBox.value); - let escapedUrl = escapeUrl(this._linkUrlInputBox.value); + let escapedUrl = escapeUrl(unquoteText(this._linkUrlInputBox.value)); if (this._previouslySelectedRange) { // Reset selection to previous state before callout was open diff --git a/src/sql/workbench/contrib/notebook/test/calloutDialog/linkCalloutDialog.test.ts b/src/sql/workbench/contrib/notebook/test/calloutDialog/linkCalloutDialog.test.ts index c26b5ee5dc..2e46f0856e 100644 --- a/src/sql/workbench/contrib/notebook/test/calloutDialog/linkCalloutDialog.test.ts +++ b/src/sql/workbench/contrib/notebook/test/calloutDialog/linkCalloutDialog.test.ts @@ -10,7 +10,7 @@ import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry'; import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService'; import { Deferred } from 'sql/base/common/promise'; -import { escapeLabel, escapeUrl } from 'sql/workbench/contrib/notebook/browser/calloutDialog/common/utils'; +import { escapeLabel, escapeUrl, unquoteText } from 'sql/workbench/contrib/notebook/browser/calloutDialog/common/utils'; import { IDialogProperties } from 'sql/workbench/browser/modal/modal'; suite('Link Callout Dialog', function (): void { @@ -42,9 +42,9 @@ suite('Link Callout Dialog', function (): void { linkCalloutDialog.cancel(); let result = await deferred.promise; - assert.equal(result.insertUnescapedLinkLabel, 'defaultLabel', 'Label not returned correctly'); - assert.equal(result.insertUnescapedLinkUrl, undefined, 'URL not returned correctly'); - assert.equal(result.insertEscapedMarkdown, '', 'Markdown not returned correctly'); + assert.strictEqual(result.insertUnescapedLinkLabel, 'defaultLabel', 'Label not returned correctly'); + assert.strictEqual(result.insertUnescapedLinkUrl, undefined, 'URL not returned correctly'); + assert.strictEqual(result.insertEscapedMarkdown, '', 'Markdown not returned correctly'); }); test('Should return expected values on insert', async function (): Promise { @@ -65,9 +65,9 @@ suite('Link Callout Dialog', function (): void { // And insert the dialog linkCalloutDialog.insert(); let result = await deferred.promise; - assert.equal(result.insertUnescapedLinkLabel, defaultLabel, 'Label not returned correctly'); - assert.equal(result.insertUnescapedLinkUrl, sampleUrl, 'URL not returned correctly'); - assert.equal(result.insertEscapedMarkdown, `[${defaultLabel}](${sampleUrl})`, 'Markdown not returned correctly'); + assert.strictEqual(result.insertUnescapedLinkLabel, defaultLabel, 'Label not returned correctly'); + assert.strictEqual(result.insertUnescapedLinkUrl, sampleUrl, 'URL not returned correctly'); + assert.strictEqual(result.insertEscapedMarkdown, `[${defaultLabel}](${sampleUrl})`, 'Markdown not returned correctly'); }); test('Should return expected values on insert when escape necessary', async function (): Promise { @@ -88,23 +88,37 @@ suite('Link Callout Dialog', function (): void { // And insert the dialog linkCalloutDialog.insert(); let result = await deferred.promise; - assert.equal(result.insertUnescapedLinkLabel, defaultLabel, 'Label not returned correctly'); - assert.equal(result.insertUnescapedLinkUrl, sampleUrl, 'URL not returned correctly'); - assert.equal(result.insertEscapedMarkdown, '[default\[\]Label](https://www.aka.ms/azuredatastudio%28%29)', 'Markdown not returned correctly'); + assert.strictEqual(result.insertUnescapedLinkLabel, defaultLabel, 'Label not returned correctly'); + assert.strictEqual(result.insertUnescapedLinkUrl, sampleUrl, 'URL not returned correctly'); + assert.strictEqual(result.insertEscapedMarkdown, '[default\[\]Label](https://www.aka.ms/azuredatastudio%28%29)', 'Markdown not returned correctly'); }); test('Label escape', function (): void { - assert.equal(escapeLabel('TestLabel'), 'TestLabel', 'Basic escape label test failed'); - assert.equal(escapeLabel('Test[]Label'), 'Test\[\]Label', 'Label test square brackets failed'); - assert.equal(escapeLabel('<>&[]'), '<>&\[\]', 'Label test known escaped characters failed'); - assert.equal(escapeLabel('<>&[]()'), '<>&\[\]()', 'Label test all escaped characters failed'); + assert.strictEqual(escapeLabel('TestLabel'), 'TestLabel', 'Basic escape label test failed'); + assert.strictEqual(escapeLabel('Test[]Label'), 'Test\[\]Label', 'Label test square brackets failed'); + assert.strictEqual(escapeLabel('<>&[]'), '<>&\[\]', 'Label test known escaped characters failed'); + assert.strictEqual(escapeLabel('<>&[]()'), '<>&\[\]()', 'Label test all escaped characters failed'); }); test('URL escape', function (): void { - assert.equal(escapeUrl('TestURL'), 'TestURL', 'Basic escape URL test failed'); - assert.equal(escapeUrl('Test()URL'), 'Test%28%29URL', 'URL test square brackets failed'); - assert.equal(escapeUrl('<>&()'), '<>&%28%29', 'URL test known escaped characters failed'); - assert.equal(escapeUrl('<>&()[]'), '<>&%28%29[]', 'URL test all escaped characters failed'); + assert.strictEqual(escapeUrl('TestURL'), 'TestURL', 'Basic escape URL test failed'); + assert.strictEqual(escapeUrl('Test()URL'), 'Test%28%29URL', 'URL test square brackets failed'); + assert.strictEqual(escapeUrl('<>&()'), '<>&%28%29', 'URL test known escaped characters failed'); + assert.strictEqual(escapeUrl('<>&()[]'), '<>&%28%29[]', 'URL test all escaped characters failed'); + }); + + test('Unquote text', function (): void { + assert.strictEqual(unquoteText('TestPath'), 'TestPath'); + assert.strictEqual(unquoteText('\"TestPath\"'), 'TestPath'); + assert.strictEqual(unquoteText('\'TestPath\''), 'TestPath'); + assert.strictEqual(unquoteText('\'TestPath\"'), 'TestPath'); + assert.strictEqual(unquoteText('\"TestPath\''), 'TestPath'); + assert.strictEqual(unquoteText('\"Tes"tPa"th\"'), 'Tes"tPa"th'); + assert.strictEqual(unquoteText('\"TestPath'), '\"TestPath'); + assert.strictEqual(unquoteText('\'TestPath'), '\'TestPath'); + assert.strictEqual(unquoteText('TestPath\"'), 'TestPath\"'); + assert.strictEqual(unquoteText('TestPath\''), 'TestPath\''); + assert.strictEqual(unquoteText(undefined), undefined); }); test('Should return file link properly', async function (): Promise { @@ -124,9 +138,9 @@ suite('Link Callout Dialog', function (): void { // And insert the dialog linkCalloutDialog.insert(); let result = await deferred.promise; - assert.equal(result.insertUnescapedLinkLabel, defaultLabel, 'Label not returned correctly'); - assert.equal(result.insertUnescapedLinkUrl, sampleUrl, 'URL not returned correctly'); - assert.equal(result.insertEscapedMarkdown, `[${defaultLabel}](${sampleUrl})`, 'Markdown not returned correctly'); + assert.strictEqual(result.insertUnescapedLinkLabel, defaultLabel, 'Label not returned correctly'); + assert.strictEqual(result.insertUnescapedLinkUrl, sampleUrl, 'URL not returned correctly'); + assert.strictEqual(result.insertEscapedMarkdown, `[${defaultLabel}](${sampleUrl})`, 'Markdown not returned correctly'); }); });