diff --git a/src/vs/base/browser/htmlContentRenderer.ts b/src/vs/base/browser/htmlContentRenderer.ts index e886bedb960..89780667b4d 100644 --- a/src/vs/base/browser/htmlContentRenderer.ts +++ b/src/vs/base/browser/htmlContentRenderer.ts @@ -6,7 +6,7 @@ import * as DOM from 'vs/base/browser/dom'; import { defaultGenerator } from 'vs/base/common/idGenerator'; import { escape } from 'vs/base/common/strings'; -import { removeMarkdownEscapes, IMarkdownString } from 'vs/base/common/htmlContent'; +import { removeMarkdownEscapes, IMarkdownString, MarkdownString } from 'vs/base/common/htmlContent'; import * as marked from 'vs/base/common/marked/marked'; import { IMouseEvent } from 'vs/base/browser/mouseEvent'; import { IDisposable } from 'vs/base/common/lifecycle'; @@ -182,7 +182,7 @@ export function renderMarkdown(markdown: IMarkdownString, options: RenderOptions } const markedOptions: marked.MarkedOptions = { - sanitize: true, + sanitize: markdown instanceof MarkdownString ? markdown.sanitize : true, renderer }; diff --git a/src/vs/base/common/htmlContent.ts b/src/vs/base/common/htmlContent.ts index 0ec7be4955a..b7e99fbf6c7 100644 --- a/src/vs/base/common/htmlContent.ts +++ b/src/vs/base/common/htmlContent.ts @@ -16,6 +16,7 @@ export class MarkdownString implements IMarkdownString { value: string; isTrusted?: boolean; + sanitize: boolean = true; constructor(value: string = '') { this.value = value; diff --git a/src/vs/editor/common/services/modelServiceImpl.ts b/src/vs/editor/common/services/modelServiceImpl.ts index 29ee9469e84..7a86cd904ec 100644 --- a/src/vs/editor/common/services/modelServiceImpl.ts +++ b/src/vs/editor/common/services/modelServiceImpl.ts @@ -3,10 +3,10 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as nls from 'vs/nls'; import { isNonEmptyArray } from 'vs/base/common/arrays'; import { Emitter, Event } from 'vs/base/common/event'; import { MarkdownString } from 'vs/base/common/htmlContent'; +import { escape } from 'vs/base/common/strings'; import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle'; import * as network from 'vs/base/common/network'; import { basename } from 'vs/base/common/paths'; @@ -192,36 +192,47 @@ class ModelMarkerHandler { let { message, source, relatedInformation, code } = marker; if (typeof message === 'string') { - message = message.trim(); + hoverMessage = new MarkdownString(); + // Disable markdown renderer sanitize to allow html + // Hence, escape all input strings + hoverMessage.sanitize = false; if (source) { - if (/\n/g.test(message)) { - if (code) { - message = nls.localize('diagAndSourceAndCodeMultiline', "[{0}]\n{1} [{2}]", source, message, code); - } else { - message = nls.localize('diagAndSourceMultiline', "[{0}]\n{1}", source, message); - } - } else { - if (code) { - message = nls.localize('diagAndSourceAndCode', "[{0}] {1} [{2}]", source, message, code); - } else { - message = nls.localize('diagAndSource', "[{0}] {1}", source, message); - } - } + hoverMessage.appendMarkdown(`[${escape(source)}]`); + hoverMessage.appendText(' '); } - hoverMessage = new MarkdownString().appendCodeblock('_', message); + message = message.trim(); + const lines = message.split(/\r\n|\r|\n/g); + if (lines.length > 1) { + if (source) { + hoverMessage.appendMarkdown(`
`); + } + for (const line of lines) { + hoverMessage.appendText(line); + hoverMessage.appendMarkdown(`
`); + } + } else { + hoverMessage.appendText(message); + } + + if (code) { + if (lines.length === 1) { + hoverMessage.appendText(' '); + } + hoverMessage.appendMarkdown(`[${escape(code)}]`); + } if (isNonEmptyArray(relatedInformation)) { - hoverMessage.appendMarkdown('\n'); + hoverMessage.appendMarkdown(`\n`); for (const { message, resource, startLineNumber, startColumn } of relatedInformation) { hoverMessage.appendMarkdown( - `* [${basename(resource.path)}(${startLineNumber}, ${startColumn})](${resource.toString(false)}#${startLineNumber},${startColumn}): ` + escape(`* [${basename(resource.path)}(${startLineNumber}, ${startColumn})](${resource.toString(false)}#${startLineNumber},${startColumn}): `) ); - hoverMessage.appendText(`${message}`); - hoverMessage.appendMarkdown('\n'); + hoverMessage.appendText(`${escape(message)}`); + hoverMessage.appendMarkdown(`\n`); } - hoverMessage.appendMarkdown('\n'); + hoverMessage.appendMarkdown(`\n`); } } diff --git a/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts b/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts index a1142a0a0e1..cba65d3fa1d 100644 --- a/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts +++ b/src/vs/editor/contrib/gotoError/gotoErrorWidget.ts @@ -125,6 +125,7 @@ class MessageWidget { const sourceElement = document.createElement('div'); sourceElement.innerText = `[${source}] `; dom.addClass(sourceElement, 'source'); + this._editor.applyFontInfo(sourceElement); this._messageBlock.appendChild(sourceElement); } const messageElement = document.createElement('div'); @@ -135,6 +136,7 @@ class MessageWidget { const codeElement = document.createElement('div'); codeElement.innerText = ` [${code}]`; dom.addClass(codeElement, 'code'); + this._editor.applyFontInfo(codeElement); this._messageBlock.appendChild(codeElement); }